From 05104ff48aa3da22bf9973398dd6306f73cfa1ae Mon Sep 17 00:00:00 2001 From: Gordon Tetlow <gordon@FreeBSD.org> Date: Wed, 9 Jan 2019 19:17:54 +0000 Subject: [PATCH] Add EN-19:01 through EN-19:05. Approved by: so --- .../advisories/FreeBSD-EN-19:01.cc_cubic.asc | 133 + .../advisories/FreeBSD-EN-19:02.tcp.asc | 128 + .../advisories/FreeBSD-EN-19:03.sqlite.asc | 145 + .../advisories/FreeBSD-EN-19:04.tzdata.asc | 147 + .../advisories/FreeBSD-EN-19:05.kqueue.asc | 126 + .../security/patches/EN-19:01/cc_cubic.patch | 194 + .../patches/EN-19:01/cc_cubic.patch.asc | 18 + share/security/patches/EN-19:02/tcp.patch | 56 + share/security/patches/EN-19:02/tcp.patch.asc | 18 + .../security/patches/EN-19:03/sqlite-11.patch | 76146 ++++++++++++++++ .../patches/EN-19:03/sqlite-11.patch.asc | 18 + .../security/patches/EN-19:03/sqlite-12.patch | 65012 +++++++++++++ .../patches/EN-19:03/sqlite-12.patch.asc | 18 + .../patches/EN-19:04/tzdata-2018i.patch | 1448 + .../patches/EN-19:04/tzdata-2018i.patch.asc | 18 + share/security/patches/EN-19:05/kqueue.patch | 49 + .../patches/EN-19:05/kqueue.patch.asc | 18 + share/xml/notices.xml | 33 + 18 files changed, 143725 insertions(+) create mode 100644 share/security/advisories/FreeBSD-EN-19:01.cc_cubic.asc create mode 100644 share/security/advisories/FreeBSD-EN-19:02.tcp.asc create mode 100644 share/security/advisories/FreeBSD-EN-19:03.sqlite.asc create mode 100644 share/security/advisories/FreeBSD-EN-19:04.tzdata.asc create mode 100644 share/security/advisories/FreeBSD-EN-19:05.kqueue.asc create mode 100644 share/security/patches/EN-19:01/cc_cubic.patch create mode 100644 share/security/patches/EN-19:01/cc_cubic.patch.asc create mode 100644 share/security/patches/EN-19:02/tcp.patch create mode 100644 share/security/patches/EN-19:02/tcp.patch.asc create mode 100644 share/security/patches/EN-19:03/sqlite-11.patch create mode 100644 share/security/patches/EN-19:03/sqlite-11.patch.asc create mode 100644 share/security/patches/EN-19:03/sqlite-12.patch create mode 100644 share/security/patches/EN-19:03/sqlite-12.patch.asc create mode 100644 share/security/patches/EN-19:04/tzdata-2018i.patch create mode 100644 share/security/patches/EN-19:04/tzdata-2018i.patch.asc create mode 100644 share/security/patches/EN-19:05/kqueue.patch create mode 100644 share/security/patches/EN-19:05/kqueue.patch.asc diff --git a/share/security/advisories/FreeBSD-EN-19:01.cc_cubic.asc b/share/security/advisories/FreeBSD-EN-19:01.cc_cubic.asc new file mode 100644 index 0000000000..7b88ad20df --- /dev/null +++ b/share/security/advisories/FreeBSD-EN-19:01.cc_cubic.asc @@ -0,0 +1,133 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-EN-19:01.cc_cubic Errata Notice + The FreeBSD Project + +Topic: Connection stalls with CUBIC congestion control + +Category: core +Module: tcp +Announced: 2019-01-09 +Credits: Matt Garber, Hiren Panchasara +Affects: FreeBSD 12.0 +Corrected: 2018-12-17 21:46:42 UTC (stable/12, 12.0-STABLE) + 2019-01-09 18:38:35 UTC (releng/12.0, 12.0-RELEASE-p2) + +For general information regarding FreeBSD Errata Notices and Security +Advisories, including descriptions of the fields above, security +branches, and the following sections, please visit +<URL:https://security.FreeBSD.org/>. + +I. Background + +CUBIC is a modern congestion control algorithm for the Transmission Control +Protocol (TCP), which along with its predecessor BIC TCP is specifically +optimized for high bandwidth, high latency networks. It is widely +implemented across a variety of operating systems, and is the default TCP +implementation or enabled by default in recent versions of Linux and +Microsoft Windows. CUBIC is available as an alternate congestion control +algorithm since FreeBSD 9.0 using the cc_cubic module. + +II. Problem Description + +Changes to the cc_cubic module in FreeBSD 12.0 can cause network stuttering +or connection stalls when loaded and enabled as default. + +III. Impact + +FreeBSD 12.0 systems loading cc_cubic and setting non-default sysctl value +net.inet.tcp.cc.algorithm=cubic exhibit stuttering and complete stalls of +network connections. Under certain conditions, this may cause loss of system +availability over the network or service unreachability. + +IV. Workaround + +Disabling cc_cubic and selecting one of the alternate included congestion +control algorithms (e.g., newreno, htcp) will restore normal network +connectivity and alleviate stuttering and stalls. Note that disabling CUBIC +may cause a reduction in expected performance based on specific, unique +network condition characteristics and the module used as a workaround. + +V. Solution + +Perform one of the following: + +1) Upgrade your system to a supported FreeBSD stable or release / security +branch (releng) dated after the correction date, and reboot the system. + +2) To update your system via a binary patch: + +Systems running a RELEASE version of FreeBSD on the i386 or amd64 +platforms can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install +# shutdown -r +30 "Rebooting for FreeBSD errata update" + +3) To update your system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +[FreeBSD 12.0] +# fetch https://security.FreeBSD.org/patches/EN-19:01/cc_cubic.patch +# fetch https://security.FreeBSD.org/patches/EN-19:01/cc_cubic.patch.asc +# gpg --verify cc_cubic.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel as described in +<URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the +system. + +VI. Correction details + +The following list contains the correction revision numbers for each +affected branch. + +Branch/path Revision +- ------------------------------------------------------------------------- +stable/12/ r342181 +releng/12.0/ r342893 +- ------------------------------------------------------------------------- + +To see which files were modified by a particular revision, run the +following command, replacing NNNNNN with the revision number, on a +machine with Subversion installed: + +# svn diff -cNNNNNN --summarize svn://svn.freebsd.org/base + +Or visit the following URL, replacing NNNNNN with the revision number: + +<URL:https://svnweb.freebsd.org/base?view=revision&revision=NNNNNN> + +VII. References + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-EN-19:01.cc_cubic.asc> +-----BEGIN PGP SIGNATURE----- + +iQKTBAEBCgB9FiEE/A6HiuWv54gCjWNV05eS9J6n5cIFAlw2Rb5fFIAAAAAALgAo +aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldEZD +MEU4NzhBRTVBRkU3ODgwMjhENjM1NUQzOTc5MkY0OUVBN0U1QzIACgkQ05eS9J6n +5cJGyRAAnpturBqU4XIZMdvInaVHOXA5P6KemeFuJkwz/aMtIbgefm49lvZVS4q6 +RO8/GytONX1OHaoJQDdincVfRbe9x+ID+ulCJfSLuZMhjLYpxDQJo9d4NWZtvpBn +3wJNEQEXB0AjrYUOrebiT7yd3zA4f+7zSHu0Uvq4k5Tk0Xxsqxsx3/MG5ezEmdxx +IWub1RnYvgmUVJBKn/C5A4v17dE12VnZtLrnfhZ4K3U3mVZYc3cJxF34wSscVqYd +iAsntF786FV+hAXBX7wHa3JIqe+uXE2uemrquNmxgup+zrbVWPWPirgku2TVcvsm +m9aQILNc9RvJ/XkViLV8+ypqCymBFsl3VhO3dzmOnsbL72G9rqjQtgdYWT2dp69p +VyU4EWsTULXIbIBNxyrYhinT+DAqyt8bdrtyT3AhcVJaVk5B5APWnXiwjgS4mPN9 +hf2mCjZw10tJgsqYYrBlTERomgHU/pyliu0Rt2sof5+iGArbe7ZhEorHrM7YhD9n +Hc+3oNzA0dYDStJQpEb4rJ7dEKP/mpppwIosMhPbku6u3ViafCJVq2dIGNQpDope +Mh00Kk7cY0o3Rukw2lGNc9vDbIyUSqT/jV4lBDhp4k5ilQynvkMZETLlynI+KQUH +J2uOOvYzkIZLzZyXtaQfkmrkV6DxzmjxDsqwiMz5DB7o70w/M54= +=e8Wg +-----END PGP SIGNATURE----- diff --git a/share/security/advisories/FreeBSD-EN-19:02.tcp.asc b/share/security/advisories/FreeBSD-EN-19:02.tcp.asc new file mode 100644 index 0000000000..7446692818 --- /dev/null +++ b/share/security/advisories/FreeBSD-EN-19:02.tcp.asc @@ -0,0 +1,128 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-EN-19:02.tcp Errata Notice + The FreeBSD Project + +Topic: TCP connections may stall and eventually fail in case of + packet loss + +Category: core +Module: kernel +Announced: 2019-01-09 +Credits: Michael Tuexen +Affects: FreeBSD 12.0 +Corrected: 2018-12-23 09:48:36 UTC (stable/12, 12.0-STABLE) + 2019-09-09 18:42:40 UTC (releng/12.0, 12.0-RELEASE-p2) + +For general information regarding FreeBSD Errata Notices and Security +Advisories, including descriptions of the fields above, security +branches, and the following sections, please visit +<URL:https://security.FreeBSD.org/>. + +I. Background + +The TCP stack limits the resources used for TCP connections. Once a limit +is reached, further received TCP segments for the TCP connection are dropped. + +II. Problem Description + +To continue delivering data to the application, accepting the TCP segment +with the next expected sequence number is required. If this TCP segment is +dropped due to a resource limit, no further progress can be made. Therefore +exceptions for this particular TCP segment have to be implemented. + +III. Impact + +In case of lost TCP segments, TCP connections may stall and then eventually +fail. + +IV. Workaround + +No workaround is available. + +V. Solution + +Perform one of the following: + +1) Upgrade your system to a supported FreeBSD stable or release / security +branch (releng) dated after the correction date. + +Afterward, reboot the system. + +2) To update your system via a binary patch: + +Systems running a RELEASE version of FreeBSD on the i386 or amd64 +platforms can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install + +Afterward, reboot the system. + +3) To update your system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +[FreeBSD 12.0] +# fetch https://security.FreeBSD.org/patches/EN-19:02/tcp.patch +# fetch https://security.FreeBSD.org/patches/EN-19:02/tcp.patch.asc +# gpg --verify tcp.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel as described in +<URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the +system. + +VI. Correction details + +The following list contains the correction revision numbers for each +affected branch. + +Branch/path Revision +- ------------------------------------------------------------------------- +stable/12/ r342378 +releng/12.0/ r342894 +- ------------------------------------------------------------------------- + +To see which files were modified by a particular revision, run the +following command, replacing NNNNNN with the revision number, on a +machine with Subversion installed: + +# svn diff -cNNNNNN --summarize svn://svn.freebsd.org/base + +Or visit the following URL, replacing NNNNNN with the revision number: + +<URL:https://svnweb.freebsd.org/base?view=revision&revision=NNNNNN> + +VII. References + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-EN-19:02.tcp.asc> +-----BEGIN PGP SIGNATURE----- + +iQKTBAEBCgB9FiEE/A6HiuWv54gCjWNV05eS9J6n5cIFAlw2Rc1fFIAAAAAALgAo +aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldEZD +MEU4NzhBRTVBRkU3ODgwMjhENjM1NUQzOTc5MkY0OUVBN0U1QzIACgkQ05eS9J6n +5cJtnxAAgOIJjP9Dg76onxJUPJWiKTAR5VZeZ8od0RJREIeZMUpgFiVUVH82fr8z +ajAzGZbVFhEgFvYwQRU4R/MokNqONoG1O3YPdjcMFyW5HPBoAG+9h67qD3CtLgTN +xnXMR72ed83oY8ts1WSfYVAKF+9X6U5G6FtchBgAhap2k9tI22QKiEmTTmqzUnoy +ddLZatOyKmig8MZKshMmleEpvU+BoYR66d2K9CYxcjHqgNNJOQwQK6yLR3oX41Z9 +n5Akkg/KC7wD02CPFjmO9008ZC4fFiQ8D4eGt9D/lPI4AzLcfkvRdzt5CjMlamXm +Rjf2H5/2f4iYSXiEi2wkChFJHh+MQuYgcfTqRJdNB0qf3DbLwTL5wULfrMVNn7LU +rLHd8CNRTN4+d+//p7nZ/atFbuLjJE08YFqE2ODcMa8eJFaY09/+X+NMIqO6AdTE +hGzqDuiVmI/1MSFjD7dxUotw6Y2iRf+DiLx+JUmb0L+C0FXfl/u8x1ErYbzuLyyL +vD1qb66fDuuSC8aNWO6Qv55bBWAhYhO668CQwfmvEgree72ShbzJPEn3vUN2dIX4 +zg0kTs30QOlizAT2lxQchiPBKkQ+IExPurTT7lW0cZ5PID8y/FSKl49yeQo/nhrD +j/vnF7yMgc6roCyasNlREdi20yTYbp2PItfhaSXWVrtYAFN1jNc= +=3a3w +-----END PGP SIGNATURE----- diff --git a/share/security/advisories/FreeBSD-EN-19:03.sqlite.asc b/share/security/advisories/FreeBSD-EN-19:03.sqlite.asc new file mode 100644 index 0000000000..c5deeb3a96 --- /dev/null +++ b/share/security/advisories/FreeBSD-EN-19:03.sqlite.asc @@ -0,0 +1,145 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-EN-19:03.sqlite Errata Notice + The FreeBSD Project + +Topic: sqlite update + +Category: contrib +Module: sqlite3 +Announced: 2019-01-09 +Credits: Cy Schubert +Affects: All supported versions of FreeBSD. +Corrected: 2018-12-21 01:58:01 UTC (stable/12, 12.0-STABLE) + 2019-01-09 18:47:10 UTC (releng/12.0, 12.0-RELEASE-p2) + 2018-12-21 02:04:15 UTC (stable/11, 11.2-STABLE) + 2019-01-09 18:50:27 UTC (releng/11.2, 11.2-RELEASE-p8) +CVE Name: CVE-2018-20346, CVE-2018-20505, CVE-2018-20506 + +For general information regarding FreeBSD Errata Notices and Security +Advisories, including descriptions of the fields above, security +branches, and the following sections, please visit +<URL:https://security.FreeBSD.org/>. + +I. Background + +SQLite is an SQL database engine in a C library. Programs that link the +SQLite library can have SQL database access without running a separate RDBMS +process. The distribution comes with a standalone command-line access +program (sqlite3) that can be used to administer an SQLite database and which +serves as an example of how to use the SQLite library. + +II. Problem Description + +According to https://blade.tencent.com/magellan/index_en.html, the +vulnerabilities known as Magellan are a group vulnerabilities that exist +in sqlite3, documented by CVE-2018-20346, CVE-2018-20505, and CVE-2018-20506. + +When the FTS3 extension is enabled an integer overflow resulting in a buffer +overflow when allowing remote attackers to run arbitrary SQL statements which +can be leveraged to execute arbitrary code. + +III. Impact + +The vulnerabilities were discovered by Tencent Blade Team and verified to be +able to successfully implement remote code execution in Chromium browsers. + +IV. Workaround + +No workaround is available. + +V. Solution + +Perform one of the following: + +1) Upgrade your system to a supported FreeBSD stable or release / security +branch (releng) dated after the correction date. + +2) To update your system via a binary patch: + +Systems running a RELEASE version of FreeBSD on the i386 or amd64 +platforms can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install + +3) To update your system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +[FreeBSD 11.2] +# fetch https://security.FreeBSD.org/patches/EN-19:03/sqlite-11.patch +# fetch https://security.FreeBSD.org/patches/EN-19:03/sqlite-11.patch.asc +# gpg --verify sqlite-11.patch.asc + +[FreeBSD 12.0] +# fetch https://security.FreeBSD.org/patches/EN-19:03/sqlite-12.patch +# fetch https://security.FreeBSD.org/patches/EN-19:03/sqlite-12.patch.asc +# gpg --verify sqlite-12.patch.asc + + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile the operating system using buildworld and installworld as +described in <URL:https://www.FreeBSD.org/handbook/makeworld.html>. + +Restart all daemons that use the library, or reboot the system. + +VI. Correction details + +The following list contains the correction revision numbers for each +affected branch. + +Branch/path Revision +- ------------------------------------------------------------------------- +stable/12/ r342291 +releng/12.0/ r342895 +stable/11/ r342292 +releng/11.2/ r342896 +- ------------------------------------------------------------------------- + +To see which files were modified by a particular revision, run the +following command, replacing NNNNNN with the revision number, on a +machine with Subversion installed: + +# svn diff -cNNNNNN --summarize svn://svn.freebsd.org/base + +Or visit the following URL, replacing NNNNNN with the revision number: + +<URL:https://svnweb.freebsd.org/base?view=revision&revision=NNNNNN> + +VII. References + +<URL:https://blade.tencent.com/magellan/index_en.html> + +<URL:https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=234113> + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-EN-19:03.sqlite.asc> +-----BEGIN PGP SIGNATURE----- + +iQKTBAEBCgB9FiEE/A6HiuWv54gCjWNV05eS9J6n5cIFAlw2RdFfFIAAAAAALgAo +aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldEZD +MEU4NzhBRTVBRkU3ODgwMjhENjM1NUQzOTc5MkY0OUVBN0U1QzIACgkQ05eS9J6n +5cLtJg/9EM0jQbTBrSgVy5X1AyQ2rcFz9KbjtA0L48wOuOLiAh7eeYxh4Wxuz9k1 +QnEJavMbpVr71yhmt6maEAbRzyGUvemDh4vlu0wjcYSlEzcvk7xaRzfXimippxky +GumFBCvs7UKDIiGRr62ukmxu3FgfEaTM/Cc4bNcuV5k4za+DWIGTu+97i0+B2ieX +/IZ5hQq42w1YIUY5QOy2vj87rnQf2t+uShcBjRg8HsnPsG9BfQfI8vfuWjjtaKMI +iva++F5UJWcsykjZo5J3aaZFxnHsW2hs3buQN+AhoEt7oKdGquOHdweSw8xtSlp9 +3Y+qj+veD7u4Mt95OtnYrJOg8Kynlrzg5uMDbNGbyqktbxfpi2gqBbPEVmx2+nGj +Aj9PDSHMliBZsVKvr1opExfYp4HL0LB9Kqhato08lFxs05TUxiT6LRcel/iXiIfl +vCqfWhKJYVZ+alAW+Kjic6iWw7AtmVLbV64dDu03jxS/14RtRp1Hbk1BRCrnJeLn +sLSdFj6bi2mQx6OXAd9G9jhReoxylyZwRXyhPSsPG1E4mzX6ZRbJfnkriSazW4hq +F+PjTyXidn3uhS6z6CZB08Ltw2NBd3baRl/TQBEiFHd6SSGByqX6gMguK/tQV92U +uM/Q4Ak4H/Q+nEN8/LdXioW0P7ZEC6X/9GXKWv+bUs6LjcZXftA= +=TG5W +-----END PGP SIGNATURE----- diff --git a/share/security/advisories/FreeBSD-EN-19:04.tzdata.asc b/share/security/advisories/FreeBSD-EN-19:04.tzdata.asc new file mode 100644 index 0000000000..8fda0df158 --- /dev/null +++ b/share/security/advisories/FreeBSD-EN-19:04.tzdata.asc @@ -0,0 +1,147 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-EN-19:04.tzdata Errata Notice + The FreeBSD Project + +Topic: Timezone database information update + +Category: contrib +Module: zoneinfo +Announced: 2019-01-09 +Credits: Philip Paeps +Affects: All supported versions of FreeBSD. +Corrected: 2019-01-01 10:04:49 UTC (stable/12, 12.0-STABLE) + 2019-01-09 18:53:35 UTC (releng/12.0, 12.0-RELEASE-p2) + 2019-01-01 10:05:12 UTC (stable/11, 11.2-STABLE) + 2019-01-09 18:54:42 UTC (releng/11.2, 11.2-RELEASE-p8) + +For general information regarding FreeBSD Errata Notices and Security +Advisories, including descriptions of the fields above, security +branches, and the following sections, please visit +<URL:https://security.FreeBSD.org/>. + +I. Background + +The tzsetup(8) program allows the user to specify the default local timezone. +Based on the selected timezone, tzsetup(8) copies one of the files from +/usr/share/zoneinfo to /etc/localtime. This file actually controls the +conversion. + +II. Problem Description + +Several changes in Daylight Savings Time happened after previous FreeBSD +releases were released that would affect many people who live in different +countries. Because of these changes, the data in the zoneinfo files need to +be updated, and if the local timezone on the running system is affected, +tzsetup(8) needs to be run so the /etc/localtime is updated. + +III. Impact + +An incorrect time will be displayed on a system configured to use one of the +affected timezones if the /usr/share/zoneinfo and /etc/localtime files are +not updated, and all applications on the system that rely on the system time, +such as cron(8) and syslog(8), will be affected. + +IV. Workaround + +The system administrator can install an updated timezone database from the +misc/zoneinfo port and run tzsetup(8) to get the timezone database corrected. + +Applications that store and display times in Coordinated Universal Time (UTC) +are not affected. + +V. Solution + +Please note that some third party software, for instance PHP, Ruby, Java and +Perl, may be using different zoneinfo data source, in such cases this +software must be updated separately. For software packages that is installed +via binary packages, they can be upgraded by executing `pkg upgrade'. + +Following the instructions in this Errata Notice will update all of the +zoneinfo files to be the same as what was released with FreeBSD release. + +Perform one of the following: + +1) Upgrade your system to a supported FreeBSD stable or release / security +branch (releng) dated after the correction date. Restart all the affected +applications and daemons, or reboot the system. + +2) To update your system via a binary patch: + +Systems running a RELEASE version of FreeBSD on the i386 or amd64 +platforms can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install + +Restart all the affected applications and daemons, or reboot the system. + +3) To update your system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +# fetch https://security.FreeBSD.org/patches/EN-19:04/tzdata-2018i.patch +# fetch https://security.FreeBSD.org/patches/EN-19:04/tzdata-2018i.patch.asc +# gpg --verify tzdata-2018i.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile the operating system using buildworld and installworld as +described in <URL:https://www.FreeBSD.org/handbook/makeworld.html>. + +Restart all the affected applications and daemons, or reboot the system. + +VI. Correction details + +The following list contains the correction revision numbers for each +affected branch. + +Branch/path Revision +- ------------------------------------------------------------------------- +stable/12/ r342667 +releng/12.0/ r342897 +stable/11/ r342668 +releng/11.2/ r342898 +- ------------------------------------------------------------------------- + +To see which files were modified by a particular revision, run the +following command, replacing NNNNNN with the revision number, on a +machine with Subversion installed: + +# svn diff -cNNNNNN --summarize svn://svn.freebsd.org/base + +Or visit the following URL, replacing NNNNNN with the revision number: + +<URL:https://svnweb.freebsd.org/base?view=revision&revision=NNNNNN> + +VII. References + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-EN-19:04.tzdata.asc> +-----BEGIN PGP SIGNATURE----- + +iQKTBAEBCgB9FiEE/A6HiuWv54gCjWNV05eS9J6n5cIFAlw2RdRfFIAAAAAALgAo +aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldEZD +MEU4NzhBRTVBRkU3ODgwMjhENjM1NUQzOTc5MkY0OUVBN0U1QzIACgkQ05eS9J6n +5cKd+Q//QYBUcMdBnW6URT8bWCrIOTPP84aGpMKmU4ZZYidUfI6CJiiWVaGQHJgD +tmdQjaHemSRfxQ+yAZ5XR8oUIBxrzBhA51cM5QMNnJMXBkpqz9yCbHefH3Fxfr6n +Dg+Vt2cZ745MHPK9uhjtUTmLYRF2iztUqlATr3R1NxBbJ6QQzQuVEyeAvTSY9Jdw +/+cQM72m28iHPP+ff5v9n2MLqoTg74HbchwJthtDvgK9elfQFuC1F07i8I6F4krT +FHnPRISpg4EEOKYG/Jjedk9FQBUpKiOhsDz+siGtjQoivz8TemaH5nTMI7P/WP/7 +jFJ6+jQirc2vCvcUzmiPGrBXRx3OptYcIiLOeKfgc+wCtgEHap4Nrl4Damt1QC13 +T4kpaOi3TcqtDtKxZyxwR8tOtJGEayqXFHA5FL1Fgr63JcvbZTXlBg0BT4oAd7mX +DuvDkap5hXh6jlQ2BM4L9J+I+GNMfrpULsM4drsqd7GVBcLrnu06po3M8jgja44T +rVzNB62FuOX19Q2W8kZ7LOfAwW+ho02GNzwuYWiLCpP4JSTaxtHrd1LexpCzO4Lg +zsttA2bkNjmzHxfcbAPbS5IMX539iJdTgZiDlBNzUi+QqiCG83/fRcVvgD7qH1iM +kF7DipZUURjlV/RbtCZFU/fsKVzR7rF5MSQl9q7llwe5uMto6lQ= +=1NIG +-----END PGP SIGNATURE----- diff --git a/share/security/advisories/FreeBSD-EN-19:05.kqueue.asc b/share/security/advisories/FreeBSD-EN-19:05.kqueue.asc new file mode 100644 index 0000000000..b32b9bd112 --- /dev/null +++ b/share/security/advisories/FreeBSD-EN-19:05.kqueue.asc @@ -0,0 +1,126 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +============================================================================= +FreeBSD-EN-19:05.kqueue Errata Notice + The FreeBSD Project + +Topic: kqueue race condition and kernel panic + +Category: core +Module: kqueue +Announced: 2019-01-09 +Credits: Mark Johnston +Affects: FreeBSD 11.2 +Corrected: 2019-11-24 17:11:47 UTC (stable/11, 11.2-STABLE) + 2019-01-09 18:57:38 UTC (releng/11.2, 11.2-RELEASE-p8) + +For general information regarding FreeBSD Errata Notices and Security +Advisories, including descriptions of the fields above, security +branches, and the following sections, please visit +<URL:https://security.FreeBSD.org/>. + +I. Background + +kevent(2) is a system call which provides a generic method of notifying the +caller when a caller-specified event happens or a condition holds. One use +for kevent(2) is to wait for a specified timeout to elapse. + +II. Problem Description + +The kevent(2) implementation in the kernel contains a race condition which +can be triggered when an event is added and fires shortly after. Most event +types are not affected, but timer events can trigger the race if the timeout +duration is very short. + +III. Impact + +The race condition can cause corruption of a queue structure, leading to +a kernel panic when it is later accessed. Applications using kevent(2) may +trigger the panic if their usage causes the race condition to occur. + +IV. Workaround + +No workaround is available. + +V. Solution + +Perform one of the following: + +1) Upgrade your system to a supported FreeBSD stable or release / security +branch (releng) dated after the correction date, and reboot. + +2) To update your system via a binary patch: + +Systems running a RELEASE version of FreeBSD on the i386 or amd64 +platforms can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install +# shutdown -r +30 "Rebooting for errata update" + +3) To update your system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +[FreeBSD 11.2] +# fetch https://security.FreeBSD.org/patches/EN-19:05/kqueue.patch +# fetch https://security.FreeBSD.org/patches/EN-19:05/kqueue.patch.asc +# gpg --verify kqueue.patch.asc + +b) Apply the patch. Execute the following commands as root: + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel as described in +<URL:https://www.FreeBSD.org/handbook/kernelconfig.html> and reboot the +system. + +VI. Correction details + +The following list contains the correction revision numbers for each +affected branch. + +Branch/path Revision +- ------------------------------------------------------------------------- +stable/11/ r340904 +releng/11.2/ r342899 +- ------------------------------------------------------------------------- + +To see which files were modified by a particular revision, run the +following command, replacing NNNNNN with the revision number, on a +machine with Subversion installed: + +# svn diff -cNNNNNN --summarize svn://svn.freebsd.org/base + +Or visit the following URL, replacing NNNNNN with the revision number: + +<URL:https://svnweb.freebsd.org/base?view=revision&revision=NNNNNN> + +VII. References + +The latest revision of this advisory is available at +<URL:https://security.FreeBSD.org/advisories/FreeBSD-EN-19:05.kqueue.asc> +-----BEGIN PGP SIGNATURE----- + +iQKTBAEBCgB9FiEE/A6HiuWv54gCjWNV05eS9J6n5cIFAlw2RdZfFIAAAAAALgAo +aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldEZD +MEU4NzhBRTVBRkU3ODgwMjhENjM1NUQzOTc5MkY0OUVBN0U1QzIACgkQ05eS9J6n +5cK0nRAAgPsdkc/TyBTqpvJrvvNaVd0xgNC2lxnYK3HxOPbo5kqj6XHZxb3KvrrN +He6TyGvwGCPHNzlFwHILH+FtFkgrvGVBoPu/U0e/NKRrkhyxPHJMz0bZPu7yqQoG +GDFRIsw5D3JKZW38yMD9Menh3mag81OVZii1LfzkcDLLKfwX/zcx1vV7MSwMzoNs +5L7Fm8lg0uIxrrlKvvmrPxfWoZENhCr9CAAdg8moL3thl64NaVVmPo7tXDXosNGo +EQYT19SY0FBSboUcpVaChgyZaCFzOeCPuXuJPoUYppIWNiv2S8ZTjuq9d1g4R4SD +7GBMozz8EG1rN0pzhx8mVEECZBzdt5rjggiWKjkOVxH/sy5LQjppONK3VVOygoCz +dve2wGq6S1ke/b2NDRpAinmIr8I3x3b7JLNkE5OvNJ6bTLk3ZmpIRYQNYT+eu8Fx +GNe/oTU9DRbB4yv0kcKsypHqQ0cKdn6+duYzKGZ4+c86B7IHJgsYoG/NTKYfFzQx +BHWuI/P/9pakHESNiDidKRz+z5w679+jIfZDcbBIXaw+PCqzg5a1GFN8Bub2mGLw +2wmVQJV1nbdE+6UbWvaV2seV/bo+N/L8k4QS6OPIDUefLPGgCdRFr/MlLoiTaJ43 +p+L3iVlVbiOTCfsCGI/QVQq+IOngKzqSUXN3Ys7PXvvAzSyaTFg= +=fD2U +-----END PGP SIGNATURE----- diff --git a/share/security/patches/EN-19:01/cc_cubic.patch b/share/security/patches/EN-19:01/cc_cubic.patch new file mode 100644 index 0000000000..263715f214 --- /dev/null +++ b/share/security/patches/EN-19:01/cc_cubic.patch @@ -0,0 +1,194 @@ +--- sys/netinet/cc/cc.h.orig ++++ sys/netinet/cc/cc.h +@@ -102,8 +102,6 @@ + #define CCF_ACKNOW 0x0008 /* Will this ack be sent now? */ + #define CCF_IPHDR_CE 0x0010 /* Does this packet set CE bit? */ + #define CCF_TCPHDR_CWR 0x0020 /* Does this packet set CWR bit? */ +-#define CCF_MAX_CWND 0x0040 /* Have we reached maximum cwnd? */ +-#define CCF_CHG_MAX_CWND 0x0080 /* Cubic max_cwnd changed, for K */ + + /* ACK types passed to the ack_received() hook. */ + #define CC_ACK 0x0001 /* Regular in sequence ACK. */ +--- sys/netinet/cc/cc_cubic.c.orig ++++ sys/netinet/cc/cc_cubic.c +@@ -88,8 +88,6 @@ + unsigned long max_cwnd; + /* cwnd at the previous congestion event. */ + unsigned long prev_max_cwnd; +- /* Cached value for t_maxseg when K was computed */ +- uint32_t k_maxseg; + /* Number of congestion events. */ + uint32_t num_cong_events; + /* Minimum observed rtt in ticks. */ +@@ -126,9 +124,6 @@ + cubic_data = ccv->cc_data; + cubic_record_rtt(ccv); + +- if (ccv->flags & CCF_MAX_CWND) +- return; +- + /* + * Regular ACK and we're not in cong/fast recovery and we're cwnd + * limited and we're either not doing ABC or are slow starting or are +@@ -156,12 +151,6 @@ + cubic_data->mean_rtt_ticks, cubic_data->max_cwnd, + CCV(ccv, t_maxseg)); + +- if (ccv->flags & CCF_CHG_MAX_CWND || cubic_data->k_maxseg != CCV(ccv, t_maxseg)) { +- cubic_data->K = cubic_k(cubic_data->max_cwnd / CCV(ccv, t_maxseg)); +- cubic_data->k_maxseg = CCV(ccv, t_maxseg); +- ccv->flags &= ~(CCF_MAX_CWND|CCF_CHG_MAX_CWND); +- } +- + w_cubic_next = cubic_cwnd(ticks_since_cong + + cubic_data->mean_rtt_ticks, cubic_data->max_cwnd, + CCV(ccv, t_maxseg), cubic_data->K); +@@ -173,18 +162,13 @@ + * TCP-friendly region, follow tf + * cwnd growth. + */ +- CCV(ccv, snd_cwnd) = ulmin(w_tf, TCP_MAXWIN << CCV(ccv, snd_scale)); ++ CCV(ccv, snd_cwnd) = w_tf; + + else if (CCV(ccv, snd_cwnd) < w_cubic_next) { + /* + * Concave or convex region, follow CUBIC + * cwnd growth. + */ +- if (w_cubic_next >= TCP_MAXWIN << CCV(ccv, snd_scale)) { +- w_cubic_next = TCP_MAXWIN << CCV(ccv, snd_scale); +- ccv->flags |= CCF_MAX_CWND; +- } +- w_cubic_next = ulmin(w_cubic_next, TCP_MAXWIN << CCV(ccv, snd_scale)); + if (V_tcp_do_rfc3465) + CCV(ccv, snd_cwnd) = w_cubic_next; + else +@@ -202,10 +186,8 @@ + * max_cwnd. + */ + if (cubic_data->num_cong_events == 0 && +- cubic_data->max_cwnd < CCV(ccv, snd_cwnd)) { ++ cubic_data->max_cwnd < CCV(ccv, snd_cwnd)) + cubic_data->max_cwnd = CCV(ccv, snd_cwnd); +- ccv->flags |= CCF_CHG_MAX_CWND; +- } + } + } + } +@@ -254,7 +236,6 @@ + cubic_data->num_cong_events++; + cubic_data->prev_max_cwnd = cubic_data->max_cwnd; + cubic_data->max_cwnd = CCV(ccv, snd_cwnd); +- ccv->flags |= CCF_CHG_MAX_CWND; + } + ENTER_RECOVERY(CCV(ccv, t_flags)); + } +@@ -267,8 +248,6 @@ + cubic_data->prev_max_cwnd = cubic_data->max_cwnd; + cubic_data->max_cwnd = CCV(ccv, snd_cwnd); + cubic_data->t_last_cong = ticks; +- ccv->flags |= CCF_CHG_MAX_CWND; +- ccv->flags &= ~CCF_MAX_CWND; + CCV(ccv, snd_cwnd) = CCV(ccv, snd_ssthresh); + ENTER_CONGRECOVERY(CCV(ccv, t_flags)); + } +@@ -285,7 +264,6 @@ + if (CCV(ccv, t_rxtshift) >= 2) { + cubic_data->num_cong_events++; + cubic_data->t_last_cong = ticks; +- ccv->flags &= ~CCF_MAX_CWND; + } + break; + } +@@ -304,7 +282,6 @@ + * get used. + */ + cubic_data->max_cwnd = CCV(ccv, snd_cwnd); +- ccv->flags |= CCF_CHG_MAX_CWND; + } + + static int +@@ -329,11 +306,9 @@ + pipe = 0; + + /* Fast convergence heuristic. */ +- if (cubic_data->max_cwnd < cubic_data->prev_max_cwnd) { ++ if (cubic_data->max_cwnd < cubic_data->prev_max_cwnd) + cubic_data->max_cwnd = (cubic_data->max_cwnd * CUBIC_FC_FACTOR) + >> CUBIC_SHIFT; +- ccv->flags |= CCF_CHG_MAX_CWND; +- } + + if (IN_FASTRECOVERY(CCV(ccv, t_flags))) { + /* +@@ -356,7 +331,6 @@ + cubic_data->max_cwnd) >> CUBIC_SHIFT)); + } + cubic_data->t_last_cong = ticks; +- ccv->flags &= ~CCF_MAX_CWND; + + /* Calculate the average RTT between congestion epochs. */ + if (cubic_data->epoch_ack_count > 0 && +@@ -367,6 +341,7 @@ + + cubic_data->epoch_ack_count = 0; + cubic_data->sum_rtt_ticks = 0; ++ cubic_data->K = cubic_k(cubic_data->max_cwnd / CCV(ccv, t_maxseg)); + } + + /* +--- sys/netinet/cc/cc_cubic.h.orig ++++ sys/netinet/cc/cc_cubic.h +@@ -41,8 +41,6 @@ + #ifndef _NETINET_CC_CUBIC_H_ + #define _NETINET_CC_CUBIC_H_ + +-#include <sys/limits.h> +- + /* Number of bits of precision for fixed point math calcs. */ + #define CUBIC_SHIFT 8 + +@@ -163,6 +161,8 @@ + /* + * Compute the new cwnd value using an implementation of eqn 1 from the I-D. + * Thanks to Kip Macy for help debugging this function. ++ * ++ * XXXLAS: Characterise bounds for overflow. + */ + static __inline unsigned long + cubic_cwnd(int ticks_since_cong, unsigned long wmax, uint32_t smss, int64_t K) +@@ -174,15 +174,6 @@ + /* t - K, with CUBIC_SHIFT worth of precision. */ + cwnd = ((int64_t)(ticks_since_cong << CUBIC_SHIFT) - (K * hz)) / hz; + +- /* moved this calculation up because it cannot overflow or underflow */ +- cwnd *= CUBIC_C_FACTOR * smss; +- +- if (cwnd > 2097151) /* 2^21 cubed is long max */ +- return INT_MAX; +- +- if (cwnd < -2097152) /* -2^21 cubed is long min */ +- return smss; +- + /* (t - K)^3, with CUBIC_SHIFT^3 worth of precision. */ + cwnd *= (cwnd * cwnd); + +@@ -191,17 +182,8 @@ + * The down shift by CUBIC_SHIFT_4 is because cwnd has 4 lots of + * CUBIC_SHIFT included in the value. 3 from the cubing of cwnd above, + * and an extra from multiplying through by CUBIC_C_FACTOR. +- * +- * The original formula was this: +- * cwnd = ((cwnd * CUBIC_C_FACTOR * smss) >> CUBIC_SHIFT_4) + wmax; +- * +- * CUBIC_C_FACTOR and smss factors were moved up to an earlier +- * calculation to simplify overflow and underflow detection. + */ +- cwnd = (cwnd >> CUBIC_SHIFT_4) + wmax; +- +- if (cwnd < 0) +- return 1; ++ cwnd = ((cwnd * CUBIC_C_FACTOR * smss) >> CUBIC_SHIFT_4) + wmax; + + return ((unsigned long)cwnd); + } diff --git a/share/security/patches/EN-19:01/cc_cubic.patch.asc b/share/security/patches/EN-19:01/cc_cubic.patch.asc new file mode 100644 index 0000000000..990bff2a54 --- /dev/null +++ b/share/security/patches/EN-19:01/cc_cubic.patch.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- + +iQKTBAABCgB9FiEE/A6HiuWv54gCjWNV05eS9J6n5cIFAlw2RhZfFIAAAAAALgAo +aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldEZD +MEU4NzhBRTVBRkU3ODgwMjhENjM1NUQzOTc5MkY0OUVBN0U1QzIACgkQ05eS9J6n +5cK6Bw/+NJXfzNxz2c9hS4RgZSeDZxtqPEC6ZG5aKN2vc7RzwYsGgv5f4VzuU40A +MsRNRmbDjoQYj9zkBKOYUWaIX6ZffOjUwc7DZ1Us4ykXRxlB2Ys4R98z5lY6mQDA +hcTnCPvKTMChcXO3hQ77W3bUPk+p5+XvcDhks8K8N5/Xixj1xoy5J8dmbGvQ9i/R +JZa2loacsPab/c2Fr/6L7DyHU3bbXIh+27HknCUOyK0dekbZ8g0oP+u/qb4VX/7s +BkSbIkLUNq3dBkb0vOAoTry/M2kKpU8Dz/SITuW4bSJqfvNWN2hiT7YTQaNg+E0J +VaaKHhpGO5TrYDnYRfmJyrAiobROEbpoGXg9TvfZ9VLk0sGOPcBN598DNJLkiZCa +dzMrimOOcgeeyPhvG0Mq4ZGBkYgqj88jb29bwJbkCLvjTfaL3kPeKxky1bylgEmR +Vevzqlp9IhrnSW21u0Kd8ZWuXka8ni+uKe2B24FyOZntziODWOi/rFAE7DV21y1V +gZsX2v9kwr/M2ApFpAhtEnF3JHX0sl5J8mF9Wnv0CdJP3fTpC9M0byZsCc2qy84g +5f6KPu57CgvuHG/YRKLDxG7tt1jXYi/LFsR7iGbbCCbthx5pImQrYfKMOdSR81s+ +Iwa8j657nxF+YjM+aq8l7E3g1uonJ2aWT95WFssUnv2ww+O14fw= +=4RIV +-----END PGP SIGNATURE----- diff --git a/share/security/patches/EN-19:02/tcp.patch b/share/security/patches/EN-19:02/tcp.patch new file mode 100644 index 0000000000..2dc3a3381d --- /dev/null +++ b/share/security/patches/EN-19:02/tcp.patch @@ -0,0 +1,56 @@ +--- sys/netinet/tcp_reass.c.orig ++++ sys/netinet/tcp_reass.c +@@ -579,7 +579,8 @@ + */ + lenofoh = tcp_reass_overhead_of_chain(m, &mlast); + sb = &tp->t_inpcb->inp_socket->so_rcv; +- if ((sb->sb_mbcnt + tp->t_segqmbuflen + lenofoh) > sb->sb_mbmax) { ++ if ((th->th_seq != tp->rcv_nxt || !TCPS_HAVEESTABLISHED(tp->t_state)) && ++ (sb->sb_mbcnt + tp->t_segqmbuflen + lenofoh) > sb->sb_mbmax) { + /* No room */ + TCPSTAT_INC(tcps_rcvreassfull); + #ifdef TCP_REASS_COUNTERS +@@ -588,6 +589,11 @@ + #ifdef TCP_REASS_LOGGING + tcp_log_reassm(tp, NULL, NULL, th->th_seq, lenofoh, TCP_R_LOG_LIMIT_REACHED, 0); + #endif ++ if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL, NULL))) { ++ log(LOG_DEBUG, "%s; %s: mbuf count limit reached, " ++ "segment dropped\n", s, __func__); ++ free(s, M_TCPLOG); ++ } + m_freem(m); + *tlenp = 0; + #ifdef TCP_REASS_LOGGING +@@ -936,6 +942,20 @@ + * is understood. + */ + new_entry: ++ if (th->th_seq == tp->rcv_nxt && TCPS_HAVEESTABLISHED(tp->t_state)) { ++ tp->rcv_nxt += *tlenp; ++ flags = th->th_flags & TH_FIN; ++ TCPSTAT_INC(tcps_rcvoopack); ++ TCPSTAT_ADD(tcps_rcvoobyte, *tlenp); ++ SOCKBUF_LOCK(&so->so_rcv); ++ if (so->so_rcv.sb_state & SBS_CANTRCVMORE) { ++ m_freem(m); ++ } else { ++ sbappendstream_locked(&so->so_rcv, m, 0); ++ } ++ sorwakeup_locked(so); ++ return (flags); ++ } + if (tcp_new_limits) { + if ((tp->t_segqlen > tcp_reass_queue_guard) && + (*tlenp < MSIZE)) { +@@ -960,9 +980,7 @@ + return (0); + } + } else { +- +- if ((th->th_seq != tp->rcv_nxt || !TCPS_HAVEESTABLISHED(tp->t_state)) && +- tp->t_segqlen >= min((so->so_rcv.sb_hiwat / tp->t_maxseg) + 1, ++ if (tp->t_segqlen >= min((so->so_rcv.sb_hiwat / tp->t_maxseg) + 1, + tcp_reass_maxqueuelen)) { + TCPSTAT_INC(tcps_rcvreassfull); + *tlenp = 0; diff --git a/share/security/patches/EN-19:02/tcp.patch.asc b/share/security/patches/EN-19:02/tcp.patch.asc new file mode 100644 index 0000000000..c93a17a849 --- /dev/null +++ b/share/security/patches/EN-19:02/tcp.patch.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- + +iQKTBAABCgB9FiEE/A6HiuWv54gCjWNV05eS9J6n5cIFAlw2RhxfFIAAAAAALgAo +aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldEZD +MEU4NzhBRTVBRkU3ODgwMjhENjM1NUQzOTc5MkY0OUVBN0U1QzIACgkQ05eS9J6n +5cIsjBAAiM9K9Y/ci+sVsH0HrunEbdJT5dI4oabI6Z7zV7X2F5OZobC0neXYCpqH +sknU/phwdWTmSdLlqxI37At2rQPRFnnAF0sfyByJEmnrNq3CPg/cFabvuNWfetPh +wpHQc7XUJAz58Lk5o382Dn4POZP+aBmo1e6ULHIXCcgR8xHvGAtQoCLJFh9VXKZx +tSP+PiwCfHXjIF1J+bEPhv6IO3H59COb5daj1qhTbUnkCmacPBDCFzrSqqbUPOru +MAvXxcUP3mhPDrIx5eDUNo5C1t54PF6fPzBj8Pq+SUKXrHI1PYHxw2yL+y0vn7vT +TImWde+rRdDwzab2mt/IP2WaRnC5wVNS+QHZc9M+QB+ujAx8e278uK/eiJwKkm59 +MShtZ46YB96aoZuLYibk+i53jW7OOJbCH9xwFXvZb2n3ObBfJcqig4aXtvug7BOr +v/90s6Q72jKpJUopgzFut6E2XtJ6ImAvq8qDxo0qLix5vASu57tst/5vyfj4dt79 +AJ05x20KKKKhaNzpnwyOWW4/egeElJPLHg8WsWzwtsRW1ZMWBRIqAzS+dLlDNod9 +ywSbOYb0FMmYe0rtv1gbm5wWjAQ8QYEe/8JoD7y5O04mUVmxmubeYYQ2vAxtxDPs +ODiJtLdALWkPidb8ynn4r5LBYDjQRvni1+3j2E+nCh9Z08nHzzs= +=KVpY +-----END PGP SIGNATURE----- diff --git a/share/security/patches/EN-19:03/sqlite-11.patch b/share/security/patches/EN-19:03/sqlite-11.patch new file mode 100644 index 0000000000..774a894939 --- /dev/null +++ b/share/security/patches/EN-19:03/sqlite-11.patch @@ -0,0 +1,76146 @@ +--- contrib/sqlite3/Makefile.am.orig ++++ contrib/sqlite3/Makefile.am +@@ -1,6 +1,5 @@ + +-AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ @FTS5_FLAGS@ @JSON1_FLAGS@ @SESSION_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE +- ++AM_CFLAGS = @BUILD_CFLAGS@ + lib_LTLIBRARIES = libsqlite3.la + libsqlite3_la_SOURCES = sqlite3.c + libsqlite3_la_LDFLAGS = -no-undefined -version-info 8:6:8 +@@ -10,11 +9,11 @@ + EXTRA_sqlite3_SOURCES = sqlite3.c + sqlite3_LDADD = @EXTRA_SHELL_OBJ@ @READLINE_LIBS@ + sqlite3_DEPENDENCIES = @EXTRA_SHELL_OBJ@ +-sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS ++sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_STMTVTAB -DSQLITE_ENABLE_DBSTAT_VTAB $(SHELL_CFLAGS) + + include_HEADERS = sqlite3.h sqlite3ext.h + +-EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt Replace.cs ++EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt Replace.cs Makefile.fallback + pkgconfigdir = ${libdir}/pkgconfig + pkgconfig_DATA = sqlite3.pc + +--- contrib/sqlite3/Makefile.fallback.orig ++++ contrib/sqlite3/Makefile.fallback +@@ -0,0 +1,19 @@ ++#!/usr/bin/make ++# ++# If the configure script does not work, then this Makefile is available ++# as a backup. Manually configure the variables below. ++# ++# Note: This makefile works out-of-the-box on MacOS 10.2 (Jaguar) ++# ++CC = gcc ++CFLAGS = -O0 -I. ++LIBS = -lz ++COPTS += -D_BSD_SOURCE ++COPTS += -DSQLITE_ENABLE_LOCKING_STYLE=0 ++COPTS += -DSQLITE_THREADSAFE=0 ++COPTS += -DSQLITE_OMIT_LOAD_EXTENSION ++COPTS += -DSQLITE_WITHOUT_ZONEMALLOC ++COPTS += -DSQLITE_ENABLE_RTREE ++ ++sqlite3: shell.c sqlite3.c ++ $(CC) $(CFLAGS) $(COPTS) -o sqlite3 shell.c sqlite3.c $(LIBS) +--- contrib/sqlite3/Makefile.in.orig ++++ contrib/sqlite3/Makefile.in +@@ -260,7 +260,6 @@ + DLLTOOL = @DLLTOOL@ + DSYMUTIL = @DSYMUTIL@ + DUMPBIN = @DUMPBIN@ +-DYNAMIC_EXTENSION_FLAGS = @DYNAMIC_EXTENSION_FLAGS@ + ECHO_C = @ECHO_C@ + ECHO_N = @ECHO_N@ + ECHO_T = @ECHO_T@ +@@ -268,7 +267,6 @@ + EXEEXT = @EXEEXT@ + EXTRA_SHELL_OBJ = @EXTRA_SHELL_OBJ@ + FGREP = @FGREP@ +-FTS5_FLAGS = @FTS5_FLAGS@ + GREP = @GREP@ + INSTALL = @INSTALL@ + INSTALL_DATA = @INSTALL_DATA@ +@@ -275,7 +273,6 @@ + INSTALL_PROGRAM = @INSTALL_PROGRAM@ + INSTALL_SCRIPT = @INSTALL_SCRIPT@ + INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +-JSON1_FLAGS = @JSON1_FLAGS@ + LD = @LD@ + LDFLAGS = @LDFLAGS@ + LIBOBJS = @LIBOBJS@ +@@ -305,11 +302,10 @@ + RANLIB = @RANLIB@ + READLINE_LIBS = @READLINE_LIBS@ + SED = @SED@ +-SESSION_FLAGS = @SESSION_FLAGS@ + SET_MAKE = @SET_MAKE@ + SHELL = @SHELL@ ++SHELL_CFLAGS = @SHELL_CFLAGS@ + STRIP = @STRIP@ +-THREADSAFE_FLAGS = @THREADSAFE_FLAGS@ + VERSION = @VERSION@ + abs_builddir = @abs_builddir@ + abs_srcdir = @abs_srcdir@ +@@ -363,7 +359,7 @@ + top_build_prefix = @top_build_prefix@ + top_builddir = @top_builddir@ + top_srcdir = @top_srcdir@ +-AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ @FTS5_FLAGS@ @JSON1_FLAGS@ @SESSION_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE ++AM_CFLAGS = @BUILD_CFLAGS@ + lib_LTLIBRARIES = libsqlite3.la + libsqlite3_la_SOURCES = sqlite3.c + libsqlite3_la_LDFLAGS = -no-undefined -version-info 8:6:8 +@@ -371,9 +367,9 @@ + EXTRA_sqlite3_SOURCES = sqlite3.c + sqlite3_LDADD = @EXTRA_SHELL_OBJ@ @READLINE_LIBS@ + sqlite3_DEPENDENCIES = @EXTRA_SHELL_OBJ@ +-sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS ++sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_STMTVTAB -DSQLITE_ENABLE_DBSTAT_VTAB $(SHELL_CFLAGS) + include_HEADERS = sqlite3.h sqlite3ext.h +-EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt Replace.cs ++EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt Replace.cs Makefile.fallback + pkgconfigdir = ${libdir}/pkgconfig + pkgconfig_DATA = sqlite3.pc + man_MANS = sqlite3.1 +--- contrib/sqlite3/Makefile.msc.orig ++++ contrib/sqlite3/Makefile.msc +@@ -277,6 +277,12 @@ + !IF $(MINIMAL_AMALGAMATION)==0 + OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1 + OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1 ++OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_GEOPOLY=1 ++OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_JSON1=1 ++OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1 ++OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1 ++OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1 ++OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_INTROSPECTION_PRAGMAS=1 + !ENDIF + OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1 + !ENDIF +@@ -561,6 +567,7 @@ + !ENDIF + !ENDIF + ++ + # This is the core library that the shell executable should link with. + # + !IFNDEF SHELL_CORE_LIB +@@ -808,7 +815,7 @@ + # If requested, link to the RPCRT4 library. + # + !IF $(USE_RPCRT4_LIB)!=0 +-LTLINK = $(LTLINK) rpcrt4.lib ++LTLIBS = $(LTLIBS) rpcrt4.lib + !ENDIF + + # If a platform was set, force the linker to target that. +@@ -927,7 +934,9 @@ + # when the shell is not being dynamically linked. + # + !IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0 +-SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_STMTVTAB ++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 + + +@@ -934,8 +943,16 @@ + # This is the default Makefile target. The objects listed here + # are what get build when you type just "make" with no arguments. + # +-all: dll shell ++core: dll shell + ++# Targets that require the Tcl library. ++# ++tcl: $(ALL_TCL_TARGETS) ++ ++# This Makefile target builds all of the standard binaries. ++# ++all: core tcl ++ + # Dynamic link library section. + # + dll: $(SQLITE3DLL) +@@ -954,11 +971,11 @@ + sqlite3.def: Replace.exe $(LIBOBJ) + echo EXPORTS > sqlite3.def + dumpbin /all $(LIBOBJ) \ +- | .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \ ++ | .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup|rebaser)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \ + | sort >> sqlite3.def + +-$(SQLITE3EXE): $(TOP)\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H) +- $(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\shell.c $(SHELL_CORE_SRC) \ ++$(SQLITE3EXE): shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H) ++ $(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) shell.c $(SHELL_CORE_SRC) \ + /link $(SQLITE3EXEPDB) $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS) + + +@@ -973,7 +990,7 @@ + !IF $(USE_RC)!=0 + _HASHCHAR=^# + !IF ![echo !IFNDEF VERSION > rcver.vc] && \ +- ![for /F "delims=" %V in ('type "$(SQLITE3H)" ^| find "$(_HASHCHAR)define SQLITE_VERSION "') do (echo VERSION = ^^%V >> rcver.vc)] && \ ++ ![for /F "delims=" %V in ('type "$(SQLITE3H)" ^| "%SystemRoot%\System32\find.exe" "$(_HASHCHAR)define SQLITE_VERSION "') do (echo VERSION = ^^%V >> rcver.vc)] && \ + ![echo !ENDIF >> rcver.vc] + !INCLUDE rcver.vc + !ENDIF +--- contrib/sqlite3/configure.orig ++++ contrib/sqlite3/configure +@@ -1,6 +1,6 @@ + #! /bin/sh + # Guess values for system-dependent variables and create Makefiles. +-# Generated by GNU Autoconf 2.69 for sqlite 3.20.0. ++# Generated by GNU Autoconf 2.69 for sqlite 3.26.0. + # + # Report bugs to <http://www.sqlite.org>. + # +@@ -590,8 +590,8 @@ + # Identity of this package. + PACKAGE_NAME='sqlite' + PACKAGE_TARNAME='sqlite' +-PACKAGE_VERSION='3.20.0' +-PACKAGE_STRING='sqlite 3.20.0' ++PACKAGE_VERSION='3.26.0' ++PACKAGE_STRING='sqlite 3.26.0' + PACKAGE_BUGREPORT='http://www.sqlite.org' + PACKAGE_URL='' + +@@ -636,12 +636,8 @@ + am__EXEEXT_TRUE + LTLIBOBJS + LIBOBJS ++SHELL_CFLAGS + EXTRA_SHELL_OBJ +-SESSION_FLAGS +-JSON1_FLAGS +-FTS5_FLAGS +-DYNAMIC_EXTENSION_FLAGS +-THREADSAFE_FLAGS + READLINE_LIBS + BUILD_CFLAGS + CPP +@@ -775,9 +771,13 @@ + enable_readline + enable_threadsafe + enable_dynamic_extensions ++enable_fts4 ++enable_fts3 + enable_fts5 + enable_json1 ++enable_rtree + enable_session ++enable_debug + enable_static_shell + ' + ac_precious_vars='build_alias +@@ -1330,7 +1330,7 @@ + # 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.20.0 to adapt to many kinds of systems. ++\`configure' configures sqlite 3.26.0 to adapt to many kinds of systems. + + Usage: $0 [OPTION]... [VAR=VALUE]... + +@@ -1400,7 +1400,7 @@ + + if test -n "$ac_init_help"; then + case $ac_init_help in +- short | recursive ) echo "Configuration of sqlite 3.20.0:";; ++ short | recursive ) echo "Configuration of sqlite 3.26.0:";; + esac + cat <<\_ACEOF + +@@ -1425,9 +1425,13 @@ + --enable-threadsafe build a thread-safe library [default=yes] + --enable-dynamic-extensions + support loadable extensions [default=yes] +- --enable-fts5 include fts5 support [default=no] +- --enable-json1 include json1 support [default=no] ++ --enable-fts4 include fts4 support [default=yes] ++ --enable-fts3 include fts3 support [default=no] ++ --enable-fts5 include fts5 support [default=yes] ++ --enable-json1 include json1 support [default=yes] ++ --enable-rtree include rtree support [default=yes] + --enable-session enable the session extension [default=no] ++ --enable-debug build with debugging features enabled [default=no] + --enable-static-shell statically link libsqlite3 into shell tool + [default=yes] + +@@ -1521,7 +1525,7 @@ + test -n "$ac_init_help" && exit $ac_status + if $ac_init_version; then + cat <<\_ACEOF +-sqlite configure 3.20.0 ++sqlite configure 3.26.0 + generated by GNU Autoconf 2.69 + + Copyright (C) 2012 Free Software Foundation, Inc. +@@ -1936,7 +1940,7 @@ + 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.20.0, which was ++It was created by sqlite $as_me 3.26.0, which was + generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ +@@ -2285,12 +2289,8 @@ + + + +- +-# Use automake. +-am__api_version='1.15' +- + ac_aux_dir= +-for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do ++for ac_dir in . "$srcdir"/.; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" +@@ -2306,7 +2306,7 @@ + fi + done + if test -z "$ac_aux_dir"; then +- as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 ++ as_fn_error $? "cannot find install-sh, install.sh, or shtool in . \"$srcdir\"/." "$LINENO" 5 + fi + + # These three variables are undocumented and unsupported, +@@ -2318,6 +2318,10 @@ + ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + ++ ++# Use automake. ++am__api_version='1.15' ++ + # Find a good install program. We prefer a C program (faster), + # so one script is as good as another. But avoid the broken or + # incompatible versions: +@@ -2802,7 +2806,7 @@ + + # Define the identity of the package. + PACKAGE='sqlite' +- VERSION='3.20.0' ++ VERSION='3.26.0' + + + cat >>confdefs.h <<_ACEOF +@@ -13038,6 +13042,7 @@ + + ac_config_files="$ac_config_files Makefile sqlite3.pc" + ++BUILD_CFLAGS= + + + #------------------------------------------------------------------------- +@@ -13302,9 +13307,8 @@ + enable_threadsafe=yes + fi + +-THREADSAFE_FLAGS=-DSQLITE_THREADSAFE=0 + if test x"$enable_threadsafe" != "xno"; then +- THREADSAFE_FLAGS="-D_REENTRANT=1 -DSQLITE_THREADSAFE=1" ++ BUILD_CFLAGS="$BUILD_CFLAGS -D_REENTRANT=1 -DSQLITE_THREADSAFE=1" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_create" >&5 + $as_echo_n "checking for library containing pthread_create... " >&6; } + if ${ac_cv_search_pthread_create+:} false; then : +@@ -13418,7 +13422,6 @@ + fi + + fi +- + #----------------------------------------------------------------------- + + #----------------------------------------------------------------------- +@@ -13489,16 +13492,43 @@ + fi + + else +- DYNAMIC_EXTENSION_FLAGS=-DSQLITE_OMIT_LOAD_EXTENSION=1 ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_OMIT_LOAD_EXTENSION=1" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for whether to support dynamic extensions" >&5 + $as_echo_n "checking for whether to support dynamic extensions... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_dynamic_extensions" >&5 + $as_echo "$enable_dynamic_extensions" >&6; } ++#----------------------------------------------------------------------- + + #----------------------------------------------------------------------- ++# --enable-fts4 ++# ++# Check whether --enable-fts4 was given. ++if test "${enable_fts4+set}" = set; then : ++ enableval=$enable_fts4; ++else ++ enable_fts4=yes ++fi + ++if test x"$enable_fts4" = "xyes"; then ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS4" ++fi + #----------------------------------------------------------------------- ++ ++#----------------------------------------------------------------------- ++# --enable-fts3 ++# ++# Check whether --enable-fts3 was given. ++if test "${enable_fts3+set}" = set; then : ++ enableval=$enable_fts3; ++fi ++ ++if test x"$enable_fts3" = "xyes" -a x"$enable_fts4" = "xno"; then ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS3" ++fi ++#----------------------------------------------------------------------- ++ ++#----------------------------------------------------------------------- + # --enable-fts5 + # + # Check whether --enable-fts5 was given. +@@ -13505,7 +13535,7 @@ + if test "${enable_fts5+set}" = set; then : + enableval=$enable_fts5; + else +- enable_fts5=no ++ enable_fts5=yes + fi + + if test x"$enable_fts5" = "xyes"; then +@@ -13565,9 +13595,8 @@ + + fi + +- FTS5_FLAGS=-DSQLITE_ENABLE_FTS5 ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS5" + fi +- + #----------------------------------------------------------------------- + + #----------------------------------------------------------------------- +@@ -13577,32 +13606,57 @@ + if test "${enable_json1+set}" = set; then : + enableval=$enable_json1; + else +- enable_json1=no ++ enable_json1=yes + fi + + if test x"$enable_json1" = "xyes"; then +- JSON1_FLAGS=-DSQLITE_ENABLE_JSON1 ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_JSON1" + fi ++#----------------------------------------------------------------------- + + #----------------------------------------------------------------------- ++# --enable-rtree ++# ++# Check whether --enable-rtree was given. ++if test "${enable_rtree+set}" = set; then : ++ enableval=$enable_rtree; ++else ++ enable_rtree=yes ++fi + ++if test x"$enable_rtree" = "xyes"; then ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_RTREE" ++fi + #----------------------------------------------------------------------- ++ ++#----------------------------------------------------------------------- + # --enable-session + # + # Check whether --enable-session was given. + if test "${enable_session+set}" = set; then : + enableval=$enable_session; +-else +- enable_session=no + fi + + if test x"$enable_session" = "xyes"; then +- SESSION_FLAGS="-DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK" ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK" + fi ++#----------------------------------------------------------------------- + + #----------------------------------------------------------------------- ++# --enable-debug ++# ++# Check whether --enable-debug was given. ++if test "${enable_debug+set}" = set; then : ++ enableval=$enable_debug; ++fi + ++if test x"$enable_debug" = "xyes"; then ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_DEBUG -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE" ++ CFLAGS="-g -O0" ++fi + #----------------------------------------------------------------------- ++ ++#----------------------------------------------------------------------- + # --enable-static-shell + # + # Check whether --enable-static-shell was given. +@@ -13631,7 +13685,136 @@ + fi + done + ++for ac_header in zlib.h ++do : ++ ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" ++if test "x$ac_cv_header_zlib_h" = xyes; then : ++ cat >>confdefs.h <<_ACEOF ++#define HAVE_ZLIB_H 1 ++_ACEOF + ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing deflate" >&5 ++$as_echo_n "checking for library containing deflate... " >&6; } ++if ${ac_cv_search_deflate+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_func_search_save_LIBS=$LIBS ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++/* Override any GCC internal prototype to avoid an error. ++ Use char because int might match the return type of a GCC ++ builtin and then its argument prototype would still apply. */ ++#ifdef __cplusplus ++extern "C" ++#endif ++char deflate (); ++int ++main () ++{ ++return deflate (); ++ ; ++ return 0; ++} ++_ACEOF ++for ac_lib in '' z; do ++ if test -z "$ac_lib"; then ++ ac_res="none required" ++ else ++ ac_res=-l$ac_lib ++ LIBS="-l$ac_lib $ac_func_search_save_LIBS" ++ fi ++ if ac_fn_c_try_link "$LINENO"; then : ++ ac_cv_search_deflate=$ac_res ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext ++ if ${ac_cv_search_deflate+:} false; then : ++ break ++fi ++done ++if ${ac_cv_search_deflate+:} false; then : ++ ++else ++ ac_cv_search_deflate=no ++fi ++rm conftest.$ac_ext ++LIBS=$ac_func_search_save_LIBS ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_deflate" >&5 ++$as_echo "$ac_cv_search_deflate" >&6; } ++ac_res=$ac_cv_search_deflate ++if test "$ac_res" != no; then : ++ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_HAVE_ZLIB" ++fi ++ ++ ++fi ++ ++done ++ ++ ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing system" >&5 ++$as_echo_n "checking for library containing system... " >&6; } ++if ${ac_cv_search_system+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_func_search_save_LIBS=$LIBS ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++/* Override any GCC internal prototype to avoid an error. ++ Use char because int might match the return type of a GCC ++ builtin and then its argument prototype would still apply. */ ++#ifdef __cplusplus ++extern "C" ++#endif ++char system (); ++int ++main () ++{ ++return system (); ++ ; ++ return 0; ++} ++_ACEOF ++for ac_lib in '' ; do ++ if test -z "$ac_lib"; then ++ ac_res="none required" ++ else ++ ac_res=-l$ac_lib ++ LIBS="-l$ac_lib $ac_func_search_save_LIBS" ++ fi ++ if ac_fn_c_try_link "$LINENO"; then : ++ ac_cv_search_system=$ac_res ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext ++ if ${ac_cv_search_system+:} false; then : ++ break ++fi ++done ++if ${ac_cv_search_system+:} false; then : ++ ++else ++ ac_cv_search_system=no ++fi ++rm conftest.$ac_ext ++LIBS=$ac_func_search_save_LIBS ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_system" >&5 ++$as_echo "$ac_cv_search_system" >&6; } ++ac_res=$ac_cv_search_system ++if test "$ac_res" != no; then : ++ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" ++ ++else ++ SHELL_CFLAGS="-DSQLITE_NOHAVE_SYSTEM" ++fi ++ ++ ++ + #----------------------------------------------------------------------- + # UPDATE: Maybe it's better if users just set CFLAGS before invoking + # configure. This option doesn't really add much... +@@ -14227,7 +14410,7 @@ + # 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.20.0, which was ++This file was extended by sqlite $as_me 3.26.0, which was + generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES +@@ -14284,7 +14467,7 @@ + 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.20.0 ++sqlite config.status 3.26.0 + configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +--- contrib/sqlite3/configure.ac.orig ++++ contrib/sqlite3/configure.ac +@@ -10,8 +10,9 @@ + # + + AC_PREREQ(2.61) +-AC_INIT(sqlite, 3.20.0, http://www.sqlite.org) ++AC_INIT(sqlite, 3.26.0, http://www.sqlite.org) + AC_CONFIG_SRCDIR([sqlite3.c]) ++AC_CONFIG_AUX_DIR([.]) + + # Use automake. + AM_INIT_AUTOMAKE([foreign]) +@@ -28,6 +29,7 @@ + AC_FUNC_STRERROR_R + + AC_CONFIG_FILES([Makefile sqlite3.pc]) ++BUILD_CFLAGS= + AC_SUBST(BUILD_CFLAGS) + + #------------------------------------------------------------------------- +@@ -85,13 +87,11 @@ + AC_ARG_ENABLE(threadsafe, [AS_HELP_STRING( + [--enable-threadsafe], [build a thread-safe library [default=yes]])], + [], [enable_threadsafe=yes]) +-THREADSAFE_FLAGS=-DSQLITE_THREADSAFE=0 + if test x"$enable_threadsafe" != "xno"; then +- THREADSAFE_FLAGS="-D_REENTRANT=1 -DSQLITE_THREADSAFE=1" ++ BUILD_CFLAGS="$BUILD_CFLAGS -D_REENTRANT=1 -DSQLITE_THREADSAFE=1" + AC_SEARCH_LIBS(pthread_create, pthread) + AC_SEARCH_LIBS(pthread_mutexattr_init, pthread) + fi +-AC_SUBST(THREADSAFE_FLAGS) + #----------------------------------------------------------------------- + + #----------------------------------------------------------------------- +@@ -103,24 +103,44 @@ + if test x"$enable_dynamic_extensions" != "xno"; then + AC_SEARCH_LIBS(dlopen, dl) + else +- DYNAMIC_EXTENSION_FLAGS=-DSQLITE_OMIT_LOAD_EXTENSION=1 ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_OMIT_LOAD_EXTENSION=1" + fi + AC_MSG_CHECKING([for whether to support dynamic extensions]) + AC_MSG_RESULT($enable_dynamic_extensions) +-AC_SUBST(DYNAMIC_EXTENSION_FLAGS) + #----------------------------------------------------------------------- + + #----------------------------------------------------------------------- ++# --enable-fts4 ++# ++AC_ARG_ENABLE(fts4, [AS_HELP_STRING( ++ [--enable-fts4], [include fts4 support [default=yes]])], ++ [], [enable_fts4=yes]) ++if test x"$enable_fts4" = "xyes"; then ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS4" ++fi ++#----------------------------------------------------------------------- ++ ++#----------------------------------------------------------------------- ++# --enable-fts3 ++# ++AC_ARG_ENABLE(fts3, [AS_HELP_STRING( ++ [--enable-fts3], [include fts3 support [default=no]])], ++ [], []) ++if test x"$enable_fts3" = "xyes" -a x"$enable_fts4" = "xno"; then ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS3" ++fi ++#----------------------------------------------------------------------- ++ ++#----------------------------------------------------------------------- + # --enable-fts5 + # + AC_ARG_ENABLE(fts5, [AS_HELP_STRING( +- [--enable-fts5], [include fts5 support [default=no]])], +- [], [enable_fts5=no]) ++ [--enable-fts5], [include fts5 support [default=yes]])], ++ [], [enable_fts5=yes]) + if test x"$enable_fts5" = "xyes"; then + AC_SEARCH_LIBS(log, m) +- FTS5_FLAGS=-DSQLITE_ENABLE_FTS5 ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS5" + fi +-AC_SUBST(FTS5_FLAGS) + #----------------------------------------------------------------------- + + #----------------------------------------------------------------------- +@@ -127,27 +147,48 @@ + # --enable-json1 + # + AC_ARG_ENABLE(json1, [AS_HELP_STRING( +- [--enable-json1], [include json1 support [default=no]])], +- [], [enable_json1=no]) ++ [--enable-json1], [include json1 support [default=yes]])], ++ [],[enable_json1=yes]) + if test x"$enable_json1" = "xyes"; then +- JSON1_FLAGS=-DSQLITE_ENABLE_JSON1 ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_JSON1" + fi +-AC_SUBST(JSON1_FLAGS) + #----------------------------------------------------------------------- + + #----------------------------------------------------------------------- ++# --enable-rtree ++# ++AC_ARG_ENABLE(rtree, [AS_HELP_STRING( ++ [--enable-rtree], [include rtree support [default=yes]])], ++ [], [enable_rtree=yes]) ++if test x"$enable_rtree" = "xyes"; then ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_RTREE" ++fi ++#----------------------------------------------------------------------- ++ ++#----------------------------------------------------------------------- + # --enable-session + # + AC_ARG_ENABLE(session, [AS_HELP_STRING( + [--enable-session], [enable the session extension [default=no]])], +- [], [enable_session=no]) ++ [], []) + if test x"$enable_session" = "xyes"; then +- SESSION_FLAGS="-DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK" ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK" + fi +-AC_SUBST(SESSION_FLAGS) + #----------------------------------------------------------------------- + + #----------------------------------------------------------------------- ++# --enable-debug ++# ++AC_ARG_ENABLE(debug, [AS_HELP_STRING( ++ [--enable-debug], [build with debugging features enabled [default=no]])], ++ [], []) ++if test x"$enable_debug" = "xyes"; then ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_DEBUG -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE" ++ CFLAGS="-g -O0" ++fi ++#----------------------------------------------------------------------- ++ ++#----------------------------------------------------------------------- + # --enable-static-shell + # + AC_ARG_ENABLE(static-shell, [AS_HELP_STRING( +@@ -163,7 +204,13 @@ + #----------------------------------------------------------------------- + + AC_CHECK_FUNCS(posix_fallocate) ++AC_CHECK_HEADERS(zlib.h,[ ++ AC_SEARCH_LIBS(deflate,z,[BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_HAVE_ZLIB"]) ++]) + ++AC_SEARCH_LIBS(system,,,[SHELL_CFLAGS="-DSQLITE_NOHAVE_SYSTEM"]) ++AC_SUBST(SHELL_CFLAGS) ++ + #----------------------------------------------------------------------- + # UPDATE: Maybe it's better if users just set CFLAGS before invoking + # configure. This option doesn't really add much... +--- contrib/sqlite3/shell.c.orig ++++ contrib/sqlite3/shell.c +@@ -79,6 +79,9 @@ + #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 +@@ -90,9 +93,22 @@ + # if !defined(__RTP__) && !defined(_WRS_KERNEL) + # include <pwd.h> + # endif ++#endif ++#if (!defined(_WIN32) && !defined(WIN32)) || defined(__MINGW32__) + # include <unistd.h> +-# include <sys/types.h> ++# include <dirent.h> ++# define GETPID getpid ++# if defined(__MINGW32__) ++# define DIRENT dirent ++# ifndef S_ISLNK ++# define S_ISLNK(mode) (0) ++# endif ++# endif ++#else ++# define GETPID (int)GetCurrentProcessId + #endif ++#include <sys/types.h> ++#include <sys/stat.h> + + #if HAVE_READLINE + # include <readline/readline.h> +@@ -137,6 +153,9 @@ + # ifndef access + # define access(f,m) _access((f),(m)) + # endif ++# ifndef unlink ++# define unlink _unlink ++# endif + # undef popen + # define popen _popen + # undef pclose +@@ -358,6 +377,11 @@ + #define UNUSED_PARAMETER(x) (void)(x) + + /* ++** Number of elements in an array ++*/ ++#define ArraySize(X) (int)(sizeof(X)/sizeof(X[0])) ++ ++/* + ** If the following flag is set, then command execution stops + ** at an error if we are not interactive. + */ +@@ -433,6 +457,12 @@ + # define raw_printf fprintf + #endif + ++/* Indicate out-of-memory and exit. */ ++static void shell_out_of_memory(void){ ++ raw_printf(stderr,"Error: out of memory\n"); ++ exit(1); ++} ++ + /* + ** Write I/O traces to the following stream. + */ +@@ -556,7 +586,7 @@ + if( n+100>nLine ){ + nLine = nLine*2 + 100; + zLine = realloc(zLine, nLine); +- if( zLine==0 ) return 0; ++ if( zLine==0 ) shell_out_of_memory(); + } + if( fgets(&zLine[n], nLine - n, in)==0 ){ + if( n==0 ){ +@@ -583,10 +613,7 @@ + int nTrans = strlen30(zTrans)+1; + if( nTrans>nLine ){ + zLine = realloc(zLine, nTrans); +- if( zLine==0 ){ +- sqlite3_free(zTrans); +- return 0; +- } ++ if( zLine==0 ) shell_out_of_memory(); + } + memcpy(zLine, zTrans, nTrans); + sqlite3_free(zTrans); +@@ -629,7 +656,66 @@ + } + return zResult; + } ++ ++ + /* ++** Return the value of a hexadecimal digit. Return -1 if the input ++** is not a hex digit. ++*/ ++static int hexDigitValue(char c){ ++ if( c>='0' && c<='9' ) return c - '0'; ++ if( c>='a' && c<='f' ) return c - 'a' + 10; ++ if( c>='A' && c<='F' ) return c - 'A' + 10; ++ return -1; ++} ++ ++/* ++** Interpret zArg as an integer value, possibly with suffixes. ++*/ ++static sqlite3_int64 integerValue(const char *zArg){ ++ sqlite3_int64 v = 0; ++ static const struct { char *zSuffix; int iMult; } aMult[] = { ++ { "KiB", 1024 }, ++ { "MiB", 1024*1024 }, ++ { "GiB", 1024*1024*1024 }, ++ { "KB", 1000 }, ++ { "MB", 1000000 }, ++ { "GB", 1000000000 }, ++ { "K", 1000 }, ++ { "M", 1000000 }, ++ { "G", 1000000000 }, ++ }; ++ int i; ++ int isNeg = 0; ++ if( zArg[0]=='-' ){ ++ isNeg = 1; ++ zArg++; ++ }else if( zArg[0]=='+' ){ ++ zArg++; ++ } ++ if( zArg[0]=='0' && zArg[1]=='x' ){ ++ int x; ++ zArg += 2; ++ while( (x = hexDigitValue(zArg[0]))>=0 ){ ++ v = (v<<4) + x; ++ zArg++; ++ } ++ }else{ ++ while( IsDigit(zArg[0]) ){ ++ v = v*10 + zArg[0] - '0'; ++ zArg++; ++ } ++ } ++ for(i=0; i<ArraySize(aMult); i++){ ++ if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){ ++ v *= aMult[i].iMult; ++ break; ++ } ++ } ++ return isNeg? -v : v; ++} ++ ++/* + ** A variable length string to which one can append text. + */ + typedef struct ShellText ShellText; +@@ -674,10 +760,7 @@ + if( p->n+len>=p->nAlloc ){ + p->nAlloc = p->nAlloc*2 + len + 20; + p->z = realloc(p->z, p->nAlloc); +- if( p->z==0 ){ +- memset(p, 0, sizeof(*p)); +- return; +- } ++ if( p->z==0 ) shell_out_of_memory(); + } + + if( quote ){ +@@ -706,48 +789,82 @@ + ** Return '"' if quoting is required. Return 0 if no quoting is required. + */ + static char quoteChar(const char *zName){ +- /* All SQLite keywords, in alphabetical order */ +- static const char *azKeywords[] = { +- "ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS", +- "ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY", +- "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT", +- "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE", +- "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE", +- "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH", +- "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN", +- "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF", +- "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER", +- "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY", +- "LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL", +- "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA", +- "PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP", +- "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT", +- "ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP", +- "TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE", +- "UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE", +- "WITH", "WITHOUT", +- }; +- int i, lwr, upr, mid, c; ++ 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 '"'; + } +- lwr = 0; +- upr = sizeof(azKeywords)/sizeof(azKeywords[0]) - 1; +- while( lwr<=upr ){ +- mid = (lwr+upr)/2; +- c = sqlite3_stricmp(azKeywords[mid], zName); +- if( c==0 ) return '"'; +- if( c<0 ){ +- lwr = mid+1; +- }else{ +- upr = mid-1; +- } ++ return sqlite3_keyword_check(zName, i) ? '"' : 0; ++} ++ ++/* ++** Construct a fake object name and column list to describe the structure ++** of the view, virtual table, or table valued function zSchema.zName. ++*/ ++static char *shellFakeSchema( ++ sqlite3 *db, /* The database connection containing the vtab */ ++ const char *zSchema, /* Schema of the database holding the vtab */ ++ const char *zName /* The name of the virtual table */ ++){ ++ sqlite3_stmt *pStmt = 0; ++ char *zSql; ++ ShellText s; ++ char cQuote; ++ char *zDiv = "("; ++ int nRow = 0; ++ ++ zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;", ++ zSchema ? zSchema : "main", zName); ++ sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); ++ sqlite3_free(zSql); ++ initText(&s); ++ if( zSchema ){ ++ cQuote = quoteChar(zSchema); ++ if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0; ++ appendText(&s, zSchema, cQuote); ++ appendText(&s, ".", 0); + } +- return 0; ++ cQuote = quoteChar(zName); ++ appendText(&s, zName, cQuote); ++ while( sqlite3_step(pStmt)==SQLITE_ROW ){ ++ const char *zCol = (const char*)sqlite3_column_text(pStmt, 1); ++ nRow++; ++ appendText(&s, zDiv, 0); ++ zDiv = ","; ++ cQuote = quoteChar(zCol); ++ appendText(&s, zCol, cQuote); ++ } ++ appendText(&s, ")", 0); ++ sqlite3_finalize(pStmt); ++ if( nRow==0 ){ ++ freeText(&s); ++ s.z = 0; ++ } ++ return s.z; + } + + /* ++** SQL function: shell_module_schema(X) ++** ++** Return a fake schema for the table-valued function or eponymous virtual ++** table X. ++*/ ++static void shellModuleSchema( ++ sqlite3_context *pCtx, ++ int nVal, ++ sqlite3_value **apVal ++){ ++ const char *zName = (const char*)sqlite3_value_text(apVal[0]); ++ char *zFake = shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName); ++ UNUSED_PARAMETER(nVal); ++ if( zFake ){ ++ sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake), ++ -1, sqlite3_free); ++ free(zFake); ++ } ++} ++ ++/* + ** SQL function: shell_add_schema(S,X) + ** + ** Add the schema name X to the CREATE statement in S and return the result. +@@ -782,20 +899,38 @@ + int i = 0; + const char *zIn = (const char*)sqlite3_value_text(apVal[0]); + const char *zSchema = (const char*)sqlite3_value_text(apVal[1]); +- assert( nVal==2 ); ++ const char *zName = (const char*)sqlite3_value_text(apVal[2]); ++ sqlite3 *db = sqlite3_context_db_handle(pCtx); ++ UNUSED_PARAMETER(nVal); + if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){ + for(i=0; i<(int)(sizeof(aPrefix)/sizeof(aPrefix[0])); i++){ + int n = strlen30(aPrefix[i]); + if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){ +- char cQuote = quoteChar(zSchema); +- char *z; +- if( cQuote ){ +- z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8); +- }else{ +- z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8); ++ char *z = 0; ++ char *zFake = 0; ++ if( zSchema ){ ++ char cQuote = quoteChar(zSchema); ++ if( cQuote && sqlite3_stricmp(zSchema,"temp")!=0 ){ ++ z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8); ++ }else{ ++ z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8); ++ } + } +- sqlite3_result_text(pCtx, z, -1, sqlite3_free); +- return; ++ if( zName ++ && aPrefix[i][0]=='V' ++ && (zFake = shellFakeSchema(db, zSchema, zName))!=0 ++ ){ ++ if( z==0 ){ ++ z = sqlite3_mprintf("%s\n/* %s */", zIn, zFake); ++ }else{ ++ z = sqlite3_mprintf("%z\n/* %s */", z, zFake); ++ } ++ free(zFake); ++ } ++ if( z ){ ++ sqlite3_result_text(pCtx, z, -1, sqlite3_free); ++ return; ++ } + } + } + } +@@ -811,6 +946,364 @@ + #define SQLITE_EXTENSION_INIT1 + #define SQLITE_EXTENSION_INIT2(X) (void)(X) + ++#if defined(_WIN32) && defined(_MSC_VER) ++/************************* Begin test_windirent.h ******************/ ++/* ++** 2015 November 30 ++** ++** The author disclaims copyright to this source code. In place of ++** a legal notice, here is a blessing: ++** ++** May you do good and not evil. ++** May you find forgiveness for yourself and forgive others. ++** May you share freely, never taking more than you give. ++** ++************************************************************************* ++** This file contains declarations for most of the opendir() family of ++** POSIX functions on Win32 using the MSVCRT. ++*/ ++ ++#if defined(_WIN32) && defined(_MSC_VER) && !defined(SQLITE_WINDIRENT_H) ++#define SQLITE_WINDIRENT_H ++ ++/* ++** We need several data types from the Windows SDK header. ++*/ ++ ++#ifndef WIN32_LEAN_AND_MEAN ++#define WIN32_LEAN_AND_MEAN ++#endif ++ ++#include "windows.h" ++ ++/* ++** We need several support functions from the SQLite core. ++*/ ++ ++ ++/* ++** We need several things from the ANSI and MSVCRT headers. ++*/ ++ ++#include <stdio.h> ++#include <stdlib.h> ++#include <errno.h> ++#include <io.h> ++#include <limits.h> ++#include <sys/types.h> ++#include <sys/stat.h> ++ ++/* ++** We may need several defines that should have been in "sys/stat.h". ++*/ ++ ++#ifndef S_ISREG ++#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) ++#endif ++ ++#ifndef S_ISDIR ++#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) ++#endif ++ ++#ifndef S_ISLNK ++#define S_ISLNK(mode) (0) ++#endif ++ ++/* ++** We may need to provide the "mode_t" type. ++*/ ++ ++#ifndef MODE_T_DEFINED ++ #define MODE_T_DEFINED ++ typedef unsigned short mode_t; ++#endif ++ ++/* ++** We may need to provide the "ino_t" type. ++*/ ++ ++#ifndef INO_T_DEFINED ++ #define INO_T_DEFINED ++ typedef unsigned short ino_t; ++#endif ++ ++/* ++** We need to define "NAME_MAX" if it was not present in "limits.h". ++*/ ++ ++#ifndef NAME_MAX ++# ifdef FILENAME_MAX ++# define NAME_MAX (FILENAME_MAX) ++# else ++# define NAME_MAX (260) ++# endif ++#endif ++ ++/* ++** We need to define "NULL_INTPTR_T" and "BAD_INTPTR_T". ++*/ ++ ++#ifndef NULL_INTPTR_T ++# define NULL_INTPTR_T ((intptr_t)(0)) ++#endif ++ ++#ifndef BAD_INTPTR_T ++# define BAD_INTPTR_T ((intptr_t)(-1)) ++#endif ++ ++/* ++** We need to provide the necessary structures and related types. ++*/ ++ ++#ifndef DIRENT_DEFINED ++#define DIRENT_DEFINED ++typedef struct DIRENT DIRENT; ++typedef DIRENT *LPDIRENT; ++struct DIRENT { ++ ino_t d_ino; /* Sequence number, do not use. */ ++ unsigned d_attributes; /* Win32 file attributes. */ ++ char d_name[NAME_MAX + 1]; /* Name within the directory. */ ++}; ++#endif ++ ++#ifndef DIR_DEFINED ++#define DIR_DEFINED ++typedef struct DIR DIR; ++typedef DIR *LPDIR; ++struct DIR { ++ intptr_t d_handle; /* Value returned by "_findfirst". */ ++ DIRENT d_first; /* DIRENT constructed based on "_findfirst". */ ++ DIRENT d_next; /* DIRENT constructed based on "_findnext". */ ++}; ++#endif ++ ++/* ++** Provide a macro, for use by the implementation, to determine if a ++** particular directory entry should be skipped over when searching for ++** the next directory entry that should be returned by the readdir() or ++** readdir_r() functions. ++*/ ++ ++#ifndef is_filtered ++# define is_filtered(a) ((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM)) ++#endif ++ ++/* ++** Provide the function prototype for the POSIX compatiable getenv() ++** function. This function is not thread-safe. ++*/ ++ ++extern const char *windirent_getenv(const char *name); ++ ++/* ++** Finally, we can provide the function prototypes for the opendir(), ++** readdir(), readdir_r(), and closedir() POSIX functions. ++*/ ++ ++extern LPDIR opendir(const char *dirname); ++extern LPDIRENT readdir(LPDIR dirp); ++extern INT readdir_r(LPDIR dirp, LPDIRENT entry, LPDIRENT *result); ++extern INT closedir(LPDIR dirp); ++ ++#endif /* defined(WIN32) && defined(_MSC_VER) */ ++ ++/************************* End test_windirent.h ********************/ ++/************************* Begin test_windirent.c ******************/ ++/* ++** 2015 November 30 ++** ++** The author disclaims copyright to this source code. In place of ++** a legal notice, here is a blessing: ++** ++** May you do good and not evil. ++** May you find forgiveness for yourself and forgive others. ++** May you share freely, never taking more than you give. ++** ++************************************************************************* ++** This file contains code to implement most of the opendir() family of ++** POSIX functions on Win32 using the MSVCRT. ++*/ ++ ++#if defined(_WIN32) && defined(_MSC_VER) ++/* #include "test_windirent.h" */ ++ ++/* ++** Implementation of the POSIX getenv() function using the Win32 API. ++** This function is not thread-safe. ++*/ ++const char *windirent_getenv( ++ const char *name ++){ ++ static char value[32768]; /* Maximum length, per MSDN */ ++ DWORD dwSize = sizeof(value) / sizeof(char); /* Size in chars */ ++ DWORD dwRet; /* Value returned by GetEnvironmentVariableA() */ ++ ++ memset(value, 0, sizeof(value)); ++ dwRet = GetEnvironmentVariableA(name, value, dwSize); ++ if( dwRet==0 || dwRet>dwSize ){ ++ /* ++ ** The function call to GetEnvironmentVariableA() failed -OR- ++ ** the buffer is not large enough. Either way, return NULL. ++ */ ++ return 0; ++ }else{ ++ /* ++ ** The function call to GetEnvironmentVariableA() succeeded ++ ** -AND- the buffer contains the entire value. ++ */ ++ return value; ++ } ++} ++ ++/* ++** Implementation of the POSIX opendir() function using the MSVCRT. ++*/ ++LPDIR opendir( ++ const char *dirname ++){ ++ struct _finddata_t data; ++ LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR)); ++ SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]); ++ ++ if( dirp==NULL ) return NULL; ++ memset(dirp, 0, sizeof(DIR)); ++ ++ /* TODO: Remove this if Unix-style root paths are not used. */ ++ if( sqlite3_stricmp(dirname, "/")==0 ){ ++ dirname = windirent_getenv("SystemDrive"); ++ } ++ ++ memset(&data, 0, sizeof(struct _finddata_t)); ++ _snprintf(data.name, namesize, "%s\\*", dirname); ++ dirp->d_handle = _findfirst(data.name, &data); ++ ++ if( dirp->d_handle==BAD_INTPTR_T ){ ++ closedir(dirp); ++ return NULL; ++ } ++ ++ /* TODO: Remove this block to allow hidden and/or system files. */ ++ if( is_filtered(data) ){ ++next: ++ ++ memset(&data, 0, sizeof(struct _finddata_t)); ++ if( _findnext(dirp->d_handle, &data)==-1 ){ ++ closedir(dirp); ++ return NULL; ++ } ++ ++ /* TODO: Remove this block to allow hidden and/or system files. */ ++ if( is_filtered(data) ) goto next; ++ } ++ ++ dirp->d_first.d_attributes = data.attrib; ++ strncpy(dirp->d_first.d_name, data.name, NAME_MAX); ++ dirp->d_first.d_name[NAME_MAX] = '\0'; ++ ++ return dirp; ++} ++ ++/* ++** Implementation of the POSIX readdir() function using the MSVCRT. ++*/ ++LPDIRENT readdir( ++ LPDIR dirp ++){ ++ struct _finddata_t data; ++ ++ if( dirp==NULL ) return NULL; ++ ++ if( dirp->d_first.d_ino==0 ){ ++ dirp->d_first.d_ino++; ++ dirp->d_next.d_ino++; ++ ++ return &dirp->d_first; ++ } ++ ++next: ++ ++ memset(&data, 0, sizeof(struct _finddata_t)); ++ if( _findnext(dirp->d_handle, &data)==-1 ) return NULL; ++ ++ /* TODO: Remove this block to allow hidden and/or system files. */ ++ if( is_filtered(data) ) goto next; ++ ++ dirp->d_next.d_ino++; ++ dirp->d_next.d_attributes = data.attrib; ++ strncpy(dirp->d_next.d_name, data.name, NAME_MAX); ++ dirp->d_next.d_name[NAME_MAX] = '\0'; ++ ++ return &dirp->d_next; ++} ++ ++/* ++** Implementation of the POSIX readdir_r() function using the MSVCRT. ++*/ ++INT readdir_r( ++ LPDIR dirp, ++ LPDIRENT entry, ++ LPDIRENT *result ++){ ++ struct _finddata_t data; ++ ++ if( dirp==NULL ) return EBADF; ++ ++ if( dirp->d_first.d_ino==0 ){ ++ dirp->d_first.d_ino++; ++ dirp->d_next.d_ino++; ++ ++ entry->d_ino = dirp->d_first.d_ino; ++ entry->d_attributes = dirp->d_first.d_attributes; ++ strncpy(entry->d_name, dirp->d_first.d_name, NAME_MAX); ++ entry->d_name[NAME_MAX] = '\0'; ++ ++ *result = entry; ++ return 0; ++ } ++ ++next: ++ ++ memset(&data, 0, sizeof(struct _finddata_t)); ++ if( _findnext(dirp->d_handle, &data)==-1 ){ ++ *result = NULL; ++ return ENOENT; ++ } ++ ++ /* TODO: Remove this block to allow hidden and/or system files. */ ++ if( is_filtered(data) ) goto next; ++ ++ entry->d_ino = (ino_t)-1; /* not available */ ++ entry->d_attributes = data.attrib; ++ strncpy(entry->d_name, data.name, NAME_MAX); ++ entry->d_name[NAME_MAX] = '\0'; ++ ++ *result = entry; ++ return 0; ++} ++ ++/* ++** Implementation of the POSIX closedir() function using the MSVCRT. ++*/ ++INT closedir( ++ LPDIR dirp ++){ ++ INT result = 0; ++ ++ if( dirp==NULL ) return EINVAL; ++ ++ if( dirp->d_handle!=NULL_INTPTR_T && dirp->d_handle!=BAD_INTPTR_T ){ ++ result = _findclose(dirp->d_handle); ++ } ++ ++ sqlite3_free(dirp); ++ return result; ++} ++ ++#endif /* defined(WIN32) && defined(_MSC_VER) */ ++ ++/************************* End test_windirent.c ********************/ ++#define dirent DIRENT ++#endif + /************************* Begin ../ext/misc/shathree.c ******************/ + /* + ** 2017-03-08 +@@ -824,7 +1317,7 @@ + ** + ****************************************************************************** + ** +-** This SQLite extension implements a functions that compute SHA1 hashes. ++** This SQLite extension implements functions that compute SHA3 hashes. + ** Two SQL functions are implemented: + ** + ** sha3(X,SIZE) +@@ -844,7 +1337,7 @@ + #include <assert.h> + #include <string.h> + #include <stdarg.h> +-typedef sqlite3_uint64 u64; ++/* typedef sqlite3_uint64 u64; */ + + /****************************************************************************** + ** The Hash Engine +@@ -891,9 +1384,9 @@ + */ + static void KeccakF1600Step(SHA3Context *p){ + int i; +- u64 B0, B1, B2, B3, B4; +- u64 C0, C1, C2, C3, C4; +- u64 D0, D1, D2, D3, D4; ++ u64 b0, b1, b2, b3, b4; ++ u64 c0, c1, c2, c3, c4; ++ u64 d0, d1, d2, d3, d4; + static const u64 RC[] = { + 0x0000000000000001ULL, 0x0000000000008082ULL, + 0x800000000000808aULL, 0x8000000080008000ULL, +@@ -908,301 +1401,301 @@ + 0x8000000080008081ULL, 0x8000000000008080ULL, + 0x0000000080000001ULL, 0x8000000080008008ULL + }; +-# define A00 (p->u.s[0]) +-# define A01 (p->u.s[1]) +-# define A02 (p->u.s[2]) +-# define A03 (p->u.s[3]) +-# define A04 (p->u.s[4]) +-# define A10 (p->u.s[5]) +-# define A11 (p->u.s[6]) +-# define A12 (p->u.s[7]) +-# define A13 (p->u.s[8]) +-# define A14 (p->u.s[9]) +-# define A20 (p->u.s[10]) +-# define A21 (p->u.s[11]) +-# define A22 (p->u.s[12]) +-# define A23 (p->u.s[13]) +-# define A24 (p->u.s[14]) +-# define A30 (p->u.s[15]) +-# define A31 (p->u.s[16]) +-# define A32 (p->u.s[17]) +-# define A33 (p->u.s[18]) +-# define A34 (p->u.s[19]) +-# define A40 (p->u.s[20]) +-# define A41 (p->u.s[21]) +-# define A42 (p->u.s[22]) +-# define A43 (p->u.s[23]) +-# define A44 (p->u.s[24]) ++# define a00 (p->u.s[0]) ++# define a01 (p->u.s[1]) ++# define a02 (p->u.s[2]) ++# define a03 (p->u.s[3]) ++# define a04 (p->u.s[4]) ++# define a10 (p->u.s[5]) ++# define a11 (p->u.s[6]) ++# define a12 (p->u.s[7]) ++# define a13 (p->u.s[8]) ++# define a14 (p->u.s[9]) ++# define a20 (p->u.s[10]) ++# define a21 (p->u.s[11]) ++# define a22 (p->u.s[12]) ++# define a23 (p->u.s[13]) ++# define a24 (p->u.s[14]) ++# define a30 (p->u.s[15]) ++# define a31 (p->u.s[16]) ++# define a32 (p->u.s[17]) ++# define a33 (p->u.s[18]) ++# define a34 (p->u.s[19]) ++# define a40 (p->u.s[20]) ++# define a41 (p->u.s[21]) ++# define a42 (p->u.s[22]) ++# define a43 (p->u.s[23]) ++# define a44 (p->u.s[24]) + # define ROL64(a,x) ((a<<x)|(a>>(64-x))) + + for(i=0; i<24; i+=4){ +- C0 = A00^A10^A20^A30^A40; +- C1 = A01^A11^A21^A31^A41; +- C2 = A02^A12^A22^A32^A42; +- C3 = A03^A13^A23^A33^A43; +- C4 = A04^A14^A24^A34^A44; +- D0 = C4^ROL64(C1, 1); +- D1 = C0^ROL64(C2, 1); +- D2 = C1^ROL64(C3, 1); +- D3 = C2^ROL64(C4, 1); +- D4 = C3^ROL64(C0, 1); ++ c0 = a00^a10^a20^a30^a40; ++ c1 = a01^a11^a21^a31^a41; ++ c2 = a02^a12^a22^a32^a42; ++ c3 = a03^a13^a23^a33^a43; ++ c4 = a04^a14^a24^a34^a44; ++ d0 = c4^ROL64(c1, 1); ++ d1 = c0^ROL64(c2, 1); ++ d2 = c1^ROL64(c3, 1); ++ d3 = c2^ROL64(c4, 1); ++ d4 = c3^ROL64(c0, 1); + +- B0 = (A00^D0); +- B1 = ROL64((A11^D1), 44); +- B2 = ROL64((A22^D2), 43); +- B3 = ROL64((A33^D3), 21); +- B4 = ROL64((A44^D4), 14); +- A00 = B0 ^((~B1)& B2 ); +- A00 ^= RC[i]; +- A11 = B1 ^((~B2)& B3 ); +- A22 = B2 ^((~B3)& B4 ); +- A33 = B3 ^((~B4)& B0 ); +- A44 = B4 ^((~B0)& B1 ); ++ b0 = (a00^d0); ++ b1 = ROL64((a11^d1), 44); ++ b2 = ROL64((a22^d2), 43); ++ b3 = ROL64((a33^d3), 21); ++ b4 = ROL64((a44^d4), 14); ++ a00 = b0 ^((~b1)& b2 ); ++ a00 ^= RC[i]; ++ a11 = b1 ^((~b2)& b3 ); ++ a22 = b2 ^((~b3)& b4 ); ++ a33 = b3 ^((~b4)& b0 ); ++ a44 = b4 ^((~b0)& b1 ); + +- B2 = ROL64((A20^D0), 3); +- B3 = ROL64((A31^D1), 45); +- B4 = ROL64((A42^D2), 61); +- B0 = ROL64((A03^D3), 28); +- B1 = ROL64((A14^D4), 20); +- A20 = B0 ^((~B1)& B2 ); +- A31 = B1 ^((~B2)& B3 ); +- A42 = B2 ^((~B3)& B4 ); +- A03 = B3 ^((~B4)& B0 ); +- A14 = B4 ^((~B0)& B1 ); ++ b2 = ROL64((a20^d0), 3); ++ b3 = ROL64((a31^d1), 45); ++ b4 = ROL64((a42^d2), 61); ++ b0 = ROL64((a03^d3), 28); ++ b1 = ROL64((a14^d4), 20); ++ a20 = b0 ^((~b1)& b2 ); ++ a31 = b1 ^((~b2)& b3 ); ++ a42 = b2 ^((~b3)& b4 ); ++ a03 = b3 ^((~b4)& b0 ); ++ a14 = b4 ^((~b0)& b1 ); + +- B4 = ROL64((A40^D0), 18); +- B0 = ROL64((A01^D1), 1); +- B1 = ROL64((A12^D2), 6); +- B2 = ROL64((A23^D3), 25); +- B3 = ROL64((A34^D4), 8); +- A40 = B0 ^((~B1)& B2 ); +- A01 = B1 ^((~B2)& B3 ); +- A12 = B2 ^((~B3)& B4 ); +- A23 = B3 ^((~B4)& B0 ); +- A34 = B4 ^((~B0)& B1 ); ++ b4 = ROL64((a40^d0), 18); ++ b0 = ROL64((a01^d1), 1); ++ b1 = ROL64((a12^d2), 6); ++ b2 = ROL64((a23^d3), 25); ++ b3 = ROL64((a34^d4), 8); ++ a40 = b0 ^((~b1)& b2 ); ++ a01 = b1 ^((~b2)& b3 ); ++ a12 = b2 ^((~b3)& b4 ); ++ a23 = b3 ^((~b4)& b0 ); ++ a34 = b4 ^((~b0)& b1 ); + +- B1 = ROL64((A10^D0), 36); +- B2 = ROL64((A21^D1), 10); +- B3 = ROL64((A32^D2), 15); +- B4 = ROL64((A43^D3), 56); +- B0 = ROL64((A04^D4), 27); +- A10 = B0 ^((~B1)& B2 ); +- A21 = B1 ^((~B2)& B3 ); +- A32 = B2 ^((~B3)& B4 ); +- A43 = B3 ^((~B4)& B0 ); +- A04 = B4 ^((~B0)& B1 ); ++ b1 = ROL64((a10^d0), 36); ++ b2 = ROL64((a21^d1), 10); ++ b3 = ROL64((a32^d2), 15); ++ b4 = ROL64((a43^d3), 56); ++ b0 = ROL64((a04^d4), 27); ++ a10 = b0 ^((~b1)& b2 ); ++ a21 = b1 ^((~b2)& b3 ); ++ a32 = b2 ^((~b3)& b4 ); ++ a43 = b3 ^((~b4)& b0 ); ++ a04 = b4 ^((~b0)& b1 ); + +- B3 = ROL64((A30^D0), 41); +- B4 = ROL64((A41^D1), 2); +- B0 = ROL64((A02^D2), 62); +- B1 = ROL64((A13^D3), 55); +- B2 = ROL64((A24^D4), 39); +- A30 = B0 ^((~B1)& B2 ); +- A41 = B1 ^((~B2)& B3 ); +- A02 = B2 ^((~B3)& B4 ); +- A13 = B3 ^((~B4)& B0 ); +- A24 = B4 ^((~B0)& B1 ); ++ b3 = ROL64((a30^d0), 41); ++ b4 = ROL64((a41^d1), 2); ++ b0 = ROL64((a02^d2), 62); ++ b1 = ROL64((a13^d3), 55); ++ b2 = ROL64((a24^d4), 39); ++ a30 = b0 ^((~b1)& b2 ); ++ a41 = b1 ^((~b2)& b3 ); ++ a02 = b2 ^((~b3)& b4 ); ++ a13 = b3 ^((~b4)& b0 ); ++ a24 = b4 ^((~b0)& b1 ); + +- C0 = A00^A20^A40^A10^A30; +- C1 = A11^A31^A01^A21^A41; +- C2 = A22^A42^A12^A32^A02; +- C3 = A33^A03^A23^A43^A13; +- C4 = A44^A14^A34^A04^A24; +- D0 = C4^ROL64(C1, 1); +- D1 = C0^ROL64(C2, 1); +- D2 = C1^ROL64(C3, 1); +- D3 = C2^ROL64(C4, 1); +- D4 = C3^ROL64(C0, 1); ++ c0 = a00^a20^a40^a10^a30; ++ c1 = a11^a31^a01^a21^a41; ++ c2 = a22^a42^a12^a32^a02; ++ c3 = a33^a03^a23^a43^a13; ++ c4 = a44^a14^a34^a04^a24; ++ d0 = c4^ROL64(c1, 1); ++ d1 = c0^ROL64(c2, 1); ++ d2 = c1^ROL64(c3, 1); ++ d3 = c2^ROL64(c4, 1); ++ d4 = c3^ROL64(c0, 1); + +- B0 = (A00^D0); +- B1 = ROL64((A31^D1), 44); +- B2 = ROL64((A12^D2), 43); +- B3 = ROL64((A43^D3), 21); +- B4 = ROL64((A24^D4), 14); +- A00 = B0 ^((~B1)& B2 ); +- A00 ^= RC[i+1]; +- A31 = B1 ^((~B2)& B3 ); +- A12 = B2 ^((~B3)& B4 ); +- A43 = B3 ^((~B4)& B0 ); +- A24 = B4 ^((~B0)& B1 ); ++ b0 = (a00^d0); ++ b1 = ROL64((a31^d1), 44); ++ b2 = ROL64((a12^d2), 43); ++ b3 = ROL64((a43^d3), 21); ++ b4 = ROL64((a24^d4), 14); ++ a00 = b0 ^((~b1)& b2 ); ++ a00 ^= RC[i+1]; ++ a31 = b1 ^((~b2)& b3 ); ++ a12 = b2 ^((~b3)& b4 ); ++ a43 = b3 ^((~b4)& b0 ); ++ a24 = b4 ^((~b0)& b1 ); + +- B2 = ROL64((A40^D0), 3); +- B3 = ROL64((A21^D1), 45); +- B4 = ROL64((A02^D2), 61); +- B0 = ROL64((A33^D3), 28); +- B1 = ROL64((A14^D4), 20); +- A40 = B0 ^((~B1)& B2 ); +- A21 = B1 ^((~B2)& B3 ); +- A02 = B2 ^((~B3)& B4 ); +- A33 = B3 ^((~B4)& B0 ); +- A14 = B4 ^((~B0)& B1 ); ++ b2 = ROL64((a40^d0), 3); ++ b3 = ROL64((a21^d1), 45); ++ b4 = ROL64((a02^d2), 61); ++ b0 = ROL64((a33^d3), 28); ++ b1 = ROL64((a14^d4), 20); ++ a40 = b0 ^((~b1)& b2 ); ++ a21 = b1 ^((~b2)& b3 ); ++ a02 = b2 ^((~b3)& b4 ); ++ a33 = b3 ^((~b4)& b0 ); ++ a14 = b4 ^((~b0)& b1 ); + +- B4 = ROL64((A30^D0), 18); +- B0 = ROL64((A11^D1), 1); +- B1 = ROL64((A42^D2), 6); +- B2 = ROL64((A23^D3), 25); +- B3 = ROL64((A04^D4), 8); +- A30 = B0 ^((~B1)& B2 ); +- A11 = B1 ^((~B2)& B3 ); +- A42 = B2 ^((~B3)& B4 ); +- A23 = B3 ^((~B4)& B0 ); +- A04 = B4 ^((~B0)& B1 ); ++ b4 = ROL64((a30^d0), 18); ++ b0 = ROL64((a11^d1), 1); ++ b1 = ROL64((a42^d2), 6); ++ b2 = ROL64((a23^d3), 25); ++ b3 = ROL64((a04^d4), 8); ++ a30 = b0 ^((~b1)& b2 ); ++ a11 = b1 ^((~b2)& b3 ); ++ a42 = b2 ^((~b3)& b4 ); ++ a23 = b3 ^((~b4)& b0 ); ++ a04 = b4 ^((~b0)& b1 ); + +- B1 = ROL64((A20^D0), 36); +- B2 = ROL64((A01^D1), 10); +- B3 = ROL64((A32^D2), 15); +- B4 = ROL64((A13^D3), 56); +- B0 = ROL64((A44^D4), 27); +- A20 = B0 ^((~B1)& B2 ); +- A01 = B1 ^((~B2)& B3 ); +- A32 = B2 ^((~B3)& B4 ); +- A13 = B3 ^((~B4)& B0 ); +- A44 = B4 ^((~B0)& B1 ); ++ b1 = ROL64((a20^d0), 36); ++ b2 = ROL64((a01^d1), 10); ++ b3 = ROL64((a32^d2), 15); ++ b4 = ROL64((a13^d3), 56); ++ b0 = ROL64((a44^d4), 27); ++ a20 = b0 ^((~b1)& b2 ); ++ a01 = b1 ^((~b2)& b3 ); ++ a32 = b2 ^((~b3)& b4 ); ++ a13 = b3 ^((~b4)& b0 ); ++ a44 = b4 ^((~b0)& b1 ); + +- B3 = ROL64((A10^D0), 41); +- B4 = ROL64((A41^D1), 2); +- B0 = ROL64((A22^D2), 62); +- B1 = ROL64((A03^D3), 55); +- B2 = ROL64((A34^D4), 39); +- A10 = B0 ^((~B1)& B2 ); +- A41 = B1 ^((~B2)& B3 ); +- A22 = B2 ^((~B3)& B4 ); +- A03 = B3 ^((~B4)& B0 ); +- A34 = B4 ^((~B0)& B1 ); ++ b3 = ROL64((a10^d0), 41); ++ b4 = ROL64((a41^d1), 2); ++ b0 = ROL64((a22^d2), 62); ++ b1 = ROL64((a03^d3), 55); ++ b2 = ROL64((a34^d4), 39); ++ a10 = b0 ^((~b1)& b2 ); ++ a41 = b1 ^((~b2)& b3 ); ++ a22 = b2 ^((~b3)& b4 ); ++ a03 = b3 ^((~b4)& b0 ); ++ a34 = b4 ^((~b0)& b1 ); + +- C0 = A00^A40^A30^A20^A10; +- C1 = A31^A21^A11^A01^A41; +- C2 = A12^A02^A42^A32^A22; +- C3 = A43^A33^A23^A13^A03; +- C4 = A24^A14^A04^A44^A34; +- D0 = C4^ROL64(C1, 1); +- D1 = C0^ROL64(C2, 1); +- D2 = C1^ROL64(C3, 1); +- D3 = C2^ROL64(C4, 1); +- D4 = C3^ROL64(C0, 1); ++ c0 = a00^a40^a30^a20^a10; ++ c1 = a31^a21^a11^a01^a41; ++ c2 = a12^a02^a42^a32^a22; ++ c3 = a43^a33^a23^a13^a03; ++ c4 = a24^a14^a04^a44^a34; ++ d0 = c4^ROL64(c1, 1); ++ d1 = c0^ROL64(c2, 1); ++ d2 = c1^ROL64(c3, 1); ++ d3 = c2^ROL64(c4, 1); ++ d4 = c3^ROL64(c0, 1); + +- B0 = (A00^D0); +- B1 = ROL64((A21^D1), 44); +- B2 = ROL64((A42^D2), 43); +- B3 = ROL64((A13^D3), 21); +- B4 = ROL64((A34^D4), 14); +- A00 = B0 ^((~B1)& B2 ); +- A00 ^= RC[i+2]; +- A21 = B1 ^((~B2)& B3 ); +- A42 = B2 ^((~B3)& B4 ); +- A13 = B3 ^((~B4)& B0 ); +- A34 = B4 ^((~B0)& B1 ); ++ b0 = (a00^d0); ++ b1 = ROL64((a21^d1), 44); ++ b2 = ROL64((a42^d2), 43); ++ b3 = ROL64((a13^d3), 21); ++ b4 = ROL64((a34^d4), 14); ++ a00 = b0 ^((~b1)& b2 ); ++ a00 ^= RC[i+2]; ++ a21 = b1 ^((~b2)& b3 ); ++ a42 = b2 ^((~b3)& b4 ); ++ a13 = b3 ^((~b4)& b0 ); ++ a34 = b4 ^((~b0)& b1 ); + +- B2 = ROL64((A30^D0), 3); +- B3 = ROL64((A01^D1), 45); +- B4 = ROL64((A22^D2), 61); +- B0 = ROL64((A43^D3), 28); +- B1 = ROL64((A14^D4), 20); +- A30 = B0 ^((~B1)& B2 ); +- A01 = B1 ^((~B2)& B3 ); +- A22 = B2 ^((~B3)& B4 ); +- A43 = B3 ^((~B4)& B0 ); +- A14 = B4 ^((~B0)& B1 ); ++ b2 = ROL64((a30^d0), 3); ++ b3 = ROL64((a01^d1), 45); ++ b4 = ROL64((a22^d2), 61); ++ b0 = ROL64((a43^d3), 28); ++ b1 = ROL64((a14^d4), 20); ++ a30 = b0 ^((~b1)& b2 ); ++ a01 = b1 ^((~b2)& b3 ); ++ a22 = b2 ^((~b3)& b4 ); ++ a43 = b3 ^((~b4)& b0 ); ++ a14 = b4 ^((~b0)& b1 ); + +- B4 = ROL64((A10^D0), 18); +- B0 = ROL64((A31^D1), 1); +- B1 = ROL64((A02^D2), 6); +- B2 = ROL64((A23^D3), 25); +- B3 = ROL64((A44^D4), 8); +- A10 = B0 ^((~B1)& B2 ); +- A31 = B1 ^((~B2)& B3 ); +- A02 = B2 ^((~B3)& B4 ); +- A23 = B3 ^((~B4)& B0 ); +- A44 = B4 ^((~B0)& B1 ); ++ b4 = ROL64((a10^d0), 18); ++ b0 = ROL64((a31^d1), 1); ++ b1 = ROL64((a02^d2), 6); ++ b2 = ROL64((a23^d3), 25); ++ b3 = ROL64((a44^d4), 8); ++ a10 = b0 ^((~b1)& b2 ); ++ a31 = b1 ^((~b2)& b3 ); ++ a02 = b2 ^((~b3)& b4 ); ++ a23 = b3 ^((~b4)& b0 ); ++ a44 = b4 ^((~b0)& b1 ); + +- B1 = ROL64((A40^D0), 36); +- B2 = ROL64((A11^D1), 10); +- B3 = ROL64((A32^D2), 15); +- B4 = ROL64((A03^D3), 56); +- B0 = ROL64((A24^D4), 27); +- A40 = B0 ^((~B1)& B2 ); +- A11 = B1 ^((~B2)& B3 ); +- A32 = B2 ^((~B3)& B4 ); +- A03 = B3 ^((~B4)& B0 ); +- A24 = B4 ^((~B0)& B1 ); ++ b1 = ROL64((a40^d0), 36); ++ b2 = ROL64((a11^d1), 10); ++ b3 = ROL64((a32^d2), 15); ++ b4 = ROL64((a03^d3), 56); ++ b0 = ROL64((a24^d4), 27); ++ a40 = b0 ^((~b1)& b2 ); ++ a11 = b1 ^((~b2)& b3 ); ++ a32 = b2 ^((~b3)& b4 ); ++ a03 = b3 ^((~b4)& b0 ); ++ a24 = b4 ^((~b0)& b1 ); + +- B3 = ROL64((A20^D0), 41); +- B4 = ROL64((A41^D1), 2); +- B0 = ROL64((A12^D2), 62); +- B1 = ROL64((A33^D3), 55); +- B2 = ROL64((A04^D4), 39); +- A20 = B0 ^((~B1)& B2 ); +- A41 = B1 ^((~B2)& B3 ); +- A12 = B2 ^((~B3)& B4 ); +- A33 = B3 ^((~B4)& B0 ); +- A04 = B4 ^((~B0)& B1 ); ++ b3 = ROL64((a20^d0), 41); ++ b4 = ROL64((a41^d1), 2); ++ b0 = ROL64((a12^d2), 62); ++ b1 = ROL64((a33^d3), 55); ++ b2 = ROL64((a04^d4), 39); ++ a20 = b0 ^((~b1)& b2 ); ++ a41 = b1 ^((~b2)& b3 ); ++ a12 = b2 ^((~b3)& b4 ); ++ a33 = b3 ^((~b4)& b0 ); ++ a04 = b4 ^((~b0)& b1 ); + +- C0 = A00^A30^A10^A40^A20; +- C1 = A21^A01^A31^A11^A41; +- C2 = A42^A22^A02^A32^A12; +- C3 = A13^A43^A23^A03^A33; +- C4 = A34^A14^A44^A24^A04; +- D0 = C4^ROL64(C1, 1); +- D1 = C0^ROL64(C2, 1); +- D2 = C1^ROL64(C3, 1); +- D3 = C2^ROL64(C4, 1); +- D4 = C3^ROL64(C0, 1); ++ c0 = a00^a30^a10^a40^a20; ++ c1 = a21^a01^a31^a11^a41; ++ c2 = a42^a22^a02^a32^a12; ++ c3 = a13^a43^a23^a03^a33; ++ c4 = a34^a14^a44^a24^a04; ++ d0 = c4^ROL64(c1, 1); ++ d1 = c0^ROL64(c2, 1); ++ d2 = c1^ROL64(c3, 1); ++ d3 = c2^ROL64(c4, 1); ++ d4 = c3^ROL64(c0, 1); + +- B0 = (A00^D0); +- B1 = ROL64((A01^D1), 44); +- B2 = ROL64((A02^D2), 43); +- B3 = ROL64((A03^D3), 21); +- B4 = ROL64((A04^D4), 14); +- A00 = B0 ^((~B1)& B2 ); +- A00 ^= RC[i+3]; +- A01 = B1 ^((~B2)& B3 ); +- A02 = B2 ^((~B3)& B4 ); +- A03 = B3 ^((~B4)& B0 ); +- A04 = B4 ^((~B0)& B1 ); ++ b0 = (a00^d0); ++ b1 = ROL64((a01^d1), 44); ++ b2 = ROL64((a02^d2), 43); ++ b3 = ROL64((a03^d3), 21); ++ b4 = ROL64((a04^d4), 14); ++ a00 = b0 ^((~b1)& b2 ); ++ a00 ^= RC[i+3]; ++ a01 = b1 ^((~b2)& b3 ); ++ a02 = b2 ^((~b3)& b4 ); ++ a03 = b3 ^((~b4)& b0 ); ++ a04 = b4 ^((~b0)& b1 ); + +- B2 = ROL64((A10^D0), 3); +- B3 = ROL64((A11^D1), 45); +- B4 = ROL64((A12^D2), 61); +- B0 = ROL64((A13^D3), 28); +- B1 = ROL64((A14^D4), 20); +- A10 = B0 ^((~B1)& B2 ); +- A11 = B1 ^((~B2)& B3 ); +- A12 = B2 ^((~B3)& B4 ); +- A13 = B3 ^((~B4)& B0 ); +- A14 = B4 ^((~B0)& B1 ); ++ b2 = ROL64((a10^d0), 3); ++ b3 = ROL64((a11^d1), 45); ++ b4 = ROL64((a12^d2), 61); ++ b0 = ROL64((a13^d3), 28); ++ b1 = ROL64((a14^d4), 20); ++ a10 = b0 ^((~b1)& b2 ); ++ a11 = b1 ^((~b2)& b3 ); ++ a12 = b2 ^((~b3)& b4 ); ++ a13 = b3 ^((~b4)& b0 ); ++ a14 = b4 ^((~b0)& b1 ); + +- B4 = ROL64((A20^D0), 18); +- B0 = ROL64((A21^D1), 1); +- B1 = ROL64((A22^D2), 6); +- B2 = ROL64((A23^D3), 25); +- B3 = ROL64((A24^D4), 8); +- A20 = B0 ^((~B1)& B2 ); +- A21 = B1 ^((~B2)& B3 ); +- A22 = B2 ^((~B3)& B4 ); +- A23 = B3 ^((~B4)& B0 ); +- A24 = B4 ^((~B0)& B1 ); ++ b4 = ROL64((a20^d0), 18); ++ b0 = ROL64((a21^d1), 1); ++ b1 = ROL64((a22^d2), 6); ++ b2 = ROL64((a23^d3), 25); ++ b3 = ROL64((a24^d4), 8); ++ a20 = b0 ^((~b1)& b2 ); ++ a21 = b1 ^((~b2)& b3 ); ++ a22 = b2 ^((~b3)& b4 ); ++ a23 = b3 ^((~b4)& b0 ); ++ a24 = b4 ^((~b0)& b1 ); + +- B1 = ROL64((A30^D0), 36); +- B2 = ROL64((A31^D1), 10); +- B3 = ROL64((A32^D2), 15); +- B4 = ROL64((A33^D3), 56); +- B0 = ROL64((A34^D4), 27); +- A30 = B0 ^((~B1)& B2 ); +- A31 = B1 ^((~B2)& B3 ); +- A32 = B2 ^((~B3)& B4 ); +- A33 = B3 ^((~B4)& B0 ); +- A34 = B4 ^((~B0)& B1 ); ++ b1 = ROL64((a30^d0), 36); ++ b2 = ROL64((a31^d1), 10); ++ b3 = ROL64((a32^d2), 15); ++ b4 = ROL64((a33^d3), 56); ++ b0 = ROL64((a34^d4), 27); ++ a30 = b0 ^((~b1)& b2 ); ++ a31 = b1 ^((~b2)& b3 ); ++ a32 = b2 ^((~b3)& b4 ); ++ a33 = b3 ^((~b4)& b0 ); ++ a34 = b4 ^((~b0)& b1 ); + +- B3 = ROL64((A40^D0), 41); +- B4 = ROL64((A41^D1), 2); +- B0 = ROL64((A42^D2), 62); +- B1 = ROL64((A43^D3), 55); +- B2 = ROL64((A44^D4), 39); +- A40 = B0 ^((~B1)& B2 ); +- A41 = B1 ^((~B2)& B3 ); +- A42 = B2 ^((~B3)& B4 ); +- A43 = B3 ^((~B4)& B0 ); +- A44 = B4 ^((~B0)& B1 ); ++ b3 = ROL64((a40^d0), 41); ++ b4 = ROL64((a41^d1), 2); ++ b0 = ROL64((a42^d2), 62); ++ b1 = ROL64((a43^d3), 55); ++ b2 = ROL64((a44^d4), 39); ++ a40 = b0 ^((~b1)& b2 ); ++ a41 = b1 ^((~b2)& b3 ); ++ a42 = b2 ^((~b3)& b4 ); ++ a43 = b3 ^((~b4)& b0 ); ++ a44 = b4 ^((~b0)& b1 ); + } + } + +@@ -1499,7 +1992,7 @@ + + + #ifdef _WIN32 +-__declspec(dllexport) ++ + #endif + int sqlite3_shathree_init( + sqlite3 *db, +@@ -1541,29 +2034,122 @@ + ****************************************************************************** + ** + ** This SQLite extension implements SQL functions readfile() and +-** writefile(). ++** writefile(), and eponymous virtual type "fsdir". ++** ++** WRITEFILE(FILE, DATA [, MODE [, MTIME]]): ++** ++** If neither of the optional arguments is present, then this UDF ++** function writes blob DATA to file FILE. If successful, the number ++** of bytes written is returned. If an error occurs, NULL is returned. ++** ++** If the first option argument - MODE - is present, then it must ++** be passed an integer value that corresponds to a POSIX mode ++** value (file type + permissions, as returned in the stat.st_mode ++** field by the stat() system call). Three types of files may ++** be written/created: ++** ++** regular files: (mode & 0170000)==0100000 ++** symbolic links: (mode & 0170000)==0120000 ++** directories: (mode & 0170000)==0040000 ++** ++** For a directory, the DATA is ignored. For a symbolic link, it is ++** interpreted as text and used as the target of the link. For a ++** regular file, it is interpreted as a blob and written into the ++** named file. Regardless of the type of file, its permissions are ++** set to (mode & 0777) before returning. ++** ++** If the optional MTIME argument is present, then it is interpreted ++** as an integer - the number of seconds since the unix epoch. The ++** modification-time of the target file is set to this value before ++** returning. ++** ++** If three or more arguments are passed to this function and an ++** error is encountered, an exception is raised. ++** ++** READFILE(FILE): ++** ++** Read and return the contents of file FILE (type blob) from disk. ++** ++** FSDIR: ++** ++** Used as follows: ++** ++** SELECT * FROM fsdir($path [, $dir]); ++** ++** Parameter $path is an absolute or relative pathname. If the file that it ++** refers to does not exist, it is an error. If the path refers to a regular ++** file or symbolic link, it returns a single row. Or, if the path refers ++** to a directory, it returns one row for the directory, and one row for each ++** file within the hierarchy rooted at $path. ++** ++** Each row has the following columns: ++** ++** name: Path to file or directory (text value). ++** mode: Value of stat.st_mode for directory entry (an integer). ++** mtime: Value of stat.st_mtime for directory entry (an integer). ++** data: For a regular file, a blob containing the file data. For a ++** symlink, a text value containing the text of the link. For a ++** directory, NULL. ++** ++** If a non-NULL value is specified for the optional $dir parameter and ++** $path is a relative path, then $path is interpreted relative to $dir. ++** And the paths returned in the "name" column of the table are also ++** relative to directory $dir. + */ + SQLITE_EXTENSION_INIT1 + #include <stdio.h> ++#include <string.h> ++#include <assert.h> + ++#include <sys/types.h> ++#include <sys/stat.h> ++#include <fcntl.h> ++#if !defined(_WIN32) && !defined(WIN32) ++# include <unistd.h> ++# include <dirent.h> ++# include <utime.h> ++# include <sys/time.h> ++#else ++# include "windows.h" ++# include <io.h> ++# include <direct.h> ++/* # include "test_windirent.h" */ ++# define dirent DIRENT ++# ifndef chmod ++# define chmod _chmod ++# endif ++# ifndef stat ++# define stat _stat ++# endif ++# define mkdir(path,mode) _mkdir(path) ++# define lstat(path,buf) stat(path,buf) ++#endif ++#include <time.h> ++#include <errno.h> ++ ++ + /* +-** Implementation of the "readfile(X)" SQL function. The entire content +-** of the file named X is read and returned as a BLOB. NULL is returned +-** if the file does not exist or is unreadable. ++** Structure of the fsdir() table-valued function + */ +-static void readfileFunc( +- sqlite3_context *context, +- int argc, +- sqlite3_value **argv +-){ +- const char *zName; ++ /* 0 1 2 3 4 5 */ ++#define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)" ++#define FSDIR_COLUMN_NAME 0 /* Name of the file */ ++#define FSDIR_COLUMN_MODE 1 /* Access mode */ ++#define FSDIR_COLUMN_MTIME 2 /* Last modification time */ ++#define FSDIR_COLUMN_DATA 3 /* File content */ ++#define FSDIR_COLUMN_PATH 4 /* Path to top of search */ ++#define FSDIR_COLUMN_DIR 5 /* Path is relative to this directory */ ++ ++ ++/* ++** Set the result stored by context ctx to a blob containing the ++** contents of file zName. ++*/ ++static void readFileContents(sqlite3_context *ctx, const char *zName){ + FILE *in; + long nIn; + void *pBuf; + +- (void)(argc); /* Unused parameter */ +- zName = (const char*)sqlite3_value_text(argv[0]); +- if( zName==0 ) return; + in = fopen(zName, "rb"); + if( in==0 ) return; + fseek(in, 0, SEEK_END); +@@ -1571,7 +2157,7 @@ + rewind(in); + pBuf = sqlite3_malloc( nIn ); + if( pBuf && 1==fread(pBuf, nIn, 1, in) ){ +- sqlite3_result_blob(context, pBuf, nIn, sqlite3_free); ++ sqlite3_result_blob(ctx, pBuf, nIn, sqlite3_free); + }else{ + sqlite3_free(pBuf); + } +@@ -1579,39 +2165,807 @@ + } + + /* +-** Implementation of the "writefile(X,Y)" SQL function. The argument Y +-** is written into file X. The number of bytes written is returned. Or +-** NULL is returned if something goes wrong, such as being unable to open +-** file X for writing. ++** Implementation of the "readfile(X)" SQL function. The entire content ++** of the file named X is read and returned as a BLOB. NULL is returned ++** if the file does not exist or is unreadable. + */ ++static void readfileFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ const char *zName; ++ (void)(argc); /* Unused parameter */ ++ zName = (const char*)sqlite3_value_text(argv[0]); ++ if( zName==0 ) return; ++ readFileContents(context, zName); ++} ++ ++/* ++** Set the error message contained in context ctx to the results of ++** vprintf(zFmt, ...). ++*/ ++static void ctxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){ ++ char *zMsg = 0; ++ va_list ap; ++ va_start(ap, zFmt); ++ zMsg = sqlite3_vmprintf(zFmt, ap); ++ sqlite3_result_error(ctx, zMsg, -1); ++ sqlite3_free(zMsg); ++ va_end(ap); ++} ++ ++#if defined(_WIN32) ++/* ++** This function is designed to convert a Win32 FILETIME structure into the ++** number of seconds since the Unix Epoch (1970-01-01 00:00:00 UTC). ++*/ ++static sqlite3_uint64 fileTimeToUnixTime( ++ LPFILETIME pFileTime ++){ ++ SYSTEMTIME epochSystemTime; ++ ULARGE_INTEGER epochIntervals; ++ FILETIME epochFileTime; ++ ULARGE_INTEGER fileIntervals; ++ ++ memset(&epochSystemTime, 0, sizeof(SYSTEMTIME)); ++ epochSystemTime.wYear = 1970; ++ epochSystemTime.wMonth = 1; ++ epochSystemTime.wDay = 1; ++ SystemTimeToFileTime(&epochSystemTime, &epochFileTime); ++ epochIntervals.LowPart = epochFileTime.dwLowDateTime; ++ epochIntervals.HighPart = epochFileTime.dwHighDateTime; ++ ++ fileIntervals.LowPart = pFileTime->dwLowDateTime; ++ fileIntervals.HighPart = pFileTime->dwHighDateTime; ++ ++ return (fileIntervals.QuadPart - epochIntervals.QuadPart) / 10000000; ++} ++ ++/* ++** This function attempts to normalize the time values found in the stat() ++** buffer to UTC. This is necessary on Win32, where the runtime library ++** appears to return these values as local times. ++*/ ++static void statTimesToUtc( ++ const char *zPath, ++ struct stat *pStatBuf ++){ ++ HANDLE hFindFile; ++ WIN32_FIND_DATAW fd; ++ LPWSTR zUnicodeName; ++ extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*); ++ zUnicodeName = sqlite3_win32_utf8_to_unicode(zPath); ++ if( zUnicodeName ){ ++ memset(&fd, 0, sizeof(WIN32_FIND_DATAW)); ++ hFindFile = FindFirstFileW(zUnicodeName, &fd); ++ if( hFindFile!=NULL ){ ++ pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime); ++ pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime); ++ pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime); ++ FindClose(hFindFile); ++ } ++ sqlite3_free(zUnicodeName); ++ } ++} ++#endif ++ ++/* ++** This function is used in place of stat(). On Windows, special handling ++** is required in order for the included time to be returned as UTC. On all ++** other systems, this function simply calls stat(). ++*/ ++static int fileStat( ++ const char *zPath, ++ struct stat *pStatBuf ++){ ++#if defined(_WIN32) ++ int rc = stat(zPath, pStatBuf); ++ if( rc==0 ) statTimesToUtc(zPath, pStatBuf); ++ return rc; ++#else ++ return stat(zPath, pStatBuf); ++#endif ++} ++ ++/* ++** This function is used in place of lstat(). On Windows, special handling ++** is required in order for the included time to be returned as UTC. On all ++** other systems, this function simply calls lstat(). ++*/ ++static int fileLinkStat( ++ const char *zPath, ++ struct stat *pStatBuf ++){ ++#if defined(_WIN32) ++ int rc = lstat(zPath, pStatBuf); ++ if( rc==0 ) statTimesToUtc(zPath, pStatBuf); ++ return rc; ++#else ++ return lstat(zPath, pStatBuf); ++#endif ++} ++ ++/* ++** Argument zFile is the name of a file that will be created and/or written ++** by SQL function writefile(). This function ensures that the directory ++** zFile will be written to exists, creating it if required. The permissions ++** for any path components created by this function are set to (mode&0777). ++** ++** If an OOM condition is encountered, SQLITE_NOMEM is returned. Otherwise, ++** SQLITE_OK is returned if the directory is successfully created, or ++** SQLITE_ERROR otherwise. ++*/ ++static int makeDirectory( ++ const char *zFile, ++ mode_t mode ++){ ++ char *zCopy = sqlite3_mprintf("%s", zFile); ++ int rc = SQLITE_OK; ++ ++ if( zCopy==0 ){ ++ rc = SQLITE_NOMEM; ++ }else{ ++ int nCopy = (int)strlen(zCopy); ++ int i = 1; ++ ++ while( rc==SQLITE_OK ){ ++ struct stat sStat; ++ int rc2; ++ ++ for(; zCopy[i]!='/' && i<nCopy; i++); ++ if( i==nCopy ) break; ++ zCopy[i] = '\0'; ++ ++ rc2 = fileStat(zCopy, &sStat); ++ if( rc2!=0 ){ ++ if( mkdir(zCopy, mode & 0777) ) rc = SQLITE_ERROR; ++ }else{ ++ if( !S_ISDIR(sStat.st_mode) ) rc = SQLITE_ERROR; ++ } ++ zCopy[i] = '/'; ++ i++; ++ } ++ ++ sqlite3_free(zCopy); ++ } ++ ++ return rc; ++} ++ ++/* ++** This function does the work for the writefile() UDF. Refer to ++** header comments at the top of this file for details. ++*/ ++static int writeFile( ++ sqlite3_context *pCtx, /* Context to return bytes written in */ ++ const char *zFile, /* File to write */ ++ sqlite3_value *pData, /* Data to write */ ++ mode_t mode, /* MODE parameter passed to writefile() */ ++ sqlite3_int64 mtime /* MTIME parameter (or -1 to not set time) */ ++){ ++#if !defined(_WIN32) && !defined(WIN32) ++ if( S_ISLNK(mode) ){ ++ const char *zTo = (const char*)sqlite3_value_text(pData); ++ if( symlink(zTo, zFile)<0 ) return 1; ++ }else ++#endif ++ { ++ if( S_ISDIR(mode) ){ ++ if( mkdir(zFile, mode) ){ ++ /* The mkdir() call to create the directory failed. This might not ++ ** be an error though - if there is already a directory at the same ++ ** path and either the permissions already match or can be changed ++ ** to do so using chmod(), it is not an error. */ ++ struct stat sStat; ++ if( errno!=EEXIST ++ || 0!=fileStat(zFile, &sStat) ++ || !S_ISDIR(sStat.st_mode) ++ || ((sStat.st_mode&0777)!=(mode&0777) && 0!=chmod(zFile, mode&0777)) ++ ){ ++ return 1; ++ } ++ } ++ }else{ ++ sqlite3_int64 nWrite = 0; ++ const char *z; ++ int rc = 0; ++ FILE *out = fopen(zFile, "wb"); ++ if( out==0 ) return 1; ++ z = (const char*)sqlite3_value_blob(pData); ++ if( z ){ ++ sqlite3_int64 n = fwrite(z, 1, sqlite3_value_bytes(pData), out); ++ nWrite = sqlite3_value_bytes(pData); ++ if( nWrite!=n ){ ++ rc = 1; ++ } ++ } ++ fclose(out); ++ if( rc==0 && mode && chmod(zFile, mode & 0777) ){ ++ rc = 1; ++ } ++ if( rc ) return 2; ++ sqlite3_result_int64(pCtx, nWrite); ++ } ++ } ++ ++ if( mtime>=0 ){ ++#if defined(_WIN32) ++ /* Windows */ ++ FILETIME lastAccess; ++ FILETIME lastWrite; ++ SYSTEMTIME currentTime; ++ LONGLONG intervals; ++ HANDLE hFile; ++ LPWSTR zUnicodeName; ++ extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*); ++ ++ GetSystemTime(¤tTime); ++ SystemTimeToFileTime(¤tTime, &lastAccess); ++ intervals = Int32x32To64(mtime, 10000000) + 116444736000000000; ++ lastWrite.dwLowDateTime = (DWORD)intervals; ++ lastWrite.dwHighDateTime = intervals >> 32; ++ zUnicodeName = sqlite3_win32_utf8_to_unicode(zFile); ++ if( zUnicodeName==0 ){ ++ return 1; ++ } ++ hFile = CreateFileW( ++ zUnicodeName, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING, ++ FILE_FLAG_BACKUP_SEMANTICS, NULL ++ ); ++ sqlite3_free(zUnicodeName); ++ if( hFile!=INVALID_HANDLE_VALUE ){ ++ BOOL bResult = SetFileTime(hFile, NULL, &lastAccess, &lastWrite); ++ CloseHandle(hFile); ++ return !bResult; ++ }else{ ++ return 1; ++ } ++#elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */ ++ /* Recent unix */ ++ struct timespec times[2]; ++ times[0].tv_nsec = times[1].tv_nsec = 0; ++ times[0].tv_sec = time(0); ++ times[1].tv_sec = mtime; ++ if( utimensat(AT_FDCWD, zFile, times, AT_SYMLINK_NOFOLLOW) ){ ++ return 1; ++ } ++#else ++ /* Legacy unix */ ++ struct timeval times[2]; ++ times[0].tv_usec = times[1].tv_usec = 0; ++ times[0].tv_sec = time(0); ++ times[1].tv_sec = mtime; ++ if( utimes(zFile, times) ){ ++ return 1; ++ } ++#endif ++ } ++ ++ return 0; ++} ++ ++/* ++** Implementation of the "writefile(W,X[,Y[,Z]]])" SQL function. ++** Refer to header comments at the top of this file for details. ++*/ + static void writefileFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv + ){ +- FILE *out; +- const char *z; +- sqlite3_int64 rc; + const char *zFile; ++ mode_t mode = 0; ++ int res; ++ sqlite3_int64 mtime = -1; + +- (void)(argc); /* Unused parameter */ ++ if( argc<2 || argc>4 ){ ++ sqlite3_result_error(context, ++ "wrong number of arguments to function writefile()", -1 ++ ); ++ return; ++ } ++ + zFile = (const char*)sqlite3_value_text(argv[0]); + if( zFile==0 ) return; +- out = fopen(zFile, "wb"); +- if( out==0 ) return; +- z = (const char*)sqlite3_value_blob(argv[1]); +- if( z==0 ){ +- rc = 0; ++ if( argc>=3 ){ ++ mode = (mode_t)sqlite3_value_int(argv[2]); ++ } ++ if( argc==4 ){ ++ mtime = sqlite3_value_int64(argv[3]); ++ } ++ ++ res = writeFile(context, zFile, argv[1], mode, mtime); ++ if( res==1 && errno==ENOENT ){ ++ if( makeDirectory(zFile, mode)==SQLITE_OK ){ ++ res = writeFile(context, zFile, argv[1], mode, mtime); ++ } ++ } ++ ++ if( argc>2 && res!=0 ){ ++ if( S_ISLNK(mode) ){ ++ ctxErrorMsg(context, "failed to create symlink: %s", zFile); ++ }else if( S_ISDIR(mode) ){ ++ ctxErrorMsg(context, "failed to create directory: %s", zFile); ++ }else{ ++ ctxErrorMsg(context, "failed to write file: %s", zFile); ++ } ++ } ++} ++ ++/* ++** SQL function: lsmode(MODE) ++** ++** Given a numberic st_mode from stat(), convert it into a human-readable ++** text string in the style of "ls -l". ++*/ ++static void lsModeFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ int i; ++ int iMode = sqlite3_value_int(argv[0]); ++ char z[16]; ++ (void)argc; ++ if( S_ISLNK(iMode) ){ ++ z[0] = 'l'; ++ }else if( S_ISREG(iMode) ){ ++ z[0] = '-'; ++ }else if( S_ISDIR(iMode) ){ ++ z[0] = 'd'; + }else{ +- rc = fwrite(z, 1, sqlite3_value_bytes(argv[1]), out); ++ z[0] = '?'; + } +- fclose(out); +- sqlite3_result_int64(context, rc); ++ for(i=0; i<3; i++){ ++ int m = (iMode >> ((2-i)*3)); ++ char *a = &z[1 + i*3]; ++ a[0] = (m & 0x4) ? 'r' : '-'; ++ a[1] = (m & 0x2) ? 'w' : '-'; ++ a[2] = (m & 0x1) ? 'x' : '-'; ++ } ++ z[10] = '\0'; ++ sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT); + } + ++#ifndef SQLITE_OMIT_VIRTUALTABLE + ++/* ++** Cursor type for recursively iterating through a directory structure. ++*/ ++typedef struct fsdir_cursor fsdir_cursor; ++typedef struct FsdirLevel FsdirLevel; ++ ++struct FsdirLevel { ++ DIR *pDir; /* From opendir() */ ++ char *zDir; /* Name of directory (nul-terminated) */ ++}; ++ ++struct fsdir_cursor { ++ sqlite3_vtab_cursor base; /* Base class - must be first */ ++ ++ int nLvl; /* Number of entries in aLvl[] array */ ++ int iLvl; /* Index of current entry */ ++ FsdirLevel *aLvl; /* Hierarchy of directories being traversed */ ++ ++ const char *zBase; ++ int nBase; ++ ++ struct stat sStat; /* Current lstat() results */ ++ char *zPath; /* Path to current entry */ ++ sqlite3_int64 iRowid; /* Current rowid */ ++}; ++ ++typedef struct fsdir_tab fsdir_tab; ++struct fsdir_tab { ++ sqlite3_vtab base; /* Base class - must be first */ ++}; ++ ++/* ++** Construct a new fsdir virtual table object. ++*/ ++static int fsdirConnect( ++ sqlite3 *db, ++ void *pAux, ++ int argc, const char *const*argv, ++ sqlite3_vtab **ppVtab, ++ char **pzErr ++){ ++ fsdir_tab *pNew = 0; ++ int rc; ++ (void)pAux; ++ (void)argc; ++ (void)argv; ++ (void)pzErr; ++ rc = sqlite3_declare_vtab(db, "CREATE TABLE x" FSDIR_SCHEMA); ++ if( rc==SQLITE_OK ){ ++ pNew = (fsdir_tab*)sqlite3_malloc( sizeof(*pNew) ); ++ if( pNew==0 ) return SQLITE_NOMEM; ++ memset(pNew, 0, sizeof(*pNew)); ++ } ++ *ppVtab = (sqlite3_vtab*)pNew; ++ return rc; ++} ++ ++/* ++** This method is the destructor for fsdir vtab objects. ++*/ ++static int fsdirDisconnect(sqlite3_vtab *pVtab){ ++ sqlite3_free(pVtab); ++ return SQLITE_OK; ++} ++ ++/* ++** Constructor for a new fsdir_cursor object. ++*/ ++static int fsdirOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ ++ fsdir_cursor *pCur; ++ (void)p; ++ pCur = sqlite3_malloc( sizeof(*pCur) ); ++ if( pCur==0 ) return SQLITE_NOMEM; ++ memset(pCur, 0, sizeof(*pCur)); ++ pCur->iLvl = -1; ++ *ppCursor = &pCur->base; ++ return SQLITE_OK; ++} ++ ++/* ++** Reset a cursor back to the state it was in when first returned ++** by fsdirOpen(). ++*/ ++static void fsdirResetCursor(fsdir_cursor *pCur){ ++ int i; ++ for(i=0; i<=pCur->iLvl; i++){ ++ FsdirLevel *pLvl = &pCur->aLvl[i]; ++ if( pLvl->pDir ) closedir(pLvl->pDir); ++ sqlite3_free(pLvl->zDir); ++ } ++ sqlite3_free(pCur->zPath); ++ sqlite3_free(pCur->aLvl); ++ pCur->aLvl = 0; ++ pCur->zPath = 0; ++ pCur->zBase = 0; ++ pCur->nBase = 0; ++ pCur->nLvl = 0; ++ pCur->iLvl = -1; ++ pCur->iRowid = 1; ++} ++ ++/* ++** Destructor for an fsdir_cursor. ++*/ ++static int fsdirClose(sqlite3_vtab_cursor *cur){ ++ fsdir_cursor *pCur = (fsdir_cursor*)cur; ++ ++ fsdirResetCursor(pCur); ++ sqlite3_free(pCur); ++ return SQLITE_OK; ++} ++ ++/* ++** Set the error message for the virtual table associated with cursor ++** pCur to the results of vprintf(zFmt, ...). ++*/ ++static void fsdirSetErrmsg(fsdir_cursor *pCur, const char *zFmt, ...){ ++ va_list ap; ++ va_start(ap, zFmt); ++ pCur->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap); ++ va_end(ap); ++} ++ ++ ++/* ++** Advance an fsdir_cursor to its next row of output. ++*/ ++static int fsdirNext(sqlite3_vtab_cursor *cur){ ++ fsdir_cursor *pCur = (fsdir_cursor*)cur; ++ mode_t m = pCur->sStat.st_mode; ++ ++ pCur->iRowid++; ++ if( S_ISDIR(m) ){ ++ /* Descend into this directory */ ++ int iNew = pCur->iLvl + 1; ++ FsdirLevel *pLvl; ++ if( iNew>=pCur->nLvl ){ ++ int nNew = iNew+1; ++ int nByte = nNew*sizeof(FsdirLevel); ++ FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc(pCur->aLvl, nByte); ++ if( aNew==0 ) return SQLITE_NOMEM; ++ memset(&aNew[pCur->nLvl], 0, sizeof(FsdirLevel)*(nNew-pCur->nLvl)); ++ pCur->aLvl = aNew; ++ pCur->nLvl = nNew; ++ } ++ pCur->iLvl = iNew; ++ pLvl = &pCur->aLvl[iNew]; ++ ++ pLvl->zDir = pCur->zPath; ++ pCur->zPath = 0; ++ pLvl->pDir = opendir(pLvl->zDir); ++ if( pLvl->pDir==0 ){ ++ fsdirSetErrmsg(pCur, "cannot read directory: %s", pCur->zPath); ++ return SQLITE_ERROR; ++ } ++ } ++ ++ while( pCur->iLvl>=0 ){ ++ FsdirLevel *pLvl = &pCur->aLvl[pCur->iLvl]; ++ struct dirent *pEntry = readdir(pLvl->pDir); ++ if( pEntry ){ ++ if( pEntry->d_name[0]=='.' ){ ++ if( pEntry->d_name[1]=='.' && pEntry->d_name[2]=='\0' ) continue; ++ if( pEntry->d_name[1]=='\0' ) continue; ++ } ++ sqlite3_free(pCur->zPath); ++ pCur->zPath = sqlite3_mprintf("%s/%s", pLvl->zDir, pEntry->d_name); ++ if( pCur->zPath==0 ) return SQLITE_NOMEM; ++ if( fileLinkStat(pCur->zPath, &pCur->sStat) ){ ++ fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath); ++ return SQLITE_ERROR; ++ } ++ return SQLITE_OK; ++ } ++ closedir(pLvl->pDir); ++ sqlite3_free(pLvl->zDir); ++ pLvl->pDir = 0; ++ pLvl->zDir = 0; ++ pCur->iLvl--; ++ } ++ ++ /* EOF */ ++ sqlite3_free(pCur->zPath); ++ pCur->zPath = 0; ++ return SQLITE_OK; ++} ++ ++/* ++** Return values of columns for the row at which the series_cursor ++** is currently pointing. ++*/ ++static int fsdirColumn( ++ sqlite3_vtab_cursor *cur, /* The cursor */ ++ sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ ++ int i /* Which column to return */ ++){ ++ fsdir_cursor *pCur = (fsdir_cursor*)cur; ++ switch( i ){ ++ case FSDIR_COLUMN_NAME: { ++ sqlite3_result_text(ctx, &pCur->zPath[pCur->nBase], -1, SQLITE_TRANSIENT); ++ break; ++ } ++ ++ case FSDIR_COLUMN_MODE: ++ sqlite3_result_int64(ctx, pCur->sStat.st_mode); ++ break; ++ ++ case FSDIR_COLUMN_MTIME: ++ sqlite3_result_int64(ctx, pCur->sStat.st_mtime); ++ break; ++ ++ case FSDIR_COLUMN_DATA: { ++ mode_t m = pCur->sStat.st_mode; ++ if( S_ISDIR(m) ){ ++ sqlite3_result_null(ctx); ++#if !defined(_WIN32) && !defined(WIN32) ++ }else if( S_ISLNK(m) ){ ++ char aStatic[64]; ++ char *aBuf = aStatic; ++ int nBuf = 64; ++ int n; ++ ++ while( 1 ){ ++ n = readlink(pCur->zPath, aBuf, nBuf); ++ if( n<nBuf ) break; ++ if( aBuf!=aStatic ) sqlite3_free(aBuf); ++ nBuf = nBuf*2; ++ aBuf = sqlite3_malloc(nBuf); ++ if( aBuf==0 ){ ++ sqlite3_result_error_nomem(ctx); ++ return SQLITE_NOMEM; ++ } ++ } ++ ++ sqlite3_result_text(ctx, aBuf, n, SQLITE_TRANSIENT); ++ if( aBuf!=aStatic ) sqlite3_free(aBuf); ++#endif ++ }else{ ++ readFileContents(ctx, pCur->zPath); ++ } ++ } ++ case FSDIR_COLUMN_PATH: ++ default: { ++ /* The FSDIR_COLUMN_PATH and FSDIR_COLUMN_DIR are input parameters. ++ ** always return their values as NULL */ ++ break; ++ } ++ } ++ 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 fsdirRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ ++ fsdir_cursor *pCur = (fsdir_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 fsdirEof(sqlite3_vtab_cursor *cur){ ++ fsdir_cursor *pCur = (fsdir_cursor*)cur; ++ return (pCur->zPath==0); ++} ++ ++/* ++** xFilter callback. ++** ++** idxNum==1 PATH parameter only ++** idxNum==2 Both PATH and DIR supplied ++*/ ++static int fsdirFilter( ++ sqlite3_vtab_cursor *cur, ++ int idxNum, const char *idxStr, ++ int argc, sqlite3_value **argv ++){ ++ const char *zDir = 0; ++ fsdir_cursor *pCur = (fsdir_cursor*)cur; ++ (void)idxStr; ++ fsdirResetCursor(pCur); ++ ++ if( idxNum==0 ){ ++ fsdirSetErrmsg(pCur, "table function fsdir requires an argument"); ++ return SQLITE_ERROR; ++ } ++ ++ assert( argc==idxNum && (argc==1 || argc==2) ); ++ zDir = (const char*)sqlite3_value_text(argv[0]); ++ if( zDir==0 ){ ++ fsdirSetErrmsg(pCur, "table function fsdir requires a non-NULL argument"); ++ return SQLITE_ERROR; ++ } ++ if( argc==2 ){ ++ pCur->zBase = (const char*)sqlite3_value_text(argv[1]); ++ } ++ if( pCur->zBase ){ ++ pCur->nBase = (int)strlen(pCur->zBase)+1; ++ pCur->zPath = sqlite3_mprintf("%s/%s", pCur->zBase, zDir); ++ }else{ ++ pCur->zPath = sqlite3_mprintf("%s", zDir); ++ } ++ ++ if( pCur->zPath==0 ){ ++ return SQLITE_NOMEM; ++ } ++ if( fileLinkStat(pCur->zPath, &pCur->sStat) ){ ++ fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath); ++ return SQLITE_ERROR; ++ } ++ ++ 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 ++** plan. ++** ++** In this implementation idxNum is used to represent the ++** query plan. idxStr is unused. ++** ++** The query plan is represented by values of idxNum: ++** ++** (1) The path value is supplied by argv[0] ++** (2) Path is in argv[0] and dir is in argv[1] ++*/ ++static int fsdirBestIndex( ++ sqlite3_vtab *tab, ++ sqlite3_index_info *pIdxInfo ++){ ++ int i; /* Loop over constraints */ ++ int idxPath = -1; /* Index in pIdxInfo->aConstraint of PATH= */ ++ int idxDir = -1; /* Index in pIdxInfo->aConstraint of DIR= */ ++ int seenPath = 0; /* True if an unusable PATH= constraint is seen */ ++ int seenDir = 0; /* True if an unusable DIR= constraint is seen */ ++ const struct sqlite3_index_constraint *pConstraint; ++ ++ (void)tab; ++ pConstraint = pIdxInfo->aConstraint; ++ for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ ++ if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; ++ switch( pConstraint->iColumn ){ ++ case FSDIR_COLUMN_PATH: { ++ if( pConstraint->usable ){ ++ idxPath = i; ++ seenPath = 0; ++ }else if( idxPath<0 ){ ++ seenPath = 1; ++ } ++ break; ++ } ++ case FSDIR_COLUMN_DIR: { ++ if( pConstraint->usable ){ ++ idxDir = i; ++ seenDir = 0; ++ }else if( idxDir<0 ){ ++ seenDir = 1; ++ } ++ break; ++ } ++ } ++ } ++ if( seenPath || seenDir ){ ++ /* If input parameters are unusable, disallow this plan */ ++ return SQLITE_CONSTRAINT; ++ } ++ ++ if( idxPath<0 ){ ++ pIdxInfo->idxNum = 0; ++ /* The pIdxInfo->estimatedCost should have been initialized to a huge ++ ** number. Leave it unchanged. */ ++ pIdxInfo->estimatedRows = 0x7fffffff; ++ }else{ ++ pIdxInfo->aConstraintUsage[idxPath].omit = 1; ++ pIdxInfo->aConstraintUsage[idxPath].argvIndex = 1; ++ if( idxDir>=0 ){ ++ pIdxInfo->aConstraintUsage[idxDir].omit = 1; ++ pIdxInfo->aConstraintUsage[idxDir].argvIndex = 2; ++ pIdxInfo->idxNum = 2; ++ pIdxInfo->estimatedCost = 10.0; ++ }else{ ++ pIdxInfo->idxNum = 1; ++ pIdxInfo->estimatedCost = 100.0; ++ } ++ } ++ ++ return SQLITE_OK; ++} ++ ++/* ++** Register the "fsdir" virtual table. ++*/ ++static int fsdirRegister(sqlite3 *db){ ++ static sqlite3_module fsdirModule = { ++ 0, /* iVersion */ ++ 0, /* xCreate */ ++ fsdirConnect, /* xConnect */ ++ fsdirBestIndex, /* xBestIndex */ ++ fsdirDisconnect, /* xDisconnect */ ++ 0, /* xDestroy */ ++ fsdirOpen, /* xOpen - open a cursor */ ++ fsdirClose, /* xClose - close a cursor */ ++ fsdirFilter, /* xFilter - configure scan constraints */ ++ fsdirNext, /* xNext - advance a cursor */ ++ fsdirEof, /* xEof - check for end of scan */ ++ fsdirColumn, /* xColumn - read data */ ++ fsdirRowid, /* xRowid - read data */ ++ 0, /* xUpdate */ ++ 0, /* xBegin */ ++ 0, /* xSync */ ++ 0, /* xCommit */ ++ 0, /* xRollback */ ++ 0, /* xFindMethod */ ++ 0, /* xRename */ ++ 0, /* xSavepoint */ ++ 0, /* xRelease */ ++ 0, /* xRollbackTo */ ++ 0, /* xShadowName */ ++ }; ++ ++ int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0); ++ return rc; ++} ++#else /* SQLITE_OMIT_VIRTUALTABLE */ ++# define fsdirRegister(x) SQLITE_OK ++#endif ++ + #ifdef _WIN32 +-__declspec(dllexport) ++ + #endif + int sqlite3_fileio_init( + sqlite3 *db, +@@ -1624,9 +2978,16 @@ + rc = sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0, + readfileFunc, 0, 0); + if( rc==SQLITE_OK ){ +- rc = sqlite3_create_function(db, "writefile", 2, SQLITE_UTF8, 0, ++ rc = sqlite3_create_function(db, "writefile", -1, SQLITE_UTF8, 0, + writefileFunc, 0, 0); + } ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3_create_function(db, "lsmode", 1, SQLITE_UTF8, 0, ++ lsModeFunc, 0, 0); ++ } ++ if( rc==SQLITE_OK ){ ++ rc = fsdirRegister(db); ++ } + return rc; + } + +@@ -1695,6 +3056,7 @@ + char *zPrefix; /* The prefix for the word we want to complete */ + char *zLine; /* The whole that we want to complete */ + const char *zCurrentRow; /* Current output row */ ++ int szRow; /* Length of the zCurrentRow string */ + sqlite3_stmt *pStmt; /* Current statement */ + sqlite3_int64 iRowid; /* The rowid */ + int ePhase; /* Current phase */ +@@ -1711,7 +3073,7 @@ + #define COMPLETION_INDEXES 5 + #define COMPLETION_TRIGGERS 6 + #define COMPLETION_DATABASES 7 +-#define COMPLETION_TABLES 8 ++#define COMPLETION_TABLES 8 /* Also VIEWs and TRIGGERs */ + #define COMPLETION_COLUMNS 9 + #define COMPLETION_MODULES 10 + #define COMPLETION_EOF 11 +@@ -1808,32 +3170,6 @@ + } + + /* +-** All SQL keywords understood by SQLite +-*/ +-static const char *completionKwrds[] = { +- "ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS", +- "ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY", +- "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT", +- "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE", +- "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE", +- "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH", +- "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN", +- "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF", +- "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER", +- "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY", +- "LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL", +- "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA", +- "PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP", +- "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT", +- "ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP", +- "TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE", +- "UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE", +- "WITH", "WITHOUT", +-}; +-#define completionKwCount \ +- (int)(sizeof(completionKwrds)/sizeof(completionKwrds[0])) +- +-/* + ** Advance a completion_cursor to its next row of output. + ** + ** The ->ePhase, ->j, and ->pStmt fields of the completion_cursor object +@@ -1855,11 +3191,11 @@ + while( pCur->ePhase!=COMPLETION_EOF ){ + switch( pCur->ePhase ){ + case COMPLETION_KEYWORDS: { +- if( pCur->j >= completionKwCount ){ ++ if( pCur->j >= sqlite3_keyword_count() ){ + pCur->zCurrentRow = 0; + pCur->ePhase = COMPLETION_DATABASES; + }else{ +- pCur->zCurrentRow = completionKwrds[pCur->j++]; ++ sqlite3_keyword_name(pCur->j++, &pCur->zCurrentRow, &pCur->szRow); + } + iCol = -1; + break; +@@ -1883,8 +3219,7 @@ + const char *zDb = (const char*)sqlite3_column_text(pS2, 1); + zSql = sqlite3_mprintf( + "%z%s" +- "SELECT name FROM \"%w\".sqlite_master" +- " WHERE type='table'", ++ "SELECT name FROM \"%w\".sqlite_master", + zSql, zSep, zDb + ); + if( zSql==0 ) return SQLITE_NOMEM; +@@ -1932,6 +3267,7 @@ + if( sqlite3_step(pCur->pStmt)==SQLITE_ROW ){ + /* Extract the next row of content */ + pCur->zCurrentRow = (const char*)sqlite3_column_text(pCur->pStmt, iCol); ++ pCur->szRow = sqlite3_column_bytes(pCur->pStmt, iCol); + }else{ + /* When all rows are finished, advance to the next phase */ + sqlite3_finalize(pCur->pStmt); +@@ -1941,7 +3277,9 @@ + } + } + if( pCur->nPrefix==0 ) break; +- if( sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0 ){ ++ if( pCur->nPrefix<=pCur->szRow ++ && sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0 ++ ){ + break; + } + } +@@ -1961,7 +3299,7 @@ + completion_cursor *pCur = (completion_cursor*)cur; + switch( i ){ + case COMPLETION_COLUMN_CANDIDATE: { +- sqlite3_result_text(ctx, pCur->zCurrentRow, -1, SQLITE_TRANSIENT); ++ sqlite3_result_text(ctx, pCur->zCurrentRow, pCur->szRow,SQLITE_TRANSIENT); + break; + } + case COMPLETION_COLUMN_PREFIX: { +@@ -2021,7 +3359,7 @@ + pCur->zPrefix = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg])); + if( pCur->zPrefix==0 ) return SQLITE_NOMEM; + } +- iArg++; ++ iArg = 1; + } + if( idxNum & 2 ){ + pCur->nLine = sqlite3_value_bytes(argv[iArg]); +@@ -2029,7 +3367,6 @@ + pCur->zLine = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg])); + if( pCur->zLine==0 ) return SQLITE_NOMEM; + } +- iArg++; + } + if( pCur->zLine!=0 && pCur->zPrefix==0 ){ + int i = pCur->nLine; +@@ -2125,7 +3462,8 @@ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ +- 0 /* xRollbackTo */ ++ 0, /* xRollbackTo */ ++ 0 /* xShadowName */ + }; + + #endif /* SQLITE_OMIT_VIRTUALTABLE */ +@@ -2139,7 +3477,7 @@ + } + + #ifdef _WIN32 +-__declspec(dllexport) ++ + #endif + int sqlite3_completion_init( + sqlite3 *db, +@@ -2156,7 +3494,5004 @@ + } + + /************************* End ../ext/misc/completion.c ********************/ ++/************************* Begin ../ext/misc/appendvfs.c ******************/ ++/* ++** 2017-10-20 ++** ++** The author disclaims copyright to this source code. In place of ++** a legal notice, here is a blessing: ++** ++** May you do good and not evil. ++** May you find forgiveness for yourself and forgive others. ++** May you share freely, never taking more than you give. ++** ++****************************************************************************** ++** ++** This file implements a VFS shim that allows an SQLite database to be ++** appended onto the end of some other file, such as an executable. ++** ++** A special record must appear at the end of the file that identifies the ++** file as an appended database and provides an offset to page 1. For ++** best performance page 1 should be located at a disk page boundary, though ++** that is not required. ++** ++** When opening a database using this VFS, the connection might treat ++** the file as an ordinary SQLite database, or it might treat is as a ++** database appended onto some other file. Here are the rules: ++** ++** (1) When opening a new empty file, that file is treated as an ordinary ++** database. ++** ++** (2) When opening a file that begins with the standard SQLite prefix ++** string "SQLite format 3", that file is treated as an ordinary ++** database. ++** ++** (3) When opening a file that ends with the appendvfs trailer string ++** "Start-Of-SQLite3-NNNNNNNN" that file is treated as an appended ++** database. ++** ++** (4) If none of the above apply and the SQLITE_OPEN_CREATE flag is ++** set, then a new database is appended to the already existing file. ++** ++** (5) Otherwise, SQLITE_CANTOPEN is returned. ++** ++** To avoid unnecessary complications with the PENDING_BYTE, the size of ++** the file containing the database is limited to 1GB. This VFS will refuse ++** to read or write past the 1GB mark. This restriction might be lifted in ++** future versions. For now, if you need a large database, then keep the ++** database in a separate file. ++** ++** If the file being opened is not an appended database, then this shim is ++** a pass-through into the default underlying VFS. ++**/ ++SQLITE_EXTENSION_INIT1 ++#include <string.h> ++#include <assert.h> + ++/* The append mark at the end of the database is: ++** ++** Start-Of-SQLite3-NNNNNNNN ++** 123456789 123456789 12345 ++** ++** The NNNNNNNN represents a 64-bit big-endian unsigned integer which is ++** the offset to page 1. ++*/ ++#define APND_MARK_PREFIX "Start-Of-SQLite3-" ++#define APND_MARK_PREFIX_SZ 17 ++#define APND_MARK_SIZE 25 ++ ++/* ++** Maximum size of the combined prefix + database + append-mark. This ++** must be less than 0x40000000 to avoid locking issues on Windows. ++*/ ++#define APND_MAX_SIZE (65536*15259) ++ ++/* ++** Forward declaration of objects used by this utility ++*/ ++typedef struct sqlite3_vfs ApndVfs; ++typedef struct ApndFile ApndFile; ++ ++/* Access to a lower-level VFS that (might) implement dynamic loading, ++** access to randomness, etc. ++*/ ++#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData)) ++#define ORIGFILE(p) ((sqlite3_file*)(((ApndFile*)(p))+1)) ++ ++/* An open file */ ++struct ApndFile { ++ sqlite3_file base; /* IO methods */ ++ sqlite3_int64 iPgOne; /* File offset to page 1 */ ++ sqlite3_int64 iMark; /* Start of the append-mark */ ++}; ++ ++/* ++** Methods for ApndFile ++*/ ++static int apndClose(sqlite3_file*); ++static int apndRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); ++static int apndWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst); ++static int apndTruncate(sqlite3_file*, sqlite3_int64 size); ++static int apndSync(sqlite3_file*, int flags); ++static int apndFileSize(sqlite3_file*, sqlite3_int64 *pSize); ++static int apndLock(sqlite3_file*, int); ++static int apndUnlock(sqlite3_file*, int); ++static int apndCheckReservedLock(sqlite3_file*, int *pResOut); ++static int apndFileControl(sqlite3_file*, int op, void *pArg); ++static int apndSectorSize(sqlite3_file*); ++static int apndDeviceCharacteristics(sqlite3_file*); ++static int apndShmMap(sqlite3_file*, int iPg, int pgsz, int, void volatile**); ++static int apndShmLock(sqlite3_file*, int offset, int n, int flags); ++static void apndShmBarrier(sqlite3_file*); ++static int apndShmUnmap(sqlite3_file*, int deleteFlag); ++static int apndFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp); ++static int apndUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p); ++ ++/* ++** Methods for ApndVfs ++*/ ++static int apndOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); ++static int apndDelete(sqlite3_vfs*, const char *zName, int syncDir); ++static int apndAccess(sqlite3_vfs*, const char *zName, int flags, int *); ++static int apndFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); ++static void *apndDlOpen(sqlite3_vfs*, const char *zFilename); ++static void apndDlError(sqlite3_vfs*, int nByte, char *zErrMsg); ++static void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void); ++static void apndDlClose(sqlite3_vfs*, void*); ++static int apndRandomness(sqlite3_vfs*, int nByte, char *zOut); ++static int apndSleep(sqlite3_vfs*, int microseconds); ++static int apndCurrentTime(sqlite3_vfs*, double*); ++static int apndGetLastError(sqlite3_vfs*, int, char *); ++static int apndCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*); ++static int apndSetSystemCall(sqlite3_vfs*, const char*,sqlite3_syscall_ptr); ++static sqlite3_syscall_ptr apndGetSystemCall(sqlite3_vfs*, const char *z); ++static const char *apndNextSystemCall(sqlite3_vfs*, const char *zName); ++ ++static sqlite3_vfs apnd_vfs = { ++ 3, /* iVersion (set when registered) */ ++ 0, /* szOsFile (set when registered) */ ++ 1024, /* mxPathname */ ++ 0, /* pNext */ ++ "apndvfs", /* zName */ ++ 0, /* pAppData (set when registered) */ ++ apndOpen, /* xOpen */ ++ apndDelete, /* xDelete */ ++ apndAccess, /* xAccess */ ++ apndFullPathname, /* xFullPathname */ ++ apndDlOpen, /* xDlOpen */ ++ apndDlError, /* xDlError */ ++ apndDlSym, /* xDlSym */ ++ apndDlClose, /* xDlClose */ ++ apndRandomness, /* xRandomness */ ++ apndSleep, /* xSleep */ ++ apndCurrentTime, /* xCurrentTime */ ++ apndGetLastError, /* xGetLastError */ ++ apndCurrentTimeInt64, /* xCurrentTimeInt64 */ ++ apndSetSystemCall, /* xSetSystemCall */ ++ apndGetSystemCall, /* xGetSystemCall */ ++ apndNextSystemCall /* xNextSystemCall */ ++}; ++ ++static const sqlite3_io_methods apnd_io_methods = { ++ 3, /* iVersion */ ++ apndClose, /* xClose */ ++ apndRead, /* xRead */ ++ apndWrite, /* xWrite */ ++ apndTruncate, /* xTruncate */ ++ apndSync, /* xSync */ ++ apndFileSize, /* xFileSize */ ++ apndLock, /* xLock */ ++ apndUnlock, /* xUnlock */ ++ apndCheckReservedLock, /* xCheckReservedLock */ ++ apndFileControl, /* xFileControl */ ++ apndSectorSize, /* xSectorSize */ ++ apndDeviceCharacteristics, /* xDeviceCharacteristics */ ++ apndShmMap, /* xShmMap */ ++ apndShmLock, /* xShmLock */ ++ apndShmBarrier, /* xShmBarrier */ ++ apndShmUnmap, /* xShmUnmap */ ++ apndFetch, /* xFetch */ ++ apndUnfetch /* xUnfetch */ ++}; ++ ++ ++ ++/* ++** Close an apnd-file. ++*/ ++static int apndClose(sqlite3_file *pFile){ ++ pFile = ORIGFILE(pFile); ++ return pFile->pMethods->xClose(pFile); ++} ++ ++/* ++** Read data from an apnd-file. ++*/ ++static int apndRead( ++ sqlite3_file *pFile, ++ void *zBuf, ++ int iAmt, ++ sqlite_int64 iOfst ++){ ++ ApndFile *p = (ApndFile *)pFile; ++ pFile = ORIGFILE(pFile); ++ return pFile->pMethods->xRead(pFile, zBuf, iAmt, iOfst+p->iPgOne); ++} ++ ++/* ++** Add the append-mark onto the end of the file. ++*/ ++static int apndWriteMark(ApndFile *p, sqlite3_file *pFile){ ++ int i; ++ unsigned char a[APND_MARK_SIZE]; ++ memcpy(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ); ++ for(i=0; i<8; i++){ ++ a[APND_MARK_PREFIX_SZ+i] = (p->iPgOne >> (56 - i*8)) & 0xff; ++ } ++ return pFile->pMethods->xWrite(pFile, a, APND_MARK_SIZE, p->iMark); ++} ++ ++/* ++** Write data to an apnd-file. ++*/ ++static int apndWrite( ++ sqlite3_file *pFile, ++ const void *zBuf, ++ int iAmt, ++ sqlite_int64 iOfst ++){ ++ int rc; ++ ApndFile *p = (ApndFile *)pFile; ++ pFile = ORIGFILE(pFile); ++ if( iOfst+iAmt>=APND_MAX_SIZE ) return SQLITE_FULL; ++ rc = pFile->pMethods->xWrite(pFile, zBuf, iAmt, iOfst+p->iPgOne); ++ if( rc==SQLITE_OK && iOfst + iAmt + p->iPgOne > p->iMark ){ ++ sqlite3_int64 sz = 0; ++ rc = pFile->pMethods->xFileSize(pFile, &sz); ++ if( rc==SQLITE_OK ){ ++ p->iMark = sz - APND_MARK_SIZE; ++ if( iOfst + iAmt + p->iPgOne > p->iMark ){ ++ p->iMark = p->iPgOne + iOfst + iAmt; ++ rc = apndWriteMark(p, pFile); ++ } ++ } ++ } ++ return rc; ++} ++ ++/* ++** Truncate an apnd-file. ++*/ ++static int apndTruncate(sqlite3_file *pFile, sqlite_int64 size){ ++ int rc; ++ ApndFile *p = (ApndFile *)pFile; ++ pFile = ORIGFILE(pFile); ++ rc = pFile->pMethods->xTruncate(pFile, size+p->iPgOne+APND_MARK_SIZE); ++ if( rc==SQLITE_OK ){ ++ p->iMark = p->iPgOne+size; ++ rc = apndWriteMark(p, pFile); ++ } ++ return rc; ++} ++ ++/* ++** Sync an apnd-file. ++*/ ++static int apndSync(sqlite3_file *pFile, int flags){ ++ pFile = ORIGFILE(pFile); ++ return pFile->pMethods->xSync(pFile, flags); ++} ++ ++/* ++** Return the current file-size of an apnd-file. ++*/ ++static int apndFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ ++ ApndFile *p = (ApndFile *)pFile; ++ int rc; ++ pFile = ORIGFILE(p); ++ rc = pFile->pMethods->xFileSize(pFile, pSize); ++ if( rc==SQLITE_OK && p->iPgOne ){ ++ *pSize -= p->iPgOne + APND_MARK_SIZE; ++ } ++ return rc; ++} ++ ++/* ++** Lock an apnd-file. ++*/ ++static int apndLock(sqlite3_file *pFile, int eLock){ ++ pFile = ORIGFILE(pFile); ++ return pFile->pMethods->xLock(pFile, eLock); ++} ++ ++/* ++** Unlock an apnd-file. ++*/ ++static int apndUnlock(sqlite3_file *pFile, int eLock){ ++ pFile = ORIGFILE(pFile); ++ return pFile->pMethods->xUnlock(pFile, eLock); ++} ++ ++/* ++** Check if another file-handle holds a RESERVED lock on an apnd-file. ++*/ ++static int apndCheckReservedLock(sqlite3_file *pFile, int *pResOut){ ++ pFile = ORIGFILE(pFile); ++ return pFile->pMethods->xCheckReservedLock(pFile, pResOut); ++} ++ ++/* ++** File control method. For custom operations on an apnd-file. ++*/ ++static int apndFileControl(sqlite3_file *pFile, int op, void *pArg){ ++ ApndFile *p = (ApndFile *)pFile; ++ int rc; ++ pFile = ORIGFILE(pFile); ++ rc = pFile->pMethods->xFileControl(pFile, op, pArg); ++ if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){ ++ *(char**)pArg = sqlite3_mprintf("apnd(%lld)/%z", p->iPgOne, *(char**)pArg); ++ } ++ return rc; ++} ++ ++/* ++** Return the sector-size in bytes for an apnd-file. ++*/ ++static int apndSectorSize(sqlite3_file *pFile){ ++ pFile = ORIGFILE(pFile); ++ return pFile->pMethods->xSectorSize(pFile); ++} ++ ++/* ++** Return the device characteristic flags supported by an apnd-file. ++*/ ++static int apndDeviceCharacteristics(sqlite3_file *pFile){ ++ pFile = ORIGFILE(pFile); ++ return pFile->pMethods->xDeviceCharacteristics(pFile); ++} ++ ++/* Create a shared memory file mapping */ ++static int apndShmMap( ++ sqlite3_file *pFile, ++ int iPg, ++ int pgsz, ++ int bExtend, ++ void volatile **pp ++){ ++ pFile = ORIGFILE(pFile); ++ return pFile->pMethods->xShmMap(pFile,iPg,pgsz,bExtend,pp); ++} ++ ++/* Perform locking on a shared-memory segment */ ++static int apndShmLock(sqlite3_file *pFile, int offset, int n, int flags){ ++ pFile = ORIGFILE(pFile); ++ return pFile->pMethods->xShmLock(pFile,offset,n,flags); ++} ++ ++/* Memory barrier operation on shared memory */ ++static void apndShmBarrier(sqlite3_file *pFile){ ++ pFile = ORIGFILE(pFile); ++ pFile->pMethods->xShmBarrier(pFile); ++} ++ ++/* Unmap a shared memory segment */ ++static int apndShmUnmap(sqlite3_file *pFile, int deleteFlag){ ++ pFile = ORIGFILE(pFile); ++ return pFile->pMethods->xShmUnmap(pFile,deleteFlag); ++} ++ ++/* Fetch a page of a memory-mapped file */ ++static int apndFetch( ++ sqlite3_file *pFile, ++ sqlite3_int64 iOfst, ++ int iAmt, ++ void **pp ++){ ++ ApndFile *p = (ApndFile *)pFile; ++ pFile = ORIGFILE(pFile); ++ return pFile->pMethods->xFetch(pFile, iOfst+p->iPgOne, iAmt, pp); ++} ++ ++/* Release a memory-mapped page */ ++static int apndUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){ ++ ApndFile *p = (ApndFile *)pFile; ++ pFile = ORIGFILE(pFile); ++ return pFile->pMethods->xUnfetch(pFile, iOfst+p->iPgOne, pPage); ++} ++ ++/* ++** Check to see if the file is an ordinary SQLite database file. ++*/ ++static int apndIsOrdinaryDatabaseFile(sqlite3_int64 sz, sqlite3_file *pFile){ ++ int rc; ++ char zHdr[16]; ++ static const char aSqliteHdr[] = "SQLite format 3"; ++ if( sz<512 ) return 0; ++ rc = pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), 0); ++ if( rc ) return 0; ++ return memcmp(zHdr, aSqliteHdr, sizeof(zHdr))==0; ++} ++ ++/* ++** Try to read the append-mark off the end of a file. Return the ++** start of the appended database if the append-mark is present. If ++** there is no append-mark, return -1; ++*/ ++static sqlite3_int64 apndReadMark(sqlite3_int64 sz, sqlite3_file *pFile){ ++ int rc, i; ++ sqlite3_int64 iMark; ++ unsigned char a[APND_MARK_SIZE]; ++ ++ if( sz<=APND_MARK_SIZE ) return -1; ++ rc = pFile->pMethods->xRead(pFile, a, APND_MARK_SIZE, sz-APND_MARK_SIZE); ++ if( rc ) return -1; ++ if( memcmp(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ)!=0 ) return -1; ++ iMark = ((sqlite3_int64)(a[APND_MARK_PREFIX_SZ]&0x7f))<<56; ++ for(i=1; i<8; i++){ ++ iMark += (sqlite3_int64)a[APND_MARK_PREFIX_SZ+i]<<(56-8*i); ++ } ++ return iMark; ++} ++ ++/* ++** Open an apnd file handle. ++*/ ++static int apndOpen( ++ sqlite3_vfs *pVfs, ++ const char *zName, ++ sqlite3_file *pFile, ++ int flags, ++ int *pOutFlags ++){ ++ ApndFile *p; ++ sqlite3_file *pSubFile; ++ sqlite3_vfs *pSubVfs; ++ int rc; ++ sqlite3_int64 sz; ++ pSubVfs = ORIGVFS(pVfs); ++ if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){ ++ return pSubVfs->xOpen(pSubVfs, zName, pFile, flags, pOutFlags); ++ } ++ p = (ApndFile*)pFile; ++ memset(p, 0, sizeof(*p)); ++ pSubFile = ORIGFILE(pFile); ++ p->base.pMethods = &apnd_io_methods; ++ rc = pSubVfs->xOpen(pSubVfs, zName, pSubFile, flags, pOutFlags); ++ if( rc ) goto apnd_open_done; ++ rc = pSubFile->pMethods->xFileSize(pSubFile, &sz); ++ if( rc ){ ++ pSubFile->pMethods->xClose(pSubFile); ++ goto apnd_open_done; ++ } ++ if( apndIsOrdinaryDatabaseFile(sz, pSubFile) ){ ++ memmove(pFile, pSubFile, pSubVfs->szOsFile); ++ return SQLITE_OK; ++ } ++ p->iMark = 0; ++ p->iPgOne = apndReadMark(sz, pFile); ++ if( p->iPgOne>0 ){ ++ return SQLITE_OK; ++ } ++ if( (flags & SQLITE_OPEN_CREATE)==0 ){ ++ pSubFile->pMethods->xClose(pSubFile); ++ rc = SQLITE_CANTOPEN; ++ } ++ p->iPgOne = (sz+0xfff) & ~(sqlite3_int64)0xfff; ++apnd_open_done: ++ if( rc ) pFile->pMethods = 0; ++ return rc; ++} ++ ++/* ++** All other VFS methods are pass-thrus. ++*/ ++static int apndDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ ++ return ORIGVFS(pVfs)->xDelete(ORIGVFS(pVfs), zPath, dirSync); ++} ++static int apndAccess( ++ sqlite3_vfs *pVfs, ++ const char *zPath, ++ int flags, ++ int *pResOut ++){ ++ return ORIGVFS(pVfs)->xAccess(ORIGVFS(pVfs), zPath, flags, pResOut); ++} ++static int apndFullPathname( ++ sqlite3_vfs *pVfs, ++ const char *zPath, ++ int nOut, ++ char *zOut ++){ ++ return ORIGVFS(pVfs)->xFullPathname(ORIGVFS(pVfs),zPath,nOut,zOut); ++} ++static void *apndDlOpen(sqlite3_vfs *pVfs, const char *zPath){ ++ return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath); ++} ++static void apndDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ ++ ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg); ++} ++static void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){ ++ return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym); ++} ++static void apndDlClose(sqlite3_vfs *pVfs, void *pHandle){ ++ ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle); ++} ++static int apndRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ ++ return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut); ++} ++static int apndSleep(sqlite3_vfs *pVfs, int nMicro){ ++ return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro); ++} ++static int apndCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ ++ return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut); ++} ++static int apndGetLastError(sqlite3_vfs *pVfs, int a, char *b){ ++ return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b); ++} ++static int apndCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){ ++ return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p); ++} ++static int apndSetSystemCall( ++ sqlite3_vfs *pVfs, ++ const char *zName, ++ sqlite3_syscall_ptr pCall ++){ ++ return ORIGVFS(pVfs)->xSetSystemCall(ORIGVFS(pVfs),zName,pCall); ++} ++static sqlite3_syscall_ptr apndGetSystemCall( ++ sqlite3_vfs *pVfs, ++ const char *zName ++){ ++ return ORIGVFS(pVfs)->xGetSystemCall(ORIGVFS(pVfs),zName); ++} ++static const char *apndNextSystemCall(sqlite3_vfs *pVfs, const char *zName){ ++ return ORIGVFS(pVfs)->xNextSystemCall(ORIGVFS(pVfs), zName); ++} ++ ++ ++#ifdef _WIN32 ++ ++#endif ++/* ++** This routine is called when the extension is loaded. ++** Register the new VFS. ++*/ ++int sqlite3_appendvfs_init( ++ sqlite3 *db, ++ char **pzErrMsg, ++ const sqlite3_api_routines *pApi ++){ ++ int rc = SQLITE_OK; ++ sqlite3_vfs *pOrig; ++ SQLITE_EXTENSION_INIT2(pApi); ++ (void)pzErrMsg; ++ (void)db; ++ pOrig = sqlite3_vfs_find(0); ++ apnd_vfs.iVersion = pOrig->iVersion; ++ apnd_vfs.pAppData = pOrig; ++ apnd_vfs.szOsFile = pOrig->szOsFile + sizeof(ApndFile); ++ rc = sqlite3_vfs_register(&apnd_vfs, 0); ++#ifdef APPENDVFS_TEST ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3_auto_extension((void(*)(void))apndvfsRegister); ++ } ++#endif ++ if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY; ++ return rc; ++} ++ ++/************************* End ../ext/misc/appendvfs.c ********************/ ++#ifdef SQLITE_HAVE_ZLIB ++/************************* Begin ../ext/misc/zipfile.c ******************/ ++/* ++** 2017-12-26 ++** ++** The author disclaims copyright to this source code. In place of ++** a legal notice, here is a blessing: ++** ++** May you do good and not evil. ++** May you find forgiveness for yourself and forgive others. ++** May you share freely, never taking more than you give. ++** ++****************************************************************************** ++** ++** This file implements a virtual table for reading and writing ZIP archive ++** files. ++** ++** Usage example: ++** ++** SELECT name, sz, datetime(mtime,'unixepoch') FROM zipfile($filename); ++** ++** Current limitations: ++** ++** * No support for encryption ++** * No support for ZIP archives spanning multiple files ++** * No support for zip64 extensions ++** * Only the "inflate/deflate" (zlib) compression method is supported ++*/ ++SQLITE_EXTENSION_INIT1 ++#include <stdio.h> ++#include <string.h> ++#include <assert.h> ++ ++#include <zlib.h> ++ ++#ifndef SQLITE_OMIT_VIRTUALTABLE ++ ++#ifndef SQLITE_AMALGAMATION ++ ++/* typedef sqlite3_int64 i64; */ ++/* typedef unsigned char u8; */ ++typedef unsigned short u16; ++typedef unsigned long u32; ++#define MIN(a,b) ((a)<(b) ? (a) : (b)) ++ ++#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST) ++# define ALWAYS(X) (1) ++# define NEVER(X) (0) ++#elif !defined(NDEBUG) ++# define ALWAYS(X) ((X)?1:(assert(0),0)) ++# define NEVER(X) ((X)?(assert(0),1):0) ++#else ++# define ALWAYS(X) (X) ++# define NEVER(X) (X) ++#endif ++ ++#endif /* SQLITE_AMALGAMATION */ ++ ++/* ++** Definitions for mode bitmasks S_IFDIR, S_IFREG and S_IFLNK. ++** ++** In some ways it would be better to obtain these values from system ++** header files. But, the dependency is undesirable and (a) these ++** have been stable for decades, (b) the values are part of POSIX and ++** are also made explicit in [man stat], and (c) are part of the ++** file format for zip archives. ++*/ ++#ifndef S_IFDIR ++# define S_IFDIR 0040000 ++#endif ++#ifndef S_IFREG ++# define S_IFREG 0100000 ++#endif ++#ifndef S_IFLNK ++# define S_IFLNK 0120000 ++#endif ++ ++static const char ZIPFILE_SCHEMA[] = ++ "CREATE TABLE y(" ++ "name PRIMARY KEY," /* 0: Name of file in zip archive */ ++ "mode," /* 1: POSIX mode for file */ ++ "mtime," /* 2: Last modification time (secs since 1970)*/ ++ "sz," /* 3: Size of object */ ++ "rawdata," /* 4: Raw data */ ++ "data," /* 5: Uncompressed data */ ++ "method," /* 6: Compression method (integer) */ ++ "z HIDDEN" /* 7: Name of zip file */ ++ ") WITHOUT ROWID;"; ++ ++#define ZIPFILE_F_COLUMN_IDX 7 /* Index of column "file" in the above */ ++#define ZIPFILE_BUFFER_SIZE (64*1024) ++ ++ ++/* ++** Magic numbers used to read and write zip files. ++** ++** ZIPFILE_NEWENTRY_MADEBY: ++** Use this value for the "version-made-by" field in new zip file ++** entries. The upper byte indicates "unix", and the lower byte ++** indicates that the zip file matches pkzip specification 3.0. ++** This is what info-zip seems to do. ++** ++** ZIPFILE_NEWENTRY_REQUIRED: ++** Value for "version-required-to-extract" field of new entries. ++** Version 2.0 is required to support folders and deflate compression. ++** ++** ZIPFILE_NEWENTRY_FLAGS: ++** Value for "general-purpose-bit-flags" field of new entries. Bit ++** 11 means "utf-8 filename and comment". ++** ++** ZIPFILE_SIGNATURE_CDS: ++** First 4 bytes of a valid CDS record. ++** ++** ZIPFILE_SIGNATURE_LFH: ++** First 4 bytes of a valid LFH record. ++** ++** ZIPFILE_SIGNATURE_EOCD ++** First 4 bytes of a valid EOCD record. ++*/ ++#define ZIPFILE_EXTRA_TIMESTAMP 0x5455 ++#define ZIPFILE_NEWENTRY_MADEBY ((3<<8) + 30) ++#define ZIPFILE_NEWENTRY_REQUIRED 20 ++#define ZIPFILE_NEWENTRY_FLAGS 0x800 ++#define ZIPFILE_SIGNATURE_CDS 0x02014b50 ++#define ZIPFILE_SIGNATURE_LFH 0x04034b50 ++#define ZIPFILE_SIGNATURE_EOCD 0x06054b50 ++ ++/* ++** The sizes of the fixed-size part of each of the three main data ++** structures in a zip archive. ++*/ ++#define ZIPFILE_LFH_FIXED_SZ 30 ++#define ZIPFILE_EOCD_FIXED_SZ 22 ++#define ZIPFILE_CDS_FIXED_SZ 46 ++ ++/* ++*** 4.3.16 End of central directory record: ++*** ++*** end of central dir signature 4 bytes (0x06054b50) ++*** number of this disk 2 bytes ++*** number of the disk with the ++*** start of the central directory 2 bytes ++*** total number of entries in the ++*** central directory on this disk 2 bytes ++*** total number of entries in ++*** the central directory 2 bytes ++*** size of the central directory 4 bytes ++*** offset of start of central ++*** directory with respect to ++*** the starting disk number 4 bytes ++*** .ZIP file comment length 2 bytes ++*** .ZIP file comment (variable size) ++*/ ++typedef struct ZipfileEOCD ZipfileEOCD; ++struct ZipfileEOCD { ++ u16 iDisk; ++ u16 iFirstDisk; ++ u16 nEntry; ++ u16 nEntryTotal; ++ u32 nSize; ++ u32 iOffset; ++}; ++ ++/* ++*** 4.3.12 Central directory structure: ++*** ++*** ... ++*** ++*** central file header signature 4 bytes (0x02014b50) ++*** version made by 2 bytes ++*** version needed to extract 2 bytes ++*** general purpose bit flag 2 bytes ++*** compression method 2 bytes ++*** last mod file time 2 bytes ++*** last mod file date 2 bytes ++*** crc-32 4 bytes ++*** compressed size 4 bytes ++*** uncompressed size 4 bytes ++*** file name length 2 bytes ++*** extra field length 2 bytes ++*** file comment length 2 bytes ++*** disk number start 2 bytes ++*** internal file attributes 2 bytes ++*** external file attributes 4 bytes ++*** relative offset of local header 4 bytes ++*/ ++typedef struct ZipfileCDS ZipfileCDS; ++struct ZipfileCDS { ++ u16 iVersionMadeBy; ++ u16 iVersionExtract; ++ u16 flags; ++ u16 iCompression; ++ u16 mTime; ++ u16 mDate; ++ u32 crc32; ++ u32 szCompressed; ++ u32 szUncompressed; ++ u16 nFile; ++ u16 nExtra; ++ u16 nComment; ++ u16 iDiskStart; ++ u16 iInternalAttr; ++ u32 iExternalAttr; ++ u32 iOffset; ++ char *zFile; /* Filename (sqlite3_malloc()) */ ++}; ++ ++/* ++*** 4.3.7 Local file header: ++*** ++*** local file header signature 4 bytes (0x04034b50) ++*** version needed to extract 2 bytes ++*** general purpose bit flag 2 bytes ++*** compression method 2 bytes ++*** last mod file time 2 bytes ++*** last mod file date 2 bytes ++*** crc-32 4 bytes ++*** compressed size 4 bytes ++*** uncompressed size 4 bytes ++*** file name length 2 bytes ++*** extra field length 2 bytes ++*** ++*/ ++typedef struct ZipfileLFH ZipfileLFH; ++struct ZipfileLFH { ++ u16 iVersionExtract; ++ u16 flags; ++ u16 iCompression; ++ u16 mTime; ++ u16 mDate; ++ u32 crc32; ++ u32 szCompressed; ++ u32 szUncompressed; ++ u16 nFile; ++ u16 nExtra; ++}; ++ ++typedef struct ZipfileEntry ZipfileEntry; ++struct ZipfileEntry { ++ ZipfileCDS cds; /* Parsed CDS record */ ++ u32 mUnixTime; /* Modification time, in UNIX format */ ++ u8 *aExtra; /* cds.nExtra+cds.nComment bytes of extra data */ ++ i64 iDataOff; /* Offset to data in file (if aData==0) */ ++ u8 *aData; /* cds.szCompressed bytes of compressed data */ ++ ZipfileEntry *pNext; /* Next element in in-memory CDS */ ++}; ++ ++/* ++** Cursor type for zipfile tables. ++*/ ++typedef struct ZipfileCsr ZipfileCsr; ++struct ZipfileCsr { ++ sqlite3_vtab_cursor base; /* Base class - must be first */ ++ i64 iId; /* Cursor ID */ ++ u8 bEof; /* True when at EOF */ ++ u8 bNoop; /* If next xNext() call is no-op */ ++ ++ /* Used outside of write transactions */ ++ FILE *pFile; /* Zip file */ ++ i64 iNextOff; /* Offset of next record in central directory */ ++ ZipfileEOCD eocd; /* Parse of central directory record */ ++ ++ ZipfileEntry *pFreeEntry; /* Free this list when cursor is closed or reset */ ++ ZipfileEntry *pCurrent; /* Current entry */ ++ ZipfileCsr *pCsrNext; /* Next cursor on same virtual table */ ++}; ++ ++typedef struct ZipfileTab ZipfileTab; ++struct ZipfileTab { ++ sqlite3_vtab base; /* Base class - must be first */ ++ char *zFile; /* Zip file this table accesses (may be NULL) */ ++ sqlite3 *db; /* Host database connection */ ++ u8 *aBuffer; /* Temporary buffer used for various tasks */ ++ ++ ZipfileCsr *pCsrList; /* List of cursors */ ++ i64 iNextCsrid; ++ ++ /* The following are used by write transactions only */ ++ ZipfileEntry *pFirstEntry; /* Linked list of all files (if pWriteFd!=0) */ ++ ZipfileEntry *pLastEntry; /* Last element in pFirstEntry list */ ++ FILE *pWriteFd; /* File handle open on zip archive */ ++ i64 szCurrent; /* Current size of zip archive */ ++ i64 szOrig; /* Size of archive at start of transaction */ ++}; ++ ++/* ++** Set the error message contained in context ctx to the results of ++** vprintf(zFmt, ...). ++*/ ++static void zipfileCtxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){ ++ char *zMsg = 0; ++ va_list ap; ++ va_start(ap, zFmt); ++ zMsg = sqlite3_vmprintf(zFmt, ap); ++ sqlite3_result_error(ctx, zMsg, -1); ++ sqlite3_free(zMsg); ++ va_end(ap); ++} ++ ++/* ++** If string zIn is quoted, dequote it in place. Otherwise, if the string ++** is not quoted, do nothing. ++*/ ++static void zipfileDequote(char *zIn){ ++ char q = zIn[0]; ++ if( q=='"' || q=='\'' || q=='`' || q=='[' ){ ++ int iIn = 1; ++ int iOut = 0; ++ if( q=='[' ) q = ']'; ++ while( ALWAYS(zIn[iIn]) ){ ++ char c = zIn[iIn++]; ++ if( c==q && zIn[iIn++]!=q ) break; ++ zIn[iOut++] = c; ++ } ++ zIn[iOut] = '\0'; ++ } ++} ++ ++/* ++** Construct a new ZipfileTab virtual table object. ++** ++** argv[0] -> module name ("zipfile") ++** argv[1] -> database name ++** argv[2] -> table name ++** argv[...] -> "column name" and other module argument fields. ++*/ ++static int zipfileConnect( ++ sqlite3 *db, ++ void *pAux, ++ int argc, const char *const*argv, ++ sqlite3_vtab **ppVtab, ++ char **pzErr ++){ ++ int nByte = sizeof(ZipfileTab) + ZIPFILE_BUFFER_SIZE; ++ int nFile = 0; ++ const char *zFile = 0; ++ ZipfileTab *pNew = 0; ++ int rc; ++ ++ /* If the table name is not "zipfile", require that the argument be ++ ** specified. This stops zipfile tables from being created as: ++ ** ++ ** CREATE VIRTUAL TABLE zzz USING zipfile(); ++ ** ++ ** It does not prevent: ++ ** ++ ** CREATE VIRTUAL TABLE zipfile USING zipfile(); ++ */ ++ assert( 0==sqlite3_stricmp(argv[0], "zipfile") ); ++ if( (0!=sqlite3_stricmp(argv[2], "zipfile") && argc<4) || argc>4 ){ ++ *pzErr = sqlite3_mprintf("zipfile constructor requires one argument"); ++ return SQLITE_ERROR; ++ } ++ ++ if( argc>3 ){ ++ zFile = argv[3]; ++ nFile = (int)strlen(zFile)+1; ++ } ++ ++ rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA); ++ if( rc==SQLITE_OK ){ ++ pNew = (ZipfileTab*)sqlite3_malloc(nByte+nFile); ++ if( pNew==0 ) return SQLITE_NOMEM; ++ memset(pNew, 0, nByte+nFile); ++ pNew->db = db; ++ pNew->aBuffer = (u8*)&pNew[1]; ++ if( zFile ){ ++ pNew->zFile = (char*)&pNew->aBuffer[ZIPFILE_BUFFER_SIZE]; ++ memcpy(pNew->zFile, zFile, nFile); ++ zipfileDequote(pNew->zFile); ++ } ++ } ++ *ppVtab = (sqlite3_vtab*)pNew; ++ return rc; ++} ++ ++/* ++** Free the ZipfileEntry structure indicated by the only argument. ++*/ ++static void zipfileEntryFree(ZipfileEntry *p){ ++ if( p ){ ++ sqlite3_free(p->cds.zFile); ++ sqlite3_free(p); ++ } ++} ++ ++/* ++** Release resources that should be freed at the end of a write ++** transaction. ++*/ ++static void zipfileCleanupTransaction(ZipfileTab *pTab){ ++ ZipfileEntry *pEntry; ++ ZipfileEntry *pNext; ++ ++ if( pTab->pWriteFd ){ ++ fclose(pTab->pWriteFd); ++ pTab->pWriteFd = 0; ++ } ++ for(pEntry=pTab->pFirstEntry; pEntry; pEntry=pNext){ ++ pNext = pEntry->pNext; ++ zipfileEntryFree(pEntry); ++ } ++ pTab->pFirstEntry = 0; ++ pTab->pLastEntry = 0; ++ pTab->szCurrent = 0; ++ pTab->szOrig = 0; ++} ++ ++/* ++** This method is the destructor for zipfile vtab objects. ++*/ ++static int zipfileDisconnect(sqlite3_vtab *pVtab){ ++ zipfileCleanupTransaction((ZipfileTab*)pVtab); ++ sqlite3_free(pVtab); ++ return SQLITE_OK; ++} ++ ++/* ++** Constructor for a new ZipfileCsr object. ++*/ ++static int zipfileOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCsr){ ++ ZipfileTab *pTab = (ZipfileTab*)p; ++ ZipfileCsr *pCsr; ++ pCsr = sqlite3_malloc(sizeof(*pCsr)); ++ *ppCsr = (sqlite3_vtab_cursor*)pCsr; ++ if( pCsr==0 ){ ++ return SQLITE_NOMEM; ++ } ++ memset(pCsr, 0, sizeof(*pCsr)); ++ pCsr->iId = ++pTab->iNextCsrid; ++ pCsr->pCsrNext = pTab->pCsrList; ++ pTab->pCsrList = pCsr; ++ return SQLITE_OK; ++} ++ ++/* ++** Reset a cursor back to the state it was in when first returned ++** by zipfileOpen(). ++*/ ++static void zipfileResetCursor(ZipfileCsr *pCsr){ ++ ZipfileEntry *p; ++ ZipfileEntry *pNext; ++ ++ pCsr->bEof = 0; ++ if( pCsr->pFile ){ ++ fclose(pCsr->pFile); ++ pCsr->pFile = 0; ++ zipfileEntryFree(pCsr->pCurrent); ++ pCsr->pCurrent = 0; ++ } ++ ++ for(p=pCsr->pFreeEntry; p; p=pNext){ ++ pNext = p->pNext; ++ zipfileEntryFree(p); ++ } ++} ++ ++/* ++** Destructor for an ZipfileCsr. ++*/ ++static int zipfileClose(sqlite3_vtab_cursor *cur){ ++ ZipfileCsr *pCsr = (ZipfileCsr*)cur; ++ ZipfileTab *pTab = (ZipfileTab*)(pCsr->base.pVtab); ++ ZipfileCsr **pp; ++ zipfileResetCursor(pCsr); ++ ++ /* Remove this cursor from the ZipfileTab.pCsrList list. */ ++ for(pp=&pTab->pCsrList; *pp!=pCsr; pp=&((*pp)->pCsrNext)); ++ *pp = pCsr->pCsrNext; ++ ++ sqlite3_free(pCsr); ++ return SQLITE_OK; ++} ++ ++/* ++** Set the error message for the virtual table associated with cursor ++** pCsr to the results of vprintf(zFmt, ...). ++*/ ++static void zipfileTableErr(ZipfileTab *pTab, const char *zFmt, ...){ ++ va_list ap; ++ va_start(ap, zFmt); ++ sqlite3_free(pTab->base.zErrMsg); ++ pTab->base.zErrMsg = sqlite3_vmprintf(zFmt, ap); ++ va_end(ap); ++} ++static void zipfileCursorErr(ZipfileCsr *pCsr, const char *zFmt, ...){ ++ va_list ap; ++ va_start(ap, zFmt); ++ sqlite3_free(pCsr->base.pVtab->zErrMsg); ++ pCsr->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap); ++ va_end(ap); ++} ++ ++/* ++** Read nRead bytes of data from offset iOff of file pFile into buffer ++** aRead[]. Return SQLITE_OK if successful, or an SQLite error code ++** otherwise. ++** ++** If an error does occur, output variable (*pzErrmsg) may be set to point ++** to an English language error message. It is the responsibility of the ++** caller to eventually free this buffer using ++** sqlite3_free(). ++*/ ++static int zipfileReadData( ++ FILE *pFile, /* Read from this file */ ++ u8 *aRead, /* Read into this buffer */ ++ int nRead, /* Number of bytes to read */ ++ i64 iOff, /* Offset to read from */ ++ char **pzErrmsg /* OUT: Error message (from sqlite3_malloc) */ ++){ ++ size_t n; ++ fseek(pFile, (long)iOff, SEEK_SET); ++ n = fread(aRead, 1, nRead, pFile); ++ if( (int)n!=nRead ){ ++ *pzErrmsg = sqlite3_mprintf("error in fread()"); ++ return SQLITE_ERROR; ++ } ++ return SQLITE_OK; ++} ++ ++static int zipfileAppendData( ++ ZipfileTab *pTab, ++ const u8 *aWrite, ++ int nWrite ++){ ++ size_t n; ++ fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET); ++ n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd); ++ if( (int)n!=nWrite ){ ++ pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()"); ++ return SQLITE_ERROR; ++ } ++ pTab->szCurrent += nWrite; ++ return SQLITE_OK; ++} ++ ++/* ++** Read and return a 16-bit little-endian unsigned integer from buffer aBuf. ++*/ ++static u16 zipfileGetU16(const u8 *aBuf){ ++ return (aBuf[1] << 8) + aBuf[0]; ++} ++ ++/* ++** Read and return a 32-bit little-endian unsigned integer from buffer aBuf. ++*/ ++static u32 zipfileGetU32(const u8 *aBuf){ ++ return ((u32)(aBuf[3]) << 24) ++ + ((u32)(aBuf[2]) << 16) ++ + ((u32)(aBuf[1]) << 8) ++ + ((u32)(aBuf[0]) << 0); ++} ++ ++/* ++** Write a 16-bit little endiate integer into buffer aBuf. ++*/ ++static void zipfilePutU16(u8 *aBuf, u16 val){ ++ aBuf[0] = val & 0xFF; ++ aBuf[1] = (val>>8) & 0xFF; ++} ++ ++/* ++** Write a 32-bit little endiate integer into buffer aBuf. ++*/ ++static void zipfilePutU32(u8 *aBuf, u32 val){ ++ aBuf[0] = val & 0xFF; ++ aBuf[1] = (val>>8) & 0xFF; ++ aBuf[2] = (val>>16) & 0xFF; ++ aBuf[3] = (val>>24) & 0xFF; ++} ++ ++#define zipfileRead32(aBuf) ( aBuf+=4, zipfileGetU32(aBuf-4) ) ++#define zipfileRead16(aBuf) ( aBuf+=2, zipfileGetU16(aBuf-2) ) ++ ++#define zipfileWrite32(aBuf,val) { zipfilePutU32(aBuf,val); aBuf+=4; } ++#define zipfileWrite16(aBuf,val) { zipfilePutU16(aBuf,val); aBuf+=2; } ++ ++/* ++** Magic numbers used to read CDS records. ++*/ ++#define ZIPFILE_CDS_NFILE_OFF 28 ++#define ZIPFILE_CDS_SZCOMPRESSED_OFF 20 ++ ++/* ++** Decode the CDS record in buffer aBuf into (*pCDS). Return SQLITE_ERROR ++** if the record is not well-formed, or SQLITE_OK otherwise. ++*/ ++static int zipfileReadCDS(u8 *aBuf, ZipfileCDS *pCDS){ ++ u8 *aRead = aBuf; ++ u32 sig = zipfileRead32(aRead); ++ int rc = SQLITE_OK; ++ if( sig!=ZIPFILE_SIGNATURE_CDS ){ ++ rc = SQLITE_ERROR; ++ }else{ ++ pCDS->iVersionMadeBy = zipfileRead16(aRead); ++ pCDS->iVersionExtract = zipfileRead16(aRead); ++ pCDS->flags = zipfileRead16(aRead); ++ pCDS->iCompression = zipfileRead16(aRead); ++ pCDS->mTime = zipfileRead16(aRead); ++ pCDS->mDate = zipfileRead16(aRead); ++ pCDS->crc32 = zipfileRead32(aRead); ++ pCDS->szCompressed = zipfileRead32(aRead); ++ pCDS->szUncompressed = zipfileRead32(aRead); ++ assert( aRead==&aBuf[ZIPFILE_CDS_NFILE_OFF] ); ++ pCDS->nFile = zipfileRead16(aRead); ++ pCDS->nExtra = zipfileRead16(aRead); ++ pCDS->nComment = zipfileRead16(aRead); ++ pCDS->iDiskStart = zipfileRead16(aRead); ++ pCDS->iInternalAttr = zipfileRead16(aRead); ++ pCDS->iExternalAttr = zipfileRead32(aRead); ++ pCDS->iOffset = zipfileRead32(aRead); ++ assert( aRead==&aBuf[ZIPFILE_CDS_FIXED_SZ] ); ++ } ++ ++ return rc; ++} ++ ++/* ++** Decode the LFH record in buffer aBuf into (*pLFH). Return SQLITE_ERROR ++** if the record is not well-formed, or SQLITE_OK otherwise. ++*/ ++static int zipfileReadLFH( ++ u8 *aBuffer, ++ ZipfileLFH *pLFH ++){ ++ u8 *aRead = aBuffer; ++ int rc = SQLITE_OK; ++ ++ u32 sig = zipfileRead32(aRead); ++ if( sig!=ZIPFILE_SIGNATURE_LFH ){ ++ rc = SQLITE_ERROR; ++ }else{ ++ pLFH->iVersionExtract = zipfileRead16(aRead); ++ pLFH->flags = zipfileRead16(aRead); ++ pLFH->iCompression = zipfileRead16(aRead); ++ pLFH->mTime = zipfileRead16(aRead); ++ pLFH->mDate = zipfileRead16(aRead); ++ pLFH->crc32 = zipfileRead32(aRead); ++ pLFH->szCompressed = zipfileRead32(aRead); ++ pLFH->szUncompressed = zipfileRead32(aRead); ++ pLFH->nFile = zipfileRead16(aRead); ++ pLFH->nExtra = zipfileRead16(aRead); ++ } ++ return rc; ++} ++ ++ ++/* ++** Buffer aExtra (size nExtra bytes) contains zip archive "extra" fields. ++** Scan through this buffer to find an "extra-timestamp" field. If one ++** exists, extract the 32-bit modification-timestamp from it and store ++** the value in output parameter *pmTime. ++** ++** Zero is returned if no extra-timestamp record could be found (and so ++** *pmTime is left unchanged), or non-zero otherwise. ++** ++** The general format of an extra field is: ++** ++** Header ID 2 bytes ++** Data Size 2 bytes ++** Data N bytes ++*/ ++static int zipfileScanExtra(u8 *aExtra, int nExtra, u32 *pmTime){ ++ int ret = 0; ++ u8 *p = aExtra; ++ u8 *pEnd = &aExtra[nExtra]; ++ ++ while( p<pEnd ){ ++ u16 id = zipfileRead16(p); ++ u16 nByte = zipfileRead16(p); ++ ++ switch( id ){ ++ case ZIPFILE_EXTRA_TIMESTAMP: { ++ u8 b = p[0]; ++ if( b & 0x01 ){ /* 0x01 -> modtime is present */ ++ *pmTime = zipfileGetU32(&p[1]); ++ ret = 1; ++ } ++ break; ++ } ++ } ++ ++ p += nByte; ++ } ++ return ret; ++} ++ ++/* ++** Convert the standard MS-DOS timestamp stored in the mTime and mDate ++** fields of the CDS structure passed as the only argument to a 32-bit ++** UNIX seconds-since-the-epoch timestamp. Return the result. ++** ++** "Standard" MS-DOS time format: ++** ++** File modification time: ++** Bits 00-04: seconds divided by 2 ++** Bits 05-10: minute ++** Bits 11-15: hour ++** File modification date: ++** Bits 00-04: day ++** Bits 05-08: month (1-12) ++** Bits 09-15: years from 1980 ++** ++** https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx ++*/ ++static u32 zipfileMtime(ZipfileCDS *pCDS){ ++ int Y = (1980 + ((pCDS->mDate >> 9) & 0x7F)); ++ int M = ((pCDS->mDate >> 5) & 0x0F); ++ int D = (pCDS->mDate & 0x1F); ++ int B = -13; ++ ++ int sec = (pCDS->mTime & 0x1F)*2; ++ int min = (pCDS->mTime >> 5) & 0x3F; ++ int hr = (pCDS->mTime >> 11) & 0x1F; ++ i64 JD; ++ ++ /* JD = INT(365.25 * (Y+4716)) + INT(30.6001 * (M+1)) + D + B - 1524.5 */ ++ ++ /* Calculate the JD in seconds for noon on the day in question */ ++ if( M<3 ){ ++ Y = Y-1; ++ M = M+12; ++ } ++ JD = (i64)(24*60*60) * ( ++ (int)(365.25 * (Y + 4716)) ++ + (int)(30.6001 * (M + 1)) ++ + D + B - 1524 ++ ); ++ ++ /* Correct the JD for the time within the day */ ++ JD += (hr-12) * 3600 + min * 60 + sec; ++ ++ /* Convert JD to unix timestamp (the JD epoch is 2440587.5) */ ++ return (u32)(JD - (i64)(24405875) * 24*60*6); ++} ++ ++/* ++** The opposite of zipfileMtime(). This function populates the mTime and ++** mDate fields of the CDS structure passed as the first argument according ++** to the UNIX timestamp value passed as the second. ++*/ ++static void zipfileMtimeToDos(ZipfileCDS *pCds, u32 mUnixTime){ ++ /* Convert unix timestamp to JD (2440588 is noon on 1/1/1970) */ ++ i64 JD = (i64)2440588 + mUnixTime / (24*60*60); ++ ++ int A, B, C, D, E; ++ int yr, mon, day; ++ int hr, min, sec; ++ ++ A = (int)((JD - 1867216.25)/36524.25); ++ A = (int)(JD + 1 + A - (A/4)); ++ B = A + 1524; ++ C = (int)((B - 122.1)/365.25); ++ D = (36525*(C&32767))/100; ++ E = (int)((B-D)/30.6001); ++ ++ day = B - D - (int)(30.6001*E); ++ mon = (E<14 ? E-1 : E-13); ++ yr = mon>2 ? C-4716 : C-4715; ++ ++ hr = (mUnixTime % (24*60*60)) / (60*60); ++ min = (mUnixTime % (60*60)) / 60; ++ sec = (mUnixTime % 60); ++ ++ if( yr>=1980 ){ ++ pCds->mDate = (u16)(day + (mon << 5) + ((yr-1980) << 9)); ++ pCds->mTime = (u16)(sec/2 + (min<<5) + (hr<<11)); ++ }else{ ++ pCds->mDate = pCds->mTime = 0; ++ } ++ ++ assert( mUnixTime<315507600 ++ || mUnixTime==zipfileMtime(pCds) ++ || ((mUnixTime % 2) && mUnixTime-1==zipfileMtime(pCds)) ++ /* || (mUnixTime % 2) */ ++ ); ++} ++ ++/* ++** If aBlob is not NULL, then it is a pointer to a buffer (nBlob bytes in ++** size) containing an entire zip archive image. Or, if aBlob is NULL, ++** then pFile is a file-handle open on a zip file. In either case, this ++** function creates a ZipfileEntry object based on the zip archive entry ++** for which the CDS record is at offset iOff. ++** ++** If successful, SQLITE_OK is returned and (*ppEntry) set to point to ++** the new object. Otherwise, an SQLite error code is returned and the ++** final value of (*ppEntry) undefined. ++*/ ++static int zipfileGetEntry( ++ ZipfileTab *pTab, /* Store any error message here */ ++ const u8 *aBlob, /* Pointer to in-memory file image */ ++ int nBlob, /* Size of aBlob[] in bytes */ ++ FILE *pFile, /* If aBlob==0, read from this file */ ++ i64 iOff, /* Offset of CDS record */ ++ ZipfileEntry **ppEntry /* OUT: Pointer to new object */ ++){ ++ u8 *aRead; ++ char **pzErr = &pTab->base.zErrMsg; ++ int rc = SQLITE_OK; ++ ++ if( aBlob==0 ){ ++ aRead = pTab->aBuffer; ++ rc = zipfileReadData(pFile, aRead, ZIPFILE_CDS_FIXED_SZ, iOff, pzErr); ++ }else{ ++ aRead = (u8*)&aBlob[iOff]; ++ } ++ ++ if( rc==SQLITE_OK ){ ++ int nAlloc; ++ ZipfileEntry *pNew; ++ ++ int nFile = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF]); ++ int nExtra = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+2]); ++ nExtra += zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+4]); ++ ++ nAlloc = sizeof(ZipfileEntry) + nExtra; ++ if( aBlob ){ ++ nAlloc += zipfileGetU32(&aRead[ZIPFILE_CDS_SZCOMPRESSED_OFF]); ++ } ++ ++ pNew = (ZipfileEntry*)sqlite3_malloc(nAlloc); ++ if( pNew==0 ){ ++ rc = SQLITE_NOMEM; ++ }else{ ++ memset(pNew, 0, sizeof(ZipfileEntry)); ++ rc = zipfileReadCDS(aRead, &pNew->cds); ++ if( rc!=SQLITE_OK ){ ++ *pzErr = sqlite3_mprintf("failed to read CDS at offset %lld", iOff); ++ }else if( aBlob==0 ){ ++ rc = zipfileReadData( ++ pFile, aRead, nExtra+nFile, iOff+ZIPFILE_CDS_FIXED_SZ, pzErr ++ ); ++ }else{ ++ aRead = (u8*)&aBlob[iOff + ZIPFILE_CDS_FIXED_SZ]; ++ } ++ } ++ ++ if( rc==SQLITE_OK ){ ++ u32 *pt = &pNew->mUnixTime; ++ pNew->cds.zFile = sqlite3_mprintf("%.*s", nFile, aRead); ++ pNew->aExtra = (u8*)&pNew[1]; ++ memcpy(pNew->aExtra, &aRead[nFile], nExtra); ++ if( pNew->cds.zFile==0 ){ ++ rc = SQLITE_NOMEM; ++ }else if( 0==zipfileScanExtra(&aRead[nFile], pNew->cds.nExtra, pt) ){ ++ pNew->mUnixTime = zipfileMtime(&pNew->cds); ++ } ++ } ++ ++ if( rc==SQLITE_OK ){ ++ static const int szFix = ZIPFILE_LFH_FIXED_SZ; ++ ZipfileLFH lfh; ++ if( pFile ){ ++ rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr); ++ }else{ ++ aRead = (u8*)&aBlob[pNew->cds.iOffset]; ++ } ++ ++ rc = zipfileReadLFH(aRead, &lfh); ++ if( rc==SQLITE_OK ){ ++ pNew->iDataOff = pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ; ++ pNew->iDataOff += lfh.nFile + lfh.nExtra; ++ if( aBlob && pNew->cds.szCompressed ){ ++ pNew->aData = &pNew->aExtra[nExtra]; ++ memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed); ++ } ++ }else{ ++ *pzErr = sqlite3_mprintf("failed to read LFH at offset %d", ++ (int)pNew->cds.iOffset ++ ); ++ } ++ } ++ ++ if( rc!=SQLITE_OK ){ ++ zipfileEntryFree(pNew); ++ }else{ ++ *ppEntry = pNew; ++ } ++ } ++ ++ return rc; ++} ++ ++/* ++** Advance an ZipfileCsr to its next row of output. ++*/ ++static int zipfileNext(sqlite3_vtab_cursor *cur){ ++ ZipfileCsr *pCsr = (ZipfileCsr*)cur; ++ int rc = SQLITE_OK; ++ ++ if( pCsr->pFile ){ ++ i64 iEof = pCsr->eocd.iOffset + pCsr->eocd.nSize; ++ zipfileEntryFree(pCsr->pCurrent); ++ pCsr->pCurrent = 0; ++ if( pCsr->iNextOff>=iEof ){ ++ pCsr->bEof = 1; ++ }else{ ++ ZipfileEntry *p = 0; ++ ZipfileTab *pTab = (ZipfileTab*)(cur->pVtab); ++ rc = zipfileGetEntry(pTab, 0, 0, pCsr->pFile, pCsr->iNextOff, &p); ++ if( rc==SQLITE_OK ){ ++ pCsr->iNextOff += ZIPFILE_CDS_FIXED_SZ; ++ pCsr->iNextOff += (int)p->cds.nExtra + p->cds.nFile + p->cds.nComment; ++ } ++ pCsr->pCurrent = p; ++ } ++ }else{ ++ if( !pCsr->bNoop ){ ++ pCsr->pCurrent = pCsr->pCurrent->pNext; ++ } ++ if( pCsr->pCurrent==0 ){ ++ pCsr->bEof = 1; ++ } ++ } ++ ++ pCsr->bNoop = 0; ++ return rc; ++} ++ ++static void zipfileFree(void *p) { ++ sqlite3_free(p); ++} ++ ++/* ++** Buffer aIn (size nIn bytes) contains compressed data. Uncompressed, the ++** size is nOut bytes. This function uncompresses the data and sets the ++** return value in context pCtx to the result (a blob). ++** ++** If an error occurs, an error code is left in pCtx instead. ++*/ ++static void zipfileInflate( ++ sqlite3_context *pCtx, /* Store result here */ ++ const u8 *aIn, /* Compressed data */ ++ int nIn, /* Size of buffer aIn[] in bytes */ ++ int nOut /* Expected output size */ ++){ ++ u8 *aRes = sqlite3_malloc(nOut); ++ if( aRes==0 ){ ++ sqlite3_result_error_nomem(pCtx); ++ }else{ ++ int err; ++ z_stream str; ++ memset(&str, 0, sizeof(str)); ++ ++ str.next_in = (Byte*)aIn; ++ str.avail_in = nIn; ++ str.next_out = (Byte*)aRes; ++ str.avail_out = nOut; ++ ++ err = inflateInit2(&str, -15); ++ if( err!=Z_OK ){ ++ zipfileCtxErrorMsg(pCtx, "inflateInit2() failed (%d)", err); ++ }else{ ++ err = inflate(&str, Z_NO_FLUSH); ++ if( err!=Z_STREAM_END ){ ++ zipfileCtxErrorMsg(pCtx, "inflate() failed (%d)", err); ++ }else{ ++ sqlite3_result_blob(pCtx, aRes, nOut, zipfileFree); ++ aRes = 0; ++ } ++ } ++ sqlite3_free(aRes); ++ inflateEnd(&str); ++ } ++} ++ ++/* ++** Buffer aIn (size nIn bytes) contains uncompressed data. This function ++** compresses it and sets (*ppOut) to point to a buffer containing the ++** compressed data. The caller is responsible for eventually calling ++** sqlite3_free() to release buffer (*ppOut). Before returning, (*pnOut) ++** is set to the size of buffer (*ppOut) in bytes. ++** ++** If no error occurs, SQLITE_OK is returned. Otherwise, an SQLite error ++** code is returned and an error message left in virtual-table handle ++** pTab. The values of (*ppOut) and (*pnOut) are left unchanged in this ++** case. ++*/ ++static int zipfileDeflate( ++ const u8 *aIn, int nIn, /* Input */ ++ u8 **ppOut, int *pnOut, /* Output */ ++ char **pzErr /* OUT: Error message */ ++){ ++ int nAlloc = (int)compressBound(nIn); ++ u8 *aOut; ++ int rc = SQLITE_OK; ++ ++ aOut = (u8*)sqlite3_malloc(nAlloc); ++ if( aOut==0 ){ ++ rc = SQLITE_NOMEM; ++ }else{ ++ int res; ++ z_stream str; ++ memset(&str, 0, sizeof(str)); ++ str.next_in = (Bytef*)aIn; ++ str.avail_in = nIn; ++ str.next_out = aOut; ++ str.avail_out = nAlloc; ++ ++ deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); ++ res = deflate(&str, Z_FINISH); ++ ++ if( res==Z_STREAM_END ){ ++ *ppOut = aOut; ++ *pnOut = (int)str.total_out; ++ }else{ ++ sqlite3_free(aOut); ++ *pzErr = sqlite3_mprintf("zipfile: deflate() error"); ++ rc = SQLITE_ERROR; ++ } ++ deflateEnd(&str); ++ } ++ ++ return rc; ++} ++ ++ ++/* ++** Return values of columns for the row at which the series_cursor ++** is currently pointing. ++*/ ++static int zipfileColumn( ++ sqlite3_vtab_cursor *cur, /* The cursor */ ++ sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ ++ int i /* Which column to return */ ++){ ++ ZipfileCsr *pCsr = (ZipfileCsr*)cur; ++ ZipfileCDS *pCDS = &pCsr->pCurrent->cds; ++ int rc = SQLITE_OK; ++ switch( i ){ ++ case 0: /* name */ ++ sqlite3_result_text(ctx, pCDS->zFile, -1, SQLITE_TRANSIENT); ++ break; ++ case 1: /* mode */ ++ /* TODO: Whether or not the following is correct surely depends on ++ ** the platform on which the archive was created. */ ++ sqlite3_result_int(ctx, pCDS->iExternalAttr >> 16); ++ break; ++ case 2: { /* mtime */ ++ sqlite3_result_int64(ctx, pCsr->pCurrent->mUnixTime); ++ break; ++ } ++ case 3: { /* sz */ ++ if( sqlite3_vtab_nochange(ctx)==0 ){ ++ sqlite3_result_int64(ctx, pCDS->szUncompressed); ++ } ++ break; ++ } ++ case 4: /* rawdata */ ++ if( sqlite3_vtab_nochange(ctx) ) break; ++ case 5: { /* data */ ++ if( i==4 || pCDS->iCompression==0 || pCDS->iCompression==8 ){ ++ int sz = pCDS->szCompressed; ++ int szFinal = pCDS->szUncompressed; ++ if( szFinal>0 ){ ++ u8 *aBuf; ++ u8 *aFree = 0; ++ if( pCsr->pCurrent->aData ){ ++ aBuf = pCsr->pCurrent->aData; ++ }else{ ++ aBuf = aFree = sqlite3_malloc(sz); ++ if( aBuf==0 ){ ++ rc = SQLITE_NOMEM; ++ }else{ ++ FILE *pFile = pCsr->pFile; ++ if( pFile==0 ){ ++ pFile = ((ZipfileTab*)(pCsr->base.pVtab))->pWriteFd; ++ } ++ rc = zipfileReadData(pFile, aBuf, sz, pCsr->pCurrent->iDataOff, ++ &pCsr->base.pVtab->zErrMsg ++ ); ++ } ++ } ++ if( rc==SQLITE_OK ){ ++ if( i==5 && pCDS->iCompression ){ ++ zipfileInflate(ctx, aBuf, sz, szFinal); ++ }else{ ++ sqlite3_result_blob(ctx, aBuf, sz, SQLITE_TRANSIENT); ++ } ++ } ++ 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 */ ++ sqlite3_result_int(ctx, pCDS->iCompression); ++ break; ++ default: /* z */ ++ assert( i==7 ); ++ sqlite3_result_int64(ctx, pCsr->iId); ++ break; ++ } ++ ++ return rc; ++} ++ ++/* ++** Return TRUE if the cursor is at EOF. ++*/ ++static int zipfileEof(sqlite3_vtab_cursor *cur){ ++ ZipfileCsr *pCsr = (ZipfileCsr*)cur; ++ return pCsr->bEof; ++} ++ ++/* ++** If aBlob is not NULL, then it points to a buffer nBlob bytes in size ++** containing an entire zip archive image. Or, if aBlob is NULL, then pFile ++** is guaranteed to be a file-handle open on a zip file. ++** ++** This function attempts to locate the EOCD record within the zip archive ++** and populate *pEOCD with the results of decoding it. SQLITE_OK is ++** returned if successful. Otherwise, an SQLite error code is returned and ++** an English language error message may be left in virtual-table pTab. ++*/ ++static int zipfileReadEOCD( ++ ZipfileTab *pTab, /* Return errors here */ ++ const u8 *aBlob, /* Pointer to in-memory file image */ ++ int nBlob, /* Size of aBlob[] in bytes */ ++ FILE *pFile, /* Read from this file if aBlob==0 */ ++ ZipfileEOCD *pEOCD /* Object to populate */ ++){ ++ u8 *aRead = pTab->aBuffer; /* Temporary buffer */ ++ int nRead; /* Bytes to read from file */ ++ int rc = SQLITE_OK; ++ ++ if( aBlob==0 ){ ++ i64 iOff; /* Offset to read from */ ++ i64 szFile; /* Total size of file in bytes */ ++ fseek(pFile, 0, SEEK_END); ++ szFile = (i64)ftell(pFile); ++ if( szFile==0 ){ ++ memset(pEOCD, 0, sizeof(ZipfileEOCD)); ++ return SQLITE_OK; ++ } ++ nRead = (int)(MIN(szFile, ZIPFILE_BUFFER_SIZE)); ++ iOff = szFile - nRead; ++ rc = zipfileReadData(pFile, aRead, nRead, iOff, &pTab->base.zErrMsg); ++ }else{ ++ nRead = (int)(MIN(nBlob, ZIPFILE_BUFFER_SIZE)); ++ aRead = (u8*)&aBlob[nBlob-nRead]; ++ } ++ ++ if( rc==SQLITE_OK ){ ++ int i; ++ ++ /* Scan backwards looking for the signature bytes */ ++ for(i=nRead-20; i>=0; i--){ ++ if( aRead[i]==0x50 && aRead[i+1]==0x4b ++ && aRead[i+2]==0x05 && aRead[i+3]==0x06 ++ ){ ++ break; ++ } ++ } ++ if( i<0 ){ ++ pTab->base.zErrMsg = sqlite3_mprintf( ++ "cannot find end of central directory record" ++ ); ++ return SQLITE_ERROR; ++ } ++ ++ aRead += i+4; ++ pEOCD->iDisk = zipfileRead16(aRead); ++ pEOCD->iFirstDisk = zipfileRead16(aRead); ++ pEOCD->nEntry = zipfileRead16(aRead); ++ pEOCD->nEntryTotal = zipfileRead16(aRead); ++ pEOCD->nSize = zipfileRead32(aRead); ++ pEOCD->iOffset = zipfileRead32(aRead); ++ } ++ ++ return rc; ++} ++ ++/* ++** Add object pNew to the linked list that begins at ZipfileTab.pFirstEntry ++** and ends with pLastEntry. If argument pBefore is NULL, then pNew is added ++** to the end of the list. Otherwise, it is added to the list immediately ++** before pBefore (which is guaranteed to be a part of said list). ++*/ ++static void zipfileAddEntry( ++ ZipfileTab *pTab, ++ ZipfileEntry *pBefore, ++ ZipfileEntry *pNew ++){ ++ assert( (pTab->pFirstEntry==0)==(pTab->pLastEntry==0) ); ++ assert( pNew->pNext==0 ); ++ if( pBefore==0 ){ ++ if( pTab->pFirstEntry==0 ){ ++ pTab->pFirstEntry = pTab->pLastEntry = pNew; ++ }else{ ++ assert( pTab->pLastEntry->pNext==0 ); ++ pTab->pLastEntry->pNext = pNew; ++ pTab->pLastEntry = pNew; ++ } ++ }else{ ++ ZipfileEntry **pp; ++ for(pp=&pTab->pFirstEntry; *pp!=pBefore; pp=&((*pp)->pNext)); ++ pNew->pNext = pBefore; ++ *pp = pNew; ++ } ++} ++ ++static int zipfileLoadDirectory(ZipfileTab *pTab, const u8 *aBlob, int nBlob){ ++ ZipfileEOCD eocd; ++ int rc; ++ int i; ++ i64 iOff; ++ ++ rc = zipfileReadEOCD(pTab, aBlob, nBlob, pTab->pWriteFd, &eocd); ++ iOff = eocd.iOffset; ++ for(i=0; rc==SQLITE_OK && i<eocd.nEntry; i++){ ++ ZipfileEntry *pNew = 0; ++ rc = zipfileGetEntry(pTab, aBlob, nBlob, pTab->pWriteFd, iOff, &pNew); ++ ++ if( rc==SQLITE_OK ){ ++ zipfileAddEntry(pTab, 0, pNew); ++ iOff += ZIPFILE_CDS_FIXED_SZ; ++ iOff += (int)pNew->cds.nExtra + pNew->cds.nFile + pNew->cds.nComment; ++ } ++ } ++ return rc; ++} ++ ++/* ++** xFilter callback. ++*/ ++static int zipfileFilter( ++ sqlite3_vtab_cursor *cur, ++ int idxNum, const char *idxStr, ++ int argc, sqlite3_value **argv ++){ ++ ZipfileTab *pTab = (ZipfileTab*)cur->pVtab; ++ ZipfileCsr *pCsr = (ZipfileCsr*)cur; ++ const char *zFile = 0; /* Zip file to scan */ ++ int rc = SQLITE_OK; /* Return Code */ ++ int bInMemory = 0; /* True for an in-memory zipfile */ ++ ++ zipfileResetCursor(pCsr); ++ ++ if( pTab->zFile ){ ++ zFile = pTab->zFile; ++ }else if( idxNum==0 ){ ++ zipfileCursorErr(pCsr, "zipfile() function requires an argument"); ++ return SQLITE_ERROR; ++ }else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){ ++ const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]); ++ int nBlob = sqlite3_value_bytes(argv[0]); ++ assert( pTab->pFirstEntry==0 ); ++ rc = zipfileLoadDirectory(pTab, aBlob, nBlob); ++ pCsr->pFreeEntry = pTab->pFirstEntry; ++ pTab->pFirstEntry = pTab->pLastEntry = 0; ++ if( rc!=SQLITE_OK ) return rc; ++ bInMemory = 1; ++ }else{ ++ zFile = (const char*)sqlite3_value_text(argv[0]); ++ } ++ ++ if( 0==pTab->pWriteFd && 0==bInMemory ){ ++ pCsr->pFile = fopen(zFile, "rb"); ++ if( pCsr->pFile==0 ){ ++ zipfileCursorErr(pCsr, "cannot open file: %s", zFile); ++ rc = SQLITE_ERROR; ++ }else{ ++ rc = zipfileReadEOCD(pTab, 0, 0, pCsr->pFile, &pCsr->eocd); ++ if( rc==SQLITE_OK ){ ++ if( pCsr->eocd.nEntry==0 ){ ++ pCsr->bEof = 1; ++ }else{ ++ pCsr->iNextOff = pCsr->eocd.iOffset; ++ rc = zipfileNext(cur); ++ } ++ } ++ } ++ }else{ ++ pCsr->bNoop = 1; ++ pCsr->pCurrent = pCsr->pFreeEntry ? pCsr->pFreeEntry : pTab->pFirstEntry; ++ rc = zipfileNext(cur); ++ } ++ ++ return rc; ++} ++ ++/* ++** xBestIndex callback. ++*/ ++static int zipfileBestIndex( ++ sqlite3_vtab *tab, ++ sqlite3_index_info *pIdxInfo ++){ ++ int i; ++ int idx = -1; ++ int unusable = 0; ++ ++ for(i=0; i<pIdxInfo->nConstraint; i++){ ++ const struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i]; ++ if( pCons->iColumn!=ZIPFILE_F_COLUMN_IDX ) continue; ++ if( pCons->usable==0 ){ ++ unusable = 1; ++ }else if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){ ++ idx = i; ++ } ++ } ++ if( idx>=0 ){ ++ pIdxInfo->aConstraintUsage[idx].argvIndex = 1; ++ pIdxInfo->aConstraintUsage[idx].omit = 1; ++ pIdxInfo->estimatedCost = 1000.0; ++ pIdxInfo->idxNum = 1; ++ }else if( unusable ){ ++ return SQLITE_CONSTRAINT; ++ } ++ return SQLITE_OK; ++} ++ ++static ZipfileEntry *zipfileNewEntry(const char *zPath){ ++ ZipfileEntry *pNew; ++ pNew = sqlite3_malloc(sizeof(ZipfileEntry)); ++ if( pNew ){ ++ memset(pNew, 0, sizeof(ZipfileEntry)); ++ pNew->cds.zFile = sqlite3_mprintf("%s", zPath); ++ if( pNew->cds.zFile==0 ){ ++ sqlite3_free(pNew); ++ pNew = 0; ++ } ++ } ++ return pNew; ++} ++ ++static int zipfileSerializeLFH(ZipfileEntry *pEntry, u8 *aBuf){ ++ ZipfileCDS *pCds = &pEntry->cds; ++ u8 *a = aBuf; ++ ++ pCds->nExtra = 9; ++ ++ /* Write the LFH itself */ ++ zipfileWrite32(a, ZIPFILE_SIGNATURE_LFH); ++ zipfileWrite16(a, pCds->iVersionExtract); ++ zipfileWrite16(a, pCds->flags); ++ zipfileWrite16(a, pCds->iCompression); ++ zipfileWrite16(a, pCds->mTime); ++ zipfileWrite16(a, pCds->mDate); ++ zipfileWrite32(a, pCds->crc32); ++ zipfileWrite32(a, pCds->szCompressed); ++ zipfileWrite32(a, pCds->szUncompressed); ++ zipfileWrite16(a, (u16)pCds->nFile); ++ zipfileWrite16(a, pCds->nExtra); ++ assert( a==&aBuf[ZIPFILE_LFH_FIXED_SZ] ); ++ ++ /* Add the file name */ ++ memcpy(a, pCds->zFile, (int)pCds->nFile); ++ a += (int)pCds->nFile; ++ ++ /* The "extra" data */ ++ zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP); ++ zipfileWrite16(a, 5); ++ *a++ = 0x01; ++ zipfileWrite32(a, pEntry->mUnixTime); ++ ++ return a-aBuf; ++} ++ ++static int zipfileAppendEntry( ++ ZipfileTab *pTab, ++ ZipfileEntry *pEntry, ++ const u8 *pData, ++ int nData ++){ ++ u8 *aBuf = pTab->aBuffer; ++ int nBuf; ++ int rc; ++ ++ nBuf = zipfileSerializeLFH(pEntry, aBuf); ++ rc = zipfileAppendData(pTab, aBuf, nBuf); ++ if( rc==SQLITE_OK ){ ++ pEntry->iDataOff = pTab->szCurrent; ++ rc = zipfileAppendData(pTab, pData, nData); ++ } ++ ++ return rc; ++} ++ ++static int zipfileGetMode( ++ sqlite3_value *pVal, ++ int bIsDir, /* If true, default to directory */ ++ u32 *pMode, /* OUT: Mode value */ ++ char **pzErr /* OUT: Error message */ ++){ ++ const char *z = (const char*)sqlite3_value_text(pVal); ++ u32 mode = 0; ++ if( z==0 ){ ++ mode = (bIsDir ? (S_IFDIR + 0755) : (S_IFREG + 0644)); ++ }else if( z[0]>='0' && z[0]<='9' ){ ++ mode = (unsigned int)sqlite3_value_int(pVal); ++ }else{ ++ const char zTemplate[11] = "-rwxrwxrwx"; ++ int i; ++ if( strlen(z)!=10 ) goto parse_error; ++ switch( z[0] ){ ++ case '-': mode |= S_IFREG; break; ++ case 'd': mode |= S_IFDIR; break; ++ case 'l': mode |= S_IFLNK; break; ++ default: goto parse_error; ++ } ++ for(i=1; i<10; i++){ ++ if( z[i]==zTemplate[i] ) mode |= 1 << (9-i); ++ else if( z[i]!='-' ) goto parse_error; ++ } ++ } ++ if( ((mode & S_IFDIR)==0)==bIsDir ){ ++ /* The "mode" attribute is a directory, but data has been specified. ++ ** Or vice-versa - no data but "mode" is a file or symlink. */ ++ *pzErr = sqlite3_mprintf("zipfile: mode does not match data"); ++ return SQLITE_CONSTRAINT; ++ } ++ *pMode = mode; ++ return SQLITE_OK; ++ ++ parse_error: ++ *pzErr = sqlite3_mprintf("zipfile: parse error in mode: %s", z); ++ return SQLITE_ERROR; ++} ++ ++/* ++** Both (const char*) arguments point to nul-terminated strings. Argument ++** nB is the value of strlen(zB). This function returns 0 if the strings are ++** identical, ignoring any trailing '/' character in either path. */ ++static int zipfileComparePath(const char *zA, const char *zB, int nB){ ++ int nA = (int)strlen(zA); ++ if( zA[nA-1]=='/' ) nA--; ++ if( zB[nB-1]=='/' ) nB--; ++ if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0; ++ return 1; ++} ++ ++static int zipfileBegin(sqlite3_vtab *pVtab){ ++ ZipfileTab *pTab = (ZipfileTab*)pVtab; ++ int rc = SQLITE_OK; ++ ++ assert( pTab->pWriteFd==0 ); ++ ++ /* Open a write fd on the file. Also load the entire central directory ++ ** structure into memory. During the transaction any new file data is ++ ** appended to the archive file, but the central directory is accumulated ++ ** in main-memory until the transaction is committed. */ ++ pTab->pWriteFd = fopen(pTab->zFile, "ab+"); ++ if( pTab->pWriteFd==0 ){ ++ pTab->base.zErrMsg = sqlite3_mprintf( ++ "zipfile: failed to open file %s for writing", pTab->zFile ++ ); ++ rc = SQLITE_ERROR; ++ }else{ ++ fseek(pTab->pWriteFd, 0, SEEK_END); ++ pTab->szCurrent = pTab->szOrig = (i64)ftell(pTab->pWriteFd); ++ rc = zipfileLoadDirectory(pTab, 0, 0); ++ } ++ ++ if( rc!=SQLITE_OK ){ ++ zipfileCleanupTransaction(pTab); ++ } ++ ++ return rc; ++} ++ ++/* ++** Return the current time as a 32-bit timestamp in UNIX epoch format (like ++** time(2)). ++*/ ++static u32 zipfileTime(void){ ++ sqlite3_vfs *pVfs = sqlite3_vfs_find(0); ++ u32 ret; ++ if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){ ++ i64 ms; ++ pVfs->xCurrentTimeInt64(pVfs, &ms); ++ ret = (u32)((ms/1000) - ((i64)24405875 * 8640)); ++ }else{ ++ double day; ++ pVfs->xCurrentTime(pVfs, &day); ++ ret = (u32)((day - 2440587.5) * 86400); ++ } ++ return ret; ++} ++ ++/* ++** Return a 32-bit timestamp in UNIX epoch format. ++** ++** If the value passed as the only argument is either NULL or an SQL NULL, ++** return the current time. Otherwise, return the value stored in (*pVal) ++** cast to a 32-bit unsigned integer. ++*/ ++static u32 zipfileGetTime(sqlite3_value *pVal){ ++ if( pVal==0 || sqlite3_value_type(pVal)==SQLITE_NULL ){ ++ return zipfileTime(); ++ } ++ return (u32)sqlite3_value_int64(pVal); ++} ++ ++/* ++** 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. ++*/ ++static int zipfileUpdate( ++ sqlite3_vtab *pVtab, ++ int nVal, ++ sqlite3_value **apVal, ++ sqlite_int64 *pRowid ++){ ++ ZipfileTab *pTab = (ZipfileTab*)pVtab; ++ int rc = SQLITE_OK; /* Return Code */ ++ ZipfileEntry *pNew = 0; /* New in-memory CDS entry */ ++ ++ u32 mode = 0; /* Mode for new entry */ ++ u32 mTime = 0; /* Modification time for new entry */ ++ i64 sz = 0; /* Uncompressed size */ ++ const char *zPath = 0; /* Path for new entry */ ++ int nPath = 0; /* strlen(zPath) */ ++ const u8 *pData = 0; /* Pointer to buffer containing content */ ++ int nData = 0; /* Size of pData buffer in bytes */ ++ int iMethod = 0; /* Compression method for new entry */ ++ u8 *pFree = 0; /* Free this */ ++ char *zFree = 0; /* Also free this */ ++ ZipfileEntry *pOld = 0; ++ ZipfileEntry *pOld2 = 0; ++ int bUpdate = 0; /* True for an update that modifies "name" */ ++ int bIsDir = 0; ++ u32 iCrc32 = 0; ++ ++ if( pTab->pWriteFd==0 ){ ++ rc = zipfileBegin(pVtab); ++ if( rc!=SQLITE_OK ) return rc; ++ } ++ ++ /* If this is a DELETE or UPDATE, find the archive entry to delete. */ ++ if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ ++ const char *zDelete = (const char*)sqlite3_value_text(apVal[0]); ++ int nDelete = (int)strlen(zDelete); ++ if( nVal>1 ){ ++ const char *zUpdate = (const char*)sqlite3_value_text(apVal[1]); ++ if( zUpdate && zipfileComparePath(zUpdate, zDelete, nDelete)!=0 ){ ++ bUpdate = 1; ++ } ++ } ++ for(pOld=pTab->pFirstEntry; 1; pOld=pOld->pNext){ ++ if( zipfileComparePath(pOld->cds.zFile, zDelete, nDelete)==0 ){ ++ break; ++ } ++ assert( pOld->pNext ); ++ } ++ } ++ ++ if( nVal>1 ){ ++ /* Check that "sz" and "rawdata" are both NULL: */ ++ if( sqlite3_value_type(apVal[5])!=SQLITE_NULL ){ ++ zipfileTableErr(pTab, "sz must be NULL"); ++ rc = SQLITE_CONSTRAINT; ++ } ++ if( sqlite3_value_type(apVal[6])!=SQLITE_NULL ){ ++ zipfileTableErr(pTab, "rawdata must be NULL"); ++ rc = SQLITE_CONSTRAINT; ++ } ++ ++ if( rc==SQLITE_OK ){ ++ if( sqlite3_value_type(apVal[7])==SQLITE_NULL ){ ++ /* data=NULL. A directory */ ++ bIsDir = 1; ++ }else{ ++ /* Value specified for "data", and possibly "method". This must be ++ ** a regular file or a symlink. */ ++ const u8 *aIn = sqlite3_value_blob(apVal[7]); ++ int nIn = sqlite3_value_bytes(apVal[7]); ++ int bAuto = sqlite3_value_type(apVal[8])==SQLITE_NULL; ++ ++ iMethod = sqlite3_value_int(apVal[8]); ++ sz = nIn; ++ pData = aIn; ++ nData = nIn; ++ if( iMethod!=0 && iMethod!=8 ){ ++ zipfileTableErr(pTab, "unknown compression method: %d", iMethod); ++ rc = SQLITE_CONSTRAINT; ++ }else{ ++ if( bAuto || iMethod ){ ++ int nCmp; ++ rc = zipfileDeflate(aIn, nIn, &pFree, &nCmp, &pTab->base.zErrMsg); ++ if( rc==SQLITE_OK ){ ++ if( iMethod || nCmp<nIn ){ ++ iMethod = 8; ++ pData = pFree; ++ nData = nCmp; ++ } ++ } ++ } ++ iCrc32 = crc32(0, aIn, nIn); ++ } ++ } ++ } ++ ++ if( rc==SQLITE_OK ){ ++ rc = zipfileGetMode(apVal[3], bIsDir, &mode, &pTab->base.zErrMsg); ++ } ++ ++ if( rc==SQLITE_OK ){ ++ zPath = (const char*)sqlite3_value_text(apVal[2]); ++ nPath = (int)strlen(zPath); ++ mTime = zipfileGetTime(apVal[4]); ++ } ++ ++ if( rc==SQLITE_OK && bIsDir ){ ++ /* For a directory, check that the last character in the path is a ++ ** '/'. This appears to be required for compatibility with info-zip ++ ** (the unzip command on unix). It does not create directories ++ ** otherwise. */ ++ if( zPath[nPath-1]!='/' ){ ++ zFree = sqlite3_mprintf("%s/", zPath); ++ if( zFree==0 ){ rc = SQLITE_NOMEM; } ++ zPath = (const char*)zFree; ++ nPath++; ++ } ++ } ++ ++ /* Check that we're not inserting a duplicate entry -OR- updating an ++ ** entry with a path, thereby making it into a duplicate. */ ++ if( (pOld==0 || bUpdate) && rc==SQLITE_OK ){ ++ ZipfileEntry *p; ++ for(p=pTab->pFirstEntry; p; p=p->pNext){ ++ if( zipfileComparePath(p->cds.zFile, zPath, nPath)==0 ){ ++ switch( sqlite3_vtab_on_conflict(pTab->db) ){ ++ case SQLITE_IGNORE: { ++ goto zipfile_update_done; ++ } ++ case SQLITE_REPLACE: { ++ pOld2 = p; ++ break; ++ } ++ default: { ++ zipfileTableErr(pTab, "duplicate name: \"%s\"", zPath); ++ rc = SQLITE_CONSTRAINT; ++ break; ++ } ++ } ++ break; ++ } ++ } ++ } ++ ++ if( rc==SQLITE_OK ){ ++ /* Create the new CDS record. */ ++ pNew = zipfileNewEntry(zPath); ++ if( pNew==0 ){ ++ rc = SQLITE_NOMEM; ++ }else{ ++ pNew->cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY; ++ pNew->cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED; ++ pNew->cds.flags = ZIPFILE_NEWENTRY_FLAGS; ++ pNew->cds.iCompression = (u16)iMethod; ++ zipfileMtimeToDos(&pNew->cds, mTime); ++ pNew->cds.crc32 = iCrc32; ++ pNew->cds.szCompressed = nData; ++ pNew->cds.szUncompressed = (u32)sz; ++ pNew->cds.iExternalAttr = (mode<<16); ++ pNew->cds.iOffset = (u32)pTab->szCurrent; ++ pNew->cds.nFile = (u16)nPath; ++ pNew->mUnixTime = (u32)mTime; ++ rc = zipfileAppendEntry(pTab, pNew, pData, nData); ++ zipfileAddEntry(pTab, pOld, pNew); ++ } ++ } ++ } ++ ++ if( rc==SQLITE_OK && (pOld || pOld2) ){ ++ ZipfileCsr *pCsr; ++ for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){ ++ if( pCsr->pCurrent && (pCsr->pCurrent==pOld || pCsr->pCurrent==pOld2) ){ ++ pCsr->pCurrent = pCsr->pCurrent->pNext; ++ pCsr->bNoop = 1; ++ } ++ } ++ ++ zipfileRemoveEntryFromList(pTab, pOld); ++ zipfileRemoveEntryFromList(pTab, pOld2); ++ } ++ ++zipfile_update_done: ++ sqlite3_free(pFree); ++ sqlite3_free(zFree); ++ return rc; ++} ++ ++static int zipfileSerializeEOCD(ZipfileEOCD *p, u8 *aBuf){ ++ u8 *a = aBuf; ++ zipfileWrite32(a, ZIPFILE_SIGNATURE_EOCD); ++ zipfileWrite16(a, p->iDisk); ++ zipfileWrite16(a, p->iFirstDisk); ++ zipfileWrite16(a, p->nEntry); ++ zipfileWrite16(a, p->nEntryTotal); ++ zipfileWrite32(a, p->nSize); ++ zipfileWrite32(a, p->iOffset); ++ zipfileWrite16(a, 0); /* Size of trailing comment in bytes*/ ++ ++ return a-aBuf; ++} ++ ++static int zipfileAppendEOCD(ZipfileTab *pTab, ZipfileEOCD *p){ ++ int nBuf = zipfileSerializeEOCD(p, pTab->aBuffer); ++ assert( nBuf==ZIPFILE_EOCD_FIXED_SZ ); ++ return zipfileAppendData(pTab, pTab->aBuffer, nBuf); ++} ++ ++/* ++** Serialize the CDS structure into buffer aBuf[]. Return the number ++** of bytes written. ++*/ ++static int zipfileSerializeCDS(ZipfileEntry *pEntry, u8 *aBuf){ ++ u8 *a = aBuf; ++ ZipfileCDS *pCDS = &pEntry->cds; ++ ++ if( pEntry->aExtra==0 ){ ++ pCDS->nExtra = 9; ++ } ++ ++ zipfileWrite32(a, ZIPFILE_SIGNATURE_CDS); ++ zipfileWrite16(a, pCDS->iVersionMadeBy); ++ zipfileWrite16(a, pCDS->iVersionExtract); ++ zipfileWrite16(a, pCDS->flags); ++ zipfileWrite16(a, pCDS->iCompression); ++ zipfileWrite16(a, pCDS->mTime); ++ zipfileWrite16(a, pCDS->mDate); ++ zipfileWrite32(a, pCDS->crc32); ++ zipfileWrite32(a, pCDS->szCompressed); ++ zipfileWrite32(a, pCDS->szUncompressed); ++ assert( a==&aBuf[ZIPFILE_CDS_NFILE_OFF] ); ++ zipfileWrite16(a, pCDS->nFile); ++ zipfileWrite16(a, pCDS->nExtra); ++ zipfileWrite16(a, pCDS->nComment); ++ zipfileWrite16(a, pCDS->iDiskStart); ++ zipfileWrite16(a, pCDS->iInternalAttr); ++ zipfileWrite32(a, pCDS->iExternalAttr); ++ zipfileWrite32(a, pCDS->iOffset); ++ ++ memcpy(a, pCDS->zFile, pCDS->nFile); ++ a += pCDS->nFile; ++ ++ if( pEntry->aExtra ){ ++ int n = (int)pCDS->nExtra + (int)pCDS->nComment; ++ memcpy(a, pEntry->aExtra, n); ++ a += n; ++ }else{ ++ assert( pCDS->nExtra==9 ); ++ zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP); ++ zipfileWrite16(a, 5); ++ *a++ = 0x01; ++ zipfileWrite32(a, pEntry->mUnixTime); ++ } ++ ++ return a-aBuf; ++} ++ ++static int zipfileCommit(sqlite3_vtab *pVtab){ ++ ZipfileTab *pTab = (ZipfileTab*)pVtab; ++ int rc = SQLITE_OK; ++ if( pTab->pWriteFd ){ ++ i64 iOffset = pTab->szCurrent; ++ ZipfileEntry *p; ++ ZipfileEOCD eocd; ++ int nEntry = 0; ++ ++ /* Write out all entries */ ++ for(p=pTab->pFirstEntry; rc==SQLITE_OK && p; p=p->pNext){ ++ int n = zipfileSerializeCDS(p, pTab->aBuffer); ++ rc = zipfileAppendData(pTab, pTab->aBuffer, n); ++ nEntry++; ++ } ++ ++ /* Write out the EOCD record */ ++ eocd.iDisk = 0; ++ eocd.iFirstDisk = 0; ++ eocd.nEntry = (u16)nEntry; ++ eocd.nEntryTotal = (u16)nEntry; ++ eocd.nSize = (u32)(pTab->szCurrent - iOffset); ++ eocd.iOffset = (u32)iOffset; ++ rc = zipfileAppendEOCD(pTab, &eocd); ++ ++ zipfileCleanupTransaction(pTab); ++ } ++ return rc; ++} ++ ++static int zipfileRollback(sqlite3_vtab *pVtab){ ++ return zipfileCommit(pVtab); ++} ++ ++static ZipfileCsr *zipfileFindCursor(ZipfileTab *pTab, i64 iId){ ++ ZipfileCsr *pCsr; ++ for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){ ++ if( iId==pCsr->iId ) break; ++ } ++ return pCsr; ++} ++ ++static void zipfileFunctionCds( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ ZipfileCsr *pCsr; ++ ZipfileTab *pTab = (ZipfileTab*)sqlite3_user_data(context); ++ assert( argc>0 ); ++ ++ pCsr = zipfileFindCursor(pTab, sqlite3_value_int64(argv[0])); ++ if( pCsr ){ ++ ZipfileCDS *p = &pCsr->pCurrent->cds; ++ char *zRes = sqlite3_mprintf("{" ++ "\"version-made-by\" : %u, " ++ "\"version-to-extract\" : %u, " ++ "\"flags\" : %u, " ++ "\"compression\" : %u, " ++ "\"time\" : %u, " ++ "\"date\" : %u, " ++ "\"crc32\" : %u, " ++ "\"compressed-size\" : %u, " ++ "\"uncompressed-size\" : %u, " ++ "\"file-name-length\" : %u, " ++ "\"extra-field-length\" : %u, " ++ "\"file-comment-length\" : %u, " ++ "\"disk-number-start\" : %u, " ++ "\"internal-attr\" : %u, " ++ "\"external-attr\" : %u, " ++ "\"offset\" : %u }", ++ (u32)p->iVersionMadeBy, (u32)p->iVersionExtract, ++ (u32)p->flags, (u32)p->iCompression, ++ (u32)p->mTime, (u32)p->mDate, ++ (u32)p->crc32, (u32)p->szCompressed, ++ (u32)p->szUncompressed, (u32)p->nFile, ++ (u32)p->nExtra, (u32)p->nComment, ++ (u32)p->iDiskStart, (u32)p->iInternalAttr, ++ (u32)p->iExternalAttr, (u32)p->iOffset ++ ); ++ ++ if( zRes==0 ){ ++ sqlite3_result_error_nomem(context); ++ }else{ ++ sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT); ++ sqlite3_free(zRes); ++ } ++ } ++} ++ ++/* ++** xFindFunction method. ++*/ ++static int zipfileFindFunction( ++ sqlite3_vtab *pVtab, /* Virtual table handle */ ++ int nArg, /* Number of SQL function arguments */ ++ const char *zName, /* Name of SQL function */ ++ void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */ ++ void **ppArg /* OUT: User data for *pxFunc */ ++){ ++ if( sqlite3_stricmp("zipfile_cds", zName)==0 ){ ++ *pxFunc = zipfileFunctionCds; ++ *ppArg = (void*)pVtab; ++ return 1; ++ } ++ return 0; ++} ++ ++typedef struct ZipfileBuffer ZipfileBuffer; ++struct ZipfileBuffer { ++ u8 *a; /* Pointer to buffer */ ++ int n; /* Size of buffer in bytes */ ++ int nAlloc; /* Byte allocated at a[] */ ++}; ++ ++typedef struct ZipfileCtx ZipfileCtx; ++struct ZipfileCtx { ++ int nEntry; ++ ZipfileBuffer body; ++ ZipfileBuffer cds; ++}; ++ ++static int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){ ++ if( pBuf->n+nByte>pBuf->nAlloc ){ ++ u8 *aNew; ++ int nNew = pBuf->n ? pBuf->n*2 : 512; ++ int nReq = pBuf->n + nByte; ++ ++ while( nNew<nReq ) nNew = nNew*2; ++ aNew = sqlite3_realloc(pBuf->a, nNew); ++ if( aNew==0 ) return SQLITE_NOMEM; ++ pBuf->a = aNew; ++ pBuf->nAlloc = nNew; ++ } ++ return SQLITE_OK; ++} ++ ++/* ++** xStep() callback for the zipfile() aggregate. This can be called in ++** any of the following ways: ++** ++** SELECT zipfile(name,data) ... ++** SELECT zipfile(name,mode,mtime,data) ... ++** SELECT zipfile(name,mode,mtime,data,method) ... ++*/ ++void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){ ++ ZipfileCtx *p; /* Aggregate function context */ ++ ZipfileEntry e; /* New entry to add to zip archive */ ++ ++ sqlite3_value *pName = 0; ++ sqlite3_value *pMode = 0; ++ sqlite3_value *pMtime = 0; ++ sqlite3_value *pData = 0; ++ sqlite3_value *pMethod = 0; ++ ++ int bIsDir = 0; ++ u32 mode; ++ int rc = SQLITE_OK; ++ char *zErr = 0; ++ ++ int iMethod = -1; /* Compression method to use (0 or 8) */ ++ ++ const u8 *aData = 0; /* Possibly compressed data for new entry */ ++ int nData = 0; /* Size of aData[] in bytes */ ++ int szUncompressed = 0; /* Size of data before compression */ ++ u8 *aFree = 0; /* Free this before returning */ ++ u32 iCrc32 = 0; /* crc32 of uncompressed data */ ++ ++ char *zName = 0; /* Path (name) of new entry */ ++ int nName = 0; /* Size of zName in bytes */ ++ char *zFree = 0; /* Free this before returning */ ++ int nByte; ++ ++ memset(&e, 0, sizeof(e)); ++ p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx)); ++ if( p==0 ) return; ++ ++ /* Martial the arguments into stack variables */ ++ if( nVal!=2 && nVal!=4 && nVal!=5 ){ ++ zErr = sqlite3_mprintf("wrong number of arguments to function zipfile()"); ++ rc = SQLITE_ERROR; ++ goto zipfile_step_out; ++ } ++ pName = apVal[0]; ++ if( nVal==2 ){ ++ pData = apVal[1]; ++ }else{ ++ pMode = apVal[1]; ++ pMtime = apVal[2]; ++ pData = apVal[3]; ++ if( nVal==5 ){ ++ pMethod = apVal[4]; ++ } ++ } ++ ++ /* Check that the 'name' parameter looks ok. */ ++ zName = (char*)sqlite3_value_text(pName); ++ nName = sqlite3_value_bytes(pName); ++ if( zName==0 ){ ++ zErr = sqlite3_mprintf("first argument to zipfile() must be non-NULL"); ++ rc = SQLITE_ERROR; ++ goto zipfile_step_out; ++ } ++ ++ /* Inspect the 'method' parameter. This must be either 0 (store), 8 (use ++ ** deflate compression) or NULL (choose automatically). */ ++ if( pMethod && SQLITE_NULL!=sqlite3_value_type(pMethod) ){ ++ iMethod = (int)sqlite3_value_int64(pMethod); ++ if( iMethod!=0 && iMethod!=8 ){ ++ zErr = sqlite3_mprintf("illegal method value: %d", iMethod); ++ rc = SQLITE_ERROR; ++ goto zipfile_step_out; ++ } ++ } ++ ++ /* Now inspect the data. If this is NULL, then the new entry must be a ++ ** directory. Otherwise, figure out whether or not the data should ++ ** be deflated or simply stored in the zip archive. */ ++ if( sqlite3_value_type(pData)==SQLITE_NULL ){ ++ bIsDir = 1; ++ iMethod = 0; ++ }else{ ++ aData = sqlite3_value_blob(pData); ++ szUncompressed = nData = sqlite3_value_bytes(pData); ++ iCrc32 = crc32(0, aData, nData); ++ if( iMethod<0 || iMethod==8 ){ ++ int nOut = 0; ++ rc = zipfileDeflate(aData, nData, &aFree, &nOut, &zErr); ++ if( rc!=SQLITE_OK ){ ++ goto zipfile_step_out; ++ } ++ if( iMethod==8 || nOut<nData ){ ++ aData = aFree; ++ nData = nOut; ++ iMethod = 8; ++ }else{ ++ iMethod = 0; ++ } ++ } ++ } ++ ++ /* Decode the "mode" argument. */ ++ rc = zipfileGetMode(pMode, bIsDir, &mode, &zErr); ++ if( rc ) goto zipfile_step_out; ++ ++ /* Decode the "mtime" argument. */ ++ e.mUnixTime = zipfileGetTime(pMtime); ++ ++ /* If this is a directory entry, ensure that there is exactly one '/' ++ ** at the end of the path. Or, if this is not a directory and the path ++ ** ends in '/' it is an error. */ ++ if( bIsDir==0 ){ ++ if( zName[nName-1]=='/' ){ ++ zErr = sqlite3_mprintf("non-directory name must not end with /"); ++ rc = SQLITE_ERROR; ++ goto zipfile_step_out; ++ } ++ }else{ ++ if( zName[nName-1]!='/' ){ ++ zName = zFree = sqlite3_mprintf("%s/", zName); ++ nName++; ++ if( zName==0 ){ ++ rc = SQLITE_NOMEM; ++ goto zipfile_step_out; ++ } ++ }else{ ++ while( nName>1 && zName[nName-2]=='/' ) nName--; ++ } ++ } ++ ++ /* Assemble the ZipfileEntry object for the new zip archive entry */ ++ e.cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY; ++ e.cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED; ++ e.cds.flags = ZIPFILE_NEWENTRY_FLAGS; ++ e.cds.iCompression = (u16)iMethod; ++ zipfileMtimeToDos(&e.cds, (u32)e.mUnixTime); ++ e.cds.crc32 = iCrc32; ++ e.cds.szCompressed = nData; ++ e.cds.szUncompressed = szUncompressed; ++ e.cds.iExternalAttr = (mode<<16); ++ e.cds.iOffset = p->body.n; ++ e.cds.nFile = (u16)nName; ++ e.cds.zFile = zName; ++ ++ /* Append the LFH to the body of the new archive */ ++ nByte = ZIPFILE_LFH_FIXED_SZ + e.cds.nFile + 9; ++ if( (rc = zipfileBufferGrow(&p->body, nByte)) ) goto zipfile_step_out; ++ p->body.n += zipfileSerializeLFH(&e, &p->body.a[p->body.n]); ++ ++ /* Append the data to the body of the new archive */ ++ if( nData>0 ){ ++ if( (rc = zipfileBufferGrow(&p->body, nData)) ) goto zipfile_step_out; ++ memcpy(&p->body.a[p->body.n], aData, nData); ++ p->body.n += nData; ++ } ++ ++ /* Append the CDS record to the directory of the new archive */ ++ nByte = ZIPFILE_CDS_FIXED_SZ + e.cds.nFile + 9; ++ if( (rc = zipfileBufferGrow(&p->cds, nByte)) ) goto zipfile_step_out; ++ p->cds.n += zipfileSerializeCDS(&e, &p->cds.a[p->cds.n]); ++ ++ /* Increment the count of entries in the archive */ ++ p->nEntry++; ++ ++ zipfile_step_out: ++ sqlite3_free(aFree); ++ sqlite3_free(zFree); ++ if( rc ){ ++ if( zErr ){ ++ sqlite3_result_error(pCtx, zErr, -1); ++ }else{ ++ sqlite3_result_error_code(pCtx, rc); ++ } ++ } ++ sqlite3_free(zErr); ++} ++ ++/* ++** xFinalize() callback for zipfile aggregate function. ++*/ ++void zipfileFinal(sqlite3_context *pCtx){ ++ ZipfileCtx *p; ++ ZipfileEOCD eocd; ++ int nZip; ++ u8 *aZip; ++ ++ p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx)); ++ if( p==0 ) return; ++ if( p->nEntry>0 ){ ++ memset(&eocd, 0, sizeof(eocd)); ++ eocd.nEntry = (u16)p->nEntry; ++ eocd.nEntryTotal = (u16)p->nEntry; ++ eocd.nSize = p->cds.n; ++ eocd.iOffset = p->body.n; ++ ++ nZip = p->body.n + p->cds.n + ZIPFILE_EOCD_FIXED_SZ; ++ aZip = (u8*)sqlite3_malloc(nZip); ++ if( aZip==0 ){ ++ sqlite3_result_error_nomem(pCtx); ++ }else{ ++ memcpy(aZip, p->body.a, p->body.n); ++ memcpy(&aZip[p->body.n], p->cds.a, p->cds.n); ++ zipfileSerializeEOCD(&eocd, &aZip[p->body.n + p->cds.n]); ++ sqlite3_result_blob(pCtx, aZip, nZip, zipfileFree); ++ } ++ } ++ ++ sqlite3_free(p->body.a); ++ sqlite3_free(p->cds.a); ++} ++ ++ ++/* ++** Register the "zipfile" virtual table. ++*/ ++static int zipfileRegister(sqlite3 *db){ ++ static sqlite3_module zipfileModule = { ++ 1, /* iVersion */ ++ zipfileConnect, /* xCreate */ ++ zipfileConnect, /* xConnect */ ++ zipfileBestIndex, /* xBestIndex */ ++ zipfileDisconnect, /* xDisconnect */ ++ zipfileDisconnect, /* xDestroy */ ++ zipfileOpen, /* xOpen - open a cursor */ ++ zipfileClose, /* xClose - close a cursor */ ++ zipfileFilter, /* xFilter - configure scan constraints */ ++ zipfileNext, /* xNext - advance a cursor */ ++ zipfileEof, /* xEof - check for end of scan */ ++ zipfileColumn, /* xColumn - read data */ ++ 0, /* xRowid - read data */ ++ zipfileUpdate, /* xUpdate */ ++ zipfileBegin, /* xBegin */ ++ 0, /* xSync */ ++ zipfileCommit, /* xCommit */ ++ zipfileRollback, /* xRollback */ ++ zipfileFindFunction, /* xFindMethod */ ++ 0, /* xRename */ ++ }; ++ ++ int rc = sqlite3_create_module(db, "zipfile" , &zipfileModule, 0); ++ if( rc==SQLITE_OK ) rc = sqlite3_overload_function(db, "zipfile_cds", -1); ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3_create_function(db, "zipfile", -1, SQLITE_UTF8, 0, 0, ++ zipfileStep, zipfileFinal ++ ); ++ } ++ return rc; ++} ++#else /* SQLITE_OMIT_VIRTUALTABLE */ ++# define zipfileRegister(x) SQLITE_OK ++#endif ++ ++#ifdef _WIN32 ++ ++#endif ++int sqlite3_zipfile_init( ++ sqlite3 *db, ++ char **pzErrMsg, ++ const sqlite3_api_routines *pApi ++){ ++ SQLITE_EXTENSION_INIT2(pApi); ++ (void)pzErrMsg; /* Unused parameter */ ++ return zipfileRegister(db); ++} ++ ++/************************* End ../ext/misc/zipfile.c ********************/ ++/************************* Begin ../ext/misc/sqlar.c ******************/ ++/* ++** 2017-12-17 ++** ++** The author disclaims copyright to this source code. In place of ++** a legal notice, here is a blessing: ++** ++** May you do good and not evil. ++** May you find forgiveness for yourself and forgive others. ++** May you share freely, never taking more than you give. ++** ++****************************************************************************** ++** ++** Utility functions sqlar_compress() and sqlar_uncompress(). Useful ++** for working with sqlar archives and used by the shell tool's built-in ++** sqlar support. ++*/ ++SQLITE_EXTENSION_INIT1 ++#include <zlib.h> ++ ++/* ++** Implementation of the "sqlar_compress(X)" SQL function. ++** ++** If the type of X is SQLITE_BLOB, and compressing that blob using ++** zlib utility function compress() yields a smaller blob, return the ++** compressed blob. Otherwise, return a copy of X. ++** ++** SQLar uses the "zlib format" for compressed content. The zlib format ++** contains a two-byte identification header and a four-byte checksum at ++** the end. This is different from ZIP which uses the raw deflate format. ++** ++** Future enhancements to SQLar might add support for new compression formats. ++** If so, those new formats will be identified by alternative headers in the ++** compressed data. ++*/ ++static void sqlarCompressFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ assert( argc==1 ); ++ if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){ ++ const Bytef *pData = sqlite3_value_blob(argv[0]); ++ uLong nData = sqlite3_value_bytes(argv[0]); ++ uLongf nOut = compressBound(nData); ++ Bytef *pOut; ++ ++ pOut = (Bytef*)sqlite3_malloc(nOut); ++ if( pOut==0 ){ ++ sqlite3_result_error_nomem(context); ++ return; ++ }else{ ++ if( Z_OK!=compress(pOut, &nOut, pData, nData) ){ ++ sqlite3_result_error(context, "error in compress()", -1); ++ }else if( nOut<nData ){ ++ sqlite3_result_blob(context, pOut, nOut, SQLITE_TRANSIENT); ++ }else{ ++ sqlite3_result_value(context, argv[0]); ++ } ++ sqlite3_free(pOut); ++ } ++ }else{ ++ sqlite3_result_value(context, argv[0]); ++ } ++} ++ ++/* ++** Implementation of the "sqlar_uncompress(X,SZ)" SQL function ++** ++** Parameter SZ is interpreted as an integer. If it is less than or ++** equal to zero, then this function returns a copy of X. Or, if ++** SZ is equal to the size of X when interpreted as a blob, also ++** return a copy of X. Otherwise, decompress blob X using zlib ++** utility function uncompress() and return the results (another ++** blob). ++*/ ++static void sqlarUncompressFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ uLong nData; ++ uLongf sz; ++ ++ assert( argc==2 ); ++ sz = sqlite3_value_int(argv[1]); ++ ++ if( sz<=0 || sz==(nData = sqlite3_value_bytes(argv[0])) ){ ++ sqlite3_result_value(context, argv[0]); ++ }else{ ++ const Bytef *pData= sqlite3_value_blob(argv[0]); ++ Bytef *pOut = sqlite3_malloc(sz); ++ if( Z_OK!=uncompress(pOut, &sz, pData, nData) ){ ++ sqlite3_result_error(context, "error in uncompress()", -1); ++ }else{ ++ sqlite3_result_blob(context, pOut, sz, SQLITE_TRANSIENT); ++ } ++ sqlite3_free(pOut); ++ } ++} ++ ++ ++#ifdef _WIN32 ++ ++#endif ++int sqlite3_sqlar_init( ++ sqlite3 *db, ++ char **pzErrMsg, ++ const sqlite3_api_routines *pApi ++){ ++ int rc = SQLITE_OK; ++ SQLITE_EXTENSION_INIT2(pApi); ++ (void)pzErrMsg; /* Unused parameter */ ++ rc = sqlite3_create_function(db, "sqlar_compress", 1, SQLITE_UTF8, 0, ++ sqlarCompressFunc, 0, 0); ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3_create_function(db, "sqlar_uncompress", 2, SQLITE_UTF8, 0, ++ sqlarUncompressFunc, 0, 0); ++ } ++ return rc; ++} ++ ++/************************* End ../ext/misc/sqlar.c ********************/ ++#endif ++/************************* Begin ../ext/expert/sqlite3expert.h ******************/ ++/* ++** 2017 April 07 ++** ++** The author disclaims copyright to this source code. In place of ++** a legal notice, here is a blessing: ++** ++** May you do good and not evil. ++** May you find forgiveness for yourself and forgive others. ++** May you share freely, never taking more than you give. ++** ++************************************************************************* ++*/ ++ ++ ++ ++typedef struct sqlite3expert sqlite3expert; ++ ++/* ++** Create a new sqlite3expert object. ++** ++** If successful, a pointer to the new object is returned and (*pzErr) set ++** to NULL. Or, if an error occurs, NULL is returned and (*pzErr) set to ++** an English-language error message. In this case it is the responsibility ++** of the caller to eventually free the error message buffer using ++** sqlite3_free(). ++*/ ++sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErr); ++ ++/* ++** Configure an sqlite3expert object. ++** ++** EXPERT_CONFIG_SAMPLE: ++** By default, sqlite3_expert_analyze() generates sqlite_stat1 data for ++** each candidate index. This involves scanning and sorting the entire ++** contents of each user database table once for each candidate index ++** associated with the table. For large databases, this can be ++** prohibitively slow. This option allows the sqlite3expert object to ++** be configured so that sqlite_stat1 data is instead generated based on a ++** subset of each table, or so that no sqlite_stat1 data is used at all. ++** ++** A single integer argument is passed to this option. If the value is less ++** than or equal to zero, then no sqlite_stat1 data is generated or used by ++** the analysis - indexes are recommended based on the database schema only. ++** Or, if the value is 100 or greater, complete sqlite_stat1 data is ++** generated for each candidate index (this is the default). Finally, if the ++** value falls between 0 and 100, then it represents the percentage of user ++** table rows that should be considered when generating sqlite_stat1 data. ++** ++** Examples: ++** ++** // Do not generate any sqlite_stat1 data ++** sqlite3_expert_config(pExpert, EXPERT_CONFIG_SAMPLE, 0); ++** ++** // Generate sqlite_stat1 data based on 10% of the rows in each table. ++** sqlite3_expert_config(pExpert, EXPERT_CONFIG_SAMPLE, 10); ++*/ ++int sqlite3_expert_config(sqlite3expert *p, int op, ...); ++ ++#define EXPERT_CONFIG_SAMPLE 1 /* int */ ++ ++/* ++** Specify zero or more SQL statements to be included in the analysis. ++** ++** Buffer zSql must contain zero or more complete SQL statements. This ++** function parses all statements contained in the buffer and adds them ++** to the internal list of statements to analyze. If successful, SQLITE_OK ++** is returned and (*pzErr) set to NULL. Or, if an error occurs - for example ++** due to a error in the SQL - an SQLite error code is returned and (*pzErr) ++** may be set to point to an English language error message. In this case ++** the caller is responsible for eventually freeing the error message buffer ++** using sqlite3_free(). ++** ++** If an error does occur while processing one of the statements in the ++** buffer passed as the second argument, none of the statements in the ++** buffer are added to the analysis. ++** ++** This function must be called before sqlite3_expert_analyze(). If a call ++** to this function is made on an sqlite3expert object that has already ++** been passed to sqlite3_expert_analyze() SQLITE_MISUSE is returned ++** immediately and no statements are added to the analysis. ++*/ ++int sqlite3_expert_sql( ++ sqlite3expert *p, /* From a successful sqlite3_expert_new() */ ++ const char *zSql, /* SQL statement(s) to add */ ++ char **pzErr /* OUT: Error message (if any) */ ++); ++ ++ ++/* ++** This function is called after the sqlite3expert object has been configured ++** with all SQL statements using sqlite3_expert_sql() to actually perform ++** the analysis. Once this function has been called, it is not possible to ++** add further SQL statements to the analysis. ++** ++** If successful, SQLITE_OK is returned and (*pzErr) is set to NULL. Or, if ++** an error occurs, an SQLite error code is returned and (*pzErr) set to ++** point to a buffer containing an English language error message. In this ++** case it is the responsibility of the caller to eventually free the buffer ++** using sqlite3_free(). ++** ++** If an error does occur within this function, the sqlite3expert object ++** is no longer useful for any purpose. At that point it is no longer ++** possible to add further SQL statements to the object or to re-attempt ++** the analysis. The sqlite3expert object must still be freed using a call ++** sqlite3_expert_destroy(). ++*/ ++int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr); ++ ++/* ++** Return the total number of statements loaded using sqlite3_expert_sql(). ++** The total number of SQL statements may be different from the total number ++** to calls to sqlite3_expert_sql(). ++*/ ++int sqlite3_expert_count(sqlite3expert*); ++ ++/* ++** Return a component of the report. ++** ++** This function is called after sqlite3_expert_analyze() to extract the ++** results of the analysis. Each call to this function returns either a ++** NULL pointer or a pointer to a buffer containing a nul-terminated string. ++** The value passed as the third argument must be one of the EXPERT_REPORT_* ++** #define constants defined below. ++** ++** For some EXPERT_REPORT_* parameters, the buffer returned contains ++** information relating to a specific SQL statement. In these cases that ++** SQL statement is identified by the value passed as the second argument. ++** SQL statements are numbered from 0 in the order in which they are parsed. ++** If an out-of-range value (less than zero or equal to or greater than the ++** value returned by sqlite3_expert_count()) is passed as the second argument ++** along with such an EXPERT_REPORT_* parameter, NULL is always returned. ++** ++** EXPERT_REPORT_SQL: ++** Return the text of SQL statement iStmt. ++** ++** EXPERT_REPORT_INDEXES: ++** Return a buffer containing the CREATE INDEX statements for all recommended ++** indexes for statement iStmt. If there are no new recommeded indexes, NULL ++** is returned. ++** ++** EXPERT_REPORT_PLAN: ++** Return a buffer containing the EXPLAIN QUERY PLAN output for SQL query ++** iStmt after the proposed indexes have been added to the database schema. ++** ++** EXPERT_REPORT_CANDIDATES: ++** Return a pointer to a buffer containing the CREATE INDEX statements ++** for all indexes that were tested (for all SQL statements). The iStmt ++** parameter is ignored for EXPERT_REPORT_CANDIDATES calls. ++*/ ++const char *sqlite3_expert_report(sqlite3expert*, int iStmt, int eReport); ++ ++/* ++** Values for the third argument passed to sqlite3_expert_report(). ++*/ ++#define EXPERT_REPORT_SQL 1 ++#define EXPERT_REPORT_INDEXES 2 ++#define EXPERT_REPORT_PLAN 3 ++#define EXPERT_REPORT_CANDIDATES 4 ++ ++/* ++** Free an (sqlite3expert*) handle and all associated resources. There ++** should be one call to this function for each successful call to ++** sqlite3-expert_new(). ++*/ ++void sqlite3_expert_destroy(sqlite3expert*); ++ ++ ++ ++/************************* End ../ext/expert/sqlite3expert.h ********************/ ++/************************* Begin ../ext/expert/sqlite3expert.c ******************/ ++/* ++** 2017 April 09 ++** ++** 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. ++** ++************************************************************************* ++*/ ++#include <assert.h> ++#include <string.h> ++#include <stdio.h> ++ ++#ifndef SQLITE_OMIT_VIRTUALTABLE ++ ++/* typedef sqlite3_int64 i64; */ ++/* typedef sqlite3_uint64 u64; */ ++ ++typedef struct IdxColumn IdxColumn; ++typedef struct IdxConstraint IdxConstraint; ++typedef struct IdxScan IdxScan; ++typedef struct IdxStatement IdxStatement; ++typedef struct IdxTable IdxTable; ++typedef struct IdxWrite IdxWrite; ++ ++#define STRLEN (int)strlen ++ ++/* ++** A temp table name that we assume no user database will actually use. ++** If this assumption proves incorrect triggers on the table with the ++** conflicting name will be ignored. ++*/ ++#define UNIQUE_TABLE_NAME "t592690916721053953805701627921227776" ++ ++/* ++** A single constraint. Equivalent to either "col = ?" or "col < ?" (or ++** any other type of single-ended range constraint on a column). ++** ++** pLink: ++** Used to temporarily link IdxConstraint objects into lists while ++** creating candidate indexes. ++*/ ++struct IdxConstraint { ++ char *zColl; /* Collation sequence */ ++ int bRange; /* True for range, false for eq */ ++ int iCol; /* Constrained table column */ ++ int bFlag; /* Used by idxFindCompatible() */ ++ int bDesc; /* True if ORDER BY <expr> DESC */ ++ IdxConstraint *pNext; /* Next constraint in pEq or pRange list */ ++ IdxConstraint *pLink; /* See above */ ++}; ++ ++/* ++** A single scan of a single table. ++*/ ++struct IdxScan { ++ IdxTable *pTab; /* Associated table object */ ++ int iDb; /* Database containing table zTable */ ++ i64 covering; /* Mask of columns required for cov. index */ ++ IdxConstraint *pOrder; /* ORDER BY columns */ ++ IdxConstraint *pEq; /* List of == constraints */ ++ IdxConstraint *pRange; /* List of < constraints */ ++ IdxScan *pNextScan; /* Next IdxScan object for same analysis */ ++}; ++ ++/* ++** Information regarding a single database table. Extracted from ++** "PRAGMA table_info" by function idxGetTableInfo(). ++*/ ++struct IdxColumn { ++ char *zName; ++ char *zColl; ++ int iPk; ++}; ++struct IdxTable { ++ int nCol; ++ char *zName; /* Table name */ ++ IdxColumn *aCol; ++ IdxTable *pNext; /* Next table in linked list of all tables */ ++}; ++ ++/* ++** An object of the following type is created for each unique table/write-op ++** seen. The objects are stored in a singly-linked list beginning at ++** sqlite3expert.pWrite. ++*/ ++struct IdxWrite { ++ IdxTable *pTab; ++ int eOp; /* SQLITE_UPDATE, DELETE or INSERT */ ++ IdxWrite *pNext; ++}; ++ ++/* ++** Each statement being analyzed is represented by an instance of this ++** structure. ++*/ ++struct IdxStatement { ++ int iId; /* Statement number */ ++ char *zSql; /* SQL statement */ ++ char *zIdx; /* Indexes */ ++ char *zEQP; /* Plan */ ++ IdxStatement *pNext; ++}; ++ ++ ++/* ++** A hash table for storing strings. With space for a payload string ++** with each entry. Methods are: ++** ++** idxHashInit() ++** idxHashClear() ++** idxHashAdd() ++** idxHashSearch() ++*/ ++#define IDX_HASH_SIZE 1023 ++typedef struct IdxHashEntry IdxHashEntry; ++typedef struct IdxHash IdxHash; ++struct IdxHashEntry { ++ char *zKey; /* nul-terminated key */ ++ char *zVal; /* nul-terminated value string */ ++ char *zVal2; /* nul-terminated value string 2 */ ++ IdxHashEntry *pHashNext; /* Next entry in same hash bucket */ ++ IdxHashEntry *pNext; /* Next entry in hash */ ++}; ++struct IdxHash { ++ IdxHashEntry *pFirst; ++ IdxHashEntry *aHash[IDX_HASH_SIZE]; ++}; ++ ++/* ++** sqlite3expert object. ++*/ ++struct sqlite3expert { ++ int iSample; /* Percentage of tables to sample for stat1 */ ++ sqlite3 *db; /* User database */ ++ sqlite3 *dbm; /* In-memory db for this analysis */ ++ sqlite3 *dbv; /* Vtab schema for this analysis */ ++ IdxTable *pTable; /* List of all IdxTable objects */ ++ IdxScan *pScan; /* List of scan objects */ ++ IdxWrite *pWrite; /* List of write objects */ ++ IdxStatement *pStatement; /* List of IdxStatement objects */ ++ int bRun; /* True once analysis has run */ ++ char **pzErrmsg; ++ int rc; /* Error code from whereinfo hook */ ++ IdxHash hIdx; /* Hash containing all candidate indexes */ ++ char *zCandidates; /* For EXPERT_REPORT_CANDIDATES */ ++}; ++ ++ ++/* ++** Allocate and return nByte bytes of zeroed memory using sqlite3_malloc(). ++** If the allocation fails, set *pRc to SQLITE_NOMEM and return NULL. ++*/ ++static void *idxMalloc(int *pRc, int nByte){ ++ void *pRet; ++ assert( *pRc==SQLITE_OK ); ++ assert( nByte>0 ); ++ pRet = sqlite3_malloc(nByte); ++ if( pRet ){ ++ memset(pRet, 0, nByte); ++ }else{ ++ *pRc = SQLITE_NOMEM; ++ } ++ return pRet; ++} ++ ++/* ++** Initialize an IdxHash hash table. ++*/ ++static void idxHashInit(IdxHash *pHash){ ++ memset(pHash, 0, sizeof(IdxHash)); ++} ++ ++/* ++** Reset an IdxHash hash table. ++*/ ++static void idxHashClear(IdxHash *pHash){ ++ int i; ++ for(i=0; i<IDX_HASH_SIZE; i++){ ++ IdxHashEntry *pEntry; ++ IdxHashEntry *pNext; ++ for(pEntry=pHash->aHash[i]; pEntry; pEntry=pNext){ ++ pNext = pEntry->pHashNext; ++ sqlite3_free(pEntry->zVal2); ++ sqlite3_free(pEntry); ++ } ++ } ++ memset(pHash, 0, sizeof(IdxHash)); ++} ++ ++/* ++** Return the index of the hash bucket that the string specified by the ++** arguments to this function belongs. ++*/ ++static int idxHashString(const char *z, int n){ ++ unsigned int ret = 0; ++ int i; ++ for(i=0; i<n; i++){ ++ ret += (ret<<3) + (unsigned char)(z[i]); ++ } ++ return (int)(ret % IDX_HASH_SIZE); ++} ++ ++/* ++** If zKey is already present in the hash table, return non-zero and do ++** nothing. Otherwise, add an entry with key zKey and payload string zVal to ++** the hash table passed as the second argument. ++*/ ++static int idxHashAdd( ++ int *pRc, ++ IdxHash *pHash, ++ const char *zKey, ++ const char *zVal ++){ ++ int nKey = STRLEN(zKey); ++ int iHash = idxHashString(zKey, nKey); ++ int nVal = (zVal ? STRLEN(zVal) : 0); ++ IdxHashEntry *pEntry; ++ assert( iHash>=0 ); ++ for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){ ++ if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){ ++ return 1; ++ } ++ } ++ pEntry = idxMalloc(pRc, sizeof(IdxHashEntry) + nKey+1 + nVal+1); ++ if( pEntry ){ ++ pEntry->zKey = (char*)&pEntry[1]; ++ memcpy(pEntry->zKey, zKey, nKey); ++ if( zVal ){ ++ pEntry->zVal = &pEntry->zKey[nKey+1]; ++ memcpy(pEntry->zVal, zVal, nVal); ++ } ++ pEntry->pHashNext = pHash->aHash[iHash]; ++ pHash->aHash[iHash] = pEntry; ++ ++ pEntry->pNext = pHash->pFirst; ++ pHash->pFirst = pEntry; ++ } ++ return 0; ++} ++ ++/* ++** If zKey/nKey is present in the hash table, return a pointer to the ++** hash-entry object. ++*/ ++static IdxHashEntry *idxHashFind(IdxHash *pHash, const char *zKey, int nKey){ ++ int iHash; ++ IdxHashEntry *pEntry; ++ if( nKey<0 ) nKey = STRLEN(zKey); ++ iHash = idxHashString(zKey, nKey); ++ assert( iHash>=0 ); ++ for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){ ++ if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){ ++ return pEntry; ++ } ++ } ++ return 0; ++} ++ ++/* ++** If the hash table contains an entry with a key equal to the string ++** passed as the final two arguments to this function, return a pointer ++** to the payload string. Otherwise, if zKey/nKey is not present in the ++** hash table, return NULL. ++*/ ++static const char *idxHashSearch(IdxHash *pHash, const char *zKey, int nKey){ ++ IdxHashEntry *pEntry = idxHashFind(pHash, zKey, nKey); ++ if( pEntry ) return pEntry->zVal; ++ return 0; ++} ++ ++/* ++** Allocate and return a new IdxConstraint object. Set the IdxConstraint.zColl ++** variable to point to a copy of nul-terminated string zColl. ++*/ ++static IdxConstraint *idxNewConstraint(int *pRc, const char *zColl){ ++ IdxConstraint *pNew; ++ int nColl = STRLEN(zColl); ++ ++ assert( *pRc==SQLITE_OK ); ++ pNew = (IdxConstraint*)idxMalloc(pRc, sizeof(IdxConstraint) * nColl + 1); ++ if( pNew ){ ++ pNew->zColl = (char*)&pNew[1]; ++ memcpy(pNew->zColl, zColl, nColl+1); ++ } ++ return pNew; ++} ++ ++/* ++** An error associated with database handle db has just occurred. Pass ++** the error message to callback function xOut. ++*/ ++static void idxDatabaseError( ++ sqlite3 *db, /* Database handle */ ++ char **pzErrmsg /* Write error here */ ++){ ++ *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db)); ++} ++ ++/* ++** Prepare an SQL statement. ++*/ ++static int idxPrepareStmt( ++ sqlite3 *db, /* Database handle to compile against */ ++ sqlite3_stmt **ppStmt, /* OUT: Compiled SQL statement */ ++ char **pzErrmsg, /* OUT: sqlite3_malloc()ed error message */ ++ const char *zSql /* SQL statement to compile */ ++){ ++ int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0); ++ if( rc!=SQLITE_OK ){ ++ *ppStmt = 0; ++ idxDatabaseError(db, pzErrmsg); ++ } ++ return rc; ++} ++ ++/* ++** Prepare an SQL statement using the results of a printf() formatting. ++*/ ++static int idxPrintfPrepareStmt( ++ sqlite3 *db, /* Database handle to compile against */ ++ sqlite3_stmt **ppStmt, /* OUT: Compiled SQL statement */ ++ char **pzErrmsg, /* OUT: sqlite3_malloc()ed error message */ ++ const char *zFmt, /* printf() format of SQL statement */ ++ ... /* Trailing printf() arguments */ ++){ ++ va_list ap; ++ int rc; ++ char *zSql; ++ va_start(ap, zFmt); ++ zSql = sqlite3_vmprintf(zFmt, ap); ++ if( zSql==0 ){ ++ rc = SQLITE_NOMEM; ++ }else{ ++ rc = idxPrepareStmt(db, ppStmt, pzErrmsg, zSql); ++ sqlite3_free(zSql); ++ } ++ va_end(ap); ++ return rc; ++} ++ ++ ++/************************************************************************* ++** Beginning of virtual table implementation. ++*/ ++typedef struct ExpertVtab ExpertVtab; ++struct ExpertVtab { ++ sqlite3_vtab base; ++ IdxTable *pTab; ++ sqlite3expert *pExpert; ++}; ++ ++typedef struct ExpertCsr ExpertCsr; ++struct ExpertCsr { ++ sqlite3_vtab_cursor base; ++ sqlite3_stmt *pData; ++}; ++ ++static char *expertDequote(const char *zIn){ ++ int n = STRLEN(zIn); ++ char *zRet = sqlite3_malloc(n); ++ ++ assert( zIn[0]=='\'' ); ++ assert( zIn[n-1]=='\'' ); ++ ++ if( zRet ){ ++ int iOut = 0; ++ int iIn = 0; ++ for(iIn=1; iIn<(n-1); iIn++){ ++ if( zIn[iIn]=='\'' ){ ++ assert( zIn[iIn+1]=='\'' ); ++ iIn++; ++ } ++ zRet[iOut++] = zIn[iIn]; ++ } ++ zRet[iOut] = '\0'; ++ } ++ ++ return zRet; ++} ++ ++/* ++** This function is the implementation of both the xConnect and xCreate ++** methods of the r-tree virtual table. ++** ++** argv[0] -> module name ++** argv[1] -> database name ++** argv[2] -> table name ++** argv[...] -> column names... ++*/ ++static int expertConnect( ++ sqlite3 *db, ++ void *pAux, ++ int argc, const char *const*argv, ++ sqlite3_vtab **ppVtab, ++ char **pzErr ++){ ++ sqlite3expert *pExpert = (sqlite3expert*)pAux; ++ ExpertVtab *p = 0; ++ int rc; ++ ++ if( argc!=4 ){ ++ *pzErr = sqlite3_mprintf("internal error!"); ++ rc = SQLITE_ERROR; ++ }else{ ++ char *zCreateTable = expertDequote(argv[3]); ++ if( zCreateTable ){ ++ rc = sqlite3_declare_vtab(db, zCreateTable); ++ if( rc==SQLITE_OK ){ ++ p = idxMalloc(&rc, sizeof(ExpertVtab)); ++ } ++ if( rc==SQLITE_OK ){ ++ p->pExpert = pExpert; ++ p->pTab = pExpert->pTable; ++ assert( sqlite3_stricmp(p->pTab->zName, argv[2])==0 ); ++ } ++ sqlite3_free(zCreateTable); ++ }else{ ++ rc = SQLITE_NOMEM; ++ } ++ } ++ ++ *ppVtab = (sqlite3_vtab*)p; ++ return rc; ++} ++ ++static int expertDisconnect(sqlite3_vtab *pVtab){ ++ ExpertVtab *p = (ExpertVtab*)pVtab; ++ sqlite3_free(p); ++ return SQLITE_OK; ++} ++ ++static int expertBestIndex(sqlite3_vtab *pVtab, sqlite3_index_info *pIdxInfo){ ++ ExpertVtab *p = (ExpertVtab*)pVtab; ++ int rc = SQLITE_OK; ++ int n = 0; ++ IdxScan *pScan; ++ const int opmask = ++ SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_GT | ++ SQLITE_INDEX_CONSTRAINT_LT | SQLITE_INDEX_CONSTRAINT_GE | ++ SQLITE_INDEX_CONSTRAINT_LE; ++ ++ pScan = idxMalloc(&rc, sizeof(IdxScan)); ++ if( pScan ){ ++ int i; ++ ++ /* Link the new scan object into the list */ ++ pScan->pTab = p->pTab; ++ pScan->pNextScan = p->pExpert->pScan; ++ p->pExpert->pScan = pScan; ++ ++ /* Add the constraints to the IdxScan object */ ++ for(i=0; i<pIdxInfo->nConstraint; i++){ ++ struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i]; ++ if( pCons->usable ++ && pCons->iColumn>=0 ++ && p->pTab->aCol[pCons->iColumn].iPk==0 ++ && (pCons->op & opmask) ++ ){ ++ IdxConstraint *pNew; ++ const char *zColl = sqlite3_vtab_collation(pIdxInfo, i); ++ pNew = idxNewConstraint(&rc, zColl); ++ if( pNew ){ ++ pNew->iCol = pCons->iColumn; ++ if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){ ++ pNew->pNext = pScan->pEq; ++ pScan->pEq = pNew; ++ }else{ ++ pNew->bRange = 1; ++ pNew->pNext = pScan->pRange; ++ pScan->pRange = pNew; ++ } ++ } ++ n++; ++ pIdxInfo->aConstraintUsage[i].argvIndex = n; ++ } ++ } ++ ++ /* Add the ORDER BY to the IdxScan object */ ++ for(i=pIdxInfo->nOrderBy-1; i>=0; i--){ ++ int iCol = pIdxInfo->aOrderBy[i].iColumn; ++ if( iCol>=0 ){ ++ IdxConstraint *pNew = idxNewConstraint(&rc, p->pTab->aCol[iCol].zColl); ++ if( pNew ){ ++ pNew->iCol = iCol; ++ pNew->bDesc = pIdxInfo->aOrderBy[i].desc; ++ pNew->pNext = pScan->pOrder; ++ pNew->pLink = pScan->pOrder; ++ pScan->pOrder = pNew; ++ n++; ++ } ++ } ++ } ++ } ++ ++ pIdxInfo->estimatedCost = 1000000.0 / (n+1); ++ return rc; ++} ++ ++static int expertUpdate( ++ sqlite3_vtab *pVtab, ++ int nData, ++ sqlite3_value **azData, ++ sqlite_int64 *pRowid ++){ ++ (void)pVtab; ++ (void)nData; ++ (void)azData; ++ (void)pRowid; ++ return SQLITE_OK; ++} ++ ++/* ++** Virtual table module xOpen method. ++*/ ++static int expertOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ ++ int rc = SQLITE_OK; ++ ExpertCsr *pCsr; ++ (void)pVTab; ++ pCsr = idxMalloc(&rc, sizeof(ExpertCsr)); ++ *ppCursor = (sqlite3_vtab_cursor*)pCsr; ++ return rc; ++} ++ ++/* ++** Virtual table module xClose method. ++*/ ++static int expertClose(sqlite3_vtab_cursor *cur){ ++ ExpertCsr *pCsr = (ExpertCsr*)cur; ++ sqlite3_finalize(pCsr->pData); ++ sqlite3_free(pCsr); ++ return SQLITE_OK; ++} ++ ++/* ++** Virtual table module xEof method. ++** ++** Return non-zero if the cursor does not currently point to a valid ++** record (i.e if the scan has finished), or zero otherwise. ++*/ ++static int expertEof(sqlite3_vtab_cursor *cur){ ++ ExpertCsr *pCsr = (ExpertCsr*)cur; ++ return pCsr->pData==0; ++} ++ ++/* ++** Virtual table module xNext method. ++*/ ++static int expertNext(sqlite3_vtab_cursor *cur){ ++ ExpertCsr *pCsr = (ExpertCsr*)cur; ++ int rc = SQLITE_OK; ++ ++ assert( pCsr->pData ); ++ rc = sqlite3_step(pCsr->pData); ++ if( rc!=SQLITE_ROW ){ ++ rc = sqlite3_finalize(pCsr->pData); ++ pCsr->pData = 0; ++ }else{ ++ rc = SQLITE_OK; ++ } ++ ++ return rc; ++} ++ ++/* ++** Virtual table module xRowid method. ++*/ ++static int expertRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ ++ (void)cur; ++ *pRowid = 0; ++ return SQLITE_OK; ++} ++ ++/* ++** Virtual table module xColumn method. ++*/ ++static int expertColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ ++ ExpertCsr *pCsr = (ExpertCsr*)cur; ++ sqlite3_value *pVal; ++ pVal = sqlite3_column_value(pCsr->pData, i); ++ if( pVal ){ ++ sqlite3_result_value(ctx, pVal); ++ } ++ return SQLITE_OK; ++} ++ ++/* ++** Virtual table module xFilter method. ++*/ ++static int expertFilter( ++ sqlite3_vtab_cursor *cur, ++ int idxNum, const char *idxStr, ++ int argc, sqlite3_value **argv ++){ ++ ExpertCsr *pCsr = (ExpertCsr*)cur; ++ ExpertVtab *pVtab = (ExpertVtab*)(cur->pVtab); ++ sqlite3expert *pExpert = pVtab->pExpert; ++ int rc; ++ ++ (void)idxNum; ++ (void)idxStr; ++ (void)argc; ++ (void)argv; ++ rc = sqlite3_finalize(pCsr->pData); ++ pCsr->pData = 0; ++ if( rc==SQLITE_OK ){ ++ rc = idxPrintfPrepareStmt(pExpert->db, &pCsr->pData, &pVtab->base.zErrMsg, ++ "SELECT * FROM main.%Q WHERE sample()", pVtab->pTab->zName ++ ); ++ } ++ ++ if( rc==SQLITE_OK ){ ++ rc = expertNext(cur); ++ } ++ return rc; ++} ++ ++static int idxRegisterVtab(sqlite3expert *p){ ++ static sqlite3_module expertModule = { ++ 2, /* iVersion */ ++ expertConnect, /* xCreate - create a table */ ++ expertConnect, /* xConnect - connect to an existing table */ ++ expertBestIndex, /* xBestIndex - Determine search strategy */ ++ expertDisconnect, /* xDisconnect - Disconnect from a table */ ++ expertDisconnect, /* xDestroy - Drop a table */ ++ expertOpen, /* xOpen - open a cursor */ ++ expertClose, /* xClose - close a cursor */ ++ expertFilter, /* xFilter - configure scan constraints */ ++ expertNext, /* xNext - advance a cursor */ ++ expertEof, /* xEof */ ++ expertColumn, /* xColumn - read data */ ++ expertRowid, /* xRowid - read data */ ++ expertUpdate, /* xUpdate - write data */ ++ 0, /* xBegin - begin transaction */ ++ 0, /* xSync - sync transaction */ ++ 0, /* xCommit - commit transaction */ ++ 0, /* xRollback - rollback transaction */ ++ 0, /* xFindFunction - function overloading */ ++ 0, /* xRename - rename the table */ ++ 0, /* xSavepoint */ ++ 0, /* xRelease */ ++ 0, /* xRollbackTo */ ++ 0, /* xShadowName */ ++ }; ++ ++ return sqlite3_create_module(p->dbv, "expert", &expertModule, (void*)p); ++} ++/* ++** End of virtual table implementation. ++*************************************************************************/ ++/* ++** Finalize SQL statement pStmt. If (*pRc) is SQLITE_OK when this function ++** is called, set it to the return value of sqlite3_finalize() before ++** returning. Otherwise, discard the sqlite3_finalize() return value. ++*/ ++static void idxFinalize(int *pRc, sqlite3_stmt *pStmt){ ++ int rc = sqlite3_finalize(pStmt); ++ if( *pRc==SQLITE_OK ) *pRc = rc; ++} ++ ++/* ++** Attempt to allocate an IdxTable structure corresponding to table zTab ++** in the main database of connection db. If successful, set (*ppOut) to ++** point to the new object and return SQLITE_OK. Otherwise, return an ++** SQLite error code and set (*ppOut) to NULL. In this case *pzErrmsg may be ++** set to point to an error string. ++** ++** It is the responsibility of the caller to eventually free either the ++** IdxTable object or error message using sqlite3_free(). ++*/ ++static int idxGetTableInfo( ++ sqlite3 *db, /* Database connection to read details from */ ++ const char *zTab, /* Table name */ ++ IdxTable **ppOut, /* OUT: New object (if successful) */ ++ char **pzErrmsg /* OUT: Error message (if not) */ ++){ ++ sqlite3_stmt *p1 = 0; ++ int nCol = 0; ++ int nTab = STRLEN(zTab); ++ int nByte = sizeof(IdxTable) + nTab + 1; ++ IdxTable *pNew = 0; ++ int rc, rc2; ++ char *pCsr = 0; ++ ++ rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_info=%Q", zTab); ++ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){ ++ const char *zCol = (const char*)sqlite3_column_text(p1, 1); ++ nByte += 1 + STRLEN(zCol); ++ rc = sqlite3_table_column_metadata( ++ db, "main", zTab, zCol, 0, &zCol, 0, 0, 0 ++ ); ++ nByte += 1 + STRLEN(zCol); ++ nCol++; ++ } ++ rc2 = sqlite3_reset(p1); ++ if( rc==SQLITE_OK ) rc = rc2; ++ ++ nByte += sizeof(IdxColumn) * nCol; ++ if( rc==SQLITE_OK ){ ++ pNew = idxMalloc(&rc, nByte); ++ } ++ if( rc==SQLITE_OK ){ ++ pNew->aCol = (IdxColumn*)&pNew[1]; ++ pNew->nCol = nCol; ++ pCsr = (char*)&pNew->aCol[nCol]; ++ } ++ ++ nCol = 0; ++ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){ ++ const char *zCol = (const char*)sqlite3_column_text(p1, 1); ++ int nCopy = STRLEN(zCol) + 1; ++ pNew->aCol[nCol].zName = pCsr; ++ pNew->aCol[nCol].iPk = sqlite3_column_int(p1, 5); ++ memcpy(pCsr, zCol, nCopy); ++ pCsr += nCopy; ++ ++ rc = sqlite3_table_column_metadata( ++ db, "main", zTab, zCol, 0, &zCol, 0, 0, 0 ++ ); ++ if( rc==SQLITE_OK ){ ++ nCopy = STRLEN(zCol) + 1; ++ pNew->aCol[nCol].zColl = pCsr; ++ memcpy(pCsr, zCol, nCopy); ++ pCsr += nCopy; ++ } ++ ++ nCol++; ++ } ++ idxFinalize(&rc, p1); ++ ++ if( rc!=SQLITE_OK ){ ++ sqlite3_free(pNew); ++ pNew = 0; ++ }else{ ++ pNew->zName = pCsr; ++ memcpy(pNew->zName, zTab, nTab+1); ++ } ++ ++ *ppOut = pNew; ++ return rc; ++} ++ ++/* ++** This function is a no-op if *pRc is set to anything other than ++** SQLITE_OK when it is called. ++** ++** If *pRc is initially set to SQLITE_OK, then the text specified by ++** the printf() style arguments is appended to zIn and the result returned ++** in a buffer allocated by sqlite3_malloc(). sqlite3_free() is called on ++** zIn before returning. ++*/ ++static char *idxAppendText(int *pRc, char *zIn, const char *zFmt, ...){ ++ va_list ap; ++ char *zAppend = 0; ++ char *zRet = 0; ++ int nIn = zIn ? STRLEN(zIn) : 0; ++ int nAppend = 0; ++ va_start(ap, zFmt); ++ if( *pRc==SQLITE_OK ){ ++ zAppend = sqlite3_vmprintf(zFmt, ap); ++ if( zAppend ){ ++ nAppend = STRLEN(zAppend); ++ zRet = (char*)sqlite3_malloc(nIn + nAppend + 1); ++ } ++ if( zAppend && zRet ){ ++ if( nIn ) memcpy(zRet, zIn, nIn); ++ memcpy(&zRet[nIn], zAppend, nAppend+1); ++ }else{ ++ sqlite3_free(zRet); ++ zRet = 0; ++ *pRc = SQLITE_NOMEM; ++ } ++ sqlite3_free(zAppend); ++ sqlite3_free(zIn); ++ } ++ va_end(ap); ++ return zRet; ++} ++ ++/* ++** Return true if zId must be quoted in order to use it as an SQL ++** identifier, or false otherwise. ++*/ ++static int idxIdentifierRequiresQuotes(const char *zId){ ++ int i; ++ for(i=0; zId[i]; i++){ ++ if( !(zId[i]=='_') ++ && !(zId[i]>='0' && zId[i]<='9') ++ && !(zId[i]>='a' && zId[i]<='z') ++ && !(zId[i]>='A' && zId[i]<='Z') ++ ){ ++ return 1; ++ } ++ } ++ return 0; ++} ++ ++/* ++** This function appends an index column definition suitable for constraint ++** pCons to the string passed as zIn and returns the result. ++*/ ++static char *idxAppendColDefn( ++ int *pRc, /* IN/OUT: Error code */ ++ char *zIn, /* Column defn accumulated so far */ ++ IdxTable *pTab, /* Table index will be created on */ ++ IdxConstraint *pCons ++){ ++ char *zRet = zIn; ++ IdxColumn *p = &pTab->aCol[pCons->iCol]; ++ if( zRet ) zRet = idxAppendText(pRc, zRet, ", "); ++ ++ if( idxIdentifierRequiresQuotes(p->zName) ){ ++ zRet = idxAppendText(pRc, zRet, "%Q", p->zName); ++ }else{ ++ zRet = idxAppendText(pRc, zRet, "%s", p->zName); ++ } ++ ++ if( sqlite3_stricmp(p->zColl, pCons->zColl) ){ ++ if( idxIdentifierRequiresQuotes(pCons->zColl) ){ ++ zRet = idxAppendText(pRc, zRet, " COLLATE %Q", pCons->zColl); ++ }else{ ++ zRet = idxAppendText(pRc, zRet, " COLLATE %s", pCons->zColl); ++ } ++ } ++ ++ if( pCons->bDesc ){ ++ zRet = idxAppendText(pRc, zRet, " DESC"); ++ } ++ return zRet; ++} ++ ++/* ++** Search database dbm for an index compatible with the one idxCreateFromCons() ++** would create from arguments pScan, pEq and pTail. If no error occurs and ++** such an index is found, return non-zero. Or, if no such index is found, ++** return zero. ++** ++** If an error occurs, set *pRc to an SQLite error code and return zero. ++*/ ++static int idxFindCompatible( ++ int *pRc, /* OUT: Error code */ ++ sqlite3* dbm, /* Database to search */ ++ IdxScan *pScan, /* Scan for table to search for index on */ ++ IdxConstraint *pEq, /* List of == constraints */ ++ IdxConstraint *pTail /* List of range constraints */ ++){ ++ const char *zTbl = pScan->pTab->zName; ++ sqlite3_stmt *pIdxList = 0; ++ IdxConstraint *pIter; ++ int nEq = 0; /* Number of elements in pEq */ ++ int rc; ++ ++ /* Count the elements in list pEq */ ++ for(pIter=pEq; pIter; pIter=pIter->pLink) nEq++; ++ ++ rc = idxPrintfPrepareStmt(dbm, &pIdxList, 0, "PRAGMA index_list=%Q", zTbl); ++ while( rc==SQLITE_OK && sqlite3_step(pIdxList)==SQLITE_ROW ){ ++ int bMatch = 1; ++ IdxConstraint *pT = pTail; ++ sqlite3_stmt *pInfo = 0; ++ const char *zIdx = (const char*)sqlite3_column_text(pIdxList, 1); ++ ++ /* Zero the IdxConstraint.bFlag values in the pEq list */ ++ for(pIter=pEq; pIter; pIter=pIter->pLink) pIter->bFlag = 0; ++ ++ rc = idxPrintfPrepareStmt(dbm, &pInfo, 0, "PRAGMA index_xInfo=%Q", zIdx); ++ while( rc==SQLITE_OK && sqlite3_step(pInfo)==SQLITE_ROW ){ ++ int iIdx = sqlite3_column_int(pInfo, 0); ++ int iCol = sqlite3_column_int(pInfo, 1); ++ const char *zColl = (const char*)sqlite3_column_text(pInfo, 4); ++ ++ if( iIdx<nEq ){ ++ for(pIter=pEq; pIter; pIter=pIter->pLink){ ++ if( pIter->bFlag ) continue; ++ if( pIter->iCol!=iCol ) continue; ++ if( sqlite3_stricmp(pIter->zColl, zColl) ) continue; ++ pIter->bFlag = 1; ++ break; ++ } ++ if( pIter==0 ){ ++ bMatch = 0; ++ break; ++ } ++ }else{ ++ if( pT ){ ++ if( pT->iCol!=iCol || sqlite3_stricmp(pT->zColl, zColl) ){ ++ bMatch = 0; ++ break; ++ } ++ pT = pT->pLink; ++ } ++ } ++ } ++ idxFinalize(&rc, pInfo); ++ ++ if( rc==SQLITE_OK && bMatch ){ ++ sqlite3_finalize(pIdxList); ++ return 1; ++ } ++ } ++ idxFinalize(&rc, pIdxList); ++ ++ *pRc = rc; ++ return 0; ++} ++ ++static int idxCreateFromCons( ++ sqlite3expert *p, ++ IdxScan *pScan, ++ IdxConstraint *pEq, ++ IdxConstraint *pTail ++){ ++ sqlite3 *dbm = p->dbm; ++ int rc = SQLITE_OK; ++ if( (pEq || pTail) && 0==idxFindCompatible(&rc, dbm, pScan, pEq, pTail) ){ ++ IdxTable *pTab = pScan->pTab; ++ char *zCols = 0; ++ char *zIdx = 0; ++ IdxConstraint *pCons; ++ unsigned int h = 0; ++ const char *zFmt; ++ ++ for(pCons=pEq; pCons; pCons=pCons->pLink){ ++ zCols = idxAppendColDefn(&rc, zCols, pTab, pCons); ++ } ++ for(pCons=pTail; pCons; pCons=pCons->pLink){ ++ zCols = idxAppendColDefn(&rc, zCols, pTab, pCons); ++ } ++ ++ if( rc==SQLITE_OK ){ ++ /* Hash the list of columns to come up with a name for the index */ ++ const char *zTable = pScan->pTab->zName; ++ char *zName; /* Index name */ ++ int i; ++ for(i=0; zCols[i]; i++){ ++ h += ((h<<3) + zCols[i]); ++ } ++ zName = sqlite3_mprintf("%s_idx_%08x", zTable, h); ++ if( zName==0 ){ ++ rc = SQLITE_NOMEM; ++ }else{ ++ if( idxIdentifierRequiresQuotes(zTable) ){ ++ zFmt = "CREATE INDEX '%q' ON %Q(%s)"; ++ }else{ ++ zFmt = "CREATE INDEX %s ON %s(%s)"; ++ } ++ zIdx = sqlite3_mprintf(zFmt, zName, zTable, zCols); ++ if( !zIdx ){ ++ rc = SQLITE_NOMEM; ++ }else{ ++ rc = sqlite3_exec(dbm, zIdx, 0, 0, p->pzErrmsg); ++ idxHashAdd(&rc, &p->hIdx, zName, zIdx); ++ } ++ sqlite3_free(zName); ++ sqlite3_free(zIdx); ++ } ++ } ++ ++ sqlite3_free(zCols); ++ } ++ return rc; ++} ++ ++/* ++** Return true if list pList (linked by IdxConstraint.pLink) contains ++** a constraint compatible with *p. Otherwise return false. ++*/ ++static int idxFindConstraint(IdxConstraint *pList, IdxConstraint *p){ ++ IdxConstraint *pCmp; ++ for(pCmp=pList; pCmp; pCmp=pCmp->pLink){ ++ if( p->iCol==pCmp->iCol ) return 1; ++ } ++ return 0; ++} ++ ++static int idxCreateFromWhere( ++ sqlite3expert *p, ++ IdxScan *pScan, /* Create indexes for this scan */ ++ IdxConstraint *pTail /* range/ORDER BY constraints for inclusion */ ++){ ++ IdxConstraint *p1 = 0; ++ IdxConstraint *pCon; ++ int rc; ++ ++ /* Gather up all the == constraints. */ ++ for(pCon=pScan->pEq; pCon; pCon=pCon->pNext){ ++ if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){ ++ pCon->pLink = p1; ++ p1 = pCon; ++ } ++ } ++ ++ /* Create an index using the == constraints collected above. And the ++ ** range constraint/ORDER BY terms passed in by the caller, if any. */ ++ rc = idxCreateFromCons(p, pScan, p1, pTail); ++ ++ /* If no range/ORDER BY passed by the caller, create a version of the ++ ** index for each range constraint. */ ++ if( pTail==0 ){ ++ for(pCon=pScan->pRange; rc==SQLITE_OK && pCon; pCon=pCon->pNext){ ++ assert( pCon->pLink==0 ); ++ if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){ ++ rc = idxCreateFromCons(p, pScan, p1, pCon); ++ } ++ } ++ } ++ ++ return rc; ++} ++ ++/* ++** Create candidate indexes in database [dbm] based on the data in ++** linked-list pScan. ++*/ ++static int idxCreateCandidates(sqlite3expert *p){ ++ int rc = SQLITE_OK; ++ IdxScan *pIter; ++ ++ for(pIter=p->pScan; pIter && rc==SQLITE_OK; pIter=pIter->pNextScan){ ++ rc = idxCreateFromWhere(p, pIter, 0); ++ if( rc==SQLITE_OK && pIter->pOrder ){ ++ rc = idxCreateFromWhere(p, pIter, pIter->pOrder); ++ } ++ } ++ ++ return rc; ++} ++ ++/* ++** Free all elements of the linked list starting at pConstraint. ++*/ ++static void idxConstraintFree(IdxConstraint *pConstraint){ ++ IdxConstraint *pNext; ++ IdxConstraint *p; ++ ++ for(p=pConstraint; p; p=pNext){ ++ pNext = p->pNext; ++ sqlite3_free(p); ++ } ++} ++ ++/* ++** Free all elements of the linked list starting from pScan up until pLast ++** (pLast is not freed). ++*/ ++static void idxScanFree(IdxScan *pScan, IdxScan *pLast){ ++ IdxScan *p; ++ IdxScan *pNext; ++ for(p=pScan; p!=pLast; p=pNext){ ++ pNext = p->pNextScan; ++ idxConstraintFree(p->pOrder); ++ idxConstraintFree(p->pEq); ++ idxConstraintFree(p->pRange); ++ sqlite3_free(p); ++ } ++} ++ ++/* ++** Free all elements of the linked list starting from pStatement up ++** until pLast (pLast is not freed). ++*/ ++static void idxStatementFree(IdxStatement *pStatement, IdxStatement *pLast){ ++ IdxStatement *p; ++ IdxStatement *pNext; ++ for(p=pStatement; p!=pLast; p=pNext){ ++ pNext = p->pNext; ++ sqlite3_free(p->zEQP); ++ sqlite3_free(p->zIdx); ++ sqlite3_free(p); ++ } ++} ++ ++/* ++** Free the linked list of IdxTable objects starting at pTab. ++*/ ++static void idxTableFree(IdxTable *pTab){ ++ IdxTable *pIter; ++ IdxTable *pNext; ++ for(pIter=pTab; pIter; pIter=pNext){ ++ pNext = pIter->pNext; ++ sqlite3_free(pIter); ++ } ++} ++ ++/* ++** Free the linked list of IdxWrite objects starting at pTab. ++*/ ++static void idxWriteFree(IdxWrite *pTab){ ++ IdxWrite *pIter; ++ IdxWrite *pNext; ++ for(pIter=pTab; pIter; pIter=pNext){ ++ pNext = pIter->pNext; ++ sqlite3_free(pIter); ++ } ++} ++ ++ ++ ++/* ++** This function is called after candidate indexes have been created. It ++** runs all the queries to see which indexes they prefer, and populates ++** IdxStatement.zIdx and IdxStatement.zEQP with the results. ++*/ ++int idxFindIndexes( ++ sqlite3expert *p, ++ char **pzErr /* OUT: Error message (sqlite3_malloc) */ ++){ ++ IdxStatement *pStmt; ++ sqlite3 *dbm = p->dbm; ++ int rc = SQLITE_OK; ++ ++ IdxHash hIdx; ++ idxHashInit(&hIdx); ++ ++ for(pStmt=p->pStatement; rc==SQLITE_OK && pStmt; pStmt=pStmt->pNext){ ++ IdxHashEntry *pEntry; ++ sqlite3_stmt *pExplain = 0; ++ idxHashClear(&hIdx); ++ rc = idxPrintfPrepareStmt(dbm, &pExplain, pzErr, ++ "EXPLAIN QUERY PLAN %s", pStmt->zSql ++ ); ++ while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){ ++ /* int iId = sqlite3_column_int(pExplain, 0); */ ++ /* int iParent = sqlite3_column_int(pExplain, 1); */ ++ /* int iNotUsed = sqlite3_column_int(pExplain, 2); */ ++ const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3); ++ int nDetail = STRLEN(zDetail); ++ int i; ++ ++ for(i=0; i<nDetail; i++){ ++ const char *zIdx = 0; ++ if( memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){ ++ zIdx = &zDetail[i+13]; ++ }else if( memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0 ){ ++ zIdx = &zDetail[i+22]; ++ } ++ if( zIdx ){ ++ const char *zSql; ++ int nIdx = 0; ++ while( zIdx[nIdx]!='\0' && (zIdx[nIdx]!=' ' || zIdx[nIdx+1]!='(') ){ ++ nIdx++; ++ } ++ zSql = idxHashSearch(&p->hIdx, zIdx, nIdx); ++ if( zSql ){ ++ idxHashAdd(&rc, &hIdx, zSql, 0); ++ if( rc ) goto find_indexes_out; ++ } ++ break; ++ } ++ } ++ ++ if( zDetail[0]!='-' ){ ++ pStmt->zEQP = idxAppendText(&rc, pStmt->zEQP, "%s\n", zDetail); ++ } ++ } ++ ++ for(pEntry=hIdx.pFirst; pEntry; pEntry=pEntry->pNext){ ++ pStmt->zIdx = idxAppendText(&rc, pStmt->zIdx, "%s;\n", pEntry->zKey); ++ } ++ ++ idxFinalize(&rc, pExplain); ++ } ++ ++ find_indexes_out: ++ idxHashClear(&hIdx); ++ return rc; ++} ++ ++static int idxAuthCallback( ++ void *pCtx, ++ int eOp, ++ const char *z3, ++ const char *z4, ++ const char *zDb, ++ const char *zTrigger ++){ ++ int rc = SQLITE_OK; ++ (void)z4; ++ (void)zTrigger; ++ if( eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE || eOp==SQLITE_DELETE ){ ++ if( sqlite3_stricmp(zDb, "main")==0 ){ ++ sqlite3expert *p = (sqlite3expert*)pCtx; ++ IdxTable *pTab; ++ for(pTab=p->pTable; pTab; pTab=pTab->pNext){ ++ if( 0==sqlite3_stricmp(z3, pTab->zName) ) break; ++ } ++ if( pTab ){ ++ IdxWrite *pWrite; ++ for(pWrite=p->pWrite; pWrite; pWrite=pWrite->pNext){ ++ if( pWrite->pTab==pTab && pWrite->eOp==eOp ) break; ++ } ++ if( pWrite==0 ){ ++ pWrite = idxMalloc(&rc, sizeof(IdxWrite)); ++ if( rc==SQLITE_OK ){ ++ pWrite->pTab = pTab; ++ pWrite->eOp = eOp; ++ pWrite->pNext = p->pWrite; ++ p->pWrite = pWrite; ++ } ++ } ++ } ++ } ++ } ++ return rc; ++} ++ ++static int idxProcessOneTrigger( ++ sqlite3expert *p, ++ IdxWrite *pWrite, ++ char **pzErr ++){ ++ static const char *zInt = UNIQUE_TABLE_NAME; ++ static const char *zDrop = "DROP TABLE " UNIQUE_TABLE_NAME; ++ IdxTable *pTab = pWrite->pTab; ++ const char *zTab = pTab->zName; ++ const char *zSql = ++ "SELECT 'CREATE TEMP' || substr(sql, 7) FROM sqlite_master " ++ "WHERE tbl_name = %Q AND type IN ('table', 'trigger') " ++ "ORDER BY type;"; ++ sqlite3_stmt *pSelect = 0; ++ int rc = SQLITE_OK; ++ char *zWrite = 0; ++ ++ /* Create the table and its triggers in the temp schema */ ++ rc = idxPrintfPrepareStmt(p->db, &pSelect, pzErr, zSql, zTab, zTab); ++ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSelect) ){ ++ const char *zCreate = (const char*)sqlite3_column_text(pSelect, 0); ++ rc = sqlite3_exec(p->dbv, zCreate, 0, 0, pzErr); ++ } ++ idxFinalize(&rc, pSelect); ++ ++ /* Rename the table in the temp schema to zInt */ ++ if( rc==SQLITE_OK ){ ++ char *z = sqlite3_mprintf("ALTER TABLE temp.%Q RENAME TO %Q", zTab, zInt); ++ if( z==0 ){ ++ rc = SQLITE_NOMEM; ++ }else{ ++ rc = sqlite3_exec(p->dbv, z, 0, 0, pzErr); ++ sqlite3_free(z); ++ } ++ } ++ ++ switch( pWrite->eOp ){ ++ case SQLITE_INSERT: { ++ int i; ++ zWrite = idxAppendText(&rc, zWrite, "INSERT INTO %Q VALUES(", zInt); ++ for(i=0; i<pTab->nCol; i++){ ++ zWrite = idxAppendText(&rc, zWrite, "%s?", i==0 ? "" : ", "); ++ } ++ zWrite = idxAppendText(&rc, zWrite, ")"); ++ break; ++ } ++ case SQLITE_UPDATE: { ++ int i; ++ zWrite = idxAppendText(&rc, zWrite, "UPDATE %Q SET ", zInt); ++ for(i=0; i<pTab->nCol; i++){ ++ zWrite = idxAppendText(&rc, zWrite, "%s%Q=?", i==0 ? "" : ", ", ++ pTab->aCol[i].zName ++ ); ++ } ++ break; ++ } ++ default: { ++ assert( pWrite->eOp==SQLITE_DELETE ); ++ if( rc==SQLITE_OK ){ ++ zWrite = sqlite3_mprintf("DELETE FROM %Q", zInt); ++ if( zWrite==0 ) rc = SQLITE_NOMEM; ++ } ++ } ++ } ++ ++ if( rc==SQLITE_OK ){ ++ sqlite3_stmt *pX = 0; ++ rc = sqlite3_prepare_v2(p->dbv, zWrite, -1, &pX, 0); ++ idxFinalize(&rc, pX); ++ if( rc!=SQLITE_OK ){ ++ idxDatabaseError(p->dbv, pzErr); ++ } ++ } ++ sqlite3_free(zWrite); ++ ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3_exec(p->dbv, zDrop, 0, 0, pzErr); ++ } ++ ++ return rc; ++} ++ ++static int idxProcessTriggers(sqlite3expert *p, char **pzErr){ ++ int rc = SQLITE_OK; ++ IdxWrite *pEnd = 0; ++ IdxWrite *pFirst = p->pWrite; ++ ++ while( rc==SQLITE_OK && pFirst!=pEnd ){ ++ IdxWrite *pIter; ++ for(pIter=pFirst; rc==SQLITE_OK && pIter!=pEnd; pIter=pIter->pNext){ ++ rc = idxProcessOneTrigger(p, pIter, pzErr); ++ } ++ pEnd = pFirst; ++ pFirst = p->pWrite; ++ } ++ ++ return rc; ++} ++ ++ ++static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){ ++ int rc = idxRegisterVtab(p); ++ sqlite3_stmt *pSchema = 0; ++ ++ /* For each table in the main db schema: ++ ** ++ ** 1) Add an entry to the p->pTable list, and ++ ** 2) Create the equivalent virtual table in dbv. ++ */ ++ rc = idxPrepareStmt(p->db, &pSchema, pzErrmsg, ++ "SELECT type, name, sql, 1 FROM sqlite_master " ++ "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%%' " ++ " UNION ALL " ++ "SELECT type, name, sql, 2 FROM sqlite_master " ++ "WHERE type = 'trigger'" ++ " AND tbl_name IN(SELECT name FROM sqlite_master WHERE type = 'view') " ++ "ORDER BY 4, 1" ++ ); ++ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSchema) ){ ++ const char *zType = (const char*)sqlite3_column_text(pSchema, 0); ++ const char *zName = (const char*)sqlite3_column_text(pSchema, 1); ++ const char *zSql = (const char*)sqlite3_column_text(pSchema, 2); ++ ++ if( zType[0]=='v' || zType[1]=='r' ){ ++ rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg); ++ }else{ ++ IdxTable *pTab; ++ rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg); ++ if( rc==SQLITE_OK ){ ++ int i; ++ char *zInner = 0; ++ char *zOuter = 0; ++ pTab->pNext = p->pTable; ++ p->pTable = pTab; ++ ++ /* The statement the vtab will pass to sqlite3_declare_vtab() */ ++ zInner = idxAppendText(&rc, 0, "CREATE TABLE x("); ++ for(i=0; i<pTab->nCol; i++){ ++ zInner = idxAppendText(&rc, zInner, "%s%Q COLLATE %s", ++ (i==0 ? "" : ", "), pTab->aCol[i].zName, pTab->aCol[i].zColl ++ ); ++ } ++ zInner = idxAppendText(&rc, zInner, ")"); ++ ++ /* The CVT statement to create the vtab */ ++ zOuter = idxAppendText(&rc, 0, ++ "CREATE VIRTUAL TABLE %Q USING expert(%Q)", zName, zInner ++ ); ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3_exec(p->dbv, zOuter, 0, 0, pzErrmsg); ++ } ++ sqlite3_free(zInner); ++ sqlite3_free(zOuter); ++ } ++ } ++ } ++ idxFinalize(&rc, pSchema); ++ return rc; ++} ++ ++struct IdxSampleCtx { ++ int iTarget; ++ double target; /* Target nRet/nRow value */ ++ double nRow; /* Number of rows seen */ ++ double nRet; /* Number of rows returned */ ++}; ++ ++static void idxSampleFunc( ++ sqlite3_context *pCtx, ++ int argc, ++ sqlite3_value **argv ++){ ++ struct IdxSampleCtx *p = (struct IdxSampleCtx*)sqlite3_user_data(pCtx); ++ int bRet; ++ ++ (void)argv; ++ assert( argc==0 ); ++ if( p->nRow==0.0 ){ ++ bRet = 1; ++ }else{ ++ bRet = (p->nRet / p->nRow) <= p->target; ++ if( bRet==0 ){ ++ unsigned short rnd; ++ sqlite3_randomness(2, (void*)&rnd); ++ bRet = ((int)rnd % 100) <= p->iTarget; ++ } ++ } ++ ++ sqlite3_result_int(pCtx, bRet); ++ p->nRow += 1.0; ++ p->nRet += (double)bRet; ++} ++ ++struct IdxRemCtx { ++ int nSlot; ++ struct IdxRemSlot { ++ int eType; /* SQLITE_NULL, INTEGER, REAL, TEXT, BLOB */ ++ i64 iVal; /* SQLITE_INTEGER value */ ++ double rVal; /* SQLITE_FLOAT value */ ++ int nByte; /* Bytes of space allocated at z */ ++ int n; /* Size of buffer z */ ++ char *z; /* SQLITE_TEXT/BLOB value */ ++ } aSlot[1]; ++}; ++ ++/* ++** Implementation of scalar function rem(). ++*/ ++static void idxRemFunc( ++ sqlite3_context *pCtx, ++ int argc, ++ sqlite3_value **argv ++){ ++ struct IdxRemCtx *p = (struct IdxRemCtx*)sqlite3_user_data(pCtx); ++ struct IdxRemSlot *pSlot; ++ int iSlot; ++ assert( argc==2 ); ++ ++ iSlot = sqlite3_value_int(argv[0]); ++ assert( iSlot<=p->nSlot ); ++ pSlot = &p->aSlot[iSlot]; ++ ++ switch( pSlot->eType ){ ++ case SQLITE_NULL: ++ /* no-op */ ++ break; ++ ++ case SQLITE_INTEGER: ++ sqlite3_result_int64(pCtx, pSlot->iVal); ++ break; ++ ++ case SQLITE_FLOAT: ++ sqlite3_result_double(pCtx, pSlot->rVal); ++ break; ++ ++ case SQLITE_BLOB: ++ sqlite3_result_blob(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT); ++ break; ++ ++ case SQLITE_TEXT: ++ sqlite3_result_text(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT); ++ break; ++ } ++ ++ pSlot->eType = sqlite3_value_type(argv[1]); ++ switch( pSlot->eType ){ ++ case SQLITE_NULL: ++ /* no-op */ ++ break; ++ ++ case SQLITE_INTEGER: ++ pSlot->iVal = sqlite3_value_int64(argv[1]); ++ break; ++ ++ case SQLITE_FLOAT: ++ pSlot->rVal = sqlite3_value_double(argv[1]); ++ break; ++ ++ case SQLITE_BLOB: ++ case SQLITE_TEXT: { ++ int nByte = sqlite3_value_bytes(argv[1]); ++ if( nByte>pSlot->nByte ){ ++ char *zNew = (char*)sqlite3_realloc(pSlot->z, nByte*2); ++ if( zNew==0 ){ ++ sqlite3_result_error_nomem(pCtx); ++ return; ++ } ++ pSlot->nByte = nByte*2; ++ pSlot->z = zNew; ++ } ++ pSlot->n = nByte; ++ if( pSlot->eType==SQLITE_BLOB ){ ++ memcpy(pSlot->z, sqlite3_value_blob(argv[1]), nByte); ++ }else{ ++ memcpy(pSlot->z, sqlite3_value_text(argv[1]), nByte); ++ } ++ break; ++ } ++ } ++} ++ ++static int idxLargestIndex(sqlite3 *db, int *pnMax, char **pzErr){ ++ int rc = SQLITE_OK; ++ const char *zMax = ++ "SELECT max(i.seqno) FROM " ++ " sqlite_master AS s, " ++ " pragma_index_list(s.name) AS l, " ++ " pragma_index_info(l.name) AS i " ++ "WHERE s.type = 'table'"; ++ sqlite3_stmt *pMax = 0; ++ ++ *pnMax = 0; ++ rc = idxPrepareStmt(db, &pMax, pzErr, zMax); ++ if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pMax) ){ ++ *pnMax = sqlite3_column_int(pMax, 0) + 1; ++ } ++ idxFinalize(&rc, pMax); ++ ++ return rc; ++} ++ ++static int idxPopulateOneStat1( ++ sqlite3expert *p, ++ sqlite3_stmt *pIndexXInfo, ++ sqlite3_stmt *pWriteStat, ++ const char *zTab, ++ const char *zIdx, ++ char **pzErr ++){ ++ char *zCols = 0; ++ char *zOrder = 0; ++ char *zQuery = 0; ++ int nCol = 0; ++ int i; ++ sqlite3_stmt *pQuery = 0; ++ int *aStat = 0; ++ int rc = SQLITE_OK; ++ ++ assert( p->iSample>0 ); ++ ++ /* Formulate the query text */ ++ sqlite3_bind_text(pIndexXInfo, 1, zIdx, -1, SQLITE_STATIC); ++ while( SQLITE_OK==rc && SQLITE_ROW==sqlite3_step(pIndexXInfo) ){ ++ const char *zComma = zCols==0 ? "" : ", "; ++ const char *zName = (const char*)sqlite3_column_text(pIndexXInfo, 0); ++ const char *zColl = (const char*)sqlite3_column_text(pIndexXInfo, 1); ++ zCols = idxAppendText(&rc, zCols, ++ "%sx.%Q IS rem(%d, x.%Q) COLLATE %s", zComma, zName, nCol, zName, zColl ++ ); ++ zOrder = idxAppendText(&rc, zOrder, "%s%d", zComma, ++nCol); ++ } ++ sqlite3_reset(pIndexXInfo); ++ if( rc==SQLITE_OK ){ ++ if( p->iSample==100 ){ ++ zQuery = sqlite3_mprintf( ++ "SELECT %s FROM %Q x ORDER BY %s", zCols, zTab, zOrder ++ ); ++ }else{ ++ zQuery = sqlite3_mprintf( ++ "SELECT %s FROM temp."UNIQUE_TABLE_NAME" x ORDER BY %s", zCols, zOrder ++ ); ++ } ++ } ++ sqlite3_free(zCols); ++ sqlite3_free(zOrder); ++ ++ /* Formulate the query text */ ++ if( rc==SQLITE_OK ){ ++ sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv); ++ rc = idxPrepareStmt(dbrem, &pQuery, pzErr, zQuery); ++ } ++ sqlite3_free(zQuery); ++ ++ if( rc==SQLITE_OK ){ ++ aStat = (int*)idxMalloc(&rc, sizeof(int)*(nCol+1)); ++ } ++ if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){ ++ IdxHashEntry *pEntry; ++ char *zStat = 0; ++ for(i=0; i<=nCol; i++) aStat[i] = 1; ++ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){ ++ aStat[0]++; ++ for(i=0; i<nCol; i++){ ++ if( sqlite3_column_int(pQuery, i)==0 ) break; ++ } ++ for(/*no-op*/; i<nCol; i++){ ++ aStat[i+1]++; ++ } ++ } ++ ++ if( rc==SQLITE_OK ){ ++ int s0 = aStat[0]; ++ zStat = sqlite3_mprintf("%d", s0); ++ if( zStat==0 ) rc = SQLITE_NOMEM; ++ for(i=1; rc==SQLITE_OK && i<=nCol; i++){ ++ zStat = idxAppendText(&rc, zStat, " %d", (s0+aStat[i]/2) / aStat[i]); ++ } ++ } ++ ++ if( rc==SQLITE_OK ){ ++ sqlite3_bind_text(pWriteStat, 1, zTab, -1, SQLITE_STATIC); ++ sqlite3_bind_text(pWriteStat, 2, zIdx, -1, SQLITE_STATIC); ++ sqlite3_bind_text(pWriteStat, 3, zStat, -1, SQLITE_STATIC); ++ sqlite3_step(pWriteStat); ++ rc = sqlite3_reset(pWriteStat); ++ } ++ ++ pEntry = idxHashFind(&p->hIdx, zIdx, STRLEN(zIdx)); ++ if( pEntry ){ ++ assert( pEntry->zVal2==0 ); ++ pEntry->zVal2 = zStat; ++ }else{ ++ sqlite3_free(zStat); ++ } ++ } ++ sqlite3_free(aStat); ++ idxFinalize(&rc, pQuery); ++ ++ return rc; ++} ++ ++static int idxBuildSampleTable(sqlite3expert *p, const char *zTab){ ++ int rc; ++ char *zSql; ++ ++ rc = sqlite3_exec(p->dbv,"DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0); ++ if( rc!=SQLITE_OK ) return rc; ++ ++ zSql = sqlite3_mprintf( ++ "CREATE TABLE temp." UNIQUE_TABLE_NAME " AS SELECT * FROM %Q", zTab ++ ); ++ if( zSql==0 ) return SQLITE_NOMEM; ++ rc = sqlite3_exec(p->dbv, zSql, 0, 0, 0); ++ sqlite3_free(zSql); ++ ++ return rc; ++} ++ ++/* ++** This function is called as part of sqlite3_expert_analyze(). Candidate ++** indexes have already been created in database sqlite3expert.dbm, this ++** function populates sqlite_stat1 table in the same database. ++** ++** The stat1 data is generated by querying the ++*/ ++static int idxPopulateStat1(sqlite3expert *p, char **pzErr){ ++ int rc = SQLITE_OK; ++ int nMax =0; ++ struct IdxRemCtx *pCtx = 0; ++ struct IdxSampleCtx samplectx; ++ int i; ++ i64 iPrev = -100000; ++ sqlite3_stmt *pAllIndex = 0; ++ sqlite3_stmt *pIndexXInfo = 0; ++ sqlite3_stmt *pWrite = 0; ++ ++ const char *zAllIndex = ++ "SELECT s.rowid, s.name, l.name FROM " ++ " sqlite_master AS s, " ++ " pragma_index_list(s.name) AS l " ++ "WHERE s.type = 'table'"; ++ const char *zIndexXInfo = ++ "SELECT name, coll FROM pragma_index_xinfo(?) WHERE key"; ++ const char *zWrite = "INSERT INTO sqlite_stat1 VALUES(?, ?, ?)"; ++ ++ /* If iSample==0, no sqlite_stat1 data is required. */ ++ if( p->iSample==0 ) return SQLITE_OK; ++ ++ rc = idxLargestIndex(p->dbm, &nMax, pzErr); ++ if( nMax<=0 || rc!=SQLITE_OK ) return rc; ++ ++ rc = sqlite3_exec(p->dbm, "ANALYZE; PRAGMA writable_schema=1", 0, 0, 0); ++ ++ if( rc==SQLITE_OK ){ ++ int nByte = sizeof(struct IdxRemCtx) + (sizeof(struct IdxRemSlot) * nMax); ++ pCtx = (struct IdxRemCtx*)idxMalloc(&rc, nByte); ++ } ++ ++ if( rc==SQLITE_OK ){ ++ sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv); ++ rc = sqlite3_create_function( ++ dbrem, "rem", 2, SQLITE_UTF8, (void*)pCtx, idxRemFunc, 0, 0 ++ ); ++ } ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3_create_function( ++ p->db, "sample", 0, SQLITE_UTF8, (void*)&samplectx, idxSampleFunc, 0, 0 ++ ); ++ } ++ ++ if( rc==SQLITE_OK ){ ++ pCtx->nSlot = nMax+1; ++ rc = idxPrepareStmt(p->dbm, &pAllIndex, pzErr, zAllIndex); ++ } ++ if( rc==SQLITE_OK ){ ++ rc = idxPrepareStmt(p->dbm, &pIndexXInfo, pzErr, zIndexXInfo); ++ } ++ if( rc==SQLITE_OK ){ ++ rc = idxPrepareStmt(p->dbm, &pWrite, pzErr, zWrite); ++ } ++ ++ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pAllIndex) ){ ++ i64 iRowid = sqlite3_column_int64(pAllIndex, 0); ++ const char *zTab = (const char*)sqlite3_column_text(pAllIndex, 1); ++ const char *zIdx = (const char*)sqlite3_column_text(pAllIndex, 2); ++ if( p->iSample<100 && iPrev!=iRowid ){ ++ samplectx.target = (double)p->iSample / 100.0; ++ samplectx.iTarget = p->iSample; ++ samplectx.nRow = 0.0; ++ samplectx.nRet = 0.0; ++ rc = idxBuildSampleTable(p, zTab); ++ if( rc!=SQLITE_OK ) break; ++ } ++ rc = idxPopulateOneStat1(p, pIndexXInfo, pWrite, zTab, zIdx, pzErr); ++ iPrev = iRowid; ++ } ++ if( rc==SQLITE_OK && p->iSample<100 ){ ++ rc = sqlite3_exec(p->dbv, ++ "DROP TABLE IF EXISTS temp." UNIQUE_TABLE_NAME, 0,0,0 ++ ); ++ } ++ ++ idxFinalize(&rc, pAllIndex); ++ idxFinalize(&rc, pIndexXInfo); ++ idxFinalize(&rc, pWrite); ++ ++ for(i=0; i<pCtx->nSlot; i++){ ++ sqlite3_free(pCtx->aSlot[i].z); ++ } ++ sqlite3_free(pCtx); ++ ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3_exec(p->dbm, "ANALYZE sqlite_master", 0, 0, 0); ++ } ++ ++ sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0); ++ return rc; ++} ++ ++/* ++** Allocate a new sqlite3expert object. ++*/ ++sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){ ++ int rc = SQLITE_OK; ++ sqlite3expert *pNew; ++ ++ pNew = (sqlite3expert*)idxMalloc(&rc, sizeof(sqlite3expert)); ++ ++ /* Open two in-memory databases to work with. The "vtab database" (dbv) ++ ** will contain a virtual table corresponding to each real table in ++ ** the user database schema, and a copy of each view. It is used to ++ ** collect information regarding the WHERE, ORDER BY and other clauses ++ ** of the user's query. ++ */ ++ if( rc==SQLITE_OK ){ ++ pNew->db = db; ++ pNew->iSample = 100; ++ rc = sqlite3_open(":memory:", &pNew->dbv); ++ } ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3_open(":memory:", &pNew->dbm); ++ if( rc==SQLITE_OK ){ ++ sqlite3_db_config(pNew->dbm, SQLITE_DBCONFIG_TRIGGER_EQP, 1, (int*)0); ++ } ++ } ++ ++ ++ /* Copy the entire schema of database [db] into [dbm]. */ ++ if( rc==SQLITE_OK ){ ++ sqlite3_stmt *pSql; ++ rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg, ++ "SELECT sql FROM sqlite_master WHERE name NOT LIKE 'sqlite_%%'" ++ " AND sql NOT LIKE 'CREATE VIRTUAL %%'" ++ ); ++ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ ++ const char *zSql = (const char*)sqlite3_column_text(pSql, 0); ++ rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg); ++ } ++ idxFinalize(&rc, pSql); ++ } ++ ++ /* Create the vtab schema */ ++ if( rc==SQLITE_OK ){ ++ rc = idxCreateVtabSchema(pNew, pzErrmsg); ++ } ++ ++ /* Register the auth callback with dbv */ ++ if( rc==SQLITE_OK ){ ++ sqlite3_set_authorizer(pNew->dbv, idxAuthCallback, (void*)pNew); ++ } ++ ++ /* If an error has occurred, free the new object and reutrn NULL. Otherwise, ++ ** return the new sqlite3expert handle. */ ++ if( rc!=SQLITE_OK ){ ++ sqlite3_expert_destroy(pNew); ++ pNew = 0; ++ } ++ return pNew; ++} ++ ++/* ++** Configure an sqlite3expert object. ++*/ ++int sqlite3_expert_config(sqlite3expert *p, int op, ...){ ++ int rc = SQLITE_OK; ++ va_list ap; ++ va_start(ap, op); ++ switch( op ){ ++ case EXPERT_CONFIG_SAMPLE: { ++ int iVal = va_arg(ap, int); ++ if( iVal<0 ) iVal = 0; ++ if( iVal>100 ) iVal = 100; ++ p->iSample = iVal; ++ break; ++ } ++ default: ++ rc = SQLITE_NOTFOUND; ++ break; ++ } ++ ++ va_end(ap); ++ return rc; ++} ++ ++/* ++** Add an SQL statement to the analysis. ++*/ ++int sqlite3_expert_sql( ++ sqlite3expert *p, /* From sqlite3_expert_new() */ ++ const char *zSql, /* SQL statement to add */ ++ char **pzErr /* OUT: Error message (if any) */ ++){ ++ IdxScan *pScanOrig = p->pScan; ++ IdxStatement *pStmtOrig = p->pStatement; ++ int rc = SQLITE_OK; ++ const char *zStmt = zSql; ++ ++ if( p->bRun ) return SQLITE_MISUSE; ++ ++ while( rc==SQLITE_OK && zStmt && zStmt[0] ){ ++ sqlite3_stmt *pStmt = 0; ++ rc = sqlite3_prepare_v2(p->dbv, zStmt, -1, &pStmt, &zStmt); ++ if( rc==SQLITE_OK ){ ++ if( pStmt ){ ++ IdxStatement *pNew; ++ const char *z = sqlite3_sql(pStmt); ++ int n = STRLEN(z); ++ pNew = (IdxStatement*)idxMalloc(&rc, sizeof(IdxStatement) + n+1); ++ if( rc==SQLITE_OK ){ ++ pNew->zSql = (char*)&pNew[1]; ++ memcpy(pNew->zSql, z, n+1); ++ pNew->pNext = p->pStatement; ++ if( p->pStatement ) pNew->iId = p->pStatement->iId+1; ++ p->pStatement = pNew; ++ } ++ sqlite3_finalize(pStmt); ++ } ++ }else{ ++ idxDatabaseError(p->dbv, pzErr); ++ } ++ } ++ ++ if( rc!=SQLITE_OK ){ ++ idxScanFree(p->pScan, pScanOrig); ++ idxStatementFree(p->pStatement, pStmtOrig); ++ p->pScan = pScanOrig; ++ p->pStatement = pStmtOrig; ++ } ++ ++ return rc; ++} ++ ++int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr){ ++ int rc; ++ IdxHashEntry *pEntry; ++ ++ /* Do trigger processing to collect any extra IdxScan structures */ ++ rc = idxProcessTriggers(p, pzErr); ++ ++ /* Create candidate indexes within the in-memory database file */ ++ if( rc==SQLITE_OK ){ ++ rc = idxCreateCandidates(p); ++ } ++ ++ /* Generate the stat1 data */ ++ if( rc==SQLITE_OK ){ ++ rc = idxPopulateStat1(p, pzErr); ++ } ++ ++ /* Formulate the EXPERT_REPORT_CANDIDATES text */ ++ for(pEntry=p->hIdx.pFirst; pEntry; pEntry=pEntry->pNext){ ++ p->zCandidates = idxAppendText(&rc, p->zCandidates, ++ "%s;%s%s\n", pEntry->zVal, ++ pEntry->zVal2 ? " -- stat1: " : "", pEntry->zVal2 ++ ); ++ } ++ ++ /* Figure out which of the candidate indexes are preferred by the query ++ ** planner and report the results to the user. */ ++ if( rc==SQLITE_OK ){ ++ rc = idxFindIndexes(p, pzErr); ++ } ++ ++ if( rc==SQLITE_OK ){ ++ p->bRun = 1; ++ } ++ return rc; ++} ++ ++/* ++** Return the total number of statements that have been added to this ++** sqlite3expert using sqlite3_expert_sql(). ++*/ ++int sqlite3_expert_count(sqlite3expert *p){ ++ int nRet = 0; ++ if( p->pStatement ) nRet = p->pStatement->iId+1; ++ return nRet; ++} ++ ++/* ++** Return a component of the report. ++*/ ++const char *sqlite3_expert_report(sqlite3expert *p, int iStmt, int eReport){ ++ const char *zRet = 0; ++ IdxStatement *pStmt; ++ ++ if( p->bRun==0 ) return 0; ++ for(pStmt=p->pStatement; pStmt && pStmt->iId!=iStmt; pStmt=pStmt->pNext); ++ switch( eReport ){ ++ case EXPERT_REPORT_SQL: ++ if( pStmt ) zRet = pStmt->zSql; ++ break; ++ case EXPERT_REPORT_INDEXES: ++ if( pStmt ) zRet = pStmt->zIdx; ++ break; ++ case EXPERT_REPORT_PLAN: ++ if( pStmt ) zRet = pStmt->zEQP; ++ break; ++ case EXPERT_REPORT_CANDIDATES: ++ zRet = p->zCandidates; ++ break; ++ } ++ return zRet; ++} ++ ++/* ++** Free an sqlite3expert object. ++*/ ++void sqlite3_expert_destroy(sqlite3expert *p){ ++ if( p ){ ++ sqlite3_close(p->dbm); ++ sqlite3_close(p->dbv); ++ idxScanFree(p->pScan, 0); ++ idxStatementFree(p->pStatement, 0); ++ idxTableFree(p->pTable); ++ idxWriteFree(p->pWrite); ++ idxHashClear(&p->hIdx); ++ sqlite3_free(p->zCandidates); ++ sqlite3_free(p); ++ } ++} ++ ++#endif /* ifndef SQLITE_OMIT_VIRTUAL_TABLE */ ++ ++/************************* End ../ext/expert/sqlite3expert.c ********************/ ++ + #if defined(SQLITE_ENABLE_SESSION) + /* + ** State information for a single open session +@@ -2182,6 +8517,29 @@ + int colWidth[100]; /* Column widths prior to ".explain on" */ + }; + ++typedef struct ExpertInfo ExpertInfo; ++struct ExpertInfo { ++ sqlite3expert *pExpert; ++ int bVerbose; ++}; ++ ++/* A single line in the EQP output */ ++typedef struct EQPGraphRow EQPGraphRow; ++struct EQPGraphRow { ++ int iEqpId; /* ID for this row */ ++ int iParentId; /* ID of the parent row */ ++ EQPGraphRow *pNext; /* Next row in sequence */ ++ char zText[1]; /* Text to display for this row */ ++}; ++ ++/* All EQP output is collected into an instance of the following */ ++typedef struct EQPGraph EQPGraph; ++struct EQPGraph { ++ EQPGraphRow *pRow; /* Linked list of all rows of the EQP output */ ++ EQPGraphRow *pLast; /* Last element of the pRow list */ ++ char zPrefix[100]; /* Graph prefix */ ++}; ++ + /* + ** State information about the database connection is contained in an + ** instance of the following structure. +@@ -2189,10 +8547,15 @@ + typedef struct ShellState ShellState; + struct ShellState { + sqlite3 *db; /* The database */ +- int autoExplain; /* Automatically turn on .explain mode */ +- int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ +- int statsOn; /* True to display memory stats before each finalize */ +- int scanstatsOn; /* True to display scan stats before each finalize */ ++ u8 autoExplain; /* Automatically turn on .explain mode */ ++ u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ ++ u8 autoEQPtest; /* autoEQP is in test mode */ ++ u8 statsOn; /* True to display memory stats before each finalize */ ++ u8 scanstatsOn; /* True to display scan stats before each finalize */ ++ u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */ ++ u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */ ++ u8 nEqpLevel; /* Depth of the EQP output graph */ ++ unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */ + int outCount; /* Revert to stdout when reaching zero */ + int cnt; /* Number of records displayed so far */ + FILE *out; /* Write results here */ +@@ -2199,6 +8562,7 @@ + FILE *traceOut; /* Output for sqlite3_trace() */ + int nErr; /* Number of errors seen */ + int mode; /* An output mode setting */ ++ int modePrior; /* Saved mode */ + int cMode; /* temporary output mode for the current query */ + int normalMode; /* Output mode before ".explain on" */ + int writableSchema; /* True if PRAGMA writable_schema=ON */ +@@ -2206,9 +8570,12 @@ + int nCheck; /* Number of ".check" commands run */ + unsigned shellFlgs; /* Various flags */ + char *zDestTable; /* Name of destination table when MODE_Insert */ ++ char *zTempFile; /* Temporary file that might need deleting */ + char zTestcase[30]; /* Name of current test case */ + char colSeparator[20]; /* Column separator character for several modes */ + char rowSeparator[20]; /* Row separator character for MODE_Ascii */ ++ char colSepPrior[20]; /* Saved column separator */ ++ char rowSepPrior[20]; /* Saved row separator */ + int colWidth[100]; /* Requested width of each column when in column mode*/ + int actualWidth[100]; /* Actual width of each column */ + char nullValue[20]; /* The text to print when a NULL comes back from +@@ -2222,23 +8589,41 @@ + int *aiIndent; /* Array of indents used in MODE_Explain */ + int nIndent; /* Size of array aiIndent[] */ + int iIndent; /* Index of current op in aiIndent[] */ ++ EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */ + #if defined(SQLITE_ENABLE_SESSION) + int nSession; /* Number of active sessions */ + OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */ + #endif ++ ExpertInfo expert; /* Valid if previous command was ".expert OPT..." */ + }; + ++ ++/* Allowed values for ShellState.autoEQP ++*/ ++#define AUTOEQP_off 0 /* Automatic EXPLAIN QUERY PLAN is off */ ++#define AUTOEQP_on 1 /* Automatic EQP is on */ ++#define AUTOEQP_trigger 2 /* On and also show plans for triggers */ ++#define AUTOEQP_full 3 /* Show full EXPLAIN */ ++ ++/* Allowed values for ShellState.openMode ++*/ ++#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */ ++#define SHELL_OPEN_NORMAL 1 /* Normal database file */ ++#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */ ++#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */ ++#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */ ++#define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */ ++ + /* + ** These are the allowed shellFlgs values + */ +-#define SHFLG_Scratch 0x00000001 /* The --scratch option is used */ +-#define SHFLG_Pagecache 0x00000002 /* The --pagecache option is used */ +-#define SHFLG_Lookaside 0x00000004 /* Lookaside memory is used */ +-#define SHFLG_Backslash 0x00000008 /* The --backslash option is used */ +-#define SHFLG_PreserveRowid 0x00000010 /* .dump preserves rowid values */ +-#define SHFLG_Newlines 0x00000020 /* .dump --newline flag */ +-#define SHFLG_CountChanges 0x00000040 /* .changes setting */ +-#define SHFLG_Echo 0x00000080 /* .echo or --echo setting */ ++#define SHFLG_Pagecache 0x00000001 /* The --pagecache option is used */ ++#define SHFLG_Lookaside 0x00000002 /* Lookaside memory is used */ ++#define SHFLG_Backslash 0x00000004 /* The --backslash option is used */ ++#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 or --echo setting */ + + /* + ** Macros for testing and setting shellFlgs +@@ -2262,6 +8647,7 @@ + #define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */ + #define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */ + #define MODE_Pretty 11 /* Pretty-print schemas */ ++#define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */ + + static const char *modeDescr[] = { + "line", +@@ -2276,6 +8662,7 @@ + "explain", + "ascii", + "prettyprint", ++ "eqp" + }; + + /* +@@ -2292,11 +8679,6 @@ + #define SEP_Record "\x1E" + + /* +-** Number of elements in an array +-*/ +-#define ArraySize(X) (int)(sizeof(X)/sizeof(X[0])) +- +-/* + ** A callback for the sqlite3_log() interface. + */ + static void shellLog(void *pArg, int iErrCode, const char *zMsg){ +@@ -2307,6 +8689,181 @@ + } + + /* ++** SQL function: shell_putsnl(X) ++** ++** Write the text X to the screen (or whatever output is being directed) ++** adding a newline at the end, and then return X. ++*/ ++static void shellPutsFunc( ++ sqlite3_context *pCtx, ++ int nVal, ++ sqlite3_value **apVal ++){ ++ ShellState *p = (ShellState*)sqlite3_user_data(pCtx); ++ (void)nVal; ++ utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0])); ++ sqlite3_result_value(pCtx, apVal[0]); ++} ++ ++/* ++** SQL function: edit(VALUE) ++** edit(VALUE,EDITOR) ++** ++** These steps: ++** ++** (1) Write VALUE into a temporary file. ++** (2) Run program EDITOR on that temporary file. ++** (3) Read the temporary file back and return its content as the result. ++** (4) Delete the temporary file ++** ++** If the EDITOR argument is omitted, use the value in the VISUAL ++** environment variable. If still there is no EDITOR, through an error. ++** ++** Also throw an error if the EDITOR program returns a non-zero exit code. ++*/ ++#ifndef SQLITE_NOHAVE_SYSTEM ++static void editFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ const char *zEditor; ++ char *zTempFile = 0; ++ sqlite3 *db; ++ char *zCmd = 0; ++ int bBin; ++ int rc; ++ int hasCRNL = 0; ++ FILE *f = 0; ++ sqlite3_int64 sz; ++ sqlite3_int64 x; ++ unsigned char *p = 0; ++ ++ if( argc==2 ){ ++ zEditor = (const char*)sqlite3_value_text(argv[1]); ++ }else{ ++ zEditor = getenv("VISUAL"); ++ } ++ if( zEditor==0 ){ ++ sqlite3_result_error(context, "no editor for edit()", -1); ++ return; ++ } ++ if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ ++ sqlite3_result_error(context, "NULL input to edit()", -1); ++ return; ++ } ++ db = sqlite3_context_db_handle(context); ++ zTempFile = 0; ++ sqlite3_file_control(db, 0, SQLITE_FCNTL_TEMPFILENAME, &zTempFile); ++ if( zTempFile==0 ){ ++ sqlite3_uint64 r = 0; ++ sqlite3_randomness(sizeof(r), &r); ++ zTempFile = sqlite3_mprintf("temp%llx", r); ++ if( zTempFile==0 ){ ++ sqlite3_result_error_nomem(context); ++ return; ++ } ++ } ++ bBin = sqlite3_value_type(argv[0])==SQLITE_BLOB; ++ /* When writing the file to be edited, do \n to \r\n conversions on systems ++ ** that want \r\n line endings */ ++ f = fopen(zTempFile, bBin ? "wb" : "w"); ++ if( f==0 ){ ++ sqlite3_result_error(context, "edit() cannot open temp file", -1); ++ goto edit_func_end; ++ } ++ sz = sqlite3_value_bytes(argv[0]); ++ if( bBin ){ ++ x = fwrite(sqlite3_value_blob(argv[0]), 1, sz, f); ++ }else{ ++ const char *z = (const char*)sqlite3_value_text(argv[0]); ++ /* Remember whether or not the value originally contained \r\n */ ++ if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1; ++ x = fwrite(sqlite3_value_text(argv[0]), 1, sz, f); ++ } ++ fclose(f); ++ f = 0; ++ if( x!=sz ){ ++ sqlite3_result_error(context, "edit() could not write the whole file", -1); ++ goto edit_func_end; ++ } ++ zCmd = sqlite3_mprintf("%s \"%s\"", zEditor, zTempFile); ++ if( zCmd==0 ){ ++ sqlite3_result_error_nomem(context); ++ goto edit_func_end; ++ } ++ rc = system(zCmd); ++ sqlite3_free(zCmd); ++ if( rc ){ ++ sqlite3_result_error(context, "EDITOR returned non-zero", -1); ++ goto edit_func_end; ++ } ++ f = fopen(zTempFile, "rb"); ++ if( f==0 ){ ++ sqlite3_result_error(context, ++ "edit() cannot reopen temp file after edit", -1); ++ goto edit_func_end; ++ } ++ fseek(f, 0, SEEK_END); ++ sz = ftell(f); ++ rewind(f); ++ p = sqlite3_malloc64( sz+(bBin==0) ); ++ if( p==0 ){ ++ sqlite3_result_error_nomem(context); ++ goto edit_func_end; ++ } ++ x = fread(p, 1, sz, f); ++ fclose(f); ++ f = 0; ++ if( x!=sz ){ ++ sqlite3_result_error(context, "could not read back the whole file", -1); ++ goto edit_func_end; ++ } ++ if( bBin ){ ++ sqlite3_result_blob64(context, p, sz, sqlite3_free); ++ }else{ ++ sqlite3_int64 i, j; ++ if( hasCRNL ){ ++ /* If the original contains \r\n then do no conversions back to \n */ ++ j = sz; ++ }else{ ++ /* If the file did not originally contain \r\n then convert any new ++ ** \r\n back into \n */ ++ for(i=j=0; i<sz; i++){ ++ if( p[i]=='\r' && p[i+1]=='\n' ) i++; ++ p[j++] = p[i]; ++ } ++ sz = j; ++ p[sz] = 0; ++ } ++ sqlite3_result_text64(context, (const char*)p, sz, ++ sqlite3_free, SQLITE_UTF8); ++ } ++ p = 0; ++ ++edit_func_end: ++ if( f ) fclose(f); ++ unlink(zTempFile); ++ sqlite3_free(zTempFile); ++ sqlite3_free(p); ++} ++#endif /* SQLITE_NOHAVE_SYSTEM */ ++ ++/* ++** Save or restore the current output mode ++*/ ++static void outputModePush(ShellState *p){ ++ p->modePrior = p->mode; ++ memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator)); ++ memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator)); ++} ++static void outputModePop(ShellState *p){ ++ p->mode = p->modePrior; ++ memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator)); ++ memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator)); ++} ++ ++/* + ** Output the given string as a hex-encoded blob (eg. X'1234' ) + */ + static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){ +@@ -2551,12 +9108,9 @@ + } + } + if( i==0 ){ +- putc('"', out); +- for(i=0; z[i]; i++){ +- if( z[i]=='"' ) putc('"', out); +- putc(z[i], out); +- } +- putc('"', out); ++ char *zQuoted = sqlite3_mprintf("\"%w\"", z); ++ utf8_printf(out, "%s", zQuoted); ++ sqlite3_free(zQuoted); + }else{ + utf8_printf(out, "%s", z); + } +@@ -2566,7 +9120,6 @@ + } + } + +-#ifdef SIGINT + /* + ** This routine runs when the user presses Ctrl-C + */ +@@ -2576,6 +9129,20 @@ + 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 ++*/ ++static BOOL WINAPI ConsoleCtrlHandler( ++ DWORD dwCtrlType /* One of the CTRL_*_EVENT constants */ ++){ ++ if( dwCtrlType==CTRL_C_EVENT ){ ++ interrupt_handler(0); ++ return TRUE; ++ } ++ return FALSE; ++} + #endif + + #ifndef SQLITE_OMIT_AUTHORIZATION +@@ -2646,6 +9213,108 @@ + } + + /* ++** Return true if string z[] has nothing but whitespace and comments to the ++** end of the first line. ++*/ ++static int wsToEol(const char *z){ ++ int i; ++ for(i=0; z[i]; i++){ ++ if( z[i]=='\n' ) return 1; ++ if( IsSpace(z[i]) ) continue; ++ if( z[i]=='-' && z[i+1]=='-' ) return 1; ++ return 0; ++ } ++ return 1; ++} ++ ++/* ++** Add a new entry to the EXPLAIN QUERY PLAN data ++*/ ++static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){ ++ EQPGraphRow *pNew; ++ int nText = strlen30(zText); ++ if( p->autoEQPtest ){ ++ utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText); ++ } ++ pNew = sqlite3_malloc64( sizeof(*pNew) + nText ); ++ if( pNew==0 ) shell_out_of_memory(); ++ pNew->iEqpId = iEqpId; ++ pNew->iParentId = p2; ++ memcpy(pNew->zText, zText, nText+1); ++ pNew->pNext = 0; ++ if( p->sGraph.pLast ){ ++ p->sGraph.pLast->pNext = pNew; ++ }else{ ++ p->sGraph.pRow = pNew; ++ } ++ p->sGraph.pLast = pNew; ++} ++ ++/* ++** Free and reset the EXPLAIN QUERY PLAN data that has been collected ++** in p->sGraph. ++*/ ++static void eqp_reset(ShellState *p){ ++ EQPGraphRow *pRow, *pNext; ++ for(pRow = p->sGraph.pRow; pRow; pRow = pNext){ ++ pNext = pRow->pNext; ++ sqlite3_free(pRow); ++ } ++ memset(&p->sGraph, 0, sizeof(p->sGraph)); ++} ++ ++/* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after ++** pOld, or return the first such line if pOld is NULL ++*/ ++static EQPGraphRow *eqp_next_row(ShellState *p, int iEqpId, EQPGraphRow *pOld){ ++ EQPGraphRow *pRow = pOld ? pOld->pNext : p->sGraph.pRow; ++ while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext; ++ return pRow; ++} ++ ++/* Render a single level of the graph that has iEqpId as its parent. Called ++** recursively to render sublevels. ++*/ ++static void eqp_render_level(ShellState *p, int iEqpId){ ++ EQPGraphRow *pRow, *pNext; ++ int n = strlen30(p->sGraph.zPrefix); ++ char *z; ++ for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){ ++ pNext = eqp_next_row(p, iEqpId, pRow); ++ z = pRow->zText; ++ utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix, pNext ? "|--" : "`--", z); ++ if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){ ++ memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4); ++ eqp_render_level(p, pRow->iEqpId); ++ p->sGraph.zPrefix[n] = 0; ++ } ++ } ++} ++ ++/* ++** Display and reset the EXPLAIN QUERY PLAN data ++*/ ++static void eqp_render(ShellState *p){ ++ EQPGraphRow *pRow = p->sGraph.pRow; ++ if( pRow ){ ++ if( pRow->zText[0]=='-' ){ ++ if( pRow->pNext==0 ){ ++ eqp_reset(p); ++ return; ++ } ++ utf8_printf(p->out, "%s\n", pRow->zText+3); ++ p->sGraph.pRow = pRow->pNext; ++ sqlite3_free(pRow); ++ }else{ ++ utf8_printf(p->out, "QUERY PLAN\n"); ++ } ++ p->sGraph.zPrefix[0] = 0; ++ eqp_render_level(p, 0); ++ eqp_reset(p); ++ } ++} ++ ++/* + ** This is the callback routine that the shell + ** invokes for each row of a query result. + */ +@@ -2659,6 +9328,7 @@ + int i; + ShellState *p = (ShellState*)pArg; + ++ if( azArg==0 ) return 0; + switch( p->cMode ){ + case MODE_Line: { + int w = 5; +@@ -2773,6 +9443,7 @@ + for(i=0; IsSpace(z[i]); i++){} + for(; (c = z[i])!=0; i++){ + if( IsSpace(c) ){ ++ if( z[j-1]=='\r' ) z[j-1] = '\n'; + if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue; + }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){ + j--; +@@ -2782,7 +9453,7 @@ + while( j>0 && IsSpace(z[j-1]) ){ j--; } + z[j] = 0; + if( strlen30(z)>=79 ){ +- for(i=j=0; (c = z[i])!=0; i++){ ++ for(i=j=0; (c = z[i])!=0; i++){ /* Copy changes from z[i] back to z[j] */ + if( c==cEnd ){ + cEnd = 0; + }else if( c=='"' || c=='\'' || c=='`' ){ +@@ -2789,6 +9460,8 @@ + cEnd = c; + }else if( c=='[' ){ + cEnd = ']'; ++ }else if( c=='-' && z[i+1]=='-' ){ ++ cEnd = '\n'; + }else if( c=='(' ){ + nParen++; + }else if( c==')' ){ +@@ -2799,7 +9472,9 @@ + } + } + z[j++] = c; +- if( nParen==1 && (c=='(' || c==',' || c=='\n') ){ ++ if( nParen==1 && cEnd==0 ++ && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1))) ++ ){ + if( c=='\n' ) j--; + printSchemaLineN(p->out, z, j, "\n "); + j = 0; +@@ -2919,8 +9594,16 @@ + }else if( aiType && aiType[i]==SQLITE_FLOAT ){ + char z[50]; + double r = sqlite3_column_double(p->pStmt, i); +- sqlite3_snprintf(50,z,"%!.20g", r); +- raw_printf(p->out, "%s", z); ++ 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); +@@ -2988,6 +9671,10 @@ + utf8_printf(p->out, "%s", p->rowSeparator); + break; + } ++ case MODE_EQP: { ++ eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]); ++ break; ++ } + } + return 0; + } +@@ -3009,6 +9696,7 @@ + ShellText *p = (ShellText*)pArg; + int i; + UNUSED_PARAMETER(az); ++ if( azArg==0 ) return 0; + if( p->n ) appendText(p, "|", 0); + for(i=0; i<nArg; i++){ + if( i ) appendText(p, ",", 0); +@@ -3073,7 +9761,7 @@ + */ + static void set_table_name(ShellState *p, const char *zName){ + int i, n; +- int cQuote; ++ char cQuote; + char *z; + + if( p->zDestTable ){ +@@ -3085,10 +9773,7 @@ + n = strlen30(zName); + if( cQuote ) n += n+2; + z = p->zDestTable = malloc( n+1 ); +- if( z==0 ){ +- raw_printf(stderr,"Error: out of memory\n"); +- exit(1); +- } ++ if( z==0 ) shell_out_of_memory(); + n = 0; + if( cQuote ) z[n++] = cQuote; + for(i=0; zName[i]; i++){ +@@ -3196,7 +9881,7 @@ + }; + int i; + for(i=0; i<ArraySize(aTrans); i++){ +- int n = (int)strlen(aTrans[i].zPattern); ++ int n = strlen30(aTrans[i].zPattern); + if( strncmp(aTrans[i].zPattern, z, n)==0 ){ + utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]); + break; +@@ -3243,37 +9928,54 @@ + ){ + int iCur; + int iHiwtr; ++ FILE *out; ++ if( pArg==0 || pArg->out==0 ) return 0; ++ out = pArg->out; + +- if( pArg && pArg->out ){ +- displayStatLine(pArg, "Memory Used:", +- "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset); +- displayStatLine(pArg, "Number of Outstanding Allocations:", +- "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset); +- if( pArg->shellFlgs & SHFLG_Pagecache ){ +- displayStatLine(pArg, "Number of Pcache Pages Used:", +- "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset); ++ if( pArg->pStmt && (pArg->statsOn & 2) ){ ++ int nCol, i, x; ++ sqlite3_stmt *pStmt = pArg->pStmt; ++ char z[100]; ++ nCol = sqlite3_column_count(pStmt); ++ raw_printf(out, "%-36s %d\n", "Number of output columns:", nCol); ++ for(i=0; i<nCol; i++){ ++ sqlite3_snprintf(sizeof(z),z,"Column %d %nname:", i, &x); ++ utf8_printf(out, "%-36s %s\n", z, sqlite3_column_name(pStmt,i)); ++#ifndef SQLITE_OMIT_DECLTYPE ++ sqlite3_snprintf(30, z+x, "declared type:"); ++ utf8_printf(out, "%-36s %s\n", z, sqlite3_column_decltype(pStmt, i)); ++#endif ++#ifdef SQLITE_ENABLE_COLUMN_METADATA ++ sqlite3_snprintf(30, z+x, "database name:"); ++ utf8_printf(out, "%-36s %s\n", z, sqlite3_column_database_name(pStmt,i)); ++ sqlite3_snprintf(30, z+x, "table name:"); ++ utf8_printf(out, "%-36s %s\n", z, sqlite3_column_table_name(pStmt,i)); ++ sqlite3_snprintf(30, z+x, "origin name:"); ++ utf8_printf(out, "%-36s %s\n", z, sqlite3_column_origin_name(pStmt,i)); ++#endif + } +- displayStatLine(pArg, "Number of Pcache Overflow Bytes:", +- "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset); +- if( pArg->shellFlgs & SHFLG_Scratch ){ +- displayStatLine(pArg, "Number of Scratch Allocations Used:", +- "%lld (max %lld)", SQLITE_STATUS_SCRATCH_USED, bReset); +- } +- displayStatLine(pArg, "Number of Scratch Overflow Bytes:", +- "%lld (max %lld) bytes", SQLITE_STATUS_SCRATCH_OVERFLOW, bReset); +- displayStatLine(pArg, "Largest Allocation:", +- "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset); +- displayStatLine(pArg, "Largest Pcache Allocation:", +- "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset); +- displayStatLine(pArg, "Largest Scratch Allocation:", +- "%lld bytes", SQLITE_STATUS_SCRATCH_SIZE, bReset); ++ } ++ ++ displayStatLine(pArg, "Memory Used:", ++ "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset); ++ displayStatLine(pArg, "Number of Outstanding Allocations:", ++ "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset); ++ if( pArg->shellFlgs & SHFLG_Pagecache ){ ++ displayStatLine(pArg, "Number of Pcache Pages Used:", ++ "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset); ++ } ++ displayStatLine(pArg, "Number of Pcache Overflow Bytes:", ++ "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset); ++ displayStatLine(pArg, "Largest Allocation:", ++ "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset); ++ displayStatLine(pArg, "Largest Pcache Allocation:", ++ "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset); + #ifdef YYTRACKMAXSTACKDEPTH +- displayStatLine(pArg, "Deepest Parser Stack:", +- "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset); ++ displayStatLine(pArg, "Deepest Parser Stack:", ++ "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset); + #endif +- } + +- if( pArg && pArg->out && db ){ ++ if( db ){ + if( pArg->shellFlgs & SHFLG_Lookaside ){ + iHiwtr = iCur = -1; + sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, +@@ -3308,6 +10010,9 @@ + sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1); + raw_printf(pArg->out, "Page cache writes: %d\n", iCur); + iHiwtr = iCur = -1; ++ sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1); ++ raw_printf(pArg->out, "Page cache spills: %d\n", iCur); ++ iHiwtr = iCur = -1; + sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset); + raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n", + iCur); +@@ -3317,7 +10022,7 @@ + iCur); + } + +- if( pArg && pArg->out && db && pArg->pStmt ){ ++ if( pArg->pStmt ){ + iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP, + bReset); + raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur); +@@ -3327,6 +10032,12 @@ + raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur); + iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset); + raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur); ++ iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE, bReset); ++ raw_printf(pArg->out, "Reprepare operations: %d\n", iCur); ++ iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset); ++ raw_printf(pArg->out, "Number of times run: %d\n", iCur); ++ iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset); ++ raw_printf(pArg->out, "Memory used by prepared stmt: %d\n", iCur); + } + + #ifdef __linux__ +@@ -3425,8 +10136,7 @@ + int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */ + int iOp; /* Index of operation in p->aiIndent[] */ + +- const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", +- "NextIfOpen", "PrevIfOpen", 0 }; ++ const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 }; + const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead", + "Rewind", 0 }; + const char *azGoto[] = { "Goto", 0 }; +@@ -3476,7 +10186,9 @@ + } + nAlloc += 100; + p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int)); ++ if( p->aiIndent==0 ) shell_out_of_memory(); + abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int)); ++ if( abYield==0 ) shell_out_of_memory(); + } + abYield[iOp] = str_in_array(zOp, azYield); + p->aiIndent[iOp] = 0; +@@ -3542,8 +10254,7 @@ + */ + static void exec_prepared_stmt( + ShellState *pArg, /* Pointer to ShellState */ +- sqlite3_stmt *pStmt, /* Statment to run */ +- int (*xCallback)(void*,int,char**,char**,int*) /* Callback function */ ++ sqlite3_stmt *pStmt /* Statment to run */ + ){ + int rc; + +@@ -3553,57 +10264,181 @@ + rc = sqlite3_step(pStmt); + /* if we have a result set... */ + if( SQLITE_ROW == rc ){ +- /* if we have a callback... */ +- if( xCallback ){ +- /* allocate space for col name ptr, value ptr, and type */ +- int nCol = sqlite3_column_count(pStmt); +- void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1); +- if( !pData ){ +- rc = SQLITE_NOMEM; +- }else{ +- char **azCols = (char **)pData; /* Names of result columns */ +- char **azVals = &azCols[nCol]; /* Results */ +- int *aiTypes = (int *)&azVals[nCol]; /* Result types */ +- int i, x; +- assert(sizeof(int) <= sizeof(char *)); +- /* save off ptrs to column names */ ++ /* allocate space for col name ptr, value ptr, and type */ ++ int nCol = sqlite3_column_count(pStmt); ++ void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1); ++ if( !pData ){ ++ rc = SQLITE_NOMEM; ++ }else{ ++ char **azCols = (char **)pData; /* Names of result columns */ ++ char **azVals = &azCols[nCol]; /* Results */ ++ int *aiTypes = (int *)&azVals[nCol]; /* Result types */ ++ int i, x; ++ assert(sizeof(int) <= sizeof(char *)); ++ /* save off ptrs to column names */ ++ for(i=0; i<nCol; i++){ ++ azCols[i] = (char *)sqlite3_column_name(pStmt, i); ++ } ++ do{ ++ /* extract the data and data types */ + for(i=0; i<nCol; i++){ +- azCols[i] = (char *)sqlite3_column_name(pStmt, i); ++ aiTypes[i] = x = sqlite3_column_type(pStmt, i); ++ if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){ ++ azVals[i] = ""; ++ }else{ ++ azVals[i] = (char*)sqlite3_column_text(pStmt, i); ++ } ++ if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){ ++ rc = SQLITE_NOMEM; ++ break; /* from for */ ++ } ++ } /* end for */ ++ ++ /* if data and types extracted successfully... */ ++ if( SQLITE_ROW == rc ){ ++ /* call the supplied callback with the result row data */ ++ if( shell_callback(pArg, nCol, azVals, azCols, aiTypes) ){ ++ rc = SQLITE_ABORT; ++ }else{ ++ rc = sqlite3_step(pStmt); ++ } + } +- do{ +- /* extract the data and data types */ +- for(i=0; i<nCol; i++){ +- aiTypes[i] = x = sqlite3_column_type(pStmt, i); +- if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){ +- azVals[i] = ""; +- }else{ +- azVals[i] = (char*)sqlite3_column_text(pStmt, i); +- } +- if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){ +- rc = SQLITE_NOMEM; +- break; /* from for */ +- } +- } /* end for */ ++ } while( SQLITE_ROW == rc ); ++ sqlite3_free(pData); ++ } ++ } ++} + +- /* if data and types extracted successfully... */ +- if( SQLITE_ROW == rc ){ +- /* call the supplied callback with the result row data */ +- if( xCallback(pArg, nCol, azVals, azCols, aiTypes) ){ +- rc = SQLITE_ABORT; +- }else{ +- rc = sqlite3_step(pStmt); +- } +- } +- } while( SQLITE_ROW == rc ); +- sqlite3_free(pData); ++#ifndef SQLITE_OMIT_VIRTUALTABLE ++/* ++** This function is called to process SQL if the previous shell command ++** was ".expert". It passes the SQL in the second argument directly to ++** the sqlite3expert object. ++** ++** If successful, SQLITE_OK is returned. Otherwise, an SQLite error ++** code. In this case, (*pzErr) may be set to point to a buffer containing ++** an English language error message. It is the responsibility of the ++** caller to eventually free this buffer using sqlite3_free(). ++*/ ++static int expertHandleSQL( ++ ShellState *pState, ++ const char *zSql, ++ char **pzErr ++){ ++ assert( pState->expert.pExpert ); ++ assert( pzErr==0 || *pzErr==0 ); ++ return sqlite3_expert_sql(pState->expert.pExpert, zSql, pzErr); ++} ++ ++/* ++** This function is called either to silently clean up the object ++** created by the ".expert" command (if bCancel==1), or to generate a ++** report from it and then clean it up (if bCancel==0). ++** ++** If successful, SQLITE_OK is returned. Otherwise, an SQLite error ++** code. In this case, (*pzErr) may be set to point to a buffer containing ++** an English language error message. It is the responsibility of the ++** caller to eventually free this buffer using sqlite3_free(). ++*/ ++static int expertFinish( ++ ShellState *pState, ++ int bCancel, ++ char **pzErr ++){ ++ int rc = SQLITE_OK; ++ sqlite3expert *p = pState->expert.pExpert; ++ assert( p ); ++ assert( bCancel || pzErr==0 || *pzErr==0 ); ++ if( bCancel==0 ){ ++ FILE *out = pState->out; ++ int bVerbose = pState->expert.bVerbose; ++ ++ rc = sqlite3_expert_analyze(p, pzErr); ++ if( rc==SQLITE_OK ){ ++ int nQuery = sqlite3_expert_count(p); ++ int i; ++ ++ if( bVerbose ){ ++ const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES); ++ raw_printf(out, "-- Candidates -----------------------------\n"); ++ raw_printf(out, "%s\n", zCand); + } ++ for(i=0; i<nQuery; i++){ ++ const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL); ++ const char *zIdx = sqlite3_expert_report(p, i, EXPERT_REPORT_INDEXES); ++ const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN); ++ if( zIdx==0 ) zIdx = "(no new indexes)\n"; ++ if( bVerbose ){ ++ raw_printf(out, "-- Query %d --------------------------------\n",i+1); ++ raw_printf(out, "%s\n\n", zSql); ++ } ++ raw_printf(out, "%s\n", zIdx); ++ raw_printf(out, "%s\n", zEQP); ++ } ++ } ++ } ++ sqlite3_expert_destroy(p); ++ pState->expert.pExpert = 0; ++ return rc; ++} ++ ++/* ++** Implementation of ".expert" dot command. ++*/ ++static int expertDotCommand( ++ ShellState *pState, /* Current shell tool state */ ++ char **azArg, /* Array of arguments passed to dot command */ ++ int nArg /* Number of entries in azArg[] */ ++){ ++ int rc = SQLITE_OK; ++ char *zErr = 0; ++ int i; ++ int iSample = 0; ++ ++ assert( pState->expert.pExpert==0 ); ++ memset(&pState->expert, 0, sizeof(ExpertInfo)); ++ ++ for(i=1; rc==SQLITE_OK && i<nArg; i++){ ++ char *z = azArg[i]; ++ int n; ++ if( z[0]=='-' && z[1]=='-' ) z++; ++ n = strlen30(z); ++ if( n>=2 && 0==strncmp(z, "-verbose", n) ){ ++ pState->expert.bVerbose = 1; ++ } ++ else if( n>=2 && 0==strncmp(z, "-sample", n) ){ ++ if( i==(nArg-1) ){ ++ raw_printf(stderr, "option requires an argument: %s\n", z); ++ rc = SQLITE_ERROR; ++ }else{ ++ iSample = (int)integerValue(azArg[++i]); ++ if( iSample<0 || iSample>100 ){ ++ raw_printf(stderr, "value out of range: %s\n", azArg[i]); ++ rc = SQLITE_ERROR; ++ } ++ } ++ } ++ else{ ++ raw_printf(stderr, "unknown option: %s\n", z); ++ rc = SQLITE_ERROR; ++ } ++ } ++ ++ if( rc==SQLITE_OK ){ ++ pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr); ++ if( pState->expert.pExpert==0 ){ ++ raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr); ++ rc = SQLITE_ERROR; + }else{ +- do{ +- rc = sqlite3_step(pStmt); +- } while( rc == SQLITE_ROW ); ++ sqlite3_expert_config( ++ pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample ++ ); + } + } ++ ++ return rc; + } ++#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ + + /* + ** Execute a statement or set of statements. Print +@@ -3615,11 +10450,8 @@ + ** and callback data argument. + */ + static int shell_exec( +- sqlite3 *db, /* An open database */ ++ ShellState *pArg, /* Pointer to ShellState */ + const char *zSql, /* SQL to be evaluated */ +- int (*xCallback)(void*,int,char**,char**,int*), /* Callback function */ +- /* (not the same as sqlite3_exec) */ +- ShellState *pArg, /* Pointer to ShellState */ + char **pzErrMsg /* Error msg written here */ + ){ + sqlite3_stmt *pStmt = NULL; /* Statement to execute. */ +@@ -3626,11 +10458,19 @@ + int rc = SQLITE_OK; /* Return Code */ + int rc2; + const char *zLeftover; /* Tail of unprocessed SQL */ ++ sqlite3 *db = pArg->db; + + if( pzErrMsg ){ + *pzErrMsg = NULL; + } + ++#ifndef SQLITE_OMIT_VIRTUALTABLE ++ if( pArg->expert.pExpert ){ ++ rc = expertHandleSQL(pArg, zSql, pzErrMsg); ++ return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg); ++ } ++#endif ++ + while( zSql[0] && (SQLITE_OK == rc) ){ + static const char *zStmtSql; + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover); +@@ -3664,20 +10504,27 @@ + if( pArg && pArg->autoEQP && sqlite3_strlike("EXPLAIN%",zStmtSql,0)!=0 ){ + sqlite3_stmt *pExplain; + char *zEQP; ++ int triggerEQP = 0; + disable_debug_trace_modes(); ++ sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP); ++ if( pArg->autoEQP>=AUTOEQP_trigger ){ ++ sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0); ++ } + zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql); + rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0); + if( rc==SQLITE_OK ){ + while( sqlite3_step(pExplain)==SQLITE_ROW ){ +- raw_printf(pArg->out,"--EQP-- %d,",sqlite3_column_int(pExplain, 0)); +- raw_printf(pArg->out,"%d,", sqlite3_column_int(pExplain, 1)); +- raw_printf(pArg->out,"%d,", sqlite3_column_int(pExplain, 2)); +- utf8_printf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3)); ++ const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3); ++ int iEqpId = sqlite3_column_int(pExplain, 0); ++ int iParentId = sqlite3_column_int(pExplain, 1); ++ if( zEQPLine[0]=='-' ) eqp_render(pArg); ++ eqp_append(pArg, iEqpId, iParentId, zEQPLine); + } ++ eqp_render(pArg); + } + sqlite3_finalize(pExplain); + sqlite3_free(zEQP); +- if( pArg->autoEQP>=2 ){ ++ if( pArg->autoEQP>=AUTOEQP_full ){ + /* Also do an EXPLAIN for ".eqp full" mode */ + zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql); + rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0); +@@ -3684,22 +10531,34 @@ + if( rc==SQLITE_OK ){ + pArg->cMode = MODE_Explain; + explain_data_prepare(pArg, pExplain); +- exec_prepared_stmt(pArg, pExplain, xCallback); ++ exec_prepared_stmt(pArg, pExplain); + explain_data_delete(pArg); + } + sqlite3_finalize(pExplain); + sqlite3_free(zEQP); + } ++ if( pArg->autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){ ++ sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0); ++ /* Reprepare pStmt before reactiving trace modes */ ++ sqlite3_finalize(pStmt); ++ sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); ++ if( pArg ) pArg->pStmt = pStmt; ++ } + restore_debug_trace_modes(); + } + + if( pArg ){ + pArg->cMode = pArg->mode; +- if( pArg->autoExplain +- && sqlite3_column_count(pStmt)==8 +- && sqlite3_strlike("EXPLAIN%", zStmtSql,0)==0 +- ){ +- pArg->cMode = MODE_Explain; ++ if( pArg->autoExplain ){ ++ if( sqlite3_column_count(pStmt)==8 ++ && sqlite3_strlike("EXPLAIN%", zStmtSql,0)==0 ++ ){ ++ pArg->cMode = MODE_Explain; ++ } ++ if( sqlite3_column_count(pStmt)==4 ++ && sqlite3_strlike("EXPLAIN QUERY PLAN%", zStmtSql,0)==0 ){ ++ pArg->cMode = MODE_EQP; ++ } + } + + /* If the shell is currently in ".explain" mode, gather the extra +@@ -3709,8 +10568,9 @@ + } + } + +- exec_prepared_stmt(pArg, pStmt, xCallback); ++ exec_prepared_stmt(pArg, pStmt); + explain_data_delete(pArg); ++ eqp_render(pArg); + + /* print usage stats if stats on */ + if( pArg && pArg->statsOn ){ +@@ -3788,10 +10648,7 @@ + if( nCol>=nAlloc-2 ){ + nAlloc = nAlloc*2 + nCol + 10; + azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0])); +- if( azCol==0 ){ +- raw_printf(stderr, "Error: out of memory\n"); +- exit(1); +- } ++ if( azCol==0 ) shell_out_of_memory(); + } + azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1)); + if( sqlite3_column_int(pStmt, 5) ){ +@@ -3807,6 +10664,7 @@ + } + } + sqlite3_finalize(pStmt); ++ if( azCol==0 ) return 0; + azCol[0] = 0; + azCol[nCol+1] = 0; + +@@ -3890,7 +10748,7 @@ + ShellState *p = (ShellState *)pArg; + + UNUSED_PARAMETER(azNotUsed); +- if( nArg!=3 ) return 1; ++ if( nArg!=3 || azArg==0 ) return 0; + zTable = azArg[0]; + zType = azArg[1]; + zSql = azArg[2]; +@@ -3971,11 +10829,11 @@ + savedMode = p->mode; + p->zDestTable = sTable.z; + p->mode = p->cMode = MODE_Insert; +- rc = shell_exec(p->db, sSelect.z, shell_callback, p, 0); ++ rc = shell_exec(p, sSelect.z, 0); + if( (rc&0xff)==SQLITE_CORRUPT ){ + raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n"); + toggleSelectOrder(p->db); +- shell_exec(p->db, sSelect.z, shell_callback, p, 0); ++ shell_exec(p, sSelect.z, 0); + toggleSelectOrder(p->db); + } + p->zDestTable = savedDestTable; +@@ -4026,124 +10884,239 @@ + } + + /* +-** Text of a help message ++** Text of help messages. ++** ++** The help text for each individual command begins with a line that starts ++** with ".". Subsequent lines are supplimental information. ++** ++** There must be two or more spaces between the end of the command and the ++** start of the description of what that command does. + */ +-static char zHelp[] = ++static const char *(azHelp[]) = { ++#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE) ++ ".archive ... Manage SQL archives", ++ " Each command must have exactly one of the following options:", ++ " -c, --create Create a new archive", ++ " -u, --update Update or add files to an existing archive", ++ " -t, --list List contents of archive", ++ " -x, --extract Extract files from archive", ++ " Optional arguments:", ++ " -v, --verbose Print each filename as it is processed", ++ " -f FILE, --file FILE Operate on archive FILE (default is current db)", ++ " -a FILE, --append FILE Operate on FILE opened using the apndvfs VFS", ++ " -C DIR, --directory DIR Change to directory DIR to read/extract files", ++ " -n, --dryrun Show the SQL that would have occurred", ++ " Examples:", ++ " .ar -cf archive.sar foo bar # Create archive.sar from files foo and bar", ++ " .ar -tf archive.sar # List members of archive.sar", ++ " .ar -xvf archive.sar # Verbosely extract files from archive.sar", ++ " See also:", ++ " http://sqlite.org/cli.html#sqlar_archive_support", ++#endif + #ifndef SQLITE_OMIT_AUTHORIZATION +- ".auth ON|OFF Show authorizer callbacks\n" ++ ".auth ON|OFF Show authorizer callbacks", + #endif +- ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n" +- ".bail on|off Stop after hitting an error. Default OFF\n" +- ".binary on|off Turn binary output on or off. Default OFF\n" +- ".cd DIRECTORY Change the working directory to DIRECTORY\n" +- ".changes on|off Show number of rows changed by SQL\n" +- ".check GLOB Fail if output since .testcase does not match\n" +- ".clone NEWDB Clone data into NEWDB from the existing database\n" +- ".databases List names and files of attached databases\n" +- ".dbinfo ?DB? Show status information about the database\n" +- ".dump ?TABLE? ... Dump the database in an SQL text format\n" +- " If TABLE specified, only dump tables matching\n" +- " LIKE pattern TABLE.\n" +- ".echo on|off Turn command echo on or off\n" +- ".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN\n" +- ".exit Exit this program\n" ++ ".backup ?DB? FILE Backup DB (default \"main\") to FILE", ++ " --append Use the appendvfs", ++ ".bail on|off Stop after hitting an error. Default OFF", ++ ".binary on|off Turn binary output on or off. Default OFF", ++ ".cd DIRECTORY Change the working directory to DIRECTORY", ++ ".changes on|off Show number of rows changed by SQL", ++ ".check GLOB Fail if output since .testcase does not match", ++ ".clone NEWDB Clone data into NEWDB from the existing database", ++ ".databases List names and files of attached databases", ++ ".dbconfig ?op? ?val? List or change sqlite3_db_config() options", ++ ".dbinfo ?DB? Show status information about the database", ++ ".dump ?TABLE? ... Render all database content as SQL", ++ " Options:", ++ " --preserve-rowids Include ROWID values in the output", ++ " --newlines Allow unescaped newline characters in output", ++ " TABLE is LIKE pattern for the tables to dump", ++ ".echo on|off Turn command echo on or off", ++ ".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN", ++ ".excel Display the output of next command in a spreadsheet", ++ ".exit ?CODE? Exit this program with return-code CODE", ++ ".expert EXPERIMENTAL. Suggest indexes for specified queries", + /* Because explain mode comes on automatically now, the ".explain" mode + ** is removed from the help screen. It is still supported for legacy, however */ +-/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic\n"*/ +- ".fullschema ?--indent? Show schema and the content of sqlite_stat tables\n" +- ".headers on|off Turn display of headers on or off\n" +- ".help Show this message\n" +- ".import FILE TABLE Import data from FILE into TABLE\n" ++/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic",*/ ++ ".fullschema ?--indent? Show schema and the content of sqlite_stat tables", ++ ".headers on|off Turn display of headers on or off", ++ ".help ?-all? ?PATTERN? Show help text for PATTERN", ++ ".import FILE TABLE Import data from FILE into TABLE", + #ifndef SQLITE_OMIT_TEST_CONTROL +- ".imposter INDEX TABLE Create imposter table TABLE on index INDEX\n" ++ ".imposter INDEX TABLE Create imposter table TABLE on index INDEX", + #endif +- ".indexes ?TABLE? Show names of all indexes\n" +- " If TABLE specified, only show indexes for tables\n" +- " matching LIKE pattern TABLE.\n" ++ ".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\n" ++ ".iotrace FILE Enable I/O diagnostic logging to FILE", + #endif +- ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT\n" +- ".lint OPTIONS Report potential schema issues. Options:\n" +- " fkey-indexes Find missing foreign key indexes\n" ++ ".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", + #ifndef SQLITE_OMIT_LOAD_EXTENSION +- ".load FILE ?ENTRY? Load an extension library\n" ++ ".load FILE ?ENTRY? Load an extension library", + #endif +- ".log FILE|off Turn logging on or off. FILE can be stderr/stdout\n" +- ".mode MODE ?TABLE? Set output mode where MODE is one of:\n" +- " ascii Columns/rows delimited by 0x1F and 0x1E\n" +- " csv Comma-separated values\n" +- " column Left-aligned columns. (See .width)\n" +- " html HTML <table> code\n" +- " insert SQL insert statements for TABLE\n" +- " line One value per line\n" +- " list Values delimited by \"|\"\n" +- " quote Escape answers as for SQL\n" +- " tabs Tab-separated values\n" +- " tcl TCL list elements\n" +- ".nullvalue STRING Use STRING in place of NULL values\n" +- ".once FILENAME Output for the next SQL command only to FILENAME\n" +- ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE\n" +- " The --new option starts with an empty file\n" +- ".output ?FILENAME? Send output to FILENAME or stdout\n" +- ".print STRING... Print literal STRING\n" +- ".prompt MAIN CONTINUE Replace the standard prompts\n" +- ".quit Exit this program\n" +- ".read FILENAME Execute SQL in FILENAME\n" +- ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n" +- ".save FILE Write in-memory database into FILE\n" +- ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off\n" +- ".schema ?PATTERN? Show the CREATE statements matching PATTERN\n" +- " Add --indent for pretty-printing\n" +- ".selftest ?--init? Run tests defined in the SELFTEST table\n" +- ".separator COL ?ROW? Change the column separator and optionally the row\n" +- " separator for both the output mode and .import\n" ++ ".log FILE|off Turn logging on or off. FILE can be stderr/stdout", ++ ".mode MODE ?TABLE? Set output mode", ++ " MODE is one of:", ++ " ascii Columns/rows delimited by 0x1F and 0x1E", ++ " csv Comma-separated values", ++ " column Left-aligned columns. (See .width)", ++ " html HTML <table> code", ++ " insert SQL insert statements for TABLE", ++ " line One value per line", ++ " list Values delimited by \"|\"", ++ " quote Escape answers as for SQL", ++ " tabs Tab-separated values", ++ " tcl TCL list elements", ++ ".nullvalue STRING Use STRING in place of NULL values", ++ ".once (-e|-x|FILE) Output for the next SQL command only to FILE", ++ " If FILE begins with '|' then open as a pipe", ++ " Other options:", ++ " -e Invoke system text editor", ++ " -x Open in a spreadsheet", ++ ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE", ++ " Options:", ++ " --append Use appendvfs to append database to the end of FILE", ++#ifdef SQLITE_ENABLE_DESERIALIZE ++ " --deserialize Load into memory useing sqlite3_deserialize()", ++#endif ++ " --new Initialize FILE to an empty database", ++ " --readonly Open FILE readonly", ++ " --zip FILE is a ZIP archive", ++ ".output ?FILE? Send output to FILE or stdout if FILE is omitted", ++ " If FILE begins with '|' then open it as a pipe.", ++ ".print STRING... Print literal STRING", ++ ".prompt MAIN CONTINUE Replace the standard prompts", ++ ".quit Exit this program", ++ ".read FILE Read input from FILE", ++ ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE", ++ ".save FILE Write in-memory database into FILE", ++ ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off", ++ ".schema ?PATTERN? Show the CREATE statements matching PATTERN", ++ " Options:", ++ " --indent Try to pretty-print the schema", ++ ".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 CMD ... Create or control sessions\n" ++ ".session ?NAME? CMD ... Create or control sessions", ++ " Subcommands:", ++ " attach TABLE Attach TABLE", ++ " changeset FILE Write a changeset into FILE", ++ " close Close one session", ++ " enable ?BOOLEAN? Set or query the enable bit", ++ " filter GLOB... Reject tables matching GLOBs", ++ " indirect ?BOOLEAN? Mark or query the indirect status", ++ " isempty Query whether the session is empty", ++ " list List currently open session names", ++ " open DB NAME Open a new session on DB", ++ " patchset FILE Write a patchset into FILE", ++ " If ?NAME? is omitted, the first defined session is used.", + #endif +- ".sha3sum ?OPTIONS...? Compute a SHA3 hash of database content\n" +- ".shell CMD ARGS... Run CMD ARGS... in a system shell\n" +- ".show Show the current values for various settings\n" +- ".stats ?on|off? Show stats or turn stats on or off\n" +- ".system CMD ARGS... Run CMD ARGS... in a system shell\n" +- ".tables ?TABLE? List names of tables\n" +- " If TABLE specified, only list tables matching\n" +- " LIKE pattern TABLE.\n" +- ".testcase NAME Begin redirecting output to 'testcase-out.txt'\n" +- ".timeout MS Try opening locked tables for MS milliseconds\n" +- ".timer on|off Turn SQL timer on or off\n" +- ".trace FILE|off Output each SQL statement as it is run\n" +- ".vfsinfo ?AUX? Information about the top-level VFS\n" +- ".vfslist List all available VFSes\n" +- ".vfsname ?AUX? Print the name of the VFS stack\n" +- ".width NUM1 NUM2 ... Set column widths for \"column\" mode\n" +- " Negative values right-justify\n" +-; ++ ".sha3sum ... Compute a SHA3 hash of database content", ++ " Options:", ++ " --schema Also hash the sqlite_master table", ++ " --sha3-224 Use the sha3-224 algorithm", ++ " --sha3-256 Use the sha3-256 algorithm. This is the default.", ++ " --sha3-384 Use the sha3-384 algorithm", ++ " --sha3-512 Use the sha3-512 algorithm", ++ " Any other argument is a LIKE pattern for tables to hash", ++#ifndef SQLITE_NOHAVE_SYSTEM ++ ".shell CMD ARGS... Run CMD ARGS... in a system shell", ++#endif ++ ".show Show the current values for various settings", ++ ".stats ?on|off? Show stats or turn stats on or off", ++#ifndef SQLITE_NOHAVE_SYSTEM ++ ".system CMD ARGS... Run CMD ARGS... in a system shell", ++#endif ++ ".tables ?TABLE? List names of tables matching LIKE pattern TABLE", ++ ".testcase NAME Begin redirecting output to 'testcase-out.txt'", ++ ".timeout MS Try opening locked tables for MS milliseconds", ++ ".timer on|off Turn SQL timer on or off", ++ ".trace FILE|off Output each SQL statement as it is run", ++ ".vfsinfo ?AUX? Information about the top-level VFS", ++ ".vfslist List all available VFSes", ++ ".vfsname ?AUX? Print the name of the VFS stack", ++ ".width NUM1 NUM2 ... Set column widths for \"column\" mode", ++ " Negative values right-justify", ++}; + +-#if defined(SQLITE_ENABLE_SESSION) + /* +-** Print help information for the ".sessions" command ++** Output help text. ++** ++** zPattern describes the set of commands for which help text is provided. ++** If zPattern is NULL, then show all commands, but only give a one-line ++** description of each. ++** ++** Return the number of matches. + */ +-void session_help(ShellState *p){ +- raw_printf(p->out, +- ".session ?NAME? SUBCOMMAND ?ARGS...?\n" +- "If ?NAME? is omitted, the first defined session is used.\n" +- "Subcommands:\n" +- " attach TABLE Attach TABLE\n" +- " changeset FILE Write a changeset into FILE\n" +- " close Close one session\n" +- " enable ?BOOLEAN? Set or query the enable bit\n" +- " filter GLOB... Reject tables matching GLOBs\n" +- " indirect ?BOOLEAN? Mark or query the indirect status\n" +- " isempty Query whether the session is empty\n" +- " list List currently open session names\n" +- " open DB NAME Open a new session on DB\n" +- " patchset FILE Write a patchset into FILE\n" +- ); ++static int showHelp(FILE *out, const char *zPattern){ ++ int i = 0; ++ int j = 0; ++ int n = 0; ++ char *zPat; ++ if( zPattern==0 ++ || zPattern[0]=='0' ++ || strcmp(zPattern,"-a")==0 ++ || 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); ++ 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); ++ 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++; ++ } ++ } ++ sqlite3_free(zPat); ++ } ++ return n; + } +-#endif + +- + /* Forward reference */ + static int process_input(ShellState *p, FILE *in); + +@@ -4172,7 +11145,7 @@ + nIn = ftell(in); + rewind(in); + pBuf = sqlite3_malloc64( nIn+1 ); +- if( pBuf==0 ) return 0; ++ if( pBuf==0 ){ fclose(in); return 0; } + nRead = fread(pBuf, nIn, 1, in); + fclose(in); + if( nRead!=1 ){ +@@ -4232,18 +11205,105 @@ + #endif + + /* ++** Try to deduce the type of file for zName based on its content. Return ++** one of the SHELL_OPEN_* constants. ++** ++** If the file does not exist or is empty but its name looks like a ZIP ++** archive and the dfltZip flag is true, then assume it is a ZIP archive. ++** Otherwise, assume an ordinary database regardless of the filename if ++** the type cannot be determined from content. ++*/ ++int deduceDatabaseType(const char *zName, int dfltZip){ ++ FILE *f = fopen(zName, "rb"); ++ size_t n; ++ int rc = SHELL_OPEN_UNSPEC; ++ char zBuf[100]; ++ if( f==0 ){ ++ if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){ ++ return SHELL_OPEN_ZIPFILE; ++ }else{ ++ return SHELL_OPEN_NORMAL; ++ } ++ } ++ n = fread(zBuf, 16, 1, f); ++ if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){ ++ fclose(f); ++ return SHELL_OPEN_NORMAL; ++ } ++ fseek(f, -25, SEEK_END); ++ n = fread(zBuf, 25, 1, f); ++ if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){ ++ rc = SHELL_OPEN_APPENDVFS; ++ }else{ ++ fseek(f, -22, SEEK_END); ++ n = fread(zBuf, 22, 1, f); ++ if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05 ++ && zBuf[3]==0x06 ){ ++ rc = SHELL_OPEN_ZIPFILE; ++ }else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){ ++ rc = SHELL_OPEN_ZIPFILE; ++ } ++ } ++ fclose(f); ++ return rc; ++} ++ ++/* 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. ++** ++** The OPEN_DB_ZIPFILE flag causes open_db() to prefer to open files as a ++** ZIP archive if the file does not exist or is empty and its name matches ++** the *.zip pattern. ++*/ ++#define OPEN_DB_KEEPALIVE 0x001 /* Return after error if true */ ++#define OPEN_DB_ZIPFILE 0x002 /* Open as ZIP if name matches *.zip */ ++ ++/* + ** Make sure the database is open. If it is not, then open it. If + ** the database fails to open, print an error message and exit. + */ +-static void open_db(ShellState *p, int keepAlive){ ++static void open_db(ShellState *p, int openFlags){ + if( p->db==0 ){ +- sqlite3_initialize(); +- sqlite3_open(p->zDbFilename, &p->db); ++ if( p->openMode==SHELL_OPEN_UNSPEC ){ ++ if( p->zDbFilename==0 || p->zDbFilename[0]==0 ){ ++ p->openMode = SHELL_OPEN_NORMAL; ++ }else{ ++ p->openMode = (u8)deduceDatabaseType(p->zDbFilename, ++ (openFlags & OPEN_DB_ZIPFILE)!=0); ++ } ++ } ++ switch( p->openMode ){ ++ case SHELL_OPEN_APPENDVFS: { ++ sqlite3_open_v2(p->zDbFilename, &p->db, ++ SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, "apndvfs"); ++ break; ++ } ++ case SHELL_OPEN_DESERIALIZE: { ++ sqlite3_open(0, &p->db); ++ break; ++ } ++ case SHELL_OPEN_ZIPFILE: { ++ sqlite3_open(":memory:", &p->db); ++ break; ++ } ++ case SHELL_OPEN_READONLY: { ++ sqlite3_open_v2(p->zDbFilename, &p->db, SQLITE_OPEN_READONLY, 0); ++ break; ++ } ++ case SHELL_OPEN_UNSPEC: ++ case SHELL_OPEN_NORMAL: { ++ sqlite3_open(p->zDbFilename, &p->db); ++ break; ++ } ++ } + globalDb = p->db; + if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){ + utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n", + p->zDbFilename, sqlite3_errmsg(p->db)); +- if( keepAlive ) return; ++ if( openFlags & OPEN_DB_KEEPALIVE ) return; + exit(1); + } + #ifndef SQLITE_OMIT_LOAD_EXTENSION +@@ -4252,11 +11312,54 @@ + sqlite3_fileio_init(p->db, 0, 0); + sqlite3_shathree_init(p->db, 0, 0); + sqlite3_completion_init(p->db, 0, 0); +- sqlite3_create_function(p->db, "shell_add_schema", 2, SQLITE_UTF8, 0, ++#ifdef SQLITE_HAVE_ZLIB ++ sqlite3_zipfile_init(p->db, 0, 0); ++ sqlite3_sqlar_init(p->db, 0, 0); ++#endif ++ 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); ++#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); ++#endif ++ if( p->openMode==SHELL_OPEN_ZIPFILE ){ ++ char *zSql = sqlite3_mprintf( ++ "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename); ++ sqlite3_exec(p->db, zSql, 0, 0, 0); ++ sqlite3_free(zSql); ++ } ++#ifdef SQLITE_ENABLE_DESERIALIZE ++ else if( p->openMode==SHELL_OPEN_DESERIALIZE ){ ++ int nData = 0; ++ unsigned char *aData = (unsigned char*)readFile(p->zDbFilename, &nData); ++ int 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); ++ } ++ } ++#endif + } + } + ++/* ++** Attempt to close the databaes connection. Report errors. ++*/ ++void close_db(sqlite3 *db){ ++ int rc = sqlite3_close(db); ++ if( rc ){ ++ utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n", ++ rc, sqlite3_errmsg(db)); ++ } ++} ++ + #if HAVE_READLINE || HAVE_EDITLINE + /* + ** Readline completion callbacks +@@ -4291,7 +11394,7 @@ + ** Linenoise completion callback + */ + static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){ +- int nLine = (int)strlen(zLine); ++ int nLine = strlen30(zLine); + int i, iStart; + sqlite3_stmt *pStmt = 0; + char *zSql; +@@ -4298,7 +11401,7 @@ + char zBuf[1000]; + + if( nLine>sizeof(zBuf)-30 ) return; +- if( zLine[0]=='.' ) 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; +@@ -4382,63 +11485,6 @@ + } + + /* +-** Return the value of a hexadecimal digit. Return -1 if the input +-** is not a hex digit. +-*/ +-static int hexDigitValue(char c){ +- if( c>='0' && c<='9' ) return c - '0'; +- if( c>='a' && c<='f' ) return c - 'a' + 10; +- if( c>='A' && c<='F' ) return c - 'A' + 10; +- return -1; +-} +- +-/* +-** Interpret zArg as an integer value, possibly with suffixes. +-*/ +-static sqlite3_int64 integerValue(const char *zArg){ +- sqlite3_int64 v = 0; +- static const struct { char *zSuffix; int iMult; } aMult[] = { +- { "KiB", 1024 }, +- { "MiB", 1024*1024 }, +- { "GiB", 1024*1024*1024 }, +- { "KB", 1000 }, +- { "MB", 1000000 }, +- { "GB", 1000000000 }, +- { "K", 1000 }, +- { "M", 1000000 }, +- { "G", 1000000000 }, +- }; +- int i; +- int isNeg = 0; +- if( zArg[0]=='-' ){ +- isNeg = 1; +- zArg++; +- }else if( zArg[0]=='+' ){ +- zArg++; +- } +- if( zArg[0]=='0' && zArg[1]=='x' ){ +- int x; +- zArg += 2; +- while( (x = hexDigitValue(zArg[0]))>=0 ){ +- v = (v<<4) + x; +- zArg++; +- } +- }else{ +- while( IsDigit(zArg[0]) ){ +- v = v*10 + zArg[0] - '0'; +- zArg++; +- } +- } +- for(i=0; i<ArraySize(aMult); i++){ +- if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){ +- v *= aMult[i].iMult; +- break; +- } +- } +- return isNeg? -v : v; +-} +- +-/* + ** Interpret zArg as either an integer or a boolean value. Return 1 or 0 + ** for TRUE and FALSE. Return the integer value if appropriate. + */ +@@ -4484,7 +11530,7 @@ + ** recognized and do the right thing. NULL is returned if the output + ** filename is "off". + */ +-static FILE *output_file_open(const char *zFile){ ++static FILE *output_file_open(const char *zFile, int bTextMode){ + FILE *f; + if( strcmp(zFile,"stdout")==0 ){ + f = stdout; +@@ -4493,7 +11539,7 @@ + }else if( strcmp(zFile, "off")==0 ){ + f = 0; + }else{ +- f = fopen(zFile, "wb"); ++ f = fopen(zFile, bTextMode ? "w" : "wb"); + if( f==0 ){ + utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile); + } +@@ -4501,7 +11547,6 @@ + return f; + } + +-#if !defined(SQLITE_UNTESTABLE) + #if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) + /* + ** A routine for handling output from sqlite3_trace(). +@@ -4517,7 +11562,7 @@ + UNUSED_PARAMETER(pP); + if( f ){ + const char *z = (const char*)pX; +- int i = (int)strlen(z); ++ int i = strlen30(z); + while( i>0 && z[i-1]==';' ){ i--; } + utf8_printf(f, "%.*s;\n", i, z); + } +@@ -4524,7 +11569,6 @@ + return 0; + } + #endif +-#endif + + /* + ** A no-op routine that runs with the ".breakpoint" doc-command. This is +@@ -4557,10 +11601,7 @@ + if( p->n+1>=p->nAlloc ){ + p->nAlloc += p->nAlloc + 100; + p->z = sqlite3_realloc64(p->z, p->nAlloc); +- if( p->z==0 ){ +- raw_printf(stderr, "out of memory\n"); +- exit(1); +- } ++ if( p->z==0 ) shell_out_of_memory(); + } + p->z[p->n++] = (char)c; + } +@@ -4706,7 +11747,7 @@ + char *zInsert = 0; + int rc; + int i, j, n; +- int nTable = (int)strlen(zTable); ++ int nTable = strlen30(zTable); + int k = 0; + int cnt = 0; + const int spinRate = 10000; +@@ -4721,13 +11762,10 @@ + } + n = sqlite3_column_count(pQuery); + zInsert = sqlite3_malloc64(200 + nTable + n*3); +- if( zInsert==0 ){ +- raw_printf(stderr, "out of memory\n"); +- goto end_data_xfer; +- } ++ if( zInsert==0 ) shell_out_of_memory(); + sqlite3_snprintf(200+nTable,zInsert, + "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable); +- i = (int)strlen(zInsert); ++ i = strlen30(zInsert); + for(j=1; j<n; j++){ + memcpy(zInsert+i, ",?", 2); + i += 2; +@@ -4902,11 +11940,15 @@ + sqlite3_exec(newDb, "COMMIT;", 0, 0, 0); + sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0); + } +- sqlite3_close(newDb); ++ close_db(newDb); + } + + /* +-** Change the output file back to stdout ++** Change the output file back to stdout. ++** ++** If the p->doXdgOpen flag is set, that means the output was being ++** redirected to a temporary file named by p->zTempFile. In that case, ++** launch start/open/xdg-open on that temporary file. + */ + static void output_reset(ShellState *p){ + if( p->outfile[0]=='|' ){ +@@ -4915,6 +11957,26 @@ + #endif + }else{ + output_file_close(p->out); ++#ifndef SQLITE_NOHAVE_SYSTEM ++ if( p->doXdgOpen ){ ++ const char *zXdgOpenCmd = ++#if defined(_WIN32) ++ "start"; ++#elif defined(__APPLE__) ++ "open"; ++#else ++ "xdg-open"; ++#endif ++ char *zCmd; ++ zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile); ++ if( system(zCmd) ){ ++ utf8_printf(stderr, "Failed: [%s]\n", zCmd); ++ } ++ sqlite3_free(zCmd); ++ outputModePop(p); ++ p->doXdgOpen = 0; ++ } ++#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */ + } + p->outfile[0] = 0; + p->out = stdout; +@@ -4976,20 +12038,25 @@ + { "schema size:", + "SELECT total(length(sql)) FROM %s" }, + }; +- sqlite3_file *pFile = 0; + int i; ++ unsigned iDataVersion; + char *zSchemaTab; + char *zDb = nArg>=2 ? azArg[1] : "main"; ++ sqlite3_stmt *pStmt = 0; + unsigned char aHdr[100]; + open_db(p, 0); + if( p->db==0 ) return 1; +- sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_FILE_POINTER, &pFile); +- if( pFile==0 || pFile->pMethods==0 || pFile->pMethods->xRead==0 ){ +- return 1; +- } +- i = pFile->pMethods->xRead(pFile, aHdr, 100, 0); +- if( i!=SQLITE_OK ){ ++ sqlite3_prepare_v2(p->db,"SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1", ++ -1, &pStmt, 0); ++ 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); +@@ -5025,6 +12092,8 @@ + utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val); + } + sqlite3_free(zSchemaTab); ++ sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion); ++ utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion); + return 0; + } + +@@ -5038,14 +12107,6 @@ + } + + /* +-** Print an out-of-memory message to stderr and return 1. +-*/ +-static int shellNomemError(void){ +- raw_printf(stderr, "Error: out of memory\n"); +- return 1; +-} +- +-/* + ** Compare the pattern in zGlob[] against the text in z[]. Return TRUE + ** if they match and FALSE (0) if they do not match. + ** +@@ -5169,8 +12230,43 @@ + return rc; + } + ++/* ++** Try to delete the temporary file (if there is one) and free the ++** memory used to hold the name of the temp file. ++*/ ++static void clearTempFile(ShellState *p){ ++ if( p->zTempFile==0 ) return; ++ if( p->doXdgOpen ) return; ++ if( shellDeleteFile(p->zTempFile) ) return; ++ sqlite3_free(p->zTempFile); ++ p->zTempFile = 0; ++} + + /* ++** Create a new temp file name with the given suffix. ++*/ ++static void newTempFile(ShellState *p, const char *zSuffix){ ++ clearTempFile(p); ++ sqlite3_free(p->zTempFile); ++ p->zTempFile = 0; ++ if( p->db ){ ++ sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile); ++ } ++ if( p->zTempFile==0 ){ ++ sqlite3_uint64 r; ++ sqlite3_randomness(sizeof(r), &r); ++ p->zTempFile = sqlite3_mprintf("temp%llx.%s", r, zSuffix); ++ }else{ ++ p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix); ++ } ++ if( p->zTempFile==0 ){ ++ raw_printf(stderr, "out of memory\n"); ++ exit(1); ++ } ++} ++ ++ ++/* + ** The implementation of SQL scalar function fkey_collate_clause(), used + ** by the ".lint fkey-indexes" command. This scalar function is always + ** called with four arguments - the parent table name, the parent column name, +@@ -5246,10 +12342,10 @@ + ** + ** 0. The text of an SQL statement similar to: + ** +- ** "EXPLAIN QUERY PLAN SELECT rowid FROM child_table WHERE child_key=?" ++ ** "EXPLAIN QUERY PLAN SELECT 1 FROM child_table WHERE child_key=?" + ** +- ** This is the same SELECT that the foreign keys implementation needs +- ** to run internally on child tables. If there is an index that can ++ ** This SELECT is similar to the one that the foreign keys implementation ++ ** needs to run internally on child tables. If there is an index that can + ** be used to optimize this query, then it can also be used by the FK + ** implementation to optimize DELETE or UPDATE statements on the parent + ** table. +@@ -5277,7 +12373,7 @@ + */ + const char *zSql = + "SELECT " +- " 'EXPLAIN QUERY PLAN SELECT rowid FROM ' || quote(s.name) || ' WHERE '" ++ " 'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '" + " || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' " + " || fkey_collate_clause(" + " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')" +@@ -5305,7 +12401,7 @@ + const char *zGlobIPK = "SEARCH TABLE * USING INTEGER PRIMARY KEY (rowid=?)"; + + for(i=2; i<nArg; i++){ +- int n = (int)strlen(azArg[i]); ++ int n = strlen30(azArg[i]); + if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){ + bVerbose = 1; + } +@@ -5408,7 +12504,7 @@ + int nArg /* Number of entries in azArg[] */ + ){ + int n; +- n = (nArg>=2 ? (int)strlen(azArg[1]) : 0); ++ n = (nArg>=2 ? strlen30(azArg[1]) : 0); + if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage; + return lintFkeyIndexes(pState, azArg, nArg); + +@@ -5419,8 +12515,741 @@ + return SQLITE_ERROR; + } + ++#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) ++/********************************************************************************* ++** The ".archive" or ".ar" command. ++*/ ++static void shellPrepare( ++ sqlite3 *db, ++ int *pRc, ++ const char *zSql, ++ sqlite3_stmt **ppStmt ++){ ++ *ppStmt = 0; ++ if( *pRc==SQLITE_OK ){ ++ int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0); ++ if( rc!=SQLITE_OK ){ ++ raw_printf(stderr, "sql error: %s (%d)\n", ++ sqlite3_errmsg(db), sqlite3_errcode(db) ++ ); ++ *pRc = rc; ++ } ++ } ++} + ++static void shellPreparePrintf( ++ sqlite3 *db, ++ int *pRc, ++ sqlite3_stmt **ppStmt, ++ const char *zFmt, ++ ... ++){ ++ *ppStmt = 0; ++ if( *pRc==SQLITE_OK ){ ++ va_list ap; ++ char *z; ++ va_start(ap, zFmt); ++ z = sqlite3_vmprintf(zFmt, ap); ++ va_end(ap); ++ if( z==0 ){ ++ *pRc = SQLITE_NOMEM; ++ }else{ ++ shellPrepare(db, pRc, z, ppStmt); ++ sqlite3_free(z); ++ } ++ } ++} ++ ++static void shellFinalize( ++ int *pRc, ++ sqlite3_stmt *pStmt ++){ ++ if( pStmt ){ ++ sqlite3 *db = sqlite3_db_handle(pStmt); ++ int rc = sqlite3_finalize(pStmt); ++ if( *pRc==SQLITE_OK ){ ++ if( rc!=SQLITE_OK ){ ++ raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db)); ++ } ++ *pRc = rc; ++ } ++ } ++} ++ ++static void shellReset( ++ int *pRc, ++ sqlite3_stmt *pStmt ++){ ++ int rc = sqlite3_reset(pStmt); ++ if( *pRc==SQLITE_OK ){ ++ if( rc!=SQLITE_OK ){ ++ sqlite3 *db = sqlite3_db_handle(pStmt); ++ raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db)); ++ } ++ *pRc = rc; ++ } ++} + /* ++** Structure representing a single ".ar" command. ++*/ ++typedef struct ArCommand ArCommand; ++struct ArCommand { ++ u8 eCmd; /* An AR_CMD_* value */ ++ u8 bVerbose; /* True if --verbose */ ++ u8 bZip; /* True if the archive is a ZIP */ ++ u8 bDryRun; /* True if --dry-run */ ++ u8 bAppend; /* True if --append */ ++ u8 fromCmdLine; /* Run from -A instead of .archive */ ++ int nArg; /* Number of command arguments */ ++ char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */ ++ const char *zFile; /* --file argument, or NULL */ ++ const char *zDir; /* --directory argument, or NULL */ ++ char **azArg; /* Array of command arguments */ ++ ShellState *p; /* Shell state */ ++ sqlite3 *db; /* Database containing the archive */ ++}; ++ ++/* ++** Print a usage message for the .ar command to stderr and return SQLITE_ERROR. ++*/ ++static int arUsage(FILE *f){ ++ showHelp(f,"archive"); ++ return SQLITE_ERROR; ++} ++ ++/* ++** Print an error message for the .ar command to stderr and return ++** SQLITE_ERROR. ++*/ ++static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){ ++ va_list ap; ++ char *z; ++ va_start(ap, zFmt); ++ z = sqlite3_vmprintf(zFmt, ap); ++ va_end(ap); ++ utf8_printf(stderr, "Error: %s\n", z); ++ if( pAr->fromCmdLine ){ ++ utf8_printf(stderr, "Use \"-A\" for more help\n"); ++ }else{ ++ utf8_printf(stderr, "Use \".archive --help\" for more help\n"); ++ } ++ sqlite3_free(z); ++ return SQLITE_ERROR; ++} ++ ++/* ++** Values for ArCommand.eCmd. ++*/ ++#define AR_CMD_CREATE 1 ++#define AR_CMD_EXTRACT 2 ++#define AR_CMD_LIST 3 ++#define AR_CMD_UPDATE 4 ++#define AR_CMD_HELP 5 ++ ++/* ++** Other (non-command) switches. ++*/ ++#define AR_SWITCH_VERBOSE 6 ++#define AR_SWITCH_FILE 7 ++#define AR_SWITCH_DIRECTORY 8 ++#define AR_SWITCH_APPEND 9 ++#define AR_SWITCH_DRYRUN 10 ++ ++static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){ ++ switch( eSwitch ){ ++ case AR_CMD_CREATE: ++ case AR_CMD_EXTRACT: ++ case AR_CMD_LIST: ++ case AR_CMD_UPDATE: ++ case AR_CMD_HELP: ++ if( pAr->eCmd ){ ++ return arErrorMsg(pAr, "multiple command options"); ++ } ++ pAr->eCmd = eSwitch; ++ break; ++ ++ case AR_SWITCH_DRYRUN: ++ pAr->bDryRun = 1; ++ break; ++ case AR_SWITCH_VERBOSE: ++ pAr->bVerbose = 1; ++ break; ++ case AR_SWITCH_APPEND: ++ pAr->bAppend = 1; ++ /* Fall thru into --file */ ++ case AR_SWITCH_FILE: ++ pAr->zFile = zArg; ++ break; ++ case AR_SWITCH_DIRECTORY: ++ pAr->zDir = zArg; ++ break; ++ } ++ ++ return SQLITE_OK; ++} ++ ++/* ++** Parse the command line for an ".ar" command. The results are written into ++** structure (*pAr). SQLITE_OK is returned if the command line is parsed ++** successfully, otherwise an error message is written to stderr and ++** SQLITE_ERROR returned. ++*/ ++static int arParseCommand( ++ char **azArg, /* Array of arguments passed to dot command */ ++ int nArg, /* Number of entries in azArg[] */ ++ ArCommand *pAr /* Populate this object */ ++){ ++ struct ArSwitch { ++ const char *zLong; ++ char cShort; ++ u8 eSwitch; ++ u8 bArg; ++ } aSwitch[] = { ++ { "create", 'c', AR_CMD_CREATE, 0 }, ++ { "extract", 'x', AR_CMD_EXTRACT, 0 }, ++ { "list", 't', AR_CMD_LIST, 0 }, ++ { "update", 'u', AR_CMD_UPDATE, 0 }, ++ { "help", 'h', AR_CMD_HELP, 0 }, ++ { "verbose", 'v', AR_SWITCH_VERBOSE, 0 }, ++ { "file", 'f', AR_SWITCH_FILE, 1 }, ++ { "append", 'a', AR_SWITCH_APPEND, 1 }, ++ { "directory", 'C', AR_SWITCH_DIRECTORY, 1 }, ++ { "dryrun", 'n', AR_SWITCH_DRYRUN, 0 }, ++ }; ++ int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch); ++ struct ArSwitch *pEnd = &aSwitch[nSwitch]; ++ ++ if( nArg<=1 ){ ++ utf8_printf(stderr, "Wrong number of arguments. Usage:\n"); ++ return arUsage(stderr); ++ }else{ ++ char *z = azArg[1]; ++ if( z[0]!='-' ){ ++ /* Traditional style [tar] invocation */ ++ int i; ++ int iArg = 2; ++ for(i=0; z[i]; i++){ ++ const char *zArg = 0; ++ struct ArSwitch *pOpt; ++ for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){ ++ if( z[i]==pOpt->cShort ) break; ++ } ++ if( pOpt==pEnd ){ ++ return arErrorMsg(pAr, "unrecognized option: %c", z[i]); ++ } ++ if( pOpt->bArg ){ ++ if( iArg>=nArg ){ ++ return arErrorMsg(pAr, "option requires an argument: %c",z[i]); ++ } ++ zArg = azArg[iArg++]; ++ } ++ if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR; ++ } ++ pAr->nArg = nArg-iArg; ++ if( pAr->nArg>0 ){ ++ pAr->azArg = &azArg[iArg]; ++ } ++ }else{ ++ /* Non-traditional invocation */ ++ int iArg; ++ for(iArg=1; iArg<nArg; iArg++){ ++ int n; ++ z = azArg[iArg]; ++ if( z[0]!='-' ){ ++ /* All remaining command line words are command arguments. */ ++ pAr->azArg = &azArg[iArg]; ++ pAr->nArg = nArg-iArg; ++ break; ++ } ++ n = strlen30(z); ++ ++ if( z[1]!='-' ){ ++ int i; ++ /* One or more short options */ ++ for(i=1; i<n; i++){ ++ const char *zArg = 0; ++ struct ArSwitch *pOpt; ++ for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){ ++ if( z[i]==pOpt->cShort ) break; ++ } ++ if( pOpt==pEnd ){ ++ return arErrorMsg(pAr, "unrecognized option: %c", z[i]); ++ } ++ if( pOpt->bArg ){ ++ if( i<(n-1) ){ ++ zArg = &z[i+1]; ++ i = n; ++ }else{ ++ if( iArg>=(nArg-1) ){ ++ return arErrorMsg(pAr, "option requires an argument: %c",z[i]); ++ } ++ zArg = azArg[++iArg]; ++ } ++ } ++ if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR; ++ } ++ }else if( z[2]=='\0' ){ ++ /* A -- option, indicating that all remaining command line words ++ ** are command arguments. */ ++ pAr->azArg = &azArg[iArg+1]; ++ pAr->nArg = nArg-iArg-1; ++ break; ++ }else{ ++ /* A long option */ ++ const char *zArg = 0; /* Argument for option, if any */ ++ struct ArSwitch *pMatch = 0; /* Matching option */ ++ struct ArSwitch *pOpt; /* Iterator */ ++ for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){ ++ const char *zLong = pOpt->zLong; ++ if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){ ++ if( pMatch ){ ++ return arErrorMsg(pAr, "ambiguous option: %s",z); ++ }else{ ++ pMatch = pOpt; ++ } ++ } ++ } ++ ++ if( pMatch==0 ){ ++ return arErrorMsg(pAr, "unrecognized option: %s", z); ++ } ++ if( pMatch->bArg ){ ++ if( iArg>=(nArg-1) ){ ++ return arErrorMsg(pAr, "option requires an argument: %s", z); ++ } ++ 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 or --list commands. ++** It checks that each of them are present. If any specified file is not ++** present in the archive, an error is printed to stderr and an error ++** code returned. Otherwise, if all specified arguments are present in ++** the archive, SQLITE_OK is returned. ++** ++** This function strips any trailing '/' characters from each argument. ++** This is consistent with the way the [tar] command seems to work on ++** Linux. ++*/ ++static int arCheckEntries(ArCommand *pAr){ ++ int rc = SQLITE_OK; ++ if( pAr->nArg ){ ++ int i, j; ++ sqlite3_stmt *pTest = 0; ++ ++ shellPreparePrintf(pAr->db, &rc, &pTest, ++ "SELECT name FROM %s WHERE name=$name", ++ pAr->zSrcTable ++ ); ++ j = sqlite3_bind_parameter_index(pTest, "$name"); ++ for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){ ++ char *z = pAr->azArg[i]; ++ int n = strlen30(z); ++ int bOk = 0; ++ while( n>0 && z[n-1]=='/' ) n--; ++ z[n] = '\0'; ++ sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC); ++ if( SQLITE_ROW==sqlite3_step(pTest) ){ ++ bOk = 1; ++ } ++ shellReset(&rc, pTest); ++ if( rc==SQLITE_OK && bOk==0 ){ ++ utf8_printf(stderr, "not found in archive: %s\n", z); ++ rc = SQLITE_ERROR; ++ } ++ } ++ shellFinalize(&rc, pTest); ++ } ++ return rc; ++} ++ ++/* ++** Format a WHERE clause that can be used against the "sqlar" table to ++** identify all archive members that match the command arguments held ++** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning. ++** The caller is responsible for eventually calling sqlite3_free() on ++** any non-NULL (*pzWhere) value. ++*/ ++static void arWhereClause( ++ int *pRc, ++ ArCommand *pAr, ++ char **pzWhere /* OUT: New WHERE clause */ ++){ ++ char *zWhere = 0; ++ if( *pRc==SQLITE_OK ){ ++ if( pAr->nArg==0 ){ ++ zWhere = sqlite3_mprintf("1"); ++ }else{ ++ int i; ++ const char *zSep = ""; ++ for(i=0; i<pAr->nArg; i++){ ++ const char *z = pAr->azArg[i]; ++ zWhere = sqlite3_mprintf( ++ "%z%s name = '%q' OR substr(name,1,%d) = '%q/'", ++ zWhere, zSep, z, strlen30(z)+1, z ++ ); ++ if( zWhere==0 ){ ++ *pRc = SQLITE_NOMEM; ++ break; ++ } ++ zSep = " OR "; ++ } ++ } ++ } ++ *pzWhere = zWhere; ++} ++ ++/* ++** Implementation of .ar "lisT" command. ++*/ ++static int arListCommand(ArCommand *pAr){ ++ const char *zSql = "SELECT %s FROM %s WHERE %s"; ++ const char *azCols[] = { ++ "name", ++ "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name" ++ }; ++ ++ char *zWhere = 0; ++ sqlite3_stmt *pSql = 0; ++ int rc; ++ ++ rc = arCheckEntries(pAr); ++ arWhereClause(&rc, pAr, &zWhere); ++ ++ shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose], ++ pAr->zSrcTable, zWhere); ++ if( pAr->bDryRun ){ ++ utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql)); ++ }else{ ++ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ ++ if( pAr->bVerbose ){ ++ utf8_printf(pAr->p->out, "%s % 10d %s %s\n", ++ sqlite3_column_text(pSql, 0), ++ sqlite3_column_int(pSql, 1), ++ sqlite3_column_text(pSql, 2), ++ sqlite3_column_text(pSql, 3) ++ ); ++ }else{ ++ utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0)); ++ } ++ } ++ } ++ shellFinalize(&rc, pSql); ++ sqlite3_free(zWhere); ++ return rc; ++} ++ ++ ++/* ++** Implementation of .ar "eXtract" command. ++*/ ++static int arExtractCommand(ArCommand *pAr){ ++ const char *zSql1 = ++ "SELECT " ++ " ($dir || name)," ++ " writefile(($dir || name), %s, mode, mtime) " ++ "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)" ++ " AND name NOT GLOB '*..[/\\]*'"; ++ ++ const char *azExtraArg[] = { ++ "sqlar_uncompress(data, sz)", ++ "data" ++ }; ++ ++ sqlite3_stmt *pSql = 0; ++ int rc = SQLITE_OK; ++ char *zDir = 0; ++ char *zWhere = 0; ++ int i, j; ++ ++ /* If arguments are specified, check that they actually exist within ++ ** the archive before proceeding. And formulate a WHERE clause to ++ ** match them. */ ++ rc = arCheckEntries(pAr); ++ arWhereClause(&rc, pAr, &zWhere); ++ ++ if( rc==SQLITE_OK ){ ++ if( pAr->zDir ){ ++ zDir = sqlite3_mprintf("%s/", pAr->zDir); ++ }else{ ++ zDir = sqlite3_mprintf(""); ++ } ++ if( zDir==0 ) rc = SQLITE_NOMEM; ++ } ++ ++ shellPreparePrintf(pAr->db, &rc, &pSql, zSql1, ++ azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere ++ ); ++ ++ if( rc==SQLITE_OK ){ ++ j = sqlite3_bind_parameter_index(pSql, "$dir"); ++ sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC); ++ ++ /* Run the SELECT statement twice. The first time, writefile() is called ++ ** for all archive members that should be extracted. The second time, ++ ** only for the directories. This is because the timestamps for ++ ** extracted directories must be reset after they are populated (as ++ ** populating them changes the timestamp). */ ++ for(i=0; i<2; i++){ ++ j = sqlite3_bind_parameter_index(pSql, "$dirOnly"); ++ sqlite3_bind_int(pSql, j, i); ++ if( pAr->bDryRun ){ ++ utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql)); ++ }else{ ++ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ ++ if( i==0 && pAr->bVerbose ){ ++ utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0)); ++ } ++ } ++ } ++ shellReset(&rc, pSql); ++ } ++ shellFinalize(&rc, pSql); ++ } ++ ++ sqlite3_free(zDir); ++ sqlite3_free(zWhere); ++ return rc; ++} ++ ++/* ++** Run the SQL statement in zSql. Or if doing a --dryrun, merely print it out. ++*/ ++static int arExecSql(ArCommand *pAr, const char *zSql){ ++ int rc; ++ if( pAr->bDryRun ){ ++ utf8_printf(pAr->p->out, "%s\n", zSql); ++ rc = SQLITE_OK; ++ }else{ ++ char *zErr = 0; ++ rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr); ++ if( zErr ){ ++ utf8_printf(stdout, "ERROR: %s\n", zErr); ++ sqlite3_free(zErr); ++ } ++ } ++ return rc; ++} ++ ++ ++/* ++** Implementation of .ar "create" and "update" commands. ++** ++** Create the "sqlar" table in the database if it does not already exist. ++** Then add each file in the azFile[] array to the archive. Directories ++** are added recursively. If argument bVerbose is non-zero, a message is ++** printed on stdout for each file archived. ++** ++** The create command is the same as update, except that it drops ++** any existing "sqlar" table before beginning. ++*/ ++static int arCreateOrUpdateCommand( ++ ArCommand *pAr, /* Command arguments and options */ ++ int bUpdate /* true for a --create. false for --update */ ++){ ++ const char *zCreate = ++ "CREATE TABLE IF NOT EXISTS sqlar(\n" ++ " name TEXT PRIMARY KEY, -- name of the file\n" ++ " mode INT, -- access permissions\n" ++ " mtime INT, -- last modification time\n" ++ " sz INT, -- original file size\n" ++ " data BLOB -- compressed content\n" ++ ")"; ++ const char *zDrop = "DROP TABLE IF EXISTS sqlar"; ++ const char *zInsertFmt[2] = { ++ "REPLACE INTO %s(name,mode,mtime,sz,data)\n" ++ " SELECT\n" ++ " %s,\n" ++ " mode,\n" ++ " mtime,\n" ++ " CASE substr(lsmode(mode),1,1)\n" ++ " WHEN '-' THEN length(data)\n" ++ " WHEN 'd' THEN 0\n" ++ " ELSE -1 END,\n" ++ " sqlar_compress(data)\n" ++ " FROM fsdir(%Q,%Q)\n" ++ " WHERE lsmode(mode) NOT LIKE '?%%';", ++ "REPLACE INTO %s(name,mode,mtime,data)\n" ++ " SELECT\n" ++ " %s,\n" ++ " mode,\n" ++ " mtime,\n" ++ " data\n" ++ " FROM fsdir(%Q,%Q)\n" ++ " WHERE lsmode(mode) NOT LIKE '?%%';" ++ }; ++ int i; /* For iterating through azFile[] */ ++ int rc; /* Return code */ ++ const char *zTab = 0; /* SQL table into which to insert */ ++ char *zSql; ++ char zTemp[50]; ++ ++ arExecSql(pAr, "PRAGMA page_size=512"); ++ rc = arExecSql(pAr, "SAVEPOINT ar;"); ++ if( rc!=SQLITE_OK ) return rc; ++ zTemp[0] = 0; ++ if( pAr->bZip ){ ++ /* Initialize the zipfile virtual table, if necessary */ ++ if( pAr->zFile ){ ++ sqlite3_uint64 r; ++ sqlite3_randomness(sizeof(r),&r); ++ sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r); ++ zTab = zTemp; ++ zSql = sqlite3_mprintf( ++ "CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)", ++ zTab, pAr->zFile ++ ); ++ rc = arExecSql(pAr, zSql); ++ sqlite3_free(zSql); ++ }else{ ++ zTab = "zip"; ++ } ++ }else{ ++ /* Initialize the table for an SQLAR */ ++ zTab = "sqlar"; ++ if( bUpdate==0 ){ ++ rc = arExecSql(pAr, zDrop); ++ if( rc!=SQLITE_OK ) goto end_ar_transaction; ++ } ++ rc = arExecSql(pAr, zCreate); ++ } ++ for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){ ++ char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab, ++ pAr->bVerbose ? "shell_putsnl(name)" : "name", ++ pAr->azArg[i], pAr->zDir); ++ rc = arExecSql(pAr, zSql2); ++ sqlite3_free(zSql2); ++ } ++end_ar_transaction: ++ if( rc!=SQLITE_OK ){ ++ arExecSql(pAr, "ROLLBACK TO ar; RELEASE ar;"); ++ }else{ ++ rc = arExecSql(pAr, "RELEASE ar;"); ++ if( pAr->bZip && pAr->zFile ){ ++ zSql = sqlite3_mprintf("DROP TABLE %s", zTemp); ++ arExecSql(pAr, zSql); ++ sqlite3_free(zSql); ++ } ++ } ++ return rc; ++} ++ ++/* ++** Implementation of ".ar" dot command. ++*/ ++static int arDotCommand( ++ ShellState *pState, /* Current shell tool state */ ++ int fromCmdLine, /* True if -A command-line option, not .ar cmd */ ++ char **azArg, /* Array of arguments passed to dot command */ ++ int nArg /* Number of entries in azArg[] */ ++){ ++ ArCommand cmd; ++ int rc; ++ memset(&cmd, 0, sizeof(cmd)); ++ cmd.fromCmdLine = fromCmdLine; ++ rc = arParseCommand(azArg, nArg, &cmd); ++ if( rc==SQLITE_OK ){ ++ int eDbType = SHELL_OPEN_UNSPEC; ++ cmd.p = pState; ++ cmd.db = pState->db; ++ if( cmd.zFile ){ ++ eDbType = deduceDatabaseType(cmd.zFile, 1); ++ }else{ ++ eDbType = pState->openMode; ++ } ++ if( eDbType==SHELL_OPEN_ZIPFILE ){ ++ if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){ ++ if( cmd.zFile==0 ){ ++ cmd.zSrcTable = sqlite3_mprintf("zip"); ++ }else{ ++ cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile); ++ } ++ } ++ cmd.bZip = 1; ++ }else if( cmd.zFile ){ ++ int flags; ++ if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS; ++ if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_UPDATE ){ ++ flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; ++ }else{ ++ flags = SQLITE_OPEN_READONLY; ++ } ++ cmd.db = 0; ++ if( cmd.bDryRun ){ ++ utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile, ++ eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : ""); ++ } ++ rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags, ++ eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0); ++ if( rc!=SQLITE_OK ){ ++ utf8_printf(stderr, "cannot open file: %s (%s)\n", ++ cmd.zFile, sqlite3_errmsg(cmd.db) ++ ); ++ goto end_ar_command; ++ } ++ sqlite3_fileio_init(cmd.db, 0, 0); ++ sqlite3_sqlar_init(cmd.db, 0, 0); ++ sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p, ++ shellPutsFunc, 0, 0); ++ ++ } ++ if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){ ++ if( cmd.eCmd!=AR_CMD_CREATE ++ && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0) ++ ){ ++ utf8_printf(stderr, "database does not contain an 'sqlar' table\n"); ++ rc = SQLITE_ERROR; ++ goto end_ar_command; ++ } ++ cmd.zSrcTable = sqlite3_mprintf("sqlar"); ++ } ++ ++ switch( cmd.eCmd ){ ++ case AR_CMD_CREATE: ++ rc = arCreateOrUpdateCommand(&cmd, 0); ++ break; ++ ++ case AR_CMD_EXTRACT: ++ rc = arExtractCommand(&cmd); ++ break; ++ ++ case AR_CMD_LIST: ++ rc = arListCommand(&cmd); ++ break; ++ ++ case AR_CMD_HELP: ++ arUsage(pState->out); ++ break; ++ ++ default: ++ assert( cmd.eCmd==AR_CMD_UPDATE ); ++ rc = arCreateOrUpdateCommand(&cmd, 1); ++ break; ++ } ++ } ++end_ar_command: ++ if( cmd.db!=pState->db ){ ++ close_db(cmd.db); ++ } ++ sqlite3_free(cmd.zSrcTable); ++ ++ return rc; ++} ++/* End of the ".archive" or ".ar" command logic ++**********************************************************************************/ ++#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */ ++ ++ ++/* + ** If an input line begins with "." then invoke this routine to + ** process that line. + ** +@@ -5433,6 +13262,12 @@ + int rc = 0; + char *azArg[50]; + ++#ifndef SQLITE_OMIT_VIRTUALTABLE ++ if( p->expert.pExpert ){ ++ expertFinish(p, 1, 0); ++ } ++#endif ++ + /* Parse the input line into tokens. + */ + while( zLine[h] && nArg<ArraySize(azArg) ){ +@@ -5462,6 +13297,7 @@ + if( nArg==0 ) return 0; /* no tokens, no error */ + n = strlen30(azArg[0]); + c = azArg[0][0]; ++ clearTempFile(p); + + #ifndef SQLITE_OMIT_AUTHORIZATION + if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){ +@@ -5479,6 +13315,13 @@ + }else + #endif + ++#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) ++ if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){ ++ open_db(p, 0); ++ rc = arDotCommand(p, 0, azArg, nArg); ++ }else ++#endif ++ + if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0) + || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0) + ){ +@@ -5487,11 +13330,14 @@ + sqlite3 *pDest; + sqlite3_backup *pBackup; + int j; ++ const char *zVfs = 0; + for(j=1; j<nArg; j++){ + const char *z = azArg[j]; + if( z[0]=='-' ){ +- while( z[0]=='-' ) z++; +- /* No options to process at this time */ ++ if( z[1]=='-' ) z++; ++ if( strcmp(z, "-append")==0 ){ ++ zVfs = "apndvfs"; ++ }else + { + utf8_printf(stderr, "unknown option: %s\n", azArg[j]); + return 1; +@@ -5502,7 +13348,7 @@ + zDb = zDestFile; + zDestFile = azArg[j]; + }else{ +- raw_printf(stderr, "too many arguments to .backup\n"); ++ raw_printf(stderr, "Usage: .backup ?DB? ?--append? FILENAME\n"); + return 1; + } + } +@@ -5511,10 +13357,11 @@ + return 1; + } + if( zDb==0 ) zDb = "main"; +- rc = sqlite3_open(zDestFile, &pDest); ++ rc = sqlite3_open_v2(zDestFile, &pDest, ++ SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs); + if( rc!=SQLITE_OK ){ + utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile); +- sqlite3_close(pDest); ++ close_db(pDest); + return 1; + } + open_db(p, 0); +@@ -5521,7 +13368,7 @@ + pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb); + if( pBackup==0 ){ + utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); +- sqlite3_close(pDest); ++ close_db(pDest); + return 1; + } + while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){} +@@ -5532,7 +13379,7 @@ + utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); + rc = 1; + } +- sqlite3_close(pDest); ++ close_db(pDest); + }else + + if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){ +@@ -5609,7 +13456,7 @@ + utf8_printf(stderr, + "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n", + p->zTestcase, azArg[1], zRes); +- rc = 2; ++ rc = 1; + }else{ + utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase); + p->nCheck++; +@@ -5644,7 +13491,39 @@ + } + }else + +- if( c=='d' && strncmp(azArg[0], "dbinfo", n)==0 ){ ++ if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){ ++ static const struct DbConfigChoices { ++ const char *zName; ++ int op; ++ } aDbConfig[] = { ++ { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY }, ++ { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER }, ++ { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER }, ++ { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION }, ++ { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE }, ++ { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG }, ++ { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP }, ++ { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE }, ++ { "defensive", SQLITE_DBCONFIG_DEFENSIVE }, ++ }; ++ int ii, v; ++ open_db(p, 0); ++ for(ii=0; ii<ArraySize(aDbConfig); ii++){ ++ if( nArg>1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue; ++ if( nArg>=3 ){ ++ sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0); ++ } ++ sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v); ++ utf8_printf(p->out, "%18s %s\n", aDbConfig[ii].zName, v ? "on" : "off"); ++ if( nArg>1 ) break; ++ } ++ if( nArg>1 && ii==ArraySize(aDbConfig) ){ ++ utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]); ++ utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n"); ++ } ++ }else ++ ++ if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){ + rc = shell_dbinfo_command(p, nArg, azArg); + }else + +@@ -5652,7 +13531,8 @@ + const char *zLike = 0; + int i; + int savedShowHeader = p->showHeader; +- ShellClearFlag(p, SHFLG_PreserveRowid|SHFLG_Newlines); ++ int savedShellFlags = p->shellFlgs; ++ ShellClearFlag(p, SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo); + for(i=1; i<nArg; i++){ + if( azArg[i][0]=='-' ){ + const char *z = azArg[i]+1; +@@ -5734,6 +13614,7 @@ + sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0); + raw_printf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n"); + p->showHeader = savedShowHeader; ++ p->shellFlgs = savedShellFlags; + }else + + if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){ +@@ -5747,13 +13628,19 @@ + + if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){ + if( nArg==2 ){ ++ p->autoEQPtest = 0; + if( strcmp(azArg[1],"full")==0 ){ +- p->autoEQP = 2; ++ p->autoEQP = AUTOEQP_full; ++ }else if( strcmp(azArg[1],"trigger")==0 ){ ++ p->autoEQP = AUTOEQP_trigger; ++ }else if( strcmp(azArg[1],"test")==0 ){ ++ p->autoEQP = AUTOEQP_on; ++ p->autoEQPtest = 1; + }else{ +- p->autoEQP = booleanValue(azArg[1]); ++ p->autoEQP = (u8)booleanValue(azArg[1]); + } + }else{ +- raw_printf(stderr, "Usage: .eqp on|off|full\n"); ++ raw_printf(stderr, "Usage: .eqp off|on|trigger|full\n"); + rc = 1; + } + }else +@@ -5787,6 +13674,13 @@ + } + }else + ++#ifndef SQLITE_OMIT_VIRTUALTABLE ++ if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){ ++ open_db(p, 0); ++ expertDotCommand(p, azArg, nArg); ++ }else ++#endif ++ + if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){ + ShellState data; + char *zErrMsg = 0; +@@ -5830,14 +13724,11 @@ + callback, &data, &zErrMsg); + data.cMode = data.mode = MODE_Insert; + data.zDestTable = "sqlite_stat1"; +- shell_exec(p->db, "SELECT * FROM sqlite_stat1", +- shell_callback, &data,&zErrMsg); ++ shell_exec(&data, "SELECT * FROM sqlite_stat1", &zErrMsg); + data.zDestTable = "sqlite_stat3"; +- shell_exec(p->db, "SELECT * FROM sqlite_stat3", +- shell_callback, &data,&zErrMsg); ++ shell_exec(&data, "SELECT * FROM sqlite_stat3", &zErrMsg); + data.zDestTable = "sqlite_stat4"; +- shell_exec(p->db, "SELECT * FROM sqlite_stat4", +- shell_callback, &data, &zErrMsg); ++ shell_exec(&data, "SELECT * FROM sqlite_stat4", &zErrMsg); + raw_printf(p->out, "ANALYZE sqlite_master;\n"); + } + }else +@@ -5852,7 +13743,14 @@ + }else + + if( c=='h' && strncmp(azArg[0], "help", n)==0 ){ +- utf8_printf(p->out, "%s", zHelp); ++ if( nArg>=2 ){ ++ n = showHelp(p->out, azArg[1]); ++ if( n==0 ){ ++ utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]); ++ } ++ }else{ ++ showHelp(p->out, 0); ++ } + }else + + if( c=='i' && strncmp(azArg[0], "import", n)==0 ){ +@@ -5935,9 +13833,8 @@ + sCtx.cRowSep = p->rowSeparator[0]; + zSql = sqlite3_mprintf("SELECT * FROM %s", zTable); + if( zSql==0 ){ +- raw_printf(stderr, "Error: out of memory\n"); + xCloser(sCtx.in); +- return 1; ++ shell_out_of_memory(); + } + nByte = strlen30(zSql); + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); +@@ -5982,9 +13879,8 @@ + if( nCol==0 ) return 0; /* no columns, no error */ + zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 ); + if( zSql==0 ){ +- raw_printf(stderr, "Error: out of memory\n"); + xCloser(sCtx.in); +- return 1; ++ shell_out_of_memory(); + } + sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable); + j = strlen30(zSql); +@@ -6060,12 +13956,17 @@ + sqlite3_stmt *pStmt; + int tnum = 0; + int i; +- if( nArg!=3 ){ +- utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"); ++ if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){ ++ utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n" ++ " .imposter off\n"); + rc = 1; + goto meta_command_exit; + } + open_db(p, 0); ++ if( nArg==2 ){ ++ sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1); ++ goto meta_command_exit; ++ } + zSql = sqlite3_mprintf("SELECT rootpage FROM sqlite_master" + " WHERE name='%q' AND type='index'", azArg[1]); + sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); +@@ -6241,13 +14142,13 @@ + }else{ + const char *zFile = azArg[1]; + output_file_close(p->pLog); +- p->pLog = output_file_open(zFile); ++ p->pLog = output_file_open(zFile, 0); + } + }else + + if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){ + const char *zMode = nArg>=2 ? azArg[1] : ""; +- int n2 = (int)strlen(zMode); ++ int n2 = strlen30(zMode); + int c2 = zMode[0]; + if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){ + p->mode = MODE_Line; +@@ -6307,16 +14208,29 @@ + int newFlag = 0; /* True to delete file before opening */ + /* Close the existing database */ + session_close_all(p); +- sqlite3_close(p->db); ++ close_db(p->db); + p->db = 0; + p->zDbFilename = 0; + sqlite3_free(p->zFreeOnClose); + p->zFreeOnClose = 0; ++ p->openMode = SHELL_OPEN_UNSPEC; + /* Check for command-line arguments */ + for(iName=1; iName<nArg && azArg[iName][0]=='-'; iName++){ + const char *z = azArg[iName]; + if( optionMatch(z,"new") ){ + newFlag = 1; ++#ifdef SQLITE_HAVE_ZLIB ++ }else if( optionMatch(z, "zip") ){ ++ p->openMode = SHELL_OPEN_ZIPFILE; ++#endif ++ }else if( optionMatch(z, "append") ){ ++ p->openMode = SHELL_OPEN_APPENDVFS; ++ }else if( optionMatch(z, "readonly") ){ ++ p->openMode = SHELL_OPEN_READONLY; ++#ifdef SQLITE_ENABLE_DESERIALIZE ++ }else if( optionMatch(z, "deserialize") ){ ++ p->openMode = SHELL_OPEN_DESERIALIZE; ++#endif + }else if( z[0]=='-' ){ + utf8_printf(stderr, "unknown option: %s\n", z); + rc = 1; +@@ -6328,7 +14242,7 @@ + if( zNewFilename ){ + if( newFlag ) shellDeleteFile(zNewFilename); + p->zDbFilename = zNewFilename; +- open_db(p, 1); ++ open_db(p, OPEN_DB_KEEPALIVE); + if( p->db==0 ){ + utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename); + sqlite3_free(zNewFilename); +@@ -6343,18 +14257,27 @@ + } + }else + +- if( c=='o' +- && (strncmp(azArg[0], "output", n)==0 || strncmp(azArg[0], "once", n)==0) ++ if( (c=='o' ++ && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0)) ++ || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0) + ){ + const char *zFile = nArg>=2 ? azArg[1] : "stdout"; ++ int bTxtMode = 0; ++ if( azArg[0][0]=='e' ){ ++ /* Transform the ".excel" command into ".once -x" */ ++ nArg = 2; ++ azArg[0] = "once"; ++ zFile = azArg[1] = "-x"; ++ n = 4; ++ } + if( nArg>2 ){ +- utf8_printf(stderr, "Usage: .%s FILE\n", azArg[0]); ++ utf8_printf(stderr, "Usage: .%s [-e|-x|FILE]\n", azArg[0]); + rc = 1; + goto meta_command_exit; + } + if( n>1 && strncmp(azArg[0], "once", n)==0 ){ + if( nArg<2 ){ +- raw_printf(stderr, "Usage: .once FILE\n"); ++ raw_printf(stderr, "Usage: .once (-e|-x|FILE)\n"); + rc = 1; + goto meta_command_exit; + } +@@ -6363,6 +14286,23 @@ + p->outCount = 0; + } + output_reset(p); ++ if( zFile[0]=='-' && zFile[1]=='-' ) zFile++; ++#ifndef SQLITE_NOHAVE_SYSTEM ++ if( strcmp(zFile, "-e")==0 || strcmp(zFile, "-x")==0 ){ ++ p->doXdgOpen = 1; ++ outputModePush(p); ++ if( zFile[1]=='x' ){ ++ newTempFile(p, "csv"); ++ p->mode = MODE_Csv; ++ sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); ++ sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf); ++ }else{ ++ newTempFile(p, "txt"); ++ bTxtMode = 1; ++ } ++ zFile = p->zTempFile; ++ } ++#endif /* SQLITE_NOHAVE_SYSTEM */ + if( zFile[0]=='|' ){ + #ifdef SQLITE_OMIT_POPEN + raw_printf(stderr, "Error: pipes are not supported in this OS\n"); +@@ -6379,7 +14319,7 @@ + } + #endif + }else{ +- p->out = output_file_open(zFile); ++ p->out = output_file_open(zFile, bTxtMode); + if( p->out==0 ){ + if( strcmp(zFile,"off")!=0 ){ + utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile); +@@ -6452,7 +14392,7 @@ + rc = sqlite3_open(zSrcFile, &pSrc); + if( rc!=SQLITE_OK ){ + utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile); +- sqlite3_close(pSrc); ++ close_db(pSrc); + return 1; + } + open_db(p, 0); +@@ -6459,7 +14399,7 @@ + pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main"); + if( pBackup==0 ){ + utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); +- sqlite3_close(pSrc); ++ close_db(pSrc); + return 1; + } + while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK +@@ -6479,13 +14419,12 @@ + utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); + rc = 1; + } +- sqlite3_close(pSrc); ++ close_db(pSrc); + }else + +- + if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){ + if( nArg==2 ){ +- p->scanstatsOn = booleanValue(azArg[1]); ++ p->scanstatsOn = (u8)booleanValue(azArg[1]); + #ifndef SQLITE_ENABLE_STMT_SCANSTATUS + raw_printf(stderr, "Warning: .scanstats not available in this build.\n"); + #endif +@@ -6499,8 +14438,11 @@ + ShellText sSelect; + ShellState data; + char *zErrMsg = 0; +- const char *zDiv = 0; ++ const char *zDiv = "("; ++ const char *zName = 0; + int iSchema = 0; ++ int bDebug = 0; ++ int ii; + + open_db(p, 0); + memcpy(&data, p, sizeof(data)); +@@ -6507,51 +14449,37 @@ + data.showHeader = 0; + data.cMode = data.mode = MODE_Semi; + initText(&sSelect); +- if( nArg>=2 && optionMatch(azArg[1], "indent") ){ +- data.cMode = data.mode = MODE_Pretty; +- nArg--; +- if( nArg==2 ) azArg[1] = azArg[2]; ++ for(ii=1; ii<nArg; ii++){ ++ if( optionMatch(azArg[ii],"indent") ){ ++ data.cMode = data.mode = MODE_Pretty; ++ }else if( optionMatch(azArg[ii],"debug") ){ ++ bDebug = 1; ++ }else if( zName==0 ){ ++ zName = azArg[ii]; ++ }else{ ++ raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n"); ++ rc = 1; ++ goto meta_command_exit; ++ } + } +- if( nArg==2 && azArg[1][0]!='-' ){ +- int i; +- for(i=0; azArg[1][i]; i++) azArg[1][i] = ToLower(azArg[1][i]); +- if( strcmp(azArg[1],"sqlite_master")==0 ){ ++ if( zName!=0 ){ ++ int isMaster = sqlite3_strlike(zName, "sqlite_master", '\\')==0; ++ if( isMaster || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0 ){ + char *new_argv[2], *new_colv[2]; +- new_argv[0] = "CREATE TABLE sqlite_master (\n" ++ new_argv[0] = sqlite3_mprintf( ++ "CREATE TABLE %s (\n" + " type text,\n" + " name text,\n" + " tbl_name text,\n" + " rootpage integer,\n" + " sql text\n" +- ")"; ++ ")", isMaster ? "sqlite_master" : "sqlite_temp_master"); + new_argv[1] = 0; + new_colv[0] = "sql"; + new_colv[1] = 0; + callback(&data, 1, new_argv, new_colv); +- rc = SQLITE_OK; +- }else if( strcmp(azArg[1],"sqlite_temp_master")==0 ){ +- char *new_argv[2], *new_colv[2]; +- new_argv[0] = "CREATE TEMP TABLE sqlite_temp_master (\n" +- " type text,\n" +- " name text,\n" +- " tbl_name text,\n" +- " rootpage integer,\n" +- " sql text\n" +- ")"; +- new_argv[1] = 0; +- new_colv[0] = "sql"; +- new_colv[1] = 0; +- callback(&data, 1, new_argv, new_colv); +- rc = SQLITE_OK; +- }else{ +- zDiv = "("; ++ sqlite3_free(new_argv[0]); + } +- }else if( nArg==1 ){ +- zDiv = "("; +- }else{ +- raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n"); +- rc = 1; +- goto meta_command_exit; + } + if( zDiv ){ + sqlite3_stmt *pStmt = 0; +@@ -6571,39 +14499,53 @@ + sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema); + appendText(&sSelect, zDiv, 0); + zDiv = " UNION ALL "; +- if( strcmp(zDb, "main")!=0 ){ +- appendText(&sSelect, "SELECT shell_add_schema(sql,", 0); ++ appendText(&sSelect, "SELECT shell_add_schema(sql,", 0); ++ if( sqlite3_stricmp(zDb, "main")!=0 ){ + appendText(&sSelect, zDb, '"'); +- appendText(&sSelect, ") AS sql, type, tbl_name, name, rowid,", 0); +- appendText(&sSelect, zScNum, 0); +- appendText(&sSelect, " AS snum, ", 0); +- appendText(&sSelect, zDb, '\''); +- appendText(&sSelect, " AS sname FROM ", 0); +- appendText(&sSelect, zDb, '"'); +- appendText(&sSelect, ".sqlite_master", 0); + }else{ +- appendText(&sSelect, "SELECT sql, type, tbl_name, name, rowid, ", 0); +- appendText(&sSelect, zScNum, 0); +- appendText(&sSelect, " AS snum, 'main' AS sname FROM sqlite_master",0); ++ appendText(&sSelect, "NULL", 0); + } ++ appendText(&sSelect, ",name) AS sql, type, tbl_name, name, rowid,", 0); ++ appendText(&sSelect, zScNum, 0); ++ appendText(&sSelect, " AS snum, ", 0); ++ appendText(&sSelect, zDb, '\''); ++ appendText(&sSelect, " AS sname FROM ", 0); ++ appendText(&sSelect, zDb, '"'); ++ appendText(&sSelect, ".sqlite_master", 0); + } + sqlite3_finalize(pStmt); ++#ifdef SQLITE_INTROSPECTION_PRAGMAS ++ if( zName ){ ++ appendText(&sSelect, ++ " UNION ALL SELECT shell_module_schema(name)," ++ " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list", 0); ++ } ++#endif + appendText(&sSelect, ") WHERE ", 0); +- if( nArg>1 ){ +- char *zQarg = sqlite3_mprintf("%Q", azArg[1]); +- if( strchr(azArg[1], '.') ){ ++ if( zName ){ ++ char *zQarg = sqlite3_mprintf("%Q", zName); ++ int bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 || ++ strchr(zName, '[') != 0; ++ if( strchr(zName, '.') ){ + appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0); + }else{ + appendText(&sSelect, "lower(tbl_name)", 0); + } +- appendText(&sSelect, strchr(azArg[1], '*') ? " GLOB " : " LIKE ", 0); ++ appendText(&sSelect, bGlob ? " GLOB " : " LIKE ", 0); + appendText(&sSelect, zQarg, 0); ++ if( !bGlob ){ ++ appendText(&sSelect, " ESCAPE '\\' ", 0); ++ } + appendText(&sSelect, " AND ", 0); + sqlite3_free(zQarg); + } + appendText(&sSelect, "type!='meta' AND sql IS NOT NULL" + " ORDER BY snum, rowid", 0); +- rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg); ++ if( bDebug ){ ++ utf8_printf(p->out, "SQL: %s;\n", sSelect.z); ++ }else{ ++ rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg); ++ } + freeText(&sSelect); + } + if( zErrMsg ){ +@@ -6816,7 +14758,7 @@ + }else + /* If no command name matches, show a syntax error */ + session_syntax_error: +- session_help(p); ++ showHelp(p->out, "session"); + }else + #endif + +@@ -6997,7 +14939,7 @@ + utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n", + azArg[i], azArg[0]); + raw_printf(stderr, "Should be one of: --schema" +- " --sha3-224 --sha3-255 --sha3-384 --sha3-512\n"); ++ " --sha3-224 --sha3-256 --sha3-384 --sha3-512\n"); + rc = 1; + goto meta_command_exit; + } +@@ -7008,7 +14950,7 @@ + }else{ + zLike = z; + bSeparate = 1; +- if( sqlite3_strlike("sqlite_%", zLike, 0)==0 ) bSchema = 1; ++ if( sqlite3_strlike("sqlite\\_%", zLike, '\\')==0 ) bSchema = 1; + } + } + if( bSchema ){ +@@ -7075,11 +15017,12 @@ + if( bDebug ){ + utf8_printf(p->out, "%s\n", zSql); + }else{ +- shell_exec(p->db, zSql, shell_callback, p, 0); ++ shell_exec(p, zSql, 0); + } + sqlite3_free(zSql); + }else + ++#ifndef SQLITE_NOHAVE_SYSTEM + if( c=='s' + && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0) + ){ +@@ -7099,9 +15042,10 @@ + sqlite3_free(zCmd); + if( x ) raw_printf(stderr, "System command returns %d\n", x); + }else ++#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */ + + if( c=='s' && strncmp(azArg[0], "show", n)==0 ){ +- static const char *azBool[] = { "off", "on", "full", "unk" }; ++ static const char *azBool[] = { "off", "on", "trigger", "full"}; + int i; + if( nArg!=1 ){ + raw_printf(stderr, "Usage: .show\n"); +@@ -7138,7 +15082,7 @@ + + if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){ + if( nArg==2 ){ +- p->statsOn = booleanValue(azArg[1]); ++ p->statsOn = (u8)booleanValue(azArg[1]); + }else if( nArg==1 ){ + display_stats(p->db, p, 0); + }else{ +@@ -7159,7 +15103,10 @@ + initText(&s); + open_db(p, 0); + rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); +- if( rc ) return shellDatabaseError(p->db); ++ if( rc ){ ++ sqlite3_finalize(pStmt); ++ return shellDatabaseError(p->db); ++ } + + if( nArg>2 && c=='i' ){ + /* It is an historical accident that the .indexes command shows an error +@@ -7167,6 +15114,7 @@ + ** command does not. */ + raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n"); + rc = 1; ++ sqlite3_finalize(pStmt); + goto meta_command_exit; + } + for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){ +@@ -7211,18 +15159,12 @@ + char **azNew; + int n2 = nAlloc*2 + 10; + azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2); +- if( azNew==0 ){ +- rc = shellNomemError(); +- break; +- } ++ if( azNew==0 ) shell_out_of_memory(); + nAlloc = n2; + azResult = azNew; + } + azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0)); +- if( 0==azResult[nRow] ){ +- rc = shellNomemError(); +- break; +- } ++ if( 0==azResult[nRow] ) shell_out_of_memory(); + nRow++; + } + if( sqlite3_finalize(pStmt)!=SQLITE_OK ){ +@@ -7258,7 +15200,7 @@ + /* Begin redirecting output to the file "testcase-out.txt" */ + if( c=='t' && strcmp(azArg[0],"testcase")==0 ){ + output_reset(p); +- p->out = output_file_open("testcase-out.txt"); ++ p->out = output_file_open("testcase-out.txt", 0); + if( p->out==0 ){ + raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n"); + } +@@ -7270,50 +15212,78 @@ + }else + + #ifndef SQLITE_UNTESTABLE +- if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 && nArg>=2 ){ ++ if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){ + static const struct { + const char *zCtrlName; /* Name of a test-control option */ + int ctrlCode; /* Integer code for that option */ ++ const char *zUsage; /* Usage notes */ + } aCtrl[] = { +- { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE }, +- { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE }, +- { "prng_reset", SQLITE_TESTCTRL_PRNG_RESET }, +- { "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST }, +- { "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL }, +- { "benign_malloc_hooks", SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS }, +- { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE }, +- { "assert", SQLITE_TESTCTRL_ASSERT }, +- { "always", SQLITE_TESTCTRL_ALWAYS }, +- { "reserve", SQLITE_TESTCTRL_RESERVE }, +- { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS }, +- { "iskeyword", SQLITE_TESTCTRL_ISKEYWORD }, +- { "scratchmalloc", SQLITE_TESTCTRL_SCRATCHMALLOC }, +- { "byteorder", SQLITE_TESTCTRL_BYTEORDER }, +- { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT }, +- { "imposter", SQLITE_TESTCTRL_IMPOSTER }, ++ { "always", SQLITE_TESTCTRL_ALWAYS, "BOOLEAN" }, ++ { "assert", SQLITE_TESTCTRL_ASSERT, "BOOLEAN" }, ++ /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, "" },*/ ++ /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, "" },*/ ++ { "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" }, ++ /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" }, */ ++ { "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"}, ++ { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "BOOLEAN" }, ++ { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" }, ++ { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" }, ++ { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" }, ++#ifdef YYCOVERAGE ++ { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" }, ++#endif ++ { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " }, ++ { "prng_reset", SQLITE_TESTCTRL_PRNG_RESET, "" }, ++ { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" }, ++ { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" }, ++ { "reserve", SQLITE_TESTCTRL_RESERVE, "BYTES-OF-RESERVE" }, + }; + int testctrl = -1; +- int rc2 = 0; ++ 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++; ++ } ++ ++ /* --help lists all test-controls */ ++ if( strcmp(zCmd,"help")==0 ){ ++ utf8_printf(p->out, "Available test-controls:\n"); ++ for(i=0; i<ArraySize(aCtrl); i++){ ++ utf8_printf(p->out, " .testctrl %s %s\n", ++ aCtrl[i].zCtrlName, aCtrl[i].zUsage); ++ } ++ rc = 1; ++ goto meta_command_exit; ++ } ++ + /* convert testctrl text option to value. allow any unique prefix + ** of the option name, or a numerical value. */ +- n2 = strlen30(azArg[1]); ++ n2 = strlen30(zCmd); + for(i=0; i<ArraySize(aCtrl); i++){ +- if( strncmp(azArg[1], aCtrl[i].zCtrlName, n2)==0 ){ ++ if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){ + if( testctrl<0 ){ + testctrl = aCtrl[i].ctrlCode; ++ iCtrl = i; + }else{ +- utf8_printf(stderr, "ambiguous option name: \"%s\"\n", azArg[1]); +- testctrl = -1; +- break; ++ utf8_printf(stderr, "Error: ambiguous test-control: \"%s\"\n" ++ "Use \".testctrl --help\" for help\n", zCmd); ++ rc = 1; ++ goto meta_command_exit; + } + } + } +- if( testctrl<0 ) testctrl = (int)integerValue(azArg[1]); +- if( (testctrl<SQLITE_TESTCTRL_FIRST) || (testctrl>SQLITE_TESTCTRL_LAST) ){ +- utf8_printf(stderr,"Error: invalid testctrl option: %s\n", azArg[1]); ++ if( testctrl<0 ){ ++ utf8_printf(stderr,"Error: unknown test-control: %s\n" ++ "Use \".testctrl --help\" for help\n", zCmd); + }else{ + switch(testctrl){ + +@@ -7323,10 +15293,7 @@ + if( nArg==3 ){ + int opt = (int)strtol(azArg[2], 0, 0); + rc2 = sqlite3_test_control(testctrl, p->db, opt); +- raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2); +- } else { +- utf8_printf(stderr,"Error: testctrl %s takes a single int option\n", +- azArg[1]); ++ isOk = 3; + } + break; + +@@ -7337,10 +15304,7 @@ + case SQLITE_TESTCTRL_BYTEORDER: + if( nArg==2 ){ + rc2 = sqlite3_test_control(testctrl); +- raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2); +- } else { +- utf8_printf(stderr,"Error: testctrl %s takes no options\n", +- azArg[1]); ++ isOk = testctrl==SQLITE_TESTCTRL_BYTEORDER ? 1 : 3; + } + break; + +@@ -7349,10 +15313,7 @@ + if( nArg==3 ){ + unsigned int opt = (unsigned int)integerValue(azArg[2]); + rc2 = sqlite3_test_control(testctrl, opt); +- raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2); +- } else { +- utf8_printf(stderr,"Error: testctrl %s takes a single unsigned" +- " int option\n", azArg[1]); ++ isOk = 3; + } + break; + +@@ -7359,31 +15320,23 @@ + /* sqlite3_test_control(int, int) */ + case SQLITE_TESTCTRL_ASSERT: + case SQLITE_TESTCTRL_ALWAYS: +- case SQLITE_TESTCTRL_NEVER_CORRUPT: ++ case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: + if( nArg==3 ){ + int opt = booleanValue(azArg[2]); + rc2 = sqlite3_test_control(testctrl, opt); +- raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2); +- } else { +- utf8_printf(stderr,"Error: testctrl %s takes a single int option\n", +- azArg[1]); ++ isOk = 1; + } + break; + +- /* sqlite3_test_control(int, char *) */ +-#ifdef SQLITE_N_KEYWORD +- case SQLITE_TESTCTRL_ISKEYWORD: ++ /* sqlite3_test_control(int, int) */ ++ case SQLITE_TESTCTRL_LOCALTIME_FAULT: ++ case SQLITE_TESTCTRL_NEVER_CORRUPT: + if( nArg==3 ){ +- const char *opt = azArg[2]; ++ int opt = booleanValue(azArg[2]); + rc2 = sqlite3_test_control(testctrl, opt); +- raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2); +- } else { +- utf8_printf(stderr, +- "Error: testctrl %s takes a single char * option\n", +- azArg[1]); ++ isOk = 3; + } + break; +-#endif + + case SQLITE_TESTCTRL_IMPOSTER: + if( nArg==5 ){ +@@ -7391,23 +15344,27 @@ + azArg[2], + integerValue(azArg[3]), + integerValue(azArg[4])); +- raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2); +- }else{ +- raw_printf(stderr,"Usage: .testctrl imposter dbName onoff tnum\n"); ++ isOk = 3; + } + break; + +- case SQLITE_TESTCTRL_BITVEC_TEST: +- case SQLITE_TESTCTRL_FAULT_INSTALL: +- case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: +- case SQLITE_TESTCTRL_SCRATCHMALLOC: +- default: +- utf8_printf(stderr, +- "Error: CLI support for testctrl %s not implemented\n", +- azArg[1]); +- break; ++#ifdef YYCOVERAGE ++ case SQLITE_TESTCTRL_PARSER_COVERAGE: ++ if( nArg==2 ){ ++ sqlite3_test_control(testctrl, p->out); ++ isOk = 3; ++ } ++#endif + } + } ++ if( isOk==0 && iCtrl>=0 ){ ++ utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd, aCtrl[iCtrl].zUsage); ++ rc = 1; ++ }else if( isOk==1 ){ ++ raw_printf(p->out, "%d\n", rc2); ++ }else if( isOk==2 ){ ++ raw_printf(p->out, "0x%08x\n", rc2); ++ } + }else + #endif /* !defined(SQLITE_UNTESTABLE) */ + +@@ -7437,7 +15394,7 @@ + goto meta_command_exit; + } + output_file_close(p->traceOut); +- p->traceOut = output_file_open(azArg[1]); ++ p->traceOut = output_file_open(azArg[1], 0); + #if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) + if( p->traceOut==0 ){ + sqlite3_trace_v2(p->db, 0, 0, 0); +@@ -7461,8 +15418,7 @@ + rc = 1; + goto meta_command_exit; + } +- rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3], +- (int)strlen(azArg[3])); ++ rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3], strlen30(azArg[3])); + if( rc ){ + utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]); + rc = 1; +@@ -7473,8 +15429,7 @@ + rc = 1; + goto meta_command_exit; + } +- rc = sqlite3_user_add(p->db, azArg[2], +- azArg[3], (int)strlen(azArg[3]), ++ rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]), + booleanValue(azArg[4])); + if( rc ){ + raw_printf(stderr, "User-Add failed: %d\n", rc); +@@ -7486,8 +15441,7 @@ + rc = 1; + goto meta_command_exit; + } +- rc = sqlite3_user_change(p->db, azArg[2], +- azArg[3], (int)strlen(azArg[3]), ++ rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]), + booleanValue(azArg[4])); + if( rc ){ + raw_printf(stderr, "User-Edit failed: %d\n", rc); +@@ -7515,6 +15469,20 @@ + if( c=='v' && strncmp(azArg[0], "version", n)==0 ){ + utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/, + sqlite3_libversion(), sqlite3_sourceid()); ++#if SQLITE_HAVE_ZLIB ++ utf8_printf(p->out, "zlib version %s\n", zlibVersion()); ++#endif ++#define CTIMEOPT_VAL_(opt) #opt ++#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt) ++#if defined(__clang__) && defined(__clang_major__) ++ utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "." ++ CTIMEOPT_VAL(__clang_minor__) "." ++ CTIMEOPT_VAL(__clang_patchlevel__) "\n"); ++#elif defined(_MSC_VER) ++ utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) "\n"); ++#elif defined(__GNUC__) && defined(__VERSION__) ++ utf8_printf(p->out, "gcc-" __VERSION__ "\n"); ++#endif + }else + + if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){ +@@ -7641,6 +15609,16 @@ + } + + /* ++** We need a default sqlite3_complete() implementation to use in case ++** the shell is compiled with SQLITE_OMIT_COMPLETE. The default assumes ++** any arbitrary text is a complete SQL statement. This is not very ++** user-friendly, but it does seem to work. ++*/ ++#ifdef SQLITE_OMIT_COMPLETE ++#define sqlite3_complete(x) 1 ++#endif ++ ++/* + ** Return true if zSql is a complete SQL statement. Return false if it + ** ends in the middle of a string literal or C-style comment. + */ +@@ -7655,7 +15633,7 @@ + } + + /* +-** Run a single line of SQL ++** Run a single line of SQL. Return the number of errors. + */ + static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){ + int rc; +@@ -7664,7 +15642,7 @@ + open_db(p, 0); + if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql); + BEGIN_TIMER; +- rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg); ++ rc = shell_exec(p, zSql, &zErrMsg); + END_TIMER; + if( rc || zErrMsg ){ + char zPrefix[100]; +@@ -7728,13 +15706,15 @@ + if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine); + continue; + } +- if( zLine && zLine[0]=='.' && nSql==0 ){ ++ if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){ + if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine); +- rc = do_meta_command(zLine, p); +- if( rc==2 ){ /* exit requested */ +- break; +- }else if( rc ){ +- errCnt++; ++ if( zLine[0]=='.' ){ ++ rc = do_meta_command(zLine, p); ++ if( rc==2 ){ /* exit requested */ ++ break; ++ }else if( rc ){ ++ errCnt++; ++ } + } + continue; + } +@@ -7745,10 +15725,7 @@ + if( nSql+nLine+2>=nAlloc ){ + nAlloc = nSql+nLine+100; + zSql = realloc(zSql, nAlloc); +- if( zSql==0 ){ +- raw_printf(stderr, "Error: out of memory\n"); +- exit(1); +- } ++ if( zSql==0 ) shell_out_of_memory(); + } + nSqlPrior = nSql; + if( nSql==0 ){ +@@ -7770,6 +15747,8 @@ + if( p->outCount ){ + output_reset(p); + p->outCount = 0; ++ }else{ ++ clearTempFile(p); + } + }else if( nSql && _all_whitespace(zSql) ){ + if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql); +@@ -7777,7 +15756,7 @@ + } + } + if( nSql && !_all_whitespace(zSql) ){ +- runOneSqlLine(p, zSql, in, startline); ++ errCnt += runOneSqlLine(p, zSql, in, startline); + } + free(zSql); + free(zLine); +@@ -7875,7 +15854,6 @@ + " cannot read ~/.sqliterc\n"); + return; + } +- sqlite3_initialize(); + zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir); + sqliterc = zBuf; + } +@@ -7894,6 +15872,10 @@ + ** 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" +@@ -7920,8 +15902,11 @@ + " -nullvalue TEXT set text string for NULL values. Default ''\n" + " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n" + " -quote set output mode to 'quote'\n" +- " -scratch SIZE N use N slots of SZ bytes each for scratch memory\n" ++ " -readonly open the database read-only\n" + " -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" + " -version show SQLite version\n" + " -vfs NAME use NAME as the default VFS\n" +@@ -7928,6 +15913,9 @@ + #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, +@@ -7943,6 +15931,17 @@ + } + + /* ++** Internal check: Verify that the SQLite is uninitialized. Print a ++** error message if it is initialized. ++*/ ++static void verify_uninitialized(void){ ++ if( sqlite3_config(-1)==SQLITE_MISUSE ){ ++ utf8_printf(stdout, "WARNING: attempt to configure SQLite after" ++ " initialization.\n"); ++ } ++} ++ ++/* + ** Initialize the state information in data + */ + static void main_init(ShellState *data) { +@@ -7953,6 +15952,7 @@ + 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); +@@ -8016,6 +16016,11 @@ + 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 */ +@@ -8022,8 +16027,25 @@ + stdin_is_interactive = isatty(0); + stdout_is_console = isatty(1); + ++#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) ++ DebugBreak(); ++#elif defined(SIGTRAP) ++ raise(SIGTRAP); ++#endif ++ } ++ } ++#endif ++ + #if USE_SYSTEM_SQLITE+0!=1 +- if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){ ++ if( 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); +@@ -8030,21 +16052,33 @@ + } + #endif + main_init(&data); ++ ++ /* On Windows, we must translate command-line arguments into UTF-8. ++ ** The SQLite memory allocator subsystem has to be enabled in order to ++ ** do this. But we want to run an sqlite3_shutdown() afterwards so that ++ ** subsequent sqlite3_config() calls will work. So copy all results into ++ ** memory that does not come from the SQLite memory allocator. ++ */ + #if !SQLITE_SHELL_IS_UTF8 + sqlite3_initialize(); +- argv = sqlite3_malloc64(sizeof(argv[0])*argc); +- if( argv==0 ){ +- raw_printf(stderr, "out of memory\n"); +- exit(1); +- } ++ argvToFree = malloc(sizeof(argv[0])*argc*2); ++ argcToFree = argc; ++ argv = argvToFree + argc; ++ if( argv==0 ) shell_out_of_memory(); + for(i=0; i<argc; i++){ +- argv[i] = sqlite3_win32_unicode_to_utf8(wargv[i]); +- if( argv[i]==0 ){ +- raw_printf(stderr, "out of memory\n"); +- exit(1); +- } ++ char *z = sqlite3_win32_unicode_to_utf8(wargv[i]); ++ int n; ++ if( z==0 ) shell_out_of_memory(); ++ n = (int)strlen(z); ++ argv[i] = malloc( n+1 ); ++ if( argv[i]==0 ) shell_out_of_memory(); ++ memcpy(argv[i], z, n+1); ++ argvToFree[i] = argv[i]; ++ sqlite3_free(z); + } ++ sqlite3_shutdown(); + #endif ++ + assert( argc>=1 && argv && argv[0] ); + Argv0 = argv[0]; + +@@ -8053,6 +16087,8 @@ + */ + #ifdef SIGINT + signal(SIGINT, interrupt_handler); ++#elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE) ++ SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE); + #endif + + #ifdef SQLITE_SHELL_DBNAME_PROC +@@ -8072,6 +16108,7 @@ + ** 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]; +@@ -8084,10 +16121,7 @@ + readStdin = 0; + nCmd++; + azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd); +- if( azCmd==0 ){ +- raw_printf(stderr, "out of memory\n"); +- exit(1); +- } ++ if( azCmd==0 ) shell_out_of_memory(); + azCmd[nCmd-1] = z; + } + } +@@ -8118,16 +16152,6 @@ + #else + (void)cmdline_option_value(argc, argv, ++i); + #endif +- }else if( strcmp(z,"-scratch")==0 ){ +- int n, sz; +- sz = (int)integerValue(cmdline_option_value(argc,argv,++i)); +- if( sz>400000 ) sz = 400000; +- if( sz<2500 ) sz = 2500; +- n = (int)integerValue(cmdline_option_value(argc,argv,++i)); +- if( n>10 ) n = 10; +- if( n<1 ) n = 1; +- sqlite3_config(SQLITE_CONFIG_SCRATCH, malloc(n*sz+1), sz, n); +- data.shellFlgs |= SHFLG_Scratch; + }else if( strcmp(z,"-pagecache")==0 ){ + int n, sz; + sz = (int)integerValue(cmdline_option_value(argc,argv,++i)); +@@ -8164,16 +16188,61 @@ + }else if( 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( 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( strcmp(z,"-vfs")==0 ){ +- sqlite3_vfs *pVfs = sqlite3_vfs_find(cmdline_option_value(argc,argv,++i)); +- if( pVfs ){ +- sqlite3_vfs_register(pVfs, 1); +- }else{ +- utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]); +- exit(1); +- } ++ zVfs = cmdline_option_value(argc, argv, ++i); ++#ifdef SQLITE_HAVE_ZLIB ++ }else if( strcmp(z,"-zip")==0 ){ ++ data.openMode = SHELL_OPEN_ZIPFILE; ++#endif ++ }else if( strcmp(z,"-append")==0 ){ ++ data.openMode = SHELL_OPEN_APPENDVFS; ++#ifdef SQLITE_ENABLE_DESERIALIZE ++ }else if( strcmp(z,"-deserialize")==0 ){ ++ data.openMode = SHELL_OPEN_DESERIALIZE; ++#endif ++ }else if( strcmp(z,"-readonly")==0 ){ ++ data.openMode = SHELL_OPEN_READONLY; ++#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) ++ }else if( strncmp(z, "-A",2)==0 ){ ++ /* All remaining command-line arguments are passed to the ".archive" ++ ** command, so ignore them */ ++ break; ++#endif + } + } ++ 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 ++ ** option to embed this shell program in larger applications. */ ++ extern void SQLITE_SHELL_INIT_PROC(void); ++ SQLITE_SHELL_INIT_PROC(); ++ } ++#else ++ /* All the sqlite3_config() calls have now been made. So it is safe ++ ** to call sqlite3_initialize() and process any command line -vfs option. */ ++ sqlite3_initialize(); ++#endif ++ ++ if( zVfs ){ ++ sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs); ++ if( pVfs ){ ++ sqlite3_vfs_register(pVfs, 1); ++ }else{ ++ utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]); ++ exit(1); ++ } ++ } ++ + if( data.zDbFilename==0 ){ + #ifndef SQLITE_OMIT_MEMORYDB + data.zDbFilename = ":memory:"; +@@ -8184,6 +16253,7 @@ + #endif + } + data.out = stdout; ++ sqlite3_appendvfs_init(0,0,0); + + /* Go ahead and open the database file if it already exists. If the + ** file does not exist, delay opening it. This prevents empty database +@@ -8224,6 +16294,18 @@ + }else if( strcmp(z,"-csv")==0 ){ + data.mode = MODE_Csv; + memcpy(data.colSeparator,",",2); ++#ifdef SQLITE_HAVE_ZLIB ++ }else if( strcmp(z,"-zip")==0 ){ ++ data.openMode = SHELL_OPEN_ZIPFILE; ++#endif ++ }else if( strcmp(z,"-append")==0 ){ ++ data.openMode = SHELL_OPEN_APPENDVFS; ++#ifdef SQLITE_ENABLE_DESERIALIZE ++ }else if( strcmp(z,"-deserialize")==0 ){ ++ data.openMode = SHELL_OPEN_DESERIALIZE; ++#endif ++ }else if( strcmp(z,"-readonly")==0 ){ ++ data.openMode = SHELL_OPEN_READONLY; + }else if( strcmp(z,"-ascii")==0 ){ + data.mode = MODE_Ascii; + sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, +@@ -8246,9 +16328,9 @@ + }else if( strcmp(z,"-echo")==0 ){ + ShellSetFlag(&data, SHFLG_Echo); + }else if( strcmp(z,"-eqp")==0 ){ +- data.autoEQP = 1; ++ data.autoEQP = AUTOEQP_on; + }else if( strcmp(z,"-eqpfull")==0 ){ +- data.autoEQP = 2; ++ data.autoEQP = AUTOEQP_full; + }else if( strcmp(z,"-stats")==0 ){ + data.statsOn = 1; + }else if( strcmp(z,"-scanstats")==0 ){ +@@ -8271,8 +16353,6 @@ + stdin_is_interactive = 0; + }else if( strcmp(z,"-heap")==0 ){ + i++; +- }else if( strcmp(z,"-scratch")==0 ){ +- i+=2; + }else if( strcmp(z,"-pagecache")==0 ){ + i+=2; + }else if( strcmp(z,"-lookaside")==0 ){ +@@ -8279,6 +16359,10 @@ + i+=2; + }else if( strcmp(z,"-mmap")==0 ){ + i++; ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ }else if( strcmp(z,"-sorterref")==0 ){ ++ i++; ++#endif + }else if( strcmp(z,"-vfs")==0 ){ + i++; + #ifdef SQLITE_ENABLE_VFSTRACE +@@ -8303,7 +16387,7 @@ + if( rc && bail_on_error ) return rc==2 ? 0 : rc; + }else{ + open_db(&data, 0); +- rc = shell_exec(data.db, z, shell_callback, &data, &zErrMsg); ++ rc = shell_exec(&data, z, &zErrMsg); + if( zErrMsg!=0 ){ + utf8_printf(stderr,"Error: %s\n", zErrMsg); + if( bail_on_error ) return rc!=0 ? rc : 1; +@@ -8312,6 +16396,23 @@ + if( bail_on_error ) return rc; + } + } ++#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) ++ }else if( strncmp(z, "-A", 2)==0 ){ ++ if( nCmd>0 ){ ++ utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands" ++ " with \"%s\"\n", z); ++ return 1; ++ } ++ open_db(&data, OPEN_DB_ZIPFILE); ++ if( z[2] ){ ++ argv[i] = &z[2]; ++ arDotCommand(&data, 1, argv+(i-1), argc-(i-1)); ++ }else{ ++ arDotCommand(&data, 1, argv+i, argc-i); ++ } ++ readStdin = 0; ++ break; ++#endif + }else{ + utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z); + raw_printf(stderr,"Use -help for a list of options.\n"); +@@ -8331,7 +16432,7 @@ + if( rc ) return rc==2 ? 0 : rc; + }else{ + open_db(&data, 0); +- rc = shell_exec(data.db, azCmd[i], shell_callback, &data, &zErrMsg); ++ rc = shell_exec(&data, azCmd[i], &zErrMsg); + if( zErrMsg!=0 ){ + utf8_printf(stderr,"Error: %s\n", zErrMsg); + return rc!=0 ? rc : 1; +@@ -8347,7 +16448,7 @@ + */ + if( stdin_is_interactive ){ + char *zHome; +- char *zHistory = 0; ++ char *zHistory; + int nHistory; + printf( + "SQLite version %s %.19s\n" /*extra-version-info*/ +@@ -8360,8 +16461,10 @@ + printf(".\nUse \".open FILENAME\" to reopen on a " + "persistent database.\n"); + } +- zHome = find_home_dir(0); +- if( zHome ){ ++ zHistory = getenv("SQLITE_HISTORY"); ++ if( zHistory ){ ++ zHistory = strdup(zHistory); ++ }else if( (zHome = find_home_dir(0))!=0 ){ + nHistory = strlen30(zHome) + 20; + if( (zHistory = malloc(nHistory))!=0 ){ + sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome); +@@ -8386,13 +16489,19 @@ + set_table_name(&data, 0); + if( data.db ){ + session_close_all(&data); +- sqlite3_close(data.db); ++ close_db(data.db); + } + sqlite3_free(data.zFreeOnClose); + find_home_dir(1); ++ output_reset(&data); ++ data.doXdgOpen = 0; ++ clearTempFile(&data); + #if !SQLITE_SHELL_IS_UTF8 +- for(i=0; i<argc; i++) sqlite3_free(argv[i]); +- sqlite3_free(argv); ++ for(i=0; i<argcToFree; i++) free(argvToFree[i]); ++ free(argvToFree); + #endif ++ /* Clear the global data structure so that valgrind will detect memory ++ ** leaks */ ++ memset(&data, 0, sizeof(data)); + return rc; + } +--- contrib/sqlite3/sqlite3.c.orig ++++ contrib/sqlite3/sqlite3.c +@@ -1,6 +1,6 @@ + /****************************************************************************** + ** This file is an amalgamation of many separate C source files from SQLite +-** version 3.20.0. By combining all the individual C code files into this ++** version 3.26.0. By combining all the individual C code files into this + ** single large file, the entire code can be compiled as a single translation + ** unit. This allows many compilers to do optimizations that would not be + ** possible if the files were compiled separately. Performance improvements +@@ -55,6 +55,12 @@ + #define CTIMEOPT_VAL_(opt) #opt + #define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt) + ++/* Like CTIMEOPT_VAL, but especially for SQLITE_DEFAULT_LOOKASIDE. This ++** option requires a separate macro because legal values contain a single ++** comma. e.g. (-DSQLITE_DEFAULT_LOOKASIDE="100,100") */ ++#define CTIMEOPT_VAL2_(opt1,opt2) #opt1 "," #opt2 ++#define CTIMEOPT_VAL2(opt) CTIMEOPT_VAL2_(opt) ++ + /* + ** An array of names of all compile-time options. This array should + ** be sorted A-Z. +@@ -138,7 +144,7 @@ + "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), + #endif + #ifdef SQLITE_DEFAULT_LOOKASIDE +- "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOOKASIDE), ++ "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL2(SQLITE_DEFAULT_LOOKASIDE), + #endif + #if SQLITE_DEFAULT_MEMSTATUS + "DEFAULT_MEMSTATUS", +@@ -209,8 +215,11 @@ + #if SQLITE_ENABLE_ATOMIC_WRITE + "ENABLE_ATOMIC_WRITE", + #endif ++#if SQLITE_ENABLE_BATCH_ATOMIC_WRITE ++ "ENABLE_BATCH_ATOMIC_WRITE", ++#endif + #if SQLITE_ENABLE_CEROD +- "ENABLE_CEROD", ++ "ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD), + #endif + #if SQLITE_ENABLE_COLUMN_METADATA + "ENABLE_COLUMN_METADATA", +@@ -251,6 +260,9 @@ + #if SQLITE_ENABLE_FTS5 + "ENABLE_FTS5", + #endif ++#if SQLITE_ENABLE_GEOPOLY ++ "ENABLE_GEOPOLY", ++#endif + #if SQLITE_ENABLE_HIDDEN_COLUMNS + "ENABLE_HIDDEN_COLUMNS", + #endif +@@ -281,6 +293,9 @@ + #if SQLITE_ENABLE_MULTIPLEX + "ENABLE_MULTIPLEX", + #endif ++#if SQLITE_ENABLE_NORMALIZE ++ "ENABLE_NORMALIZE", ++#endif + #if SQLITE_ENABLE_NULL_TRIM + "ENABLE_NULL_TRIM", + #endif +@@ -308,6 +323,9 @@ + #if SQLITE_ENABLE_SNAPSHOT + "ENABLE_SNAPSHOT", + #endif ++#if SQLITE_ENABLE_SORTER_REFERENCES ++ "ENABLE_SORTER_REFERENCES", ++#endif + #if SQLITE_ENABLE_SQLLOG + "ENABLE_SQLLOG", + #endif +@@ -828,14 +846,6 @@ + #endif + + /* +-** Make sure that rand_s() is available on Windows systems with MSVC 2005 +-** or higher. +-*/ +-#if defined(_MSC_VER) && _MSC_VER>=1400 +-# define _CRT_RAND_S +-#endif +- +-/* + ** Include the header file used to customize the compiler options for MSVC. + ** This should be done first so that it can successfully prevent spurious + ** compiler warnings due to subsequent content in this file and other files +@@ -1144,15 +1154,17 @@ + ** a string which identifies a particular check-in of SQLite + ** within its configuration management system. ^The SQLITE_SOURCE_ID + ** string contains the date and time of the check-in (UTC) and a SHA1 +-** or SHA3-256 hash of the entire source tree. ++** or SHA3-256 hash of the entire source tree. If the source code has ++** been edited in any way since it was last checked in, then the last ++** four hexadecimal digits of the hash may be modified. + ** + ** See also: [sqlite3_libversion()], + ** [sqlite3_libversion_number()], [sqlite3_sourceid()], + ** [sqlite_version()] and [sqlite_source_id()]. + */ +-#define SQLITE_VERSION "3.20.0" +-#define SQLITE_VERSION_NUMBER 3020000 +-#define SQLITE_SOURCE_ID "2017-08-01 13:24:15 9501e22dfeebdcefa783575e47c60b514d7c2e0cad73b2a496c0bc4b680900a8" ++#define SQLITE_VERSION "3.26.0" ++#define SQLITE_VERSION_NUMBER 3026000 ++#define SQLITE_SOURCE_ID "2018-12-01 12:34:55 bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238b4f9" + + /* + ** CAPI3REF: Run-Time Library Version Numbers +@@ -1168,7 +1180,7 @@ + ** + ** <blockquote><pre> + ** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER ); +-** assert( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)==0 ); ++** assert( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,80)==0 ); + ** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 ); + ** </pre></blockquote>)^ + ** +@@ -1178,9 +1190,11 @@ + ** function is provided for use in DLLs since DLL users usually do not have + ** direct access to string constants within the DLL. ^The + ** sqlite3_libversion_number() function returns an integer equal to +-** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns ++** [SQLITE_VERSION_NUMBER]. ^(The sqlite3_sourceid() function returns + ** a pointer to a string constant whose value is the same as the +-** [SQLITE_SOURCE_ID] C preprocessor macro. ++** [SQLITE_SOURCE_ID] C preprocessor macro. Except if SQLite is built ++** using an edited copy of [the amalgamation], then the last four characters ++** of the hash might be different from [SQLITE_SOURCE_ID].)^ + ** + ** See also: [sqlite_version()] and [sqlite_source_id()]. + */ +@@ -1461,7 +1475,7 @@ + #define SQLITE_FULL 13 /* Insertion failed because database is full */ + #define SQLITE_CANTOPEN 14 /* Unable to open the database file */ + #define SQLITE_PROTOCOL 15 /* Database lock protocol error */ +-#define SQLITE_EMPTY 16 /* Not used */ ++#define SQLITE_EMPTY 16 /* Internal use only */ + #define SQLITE_SCHEMA 17 /* The database schema changed */ + #define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ + #define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ +@@ -1495,6 +1509,9 @@ + ** the most recent error can be obtained using + ** [sqlite3_extended_errcode()]. + */ ++#define SQLITE_ERROR_MISSING_COLLSEQ (SQLITE_ERROR | (1<<8)) ++#define SQLITE_ERROR_RETRY (SQLITE_ERROR | (2<<8)) ++#define SQLITE_ERROR_SNAPSHOT (SQLITE_ERROR | (3<<8)) + #define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) + #define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) + #define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) +@@ -1523,7 +1540,11 @@ + #define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8)) + #define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8)) + #define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28<<8)) ++#define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8)) ++#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8)) ++#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8)) + #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) ++#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) + #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) + #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) + #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) +@@ -1530,11 +1551,15 @@ + #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) + #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) + #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) ++#define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */ + #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) ++#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8)) + #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) + #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) + #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) + #define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8)) ++#define SQLITE_READONLY_CANTINIT (SQLITE_READONLY | (5<<8)) ++#define SQLITE_READONLY_DIRECTORY (SQLITE_READONLY | (6<<8)) + #define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) + #define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8)) + #define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8)) +@@ -1609,6 +1634,11 @@ + ** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on + ** read-only media and cannot be changed even by processes with + ** elevated privileges. ++** ++** The SQLITE_IOCAP_BATCH_ATOMIC property means that the underlying ++** filesystem supports doing multiple write operations atomically when those ++** write operations are bracketed by [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] and ++** [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]. + */ + #define SQLITE_IOCAP_ATOMIC 0x00000001 + #define SQLITE_IOCAP_ATOMIC512 0x00000002 +@@ -1624,6 +1654,7 @@ + #define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800 + #define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000 + #define SQLITE_IOCAP_IMMUTABLE 0x00002000 ++#define SQLITE_IOCAP_BATCH_ATOMIC 0x00004000 + + /* + ** CAPI3REF: File Locking Levels +@@ -1758,6 +1789,7 @@ + ** <li> [SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN] + ** <li> [SQLITE_IOCAP_POWERSAFE_OVERWRITE] + ** <li> [SQLITE_IOCAP_IMMUTABLE] ++** <li> [SQLITE_IOCAP_BATCH_ATOMIC] + ** </ul> + ** + ** The SQLITE_IOCAP_ATOMIC property means that all writes of +@@ -1895,7 +1927,8 @@ + ** <li>[[SQLITE_FCNTL_PERSIST_WAL]] + ** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the + ** persistent [WAL | Write Ahead Log] setting. By default, the auxiliary +-** write ahead log and shared memory files used for transaction control ++** write ahead log ([WAL file]) and shared memory ++** files used for transaction control + ** are automatically deleted when the latest connection to the database + ** closes. Setting persistent WAL mode causes those files to persist after + ** close. Persisting the files is useful when other processes that do not +@@ -2041,6 +2074,66 @@ + ** The [SQLITE_FCNTL_RBU] opcode is implemented by the special VFS used by + ** the RBU extension only. All other VFS should return SQLITE_NOTFOUND for + ** this opcode. ++** ++** <li>[[SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]] ++** If the [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] opcode returns SQLITE_OK, then ++** the file descriptor is placed in "batch write mode", which ++** means all subsequent write operations will be deferred and done ++** atomically at the next [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]. Systems ++** that do not support batch atomic writes will return SQLITE_NOTFOUND. ++** ^Following a successful SQLITE_FCNTL_BEGIN_ATOMIC_WRITE and prior to ++** the closing [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] or ++** [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE], SQLite will make ++** no VFS interface calls on the same [sqlite3_file] file descriptor ++** except for calls to the xWrite method and the xFileControl method ++** with [SQLITE_FCNTL_SIZE_HINT]. ++** ++** <li>[[SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]] ++** The [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] opcode causes all write ++** operations since the previous successful call to ++** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be performed atomically. ++** This file control returns [SQLITE_OK] if and only if the writes were ++** all performed successfully and have been committed to persistent storage. ++** ^Regardless of whether or not it is successful, this file control takes ++** the file descriptor out of batch write mode so that all subsequent ++** write operations are independent. ++** ^SQLite will never invoke SQLITE_FCNTL_COMMIT_ATOMIC_WRITE without ++** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]. ++** ++** <li>[[SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE]] ++** The [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE] opcode causes all write ++** operations since the previous successful call to ++** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be rolled back. ++** ^This file control takes the file descriptor out of batch write mode ++** so that all subsequent write operations are independent. ++** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without ++** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]. ++** ++** <li>[[SQLITE_FCNTL_LOCK_TIMEOUT]] ++** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode causes attempts to obtain ++** a file lock using the xLock or xShmLock methods of the VFS to wait ++** for up to M milliseconds before failing, where M is the single ++** unsigned integer parameter. ++** ++** <li>[[SQLITE_FCNTL_DATA_VERSION]] ++** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to ++** a database file. The argument is a pointer to a 32-bit unsigned integer. ++** The "data version" for the pager is written into the pointer. The ++** "data version" changes whenever any change occurs to the corresponding ++** database file, either through SQL statements on the same database ++** connection or through transactions committed by separate database ++** connections possibly in other processes. The [sqlite3_total_changes()] ++** interface can be used to find if any database on the connection has changed, ++** but that interface responds to changes on TEMP as well as MAIN and does ++** not provide a mechanism to detect changes to MAIN only. Also, the ++** [sqlite3_total_changes()] interface responds to internal changes only and ++** omits changes made by other database connections. The ++** [PRAGMA data_version] command provide a mechanism to detect changes to ++** a single attached database that occur due to other database connections, ++** but omits changes implemented by the database connection on which it is ++** called. This file control is the only mechanism to detect changes that ++** happen either internally or externally and that are associated with ++** a particular attached database. + ** </ul> + */ + #define SQLITE_FCNTL_LOCKSTATE 1 +@@ -2072,6 +2165,11 @@ + #define SQLITE_FCNTL_JOURNAL_POINTER 28 + #define SQLITE_FCNTL_WIN32_GET_HANDLE 29 + #define SQLITE_FCNTL_PDB 30 ++#define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE 31 ++#define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32 ++#define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33 ++#define SQLITE_FCNTL_LOCK_TIMEOUT 34 ++#define SQLITE_FCNTL_DATA_VERSION 35 + + /* deprecated names */ + #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE +@@ -2109,12 +2207,18 @@ + ** in the name of the object stands for "virtual file system". See + ** the [VFS | VFS documentation] for further information. + ** +-** The value of the iVersion field is initially 1 but may be larger in +-** future versions of SQLite. Additional fields may be appended to this +-** object when the iVersion value is increased. Note that the structure +-** of the sqlite3_vfs object changes in the transaction between +-** SQLite version 3.5.9 and 3.6.0 and yet the iVersion field was not +-** modified. ++** The VFS interface is sometimes extended by adding new methods onto ++** the end. Each time such an extension occurs, the iVersion field ++** is incremented. The iVersion value started out as 1 in ++** SQLite [version 3.5.0] on [dateof:3.5.0], then increased to 2 ++** with SQLite [version 3.7.0] on [dateof:3.7.0], and then increased ++** to 3 with SQLite [version 3.7.6] on [dateof:3.7.6]. Additional fields ++** may be appended to the sqlite3_vfs object and the iVersion value ++** may increase again in future versions of SQLite. ++** Note that the structure ++** of the sqlite3_vfs object changes in the transition from ++** SQLite [version 3.5.9] to [version 3.6.0] on [dateof:3.6.0] ++** and yet the iVersion field was not modified. + ** + ** The szOsFile field is the size of the subclassed [sqlite3_file] + ** structure used by this VFS. mxPathname is the maximum length of +@@ -2642,6 +2746,16 @@ + ** routines with a wrapper that simulations memory allocation failure or + ** tracks memory usage, for example. </dd> + ** ++** [[SQLITE_CONFIG_SMALL_MALLOC]] <dt>SQLITE_CONFIG_SMALL_MALLOC</dt> ++** <dd> ^The SQLITE_CONFIG_SMALL_MALLOC option takes single argument of ++** type int, interpreted as a boolean, which if true provides a hint to ++** SQLite that it should avoid large memory allocations if possible. ++** SQLite will run faster if it is free to make large memory allocations, ++** but some application might prefer to run slower in exchange for ++** guarantees about memory fragmentation that are possible if large ++** allocations are avoided. This hint is normally off. ++** </dd> ++** + ** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt> + ** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int, + ** interpreted as a boolean, which enables or disables the collection of +@@ -2659,25 +2773,7 @@ + ** </dd> + ** + ** [[SQLITE_CONFIG_SCRATCH]] <dt>SQLITE_CONFIG_SCRATCH</dt> +-** <dd> ^The SQLITE_CONFIG_SCRATCH option specifies a static memory buffer +-** that SQLite can use for scratch memory. ^(There are three arguments +-** to SQLITE_CONFIG_SCRATCH: A pointer an 8-byte +-** aligned memory buffer from which the scratch allocations will be +-** drawn, the size of each scratch allocation (sz), +-** and the maximum number of scratch allocations (N).)^ +-** The first argument must be a pointer to an 8-byte aligned buffer +-** of at least sz*N bytes of memory. +-** ^SQLite will not use more than one scratch buffers per thread. +-** ^SQLite will never request a scratch buffer that is more than 6 +-** times the database page size. +-** ^If SQLite needs needs additional +-** scratch memory beyond what is provided by this configuration option, then +-** [sqlite3_malloc()] will be used to obtain the memory needed.<p> +-** ^When the application provides any amount of scratch memory using +-** SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary large +-** [sqlite3_malloc|heap allocations]. +-** This can help [Robson proof|prevent memory allocation failures] due to heap +-** fragmentation in low-memory embedded systems. ++** <dd> The SQLITE_CONFIG_SCRATCH option is no longer used. + ** </dd> + ** + ** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt> +@@ -2713,8 +2809,7 @@ + ** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt> + ** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer + ** that SQLite will use for all of its dynamic memory allocation needs +-** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and +-** [SQLITE_CONFIG_PAGECACHE]. ++** beyond those provided for by [SQLITE_CONFIG_PAGECACHE]. + ** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled + ** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns + ** [SQLITE_ERROR] if invoked otherwise. +@@ -2900,6 +2995,22 @@ + ** I/O required to support statement rollback. + ** The default value for this setting is controlled by the + ** [SQLITE_STMTJRNL_SPILL] compile-time option. ++** ++** [[SQLITE_CONFIG_SORTERREF_SIZE]] ++** <dt>SQLITE_CONFIG_SORTERREF_SIZE ++** <dd>The SQLITE_CONFIG_SORTERREF_SIZE option accepts a single parameter ++** of type (int) - the new value of the sorter-reference size threshold. ++** Usually, when SQLite uses an external sort to order records according ++** to an ORDER BY clause, all fields required by the caller are present in the ++** sorted records. However, if SQLite determines based on the declared type ++** of a table column that its values are likely to be very large - larger ++** than the configured sorter-reference size threshold - then a reference ++** is stored in each sorted record and the required column values loaded ++** from the database as records are returned in sorted order. The default ++** value for this option is to never use this optimization. Specifying a ++** negative value for this option restores the default behaviour. ++** This option is only available if SQLite is compiled with the ++** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option. + ** </dl> + */ + #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ +@@ -2907,7 +3018,7 @@ + #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ + #define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ + #define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */ +-#define SQLITE_CONFIG_SCRATCH 6 /* void*, int sz, int N */ ++#define SQLITE_CONFIG_SCRATCH 6 /* No longer used */ + #define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */ + #define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */ + #define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */ +@@ -2928,6 +3039,8 @@ + #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */ + #define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */ + #define SQLITE_CONFIG_STMTJRNL_SPILL 26 /* int nByte */ ++#define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */ ++#define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */ + + /* + ** CAPI3REF: Database Connection Configuration Options +@@ -2943,6 +3056,7 @@ + ** is invoked. + ** + ** <dl> ++** [[SQLITE_DBCONFIG_LOOKASIDE]] + ** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt> + ** <dd> ^This option takes three additional arguments that determine the + ** [lookaside memory allocator] configuration for the [database connection]. +@@ -2965,6 +3079,7 @@ + ** memory is in use leaves the configuration unchanged and returns + ** [SQLITE_BUSY].)^</dd> + ** ++** [[SQLITE_DBCONFIG_ENABLE_FKEY]] + ** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt> + ** <dd> ^This option is used to enable or disable the enforcement of + ** [foreign key constraints]. There should be two additional arguments. +@@ -2975,6 +3090,7 @@ + ** following this call. The second parameter may be a NULL pointer, in + ** which case the FK enforcement setting is not reported back. </dd> + ** ++** [[SQLITE_DBCONFIG_ENABLE_TRIGGER]] + ** <dt>SQLITE_DBCONFIG_ENABLE_TRIGGER</dt> + ** <dd> ^This option is used to enable or disable [CREATE TRIGGER | triggers]. + ** There should be two additional arguments. +@@ -2985,6 +3101,7 @@ + ** following this call. The second parameter may be a NULL pointer, in + ** which case the trigger setting is not reported back. </dd> + ** ++** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]] + ** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt> + ** <dd> ^This option is used to enable or disable the two-argument + ** version of the [fts3_tokenizer()] function which is part of the +@@ -2998,6 +3115,7 @@ + ** following this call. The second parameter may be a NULL pointer, in + ** which case the new setting is not reported back. </dd> + ** ++** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]] + ** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt> + ** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()] + ** interface independently of the [load_extension()] SQL function. +@@ -3015,7 +3133,7 @@ + ** be a NULL pointer, in which case the new setting is not reported back. + ** </dd> + ** +-** <dt>SQLITE_DBCONFIG_MAINDBNAME</dt> ++** [[SQLITE_DBCONFIG_MAINDBNAME]] <dt>SQLITE_DBCONFIG_MAINDBNAME</dt> + ** <dd> ^This option is used to change the name of the "main" database + ** schema. ^The sole argument is a pointer to a constant UTF8 string + ** which will become the new schema name in place of "main". ^SQLite +@@ -3024,6 +3142,7 @@ + ** until after the database connection closes. + ** </dd> + ** ++** [[SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE]] + ** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt> + ** <dd> Usually, when a database in wal mode is closed or detached from a + ** database handle, SQLite checks if this will mean that there are now no +@@ -3030,13 +3149,14 @@ + ** connections at all to the database. If so, it performs a checkpoint + ** operation before closing the connection. This option may be used to + ** override this behaviour. The first parameter passed to this operation +-** is an integer - non-zero to disable checkpoints-on-close, or zero (the +-** default) to enable them. The second parameter is a pointer to an integer ++** is an integer - positive to disable checkpoints-on-close, or zero (the ++** default) to enable them, and negative to leave the setting unchanged. ++** The second parameter is a pointer to an integer + ** into which is written 0 or 1 to indicate whether checkpoints-on-close + ** have been disabled - 0 if they are not disabled, 1 if they are. + ** </dd> + ** +-** <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt> ++** [[SQLITE_DBCONFIG_ENABLE_QPSG]] <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt> + ** <dd>^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates + ** the [query planner stability guarantee] (QPSG). When the QPSG is active, + ** a single SQL query statement will always use the same algorithm regardless +@@ -3045,8 +3165,57 @@ + ** slower. But the QPSG has the advantage of more predictable behavior. With + ** the QPSG active, SQLite will always use the same query plan in the field as + ** was used during testing in the lab. ++** The first argument to this setting is an integer which is 0 to disable ++** the QPSG, positive to enable QPSG, or negative to leave the setting ++** unchanged. The second parameter is a pointer to an integer into which ++** is written 0 or 1 to indicate whether the QPSG is disabled or enabled ++** following this call. + ** </dd> + ** ++** [[SQLITE_DBCONFIG_TRIGGER_EQP]] <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt> ++** <dd> By default, the output of EXPLAIN QUERY PLAN commands does not ++** include output for any operations performed by trigger programs. This ++** option is used to set or clear (the default) a flag that governs this ++** behavior. The first parameter passed to this operation is an integer - ++** positive to enable output for trigger programs, or zero to disable it, ++** or negative to leave the setting unchanged. ++** The second parameter is a pointer to an integer into which is written ++** 0 or 1 to indicate whether output-for-triggers has been disabled - 0 if ++** it is not disabled, 1 if it is. ++** </dd> ++** ++** [[SQLITE_DBCONFIG_RESET_DATABASE]] <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt> ++** <dd> Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run ++** [VACUUM] in order to reset a database back to an empty database ++** with no schema and no content. The following process works even for ++** a badly corrupted database file: ++** <ol> ++** <li> If the database connection is newly opened, make sure it has read the ++** database schema by preparing then discarding some query against the ++** database, or calling sqlite3_table_column_metadata(), ignoring any ++** errors. This step is only necessary if the application desires to keep ++** the database in WAL mode after the reset if it was in WAL mode before ++** the reset. ++** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0); ++** <li> [sqlite3_exec](db, "[VACUUM]", 0, 0, 0); ++** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0); ++** </ol> ++** Because resetting a database is destructive and irreversible, the ++** process requires the use of this obscure API and multiple steps to help ++** ensure that it does not happen by accident. ++** ++** [[SQLITE_DBCONFIG_DEFENSIVE]] <dt>SQLITE_DBCONFIG_DEFENSIVE</dt> ++** <dd>The SQLITE_DBCONFIG_DEFENSIVE option activates or deactivates the ++** "defensive" flag for a database connection. When the defensive ++** flag is enabled, language features that allow ordinary SQL to ++** deliberately corrupt the database file are disabled. The disabled ++** features include but are not limited to the following: ++** <ul> ++** <li> The [PRAGMA writable_schema=ON] statement. ++** <li> Writes to the [sqlite_dbpage] virtual table. ++** <li> Direct writes to [shadow tables]. ++** </ul> ++** </dd> + ** </dl> + */ + #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ +@@ -3057,8 +3226,11 @@ + #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_MAX 1010 /* Largest DBCONFIG */ + +- + /* + ** CAPI3REF: Enable Or Disable Extended Result Codes + ** METHOD: sqlite3 +@@ -3185,12 +3357,17 @@ + ** program, the value returned reflects the number of rows modified by the + ** previous INSERT, UPDATE or DELETE statement within the same trigger. + ** +-** See also the [sqlite3_total_changes()] interface, the +-** [count_changes pragma], and the [changes() SQL function]. +-** + ** If a separate thread makes changes on the same database connection + ** while [sqlite3_changes()] is running then the value returned + ** is unpredictable and not meaningful. ++** ++** See also: ++** <ul> ++** <li> the [sqlite3_total_changes()] interface ++** <li> the [count_changes pragma] ++** <li> the [changes() SQL function] ++** <li> the [data_version pragma] ++** </ul> + */ + SQLITE_API int sqlite3_changes(sqlite3*); + +@@ -3208,13 +3385,26 @@ + ** count, but those made as part of REPLACE constraint resolution are + ** not. ^Changes to a view that are intercepted by INSTEAD OF triggers + ** are not counted. ++** ++** This the [sqlite3_total_changes(D)] interface only reports the number ++** of rows that changed due to SQL statement run against database ++** connection D. Any changes by other database connections are ignored. ++** To detect changes against a database file from other database ++** connections use the [PRAGMA data_version] command or the ++** [SQLITE_FCNTL_DATA_VERSION] [file control]. + ** +-** See also the [sqlite3_changes()] interface, the +-** [count_changes pragma], and the [total_changes() SQL function]. +-** + ** If a separate thread makes changes on the same database connection + ** while [sqlite3_total_changes()] is running then the value + ** returned is unpredictable and not meaningful. ++** ++** See also: ++** <ul> ++** <li> the [sqlite3_changes()] interface ++** <li> the [count_changes pragma] ++** <li> the [changes() SQL function] ++** <li> the [data_version pragma] ++** <li> the [SQLITE_FCNTL_DATA_VERSION] [file control] ++** </ul> + */ + SQLITE_API int sqlite3_total_changes(sqlite3*); + +@@ -3463,16 +3653,16 @@ + ** + ** These routines are work-alikes of the "printf()" family of functions + ** from the standard C library. +-** These routines understand most of the common K&R formatting options, +-** plus some additional non-standard formats, detailed below. +-** Note that some of the more obscure formatting options from recent +-** C-library standards are omitted from this implementation. ++** These routines understand most of the common formatting options from ++** the standard library printf() ++** plus some additional non-standard formats ([%q], [%Q], [%w], and [%z]). ++** See the [built-in printf()] documentation for details. + ** + ** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their +-** results into memory obtained from [sqlite3_malloc()]. ++** results into memory obtained from [sqlite3_malloc64()]. + ** The strings returned by these two routines should be + ** released by [sqlite3_free()]. ^Both routines return a +-** NULL pointer if [sqlite3_malloc()] is unable to allocate enough ++** NULL pointer if [sqlite3_malloc64()] is unable to allocate enough + ** memory to hold the resulting string. + ** + ** ^(The sqlite3_snprintf() routine is similar to "snprintf()" from +@@ -3496,71 +3686,7 @@ + ** + ** ^The sqlite3_vsnprintf() routine is a varargs version of sqlite3_snprintf(). + ** +-** These routines all implement some additional formatting +-** options that are useful for constructing SQL statements. +-** All of the usual printf() formatting options apply. In addition, there +-** is are "%q", "%Q", "%w" and "%z" options. +-** +-** ^(The %q option works like %s in that it substitutes a nul-terminated +-** string from the argument list. But %q also doubles every '\'' character. +-** %q is designed for use inside a string literal.)^ By doubling each '\'' +-** character it escapes that character and allows it to be inserted into +-** the string. +-** +-** For example, assume the string variable zText contains text as follows: +-** +-** <blockquote><pre> +-** char *zText = "It's a happy day!"; +-** </pre></blockquote> +-** +-** One can use this text in an SQL statement as follows: +-** +-** <blockquote><pre> +-** char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText); +-** sqlite3_exec(db, zSQL, 0, 0, 0); +-** sqlite3_free(zSQL); +-** </pre></blockquote> +-** +-** Because the %q format string is used, the '\'' character in zText +-** is escaped and the SQL generated is as follows: +-** +-** <blockquote><pre> +-** INSERT INTO table1 VALUES('It''s a happy day!') +-** </pre></blockquote> +-** +-** This is correct. Had we used %s instead of %q, the generated SQL +-** would have looked like this: +-** +-** <blockquote><pre> +-** INSERT INTO table1 VALUES('It's a happy day!'); +-** </pre></blockquote> +-** +-** This second example is an SQL syntax error. As a general rule you should +-** always use %q instead of %s when inserting text into a string literal. +-** +-** ^(The %Q option works like %q except it also adds single quotes around +-** the outside of the total string. Additionally, if the parameter in the +-** argument list is a NULL pointer, %Q substitutes the text "NULL" (without +-** single quotes).)^ So, for example, one could say: +-** +-** <blockquote><pre> +-** char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText); +-** sqlite3_exec(db, zSQL, 0, 0, 0); +-** sqlite3_free(zSQL); +-** </pre></blockquote> +-** +-** The code above will render a correct SQL statement in the zSQL +-** variable even if the zText variable is a NULL pointer. +-** +-** ^(The "%w" formatting option is like "%q" except that it expects to +-** be contained within double-quotes instead of single quotes, and it +-** escapes the double-quote character instead of the single-quote +-** character.)^ The "%w" formatting option is intended for safely inserting +-** table and column names into a constructed SQL statement. +-** +-** ^(The "%z" formatting option works like "%s" but with the +-** addition that after the string has been read and copied into +-** the result, [sqlite3_free()] is called on the input string.)^ ++** See also: [built-in printf()], [printf() SQL function] + */ + SQLITE_API char *sqlite3_mprintf(const char*,...); + SQLITE_API char *sqlite3_vmprintf(const char*, va_list); +@@ -3918,8 +4044,8 @@ + ** KEYWORDS: SQLITE_TRACE + ** + ** These constants identify classes of events that can be monitored +-** using the [sqlite3_trace_v2()] tracing logic. The third argument +-** to [sqlite3_trace_v2()] is an OR-ed combination of one or more of ++** using the [sqlite3_trace_v2()] tracing logic. The M argument ++** to [sqlite3_trace_v2(D,M,X,P)] is an OR-ed combination of one or more of + ** the following constants. ^The first argument to the trace callback + ** is one of the following constants. + ** +@@ -4128,10 +4254,10 @@ + ** ^If [URI filename] interpretation is enabled, and the filename argument + ** begins with "file:", then the filename is interpreted as a URI. ^URI + ** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is +-** set in the fourth argument to sqlite3_open_v2(), or if it has ++** set in the third argument to sqlite3_open_v2(), or if it has + ** been enabled globally using the [SQLITE_CONFIG_URI] option with the + ** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option. +-** As of SQLite version 3.7.7, URI filename interpretation is turned off ++** URI filename interpretation is turned off + ** by default, but future releases of SQLite might enable URI filename + ** interpretation by default. See "[URI filenames]" for additional + ** information. +@@ -4334,13 +4460,24 @@ + ** [database connection] D failed, then the sqlite3_errcode(D) interface + ** returns the numeric [result code] or [extended result code] for that + ** API call. +-** If the most recent API call was successful, +-** then the return value from sqlite3_errcode() is undefined. + ** ^The sqlite3_extended_errcode() + ** interface is the same except that it always returns the + ** [extended result code] even when extended result codes are + ** disabled. + ** ++** The values returned by sqlite3_errcode() and/or ++** sqlite3_extended_errcode() might change with each API call. ++** Except, there are some interfaces that are guaranteed to never ++** change the value of the error code. The error-code preserving ++** interfaces are: ++** ++** <ul> ++** <li> sqlite3_errcode() ++** <li> sqlite3_extended_errcode() ++** <li> sqlite3_errmsg() ++** <li> sqlite3_errmsg16() ++** </ul> ++** + ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language + ** text that describes the error, as either UTF-8 or UTF-16 respectively. + ** ^(Memory to hold the error message string is managed internally. +@@ -4530,9 +4667,19 @@ + ** on this hint by avoiding the use of [lookaside memory] so as not to + ** deplete the limited store of lookaside memory. Future versions of + ** SQLite may act on this hint differently. ++** ++** [[SQLITE_PREPARE_NORMALIZE]] ^(<dt>SQLITE_PREPARE_NORMALIZE</dt> ++** <dd>The SQLITE_PREPARE_NORMALIZE flag indicates that a normalized ++** representation of the SQL statement should be calculated and then ++** associated with the prepared statement, which can be obtained via ++** the [sqlite3_normalized_sql()] interface.)^ The semantics used to ++** normalize a SQL statement are unspecified and subject to change. ++** At a minimum, literal values will be replaced with suitable ++** placeholders. + ** </dl> + */ + #define SQLITE_PREPARE_PERSISTENT 0x01 ++#define SQLITE_PREPARE_NORMALIZE 0x02 + + /* + ** CAPI3REF: Compiling An SQL Statement +@@ -4626,6 +4773,7 @@ + ** or [GLOB] operator or if the parameter is compared to an indexed column + ** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled. + ** </li> ++** </ol> + ** + ** <p>^sqlite3_prepare_v3() differs from sqlite3_prepare_v2() only in having + ** the extra prepFlags parameter, which is a bit array consisting of zero or +@@ -4632,7 +4780,6 @@ + ** more of the [SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_*] flags. ^The + ** sqlite3_prepare_v2() interface works exactly the same as + ** sqlite3_prepare_v3() with a zero prepFlags parameter. +-** </ol> + */ + SQLITE_API int sqlite3_prepare( + sqlite3 *db, /* Database handle */ +@@ -4690,6 +4837,11 @@ + ** ^The sqlite3_expanded_sql(P) interface returns a pointer to a UTF-8 + ** string containing the SQL text of prepared statement P with + ** [bound parameters] expanded. ++** ^The sqlite3_normalized_sql(P) interface returns a pointer to a UTF-8 ++** string containing the normalized SQL text of prepared statement P. The ++** semantics used to normalize a SQL statement are unspecified and subject ++** to change. At a minimum, literal values will be replaced with suitable ++** placeholders. + ** + ** ^(For example, if a prepared statement is created using the SQL + ** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345 +@@ -4705,8 +4857,9 @@ + ** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time + ** option causes sqlite3_expanded_sql() to always return NULL. + ** +-** ^The string returned by sqlite3_sql(P) is managed by SQLite and is +-** automatically freed when the prepared statement is finalized. ++** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P) ++** are managed by SQLite and are automatically freed when the prepared ++** statement is finalized. + ** ^The string returned by sqlite3_expanded_sql(P), on the other hand, + ** is obtained from [sqlite3_malloc()] and must be free by the application + ** by passing it to [sqlite3_free()]. +@@ -4713,6 +4866,7 @@ + */ + SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); + SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt); ++SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt); + + /* + ** CAPI3REF: Determine If An SQL Statement Writes The Database +@@ -4805,8 +4959,9 @@ + ** implementation of [application-defined SQL functions] are protected. + ** ^The sqlite3_value object returned by + ** [sqlite3_column_value()] is unprotected. +-** Unprotected sqlite3_value objects may only be used with +-** [sqlite3_result_value()] and [sqlite3_bind_value()]. ++** Unprotected sqlite3_value objects may only be used as arguments ++** to [sqlite3_result_value()], [sqlite3_bind_value()], and ++** [sqlite3_value_dup()]. + ** The [sqlite3_value_blob | sqlite3_value_type()] family of + ** interfaces require protected sqlite3_value objects. + */ +@@ -5228,7 +5383,7 @@ + ** other than [SQLITE_ROW] before any subsequent invocation of + ** sqlite3_step(). Failure to reset the prepared statement using + ** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from +-** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1]), ++** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1], + ** sqlite3_step() began + ** calling [sqlite3_reset()] automatically in this circumstance rather + ** than returning [SQLITE_MISUSE]. This is not considered a compatibility +@@ -5493,11 +5648,25 @@ + ** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into + ** [sqlite3_free()]. + ** +-** ^(If a memory allocation error occurs during the evaluation of any +-** of these routines, a default value is returned. The default value +-** is either the integer 0, the floating point number 0.0, or a NULL +-** pointer. Subsequent calls to [sqlite3_errcode()] will return +-** [SQLITE_NOMEM].)^ ++** As long as the input parameters are correct, these routines will only ++** fail if an out-of-memory error occurs during a format conversion. ++** Only the following subset of interfaces are subject to out-of-memory ++** errors: ++** ++** <ul> ++** <li> sqlite3_column_blob() ++** <li> sqlite3_column_text() ++** <li> sqlite3_column_text16() ++** <li> sqlite3_column_bytes() ++** <li> sqlite3_column_bytes16() ++** </ul> ++** ++** If an out-of-memory error occurs, then the return value from these ++** routines is the same as if the column had contained an SQL NULL value. ++** Valid SQL NULL returns can be distinguished from out-of-memory errors ++** by invoking the [sqlite3_errcode()] immediately after the suspect ++** return value is obtained and before any ++** other SQLite interface is called on the same [database connection]. + */ + SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); + SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol); +@@ -5574,11 +5743,13 @@ + ** + ** ^These functions (collectively known as "function creation routines") + ** are used to add SQL functions or aggregates or to redefine the behavior +-** of existing SQL functions or aggregates. The only differences between +-** these routines are the text encoding expected for +-** the second parameter (the name of the function being created) +-** and the presence or absence of a destructor callback for +-** the application data pointer. ++** of existing SQL functions or aggregates. The only differences between ++** the three "sqlite3_create_function*" routines are the text encoding ++** expected for the second parameter (the name of the function being ++** created) and the presence or absence of a destructor callback for ++** the application data pointer. Function sqlite3_create_window_function() ++** is similar, but allows the user to supply the extra callback functions ++** needed by [aggregate window functions]. + ** + ** ^The first parameter is the [database connection] to which the SQL + ** function is to be added. ^If an application uses more than one database +@@ -5624,7 +5795,8 @@ + ** ^(The fifth parameter is an arbitrary pointer. The implementation of the + ** function can gain access to this pointer using [sqlite3_user_data()].)^ + ** +-** ^The sixth, seventh and eighth parameters, xFunc, xStep and xFinal, are ++** ^The sixth, seventh and eighth parameters passed to the three ++** "sqlite3_create_function*" functions, xFunc, xStep and xFinal, are + ** pointers to C-language functions that implement the SQL function or + ** aggregate. ^A scalar SQL function requires an implementation of the xFunc + ** callback only; NULL pointers must be passed as the xStep and xFinal +@@ -5633,16 +5805,25 @@ + ** SQL function or aggregate, pass NULL pointers for all three function + ** callbacks. + ** +-** ^(If the ninth parameter to sqlite3_create_function_v2() is not NULL, +-** then it is destructor for the application data pointer. +-** The destructor is invoked when the function is deleted, either by being +-** overloaded or when the database connection closes.)^ +-** ^The destructor is also invoked if the call to +-** sqlite3_create_function_v2() fails. +-** ^When the destructor callback of the tenth parameter is invoked, it +-** is passed a single argument which is a copy of the application data +-** pointer which was the fifth parameter to sqlite3_create_function_v2(). ++** ^The sixth, seventh, eighth and ninth parameters (xStep, xFinal, xValue ++** and xInverse) passed to sqlite3_create_window_function are pointers to ++** C-language callbacks that implement the new function. xStep and xFinal ++** must both be non-NULL. xValue and xInverse may either both be NULL, in ++** which case a regular aggregate function is created, or must both be ++** non-NULL, in which case the new function may be used as either an aggregate ++** or aggregate window function. More details regarding the implementation ++** of aggregate window functions are ++** [user-defined window functions|available here]. + ** ++** ^(If the final parameter to sqlite3_create_function_v2() or ++** sqlite3_create_window_function() is not NULL, then it is destructor for ++** the application data pointer. The destructor is invoked when the function ++** is deleted, either by being overloaded or when the database connection ++** closes.)^ ^The destructor is also invoked if the call to ++** sqlite3_create_function_v2() fails. ^When the destructor callback is ++** invoked, it is passed a single argument which is a copy of the application ++** data pointer which was the fifth parameter to sqlite3_create_function_v2(). ++** + ** ^It is permitted to register multiple implementations of the same + ** functions with the same name but with either differing numbers of + ** arguments or differing preferred text encodings. ^SQLite will use +@@ -5694,6 +5875,18 @@ + void (*xFinal)(sqlite3_context*), + void(*xDestroy)(void*) + ); ++SQLITE_API int sqlite3_create_window_function( ++ sqlite3 *db, ++ const char *zFunctionName, ++ int nArg, ++ int eTextRep, ++ void *pApp, ++ void (*xStep)(sqlite3_context*,int,sqlite3_value**), ++ void (*xFinal)(sqlite3_context*), ++ void (*xValue)(sqlite3_context*), ++ void (*xInverse)(sqlite3_context*,int,sqlite3_value**), ++ void(*xDestroy)(void*) ++); + + /* + ** CAPI3REF: Text Encodings +@@ -5764,6 +5957,9 @@ + ** datatype of the value + ** <tr><td><b>sqlite3_value_numeric_type </b> + ** <td>→ <td>Best numeric datatype of the value ++** <tr><td><b>sqlite3_value_nochange </b> ++** <td>→ <td>True if the column is unchanged in an UPDATE ++** against a virtual table. + ** </table></blockquote> + ** + ** <b>Details:</b> +@@ -5812,6 +6008,19 @@ + ** then the conversion is performed. Otherwise no conversion occurs. + ** The [SQLITE_INTEGER | datatype] after conversion is returned.)^ + ** ++** ^Within the [xUpdate] method of a [virtual table], the ++** sqlite3_value_nochange(X) interface returns true if and only if ++** the column corresponding to X is unchanged by the UPDATE operation ++** that the xUpdate method call was invoked to implement and if ++** and the prior [xColumn] method call that was invoked to extracted ++** the value for that column returned without setting a result (probably ++** because it queried [sqlite3_vtab_nochange()] and found that the column ++** was unchanging). ^Within an [xUpdate] method, any value for which ++** sqlite3_value_nochange(X) is true will in all other respects appear ++** to be a NULL value. If sqlite3_value_nochange(X) is invoked anywhere other ++** than within an [xUpdate] method call for an UPDATE statement, then ++** the return value is arbitrary and meaningless. ++** + ** Please pay particular attention to the fact that the pointer returned + ** from [sqlite3_value_blob()], [sqlite3_value_text()], or + ** [sqlite3_value_text16()] can be invalidated by a subsequent call to +@@ -5820,6 +6029,28 @@ + ** + ** These routines must be called from the same thread as + ** the SQL function that supplied the [sqlite3_value*] parameters. ++** ++** As long as the input parameter is correct, these routines can only ++** fail if an out-of-memory error occurs during a format conversion. ++** Only the following subset of interfaces are subject to out-of-memory ++** errors: ++** ++** <ul> ++** <li> sqlite3_value_blob() ++** <li> sqlite3_value_text() ++** <li> sqlite3_value_text16() ++** <li> sqlite3_value_text16le() ++** <li> sqlite3_value_text16be() ++** <li> sqlite3_value_bytes() ++** <li> sqlite3_value_bytes16() ++** </ul> ++** ++** If an out-of-memory error occurs, then the return value from these ++** routines is the same as if the column had contained an SQL NULL value. ++** Valid SQL NULL returns can be distinguished from out-of-memory errors ++** by invoking the [sqlite3_errcode()] immediately after the suspect ++** return value is obtained and before any ++** other SQLite interface is called on the same [database connection]. + */ + SQLITE_API const void *sqlite3_value_blob(sqlite3_value*); + SQLITE_API double sqlite3_value_double(sqlite3_value*); +@@ -5834,6 +6065,7 @@ + SQLITE_API int sqlite3_value_bytes16(sqlite3_value*); + SQLITE_API int sqlite3_value_type(sqlite3_value*); + SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); ++SQLITE_API int sqlite3_value_nochange(sqlite3_value*); + + /* + ** CAPI3REF: Finding The Subtype Of SQL Values +@@ -6490,6 +6722,41 @@ + SQLITE_API char *sqlite3_data_directory; + + /* ++** CAPI3REF: Win32 Specific Interface ++** ++** These interfaces are available only on Windows. The ++** [sqlite3_win32_set_directory] interface is used to set the value associated ++** with the [sqlite3_temp_directory] or [sqlite3_data_directory] variable, to ++** zValue, depending on the value of the type parameter. The zValue parameter ++** should be NULL to cause the previous value to be freed via [sqlite3_free]; ++** a non-NULL value will be copied into memory obtained from [sqlite3_malloc] ++** prior to being used. The [sqlite3_win32_set_directory] interface returns ++** [SQLITE_OK] to indicate success, [SQLITE_ERROR] if the type is unsupported, ++** or [SQLITE_NOMEM] if memory could not be allocated. The value of the ++** [sqlite3_data_directory] variable is intended to act as a replacement for ++** the current directory on the sub-platforms of Win32 where that concept is ++** not present, e.g. WinRT and UWP. The [sqlite3_win32_set_directory8] and ++** [sqlite3_win32_set_directory16] interfaces behave exactly the same as the ++** sqlite3_win32_set_directory interface except the string parameter must be ++** UTF-8 or UTF-16, respectively. ++*/ ++SQLITE_API int sqlite3_win32_set_directory( ++ unsigned long type, /* Identifier for directory being set or reset */ ++ void *zValue /* New value for directory being set or reset */ ++); ++SQLITE_API int sqlite3_win32_set_directory8(unsigned long type, const char *zValue); ++SQLITE_API int sqlite3_win32_set_directory16(unsigned long type, const void *zValue); ++ ++/* ++** CAPI3REF: Win32 Directory Types ++** ++** These macros are only available on Windows. They define the allowed values ++** for the type argument to the [sqlite3_win32_set_directory] interface. ++*/ ++#define SQLITE_WIN32_DATA_DIRECTORY_TYPE 1 ++#define SQLITE_WIN32_TEMP_DIRECTORY_TYPE 2 ++ ++/* + ** CAPI3REF: Test For Auto-Commit Mode + ** KEYWORDS: {autocommit mode} + ** METHOD: sqlite3 +@@ -7089,6 +7356,9 @@ + int (*xSavepoint)(sqlite3_vtab *pVTab, int); + int (*xRelease)(sqlite3_vtab *pVTab, int); + int (*xRollbackTo)(sqlite3_vtab *pVTab, int); ++ /* The methods above are in versions 1 and 2 of the sqlite_module object. ++ ** Those below are for version 3 and greater. */ ++ int (*xShadowName)(const char*); + }; + + /* +@@ -7221,6 +7491,10 @@ + + /* + ** CAPI3REF: Virtual Table Scan Flags ++** ++** Virtual table implementations are allowed to set the ++** [sqlite3_index_info].idxFlags field to some combination of ++** these bits. + */ + #define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */ + +@@ -7232,15 +7506,21 @@ + ** an operator that is part of a constraint term in the wHERE clause of + ** a query that uses a [virtual table]. + */ +-#define SQLITE_INDEX_CONSTRAINT_EQ 2 +-#define SQLITE_INDEX_CONSTRAINT_GT 4 +-#define SQLITE_INDEX_CONSTRAINT_LE 8 +-#define SQLITE_INDEX_CONSTRAINT_LT 16 +-#define SQLITE_INDEX_CONSTRAINT_GE 32 +-#define SQLITE_INDEX_CONSTRAINT_MATCH 64 +-#define SQLITE_INDEX_CONSTRAINT_LIKE 65 +-#define SQLITE_INDEX_CONSTRAINT_GLOB 66 +-#define SQLITE_INDEX_CONSTRAINT_REGEXP 67 ++#define SQLITE_INDEX_CONSTRAINT_EQ 2 ++#define SQLITE_INDEX_CONSTRAINT_GT 4 ++#define SQLITE_INDEX_CONSTRAINT_LE 8 ++#define SQLITE_INDEX_CONSTRAINT_LT 16 ++#define SQLITE_INDEX_CONSTRAINT_GE 32 ++#define SQLITE_INDEX_CONSTRAINT_MATCH 64 ++#define SQLITE_INDEX_CONSTRAINT_LIKE 65 ++#define SQLITE_INDEX_CONSTRAINT_GLOB 66 ++#define SQLITE_INDEX_CONSTRAINT_REGEXP 67 ++#define SQLITE_INDEX_CONSTRAINT_NE 68 ++#define SQLITE_INDEX_CONSTRAINT_ISNOT 69 ++#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70 ++#define SQLITE_INDEX_CONSTRAINT_ISNULL 71 ++#define SQLITE_INDEX_CONSTRAINT_IS 72 ++#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150 + + /* + ** CAPI3REF: Register A Virtual Table Implementation +@@ -7917,6 +8197,7 @@ + /* + ** CAPI3REF: Low-Level Control Of Database Files + ** METHOD: sqlite3 ++** KEYWORDS: {file control} + ** + ** ^The [sqlite3_file_control()] interface makes a direct call to the + ** xFileControl method for the [sqlite3_io_methods] object associated +@@ -7931,11 +8212,18 @@ + ** the xFileControl method. ^The return value of the xFileControl + ** method becomes the return value of this routine. + ** +-** ^The SQLITE_FCNTL_FILE_POINTER value for the op parameter causes ++** A few opcodes for [sqlite3_file_control()] are handled directly ++** by the SQLite core and never invoke the ++** sqlite3_io_methods.xFileControl method. ++** ^The [SQLITE_FCNTL_FILE_POINTER] value for the op parameter causes + ** a pointer to the underlying [sqlite3_file] object to be written into +-** the space pointed to by the 4th parameter. ^The SQLITE_FCNTL_FILE_POINTER +-** case is a short-circuit path which does not actually invoke the +-** underlying sqlite3_io_methods.xFileControl method. ++** the space pointed to by the 4th parameter. The ++** [SQLITE_FCNTL_JOURNAL_POINTER] works similarly except that it returns ++** the [sqlite3_file] object associated with the journal file instead of ++** the main database. The [SQLITE_FCNTL_VFS_POINTER] opcode returns ++** a pointer to the underlying [sqlite3_vfs] object for the file. ++** The [SQLITE_FCNTL_DATA_VERSION] returns the data version counter ++** from the pager. + ** + ** ^If the second parameter (zDbName) does not match the name of any + ** open database file, then SQLITE_ERROR is returned. ^This error +@@ -7945,7 +8233,7 @@ + ** an incorrect zDbName and an SQLITE_ERROR return from the underlying + ** xFileControl method. + ** +-** See also: [SQLITE_FCNTL_LOCKSTATE] ++** See also: [file control opcodes] + */ + SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); + +@@ -7991,8 +8279,9 @@ + #define SQLITE_TESTCTRL_ALWAYS 13 + #define SQLITE_TESTCTRL_RESERVE 14 + #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 +-#define SQLITE_TESTCTRL_ISKEYWORD 16 +-#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 ++#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ ++#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ ++#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17 + #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 + #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ + #define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19 +@@ -8002,9 +8291,193 @@ + #define SQLITE_TESTCTRL_ISINIT 23 + #define SQLITE_TESTCTRL_SORTER_MMAP 24 + #define SQLITE_TESTCTRL_IMPOSTER 25 +-#define SQLITE_TESTCTRL_LAST 25 ++#define SQLITE_TESTCTRL_PARSER_COVERAGE 26 ++#define SQLITE_TESTCTRL_LAST 26 /* Largest TESTCTRL */ + + /* ++** CAPI3REF: SQL Keyword Checking ++** ++** These routines provide access to the set of SQL language keywords ++** recognized by SQLite. Applications can uses these routines to determine ++** whether or not a specific identifier needs to be escaped (for example, ++** by enclosing in double-quotes) so as not to confuse the parser. ++** ++** The sqlite3_keyword_count() interface returns the number of distinct ++** keywords understood by SQLite. ++** ++** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and ++** makes *Z point to that keyword expressed as UTF8 and writes the number ++** of bytes in the keyword into *L. The string that *Z points to is not ++** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns ++** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z ++** or L are NULL or invalid pointers then calls to ++** sqlite3_keyword_name(N,Z,L) result in undefined behavior. ++** ++** The sqlite3_keyword_check(Z,L) interface checks to see whether or not ++** the L-byte UTF8 identifier that Z points to is a keyword, returning non-zero ++** if it is and zero if not. ++** ++** The parser used by SQLite is forgiving. It is often possible to use ++** a keyword as an identifier as long as such use does not result in a ++** parsing ambiguity. For example, the statement ++** "CREATE TABLE BEGIN(REPLACE,PRAGMA,END);" is accepted by SQLite, and ++** creates a new table named "BEGIN" with three columns named ++** "REPLACE", "PRAGMA", and "END". Nevertheless, best practice is to avoid ++** using keywords as identifiers. Common techniques used to avoid keyword ++** name collisions include: ++** <ul> ++** <li> Put all identifier names inside double-quotes. This is the official ++** SQL way to escape identifier names. ++** <li> Put identifier names inside [...]. This is not standard SQL, ++** but it is what SQL Server does and so lots of programmers use this ++** technique. ++** <li> Begin every identifier with the letter "Z" as no SQL keywords start ++** with "Z". ++** <li> Include a digit somewhere in every identifier name. ++** </ul> ++** ++** Note that the number of keywords understood by SQLite can depend on ++** compile-time options. For example, "VACUUM" is not a keyword if ++** SQLite is compiled with the [-DSQLITE_OMIT_VACUUM] option. Also, ++** new keywords may be added to future releases of SQLite. ++*/ ++SQLITE_API int sqlite3_keyword_count(void); ++SQLITE_API int sqlite3_keyword_name(int,const char**,int*); ++SQLITE_API int sqlite3_keyword_check(const char*,int); ++ ++/* ++** CAPI3REF: Dynamic String Object ++** KEYWORDS: {dynamic string} ++** ++** An instance of the sqlite3_str object contains a dynamically-sized ++** string under construction. ++** ++** The lifecycle of an sqlite3_str object is as follows: ++** <ol> ++** <li> ^The sqlite3_str object is created using [sqlite3_str_new()]. ++** <li> ^Text is appended to the sqlite3_str object using various ++** methods, such as [sqlite3_str_appendf()]. ++** <li> ^The sqlite3_str object is destroyed and the string it created ++** is returned using the [sqlite3_str_finish()] interface. ++** </ol> ++*/ ++typedef struct sqlite3_str sqlite3_str; ++ ++/* ++** CAPI3REF: Create A New Dynamic String Object ++** CONSTRUCTOR: sqlite3_str ++** ++** ^The [sqlite3_str_new(D)] interface allocates and initializes ++** a new [sqlite3_str] object. To avoid memory leaks, the object returned by ++** [sqlite3_str_new()] must be freed by a subsequent call to ++** [sqlite3_str_finish(X)]. ++** ++** ^The [sqlite3_str_new(D)] interface always returns a pointer to a ++** valid [sqlite3_str] object, though in the event of an out-of-memory ++** error the returned object might be a special singleton that will ++** silently reject new text, always return SQLITE_NOMEM from ++** [sqlite3_str_errcode()], always return 0 for ++** [sqlite3_str_length()], and always return NULL from ++** [sqlite3_str_finish(X)]. It is always safe to use the value ++** returned by [sqlite3_str_new(D)] as the sqlite3_str parameter ++** to any of the other [sqlite3_str] methods. ++** ++** The D parameter to [sqlite3_str_new(D)] may be NULL. If the ++** D parameter in [sqlite3_str_new(D)] is not NULL, then the maximum ++** length of the string contained in the [sqlite3_str] object will be ++** the value set for [sqlite3_limit](D,[SQLITE_LIMIT_LENGTH]) instead ++** of [SQLITE_MAX_LENGTH]. ++*/ ++SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3*); ++ ++/* ++** CAPI3REF: Finalize A Dynamic String ++** DESTRUCTOR: sqlite3_str ++** ++** ^The [sqlite3_str_finish(X)] interface destroys the sqlite3_str object X ++** and returns a pointer to a memory buffer obtained from [sqlite3_malloc64()] ++** that contains the constructed string. The calling application should ++** pass the returned value to [sqlite3_free()] to avoid a memory leak. ++** ^The [sqlite3_str_finish(X)] interface may return a NULL pointer if any ++** errors were encountered during construction of the string. ^The ++** [sqlite3_str_finish(X)] interface will also return a NULL pointer if the ++** string in [sqlite3_str] object X is zero bytes long. ++*/ ++SQLITE_API char *sqlite3_str_finish(sqlite3_str*); ++ ++/* ++** CAPI3REF: Add Content To A Dynamic String ++** METHOD: sqlite3_str ++** ++** These interfaces add content to an sqlite3_str object previously obtained ++** from [sqlite3_str_new()]. ++** ++** ^The [sqlite3_str_appendf(X,F,...)] and ++** [sqlite3_str_vappendf(X,F,V)] interfaces uses the [built-in printf] ++** functionality of SQLite to append formatted text onto the end of ++** [sqlite3_str] object X. ++** ++** ^The [sqlite3_str_append(X,S,N)] method appends exactly N bytes from string S ++** onto the end of the [sqlite3_str] object X. N must be non-negative. ++** S must contain at least N non-zero bytes of content. To append a ++** zero-terminated string in its entirety, use the [sqlite3_str_appendall()] ++** method instead. ++** ++** ^The [sqlite3_str_appendall(X,S)] method appends the complete content of ++** zero-terminated string S onto the end of [sqlite3_str] object X. ++** ++** ^The [sqlite3_str_appendchar(X,N,C)] method appends N copies of the ++** single-byte character C onto the end of [sqlite3_str] object X. ++** ^This method can be used, for example, to add whitespace indentation. ++** ++** ^The [sqlite3_str_reset(X)] method resets the string under construction ++** inside [sqlite3_str] object X back to zero bytes in length. ++** ++** These methods do not return a result code. ^If an error occurs, that fact ++** is recorded in the [sqlite3_str] object and can be recovered by a ++** subsequent call to [sqlite3_str_errcode(X)]. ++*/ ++SQLITE_API void sqlite3_str_appendf(sqlite3_str*, const char *zFormat, ...); ++SQLITE_API void sqlite3_str_vappendf(sqlite3_str*, const char *zFormat, va_list); ++SQLITE_API void sqlite3_str_append(sqlite3_str*, const char *zIn, int N); ++SQLITE_API void sqlite3_str_appendall(sqlite3_str*, const char *zIn); ++SQLITE_API void sqlite3_str_appendchar(sqlite3_str*, int N, char C); ++SQLITE_API void sqlite3_str_reset(sqlite3_str*); ++ ++/* ++** CAPI3REF: Status Of A Dynamic String ++** METHOD: sqlite3_str ++** ++** These interfaces return the current status of an [sqlite3_str] object. ++** ++** ^If any prior errors have occurred while constructing the dynamic string ++** in sqlite3_str X, then the [sqlite3_str_errcode(X)] method will return ++** an appropriate error code. ^The [sqlite3_str_errcode(X)] method returns ++** [SQLITE_NOMEM] following any out-of-memory error, or ++** [SQLITE_TOOBIG] if the size of the dynamic string exceeds ++** [SQLITE_MAX_LENGTH], or [SQLITE_OK] if there have been no errors. ++** ++** ^The [sqlite3_str_length(X)] method returns the current length, in bytes, ++** of the dynamic string under construction in [sqlite3_str] object X. ++** ^The length returned by [sqlite3_str_length(X)] does not include the ++** zero-termination byte. ++** ++** ^The [sqlite3_str_value(X)] method returns a pointer to the current ++** content of the dynamic string under construction in X. The value ++** returned by [sqlite3_str_value(X)] is managed by the sqlite3_str object X ++** and might be freed or altered by any subsequent method on the same ++** [sqlite3_str] object. Applications must not used the pointer returned ++** [sqlite3_str_value(X)] after any subsequent method call on the same ++** object. ^Applications may change the content of the string returned ++** by [sqlite3_str_value(X)] as long as they do not write into any bytes ++** outside the range of 0 to [sqlite3_str_length(X)] and do not read or ++** write any byte after any subsequent sqlite3_str method call. ++*/ ++SQLITE_API int sqlite3_str_errcode(sqlite3_str*); ++SQLITE_API int sqlite3_str_length(sqlite3_str*); ++SQLITE_API char *sqlite3_str_value(sqlite3_str*); ++ ++/* + ** CAPI3REF: SQLite Runtime Status + ** + ** ^These interfaces are used to retrieve runtime status information +@@ -8051,8 +8524,7 @@ + ** <dd>This parameter is the current amount of memory checked out + ** using [sqlite3_malloc()], either directly or indirectly. The + ** figure includes calls made to [sqlite3_malloc()] by the application +-** and internal memory usage by the SQLite library. Scratch memory +-** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache ++** and internal memory usage by the SQLite library. Auxiliary page-cache + ** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in + ** this parameter. The amount returned is the sum of the allocation + ** sizes as reported by the xSize method in [sqlite3_mem_methods].</dd>)^ +@@ -8090,29 +8562,14 @@ + ** *pHighwater parameter to [sqlite3_status()] is of interest. + ** The value written into the *pCurrent parameter is undefined.</dd>)^ + ** +-** [[SQLITE_STATUS_SCRATCH_USED]] ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt> +-** <dd>This parameter returns the number of allocations used out of the +-** [scratch memory allocator] configured using +-** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not +-** in bytes. Since a single thread may only have one scratch allocation +-** outstanding at time, this parameter also reports the number of threads +-** using scratch memory at the same time.</dd>)^ ++** [[SQLITE_STATUS_SCRATCH_USED]] <dt>SQLITE_STATUS_SCRATCH_USED</dt> ++** <dd>No longer used.</dd> + ** + ** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt> +-** <dd>This parameter returns the number of bytes of scratch memory +-** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH] +-** buffer and where forced to overflow to [sqlite3_malloc()]. The values +-** returned include overflows because the requested allocation was too +-** larger (that is, because the requested allocation was larger than the +-** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer +-** slots were available. +-** </dd>)^ ++** <dd>No longer used.</dd> + ** +-** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt> +-** <dd>This parameter records the largest memory allocation request +-** handed to [scratch memory allocator]. Only the value returned in the +-** *pHighwater parameter to [sqlite3_status()] is of interest. +-** The value written into the *pCurrent parameter is undefined.</dd>)^ ++** [[SQLITE_STATUS_SCRATCH_SIZE]] <dt>SQLITE_STATUS_SCRATCH_SIZE</dt> ++** <dd>No longer used.</dd> + ** + ** [[SQLITE_STATUS_PARSER_STACK]] ^(<dt>SQLITE_STATUS_PARSER_STACK</dt> + ** <dd>The *pHighwater parameter records the deepest parser stack. +@@ -8125,12 +8582,12 @@ + #define SQLITE_STATUS_MEMORY_USED 0 + #define SQLITE_STATUS_PAGECACHE_USED 1 + #define SQLITE_STATUS_PAGECACHE_OVERFLOW 2 +-#define SQLITE_STATUS_SCRATCH_USED 3 +-#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 ++#define SQLITE_STATUS_SCRATCH_USED 3 /* NOT USED */ ++#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 /* NOT USED */ + #define SQLITE_STATUS_MALLOC_SIZE 5 + #define SQLITE_STATUS_PARSER_STACK 6 + #define SQLITE_STATUS_PAGECACHE_SIZE 7 +-#define SQLITE_STATUS_SCRATCH_SIZE 8 ++#define SQLITE_STATUS_SCRATCH_SIZE 8 /* NOT USED */ + #define SQLITE_STATUS_MALLOC_COUNT 9 + + /* +@@ -8253,6 +8710,15 @@ + ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. + ** </dd> + ** ++** [[SQLITE_DBSTATUS_CACHE_SPILL]] ^(<dt>SQLITE_DBSTATUS_CACHE_SPILL</dt> ++** <dd>This parameter returns the number of dirty cache entries that have ++** been written to disk in the middle of a transaction due to the page ++** cache overflowing. Transactions are more efficient if they are written ++** to disk all at once. When pages spill mid-transaction, that introduces ++** additional overhead. This parameter can be used help identify ++** inefficiencies that can be resolve by increasing the cache size. ++** </dd> ++** + ** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt> + ** <dd>This parameter returns zero for the current value if and only if + ** all foreign key constraints (deferred or immediate) have been +@@ -8272,7 +8738,8 @@ + #define SQLITE_DBSTATUS_CACHE_WRITE 9 + #define SQLITE_DBSTATUS_DEFERRED_FKS 10 + #define SQLITE_DBSTATUS_CACHE_USED_SHARED 11 +-#define SQLITE_DBSTATUS_MAX 11 /* Largest defined DBSTATUS */ ++#define SQLITE_DBSTATUS_CACHE_SPILL 12 ++#define SQLITE_DBSTATUS_MAX 12 /* Largest defined DBSTATUS */ + + + /* +@@ -9227,6 +9694,7 @@ + ** can use to customize and optimize their behavior. + ** + ** <dl> ++** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]] + ** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT + ** <dd>Calls of the form + ** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported, +@@ -9273,6 +9741,40 @@ + SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *); + + /* ++** CAPI3REF: Determine If Virtual Table Column Access Is For UPDATE ++** ++** If the sqlite3_vtab_nochange(X) routine is called within the [xColumn] ++** method of a [virtual table], then it returns true if and only if the ++** column is being fetched as part of an UPDATE operation during which the ++** column value will not change. Applications might use this to substitute ++** a return value that is less expensive to compute and that the corresponding ++** [xUpdate] method understands as a "no-change" value. ++** ++** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that ++** the column is not changed by the UPDATE statement, then the xColumn ++** method can optionally return without setting a result, without calling ++** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces]. ++** In that case, [sqlite3_value_nochange(X)] will return true for the ++** same column in the [xUpdate] method. ++*/ ++SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*); ++ ++/* ++** CAPI3REF: Determine The Collation For a Virtual Table Constraint ++** ++** This function may only be called from within a call to the [xBestIndex] ++** method of a [virtual table]. ++** ++** The first argument must be the sqlite3_index_info object that is the ++** first parameter to the xBestIndex() method. The second argument must be ++** an index into the aConstraint[] array belonging to the sqlite3_index_info ++** structure passed to xBestIndex. This function returns a pointer to a buffer ++** containing the name of the collation sequence for the corresponding ++** constraint. ++*/ ++SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_info*,int); ++ ++/* + ** CAPI3REF: Conflict resolution modes + ** KEYWORDS: {conflict resolution mode} + ** +@@ -9542,7 +10044,6 @@ + /* + ** CAPI3REF: Database Snapshot + ** KEYWORDS: {snapshot} {sqlite3_snapshot} +-** EXPERIMENTAL + ** + ** An instance of the snapshot object records the state of a [WAL mode] + ** database for some specific point in history. +@@ -9559,11 +10060,6 @@ + ** version of the database file so that it is possible to later open a new read + ** transaction that sees that historical version of the database rather than + ** the most recent version. +-** +-** The constructor for this object is [sqlite3_snapshot_get()]. The +-** [sqlite3_snapshot_open()] method causes a fresh read transaction to refer +-** to an historical snapshot (if possible). The destructor for +-** sqlite3_snapshot objects is [sqlite3_snapshot_free()]. + */ + typedef struct sqlite3_snapshot { + unsigned char hidden[48]; +@@ -9571,7 +10067,7 @@ + + /* + ** CAPI3REF: Record A Database Snapshot +-** EXPERIMENTAL ++** CONSTRUCTOR: sqlite3_snapshot + ** + ** ^The [sqlite3_snapshot_get(D,S,P)] interface attempts to make a + ** new [sqlite3_snapshot] object that records the current state of +@@ -9587,7 +10083,7 @@ + ** in this case. + ** + ** <ul> +-** <li> The database handle must be in [autocommit mode]. ++** <li> The database handle must not be in [autocommit mode]. + ** + ** <li> Schema S of [database connection] D must be a [WAL mode] database. + ** +@@ -9610,7 +10106,7 @@ + ** to avoid a memory leak. + ** + ** The [sqlite3_snapshot_get()] interface is only available when the +-** SQLITE_ENABLE_SNAPSHOT compile-time option is used. ++** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. + */ + SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get( + sqlite3 *db, +@@ -9620,24 +10116,35 @@ + + /* + ** CAPI3REF: Start a read transaction on an historical snapshot +-** EXPERIMENTAL ++** METHOD: sqlite3_snapshot + ** +-** ^The [sqlite3_snapshot_open(D,S,P)] interface starts a +-** read transaction for schema S of +-** [database connection] D such that the read transaction +-** refers to historical [snapshot] P, rather than the most +-** recent change to the database. +-** ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK on success +-** or an appropriate [error code] if it fails. ++** ^The [sqlite3_snapshot_open(D,S,P)] interface either starts a new read ++** transaction or upgrades an existing one for schema S of ++** [database connection] D such that the read transaction refers to ++** historical [snapshot] P, rather than the most recent change to the ++** database. ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK ++** on success or an appropriate [error code] if it fails. + ** +-** ^In order to succeed, a call to [sqlite3_snapshot_open(D,S,P)] must be +-** the first operation following the [BEGIN] that takes the schema S +-** out of [autocommit mode]. +-** ^In other words, schema S must not currently be in +-** a transaction for [sqlite3_snapshot_open(D,S,P)] to work, but the +-** database connection D must be out of [autocommit mode]. +-** ^A [snapshot] will fail to open if it has been overwritten by a +-** [checkpoint]. ++** ^In order to succeed, the database connection must not be in ++** [autocommit mode] when [sqlite3_snapshot_open(D,S,P)] is called. If there ++** is already a read transaction open on schema S, then the database handle ++** must have no active statements (SELECT statements that have been passed ++** to sqlite3_step() but not sqlite3_reset() or sqlite3_finalize()). ++** SQLITE_ERROR is returned if either of these conditions is violated, or ++** if schema S does not exist, or if the snapshot object is invalid. ++** ++** ^A call to sqlite3_snapshot_open() will fail to open if the specified ++** snapshot has been overwritten by a [checkpoint]. In this case ++** SQLITE_ERROR_SNAPSHOT is returned. ++** ++** If there is already a read transaction open when this function is ++** invoked, then the same read transaction remains open (on the same ++** database snapshot) if SQLITE_ERROR, SQLITE_BUSY or SQLITE_ERROR_SNAPSHOT ++** is returned. If another error code - for example SQLITE_PROTOCOL or an ++** SQLITE_IOERR error code - is returned, then the final state of the ++** read transaction is undefined. If SQLITE_OK is returned, then the ++** read transaction is now open on database snapshot P. ++** + ** ^(A call to [sqlite3_snapshot_open(D,S,P)] will fail if the + ** database connection D does not know that the database file for + ** schema S is in [WAL mode]. A database connection might not know +@@ -9648,7 +10155,7 @@ + ** database connection in order to make it ready to use snapshots.) + ** + ** The [sqlite3_snapshot_open()] interface is only available when the +-** SQLITE_ENABLE_SNAPSHOT compile-time option is used. ++** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. + */ + SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open( + sqlite3 *db, +@@ -9658,7 +10165,7 @@ + + /* + ** CAPI3REF: Destroy a snapshot +-** EXPERIMENTAL ++** DESTRUCTOR: sqlite3_snapshot + ** + ** ^The [sqlite3_snapshot_free(P)] interface destroys [sqlite3_snapshot] P. + ** The application must eventually free every [sqlite3_snapshot] object +@@ -9665,13 +10172,13 @@ + ** using this routine to avoid a memory leak. + ** + ** The [sqlite3_snapshot_free()] interface is only available when the +-** SQLITE_ENABLE_SNAPSHOT compile-time option is used. ++** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. + */ + SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*); + + /* + ** CAPI3REF: Compare the ages of two snapshot handles. +-** EXPERIMENTAL ++** METHOD: sqlite3_snapshot + ** + ** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages + ** of two valid snapshot handles. +@@ -9690,6 +10197,9 @@ + ** Otherwise, this API returns a negative value if P1 refers to an older + ** snapshot than P2, zero if the two handles refer to the same database + ** snapshot, and a positive value if P1 is a newer snapshot than P2. ++** ++** This interface is only available if SQLite is compiled with the ++** [SQLITE_ENABLE_SNAPSHOT] option. + */ + SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( + sqlite3_snapshot *p1, +@@ -9698,27 +10208,152 @@ + + /* + ** CAPI3REF: Recover snapshots from a wal file +-** EXPERIMENTAL ++** METHOD: sqlite3_snapshot + ** +-** If all connections disconnect from a database file but do not perform +-** a checkpoint, the existing wal file is opened along with the database +-** file the next time the database is opened. At this point it is only +-** possible to successfully call sqlite3_snapshot_open() to open the most +-** recent snapshot of the database (the one at the head of the wal file), +-** even though the wal file may contain other valid snapshots for which +-** clients have sqlite3_snapshot handles. ++** If a [WAL file] remains on disk after all database connections close ++** (either through the use of the [SQLITE_FCNTL_PERSIST_WAL] [file control] ++** or because the last process to have the database opened exited without ++** calling [sqlite3_close()]) and a new connection is subsequently opened ++** on that database and [WAL file], the [sqlite3_snapshot_open()] interface ++** will only be able to open the last transaction added to the WAL file ++** even though the WAL file contains other valid transactions. + ** +-** This function attempts to scan the wal file associated with database zDb ++** This function attempts to scan the WAL file associated with database zDb + ** of database handle db and make all valid snapshots available to + ** sqlite3_snapshot_open(). It is an error if there is already a read +-** transaction open on the database, or if the database is not a wal mode ++** transaction open on the database, or if the database is not a WAL mode + ** database. + ** + ** SQLITE_OK is returned if successful, or an SQLite error code otherwise. ++** ++** This interface is only available if SQLite is compiled with the ++** [SQLITE_ENABLE_SNAPSHOT] option. + */ + SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); + + /* ++** CAPI3REF: Serialize a database ++** ++** The sqlite3_serialize(D,S,P,F) interface returns a pointer to memory ++** that is a serialization of the S database on [database connection] D. ++** If P is not a NULL pointer, then the size of the database in bytes ++** is written into *P. ++** ++** For an ordinary on-disk database file, the serialization is just a ++** copy of the disk file. For an in-memory database or a "TEMP" database, ++** the serialization is the same sequence of bytes which would be written ++** to disk if that database where backed up to disk. ++** ++** The usual case is that sqlite3_serialize() copies the serialization of ++** the database into memory obtained from [sqlite3_malloc64()] and returns ++** a pointer to that memory. The caller is responsible for freeing the ++** returned value to avoid a memory leak. However, if the F argument ++** contains the SQLITE_SERIALIZE_NOCOPY bit, then no memory allocations ++** are made, and the sqlite3_serialize() function will return a pointer ++** to the contiguous memory representation of the database that SQLite ++** is currently using for that database, or NULL if the no such contiguous ++** memory representation of the database exists. A contiguous memory ++** representation of the database will usually only exist if there has ++** been a prior call to [sqlite3_deserialize(D,S,...)] with the same ++** values of D and S. ++** The size of the database is written into *P even if the ++** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy ++** of the database exists. ++** ++** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the ++** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory ++** allocation error occurs. ++** ++** This interface is only available if SQLite is compiled with the ++** [SQLITE_ENABLE_DESERIALIZE] option. ++*/ ++SQLITE_API unsigned char *sqlite3_serialize( ++ sqlite3 *db, /* The database connection */ ++ const char *zSchema, /* Which DB to serialize. ex: "main", "temp", ... */ ++ sqlite3_int64 *piSize, /* Write size of the DB here, if not NULL */ ++ unsigned int mFlags /* Zero or more SQLITE_SERIALIZE_* flags */ ++); ++ ++/* ++** CAPI3REF: Flags for sqlite3_serialize ++** ++** Zero or more of the following constants can be OR-ed together for ++** the F argument to [sqlite3_serialize(D,S,P,F)]. ++** ++** SQLITE_SERIALIZE_NOCOPY means that [sqlite3_serialize()] will return ++** a pointer to contiguous in-memory database that it is currently using, ++** without making a copy of the database. If SQLite is not currently using ++** a contiguous in-memory database, then this option causes ++** [sqlite3_serialize()] to return a NULL pointer. SQLite will only be ++** using a contiguous in-memory database if it has been initialized by a ++** prior call to [sqlite3_deserialize()]. ++*/ ++#define SQLITE_SERIALIZE_NOCOPY 0x001 /* Do no memory allocations */ ++ ++/* ++** CAPI3REF: Deserialize a database ++** ++** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the ++** [database connection] D to disconnect from database S and then ++** reopen S as an in-memory database based on the serialization contained ++** in P. The serialized database P is N bytes in size. M is the size of ++** the buffer P, which might be larger than N. If M is larger than N, and ++** the SQLITE_DESERIALIZE_READONLY bit is not set in F, then SQLite is ++** permitted to add content to the in-memory database as long as the total ++** size does not exceed M bytes. ++** ++** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will ++** invoke sqlite3_free() on the serialization buffer when the database ++** connection closes. If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then ++** SQLite will try to increase the buffer size using sqlite3_realloc64() ++** if writes on the database cause it to grow larger than M bytes. ++** ++** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the ++** database is currently in a read transaction or is involved in a backup ++** operation. ++** ++** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the ++** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then ++** [sqlite3_free()] is invoked on argument P prior to returning. ++** ++** This interface is only available if SQLite is compiled with the ++** [SQLITE_ENABLE_DESERIALIZE] option. ++*/ ++SQLITE_API int sqlite3_deserialize( ++ sqlite3 *db, /* The database connection */ ++ const char *zSchema, /* Which DB to reopen with the deserialization */ ++ unsigned char *pData, /* The serialized database content */ ++ sqlite3_int64 szDb, /* Number bytes in the deserialization */ ++ sqlite3_int64 szBuf, /* Total size of buffer pData[] */ ++ unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */ ++); ++ ++/* ++** CAPI3REF: Flags for sqlite3_deserialize() ++** ++** The following are allowed values for 6th argument (the F argument) to ++** the [sqlite3_deserialize(D,S,P,N,M,F)] interface. ++** ++** The SQLITE_DESERIALIZE_FREEONCLOSE means that the database serialization ++** in the P argument is held in memory obtained from [sqlite3_malloc64()] ++** and that SQLite should take ownership of this memory and automatically ++** free it when it has finished using it. Without this flag, the caller ++** is responsible for freeing any dynamically allocated memory. ++** ++** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to ++** grow the size of the database using calls to [sqlite3_realloc64()]. This ++** flag should only be used if SQLITE_DESERIALIZE_FREEONCLOSE is also used. ++** Without this flag, the deserialized database cannot increase in size beyond ++** the number of bytes specified by the M parameter. ++** ++** The SQLITE_DESERIALIZE_READONLY flag means that the deserialized database ++** should be treated as read-only. ++*/ ++#define SQLITE_DESERIALIZE_FREEONCLOSE 1 /* Call sqlite3_free() on close */ ++#define SQLITE_DESERIALIZE_RESIZEABLE 2 /* Resize using sqlite3_realloc64() */ ++#define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */ ++ ++/* + ** Undo the hack that converts floating point types to integer for + ** builds on processors without floating point support. + */ +@@ -9829,7 +10464,7 @@ + sqlite3_int64 iRowid; /* Rowid for current entry */ + sqlite3_rtree_dbl rParentScore; /* Score of parent node */ + int eParentWithin; /* Visibility of parent node */ +- int eWithin; /* OUT: Visiblity */ ++ int eWithin; /* OUT: Visibility */ + sqlite3_rtree_dbl rScore; /* OUT: Write the score here */ + /* The following fields are only available in 3.8.11 and later */ + sqlite3_value **apSqlParam; /* Original SQL values of parameters */ +@@ -9865,16 +10500,23 @@ + + /* + ** CAPI3REF: Session Object Handle ++** ++** An instance of this object is a [session] that can be used to ++** record changes to a database. + */ + typedef struct sqlite3_session sqlite3_session; + + /* + ** CAPI3REF: Changeset Iterator Handle ++** ++** An instance of this object acts as a cursor for iterating ++** over the elements of a [changeset] or [patchset]. + */ + typedef struct sqlite3_changeset_iter sqlite3_changeset_iter; + + /* + ** CAPI3REF: Create A New Session Object ++** CONSTRUCTOR: sqlite3_session + ** + ** Create a new session object attached to database handle db. If successful, + ** a pointer to the new object is written to *ppSession and SQLITE_OK is +@@ -9911,6 +10553,7 @@ + + /* + ** CAPI3REF: Delete A Session Object ++** DESTRUCTOR: sqlite3_session + ** + ** Delete a session object previously allocated using + ** [sqlite3session_create()]. Once a session object has been deleted, the +@@ -9926,6 +10569,7 @@ + + /* + ** 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 +@@ -9945,6 +10589,7 @@ + + /* + ** CAPI3REF: Set Or Clear the Indirect Change Flag ++** METHOD: sqlite3_session + ** + ** Each change recorded by a session object is marked as either direct or + ** indirect. A change is marked as indirect if either: +@@ -9974,6 +10619,7 @@ + + /* + ** CAPI3REF: Attach A Table To A Session Object ++** METHOD: sqlite3_session + ** + ** If argument zTab is not NULL, then it is the name of a table to attach + ** to the session object passed as the first argument. All subsequent changes +@@ -9999,6 +10645,35 @@ + ** + ** SQLITE_OK is returned if the call completes without error. Or, if an error + ** occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned. ++** ++** <h3>Special sqlite_stat1 Handling</h3> ++** ++** As of SQLite version 3.22.0, the "sqlite_stat1" table is an exception to ++** some of the rules above. In SQLite, the schema of sqlite_stat1 is: ++** <pre> ++** CREATE TABLE sqlite_stat1(tbl,idx,stat) ++** </pre> ++** ++** Even though sqlite_stat1 does not have a PRIMARY KEY, changes are ++** recorded for it as if the PRIMARY KEY is (tbl,idx). Additionally, changes ++** are recorded for rows for which (idx IS NULL) is true. However, for such ++** rows a zero-length blob (SQL value X'') is stored in the changeset or ++** patchset instead of a NULL value. This allows such changesets to be ++** manipulated by legacy implementations of sqlite3changeset_invert(), ++** concat() and similar. ++** ++** The sqlite3changeset_apply() function automatically converts the ++** zero-length blob back to a NULL value when updating the sqlite_stat1 ++** table. However, if the application calls sqlite3changeset_new(), ++** sqlite3changeset_old() or sqlite3changeset_conflict on a changeset ++** iterator directly (including on a changeset iterator passed to a ++** conflict-handler callback) then the X'' value is returned. The application ++** must translate X'' to NULL itself if required. ++** ++** Legacy (older than 3.22.0) versions of the sessions module cannot capture ++** changes made to the sqlite_stat1 table. Legacy versions of the ++** sqlite3changeset_apply() function silently ignore any modifications to the ++** sqlite_stat1 table that are part of a changeset or patchset. + */ + SQLITE_API int sqlite3session_attach( + sqlite3_session *pSession, /* Session object */ +@@ -10007,6 +10682,7 @@ + + /* + ** CAPI3REF: Set a table filter on a Session Object. ++** METHOD: sqlite3_session + ** + ** The second argument (xFilter) is the "filter callback". For changes to rows + ** in tables that are not attached to the Session object, the filter is called +@@ -10025,6 +10701,7 @@ + + /* + ** CAPI3REF: Generate A Changeset From A Session Object ++** METHOD: sqlite3_session + ** + ** Obtain a changeset containing changes to the tables attached to the + ** session object passed as the first argument. If successful, +@@ -10134,7 +10811,8 @@ + ); + + /* +-** CAPI3REF: Load The Difference Between Tables Into A Session ++** CAPI3REF: Load The Difference Between Tables Into A Session ++** METHOD: sqlite3_session + ** + ** If it is not already attached to the session object passed as the first + ** argument, this function attaches table zTbl in the same manner as the +@@ -10199,6 +10877,7 @@ + + /* + ** CAPI3REF: Generate A Patchset From A Session Object ++** METHOD: sqlite3_session + ** + ** The differences between a patchset and a changeset are that: + ** +@@ -10227,8 +10906,8 @@ + */ + SQLITE_API int sqlite3session_patchset( + sqlite3_session *pSession, /* Session object */ +- int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */ +- void **ppPatchset /* OUT: Buffer containing changeset */ ++ int *pnPatchset, /* OUT: Size of buffer at *ppPatchset */ ++ void **ppPatchset /* OUT: Buffer containing patchset */ + ); + + /* +@@ -10250,6 +10929,7 @@ + + /* + ** CAPI3REF: Create An Iterator To Traverse A Changeset ++** CONSTRUCTOR: sqlite3_changeset_iter + ** + ** Create an iterator used to iterate through the contents of a changeset. + ** If successful, *pp is set to point to the iterator handle and SQLITE_OK +@@ -10280,6 +10960,13 @@ + ** consecutively. There is no chance that the iterator will visit a change + ** the applies to table X, then one for table Y, and then later on visit + ** another change for table X. ++** ++** The behavior of sqlite3changeset_start_v2() and its streaming equivalent ++** may be modified by passing a combination of ++** [SQLITE_CHANGESETSTART_INVERT | supported flags] as the 4th parameter. ++** ++** Note that the sqlite3changeset_start_v2() API is still <b>experimental</b> ++** and therefore subject to change. + */ + SQLITE_API int sqlite3changeset_start( + sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ +@@ -10286,10 +10973,30 @@ + int nChangeset, /* Size of changeset blob in bytes */ + void *pChangeset /* Pointer to blob containing changeset */ + ); ++SQLITE_API int sqlite3changeset_start_v2( ++ sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ ++ int nChangeset, /* Size of changeset blob in bytes */ ++ void *pChangeset, /* Pointer to blob containing changeset */ ++ int flags /* SESSION_CHANGESETSTART_* flags */ ++); + ++/* ++** CAPI3REF: Flags for sqlite3changeset_start_v2 ++** ++** The following flags may passed via the 4th parameter to ++** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]: ++** ++** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd> ++** Invert the changeset while iterating through 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_CHANGESETSTART_INVERT 0x0002 + ++ + /* + ** CAPI3REF: Advance A Changeset Iterator ++** METHOD: sqlite3_changeset_iter + ** + ** This function may only be used with iterators created by function + ** [sqlite3changeset_start()]. If it is called on an iterator passed to +@@ -10314,6 +11021,7 @@ + + /* + ** CAPI3REF: Obtain The Current Operation From A Changeset Iterator ++** METHOD: sqlite3_changeset_iter + ** + ** The pIter argument passed to this function may either be an iterator + ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator +@@ -10348,6 +11056,7 @@ + + /* + ** CAPI3REF: Obtain The Primary Key Definition Of A Table ++** METHOD: sqlite3_changeset_iter + ** + ** For each modified table, a changeset includes the following: + ** +@@ -10379,6 +11088,7 @@ + + /* + ** CAPI3REF: Obtain old.* Values From A Changeset Iterator ++** METHOD: sqlite3_changeset_iter + ** + ** The pIter argument passed to this function may either be an iterator + ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator +@@ -10409,6 +11119,7 @@ + + /* + ** CAPI3REF: Obtain new.* Values From A Changeset Iterator ++** METHOD: sqlite3_changeset_iter + ** + ** The pIter argument passed to this function may either be an iterator + ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator +@@ -10442,6 +11153,7 @@ + + /* + ** CAPI3REF: Obtain Conflicting Row Values From A Changeset Iterator ++** METHOD: sqlite3_changeset_iter + ** + ** This function should only be used with iterator objects passed to a + ** conflict-handler callback by [sqlite3changeset_apply()] with either +@@ -10469,6 +11181,7 @@ + + /* + ** CAPI3REF: Determine The Number Of Foreign Key Constraint Violations ++** METHOD: sqlite3_changeset_iter + ** + ** This function may only be called with an iterator passed to an + ** SQLITE_CHANGESET_FOREIGN_KEY conflict handler callback. In this case +@@ -10485,6 +11198,7 @@ + + /* + ** CAPI3REF: Finalize A Changeset Iterator ++** METHOD: sqlite3_changeset_iter + ** + ** This function is used to finalize an iterator allocated with + ** [sqlite3changeset_start()]. +@@ -10501,6 +11215,7 @@ + ** to that error is returned by this function. Otherwise, SQLITE_OK is + ** returned. This is to allow the following pattern (pseudo-code): + ** ++** <pre> + ** sqlite3changeset_start(); + ** while( SQLITE_ROW==sqlite3changeset_next() ){ + ** // Do something with change. +@@ -10509,6 +11224,7 @@ + ** if( rc!=SQLITE_OK ){ + ** // An error has occurred + ** } ++** </pre> + */ + SQLITE_API int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); + +@@ -10556,6 +11272,7 @@ + ** sqlite3_changegroup object. Calling it produces similar results as the + ** following code fragment: + ** ++** <pre> + ** sqlite3_changegroup *pGrp; + ** rc = sqlite3_changegroup_new(&pGrp); + ** if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nA, pA); +@@ -10566,6 +11283,7 @@ + ** *ppOut = 0; + ** *pnOut = 0; + ** } ++** </pre> + ** + ** Refer to the sqlite3_changegroup documentation below for details. + */ +@@ -10581,11 +11299,15 @@ + + /* + ** CAPI3REF: Changegroup Handle ++** ++** A changegroup is an object used to combine two or more ++** [changesets] or [patchsets] + */ + typedef struct sqlite3_changegroup sqlite3_changegroup; + + /* + ** CAPI3REF: Create A New Changegroup Object ++** CONSTRUCTOR: sqlite3_changegroup + ** + ** An sqlite3_changegroup object is used to combine two or more changesets + ** (or patchsets) into a single changeset (or patchset). A single changegroup +@@ -10623,6 +11345,7 @@ + + /* + ** CAPI3REF: Add A Changeset To A Changegroup ++** METHOD: sqlite3_changegroup + ** + ** Add all changes within the changeset (or patchset) in buffer pData (size + ** nData bytes) to the changegroup. +@@ -10700,6 +11423,7 @@ + + /* + ** CAPI3REF: Obtain A Composite Changeset From A Changegroup ++** METHOD: sqlite3_changegroup + ** + ** Obtain a buffer containing a changeset (or patchset) representing the + ** current contents of the changegroup. If the inputs to the changegroup +@@ -10730,6 +11454,7 @@ + + /* + ** CAPI3REF: Delete A Changegroup Object ++** DESTRUCTOR: sqlite3_changegroup + */ + SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); + +@@ -10736,19 +11461,18 @@ + /* + ** CAPI3REF: Apply A Changeset To A Database + ** +-** Apply a changeset to a database. This function attempts to update the +-** "main" database attached to handle db with the changes found in the +-** changeset passed via the second and third arguments. ++** Apply a changeset or patchset to a database. These functions attempt to ++** update the "main" database attached to handle db with the changes found in ++** the changeset passed via the second and third arguments. + ** +-** The fourth argument (xFilter) passed to this function is the "filter ++** The fourth argument (xFilter) passed to these functions is the "filter + ** callback". If it is not NULL, then for each table affected by at least one + ** change in the changeset, the filter callback is invoked with + ** the table name as the second argument, and a copy of the context pointer +-** passed as the sixth argument to this function as the first. If the "filter +-** callback" returns zero, then no attempt is made to apply any changes to +-** the table. Otherwise, if the return value is non-zero or the xFilter +-** argument to this function is NULL, all changes related to the table are +-** attempted. ++** passed as the sixth argument as the first. If the "filter callback" ++** returns zero, then no attempt is made to apply any changes to the table. ++** Otherwise, if the return value is non-zero or the xFilter argument to ++** is NULL, all changes related to the table are attempted. + ** + ** For each table that is not excluded by the filter callback, this function + ** tests that the target database contains a compatible table. A table is +@@ -10793,7 +11517,7 @@ + ** + ** <dl> + ** <dt>DELETE Changes<dd> +-** For each DELETE change, this function checks if the target database ++** For each DELETE change, the function checks if the target database + ** contains a row with the same primary key value (or values) as the + ** original row values stored in the changeset. If it does, and the values + ** stored in all non-primary key columns also match the values stored in +@@ -10838,7 +11562,7 @@ + ** [SQLITE_CHANGESET_REPLACE]. + ** + ** <dt>UPDATE Changes<dd> +-** For each UPDATE change, this function checks if the target database ++** For each UPDATE change, the function checks if the target database + ** contains a row with the same primary key value (or values) as the + ** original row values stored in the changeset. If it does, and the values + ** stored in all modified non-primary key columns also match the values +@@ -10869,11 +11593,28 @@ + ** This can be used to further customize the applications conflict + ** resolution strategy. + ** +-** All changes made by this function are enclosed in a savepoint transaction. ++** All changes made by these functions are enclosed in a savepoint transaction. + ** If any other error (aside from a constraint failure when attempting to + ** write to the target database) occurs, then the savepoint transaction is + ** rolled back, restoring the target database to its original state, and an + ** SQLite error code returned. ++** ++** If the output parameters (ppRebase) and (pnRebase) are non-NULL and ++** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2() ++** may set (*ppRebase) to point to a "rebase" that may be used with the ++** sqlite3_rebaser APIs buffer before returning. In this case (*pnRebase) ++** is set to the size of the buffer in bytes. It is the responsibility of the ++** caller to eventually free any such buffer using sqlite3_free(). The buffer ++** is only allocated and populated if one or more conflicts were encountered ++** while applying the patchset. See comments surrounding the sqlite3_rebaser ++** APIs for further details. ++** ++** The behavior of sqlite3changeset_apply_v2() and its streaming equivalent ++** may be modified by passing a combination of ++** [SQLITE_CHANGESETAPPLY_NOSAVEPOINT | supported flags] as the 9th parameter. ++** ++** Note that the sqlite3changeset_apply_v2() API is still <b>experimental</b> ++** and therefore subject to change. + */ + SQLITE_API int sqlite3changeset_apply( + sqlite3 *db, /* Apply change to "main" db of this handle */ +@@ -10890,7 +11631,48 @@ + ), + void *pCtx /* First argument passed to xConflict */ + ); ++SQLITE_API int sqlite3changeset_apply_v2( ++ sqlite3 *db, /* Apply change to "main" db of this handle */ ++ int nChangeset, /* Size of changeset in bytes */ ++ void *pChangeset, /* Changeset blob */ ++ int(*xFilter)( ++ void *pCtx, /* Copy of sixth arg to _apply() */ ++ const char *zTab /* Table name */ ++ ), ++ int(*xConflict)( ++ void *pCtx, /* Copy of sixth arg to _apply() */ ++ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ ++ sqlite3_changeset_iter *p /* Handle describing change and conflict */ ++ ), ++ void *pCtx, /* First argument passed to xConflict */ ++ void **ppRebase, int *pnRebase, /* OUT: Rebase data */ ++ int flags /* SESSION_CHANGESETAPPLY_* flags */ ++); + ++/* ++** CAPI3REF: Flags for sqlite3changeset_apply_v2 ++** ++** The following flags may passed via the 9th parameter to ++** [sqlite3changeset_apply_v2] and [sqlite3changeset_apply_v2_strm]: ++** ++** <dl> ++** <dt>SQLITE_CHANGESETAPPLY_NOSAVEPOINT <dd> ++** Usually, the sessions module encloses all operations performed by ++** a single call to apply_v2() or apply_v2_strm() in a [SAVEPOINT]. The ++** SAVEPOINT is committed if the changeset or patchset is successfully ++** applied, or rolled back if an error occurs. Specifying this flag ++** causes the sessions module to omit this savepoint. In this case, if the ++** 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 + ** +@@ -10987,7 +11769,162 @@ + #define SQLITE_CHANGESET_REPLACE 1 + #define SQLITE_CHANGESET_ABORT 2 + ++/* ++** CAPI3REF: Rebasing changesets ++** EXPERIMENTAL ++** ++** Suppose there is a site hosting a database in state S0. And that ++** modifications are made that move that database to state S1 and a ++** changeset recorded (the "local" changeset). Then, a changeset based ++** on S0 is received from another site (the "remote" changeset) and ++** applied to the database. The database is then in state ++** (S1+"remote"), where the exact state depends on any conflict ++** resolution decisions (OMIT or REPLACE) made while applying "remote". ++** Rebasing a changeset is to update it to take those conflict ++** resolution decisions into account, so that the same conflicts ++** do not have to be resolved elsewhere in the network. ++** ++** For example, if both the local and remote changesets contain an ++** INSERT of the same key on "CREATE TABLE t1(a PRIMARY KEY, b)": ++** ++** local: INSERT INTO t1 VALUES(1, 'v1'); ++** remote: INSERT INTO t1 VALUES(1, 'v2'); ++** ++** and the conflict resolution is REPLACE, then the INSERT change is ++** removed from the local changeset (it was overridden). Or, if the ++** conflict resolution was "OMIT", then the local changeset is modified ++** to instead contain: ++** ++** UPDATE t1 SET b = 'v2' WHERE a=1; ++** ++** Changes within the local changeset are rebased as follows: ++** ++** <dl> ++** <dt>Local INSERT<dd> ++** This may only conflict with a remote INSERT. If the conflict ++** resolution was OMIT, then add an UPDATE change to the rebased ++** changeset. Or, if the conflict resolution was REPLACE, add ++** nothing to the rebased changeset. ++** ++** <dt>Local DELETE<dd> ++** This may conflict with a remote UPDATE or DELETE. In both cases the ++** only possible resolution is OMIT. If the remote operation was a ++** DELETE, then add no change to the rebased changeset. If the remote ++** operation was an UPDATE, then the old.* fields of change are updated ++** to reflect the new.* values in the UPDATE. ++** ++** <dt>Local UPDATE<dd> ++** This may conflict with a remote UPDATE or DELETE. If it conflicts ++** with a DELETE, and the conflict resolution was OMIT, then the update ++** is changed into an INSERT. Any undefined values in the new.* record ++** from the update change are filled in using the old.* values from ++** the conflicting DELETE. Or, if the conflict resolution was REPLACE, ++** the UPDATE change is simply omitted from the rebased changeset. ++** ++** If conflict is with a remote UPDATE and the resolution is OMIT, then ++** the old.* values are rebased using the new.* values in the remote ++** change. Or, if the resolution is REPLACE, then the change is copied ++** into the rebased changeset with updates to columns also updated by ++** the conflicting remote UPDATE removed. If this means no columns would ++** be updated, the change is omitted. ++** </dl> ++** ++** A local change may be rebased against multiple remote changes ++** simultaneously. If a single key is modified by multiple remote ++** changesets, they are combined as follows before the local changeset ++** is rebased: ++** ++** <ul> ++** <li> If there has been one or more REPLACE resolutions on a ++** key, it is rebased according to a REPLACE. ++** ++** <li> If there have been no REPLACE resolutions on a key, then ++** the local changeset is rebased according to the most recent ++** of the OMIT resolutions. ++** </ul> ++** ++** Note that conflict resolutions from multiple remote changesets are ++** combined on a per-field basis, not per-row. This means that in the ++** case of multiple remote UPDATE operations, some fields of a single ++** local change may be rebased for REPLACE while others are rebased for ++** OMIT. ++** ++** In order to rebase a local changeset, the remote changeset must first ++** be applied to the local database using sqlite3changeset_apply_v2() and ++** the buffer of rebase information captured. Then: ++** ++** <ol> ++** <li> An sqlite3_rebaser object is created by calling ++** sqlite3rebaser_create(). ++** <li> The new object is configured with the rebase buffer obtained from ++** sqlite3changeset_apply_v2() by calling sqlite3rebaser_configure(). ++** If the local changeset is to be rebased against multiple remote ++** changesets, then sqlite3rebaser_configure() should be called ++** multiple times, in the same order that the multiple ++** sqlite3changeset_apply_v2() calls were made. ++** <li> Each local changeset is rebased by calling sqlite3rebaser_rebase(). ++** <li> The sqlite3_rebaser object is deleted by calling ++** sqlite3rebaser_delete(). ++** </ol> ++*/ ++typedef struct sqlite3_rebaser sqlite3_rebaser; ++ + /* ++** CAPI3REF: Create a changeset rebaser object. ++** EXPERIMENTAL ++** ++** Allocate a new changeset rebaser object. If successful, set (*ppNew) to ++** point to the new object and return SQLITE_OK. Otherwise, if an error ++** occurs, return an SQLite error code (e.g. SQLITE_NOMEM) and set (*ppNew) ++** to NULL. ++*/ ++SQLITE_API int sqlite3rebaser_create(sqlite3_rebaser **ppNew); ++ ++/* ++** CAPI3REF: Configure a changeset rebaser object. ++** EXPERIMENTAL ++** ++** Configure the changeset rebaser object to rebase changesets according ++** to the conflict resolutions described by buffer pRebase (size nRebase ++** bytes), which must have been obtained from a previous call to ++** sqlite3changeset_apply_v2(). ++*/ ++SQLITE_API int sqlite3rebaser_configure( ++ sqlite3_rebaser*, ++ int nRebase, const void *pRebase ++); ++ ++/* ++** CAPI3REF: Rebase a changeset ++** EXPERIMENTAL ++** ++** Argument pIn must point to a buffer containing a changeset nIn bytes ++** in size. This function allocates and populates a buffer with a copy ++** of the changeset rebased rebased according to the configuration of the ++** rebaser object passed as the first argument. If successful, (*ppOut) ++** is set to point to the new buffer containing the rebased changset and ++** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the ++** responsibility of the caller to eventually free the new buffer using ++** sqlite3_free(). Otherwise, if an error occurs, (*ppOut) and (*pnOut) ++** are set to zero and an SQLite error code returned. ++*/ ++SQLITE_API int sqlite3rebaser_rebase( ++ sqlite3_rebaser*, ++ int nIn, const void *pIn, ++ int *pnOut, void **ppOut ++); ++ ++/* ++** CAPI3REF: Delete a changeset rebaser object. ++** EXPERIMENTAL ++** ++** Delete the changeset rebaser object and all associated resources. There ++** should be one call to this function for each successful invocation ++** of sqlite3rebaser_create(). ++*/ ++SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p); ++ ++/* + ** CAPI3REF: Streaming Versions of API functions. + ** + ** The six streaming API xxx_strm() functions serve similar purposes to the +@@ -10995,12 +11932,13 @@ + ** + ** <table border=1 style="margin-left:8ex;margin-right:8ex"> + ** <tr><th>Streaming function<th>Non-streaming equivalent</th> +-** <tr><td>sqlite3changeset_apply_str<td>[sqlite3changeset_apply] +-** <tr><td>sqlite3changeset_concat_str<td>[sqlite3changeset_concat] +-** <tr><td>sqlite3changeset_invert_str<td>[sqlite3changeset_invert] +-** <tr><td>sqlite3changeset_start_str<td>[sqlite3changeset_start] +-** <tr><td>sqlite3session_changeset_str<td>[sqlite3session_changeset] +-** <tr><td>sqlite3session_patchset_str<td>[sqlite3session_patchset] ++** <tr><td>sqlite3changeset_apply_strm<td>[sqlite3changeset_apply] ++** <tr><td>sqlite3changeset_apply_strm_v2<td>[sqlite3changeset_apply_v2] ++** <tr><td>sqlite3changeset_concat_strm<td>[sqlite3changeset_concat] ++** <tr><td>sqlite3changeset_invert_strm<td>[sqlite3changeset_invert] ++** <tr><td>sqlite3changeset_start_strm<td>[sqlite3changeset_start] ++** <tr><td>sqlite3session_changeset_strm<td>[sqlite3session_changeset] ++** <tr><td>sqlite3session_patchset_strm<td>[sqlite3session_patchset] + ** </table> + ** + ** Non-streaming functions that accept changesets (or patchsets) as input +@@ -11091,6 +12029,23 @@ + ), + void *pCtx /* First argument passed to xConflict */ + ); ++SQLITE_API int sqlite3changeset_apply_v2_strm( ++ sqlite3 *db, /* Apply change to "main" db of this handle */ ++ int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ ++ void *pIn, /* First arg for xInput */ ++ int(*xFilter)( ++ void *pCtx, /* Copy of sixth arg to _apply() */ ++ const char *zTab /* Table name */ ++ ), ++ int(*xConflict)( ++ void *pCtx, /* Copy of sixth arg to _apply() */ ++ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ ++ sqlite3_changeset_iter *p /* Handle describing change and conflict */ ++ ), ++ void *pCtx, /* First argument passed to xConflict */ ++ void **ppRebase, int *pnRebase, ++ int flags ++); + SQLITE_API int sqlite3changeset_concat_strm( + int (*xInputA)(void *pIn, void *pData, int *pnData), + void *pInA, +@@ -11110,6 +12065,12 @@ + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn + ); ++SQLITE_API int sqlite3changeset_start_v2_strm( ++ sqlite3_changeset_iter **pp, ++ int (*xInput)(void *pIn, void *pData, int *pnData), ++ void *pIn, ++ int flags ++); + SQLITE_API int sqlite3session_changeset_strm( + sqlite3_session *pSession, + int (*xOutput)(void *pOut, const void *pData, int nData), +@@ -11128,9 +12089,55 @@ + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut + ); ++SQLITE_API int sqlite3rebaser_rebase_strm( ++ sqlite3_rebaser *pRebaser, ++ int (*xInput)(void *pIn, void *pData, int *pnData), ++ void *pIn, ++ int (*xOutput)(void *pOut, const void *pData, int nData), ++ void *pOut ++); + ++/* ++** CAPI3REF: Configure global parameters ++** ++** The sqlite3session_config() interface is used to make global configuration ++** changes to the sessions module in order to tune it to the specific needs ++** of the application. ++** ++** The sqlite3session_config() interface is not threadsafe. If it is invoked ++** while any other thread is inside any other sessions method then the ++** results are undefined. Furthermore, if it is invoked after any sessions ++** related objects have been created, the results are also undefined. ++** ++** The first argument to the sqlite3session_config() function must be one ++** of the SQLITE_SESSION_CONFIG_XXX constants defined below. The ++** interpretation of the (void*) value passed as the second parameter and ++** the effect of calling this function depends on the value of the first ++** parameter. ++** ++** <dl> ++** <dt>SQLITE_SESSION_CONFIG_STRMSIZE<dd> ++** By default, the sessions module streaming interfaces attempt to input ++** and output data in approximately 1 KiB chunks. This operand may be used ++** to set and query the value of this configuration setting. The pointer ++** passed as the second argument must point to a value of type (int). ++** If this value is greater than 0, it is used as the new streaming data ++** chunk size for both input and output. Before returning, the (int) value ++** pointed to by pArg is set to the final value of the streaming interface ++** chunk size. ++** </dl> ++** ++** This function returns SQLITE_OK if successful, or an SQLite error code ++** otherwise. ++*/ ++SQLITE_API int sqlite3session_config(int op, void *pArg); + + /* ++** CAPI3REF: Values for sqlite3session_config(). ++*/ ++#define SQLITE_SESSION_CONFIG_STRMSIZE 1 ++ ++/* + ** Make sure we can call this stuff from C++. + */ + #if 0 +@@ -11586,7 +12593,7 @@ + ** This way, even if the tokenizer does not provide synonyms + ** when tokenizing query text (it should not - to do would be + ** inefficient), it doesn't matter if the user queries for +-** 'first + place' or '1st + place', as there are entires in the ++** 'first + place' or '1st + place', as there are entries in the + ** FTS index corresponding to both forms of the first token. + ** </ol> + ** +@@ -11614,7 +12621,7 @@ + ** extra data to the FTS index or require FTS5 to query for multiple terms, + ** so it is efficient in terms of disk space and query speed. However, it + ** does not support prefix queries very well. If, as suggested above, the +-** token "first" is subsituted for "1st" by the tokenizer, then the query: ++** token "first" is substituted for "1st" by the tokenizer, then the query: + ** + ** <codeblock> + ** ... MATCH '1s*'</codeblock> +@@ -12221,6 +13228,21 @@ + #endif + + /* ++** Some conditionals are optimizations only. In other words, if the ++** conditionals are replaced with a constant 1 (true) or 0 (false) then ++** the correct answer is still obtained, though perhaps not as quickly. ++** ++** The following macros mark these optimizations conditionals. ++*/ ++#if defined(SQLITE_MUTATION_TEST) ++# define OK_IF_ALWAYS_TRUE(X) (1) ++# define OK_IF_ALWAYS_FALSE(X) (0) ++#else ++# define OK_IF_ALWAYS_TRUE(X) (X) ++# define OK_IF_ALWAYS_FALSE(X) (X) ++#endif ++ ++/* + ** Some malloc failures are only possible if SQLITE_TEST_REALLOC_STRESS is + ** defined. We need to defend against those failures when testing with + ** SQLITE_TEST_REALLOC_STRESS, but we don't want the unreachable branches +@@ -12414,144 +13436,153 @@ + #define TK_AS 24 + #define TK_WITHOUT 25 + #define TK_COMMA 26 +-#define TK_ID 27 +-#define TK_ABORT 28 +-#define TK_ACTION 29 +-#define TK_AFTER 30 +-#define TK_ANALYZE 31 +-#define TK_ASC 32 +-#define TK_ATTACH 33 +-#define TK_BEFORE 34 +-#define TK_BY 35 +-#define TK_CASCADE 36 +-#define TK_CAST 37 +-#define TK_COLUMNKW 38 +-#define TK_CONFLICT 39 +-#define TK_DATABASE 40 +-#define TK_DESC 41 +-#define TK_DETACH 42 +-#define TK_EACH 43 +-#define TK_FAIL 44 +-#define TK_FOR 45 +-#define TK_IGNORE 46 +-#define TK_INITIALLY 47 +-#define TK_INSTEAD 48 +-#define TK_LIKE_KW 49 +-#define TK_MATCH 50 +-#define TK_NO 51 +-#define TK_KEY 52 +-#define TK_OF 53 +-#define TK_OFFSET 54 +-#define TK_PRAGMA 55 +-#define TK_RAISE 56 +-#define TK_RECURSIVE 57 +-#define TK_REPLACE 58 +-#define TK_RESTRICT 59 +-#define TK_ROW 60 +-#define TK_TRIGGER 61 +-#define TK_VACUUM 62 +-#define TK_VIEW 63 +-#define TK_VIRTUAL 64 +-#define TK_WITH 65 +-#define TK_REINDEX 66 +-#define TK_RENAME 67 +-#define TK_CTIME_KW 68 +-#define TK_ANY 69 +-#define TK_OR 70 +-#define TK_AND 71 +-#define TK_IS 72 +-#define TK_BETWEEN 73 +-#define TK_IN 74 +-#define TK_ISNULL 75 +-#define TK_NOTNULL 76 +-#define TK_NE 77 +-#define TK_EQ 78 +-#define TK_GT 79 +-#define TK_LE 80 +-#define TK_LT 81 +-#define TK_GE 82 +-#define TK_ESCAPE 83 +-#define TK_BITAND 84 +-#define TK_BITOR 85 +-#define TK_LSHIFT 86 +-#define TK_RSHIFT 87 +-#define TK_PLUS 88 +-#define TK_MINUS 89 +-#define TK_STAR 90 +-#define TK_SLASH 91 +-#define TK_REM 92 +-#define TK_CONCAT 93 +-#define TK_COLLATE 94 +-#define TK_BITNOT 95 +-#define TK_INDEXED 96 +-#define TK_STRING 97 +-#define TK_JOIN_KW 98 +-#define TK_CONSTRAINT 99 +-#define TK_DEFAULT 100 +-#define TK_NULL 101 +-#define TK_PRIMARY 102 +-#define TK_UNIQUE 103 +-#define TK_CHECK 104 +-#define TK_REFERENCES 105 +-#define TK_AUTOINCR 106 +-#define TK_ON 107 +-#define TK_INSERT 108 +-#define TK_DELETE 109 +-#define TK_UPDATE 110 +-#define TK_SET 111 +-#define TK_DEFERRABLE 112 +-#define TK_FOREIGN 113 +-#define TK_DROP 114 +-#define TK_UNION 115 +-#define TK_ALL 116 +-#define TK_EXCEPT 117 +-#define TK_INTERSECT 118 +-#define TK_SELECT 119 +-#define TK_VALUES 120 +-#define TK_DISTINCT 121 +-#define TK_DOT 122 +-#define TK_FROM 123 +-#define TK_JOIN 124 +-#define TK_USING 125 +-#define TK_ORDER 126 +-#define TK_GROUP 127 +-#define TK_HAVING 128 +-#define TK_LIMIT 129 +-#define TK_WHERE 130 +-#define TK_INTO 131 +-#define TK_FLOAT 132 +-#define TK_BLOB 133 +-#define TK_INTEGER 134 +-#define TK_VARIABLE 135 +-#define TK_CASE 136 +-#define TK_WHEN 137 +-#define TK_THEN 138 +-#define TK_ELSE 139 +-#define TK_INDEX 140 +-#define TK_ALTER 141 +-#define TK_ADD 142 +-#define TK_TO_TEXT 143 +-#define TK_TO_BLOB 144 +-#define TK_TO_NUMERIC 145 +-#define TK_TO_INT 146 +-#define TK_TO_REAL 147 +-#define TK_ISNOT 148 +-#define TK_END_OF_FILE 149 +-#define TK_UNCLOSED_STRING 150 +-#define TK_FUNCTION 151 +-#define TK_COLUMN 152 +-#define TK_AGG_FUNCTION 153 +-#define TK_AGG_COLUMN 154 +-#define TK_UMINUS 155 +-#define TK_UPLUS 156 +-#define TK_REGISTER 157 +-#define TK_VECTOR 158 +-#define TK_SELECT_COLUMN 159 +-#define TK_IF_NULL_ROW 160 +-#define TK_ASTERISK 161 +-#define TK_SPAN 162 +-#define TK_SPACE 163 +-#define TK_ILLEGAL 164 ++#define TK_ABORT 27 ++#define TK_ACTION 28 ++#define TK_AFTER 29 ++#define TK_ANALYZE 30 ++#define TK_ASC 31 ++#define TK_ATTACH 32 ++#define TK_BEFORE 33 ++#define TK_BY 34 ++#define TK_CASCADE 35 ++#define TK_CAST 36 ++#define TK_CONFLICT 37 ++#define TK_DATABASE 38 ++#define TK_DESC 39 ++#define TK_DETACH 40 ++#define TK_EACH 41 ++#define TK_FAIL 42 ++#define TK_OR 43 ++#define TK_AND 44 ++#define TK_IS 45 ++#define TK_MATCH 46 ++#define TK_LIKE_KW 47 ++#define TK_BETWEEN 48 ++#define TK_IN 49 ++#define TK_ISNULL 50 ++#define TK_NOTNULL 51 ++#define TK_NE 52 ++#define TK_EQ 53 ++#define TK_GT 54 ++#define TK_LE 55 ++#define TK_LT 56 ++#define TK_GE 57 ++#define TK_ESCAPE 58 ++#define TK_ID 59 ++#define TK_COLUMNKW 60 ++#define TK_DO 61 ++#define TK_FOR 62 ++#define TK_IGNORE 63 ++#define TK_INITIALLY 64 ++#define TK_INSTEAD 65 ++#define TK_NO 66 ++#define TK_KEY 67 ++#define TK_OF 68 ++#define TK_OFFSET 69 ++#define TK_PRAGMA 70 ++#define TK_RAISE 71 ++#define TK_RECURSIVE 72 ++#define TK_REPLACE 73 ++#define TK_RESTRICT 74 ++#define TK_ROW 75 ++#define TK_ROWS 76 ++#define TK_TRIGGER 77 ++#define TK_VACUUM 78 ++#define TK_VIEW 79 ++#define TK_VIRTUAL 80 ++#define TK_WITH 81 ++#define TK_CURRENT 82 ++#define TK_FOLLOWING 83 ++#define TK_PARTITION 84 ++#define TK_PRECEDING 85 ++#define TK_RANGE 86 ++#define TK_UNBOUNDED 87 ++#define TK_REINDEX 88 ++#define TK_RENAME 89 ++#define TK_CTIME_KW 90 ++#define TK_ANY 91 ++#define TK_BITAND 92 ++#define TK_BITOR 93 ++#define TK_LSHIFT 94 ++#define TK_RSHIFT 95 ++#define TK_PLUS 96 ++#define TK_MINUS 97 ++#define TK_STAR 98 ++#define TK_SLASH 99 ++#define TK_REM 100 ++#define TK_CONCAT 101 ++#define TK_COLLATE 102 ++#define TK_BITNOT 103 ++#define TK_ON 104 ++#define TK_INDEXED 105 ++#define TK_STRING 106 ++#define TK_JOIN_KW 107 ++#define TK_CONSTRAINT 108 ++#define TK_DEFAULT 109 ++#define TK_NULL 110 ++#define TK_PRIMARY 111 ++#define TK_UNIQUE 112 ++#define TK_CHECK 113 ++#define TK_REFERENCES 114 ++#define TK_AUTOINCR 115 ++#define TK_INSERT 116 ++#define TK_DELETE 117 ++#define TK_UPDATE 118 ++#define TK_SET 119 ++#define TK_DEFERRABLE 120 ++#define TK_FOREIGN 121 ++#define TK_DROP 122 ++#define TK_UNION 123 ++#define TK_ALL 124 ++#define TK_EXCEPT 125 ++#define TK_INTERSECT 126 ++#define TK_SELECT 127 ++#define TK_VALUES 128 ++#define TK_DISTINCT 129 ++#define TK_DOT 130 ++#define TK_FROM 131 ++#define TK_JOIN 132 ++#define TK_USING 133 ++#define TK_ORDER 134 ++#define TK_GROUP 135 ++#define TK_HAVING 136 ++#define TK_LIMIT 137 ++#define TK_WHERE 138 ++#define TK_INTO 139 ++#define TK_NOTHING 140 ++#define TK_FLOAT 141 ++#define TK_BLOB 142 ++#define TK_INTEGER 143 ++#define TK_VARIABLE 144 ++#define TK_CASE 145 ++#define TK_WHEN 146 ++#define TK_THEN 147 ++#define TK_ELSE 148 ++#define TK_INDEX 149 ++#define TK_ALTER 150 ++#define TK_ADD 151 ++#define TK_WINDOW 152 ++#define TK_OVER 153 ++#define TK_FILTER 154 ++#define TK_TRUEFALSE 155 ++#define TK_ISNOT 156 ++#define TK_FUNCTION 157 ++#define TK_COLUMN 158 ++#define TK_AGG_FUNCTION 159 ++#define TK_AGG_COLUMN 160 ++#define TK_UMINUS 161 ++#define TK_UPLUS 162 ++#define TK_TRUTH 163 ++#define TK_REGISTER 164 ++#define TK_VECTOR 165 ++#define TK_SELECT_COLUMN 166 ++#define TK_IF_NULL_ROW 167 ++#define TK_ASTERISK 168 ++#define TK_SPAN 169 ++#define TK_END_OF_FILE 170 ++#define TK_UNCLOSED_STRING 171 ++#define TK_SPACE 172 ++#define TK_ILLEGAL 173 + + /* The token codes above must all fit in 8 bits */ + #define TKFLG_MASK 0xff +@@ -12672,6 +13703,22 @@ + #endif + + /* ++** Default value for the SQLITE_CONFIG_SORTERREF_SIZE option. ++*/ ++#ifndef SQLITE_DEFAULT_SORTERREF_SIZE ++# define SQLITE_DEFAULT_SORTERREF_SIZE 0x7fffffff ++#endif ++ ++/* ++** The compile-time options SQLITE_MMAP_READWRITE and ++** SQLITE_ENABLE_BATCH_ATOMIC_WRITE are not compatible with one another. ++** You must choose one or the other (or neither) but not both. ++*/ ++#if defined(SQLITE_MMAP_READWRITE) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) ++#error Cannot use both SQLITE_MMAP_READWRITE and SQLITE_ENABLE_BATCH_ATOMIC_WRITE ++#endif ++ ++/* + ** GCC does not define the offsetof() macro so we'll have to do it + ** ourselves. + */ +@@ -12809,7 +13856,8 @@ + # if defined(__SIZEOF_POINTER__) + # define SQLITE_PTRSIZE __SIZEOF_POINTER__ + # elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \ +- defined(_M_ARM) || defined(__arm__) || defined(__x86) ++ defined(_M_ARM) || defined(__arm__) || defined(__x86) || \ ++ (defined(__TOS_AIX__) && !defined(__64BIT__)) + # define SQLITE_PTRSIZE 4 + # else + # define SQLITE_PTRSIZE 8 +@@ -12850,7 +13898,7 @@ + # 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__) ++ defined(__arm__) || defined(_M_ARM64) + # define SQLITE_BYTEORDER 1234 + # elif defined(sparc) || defined(__ppc__) + # define SQLITE_BYTEORDER 4321 +@@ -12969,7 +14017,7 @@ + ** SELECTTRACE_ENABLED will be either 1 or 0 depending on whether or not + ** the Select query generator tracing logic is turned on. + */ +-#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_SELECTTRACE) ++#if defined(SQLITE_ENABLE_SELECTTRACE) + # define SELECTTRACE_ENABLED 1 + #else + # define SELECTTRACE_ENABLED 0 +@@ -12986,9 +14034,10 @@ + */ + typedef struct BusyHandler BusyHandler; + struct BusyHandler { +- int (*xFunc)(void *,int); /* The busy callback */ +- void *pArg; /* First arg to busy callback */ +- int nBusy; /* Incremented with each busy call */ ++ int (*xBusyHandler)(void *,int); /* The busy callback */ ++ void *pBusyArg; /* First arg to busy callback */ ++ int nBusy; /* Incremented with each busy call */ ++ u8 bExtraFileArg; /* Include sqlite3_file as callback arg */ + }; + + /* +@@ -13088,7 +14137,6 @@ + typedef struct Schema Schema; + typedef struct Expr Expr; + typedef struct ExprList ExprList; +-typedef struct ExprSpan ExprSpan; + typedef struct FKey FKey; + typedef struct FuncDestructor FuncDestructor; + typedef struct FuncDef FuncDef; +@@ -13105,6 +14153,7 @@ + typedef struct Parse Parse; + typedef struct PreUpdate PreUpdate; + typedef struct PrintfArguments PrintfArguments; ++typedef struct RenameToken RenameToken; + typedef struct RowSet RowSet; + typedef struct Savepoint Savepoint; + typedef struct Select Select; +@@ -13111,7 +14160,7 @@ + typedef struct SQLiteThread SQLiteThread; + typedef struct SelectDest SelectDest; + typedef struct SrcList SrcList; +-typedef struct StrAccum StrAccum; ++typedef struct sqlite3_str StrAccum; /* Internal alias for sqlite3_str */ + typedef struct Table Table; + typedef struct TableLock TableLock; + typedef struct Token Token; +@@ -13120,12 +14169,40 @@ + typedef struct TriggerPrg TriggerPrg; + typedef struct TriggerStep TriggerStep; + typedef struct UnpackedRecord UnpackedRecord; ++typedef struct Upsert Upsert; + typedef struct VTable VTable; + typedef struct VtabCtx VtabCtx; + typedef struct Walker Walker; + typedef struct WhereInfo WhereInfo; ++typedef struct Window Window; + typedef struct With With; + ++ ++/* ++** The bitmask datatype defined below is used for various optimizations. ++** ++** Changing this from a 64-bit to a 32-bit type limits the number of ++** tables in a join to 32 instead of 64. But it also reduces the size ++** of the library by 738 bytes on ix86. ++*/ ++#ifdef SQLITE_BITMASK_TYPE ++ typedef SQLITE_BITMASK_TYPE Bitmask; ++#else ++ typedef u64 Bitmask; ++#endif ++ ++/* ++** The number of bits in a Bitmask. "BMS" means "BitMask Size". ++*/ ++#define BMS ((int)(sizeof(Bitmask)*8)) ++ ++/* ++** A bit in a Bitmask ++*/ ++#define MASKBIT(n) (((Bitmask)1)<<(n)) ++#define MASKBIT32(n) (((unsigned int)1)<<(n)) ++#define ALLBITS ((Bitmask)-1) ++ + /* A VList object records a mapping between parameters/variables/wildcards + ** in the SQL statement (such as $abc, @pqr, or :xyz) and the integer + ** variable number associated with that parameter. See the format description +@@ -13221,7 +14298,7 @@ + SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p); + SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int); + SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *); +-SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int); ++SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int,int*); + SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); + SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*, int); + SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*); +@@ -13373,6 +14450,7 @@ + struct KeyInfo*, /* First argument to compare function */ + BtCursor *pCursor /* Space to write cursor structure */ + ); ++SQLITE_PRIVATE BtCursor *sqlite3BtreeFakeValidCursor(void); + SQLITE_PRIVATE int sqlite3BtreeCursorSize(void); + SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor*); + SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned); +@@ -13401,14 +14479,29 @@ + ** entry in either an index or table btree. + ** + ** Index btrees (used for indexes and also WITHOUT ROWID tables) contain +-** an arbitrary key and no data. These btrees have pKey,nKey set to their +-** key and pData,nData,nZero set to zero. ++** an arbitrary key and no data. These btrees have pKey,nKey set to the ++** key and the pData,nData,nZero fields are uninitialized. The aMem,nMem ++** fields give an array of Mem objects that are a decomposition of the key. ++** The nMem field might be zero, indicating that no decomposition is available. + ** + ** Table btrees (used for rowid tables) contain an integer rowid used as + ** the key and passed in the nKey field. The pKey field is zero. + ** pData,nData hold the content of the new entry. nZero extra zero bytes + ** are appended to the end of the content when constructing the entry. ++** The aMem,nMem fields are uninitialized for table btrees. + ** ++** Field usage summary: ++** ++** Table BTrees Index Btrees ++** ++** pKey always NULL encoded key ++** nKey the ROWID length of pKey ++** pData data not used ++** aMem not used decomposed key value ++** nMem not used entries in aMem ++** nData length of pData not used ++** nZero extra zeros after pData not used ++** + ** This object is used to pass information into sqlite3BtreeInsert(). The + ** same information used to be passed as five separate parameters. But placing + ** the information into this object helps to keep the interface more +@@ -13418,7 +14511,7 @@ + struct BtreePayload { + const void *pKey; /* Key content for indexes. NULL for tables */ + sqlite3_int64 nKey; /* Size of pKey for indexes. PRIMARY KEY for tabs */ +- const void *pData; /* Data for tables. NULL for indexes */ ++ const void *pData; /* Data for tables. */ + sqlite3_value *aMem; /* First of nMem value in the unpacked pKey */ + u16 nMem; /* Number of aMem[] value. Might be zero */ + int nData; /* Size of pData. 0 if none. */ +@@ -13428,11 +14521,17 @@ + SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload, + int flags, int seekResult); + SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++SQLITE_PRIVATE void sqlite3BtreeSkipNext(BtCursor*); ++#endif + SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes); + SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int flags); + SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*); + SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int flags); + SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor*); ++#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC ++SQLITE_PRIVATE i64 sqlite3BtreeOffset(BtCursor*); ++#endif + SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*); + SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt); + SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor*); +@@ -13592,7 +14691,8 @@ + u64 cycles; /* Total time spent executing this instruction */ + #endif + #ifdef SQLITE_VDBE_COVERAGE +- int iSrcLine; /* Source-code line that generated this opcode */ ++ u32 iSrcLine; /* Source-code line that generated this opcode ++ ** with flags in the upper 8 bits */ + #endif + }; + typedef struct VdbeOp VdbeOp; +@@ -13646,6 +14746,7 @@ + #define P4_INT64 (-14) /* P4 is a 64-bit signed integer */ + #define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */ + #define P4_FUNCCTX (-16) /* P4 is a pointer to an sqlite3_context object */ ++#define P4_DYNBLOB (-17) /* Pointer to memory from sqliteMalloc() */ + + /* Error message codes for OP_Halt */ + #define P5_ConstraintNotNull 1 +@@ -13691,171 +14792,177 @@ + #define OP_Savepoint 0 + #define OP_AutoCommit 1 + #define OP_Transaction 2 +-#define OP_SorterNext 3 +-#define OP_PrevIfOpen 4 +-#define OP_NextIfOpen 5 +-#define OP_Prev 6 +-#define OP_Next 7 +-#define OP_Checkpoint 8 +-#define OP_JournalMode 9 +-#define OP_Vacuum 10 +-#define OP_VFilter 11 /* synopsis: iplan=r[P3] zplan='P4' */ +-#define OP_VUpdate 12 /* synopsis: data=r[P3@P2] */ +-#define OP_Goto 13 +-#define OP_Gosub 14 +-#define OP_InitCoroutine 15 +-#define OP_Yield 16 +-#define OP_MustBeInt 17 +-#define OP_Jump 18 ++#define OP_SorterNext 3 /* jump */ ++#define OP_Prev 4 /* jump */ ++#define OP_Next 5 /* jump */ ++#define OP_Checkpoint 6 ++#define OP_JournalMode 7 ++#define OP_Vacuum 8 ++#define OP_VFilter 9 /* jump, synopsis: iplan=r[P3] zplan='P4' */ ++#define OP_VUpdate 10 /* synopsis: data=r[P3@P2] */ ++#define OP_Goto 11 /* jump */ ++#define OP_Gosub 12 /* jump */ ++#define OP_InitCoroutine 13 /* jump */ ++#define OP_Yield 14 /* jump */ ++#define OP_MustBeInt 15 /* jump */ ++#define OP_Jump 16 /* jump */ ++#define OP_Once 17 /* jump */ ++#define OP_If 18 /* jump */ + #define OP_Not 19 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */ +-#define OP_Once 20 +-#define OP_If 21 +-#define OP_IfNot 22 +-#define OP_IfNullRow 23 /* synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */ +-#define OP_SeekLT 24 /* synopsis: key=r[P3@P4] */ +-#define OP_SeekLE 25 /* synopsis: key=r[P3@P4] */ +-#define OP_SeekGE 26 /* synopsis: key=r[P3@P4] */ +-#define OP_SeekGT 27 /* synopsis: key=r[P3@P4] */ +-#define OP_NoConflict 28 /* synopsis: key=r[P3@P4] */ +-#define OP_NotFound 29 /* synopsis: key=r[P3@P4] */ +-#define OP_Found 30 /* synopsis: key=r[P3@P4] */ +-#define OP_SeekRowid 31 /* synopsis: intkey=r[P3] */ +-#define OP_NotExists 32 /* synopsis: intkey=r[P3] */ +-#define OP_Last 33 +-#define OP_IfSmaller 34 +-#define OP_SorterSort 35 +-#define OP_Sort 36 +-#define OP_Rewind 37 +-#define OP_IdxLE 38 /* synopsis: key=r[P3@P4] */ +-#define OP_IdxGT 39 /* synopsis: key=r[P3@P4] */ +-#define OP_IdxLT 40 /* synopsis: key=r[P3@P4] */ +-#define OP_IdxGE 41 /* synopsis: key=r[P3@P4] */ +-#define OP_RowSetRead 42 /* synopsis: r[P3]=rowset(P1) */ +-#define OP_RowSetTest 43 /* synopsis: if r[P3] in rowset(P1) goto P2 */ +-#define OP_Program 44 +-#define OP_FkIfZero 45 /* synopsis: if fkctr[P1]==0 goto P2 */ +-#define OP_IfPos 46 /* synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ +-#define OP_IfNotZero 47 /* synopsis: if r[P1]!=0 then r[P1]--, goto P2 */ +-#define OP_DecrJumpZero 48 /* synopsis: if (--r[P1])==0 goto P2 */ +-#define OP_IncrVacuum 49 +-#define OP_VNext 50 +-#define OP_Init 51 /* synopsis: Start at P2 */ +-#define OP_Return 52 +-#define OP_EndCoroutine 53 +-#define OP_HaltIfNull 54 /* synopsis: if r[P3]=null halt */ +-#define OP_Halt 55 +-#define OP_Integer 56 /* synopsis: r[P2]=P1 */ +-#define OP_Int64 57 /* synopsis: r[P2]=P4 */ +-#define OP_String 58 /* synopsis: r[P2]='P4' (len=P1) */ +-#define OP_Null 59 /* synopsis: r[P2..P3]=NULL */ +-#define OP_SoftNull 60 /* synopsis: r[P1]=NULL */ +-#define OP_Blob 61 /* synopsis: r[P2]=P4 (len=P1) */ +-#define OP_Variable 62 /* synopsis: r[P2]=parameter(P1,P4) */ +-#define OP_Move 63 /* synopsis: r[P2@P3]=r[P1@P3] */ +-#define OP_Copy 64 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ +-#define OP_SCopy 65 /* synopsis: r[P2]=r[P1] */ +-#define OP_IntCopy 66 /* synopsis: r[P2]=r[P1] */ +-#define OP_ResultRow 67 /* synopsis: output=r[P1@P2] */ +-#define OP_CollSeq 68 +-#define OP_AddImm 69 /* synopsis: r[P1]=r[P1]+P2 */ +-#define OP_Or 70 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */ +-#define OP_And 71 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */ +-#define OP_RealAffinity 72 +-#define OP_Cast 73 /* synopsis: affinity(r[P1]) */ +-#define OP_Permutation 74 +-#define OP_IsNull 75 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */ +-#define OP_NotNull 76 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */ +-#define OP_Ne 77 /* same as TK_NE, synopsis: IF r[P3]!=r[P1] */ +-#define OP_Eq 78 /* same as TK_EQ, synopsis: IF r[P3]==r[P1] */ +-#define OP_Gt 79 /* same as TK_GT, synopsis: IF r[P3]>r[P1] */ +-#define OP_Le 80 /* same as TK_LE, synopsis: IF r[P3]<=r[P1] */ +-#define OP_Lt 81 /* same as TK_LT, synopsis: IF r[P3]<r[P1] */ +-#define OP_Ge 82 /* same as TK_GE, synopsis: IF r[P3]>=r[P1] */ +-#define OP_ElseNotEq 83 /* same as TK_ESCAPE */ +-#define OP_BitAnd 84 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */ +-#define OP_BitOr 85 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */ +-#define OP_ShiftLeft 86 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */ +-#define OP_ShiftRight 87 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */ +-#define OP_Add 88 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */ +-#define OP_Subtract 89 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */ +-#define OP_Multiply 90 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */ +-#define OP_Divide 91 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ +-#define OP_Remainder 92 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ +-#define OP_Concat 93 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ +-#define OP_Compare 94 /* synopsis: r[P1@P3] <-> r[P2@P3] */ +-#define OP_BitNot 95 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */ +-#define OP_Column 96 /* synopsis: r[P3]=PX */ +-#define OP_String8 97 /* same as TK_STRING, synopsis: r[P2]='P4' */ +-#define OP_Affinity 98 /* synopsis: affinity(r[P1@P2]) */ +-#define OP_MakeRecord 99 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ +-#define OP_Count 100 /* synopsis: r[P2]=count() */ +-#define OP_ReadCookie 101 +-#define OP_SetCookie 102 +-#define OP_ReopenIdx 103 /* synopsis: root=P2 iDb=P3 */ +-#define OP_OpenRead 104 /* synopsis: root=P2 iDb=P3 */ +-#define OP_OpenWrite 105 /* synopsis: root=P2 iDb=P3 */ +-#define OP_OpenDup 106 +-#define OP_OpenAutoindex 107 /* synopsis: nColumn=P2 */ +-#define OP_OpenEphemeral 108 /* synopsis: nColumn=P2 */ +-#define OP_SorterOpen 109 +-#define OP_SequenceTest 110 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ +-#define OP_OpenPseudo 111 /* synopsis: P3 columns in r[P2] */ +-#define OP_Close 112 +-#define OP_ColumnsUsed 113 +-#define OP_Sequence 114 /* synopsis: r[P2]=cursor[P1].ctr++ */ +-#define OP_NewRowid 115 /* synopsis: r[P2]=rowid */ +-#define OP_Insert 116 /* synopsis: intkey=r[P3] data=r[P2] */ +-#define OP_InsertInt 117 /* synopsis: intkey=P3 data=r[P2] */ +-#define OP_Delete 118 +-#define OP_ResetCount 119 +-#define OP_SorterCompare 120 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ +-#define OP_SorterData 121 /* synopsis: r[P2]=data */ +-#define OP_RowData 122 /* synopsis: r[P2]=data */ +-#define OP_Rowid 123 /* synopsis: r[P2]=rowid */ +-#define OP_NullRow 124 +-#define OP_SorterInsert 125 /* synopsis: key=r[P2] */ +-#define OP_IdxInsert 126 /* synopsis: key=r[P2] */ +-#define OP_IdxDelete 127 /* synopsis: key=r[P2@P3] */ +-#define OP_DeferredSeek 128 /* synopsis: Move P3 to P1.rowid if needed */ +-#define OP_IdxRowid 129 /* synopsis: r[P2]=rowid */ +-#define OP_Destroy 130 +-#define OP_Clear 131 +-#define OP_Real 132 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ +-#define OP_ResetSorter 133 +-#define OP_CreateIndex 134 /* synopsis: r[P2]=root iDb=P1 */ +-#define OP_CreateTable 135 /* synopsis: r[P2]=root iDb=P1 */ +-#define OP_SqlExec 136 +-#define OP_ParseSchema 137 +-#define OP_LoadAnalysis 138 +-#define OP_DropTable 139 +-#define OP_DropIndex 140 +-#define OP_DropTrigger 141 +-#define OP_IntegrityCk 142 +-#define OP_RowSetAdd 143 /* synopsis: rowset(P1)=r[P2] */ +-#define OP_Param 144 +-#define OP_FkCounter 145 /* synopsis: fkctr[P1]+=P2 */ +-#define OP_MemMax 146 /* synopsis: r[P1]=max(r[P1],r[P2]) */ +-#define OP_OffsetLimit 147 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ +-#define OP_AggStep0 148 /* synopsis: accum=r[P3] step(r[P2@P5]) */ +-#define OP_AggStep 149 /* synopsis: accum=r[P3] step(r[P2@P5]) */ +-#define OP_AggFinal 150 /* synopsis: accum=r[P1] N=P2 */ +-#define OP_Expire 151 +-#define OP_TableLock 152 /* synopsis: iDb=P1 root=P2 write=P3 */ +-#define OP_VBegin 153 +-#define OP_VCreate 154 +-#define OP_VDestroy 155 +-#define OP_VOpen 156 +-#define OP_VColumn 157 /* synopsis: r[P3]=vcolumn(P2) */ +-#define OP_VRename 158 +-#define OP_Pagecount 159 +-#define OP_MaxPgcnt 160 +-#define OP_PureFunc0 161 +-#define OP_Function0 162 /* synopsis: r[P3]=func(r[P2@P5]) */ +-#define OP_PureFunc 163 +-#define OP_Function 164 /* synopsis: r[P3]=func(r[P2@P5]) */ +-#define OP_CursorHint 165 +-#define OP_Noop 166 +-#define OP_Explain 167 ++#define OP_IfNot 20 /* jump */ ++#define OP_IfNullRow 21 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */ ++#define OP_SeekLT 22 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_SeekLE 23 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_SeekGE 24 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_SeekGT 25 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_IfNoHope 26 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_NoConflict 27 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_NotFound 28 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_Found 29 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_SeekRowid 30 /* jump, synopsis: intkey=r[P3] */ ++#define OP_NotExists 31 /* jump, synopsis: intkey=r[P3] */ ++#define OP_Last 32 /* jump */ ++#define OP_IfSmaller 33 /* jump */ ++#define OP_SorterSort 34 /* jump */ ++#define OP_Sort 35 /* jump */ ++#define OP_Rewind 36 /* jump */ ++#define OP_IdxLE 37 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_IdxGT 38 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_IdxLT 39 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_IdxGE 40 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_RowSetRead 41 /* jump, synopsis: r[P3]=rowset(P1) */ ++#define OP_RowSetTest 42 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */ ++#define OP_Or 43 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */ ++#define OP_And 44 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */ ++#define OP_Program 45 /* jump */ ++#define OP_FkIfZero 46 /* jump, synopsis: if fkctr[P1]==0 goto P2 */ ++#define OP_IfPos 47 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ ++#define OP_IfNotZero 48 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */ ++#define OP_DecrJumpZero 49 /* jump, synopsis: if (--r[P1])==0 goto P2 */ ++#define OP_IsNull 50 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */ ++#define OP_NotNull 51 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */ ++#define OP_Ne 52 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */ ++#define OP_Eq 53 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */ ++#define OP_Gt 54 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */ ++#define OP_Le 55 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */ ++#define OP_Lt 56 /* jump, same as TK_LT, synopsis: IF r[P3]<r[P1] */ ++#define OP_Ge 57 /* jump, same as TK_GE, synopsis: IF r[P3]>=r[P1] */ ++#define OP_ElseNotEq 58 /* jump, same as TK_ESCAPE */ ++#define OP_IncrVacuum 59 /* jump */ ++#define OP_VNext 60 /* jump */ ++#define OP_Init 61 /* jump, synopsis: Start at P2 */ ++#define OP_PureFunc0 62 ++#define OP_Function0 63 /* synopsis: r[P3]=func(r[P2@P5]) */ ++#define OP_PureFunc 64 ++#define OP_Function 65 /* synopsis: r[P3]=func(r[P2@P5]) */ ++#define OP_Return 66 ++#define OP_EndCoroutine 67 ++#define OP_HaltIfNull 68 /* synopsis: if r[P3]=null halt */ ++#define OP_Halt 69 ++#define OP_Integer 70 /* synopsis: r[P2]=P1 */ ++#define OP_Int64 71 /* synopsis: r[P2]=P4 */ ++#define OP_String 72 /* synopsis: r[P2]='P4' (len=P1) */ ++#define OP_Null 73 /* synopsis: r[P2..P3]=NULL */ ++#define OP_SoftNull 74 /* synopsis: r[P1]=NULL */ ++#define OP_Blob 75 /* synopsis: r[P2]=P4 (len=P1) */ ++#define OP_Variable 76 /* synopsis: r[P2]=parameter(P1,P4) */ ++#define OP_Move 77 /* synopsis: r[P2@P3]=r[P1@P3] */ ++#define OP_Copy 78 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ ++#define OP_SCopy 79 /* synopsis: r[P2]=r[P1] */ ++#define OP_IntCopy 80 /* synopsis: r[P2]=r[P1] */ ++#define OP_ResultRow 81 /* synopsis: output=r[P1@P2] */ ++#define OP_CollSeq 82 ++#define OP_AddImm 83 /* synopsis: r[P1]=r[P1]+P2 */ ++#define OP_RealAffinity 84 ++#define OP_Cast 85 /* synopsis: affinity(r[P1]) */ ++#define OP_Permutation 86 ++#define OP_Compare 87 /* synopsis: r[P1@P3] <-> r[P2@P3] */ ++#define OP_IsTrue 88 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */ ++#define OP_Offset 89 /* synopsis: r[P3] = sqlite_offset(P1) */ ++#define OP_Column 90 /* synopsis: r[P3]=PX */ ++#define OP_Affinity 91 /* synopsis: affinity(r[P1@P2]) */ ++#define OP_BitAnd 92 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */ ++#define OP_BitOr 93 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */ ++#define OP_ShiftLeft 94 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */ ++#define OP_ShiftRight 95 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */ ++#define OP_Add 96 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */ ++#define OP_Subtract 97 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */ ++#define OP_Multiply 98 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */ ++#define OP_Divide 99 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ ++#define OP_Remainder 100 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ ++#define OP_Concat 101 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ ++#define OP_MakeRecord 102 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ ++#define OP_BitNot 103 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */ ++#define OP_Count 104 /* synopsis: r[P2]=count() */ ++#define OP_ReadCookie 105 ++#define OP_String8 106 /* same as TK_STRING, synopsis: r[P2]='P4' */ ++#define OP_SetCookie 107 ++#define OP_ReopenIdx 108 /* synopsis: root=P2 iDb=P3 */ ++#define OP_OpenRead 109 /* synopsis: root=P2 iDb=P3 */ ++#define OP_OpenWrite 110 /* synopsis: root=P2 iDb=P3 */ ++#define OP_OpenDup 111 ++#define OP_OpenAutoindex 112 /* synopsis: nColumn=P2 */ ++#define OP_OpenEphemeral 113 /* synopsis: nColumn=P2 */ ++#define OP_SorterOpen 114 ++#define OP_SequenceTest 115 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ ++#define OP_OpenPseudo 116 /* synopsis: P3 columns in r[P2] */ ++#define OP_Close 117 ++#define OP_ColumnsUsed 118 ++#define OP_SeekHit 119 /* synopsis: seekHit=P2 */ ++#define OP_Sequence 120 /* synopsis: r[P2]=cursor[P1].ctr++ */ ++#define OP_NewRowid 121 /* synopsis: r[P2]=rowid */ ++#define OP_Insert 122 /* synopsis: intkey=r[P3] data=r[P2] */ ++#define OP_InsertInt 123 /* synopsis: intkey=P3 data=r[P2] */ ++#define OP_Delete 124 ++#define OP_ResetCount 125 ++#define OP_SorterCompare 126 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ ++#define OP_SorterData 127 /* synopsis: r[P2]=data */ ++#define OP_RowData 128 /* synopsis: r[P2]=data */ ++#define OP_Rowid 129 /* synopsis: r[P2]=rowid */ ++#define OP_NullRow 130 ++#define OP_SeekEnd 131 ++#define OP_SorterInsert 132 /* synopsis: key=r[P2] */ ++#define OP_IdxInsert 133 /* synopsis: key=r[P2] */ ++#define OP_IdxDelete 134 /* synopsis: key=r[P2@P3] */ ++#define OP_DeferredSeek 135 /* synopsis: Move P3 to P1.rowid if needed */ ++#define OP_IdxRowid 136 /* synopsis: r[P2]=rowid */ ++#define OP_Destroy 137 ++#define OP_Clear 138 ++#define OP_ResetSorter 139 ++#define OP_CreateBtree 140 /* synopsis: r[P2]=root iDb=P1 flags=P3 */ ++#define OP_Real 141 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ ++#define OP_SqlExec 142 ++#define OP_ParseSchema 143 ++#define OP_LoadAnalysis 144 ++#define OP_DropTable 145 ++#define OP_DropIndex 146 ++#define OP_DropTrigger 147 ++#define OP_IntegrityCk 148 ++#define OP_RowSetAdd 149 /* synopsis: rowset(P1)=r[P2] */ ++#define OP_Param 150 ++#define OP_FkCounter 151 /* synopsis: fkctr[P1]+=P2 */ ++#define OP_MemMax 152 /* synopsis: r[P1]=max(r[P1],r[P2]) */ ++#define OP_OffsetLimit 153 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ ++#define OP_AggInverse 154 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */ ++#define OP_AggStep 155 /* synopsis: accum=r[P3] step(r[P2@P5]) */ ++#define OP_AggStep1 156 /* synopsis: accum=r[P3] step(r[P2@P5]) */ ++#define OP_AggValue 157 /* synopsis: r[P3]=value N=P2 */ ++#define OP_AggFinal 158 /* synopsis: accum=r[P1] N=P2 */ ++#define OP_Expire 159 ++#define OP_TableLock 160 /* synopsis: iDb=P1 root=P2 write=P3 */ ++#define OP_VBegin 161 ++#define OP_VCreate 162 ++#define OP_VDestroy 163 ++#define OP_VOpen 164 ++#define OP_VColumn 165 /* synopsis: r[P3]=vcolumn(P2) */ ++#define OP_VRename 166 ++#define OP_Pagecount 167 ++#define OP_MaxPgcnt 168 ++#define OP_Trace 169 ++#define OP_CursorHint 170 ++#define OP_Noop 171 ++#define OP_Explain 172 ++#define OP_Abortable 173 + + /* Properties such as "out2" or "jump" that are specified in + ** comments following the "case" for each opcode in the vdbe.c +@@ -13868,28 +14975,28 @@ + #define OPFLG_OUT2 0x10 /* out2: P2 is an output */ + #define OPFLG_OUT3 0x20 /* out3: P3 is an output */ + #define OPFLG_INITIALIZER {\ +-/* 0 */ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,\ +-/* 8 */ 0x00, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01,\ +-/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0x03, 0x03, 0x01,\ ++/* 0 */ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x10,\ ++/* 8 */ 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x03, 0x03,\ ++/* 16 */ 0x01, 0x01, 0x03, 0x12, 0x03, 0x01, 0x09, 0x09,\ + /* 24 */ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,\ +-/* 32 */ 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\ +-/* 40 */ 0x01, 0x01, 0x23, 0x0b, 0x01, 0x01, 0x03, 0x03,\ +-/* 48 */ 0x03, 0x01, 0x01, 0x01, 0x02, 0x02, 0x08, 0x00,\ +-/* 56 */ 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00,\ +-/* 64 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x02, 0x26, 0x26,\ +-/* 72 */ 0x02, 0x02, 0x00, 0x03, 0x03, 0x0b, 0x0b, 0x0b,\ +-/* 80 */ 0x0b, 0x0b, 0x0b, 0x01, 0x26, 0x26, 0x26, 0x26,\ +-/* 88 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00, 0x12,\ +-/* 96 */ 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ +-/* 104 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +-/* 112 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,\ +-/* 120 */ 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x04, 0x00,\ +-/* 128 */ 0x00, 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10,\ +-/* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,\ +-/* 144 */ 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00,\ +-/* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\ +-/* 160 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +-} ++/* 32 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\ ++/* 40 */ 0x01, 0x23, 0x0b, 0x26, 0x26, 0x01, 0x01, 0x03,\ ++/* 48 */ 0x03, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\ ++/* 56 */ 0x0b, 0x0b, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,\ ++/* 64 */ 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10, 0x10,\ ++/* 72 */ 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,\ ++/* 80 */ 0x10, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,\ ++/* 88 */ 0x12, 0x20, 0x00, 0x00, 0x26, 0x26, 0x26, 0x26,\ ++/* 96 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00, 0x12,\ ++/* 104 */ 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\ ++/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ ++/* 120 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ ++/* 128 */ 0x00, 0x10, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00,\ ++/* 136 */ 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ ++/* 144 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00,\ ++/* 152 */ 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ ++/* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\ ++/* 168 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,} + + /* The sqlite3P2Values() routine is able to run faster if it knows + ** the value of the largest JUMP opcode. The smaller the maximum +@@ -13897,7 +15004,7 @@ + ** generated this include file strives to group all JUMP opcodes + ** together near the beginning of the list. + */ +-#define SQLITE_MX_JUMP_OPCODE 83 /* Maximum JUMP opcode */ ++#define SQLITE_MX_JUMP_OPCODE 61 /* Maximum JUMP opcode */ + + /************** End of opcodes.h *********************************************/ + /************** Continuing where we left off in vdbe.h ***********************/ +@@ -13931,7 +15038,24 @@ + # define sqlite3VdbeVerifyNoMallocRequired(A,B) + # define sqlite3VdbeVerifyNoResultRow(A) + #endif +-SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno); ++#if defined(SQLITE_DEBUG) ++SQLITE_PRIVATE void sqlite3VdbeVerifyAbortable(Vdbe *p, int); ++#else ++# define sqlite3VdbeVerifyAbortable(A,B) ++#endif ++SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno); ++#ifndef SQLITE_OMIT_EXPLAIN ++SQLITE_PRIVATE void sqlite3VdbeExplain(Parse*,u8,const char*,...); ++SQLITE_PRIVATE void sqlite3VdbeExplainPop(Parse*); ++SQLITE_PRIVATE int sqlite3VdbeExplainParent(Parse*); ++# define ExplainQueryPlan(P) sqlite3VdbeExplain P ++# define ExplainQueryPlanPop(P) sqlite3VdbeExplainPop(P) ++# define ExplainQueryPlanParent(P) sqlite3VdbeExplainParent(P) ++#else ++# define ExplainQueryPlan(P) ++# define ExplainQueryPlanPop(P) ++# define ExplainQueryPlanParent(P) 0 ++#endif + SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*); + SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8); + SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1); +@@ -13975,6 +15099,7 @@ + SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*); + #endif + SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); ++SQLITE_PRIVATE int sqlite3BlobCompare(const Mem*, const Mem*); + + SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); + SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); +@@ -14030,17 +15155,43 @@ + ** + ** VdbeCoverageNeverTaken(v) // Previous branch is never taken + ** ++** VdbeCoverageNeverNull(v) // Previous three-way branch is only ++** // taken on the first two ways. The ++** // NULL option is not possible ++** ++** VdbeCoverageEqNe(v) // Previous OP_Jump is only interested ++** // in distingishing equal and not-equal. ++** + ** Every VDBE branch operation must be tagged with one of the macros above. + ** If not, then when "make test" is run with -DSQLITE_VDBE_COVERAGE and + ** -DSQLITE_DEBUG then an ALWAYS() will fail in the vdbeTakeBranch() + ** routine in vdbe.c, alerting the developer to the missed tag. ++** ++** During testing, the test application will invoke ++** sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE,...) to set a callback ++** routine that is invoked as each bytecode branch is taken. The callback ++** contains the sqlite3.c source line number ov the VdbeCoverage macro and ++** flags to indicate whether or not the branch was taken. The test application ++** is responsible for keeping track of this and reporting byte-code branches ++** that are never taken. ++** ++** See the VdbeBranchTaken() macro and vdbeTakeBranch() function in the ++** vdbe.c source file for additional information. + */ + #ifdef SQLITE_VDBE_COVERAGE + SQLITE_PRIVATE void sqlite3VdbeSetLineNumber(Vdbe*,int); + # define VdbeCoverage(v) sqlite3VdbeSetLineNumber(v,__LINE__) + # define VdbeCoverageIf(v,x) if(x)sqlite3VdbeSetLineNumber(v,__LINE__) +-# define VdbeCoverageAlwaysTaken(v) sqlite3VdbeSetLineNumber(v,2); +-# define VdbeCoverageNeverTaken(v) sqlite3VdbeSetLineNumber(v,1); ++# define VdbeCoverageAlwaysTaken(v) \ ++ sqlite3VdbeSetLineNumber(v,__LINE__|0x5000000); ++# define VdbeCoverageNeverTaken(v) \ ++ sqlite3VdbeSetLineNumber(v,__LINE__|0x6000000); ++# define VdbeCoverageNeverNull(v) \ ++ sqlite3VdbeSetLineNumber(v,__LINE__|0x4000000); ++# define VdbeCoverageNeverNullIf(v,x) \ ++ if(x)sqlite3VdbeSetLineNumber(v,__LINE__|0x4000000); ++# define VdbeCoverageEqNe(v) \ ++ sqlite3VdbeSetLineNumber(v,__LINE__|0x8000000); + # define VDBE_OFFSET_LINENO(x) (__LINE__+x) + #else + # define VdbeCoverage(v) +@@ -14047,6 +15198,9 @@ + # define VdbeCoverageIf(v,x) + # define VdbeCoverageAlwaysTaken(v) + # define VdbeCoverageNeverTaken(v) ++# define VdbeCoverageNeverNull(v) ++# define VdbeCoverageNeverNullIf(v,x) ++# define VdbeCoverageEqNe(v) + # define VDBE_OFFSET_LINENO(x) 0 + #endif + +@@ -14056,6 +15210,10 @@ + # define sqlite3VdbeScanStatus(a,b,c,d,e) + #endif + ++#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) ++SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, VdbeOp*); ++#endif ++ + #endif /* SQLITE_VDBE_H */ + + /************** End of vdbe.h ************************************************/ +@@ -14190,7 +15348,7 @@ + SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); + + /* Functions used to configure a Pager object. */ +-SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); ++SQLITE_PRIVATE void sqlite3PagerSetBusyHandler(Pager*, int(*)(void *), void *); + SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); + #ifdef SQLITE_HAS_CODEC + SQLITE_PRIVATE void sqlite3PagerAlignReserve(Pager*,Pager*); +@@ -14215,6 +15373,7 @@ + SQLITE_PRIVATE void sqlite3PagerRef(DbPage*); + SQLITE_PRIVATE void sqlite3PagerUnref(DbPage*); + SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage*); ++SQLITE_PRIVATE void sqlite3PagerUnrefPageOne(DbPage*); + + /* Operations on page references. */ + SQLITE_PRIVATE int sqlite3PagerWrite(DbPage*); +@@ -14242,18 +15401,19 @@ + SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); + SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); + SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3*); +-# ifdef SQLITE_DIRECT_OVERFLOW_READ +-SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager, Pgno); +-# endif + # ifdef SQLITE_ENABLE_SNAPSHOT + SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot); + SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot); + SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager); ++SQLITE_PRIVATE int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot); ++SQLITE_PRIVATE void sqlite3PagerSnapshotUnlock(Pager *pPager); + # endif +-#else +-# define sqlite3PagerUseWal(x,y) 0 + #endif + ++#ifdef SQLITE_DIRECT_OVERFLOW_READ ++SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno); ++#endif ++ + #ifdef SQLITE_ENABLE_ZIPVFS + SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); + #endif +@@ -14275,6 +15435,11 @@ + SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *); + SQLITE_PRIVATE void sqlite3PagerClearCache(Pager*); + SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *); ++#ifdef SQLITE_ENABLE_SETLK_TIMEOUT ++SQLITE_PRIVATE void sqlite3PagerResetLockTimeout(Pager *pPager); ++#else ++# define sqlite3PagerResetLockTimeout(X) ++#endif + + /* Functions used to truncate the database file. */ + SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno); +@@ -14351,6 +15516,8 @@ + 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 */ +@@ -14489,6 +15656,10 @@ + /* Number of dirty pages as a percentage of the configured cache size */ + SQLITE_PRIVATE int sqlite3PCachePercentDirty(PCache*); + ++#ifdef SQLITE_DIRECT_OVERFLOW_READ ++SQLITE_PRIVATE int sqlite3PCacheIsDirty(PCache *pCache); ++#endif ++ + #endif /* _PCACHE_H_ */ + + /************** End of pcache.h **********************************************/ +@@ -14732,10 +15903,12 @@ + #define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0 + SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id); + SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id); ++#ifndef SQLITE_OMIT_WAL + SQLITE_PRIVATE int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **); + SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int, int, int); + SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id); + SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int); ++#endif /* SQLITE_OMIT_WAL */ + SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64, int, void **); + SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *, i64, void *); + +@@ -14944,6 +16117,7 @@ + #define DB_SchemaLoaded 0x0001 /* The schema has been loaded */ + #define DB_UnresetViews 0x0002 /* Some views have defined column names */ + #define DB_Empty 0x0004 /* The file is empty (length 0 bytes) */ ++#define DB_ResetWanted 0x0008 /* Reset the schema when nSchemaLock==0 */ + + /* + ** The number of different kinds of things that can be limited +@@ -14975,9 +16149,9 @@ + u32 bDisable; /* Only operate the lookaside when zero */ + u16 sz; /* Size of each buffer in bytes */ + u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */ +- int nOut; /* Number of buffers currently checked out */ +- int mxOut; /* Highwater mark for nOut */ +- int anStat[3]; /* 0: hits. 1: size misses. 2: full misses */ ++ u32 nSlot; /* Number of lookaside slots allocated */ ++ u32 anStat[3]; /* 0: hits. 1: size misses. 2: full misses */ ++ LookasideSlot *pInit; /* List of buffers not previously used */ + LookasideSlot *pFree; /* List of available buffers */ + void *pStart; /* First byte of available memory space */ + void *pEnd; /* First byte past end of available space */ +@@ -14991,12 +16165,14 @@ + ** functions use a regular table table from hash.h.) + ** + ** Hash each FuncDef structure into one of the FuncDefHash.a[] slots. +-** Collisions are on the FuncDef.u.pHash chain. ++** Collisions are on the FuncDef.u.pHash chain. Use the SQLITE_FUNC_HASH() ++** macro to compute a hash on the function name. + */ + #define SQLITE_FUNC_HASH_SZ 23 + struct FuncDefHash { + FuncDef *a[SQLITE_FUNC_HASH_SZ]; /* Hash table for functions */ + }; ++#define SQLITE_FUNC_HASH(C,L) (((C)+(L))%SQLITE_FUNC_HASH_SZ) + + #ifdef SQLITE_USER_AUTHENTICATION + /* +@@ -15056,9 +16232,11 @@ + sqlite3_mutex *mutex; /* Connection mutex */ + Db *aDb; /* All backends */ + int nDb; /* Number of backends currently in use */ +- int flags; /* Miscellaneous flags. See below */ ++ u32 mDbFlags; /* flags recording internal state */ ++ u64 flags; /* flags settable by pragmas. See below */ + i64 lastRowid; /* ROWID of most recent insert (see above) */ + i64 szMmap; /* Default mmap_size setting */ ++ u32 nSchemaLock; /* Do not reset the schema when non-zero */ + unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ + int errCode; /* Most recent error code (SQLITE_*) */ + int errMask; /* & result codes with this before returning */ +@@ -15075,7 +16253,7 @@ + u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */ + u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ + u8 mTrace; /* zero or more SQLITE_TRACE flags */ +- u8 skipBtreeMutex; /* True if no shared-cache backends */ ++ u8 noSharedCache; /* True if no shared-cache backends */ + u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */ + int nextPagesize; /* Pagesize after VACUUM if >0 */ + u32 magic; /* Magic number for detect library misuse */ +@@ -15087,8 +16265,9 @@ + int newTnum; /* Rootpage of table being initialized */ + u8 iDb; /* Which db file is being initialized */ + u8 busy; /* TRUE if currently initializing */ +- u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */ +- u8 imposterTable; /* Building an imposter table */ ++ unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */ ++ unsigned imposterTable : 1; /* Building an imposter table */ ++ unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */ + } init; + int nVdbeActive; /* Number of VDBEs currently running */ + int nVdbeRead; /* Number of active VDBEs that read or write */ +@@ -15141,7 +16320,7 @@ + Hash aModule; /* populated by sqlite3_create_module() */ + VtabCtx *pVtabCtx; /* Context for active vtab connect/create */ + VTable **aVTrans; /* Virtual tables with open transactions */ +- VTable *pDisconnect; /* Disconnect these in next sqlite3_prepare() */ ++ VTable *pDisconnect; /* Disconnect these in next sqlite3_prepare() */ + #endif + Hash aFunc; /* Hash table of connection functions */ + Hash aCollSeq; /* All collating sequences */ +@@ -15210,27 +16389,36 @@ + #define SQLITE_ForeignKeys 0x00004000 /* Enforce foreign key constraints */ + #define SQLITE_AutoIndex 0x00008000 /* Enable automatic indexes */ + #define SQLITE_LoadExtension 0x00010000 /* Enable load_extension */ +-#define SQLITE_EnableTrigger 0x00020000 /* True to enable triggers */ +-#define SQLITE_DeferFKs 0x00040000 /* Defer all FK constraints */ +-#define SQLITE_QueryOnly 0x00080000 /* Disable database changes */ +-#define SQLITE_CellSizeCk 0x00100000 /* Check btree cell sizes on load */ +-#define SQLITE_Fts3Tokenizer 0x00200000 /* Enable fts3_tokenizer(2) */ +-#define SQLITE_EnableQPSG 0x00400000 /* Query Planner Stability Guarantee */ +-/* The next four values are not used by PRAGMAs or by sqlite3_dbconfig() and +-** could be factored out into a separate bit vector of the sqlite3 object. */ +-#define SQLITE_InternChanges 0x00800000 /* Uncommitted Hash table changes */ +-#define SQLITE_LoadExtFunc 0x01000000 /* Enable load_extension() SQL func */ +-#define SQLITE_PreferBuiltin 0x02000000 /* Preference to built-in funcs */ +-#define SQLITE_Vacuum 0x04000000 /* Currently in a VACUUM */ ++#define SQLITE_LoadExtFunc 0x00020000 /* Enable load_extension() SQL func */ ++#define SQLITE_EnableTrigger 0x00040000 /* True to enable triggers */ ++#define SQLITE_DeferFKs 0x00080000 /* Defer all FK constraints */ ++#define SQLITE_QueryOnly 0x00100000 /* Disable database changes */ ++#define SQLITE_CellSizeCk 0x00200000 /* Check btree cell sizes on load */ ++#define SQLITE_Fts3Tokenizer 0x00400000 /* Enable fts3_tokenizer(2) */ ++#define SQLITE_EnableQPSG 0x00800000 /* Query Planner Stability Guarantee*/ ++#define SQLITE_TriggerEQP 0x01000000 /* Show trigger EXPLAIN QUERY PLAN */ ++#define SQLITE_ResetDatabase 0x02000000 /* Reset the database */ ++#define SQLITE_LegacyAlter 0x04000000 /* Legacy ALTER TABLE behaviour */ ++#define SQLITE_NoSchemaError 0x08000000 /* Do not report schema parse errors*/ ++#define SQLITE_Defensive 0x10000000 /* Input SQL is likely hostile */ ++ + /* Flags used only if debugging */ ++#define HI(X) ((u64)(X)<<32) + #ifdef SQLITE_DEBUG +-#define SQLITE_SqlTrace 0x08000000 /* Debug print SQL as it executes */ +-#define SQLITE_VdbeListing 0x10000000 /* Debug listings of VDBE programs */ +-#define SQLITE_VdbeTrace 0x20000000 /* True to trace VDBE execution */ +-#define SQLITE_VdbeAddopTrace 0x40000000 /* Trace sqlite3VdbeAddOp() calls */ +-#define SQLITE_VdbeEQP 0x80000000 /* Debug EXPLAIN QUERY PLAN */ ++#define SQLITE_SqlTrace HI(0x0001) /* Debug print SQL as it executes */ ++#define SQLITE_VdbeListing HI(0x0002) /* Debug listings of VDBE progs */ ++#define SQLITE_VdbeTrace HI(0x0004) /* True to trace VDBE execution */ ++#define SQLITE_VdbeAddopTrace HI(0x0008) /* Trace sqlite3VdbeAddOp() calls */ ++#define SQLITE_VdbeEQP HI(0x0010) /* Debug EXPLAIN QUERY PLAN */ + #endif + ++/* ++** Allowed values for sqlite3.mDbFlags ++*/ ++#define DBFLAG_SchemaChange 0x0001 /* Uncommitted Hash table changes */ ++#define DBFLAG_PreferBuiltin 0x0002 /* Preference to built-in funcs */ ++#define DBFLAG_Vacuum 0x0004 /* Currently in a VACUUM */ ++#define DBFLAG_SchemaKnownOk 0x0008 /* Schema is known to be valid */ + + /* + ** Bits of the sqlite3.dbOptFlags field that are used by the +@@ -15238,19 +16426,22 @@ + ** selectively disable various optimizations. + */ + #define SQLITE_QueryFlattener 0x0001 /* Query flattening */ +-#define SQLITE_ColumnCache 0x0002 /* Column cache */ ++ /* 0x0002 available for reuse */ + #define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */ + #define SQLITE_FactorOutConst 0x0008 /* Constant factoring */ +-/* not used 0x0010 // Was: SQLITE_IdxRealAsInt */ +-#define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */ +-#define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */ +-#define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */ +-#define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */ +-#define SQLITE_Transitive 0x0200 /* Transitive constraints */ +-#define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */ ++#define SQLITE_DistinctOpt 0x0010 /* DISTINCT using indexes */ ++#define SQLITE_CoverIdxScan 0x0020 /* Covering index scans */ ++#define SQLITE_OrderByIdxJoin 0x0040 /* ORDER BY of joins via index */ ++#define SQLITE_Transitive 0x0080 /* Transitive constraints */ ++#define SQLITE_OmitNoopJoin 0x0100 /* Omit unused tables in joins */ ++#define SQLITE_CountOfView 0x0200 /* The count-of-view optimization */ ++#define SQLITE_CursorHints 0x0400 /* Add OP_CursorHint opcodes */ + #define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */ +-#define SQLITE_CountOfView 0x1000 /* The count-of-view optimization */ +-#define SQLITE_CursorHints 0x2000 /* Add OP_CursorHint opcodes */ ++ /* TH3 expects the Stat34 ^^^^^^ value to be 0x0800. Don't change it */ ++#define SQLITE_PushDown 0x1000 /* The push-down optimization */ ++#define SQLITE_SimplifyJoin 0x2000 /* Convert LEFT JOIN to JOIN */ ++#define SQLITE_SkipScan 0x4000 /* Skip-scans */ ++#define SQLITE_PropagateConst 0x8000 /* The constant propagation opt */ + #define SQLITE_AllOpts 0xffff /* All optimizations */ + + /* +@@ -15289,11 +16480,13 @@ + */ + struct FuncDef { + i8 nArg; /* Number of arguments. -1 means unlimited */ +- u16 funcFlags; /* Some combination of SQLITE_FUNC_* */ ++ u32 funcFlags; /* Some combination of SQLITE_FUNC_* */ + void *pUserData; /* User data parameter */ + FuncDef *pNext; /* Next function with same name */ + void (*xSFunc)(sqlite3_context*,int,sqlite3_value**); /* func or agg-step */ + void (*xFinalize)(sqlite3_context*); /* Agg finalizer */ ++ void (*xValue)(sqlite3_context*); /* Current agg value */ ++ void (*xInverse)(sqlite3_context*,int,sqlite3_value**); /* inverse agg-step */ + const char *zName; /* SQL name of the function. */ + union { + FuncDef *pHash; /* Next with a different name but the same hash */ +@@ -15349,6 +16542,10 @@ + #define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a + ** single query - might change over time */ + #define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */ ++#define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */ ++#define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */ ++#define SQLITE_FUNC_WINDOW_SIZE 0x20000 /* Requires partition size as arg. */ ++#define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */ + + /* + ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are +@@ -15383,6 +16580,12 @@ + ** are interpreted in the same way as the first 4 parameters to + ** FUNCTION(). + ** ++** WFUNCTION(zName, nArg, iArg, xStep, xFinal, xValue, xInverse) ++** Used to create an aggregate function definition implemented by ++** the C functions xStep and xFinal. The first four parameters ++** are interpreted in the same way as the first 4 parameters to ++** FUNCTION(). ++** + ** LIKEFUNC(zName, nArg, pArg, flags) + ** Used to create a scalar function definition of a function zName + ** that accepts nArg arguments and is implemented by a call to C +@@ -15393,32 +16596,39 @@ + */ + #define FUNCTION(zName, nArg, iArg, bNC, xFunc) \ + {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ +- SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} } ++ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} } + #define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \ + {nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ +- SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} } ++ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} } + #define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \ + {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8, \ +- 0, 0, xFunc, 0, #zName, {0} } ++ 0, 0, xFunc, 0, 0, 0, #zName, {0} } + #define PURE_DATE(zName, nArg, iArg, bNC, xFunc) \ + {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \ +- (void*)&sqlite3Config, 0, xFunc, 0, #zName, {0} } ++ (void*)&sqlite3Config, 0, xFunc, 0, 0, 0, #zName, {0} } + #define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \ + {nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\ +- SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} } ++ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} } + #define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \ + {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ +- pArg, 0, xFunc, 0, #zName, } ++ pArg, 0, xFunc, 0, 0, 0, #zName, } + #define LIKEFUNC(zName, nArg, arg, flags) \ + {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \ +- (void *)arg, 0, likeFunc, 0, #zName, {0} } +-#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \ ++ (void *)arg, 0, likeFunc, 0, 0, 0, #zName, {0} } ++#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue) \ + {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \ +- SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,#zName, {0}} ++ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,0,#zName, {0}} + #define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \ + {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \ +- SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,#zName, {0}} ++ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xFinal,0,#zName, {0}} ++#define WAGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue, xInverse, f) \ ++ {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|f, \ ++ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,xInverse,#zName, {0}} ++#define INTERNAL_FUNCTION(zName, nArg, xFunc) \ ++ {nArg, SQLITE_FUNC_INTERNAL|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \ ++ 0, 0, xFunc, 0, 0, 0, #zName, {0} } + ++ + /* + ** All current savepoints are stored in a linked list starting at + ** sqlite3.pSavepoint. The first element in the list is the most recently +@@ -15473,6 +16683,8 @@ + #define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */ + #define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */ + #define COLFLAG_HASTYPE 0x0004 /* Type name follows column name */ ++#define COLFLAG_UNIQUE 0x0008 /* Column def contains "UNIQUE" or "PK" */ ++#define COLFLAG_SORTERREF 0x0010 /* Use sorter-refs with this column */ + + /* + ** A "Collating Sequence" is defined by an instance of the following +@@ -15600,6 +16812,9 @@ + struct Table { + char *zName; /* Name of the table or view */ + Column *aCol; /* Information about each column */ ++#ifdef SQLITE_ENABLE_NORMALIZE ++ Hash *pColHash; /* All columns indexed by name */ ++#endif + Index *pIndex; /* List of SQL indexes on this table. */ + Select *pSelect; /* NULL for tables. Points to definition if a view. */ + FKey *pFKey; /* Linked list of all foreign keys in this table */ +@@ -15650,6 +16865,7 @@ + #define TF_StatsUsed 0x0100 /* Query planner decisions affected by + ** Index.aiRowLogEst[] values */ + #define TF_HasNotNull 0x0200 /* Contains NOT NULL constraints */ ++#define TF_Shadow 0x0400 /* True for a shadow table */ + + /* + ** Test to see whether or not a table is a virtual table. This is +@@ -15760,15 +16976,14 @@ + #define OE_Fail 3 /* Stop the operation but leave all prior changes */ + #define OE_Ignore 4 /* Ignore the error. Do not do the INSERT or UPDATE */ + #define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */ ++#define OE_Update 6 /* Process as a DO UPDATE in an upsert */ ++#define OE_Restrict 7 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */ ++#define OE_SetNull 8 /* Set the foreign key value to NULL */ ++#define OE_SetDflt 9 /* Set the foreign key value to its default */ ++#define OE_Cascade 10 /* Cascade the changes */ ++#define OE_Default 11 /* Do whatever the default action is */ + +-#define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */ +-#define OE_SetNull 7 /* Set the foreign key value to NULL */ +-#define OE_SetDflt 8 /* Set the foreign key value to its default */ +-#define OE_Cascade 9 /* Cascade the changes */ + +-#define OE_Default 10 /* Do whatever the default action is */ +- +- + /* + ** An instance of the following structure is passed as the first + ** argument to sqlite3VdbeKeyCompare and is used to control the +@@ -15781,8 +16996,8 @@ + struct KeyInfo { + u32 nRef; /* Number of references to this KeyInfo object */ + u8 enc; /* Text encoding - one of the SQLITE_UTF* values */ +- u16 nField; /* Number of key columns in the index */ +- u16 nXField; /* Number of columns beyond the key columns */ ++ u16 nKeyField; /* Number of key columns in the index */ ++ u16 nAllField; /* Total columns, including key plus others */ + sqlite3 *db; /* The database connection */ + u8 *aSortOrder; /* Sort order for each column. */ + CollSeq *aColl[1]; /* Collating sequence for each term of the key */ +@@ -15829,8 +17044,8 @@ + u16 nField; /* Number of entries in apMem[] */ + i8 default_rc; /* Comparison result if keys are equal */ + u8 errCode; /* Error detected by xRecordCompare (CORRUPT or NOMEM) */ +- i8 r1; /* Value to return if (lhs > rhs) */ +- i8 r2; /* Value to return if (rhs < lhs) */ ++ i8 r1; /* Value to return if (lhs < rhs) */ ++ i8 r2; /* Value to return if (lhs > rhs) */ + u8 eqSeen; /* True if an equality comparison has been seen */ + }; + +@@ -15893,6 +17108,7 @@ + unsigned isCovering:1; /* True if this is a covering index */ + unsigned noSkipScan:1; /* Do not try to use skip-scan if true */ + unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */ ++ unsigned bNoQuery:1; /* Do not use this index to optimize queries */ + #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + int nSample; /* Number of elements in aSample[] */ + int nSampleCol; /* Size of IndexSample.anEq[] and so on */ +@@ -15901,6 +17117,7 @@ + tRowcnt *aiRowEst; /* Non-logarithmic stat1 data for this index */ + tRowcnt nRowEst0; /* Non-logarithmic number of rows in the index */ + #endif ++ Bitmask colNotIdxed; /* 0 for unindexed columns in pTab */ + }; + + /* +@@ -15936,12 +17153,20 @@ + }; + + /* ++** Possible values to use within the flags argument to sqlite3GetToken(). ++*/ ++#define SQLITE_TOKEN_QUOTED 0x1 /* Token is a quoted identifier. */ ++#define SQLITE_TOKEN_KEYWORD 0x2 /* Token is a keyword. */ ++ ++/* + ** Each token coming out of the lexer is an instance of + ** this structure. Tokens are also used as part of an expression. + ** +-** Note if Token.z==0 then Token.dyn and Token.n are undefined and +-** may contain random values. Do not make any assumptions about Token.dyn +-** and Token.n when Token.z==0. ++** The memory that "z" points to is owned by other objects. Take care ++** that the owner of the "z" string does not deallocate the string before ++** the Token goes out of scope! Very often, the "z" points to some place ++** in the middle of the Parse.zSql text. But it might also point to a ++** static string. + */ + struct Token { + const char *z; /* Text of the token. Not NULL-terminated! */ +@@ -16114,7 +17339,11 @@ + ** TK_COLUMN: the value of p5 for OP_Column + ** TK_AGG_FUNCTION: nesting depth */ + AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ +- Table *pTab; /* Table for TK_COLUMN expressions. */ ++ union { ++ Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL ++ ** for a column of an index on an expression */ ++ Window *pWin; /* TK_FUNCTION: Window definition for the func */ ++ } y; + }; + + /* +@@ -16122,8 +17351,8 @@ + */ + #define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */ + #define EP_Agg 0x000002 /* Contains one or more aggregate functions */ +- /* 0x000004 // available for use */ +- /* 0x000008 // available for use */ ++#define EP_HasFunc 0x000004 /* Contains one or more functions of any kind */ ++#define EP_FixedCol 0x000008 /* TK_Column with a known fixed value */ + #define EP_Distinct 0x000010 /* Aggregate function with DISTINCT keyword */ + #define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */ + #define EP_DblQuoted 0x000040 /* token.z was originally in "..." */ +@@ -16144,11 +17373,13 @@ + #define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */ + #define EP_Alias 0x400000 /* Is an alias for a result set column */ + #define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */ ++#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */ + + /* +-** Combinations of two or more EP_* flags ++** The EP_Propagate mask is a set of properties that automatically propagate ++** upwards into parent nodes. + */ +-#define EP_Propagate (EP_Collate|EP_Subquery) /* Propagate these bits up tree */ ++#define EP_Propagate (EP_Collate|EP_Subquery|EP_HasFunc) + + /* + ** These macros can be used to test, set, or clear bits in the +@@ -16202,7 +17433,6 @@ + */ + struct ExprList { + int nExpr; /* Number of expressions on the list */ +- int nAlloc; /* Number of a[] slots allocated */ + struct ExprList_item { /* For each expression in the list */ + Expr *pExpr; /* The parse tree for this expression */ + char *zName; /* Token associated with this expression */ +@@ -16211,6 +17441,7 @@ + unsigned done :1; /* A flag to indicate when processing is finished */ + unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */ + unsigned reusable :1; /* Constant expression is reusable */ ++ unsigned bSorterRef :1; /* Defer evaluation until after sorting */ + union { + struct { + u16 iOrderByCol; /* For ORDER BY, column number in result set */ +@@ -16222,17 +17453,6 @@ + }; + + /* +-** An instance of this structure is used by the parser to record both +-** the parse tree for an expression and the span of input text for an +-** expression. +-*/ +-struct ExprSpan { +- Expr *pExpr; /* The expression parse tree */ +- const char *zStart; /* First character of input text */ +- const char *zEnd; /* One character past the end of input text */ +-}; +- +-/* + ** An instance of this structure can hold a simple list of identifiers, + ** such as the list "a,b,c" in the following statements: + ** +@@ -16256,31 +17476,6 @@ + }; + + /* +-** The bitmask datatype defined below is used for various optimizations. +-** +-** Changing this from a 64-bit to a 32-bit type limits the number of +-** tables in a join to 32 instead of 64. But it also reduces the size +-** of the library by 738 bytes on ix86. +-*/ +-#ifdef SQLITE_BITMASK_TYPE +- typedef SQLITE_BITMASK_TYPE Bitmask; +-#else +- typedef u64 Bitmask; +-#endif +- +-/* +-** The number of bits in a Bitmask. "BMS" means "BitMask Size". +-*/ +-#define BMS ((int)(sizeof(Bitmask)*8)) +- +-/* +-** A bit in a Bitmask +-*/ +-#define MASKBIT(n) (((Bitmask)1)<<(n)) +-#define MASKBIT32(n) (((unsigned int)1)<<(n)) +-#define ALLBITS ((Bitmask)-1) +- +-/* + ** The following structure describes the FROM clause of a SELECT statement. + ** Each table or subquery in the FROM clause is a separate element of + ** the SrcList.a[] array. +@@ -16321,9 +17516,6 @@ + unsigned viaCoroutine :1; /* Implemented as a co-routine */ + unsigned isRecursive :1; /* True for recursive reference in WITH */ + } fg; +-#ifndef SQLITE_OMIT_EXPLAIN +- u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */ +-#endif + int iCursor; /* The VDBE cursor number used to access this table */ + Expr *pOn; /* The ON clause of a join */ + IdList *pUsing; /* The USING clause of a join */ +@@ -16405,12 +17597,16 @@ + struct NameContext { + Parse *pParse; /* The parser */ + SrcList *pSrcList; /* One or more tables used to resolve names */ +- ExprList *pEList; /* Optional list of result-set columns */ +- AggInfo *pAggInfo; /* Information about aggregates at this level */ ++ union { ++ ExprList *pEList; /* Optional list of result-set columns */ ++ AggInfo *pAggInfo; /* Information about aggregates at this level */ ++ Upsert *pUpsert; /* ON CONFLICT clause information from an upsert */ ++ } uNC; + NameContext *pNext; /* Next outer name context. NULL for outermost */ + int nRef; /* Number of names resolved by this context */ + int nErr; /* Number of errors encountered while resolving names */ + u16 ncFlags; /* Zero or more NC_* flags defined below */ ++ Select *pWinSelect; /* SELECT statement for any window functions */ + }; + + /* +@@ -16428,17 +17624,49 @@ + #define NC_HasAgg 0x0010 /* One or more aggregate functions seen */ + #define NC_IdxExpr 0x0020 /* True if resolving columns of CREATE INDEX */ + #define NC_VarSelect 0x0040 /* A correlated subquery has been seen */ ++#define NC_UEList 0x0080 /* True if uNC.pEList is used */ ++#define NC_UAggInfo 0x0100 /* True if uNC.pAggInfo is used */ ++#define NC_UUpsert 0x0200 /* True if uNC.pUpsert is used */ + #define NC_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */ ++#define NC_Complex 0x2000 /* True if a function or subquery seen */ ++#define NC_AllowWin 0x4000 /* Window functions are allowed here */ + + /* ++** An instance of the following object describes a single ON CONFLICT ++** clause in an upsert. ++** ++** The pUpsertTarget field is only set if the ON CONFLICT clause includes ++** conflict-target clause. (In "ON CONFLICT(a,b)" the "(a,b)" is the ++** conflict-target clause.) The pUpsertTargetWhere is the optional ++** WHERE clause used to identify partial unique indexes. ++** ++** pUpsertSet is the list of column=expr terms of the UPDATE statement. ++** The pUpsertSet field is NULL for a ON CONFLICT DO NOTHING. The ++** pUpsertWhere is the WHERE clause for the UPDATE and is NULL if the ++** WHERE clause is omitted. ++*/ ++struct Upsert { ++ ExprList *pUpsertTarget; /* Optional description of conflicting index */ ++ Expr *pUpsertTargetWhere; /* WHERE clause for partial index targets */ ++ ExprList *pUpsertSet; /* The SET clause from an ON CONFLICT UPDATE */ ++ Expr *pUpsertWhere; /* WHERE clause for the ON CONFLICT UPDATE */ ++ /* The fields above comprise the parse tree for the upsert clause. ++ ** The fields below are used to transfer information from the INSERT ++ ** processing down into the UPDATE processing while generating code. ++ ** Upsert owns the memory allocated above, but not the memory below. */ ++ Index *pUpsertIdx; /* Constraint that pUpsertTarget identifies */ ++ SrcList *pUpsertSrc; /* Table to be updated */ ++ int regData; /* First register holding array of VALUES */ ++ int iDataCur; /* Index of the data cursor */ ++ int iIdxCur; /* Index of the first index cursor */ ++}; ++ ++/* + ** An instance of the following structure contains all information + ** needed to generate code for a single SELECT statement. + ** +-** nLimit is set to -1 if there is no LIMIT clause. nOffset is set to 0. +-** If there is a LIMIT clause, the parser sets nLimit to the value of the +-** limit and nOffset to the value of the offset (or 0 if there is not +-** offset). But later on, nLimit and nOffset become the memory locations +-** in the VDBE that record the limit and offset counters. ++** See the header comment on the computeLimitRegisters() routine for a ++** detailed description of the meaning of the iLimit and iOffset fields. + ** + ** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes. + ** These addresses must be stored so that we can go back and fill in +@@ -16456,9 +17684,7 @@ + LogEst nSelectRow; /* Estimated number of result rows */ + u32 selFlags; /* Various SF_* values */ + int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */ +-#if SELECTTRACE_ENABLED +- char zSelName[12]; /* Symbolic name of this SELECT use for debugging */ +-#endif ++ u32 selId; /* Unique identifier number for this SELECT */ + int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */ + SrcList *pSrc; /* The FROM clause */ + Expr *pWhere; /* The WHERE clause */ +@@ -16468,8 +17694,11 @@ + Select *pPrior; /* Prior select in a compound select statement */ + Select *pNext; /* Next select to the left in a compound */ + Expr *pLimit; /* LIMIT expression. NULL means not used. */ +- Expr *pOffset; /* OFFSET expression. NULL means not used. */ + With *pWith; /* WITH clause attached to this select. Or NULL. */ ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ Window *pWin; /* List of window functions */ ++ Window *pWinDefn; /* List of named window definitions */ ++#endif + }; + + /* +@@ -16499,8 +17728,8 @@ + #define SF_MaybeConvert 0x08000 /* Need convertCompoundSelectToSubquery() */ + #define SF_Converted 0x10000 /* By convertCompoundSelectToSubquery() */ + #define SF_IncludeHidden 0x20000 /* Include hidden columns in output */ ++#define SF_ComplexResult 0x40000 /* Result contains subquery or function */ + +- + /* + ** The results of a SELECT can be distributed in several ways, as defined + ** by one of the following macros. The "SRT" prefix means "SELECT Result +@@ -16614,13 +17843,6 @@ + }; + + /* +-** Size of the column cache +-*/ +-#ifndef SQLITE_N_COLCACHE +-# define SQLITE_N_COLCACHE 10 +-#endif +- +-/* + ** At least one instance of the following structure is created for each + ** trigger that may be fired while parsing an INSERT, UPDATE or DELETE + ** statement. All such objects are stored in the linked list headed at +@@ -16695,7 +17917,6 @@ + u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ + u8 okConstFactor; /* OK to factor out constants */ + u8 disableLookaside; /* Number of times lookaside has been disabled */ +- u8 nColCache; /* Number of entries in aColCache[] */ + int nRangeReg; /* Size of the temporary register block */ + int iRangeReg; /* First register in temporary register block */ + int nErr; /* Number of errors seen */ +@@ -16703,10 +17924,8 @@ + int nMem; /* Number of memory cells used so far */ + int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */ + int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */ +- int iSelfTab; /* Table for associated with an index on expr, or negative ++ int iSelfTab; /* Table associated with an index on expr, or negative + ** of the base register during check-constraint eval */ +- int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */ +- int iCacheCnt; /* Counter used to generate aColCache[].lru values */ + int nLabel; /* Number of labels used */ + int *aLabel; /* Space to hold the labels */ + ExprList *pConstExpr;/* Constant expressions */ +@@ -16716,10 +17935,7 @@ + int regRowid; /* Register holding rowid of CREATE TABLE entry */ + int regRoot; /* Register holding root page number for new objects */ + int nMaxArg; /* Max args passed to user function by sub-program */ +-#if SELECTTRACE_ENABLED +- int nSelect; /* Number of SELECT statements seen */ +- int nSelectIndent; /* How far to indent SELECTTRACE() output */ +-#endif ++ int nSelect; /* Number of SELECT stmts. Counter for Select.selId */ + #ifndef SQLITE_OMIT_SHARED_CACHE + int nTableLock; /* Number of locks in aTableLock */ + TableLock *aTableLock; /* Required table locks for shared-cache mode */ +@@ -16727,7 +17943,7 @@ + AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ + Parse *pToplevel; /* Parse structure for main program (or NULL) */ + Table *pTriggerTab; /* Table triggers are being coded for */ +- int addrCrTab; /* Address of OP_CreateTable opcode on CREATE TABLE */ ++ int addrCrTab; /* Address of OP_CreateBtree opcode on CREATE TABLE */ + u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ + u32 oldmask; /* Mask of old.* columns referenced */ + u32 newmask; /* Mask of new.* columns referenced */ +@@ -16739,17 +17955,9 @@ + ** Fields above must be initialized to zero. The fields that follow, + ** down to the beginning of the recursive section, do not need to be + ** initialized as they will be set before being used. The boundary is +- ** determined by offsetof(Parse,aColCache). ++ ** determined by offsetof(Parse,aTempReg). + **************************************************************************/ + +- struct yColCache { +- int iTable; /* Table cursor number */ +- i16 iColumn; /* Table column number */ +- u8 tempReg; /* iReg is a temp register that needs to be freed */ +- int iLevel; /* Nesting level */ +- int iReg; /* Reg with value of this column. 0 means none. */ +- int lru; /* Least recently used entry has the smallest value */ +- } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */ + int aTempReg[8]; /* Holding area for temporary registers */ + Token sNameToken; /* Token with unqualified schema object name */ + +@@ -16764,19 +17972,21 @@ + ynVar nVar; /* Number of '?' variables seen in the SQL so far */ + u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */ + u8 explain; /* True if the EXPLAIN flag is found on the query */ ++#if !(defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_OMIT_ALTERTABLE)) ++ u8 eParseMode; /* PARSE_MODE_XXX constant */ ++#endif + #ifndef SQLITE_OMIT_VIRTUALTABLE +- u8 declareVtab; /* True if inside sqlite3_declare_vtab() */ + int nVtabLock; /* Number of virtual tables to lock */ + #endif + int nHeight; /* Expression tree height of current sub-select */ + #ifndef SQLITE_OMIT_EXPLAIN +- int iSelectId; /* ID of current select for EXPLAIN output */ +- int iNextSelectId; /* Next available select ID for EXPLAIN output */ ++ int addrExplain; /* Address of current OP_Explain opcode */ + #endif + VList *pVList; /* Mapping between variable names and numbers */ + Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */ + const char *zTail; /* All SQL text past the last semicolon parsed */ + Table *pNewTable; /* A table being constructed by CREATE TABLE */ ++ Index *pNewIndex; /* An index being constructed by CREATE INDEX */ + Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */ + const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ + #ifndef SQLITE_OMIT_VIRTUALTABLE +@@ -16787,12 +17997,20 @@ + TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ + With *pWith; /* Current WITH clause, or NULL */ + With *pWithToFree; /* Free this WITH object at the end of the parse */ ++#ifndef SQLITE_OMIT_ALTERTABLE ++ RenameToken *pRename; /* Tokens subject to renaming by ALTER TABLE */ ++#endif + }; + ++#define PARSE_MODE_NORMAL 0 ++#define PARSE_MODE_DECLARE_VTAB 1 ++#define PARSE_MODE_RENAME_COLUMN 2 ++#define PARSE_MODE_RENAME_TABLE 3 ++ + /* + ** Sizes and pointers of various parts of the Parse object. + */ +-#define PARSE_HDR_SZ offsetof(Parse,aColCache) /* Recursive part w/o aColCache*/ ++#define PARSE_HDR_SZ offsetof(Parse,aTempReg) /* Recursive part w/o aColCache*/ + #define PARSE_RECURSE_SZ offsetof(Parse,sLastToken) /* Recursive part */ + #define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */ + #define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */ +@@ -16803,9 +18021,21 @@ + #ifdef SQLITE_OMIT_VIRTUALTABLE + #define IN_DECLARE_VTAB 0 + #else +- #define IN_DECLARE_VTAB (pParse->declareVtab) ++ #define IN_DECLARE_VTAB (pParse->eParseMode==PARSE_MODE_DECLARE_VTAB) + #endif + ++#if defined(SQLITE_OMIT_ALTERTABLE) ++ #define IN_RENAME_OBJECT 0 ++#else ++ #define IN_RENAME_OBJECT (pParse->eParseMode>=PARSE_MODE_RENAME_COLUMN) ++#endif ++ ++#if defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_OMIT_ALTERTABLE) ++ #define IN_SPECIAL_PARSE 0 ++#else ++ #define IN_SPECIAL_PARSE (pParse->eParseMode!=PARSE_MODE_NORMAL) ++#endif ++ + /* + ** An instance of the following structure can be declared on a stack and used + ** to save the Parse.zAuthContext value so that it can be restored later. +@@ -16829,6 +18059,7 @@ + */ + #define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */ + /* Also used in P2 (not P5) of OP_Delete */ ++#define OPFLAG_NOCHNG 0x01 /* OP_VColumn nochange for UPDATE */ + #define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */ + #define OPFLAG_LASTROWID 0x20 /* Set to update db->lastRowid */ + #define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */ +@@ -16844,6 +18075,7 @@ + #define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ + #define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete/Insert: save cursor pos */ + #define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */ ++#define OPFLAG_NOCHNG_MAGIC 0x6d /* OP_MakeRecord: serialtype 10 is ok */ + + /* + * Each trigger present in the database schema is stored as an instance of +@@ -16929,8 +18161,10 @@ + Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */ + char *zTarget; /* Target table for DELETE, UPDATE, INSERT */ + Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */ +- ExprList *pExprList; /* SET clause for UPDATE. */ ++ ExprList *pExprList; /* SET clause for UPDATE */ + IdList *pIdList; /* Column names for INSERT */ ++ Upsert *pUpsert; /* Upsert clauses on an INSERT */ ++ char *zSpan; /* Original SQL text of this command */ + TriggerStep *pNext; /* Next in the link-list */ + TriggerStep *pLast; /* Last element in link-list. Valid for 1st elem only */ + }; +@@ -16954,18 +18188,15 @@ + ** An objected used to accumulate the text of a string where we + ** do not necessarily know how big the string will be in the end. + */ +-struct StrAccum { ++struct sqlite3_str { + sqlite3 *db; /* Optional database for lookaside. Can be NULL */ +- char *zBase; /* A base allocation. Not from malloc. */ + char *zText; /* The string collected so far */ +- u32 nChar; /* Length of the string so far */ + u32 nAlloc; /* Amount of space allocated in zText */ + u32 mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */ +- u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */ ++ u32 nChar; /* Length of the string so far */ ++ u8 accError; /* SQLITE_NOMEM or SQLITE_TOOBIG */ + u8 printfFlags; /* SQLITE_PRINTF flags below */ + }; +-#define STRACCUM_NOMEM 1 +-#define STRACCUM_TOOBIG 2 + #define SQLITE_PRINTF_INTERNAL 0x01 /* Internal-use-only converters allowed */ + #define SQLITE_PRINTF_SQLFUNC 0x02 /* SQL function arguments to VXPrintf */ + #define SQLITE_PRINTF_MALLOCED 0x04 /* True if xText is allocated space */ +@@ -16982,9 +18213,15 @@ + char **pzErrMsg; /* Error message stored here */ + int iDb; /* 0 for main database. 1 for TEMP, 2.. for ATTACHed */ + int rc; /* Result code stored here */ ++ u32 mInitFlags; /* Flags controlling error messages */ + } InitData; + + /* ++** Allowed values for mInitFlags ++*/ ++#define INITFLAG_AlterTable 0x0001 /* This is a reparse after ALTER TABLE */ ++ ++/* + ** Structure containing global configuration data for the SQLite library. + ** + ** This structure also contains some state information. +@@ -16995,6 +18232,7 @@ + int bFullMutex; /* True to enable full mutexing */ + int bOpenUri; /* True to interpret filenames as URIs */ + int bUseCis; /* Use covering indices for full-scans */ ++ int bSmallMalloc; /* Avoid large memory allocations if true */ + int mxStrlen; /* Maximum string length */ + int neverCorrupt; /* Database is always well-formed */ + int szLookaside; /* Default lookaside buffer size */ +@@ -17008,9 +18246,6 @@ + int mnReq, mxReq; /* Min and max heap requests sizes */ + sqlite3_int64 szMmap; /* mmap() space per open file */ + sqlite3_int64 mxMmap; /* Maximum value for szMmap */ +- void *pScratch; /* Scratch memory */ +- int szScratch; /* Size of each scratch buffer */ +- int nScratch; /* Number of scratch buffers */ + void *pPage; /* Page cache memory */ + int szPage; /* Size of each page in pPage[] */ + int nPage; /* Number of pages in pPage[] */ +@@ -17036,7 +18271,7 @@ + /* The following callback (if not NULL) is invoked on every VDBE branch + ** operation. Set the callback using SQLITE_TESTCTRL_VDBE_COVERAGE. + */ +- void (*xVdbeBranch)(void*,int iSrcLine,u8 eThis,u8 eMx); /* Callback */ ++ void (*xVdbeBranch)(void*,unsigned iSrcLine,u8 eThis,u8 eMx); /* Callback */ + void *pVdbeBranchArg; /* 1st argument */ + #endif + #ifndef SQLITE_UNTESTABLE +@@ -17043,7 +18278,9 @@ + int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */ + #endif + int bLocaltimeFault; /* True to fail localtime() calls */ ++ int bInternalFunctions; /* Internal SQL functions are visible */ + int iOnceResetThreshold; /* When to reset OP_Once counters */ ++ u32 szSorterRef; /* Min size in bytes to use sorter-refs */ + }; + + /* +@@ -17083,9 +18320,12 @@ + struct CCurHint *pCCurHint; /* Used by codeCursorHint() */ + int *aiCol; /* array of column indexes */ + struct IdxCover *pIdxCover; /* Check for index coverage */ +- struct IdxExprTrans *pIdxTrans; /* Convert indexed expr to column */ ++ struct IdxExprTrans *pIdxTrans; /* Convert idxed expr to column */ + ExprList *pGroupBy; /* GROUP BY clause */ +- struct HavingToWhereCtx *pHavingCtx; /* HAVING to WHERE clause ctx */ ++ Select *pSelect; /* HAVING to WHERE clause ctx */ ++ struct WindowRewrite *pRewrite; /* Window rewrite context */ ++ struct WhereConst *pConst; /* WHERE clause constants */ ++ struct RenameCtx *pRename; /* RENAME COLUMN context */ + } u; + }; + +@@ -17097,6 +18337,7 @@ + SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*); + SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker*, Expr*); + SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker*, Select*); ++SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker*, Select*); + #ifdef SQLITE_DEBUG + SQLITE_PRIVATE void sqlite3SelectWalkAssert2(Walker*, Select*); + #endif +@@ -17136,6 +18377,68 @@ + #endif /* SQLITE_DEBUG */ + + /* ++** This object is used in varioius ways, all related to window functions ++** ++** (1) A single instance of this structure is attached to the ++** the Expr.pWin field for each window function in an expression tree. ++** This object holds the information contained in the OVER clause, ++** plus additional fields used during code generation. ++** ++** (2) All window functions in a single SELECT form a linked-list ++** attached to Select.pWin. The Window.pFunc and Window.pExpr ++** fields point back to the expression that is the window function. ++** ++** (3) The terms of the WINDOW clause of a SELECT are instances of this ++** object on a linked list attached to Select.pWinDefn. ++** ++** The uses (1) and (2) are really the same Window object that just happens ++** to be accessible in two different ways. Use (3) is are separate objects. ++*/ ++struct Window { ++ char *zName; /* Name of window (may be NULL) */ ++ ExprList *pPartition; /* PARTITION BY clause */ ++ ExprList *pOrderBy; /* ORDER BY clause */ ++ u8 eType; /* TK_RANGE or TK_ROWS */ ++ u8 eStart; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */ ++ u8 eEnd; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */ ++ Expr *pStart; /* Expression for "<expr> PRECEDING" */ ++ Expr *pEnd; /* Expression for "<expr> FOLLOWING" */ ++ Window *pNextWin; /* Next window function belonging to this SELECT */ ++ Expr *pFilter; /* The FILTER expression */ ++ FuncDef *pFunc; /* The function */ ++ int iEphCsr; /* Partition buffer or Peer buffer */ ++ int regAccum; ++ int regResult; ++ int csrApp; /* Function cursor (used by min/max) */ ++ int regApp; /* Function register (also used by min/max) */ ++ int regPart; /* First in a set of registers holding PARTITION BY ++ ** and ORDER BY values for the window */ ++ Expr *pOwner; /* Expression object this window is attached to */ ++ int nBufferCol; /* Number of columns in buffer table */ ++ int iArgCol; /* Offset of first argument for this function */ ++}; ++ ++#ifndef SQLITE_OMIT_WINDOWFUNC ++SQLITE_PRIVATE void sqlite3WindowDelete(sqlite3*, Window*); ++SQLITE_PRIVATE void sqlite3WindowListDelete(sqlite3 *db, Window *p); ++SQLITE_PRIVATE Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*); ++SQLITE_PRIVATE void sqlite3WindowAttach(Parse*, Expr*, Window*); ++SQLITE_PRIVATE int sqlite3WindowCompare(Parse*, Window*, Window*); ++SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse*, Window*); ++SQLITE_PRIVATE void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int); ++SQLITE_PRIVATE int sqlite3WindowRewrite(Parse*, Select*); ++SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse*, struct SrcList_item*); ++SQLITE_PRIVATE void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*); ++SQLITE_PRIVATE Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p); ++SQLITE_PRIVATE Window *sqlite3WindowListDup(sqlite3 *db, Window *p); ++SQLITE_PRIVATE void sqlite3WindowFunctions(void); ++#else ++# define sqlite3WindowDelete(a,b) ++# define sqlite3WindowFunctions() ++# define sqlite3WindowAttach(a,b,c) ++#endif ++ ++/* + ** Assuming zIn points to the first byte of a UTF-8 character, + ** advance zIn to point to the first byte of the next UTF-8 character. + */ +@@ -17152,6 +18455,7 @@ + ** using sqlite3_log(). The routines also provide a convenient place + ** to set a debugger breakpoint. + */ ++SQLITE_PRIVATE int sqlite3ReportError(int iErr, int lineno, const char *zType); + SQLITE_PRIVATE int sqlite3CorruptError(int); + SQLITE_PRIVATE int sqlite3MisuseError(int); + SQLITE_PRIVATE int sqlite3CantopenError(int); +@@ -17221,9 +18525,7 @@ + # define sqlite3Tolower(x) tolower((unsigned char)(x)) + # define sqlite3Isquote(x) ((x)=='"'||(x)=='\''||(x)=='['||(x)=='`') + #endif +-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS + SQLITE_PRIVATE int sqlite3IsIdChar(u8); +-#endif + + /* + ** Internal function prototypes +@@ -17230,6 +18532,7 @@ + */ + SQLITE_PRIVATE int sqlite3StrICmp(const char*,const char*); + SQLITE_PRIVATE int sqlite3Strlen30(const char*); ++#define sqlite3Strlen30NN(C) (strlen(C)&0x3fffffff) + SQLITE_PRIVATE char *sqlite3ColumnType(Column*,char*); + #define sqlite3StrNICmp sqlite3_strnicmp + +@@ -17242,6 +18545,7 @@ + SQLITE_PRIVATE void *sqlite3DbMallocRawNN(sqlite3*, u64); + SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3*,const char*); + SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3*,const char*, u64); ++SQLITE_PRIVATE char *sqlite3DbSpanDup(sqlite3*,const char*,const char*); + SQLITE_PRIVATE void *sqlite3Realloc(void*, u64); + SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64); + SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *, void *, u64); +@@ -17249,8 +18553,6 @@ + SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3*, void*); + SQLITE_PRIVATE int sqlite3MallocSize(void*); + SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3*, void*); +-SQLITE_PRIVATE void *sqlite3ScratchMalloc(int); +-SQLITE_PRIVATE void sqlite3ScratchFree(void*); + SQLITE_PRIVATE void *sqlite3PageMalloc(int); + SQLITE_PRIVATE void sqlite3PageFree(void*); + SQLITE_PRIVATE void sqlite3MemSetDefault(void); +@@ -17306,11 +18608,18 @@ + SQLITE_PRIVATE void sqlite3StatusUp(int, int); + SQLITE_PRIVATE void sqlite3StatusDown(int, int); + SQLITE_PRIVATE void sqlite3StatusHighwater(int, int); ++SQLITE_PRIVATE int sqlite3LookasideUsed(sqlite3*,int*); + + /* Access to mutexes used by sqlite3_status() */ + SQLITE_PRIVATE sqlite3_mutex *sqlite3Pcache1Mutex(void); + SQLITE_PRIVATE sqlite3_mutex *sqlite3MallocMutex(void); + ++#if defined(SQLITE_ENABLE_MULTITHREADED_CHECKS) && !defined(SQLITE_MUTEX_OMIT) ++SQLITE_PRIVATE void sqlite3MutexWarnOnContention(sqlite3_mutex*); ++#else ++# define sqlite3MutexWarnOnContention(x) ++#endif ++ + #ifndef SQLITE_OMIT_FLOATING_POINT + SQLITE_PRIVATE int sqlite3IsNaN(double); + #else +@@ -17327,8 +18636,6 @@ + sqlite3_value **apArg; /* The argument values */ + }; + +-SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, const char*, va_list); +-SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, const char*, ...); + SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...); + SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list); + #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) +@@ -17342,9 +18649,14 @@ + SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView*, const Expr*, u8); + SQLITE_PRIVATE void sqlite3TreeViewBareExprList(TreeView*, const ExprList*, const char*); + SQLITE_PRIVATE void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*); ++SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView*, const SrcList*); + SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView*, const Select*, u8); + SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView*, const With*, u8); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView*, const Window*, u8); ++SQLITE_PRIVATE void sqlite3TreeViewWinFunc(TreeView*, const Window*, u8); + #endif ++#endif + + + SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*); +@@ -17368,7 +18680,7 @@ + SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*); + SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*); + SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*); +-SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*); ++SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int); + SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32); + SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*); + SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); +@@ -17375,11 +18687,12 @@ + SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*); + SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int); + SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); +-SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*); ++SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*); + SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*); + SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*); + SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**); + SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**); ++SQLITE_PRIVATE int sqlite3InitOne(sqlite3*, int, char**, u32); + SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); + #ifndef SQLITE_OMIT_VIRTUALTABLE + SQLITE_PRIVATE Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName); +@@ -17405,7 +18718,7 @@ + SQLITE_PRIVATE void sqlite3AddNotNull(Parse*, int); + SQLITE_PRIVATE void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int); + SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*); +-SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,ExprSpan*); ++SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*); + SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*); + SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*); + SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*, +@@ -17429,8 +18742,9 @@ + SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int,int*); + #endif + +-SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int); +-SQLITE_PRIVATE void sqlite3RowSetClear(RowSet*); ++SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3*); ++SQLITE_PRIVATE void sqlite3RowSetDelete(void*); ++SQLITE_PRIVATE void sqlite3RowSetClear(void*); + SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet*, i64); + SQLITE_PRIVATE int sqlite3RowSetTest(RowSet*, int iBatch, i64); + SQLITE_PRIVATE int sqlite3RowSetNext(RowSet*, i64*); +@@ -17449,6 +18763,7 @@ + SQLITE_PRIVATE void sqlite3DropTable(Parse*, SrcList*, int, int); + SQLITE_PRIVATE void sqlite3CodeDropTable(Parse*, Table*, int, int); + SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3*, Table*); ++SQLITE_PRIVATE void sqlite3FreeIndex(sqlite3*, Index*); + #ifndef SQLITE_OMIT_AUTOINCREMENT + SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse); + SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse); +@@ -17456,9 +18771,9 @@ + # define sqlite3AutoincrementBegin(X) + # define sqlite3AutoincrementEnd(X) + #endif +-SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int); ++SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int, Upsert*); + SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*); +-SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*); ++SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse*, IdList*, Token*); + SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*); + SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(sqlite3*, SrcList*, int, int); + SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*); +@@ -17477,22 +18792,23 @@ + SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int); + SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*); + SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, +- Expr*,ExprList*,u32,Expr*,Expr*); ++ Expr*,ExprList*,u32,Expr*); + SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*); + SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*); + SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int); + SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); + #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) +-SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,Expr*,char*); ++SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*); + #endif +-SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); +-SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); ++SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*); ++SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*, ++ Upsert*); + SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int); + SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*); + SQLITE_PRIVATE LogEst sqlite3WhereOutputRowCount(WhereInfo*); + SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo*); + SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo*); +-SQLITE_PRIVATE int sqlite3WhereOrderedInnerLoop(WhereInfo*); ++SQLITE_PRIVATE int sqlite3WhereOrderByLimitOptLabel(WhereInfo*); + SQLITE_PRIVATE int sqlite3WhereIsSorted(WhereInfo*); + SQLITE_PRIVATE int sqlite3WhereContinueLabel(WhereInfo*); + SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo*); +@@ -17502,15 +18818,8 @@ + #define ONEPASS_MULTI 2 /* ONEPASS is valid for multiple rows */ + SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int); + SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8); +-SQLITE_PRIVATE void sqlite3ExprCodeGetColumnToReg(Parse*, Table*, int, int, int); + SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int); + SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int); +-SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse*, int, int, int); +-SQLITE_PRIVATE void sqlite3ExprCachePush(Parse*); +-SQLITE_PRIVATE void sqlite3ExprCachePop(Parse*); +-SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse*, int, int); +-SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse*); +-SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse*, int, int); + SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int); + SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, Expr*, int); + SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int); +@@ -17541,6 +18850,7 @@ + SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr*, Expr*, int); + SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList*, ExprList*, int); + SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Parse*,Expr*, Expr*, int); ++SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr*,int); + SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); + SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); + SQLITE_PRIVATE int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx); +@@ -17558,6 +18868,8 @@ + SQLITE_PRIVATE void sqlite3Savepoint(Parse*, int, Token*); + SQLITE_PRIVATE void sqlite3CloseSavepoints(sqlite3 *); + SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3*); ++SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr*); ++SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr*); + SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr*); + SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*); + SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8); +@@ -17570,13 +18882,17 @@ + SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*); + SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); + SQLITE_PRIVATE int sqlite3IsRowid(const char*); ++#ifdef SQLITE_ENABLE_NORMALIZE ++SQLITE_PRIVATE int sqlite3IsRowidN(const char*, int); ++#endif + SQLITE_PRIVATE void sqlite3GenerateRowDelete( + Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int); + SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int); + SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int); + SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse*,int); ++SQLITE_PRIVATE int sqlite3ExprReferencesUpdatedColumn(Expr*,int*,int); + SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int, +- u8,u8,int,int*,int*); ++ u8,u8,int,int*,int*,Upsert*); + #ifdef SQLITE_ENABLE_NULL_TRIM + SQLITE_PRIVATE void sqlite3SetMakeRecordP5(Vdbe*,Table*); + #else +@@ -17595,10 +18911,8 @@ + SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int); + SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*); + SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*,int); +-#if SELECTTRACE_ENABLED +-SQLITE_PRIVATE void sqlite3SelectSetName(Select*,const char*); +-#else +-# define sqlite3SelectSetName(A,B) ++#ifdef SQLITE_ENABLE_NORMALIZE ++SQLITE_PRIVATE FuncDef *sqlite3FunctionSearchN(int,const char*,int); + #endif + SQLITE_PRIVATE void sqlite3InsertBuiltinFuncs(FuncDef*,int); + SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8); +@@ -17610,7 +18924,7 @@ + SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int); + + #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) +-SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Table*, Expr*, int); ++SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int); + #endif + + #ifndef SQLITE_OMIT_TRIGGER +@@ -17626,11 +18940,15 @@ + SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, int, int, int); + void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*); + SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*); +-SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*); +-SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*, +- Select*,u8); +-SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8); +-SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*); ++SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*, ++ const char*,const char*); ++SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(Parse*,Token*, IdList*, ++ Select*,u8,Upsert*, ++ const char*,const char*); ++SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(Parse*,Token*,ExprList*, Expr*, u8, ++ const char*,const char*); ++SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(Parse*,Token*, Expr*, ++ const char*,const char*); + SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*); + SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); + SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int); +@@ -17737,15 +19055,23 @@ + SQLITE_PRIVATE const char *sqlite3ErrName(int); + #endif + ++#ifdef SQLITE_ENABLE_DESERIALIZE ++SQLITE_PRIVATE int sqlite3MemdbInit(void); ++#endif ++ + SQLITE_PRIVATE const char *sqlite3ErrStr(int); + SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse); + SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); ++SQLITE_PRIVATE int sqlite3IsBinary(const CollSeq*); + SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); + SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); ++SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr); ++SQLITE_PRIVATE int sqlite3ExprCollSeqMatch(Parse*,Expr*,Expr*); + SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int); + SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*); + SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*); + SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *); ++SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3*); + SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *); + SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int); + SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64); +@@ -17783,13 +19109,20 @@ + SQLITE_PRIVATE int sqlite3PendingByte; + #endif + #endif ++#ifdef VDBE_PROFILE ++SQLITE_PRIVATE sqlite3_uint64 sqlite3NProfileCnt; ++#endif + SQLITE_PRIVATE void sqlite3RootPageMoved(sqlite3*, int, int, int); + SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*); + SQLITE_PRIVATE void sqlite3AlterFunctions(void); + SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); ++SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*); + SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *); ++#ifdef SQLITE_ENABLE_NORMALIZE ++SQLITE_PRIVATE int sqlite3GetTokenNormalized(const unsigned char *, int *, int *); ++#endif + SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); +-SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*); ++SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, int); + SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr *, int, int); + SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); + SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p); +@@ -17802,10 +19135,14 @@ + SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int); + SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *); + SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *); ++SQLITE_PRIVATE void *sqlite3RenameTokenMap(Parse*, void*, Token*); ++SQLITE_PRIVATE void sqlite3RenameTokenRemap(Parse*, void *pTo, void *pFrom); ++SQLITE_PRIVATE void sqlite3RenameExprUnmap(Parse*, Expr*); ++SQLITE_PRIVATE void sqlite3RenameExprlistUnmap(Parse*, ExprList*); + SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*); +-SQLITE_PRIVATE char sqlite3AffinityType(const char*, u8*); ++SQLITE_PRIVATE char sqlite3AffinityType(const char*, Column*); + SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*); +-SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*); ++SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*, sqlite3_file*); + SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*); + SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *); + SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB); +@@ -17820,14 +19157,20 @@ + SQLITE_PRIVATE void sqlite3KeyInfoUnref(KeyInfo*); + SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoRef(KeyInfo*); + SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*); ++SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoFromExprList(Parse*, ExprList*, int, int); ++ + #ifdef SQLITE_DEBUG + SQLITE_PRIVATE int sqlite3KeyInfoIsWriteable(KeyInfo*); + #endif + SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, + void (*)(sqlite3_context*,int,sqlite3_value **), +- void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*), ++ void (*)(sqlite3_context*,int,sqlite3_value **), ++ void (*)(sqlite3_context*), ++ void (*)(sqlite3_context*), ++ void (*)(sqlite3_context*,int,sqlite3_value **), + FuncDestructor *pDestructor + ); ++SQLITE_PRIVATE void sqlite3NoopDestructor(void*); + SQLITE_PRIVATE void sqlite3OomFault(sqlite3*); + SQLITE_PRIVATE void sqlite3OomClear(sqlite3*); + SQLITE_PRIVATE int sqlite3ApiExit(sqlite3 *db, int); +@@ -17834,11 +19177,7 @@ + SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *); + + SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int); +-SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum*,const char*,int); +-SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum*,const char*); +-SQLITE_PRIVATE void sqlite3AppendChar(StrAccum*,int,char); + SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum*); +-SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum*); + SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest*,int,int); + SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int); + +@@ -17865,10 +19204,11 @@ + ** The interface to the LEMON-generated parser + */ + #ifndef SQLITE_AMALGAMATION +-SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(u64)); ++SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(u64), Parse*); + SQLITE_PRIVATE void sqlite3ParserFree(void*, void(*)(void*)); + #endif +-SQLITE_PRIVATE void sqlite3Parser(void*, int, Token, Parse*); ++SQLITE_PRIVATE void sqlite3Parser(void*, int, Token); ++SQLITE_PRIVATE int sqlite3ParserFallback(int); + #ifdef YYTRACKMAXSTACKDEPTH + SQLITE_PRIVATE int sqlite3ParserStackPeak(void*); + #endif +@@ -17934,11 +19274,13 @@ + SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *); + SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, VTable *); + SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); +-SQLITE_PRIVATE void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**); + SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*); + SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); + SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); + SQLITE_PRIVATE void sqlite3ParserReset(Parse*); ++#ifdef SQLITE_ENABLE_NORMALIZE ++SQLITE_PRIVATE void sqlite3Normalize(Vdbe*, const char*, int, u8); ++#endif + SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*); + SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*); + SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *); +@@ -17956,7 +19298,19 @@ + #define sqlite3WithPush(x,y,z) + #define sqlite3WithDelete(x,y) + #endif ++#ifndef SQLITE_OMIT_UPSERT ++SQLITE_PRIVATE Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*); ++SQLITE_PRIVATE void sqlite3UpsertDelete(sqlite3*,Upsert*); ++SQLITE_PRIVATE Upsert *sqlite3UpsertDup(sqlite3*,Upsert*); ++SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*); ++SQLITE_PRIVATE void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int); ++#else ++#define sqlite3UpsertNew(v,w,x,y,z) ((Upsert*)0) ++#define sqlite3UpsertDelete(x,y) ++#define sqlite3UpsertDup(x,y) ((Upsert*)0) ++#endif + ++ + /* Declarations for functions in fkey.c. All of these are replaced by + ** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign + ** key functionality is available. If OMIT_TRIGGER is defined but +@@ -18025,7 +19379,8 @@ + + SQLITE_PRIVATE int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int); + SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *); +-#ifdef SQLITE_ENABLE_ATOMIC_WRITE ++#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \ ++ || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) + SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *); + #endif + +@@ -18057,6 +19412,9 @@ + #ifdef SQLITE_DEBUG + SQLITE_PRIVATE void sqlite3ParserTrace(FILE*, char *); + #endif ++#if defined(YYCOVERAGE) ++SQLITE_PRIVATE int sqlite3ParserCoverage(FILE*); ++#endif + + /* + ** If the SQLITE_ENABLE IOTRACE exists then the global variable +@@ -18111,8 +19469,7 @@ + #endif + #define MEMTYPE_HEAP 0x01 /* General heap allocations */ + #define MEMTYPE_LOOKASIDE 0x02 /* Heap that might have been lookaside */ +-#define MEMTYPE_SCRATCH 0x04 /* Scratch allocations */ +-#define MEMTYPE_PCACHE 0x08 /* Page cache allocations */ ++#define MEMTYPE_PCACHE 0x04 /* Page cache allocations */ + + /* + ** Threading interface +@@ -18122,6 +19479,9 @@ + SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread*, void**); + #endif + ++#if defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST) ++SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3*); ++#endif + #if defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST) + SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3*); + #endif +@@ -18341,6 +19701,7 @@ + SQLITE_THREADSAFE==1, /* bFullMutex */ + SQLITE_USE_URI, /* bOpenUri */ + SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */ ++ 0, /* bSmallMalloc */ + 0x7ffffffe, /* mxStrlen */ + 0, /* neverCorrupt */ + SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */ +@@ -18353,9 +19714,6 @@ + 0, 0, /* mnHeap, mxHeap */ + SQLITE_DEFAULT_MMAP_SIZE, /* szMmap */ + SQLITE_MAX_MMAP_SIZE, /* mxMmap */ +- (void*)0, /* pScratch */ +- 0, /* szScratch */ +- 0, /* nScratch */ + (void*)0, /* pPage */ + 0, /* szPage */ + SQLITE_DEFAULT_PCACHE_INITSZ, /* nPage */ +@@ -18384,7 +19742,9 @@ + 0, /* xTestCallback */ + #endif + 0, /* bLocaltimeFault */ +- 0x7ffffffe /* iOnceResetThreshold */ ++ 0, /* bInternalFunctions */ ++ 0x7ffffffe, /* iOnceResetThreshold */ ++ SQLITE_DEFAULT_SORTERREF_SIZE /* szSorterRef */ + }; + + /* +@@ -18402,6 +19762,13 @@ + { "1", 1 } + }; + ++#ifdef VDBE_PROFILE ++/* ++** The following performance counter can be used in place of ++** sqlite3Hwtime() for profiling. This is a no-op on standard builds. ++*/ ++SQLITE_PRIVATE sqlite3_uint64 sqlite3NProfileCnt = 0; ++#endif + + /* + ** The value of the "pending" byte must be 0x40000000 (1 byte past the +@@ -18546,6 +19913,7 @@ + Bool isEphemeral:1; /* True for an ephemeral table */ + Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */ + Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */ ++ Bool seekHit:1; /* See the OP_SeekHit and OP_IfNoHope opcodes */ + Btree *pBtx; /* Separate file holding temporary table */ + i64 seqCount; /* Sequence counter */ + int *aAltMap; /* Mapping from table to index column numbers */ +@@ -18557,8 +19925,9 @@ + u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */ + int seekResult; /* Result of previous sqlite3BtreeMoveto() or 0 + ** if there have been no prior seeks on the cursor. */ +- /* NB: seekResult does not distinguish between "no seeks have ever occurred +- ** on this cursor" and "the most recent seek was an exact match". */ ++ /* seekResult does not distinguish between "no seeks have ever occurred ++ ** on this cursor" and "the most recent seek was an exact match". ++ ** For CURTYPE_PSEUDO, seekResult is the register holding the record */ + + /* When a new VdbeCursor is allocated, only the fields above are zeroed. + ** The fields that follow are uninitialized, and must be individually +@@ -18565,10 +19934,9 @@ + ** initialized prior to first use. */ + VdbeCursor *pAltCursor; /* Associated index cursor from which to read */ + union { +- BtCursor *pCursor; /* CURTYPE_BTREE. Btree cursor */ +- sqlite3_vtab_cursor *pVCur; /* CURTYPE_VTAB. Vtab cursor */ +- int pseudoTableReg; /* CURTYPE_PSEUDO. Reg holding content. */ +- VdbeSorter *pSorter; /* CURTYPE_SORTER. Sorter object */ ++ BtCursor *pCursor; /* CURTYPE_BTREE or _PSEUDO. Btree cursor */ ++ sqlite3_vtab_cursor *pVCur; /* CURTYPE_VTAB. Vtab cursor */ ++ VdbeSorter *pSorter; /* CURTYPE_SORTER. Sorter object */ + } uc; + KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */ + u32 iHdrOffset; /* Offset to next unparsed byte of the header */ +@@ -18629,6 +19997,9 @@ + void *token; /* Copy of SubProgram.token */ + i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ + AuxData *pAuxData; /* Linked list of auxdata allocations */ ++#if SQLITE_DEBUG ++ u32 iFrameMagic; /* magic number for sanity checking */ ++#endif + int nCursor; /* Number of entries in apCsr */ + int pc; /* Program Counter in parent (calling) frame */ + int nOp; /* Size of aOp array */ +@@ -18639,6 +20010,13 @@ + int nDbChange; /* Value of db->nChange */ + }; + ++/* Magic number for sanity checking on VdbeFrame objects */ ++#define SQLITE_FRAME_MAGIC 0x879fb71e ++ ++/* ++** Return a pointer to the array of registers allocated for use ++** by a VdbeFrame. ++*/ + #define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))]) + + /* +@@ -18653,8 +20031,6 @@ + int nZero; /* Extra zero bytes when MEM_Zero and MEM_Blob set */ + const char *zPType; /* Pointer type when MEM_Term|MEM_Subtype|MEM_Null */ + FuncDef *pDef; /* Used only when flags==MEM_Agg */ +- RowSet *pRowSet; /* Used only when flags==MEM_RowSet */ +- VdbeFrame *pFrame; /* Used when flags==MEM_Frame */ + } u; + u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ + u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */ +@@ -18669,7 +20045,7 @@ + void (*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */ + #ifdef SQLITE_DEBUG + Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */ +- void *pFiller; /* So that sizeof(Mem) is a multiple of 8 */ ++ u16 mScopyFlags; /* flags value immediately after the shallow copy */ + #endif + }; + +@@ -18698,8 +20074,8 @@ + #define MEM_Real 0x0008 /* Value is a real number */ + #define MEM_Blob 0x0010 /* Value is a BLOB */ + #define MEM_AffMask 0x001f /* Mask of affinity bits */ +-#define MEM_RowSet 0x0020 /* Value is a RowSet object */ +-#define MEM_Frame 0x0040 /* Value is a VdbeFrame object */ ++/* Available 0x0020 */ ++/* Available 0x0040 */ + #define MEM_Undefined 0x0080 /* Value is undefined */ + #define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */ + #define MEM_TypeMask 0xc1ff /* Mask of type bits */ +@@ -18726,7 +20102,7 @@ + ** that needs to be deallocated to avoid a leak. + */ + #define VdbeMemDynamic(X) \ +- (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0) ++ (((X)->flags&(MEM_Agg|MEM_Dyn))!=0) + + /* + ** Clear any existing type flags from a Mem and replace them with f +@@ -18778,7 +20154,6 @@ + int iOp; /* Instruction number of OP_Function */ + int isError; /* Error code returned by the function. */ + u8 skipFlag; /* Skip accumulator loading if true */ +- u8 fErrorOrAux; /* isError!=0 or pVdbe->pAuxData modified */ + u8 argc; /* Number of arguments */ + sqlite3_value *argv[1]; /* Argument set */ + }; +@@ -18841,14 +20216,15 @@ + int nOp; /* Number of instructions in the program */ + #ifdef SQLITE_DEBUG + int rcApp; /* errcode set by sqlite3_result_error_code() */ ++ u32 nWrite; /* Number of write operations that have occurred */ + #endif + u16 nResColumn; /* Number of columns in one row of the result set */ + u8 errorAction; /* Recovery action to do in case of an error */ + u8 minWriteFileFormat; /* Minimum file format for writable database files */ + u8 prepFlags; /* SQLITE_PREPARE_* flags */ +- bft expired:1; /* True if the VM needs to be recompiled */ ++ bft expired:2; /* 1: recompile VM immediately 2: when convenient */ ++ bft explain:2; /* True if EXPLAIN present on SQL command */ + bft doingRerun:1; /* True if rerunning after an auto-reprepare */ +- bft explain:2; /* True if EXPLAIN present on SQL command */ + bft changeCntOn:1; /* True to update the change-counter */ + bft runOnlyOnce:1; /* Automatically expire on reset */ + bft usesStmtJournal:1; /* True if uses a statement journal */ +@@ -18858,6 +20234,9 @@ + yDbMask lockMask; /* Subset of btreeMask that requires a lock */ + u32 aCounter[7]; /* Counters used by sqlite3_stmt_status() */ + char *zSql; /* Text of the SQL statement that generated this */ ++#ifdef SQLITE_ENABLE_NORMALIZE ++ char *zNormSql; /* Normalization of the associated SQL statement */ ++#endif + void *pFree; /* Free this when deleting the vdbe */ + VdbeFrame *pFrame; /* Parent frame */ + VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */ +@@ -18909,9 +20288,6 @@ + void sqliteVdbePopStack(Vdbe*,int); + SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor**, int*); + SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor*); +-#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) +-SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, Op*); +-#endif + SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32); + SQLITE_PRIVATE u8 sqlite3VdbeOneByteSerialTypeLen(u8); + SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int, u32*); +@@ -18923,7 +20299,9 @@ + SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*); + SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*); + SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*); ++#ifndef SQLITE_OMIT_EXPLAIN + SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*); ++#endif + SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*); + SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *, int); + SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem*); +@@ -18942,12 +20320,16 @@ + SQLITE_PRIVATE void sqlite3VdbeMemInit(Mem*,sqlite3*,u16); + SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*); + SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int); +-SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem*); ++#ifdef SQLITE_DEBUG ++SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem*); ++#endif ++SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem*); + SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*); + SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8); + SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*); + SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*); + SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*); ++SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem*, int ifNull); + SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*); + SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*); + SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*); +@@ -18955,11 +20337,20 @@ + SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*); + SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p); + SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*); ++#endif ++#ifndef SQLITE_OMIT_EXPLAIN + SQLITE_PRIVATE const char *sqlite3OpcodeName(int); ++#endif + SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); + SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int n); + SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int); +-SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*); ++#ifdef SQLITE_DEBUG ++SQLITE_PRIVATE int sqlite3VdbeFrameIsValid(VdbeFrame*); ++#endif ++SQLITE_PRIVATE void sqlite3VdbeFrameMemDel(void*); /* Destructor on Mem */ ++SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*); /* Actually deletes the Frame */ + SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *); + #ifdef SQLITE_ENABLE_PREUPDATE_HOOK + SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int); +@@ -18975,6 +20366,14 @@ + SQLITE_PRIVATE int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *); + SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *); + ++#ifdef SQLITE_DEBUG ++SQLITE_PRIVATE void sqlite3VdbeIncrWriteCounter(Vdbe*, VdbeCursor*); ++SQLITE_PRIVATE void sqlite3VdbeAssertAbortable(Vdbe*); ++#else ++# define sqlite3VdbeIncrWriteCounter(V,C) ++# define sqlite3VdbeAssertAbortable(V) ++#endif ++ + #if !defined(SQLITE_OMIT_SHARED_CACHE) + SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe*); + #else +@@ -19126,7 +20525,6 @@ + : sqlite3MallocMutex()) ); + assert( op==SQLITE_STATUS_MALLOC_SIZE + || op==SQLITE_STATUS_PAGECACHE_SIZE +- || op==SQLITE_STATUS_SCRATCH_SIZE + || op==SQLITE_STATUS_PARSER_STACK ); + if( newValue>wsdStat.mxValue[op] ){ + wsdStat.mxValue[op] = newValue; +@@ -19176,6 +20574,28 @@ + } + + /* ++** Return the number of LookasideSlot elements on the linked list ++*/ ++static u32 countLookasideSlots(LookasideSlot *p){ ++ u32 cnt = 0; ++ while( p ){ ++ p = p->pNext; ++ cnt++; ++ } ++ return cnt; ++} ++ ++/* ++** Count the number of slots of lookaside memory that are outstanding ++*/ ++SQLITE_PRIVATE int sqlite3LookasideUsed(sqlite3 *db, int *pHighwater){ ++ u32 nInit = countLookasideSlots(db->lookaside.pInit); ++ u32 nFree = countLookasideSlots(db->lookaside.pFree); ++ if( pHighwater ) *pHighwater = db->lookaside.nSlot - nInit; ++ return db->lookaside.nSlot - (nInit+nFree); ++} ++ ++/* + ** Query status information for a single database connection + */ + SQLITE_API int sqlite3_db_status( +@@ -19194,10 +20614,15 @@ + sqlite3_mutex_enter(db->mutex); + switch( op ){ + case SQLITE_DBSTATUS_LOOKASIDE_USED: { +- *pCurrent = db->lookaside.nOut; +- *pHighwater = db->lookaside.mxOut; ++ *pCurrent = sqlite3LookasideUsed(db, pHighwater); + if( resetFlag ){ +- db->lookaside.mxOut = db->lookaside.nOut; ++ LookasideSlot *p = db->lookaside.pFree; ++ if( p ){ ++ while( p->pNext ) p = p->pNext; ++ p->pNext = db->lookaside.pInit; ++ db->lookaside.pInit = db->lookaside.pFree; ++ db->lookaside.pFree = 0; ++ } + } + break; + } +@@ -19315,6 +20740,9 @@ + ** pagers the database handle is connected to. *pHighwater is always set + ** to zero. + */ ++ case SQLITE_DBSTATUS_CACHE_SPILL: ++ op = SQLITE_DBSTATUS_CACHE_WRITE+1; ++ /* Fall through into the next case */ + case SQLITE_DBSTATUS_CACHE_HIT: + case SQLITE_DBSTATUS_CACHE_MISS: + case SQLITE_DBSTATUS_CACHE_WRITE:{ +@@ -19397,7 +20825,7 @@ + ** + ** Jean Meeus + ** Astronomical Algorithms, 2nd Edition, 1998 +-** ISBM 0-943396-61-1 ++** ISBN 0-943396-61-1 + ** Willmann-Bell, Inc + ** Richmond, Virginia (USA) + */ +@@ -20708,7 +22136,7 @@ + } + SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file *id, int flags){ + DO_OS_MALLOC_TEST(id); +- return id->pMethods->xSync(id, flags); ++ return flags ? id->pMethods->xSync(id, flags) : SQLITE_OK; + } + SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){ + DO_OS_MALLOC_TEST(id); +@@ -20735,8 +22163,11 @@ + ** routine has no return value since the return value would be meaningless. + */ + SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ ++ if( id->pMethods==0 ) return SQLITE_NOTFOUND; + #ifdef SQLITE_TEST +- if( op!=SQLITE_FCNTL_COMMIT_PHASETWO ){ ++ if( op!=SQLITE_FCNTL_COMMIT_PHASETWO ++ && op!=SQLITE_FCNTL_LOCK_TIMEOUT ++ ){ + /* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite + ** is using a regular VFS, it is called after the corresponding + ** transaction has been committed. Injecting a fault at this point +@@ -20753,7 +22184,7 @@ + return id->pMethods->xFileControl(id, op, pArg); + } + SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){ +- (void)id->pMethods->xFileControl(id, op, pArg); ++ if( id->pMethods ) (void)id->pMethods->xFileControl(id, op, pArg); + } + + SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id){ +@@ -20763,6 +22194,7 @@ + SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id){ + return id->pMethods->xDeviceCharacteristics(id); + } ++#ifndef SQLITE_OMIT_WAL + SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int offset, int n, int flags){ + return id->pMethods->xShmLock(id, offset, n, flags); + } +@@ -20782,6 +22214,7 @@ + DO_OS_MALLOC_TEST(id); + return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp); + } ++#endif /* SQLITE_OMIT_WAL */ + + #if SQLITE_MAX_MMAP_SIZE>0 + /* The real implementation of xFetch and xUnfetch */ +@@ -21015,9 +22448,12 @@ + ** Unregister a VFS so that it is no longer accessible. + */ + SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ +-#if SQLITE_THREADSAFE +- sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); ++ MUTEX_LOGIC(sqlite3_mutex *mutex;) ++#ifndef SQLITE_OMIT_AUTOINIT ++ int rc = sqlite3_initialize(); ++ if( rc ) return rc; + #endif ++ MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); ) + sqlite3_mutex_enter(mutex); + vfsUnlink(pVfs); + sqlite3_mutex_leave(mutex); +@@ -23300,7 +24736,194 @@ + + + #ifndef SQLITE_MUTEX_OMIT ++ ++#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS + /* ++** This block (enclosed by SQLITE_ENABLE_MULTITHREADED_CHECKS) contains ++** the implementation of a wrapper around the system default mutex ++** implementation (sqlite3DefaultMutex()). ++** ++** Most calls are passed directly through to the underlying default ++** mutex implementation. Except, if a mutex is configured by calling ++** sqlite3MutexWarnOnContention() on it, then if contention is ever ++** encountered within xMutexEnter() a warning is emitted via sqlite3_log(). ++** ++** This type of mutex is used as the database handle mutex when testing ++** apps that usually use SQLITE_CONFIG_MULTITHREAD mode. ++*/ ++ ++/* ++** Type for all mutexes used when SQLITE_ENABLE_MULTITHREADED_CHECKS ++** is defined. Variable CheckMutex.mutex is a pointer to the real mutex ++** allocated by the system mutex implementation. Variable iType is usually set ++** to the type of mutex requested - SQLITE_MUTEX_RECURSIVE, SQLITE_MUTEX_FAST ++** or one of the static mutex identifiers. Or, if this is a recursive mutex ++** that has been configured using sqlite3MutexWarnOnContention(), it is ++** set to SQLITE_MUTEX_WARNONCONTENTION. ++*/ ++typedef struct CheckMutex CheckMutex; ++struct CheckMutex { ++ int iType; ++ sqlite3_mutex *mutex; ++}; ++ ++#define SQLITE_MUTEX_WARNONCONTENTION (-1) ++ ++/* ++** Pointer to real mutex methods object used by the CheckMutex ++** implementation. Set by checkMutexInit(). ++*/ ++static SQLITE_WSD const sqlite3_mutex_methods *pGlobalMutexMethods; ++ ++#ifdef SQLITE_DEBUG ++static int checkMutexHeld(sqlite3_mutex *p){ ++ return pGlobalMutexMethods->xMutexHeld(((CheckMutex*)p)->mutex); ++} ++static int checkMutexNotheld(sqlite3_mutex *p){ ++ return pGlobalMutexMethods->xMutexNotheld(((CheckMutex*)p)->mutex); ++} ++#endif ++ ++/* ++** Initialize and deinitialize the mutex subsystem. ++*/ ++static int checkMutexInit(void){ ++ pGlobalMutexMethods = sqlite3DefaultMutex(); ++ return SQLITE_OK; ++} ++static int checkMutexEnd(void){ ++ pGlobalMutexMethods = 0; ++ return SQLITE_OK; ++} ++ ++/* ++** Allocate a mutex. ++*/ ++static sqlite3_mutex *checkMutexAlloc(int iType){ ++ static CheckMutex staticMutexes[] = { ++ {2, 0}, {3, 0}, {4, 0}, {5, 0}, ++ {6, 0}, {7, 0}, {8, 0}, {9, 0}, ++ {10, 0}, {11, 0}, {12, 0}, {13, 0} ++ }; ++ CheckMutex *p = 0; ++ ++ assert( SQLITE_MUTEX_RECURSIVE==1 && SQLITE_MUTEX_FAST==0 ); ++ if( iType<2 ){ ++ p = sqlite3MallocZero(sizeof(CheckMutex)); ++ if( p==0 ) return 0; ++ p->iType = iType; ++ }else{ ++#ifdef SQLITE_ENABLE_API_ARMOR ++ if( iType-2>=ArraySize(staticMutexes) ){ ++ (void)SQLITE_MISUSE_BKPT; ++ return 0; ++ } ++#endif ++ p = &staticMutexes[iType-2]; ++ } ++ ++ if( p->mutex==0 ){ ++ p->mutex = pGlobalMutexMethods->xMutexAlloc(iType); ++ if( p->mutex==0 ){ ++ if( iType<2 ){ ++ sqlite3_free(p); ++ } ++ p = 0; ++ } ++ } ++ ++ return (sqlite3_mutex*)p; ++} ++ ++/* ++** Free a mutex. ++*/ ++static void checkMutexFree(sqlite3_mutex *p){ ++ assert( SQLITE_MUTEX_RECURSIVE<2 ); ++ assert( SQLITE_MUTEX_FAST<2 ); ++ assert( SQLITE_MUTEX_WARNONCONTENTION<2 ); ++ ++#if SQLITE_ENABLE_API_ARMOR ++ if( ((CheckMutex*)p)->iType<2 ) ++#endif ++ { ++ CheckMutex *pCheck = (CheckMutex*)p; ++ pGlobalMutexMethods->xMutexFree(pCheck->mutex); ++ sqlite3_free(pCheck); ++ } ++#ifdef SQLITE_ENABLE_API_ARMOR ++ else{ ++ (void)SQLITE_MISUSE_BKPT; ++ } ++#endif ++} ++ ++/* ++** Enter the mutex. ++*/ ++static void checkMutexEnter(sqlite3_mutex *p){ ++ CheckMutex *pCheck = (CheckMutex*)p; ++ if( pCheck->iType==SQLITE_MUTEX_WARNONCONTENTION ){ ++ if( SQLITE_OK==pGlobalMutexMethods->xMutexTry(pCheck->mutex) ){ ++ return; ++ } ++ sqlite3_log(SQLITE_MISUSE, ++ "illegal multi-threaded access to database connection" ++ ); ++ } ++ pGlobalMutexMethods->xMutexEnter(pCheck->mutex); ++} ++ ++/* ++** Enter the mutex (do not block). ++*/ ++static int checkMutexTry(sqlite3_mutex *p){ ++ CheckMutex *pCheck = (CheckMutex*)p; ++ return pGlobalMutexMethods->xMutexTry(pCheck->mutex); ++} ++ ++/* ++** Leave the mutex. ++*/ ++static void checkMutexLeave(sqlite3_mutex *p){ ++ CheckMutex *pCheck = (CheckMutex*)p; ++ pGlobalMutexMethods->xMutexLeave(pCheck->mutex); ++} ++ ++sqlite3_mutex_methods const *multiThreadedCheckMutex(void){ ++ static const sqlite3_mutex_methods sMutex = { ++ checkMutexInit, ++ checkMutexEnd, ++ checkMutexAlloc, ++ checkMutexFree, ++ checkMutexEnter, ++ checkMutexTry, ++ checkMutexLeave, ++#ifdef SQLITE_DEBUG ++ checkMutexHeld, ++ checkMutexNotheld ++#else ++ 0, ++ 0 ++#endif ++ }; ++ return &sMutex; ++} ++ ++/* ++** Mark the SQLITE_MUTEX_RECURSIVE mutex passed as the only argument as ++** one on which there should be no contention. ++*/ ++SQLITE_PRIVATE void sqlite3MutexWarnOnContention(sqlite3_mutex *p){ ++ if( sqlite3GlobalConfig.mutex.xMutexAlloc==checkMutexAlloc ){ ++ CheckMutex *pCheck = (CheckMutex*)p; ++ assert( pCheck->iType==SQLITE_MUTEX_RECURSIVE ); ++ pCheck->iType = SQLITE_MUTEX_WARNONCONTENTION; ++ } ++} ++#endif /* ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS */ ++ ++/* + ** Initialize the mutex system. + */ + SQLITE_PRIVATE int sqlite3MutexInit(void){ +@@ -23315,7 +24938,11 @@ + sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex; + + if( sqlite3GlobalConfig.bCoreMutex ){ ++#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS ++ pFrom = multiThreadedCheckMutex(); ++#else + pFrom = sqlite3DefaultMutex(); ++#endif + }else{ + pFrom = sqlite3NoopMutex(); + } +@@ -23714,11 +25341,12 @@ + #endif + }; + #if SQLITE_MUTEX_NREF +-#define SQLITE3_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER,0,0,(pthread_t)0,0} ++# define SQLITE3_MUTEX_INITIALIZER(id) \ ++ {PTHREAD_MUTEX_INITIALIZER,id,0,(pthread_t)0,0} + #elif defined(SQLITE_ENABLE_API_ARMOR) +-#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0 } ++# define SQLITE3_MUTEX_INITIALIZER(id) { PTHREAD_MUTEX_INITIALIZER, id } + #else +-#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER } ++#define SQLITE3_MUTEX_INITIALIZER(id) { PTHREAD_MUTEX_INITIALIZER } + #endif + + /* +@@ -23815,18 +25443,18 @@ + */ + static sqlite3_mutex *pthreadMutexAlloc(int iType){ + static sqlite3_mutex staticMutexes[] = { +- SQLITE3_MUTEX_INITIALIZER, +- SQLITE3_MUTEX_INITIALIZER, +- SQLITE3_MUTEX_INITIALIZER, +- SQLITE3_MUTEX_INITIALIZER, +- SQLITE3_MUTEX_INITIALIZER, +- SQLITE3_MUTEX_INITIALIZER, +- SQLITE3_MUTEX_INITIALIZER, +- SQLITE3_MUTEX_INITIALIZER, +- SQLITE3_MUTEX_INITIALIZER, +- SQLITE3_MUTEX_INITIALIZER, +- SQLITE3_MUTEX_INITIALIZER, +- SQLITE3_MUTEX_INITIALIZER ++ SQLITE3_MUTEX_INITIALIZER(2), ++ SQLITE3_MUTEX_INITIALIZER(3), ++ SQLITE3_MUTEX_INITIALIZER(4), ++ SQLITE3_MUTEX_INITIALIZER(5), ++ SQLITE3_MUTEX_INITIALIZER(6), ++ SQLITE3_MUTEX_INITIALIZER(7), ++ SQLITE3_MUTEX_INITIALIZER(8), ++ SQLITE3_MUTEX_INITIALIZER(9), ++ SQLITE3_MUTEX_INITIALIZER(10), ++ SQLITE3_MUTEX_INITIALIZER(11), ++ SQLITE3_MUTEX_INITIALIZER(12), ++ SQLITE3_MUTEX_INITIALIZER(13) + }; + sqlite3_mutex *p; + switch( iType ){ +@@ -23845,6 +25473,9 @@ + pthread_mutex_init(&p->mutex, &recursiveAttr); + pthread_mutexattr_destroy(&recursiveAttr); + #endif ++#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) ++ p->id = SQLITE_MUTEX_RECURSIVE; ++#endif + } + break; + } +@@ -23852,6 +25483,9 @@ + p = sqlite3MallocZero( sizeof(*p) ); + if( p ){ + pthread_mutex_init(&p->mutex, 0); ++#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) ++ p->id = SQLITE_MUTEX_FAST; ++#endif + } + break; + } +@@ -23867,7 +25501,7 @@ + } + } + #if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) +- if( p ) p->id = iType; ++ assert( p==0 || p->id==iType ); + #endif + return p; + } +@@ -24384,7 +26018,7 @@ + #ifdef SQLITE_DEBUG + volatile int nRef; /* Number of enterances */ + volatile DWORD owner; /* Thread holding this mutex */ +- volatile int trace; /* True to trace changes */ ++ volatile LONG trace; /* True to trace changes */ + #endif + }; + +@@ -24396,10 +26030,10 @@ + #define SQLITE_W32_MUTEX_INITIALIZER { 0 } + + #ifdef SQLITE_DEBUG +-#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, \ ++#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id, \ + 0L, (DWORD)0, 0 } + #else +-#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 } ++#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id } + #endif + + #ifdef SQLITE_DEBUG +@@ -24442,18 +26076,18 @@ + ** Initialize and deinitialize the mutex subsystem. + */ + static sqlite3_mutex winMutex_staticMutexes[] = { +- SQLITE3_MUTEX_INITIALIZER, +- SQLITE3_MUTEX_INITIALIZER, +- SQLITE3_MUTEX_INITIALIZER, +- SQLITE3_MUTEX_INITIALIZER, +- SQLITE3_MUTEX_INITIALIZER, +- SQLITE3_MUTEX_INITIALIZER, +- SQLITE3_MUTEX_INITIALIZER, +- SQLITE3_MUTEX_INITIALIZER, +- SQLITE3_MUTEX_INITIALIZER, +- SQLITE3_MUTEX_INITIALIZER, +- SQLITE3_MUTEX_INITIALIZER, +- SQLITE3_MUTEX_INITIALIZER ++ SQLITE3_MUTEX_INITIALIZER(2), ++ SQLITE3_MUTEX_INITIALIZER(3), ++ SQLITE3_MUTEX_INITIALIZER(4), ++ SQLITE3_MUTEX_INITIALIZER(5), ++ SQLITE3_MUTEX_INITIALIZER(6), ++ SQLITE3_MUTEX_INITIALIZER(7), ++ SQLITE3_MUTEX_INITIALIZER(8), ++ SQLITE3_MUTEX_INITIALIZER(9), ++ SQLITE3_MUTEX_INITIALIZER(10), ++ SQLITE3_MUTEX_INITIALIZER(11), ++ SQLITE3_MUTEX_INITIALIZER(12), ++ SQLITE3_MUTEX_INITIALIZER(13) + }; + + static int winMutex_isInit = 0; +@@ -24583,15 +26217,15 @@ + } + #endif + p = &winMutex_staticMutexes[iType-2]; +- p->id = iType; + #ifdef SQLITE_DEBUG + #ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC +- p->trace = 1; ++ InterlockedCompareExchange(&p->trace, 1, 0); + #endif + #endif + break; + } + } ++ assert( p==0 || p->id==iType ); + return p; + } + +@@ -24779,14 +26413,6 @@ + } + + /* +-** An instance of the following object records the location of +-** each unused scratch buffer. +-*/ +-typedef struct ScratchFreeslot { +- struct ScratchFreeslot *pNext; /* Next unused scratch buffer */ +-} ScratchFreeslot; +- +-/* + ** State information local to the memory allocation subsystem. + */ + static SQLITE_WSD struct Mem0Global { +@@ -24794,21 +26420,11 @@ + sqlite3_int64 alarmThreshold; /* The soft heap limit */ + + /* +- ** Pointers to the end of sqlite3GlobalConfig.pScratch memory +- ** (so that a range test can be used to determine if an allocation +- ** being freed came from pScratch) and a pointer to the list of +- ** unused scratch allocations. +- */ +- void *pScratchEnd; +- ScratchFreeslot *pScratchFree; +- u32 nScratchFree; +- +- /* + ** True if heap is nearly "full" where "full" is defined by the + ** sqlite3_soft_heap_limit() setting. + */ + int nearlyFull; +-} mem0 = { 0, 0, 0, 0, 0, 0 }; ++} mem0 = { 0, 0, 0 }; + + #define mem0 GLOBAL(struct Mem0Global, mem0) + +@@ -24878,28 +26494,6 @@ + } + memset(&mem0, 0, sizeof(mem0)); + mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); +- if( sqlite3GlobalConfig.pScratch && sqlite3GlobalConfig.szScratch>=100 +- && sqlite3GlobalConfig.nScratch>0 ){ +- int i, n, sz; +- ScratchFreeslot *pSlot; +- sz = ROUNDDOWN8(sqlite3GlobalConfig.szScratch); +- sqlite3GlobalConfig.szScratch = sz; +- pSlot = (ScratchFreeslot*)sqlite3GlobalConfig.pScratch; +- n = sqlite3GlobalConfig.nScratch; +- mem0.pScratchFree = pSlot; +- mem0.nScratchFree = n; +- for(i=0; i<n-1; i++){ +- pSlot->pNext = (ScratchFreeslot*)(sz+(char*)pSlot); +- pSlot = pSlot->pNext; +- } +- pSlot->pNext = 0; +- mem0.pScratchEnd = (void*)&pSlot[1]; +- }else{ +- mem0.pScratchEnd = 0; +- sqlite3GlobalConfig.pScratch = 0; +- sqlite3GlobalConfig.szScratch = 0; +- sqlite3GlobalConfig.nScratch = 0; +- } + if( sqlite3GlobalConfig.pPage==0 || sqlite3GlobalConfig.szPage<512 + || sqlite3GlobalConfig.nPage<=0 ){ + sqlite3GlobalConfig.pPage = 0; +@@ -25051,105 +26645,6 @@ + } + + /* +-** Each thread may only have a single outstanding allocation from +-** xScratchMalloc(). We verify this constraint in the single-threaded +-** case by setting scratchAllocOut to 1 when an allocation +-** is outstanding clearing it when the allocation is freed. +-*/ +-#if SQLITE_THREADSAFE==0 && !defined(NDEBUG) +-static int scratchAllocOut = 0; +-#endif +- +- +-/* +-** Allocate memory that is to be used and released right away. +-** This routine is similar to alloca() in that it is not intended +-** for situations where the memory might be held long-term. This +-** routine is intended to get memory to old large transient data +-** structures that would not normally fit on the stack of an +-** embedded processor. +-*/ +-SQLITE_PRIVATE void *sqlite3ScratchMalloc(int n){ +- void *p; +- assert( n>0 ); +- +- sqlite3_mutex_enter(mem0.mutex); +- sqlite3StatusHighwater(SQLITE_STATUS_SCRATCH_SIZE, n); +- if( mem0.nScratchFree && sqlite3GlobalConfig.szScratch>=n ){ +- p = mem0.pScratchFree; +- mem0.pScratchFree = mem0.pScratchFree->pNext; +- mem0.nScratchFree--; +- sqlite3StatusUp(SQLITE_STATUS_SCRATCH_USED, 1); +- sqlite3_mutex_leave(mem0.mutex); +- }else{ +- sqlite3_mutex_leave(mem0.mutex); +- p = sqlite3Malloc(n); +- if( sqlite3GlobalConfig.bMemstat && p ){ +- sqlite3_mutex_enter(mem0.mutex); +- sqlite3StatusUp(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p)); +- sqlite3_mutex_leave(mem0.mutex); +- } +- sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH); +- } +- assert( sqlite3_mutex_notheld(mem0.mutex) ); +- +- +-#if SQLITE_THREADSAFE==0 && !defined(NDEBUG) +- /* EVIDENCE-OF: R-12970-05880 SQLite will not use more than one scratch +- ** buffers per thread. +- ** +- ** This can only be checked in single-threaded mode. +- */ +- assert( scratchAllocOut==0 ); +- if( p ) scratchAllocOut++; +-#endif +- +- return p; +-} +-SQLITE_PRIVATE void sqlite3ScratchFree(void *p){ +- if( p ){ +- +-#if SQLITE_THREADSAFE==0 && !defined(NDEBUG) +- /* Verify that no more than two scratch allocation per thread +- ** is outstanding at one time. (This is only checked in the +- ** single-threaded case since checking in the multi-threaded case +- ** would be much more complicated.) */ +- assert( scratchAllocOut>=1 && scratchAllocOut<=2 ); +- scratchAllocOut--; +-#endif +- +- if( SQLITE_WITHIN(p, sqlite3GlobalConfig.pScratch, mem0.pScratchEnd) ){ +- /* Release memory from the SQLITE_CONFIG_SCRATCH allocation */ +- ScratchFreeslot *pSlot; +- pSlot = (ScratchFreeslot*)p; +- sqlite3_mutex_enter(mem0.mutex); +- pSlot->pNext = mem0.pScratchFree; +- mem0.pScratchFree = pSlot; +- mem0.nScratchFree++; +- assert( mem0.nScratchFree <= (u32)sqlite3GlobalConfig.nScratch ); +- sqlite3StatusDown(SQLITE_STATUS_SCRATCH_USED, 1); +- sqlite3_mutex_leave(mem0.mutex); +- }else{ +- /* Release memory back to the heap */ +- assert( sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH) ); +- assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_SCRATCH) ); +- sqlite3MemdebugSetType(p, MEMTYPE_HEAP); +- if( sqlite3GlobalConfig.bMemstat ){ +- int iSize = sqlite3MallocSize(p); +- sqlite3_mutex_enter(mem0.mutex); +- sqlite3StatusDown(SQLITE_STATUS_SCRATCH_OVERFLOW, iSize); +- sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, iSize); +- sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1); +- sqlite3GlobalConfig.m.xFree(p); +- sqlite3_mutex_leave(mem0.mutex); +- }else{ +- sqlite3GlobalConfig.m.xFree(p); +- } +- } +- } +-} +- +-/* + ** TRUE if p is a lookaside memory allocation from db + */ + #ifndef SQLITE_OMIT_LOOKASIDE +@@ -25239,7 +26734,6 @@ + #endif + pBuf->pNext = db->lookaside.pFree; + db->lookaside.pFree = pBuf; +- db->lookaside.nOut--; + return; + } + } +@@ -25400,16 +26894,16 @@ + assert( db->mallocFailed==0 ); + if( n>db->lookaside.sz ){ + db->lookaside.anStat[1]++; +- }else if( (pBuf = db->lookaside.pFree)==0 ){ +- db->lookaside.anStat[2]++; +- }else{ ++ }else if( (pBuf = db->lookaside.pFree)!=0 ){ + db->lookaside.pFree = pBuf->pNext; +- db->lookaside.nOut++; + db->lookaside.anStat[0]++; +- if( db->lookaside.nOut>db->lookaside.mxOut ){ +- db->lookaside.mxOut = db->lookaside.nOut; +- } + return (void*)pBuf; ++ }else if( (pBuf = db->lookaside.pInit)!=0 ){ ++ db->lookaside.pInit = pBuf->pNext; ++ db->lookaside.anStat[0]++; ++ return (void*)pBuf; ++ }else{ ++ db->lookaside.anStat[2]++; + } + }else if( db->mallocFailed ){ + return 0; +@@ -25514,6 +27008,19 @@ + } + + /* ++** The text between zStart and zEnd represents a phrase within a larger ++** SQL statement. Make a copy of this phrase in space obtained form ++** sqlite3DbMalloc(). Omit leading and trailing whitespace. ++*/ ++SQLITE_PRIVATE char *sqlite3DbSpanDup(sqlite3 *db, const char *zStart, const char *zEnd){ ++ int n; ++ while( sqlite3Isspace(zStart[0]) ) zStart++; ++ n = (int)(zEnd - zStart); ++ while( ALWAYS(n>0) && sqlite3Isspace(zStart[n-1]) ) n--; ++ return sqlite3DbStrNDup(db, zStart, n); ++} ++ ++/* + ** Free any prior content in *pz and replace it with a copy of zNew. + */ + SQLITE_PRIVATE void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){ +@@ -25725,7 +27232,7 @@ + ** Set the StrAccum object to an error mode. + */ + static void setStrAccumError(StrAccum *p, u8 eError){ +- assert( eError==STRACCUM_NOMEM || eError==STRACCUM_TOOBIG ); ++ assert( eError==SQLITE_NOMEM || eError==SQLITE_TOOBIG ); + p->accError = eError; + p->nAlloc = 0; + } +@@ -25759,8 +27266,8 @@ + /* + ** Render a string given by "fmt" into the StrAccum object. + */ +-SQLITE_PRIVATE void sqlite3VXPrintf( +- StrAccum *pAccum, /* Accumulate results here */ ++SQLITE_API void sqlite3_str_vappendf( ++ sqlite3_str *pAccum, /* Accumulate results here */ + const char *fmt, /* Format string */ + va_list ap /* arguments */ + ){ +@@ -25797,6 +27304,11 @@ + PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */ + char buf[etBUFSIZE]; /* Conversion buffer */ + ++ /* pAccum never starts out with an empty buffer that was obtained from ++ ** malloc(). This precondition is required by the mprintf("%z...") ++ ** optimization. */ ++ assert( pAccum->nChar>0 || (pAccum->printfFlags&SQLITE_PRINTF_MALLOCED)==0 ); ++ + bufpt = 0; + if( (pAccum->printfFlags & SQLITE_PRINTF_SQLFUNC)!=0 ){ + pArgList = va_arg(ap, PrintfArguments*); +@@ -25812,11 +27324,11 @@ + #else + do{ fmt++; }while( *fmt && *fmt != '%' ); + #endif +- sqlite3StrAccumAppend(pAccum, bufpt, (int)(fmt - bufpt)); ++ sqlite3_str_append(pAccum, bufpt, (int)(fmt - bufpt)); + if( *fmt==0 ) break; + } + if( (c=(*++fmt))==0 ){ +- sqlite3StrAccumAppend(pAccum, "%", 1); ++ sqlite3_str_append(pAccum, "%", 1); + break; + } + /* Find out what flags are present */ +@@ -25994,7 +27506,7 @@ + u64 n = (u64)precision + 10 + precision/3; + zOut = zExtra = sqlite3Malloc( n ); + if( zOut==0 ){ +- setStrAccumError(pAccum, STRACCUM_NOMEM); ++ setStrAccumError(pAccum, SQLITE_NOMEM); + return; + } + nOut = (int)n; +@@ -26119,7 +27631,7 @@ + bufpt = zExtra + = sqlite3Malloc( MAX(e2,0)+(i64)precision+(i64)width+15 ); + if( bufpt==0 ){ +- setStrAccumError(pAccum, STRACCUM_NOMEM); ++ setStrAccumError(pAccum, SQLITE_NOMEM); + return; + } + } +@@ -26215,22 +27727,52 @@ + case etCHARX: + if( bArgList ){ + bufpt = getTextArg(pArgList); +- c = bufpt ? bufpt[0] : 0; ++ length = 1; ++ if( bufpt ){ ++ buf[0] = c = *(bufpt++); ++ if( (c&0xc0)==0xc0 ){ ++ while( length<4 && (bufpt[0]&0xc0)==0x80 ){ ++ buf[length++] = *(bufpt++); ++ } ++ } ++ }else{ ++ buf[0] = 0; ++ } + }else{ +- c = va_arg(ap,int); ++ unsigned int ch = va_arg(ap,unsigned int); ++ if( ch<0x00080 ){ ++ buf[0] = ch & 0xff; ++ length = 1; ++ }else if( ch<0x00800 ){ ++ buf[0] = 0xc0 + (u8)((ch>>6)&0x1f); ++ buf[1] = 0x80 + (u8)(ch & 0x3f); ++ length = 2; ++ }else if( ch<0x10000 ){ ++ buf[0] = 0xe0 + (u8)((ch>>12)&0x0f); ++ buf[1] = 0x80 + (u8)((ch>>6) & 0x3f); ++ buf[2] = 0x80 + (u8)(ch & 0x3f); ++ length = 3; ++ }else{ ++ buf[0] = 0xf0 + (u8)((ch>>18) & 0x07); ++ buf[1] = 0x80 + (u8)((ch>>12) & 0x3f); ++ buf[2] = 0x80 + (u8)((ch>>6) & 0x3f); ++ buf[3] = 0x80 + (u8)(ch & 0x3f); ++ length = 4; ++ } + } + if( precision>1 ){ + width -= precision-1; + if( width>1 && !flag_leftjustify ){ +- sqlite3AppendChar(pAccum, width-1, ' '); ++ sqlite3_str_appendchar(pAccum, width-1, ' '); + width = 0; + } +- sqlite3AppendChar(pAccum, precision-1, c); ++ while( precision-- > 1 ){ ++ sqlite3_str_append(pAccum, buf, length); ++ } + } +- length = 1; +- buf[0] = c; + bufpt = buf; +- break; ++ flag_altform2 = 1; ++ goto adjust_width_for_utf8; + case etSTRING: + case etDYNSTRING: + if( bArgList ){ +@@ -26242,17 +27784,50 @@ + if( bufpt==0 ){ + bufpt = ""; + }else if( xtype==etDYNSTRING ){ ++ if( pAccum->nChar==0 ++ && pAccum->mxAlloc ++ && width==0 ++ && precision<0 ++ && pAccum->accError==0 ++ ){ ++ /* Special optimization for sqlite3_mprintf("%z..."): ++ ** Extend an existing memory allocation rather than creating ++ ** a new one. */ ++ assert( (pAccum->printfFlags&SQLITE_PRINTF_MALLOCED)==0 ); ++ pAccum->zText = bufpt; ++ pAccum->nAlloc = sqlite3DbMallocSize(pAccum->db, bufpt); ++ pAccum->nChar = 0x7fffffff & (int)strlen(bufpt); ++ pAccum->printfFlags |= SQLITE_PRINTF_MALLOCED; ++ length = 0; ++ break; ++ } + zExtra = bufpt; + } + if( precision>=0 ){ +- for(length=0; length<precision && bufpt[length]; length++){} ++ if( flag_altform2 ){ ++ /* Set length to the number of bytes needed in order to display ++ ** precision characters */ ++ unsigned char *z = (unsigned char*)bufpt; ++ while( precision-- > 0 && z[0] ){ ++ SQLITE_SKIP_UTF8(z); ++ } ++ length = (int)(z - (unsigned char*)bufpt); ++ }else{ ++ for(length=0; length<precision && bufpt[length]; length++){} ++ } + }else{ +- length = sqlite3Strlen30(bufpt); ++ length = 0x7fffffff & (int)strlen(bufpt); + } ++ adjust_width_for_utf8: ++ if( flag_altform2 && width>0 ){ ++ /* Adjust width to account for extra bytes in UTF-8 characters */ ++ int ii = length - 1; ++ while( ii>=0 ) if( (bufpt[ii--] & 0xc0)==0x80 ) width++; ++ } + break; +- case etSQLESCAPE: /* Escape ' characters */ +- case etSQLESCAPE2: /* Escape ' and enclose in '...' */ +- case etSQLESCAPE3: { /* Escape " characters */ ++ case etSQLESCAPE: /* %q: Escape ' characters */ ++ case etSQLESCAPE2: /* %Q: Escape ' and enclose in '...' */ ++ case etSQLESCAPE3: { /* %w: Escape " characters */ + int i, j, k, n, isnull; + int needQuote; + char ch; +@@ -26266,9 +27841,17 @@ + } + isnull = escarg==0; + if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)"); ++ /* For %q, %Q, and %w, the precision is the number of byte (or ++ ** characters if the ! flags is present) to use from the input. ++ ** Because of the extra quoting characters inserted, the number ++ ** of output characters may be larger than the precision. ++ */ + k = precision; + for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){ + if( ch==q ) n++; ++ if( flag_altform2 && (ch&0xc0)==0xc0 ){ ++ while( (escarg[i+1]&0xc0)==0x80 ){ i++; } ++ } + } + needQuote = !isnull && xtype==etSQLESCAPE2; + n += i + 3; +@@ -26275,7 +27858,7 @@ + if( n>etBUFSIZE ){ + bufpt = zExtra = sqlite3Malloc( n ); + if( bufpt==0 ){ +- setStrAccumError(pAccum, STRACCUM_NOMEM); ++ setStrAccumError(pAccum, SQLITE_NOMEM); + return; + } + }else{ +@@ -26291,10 +27874,7 @@ + if( needQuote ) bufpt[j++] = q; + bufpt[j] = 0; + length = j; +- /* The precision in %q and %Q means how many input characters to +- ** consume, not the length of the output... +- ** if( precision>=0 && precision<length ) length = precision; */ +- break; ++ goto adjust_width_for_utf8; + } + case etTOKEN: { + Token *pToken; +@@ -26302,7 +27882,7 @@ + pToken = va_arg(ap, Token*); + assert( bArgList==0 ); + if( pToken && pToken->n ){ +- sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n); ++ sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n); + } + length = width = 0; + break; +@@ -26318,10 +27898,10 @@ + assert( bArgList==0 ); + assert( k>=0 && k<pSrc->nSrc ); + if( pItem->zDatabase ){ +- sqlite3StrAccumAppendAll(pAccum, pItem->zDatabase); +- sqlite3StrAccumAppend(pAccum, ".", 1); ++ sqlite3_str_appendall(pAccum, pItem->zDatabase); ++ sqlite3_str_append(pAccum, ".", 1); + } +- sqlite3StrAccumAppendAll(pAccum, pItem->zName); ++ sqlite3_str_appendall(pAccum, pItem->zName); + length = width = 0; + break; + } +@@ -26333,15 +27913,18 @@ + /* + ** The text of the conversion is pointed to by "bufpt" and is + ** "length" characters long. The field width is "width". Do +- ** the output. ++ ** the output. Both length and width are in bytes, not characters, ++ ** at this point. If the "!" flag was present on string conversions ++ ** indicating that width and precision should be expressed in characters, ++ ** then the values have been translated prior to reaching this point. + */ + width -= length; + if( width>0 ){ +- if( !flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); +- sqlite3StrAccumAppend(pAccum, bufpt, length); +- if( flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); ++ if( !flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' '); ++ sqlite3_str_append(pAccum, bufpt, length); ++ if( flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' '); + }else{ +- sqlite3StrAccumAppend(pAccum, bufpt, length); ++ sqlite3_str_append(pAccum, bufpt, length); + } + + if( zExtra ){ +@@ -26362,18 +27945,17 @@ + char *zNew; + assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */ + if( p->accError ){ +- testcase(p->accError==STRACCUM_TOOBIG); +- testcase(p->accError==STRACCUM_NOMEM); ++ testcase(p->accError==SQLITE_TOOBIG); ++ testcase(p->accError==SQLITE_NOMEM); + return 0; + } + if( p->mxAlloc==0 ){ + N = p->nAlloc - p->nChar - 1; +- setStrAccumError(p, STRACCUM_TOOBIG); ++ setStrAccumError(p, SQLITE_TOOBIG); + return N; + }else{ + char *zOld = isMalloced(p) ? p->zText : 0; + i64 szNew = p->nChar; +- assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) ); + szNew += N + 1; + if( szNew+p->nChar<=p->mxAlloc ){ + /* Force exponential buffer size growth as long as it does not overflow, +@@ -26381,8 +27963,8 @@ + szNew += p->nChar; + } + if( szNew > p->mxAlloc ){ +- sqlite3StrAccumReset(p); +- setStrAccumError(p, STRACCUM_TOOBIG); ++ sqlite3_str_reset(p); ++ setStrAccumError(p, SQLITE_TOOBIG); + return 0; + }else{ + p->nAlloc = (int)szNew; +@@ -26399,8 +27981,8 @@ + p->nAlloc = sqlite3DbMallocSize(p->db, zNew); + p->printfFlags |= SQLITE_PRINTF_MALLOCED; + }else{ +- sqlite3StrAccumReset(p); +- setStrAccumError(p, STRACCUM_NOMEM); ++ sqlite3_str_reset(p); ++ setStrAccumError(p, SQLITE_NOMEM); + return 0; + } + } +@@ -26410,12 +27992,11 @@ + /* + ** Append N copies of character c to the given string buffer. + */ +-SQLITE_PRIVATE void sqlite3AppendChar(StrAccum *p, int N, char c){ ++SQLITE_API void sqlite3_str_appendchar(sqlite3_str *p, int N, char c){ + testcase( p->nChar + (i64)N > 0x7fffffff ); + if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){ + return; + } +- assert( (p->zText==p->zBase)==!isMalloced(p) ); + while( (N--)>0 ) p->zText[p->nChar++] = c; + } + +@@ -26423,9 +28004,9 @@ + ** The StrAccum "p" is not large enough to accept N new bytes of z[]. + ** So enlarge if first, then do the append. + ** +-** This is a helper routine to sqlite3StrAccumAppend() that does special-case ++** This is a helper routine to sqlite3_str_append() that does special-case + ** work (enlarging the buffer) using tail recursion, so that the +-** sqlite3StrAccumAppend() routine can use fast calling semantics. ++** sqlite3_str_append() routine can use fast calling semantics. + */ + static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){ + N = sqlite3StrAccumEnlarge(p, N); +@@ -26433,7 +28014,6 @@ + memcpy(&p->zText[p->nChar], z, N); + p->nChar += N; + } +- assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) ); + } + + /* +@@ -26440,7 +28020,7 @@ + ** Append N bytes of text from z to the StrAccum object. Increase the + ** size of the memory allocation for StrAccum if necessary. + */ +-SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ ++SQLITE_API void sqlite3_str_append(sqlite3_str *p, const char *z, int N){ + assert( z!=0 || N==0 ); + assert( p->zText!=0 || p->nChar==0 || p->accError ); + assert( N>=0 ); +@@ -26457,8 +28037,8 @@ + /* + ** Append the complete text of zero-terminated string z[] to the p string. + */ +-SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){ +- sqlite3StrAccumAppend(p, z, sqlite3Strlen30(z)); ++SQLITE_API void sqlite3_str_appendall(sqlite3_str *p, const char *z){ ++ sqlite3_str_append(p, z, sqlite3Strlen30(z)); + } + + +@@ -26468,19 +28048,20 @@ + ** pointer if any kind of error was encountered. + */ + static SQLITE_NOINLINE char *strAccumFinishRealloc(StrAccum *p){ ++ char *zText; + assert( p->mxAlloc>0 && !isMalloced(p) ); +- p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); +- if( p->zText ){ +- memcpy(p->zText, p->zBase, p->nChar+1); ++ zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); ++ if( zText ){ ++ memcpy(zText, p->zText, p->nChar+1); + p->printfFlags |= SQLITE_PRINTF_MALLOCED; + }else{ +- setStrAccumError(p, STRACCUM_NOMEM); ++ setStrAccumError(p, SQLITE_NOMEM); + } +- return p->zText; ++ p->zText = zText; ++ return zText; + } + SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){ + if( p->zText ){ +- assert( (p->zText==p->zBase)==!isMalloced(p) ); + p->zText[p->nChar] = 0; + if( p->mxAlloc>0 && !isMalloced(p) ){ + return strAccumFinishRealloc(p); +@@ -26490,14 +28071,55 @@ + } + + /* ++** This singleton is an sqlite3_str object that is returned if ++** sqlite3_malloc() fails to provide space for a real one. This ++** sqlite3_str object accepts no new text and always returns ++** an SQLITE_NOMEM error. ++*/ ++static sqlite3_str sqlite3OomStr = { ++ 0, 0, 0, 0, 0, SQLITE_NOMEM, 0 ++}; ++ ++/* Finalize a string created using sqlite3_str_new(). ++*/ ++SQLITE_API char *sqlite3_str_finish(sqlite3_str *p){ ++ char *z; ++ if( p!=0 && p!=&sqlite3OomStr ){ ++ z = sqlite3StrAccumFinish(p); ++ sqlite3_free(p); ++ }else{ ++ z = 0; ++ } ++ return z; ++} ++ ++/* Return any error code associated with p */ ++SQLITE_API int sqlite3_str_errcode(sqlite3_str *p){ ++ return p ? p->accError : SQLITE_NOMEM; ++} ++ ++/* Return the current length of p in bytes */ ++SQLITE_API int sqlite3_str_length(sqlite3_str *p){ ++ return p ? p->nChar : 0; ++} ++ ++/* Return the current value for p */ ++SQLITE_API char *sqlite3_str_value(sqlite3_str *p){ ++ if( p==0 || p->nChar==0 ) return 0; ++ p->zText[p->nChar] = 0; ++ return p->zText; ++} ++ ++/* + ** Reset an StrAccum string. Reclaim all malloced memory. + */ +-SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum *p){ +- assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) ); ++SQLITE_API void sqlite3_str_reset(StrAccum *p){ + if( isMalloced(p) ){ + sqlite3DbFree(p->db, p->zText); + p->printfFlags &= ~SQLITE_PRINTF_MALLOCED; + } ++ p->nAlloc = 0; ++ p->nChar = 0; + p->zText = 0; + } + +@@ -26516,15 +28138,27 @@ + ** allocations will ever occur. + */ + SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){ +- p->zText = p->zBase = zBase; ++ p->zText = zBase; + p->db = db; +- p->nChar = 0; + p->nAlloc = n; + p->mxAlloc = mx; ++ p->nChar = 0; + p->accError = 0; + p->printfFlags = 0; + } + ++/* Allocate and initialize a new dynamic string object */ ++SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3 *db){ ++ sqlite3_str *p = sqlite3_malloc64(sizeof(*p)); ++ if( p ){ ++ sqlite3StrAccumInit(p, 0, 0, 0, ++ db ? db->aLimit[SQLITE_LIMIT_LENGTH] : SQLITE_MAX_LENGTH); ++ }else{ ++ p = &sqlite3OomStr; ++ } ++ return p; ++} ++ + /* + ** Print into memory obtained from sqliteMalloc(). Use the internal + ** %-conversion extensions. +@@ -26537,9 +28171,9 @@ + sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase), + db->aLimit[SQLITE_LIMIT_LENGTH]); + acc.printfFlags = SQLITE_PRINTF_INTERNAL; +- sqlite3VXPrintf(&acc, zFormat, ap); ++ sqlite3_str_vappendf(&acc, zFormat, ap); + z = sqlite3StrAccumFinish(&acc); +- if( acc.accError==STRACCUM_NOMEM ){ ++ if( acc.accError==SQLITE_NOMEM ){ + sqlite3OomFault(db); + } + return z; +@@ -26577,7 +28211,7 @@ + if( sqlite3_initialize() ) return 0; + #endif + sqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); +- sqlite3VXPrintf(&acc, zFormat, ap); ++ sqlite3_str_vappendf(&acc, zFormat, ap); + z = sqlite3StrAccumFinish(&acc); + return z; + } +@@ -26622,7 +28256,7 @@ + } + #endif + sqlite3StrAccumInit(&acc, 0, zBuf, n, 0); +- sqlite3VXPrintf(&acc, zFormat, ap); ++ sqlite3_str_vappendf(&acc, zFormat, ap); + zBuf[acc.nChar] = 0; + return zBuf; + } +@@ -26644,7 +28278,7 @@ + ** allocate memory because it might be called while the memory allocator + ** mutex is held. + ** +-** sqlite3VXPrintf() might ask for *temporary* memory allocations for ++** sqlite3_str_vappendf() might ask for *temporary* memory allocations for + ** certain format characters (%q) or for very large precisions or widths. + ** Care must be taken that any sqlite3_log() calls that occur while the + ** memory mutex is held do not use these mechanisms. +@@ -26654,7 +28288,7 @@ + char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */ + + sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0); +- sqlite3VXPrintf(&acc, zFormat, ap); ++ sqlite3_str_vappendf(&acc, zFormat, ap); + sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode, + sqlite3StrAccumFinish(&acc)); + } +@@ -26683,23 +28317,30 @@ + char zBuf[500]; + sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); + va_start(ap,zFormat); +- sqlite3VXPrintf(&acc, zFormat, ap); ++ sqlite3_str_vappendf(&acc, zFormat, ap); + va_end(ap); + sqlite3StrAccumFinish(&acc); ++#ifdef SQLITE_OS_TRACE_PROC ++ { ++ extern void SQLITE_OS_TRACE_PROC(const char *zBuf, int nBuf); ++ SQLITE_OS_TRACE_PROC(zBuf, sizeof(zBuf)); ++ } ++#else + fprintf(stdout,"%s", zBuf); + fflush(stdout); ++#endif + } + #endif + + + /* +-** variable-argument wrapper around sqlite3VXPrintf(). The bFlags argument ++** variable-argument wrapper around sqlite3_str_vappendf(). The bFlags argument + ** can contain the bit SQLITE_PRINTF_INTERNAL enable internal formats. + */ +-SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){ ++SQLITE_API void sqlite3_str_appendf(StrAccum *p, const char *zFormat, ...){ + va_list ap; + va_start(ap,zFormat); +- sqlite3VXPrintf(p, zFormat, ap); ++ sqlite3_str_vappendf(p, zFormat, ap); + va_end(ap); + } + +@@ -26765,15 +28406,17 @@ + sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); + if( p ){ + for(i=0; i<p->iLevel && i<sizeof(p->bLine)-1; i++){ +- sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4); ++ sqlite3_str_append(&acc, p->bLine[i] ? "| " : " ", 4); + } +- sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4); ++ sqlite3_str_append(&acc, p->bLine[i] ? "|-- " : "'-- ", 4); + } +- va_start(ap, zFormat); +- sqlite3VXPrintf(&acc, zFormat, ap); +- va_end(ap); +- assert( acc.nChar>0 ); +- if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1); ++ if( zFormat!=0 ){ ++ va_start(ap, zFormat); ++ sqlite3_str_vappendf(&acc, zFormat, ap); ++ va_end(ap); ++ assert( acc.nChar>0 ); ++ sqlite3_str_append(&acc, "\n", 1); ++ } + sqlite3StrAccumFinish(&acc); + fprintf(stdout,"%s", zBuf); + fflush(stdout); +@@ -26806,17 +28449,17 @@ + char zLine[1000]; + const struct Cte *pCte = &pWith->a[i]; + sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); +- sqlite3XPrintf(&x, "%s", pCte->zName); ++ sqlite3_str_appendf(&x, "%s", pCte->zName); + if( pCte->pCols && pCte->pCols->nExpr>0 ){ + char cSep = '('; + int j; + for(j=0; j<pCte->pCols->nExpr; j++){ +- sqlite3XPrintf(&x, "%c%s", cSep, pCte->pCols->a[j].zName); ++ sqlite3_str_appendf(&x, "%c%s", cSep, pCte->pCols->a[j].zName); + cSep = ','; + } +- sqlite3XPrintf(&x, ")"); ++ sqlite3_str_appendf(&x, ")"); + } +- sqlite3XPrintf(&x, " AS"); ++ sqlite3_str_appendf(&x, " AS"); + sqlite3StrAccumFinish(&x); + sqlite3TreeViewItem(pView, zLine, i<pWith->nCte-1); + sqlite3TreeViewSelect(pView, pCte->pSelect, 0); +@@ -26826,6 +28469,42 @@ + } + } + ++/* ++** Generate a human-readable description of a SrcList object. ++*/ ++SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){ ++ int i; ++ for(i=0; i<pSrc->nSrc; i++){ ++ const struct SrcList_item *pItem = &pSrc->a[i]; ++ StrAccum x; ++ char zLine[100]; ++ sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); ++ sqlite3_str_appendf(&x, "{%d,*}", pItem->iCursor); ++ if( pItem->zDatabase ){ ++ sqlite3_str_appendf(&x, " %s.%s", pItem->zDatabase, pItem->zName); ++ }else if( pItem->zName ){ ++ sqlite3_str_appendf(&x, " %s", pItem->zName); ++ } ++ if( pItem->pTab ){ ++ sqlite3_str_appendf(&x, " tabname=%Q", pItem->pTab->zName); ++ } ++ if( pItem->zAlias ){ ++ sqlite3_str_appendf(&x, " (AS %s)", pItem->zAlias); ++ } ++ if( pItem->fg.jointype & JT_LEFT ){ ++ sqlite3_str_appendf(&x, " LEFT-JOIN"); ++ } ++ sqlite3StrAccumFinish(&x); ++ sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1); ++ if( pItem->pSelect ){ ++ sqlite3TreeViewSelect(pView, pItem->pSelect, 0); ++ } ++ if( pItem->fg.isTabFunc ){ ++ sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:"); ++ } ++ sqlite3TreeViewPop(pView); ++ } ++} + + /* + ** Generate a human-readable description of a Select object. +@@ -26844,9 +28523,11 @@ + sqlite3TreeViewPush(pView, 1); + } + do{ +- sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x nSelectRow=%d", ++ sqlite3TreeViewLine(pView, ++ "SELECT%s%s (%u/%p) selFlags=0x%x nSelectRow=%d", + ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""), +- ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p, p->selFlags, ++ ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), ++ p->selId, p, p->selFlags, + (int)p->nSelectRow + ); + if( cnt++ ) sqlite3TreeViewPop(pView); +@@ -26860,43 +28541,27 @@ + if( p->pHaving ) n++; + if( p->pOrderBy ) n++; + if( p->pLimit ) n++; +- if( p->pOffset ) n++; ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( p->pWin ) n++; ++ if( p->pWinDefn ) n++; ++#endif + } + sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set"); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( p->pWin ){ ++ Window *pX; ++ pView = sqlite3TreeViewPush(pView, (n--)>0); ++ sqlite3TreeViewLine(pView, "window-functions"); ++ for(pX=p->pWin; pX; pX=pX->pNextWin){ ++ sqlite3TreeViewWinFunc(pView, pX, pX->pNextWin!=0); ++ } ++ sqlite3TreeViewPop(pView); ++ } ++#endif + if( p->pSrc && p->pSrc->nSrc ){ +- int i; + pView = sqlite3TreeViewPush(pView, (n--)>0); + sqlite3TreeViewLine(pView, "FROM"); +- for(i=0; i<p->pSrc->nSrc; i++){ +- struct SrcList_item *pItem = &p->pSrc->a[i]; +- StrAccum x; +- char zLine[100]; +- sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); +- sqlite3XPrintf(&x, "{%d,*}", pItem->iCursor); +- if( pItem->zDatabase ){ +- sqlite3XPrintf(&x, " %s.%s", pItem->zDatabase, pItem->zName); +- }else if( pItem->zName ){ +- sqlite3XPrintf(&x, " %s", pItem->zName); +- } +- if( pItem->pTab ){ +- sqlite3XPrintf(&x, " tabname=%Q", pItem->pTab->zName); +- } +- if( pItem->zAlias ){ +- sqlite3XPrintf(&x, " (AS %s)", pItem->zAlias); +- } +- if( pItem->fg.jointype & JT_LEFT ){ +- sqlite3XPrintf(&x, " LEFT-JOIN"); +- } +- sqlite3StrAccumFinish(&x); +- sqlite3TreeViewItem(pView, zLine, i<p->pSrc->nSrc-1); +- if( pItem->pSelect ){ +- sqlite3TreeViewSelect(pView, pItem->pSelect, 0); +- } +- if( pItem->fg.isTabFunc ){ +- sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:"); +- } +- sqlite3TreeViewPop(pView); +- } ++ sqlite3TreeViewSrcList(pView, p->pSrc); + sqlite3TreeViewPop(pView); + } + if( p->pWhere ){ +@@ -26912,19 +28577,29 @@ + sqlite3TreeViewExpr(pView, p->pHaving, 0); + sqlite3TreeViewPop(pView); + } ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( p->pWinDefn ){ ++ Window *pX; ++ sqlite3TreeViewItem(pView, "WINDOW", (n--)>0); ++ for(pX=p->pWinDefn; pX; pX=pX->pNextWin){ ++ sqlite3TreeViewWindow(pView, pX, pX->pNextWin!=0); ++ } ++ sqlite3TreeViewPop(pView); ++ } ++#endif + if( p->pOrderBy ){ + sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY"); + } + if( p->pLimit ){ + sqlite3TreeViewItem(pView, "LIMIT", (n--)>0); +- sqlite3TreeViewExpr(pView, p->pLimit, 0); ++ sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0); ++ if( p->pLimit->pRight ){ ++ sqlite3TreeViewItem(pView, "OFFSET", (n--)>0); ++ sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0); ++ sqlite3TreeViewPop(pView); ++ } + sqlite3TreeViewPop(pView); + } +- if( p->pOffset ){ +- sqlite3TreeViewItem(pView, "OFFSET", (n--)>0); +- sqlite3TreeViewExpr(pView, p->pOffset, 0); +- sqlite3TreeViewPop(pView); +- } + if( p->pPrior ){ + const char *zOp = "UNION"; + switch( p->op ){ +@@ -26939,7 +28614,84 @@ + sqlite3TreeViewPop(pView); + } + ++#ifndef SQLITE_OMIT_WINDOWFUNC + /* ++** Generate a description of starting or stopping bounds ++*/ ++SQLITE_PRIVATE void sqlite3TreeViewBound( ++ TreeView *pView, /* View context */ ++ u8 eBound, /* UNBOUNDED, CURRENT, PRECEDING, FOLLOWING */ ++ Expr *pExpr, /* Value for PRECEDING or FOLLOWING */ ++ u8 moreToFollow /* True if more to follow */ ++){ ++ switch( eBound ){ ++ case TK_UNBOUNDED: { ++ sqlite3TreeViewItem(pView, "UNBOUNDED", moreToFollow); ++ sqlite3TreeViewPop(pView); ++ break; ++ } ++ case TK_CURRENT: { ++ sqlite3TreeViewItem(pView, "CURRENT", moreToFollow); ++ sqlite3TreeViewPop(pView); ++ break; ++ } ++ case TK_PRECEDING: { ++ sqlite3TreeViewItem(pView, "PRECEDING", moreToFollow); ++ sqlite3TreeViewExpr(pView, pExpr, 0); ++ sqlite3TreeViewPop(pView); ++ break; ++ } ++ case TK_FOLLOWING: { ++ sqlite3TreeViewItem(pView, "FOLLOWING", moreToFollow); ++ sqlite3TreeViewExpr(pView, pExpr, 0); ++ sqlite3TreeViewPop(pView); ++ break; ++ } ++ } ++} ++#endif /* SQLITE_OMIT_WINDOWFUNC */ ++ ++#ifndef SQLITE_OMIT_WINDOWFUNC ++/* ++** Generate a human-readable explanation for a Window object ++*/ ++SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u8 more){ ++ pView = sqlite3TreeViewPush(pView, more); ++ if( pWin->zName ){ ++ sqlite3TreeViewLine(pView, "OVER %s", pWin->zName); ++ }else{ ++ sqlite3TreeViewLine(pView, "OVER"); ++ } ++ if( pWin->pPartition ){ ++ sqlite3TreeViewExprList(pView, pWin->pPartition, 1, "PARTITION-BY"); ++ } ++ if( pWin->pOrderBy ){ ++ sqlite3TreeViewExprList(pView, pWin->pOrderBy, 1, "ORDER-BY"); ++ } ++ if( pWin->eType ){ ++ sqlite3TreeViewItem(pView, pWin->eType==TK_RANGE ? "RANGE" : "ROWS", 0); ++ sqlite3TreeViewBound(pView, pWin->eStart, pWin->pStart, 1); ++ sqlite3TreeViewBound(pView, pWin->eEnd, pWin->pEnd, 0); ++ sqlite3TreeViewPop(pView); ++ } ++ sqlite3TreeViewPop(pView); ++} ++#endif /* SQLITE_OMIT_WINDOWFUNC */ ++ ++#ifndef SQLITE_OMIT_WINDOWFUNC ++/* ++** Generate a human-readable explanation for a Window Function object ++*/ ++SQLITE_PRIVATE void sqlite3TreeViewWinFunc(TreeView *pView, const Window *pWin, u8 more){ ++ pView = sqlite3TreeViewPush(pView, more); ++ sqlite3TreeViewLine(pView, "WINFUNC %s(%d)", ++ pWin->pFunc->zName, pWin->pFunc->nArg); ++ sqlite3TreeViewWindow(pView, pWin, 0); ++ sqlite3TreeViewPop(pView); ++} ++#endif /* SQLITE_OMIT_WINDOWFUNC */ ++ ++/* + ** Generate a human-readable explanation of an expression tree. + */ + SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ +@@ -26976,6 +28728,9 @@ + sqlite3TreeViewLine(pView, "{%d:%d}%s", + pExpr->iTable, pExpr->iColumn, zFlgs); + } ++ if( ExprHasProperty(pExpr, EP_FixedCol) ){ ++ sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); ++ } + break; + } + case TK_INTEGER: { +@@ -27000,6 +28755,11 @@ + sqlite3TreeViewLine(pView,"NULL"); + break; + } ++ case TK_TRUEFALSE: { ++ sqlite3TreeViewLine(pView, ++ sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE"); ++ break; ++ } + #ifndef SQLITE_OMIT_BLOB_LITERAL + case TK_BLOB: { + sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken); +@@ -27056,6 +28816,19 @@ + case TK_ISNULL: zUniOp = "ISNULL"; break; + case TK_NOTNULL: zUniOp = "NOTNULL"; break; + ++ case TK_TRUTH: { ++ int x; ++ const char *azOp[] = { ++ "IS-FALSE", "IS-TRUE", "IS-NOT-FALSE", "IS-NOT-TRUE" ++ }; ++ assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT ); ++ assert( pExpr->pRight ); ++ assert( pExpr->pRight->op==TK_TRUEFALSE ); ++ x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight); ++ zUniOp = azOp[x]; ++ break; ++ } ++ + case TK_SPAN: { + sqlite3TreeViewLine(pView, "SPAN %Q", pExpr->u.zToken); + sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); +@@ -27071,10 +28844,17 @@ + case TK_AGG_FUNCTION: + case TK_FUNCTION: { + ExprList *pFarg; /* List of function arguments */ ++ Window *pWin; + if( ExprHasProperty(pExpr, EP_TokenOnly) ){ + pFarg = 0; ++ pWin = 0; + }else{ + pFarg = pExpr->x.pList; ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ pWin = pExpr->y.pWin; ++#else ++ pWin = 0; ++#endif + } + if( pExpr->op==TK_AGG_FUNCTION ){ + sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q", +@@ -27083,8 +28863,13 @@ + sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken); + } + if( pFarg ){ +- sqlite3TreeViewExprList(pView, pFarg, 0, 0); ++ sqlite3TreeViewExprList(pView, pFarg, pWin!=0, 0); + } ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( pWin ){ ++ sqlite3TreeViewWindow(pView, pWin, 0); ++ } ++#endif + break; + } + #ifndef SQLITE_OMIT_SUBQUERY +@@ -27215,12 +29000,25 @@ + sqlite3TreeViewLine(pView, "%s", zLabel); + for(i=0; i<pList->nExpr; i++){ + int j = pList->a[i].u.x.iOrderByCol; +- if( j ){ +- sqlite3TreeViewPush(pView, 0); +- sqlite3TreeViewLine(pView, "iOrderByCol=%d", j); ++ char *zName = pList->a[i].zName; ++ int moreToFollow = i<pList->nExpr - 1; ++ if( j || zName ){ ++ sqlite3TreeViewPush(pView, moreToFollow); ++ moreToFollow = 0; ++ sqlite3TreeViewLine(pView, 0); ++ if( zName ){ ++ fprintf(stdout, "AS %s ", zName); ++ } ++ if( j ){ ++ fprintf(stdout, "iOrderByCol=%d", j); ++ } ++ fprintf(stdout, "\n"); ++ fflush(stdout); + } +- sqlite3TreeViewExpr(pView, pList->a[i].pExpr, i<pList->nExpr-1); +- if( j ) sqlite3TreeViewPop(pView); ++ sqlite3TreeViewExpr(pView, pList->a[i].pExpr, moreToFollow); ++ if( j || zName ){ ++ sqlite3TreeViewPop(pView); ++ } + } + } + } +@@ -28511,6 +30309,45 @@ + } + + /* ++** Compute 10 to the E-th power. Examples: E==1 results in 10. ++** E==2 results in 100. E==50 results in 1.0e50. ++** ++** This routine only works for values of E between 1 and 341. ++*/ ++static LONGDOUBLE_TYPE sqlite3Pow10(int E){ ++#if defined(_MSC_VER) ++ static const LONGDOUBLE_TYPE x[] = { ++ 1.0e+001, ++ 1.0e+002, ++ 1.0e+004, ++ 1.0e+008, ++ 1.0e+016, ++ 1.0e+032, ++ 1.0e+064, ++ 1.0e+128, ++ 1.0e+256 ++ }; ++ LONGDOUBLE_TYPE r = 1.0; ++ int i; ++ assert( E>=0 && E<=307 ); ++ for(i=0; E!=0; i++, E >>=1){ ++ if( E & 1 ) r *= x[i]; ++ } ++ return r; ++#else ++ LONGDOUBLE_TYPE x = 10.0; ++ LONGDOUBLE_TYPE r = 1.0; ++ while(1){ ++ if( E & 1 ) r *= x; ++ E >>= 1; ++ if( E==0 ) break; ++ x *= x; ++ } ++ return r; ++#endif ++} ++ ++/* + ** The string z[] is an text representation of a real number. + ** Convert this string to a double and write it into *pResult. + ** +@@ -28577,12 +30414,12 @@ + /* copy max significant digits to significand */ + while( z<zEnd && sqlite3Isdigit(*z) && s<((LARGEST_INT64-9)/10) ){ + s = s*10 + (*z - '0'); +- z+=incr, nDigits++; ++ z+=incr; nDigits++; + } + + /* skip non-significant significand digits + ** (increase exponent by d to shift decimal left) */ +- while( z<zEnd && sqlite3Isdigit(*z) ) z+=incr, nDigits++, d++; ++ while( z<zEnd && sqlite3Isdigit(*z) ){ z+=incr; nDigits++; d++; } + if( z>=zEnd ) goto do_atof_calc; + + /* if decimal point is present */ +@@ -28595,7 +30432,7 @@ + s = s*10 + (*z - '0'); + d--; + } +- z+=incr, nDigits++; ++ z+=incr; nDigits++; + } + } + if( z>=zEnd ) goto do_atof_calc; +@@ -28665,11 +30502,10 @@ + if( e==0 ){ /*OPTIMIZATION-IF-TRUE*/ + result = (double)s; + }else{ +- LONGDOUBLE_TYPE scale = 1.0; + /* attempt to handle extremely small/large numbers better */ + if( e>307 ){ /*OPTIMIZATION-IF-TRUE*/ + if( e<342 ){ /*OPTIMIZATION-IF-TRUE*/ +- while( e%308 ) { scale *= 1.0e+1; e -= 1; } ++ LONGDOUBLE_TYPE scale = sqlite3Pow10(e-308); + if( esign<0 ){ + result = s / scale; + result /= 1.0e+308; +@@ -28681,14 +30517,15 @@ + if( esign<0 ){ + result = 0.0*s; + }else{ ++#ifdef INFINITY ++ result = INFINITY*s; ++#else + result = 1e308*1e308*s; /* Infinity */ ++#endif + } + } + }else{ +- /* 1.0e+22 is the largest power of 10 than can be +- ** represented exactly. */ +- while( e%22 ) { scale *= 1.0e+1; e -= 1; } +- while( e>0 ) { scale *= 1.0e+22; e -= 22; } ++ LONGDOUBLE_TYPE scale = sqlite3Pow10(e); + if( esign<0 ){ + result = s / scale; + }else{ +@@ -28743,17 +30580,13 @@ + ** Convert zNum to a 64-bit signed integer. zNum must be decimal. This + ** routine does *not* accept hexadecimal notation. + ** +-** If the zNum value is representable as a 64-bit twos-complement +-** integer, then write that value into *pNum and return 0. ++** Returns: + ** +-** If zNum is exactly 9223372036854775808, return 2. This special +-** case is broken out because while 9223372036854775808 cannot be a +-** signed 64-bit integer, its negative -9223372036854775808 can be. ++** 0 Successful transformation. Fits in a 64-bit signed integer. ++** 1 Excess non-space text after the integer value ++** 2 Integer too large for a 64-bit signed integer or is malformed ++** 3 Special case of 9223372036854775808 + ** +-** If zNum is too big for a 64-bit integer and is not +-** 9223372036854775808 or if zNum contains any non-numeric text, +-** then return 1. +-** + ** length is the number of bytes in the string (bytes, not characters). + ** The string is not necessarily zero-terminated. The encoding is + ** given by enc. +@@ -28765,6 +30598,7 @@ + int i; + int c = 0; + int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */ ++ int rc; /* Baseline return code */ + const char *zStart; + const char *zEnd = zNum + length; + assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); +@@ -28792,7 +30626,14 @@ + for(i=0; &zNum[i]<zEnd && (c=zNum[i])>='0' && c<='9'; i+=incr){ + u = u*10 + c - '0'; + } ++ testcase( i==18*incr ); ++ testcase( i==19*incr ); ++ testcase( i==20*incr ); + if( u>LARGEST_INT64 ){ ++ /* This test and assignment is needed only to suppress UB warnings ++ ** from clang and -fsanitize=undefined. This test and assignment make ++ ** the code a little larger and slower, and no harm comes from omitting ++ ** them, but we must appaise the undefined-behavior pharisees. */ + *pNum = neg ? SMALLEST_INT64 : LARGEST_INT64; + }else if( neg ){ + *pNum = -(i64)u; +@@ -28799,36 +30640,43 @@ + }else{ + *pNum = (i64)u; + } +- testcase( i==18 ); +- testcase( i==19 ); +- testcase( i==20 ); +- if( &zNum[i]<zEnd /* Extra bytes at the end */ +- || (i==0 && zStart==zNum) /* No digits */ +- || i>19*incr /* Too many digits */ ++ rc = 0; ++ if( (i==0 && zStart==zNum) /* No digits */ + || nonNum /* UTF16 with high-order bytes non-zero */ + ){ +- /* zNum is empty or contains non-numeric text or is longer +- ** than 19 digits (thus guaranteeing that it is too large) */ +- return 1; +- }else if( i<19*incr ){ ++ rc = 1; ++ }else if( &zNum[i]<zEnd ){ /* Extra bytes at the end */ ++ int jj = i; ++ do{ ++ if( !sqlite3Isspace(zNum[jj]) ){ ++ rc = 1; /* Extra non-space text after the integer */ ++ break; ++ } ++ jj += incr; ++ }while( &zNum[jj]<zEnd ); ++ } ++ if( i<19*incr ){ + /* Less than 19 digits, so we know that it fits in 64 bits */ + assert( u<=LARGEST_INT64 ); +- return 0; ++ return rc; + }else{ + /* zNum is a 19-digit numbers. Compare it against 9223372036854775808. */ +- c = compare2pow63(zNum, incr); ++ c = i>19*incr ? 1 : compare2pow63(zNum, incr); + if( c<0 ){ + /* zNum is less than 9223372036854775808 so it fits */ + assert( u<=LARGEST_INT64 ); +- return 0; +- }else if( c>0 ){ +- /* zNum is greater than 9223372036854775808 so it overflows */ +- return 1; ++ return rc; + }else{ +- /* zNum is exactly 9223372036854775808. Fits if negative. The +- ** special case 2 overflow if positive */ +- assert( u-1==LARGEST_INT64 ); +- return neg ? 0 : 2; ++ *pNum = neg ? SMALLEST_INT64 : LARGEST_INT64; ++ if( c>0 ){ ++ /* zNum is greater than 9223372036854775808 so it overflows */ ++ return 2; ++ }else{ ++ /* zNum is exactly 9223372036854775808. Fits if negative. The ++ ** special case 2 overflow if positive */ ++ assert( u-1==LARGEST_INT64 ); ++ return neg ? rc : 3; ++ } + } + } + } +@@ -28841,8 +30689,9 @@ + ** Returns: + ** + ** 0 Successful transformation. Fits in a 64-bit signed integer. +-** 1 Integer too large for a 64-bit signed integer or is malformed +-** 2 Special case of 9223372036854775808 ++** 1 Excess text after the integer value ++** 2 Integer too large for a 64-bit signed integer or is malformed ++** 3 Special case of 9223372036854775808 + */ + SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char *z, i64 *pOut){ + #ifndef SQLITE_OMIT_HEX_INTEGER +@@ -28856,7 +30705,7 @@ + u = u*16 + sqlite3HexToInt(z[k]); + } + memcpy(pOut, &u, 8); +- return (z[k]==0 && k-i<=16) ? 0 : 1; ++ return (z[k]==0 && k-i<=16) ? 0 : 2; + }else + #endif /* SQLITE_OMIT_HEX_INTEGER */ + { +@@ -29466,7 +31315,7 @@ + ** overflow, leave *pA unchanged and return 1. + */ + SQLITE_PRIVATE int sqlite3AddInt64(i64 *pA, i64 iB){ +-#if GCC_VERSION>=5004000 ++#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER) + return __builtin_add_overflow(*pA, iB, pA); + #else + i64 iA = *pA; +@@ -29486,7 +31335,7 @@ + #endif + } + SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){ +-#if GCC_VERSION>=5004000 ++#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER) + return __builtin_sub_overflow(*pA, iB, pA); + #else + testcase( iB==SMALLEST_INT64+1 ); +@@ -29501,7 +31350,7 @@ + #endif + } + SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){ +-#if GCC_VERSION>=5004000 ++#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER) + return __builtin_mul_overflow(*pA, iB, pA); + #else + i64 iA = *pA; +@@ -29603,8 +31452,14 @@ + if( x<2 ) return 0; + while( x<8 ){ y -= 10; x <<= 1; } + }else{ ++#if GCC_VERSION>=5004000 ++ int i = 60 - __builtin_clzll(x); ++ y += i*10; ++ x >>= i; ++#else + while( x>255 ){ y += 40; x >>= 4; } /*OPTIMIZATION-IF-TRUE*/ + while( x>15 ){ y += 10; x >>= 1; } ++#endif + } + return a[x&7] + y - 10; + } +@@ -29824,6 +31679,20 @@ + } + return h; + } ++#ifdef SQLITE_ENABLE_NORMALIZE ++static unsigned int strHashN(const char *z, int n){ ++ unsigned int h = 0; ++ int i; ++ for(i=0; i<n; i++){ ++ /* Knuth multiplicative hashing. (Sorting & Searching, p. 510). ++ ** 0x9e3779b1 is 2654435761 which is the closest prime number to ++ ** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2. */ ++ h += sqlite3UpperToLower[z[i]]; ++ h *= 0x9e3779b1; ++ } ++ return h; ++} ++#endif /* SQLITE_ENABLE_NORMALIZE */ + + + /* Link pNew element into the hash table pH. If pEntry!=0 then also +@@ -29935,7 +31804,41 @@ + } + return &nullElement; + } ++#ifdef SQLITE_ENABLE_NORMALIZE ++static HashElem *findElementWithHashN( ++ const Hash *pH, /* The pH to be searched */ ++ const char *pKey, /* The key we are searching for */ ++ int nKey, /* Number of key bytes to use */ ++ unsigned int *pHash /* Write the hash value here */ ++){ ++ HashElem *elem; /* Used to loop thru the element list */ ++ int count; /* Number of elements left to test */ ++ unsigned int h; /* The computed hash */ ++ static HashElem nullElement = { 0, 0, 0, 0 }; + ++ if( pH->ht ){ /*OPTIMIZATION-IF-TRUE*/ ++ struct _ht *pEntry; ++ h = strHashN(pKey, nKey) % pH->htsize; ++ pEntry = &pH->ht[h]; ++ elem = pEntry->chain; ++ count = pEntry->count; ++ }else{ ++ h = 0; ++ elem = pH->first; ++ count = pH->count; ++ } ++ if( pHash ) *pHash = h; ++ while( count-- ){ ++ assert( elem!=0 ); ++ if( sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){ ++ return elem; ++ } ++ elem = elem->next; ++ } ++ return &nullElement; ++} ++#endif /* SQLITE_ENABLE_NORMALIZE */ ++ + /* Remove a single entry from the hash table given a pointer to that + ** element and a hash on the element's key. + */ +@@ -29979,6 +31882,14 @@ + assert( pKey!=0 ); + return findElementWithHash(pH, pKey, 0)->data; + } ++#ifdef SQLITE_ENABLE_NORMALIZE ++SQLITE_PRIVATE void *sqlite3HashFindN(const Hash *pH, const char *pKey, int nKey){ ++ assert( pH!=0 ); ++ assert( pKey!=0 ); ++ assert( nKey>=0 ); ++ return findElementWithHashN(pH, pKey, nKey, 0)->data; ++} ++#endif /* SQLITE_ENABLE_NORMALIZE */ + + /* Insert an element into the hash table pH. The key is pKey + ** and the data is "data". +@@ -30046,170 +31957,176 @@ + /* 1 */ "AutoCommit" OpHelp(""), + /* 2 */ "Transaction" OpHelp(""), + /* 3 */ "SorterNext" OpHelp(""), +- /* 4 */ "PrevIfOpen" OpHelp(""), +- /* 5 */ "NextIfOpen" OpHelp(""), +- /* 6 */ "Prev" OpHelp(""), +- /* 7 */ "Next" OpHelp(""), +- /* 8 */ "Checkpoint" OpHelp(""), +- /* 9 */ "JournalMode" OpHelp(""), +- /* 10 */ "Vacuum" OpHelp(""), +- /* 11 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"), +- /* 12 */ "VUpdate" OpHelp("data=r[P3@P2]"), +- /* 13 */ "Goto" OpHelp(""), +- /* 14 */ "Gosub" OpHelp(""), +- /* 15 */ "InitCoroutine" OpHelp(""), +- /* 16 */ "Yield" OpHelp(""), +- /* 17 */ "MustBeInt" OpHelp(""), +- /* 18 */ "Jump" OpHelp(""), ++ /* 4 */ "Prev" OpHelp(""), ++ /* 5 */ "Next" OpHelp(""), ++ /* 6 */ "Checkpoint" OpHelp(""), ++ /* 7 */ "JournalMode" OpHelp(""), ++ /* 8 */ "Vacuum" OpHelp(""), ++ /* 9 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"), ++ /* 10 */ "VUpdate" OpHelp("data=r[P3@P2]"), ++ /* 11 */ "Goto" OpHelp(""), ++ /* 12 */ "Gosub" OpHelp(""), ++ /* 13 */ "InitCoroutine" OpHelp(""), ++ /* 14 */ "Yield" OpHelp(""), ++ /* 15 */ "MustBeInt" OpHelp(""), ++ /* 16 */ "Jump" OpHelp(""), ++ /* 17 */ "Once" OpHelp(""), ++ /* 18 */ "If" OpHelp(""), + /* 19 */ "Not" OpHelp("r[P2]= !r[P1]"), +- /* 20 */ "Once" OpHelp(""), +- /* 21 */ "If" OpHelp(""), +- /* 22 */ "IfNot" OpHelp(""), +- /* 23 */ "IfNullRow" OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"), +- /* 24 */ "SeekLT" OpHelp("key=r[P3@P4]"), +- /* 25 */ "SeekLE" OpHelp("key=r[P3@P4]"), +- /* 26 */ "SeekGE" OpHelp("key=r[P3@P4]"), +- /* 27 */ "SeekGT" OpHelp("key=r[P3@P4]"), +- /* 28 */ "NoConflict" OpHelp("key=r[P3@P4]"), +- /* 29 */ "NotFound" OpHelp("key=r[P3@P4]"), +- /* 30 */ "Found" OpHelp("key=r[P3@P4]"), +- /* 31 */ "SeekRowid" OpHelp("intkey=r[P3]"), +- /* 32 */ "NotExists" OpHelp("intkey=r[P3]"), +- /* 33 */ "Last" OpHelp(""), +- /* 34 */ "IfSmaller" OpHelp(""), +- /* 35 */ "SorterSort" OpHelp(""), +- /* 36 */ "Sort" OpHelp(""), +- /* 37 */ "Rewind" OpHelp(""), +- /* 38 */ "IdxLE" OpHelp("key=r[P3@P4]"), +- /* 39 */ "IdxGT" OpHelp("key=r[P3@P4]"), +- /* 40 */ "IdxLT" OpHelp("key=r[P3@P4]"), +- /* 41 */ "IdxGE" OpHelp("key=r[P3@P4]"), +- /* 42 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), +- /* 43 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), +- /* 44 */ "Program" OpHelp(""), +- /* 45 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), +- /* 46 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), +- /* 47 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"), +- /* 48 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), +- /* 49 */ "IncrVacuum" OpHelp(""), +- /* 50 */ "VNext" OpHelp(""), +- /* 51 */ "Init" OpHelp("Start at P2"), +- /* 52 */ "Return" OpHelp(""), +- /* 53 */ "EndCoroutine" OpHelp(""), +- /* 54 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), +- /* 55 */ "Halt" OpHelp(""), +- /* 56 */ "Integer" OpHelp("r[P2]=P1"), +- /* 57 */ "Int64" OpHelp("r[P2]=P4"), +- /* 58 */ "String" OpHelp("r[P2]='P4' (len=P1)"), +- /* 59 */ "Null" OpHelp("r[P2..P3]=NULL"), +- /* 60 */ "SoftNull" OpHelp("r[P1]=NULL"), +- /* 61 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), +- /* 62 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), +- /* 63 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), +- /* 64 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), +- /* 65 */ "SCopy" OpHelp("r[P2]=r[P1]"), +- /* 66 */ "IntCopy" OpHelp("r[P2]=r[P1]"), +- /* 67 */ "ResultRow" OpHelp("output=r[P1@P2]"), +- /* 68 */ "CollSeq" OpHelp(""), +- /* 69 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), +- /* 70 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"), +- /* 71 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"), +- /* 72 */ "RealAffinity" OpHelp(""), +- /* 73 */ "Cast" OpHelp("affinity(r[P1])"), +- /* 74 */ "Permutation" OpHelp(""), +- /* 75 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"), +- /* 76 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"), +- /* 77 */ "Ne" OpHelp("IF r[P3]!=r[P1]"), +- /* 78 */ "Eq" OpHelp("IF r[P3]==r[P1]"), +- /* 79 */ "Gt" OpHelp("IF r[P3]>r[P1]"), +- /* 80 */ "Le" OpHelp("IF r[P3]<=r[P1]"), +- /* 81 */ "Lt" OpHelp("IF r[P3]<r[P1]"), +- /* 82 */ "Ge" OpHelp("IF r[P3]>=r[P1]"), +- /* 83 */ "ElseNotEq" OpHelp(""), +- /* 84 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), +- /* 85 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), +- /* 86 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"), +- /* 87 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"), +- /* 88 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"), +- /* 89 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"), +- /* 90 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"), +- /* 91 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), +- /* 92 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), +- /* 93 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), +- /* 94 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), +- /* 95 */ "BitNot" OpHelp("r[P1]= ~r[P1]"), +- /* 96 */ "Column" OpHelp("r[P3]=PX"), +- /* 97 */ "String8" OpHelp("r[P2]='P4'"), +- /* 98 */ "Affinity" OpHelp("affinity(r[P1@P2])"), +- /* 99 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), +- /* 100 */ "Count" OpHelp("r[P2]=count()"), +- /* 101 */ "ReadCookie" OpHelp(""), +- /* 102 */ "SetCookie" OpHelp(""), +- /* 103 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), +- /* 104 */ "OpenRead" OpHelp("root=P2 iDb=P3"), +- /* 105 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), +- /* 106 */ "OpenDup" OpHelp(""), +- /* 107 */ "OpenAutoindex" OpHelp("nColumn=P2"), +- /* 108 */ "OpenEphemeral" OpHelp("nColumn=P2"), +- /* 109 */ "SorterOpen" OpHelp(""), +- /* 110 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), +- /* 111 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), +- /* 112 */ "Close" OpHelp(""), +- /* 113 */ "ColumnsUsed" OpHelp(""), +- /* 114 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), +- /* 115 */ "NewRowid" OpHelp("r[P2]=rowid"), +- /* 116 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), +- /* 117 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), +- /* 118 */ "Delete" OpHelp(""), +- /* 119 */ "ResetCount" OpHelp(""), +- /* 120 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), +- /* 121 */ "SorterData" OpHelp("r[P2]=data"), +- /* 122 */ "RowData" OpHelp("r[P2]=data"), +- /* 123 */ "Rowid" OpHelp("r[P2]=rowid"), +- /* 124 */ "NullRow" OpHelp(""), +- /* 125 */ "SorterInsert" OpHelp("key=r[P2]"), +- /* 126 */ "IdxInsert" OpHelp("key=r[P2]"), +- /* 127 */ "IdxDelete" OpHelp("key=r[P2@P3]"), +- /* 128 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"), +- /* 129 */ "IdxRowid" OpHelp("r[P2]=rowid"), +- /* 130 */ "Destroy" OpHelp(""), +- /* 131 */ "Clear" OpHelp(""), +- /* 132 */ "Real" OpHelp("r[P2]=P4"), +- /* 133 */ "ResetSorter" OpHelp(""), +- /* 134 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"), +- /* 135 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"), +- /* 136 */ "SqlExec" OpHelp(""), +- /* 137 */ "ParseSchema" OpHelp(""), +- /* 138 */ "LoadAnalysis" OpHelp(""), +- /* 139 */ "DropTable" OpHelp(""), +- /* 140 */ "DropIndex" OpHelp(""), +- /* 141 */ "DropTrigger" OpHelp(""), +- /* 142 */ "IntegrityCk" OpHelp(""), +- /* 143 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), +- /* 144 */ "Param" OpHelp(""), +- /* 145 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), +- /* 146 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), +- /* 147 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), +- /* 148 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"), +- /* 149 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), +- /* 150 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), +- /* 151 */ "Expire" OpHelp(""), +- /* 152 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), +- /* 153 */ "VBegin" OpHelp(""), +- /* 154 */ "VCreate" OpHelp(""), +- /* 155 */ "VDestroy" OpHelp(""), +- /* 156 */ "VOpen" OpHelp(""), +- /* 157 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), +- /* 158 */ "VRename" OpHelp(""), +- /* 159 */ "Pagecount" OpHelp(""), +- /* 160 */ "MaxPgcnt" OpHelp(""), +- /* 161 */ "PureFunc0" OpHelp(""), +- /* 162 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), +- /* 163 */ "PureFunc" OpHelp(""), +- /* 164 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), +- /* 165 */ "CursorHint" OpHelp(""), +- /* 166 */ "Noop" OpHelp(""), +- /* 167 */ "Explain" OpHelp(""), ++ /* 20 */ "IfNot" OpHelp(""), ++ /* 21 */ "IfNullRow" OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"), ++ /* 22 */ "SeekLT" OpHelp("key=r[P3@P4]"), ++ /* 23 */ "SeekLE" OpHelp("key=r[P3@P4]"), ++ /* 24 */ "SeekGE" OpHelp("key=r[P3@P4]"), ++ /* 25 */ "SeekGT" OpHelp("key=r[P3@P4]"), ++ /* 26 */ "IfNoHope" OpHelp("key=r[P3@P4]"), ++ /* 27 */ "NoConflict" OpHelp("key=r[P3@P4]"), ++ /* 28 */ "NotFound" OpHelp("key=r[P3@P4]"), ++ /* 29 */ "Found" OpHelp("key=r[P3@P4]"), ++ /* 30 */ "SeekRowid" OpHelp("intkey=r[P3]"), ++ /* 31 */ "NotExists" OpHelp("intkey=r[P3]"), ++ /* 32 */ "Last" OpHelp(""), ++ /* 33 */ "IfSmaller" OpHelp(""), ++ /* 34 */ "SorterSort" OpHelp(""), ++ /* 35 */ "Sort" OpHelp(""), ++ /* 36 */ "Rewind" OpHelp(""), ++ /* 37 */ "IdxLE" OpHelp("key=r[P3@P4]"), ++ /* 38 */ "IdxGT" OpHelp("key=r[P3@P4]"), ++ /* 39 */ "IdxLT" OpHelp("key=r[P3@P4]"), ++ /* 40 */ "IdxGE" OpHelp("key=r[P3@P4]"), ++ /* 41 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), ++ /* 42 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), ++ /* 43 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"), ++ /* 44 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"), ++ /* 45 */ "Program" OpHelp(""), ++ /* 46 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), ++ /* 47 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), ++ /* 48 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"), ++ /* 49 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), ++ /* 50 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"), ++ /* 51 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"), ++ /* 52 */ "Ne" OpHelp("IF r[P3]!=r[P1]"), ++ /* 53 */ "Eq" OpHelp("IF r[P3]==r[P1]"), ++ /* 54 */ "Gt" OpHelp("IF r[P3]>r[P1]"), ++ /* 55 */ "Le" OpHelp("IF r[P3]<=r[P1]"), ++ /* 56 */ "Lt" OpHelp("IF r[P3]<r[P1]"), ++ /* 57 */ "Ge" OpHelp("IF r[P3]>=r[P1]"), ++ /* 58 */ "ElseNotEq" OpHelp(""), ++ /* 59 */ "IncrVacuum" OpHelp(""), ++ /* 60 */ "VNext" OpHelp(""), ++ /* 61 */ "Init" OpHelp("Start at P2"), ++ /* 62 */ "PureFunc0" OpHelp(""), ++ /* 63 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), ++ /* 64 */ "PureFunc" OpHelp(""), ++ /* 65 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), ++ /* 66 */ "Return" OpHelp(""), ++ /* 67 */ "EndCoroutine" OpHelp(""), ++ /* 68 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), ++ /* 69 */ "Halt" OpHelp(""), ++ /* 70 */ "Integer" OpHelp("r[P2]=P1"), ++ /* 71 */ "Int64" OpHelp("r[P2]=P4"), ++ /* 72 */ "String" OpHelp("r[P2]='P4' (len=P1)"), ++ /* 73 */ "Null" OpHelp("r[P2..P3]=NULL"), ++ /* 74 */ "SoftNull" OpHelp("r[P1]=NULL"), ++ /* 75 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), ++ /* 76 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), ++ /* 77 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), ++ /* 78 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), ++ /* 79 */ "SCopy" OpHelp("r[P2]=r[P1]"), ++ /* 80 */ "IntCopy" OpHelp("r[P2]=r[P1]"), ++ /* 81 */ "ResultRow" OpHelp("output=r[P1@P2]"), ++ /* 82 */ "CollSeq" OpHelp(""), ++ /* 83 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), ++ /* 84 */ "RealAffinity" OpHelp(""), ++ /* 85 */ "Cast" OpHelp("affinity(r[P1])"), ++ /* 86 */ "Permutation" OpHelp(""), ++ /* 87 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), ++ /* 88 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"), ++ /* 89 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"), ++ /* 90 */ "Column" OpHelp("r[P3]=PX"), ++ /* 91 */ "Affinity" OpHelp("affinity(r[P1@P2])"), ++ /* 92 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), ++ /* 93 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), ++ /* 94 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"), ++ /* 95 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"), ++ /* 96 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"), ++ /* 97 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"), ++ /* 98 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"), ++ /* 99 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), ++ /* 100 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), ++ /* 101 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), ++ /* 102 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), ++ /* 103 */ "BitNot" OpHelp("r[P2]= ~r[P1]"), ++ /* 104 */ "Count" OpHelp("r[P2]=count()"), ++ /* 105 */ "ReadCookie" OpHelp(""), ++ /* 106 */ "String8" OpHelp("r[P2]='P4'"), ++ /* 107 */ "SetCookie" OpHelp(""), ++ /* 108 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), ++ /* 109 */ "OpenRead" OpHelp("root=P2 iDb=P3"), ++ /* 110 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), ++ /* 111 */ "OpenDup" OpHelp(""), ++ /* 112 */ "OpenAutoindex" OpHelp("nColumn=P2"), ++ /* 113 */ "OpenEphemeral" OpHelp("nColumn=P2"), ++ /* 114 */ "SorterOpen" OpHelp(""), ++ /* 115 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), ++ /* 116 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), ++ /* 117 */ "Close" OpHelp(""), ++ /* 118 */ "ColumnsUsed" OpHelp(""), ++ /* 119 */ "SeekHit" OpHelp("seekHit=P2"), ++ /* 120 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), ++ /* 121 */ "NewRowid" OpHelp("r[P2]=rowid"), ++ /* 122 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), ++ /* 123 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), ++ /* 124 */ "Delete" OpHelp(""), ++ /* 125 */ "ResetCount" OpHelp(""), ++ /* 126 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), ++ /* 127 */ "SorterData" OpHelp("r[P2]=data"), ++ /* 128 */ "RowData" OpHelp("r[P2]=data"), ++ /* 129 */ "Rowid" OpHelp("r[P2]=rowid"), ++ /* 130 */ "NullRow" OpHelp(""), ++ /* 131 */ "SeekEnd" OpHelp(""), ++ /* 132 */ "SorterInsert" OpHelp("key=r[P2]"), ++ /* 133 */ "IdxInsert" OpHelp("key=r[P2]"), ++ /* 134 */ "IdxDelete" OpHelp("key=r[P2@P3]"), ++ /* 135 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"), ++ /* 136 */ "IdxRowid" OpHelp("r[P2]=rowid"), ++ /* 137 */ "Destroy" OpHelp(""), ++ /* 138 */ "Clear" OpHelp(""), ++ /* 139 */ "ResetSorter" OpHelp(""), ++ /* 140 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"), ++ /* 141 */ "Real" OpHelp("r[P2]=P4"), ++ /* 142 */ "SqlExec" OpHelp(""), ++ /* 143 */ "ParseSchema" OpHelp(""), ++ /* 144 */ "LoadAnalysis" OpHelp(""), ++ /* 145 */ "DropTable" OpHelp(""), ++ /* 146 */ "DropIndex" OpHelp(""), ++ /* 147 */ "DropTrigger" OpHelp(""), ++ /* 148 */ "IntegrityCk" OpHelp(""), ++ /* 149 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), ++ /* 150 */ "Param" OpHelp(""), ++ /* 151 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), ++ /* 152 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), ++ /* 153 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), ++ /* 154 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"), ++ /* 155 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), ++ /* 156 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"), ++ /* 157 */ "AggValue" OpHelp("r[P3]=value N=P2"), ++ /* 158 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), ++ /* 159 */ "Expire" OpHelp(""), ++ /* 160 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), ++ /* 161 */ "VBegin" OpHelp(""), ++ /* 162 */ "VCreate" OpHelp(""), ++ /* 163 */ "VDestroy" OpHelp(""), ++ /* 164 */ "VOpen" OpHelp(""), ++ /* 165 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), ++ /* 166 */ "VRename" OpHelp(""), ++ /* 167 */ "Pagecount" OpHelp(""), ++ /* 168 */ "MaxPgcnt" OpHelp(""), ++ /* 169 */ "Trace" OpHelp(""), ++ /* 170 */ "CursorHint" OpHelp(""), ++ /* 171 */ "Noop" OpHelp(""), ++ /* 172 */ "Explain" OpHelp(""), ++ /* 173 */ "Abortable" OpHelp(""), + }; + return azName[i]; + } +@@ -30309,6 +32226,7 @@ + #include <sys/types.h> + #include <sys/stat.h> + #include <fcntl.h> ++#include <sys/ioctl.h> + #include <unistd.h> + /* #include <time.h> */ + #include <sys/time.h> +@@ -30318,7 +32236,7 @@ + #endif + + #if SQLITE_ENABLE_LOCKING_STYLE +-# include <sys/ioctl.h> ++/* # include <sys/ioctl.h> */ + # include <sys/file.h> + # include <sys/param.h> + #endif /* SQLITE_ENABLE_LOCKING_STYLE */ +@@ -30354,12 +32272,10 @@ + #define SQLITE_FSFLAGS_IS_MSDOS 0x1 + + /* +-** If we are to be thread-safe, include the pthreads header and define +-** the SQLITE_UNIX_THREADS macro. ++** If we are to be thread-safe, include the pthreads header. + */ + #if SQLITE_THREADSAFE + /* # include <pthread.h> */ +-# define SQLITE_UNIX_THREADS 1 + #endif + + /* +@@ -30428,7 +32344,7 @@ + unsigned short int ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */ + int lastErrno; /* The unix errno from last I/O error */ + void *lockingContext; /* Locking style specific state */ +- UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ ++ UnixUnusedFd *pPreallocatedUnused; /* Pre-allocated UnixUnusedFd */ + const char *zPath; /* Name of the file */ + unixShm *pShm; /* Shared memory segment information */ + int szChunk; /* Configured by FCNTL_CHUNK_SIZE */ +@@ -30439,10 +32355,8 @@ + sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */ + void *pMapRegion; /* Memory mapped region */ + #endif +-#ifdef __QNXNTO__ + int sectorSize; /* Device sector size */ + int deviceCharacteristics; /* Precomputed device characteristics */ +-#endif + #if SQLITE_ENABLE_LOCKING_STYLE + int openFlags; /* The flags specified at open() */ + #endif +@@ -30449,6 +32363,9 @@ + #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) + unsigned fsFlags; /* cached details from statfs() */ + #endif ++#ifdef SQLITE_ENABLE_SETLK_TIMEOUT ++ unsigned iBusyTimeout; /* Wait this many millisec on locks */ ++#endif + #if OS_VXWORKS + struct vxworksFileId *pId; /* Unique file ID */ + #endif +@@ -30745,7 +32662,21 @@ + # define lseek lseek64 + #endif + ++#ifdef __linux__ + /* ++** Linux-specific IOCTL magic numbers used for controlling F2FS ++*/ ++#define F2FS_IOCTL_MAGIC 0xf5 ++#define F2FS_IOC_START_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 1) ++#define F2FS_IOC_COMMIT_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 2) ++#define F2FS_IOC_START_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 3) ++#define F2FS_IOC_ABORT_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 5) ++#define F2FS_IOC_GET_FEATURES _IOR(F2FS_IOCTL_MAGIC, 12, u32) ++#define F2FS_FEATURE_ATOMIC_WRITE 0x0004 ++#endif /* __linux__ */ ++ ++ ++/* + ** Different Unix systems declare open() in different ways. Same use + ** open(const char*,int,mode_t). Others use open(const char*,int,...). + ** The difference is important when using a pointer to the function. +@@ -30872,7 +32803,11 @@ + #endif + #define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent) + ++#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 +@@ -30887,7 +32822,7 @@ + #else + { "munmap", (sqlite3_syscall_ptr)0, 0 }, + #endif +-#define osMunmap ((void*(*)(void*,size_t))aSyscall[23].pCurrent) ++#define osMunmap ((int(*)(void*,size_t))aSyscall[23].pCurrent) + + #if HAVE_MREMAP && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) + { "mremap", (sqlite3_syscall_ptr)mremap, 0 }, +@@ -30917,6 +32852,17 @@ + #endif + #define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent) + ++#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) ++# ifdef __ANDROID__ ++ { "ioctl", (sqlite3_syscall_ptr)(int(*)(int, int, ...))ioctl, 0 }, ++# else ++ { "ioctl", (sqlite3_syscall_ptr)ioctl, 0 }, ++# endif ++#else ++ { "ioctl", (sqlite3_syscall_ptr)0, 0 }, ++#endif ++#define osIoctl ((int(*)(int,int,...))aSyscall[28].pCurrent) ++ + }; /* End of the overrideable system calls */ + + +@@ -31092,16 +33038,30 @@ + ** unixEnterMutex() + ** assert( unixMutexHeld() ); + ** unixEnterLeave() ++** ++** To prevent deadlock, the global unixBigLock must must be acquired ++** before the unixInodeInfo.pLockMutex mutex, if both are held. It is ++** OK to get the pLockMutex without holding unixBigLock first, but if ++** that happens, the unixBigLock mutex must not be acquired until after ++** pLockMutex is released. ++** ++** OK: enter(unixBigLock), enter(pLockInfo) ++** OK: enter(unixBigLock) ++** OK: enter(pLockInfo) ++** ERROR: enter(pLockInfo), enter(unixBigLock) + */ ++static sqlite3_mutex *unixBigLock = 0; + static void unixEnterMutex(void){ +- sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); ++ assert( sqlite3_mutex_notheld(unixBigLock) ); /* Not a recursive mutex */ ++ sqlite3_mutex_enter(unixBigLock); + } + static void unixLeaveMutex(void){ +- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); ++ assert( sqlite3_mutex_held(unixBigLock) ); ++ sqlite3_mutex_leave(unixBigLock); + } + #ifdef SQLITE_DEBUG + static int unixMutexHeld(void) { +- return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); ++ return sqlite3_mutex_held(unixBigLock); + } + #endif + +@@ -31491,22 +33451,39 @@ + + /* + ** An instance of the following structure is allocated for each open +-** inode. Or, on LinuxThreads, there is one of these structures for +-** each inode opened by each thread. ++** inode. + ** + ** A single inode can have multiple file descriptors, so each unixFile + ** structure contains a pointer to an instance of this object and this + ** object keeps a count of the number of unixFile pointing to it. ++** ++** Mutex rules: ++** ++** (1) Only the pLockMutex mutex must be held in order to read or write ++** any of the locking fields: ++** nShared, nLock, eFileLock, bProcessLock, pUnused ++** ++** (2) When nRef>0, then the following fields are unchanging and can ++** be read (but not written) without holding any mutex: ++** fileId, pLockMutex ++** ++** (3) With the exceptions above, all the fields may only be read ++** or written while holding the global unixBigLock mutex. ++** ++** Deadlock prevention: The global unixBigLock mutex may not ++** be acquired while holding the pLockMutex mutex. If both unixBigLock ++** and pLockMutex are needed, then unixBigLock must be acquired first. + */ + struct unixInodeInfo { + struct unixFileId fileId; /* The lookup key */ +- int nShared; /* Number of SHARED locks held */ +- unsigned char eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ +- unsigned char bProcessLock; /* An exclusive process lock is held */ ++ sqlite3_mutex *pLockMutex; /* Hold this mutex for... */ ++ int nShared; /* Number of SHARED locks held */ ++ int nLock; /* Number of outstanding file locks */ ++ unsigned char eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ ++ unsigned char bProcessLock; /* An exclusive process lock is held */ ++ UnixUnusedFd *pUnused; /* Unused file descriptors to close */ + int nRef; /* Number of pointers to this structure */ + unixShmNode *pShmNode; /* Shared memory associated with this inode */ +- int nLock; /* Number of outstanding file locks */ +- UnixUnusedFd *pUnused; /* Unused file descriptors to close */ + unixInodeInfo *pNext; /* List of all unixInodeInfo objects */ + unixInodeInfo *pPrev; /* .... doubly linked */ + #if SQLITE_ENABLE_LOCKING_STYLE +@@ -31520,10 +33497,28 @@ + + /* + ** A lists of all unixInodeInfo objects. ++** ++** Must hold unixBigLock in order to read or write this variable. + */ +-static unixInodeInfo *inodeList = 0; ++static unixInodeInfo *inodeList = 0; /* All unixInodeInfo objects */ + ++#ifdef SQLITE_DEBUG + /* ++** True if the inode mutex (on the unixFile.pFileMutex field) is held, or not. ++** This routine is used only within assert() to help verify correct mutex ++** usage. ++*/ ++int unixFileMutexHeld(unixFile *pFile){ ++ assert( pFile->pInode ); ++ return sqlite3_mutex_held(pFile->pInode->pLockMutex); ++} ++int unixFileMutexNotheld(unixFile *pFile){ ++ assert( pFile->pInode ); ++ return sqlite3_mutex_notheld(pFile->pInode->pLockMutex); ++} ++#endif ++ ++/* + ** + ** This function - unixLogErrorAtLine(), is only ever called via the macro + ** unixLogError(). +@@ -31627,6 +33622,7 @@ + unixInodeInfo *pInode = pFile->pInode; + UnixUnusedFd *p; + UnixUnusedFd *pNext; ++ assert( unixFileMutexHeld(pFile) ); + for(p=pInode->pUnused; p; p=pNext){ + pNext = p->pNext; + robust_close(pFile, p->fd, __LINE__); +@@ -31638,17 +33634,20 @@ + /* + ** Release a unixInodeInfo structure previously allocated by findInodeInfo(). + ** +-** The mutex entered using the unixEnterMutex() function must be held +-** when this function is called. ++** The global mutex must be held when this routine is called, but the mutex ++** on the inode being deleted must NOT be held. + */ + static void releaseInodeInfo(unixFile *pFile){ + unixInodeInfo *pInode = pFile->pInode; + assert( unixMutexHeld() ); ++ assert( unixFileMutexNotheld(pFile) ); + if( ALWAYS(pInode) ){ + pInode->nRef--; + if( pInode->nRef==0 ){ + assert( pInode->pShmNode==0 ); ++ sqlite3_mutex_enter(pInode->pLockMutex); + closePendingFds(pFile); ++ sqlite3_mutex_leave(pInode->pLockMutex); + if( pInode->pPrev ){ + assert( pInode->pPrev->pNext==pInode ); + pInode->pPrev->pNext = pInode->pNext; +@@ -31660,6 +33659,7 @@ + assert( pInode->pNext->pPrev==pInode ); + pInode->pNext->pPrev = pInode->pPrev; + } ++ sqlite3_mutex_free(pInode->pLockMutex); + sqlite3_free(pInode); + } + } +@@ -31670,8 +33670,7 @@ + ** describes that file descriptor. Create a new one if necessary. The + ** return value might be uninitialized if an error occurs. + ** +-** The mutex entered using the unixEnterMutex() function must be held +-** when this function is called. ++** The global mutex must held when calling this routine. + ** + ** Return an appropriate error code. + */ +@@ -31732,6 +33731,7 @@ + #else + fileId.ino = (u64)statbuf.st_ino; + #endif ++ assert( unixMutexHeld() ); + pInode = inodeList; + while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){ + pInode = pInode->pNext; +@@ -31743,7 +33743,15 @@ + } + memset(pInode, 0, sizeof(*pInode)); + memcpy(&pInode->fileId, &fileId, sizeof(fileId)); ++ if( sqlite3GlobalConfig.bCoreMutex ){ ++ pInode->pLockMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); ++ if( pInode->pLockMutex==0 ){ ++ sqlite3_free(pInode); ++ return SQLITE_NOMEM_BKPT; ++ } ++ } + pInode->nRef = 1; ++ assert( unixMutexHeld() ); + pInode->pNext = inodeList; + pInode->pPrev = 0; + if( inodeList ) inodeList->pPrev = pInode; +@@ -31821,7 +33829,7 @@ + + assert( pFile ); + assert( pFile->eFileLock<=SHARED_LOCK ); +- unixEnterMutex(); /* Because pFile->pInode is shared across threads */ ++ sqlite3_mutex_enter(pFile->pInode->pLockMutex); + + /* Check if a thread in this process holds such a lock */ + if( pFile->pInode->eFileLock>SHARED_LOCK ){ +@@ -31846,7 +33854,7 @@ + } + #endif + +- unixLeaveMutex(); ++ sqlite3_mutex_leave(pFile->pInode->pLockMutex); + OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved)); + + *pResOut = reserved; +@@ -31854,6 +33862,43 @@ + } + + /* ++** Set a posix-advisory-lock. ++** ++** There are two versions of this routine. If compiled with ++** SQLITE_ENABLE_SETLK_TIMEOUT then the routine has an extra parameter ++** which is a pointer to a unixFile. If the unixFile->iBusyTimeout ++** value is set, then it is the number of milliseconds to wait before ++** failing the lock. The iBusyTimeout value is always reset back to ++** zero on each call. ++** ++** If SQLITE_ENABLE_SETLK_TIMEOUT is not defined, then do a non-blocking ++** attempt to set the lock. ++*/ ++#ifndef SQLITE_ENABLE_SETLK_TIMEOUT ++# define osSetPosixAdvisoryLock(h,x,t) osFcntl(h,F_SETLK,x) ++#else ++static int osSetPosixAdvisoryLock( ++ int h, /* The file descriptor on which to take the lock */ ++ struct flock *pLock, /* The description of the lock */ ++ unixFile *pFile /* Structure holding timeout value */ ++){ ++ int rc = osFcntl(h,F_SETLK,pLock); ++ while( rc<0 && pFile->iBusyTimeout>0 ){ ++ /* On systems that support some kind of blocking file lock with a timeout, ++ ** make appropriate changes here to invoke that blocking file lock. On ++ ** generic posix, however, there is no such API. So we simply try the ++ ** lock once every millisecond until either the timeout expires, or until ++ ** the lock is obtained. */ ++ usleep(1000); ++ rc = osFcntl(h,F_SETLK,pLock); ++ pFile->iBusyTimeout--; ++ } ++ return rc; ++} ++#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */ ++ ++ ++/* + ** Attempt to set a system-lock on the file pFile. The lock is + ** described by pLock. + ** +@@ -31875,8 +33920,8 @@ + static int unixFileLock(unixFile *pFile, struct flock *pLock){ + int rc; + unixInodeInfo *pInode = pFile->pInode; +- assert( unixMutexHeld() ); + assert( pInode!=0 ); ++ assert( sqlite3_mutex_held(pInode->pLockMutex) ); + if( (pFile->ctrlFlags & (UNIXFILE_EXCL|UNIXFILE_RDONLY))==UNIXFILE_EXCL ){ + if( pInode->bProcessLock==0 ){ + struct flock lock; +@@ -31885,7 +33930,7 @@ + lock.l_start = SHARED_FIRST; + lock.l_len = SHARED_SIZE; + lock.l_type = F_WRLCK; +- rc = osFcntl(pFile->h, F_SETLK, &lock); ++ rc = osSetPosixAdvisoryLock(pFile->h, &lock, pFile); + if( rc<0 ) return rc; + pInode->bProcessLock = 1; + pInode->nLock++; +@@ -31893,7 +33938,7 @@ + rc = 0; + } + }else{ +- rc = osFcntl(pFile->h, F_SETLK, pLock); ++ rc = osSetPosixAdvisoryLock(pFile->h, pLock, pFile); + } + return rc; + } +@@ -31995,8 +34040,8 @@ + + /* This mutex is needed because pFile->pInode is shared across threads + */ +- unixEnterMutex(); + pInode = pFile->pInode; ++ sqlite3_mutex_enter(pInode->pLockMutex); + + /* If some thread using this PID has a lock via a different unixFile* + ** handle that precludes the requested lock, return BUSY. +@@ -32139,7 +34184,7 @@ + } + + end_lock: +- unixLeaveMutex(); ++ sqlite3_mutex_leave(pInode->pLockMutex); + OSTRACE(("LOCK %d %s %s (unix)\n", pFile->h, azFileLock(eFileLock), + rc==SQLITE_OK ? "ok" : "failed")); + return rc; +@@ -32151,11 +34196,12 @@ + */ + static void setPendingFd(unixFile *pFile){ + unixInodeInfo *pInode = pFile->pInode; +- UnixUnusedFd *p = pFile->pUnused; ++ UnixUnusedFd *p = pFile->pPreallocatedUnused; ++ assert( unixFileMutexHeld(pFile) ); + p->pNext = pInode->pUnused; + pInode->pUnused = p; + pFile->h = -1; +- pFile->pUnused = 0; ++ pFile->pPreallocatedUnused = 0; + } + + /* +@@ -32186,8 +34232,8 @@ + if( pFile->eFileLock<=eFileLock ){ + return SQLITE_OK; + } +- unixEnterMutex(); + pInode = pFile->pInode; ++ sqlite3_mutex_enter(pInode->pLockMutex); + assert( pInode->nShared!=0 ); + if( pFile->eFileLock>SHARED_LOCK ){ + assert( pInode->eFileLock==pFile->eFileLock ); +@@ -32313,14 +34359,14 @@ + */ + pInode->nLock--; + assert( pInode->nLock>=0 ); +- if( pInode->nLock==0 ){ +- closePendingFds(pFile); +- } ++ if( pInode->nLock==0 ) closePendingFds(pFile); + } + + end_unlock: +- unixLeaveMutex(); +- if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock; ++ sqlite3_mutex_leave(pInode->pLockMutex); ++ if( rc==SQLITE_OK ){ ++ pFile->eFileLock = eFileLock; ++ } + return rc; + } + +@@ -32380,7 +34426,7 @@ + #endif + OSTRACE(("CLOSE %-3d\n", pFile->h)); + OpenCounter(-1); +- sqlite3_free(pFile->pUnused); ++ sqlite3_free(pFile->pPreallocatedUnused); + memset(pFile, 0, sizeof(unixFile)); + return SQLITE_OK; + } +@@ -32391,8 +34437,12 @@ + static int unixClose(sqlite3_file *id){ + int rc = SQLITE_OK; + unixFile *pFile = (unixFile *)id; ++ unixInodeInfo *pInode = pFile->pInode; ++ ++ assert( pInode!=0 ); + verifyDbFile(pFile); + unixUnlock(id, NO_LOCK); ++ assert( unixFileMutexNotheld(pFile) ); + unixEnterMutex(); + + /* unixFile.pInode is always valid here. Otherwise, a different close +@@ -32399,7 +34449,8 @@ + ** routine (e.g. nolockClose()) would be called instead. + */ + assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 ); +- if( ALWAYS(pFile->pInode) && pFile->pInode->nLock ){ ++ sqlite3_mutex_enter(pInode->pLockMutex); ++ if( pInode->nLock ){ + /* If there are outstanding locks, do not actually close the file just + ** yet because that would clear those locks. Instead, add the file + ** descriptor to pInode->pUnused list. It will be automatically closed +@@ -32407,6 +34458,7 @@ + */ + setPendingFd(pFile); + } ++ sqlite3_mutex_leave(pInode->pLockMutex); + releaseInodeInfo(pFile); + rc = closeUnixFile(id); + unixLeaveMutex(); +@@ -32717,7 +34769,7 @@ + OSTRACE(("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved)); + + #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS +- if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){ ++ if( (rc & 0xff) == SQLITE_IOERR ){ + rc = SQLITE_OK; + reserved=1; + } +@@ -32784,7 +34836,7 @@ + OSTRACE(("LOCK %d %s %s (flock)\n", pFile->h, azFileLock(eFileLock), + rc==SQLITE_OK ? "ok" : "failed")); + #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS +- if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){ ++ if( (rc & 0xff) == SQLITE_IOERR ){ + rc = SQLITE_BUSY; + } + #endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */ +@@ -33004,6 +35056,7 @@ + unixFile *pFile = (unixFile*)id; + semXUnlock(id, NO_LOCK); + assert( pFile ); ++ assert( unixFileMutexNotheld(pFile) ); + unixEnterMutex(); + releaseInodeInfo(pFile); + unixLeaveMutex(); +@@ -33118,8 +35171,7 @@ + *pResOut = 1; + return SQLITE_OK; + } +- unixEnterMutex(); /* Because pFile->pInode is shared across threads */ +- ++ sqlite3_mutex_enter(pFile->pInode->pLockMutex); + /* Check if a thread in this process holds such a lock */ + if( pFile->pInode->eFileLock>SHARED_LOCK ){ + reserved = 1; +@@ -33143,7 +35195,7 @@ + } + } + +- unixLeaveMutex(); ++ sqlite3_mutex_leave(pFile->pInode->pLockMutex); + OSTRACE(("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved)); + + *pResOut = reserved; +@@ -33206,8 +35258,8 @@ + + /* This mutex is needed because pFile->pInode is shared across threads + */ +- unixEnterMutex(); + pInode = pFile->pInode; ++ sqlite3_mutex_enter(pInode->pLockMutex); + + /* If some thread using this PID has a lock via a different unixFile* + ** handle that precludes the requested lock, return BUSY. +@@ -33321,7 +35373,7 @@ + /* Can't reestablish the shared lock. Sqlite can't deal, this is + ** a critical I/O error + */ +- rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 : ++ rc = ((failed & 0xff) == SQLITE_IOERR) ? failed2 : + SQLITE_IOERR_LOCK; + goto afp_end_lock; + } +@@ -33343,7 +35395,7 @@ + } + + afp_end_lock: +- unixLeaveMutex(); ++ sqlite3_mutex_leave(pInode->pLockMutex); + OSTRACE(("LOCK %d %s %s (afp)\n", pFile->h, azFileLock(eFileLock), + rc==SQLITE_OK ? "ok" : "failed")); + return rc; +@@ -33375,8 +35427,8 @@ + if( pFile->eFileLock<=eFileLock ){ + return SQLITE_OK; + } +- unixEnterMutex(); + pInode = pFile->pInode; ++ sqlite3_mutex_enter(pInode->pLockMutex); + assert( pInode->nShared!=0 ); + if( pFile->eFileLock>SHARED_LOCK ){ + assert( pInode->eFileLock==pFile->eFileLock ); +@@ -33445,14 +35497,14 @@ + if( rc==SQLITE_OK ){ + pInode->nLock--; + assert( pInode->nLock>=0 ); +- if( pInode->nLock==0 ){ +- closePendingFds(pFile); +- } ++ if( pInode->nLock==0 ) closePendingFds(pFile); + } + } + +- unixLeaveMutex(); +- if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock; ++ sqlite3_mutex_leave(pInode->pLockMutex); ++ if( rc==SQLITE_OK ){ ++ pFile->eFileLock = eFileLock; ++ } + return rc; + } + +@@ -33464,14 +35516,20 @@ + unixFile *pFile = (unixFile*)id; + assert( id!=0 ); + afpUnlock(id, NO_LOCK); ++ assert( unixFileMutexNotheld(pFile) ); + unixEnterMutex(); +- if( pFile->pInode && pFile->pInode->nLock ){ +- /* If there are outstanding locks, do not actually close the file just +- ** yet because that would clear those locks. Instead, add the file +- ** descriptor to pInode->aPending. It will be automatically closed when +- ** the last lock is cleared. +- */ +- setPendingFd(pFile); ++ if( pFile->pInode ){ ++ unixInodeInfo *pInode = pFile->pInode; ++ sqlite3_mutex_enter(pInode->pLockMutex); ++ if( pInode->nLock ){ ++ /* If there are outstanding locks, do not actually close the file just ++ ** yet because that would clear those locks. Instead, add the file ++ ** descriptor to pInode->aPending. It will be automatically closed when ++ ** the last lock is cleared. ++ */ ++ setPendingFd(pFile); ++ } ++ sqlite3_mutex_leave(pInode->pLockMutex); + } + releaseInodeInfo(pFile); + sqlite3_free(pFile->lockingContext); +@@ -33601,7 +35659,7 @@ + /* If this is a database file (not a journal, master-journal or temp + ** file), the bytes in the locking range should never be read or written. */ + #if 0 +- assert( pFile->pUnused==0 ++ assert( pFile->pPreallocatedUnused==0 + || offset>=PENDING_BYTE+512 + || offset+amt<=PENDING_BYTE + ); +@@ -33714,7 +35772,7 @@ + /* If this is a database file (not a journal, master-journal or temp + ** file), the bytes in the locking range should never be read or written. */ + #if 0 +- assert( pFile->pUnused==0 ++ assert( pFile->pPreallocatedUnused==0 + || offset>=PENDING_BYTE+512 + || offset+amt<=PENDING_BYTE + ); +@@ -34126,7 +36184,7 @@ + do{ + err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size); + }while( err==EINTR ); +- if( err ) return SQLITE_IOERR_WRITE; ++ if( err && err!=EINVAL ) return SQLITE_IOERR_WRITE; + #else + /* If the OS does not have posix_fallocate(), fake it. Write a + ** single byte to the last byte in each block that falls entirely +@@ -34194,6 +36252,21 @@ + static int unixFileControl(sqlite3_file *id, int op, void *pArg){ + unixFile *pFile = (unixFile*)id; + switch( op ){ ++#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) ++ case SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: { ++ int rc = osIoctl(pFile->h, F2FS_IOC_START_ATOMIC_WRITE); ++ return rc ? SQLITE_IOERR_BEGIN_ATOMIC : SQLITE_OK; ++ } ++ case SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: { ++ int rc = osIoctl(pFile->h, F2FS_IOC_COMMIT_ATOMIC_WRITE); ++ return rc ? SQLITE_IOERR_COMMIT_ATOMIC : SQLITE_OK; ++ } ++ case SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: { ++ int rc = osIoctl(pFile->h, F2FS_IOC_ABORT_VOLATILE_WRITE); ++ return rc ? SQLITE_IOERR_ROLLBACK_ATOMIC : SQLITE_OK; ++ } ++#endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */ ++ + case SQLITE_FCNTL_LOCKSTATE: { + *(int*)pArg = pFile->eFileLock; + return SQLITE_OK; +@@ -34237,6 +36310,12 @@ + *(int*)pArg = fileHasMoved(pFile); + return SQLITE_OK; + } ++#ifdef SQLITE_ENABLE_SETLK_TIMEOUT ++ case SQLITE_FCNTL_LOCK_TIMEOUT: { ++ pFile->iBusyTimeout = *(int*)pArg; ++ return SQLITE_OK; ++ } ++#endif + #if SQLITE_MAX_MMAP_SIZE>0 + case SQLITE_FCNTL_MMAP_SIZE: { + i64 newLimit = *(i64*)pArg; +@@ -34244,6 +36323,14 @@ + if( newLimit>sqlite3GlobalConfig.mxMmap ){ + newLimit = sqlite3GlobalConfig.mxMmap; + } ++ ++ /* The value of newLimit may be eventually cast to (size_t) and passed ++ ** to mmap(). Restrict its value to 2GB if (size_t) is not at least a ++ ** 64-bit type. */ ++ if( newLimit>0 && sizeof(size_t)<8 ){ ++ newLimit = (newLimit & 0x7FFFFFFF); ++ } ++ + *(i64*)pArg = pFile->mmapSizeMax; + if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){ + pFile->mmapSizeMax = newLimit; +@@ -34277,30 +36364,41 @@ + } + + /* +-** Return the sector size in bytes of the underlying block device for +-** the specified file. This is almost always 512 bytes, but may be +-** larger for some devices. ++** If pFd->sectorSize is non-zero when this function is called, it is a ++** no-op. Otherwise, the values of pFd->sectorSize and ++** pFd->deviceCharacteristics are set according to the file-system ++** characteristics. + ** +-** SQLite code assumes this function cannot fail. It also assumes that +-** if two files are created in the same file-system directory (i.e. +-** a database and its journal file) that the sector size will be the +-** same for both. ++** There are two versions of this function. One for QNX and one for all ++** other systems. + */ +-#ifndef __QNXNTO__ +-static int unixSectorSize(sqlite3_file *NotUsed){ +- UNUSED_PARAMETER(NotUsed); +- return SQLITE_DEFAULT_SECTOR_SIZE; ++#ifndef __QNXNTO__ ++static void setDeviceCharacteristics(unixFile *pFd){ ++ assert( pFd->deviceCharacteristics==0 || pFd->sectorSize!=0 ); ++ if( pFd->sectorSize==0 ){ ++#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) ++ int res; ++ u32 f = 0; ++ ++ /* Check for support for F2FS atomic batch writes. */ ++ res = osIoctl(pFd->h, F2FS_IOC_GET_FEATURES, &f); ++ if( res==0 && (f & F2FS_FEATURE_ATOMIC_WRITE) ){ ++ pFd->deviceCharacteristics = SQLITE_IOCAP_BATCH_ATOMIC; ++ } ++#endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */ ++ ++ /* Set the POWERSAFE_OVERWRITE flag if requested. */ ++ if( pFd->ctrlFlags & UNIXFILE_PSOW ){ ++ pFd->deviceCharacteristics |= SQLITE_IOCAP_POWERSAFE_OVERWRITE; ++ } ++ ++ pFd->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE; ++ } + } +-#endif +- +-/* +-** The following version of unixSectorSize() is optimized for QNX. +-*/ +-#ifdef __QNXNTO__ ++#else + #include <sys/dcmd_blk.h> + #include <sys/statvfs.h> +-static int unixSectorSize(sqlite3_file *id){ +- unixFile *pFile = (unixFile*)id; ++static void setDeviceCharacteristics(unixFile *pFile){ + if( pFile->sectorSize == 0 ){ + struct statvfs fsInfo; + +@@ -34308,7 +36406,7 @@ + pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE; + pFile->deviceCharacteristics = 0; + if( fstatvfs(pFile->h, &fsInfo) == -1 ) { +- return pFile->sectorSize; ++ return; + } + + if( !strcmp(fsInfo.f_basetype, "tmp") ) { +@@ -34369,11 +36467,26 @@ + pFile->deviceCharacteristics = 0; + pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE; + } +- return pFile->sectorSize; + } +-#endif /* __QNXNTO__ */ ++#endif + + /* ++** Return the sector size in bytes of the underlying block device for ++** the specified file. This is almost always 512 bytes, but may be ++** larger for some devices. ++** ++** SQLite code assumes this function cannot fail. It also assumes that ++** if two files are created in the same file-system directory (i.e. ++** a database and its journal file) that the sector size will be the ++** same for both. ++*/ ++static int unixSectorSize(sqlite3_file *id){ ++ unixFile *pFd = (unixFile*)id; ++ setDeviceCharacteristics(pFd); ++ return pFd->sectorSize; ++} ++ ++/* + ** Return the device characteristics for the file. + ** + ** This VFS is set up to return SQLITE_IOCAP_POWERSAFE_OVERWRITE by default. +@@ -34387,16 +36500,9 @@ + ** available to turn it off and URI query parameter available to turn it off. + */ + static int unixDeviceCharacteristics(sqlite3_file *id){ +- unixFile *p = (unixFile*)id; +- int rc = 0; +-#ifdef __QNXNTO__ +- if( p->sectorSize==0 ) unixSectorSize(id); +- rc = p->deviceCharacteristics; +-#endif +- if( p->ctrlFlags & UNIXFILE_PSOW ){ +- rc |= SQLITE_IOCAP_POWERSAFE_OVERWRITE; +- } +- return rc; ++ unixFile *pFd = (unixFile*)id; ++ setDeviceCharacteristics(pFd); ++ return pFd->deviceCharacteristics; + } + + #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 +@@ -34443,21 +36549,22 @@ + ** + ** The following fields are read-only after the object is created: + ** +-** fid ++** hShm + ** zFilename + ** +-** Either unixShmNode.mutex must be held or unixShmNode.nRef==0 and ++** Either unixShmNode.pShmMutex must be held or unixShmNode.nRef==0 and + ** unixMutexHeld() is true when reading or writing any other field + ** in this structure. + */ + struct unixShmNode { + unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */ +- sqlite3_mutex *mutex; /* Mutex to access this object */ ++ sqlite3_mutex *pShmMutex; /* Mutex to access this object */ + char *zFilename; /* Name of the mmapped file */ +- int h; /* Open file descriptor */ ++ int hShm; /* Open file descriptor */ + int szRegion; /* Size of shared-memory regions */ + u16 nRegion; /* Size of array apRegion */ + u8 isReadonly; /* True if read-only */ ++ u8 isUnlocked; /* True if no DMS lock held */ + char **apRegion; /* Array of mapped shared-memory regions */ + int nRef; /* Number of unixShm objects pointing to this */ + unixShm *pFirst; /* All unixShm objects pointing to this */ +@@ -34475,16 +36582,16 @@ + ** The following fields are initialized when this object is created and + ** are read-only thereafter: + ** +-** unixShm.pFile ++** unixShm.pShmNode + ** unixShm.id + ** +-** All other fields are read/write. The unixShm.pFile->mutex must be held +-** while accessing any read/write fields. ++** All other fields are read/write. The unixShm.pShmNode->pShmMutex must ++** be held while accessing any read/write fields. + */ + struct unixShm { + unixShmNode *pShmNode; /* The underlying unixShmNode object */ + unixShm *pNext; /* Next unixShm with the same unixShmNode */ +- u8 hasMutex; /* True if holding the unixShmNode mutex */ ++ u8 hasMutex; /* True if holding the unixShmNode->pShmMutex */ + u8 id; /* Id of this connection within its unixShmNode */ + u16 sharedMask; /* Mask of shared locks held */ + u16 exclMask; /* Mask of exclusive locks held */ +@@ -34514,7 +36621,8 @@ + + /* Access to the unixShmNode object is serialized by the caller */ + pShmNode = pFile->pInode->pShmNode; +- assert( sqlite3_mutex_held(pShmNode->mutex) || pShmNode->nRef==0 ); ++ assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->pShmMutex) ); ++ assert( pShmNode->nRef>0 || unixMutexHeld() ); + + /* Shared locks never span more than one byte */ + assert( n==1 || lockType!=F_RDLCK ); +@@ -34522,15 +36630,13 @@ + /* Locks are within range */ + assert( n>=1 && n<=SQLITE_SHM_NLOCK ); + +- if( pShmNode->h>=0 ){ ++ if( pShmNode->hShm>=0 ){ + /* Initialize the locking parameters */ +- memset(&f, 0, sizeof(f)); + f.l_type = lockType; + f.l_whence = SEEK_SET; + f.l_start = ofst; + f.l_len = n; +- +- rc = osFcntl(pShmNode->h, F_SETLK, &f); ++ rc = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile); + rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY; + } + +@@ -34602,9 +36708,9 @@ + int nShmPerMap = unixShmRegionPerMap(); + int i; + assert( p->pInode==pFd->pInode ); +- sqlite3_mutex_free(p->mutex); ++ sqlite3_mutex_free(p->pShmMutex); + for(i=0; i<p->nRegion; i+=nShmPerMap){ +- if( p->h>=0 ){ ++ if( p->hShm>=0 ){ + osMunmap(p->apRegion[i], p->szRegion); + }else{ + sqlite3_free(p->apRegion[i]); +@@ -34611,9 +36717,9 @@ + } + } + sqlite3_free(p->apRegion); +- if( p->h>=0 ){ +- robust_close(pFd, p->h, __LINE__); +- p->h = -1; ++ if( p->hShm>=0 ){ ++ robust_close(pFd, p->hShm, __LINE__); ++ p->hShm = -1; + } + p->pInode->pShmNode = 0; + sqlite3_free(p); +@@ -34621,6 +36727,69 @@ + } + + /* ++** The DMS lock has not yet been taken on shm file pShmNode. Attempt to ++** take it now. Return SQLITE_OK if successful, or an SQLite error ++** code otherwise. ++** ++** If the DMS cannot be locked because this is a readonly_shm=1 ++** connection and no other process already holds a lock, return ++** SQLITE_READONLY_CANTINIT and set pShmNode->isUnlocked=1. ++*/ ++static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){ ++ struct flock lock; ++ int rc = SQLITE_OK; ++ ++ /* Use F_GETLK to determine the locks other processes are holding ++ ** on the DMS byte. If it indicates that another process is holding ++ ** a SHARED lock, then this process may also take a SHARED lock ++ ** and proceed with opening the *-shm file. ++ ** ++ ** Or, if no other process is holding any lock, then this process ++ ** is the first to open it. In this case take an EXCLUSIVE lock on the ++ ** DMS byte and truncate the *-shm file to zero bytes in size. Then ++ ** downgrade to a SHARED lock on the DMS byte. ++ ** ++ ** If another process is holding an EXCLUSIVE lock on the DMS byte, ++ ** return SQLITE_BUSY to the caller (it will try again). An earlier ++ ** version of this code attempted the SHARED lock at this point. But ++ ** this introduced a subtle race condition: if the process holding ++ ** EXCLUSIVE failed just before truncating the *-shm file, then this ++ ** process might open and use the *-shm file without truncating it. ++ ** And if the *-shm file has been corrupted by a power failure or ++ ** system crash, the database itself may also become corrupt. */ ++ lock.l_whence = SEEK_SET; ++ lock.l_start = UNIX_SHM_DMS; ++ lock.l_len = 1; ++ lock.l_type = F_WRLCK; ++ if( osFcntl(pShmNode->hShm, F_GETLK, &lock)!=0 ) { ++ rc = SQLITE_IOERR_LOCK; ++ }else if( lock.l_type==F_UNLCK ){ ++ if( pShmNode->isReadonly ){ ++ pShmNode->isUnlocked = 1; ++ rc = SQLITE_READONLY_CANTINIT; ++ }else{ ++ rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1); ++ /* The first connection to attach must truncate the -shm file. We ++ ** truncate to 3 bytes (an arbitrary small number, less than the ++ ** -shm header size) rather than 0 as a system debugging aid, to ++ ** help detect if a -shm file truncation is legitimate or is the work ++ ** or a rogue process. */ ++ if( rc==SQLITE_OK && robust_ftruncate(pShmNode->hShm, 3) ){ ++ rc = unixLogError(SQLITE_IOERR_SHMOPEN,"ftruncate",pShmNode->zFilename); ++ } ++ } ++ }else if( lock.l_type==F_WRLCK ){ ++ rc = SQLITE_BUSY; ++ } ++ ++ if( rc==SQLITE_OK ){ ++ assert( lock.l_type==F_UNLCK || lock.l_type==F_RDLCK ); ++ rc = unixShmSystemLock(pDbFd, F_RDLCK, UNIX_SHM_DMS, 1); ++ } ++ return rc; ++} ++ ++/* + ** Open a shared-memory area associated with open database file pDbFd. + ** This particular implementation uses mmapped files. + ** +@@ -34658,9 +36827,9 @@ + static int unixOpenSharedMemory(unixFile *pDbFd){ + struct unixShm *p = 0; /* The connection to be opened */ + struct unixShmNode *pShmNode; /* The underlying mmapped file */ +- int rc; /* Result code */ ++ int rc = SQLITE_OK; /* Result code */ + unixInodeInfo *pInode; /* The inode of fd */ +- char *zShmFilename; /* Name of the file used for SHM */ ++ char *zShm; /* Name of the file used for SHM */ + int nShmFilename; /* Size of the SHM filename in bytes */ + + /* Allocate space for the new unixShm object. */ +@@ -34672,6 +36841,7 @@ + /* Check to see if a unixShmNode object already exists. Reuse an existing + ** one if present. Create a new one if necessary. + */ ++ assert( unixFileMutexNotheld(pDbFd) ); + unixEnterMutex(); + pInode = pDbFd->pInode; + pShmNode = pInode->pShmNode; +@@ -34701,21 +36871,21 @@ + goto shm_open_err; + } + memset(pShmNode, 0, sizeof(*pShmNode)+nShmFilename); +- zShmFilename = pShmNode->zFilename = (char*)&pShmNode[1]; ++ zShm = pShmNode->zFilename = (char*)&pShmNode[1]; + #ifdef SQLITE_SHM_DIRECTORY +- sqlite3_snprintf(nShmFilename, zShmFilename, ++ sqlite3_snprintf(nShmFilename, zShm, + SQLITE_SHM_DIRECTORY "/sqlite-shm-%x-%x", + (u32)sStat.st_ino, (u32)sStat.st_dev); + #else +- sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", zBasePath); +- sqlite3FileSuffix3(pDbFd->zPath, zShmFilename); ++ sqlite3_snprintf(nShmFilename, zShm, "%s-shm", zBasePath); ++ sqlite3FileSuffix3(pDbFd->zPath, zShm); + #endif +- pShmNode->h = -1; ++ pShmNode->hShm = -1; + pDbFd->pInode->pShmNode = pShmNode; + pShmNode->pInode = pDbFd->pInode; + if( sqlite3GlobalConfig.bCoreMutex ){ +- pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); +- if( pShmNode->mutex==0 ){ ++ pShmNode->pShmMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); ++ if( pShmNode->pShmMutex==0 ){ + rc = SQLITE_NOMEM_BKPT; + goto shm_open_err; + } +@@ -34722,36 +36892,26 @@ + } + + if( pInode->bProcessLock==0 ){ +- int openFlags = O_RDWR | O_CREAT; +- if( sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){ +- openFlags = O_RDONLY; ++ if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){ ++ pShmNode->hShm = robust_open(zShm, O_RDWR|O_CREAT,(sStat.st_mode&0777)); ++ } ++ if( pShmNode->hShm<0 ){ ++ pShmNode->hShm = robust_open(zShm, O_RDONLY, (sStat.st_mode&0777)); ++ if( pShmNode->hShm<0 ){ ++ rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShm); ++ goto shm_open_err; ++ } + pShmNode->isReadonly = 1; + } +- pShmNode->h = robust_open(zShmFilename, openFlags, (sStat.st_mode&0777)); +- if( pShmNode->h<0 ){ +- rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename); +- goto shm_open_err; +- } + + /* If this process is running as root, make sure that the SHM file + ** is owned by the same user that owns the original database. Otherwise, + ** the original owner will not be able to connect. + */ +- robustFchown(pShmNode->h, sStat.st_uid, sStat.st_gid); +- +- /* Check to see if another process is holding the dead-man switch. +- ** If not, truncate the file to zero length. +- */ +- rc = SQLITE_OK; +- if( unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){ +- if( robust_ftruncate(pShmNode->h, 0) ){ +- rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename); +- } +- } +- if( rc==SQLITE_OK ){ +- rc = unixShmSystemLock(pDbFd, F_RDLCK, UNIX_SHM_DMS, 1); +- } +- if( rc ) goto shm_open_err; ++ robustFchown(pShmNode->hShm, sStat.st_uid, sStat.st_gid); ++ ++ rc = unixLockSharedMemory(pDbFd, pShmNode); ++ if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err; + } + } + +@@ -34768,14 +36928,14 @@ + ** the cover of the unixEnterMutex() mutex and the pointer from the + ** new (struct unixShm) object to the pShmNode has been set. All that is + ** left to do is to link the new object into the linked list starting +- ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex +- ** mutex. ++ ** at pShmNode->pFirst. This must be done while holding the ++ ** pShmNode->pShmMutex. + */ +- sqlite3_mutex_enter(pShmNode->mutex); ++ sqlite3_mutex_enter(pShmNode->pShmMutex); + p->pNext = pShmNode->pFirst; + pShmNode->pFirst = p; +- sqlite3_mutex_leave(pShmNode->mutex); +- return SQLITE_OK; ++ sqlite3_mutex_leave(pShmNode->pShmMutex); ++ return rc; + + /* Jump here on any error */ + shm_open_err: +@@ -34826,11 +36986,16 @@ + + p = pDbFd->pShm; + pShmNode = p->pShmNode; +- sqlite3_mutex_enter(pShmNode->mutex); ++ sqlite3_mutex_enter(pShmNode->pShmMutex); ++ if( pShmNode->isUnlocked ){ ++ rc = unixLockSharedMemory(pDbFd, pShmNode); ++ if( rc!=SQLITE_OK ) goto shmpage_out; ++ pShmNode->isUnlocked = 0; ++ } + assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 ); + assert( pShmNode->pInode==pDbFd->pInode ); +- assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 ); +- assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 ); ++ assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 ); ++ assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 ); + + /* Minimum number of regions required to be mapped. */ + nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap; +@@ -34842,12 +37007,12 @@ + + pShmNode->szRegion = szRegion; + +- if( pShmNode->h>=0 ){ ++ if( pShmNode->hShm>=0 ){ + /* The requested region is not mapped into this processes address space. + ** Check to see if it has been allocated (i.e. if the wal-index file is + ** large enough to contain the requested region). + */ +- if( osFstat(pShmNode->h, &sStat) ){ ++ if( osFstat(pShmNode->hShm, &sStat) ){ + rc = SQLITE_IOERR_SHMSIZE; + goto shmpage_out; + } +@@ -34875,7 +37040,7 @@ + assert( (nByte % pgsz)==0 ); + for(iPg=(sStat.st_size/pgsz); iPg<(nByte/pgsz); iPg++){ + int x = 0; +- if( seekAndWriteFd(pShmNode->h, iPg*pgsz + pgsz-1, "", 1, &x)!=1 ){ ++ if( seekAndWriteFd(pShmNode->hShm, iPg*pgsz + pgsz-1,"",1,&x)!=1 ){ + const char *zFile = pShmNode->zFilename; + rc = unixLogError(SQLITE_IOERR_SHMSIZE, "write", zFile); + goto shmpage_out; +@@ -34898,10 +37063,10 @@ + int nMap = szRegion*nShmPerMap; + int i; + void *pMem; +- if( pShmNode->h>=0 ){ ++ if( pShmNode->hShm>=0 ){ + pMem = osMmap(0, nMap, + pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, +- MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion ++ MAP_SHARED, pShmNode->hShm, szRegion*(i64)pShmNode->nRegion + ); + if( pMem==MAP_FAILED ){ + rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename); +@@ -34908,12 +37073,12 @@ + goto shmpage_out; + } + }else{ +- pMem = sqlite3_malloc64(szRegion); ++ pMem = sqlite3_malloc64(nMap); + if( pMem==0 ){ + rc = SQLITE_NOMEM_BKPT; + goto shmpage_out; + } +- memset(pMem, 0, szRegion); ++ memset(pMem, 0, nMap); + } + + for(i=0; i<nShmPerMap; i++){ +@@ -34930,7 +37095,7 @@ + *pp = 0; + } + if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY; +- sqlite3_mutex_leave(pShmNode->mutex); ++ sqlite3_mutex_leave(pShmNode->pShmMutex); + return rc; + } + +@@ -34964,12 +37129,12 @@ + || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED) + || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) ); + assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 ); +- assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 ); +- assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 ); ++ assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 ); ++ assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 ); + + mask = (1<<(ofst+n)) - (1<<ofst); + assert( n>1 || mask==(1<<ofst) ); +- sqlite3_mutex_enter(pShmNode->mutex); ++ sqlite3_mutex_enter(pShmNode->pShmMutex); + if( flags & SQLITE_SHM_UNLOCK ){ + u16 allMask = 0; /* Mask of locks held by siblings */ + +@@ -35042,7 +37207,7 @@ + } + } + } +- sqlite3_mutex_leave(pShmNode->mutex); ++ sqlite3_mutex_leave(pShmNode->pShmMutex); + OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n", + p->id, osGetpid(0), p->sharedMask, p->exclMask)); + return rc; +@@ -35059,6 +37224,9 @@ + ){ + UNUSED_PARAMETER(fd); + sqlite3MemoryBarrier(); /* compiler-defined memory barrier */ ++ assert( fd->pMethods->xLock==nolockLock ++ || unixFileMutexNotheld((unixFile*)fd) ++ ); + unixEnterMutex(); /* Also mutex, for redundancy */ + unixLeaveMutex(); + } +@@ -35089,7 +37257,7 @@ + + /* Remove connection p from the set of connections associated + ** with pShmNode */ +- sqlite3_mutex_enter(pShmNode->mutex); ++ sqlite3_mutex_enter(pShmNode->pShmMutex); + for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){} + *pp = p->pNext; + +@@ -35096,15 +37264,16 @@ + /* Free the connection p */ + sqlite3_free(p); + pDbFd->pShm = 0; +- sqlite3_mutex_leave(pShmNode->mutex); ++ sqlite3_mutex_leave(pShmNode->pShmMutex); + + /* If pShmNode->nRef has reached 0, then close the underlying + ** shared-memory file, too */ ++ assert( unixFileMutexNotheld(pDbFd) ); + unixEnterMutex(); + assert( pShmNode->nRef>0 ); + pShmNode->nRef--; + if( pShmNode->nRef==0 ){ +- if( deleteFlag && pShmNode->h>=0 ){ ++ if( deleteFlag && pShmNode->hShm>=0 ){ + osUnlink(pShmNode->zFilename); + } + unixShmPurge(pDbFd); +@@ -35426,7 +37595,7 @@ + IOMETHODS( + nolockIoFinder, /* Finder function name */ + nolockIoMethods, /* sqlite3_io_methods object name */ +- 3, /* shared memory is disabled */ ++ 3, /* shared memory and mmap are enabled */ + nolockClose, /* xClose method */ + nolockLock, /* xLock method */ + nolockUnlock, /* xUnlock method */ +@@ -35654,17 +37823,6 @@ + + assert( pNew->pInode==NULL ); + +- /* Usually the path zFilename should not be a relative pathname. The +- ** exception is when opening the proxy "conch" file in builds that +- ** include the special Apple locking styles. +- */ +-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE +- assert( zFilename==0 || zFilename[0]=='/' +- || pVfs->pAppData==(void*)&autolockIoFinder ); +-#else +- assert( zFilename==0 || zFilename[0]=='/' ); +-#endif +- + /* No locking occurs in temporary files */ + assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 ); + +@@ -35923,6 +38081,8 @@ + #if !OS_VXWORKS + struct stat sStat; /* Results of stat() call */ + ++ unixEnterMutex(); ++ + /* A stat() call may fail for various reasons. If this happens, it is + ** almost certain that an open() call on the same path will also fail. + ** For this reason, if an error occurs in the stat() call here, it is +@@ -35931,10 +38091,9 @@ + ** + ** Even if a subsequent open() call does succeed, the consequences of + ** not searching for a reusable file descriptor are not dire. */ +- if( 0==osStat(zPath, &sStat) ){ ++ if( inodeList!=0 && 0==osStat(zPath, &sStat) ){ + unixInodeInfo *pInode; + +- unixEnterMutex(); + pInode = inodeList; + while( pInode && (pInode->fileId.dev!=sStat.st_dev + || pInode->fileId.ino!=(u64)sStat.st_ino) ){ +@@ -35942,14 +38101,17 @@ + } + if( pInode ){ + UnixUnusedFd **pp; ++ assert( sqlite3_mutex_notheld(pInode->pLockMutex) ); ++ sqlite3_mutex_enter(pInode->pLockMutex); + for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext)); + pUnused = *pp; + if( pUnused ){ + *pp = pUnused->pNext; + } ++ sqlite3_mutex_leave(pInode->pLockMutex); + } +- unixLeaveMutex(); + } ++ unixLeaveMutex(); + #endif /* if !OS_VXWORKS */ + return pUnused; + } +@@ -36025,16 +38187,11 @@ + */ + nDb = sqlite3Strlen30(zPath) - 1; + while( zPath[nDb]!='-' ){ +-#ifndef SQLITE_ENABLE_8_3_NAMES +- /* In the normal case (8+3 filenames disabled) the journal filename +- ** is guaranteed to contain a '-' character. */ +- assert( nDb>0 ); +- assert( sqlite3Isalnum(zPath[nDb]) ); +-#else +- /* If 8+3 names are possible, then the journal file might not contain +- ** a '-' character. So check for that case and return early. */ ++ /* In normal operation, the journal file name will always contain ++ ** a '-' character. However in 8+3 filename mode, or if a corrupt ++ ** rollback journal specifies a master journal with a goofy name, then ++ ** the '-' might be missing. */ + if( nDb==0 || zPath[nDb]=='.' ) return SQLITE_OK; +-#endif + nDb--; + } + memcpy(zDb, zPath, nDb); +@@ -36109,7 +38266,7 @@ + ** a file-descriptor on the directory too. The first time unixSync() + ** is called the directory file descriptor will be fsync()ed and close()d. + */ +- int syncDir = (isCreate && ( ++ int isNewJrnl = (isCreate && ( + eType==SQLITE_OPEN_MASTER_JOURNAL + || eType==SQLITE_OPEN_MAIN_JOURNAL + || eType==SQLITE_OPEN_WAL +@@ -36156,7 +38313,6 @@ + randomnessPid = osGetpid(0); + sqlite3_randomness(0,0); + } +- + memset(p, 0, sizeof(unixFile)); + + if( eType==SQLITE_OPEN_MAIN_DB ){ +@@ -36170,7 +38326,7 @@ + return SQLITE_NOMEM_BKPT; + } + } +- p->pUnused = pUnused; ++ p->pPreallocatedUnused = pUnused; + + /* Database filenames are double-zero terminated if they are not + ** URIs with parameters. Hence, they can always be passed into +@@ -36179,7 +38335,7 @@ + + }else if( !zName ){ + /* If zName is NULL, the upper layer is requesting a temp file. */ +- assert(isDelete && !syncDir); ++ assert(isDelete && !isNewJrnl); + rc = unixGetTempname(pVfs->mxPathname, zTmpname); + if( rc!=SQLITE_OK ){ + return rc; +@@ -36207,7 +38363,7 @@ + gid_t gid; /* Groupid for the file */ + rc = findCreateFileMode(zName, flags, &openMode, &uid, &gid); + if( rc!=SQLITE_OK ){ +- assert( !p->pUnused ); ++ assert( !p->pPreallocatedUnused ); + assert( eType==SQLITE_OPEN_WAL || eType==SQLITE_OPEN_MAIN_JOURNAL ); + return rc; + } +@@ -36214,17 +38370,24 @@ + fd = robust_open(zName, openFlags, openMode); + OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags)); + assert( !isExclusive || (openFlags & O_CREAT)!=0 ); +- if( fd<0 && errno!=EISDIR && isReadWrite ){ +- /* Failed to open the file for read/write access. Try read-only. */ +- flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); +- openFlags &= ~(O_RDWR|O_CREAT); +- flags |= SQLITE_OPEN_READONLY; +- openFlags |= O_RDONLY; +- isReadonly = 1; +- fd = robust_open(zName, openFlags, openMode); ++ if( fd<0 ){ ++ if( isNewJrnl && errno==EACCES && osAccess(zName, F_OK) ){ ++ /* If unable to create a journal because the directory is not ++ ** writable, change the error code to indicate that. */ ++ rc = SQLITE_READONLY_DIRECTORY; ++ }else if( errno!=EISDIR && isReadWrite ){ ++ /* Failed to open the file for read/write access. Try read-only. */ ++ flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); ++ openFlags &= ~(O_RDWR|O_CREAT); ++ flags |= SQLITE_OPEN_READONLY; ++ openFlags |= O_RDONLY; ++ isReadonly = 1; ++ fd = robust_open(zName, openFlags, openMode); ++ } + } + if( fd<0 ){ +- rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName); ++ int rc2 = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName); ++ if( rc==SQLITE_OK ) rc = rc2; + goto open_finished; + } + +@@ -36241,9 +38404,9 @@ + *pOutFlags = flags; + } + +- if( p->pUnused ){ +- p->pUnused->fd = fd; +- p->pUnused->flags = flags; ++ if( p->pPreallocatedUnused ){ ++ p->pPreallocatedUnused->fd = fd; ++ p->pPreallocatedUnused->flags = flags; + } + + if( isDelete ){ +@@ -36284,7 +38447,7 @@ + if( isReadonly ) ctrlFlags |= UNIXFILE_RDONLY; + noLock = eType!=SQLITE_OPEN_MAIN_DB; + if( noLock ) ctrlFlags |= UNIXFILE_NOLOCK; +- if( syncDir ) ctrlFlags |= UNIXFILE_DIRSYNC; ++ if( isNewJrnl ) ctrlFlags |= UNIXFILE_DIRSYNC; + if( flags & SQLITE_OPEN_URI ) ctrlFlags |= UNIXFILE_URI; + + #if SQLITE_ENABLE_LOCKING_STYLE +@@ -36320,11 +38483,14 @@ + } + #endif + ++ assert( zPath==0 || zPath[0]=='/' ++ || eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL ++ ); + rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags); + + open_finished: + if( rc!=SQLITE_OK ){ +- sqlite3_free(p->pUnused); ++ sqlite3_free(p->pPreallocatedUnused); + } + return rc; + } +@@ -37065,7 +39231,7 @@ + dummyVfs.zName = "dummy"; + pUnused->fd = fd; + pUnused->flags = openFlags; +- pNew->pUnused = pUnused; ++ pNew->pPreallocatedUnused = pUnused; + + rc = fillInUnixFile(&dummyVfs, fd, (sqlite3_file*)pNew, path, 0); + if( rc==SQLITE_OK ){ +@@ -38015,12 +40181,13 @@ + + /* Double-check that the aSyscall[] array has been constructed + ** correctly. See ticket [bb3a86e890c8e96ab] */ +- assert( ArraySize(aSyscall)==28 ); ++ assert( ArraySize(aSyscall)==29 ); + + /* Register all VFSes defined in the aVfs[] array */ + for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ + sqlite3_vfs_register(&aVfs[i], i==0); + } ++ unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1); + return SQLITE_OK; + } + +@@ -38032,6 +40199,7 @@ + ** This routine is a no-op for unix. + */ + SQLITE_API int sqlite3_os_end(void){ ++ unixBigLock = 0; + return SQLITE_OK; + } + +@@ -38523,8 +40691,7 @@ + int nFetchOut; /* Number of outstanding xFetch references */ + HANDLE hMap; /* Handle for accessing memory mapping */ + void *pMapRegion; /* Area memory mapped */ +- sqlite3_int64 mmapSize; /* Usable size of mapped region */ +- sqlite3_int64 mmapSizeActual; /* Actual size of mapped region */ ++ sqlite3_int64 mmapSize; /* Size of mapped region */ + sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */ + #endif + }; +@@ -38555,22 +40722,6 @@ + #endif + + /* +- * The value used with sqlite3_win32_set_directory() to specify that +- * the data directory should be changed. +- */ +-#ifndef SQLITE_WIN32_DATA_DIRECTORY_TYPE +-# define SQLITE_WIN32_DATA_DIRECTORY_TYPE (1) +-#endif +- +-/* +- * The value used with sqlite3_win32_set_directory() to specify that +- * the temporary directory should be changed. +- */ +-#ifndef SQLITE_WIN32_TEMP_DIRECTORY_TYPE +-# define SQLITE_WIN32_TEMP_DIRECTORY_TYPE (2) +-#endif +- +-/* + * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the + * various Win32 API heap functions instead of our own. + */ +@@ -40166,13 +42317,13 @@ + } + + /* +-** This function sets the data directory or the temporary directory based on +-** the provided arguments. The type argument must be 1 in order to set the +-** data directory or 2 in order to set the temporary directory. The zValue +-** argument is the name of the directory to use. The return value will be +-** SQLITE_OK if successful. ++** This function is the same as sqlite3_win32_set_directory (below); however, ++** it accepts a UTF-8 string. + */ +-SQLITE_API int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){ ++SQLITE_API int sqlite3_win32_set_directory8( ++ unsigned long type, /* Identifier for directory being set or reset */ ++ const char *zValue /* New value for directory being set or reset */ ++){ + char **ppDirectory = 0; + #ifndef SQLITE_OMIT_AUTOINIT + int rc = sqlite3_initialize(); +@@ -40188,15 +42339,15 @@ + ); + assert( !ppDirectory || sqlite3MemdebugHasType(*ppDirectory, MEMTYPE_HEAP) ); + if( ppDirectory ){ +- char *zValueUtf8 = 0; ++ char *zCopy = 0; + if( zValue && zValue[0] ){ +- zValueUtf8 = winUnicodeToUtf8(zValue); +- if ( zValueUtf8==0 ){ ++ zCopy = sqlite3_mprintf("%s", zValue); ++ if ( zCopy==0 ){ + return SQLITE_NOMEM_BKPT; + } + } + sqlite3_free(*ppDirectory); +- *ppDirectory = zValueUtf8; ++ *ppDirectory = zCopy; + return SQLITE_OK; + } + return SQLITE_ERROR; +@@ -40203,6 +42354,39 @@ + } + + /* ++** This function is the same as sqlite3_win32_set_directory (below); however, ++** it accepts a UTF-16 string. ++*/ ++SQLITE_API int sqlite3_win32_set_directory16( ++ unsigned long type, /* Identifier for directory being set or reset */ ++ const void *zValue /* New value for directory being set or reset */ ++){ ++ int rc; ++ char *zUtf8 = 0; ++ if( zValue ){ ++ zUtf8 = sqlite3_win32_unicode_to_utf8(zValue); ++ if( zUtf8==0 ) return SQLITE_NOMEM_BKPT; ++ } ++ rc = sqlite3_win32_set_directory8(type, zUtf8); ++ if( zUtf8 ) sqlite3_free(zUtf8); ++ return rc; ++} ++ ++/* ++** This function sets the data directory or the temporary directory based on ++** the provided arguments. The type argument must be 1 in order to set the ++** data directory or 2 in order to set the temporary directory. The zValue ++** argument is the name of the directory to use. The return value will be ++** SQLITE_OK if successful. ++*/ ++SQLITE_API int sqlite3_win32_set_directory( ++ unsigned long type, /* Identifier for directory being set or reset */ ++ void *zValue /* New value for directory being set or reset */ ++){ ++ return sqlite3_win32_set_directory16(type, zValue); ++} ++ ++/* + ** The return value of winGetLastErrorMsg + ** is zero if the error message fits in the buffer, or non-zero + ** otherwise (if the message was truncated). +@@ -41126,6 +43310,29 @@ + winFile *pFile = (winFile*)id; /* File handle object */ + int rc = SQLITE_OK; /* Return code for this function */ + DWORD lastErrno; ++#if SQLITE_MAX_MMAP_SIZE>0 ++ sqlite3_int64 oldMmapSize; ++ if( pFile->nFetchOut>0 ){ ++ /* File truncation is a no-op if there are outstanding memory mapped ++ ** pages. This is because truncating the file means temporarily unmapping ++ ** the file, and that might delete memory out from under existing cursors. ++ ** ++ ** This can result in incremental vacuum not truncating the file, ++ ** if there is an active read cursor when the incremental vacuum occurs. ++ ** No real harm comes of this - the database file is not corrupted, ++ ** though some folks might complain that the file is bigger than it ++ ** needs to be. ++ ** ++ ** The only feasible work-around is to defer the truncation until after ++ ** all references to memory-mapped content are closed. That is doable, ++ ** but involves adding a few branches in the common write code path which ++ ** could slow down normal operations slightly. Hence, we have decided for ++ ** now to simply make trancations a no-op if there are pending reads. We ++ ** can maybe revisit this decision in the future. ++ */ ++ return SQLITE_OK; ++ } ++#endif + + assert( pFile ); + SimulateIOError(return SQLITE_IOERR_TRUNCATE); +@@ -41141,6 +43348,15 @@ + nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk; + } + ++#if SQLITE_MAX_MMAP_SIZE>0 ++ if( pFile->pMapRegion ){ ++ oldMmapSize = pFile->mmapSize; ++ }else{ ++ oldMmapSize = 0; ++ } ++ winUnmapfile(pFile); ++#endif ++ + /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */ + if( winSeekFile(pFile, nByte) ){ + rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno, +@@ -41153,12 +43369,12 @@ + } + + #if SQLITE_MAX_MMAP_SIZE>0 +- /* If the file was truncated to a size smaller than the currently +- ** mapped region, reduce the effective mapping size as well. SQLite will +- ** use read() and write() to access data beyond this point from now on. +- */ +- if( pFile->pMapRegion && nByte<pFile->mmapSize ){ +- pFile->mmapSize = nByte; ++ if( rc==SQLITE_OK && oldMmapSize>0 ){ ++ if( oldMmapSize>nByte ){ ++ winMapfile(pFile, -1); ++ }else{ ++ winMapfile(pFile, oldMmapSize); ++ } + } + #endif + +@@ -41798,6 +44014,14 @@ + if( newLimit>sqlite3GlobalConfig.mxMmap ){ + newLimit = sqlite3GlobalConfig.mxMmap; + } ++ ++ /* The value of newLimit may be eventually cast to (SIZE_T) and passed ++ ** to MapViewOfFile(). Restrict its value to 2GB if (SIZE_T) is not at ++ ** least a 64-bit type. */ ++ if( newLimit>0 && sizeof(SIZE_T)<8 ){ ++ newLimit = (newLimit & 0x7FFFFFFF); ++ } ++ + *(i64*)pArg = pFile->mmapSizeMax; + if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){ + pFile->mmapSizeMax = newLimit; +@@ -41862,15 +44086,16 @@ + ** assert( winShmMutexHeld() ); + ** winShmLeaveMutex() + */ ++static sqlite3_mutex *winBigLock = 0; + static void winShmEnterMutex(void){ +- sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); ++ sqlite3_mutex_enter(winBigLock); + } + static void winShmLeaveMutex(void){ +- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); ++ sqlite3_mutex_leave(winBigLock); + } + #ifndef NDEBUG + static int winShmMutexHeld(void) { +- return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); ++ return sqlite3_mutex_held(winBigLock); + } + #endif + +@@ -41904,6 +44129,9 @@ + + int szRegion; /* Size of shared-memory regions */ + int nRegion; /* Size of array apRegion */ ++ u8 isReadonly; /* True if read-only */ ++ u8 isUnlocked; /* True if no DMS lock held */ ++ + struct ShmRegion { + HANDLE hMap; /* File handle from CreateFileMapping */ + void *pMap; +@@ -41970,7 +44198,7 @@ + int rc = 0; /* Result code form Lock/UnlockFileEx() */ + + /* Access to the winShmNode object is serialized by the caller */ +- assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 ); ++ assert( pFile->nRef==0 || sqlite3_mutex_held(pFile->mutex) ); + + OSTRACE(("SHM-LOCK file=%p, lock=%d, offset=%d, size=%d\n", + pFile->hFile.h, lockType, ofst, nByte)); +@@ -42052,6 +44280,37 @@ + } + + /* ++** The DMS lock has not yet been taken on shm file pShmNode. Attempt to ++** take it now. Return SQLITE_OK if successful, or an SQLite error ++** code otherwise. ++** ++** If the DMS cannot be locked because this is a readonly_shm=1 ++** connection and no other process already holds a lock, return ++** SQLITE_READONLY_CANTINIT and set pShmNode->isUnlocked=1. ++*/ ++static int winLockSharedMemory(winShmNode *pShmNode){ ++ int rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, WIN_SHM_DMS, 1); ++ ++ if( rc==SQLITE_OK ){ ++ if( pShmNode->isReadonly ){ ++ pShmNode->isUnlocked = 1; ++ winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1); ++ return SQLITE_READONLY_CANTINIT; ++ }else if( winTruncate((sqlite3_file*)&pShmNode->hFile, 0) ){ ++ winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1); ++ return winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(), ++ "winLockSharedMemory", pShmNode->zFilename); ++ } ++ } ++ ++ if( rc==SQLITE_OK ){ ++ winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1); ++ } ++ ++ return winShmSystemLock(pShmNode, WINSHM_RDLCK, WIN_SHM_DMS, 1); ++} ++ ++/* + ** Open the shared-memory area associated with database file pDbFd. + ** + ** When opening a new shared-memory file, if no other instances of that +@@ -42060,9 +44319,9 @@ + */ + static int winOpenSharedMemory(winFile *pDbFd){ + struct winShm *p; /* The connection to be opened */ +- struct winShmNode *pShmNode = 0; /* The underlying mmapped file */ +- int rc; /* Result code */ +- struct winShmNode *pNew; /* Newly allocated winShmNode */ ++ winShmNode *pShmNode = 0; /* The underlying mmapped file */ ++ int rc = SQLITE_OK; /* Result code */ ++ winShmNode *pNew; /* Newly allocated winShmNode */ + int nName; /* Size of zName in bytes */ + + assert( pDbFd->pShm==0 ); /* Not previously opened */ +@@ -42095,6 +44354,9 @@ + if( pShmNode ){ + sqlite3_free(pNew); + }else{ ++ int inFlags = SQLITE_OPEN_WAL; ++ int outFlags = 0; ++ + pShmNode = pNew; + pNew = 0; + ((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE; +@@ -42109,30 +44371,23 @@ + } + } + +- rc = winOpen(pDbFd->pVfs, +- pShmNode->zFilename, /* Name of the file (UTF-8) */ +- (sqlite3_file*)&pShmNode->hFile, /* File handle here */ +- SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, +- 0); +- if( SQLITE_OK!=rc ){ ++ if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){ ++ inFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; ++ }else{ ++ inFlags |= SQLITE_OPEN_READONLY; ++ } ++ rc = winOpen(pDbFd->pVfs, pShmNode->zFilename, ++ (sqlite3_file*)&pShmNode->hFile, ++ inFlags, &outFlags); ++ if( rc!=SQLITE_OK ){ ++ rc = winLogError(rc, osGetLastError(), "winOpenShm", ++ pShmNode->zFilename); + goto shm_open_err; + } ++ if( outFlags==SQLITE_OPEN_READONLY ) pShmNode->isReadonly = 1; + +- /* Check to see if another process is holding the dead-man switch. +- ** If not, truncate the file to zero length. +- */ +- if( winShmSystemLock(pShmNode, WINSHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){ +- rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0); +- if( rc!=SQLITE_OK ){ +- rc = winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(), +- "winOpenShm", pDbFd->zPath); +- } +- } +- if( rc==SQLITE_OK ){ +- winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1); +- rc = winShmSystemLock(pShmNode, WINSHM_RDLCK, WIN_SHM_DMS, 1); +- } +- if( rc ) goto shm_open_err; ++ rc = winLockSharedMemory(pShmNode); ++ if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err; + } + + /* Make the new connection a child of the winShmNode */ +@@ -42155,7 +44410,7 @@ + p->pNext = pShmNode->pFirst; + pShmNode->pFirst = p; + sqlite3_mutex_leave(pShmNode->mutex); +- return SQLITE_OK; ++ return rc; + + /* Jump here on any error */ + shm_open_err: +@@ -42359,6 +44614,8 @@ + winFile *pDbFd = (winFile*)fd; + winShm *pShm = pDbFd->pShm; + winShmNode *pShmNode; ++ DWORD protect = PAGE_READWRITE; ++ DWORD flags = FILE_MAP_WRITE | FILE_MAP_READ; + int rc = SQLITE_OK; + + if( !pShm ){ +@@ -42369,6 +44626,11 @@ + pShmNode = pShm->pShmNode; + + sqlite3_mutex_enter(pShmNode->mutex); ++ if( pShmNode->isUnlocked ){ ++ rc = winLockSharedMemory(pShmNode); ++ if( rc!=SQLITE_OK ) goto shmpage_out; ++ pShmNode->isUnlocked = 0; ++ } + assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 ); + + if( pShmNode->nRegion<=iRegion ){ +@@ -42415,6 +44677,11 @@ + } + pShmNode->aRegion = apNew; + ++ if( pShmNode->isReadonly ){ ++ protect = PAGE_READONLY; ++ flags = FILE_MAP_READ; ++ } ++ + while( pShmNode->nRegion<=iRegion ){ + HANDLE hMap = NULL; /* file-mapping handle */ + void *pMap = 0; /* Mapped memory region */ +@@ -42421,15 +44688,15 @@ + + #if SQLITE_OS_WINRT + hMap = osCreateFileMappingFromApp(pShmNode->hFile.h, +- NULL, PAGE_READWRITE, nByte, NULL ++ NULL, protect, nByte, NULL + ); + #elif defined(SQLITE_WIN32_HAS_WIDE) + hMap = osCreateFileMappingW(pShmNode->hFile.h, +- NULL, PAGE_READWRITE, 0, nByte, NULL ++ NULL, protect, 0, nByte, NULL + ); + #elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA + hMap = osCreateFileMappingA(pShmNode->hFile.h, +- NULL, PAGE_READWRITE, 0, nByte, NULL ++ NULL, protect, 0, nByte, NULL + ); + #endif + OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n", +@@ -42439,11 +44706,11 @@ + int iOffset = pShmNode->nRegion*szRegion; + int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity; + #if SQLITE_OS_WINRT +- pMap = osMapViewOfFileFromApp(hMap, FILE_MAP_WRITE | FILE_MAP_READ, ++ pMap = osMapViewOfFileFromApp(hMap, flags, + iOffset - iOffsetShift, szRegion + iOffsetShift + ); + #else +- pMap = osMapViewOfFile(hMap, FILE_MAP_WRITE | FILE_MAP_READ, ++ pMap = osMapViewOfFile(hMap, flags, + 0, iOffset - iOffsetShift, szRegion + iOffsetShift + ); + #endif +@@ -42474,6 +44741,7 @@ + }else{ + *pp = 0; + } ++ if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY; + sqlite3_mutex_leave(pShmNode->mutex); + return rc; + } +@@ -42492,9 +44760,9 @@ + static int winUnmapfile(winFile *pFile){ + assert( pFile!=0 ); + OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, pMapRegion=%p, " +- "mmapSize=%lld, mmapSizeActual=%lld, mmapSizeMax=%lld\n", ++ "mmapSize=%lld, mmapSizeMax=%lld\n", + osGetCurrentProcessId(), pFile, pFile->hMap, pFile->pMapRegion, +- pFile->mmapSize, pFile->mmapSizeActual, pFile->mmapSizeMax)); ++ pFile->mmapSize, pFile->mmapSizeMax)); + if( pFile->pMapRegion ){ + if( !osUnmapViewOfFile(pFile->pMapRegion) ){ + pFile->lastErrno = osGetLastError(); +@@ -42506,7 +44774,6 @@ + } + pFile->pMapRegion = 0; + pFile->mmapSize = 0; +- pFile->mmapSizeActual = 0; + } + if( pFile->hMap!=NULL ){ + if( !osCloseHandle(pFile->hMap) ){ +@@ -42617,7 +44884,6 @@ + } + pFd->pMapRegion = pNew; + pFd->mmapSize = nMap; +- pFd->mmapSizeActual = nMap; + } + + OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n", +@@ -43110,6 +45376,14 @@ + return (attr!=INVALID_FILE_ATTRIBUTES) && (attr&FILE_ATTRIBUTE_DIRECTORY); + } + ++/* forward reference */ ++static int winAccess( ++ sqlite3_vfs *pVfs, /* Not used on win32 */ ++ const char *zFilename, /* Name of file to check */ ++ int flags, /* Type of test to make on this file */ ++ int *pResOut /* OUT: Result */ ++); ++ + /* + ** Open a file. + */ +@@ -43286,37 +45560,58 @@ + extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS; + extendedParameters.lpSecurityAttributes = NULL; + extendedParameters.hTemplateFile = NULL; +- while( (h = osCreateFile2((LPCWSTR)zConverted, +- dwDesiredAccess, +- dwShareMode, +- dwCreationDisposition, +- &extendedParameters))==INVALID_HANDLE_VALUE && +- winRetryIoerr(&cnt, &lastErrno) ){ +- /* Noop */ +- } ++ do{ ++ h = osCreateFile2((LPCWSTR)zConverted, ++ dwDesiredAccess, ++ 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 +- while( (h = osCreateFileW((LPCWSTR)zConverted, +- dwDesiredAccess, +- dwShareMode, NULL, +- dwCreationDisposition, +- dwFlagsAndAttributes, +- NULL))==INVALID_HANDLE_VALUE && +- winRetryIoerr(&cnt, &lastErrno) ){ +- /* Noop */ +- } ++ 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{ +- while( (h = osCreateFileA((LPCSTR)zConverted, +- dwDesiredAccess, +- dwShareMode, NULL, +- dwCreationDisposition, +- dwFlagsAndAttributes, +- NULL))==INVALID_HANDLE_VALUE && +- winRetryIoerr(&cnt, &lastErrno) ){ +- /* Noop */ +- } ++ 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__); +@@ -43325,8 +45620,6 @@ + dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok")); + + if( h==INVALID_HANDLE_VALUE ){ +- pFile->lastErrno = lastErrno; +- winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name); + sqlite3_free(zConverted); + sqlite3_free(zTmpname); + if( isReadWrite && !isExclusive ){ +@@ -43335,6 +45628,8 @@ + ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)), + pOutFlags); + }else{ ++ pFile->lastErrno = lastErrno; ++ winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name); + return SQLITE_CANTOPEN_BKPT; + } + } +@@ -43390,7 +45685,6 @@ + pFile->hMap = NULL; + pFile->pMapRegion = 0; + pFile->mmapSize = 0; +- pFile->mmapSizeActual = 0; + pFile->mmapSizeMax = sqlite3GlobalConfig.szMmap; + #endif + +@@ -43927,9 +46221,6 @@ + EntropyGatherer e; + UNUSED_PARAMETER(pVfs); + memset(zBuf, 0, nBuf); +-#if defined(_MSC_VER) && _MSC_VER>=1400 && !SQLITE_OS_WINCE +- rand_s((unsigned int*)zBuf); /* rand_s() is not available with MinGW */ +-#endif /* defined(_MSC_VER) && _MSC_VER>=1400 */ + e.a = (unsigned char*)zBuf; + e.na = nBuf; + e.nXor = 0; +@@ -44224,6 +46515,10 @@ + sqlite3_vfs_register(&winLongPathNolockVfs, 0); + #endif + ++#ifndef SQLITE_OMIT_WAL ++ winBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1); ++#endif ++ + return SQLITE_OK; + } + +@@ -44234,6 +46529,11 @@ + sleepObj = NULL; + } + #endif ++ ++#ifndef SQLITE_OMIT_WAL ++ winBigLock = 0; ++#endif ++ + return SQLITE_OK; + } + +@@ -44240,6 +46540,598 @@ + #endif /* SQLITE_OS_WIN */ + + /************** End of os_win.c **********************************************/ ++/************** Begin file memdb.c *******************************************/ ++/* ++** 2016-09-07 ++** ++** The author disclaims copyright to this source code. In place of ++** a legal notice, here is a blessing: ++** ++** May you do good and not evil. ++** May you find forgiveness for yourself and forgive others. ++** May you share freely, never taking more than you give. ++** ++****************************************************************************** ++** ++** This file implements an in-memory VFS. A database is held as a contiguous ++** block of memory. ++** ++** This file also implements interface sqlite3_serialize() and ++** sqlite3_deserialize(). ++*/ ++/* #include "sqliteInt.h" */ ++#ifdef SQLITE_ENABLE_DESERIALIZE ++ ++/* ++** Forward declaration of objects used by this utility ++*/ ++typedef struct sqlite3_vfs MemVfs; ++typedef struct MemFile MemFile; ++ ++/* Access to a lower-level VFS that (might) implement dynamic loading, ++** access to randomness, etc. ++*/ ++#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData)) ++ ++/* An open file */ ++struct MemFile { ++ sqlite3_file base; /* IO methods */ ++ sqlite3_int64 sz; /* Size of the file */ ++ sqlite3_int64 szMax; /* Space allocated to aData */ ++ unsigned char *aData; /* content of the file */ ++ int nMmap; /* Number of memory mapped pages */ ++ unsigned mFlags; /* Flags */ ++ int eLock; /* Most recent lock against this file */ ++}; ++ ++/* ++** Methods for MemFile ++*/ ++static int memdbClose(sqlite3_file*); ++static int memdbRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); ++static int memdbWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst); ++static int memdbTruncate(sqlite3_file*, sqlite3_int64 size); ++static int memdbSync(sqlite3_file*, int flags); ++static int memdbFileSize(sqlite3_file*, sqlite3_int64 *pSize); ++static int memdbLock(sqlite3_file*, int); ++/* static int memdbCheckReservedLock(sqlite3_file*, int *pResOut);// not used */ ++static int memdbFileControl(sqlite3_file*, int op, void *pArg); ++/* static int memdbSectorSize(sqlite3_file*); // not used */ ++static int memdbDeviceCharacteristics(sqlite3_file*); ++static int memdbFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp); ++static int memdbUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p); ++ ++/* ++** Methods for MemVfs ++*/ ++static int memdbOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); ++/* static int memdbDelete(sqlite3_vfs*, const char *zName, int syncDir); */ ++static int memdbAccess(sqlite3_vfs*, const char *zName, int flags, int *); ++static int memdbFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); ++static void *memdbDlOpen(sqlite3_vfs*, const char *zFilename); ++static void memdbDlError(sqlite3_vfs*, int nByte, char *zErrMsg); ++static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void); ++static void memdbDlClose(sqlite3_vfs*, void*); ++static int memdbRandomness(sqlite3_vfs*, int nByte, char *zOut); ++static int memdbSleep(sqlite3_vfs*, int microseconds); ++/* static int memdbCurrentTime(sqlite3_vfs*, double*); */ ++static int memdbGetLastError(sqlite3_vfs*, int, char *); ++static int memdbCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*); ++ ++static sqlite3_vfs memdb_vfs = { ++ 2, /* iVersion */ ++ 0, /* szOsFile (set when registered) */ ++ 1024, /* mxPathname */ ++ 0, /* pNext */ ++ "memdb", /* zName */ ++ 0, /* pAppData (set when registered) */ ++ memdbOpen, /* xOpen */ ++ 0, /* memdbDelete, */ /* xDelete */ ++ memdbAccess, /* xAccess */ ++ memdbFullPathname, /* xFullPathname */ ++ memdbDlOpen, /* xDlOpen */ ++ memdbDlError, /* xDlError */ ++ memdbDlSym, /* xDlSym */ ++ memdbDlClose, /* xDlClose */ ++ memdbRandomness, /* xRandomness */ ++ memdbSleep, /* xSleep */ ++ 0, /* memdbCurrentTime, */ /* xCurrentTime */ ++ memdbGetLastError, /* xGetLastError */ ++ memdbCurrentTimeInt64 /* xCurrentTimeInt64 */ ++}; ++ ++static const sqlite3_io_methods memdb_io_methods = { ++ 3, /* iVersion */ ++ memdbClose, /* xClose */ ++ memdbRead, /* xRead */ ++ memdbWrite, /* xWrite */ ++ memdbTruncate, /* xTruncate */ ++ memdbSync, /* xSync */ ++ memdbFileSize, /* xFileSize */ ++ memdbLock, /* xLock */ ++ memdbLock, /* xUnlock - same as xLock in this case */ ++ 0, /* memdbCheckReservedLock, */ /* xCheckReservedLock */ ++ memdbFileControl, /* xFileControl */ ++ 0, /* memdbSectorSize,*/ /* xSectorSize */ ++ memdbDeviceCharacteristics, /* xDeviceCharacteristics */ ++ 0, /* xShmMap */ ++ 0, /* xShmLock */ ++ 0, /* xShmBarrier */ ++ 0, /* xShmUnmap */ ++ memdbFetch, /* xFetch */ ++ memdbUnfetch /* xUnfetch */ ++}; ++ ++ ++ ++/* ++** Close an memdb-file. ++** ++** The pData pointer is owned by the application, so there is nothing ++** to free. ++*/ ++static int memdbClose(sqlite3_file *pFile){ ++ MemFile *p = (MemFile *)pFile; ++ if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ) sqlite3_free(p->aData); ++ return SQLITE_OK; ++} ++ ++/* ++** Read data from an memdb-file. ++*/ ++static int memdbRead( ++ sqlite3_file *pFile, ++ void *zBuf, ++ int iAmt, ++ sqlite_int64 iOfst ++){ ++ MemFile *p = (MemFile *)pFile; ++ if( iOfst+iAmt>p->sz ){ ++ memset(zBuf, 0, iAmt); ++ if( iOfst<p->sz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst); ++ return SQLITE_IOERR_SHORT_READ; ++ } ++ memcpy(zBuf, p->aData+iOfst, iAmt); ++ return SQLITE_OK; ++} ++ ++/* ++** Try to enlarge the memory allocation to hold at least sz bytes ++*/ ++static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){ ++ unsigned char *pNew; ++ if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || p->nMmap>0 ){ ++ return SQLITE_FULL; ++ } ++ pNew = sqlite3_realloc64(p->aData, newSz); ++ if( pNew==0 ) return SQLITE_NOMEM; ++ p->aData = pNew; ++ p->szMax = newSz; ++ return SQLITE_OK; ++} ++ ++/* ++** Write data to an memdb-file. ++*/ ++static int memdbWrite( ++ sqlite3_file *pFile, ++ const void *z, ++ int iAmt, ++ sqlite_int64 iOfst ++){ ++ MemFile *p = (MemFile *)pFile; ++ if( iOfst+iAmt>p->sz ){ ++ int rc; ++ if( iOfst+iAmt>p->szMax ++ && (rc = memdbEnlarge(p, (iOfst+iAmt)*2))!=SQLITE_OK ++ ){ ++ return rc; ++ } ++ if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz); ++ p->sz = iOfst+iAmt; ++ } ++ memcpy(p->aData+iOfst, z, iAmt); ++ return SQLITE_OK; ++} ++ ++/* ++** Truncate an memdb-file. ++** ++** In rollback mode (which is always the case for memdb, as it does not ++** support WAL mode) the truncate() method is only used to reduce ++** the size of a file, never to increase the size. ++*/ ++static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){ ++ MemFile *p = (MemFile *)pFile; ++ if( NEVER(size>p->sz) ) return SQLITE_FULL; ++ p->sz = size; ++ return SQLITE_OK; ++} ++ ++/* ++** Sync an memdb-file. ++*/ ++static int memdbSync(sqlite3_file *pFile, int flags){ ++ return SQLITE_OK; ++} ++ ++/* ++** Return the current file-size of an memdb-file. ++*/ ++static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ ++ MemFile *p = (MemFile *)pFile; ++ *pSize = p->sz; ++ return SQLITE_OK; ++} ++ ++/* ++** Lock an memdb-file. ++*/ ++static int memdbLock(sqlite3_file *pFile, int eLock){ ++ MemFile *p = (MemFile *)pFile; ++ p->eLock = eLock; ++ return SQLITE_OK; ++} ++ ++#if 0 /* Never used because memdbAccess() always returns false */ ++/* ++** Check if another file-handle holds a RESERVED lock on an memdb-file. ++*/ ++static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){ ++ *pResOut = 0; ++ return SQLITE_OK; ++} ++#endif ++ ++/* ++** File control method. For custom operations on an memdb-file. ++*/ ++static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){ ++ MemFile *p = (MemFile *)pFile; ++ int rc = SQLITE_NOTFOUND; ++ if( op==SQLITE_FCNTL_VFSNAME ){ ++ *(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz); ++ rc = SQLITE_OK; ++ } ++ return rc; ++} ++ ++#if 0 /* Not used because of SQLITE_IOCAP_POWERSAFE_OVERWRITE */ ++/* ++** Return the sector-size in bytes for an memdb-file. ++*/ ++static int memdbSectorSize(sqlite3_file *pFile){ ++ return 1024; ++} ++#endif ++ ++/* ++** Return the device characteristic flags supported by an memdb-file. ++*/ ++static int memdbDeviceCharacteristics(sqlite3_file *pFile){ ++ return SQLITE_IOCAP_ATOMIC | ++ SQLITE_IOCAP_POWERSAFE_OVERWRITE | ++ SQLITE_IOCAP_SAFE_APPEND | ++ SQLITE_IOCAP_SEQUENTIAL; ++} ++ ++/* Fetch a page of a memory-mapped file */ ++static int memdbFetch( ++ sqlite3_file *pFile, ++ sqlite3_int64 iOfst, ++ int iAmt, ++ void **pp ++){ ++ MemFile *p = (MemFile *)pFile; ++ p->nMmap++; ++ *pp = (void*)(p->aData + iOfst); ++ return SQLITE_OK; ++} ++ ++/* Release a memory-mapped page */ ++static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){ ++ MemFile *p = (MemFile *)pFile; ++ p->nMmap--; ++ return SQLITE_OK; ++} ++ ++/* ++** Open an mem file handle. ++*/ ++static int memdbOpen( ++ sqlite3_vfs *pVfs, ++ const char *zName, ++ sqlite3_file *pFile, ++ int flags, ++ int *pOutFlags ++){ ++ MemFile *p = (MemFile*)pFile; ++ if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){ ++ return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFile, flags, pOutFlags); ++ } ++ memset(p, 0, sizeof(*p)); ++ p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE; ++ assert( pOutFlags!=0 ); /* True because flags==SQLITE_OPEN_MAIN_DB */ ++ *pOutFlags = flags | SQLITE_OPEN_MEMORY; ++ p->base.pMethods = &memdb_io_methods; ++ return SQLITE_OK; ++} ++ ++#if 0 /* Only used to delete rollback journals, master journals, and WAL ++ ** files, none of which exist in memdb. So this routine is never used */ ++/* ++** Delete the file located at zPath. If the dirSync argument is true, ++** ensure the file-system modifications are synced to disk before ++** returning. ++*/ ++static int memdbDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ ++ return SQLITE_IOERR_DELETE; ++} ++#endif ++ ++/* ++** Test for access permissions. Return true if the requested permission ++** is available, or false otherwise. ++** ++** With memdb, no files ever exist on disk. So always return false. ++*/ ++static int memdbAccess( ++ sqlite3_vfs *pVfs, ++ const char *zPath, ++ int flags, ++ int *pResOut ++){ ++ *pResOut = 0; ++ return SQLITE_OK; ++} ++ ++/* ++** Populate buffer zOut with the full canonical pathname corresponding ++** to the pathname in zPath. zOut is guaranteed to point to a buffer ++** of at least (INST_MAX_PATHNAME+1) bytes. ++*/ ++static int memdbFullPathname( ++ sqlite3_vfs *pVfs, ++ const char *zPath, ++ int nOut, ++ char *zOut ++){ ++ sqlite3_snprintf(nOut, zOut, "%s", zPath); ++ return SQLITE_OK; ++} ++ ++/* ++** Open the dynamic library located at zPath and return a handle. ++*/ ++static void *memdbDlOpen(sqlite3_vfs *pVfs, const char *zPath){ ++ return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath); ++} ++ ++/* ++** Populate the buffer zErrMsg (size nByte bytes) with a human readable ++** utf-8 string describing the most recent error encountered associated ++** with dynamic libraries. ++*/ ++static void memdbDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ ++ ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg); ++} ++ ++/* ++** Return a pointer to the symbol zSymbol in the dynamic library pHandle. ++*/ ++static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){ ++ return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym); ++} ++ ++/* ++** Close the dynamic library handle pHandle. ++*/ ++static void memdbDlClose(sqlite3_vfs *pVfs, void *pHandle){ ++ ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle); ++} ++ ++/* ++** Populate the buffer pointed to by zBufOut with nByte bytes of ++** random data. ++*/ ++static int memdbRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ ++ return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut); ++} ++ ++/* ++** Sleep for nMicro microseconds. Return the number of microseconds ++** actually slept. ++*/ ++static int memdbSleep(sqlite3_vfs *pVfs, int nMicro){ ++ return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro); ++} ++ ++#if 0 /* Never used. Modern cores only call xCurrentTimeInt64() */ ++/* ++** Return the current time as a Julian Day number in *pTimeOut. ++*/ ++static int memdbCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ ++ return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut); ++} ++#endif ++ ++static int memdbGetLastError(sqlite3_vfs *pVfs, int a, char *b){ ++ return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b); ++} ++static int memdbCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){ ++ return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p); ++} ++ ++/* ++** Translate a database connection pointer and schema name into a ++** MemFile pointer. ++*/ ++static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){ ++ MemFile *p = 0; ++ int rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p); ++ if( rc ) return 0; ++ if( p->base.pMethods!=&memdb_io_methods ) return 0; ++ return p; ++} ++ ++/* ++** Return the serialization of a database ++*/ ++SQLITE_API unsigned char *sqlite3_serialize( ++ sqlite3 *db, /* The database connection */ ++ const char *zSchema, /* Which database within the connection */ ++ sqlite3_int64 *piSize, /* Write size here, if not NULL */ ++ unsigned int mFlags /* Maybe SQLITE_SERIALIZE_NOCOPY */ ++){ ++ MemFile *p; ++ int iDb; ++ Btree *pBt; ++ sqlite3_int64 sz; ++ int szPage = 0; ++ sqlite3_stmt *pStmt = 0; ++ unsigned char *pOut; ++ char *zSql; ++ int rc; ++ ++#ifdef SQLITE_ENABLE_API_ARMOR ++ if( !sqlite3SafetyCheckOk(db) ){ ++ (void)SQLITE_MISUSE_BKPT; ++ return 0; ++ } ++#endif ++ ++ if( zSchema==0 ) zSchema = db->aDb[0].zDbSName; ++ p = memdbFromDbSchema(db, zSchema); ++ iDb = sqlite3FindDbName(db, zSchema); ++ if( piSize ) *piSize = -1; ++ if( iDb<0 ) return 0; ++ if( p ){ ++ if( piSize ) *piSize = p->sz; ++ if( mFlags & SQLITE_SERIALIZE_NOCOPY ){ ++ pOut = p->aData; ++ }else{ ++ pOut = sqlite3_malloc64( p->sz ); ++ if( pOut ) memcpy(pOut, p->aData, p->sz); ++ } ++ return pOut; ++ } ++ pBt = db->aDb[iDb].pBt; ++ if( pBt==0 ) return 0; ++ szPage = sqlite3BtreeGetPageSize(pBt); ++ zSql = sqlite3_mprintf("PRAGMA \"%w\".page_count", zSchema); ++ rc = zSql ? sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0) : SQLITE_NOMEM; ++ sqlite3_free(zSql); ++ if( rc ) return 0; ++ rc = sqlite3_step(pStmt); ++ if( rc!=SQLITE_ROW ){ ++ pOut = 0; ++ }else{ ++ sz = sqlite3_column_int64(pStmt, 0)*szPage; ++ if( piSize ) *piSize = sz; ++ if( mFlags & SQLITE_SERIALIZE_NOCOPY ){ ++ pOut = 0; ++ }else{ ++ pOut = sqlite3_malloc64( sz ); ++ if( pOut ){ ++ int nPage = sqlite3_column_int(pStmt, 0); ++ Pager *pPager = sqlite3BtreePager(pBt); ++ int pgno; ++ for(pgno=1; pgno<=nPage; pgno++){ ++ DbPage *pPage = 0; ++ unsigned char *pTo = pOut + szPage*(sqlite3_int64)(pgno-1); ++ rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pPage, 0); ++ if( rc==SQLITE_OK ){ ++ memcpy(pTo, sqlite3PagerGetData(pPage), szPage); ++ }else{ ++ memset(pTo, 0, szPage); ++ } ++ sqlite3PagerUnref(pPage); ++ } ++ } ++ } ++ } ++ sqlite3_finalize(pStmt); ++ return pOut; ++} ++ ++/* Convert zSchema to a MemDB and initialize its content. ++*/ ++SQLITE_API int sqlite3_deserialize( ++ sqlite3 *db, /* The database connection */ ++ const char *zSchema, /* Which DB to reopen with the deserialization */ ++ unsigned char *pData, /* The serialized database content */ ++ sqlite3_int64 szDb, /* Number bytes in the deserialization */ ++ sqlite3_int64 szBuf, /* Total size of buffer pData[] */ ++ unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */ ++){ ++ MemFile *p; ++ char *zSql; ++ sqlite3_stmt *pStmt = 0; ++ int rc; ++ int iDb; ++ ++#ifdef SQLITE_ENABLE_API_ARMOR ++ if( !sqlite3SafetyCheckOk(db) ){ ++ return SQLITE_MISUSE_BKPT; ++ } ++ if( szDb<0 ) return SQLITE_MISUSE_BKPT; ++ if( szBuf<0 ) return SQLITE_MISUSE_BKPT; ++#endif ++ ++ sqlite3_mutex_enter(db->mutex); ++ if( zSchema==0 ) zSchema = db->aDb[0].zDbSName; ++ iDb = sqlite3FindDbName(db, zSchema); ++ if( iDb<0 ){ ++ rc = SQLITE_ERROR; ++ goto end_deserialize; ++ } ++ zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema); ++ rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); ++ sqlite3_free(zSql); ++ if( rc ) goto end_deserialize; ++ db->init.iDb = (u8)iDb; ++ db->init.reopenMemdb = 1; ++ rc = sqlite3_step(pStmt); ++ db->init.reopenMemdb = 0; ++ if( rc!=SQLITE_DONE ){ ++ rc = SQLITE_ERROR; ++ goto end_deserialize; ++ } ++ p = memdbFromDbSchema(db, zSchema); ++ if( p==0 ){ ++ rc = SQLITE_ERROR; ++ }else{ ++ p->aData = pData; ++ p->sz = szDb; ++ p->szMax = szBuf; ++ p->mFlags = mFlags; ++ rc = SQLITE_OK; ++ } ++ ++end_deserialize: ++ sqlite3_finalize(pStmt); ++ sqlite3_mutex_leave(db->mutex); ++ return rc; ++} ++ ++/* ++** This routine is called when the extension is loaded. ++** Register the new VFS. ++*/ ++SQLITE_PRIVATE int sqlite3MemdbInit(void){ ++ sqlite3_vfs *pLower = sqlite3_vfs_find(0); ++ int sz = pLower->szOsFile; ++ memdb_vfs.pAppData = pLower; ++ /* In all known configurations of SQLite, the size of a default ++ ** sqlite3_file is greater than the size of a memdb sqlite3_file. ++ ** Should that ever change, remove the following NEVER() */ ++ if( NEVER(sz<sizeof(MemFile)) ) sz = sizeof(MemFile); ++ memdb_vfs.szOsFile = sz; ++ return sqlite3_vfs_register(&memdb_vfs, 0); ++} ++#endif /* SQLITE_ENABLE_DESERIALIZE */ ++ ++/************** End of memdb.c ***********************************************/ + /************** Begin file bitvec.c ******************************************/ + /* + ** 2008 February 16 +@@ -44689,7 +47581,7 @@ + ** The PCache.pSynced variable is used to optimize searching for a dirty + ** page to eject from the cache mid-transaction. It is better to eject + ** a page that does not require a journal sync than one that does. +-** Therefore, pSynced is maintained to that it *almost* always points ++** Therefore, pSynced is maintained so that it *almost* always points + ** to either the oldest page in the pDirty/pDirtyTail list that has a + ** 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 +@@ -44848,12 +47740,9 @@ + p->eCreate = 2; + } + } +- pPage->pDirtyNext = 0; +- pPage->pDirtyPrev = 0; + } + if( addRemove & PCACHE_DIRTYLIST_ADD ){ +- assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage ); +- ++ pPage->pDirtyPrev = 0; + pPage->pDirtyNext = p->pDirty; + if( pPage->pDirtyNext ){ + assert( pPage->pDirtyNext->pDirtyPrev==0 ); +@@ -45091,7 +47980,7 @@ + sqlite3_log(SQLITE_FULL, + "spill page %d making room for %d - cache used: %d/%d", + pPg->pgno, pgno, +- sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache), ++ sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache), + numberOfCachePages(pCache)); + #endif + pcacheTrace(("%p.SPILL %d\n",pCache,pPg->pgno)); +@@ -45170,11 +48059,7 @@ + if( (--p->nRef)==0 ){ + if( p->flags&PGHDR_CLEAN ){ + pcacheUnpin(p); +- }else if( p->pDirtyPrev!=0 ){ /*OPTIMIZATION-IF-FALSE*/ +- /* Move the page to the head of the dirty list. If p->pDirtyPrev==0, +- ** then page p is already at the head of the dirty list and the +- ** following call would be a no-op. Hence the OPTIMIZATION-IF-FALSE +- ** tag above. */ ++ }else{ + pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT); + } + } +@@ -45230,16 +48115,15 @@ + */ + SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr *p){ + assert( sqlite3PcachePageSanity(p) ); +- if( ALWAYS((p->flags & PGHDR_DIRTY)!=0) ){ +- assert( (p->flags & PGHDR_CLEAN)==0 ); +- pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE); +- p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC|PGHDR_WRITEABLE); +- p->flags |= PGHDR_CLEAN; +- pcacheTrace(("%p.CLEAN %d\n",p->pCache,p->pgno)); +- assert( sqlite3PcachePageSanity(p) ); +- if( p->nRef==0 ){ +- pcacheUnpin(p); +- } ++ assert( (p->flags & PGHDR_DIRTY)!=0 ); ++ assert( (p->flags & PGHDR_CLEAN)==0 ); ++ pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE); ++ p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC|PGHDR_WRITEABLE); ++ p->flags |= PGHDR_CLEAN; ++ pcacheTrace(("%p.CLEAN %d\n",p->pCache,p->pgno)); ++ assert( sqlite3PcachePageSanity(p) ); ++ if( p->nRef==0 ){ ++ pcacheUnpin(p); + } + } + +@@ -45521,6 +48405,15 @@ + return nCache ? (int)(((i64)nDirty * 100) / nCache) : 0; + } + ++#ifdef SQLITE_DIRECT_OVERFLOW_READ ++/* ++** Return true if there are one or more dirty pages in the cache. Else false. ++*/ ++SQLITE_PRIVATE int sqlite3PCacheIsDirty(PCache *pCache){ ++ return (pCache->pDirty!=0); ++} ++#endif ++ + #if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) + /* + ** For all dirty pages currently in the cache, invoke the specified +@@ -45635,7 +48528,6 @@ + struct PgHdr1 { + sqlite3_pcache_page page; /* Base class. Must be first. pBuf & pExtra */ + unsigned int iKey; /* Key value (page number) */ +- u8 isPinned; /* Page in use, not on the LRU list */ + u8 isBulkLocal; /* This page from bulk local storage */ + u8 isAnchor; /* This is the PGroup.lru element */ + PgHdr1 *pNext; /* Next in hash table chain */ +@@ -45644,6 +48536,13 @@ + PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */ + }; + ++/* ++** A page is pinned if it is not on the LRU list. To be "pinned" means ++** that the page is in active use and must not be deallocated. ++*/ ++#define PAGE_IS_PINNED(p) ((p)->pLruNext==0) ++#define PAGE_IS_UNPINNED(p) ((p)->pLruNext!=0) ++ + /* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set + ** of one or more PCaches that are able to recycle each other's unpinned + ** pages when they are under memory pressure. A PGroup is an instance of +@@ -45671,7 +48570,7 @@ + unsigned int nMaxPage; /* Sum of nMax for purgeable caches */ + unsigned int nMinPage; /* Sum of nMin for purgeable caches */ + unsigned int mxPinned; /* nMaxpage + 10 - nMinPage */ +- unsigned int nCurrentPage; /* Number of purgeable pages allocated */ ++ unsigned int nPurgeable; /* Number of purgeable pages allocated */ + PgHdr1 lru; /* The beginning and end of the LRU list */ + }; + +@@ -45685,11 +48584,13 @@ + */ + struct PCache1 { + /* Cache configuration parameters. Page size (szPage) and the purgeable +- ** flag (bPurgeable) are set when the cache is created. nMax may be ++ ** flag (bPurgeable) and the pnPurgeable pointer are all set when the ++ ** cache is created and are never changed thereafter. nMax may be + ** modified at any time by a call to the pcache1Cachesize() method. + ** The PGroup mutex must be held when accessing nMax. + */ + PGroup *pGroup; /* PGroup this cache belongs to */ ++ unsigned int *pnPurgeable; /* Pointer to pGroup->nPurgeable */ + int szPage; /* Size of database content section */ + int szExtra; /* sizeof(MemPage)+sizeof(PgHdr) */ + int szAlloc; /* Total size of one pcache line */ +@@ -45784,6 +48685,7 @@ + if( pcache1.isInit ){ + PgFreeslot *p; + if( pBuf==0 ) sz = n = 0; ++ if( n==0 ) sz = 0; + sz = ROUNDDOWN8(sz); + pcache1.szSlot = sz; + pcache1.nSlot = pcache1.nFreeSlot = n; +@@ -45976,9 +48878,7 @@ + p->isBulkLocal = 0; + p->isAnchor = 0; + } +- if( pCache->bPurgeable ){ +- pCache->pGroup->nCurrentPage++; +- } ++ (*pCache->pnPurgeable)++; + return p; + } + +@@ -45999,9 +48899,7 @@ + sqlite3_free(p); + #endif + } +- if( pCache->bPurgeable ){ +- pCache->pGroup->nCurrentPage--; +- } ++ (*pCache->pnPurgeable)--; + } + + /* +@@ -46096,22 +48994,18 @@ + ** The PGroup mutex must be held when this function is called. + */ + static PgHdr1 *pcache1PinPage(PgHdr1 *pPage){ +- PCache1 *pCache; +- + assert( pPage!=0 ); +- assert( pPage->isPinned==0 ); +- pCache = pPage->pCache; ++ assert( PAGE_IS_UNPINNED(pPage) ); + assert( pPage->pLruNext ); + assert( pPage->pLruPrev ); +- assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); ++ assert( sqlite3_mutex_held(pPage->pCache->pGroup->mutex) ); + pPage->pLruPrev->pLruNext = pPage->pLruNext; + pPage->pLruNext->pLruPrev = pPage->pLruPrev; + pPage->pLruNext = 0; + pPage->pLruPrev = 0; +- pPage->isPinned = 1; + assert( pPage->isAnchor==0 ); +- assert( pCache->pGroup->lru.isAnchor==1 ); +- pCache->nRecyclable--; ++ assert( pPage->pCache->pGroup->lru.isAnchor==1 ); ++ pPage->pCache->nRecyclable--; + return pPage; + } + +@@ -46145,11 +49039,11 @@ + PGroup *pGroup = pCache->pGroup; + PgHdr1 *p; + assert( sqlite3_mutex_held(pGroup->mutex) ); +- while( pGroup->nCurrentPage>pGroup->nMaxPage ++ while( pGroup->nPurgeable>pGroup->nMaxPage + && (p=pGroup->lru.pLruPrev)->isAnchor==0 + ){ + assert( p->pCache->pGroup==pGroup ); +- assert( p->isPinned==0 ); ++ assert( PAGE_IS_UNPINNED(p) ); + pcache1PinPage(p); + pcache1RemoveFromHash(p, 1); + } +@@ -46198,7 +49092,7 @@ + if( pPage->iKey>=iLimit ){ + pCache->nPage--; + *pp = pPage->pNext; +- if( !pPage->isPinned ) pcache1PinPage(pPage); ++ if( PAGE_IS_UNPINNED(pPage) ) pcache1PinPage(pPage); + pcache1FreePage(pPage); + }else{ + pp = &pPage->pNext; +@@ -46316,6 +49210,10 @@ + pCache->nMin = 10; + pGroup->nMinPage += pCache->nMin; + pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; ++ pCache->pnPurgeable = &pGroup->nPurgeable; ++ }else{ ++ static unsigned int dummyCurrentPage; ++ pCache->pnPurgeable = &dummyCurrentPage; + } + pcache1LeaveMutex(pGroup); + if( pCache->nHash==0 ){ +@@ -46417,7 +49315,7 @@ + ){ + PCache1 *pOther; + pPage = pGroup->lru.pLruPrev; +- assert( pPage->isPinned==0 ); ++ assert( PAGE_IS_UNPINNED(pPage) ); + pcache1RemoveFromHash(pPage, 0); + pcache1PinPage(pPage); + pOther = pPage->pCache; +@@ -46425,7 +49323,7 @@ + pcache1FreePage(pPage); + pPage = 0; + }else{ +- pGroup->nCurrentPage -= (pOther->bPurgeable - pCache->bPurgeable); ++ pGroup->nPurgeable -= (pOther->bPurgeable - pCache->bPurgeable); + } + } + +@@ -46444,7 +49342,6 @@ + pPage->pCache = pCache; + pPage->pLruPrev = 0; + pPage->pLruNext = 0; +- pPage->isPinned = 1; + *(void **)pPage->page.pExtra = 0; + pCache->apHash[h] = pPage; + if( iKey>pCache->iMaxKey ){ +@@ -46530,7 +49427,7 @@ + ** Otherwise (page not in hash and createFlag!=0) continue with + ** subsequent steps to try to create the page. */ + if( pPage ){ +- if( !pPage->isPinned ){ ++ if( PAGE_IS_UNPINNED(pPage) ){ + return pcache1PinPage(pPage); + }else{ + return pPage; +@@ -46605,9 +49502,9 @@ + ** part of the PGroup LRU list. + */ + assert( pPage->pLruPrev==0 && pPage->pLruNext==0 ); +- assert( pPage->isPinned==1 ); ++ assert( PAGE_IS_PINNED(pPage) ); + +- if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){ ++ if( reuseUnlikely || pGroup->nPurgeable>pGroup->nMaxPage ){ + pcache1RemoveFromHash(pPage, 1); + }else{ + /* Add the page to the PGroup LRU list. */ +@@ -46616,7 +49513,6 @@ + (pPage->pLruNext = *ppFirst)->pLruPrev = pPage; + *ppFirst = pPage; + pCache->nRecyclable++; +- pPage->isPinned = 0; + } + + pcache1LeaveMutex(pCache->pGroup); +@@ -46760,7 +49656,7 @@ + #ifdef SQLITE_PCACHE_SEPARATE_HEADER + nFree += sqlite3MemSize(p); + #endif +- assert( p->isPinned==0 ); ++ assert( PAGE_IS_UNPINNED(p) ); + pcache1PinPage(p); + pcache1RemoveFromHash(p, 1); + } +@@ -46784,10 +49680,10 @@ + PgHdr1 *p; + int nRecyclable = 0; + for(p=pcache1.grp.lru.pLruNext; p && !p->isAnchor; p=p->pLruNext){ +- assert( p->isPinned==0 ); ++ assert( PAGE_IS_UNPINNED(p) ); + nRecyclable++; + } +- *pnCurrent = pcache1.grp.nCurrentPage; ++ *pnCurrent = pcache1.grp.nPurgeable; + *pnMax = (int)pcache1.grp.nMaxPage; + *pnMin = (int)pcache1.grp.nMinPage; + *pnRecyclable = nRecyclable; +@@ -46922,30 +49818,23 @@ + #define ROWSET_NEXT 0x02 /* True if sqlite3RowSetNext() has been called */ + + /* +-** Turn bulk memory into a RowSet object. N bytes of memory +-** are available at pSpace. The db pointer is used as a memory context +-** for any subsequent allocations that need to occur. +-** Return a pointer to the new RowSet object. +-** +-** It must be the case that N is sufficient to make a Rowset. If not +-** an assertion fault occurs. +-** +-** If N is larger than the minimum, use the surplus as an initial +-** allocation of entries available to be filled. ++** Allocate a RowSet object. Return NULL if a memory allocation ++** error occurs. + */ +-SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3 *db, void *pSpace, unsigned int N){ +- RowSet *p; +- assert( N >= ROUND8(sizeof(*p)) ); +- p = pSpace; +- p->pChunk = 0; +- p->db = db; +- p->pEntry = 0; +- p->pLast = 0; +- p->pForest = 0; +- p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p); +- p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry)); +- p->rsFlags = ROWSET_SORTED; +- p->iBatch = 0; ++SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3 *db){ ++ RowSet *p = sqlite3DbMallocRawNN(db, sizeof(*p)); ++ if( p ){ ++ int N = sqlite3DbMallocSize(db, p); ++ p->pChunk = 0; ++ p->db = db; ++ p->pEntry = 0; ++ p->pLast = 0; ++ p->pForest = 0; ++ p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p); ++ p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry)); ++ p->rsFlags = ROWSET_SORTED; ++ p->iBatch = 0; ++ } + return p; + } + +@@ -46954,7 +49843,8 @@ + ** the RowSet has allocated over its lifetime. This routine is + ** the destructor for the RowSet. + */ +-SQLITE_PRIVATE void sqlite3RowSetClear(RowSet *p){ ++SQLITE_PRIVATE void sqlite3RowSetClear(void *pArg){ ++ RowSet *p = (RowSet*)pArg; + struct RowSetChunk *pChunk, *pNextChunk; + for(pChunk=p->pChunk; pChunk; pChunk = pNextChunk){ + pNextChunk = pChunk->pNextChunk; +@@ -46969,6 +49859,16 @@ + } + + /* ++** Deallocate all chunks from a RowSet. This frees all memory that ++** the RowSet has allocated over its lifetime. This routine is ++** the destructor for the RowSet. ++*/ ++SQLITE_PRIVATE void sqlite3RowSetDelete(void *pArg){ ++ sqlite3RowSetClear(pArg); ++ sqlite3DbFree(((RowSet*)pArg)->db, pArg); ++} ++ ++/* + ** Allocate a new RowSetEntry object that is associated with the + ** given RowSet. Return a pointer to the new and completely uninitialized + ** objected. +@@ -47342,11 +50242,11 @@ + + /* #include "sqliteInt.h" */ + +-/* Additional values that can be added to the sync_flags argument of +-** sqlite3WalFrames(): ++/* Macros for extracting appropriate sync flags for either transaction ++** commits (WAL_SYNC_FLAGS(X)) or for checkpoint ops (CKPT_SYNC_FLAGS(X)): + */ +-#define WAL_SYNC_TRANSACTIONS 0x20 /* Sync at the end of each transaction */ +-#define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */ ++#define WAL_SYNC_FLAGS(X) ((X)&0x03) ++#define CKPT_SYNC_FLAGS(X) (((X)>>2)&0x03) + + #ifdef SQLITE_OMIT_WAL + # define sqlite3WalOpen(x,y,z) 0 +@@ -47455,6 +50355,8 @@ + SQLITE_PRIVATE int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot); + SQLITE_PRIVATE void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot); + SQLITE_PRIVATE int sqlite3WalSnapshotRecover(Wal *pWal); ++SQLITE_PRIVATE int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot); ++SQLITE_PRIVATE void sqlite3WalSnapshotUnlock(Wal *pWal); + #endif + + #ifdef SQLITE_ENABLE_ZIPVFS +@@ -47579,8 +50481,8 @@ + ** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file + ** struct as its argument. + */ +-#define PAGERID(p) ((int)(p->fd)) +-#define FILEHANDLEID(fd) ((int)fd) ++#define PAGERID(p) (SQLITE_PTR_TO_INT(p->fd)) ++#define FILEHANDLEID(fd) (SQLITE_PTR_TO_INT(fd)) + + /* + ** The Pager.eState variable stores the current 'state' of a pager. A +@@ -48067,6 +50969,18 @@ + ** is set to zero in all other states. In PAGER_ERROR state, Pager.errCode + ** is always set to SQLITE_FULL, SQLITE_IOERR or one of the SQLITE_IOERR_XXX + ** sub-codes. ++** ++** syncFlags, walSyncFlags ++** ++** syncFlags is either SQLITE_SYNC_NORMAL (0x02) or SQLITE_SYNC_FULL (0x03). ++** syncFlags is used for rollback mode. walSyncFlags is used for WAL mode ++** and contains the flags used to sync the checkpoint operations in the ++** lower two bits, and sync flags used for transaction commits in the WAL ++** file in bits 0x04 and 0x08. In other words, to get the correct sync flags ++** for checkpoint operations, use (walSyncFlags&0x03) and to get the correct ++** sync flags for transaction commit, use ((walSyncFlags>>2)&0x03). Note ++** that with synchronous=NORMAL in WAL mode, transaction commit is not synced ++** meaning that the 0x04 and 0x08 bits are both zero. + */ + struct Pager { + sqlite3_vfs *pVfs; /* OS functions to use for IO */ +@@ -48076,9 +50990,8 @@ + u8 noSync; /* Do not sync the journal if true */ + u8 fullSync; /* Do extra syncs of the journal for robustness */ + u8 extraSync; /* sync directory after journal delete */ +- u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */ +- u8 walSyncFlags; /* SYNC_NORMAL or SYNC_FULL for wal writes */ + u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */ ++ u8 walSyncFlags; /* See description above */ + u8 tempFile; /* zFilename is a temporary or immutable file */ + u8 noLock; /* Do not lock (except in WAL mode) */ + u8 readOnly; /* True for a read-only database */ +@@ -48139,7 +51052,7 @@ + char *zJournal; /* Name of the journal file */ + int (*xBusyHandler)(void*); /* Function to call when busy */ + void *pBusyHandlerArg; /* Context argument for xBusyHandler */ +- int aStat[3]; /* Total cache hits, misses and writes */ ++ int aStat[4]; /* Total cache hits, misses, writes, spills */ + #ifdef SQLITE_TEST + int nRead; /* Database pages read */ + #endif +@@ -48167,6 +51080,7 @@ + #define PAGER_STAT_HIT 0 + #define PAGER_STAT_MISS 1 + #define PAGER_STAT_WRITE 2 ++#define PAGER_STAT_SPILL 3 + + /* + ** The following global variables hold counters used for +@@ -48264,19 +51178,30 @@ + */ + #define isOpen(pFd) ((pFd)->pMethods!=0) + ++#ifdef SQLITE_DIRECT_OVERFLOW_READ + /* +-** Return true if this pager uses a write-ahead log to read page pgno. +-** Return false if the pager reads pgno directly from the database. ++** Return true if page pgno can be read directly from the database file ++** by the b-tree layer. This is the case if: ++** ++** * the database file is open, ++** * there are no dirty pages in the cache, and ++** * the desired page is not currently in the wal file. + */ +-#if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_DIRECT_OVERFLOW_READ) +-SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager, Pgno pgno){ +- u32 iRead = 0; +- int rc; +- if( pPager->pWal==0 ) return 0; +- rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead); +- return rc || iRead; ++SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){ ++ if( pPager->fd->pMethods==0 ) return 0; ++ if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0; ++#ifndef SQLITE_OMIT_WAL ++ if( pPager->pWal ){ ++ u32 iRead = 0; ++ int rc; ++ rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead); ++ return (rc==SQLITE_OK && iRead==0); ++ } ++#endif ++ return 1; + } + #endif ++ + #ifndef SQLITE_OMIT_WAL + # define pagerUseWal(x) ((x)->pWal!=0) + #else +@@ -48398,6 +51323,7 @@ + assert( isOpen(p->jfd) + || p->journalMode==PAGER_JOURNALMODE_OFF + || p->journalMode==PAGER_JOURNALMODE_WAL ++ || (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC) + ); + assert( pPager->dbOrigSize<=pPager->dbHintSize ); + break; +@@ -48409,6 +51335,7 @@ + assert( isOpen(p->jfd) + || p->journalMode==PAGER_JOURNALMODE_OFF + || p->journalMode==PAGER_JOURNALMODE_WAL ++ || (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC) + ); + break; + +@@ -48434,8 +51361,12 @@ + ** to "print *pPager" in gdb: + ** + ** (gdb) printf "%s", print_pager_state(pPager) ++** ++** This routine has external linkage in order to suppress compiler warnings ++** about an unused function. It is enclosed within SQLITE_DEBUG and so does ++** not appear in normal builds. + */ +-static char *print_pager_state(Pager *p){ ++char *print_pager_state(Pager *p){ + static char zRet[1024]; + + sqlite3_snprintf(1024, zRet, +@@ -48619,8 +51550,9 @@ + } + + /* +-** This function determines whether or not the atomic-write optimization +-** can be used with this pager. The optimization can be used if: ++** This function determines whether or not the atomic-write or ++** atomic-batch-write optimizations can be used with this pager. The ++** atomic-write optimization can be used if: + ** + ** (a) the value returned by OsDeviceCharacteristics() indicates that + ** a database page may be written atomically, and +@@ -48627,27 +51559,39 @@ + ** (b) the value returned by OsSectorSize() is less than or equal + ** to the page size. + ** +-** The optimization is also always enabled for temporary files. It is +-** an error to call this function if pPager is opened on an in-memory +-** database. ++** If it can be used, then the value returned is the size of the journal ++** file when it contains rollback data for exactly one page. + ** +-** If the optimization cannot be used, 0 is returned. If it can be used, +-** then the value returned is the size of the journal file when it +-** contains rollback data for exactly one page. ++** The atomic-batch-write optimization can be used if OsDeviceCharacteristics() ++** returns a value with the SQLITE_IOCAP_BATCH_ATOMIC bit set. -1 is ++** returned in this case. ++** ++** If neither optimization can be used, 0 is returned. + */ +-#ifdef SQLITE_ENABLE_ATOMIC_WRITE + static int jrnlBufferSize(Pager *pPager){ + assert( !MEMDB ); +- if( !pPager->tempFile ){ +- int dc; /* Device characteristics */ +- int nSector; /* Sector size */ +- int szPage; /* Page size */ + +- assert( isOpen(pPager->fd) ); +- dc = sqlite3OsDeviceCharacteristics(pPager->fd); +- nSector = pPager->sectorSize; +- szPage = pPager->pageSize; ++#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \ ++ || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) ++ int dc; /* Device characteristics */ + ++ assert( isOpen(pPager->fd) ); ++ dc = sqlite3OsDeviceCharacteristics(pPager->fd); ++#else ++ UNUSED_PARAMETER(pPager); ++#endif ++ ++#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE ++ if( pPager->dbSize>0 && (dc&SQLITE_IOCAP_BATCH_ATOMIC) ){ ++ return -1; ++ } ++#endif ++ ++#ifdef SQLITE_ENABLE_ATOMIC_WRITE ++ { ++ int nSector = pPager->sectorSize; ++ int szPage = pPager->pageSize; ++ + assert(SQLITE_IOCAP_ATOMIC512==(512>>8)); + assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8)); + if( 0==(dc&(SQLITE_IOCAP_ATOMIC|(szPage>>8)) || nSector>szPage) ){ +@@ -48656,11 +51600,11 @@ + } + + return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager); +-} +-#else +-# define jrnlBufferSize(x) 0 + #endif + ++ return 0; ++} ++ + /* + ** If SQLITE_CHECK_PAGES is defined then we do some sanity checking + ** on the cache using a hash function. This is used for testing +@@ -48742,6 +51686,7 @@ + || szJ<16 + || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len)) + || len>=nMaster ++ || len>szJ-16 + || len==0 + || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum)) + || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8)) +@@ -49187,7 +52132,6 @@ + ** Return the pPager->iDataVersion value + */ + SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager *pPager){ +- assert( pPager->eState>PAGER_OPEN ); + return pPager->iDataVersion; + } + +@@ -49463,7 +52407,9 @@ + } + + releaseAllSavepoints(pPager); +- assert( isOpen(pPager->jfd) || pPager->pInJournal==0 ); ++ assert( isOpen(pPager->jfd) || pPager->pInJournal==0 ++ || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_BATCH_ATOMIC) ++ ); + if( isOpen(pPager->jfd) ){ + assert( !pagerUseWal(pPager) ); + +@@ -49551,7 +52497,7 @@ + rc = pager_truncate(pPager, pPager->dbSize); + } + +- if( rc==SQLITE_OK && bCommit && isOpen(pPager->fd) ){ ++ if( rc==SQLITE_OK && bCommit ){ + rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_COMMIT_PHASETWO, 0); + if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; + } +@@ -50231,6 +53177,7 @@ + char *zMaster = 0; /* Name of master journal file if any */ + int needPagerReset; /* True to reset page prior to first page rollback */ + int nPlayback = 0; /* Total number of pages restored from journal */ ++ u32 savedPageSize = pPager->pageSize; + + /* Figure out how many records are in the journal. Abort early if + ** the journal is empty. +@@ -50360,6 +53307,9 @@ + assert( 0 ); + + end_playback: ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3PagerSetPagesize(pPager, &savedPageSize, -1); ++ } + /* Following a rollback, the database file should be back in its original + ** state prior to the start of the transaction, so invoke the + ** SQLITE_FCNTL_DB_UNCHANGED file-control method to disable the +@@ -50366,9 +53316,7 @@ + ** assertion that the transaction counter was modified. + */ + #ifdef SQLITE_DEBUG +- if( pPager->fd->pMethods ){ +- sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0); +- } ++ sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0); + #endif + + /* If this playback is happening automatically as a result of an IO or +@@ -50418,7 +53366,8 @@ + + + /* +-** Read the content for page pPg out of the database file and into ++** Read the content for page pPg out of the database file (or out of ++** the WAL if that is where the most recent copy if found) into + ** pPg->pData. A shared lock or greater must be held on the database + ** file before this function is called. + ** +@@ -50428,30 +53377,33 @@ + ** If an IO error occurs, then the IO error is returned to the caller. + ** Otherwise, SQLITE_OK is returned. + */ +-static int readDbPage(PgHdr *pPg, u32 iFrame){ ++static int readDbPage(PgHdr *pPg){ + Pager *pPager = pPg->pPager; /* Pager object associated with page pPg */ +- Pgno pgno = pPg->pgno; /* Page number to read */ + int rc = SQLITE_OK; /* Return code */ +- int pgsz = pPager->pageSize; /* Number of bytes to read */ + ++#ifndef SQLITE_OMIT_WAL ++ u32 iFrame = 0; /* Frame of WAL containing pgno */ ++ + assert( pPager->eState>=PAGER_READER && !MEMDB ); + assert( isOpen(pPager->fd) ); + +-#ifndef SQLITE_OMIT_WAL ++ if( pagerUseWal(pPager) ){ ++ rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame); ++ if( rc ) return rc; ++ } + if( iFrame ){ +- /* Try to pull the page from the write-ahead log. */ +- rc = sqlite3WalReadFrame(pPager->pWal, iFrame, pgsz, pPg->pData); ++ rc = sqlite3WalReadFrame(pPager->pWal, iFrame,pPager->pageSize,pPg->pData); + }else + #endif + { +- i64 iOffset = (pgno-1)*(i64)pPager->pageSize; +- rc = sqlite3OsRead(pPager->fd, pPg->pData, pgsz, iOffset); ++ i64 iOffset = (pPg->pgno-1)*(i64)pPager->pageSize; ++ rc = sqlite3OsRead(pPager->fd, pPg->pData, pPager->pageSize, iOffset); + if( rc==SQLITE_IOERR_SHORT_READ ){ + rc = SQLITE_OK; + } + } + +- if( pgno==1 ){ ++ if( pPg->pgno==1 ){ + if( rc ){ + /* If the read is unsuccessful, set the dbFileVers[] to something + ** that will never be a valid file version. dbFileVers[] is a copy +@@ -50471,13 +53423,13 @@ + memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers)); + } + } +- CODEC1(pPager, pPg->pData, pgno, 3, rc = SQLITE_NOMEM_BKPT); ++ CODEC1(pPager, pPg->pData, pPg->pgno, 3, rc = SQLITE_NOMEM_BKPT); + + PAGER_INCR(sqlite3_pager_readdb_count); + PAGER_INCR(pPager->nRead); +- IOTRACE(("PGIN %p %d\n", pPager, pgno)); ++ IOTRACE(("PGIN %p %d\n", pPager, pPg->pgno)); + PAGERTRACE(("FETCH %d page %d hash(%08x)\n", +- PAGERID(pPager), pgno, pager_pagehash(pPg))); ++ PAGERID(pPager), pPg->pgno, pager_pagehash(pPg))); + + return rc; + } +@@ -50528,12 +53480,8 @@ + if( sqlite3PcachePageRefcount(pPg)==1 ){ + sqlite3PcacheDrop(pPg); + }else{ +- u32 iFrame = 0; +- rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame); ++ rc = readDbPage(pPg); + if( rc==SQLITE_OK ){ +- rc = readDbPage(pPg, iFrame); +- } +- if( rc==SQLITE_OK ){ + pPager->xReiniter(pPg); + } + sqlite3PagerUnrefNotNull(pPg); +@@ -51038,21 +53986,18 @@ + } + if( pPager->noSync ){ + pPager->syncFlags = 0; +- pPager->ckptSyncFlags = 0; + }else if( pgFlags & PAGER_FULLFSYNC ){ + pPager->syncFlags = SQLITE_SYNC_FULL; +- pPager->ckptSyncFlags = SQLITE_SYNC_FULL; +- }else if( pgFlags & PAGER_CKPT_FULLFSYNC ){ +- pPager->syncFlags = SQLITE_SYNC_NORMAL; +- pPager->ckptSyncFlags = SQLITE_SYNC_FULL; + }else{ + pPager->syncFlags = SQLITE_SYNC_NORMAL; +- pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL; + } +- pPager->walSyncFlags = pPager->syncFlags; ++ pPager->walSyncFlags = (pPager->syncFlags<<2); + if( pPager->fullSync ){ +- pPager->walSyncFlags |= WAL_SYNC_TRANSACTIONS; ++ pPager->walSyncFlags |= pPager->syncFlags; + } ++ if( (pgFlags & PAGER_CKPT_FULLFSYNC) && !pPager->noSync ){ ++ pPager->walSyncFlags |= (SQLITE_SYNC_FULL<<2); ++ } + if( pgFlags & PAGER_CACHESPILL ){ + pPager->doNotSpill &= ~SPILLFLAG_OFF; + }else{ +@@ -51124,20 +54069,18 @@ + ** retried. If it returns zero, then the SQLITE_BUSY error is + ** returned to the caller of the pager API function. + */ +-SQLITE_PRIVATE void sqlite3PagerSetBusyhandler( ++SQLITE_PRIVATE void sqlite3PagerSetBusyHandler( + Pager *pPager, /* Pager object */ + int (*xBusyHandler)(void *), /* Pointer to busy-handler function */ + void *pBusyHandlerArg /* Argument to pass to xBusyHandler */ + ){ ++ void **ap; + pPager->xBusyHandler = xBusyHandler; + pPager->pBusyHandlerArg = pBusyHandlerArg; +- +- if( isOpen(pPager->fd) ){ +- void **ap = (void **)&pPager->xBusyHandler; +- assert( ((int(*)(void *))(ap[0]))==xBusyHandler ); +- assert( ap[1]==pBusyHandlerArg ); +- sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap); +- } ++ ap = (void **)&pPager->xBusyHandler; ++ assert( ((int(*)(void *))(ap[0]))==xBusyHandler ); ++ assert( ap[1]==pBusyHandlerArg ); ++ sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap); + } + + /* +@@ -51523,7 +54466,31 @@ + } + } + ++/* Verify that the database file has not be deleted or renamed out from ++** under the pager. Return SQLITE_OK if the database is still where it ought ++** to be on disk. Return non-zero (SQLITE_READONLY_DBMOVED or some other error ++** code from sqlite3OsAccess()) if the database has gone missing. ++*/ ++static int databaseIsUnmoved(Pager *pPager){ ++ int bHasMoved = 0; ++ int rc; + ++ if( pPager->tempFile ) return SQLITE_OK; ++ if( pPager->dbSize==0 ) return SQLITE_OK; ++ assert( pPager->zFilename && pPager->zFilename[0] ); ++ rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved); ++ if( rc==SQLITE_NOTFOUND ){ ++ /* If the HAS_MOVED file-control is unimplemented, assume that the file ++ ** has not been moved. That is the historical behavior of SQLite: prior to ++ ** version 3.8.3, it never checked */ ++ rc = SQLITE_OK; ++ }else if( rc==SQLITE_OK && bHasMoved ){ ++ rc = SQLITE_READONLY_DBMOVED; ++ } ++ return rc; ++} ++ ++ + /* + ** Shutdown the page cache. Free all memory and close all files. + ** +@@ -51539,8 +54506,7 @@ + ** to the caller. + */ + SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){ +- u8 *pTmp = (u8 *)pPager->pTmpSpace; +- ++ u8 *pTmp = (u8*)pPager->pTmpSpace; + assert( db || pagerUseWal(pPager)==0 ); + assert( assert_pager_state(pPager) ); + disable_simulated_io_errors(); +@@ -51549,11 +54515,17 @@ + /* pPager->errCode = 0; */ + pPager->exclusiveMode = 0; + #ifndef SQLITE_OMIT_WAL +- assert( db || pPager->pWal==0 ); +- sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags, pPager->pageSize, +- (db && (db->flags & SQLITE_NoCkptOnClose) ? 0 : pTmp) +- ); +- pPager->pWal = 0; ++ { ++ u8 *a = 0; ++ assert( db || pPager->pWal==0 ); ++ if( db && 0==(db->flags & SQLITE_NoCkptOnClose) ++ && SQLITE_OK==databaseIsUnmoved(pPager) ++ ){ ++ a = pTmp; ++ } ++ sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize,a); ++ pPager->pWal = 0; ++ } + #endif + pager_reset(pPager); + if( MEMDB ){ +@@ -52010,6 +54982,7 @@ + return SQLITE_OK; + } + ++ pPager->aStat[PAGER_STAT_SPILL]++; + pPg->pDirty = 0; + if( pagerUseWal(pPager) ){ + /* Write a single frame for this page to the log. */ +@@ -52018,6 +54991,13 @@ + rc = pagerWalFrames(pPager, pPg, 0, 0); + } + }else{ ++ ++#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE ++ if( pPager->tempFile==0 ){ ++ rc = sqlite3JournalCreate(pPager->jfd); ++ if( rc!=SQLITE_OK ) return pager_error(pPager, rc); ++ } ++#endif + + /* Sync the journal file if required. */ + if( pPg->flags&PGHDR_NEED_SYNC +@@ -52108,6 +55088,11 @@ + int rc = SQLITE_OK; /* Return code */ + int tempFile = 0; /* True for temp files (incl. in-memory files) */ + int memDb = 0; /* True if this is an in-memory file */ ++#ifdef SQLITE_ENABLE_DESERIALIZE ++ int memJM = 0; /* Memory journal mode */ ++#else ++# define memJM 0 ++#endif + int readOnly = 0; /* True if this is a read-only file */ + int journalFileSize; /* Bytes to allocate for each journal fd */ + char *zPathname = 0; /* Full path to database file */ +@@ -52235,7 +55220,10 @@ + int fout = 0; /* VFS flags returned by xOpen() */ + rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout); + assert( !memDb ); +- readOnly = (fout&SQLITE_OPEN_READONLY); ++#ifdef SQLITE_ENABLE_DESERIALIZE ++ memJM = (fout&SQLITE_OPEN_MEMORY)!=0; ++#endif ++ readOnly = (fout&SQLITE_OPEN_READONLY)!=0; + + /* If the file was successfully opened for read/write access, + ** choose a default page size in case we have to create the +@@ -52351,13 +55339,11 @@ + assert( pPager->extraSync==0 ); + assert( pPager->syncFlags==0 ); + assert( pPager->walSyncFlags==0 ); +- assert( pPager->ckptSyncFlags==0 ); + }else{ + pPager->fullSync = 1; + pPager->extraSync = 0; + pPager->syncFlags = SQLITE_SYNC_NORMAL; +- pPager->walSyncFlags = SQLITE_SYNC_NORMAL | WAL_SYNC_TRANSACTIONS; +- pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL; ++ pPager->walSyncFlags = SQLITE_SYNC_NORMAL | (SQLITE_SYNC_NORMAL<<2); + } + /* pPager->pFirst = 0; */ + /* pPager->pFirstSynced = 0; */ +@@ -52368,7 +55354,7 @@ + setSectorSize(pPager); + if( !useJournal ){ + pPager->journalMode = PAGER_JOURNALMODE_OFF; +- }else if( memDb ){ ++ }else if( memDb || memJM ){ + pPager->journalMode = PAGER_JOURNALMODE_MEMORY; + } + /* pPager->xBusyHandler = 0; */ +@@ -52383,31 +55369,7 @@ + } + + +-/* Verify that the database file has not be deleted or renamed out from +-** under the pager. Return SQLITE_OK if the database is still were it ought +-** to be on disk. Return non-zero (SQLITE_READONLY_DBMOVED or some other error +-** code from sqlite3OsAccess()) if the database has gone missing. +-*/ +-static int databaseIsUnmoved(Pager *pPager){ +- int bHasMoved = 0; +- int rc; + +- if( pPager->tempFile ) return SQLITE_OK; +- if( pPager->dbSize==0 ) return SQLITE_OK; +- assert( pPager->zFilename && pPager->zFilename[0] ); +- rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved); +- if( rc==SQLITE_NOTFOUND ){ +- /* If the HAS_MOVED file-control is unimplemented, assume that the file +- ** has not been moved. That is the historical behavior of SQLite: prior to +- ** version 3.8.3, it never checked */ +- rc = SQLITE_OK; +- }else if( rc==SQLITE_OK && bHasMoved ){ +- rc = SQLITE_READONLY_DBMOVED; +- } +- return rc; +-} +- +- + /* + ** This function is called after transitioning from PAGER_UNLOCK to + ** PAGER_SHARED state. It tests if there is a hot journal present in +@@ -52777,7 +55739,8 @@ + ** nothing to rollback, so this routine is a no-op. + */ + static void pagerUnlockIfUnused(Pager *pPager){ +- if( pPager->nMmapOut==0 && (sqlite3PcacheRefCount(pPager->pPCache)==0) ){ ++ if( sqlite3PcacheRefCount(pPager->pPCache)==0 ){ ++ assert( pPager->nMmapOut==0 ); /* because page1 is never memory mapped */ + pagerUnlockAndRollback(pPager); + } + } +@@ -52918,14 +55881,9 @@ + memset(pPg->pData, 0, pPager->pageSize); + IOTRACE(("ZERO %p %d\n", pPager, pgno)); + }else{ +- u32 iFrame = 0; /* Frame to read from WAL file */ +- if( pagerUseWal(pPager) ){ +- rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame); +- if( rc!=SQLITE_OK ) goto pager_acquire_err; +- } + assert( pPg->pPager==pPager ); + pPager->aStat[PAGER_STAT_MISS]++; +- rc = readDbPage(pPg, iFrame); ++ rc = readDbPage(pPg); + if( rc!=SQLITE_OK ){ + goto pager_acquire_err; + } +@@ -52999,7 +55957,7 @@ + } + if( pPg==0 ){ + rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg); +- }else{ ++ }else{ + sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData); + } + if( pPg ){ +@@ -53068,25 +56026,40 @@ + /* + ** Release a page reference. + ** +-** If the number of references to the page drop to zero, then the +-** page is added to the LRU list. When all references to all pages +-** are released, a rollback occurs and the lock on the database is +-** removed. ++** 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. + */ + SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage *pPg){ +- Pager *pPager; ++ TESTONLY( Pager *pPager = pPg->pPager; ) + assert( pPg!=0 ); +- pPager = pPg->pPager; + if( pPg->flags & PGHDR_MMAP ){ ++ assert( pPg->pgno!=1 ); /* Page1 is never memory mapped */ + pagerReleaseMapPage(pPg); + }else{ + sqlite3PcacheRelease(pPg); + } +- pagerUnlockIfUnused(pPager); ++ /* Do not use this routine to release the last reference to page1 */ ++ assert( sqlite3PcacheRefCount(pPager->pPCache)>0 ); + } + SQLITE_PRIVATE void sqlite3PagerUnref(DbPage *pPg){ + if( pPg ) sqlite3PagerUnrefNotNull(pPg); + } ++SQLITE_PRIVATE void sqlite3PagerUnrefPageOne(DbPage *pPg){ ++ Pager *pPager; ++ assert( pPg!=0 ); ++ assert( pPg->pgno==1 ); ++ assert( (pPg->flags & PGHDR_MMAP)==0 ); /* Page1 is never memory mapped */ ++ pPager = pPg->pPager; ++ sqlite3PagerResetLockTimeout(pPager); ++ sqlite3PcacheRelease(pPg); ++ pagerUnlockIfUnused(pPager); ++} + + /* + ** This function is called at the start of every write transaction. +@@ -53679,12 +56652,9 @@ + */ + SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zMaster){ + int rc = SQLITE_OK; +- +- if( isOpen(pPager->fd) ){ +- void *pArg = (void*)zMaster; +- rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg); +- if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; +- } ++ void *pArg = (void*)zMaster; ++ rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg); ++ if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; + if( rc==SQLITE_OK && !pPager->noSync ){ + assert( !MEMDB ); + rc = sqlite3OsSync(pPager->fd, pPager->syncFlags); +@@ -53779,9 +56749,10 @@ + ** backup in progress needs to be restarted. */ + sqlite3BackupRestart(pPager->pBackup); + }else{ ++ PgHdr *pList; + if( pagerUseWal(pPager) ){ +- PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache); + PgHdr *pPageOne = 0; ++ pList = sqlite3PcacheDirtyList(pPager->pPCache); + if( pList==0 ){ + /* Must have at least one page for the WAL commit flag. + ** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */ +@@ -53798,6 +56769,21 @@ + sqlite3PcacheCleanAll(pPager->pPCache); + } + }else{ ++ /* The bBatch boolean is true if the batch-atomic-write commit method ++ ** should be used. No rollback journal is created if batch-atomic-write ++ ** is enabled. ++ */ ++#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE ++ sqlite3_file *fd = pPager->fd; ++ int bBatch = zMaster==0 /* An SQLITE_IOCAP_BATCH_ATOMIC commit */ ++ && (sqlite3OsDeviceCharacteristics(fd) & SQLITE_IOCAP_BATCH_ATOMIC) ++ && !pPager->noSync ++ && sqlite3JournalIsInMemory(pPager->jfd); ++#else ++# define bBatch 0 ++#endif ++ ++#ifdef SQLITE_ENABLE_ATOMIC_WRITE + /* The following block updates the change-counter. Exactly how it + ** does this depends on whether or not the atomic-update optimization + ** was enabled at compile time, and if this transaction meets the +@@ -53821,33 +56807,41 @@ + ** in 'direct' mode. In this case the journal file will never be + ** created for this transaction. + */ +- #ifdef SQLITE_ENABLE_ATOMIC_WRITE +- PgHdr *pPg; +- assert( isOpen(pPager->jfd) +- || pPager->journalMode==PAGER_JOURNALMODE_OFF +- || pPager->journalMode==PAGER_JOURNALMODE_WAL +- ); +- if( !zMaster && isOpen(pPager->jfd) +- && pPager->journalOff==jrnlBufferSize(pPager) +- && pPager->dbSize>=pPager->dbOrigSize +- && (0==(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty) +- ){ +- /* Update the db file change counter via the direct-write method. The +- ** following call will modify the in-memory representation of page 1 +- ** to include the updated change counter and then write page 1 +- ** directly to the database file. Because of the atomic-write +- ** property of the host file-system, this is safe. +- */ +- rc = pager_incr_changecounter(pPager, 1); +- }else{ +- rc = sqlite3JournalCreate(pPager->jfd); +- if( rc==SQLITE_OK ){ +- rc = pager_incr_changecounter(pPager, 0); ++ if( bBatch==0 ){ ++ PgHdr *pPg; ++ assert( isOpen(pPager->jfd) ++ || pPager->journalMode==PAGER_JOURNALMODE_OFF ++ || pPager->journalMode==PAGER_JOURNALMODE_WAL ++ ); ++ if( !zMaster && isOpen(pPager->jfd) ++ && pPager->journalOff==jrnlBufferSize(pPager) ++ && pPager->dbSize>=pPager->dbOrigSize ++ && (!(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty) ++ ){ ++ /* Update the db file change counter via the direct-write method. The ++ ** following call will modify the in-memory representation of page 1 ++ ** to include the updated change counter and then write page 1 ++ ** directly to the database file. Because of the atomic-write ++ ** property of the host file-system, this is safe. ++ */ ++ rc = pager_incr_changecounter(pPager, 1); ++ }else{ ++ rc = sqlite3JournalCreate(pPager->jfd); ++ if( rc==SQLITE_OK ){ ++ rc = pager_incr_changecounter(pPager, 0); ++ } + } + } +- #else ++#else /* SQLITE_ENABLE_ATOMIC_WRITE */ ++#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE ++ if( zMaster ){ ++ rc = sqlite3JournalCreate(pPager->jfd); ++ if( rc!=SQLITE_OK ) goto commit_phase_one_exit; ++ assert( bBatch==0 ); ++ } ++#endif + rc = pager_incr_changecounter(pPager, 0); +- #endif ++#endif /* !SQLITE_ENABLE_ATOMIC_WRITE */ + if( rc!=SQLITE_OK ) goto commit_phase_one_exit; + + /* Write the master journal name into the journal file. If a master +@@ -53870,8 +56864,37 @@ + */ + rc = syncJournal(pPager, 0); + if( rc!=SQLITE_OK ) goto commit_phase_one_exit; +- +- rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache)); ++ ++ pList = sqlite3PcacheDirtyList(pPager->pPCache); ++#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE ++ if( bBatch ){ ++ rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_BEGIN_ATOMIC_WRITE, 0); ++ if( rc==SQLITE_OK ){ ++ rc = pager_write_pagelist(pPager, pList); ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_COMMIT_ATOMIC_WRITE, 0); ++ } ++ if( rc!=SQLITE_OK ){ ++ sqlite3OsFileControlHint(fd, SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE, 0); ++ } ++ } ++ ++ if( (rc&0xFF)==SQLITE_IOERR && rc!=SQLITE_IOERR_NOMEM ){ ++ rc = sqlite3JournalCreate(pPager->jfd); ++ if( rc!=SQLITE_OK ){ ++ sqlite3OsClose(pPager->jfd); ++ goto commit_phase_one_exit; ++ } ++ bBatch = 0; ++ }else{ ++ sqlite3OsClose(pPager->jfd); ++ } ++ } ++#endif /* SQLITE_ENABLE_BATCH_ATOMIC_WRITE */ ++ ++ if( bBatch==0 ){ ++ rc = pager_write_pagelist(pPager, pList); ++ } + if( rc!=SQLITE_OK ){ + assert( rc!=SQLITE_IOERR_BLOCKED ); + goto commit_phase_one_exit; +@@ -54092,8 +57115,12 @@ + #endif + + /* +-** Parameter eStat must be either SQLITE_DBSTATUS_CACHE_HIT or +-** SQLITE_DBSTATUS_CACHE_MISS. Before returning, *pnVal is incremented by the ++** Parameter eStat must be one of SQLITE_DBSTATUS_CACHE_HIT, _MISS, _WRITE, ++** or _WRITE+1. The SQLITE_DBSTATUS_CACHE_WRITE+1 case is a translation ++** of SQLITE_DBSTATUS_CACHE_SPILL. The _SPILL case is not contiguous because ++** it was added later. ++** ++** Before returning, *pnVal is incremented by the + ** current cache hit or miss count, according to the value of eStat. If the + ** reset parameter is non-zero, the cache hit or miss count is zeroed before + ** returning. +@@ -54103,15 +57130,18 @@ + assert( eStat==SQLITE_DBSTATUS_CACHE_HIT + || eStat==SQLITE_DBSTATUS_CACHE_MISS + || eStat==SQLITE_DBSTATUS_CACHE_WRITE ++ || eStat==SQLITE_DBSTATUS_CACHE_WRITE+1 + ); + + assert( SQLITE_DBSTATUS_CACHE_HIT+1==SQLITE_DBSTATUS_CACHE_MISS ); + assert( SQLITE_DBSTATUS_CACHE_HIT+2==SQLITE_DBSTATUS_CACHE_WRITE ); +- assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1 && PAGER_STAT_WRITE==2 ); ++ assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1 ++ && PAGER_STAT_WRITE==2 && PAGER_STAT_SPILL==3 ); + +- *pnVal += pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT]; ++ eStat -= SQLITE_DBSTATUS_CACHE_HIT; ++ *pnVal += pPager->aStat[eStat]; + if( reset ){ +- pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT] = 0; ++ pPager->aStat[eStat] = 0; + } + } + +@@ -54315,7 +57345,17 @@ + return pPager->fd; + } + ++#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + /* ++** Reset the lock timeout for pager. ++*/ ++SQLITE_PRIVATE void sqlite3PagerResetLockTimeout(Pager *pPager){ ++ int x = 0; ++ sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_LOCK_TIMEOUT, &x); ++} ++#endif ++ ++/* + ** Return the file handle for the journal file (if it exists). + ** This will be either the rollback journal or the WAL file. + */ +@@ -54345,7 +57385,11 @@ + void (*xCodecFree)(void*), + void *pCodec + ){ +- if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec); ++ if( pPager->xCodecFree ){ ++ pPager->xCodecFree(pPager->pCodec); ++ }else{ ++ pager_reset(pPager); ++ } + pPager->xCodec = pPager->memDb ? 0 : xCodec; + pPager->xCodecSizeChng = xCodecSizeChng; + pPager->xCodecFree = xCodecFree; +@@ -54606,13 +57650,6 @@ + SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){ + u8 eOld = pPager->journalMode; /* Prior journalmode */ + +-#ifdef SQLITE_DEBUG +- /* The print_pager_state() routine is intended to be used by the debugger +- ** only. We invoke it once here to suppress a compiler warning. */ +- print_pager_state(pPager); +-#endif +- +- + /* The eMode parameter is always valid */ + assert( eMode==PAGER_JOURNALMODE_DELETE + || eMode==PAGER_JOURNALMODE_TRUNCATE +@@ -54772,9 +57809,10 @@ + rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode, + (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), + pPager->pBusyHandlerArg, +- pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, ++ pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, + pnLog, pnCkpt + ); ++ sqlite3PagerResetLockTimeout(pPager); + } + return rc; + } +@@ -54929,7 +57967,7 @@ + if( rc==SQLITE_OK && pPager->pWal ){ + rc = pagerExclusiveLock(pPager); + if( rc==SQLITE_OK ){ +- rc = sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags, ++ rc = sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, + pPager->pageSize, (u8*)pPager->pTmpSpace); + pPager->pWal = 0; + pagerFixMaplimit(pPager); +@@ -54980,6 +58018,38 @@ + } + return rc; + } ++ ++/* ++** The caller currently has a read transaction open on the database. ++** If this is not a WAL database, SQLITE_ERROR is returned. Otherwise, ++** this function takes a SHARED lock on the CHECKPOINTER slot and then ++** checks if the snapshot passed as the second argument is still ++** available. If so, SQLITE_OK is returned. ++** ++** If the snapshot is not available, SQLITE_ERROR is returned. Or, if ++** the CHECKPOINTER lock cannot be obtained, SQLITE_BUSY. If any error ++** occurs (any value other than SQLITE_OK is returned), the CHECKPOINTER ++** lock is released before returning. ++*/ ++SQLITE_PRIVATE int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot){ ++ int rc; ++ if( pPager->pWal ){ ++ rc = sqlite3WalSnapshotCheck(pPager->pWal, pSnapshot); ++ }else{ ++ rc = SQLITE_ERROR; ++ } ++ return rc; ++} ++ ++/* ++** Release a lock obtained by an earlier successful call to ++** sqlite3PagerSnapshotCheck(). ++*/ ++SQLITE_PRIVATE void sqlite3PagerSnapshotUnlock(Pager *pPager){ ++ assert( pPager->pWal ); ++ return sqlite3WalSnapshotUnlock(pPager->pWal); ++} ++ + #endif /* SQLITE_ENABLE_SNAPSHOT */ + #endif /* !SQLITE_OMIT_WAL */ + +@@ -55135,6 +58205,10 @@ + ** on a network filesystem. All users of the database must be able to + ** share memory. + ** ++** In the default unix and windows implementation, the wal-index is a mmapped ++** file whose name is the database name with a "-shm" suffix added. For that ++** reason, the wal-index is sometimes called the "shm" file. ++** + ** The wal-index is transient. After a crash, the wal-index can (and should + ** be) reconstructed from the original WAL file. In fact, the VFS is required + ** to either truncate or zero the header of the wal-index when the last +@@ -55258,6 +58332,18 @@ + #endif + + /* ++** WAL mode depends on atomic aligned 32-bit loads and stores in a few ++** places. The following macros try to make this explicit. ++*/ ++#if GCC_VESRION>=5004000 ++# define AtomicLoad(PTR) __atomic_load_n((PTR),__ATOMIC_RELAXED) ++# define AtomicStore(PTR,VAL) __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED) ++#else ++# define AtomicLoad(PTR) (*(PTR)) ++# define AtomicStore(PTR,VAL) (*(PTR) = (VAL)) ++#endif ++ ++/* + ** The maximum (and only) versions of the wal and wal-index formats + ** that may be interpreted by this version of SQLite. + ** +@@ -55274,9 +58360,18 @@ + #define WALINDEX_MAX_VERSION 3007000 + + /* +-** Indices of various locking bytes. WAL_NREADER is the number ++** Index numbers for various locking bytes. WAL_NREADER is the number + ** of available reader locks and should be at least 3. The default + ** is SQLITE_SHM_NLOCK==8 and WAL_NREADER==5. ++** ++** Technically, the various VFSes are free to implement these locks however ++** they see fit. However, compatibility is encouraged so that VFSes can ++** interoperate. The standard implemention used on both unix and windows ++** is for the index number to indicate a byte offset into the ++** WalCkptInfo.aLock[] array in the wal-index header. In other words, all ++** locks are on the shm file. The WALINDEX_LOCK_OFFSET constant (which ++** should be 120) is the location in the shm file for the first locking ++** byte. + */ + #define WAL_WRITE_LOCK 0 + #define WAL_ALL_BUT_WRITE 1 +@@ -55400,7 +58495,6 @@ + #define WAL_FRAME_HDRSIZE 24 + + /* Size of write ahead log header, including checksum. */ +-/* #define WAL_HDRSIZE 24 */ + #define WAL_HDRSIZE 32 + + /* WAL magic value. Either this value, or the same value with the least +@@ -55446,6 +58540,7 @@ + u8 truncateOnCommit; /* True to truncate WAL file on commit */ + u8 syncHeader; /* Fsync the WAL header if true */ + u8 padToSectorBoundary; /* Pad transactions out to the next sector */ ++ u8 bShmUnreliable; /* SHM content is read-only and unreliable */ + WalIndexHdr hdr; /* Wal-index header for current transaction */ + u32 minFrame; /* Ignore wal frames before this one */ + u32 iReCksum; /* On commit, recalculate checksums from here */ +@@ -55535,11 +58630,20 @@ + ** is broken into pages of WALINDEX_PGSZ bytes. Wal-index pages are + ** numbered from zero. + ** ++** If the wal-index is currently smaller the iPage pages then the size ++** of the wal-index might be increased, but only if it is safe to do ++** so. It is safe to enlarge the wal-index if pWal->writeLock is true ++** or pWal->exclusiveMode==WAL_HEAPMEMORY_MODE. ++** + ** If this call is successful, *ppPage is set to point to the wal-index + ** page and SQLITE_OK is returned. If an error (an OOM or VFS error) occurs, + ** then an SQLite error code is returned and *ppPage is set to 0. + */ +-static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){ ++static SQLITE_NOINLINE int walIndexPageRealloc( ++ Wal *pWal, /* The WAL context */ ++ int iPage, /* The page we seek */ ++ volatile u32 **ppPage /* Write the page pointer here */ ++){ + int rc = SQLITE_OK; + + /* Enlarge the pWal->apWiData[] array if required */ +@@ -55558,16 +58662,19 @@ + } + + /* Request a pointer to the required page from the VFS */ +- if( pWal->apWiData[iPage]==0 ){ +- if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){ +- pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ); +- if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM_BKPT; +- }else{ +- rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, +- pWal->writeLock, (void volatile **)&pWal->apWiData[iPage] +- ); ++ assert( pWal->apWiData[iPage]==0 ); ++ if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){ ++ pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ); ++ if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM_BKPT; ++ }else{ ++ rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, ++ pWal->writeLock, (void volatile **)&pWal->apWiData[iPage] ++ ); ++ assert( pWal->apWiData[iPage]!=0 || rc!=SQLITE_OK || pWal->writeLock==0 ); ++ testcase( pWal->apWiData[iPage]==0 && rc==SQLITE_OK ); ++ if( (rc&0xff)==SQLITE_READONLY ){ ++ pWal->readOnly |= WAL_SHM_RDONLY; + if( rc==SQLITE_READONLY ){ +- pWal->readOnly |= WAL_SHM_RDONLY; + rc = SQLITE_OK; + } + } +@@ -55577,6 +58684,16 @@ + assert( iPage==0 || *ppPage || rc!=SQLITE_OK ); + return rc; + } ++static int walIndexPage( ++ Wal *pWal, /* The WAL context */ ++ int iPage, /* The page we seek */ ++ volatile u32 **ppPage /* Write the page pointer here */ ++){ ++ if( pWal->nWiData<=iPage || (*ppPage = pWal->apWiData[iPage])==0 ){ ++ return walIndexPageRealloc(pWal, iPage, ppPage); ++ } ++ return SQLITE_OK; ++} + + /* + ** Return a pointer to the WalCkptInfo structure in the wal-index. +@@ -55848,48 +58965,51 @@ + return (iPriorHash+1)&(HASHTABLE_NSLOT-1); + } + ++/* ++** An instance of the WalHashLoc object is used to describe the location ++** of a page hash table in the wal-index. This becomes the return value ++** from walHashGet(). ++*/ ++typedef struct WalHashLoc WalHashLoc; ++struct WalHashLoc { ++ volatile ht_slot *aHash; /* Start of the wal-index hash table */ ++ volatile u32 *aPgno; /* aPgno[1] is the page of first frame indexed */ ++ u32 iZero; /* One less than the frame number of first indexed*/ ++}; ++ + /* + ** Return pointers to the hash table and page number array stored on + ** page iHash of the wal-index. The wal-index is broken into 32KB pages + ** numbered starting from 0. + ** +-** Set output variable *paHash to point to the start of the hash table +-** in the wal-index file. Set *piZero to one less than the frame ++** Set output variable pLoc->aHash to point to the start of the hash table ++** in the wal-index file. Set pLoc->iZero to one less than the frame + ** number of the first frame indexed by this hash table. If a + ** slot in the hash table is set to N, it refers to frame number +-** (*piZero+N) in the log. ++** (pLoc->iZero+N) in the log. + ** +-** Finally, set *paPgno so that *paPgno[1] is the page number of the +-** first frame indexed by the hash table, frame (*piZero+1). ++** Finally, set pLoc->aPgno so that pLoc->aPgno[1] is the page number of the ++** first frame indexed by the hash table, frame (pLoc->iZero+1). + */ + static int walHashGet( + Wal *pWal, /* WAL handle */ + int iHash, /* Find the iHash'th table */ +- volatile ht_slot **paHash, /* OUT: Pointer to hash index */ +- volatile u32 **paPgno, /* OUT: Pointer to page number array */ +- u32 *piZero /* OUT: Frame associated with *paPgno[0] */ ++ WalHashLoc *pLoc /* OUT: Hash table location */ + ){ + int rc; /* Return code */ +- volatile u32 *aPgno; + +- rc = walIndexPage(pWal, iHash, &aPgno); ++ rc = walIndexPage(pWal, iHash, &pLoc->aPgno); + assert( rc==SQLITE_OK || iHash>0 ); + + if( rc==SQLITE_OK ){ +- u32 iZero; +- volatile ht_slot *aHash; +- +- aHash = (volatile ht_slot *)&aPgno[HASHTABLE_NPAGE]; ++ pLoc->aHash = (volatile ht_slot *)&pLoc->aPgno[HASHTABLE_NPAGE]; + if( iHash==0 ){ +- aPgno = &aPgno[WALINDEX_HDR_SIZE/sizeof(u32)]; +- iZero = 0; ++ pLoc->aPgno = &pLoc->aPgno[WALINDEX_HDR_SIZE/sizeof(u32)]; ++ pLoc->iZero = 0; + }else{ +- iZero = HASHTABLE_NPAGE_ONE + (iHash-1)*HASHTABLE_NPAGE; ++ pLoc->iZero = HASHTABLE_NPAGE_ONE + (iHash-1)*HASHTABLE_NPAGE; + } +- +- *paPgno = &aPgno[-1]; +- *paHash = aHash; +- *piZero = iZero; ++ pLoc->aPgno = &pLoc->aPgno[-1]; + } + return rc; + } +@@ -55935,9 +59055,7 @@ + ** actually needed. + */ + static void walCleanupHash(Wal *pWal){ +- volatile ht_slot *aHash = 0; /* Pointer to hash table to clear */ +- volatile u32 *aPgno = 0; /* Page number array for hash table */ +- u32 iZero = 0; /* frame == (aHash[x]+iZero) */ ++ WalHashLoc sLoc; /* Hash table location */ + int iLimit = 0; /* Zero values greater than this */ + int nByte; /* Number of bytes to zero in aPgno[] */ + int i; /* Used to iterate through aHash[] */ +@@ -55955,16 +59073,16 @@ + */ + assert( pWal->nWiData>walFramePage(pWal->hdr.mxFrame) ); + assert( pWal->apWiData[walFramePage(pWal->hdr.mxFrame)] ); +- walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &aHash, &aPgno, &iZero); ++ walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &sLoc); + + /* Zero all hash-table entries that correspond to frame numbers greater + ** than pWal->hdr.mxFrame. + */ +- iLimit = pWal->hdr.mxFrame - iZero; ++ iLimit = pWal->hdr.mxFrame - sLoc.iZero; + assert( iLimit>0 ); + for(i=0; i<HASHTABLE_NSLOT; i++){ +- if( aHash[i]>iLimit ){ +- aHash[i] = 0; ++ if( sLoc.aHash[i]>iLimit ){ ++ sLoc.aHash[i] = 0; + } + } + +@@ -55971,8 +59089,8 @@ + /* Zero the entries in the aPgno array that correspond to frames with + ** frame numbers greater than pWal->hdr.mxFrame. + */ +- nByte = (int)((char *)aHash - (char *)&aPgno[iLimit+1]); +- memset((void *)&aPgno[iLimit+1], 0, nByte); ++ nByte = (int)((char *)sLoc.aHash - (char *)&sLoc.aPgno[iLimit+1]); ++ memset((void *)&sLoc.aPgno[iLimit+1], 0, nByte); + + #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT + /* Verify that the every entry in the mapping region is still reachable +@@ -55982,10 +59100,10 @@ + int j; /* Loop counter */ + int iKey; /* Hash key */ + for(j=1; j<=iLimit; j++){ +- for(iKey=walHash(aPgno[j]); aHash[iKey]; iKey=walNextHash(iKey)){ +- if( aHash[iKey]==j ) break; ++ for(iKey=walHash(sLoc.aPgno[j]);sLoc.aHash[iKey];iKey=walNextHash(iKey)){ ++ if( sLoc.aHash[iKey]==j ) break; + } +- assert( aHash[iKey]==j ); ++ assert( sLoc.aHash[iKey]==j ); + } + } + #endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */ +@@ -55998,11 +59116,9 @@ + */ + static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){ + int rc; /* Return code */ +- u32 iZero = 0; /* One less than frame number of aPgno[1] */ +- volatile u32 *aPgno = 0; /* Page number array */ +- volatile ht_slot *aHash = 0; /* Hash table */ ++ WalHashLoc sLoc; /* Wal-index hash table location */ + +- rc = walHashGet(pWal, walFramePage(iFrame), &aHash, &aPgno, &iZero); ++ rc = walHashGet(pWal, walFramePage(iFrame), &sLoc); + + /* Assuming the wal-index file was successfully mapped, populate the + ** page number array and hash table entry. +@@ -56012,7 +59128,7 @@ + int idx; /* Value to write to hash-table slot */ + int nCollide; /* Number of hash collisions */ + +- idx = iFrame - iZero; ++ idx = iFrame - sLoc.iZero; + assert( idx <= HASHTABLE_NSLOT/2 + 1 ); + + /* If this is the first entry to be added to this hash-table, zero the +@@ -56019,8 +59135,9 @@ + ** entire hash table and aPgno[] array before proceeding. + */ + if( idx==1 ){ +- int nByte = (int)((u8 *)&aHash[HASHTABLE_NSLOT] - (u8 *)&aPgno[1]); +- memset((void*)&aPgno[1], 0, nByte); ++ int nByte = (int)((u8 *)&sLoc.aHash[HASHTABLE_NSLOT] ++ - (u8 *)&sLoc.aPgno[1]); ++ memset((void*)&sLoc.aPgno[1], 0, nByte); + } + + /* If the entry in aPgno[] is already set, then the previous writer +@@ -56029,18 +59146,18 @@ + ** Remove the remnants of that writers uncommitted transaction from + ** the hash-table before writing any new entries. + */ +- if( aPgno[idx] ){ ++ if( sLoc.aPgno[idx] ){ + walCleanupHash(pWal); +- assert( !aPgno[idx] ); ++ assert( !sLoc.aPgno[idx] ); + } + + /* Write the aPgno[] array entry and the hash-table slot. */ + nCollide = idx; +- for(iKey=walHash(iPage); aHash[iKey]; iKey=walNextHash(iKey)){ ++ for(iKey=walHash(iPage); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){ + if( (nCollide--)==0 ) return SQLITE_CORRUPT_BKPT; + } +- aPgno[idx] = iPage; +- aHash[iKey] = (ht_slot)idx; ++ sLoc.aPgno[idx] = iPage; ++ sLoc.aHash[iKey] = (ht_slot)idx; + + #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT + /* Verify that the number of entries in the hash table exactly equals +@@ -56049,7 +59166,7 @@ + { + int i; /* Loop counter */ + int nEntry = 0; /* Number of entries in the hash table */ +- for(i=0; i<HASHTABLE_NSLOT; i++){ if( aHash[i] ) nEntry++; } ++ for(i=0; i<HASHTABLE_NSLOT; i++){ if( sLoc.aHash[i] ) nEntry++; } + assert( nEntry==idx ); + } + +@@ -56061,10 +59178,12 @@ + if( (idx&0x3ff)==0 ){ + int i; /* Loop counter */ + for(i=1; i<=idx; i++){ +- for(iKey=walHash(aPgno[i]); aHash[iKey]; iKey=walNextHash(iKey)){ +- if( aHash[iKey]==i ) break; ++ for(iKey=walHash(sLoc.aPgno[i]); ++ sLoc.aHash[iKey]; ++ iKey=walNextHash(iKey)){ ++ if( sLoc.aHash[iKey]==i ) break; + } +- assert( aHash[iKey]==i ); ++ assert( sLoc.aHash[iKey]==i ); + } + } + #endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */ +@@ -56090,7 +59209,6 @@ + i64 nSize; /* Size of log file */ + u32 aFrameCksum[2] = {0, 0}; + int iLock; /* Lock offset to lock for checkpoint */ +- int nLock; /* Number of locks to hold */ + + /* Obtain an exclusive lock on all byte in the locking range not already + ** locked by the caller. The caller is guaranteed to have locked the +@@ -56103,11 +59221,17 @@ + assert( WAL_CKPT_LOCK==WAL_ALL_BUT_WRITE ); + assert( pWal->writeLock ); + iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock; +- nLock = SQLITE_SHM_NLOCK - iLock; +- rc = walLockExclusive(pWal, iLock, nLock); ++ rc = walLockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock); ++ if( rc==SQLITE_OK ){ ++ rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); ++ if( rc!=SQLITE_OK ){ ++ walUnlockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock); ++ } ++ } + if( rc ){ + return rc; + } ++ + WALTRACE(("WAL%p: recovery begin...\n", pWal)); + + memset(&pWal->hdr, 0, sizeof(WalIndexHdr)); +@@ -56245,7 +59369,8 @@ + + recovery_error: + WALTRACE(("WAL%p: recovery %s\n", pWal, rc ? "failed" : "ok")); +- walUnlockExclusive(pWal, iLock, nLock); ++ walUnlockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock); ++ walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); + return rc; + } + +@@ -56253,13 +59378,14 @@ + ** Close an open wal-index. + */ + static void walIndexClose(Wal *pWal, int isDelete){ +- if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){ ++ if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE || pWal->bShmUnreliable ){ + int i; + for(i=0; i<pWal->nWiData; i++){ + sqlite3_free((void *)pWal->apWiData[i]); + pWal->apWiData[i] = 0; + } +- }else{ ++ } ++ if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){ + sqlite3OsShmUnmap(pWal->pDbFd, isDelete); + } + } +@@ -56546,8 +59672,9 @@ + + /* + ** Construct a WalInterator object that can be used to loop over all +-** pages in the WAL in ascending order. The caller must hold the checkpoint +-** lock. ++** pages in the WAL following frame nBackfill in ascending order. Frames ++** nBackfill or earlier may be included - excluding them is an optimization ++** only. The caller must hold the checkpoint lock. + ** + ** On success, make *pp point to the newly allocated WalInterator object + ** return SQLITE_OK. Otherwise, return an error code. If this routine +@@ -56556,7 +59683,7 @@ + ** The calling routine should invoke walIteratorFree() to destroy the + ** WalIterator object when it has finished with it. + */ +-static int walIteratorInit(Wal *pWal, WalIterator **pp){ ++static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){ + WalIterator *p; /* Return value */ + int nSegment; /* Number of segments to merge */ + u32 iLast; /* Last frame in log */ +@@ -56593,34 +59720,32 @@ + rc = SQLITE_NOMEM_BKPT; + } + +- for(i=0; rc==SQLITE_OK && i<nSegment; i++){ +- volatile ht_slot *aHash; +- u32 iZero; +- volatile u32 *aPgno; ++ for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && i<nSegment; i++){ ++ WalHashLoc sLoc; + +- rc = walHashGet(pWal, i, &aHash, &aPgno, &iZero); ++ rc = walHashGet(pWal, i, &sLoc); + if( rc==SQLITE_OK ){ + int j; /* Counter variable */ + int nEntry; /* Number of entries in this segment */ + ht_slot *aIndex; /* Sorted index for this segment */ + +- aPgno++; ++ sLoc.aPgno++; + if( (i+1)==nSegment ){ +- nEntry = (int)(iLast - iZero); ++ nEntry = (int)(iLast - sLoc.iZero); + }else{ +- nEntry = (int)((u32*)aHash - (u32*)aPgno); ++ nEntry = (int)((u32*)sLoc.aHash - (u32*)sLoc.aPgno); + } +- aIndex = &((ht_slot *)&p->aSegment[p->nSegment])[iZero]; +- iZero++; ++ aIndex = &((ht_slot *)&p->aSegment[p->nSegment])[sLoc.iZero]; ++ sLoc.iZero++; + + for(j=0; j<nEntry; j++){ + aIndex[j] = (ht_slot)j; + } +- walMergesort((u32 *)aPgno, aTmp, aIndex, &nEntry); +- p->aSegment[i].iZero = iZero; ++ walMergesort((u32 *)sLoc.aPgno, aTmp, aIndex, &nEntry); ++ p->aSegment[i].iZero = sLoc.iZero; + p->aSegment[i].nEntry = nEntry; + p->aSegment[i].aIndex = aIndex; +- p->aSegment[i].aPgno = (u32 *)aPgno; ++ p->aSegment[i].aPgno = (u32 *)sLoc.aPgno; + } + } + sqlite3_free(aTmp); +@@ -56627,6 +59752,7 @@ + + if( rc!=SQLITE_OK ){ + walIteratorFree(p); ++ p = 0; + } + *pp = p; + return rc; +@@ -56749,13 +59875,6 @@ + pInfo = walCkptInfo(pWal); + if( pInfo->nBackfill<pWal->hdr.mxFrame ){ + +- /* Allocate the iterator */ +- rc = walIteratorInit(pWal, &pIter); +- if( rc!=SQLITE_OK ){ +- return rc; +- } +- assert( pIter ); +- + /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked + ** in the SQLITE_CHECKPOINT_PASSIVE mode. */ + assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 ); +@@ -56792,18 +59911,21 @@ + } + } + +- if( pInfo->nBackfill<mxSafeFrame ++ /* Allocate the iterator */ ++ if( pInfo->nBackfill<mxSafeFrame ){ ++ rc = walIteratorInit(pWal, pInfo->nBackfill, &pIter); ++ assert( rc==SQLITE_OK || pIter==0 ); ++ } ++ ++ if( pIter + && (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0),1))==SQLITE_OK + ){ +- i64 nSize; /* Current size of database file */ + u32 nBackfill = pInfo->nBackfill; + + pInfo->nBackfillAttempted = mxSafeFrame; + + /* Sync the WAL to disk */ +- if( sync_flags ){ +- rc = sqlite3OsSync(pWal->pWalFd, sync_flags); +- } ++ rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags)); + + /* If the database may grow as a result of this checkpoint, hint + ** about the eventual size of the db file to the VFS layer. +@@ -56810,6 +59932,7 @@ + */ + if( rc==SQLITE_OK ){ + i64 nReq = ((i64)mxPage * szPage); ++ i64 nSize; /* Current size of database file */ + rc = sqlite3OsFileSize(pWal->pDbFd, &nSize); + if( rc==SQLITE_OK && nSize<nReq ){ + sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq); +@@ -56844,8 +59967,8 @@ + i64 szDb = pWal->hdr.nPage*(i64)szPage; + testcase( IS_BIG_INT(szDb) ); + rc = sqlite3OsTruncate(pWal->pDbFd, szDb); +- if( rc==SQLITE_OK && sync_flags ){ +- rc = sqlite3OsSync(pWal->pDbFd, sync_flags); ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags)); + } + } + if( rc==SQLITE_OK ){ +@@ -57055,6 +60178,12 @@ + } + + /* ++** This is the value that walTryBeginRead returns when it needs to ++** be retried. ++*/ ++#define WAL_RETRY (-1) ++ ++/* + ** Read the wal-index header from the wal-index and into pWal->hdr. + ** If the wal-header appears to be corrupt, try to reconstruct the + ** wal-index from the WAL before returning. +@@ -57077,9 +60206,29 @@ + assert( pChanged ); + rc = walIndexPage(pWal, 0, &page0); + if( rc!=SQLITE_OK ){ +- return rc; +- }; +- assert( page0 || pWal->writeLock==0 ); ++ assert( rc!=SQLITE_READONLY ); /* READONLY changed to OK in walIndexPage */ ++ if( rc==SQLITE_READONLY_CANTINIT ){ ++ /* The SQLITE_READONLY_CANTINIT return means that the shared-memory ++ ** was openable but is not writable, and this thread is unable to ++ ** confirm that another write-capable connection has the shared-memory ++ ** open, and hence the content of the shared-memory is unreliable, ++ ** since the shared-memory might be inconsistent with the WAL file ++ ** and there is no writer on hand to fix it. */ ++ assert( page0==0 ); ++ assert( pWal->writeLock==0 ); ++ assert( pWal->readOnly & WAL_SHM_RDONLY ); ++ pWal->bShmUnreliable = 1; ++ pWal->exclusiveMode = WAL_HEAPMEMORY_MODE; ++ *pChanged = 1; ++ }else{ ++ return rc; /* Any other non-OK return is just an error */ ++ } ++ }else{ ++ /* page0 can be NULL if the SHM is zero bytes in size and pWal->writeLock ++ ** is zero, which prevents the SHM from growing */ ++ testcase( page0!=0 ); ++ } ++ assert( page0!=0 || pWal->writeLock==0 ); + + /* If the first page of the wal-index has been mapped, try to read the + ** wal-index header immediately, without holding any lock. This usually +@@ -57093,7 +60242,7 @@ + */ + assert( badHdr==0 || pWal->writeLock==0 ); + if( badHdr ){ +- if( pWal->readOnly & WAL_SHM_RDONLY ){ ++ if( pWal->bShmUnreliable==0 && (pWal->readOnly & WAL_SHM_RDONLY) ){ + if( SQLITE_OK==(rc = walLockShared(pWal, WAL_WRITE_LOCK)) ){ + walUnlockShared(pWal, WAL_WRITE_LOCK); + rc = SQLITE_READONLY_RECOVERY; +@@ -57123,16 +60272,194 @@ + if( badHdr==0 && pWal->hdr.iVersion!=WALINDEX_MAX_VERSION ){ + rc = SQLITE_CANTOPEN_BKPT; + } ++ if( pWal->bShmUnreliable ){ ++ if( rc!=SQLITE_OK ){ ++ walIndexClose(pWal, 0); ++ pWal->bShmUnreliable = 0; ++ assert( pWal->nWiData>0 && pWal->apWiData[0]==0 ); ++ /* walIndexRecover() might have returned SHORT_READ if a concurrent ++ ** writer truncated the WAL out from under it. If that happens, it ++ ** indicates that a writer has fixed the SHM file for us, so retry */ ++ if( rc==SQLITE_IOERR_SHORT_READ ) rc = WAL_RETRY; ++ } ++ pWal->exclusiveMode = WAL_NORMAL_MODE; ++ } + + return rc; + } + + /* +-** This is the value that walTryBeginRead returns when it needs to +-** be retried. ++** Open a transaction in a connection where the shared-memory is read-only ++** and where we cannot verify that there is a separate write-capable connection ++** on hand to keep the shared-memory up-to-date with the WAL file. ++** ++** This can happen, for example, when the shared-memory is implemented by ++** memory-mapping a *-shm file, where a prior writer has shut down and ++** left the *-shm file on disk, and now the present connection is trying ++** to use that database but lacks write permission on the *-shm file. ++** Other scenarios are also possible, depending on the VFS implementation. ++** ++** Precondition: ++** ++** The *-wal file has been read and an appropriate wal-index has been ++** constructed in pWal->apWiData[] using heap memory instead of shared ++** memory. ++** ++** If this function returns SQLITE_OK, then the read transaction has ++** been successfully opened. In this case output variable (*pChanged) ++** is set to true before returning if the caller should discard the ++** contents of the page cache before proceeding. Or, if it returns ++** WAL_RETRY, then the heap memory wal-index has been discarded and ++** the caller should retry opening the read transaction from the ++** beginning (including attempting to map the *-shm file). ++** ++** If an error occurs, an SQLite error code is returned. + */ +-#define WAL_RETRY (-1) ++static int walBeginShmUnreliable(Wal *pWal, int *pChanged){ ++ i64 szWal; /* Size of wal file on disk in bytes */ ++ i64 iOffset; /* Current offset when reading wal file */ ++ u8 aBuf[WAL_HDRSIZE]; /* Buffer to load WAL header into */ ++ u8 *aFrame = 0; /* Malloc'd buffer to load entire frame */ ++ int szFrame; /* Number of bytes in buffer aFrame[] */ ++ u8 *aData; /* Pointer to data part of aFrame buffer */ ++ volatile void *pDummy; /* Dummy argument for xShmMap */ ++ int rc; /* Return code */ ++ u32 aSaveCksum[2]; /* Saved copy of pWal->hdr.aFrameCksum */ + ++ assert( pWal->bShmUnreliable ); ++ assert( pWal->readOnly & WAL_SHM_RDONLY ); ++ assert( pWal->nWiData>0 && pWal->apWiData[0] ); ++ ++ /* Take WAL_READ_LOCK(0). This has the effect of preventing any ++ ** writers from running a checkpoint, but does not stop them ++ ** from running recovery. */ ++ rc = walLockShared(pWal, WAL_READ_LOCK(0)); ++ if( rc!=SQLITE_OK ){ ++ if( rc==SQLITE_BUSY ) rc = WAL_RETRY; ++ goto begin_unreliable_shm_out; ++ } ++ pWal->readLock = 0; ++ ++ /* Check to see if a separate writer has attached to the shared-memory area, ++ ** thus making the shared-memory "reliable" again. Do this by invoking ++ ** the xShmMap() routine of the VFS and looking to see if the return ++ ** is SQLITE_READONLY instead of SQLITE_READONLY_CANTINIT. ++ ** ++ ** If the shared-memory is now "reliable" return WAL_RETRY, which will ++ ** cause the heap-memory WAL-index to be discarded and the actual ++ ** shared memory to be used in its place. ++ ** ++ ** This step is important because, even though this connection is holding ++ ** the WAL_READ_LOCK(0) which prevents a checkpoint, a writer might ++ ** have already checkpointed the WAL file and, while the current ++ ** is active, wrap the WAL and start overwriting frames that this ++ ** process wants to use. ++ ** ++ ** Once sqlite3OsShmMap() has been called for an sqlite3_file and has ++ ** returned any SQLITE_READONLY value, it must return only SQLITE_READONLY ++ ** or SQLITE_READONLY_CANTINIT or some error for all subsequent invocations, ++ ** even if some external agent does a "chmod" to make the shared-memory ++ ** writable by us, until sqlite3OsShmUnmap() has been called. ++ ** This is a requirement on the VFS implementation. ++ */ ++ rc = sqlite3OsShmMap(pWal->pDbFd, 0, WALINDEX_PGSZ, 0, &pDummy); ++ assert( rc!=SQLITE_OK ); /* SQLITE_OK not possible for read-only connection */ ++ if( rc!=SQLITE_READONLY_CANTINIT ){ ++ rc = (rc==SQLITE_READONLY ? WAL_RETRY : rc); ++ goto begin_unreliable_shm_out; ++ } ++ ++ /* We reach this point only if the real shared-memory is still unreliable. ++ ** Assume the in-memory WAL-index substitute is correct and load it ++ ** into pWal->hdr. ++ */ ++ memcpy(&pWal->hdr, (void*)walIndexHdr(pWal), sizeof(WalIndexHdr)); ++ ++ /* Make sure some writer hasn't come in and changed the WAL file out ++ ** from under us, then disconnected, while we were not looking. ++ */ ++ rc = sqlite3OsFileSize(pWal->pWalFd, &szWal); ++ if( rc!=SQLITE_OK ){ ++ goto begin_unreliable_shm_out; ++ } ++ if( szWal<WAL_HDRSIZE ){ ++ /* If the wal file is too small to contain a wal-header and the ++ ** wal-index header has mxFrame==0, then it must be safe to proceed ++ ** reading the database file only. However, the page cache cannot ++ ** be trusted, as a read/write connection may have connected, written ++ ** the db, run a checkpoint, truncated the wal file and disconnected ++ ** since this client's last read transaction. */ ++ *pChanged = 1; ++ rc = (pWal->hdr.mxFrame==0 ? SQLITE_OK : WAL_RETRY); ++ goto begin_unreliable_shm_out; ++ } ++ ++ /* Check the salt keys at the start of the wal file still match. */ ++ rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0); ++ if( rc!=SQLITE_OK ){ ++ goto begin_unreliable_shm_out; ++ } ++ if( memcmp(&pWal->hdr.aSalt, &aBuf[16], 8) ){ ++ /* Some writer has wrapped the WAL file while we were not looking. ++ ** Return WAL_RETRY which will cause the in-memory WAL-index to be ++ ** rebuilt. */ ++ rc = WAL_RETRY; ++ goto begin_unreliable_shm_out; ++ } ++ ++ /* Allocate a buffer to read frames into */ ++ szFrame = pWal->hdr.szPage + WAL_FRAME_HDRSIZE; ++ aFrame = (u8 *)sqlite3_malloc64(szFrame); ++ if( aFrame==0 ){ ++ rc = SQLITE_NOMEM_BKPT; ++ goto begin_unreliable_shm_out; ++ } ++ aData = &aFrame[WAL_FRAME_HDRSIZE]; ++ ++ /* Check to see if a complete transaction has been appended to the ++ ** wal file since the heap-memory wal-index was created. If so, the ++ ** heap-memory wal-index is discarded and WAL_RETRY returned to ++ ** the caller. */ ++ aSaveCksum[0] = pWal->hdr.aFrameCksum[0]; ++ aSaveCksum[1] = pWal->hdr.aFrameCksum[1]; ++ for(iOffset=walFrameOffset(pWal->hdr.mxFrame+1, pWal->hdr.szPage); ++ iOffset+szFrame<=szWal; ++ iOffset+=szFrame ++ ){ ++ u32 pgno; /* Database page number for frame */ ++ u32 nTruncate; /* dbsize field from frame header */ ++ ++ /* Read and decode the next log frame. */ ++ rc = sqlite3OsRead(pWal->pWalFd, aFrame, szFrame, iOffset); ++ if( rc!=SQLITE_OK ) break; ++ if( !walDecodeFrame(pWal, &pgno, &nTruncate, aData, aFrame) ) break; ++ ++ /* If nTruncate is non-zero, then a complete transaction has been ++ ** appended to this wal file. Set rc to WAL_RETRY and break out of ++ ** the loop. */ ++ if( nTruncate ){ ++ rc = WAL_RETRY; ++ break; ++ } ++ } ++ pWal->hdr.aFrameCksum[0] = aSaveCksum[0]; ++ pWal->hdr.aFrameCksum[1] = aSaveCksum[1]; ++ ++ begin_unreliable_shm_out: ++ sqlite3_free(aFrame); ++ if( rc!=SQLITE_OK ){ ++ int i; ++ for(i=0; i<pWal->nWiData; i++){ ++ sqlite3_free((void*)pWal->apWiData[i]); ++ pWal->apWiData[i] = 0; ++ } ++ pWal->bShmUnreliable = 0; ++ sqlite3WalEndReadTransaction(pWal); ++ *pChanged = 1; ++ } ++ return rc; ++} ++ + /* + ** Attempt to start a read transaction. This might fail due to a race or + ** other transient condition. When that happens, it returns WAL_RETRY to +@@ -57147,7 +60474,7 @@ + ** checkpointed. If useWal==0 then this routine calls walIndexReadHdr() + ** to make a copy of the wal-index header into pWal->hdr. If the + ** wal-index header has changed, *pChanged is set to 1 (as an indication +-** to the caller that the local paget cache is obsolete and needs to be ++** to the caller that the local page cache is obsolete and needs to be + ** flushed.) When useWal==1, the wal-index header is assumed to already + ** be loaded and the pChanged parameter is unused. + ** +@@ -57193,6 +60520,9 @@ + + assert( pWal->readLock<0 ); /* Not currently locked */ + ++ /* useWal may only be set for read/write connections */ ++ assert( (pWal->readOnly & WAL_SHM_RDONLY)==0 || useWal==0 ); ++ + /* Take steps to avoid spinning forever if there is a protocol error. + ** + ** Circumstances that cause a RETRY should only last for the briefest +@@ -57221,7 +60551,10 @@ + } + + if( !useWal ){ +- rc = walIndexReadHdr(pWal, pChanged); ++ assert( rc==SQLITE_OK ); ++ if( pWal->bShmUnreliable==0 ){ ++ rc = walIndexReadHdr(pWal, pChanged); ++ } + if( rc==SQLITE_BUSY ){ + /* If there is not a recovery running in another thread or process + ** then convert BUSY errors to WAL_RETRY. If recovery is known to +@@ -57250,13 +60583,17 @@ + if( rc!=SQLITE_OK ){ + return rc; + } ++ else if( pWal->bShmUnreliable ){ ++ return walBeginShmUnreliable(pWal, pChanged); ++ } + } + ++ assert( pWal->nWiData>0 ); ++ assert( pWal->apWiData[0]!=0 ); + pInfo = walCkptInfo(pWal); +- if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame ++ if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame + #ifdef SQLITE_ENABLE_SNAPSHOT +- && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0 +- || 0==memcmp(&pWal->hdr, pWal->pSnapshot, sizeof(WalIndexHdr))) ++ && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0) + #endif + ){ + /* The WAL has been completely backfilled (or it is empty). +@@ -57303,7 +60640,7 @@ + } + #endif + for(i=1; i<WAL_NREADER; i++){ +- u32 thisMark = pInfo->aReadMark[i]; ++ u32 thisMark = AtomicLoad(pInfo->aReadMark+i); + if( mxReadMark<=thisMark && thisMark<=mxFrame ){ + assert( thisMark!=READMARK_NOT_USED ); + mxReadMark = thisMark; +@@ -57316,7 +60653,7 @@ + for(i=1; i<WAL_NREADER; i++){ + rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1); + if( rc==SQLITE_OK ){ +- mxReadMark = pInfo->aReadMark[i] = mxFrame; ++ mxReadMark = AtomicStore(pInfo->aReadMark+i,mxFrame); + mxI = i; + walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); + break; +@@ -57327,7 +60664,7 @@ + } + if( mxI==0 ){ + assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 ); +- return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTLOCK; ++ return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTINIT; + } + + rc = walLockShared(pWal, WAL_READ_LOCK(mxI)); +@@ -57368,9 +60705,9 @@ + ** we can guarantee that the checkpointer that set nBackfill could not + ** see any pages past pWal->hdr.mxFrame, this problem does not come up. + */ +- pWal->minFrame = pInfo->nBackfill+1; ++ pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1; + walShmBarrier(pWal); +- if( pInfo->aReadMark[mxI]!=mxReadMark ++ if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark + || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) + ){ + walUnlockShared(pWal, WAL_READ_LOCK(mxI)); +@@ -57421,16 +60758,14 @@ + }else{ + u32 i = pInfo->nBackfillAttempted; + for(i=pInfo->nBackfillAttempted; i>pInfo->nBackfill; i--){ +- volatile ht_slot *dummy; +- volatile u32 *aPgno; /* Array of page numbers */ +- u32 iZero; /* Frame corresponding to aPgno[0] */ ++ WalHashLoc sLoc; /* Hash table location */ + u32 pgno; /* Page number in db file */ + i64 iDbOff; /* Offset of db file entry */ + i64 iWalOff; /* Offset of wal file entry */ + +- rc = walHashGet(pWal, walFramePage(i), &dummy, &aPgno, &iZero); ++ rc = walHashGet(pWal, walFramePage(i), &sLoc); + if( rc!=SQLITE_OK ) break; +- pgno = aPgno[i-iZero]; ++ pgno = sLoc.aPgno[i-sLoc.iZero]; + iDbOff = (i64)(pgno-1) * szPage; + + if( iDbOff+szPage<=szDb ){ +@@ -57471,7 +60806,7 @@ + ** + ** If the database contents have changes since the previous read + ** transaction, then *pChanged is set to 1 before returning. The +-** Pager layer will use this to know that is cache is stale and ++** Pager layer will use this to know that its cache is stale and + ** needs to be flushed. + */ + SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ +@@ -57533,7 +60868,7 @@ + /* Check that the wal file has not been wrapped. Assuming that it has + ** not, also check that no checkpointer has attempted to checkpoint any + ** frames beyond pSnapshot->mxFrame. If either of these conditions are +- ** true, return SQLITE_BUSY_SNAPSHOT. Otherwise, overwrite pWal->hdr ++ ** true, return SQLITE_ERROR_SNAPSHOT. Otherwise, overwrite pWal->hdr + ** with *pSnapshot and set *pChanged as appropriate for opening the + ** snapshot. */ + if( !memcmp(pSnapshot->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)) +@@ -57543,11 +60878,12 @@ + memcpy(&pWal->hdr, pSnapshot, sizeof(WalIndexHdr)); + *pChanged = bChanged; + }else{ +- rc = SQLITE_BUSY_SNAPSHOT; ++ rc = SQLITE_ERROR_SNAPSHOT; + } + + /* Release the shared CKPT lock obtained above. */ + walUnlockShared(pWal, WAL_CKPT_LOCK); ++ pWal->minFrame = 1; + } + + +@@ -57599,7 +60935,7 @@ + ** then the WAL is ignored by the reader so return early, as if the + ** WAL were empty. + */ +- if( iLast==0 || pWal->readLock==0 ){ ++ if( iLast==0 || (pWal->readLock==0 && pWal->bShmUnreliable==0) ){ + *piRead = 0; + return SQLITE_OK; + } +@@ -57630,22 +60966,21 @@ + ** table after the current read-transaction had started. + */ + iMinHash = walFramePage(pWal->minFrame); +- for(iHash=walFramePage(iLast); iHash>=iMinHash && iRead==0; iHash--){ +- volatile ht_slot *aHash; /* Pointer to hash table */ +- volatile u32 *aPgno; /* Pointer to array of page numbers */ +- u32 iZero; /* Frame number corresponding to aPgno[0] */ ++ for(iHash=walFramePage(iLast); iHash>=iMinHash; iHash--){ ++ WalHashLoc sLoc; /* Hash table location */ + int iKey; /* Hash slot index */ + int nCollide; /* Number of hash collisions remaining */ + int rc; /* Error code */ + +- rc = walHashGet(pWal, iHash, &aHash, &aPgno, &iZero); ++ rc = walHashGet(pWal, iHash, &sLoc); + if( rc!=SQLITE_OK ){ + return rc; + } + nCollide = HASHTABLE_NSLOT; +- for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){ +- u32 iFrame = aHash[iKey] + iZero; +- if( iFrame<=iLast && iFrame>=pWal->minFrame && aPgno[aHash[iKey]]==pgno ){ ++ for(iKey=walHash(pgno); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){ ++ u32 iFrame = sLoc.aHash[iKey] + sLoc.iZero; ++ if( iFrame<=iLast && iFrame>=pWal->minFrame ++ && sLoc.aPgno[sLoc.aHash[iKey]]==pgno ){ + assert( iFrame>iRead || CORRUPT_DB ); + iRead = iFrame; + } +@@ -57653,6 +60988,7 @@ + return SQLITE_CORRUPT_BKPT; + } + } ++ if( iRead ) break; + } + + #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT +@@ -57662,8 +60998,8 @@ + { + u32 iRead2 = 0; + u32 iTest; +- assert( pWal->minFrame>0 ); +- for(iTest=iLast; iTest>=pWal->minFrame; iTest--){ ++ assert( pWal->bShmUnreliable || pWal->minFrame>0 ); ++ for(iTest=iLast; iTest>=pWal->minFrame && iTest>0; iTest--){ + if( walFramePgno(pWal, iTest)==pgno ){ + iRead2 = iTest; + break; +@@ -57951,8 +61287,8 @@ + iOffset += iFirstAmt; + iAmt -= iFirstAmt; + pContent = (void*)(iFirstAmt + (char*)pContent); +- assert( p->syncFlags & (SQLITE_SYNC_NORMAL|SQLITE_SYNC_FULL) ); +- rc = sqlite3OsSync(p->pFd, p->syncFlags & SQLITE_SYNC_MASK); ++ assert( WAL_SYNC_FLAGS(p->syncFlags)!=0 ); ++ rc = sqlite3OsSync(p->pFd, WAL_SYNC_FLAGS(p->syncFlags)); + if( iAmt==0 || rc ) return rc; + } + rc = sqlite3OsWrite(p->pFd, pContent, iAmt, iOffset); +@@ -58122,10 +61458,10 @@ + ** an out-of-order write following a WAL restart could result in + ** database corruption. See the ticket: + ** +- ** http://localhost:591/sqlite/info/ff5be73dee ++ ** https://sqlite.org/src/info/ff5be73dee + */ +- if( pWal->syncHeader && sync_flags ){ +- rc = sqlite3OsSync(pWal->pWalFd, sync_flags & SQLITE_SYNC_MASK); ++ if( pWal->syncHeader ){ ++ rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags)); + if( rc ) return rc; + } + } +@@ -58200,7 +61536,7 @@ + ** sector boundary is synced; the part of the last frame that extends + ** past the sector boundary is written after the sync. + */ +- if( isCommit && (sync_flags & WAL_SYNC_TRANSACTIONS)!=0 ){ ++ if( isCommit && WAL_SYNC_FLAGS(sync_flags)!=0 ){ + int bSync = 1; + if( pWal->padToSectorBoundary ){ + int sectorSize = sqlite3SectorSize(pWal->pWalFd); +@@ -58216,7 +61552,7 @@ + } + if( bSync ){ + assert( rc==SQLITE_OK ); +- rc = sqlite3OsSync(w.pFd, sync_flags & SQLITE_SYNC_MASK); ++ rc = sqlite3OsSync(w.pFd, WAL_SYNC_FLAGS(sync_flags)); + } + } + +@@ -58439,24 +61775,24 @@ + assert( pWal->readLock>=0 || (op<=0 && pWal->exclusiveMode==0) ); + + if( op==0 ){ +- if( pWal->exclusiveMode ){ +- pWal->exclusiveMode = 0; ++ if( pWal->exclusiveMode!=WAL_NORMAL_MODE ){ ++ pWal->exclusiveMode = WAL_NORMAL_MODE; + if( walLockShared(pWal, WAL_READ_LOCK(pWal->readLock))!=SQLITE_OK ){ +- pWal->exclusiveMode = 1; ++ pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; + } +- rc = pWal->exclusiveMode==0; ++ rc = pWal->exclusiveMode==WAL_NORMAL_MODE; + }else{ + /* Already in locking_mode=NORMAL */ + rc = 0; + } + }else if( op>0 ){ +- assert( pWal->exclusiveMode==0 ); ++ assert( pWal->exclusiveMode==WAL_NORMAL_MODE ); + assert( pWal->readLock>=0 ); + walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock)); +- pWal->exclusiveMode = 1; ++ pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; + rc = 1; + }else{ +- rc = pWal->exclusiveMode==0; ++ rc = pWal->exclusiveMode==WAL_NORMAL_MODE; + } + return rc; + } +@@ -58519,6 +61855,43 @@ + if( pHdr1->mxFrame>pHdr2->mxFrame ) return +1; + return 0; + } ++ ++/* ++** The caller currently has a read transaction open on the database. ++** This function takes a SHARED lock on the CHECKPOINTER slot and then ++** checks if the snapshot passed as the second argument is still ++** available. If so, SQLITE_OK is returned. ++** ++** If the snapshot is not available, SQLITE_ERROR is returned. Or, if ++** the CHECKPOINTER lock cannot be obtained, SQLITE_BUSY. If any error ++** occurs (any value other than SQLITE_OK is returned), the CHECKPOINTER ++** lock is released before returning. ++*/ ++SQLITE_PRIVATE int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot){ ++ int rc; ++ rc = walLockShared(pWal, WAL_CKPT_LOCK); ++ if( rc==SQLITE_OK ){ ++ WalIndexHdr *pNew = (WalIndexHdr*)pSnapshot; ++ if( memcmp(pNew->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)) ++ || pNew->mxFrame<walCkptInfo(pWal)->nBackfillAttempted ++ ){ ++ rc = SQLITE_ERROR_SNAPSHOT; ++ walUnlockShared(pWal, WAL_CKPT_LOCK); ++ } ++ } ++ return rc; ++} ++ ++/* ++** Release a lock obtained by an earlier successful call to ++** sqlite3WalSnapshotCheck(). ++*/ ++SQLITE_PRIVATE void sqlite3WalSnapshotUnlock(Wal *pWal){ ++ assert( pWal ); ++ walUnlockShared(pWal, WAL_CKPT_LOCK); ++} ++ ++ + #endif /* SQLITE_ENABLE_SNAPSHOT */ + + #ifdef SQLITE_ENABLE_ZIPVFS +@@ -59063,30 +62436,31 @@ + ** eState==FAULT: Cursor fault with skipNext as error code. + */ + struct BtCursor { ++ u8 eState; /* One of the CURSOR_XXX constants (see below) */ ++ u8 curFlags; /* zero or more BTCF_* flags defined below */ ++ u8 curPagerFlags; /* Flags to send to sqlite3PagerGet() */ ++ u8 hints; /* As configured by CursorSetHints() */ ++ int skipNext; /* Prev() is noop if negative. Next() is noop if positive. ++ ** Error code if eState==CURSOR_FAULT */ + Btree *pBtree; /* The Btree to which this cursor belongs */ ++ Pgno *aOverflow; /* Cache of overflow page locations */ ++ void *pKey; /* Saved key that was cursor last known position */ ++ /* All fields above are zeroed when the cursor is allocated. See ++ ** sqlite3BtreeCursorZero(). Fields that follow must be manually ++ ** initialized. */ ++#define BTCURSOR_FIRST_UNINIT pBt /* Name of first uninitialized field */ + BtShared *pBt; /* The BtShared this cursor points to */ + BtCursor *pNext; /* Forms a linked list of all cursors */ +- Pgno *aOverflow; /* Cache of overflow page locations */ + CellInfo info; /* A parse of the cell we are pointing at */ + i64 nKey; /* Size of pKey, or last integer key */ +- void *pKey; /* Saved key that was cursor last known position */ + Pgno pgnoRoot; /* The root page of this tree */ +- int nOvflAlloc; /* Allocated size of aOverflow[] array */ +- int skipNext; /* Prev() is noop if negative. Next() is noop if positive. +- ** Error code if eState==CURSOR_FAULT */ +- u8 curFlags; /* zero or more BTCF_* flags defined below */ +- u8 curPagerFlags; /* Flags to send to sqlite3PagerGet() */ +- u8 eState; /* One of the CURSOR_XXX constants (see below) */ +- u8 hints; /* As configured by CursorSetHints() */ +- /* All fields above are zeroed when the cursor is allocated. See +- ** sqlite3BtreeCursorZero(). Fields that follow must be manually +- ** initialized. */ + i8 iPage; /* Index of current page in apPage */ + u8 curIntKey; /* Value of apPage[0]->intKey */ + u16 ix; /* Current index for apPage[iPage] */ + u16 aiIdx[BTCURSOR_MAX_DEPTH-1]; /* Current index in apPage[i] */ + struct KeyInfo *pKeyInfo; /* Arg passed to comparison function */ +- MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */ ++ MemPage *pPage; /* Current page */ ++ MemPage *apPage[BTCURSOR_MAX_DEPTH-1]; /* Stack of parents of current page */ + }; + + /* +@@ -59129,8 +62503,8 @@ + ** Do nothing else with this cursor. Any attempt to use the cursor + ** should return the error code stored in BtCursor.skipNext + */ +-#define CURSOR_INVALID 0 +-#define CURSOR_VALID 1 ++#define CURSOR_VALID 0 ++#define CURSOR_INVALID 1 + #define CURSOR_SKIPNEXT 2 + #define CURSOR_REQUIRESEEK 3 + #define CURSOR_FAULT 4 +@@ -59447,10 +62821,10 @@ + skipOk = 0; + } + } +- db->skipBtreeMutex = skipOk; ++ db->noSharedCache = skipOk; + } + SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3 *db){ +- if( db->skipBtreeMutex==0 ) btreeEnterAll(db); ++ if( db->noSharedCache==0 ) btreeEnterAll(db); + } + static void SQLITE_NOINLINE btreeLeaveAll(sqlite3 *db){ + int i; +@@ -59462,7 +62836,7 @@ + } + } + SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3 *db){ +- if( db->skipBtreeMutex==0 ) btreeLeaveAll(db); ++ if( db->noSharedCache==0 ) btreeLeaveAll(db); + } + + #ifndef NDEBUG +@@ -59675,6 +63049,34 @@ + #define hasReadConflicts(a, b) 0 + #endif + ++/* ++** Implementation of the SQLITE_CORRUPT_PAGE() macro. Takes a single ++** (MemPage*) as an argument. The (MemPage*) must not be NULL. ++** ++** If SQLITE_DEBUG is not defined, then this macro is equivalent to ++** SQLITE_CORRUPT_BKPT. Or, if SQLITE_DEBUG is set, then the log message ++** 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; ++} ++# define SQLITE_CORRUPT_PAGE(pMemPage) corruptPageError(__LINE__, pMemPage) ++#else ++# define SQLITE_CORRUPT_PAGE(pMemPage) SQLITE_CORRUPT_PGNO(pMemPage->pgno) ++#endif ++ + #ifndef SQLITE_OMIT_SHARED_CACHE + + #ifdef SQLITE_DEBUG +@@ -60002,7 +63404,9 @@ + + #endif /* SQLITE_OMIT_SHARED_CACHE */ + +-static void releasePage(MemPage *pPage); /* Forward reference */ ++static void releasePage(MemPage *pPage); /* Forward reference */ ++static void releasePageOne(MemPage *pPage); /* Forward reference */ ++static void releasePageNotNull(MemPage *pPage); /* Forward reference */ + + /* + ***** This routine is used inside of assert() only **** +@@ -60161,11 +63565,13 @@ + */ + static void btreeReleaseAllCursorPages(BtCursor *pCur){ + int i; +- for(i=0; i<=pCur->iPage; i++){ +- releasePage(pCur->apPage[i]); +- pCur->apPage[i] = 0; ++ if( pCur->iPage>=0 ){ ++ for(i=0; i<pCur->iPage; i++){ ++ releasePageNotNull(pCur->apPage[i]); ++ } ++ releasePageNotNull(pCur->pPage); ++ pCur->iPage = -1; + } +- pCur->iPage = -1; + } + + /* +@@ -60294,7 +63700,7 @@ + return rc; + } + }else{ +- testcase( p->iPage>0 ); ++ testcase( p->iPage>=0 ); + btreeReleaseAllCursorPages(p); + } + } +@@ -60334,7 +63740,7 @@ + if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT; + sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey); + if( pIdxKey->nField==0 ){ +- rc = SQLITE_CORRUPT_PGNO(pCur->apPage[pCur->iPage]->pgno); ++ rc = SQLITE_CORRUPT_BKPT; + goto moveto_done; + } + }else{ +@@ -60395,10 +63801,25 @@ + ** back to where it ought to be if this routine returns true. + */ + SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor *pCur){ +- return pCur->eState!=CURSOR_VALID; ++ assert( EIGHT_BYTE_ALIGNMENT(pCur) ++ || pCur==sqlite3BtreeFakeValidCursor() ); ++ assert( offsetof(BtCursor, eState)==0 ); ++ assert( sizeof(pCur->eState)==1 ); ++ return CURSOR_VALID != *(u8*)pCur; + } + + /* ++** Return a pointer to a fake BtCursor object that will always answer ++** false to the sqlite3BtreeCursorHasMoved() routine above. The fake ++** cursor returned must not be used with any other Btree interface. ++*/ ++SQLITE_PRIVATE BtCursor *sqlite3BtreeFakeValidCursor(void){ ++ static u8 fakeCursor = CURSOR_VALID; ++ assert( offsetof(BtCursor, eState)==0 ); ++ return (BtCursor*)&fakeCursor; ++} ++ ++/* + ** This routine restores a cursor back to its original position after it + ** has been moved by some outside activity (such as a btree rebalance or + ** a row having been deleted out from under the cursor). +@@ -60947,8 +64368,11 @@ + int sz2 = 0; + int sz = get2byte(&data[iFree+2]); + int top = get2byte(&data[hdr+5]); ++ if( top>=iFree ){ ++ return SQLITE_CORRUPT_PAGE(pPage); ++ } + if( iFree2 ){ +- if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ assert( iFree+sz<=iFree2 ); /* Verified by pageFindSlot() */ + sz2 = get2byte(&data[iFree2+2]); + assert( iFree+sz+sz2+iFree2-(iFree+sz) <= usableSize ); + memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz)); +@@ -60979,13 +64403,13 @@ + ** if PRAGMA cell_size_check=ON. + */ + if( pc<iCellFirst || pc>iCellLast ){ +- return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ return SQLITE_CORRUPT_PAGE(pPage); + } + assert( pc>=iCellFirst && pc<=iCellLast ); + size = pPage->xCellSize(pPage, &src[pc]); + cbrk -= size; + if( cbrk<iCellFirst || pc+size>usableSize ){ +- return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ return SQLITE_CORRUPT_PAGE(pPage); + } + assert( cbrk+size<=usableSize && cbrk>=iCellFirst ); + testcase( cbrk+size==usableSize ); +@@ -61005,7 +64429,7 @@ + + defragment_out: + if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){ +- return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ return SQLITE_CORRUPT_PAGE(pPage); + } + assert( cbrk>=iCellFirst ); + put2byte(&data[hdr+5], cbrk); +@@ -61037,16 +64461,10 @@ + int pc = get2byte(&aData[iAddr]); + int x; + int usableSize = pPg->pBt->usableSize; ++ int size; /* Size of the free slot */ + + assert( pc>0 ); +- do{ +- int size; /* Size of the free slot */ +- /* EVIDENCE-OF: R-06866-39125 Freeblocks are always connected in order of +- ** increasing offset. */ +- if( pc>usableSize-4 || pc<iAddr+4 ){ +- *pRc = SQLITE_CORRUPT_PGNO(pPg->pgno); +- return 0; +- } ++ while( pc<=usableSize-4 ){ + /* EVIDENCE-OF: R-22710-53328 The third and fourth bytes of each + ** freeblock form a big-endian integer which is the size of the freeblock + ** in bytes, including the 4-byte header. */ +@@ -61054,8 +64472,8 @@ + if( (x = size - nByte)>=0 ){ + testcase( x==4 ); + testcase( x==3 ); +- if( pc < pPg->cellOffset+2*pPg->nCell || size+pc > usableSize ){ +- *pRc = SQLITE_CORRUPT_PGNO(pPg->pgno); ++ if( size+pc > usableSize ){ ++ *pRc = SQLITE_CORRUPT_PAGE(pPg); + return 0; + }else if( x<4 ){ + /* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total +@@ -61075,7 +64493,11 @@ + } + iAddr = pc; + pc = get2byte(&aData[pc]); +- }while( pc ); ++ if( pc<iAddr+size ) break; ++ } ++ if( pc ){ ++ *pRc = SQLITE_CORRUPT_PAGE(pPg); ++ } + + return 0; + } +@@ -61122,7 +64544,7 @@ + if( top==0 && pPage->pBt->usableSize==65536 ){ + top = 65536; + }else{ +- return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ return SQLITE_CORRUPT_PAGE(pPage); + } + } + +@@ -61189,7 +64611,7 @@ + u8 hdr; /* Page header size. 0 or 100 */ + u8 nFrag = 0; /* Reduction in fragmentation */ + u16 iOrigSize = iSize; /* Original value of iSize */ +- u32 iLast = pPage->pBt->usableSize-4; /* Largest possible freeblock offset */ ++ u16 x; /* Offset to cell content area */ + u32 iEnd = iStart + iSize; /* First byte past the iStart buffer */ + unsigned char *data = pPage->aData; /* Page content */ + +@@ -61199,14 +64621,8 @@ + assert( CORRUPT_DB || iEnd <= pPage->pBt->usableSize ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + assert( iSize>=4 ); /* Minimum cell size is 4 */ +- assert( iStart<=iLast ); ++ assert( iStart<=pPage->pBt->usableSize-4 ); + +- /* Overwrite deleted information with zeros when the secure_delete +- ** option is enabled */ +- if( pPage->pBt->btsFlags & BTS_FAST_SECURE ){ +- memset(&data[iStart], 0, iSize); +- } +- + /* The list of freeblocks must be in ascending order. Find the + ** spot on the list where iStart should be inserted. + */ +@@ -61218,11 +64634,13 @@ + while( (iFreeBlk = get2byte(&data[iPtr]))<iStart ){ + if( iFreeBlk<iPtr+4 ){ + if( iFreeBlk==0 ) break; +- return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ return SQLITE_CORRUPT_PAGE(pPage); + } + iPtr = iFreeBlk; + } +- if( iFreeBlk>iLast ) return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ if( iFreeBlk>pPage->pBt->usableSize-4 ){ ++ return SQLITE_CORRUPT_PAGE(pPage); ++ } + assert( iFreeBlk>iPtr || iFreeBlk==0 ); + + /* At this point: +@@ -61233,10 +64651,10 @@ + */ + if( iFreeBlk && iEnd+3>=iFreeBlk ){ + nFrag = iFreeBlk - iEnd; +- if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_PAGE(pPage); + iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]); + if( iEnd > pPage->pBt->usableSize ){ +- return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ return SQLITE_CORRUPT_PAGE(pPage); + } + iSize = iEnd - iStart; + iFreeBlk = get2byte(&data[iFreeBlk]); +@@ -61249,28 +64667,34 @@ + if( iPtr>hdr+1 ){ + int iPtrEnd = iPtr + get2byte(&data[iPtr+2]); + if( iPtrEnd+3>=iStart ){ +- if( iPtrEnd>iStart ) return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ if( iPtrEnd>iStart ) return SQLITE_CORRUPT_PAGE(pPage); + nFrag += iStart - iPtrEnd; + iSize = iEnd - iPtr; + iStart = iPtr; + } + } +- if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PAGE(pPage); + data[hdr+7] -= nFrag; + } +- if( iStart==get2byte(&data[hdr+5]) ){ ++ x = get2byte(&data[hdr+5]); ++ 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( iPtr!=hdr+1 ) return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ if( iStart<x || 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); +- put2byte(&data[iStart], iFreeBlk); +- put2byte(&data[iStart+2], iSize); + } ++ 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; + } +@@ -61330,7 +64754,7 @@ + }else{ + /* EVIDENCE-OF: R-47608-56469 Any other value for the b-tree page type is + ** an error. */ +- return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ return SQLITE_CORRUPT_PAGE(pPage); + } + pPage->max1bytePayload = pBt->max1bytePayload; + return SQLITE_OK; +@@ -61371,7 +64795,7 @@ + /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating + ** the b-tree page type. */ + if( decodeFlags(pPage, data[hdr]) ){ +- return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ return SQLITE_CORRUPT_PAGE(pPage); + } + assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); + pPage->maskPage = (u16)(pBt->pageSize - 1); +@@ -61390,7 +64814,7 @@ + pPage->nCell = get2byte(&data[hdr+3]); + if( pPage->nCell>MX_CELL(pBt) ){ + /* To many cells for a single page. The page must be corrupt */ +- return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ return SQLITE_CORRUPT_PAGE(pPage); + } + testcase( pPage->nCell==MX_CELL(pBt) ); + /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only +@@ -61418,12 +64842,12 @@ + testcase( pc==iCellFirst ); + testcase( pc==iCellLast ); + if( pc<iCellFirst || pc>iCellLast ){ +- return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ return SQLITE_CORRUPT_PAGE(pPage); + } + sz = pPage->xCellSize(pPage, &data[pc]); + testcase( pc+sz==usableSize ); + if( pc+sz>usableSize ){ +- return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ return SQLITE_CORRUPT_PAGE(pPage); + } + } + if( !pPage->leaf ) iCellLast++; +@@ -61441,12 +64865,12 @@ + /* EVIDENCE-OF: R-55530-52930 In a well-formed b-tree page, there will + ** always be at least one cell before the first freeblock. + */ +- return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ return SQLITE_CORRUPT_PAGE(pPage); + } + while( 1 ){ + if( pc>iCellLast ){ + /* Freeblock off the end of the page */ +- return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ return SQLITE_CORRUPT_PAGE(pPage); + } + next = get2byte(&data[pc]); + size = get2byte(&data[pc+2]); +@@ -61456,11 +64880,11 @@ + } + if( next>0 ){ + /* Freeblock not in ascending order */ +- return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ return SQLITE_CORRUPT_PAGE(pPage); + } + if( pc+size>(unsigned int)usableSize ){ + /* Last freeblock extends past page end */ +- return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ return SQLITE_CORRUPT_PAGE(pPage); + } + } + +@@ -61472,7 +64896,7 @@ + ** area, according to the page header, lies within the page. + */ + if( nFree>usableSize ){ +- return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ return SQLITE_CORRUPT_PAGE(pPage); + } + pPage->nFree = (u16)(nFree - iCellFirst); + pPage->isInit = 1; +@@ -61585,7 +65009,7 @@ + } + SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree *p){ + assert( sqlite3BtreeHoldsMutex(p) ); +- assert( ((p->pBt->nPage)&0x8000000)==0 ); ++ assert( ((p->pBt->nPage)&0x80000000)==0 ); + return btreePagecount(p->pBt); + } + +@@ -61612,7 +65036,7 @@ + int rc; + DbPage *pDbPage; + assert( sqlite3_mutex_held(pBt->mutex) ); +- assert( pCur==0 || ppPage==&pCur->apPage[pCur->iPage] ); ++ assert( pCur==0 || ppPage==&pCur->pPage ); + assert( pCur==0 || bReadOnly==pCur->curPagerFlags ); + assert( pCur==0 || pCur->iPage>0 ); + +@@ -61646,7 +65070,10 @@ + return SQLITE_OK; + + getAndInitPage_error: +- if( pCur ) pCur->iPage--; ++ if( pCur ){ ++ pCur->iPage--; ++ pCur->pPage = pCur->apPage[pCur->iPage]; ++ } + testcase( pgno==0 ); + assert( pgno!=0 || rc==SQLITE_CORRUPT ); + return rc; +@@ -61655,6 +65082,8 @@ + /* + ** Release a MemPage. This should be called once for each prior + ** call to btreeGetPage. ++** ++** Page1 is a special case and must be released using releasePageOne(). + */ + static void releasePageNotNull(MemPage *pPage){ + assert( pPage->aData ); +@@ -61668,6 +65097,16 @@ + static void releasePage(MemPage *pPage){ + if( pPage ) releasePageNotNull(pPage); + } ++static void releasePageOne(MemPage *pPage){ ++ assert( pPage!=0 ); ++ assert( pPage->aData ); ++ assert( pPage->pBt ); ++ assert( pPage->pDbPage!=0 ); ++ assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); ++ assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData ); ++ assert( sqlite3_mutex_held(pPage->pBt->mutex) ); ++ sqlite3PagerUnrefPageOne(pPage->pDbPage); ++} + + /* + ** Get an unused page. +@@ -61733,7 +65172,8 @@ + BtShared *pBt = (BtShared*)pArg; + assert( pBt->db ); + assert( sqlite3_mutex_held(pBt->db->mutex) ); +- return sqlite3InvokeBusyHandler(&pBt->db->busyHandler); ++ return sqlite3InvokeBusyHandler(&pBt->db->busyHandler, ++ sqlite3PagerFile(pBt->pPager)); + } + + /* +@@ -61911,7 +65351,7 @@ + } + pBt->openFlags = (u8)flags; + pBt->db = db; +- sqlite3PagerSetBusyhandler(pBt->pPager, btreeInvokeBusyHandler, pBt); ++ sqlite3PagerSetBusyHandler(pBt->pPager, btreeInvokeBusyHandler, pBt); + p->pBt = pBt; + + pBt->pCursor = 0; +@@ -62452,7 +65892,8 @@ + ** set to the value passed to this function as the second parameter, + ** set it so. + */ +-#if SQLITE_DEFAULT_SYNCHRONOUS!=SQLITE_DEFAULT_WAL_SYNCHRONOUS ++#if SQLITE_DEFAULT_SYNCHRONOUS!=SQLITE_DEFAULT_WAL_SYNCHRONOUS \ ++ && !defined(SQLITE_OMIT_WAL) + static void setDefaultSyncFlag(BtShared *pBt, u8 safety_level){ + sqlite3 *db; + Db *pDb; +@@ -62472,6 +65913,10 @@ + # define setDefaultSyncFlag(pBt,safety_level) + #endif + ++/* Forward declaration */ ++static int newDatabase(BtShared*); ++ ++ + /* + ** Get a reference to pPage1 of the database file. This will + ** also acquire a readlock on that file. +@@ -62503,6 +65948,9 @@ + if( nPage==0 || memcmp(24+(u8*)pPage1->aData, 92+(u8*)pPage1->aData,4)!=0 ){ + nPage = nPageFile; + } ++ if( (pBt->db->flags & SQLITE_ResetDatabase)!=0 ){ ++ nPage = 0; ++ } + if( nPage>0 ){ + u32 pageSize; + u32 usableSize; +@@ -62546,7 +65994,7 @@ + }else{ + setDefaultSyncFlag(pBt, SQLITE_DEFAULT_WAL_SYNCHRONOUS+1); + if( isOpen==0 ){ +- releasePage(pPage1); ++ releasePageOne(pPage1); + return SQLITE_OK; + } + } +@@ -62593,7 +66041,7 @@ + ** zero and return SQLITE_OK. The caller will call this function + ** again with the correct page-size. + */ +- releasePage(pPage1); ++ releasePageOne(pPage1); + pBt->usableSize = usableSize; + pBt->pageSize = pageSize; + freeTempSpace(pBt); +@@ -62601,7 +66049,7 @@ + pageSize-usableSize); + return rc; + } +- if( (pBt->db->flags & SQLITE_WriteSchema)==0 && nPage>nPageFile ){ ++ if( sqlite3WritableSchema(pBt->db)==0 && nPage>nPageFile ){ + rc = SQLITE_CORRUPT_BKPT; + goto page1_init_failed; + } +@@ -62647,7 +66095,7 @@ + return SQLITE_OK; + + page1_init_failed: +- releasePage(pPage1); ++ releasePageOne(pPage1); + pBt->pPage1 = 0; + return rc; + } +@@ -62692,7 +66140,7 @@ + assert( pPage1->aData ); + assert( sqlite3PagerRefcount(pBt->pPager)==1 ); + pBt->pPage1 = 0; +- releasePageNotNull(pPage1); ++ releasePageOne(pPage1); + } + } + +@@ -62789,7 +66237,7 @@ + ** when A already has a read lock, we encourage A to give up and let B + ** proceed. + */ +-SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){ ++SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){ + BtShared *pBt = p->pBt; + int rc = SQLITE_OK; + +@@ -62805,6 +66253,12 @@ + } + assert( pBt->inTransaction==TRANS_WRITE || IfNotOmitAV(pBt->bDoTruncate)==0 ); + ++ if( (p->db->flags & SQLITE_ResetDatabase) ++ && sqlite3PagerIsreadonly(pBt->pPager)==0 ++ ){ ++ pBt->btsFlags &= ~BTS_READ_ONLY; ++ } ++ + /* Write transactions are not possible on a read-only database */ + if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){ + rc = SQLITE_READONLY; +@@ -62864,6 +66318,11 @@ + rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db)); + if( rc==SQLITE_OK ){ + rc = newDatabase(pBt); ++ }else if( rc==SQLITE_BUSY_SNAPSHOT && pBt->inTransaction==TRANS_NONE ){ ++ /* if there was no transaction opened when this function was ++ ** called and SQLITE_BUSY_SNAPSHOT is returned, change the error ++ ** code to SQLITE_BUSY. */ ++ rc = SQLITE_BUSY; + } + } + } +@@ -62873,6 +66332,7 @@ + } + }while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE && + btreeInvokeBusyHandler(pBt) ); ++ sqlite3PagerResetLockTimeout(pBt->pPager); + + if( rc==SQLITE_OK ){ + if( p->inTrans==TRANS_NONE ){ +@@ -62914,14 +66374,18 @@ + } + } + +- + trans_begun: +- if( rc==SQLITE_OK && wrflag ){ +- /* This call makes sure that the pager has the correct number of +- ** open savepoints. If the second parameter is greater than 0 and +- ** the sub-journal is not already open, then it will be opened here. +- */ +- rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint); ++ if( rc==SQLITE_OK ){ ++ if( pSchemaVersion ){ ++ *pSchemaVersion = get4byte(&pBt->pPage1->aData[40]); ++ } ++ if( wrflag ){ ++ /* This call makes sure that the pager has the correct number of ++ ** open savepoints. If the second parameter is greater than 0 and ++ ** the sub-journal is not already open, then it will be opened here. ++ */ ++ rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint); ++ } + } + + btreeIntegrity(p); +@@ -62987,7 +66451,7 @@ + if( eType==PTRMAP_OVERFLOW2 ){ + /* The pointer is always the first 4 bytes of the page in this case. */ + if( get4byte(pPage->aData)!=iFrom ){ +- return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ return SQLITE_CORRUPT_PAGE(pPage); + } + put4byte(pPage->aData, iTo); + }else{ +@@ -63006,7 +66470,7 @@ + pPage->xParseCell(pPage, pCell, &info); + if( info.nLocal<info.nPayload ){ + if( pCell+info.nSize > pPage->aData+pPage->pBt->usableSize ){ +- return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ return SQLITE_CORRUPT_PAGE(pPage); + } + if( iFrom==get4byte(pCell+info.nSize-4) ){ + put4byte(pCell+info.nSize-4, iTo); +@@ -63024,7 +66488,7 @@ + if( i==nCell ){ + if( eType!=PTRMAP_BTREE || + get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){ +- return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ return SQLITE_CORRUPT_PAGE(pPage); + } + put4byte(&pPage->aData[pPage->hdrOffset+8], iTo); + } +@@ -63059,6 +66523,7 @@ + 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", +@@ -63544,7 +67009,6 @@ + if( pBtree ){ + sqlite3BtreeEnter(pBtree); + for(p=pBtree->pBt->pCursor; p; p=p->pNext){ +- int i; + if( writeOnly && (p->curFlags & BTCF_WriteFlag)==0 ){ + if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){ + rc = saveCursorPosition(p); +@@ -63558,10 +67022,7 @@ + p->eState = CURSOR_FAULT; + p->skipNext = errCode; + } +- for(i=0; i<=p->iPage; i++){ +- releasePage(p->apPage[i]); +- p->apPage[i] = 0; +- } ++ btreeReleaseAllCursorPages(p); + } + sqlite3BtreeLeave(pBtree); + } +@@ -63618,7 +67079,7 @@ + if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage); + testcase( pBt->nPage!=nPage ); + pBt->nPage = nPage; +- releasePage(pPage1); ++ releasePageOne(pPage1); + } + assert( countValidCursors(pBt, 1)==0 ); + pBt->inTransaction = TRANS_READ; +@@ -63850,7 +67311,7 @@ + ** of run-time by skipping the initialization of those elements. + */ + SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor *p){ +- memset(p, 0, offsetof(BtCursor, iPage)); ++ memset(p, 0, offsetof(BtCursor, BTCURSOR_FIRST_UNINIT)); + } + + /* +@@ -63860,10 +67321,8 @@ + SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){ + Btree *pBtree = pCur->pBtree; + if( pBtree ){ +- int i; + BtShared *pBt = pCur->pBt; + sqlite3BtreeEnter(pBtree); +- sqlite3BtreeClearCursor(pCur); + assert( pBt->pCursor!=0 ); + if( pBt->pCursor==pCur ){ + pBt->pCursor = pCur->pNext; +@@ -63877,12 +67336,10 @@ + pPrev = pPrev->pNext; + }while( ALWAYS(pPrev) ); + } +- for(i=0; i<=pCur->iPage; i++){ +- releasePage(pCur->apPage[i]); +- } ++ btreeReleaseAllCursorPages(pCur); + unlockBtreeIfUnused(pBt); + sqlite3_free(pCur->aOverflow); +- /* sqlite3_free(pCur); */ ++ sqlite3_free(pCur->pKey); + sqlite3BtreeLeave(pBtree); + } + return SQLITE_OK; +@@ -63897,12 +67354,19 @@ + ** Using this cache reduces the number of calls to btreeParseCell(). + */ + #ifndef NDEBUG ++ static int cellInfoEqual(CellInfo *a, CellInfo *b){ ++ if( a->nKey!=b->nKey ) return 0; ++ if( a->pPayload!=b->pPayload ) return 0; ++ if( a->nPayload!=b->nPayload ) return 0; ++ if( a->nLocal!=b->nLocal ) return 0; ++ if( a->nSize!=b->nSize ) return 0; ++ return 1; ++ } + static void assertCellInfo(BtCursor *pCur){ + CellInfo info; +- int iPage = pCur->iPage; + memset(&info, 0, sizeof(info)); +- btreeParseCell(pCur->apPage[iPage], pCur->ix, &info); +- assert( CORRUPT_DB || memcmp(&info, &pCur->info, sizeof(info))==0 ); ++ btreeParseCell(pCur->pPage, pCur->ix, &info); ++ assert( CORRUPT_DB || cellInfoEqual(&info, &pCur->info) ); + } + #else + #define assertCellInfo(x) +@@ -63909,9 +67373,8 @@ + #endif + static SQLITE_NOINLINE void getCellInfo(BtCursor *pCur){ + if( pCur->info.nSize==0 ){ +- int iPage = pCur->iPage; + pCur->curFlags |= BTCF_ValidNKey; +- btreeParseCell(pCur->apPage[iPage],pCur->ix,&pCur->info); ++ btreeParseCell(pCur->pPage,pCur->ix,&pCur->info); + }else{ + assertCellInfo(pCur); + } +@@ -63946,7 +67409,21 @@ + return pCur->info.nKey; + } + ++#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC + /* ++** Return the offset into the database file for the start of the ++** payload to which the cursor is pointing. ++*/ ++SQLITE_PRIVATE i64 sqlite3BtreeOffset(BtCursor *pCur){ ++ assert( cursorHoldsMutex(pCur) ); ++ assert( pCur->eState==CURSOR_VALID ); ++ getCellInfo(pCur); ++ return (i64)pCur->pBt->pageSize*((i64)pCur->pPage->pgno - 1) + ++ (i64)(pCur->info.pPayload - pCur->pPage->aData); ++} ++#endif /* SQLITE_ENABLE_OFFSET_SQL_FUNC */ ++ ++/* + ** Return the number of bytes of payload for the entry that pCur is + ** currently pointing to. For table btrees, this will be the amount + ** of data. For index btrees, this will be the size of the key. +@@ -64109,7 +67586,7 @@ + unsigned char *aPayload; + int rc = SQLITE_OK; + int iIdx = 0; +- MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */ ++ MemPage *pPage = pCur->pPage; /* Btree page of current entry */ + BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */ + #ifdef SQLITE_DIRECT_OVERFLOW_READ + unsigned char * const pBufStart = pBuf; /* Start of original out buffer */ +@@ -64132,7 +67609,7 @@ + ** &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize] + ** but is recast into its current form to avoid integer overflow problems + */ +- return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ return SQLITE_CORRUPT_PAGE(pPage); + } + + /* Check if data must be read/written to/from the btree page itself. */ +@@ -64165,7 +67642,9 @@ + */ + if( (pCur->curFlags & BTCF_ValidOvfl)==0 ){ + int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize; +- if( nOvfl>pCur->nOvflAlloc ){ ++ if( pCur->aOverflow==0 ++ || nOvfl*(int)sizeof(Pgno) > sqlite3MallocSize(pCur->aOverflow) ++ ){ + Pgno *aNew = (Pgno*)sqlite3Realloc( + pCur->aOverflow, nOvfl*2*sizeof(Pgno) + ); +@@ -64172,7 +67651,6 @@ + if( aNew==0 ){ + return SQLITE_NOMEM_BKPT; + }else{ +- pCur->nOvflAlloc = nOvfl*2; + pCur->aOverflow = aNew; + } + } +@@ -64217,9 +67695,6 @@ + /* Need to read this page properly. It contains some of the + ** range of data that is being read (eOp==0) or written (eOp!=0). + */ +-#ifdef SQLITE_DIRECT_OVERFLOW_READ +- sqlite3_file *fd; /* File from which to do direct overflow read */ +-#endif + int a = amt; + if( a + offset > ovflSize ){ + a = ovflSize - offset; +@@ -64230,7 +67705,7 @@ + ** + ** 1) this is a read operation, and + ** 2) data is required from the start of this overflow page, and +- ** 3) there is no open write-transaction, and ++ ** 3) there are no dirty pages in the page-cache + ** 4) the database is file-backed, and + ** 5) the page is not in the WAL file + ** 6) at least 4 bytes have already been read into the output buffer +@@ -64241,11 +67716,10 @@ + */ + if( eOp==0 /* (1) */ + && offset==0 /* (2) */ +- && pBt->inTransaction==TRANS_READ /* (3) */ +- && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (4) */ +- && 0==sqlite3PagerUseWal(pBt->pPager, nextPage) /* (5) */ ++ && sqlite3PagerDirectReadOk(pBt->pPager, nextPage) /* (3,4,5) */ + && &pBuf[-4]>=pBufStart /* (6) */ + ){ ++ sqlite3_file *fd = sqlite3PagerFile(pBt->pPager); + u8 aSave[4]; + u8 *aWrite = &pBuf[-4]; + assert( aWrite>=pBufStart ); /* due to (6) */ +@@ -64280,7 +67754,7 @@ + + if( rc==SQLITE_OK && amt>0 ){ + /* Overflow chain ends prematurely */ +- return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ return SQLITE_CORRUPT_PAGE(pPage); + } + return rc; + } +@@ -64305,8 +67779,8 @@ + SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState==CURSOR_VALID ); +- assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] ); +- assert( pCur->ix<pCur->apPage[pCur->iPage]->nCell ); ++ assert( pCur->iPage>=0 && pCur->pPage ); ++ assert( pCur->ix<pCur->pPage->nCell ); + return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0); + } + +@@ -64363,18 +67837,23 @@ + BtCursor *pCur, /* Cursor pointing to entry to read from */ + u32 *pAmt /* Write the number of available bytes here */ + ){ +- u32 amt; +- assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]); ++ int amt; ++ assert( pCur!=0 && pCur->iPage>=0 && pCur->pPage); + assert( pCur->eState==CURSOR_VALID ); + assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); + assert( cursorOwnsBtShared(pCur) ); +- assert( pCur->ix<pCur->apPage[pCur->iPage]->nCell ); ++ assert( pCur->ix<pCur->pPage->nCell ); + assert( pCur->info.nSize>0 ); +- assert( pCur->info.pPayload>pCur->apPage[pCur->iPage]->aData || CORRUPT_DB ); +- assert( pCur->info.pPayload<pCur->apPage[pCur->iPage]->aDataEnd ||CORRUPT_DB); +- amt = (int)(pCur->apPage[pCur->iPage]->aDataEnd - pCur->info.pPayload); +- if( pCur->info.nLocal<amt ) amt = pCur->info.nLocal; +- *pAmt = amt; ++ assert( pCur->info.pPayload>pCur->pPage->aData || CORRUPT_DB ); ++ assert( pCur->info.pPayload<pCur->pPage->aDataEnd ||CORRUPT_DB); ++ amt = pCur->info.nLocal; ++ if( amt>(int)(pCur->pPage->aDataEnd - pCur->info.pPayload) ){ ++ /* There is too little space on the page for the expected amount ++ ** of local content. Database must be corrupt. */ ++ assert( CORRUPT_DB ); ++ amt = MAX(0, (int)(pCur->pPage->aDataEnd - pCur->info.pPayload)); ++ } ++ *pAmt = (u32)amt; + return (void*)pCur->info.pPayload; + } + +@@ -64419,10 +67898,11 @@ + } + pCur->info.nSize = 0; + pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); +- pCur->aiIdx[pCur->iPage++] = pCur->ix; ++ pCur->aiIdx[pCur->iPage] = pCur->ix; ++ pCur->apPage[pCur->iPage] = pCur->pPage; + pCur->ix = 0; +- return getAndInitPage(pBt, newPgno, &pCur->apPage[pCur->iPage], +- pCur, pCur->curPagerFlags); ++ pCur->iPage++; ++ return getAndInitPage(pBt, newPgno, &pCur->pPage, pCur, pCur->curPagerFlags); + } + + #ifdef SQLITE_DEBUG +@@ -64456,20 +67936,23 @@ + ** the largest cell index. + */ + static void moveToParent(BtCursor *pCur){ ++ MemPage *pLeaf; + assert( cursorOwnsBtShared(pCur) ); + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->iPage>0 ); +- assert( pCur->apPage[pCur->iPage] ); ++ assert( pCur->pPage ); + assertParentIndex( + pCur->apPage[pCur->iPage-1], + pCur->aiIdx[pCur->iPage-1], +- pCur->apPage[pCur->iPage]->pgno ++ pCur->pPage->pgno + ); + testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell ); + pCur->info.nSize = 0; + pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); + pCur->ix = pCur->aiIdx[pCur->iPage-1]; +- releasePageNotNull(pCur->apPage[pCur->iPage--]); ++ pLeaf = pCur->pPage; ++ pCur->pPage = pCur->apPage[--pCur->iPage]; ++ releasePageNotNull(pLeaf); + } + + /* +@@ -64481,9 +67964,9 @@ + ** single child page. This can only happen with the table rooted at page 1. + ** + ** If the b-tree structure is empty, the cursor state is set to +-** CURSOR_INVALID. Otherwise, the cursor is set to point to the first +-** cell located on the root (or virtual root) page and the cursor state +-** is set to CURSOR_VALID. ++** CURSOR_INVALID and this routine returns SQLITE_EMPTY. Otherwise, ++** the cursor is set to point to the first cell located on the root ++** (or virtual root) page and the cursor state is set to CURSOR_VALID. + ** + ** If this function returns successfully, it may be assumed that the + ** page-header flags indicate that the [virtual] root-page is the expected +@@ -64501,37 +67984,40 @@ + assert( CURSOR_INVALID < CURSOR_REQUIRESEEK ); + assert( CURSOR_VALID < CURSOR_REQUIRESEEK ); + assert( CURSOR_FAULT > CURSOR_REQUIRESEEK ); +- if( pCur->eState>=CURSOR_REQUIRESEEK ){ +- if( pCur->eState==CURSOR_FAULT ){ +- assert( pCur->skipNext!=SQLITE_OK ); +- return pCur->skipNext; +- } +- sqlite3BtreeClearCursor(pCur); +- } ++ assert( pCur->eState < CURSOR_REQUIRESEEK || pCur->iPage<0 ); ++ assert( pCur->pgnoRoot>0 || pCur->iPage<0 ); + + if( pCur->iPage>=0 ){ + if( pCur->iPage ){ +- do{ +- assert( pCur->apPage[pCur->iPage]!=0 ); +- releasePageNotNull(pCur->apPage[pCur->iPage--]); +- }while( pCur->iPage); ++ releasePageNotNull(pCur->pPage); ++ while( --pCur->iPage ){ ++ releasePageNotNull(pCur->apPage[pCur->iPage]); ++ } ++ pCur->pPage = pCur->apPage[0]; + goto skip_init; + } + }else if( pCur->pgnoRoot==0 ){ + pCur->eState = CURSOR_INVALID; +- return SQLITE_OK; ++ return SQLITE_EMPTY; + }else{ + assert( pCur->iPage==(-1) ); +- rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0], ++ if( pCur->eState>=CURSOR_REQUIRESEEK ){ ++ if( pCur->eState==CURSOR_FAULT ){ ++ assert( pCur->skipNext!=SQLITE_OK ); ++ return pCur->skipNext; ++ } ++ sqlite3BtreeClearCursor(pCur); ++ } ++ rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->pPage, + 0, pCur->curPagerFlags); + if( rc!=SQLITE_OK ){ + pCur->eState = CURSOR_INVALID; +- return rc; ++ return rc; + } + pCur->iPage = 0; +- pCur->curIntKey = pCur->apPage[0]->intKey; ++ pCur->curIntKey = pCur->pPage->intKey; + } +- pRoot = pCur->apPage[0]; ++ pRoot = pCur->pPage; + assert( pRoot->pgno==pCur->pgnoRoot ); + + /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor +@@ -64546,7 +68032,7 @@ + ** (or the freelist). */ + assert( pRoot->intKey==1 || pRoot->intKey==0 ); + if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){ +- return SQLITE_CORRUPT_PGNO(pCur->apPage[pCur->iPage]->pgno); ++ return SQLITE_CORRUPT_PAGE(pCur->pPage); + } + + skip_init: +@@ -64554,7 +68040,7 @@ + pCur->info.nSize = 0; + pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl); + +- pRoot = pCur->apPage[0]; ++ pRoot = pCur->pPage; + if( pRoot->nCell>0 ){ + pCur->eState = CURSOR_VALID; + }else if( !pRoot->leaf ){ +@@ -64565,6 +68051,7 @@ + rc = moveToChild(pCur, subpage); + }else{ + pCur->eState = CURSOR_INVALID; ++ rc = SQLITE_EMPTY; + } + return rc; + } +@@ -64583,7 +68070,7 @@ + + assert( cursorOwnsBtShared(pCur) ); + assert( pCur->eState==CURSOR_VALID ); +- while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){ ++ while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){ + assert( pCur->ix<pPage->nCell ); + pgno = get4byte(findCell(pPage, pCur->ix)); + rc = moveToChild(pCur, pgno); +@@ -64608,7 +68095,7 @@ + + assert( cursorOwnsBtShared(pCur) ); + assert( pCur->eState==CURSOR_VALID ); +- while( !(pPage = pCur->apPage[pCur->iPage])->leaf ){ ++ while( !(pPage = pCur->pPage)->leaf ){ + pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); + pCur->ix = pPage->nCell; + rc = moveToChild(pCur, pgno); +@@ -64631,18 +68118,34 @@ + assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); + rc = moveToRoot(pCur); + if( rc==SQLITE_OK ){ +- if( pCur->eState==CURSOR_INVALID ){ +- assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 ); +- *pRes = 1; +- }else{ +- assert( pCur->apPage[pCur->iPage]->nCell>0 ); +- *pRes = 0; +- rc = moveToLeftmost(pCur); +- } ++ assert( pCur->pPage->nCell>0 ); ++ *pRes = 0; ++ rc = moveToLeftmost(pCur); ++ }else if( rc==SQLITE_EMPTY ){ ++ assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 ); ++ *pRes = 1; ++ rc = SQLITE_OK; + } + return rc; + } + ++/* ++** This function is a no-op if cursor pCur does not point to a valid row. ++** Otherwise, if pCur is valid, configure it so that the next call to ++** sqlite3BtreeNext() is a no-op. ++*/ ++#ifndef SQLITE_OMIT_WINDOWFUNC ++SQLITE_PRIVATE void sqlite3BtreeSkipNext(BtCursor *pCur){ ++ /* We believe that the cursor must always be in the valid state when ++ ** this routine is called, but the proof is difficult, so we add an ++ ** ALWaYS() test just in case we are wrong. */ ++ if( ALWAYS(pCur->eState==CURSOR_VALID) ){ ++ pCur->eState = CURSOR_SKIPNEXT; ++ pCur->skipNext = 1; ++ } ++} ++#endif /* SQLITE_OMIT_WINDOWFUNC */ ++ + /* Move the cursor to the last entry in the table. Return SQLITE_OK + ** on success. Set *pRes to 0 if the cursor actually points to something + ** or set *pRes to 1 if the table is empty. +@@ -64662,8 +68165,8 @@ + for(ii=0; ii<pCur->iPage; ii++){ + assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell ); + } +- assert( pCur->ix==pCur->apPage[pCur->iPage]->nCell-1 ); +- assert( pCur->apPage[pCur->iPage]->leaf ); ++ assert( pCur->ix==pCur->pPage->nCell-1 ); ++ assert( pCur->pPage->leaf ); + #endif + return SQLITE_OK; + } +@@ -64670,20 +68173,18 @@ + + rc = moveToRoot(pCur); + if( rc==SQLITE_OK ){ +- if( CURSOR_INVALID==pCur->eState ){ +- assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 ); +- *pRes = 1; ++ assert( pCur->eState==CURSOR_VALID ); ++ *pRes = 0; ++ rc = moveToRightmost(pCur); ++ if( rc==SQLITE_OK ){ ++ pCur->curFlags |= BTCF_AtLast; + }else{ +- assert( pCur->eState==CURSOR_VALID ); +- *pRes = 0; +- rc = moveToRightmost(pCur); +- if( rc==SQLITE_OK ){ +- pCur->curFlags |= BTCF_AtLast; +- }else{ +- pCur->curFlags &= ~BTCF_AtLast; +- } +- ++ pCur->curFlags &= ~BTCF_AtLast; + } ++ }else if( rc==SQLITE_EMPTY ){ ++ assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 ); ++ *pRes = 1; ++ rc = SQLITE_OK; + } + return rc; + } +@@ -64782,22 +68283,23 @@ + + rc = moveToRoot(pCur); + if( rc ){ ++ if( rc==SQLITE_EMPTY ){ ++ assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 ); ++ *pRes = -1; ++ return SQLITE_OK; ++ } + return rc; + } +- assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage] ); +- assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->isInit ); +- assert( pCur->eState==CURSOR_INVALID || pCur->apPage[pCur->iPage]->nCell>0 ); +- if( pCur->eState==CURSOR_INVALID ){ +- *pRes = -1; +- assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 ); +- return SQLITE_OK; +- } +- assert( pCur->apPage[0]->intKey==pCur->curIntKey ); ++ assert( pCur->pPage ); ++ assert( pCur->pPage->isInit ); ++ assert( pCur->eState==CURSOR_VALID ); ++ assert( pCur->pPage->nCell > 0 ); ++ assert( pCur->iPage==0 || pCur->apPage[0]->intKey==pCur->curIntKey ); + assert( pCur->curIntKey || pIdxKey ); + for(;;){ + int lwr, upr, idx, c; + Pgno chldPg; +- MemPage *pPage = pCur->apPage[pCur->iPage]; ++ MemPage *pPage = pCur->pPage; + u8 *pCell; /* Pointer to current cell in pPage */ + + /* pPage->nCell must be greater than zero. If this is the root-page +@@ -64820,7 +68322,7 @@ + if( pPage->intKeyLeaf ){ + while( 0x80 <= *(pCell++) ){ + if( pCell>=pPage->aDataEnd ){ +- return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ return SQLITE_CORRUPT_PAGE(pPage); + } + } + } +@@ -64894,7 +68396,7 @@ + testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */ + testcase( nCell==2 ); /* Minimum legal index key size */ + if( nCell<2 ){ +- rc = SQLITE_CORRUPT_PGNO(pPage->pgno); ++ rc = SQLITE_CORRUPT_PAGE(pPage); + goto moveto_finish; + } + pCellKey = sqlite3Malloc( nCell+18 ); +@@ -64925,7 +68427,7 @@ + *pRes = 0; + rc = SQLITE_OK; + pCur->ix = (u16)idx; +- if( pIdxKey->errCode ) rc = SQLITE_CORRUPT; ++ if( pIdxKey->errCode ) rc = SQLITE_CORRUPT_BKPT; + goto moveto_finish; + } + if( lwr>upr ) break; +@@ -64936,7 +68438,7 @@ + assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) ); + assert( pPage->isInit ); + if( pPage->leaf ){ +- assert( pCur->ix<pCur->apPage[pCur->iPage]->nCell ); ++ assert( pCur->ix<pCur->pPage->nCell ); + pCur->ix = (u16)idx; + *pRes = c; + rc = SQLITE_OK; +@@ -64990,9 +68492,10 @@ + ** opcode, and it that case the cursor will always be valid and + ** will always point to a leaf node. */ + if( NEVER(pCur->eState!=CURSOR_VALID) ) return -1; +- if( NEVER(pCur->apPage[pCur->iPage]->leaf==0) ) return -1; ++ if( NEVER(pCur->pPage->leaf==0) ) return -1; + +- for(n=1, i=0; i<=pCur->iPage; i++){ ++ n = pCur->pPage->nCell; ++ for(i=0; i<pCur->iPage; i++){ + n *= pCur->apPage[i]->nCell; + } + return n; +@@ -65045,9 +68548,18 @@ + } + } + +- pPage = pCur->apPage[pCur->iPage]; ++ pPage = pCur->pPage; + idx = ++pCur->ix; +- assert( pPage->isInit ); ++ if( !pPage->isInit ){ ++ /* The only known way for this to happen is for there to be a ++ ** recursive SQL function that does a DELETE operation as part of a ++ ** SELECT which deletes content out from under an active cursor ++ ** in a corrupt database file where the table being DELETE-ed from ++ ** has pages in common with the table being queried. See TH3 ++ ** module cov1/btree78.test testcase 220 (2018-06-08) for an ++ ** example. */ ++ return SQLITE_CORRUPT_BKPT; ++ } + + /* If the database file is corrupt, it is possible for the value of idx + ** to be invalid here. This can only occur if a second cursor modifies +@@ -65068,7 +68580,7 @@ + return SQLITE_DONE; + } + moveToParent(pCur); +- pPage = pCur->apPage[pCur->iPage]; ++ pPage = pCur->pPage; + }while( pCur->ix>=pPage->nCell ); + if( pPage->intKey ){ + return sqlite3BtreeNext(pCur, 0); +@@ -65091,7 +68603,7 @@ + pCur->info.nSize = 0; + pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); + if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur); +- pPage = pCur->apPage[pCur->iPage]; ++ pPage = pCur->pPage; + if( (++pCur->ix)>=pPage->nCell ){ + pCur->ix--; + return btreeNext(pCur); +@@ -65150,7 +68662,7 @@ + } + } + +- pPage = pCur->apPage[pCur->iPage]; ++ pPage = pCur->pPage; + assert( pPage->isInit ); + if( !pPage->leaf ){ + int idx = pCur->ix; +@@ -65169,7 +68681,7 @@ + assert( (pCur->curFlags & (BTCF_ValidOvfl))==0 ); + + pCur->ix--; +- pPage = pCur->apPage[pCur->iPage]; ++ pPage = pCur->pPage; + if( pPage->intKey && !pPage->leaf ){ + rc = sqlite3BtreePrevious(pCur, 0); + }else{ +@@ -65187,7 +68699,7 @@ + pCur->info.nSize = 0; + if( pCur->eState!=CURSOR_VALID + || pCur->ix==0 +- || pCur->apPage[pCur->iPage]->leaf==0 ++ || pCur->pPage->leaf==0 + ){ + return btreePrevious(pCur); + } +@@ -65674,9 +69186,8 @@ + } + + /* +-** Free any overflow pages associated with the given Cell. Write the +-** local Cell size (the number of bytes on the original page, omitting +-** overflow) into *pnSize. ++** Free any overflow pages associated with the given Cell. Store ++** size information about the cell in pInfo. + */ + static int clearCell( + MemPage *pPage, /* The page that contains the Cell */ +@@ -65683,7 +69194,7 @@ + unsigned char *pCell, /* First byte of the Cell */ + CellInfo *pInfo /* Size information about the cell */ + ){ +- BtShared *pBt = pPage->pBt; ++ BtShared *pBt; + Pgno ovflPgno; + int rc; + int nOvfl; +@@ -65694,11 +69205,14 @@ + if( pInfo->nLocal==pInfo->nPayload ){ + return SQLITE_OK; /* No overflow pages. Return without doing anything */ + } +- if( pCell+pInfo->nSize-1 > pPage->aData+pPage->maskPage ){ ++ testcase( pCell + pInfo->nSize == pPage->aDataEnd ); ++ testcase( pCell + (pInfo->nSize-1) == pPage->aDataEnd ); ++ if( pCell + pInfo->nSize > pPage->aDataEnd ){ + /* Cell extends past end of page */ +- return SQLITE_CORRUPT_PGNO(pPage->pgno); ++ return SQLITE_CORRUPT_PAGE(pPage); + } + ovflPgno = get4byte(pCell + pInfo->nSize - 4); ++ pBt = pPage->pBt; + assert( pBt->usableSize > 4 ); + ovflPageSize = pBt->usableSize - 4; + nOvfl = (pInfo->nPayload - pInfo->nLocal + ovflPageSize - 1)/ovflPageSize; +@@ -65766,14 +69280,13 @@ + ){ + int nPayload; + const u8 *pSrc; +- int nSrc, n, rc; ++ int nSrc, n, rc, mn; + int spaceLeft; +- MemPage *pOvfl = 0; +- MemPage *pToRelease = 0; ++ MemPage *pToRelease; + unsigned char *pPrior; + unsigned char *pPayload; +- BtShared *pBt = pPage->pBt; +- Pgno pgnoOvfl = 0; ++ BtShared *pBt; ++ Pgno pgnoOvfl; + int nHeader; + + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); +@@ -65780,7 +69293,7 @@ + + /* pPage is not necessarily writeable since pCell might be auxiliary + ** buffer space that is separate from the pPage buffer area */ +- assert( pCell<pPage->aData || pCell>=&pPage->aData[pBt->pageSize] ++ assert( pCell<pPage->aData || pCell>=&pPage->aData[pPage->pBt->pageSize] + || sqlite3PagerIswriteable(pPage->pDbPage) ); + + /* Fill in the header. */ +@@ -65800,26 +69313,37 @@ + } + + /* Fill in the payload */ ++ pPayload = &pCell[nHeader]; + if( nPayload<=pPage->maxLocal ){ ++ /* This is the common case where everything fits on the btree page ++ ** and no overflow pages are required. */ + n = nHeader + nPayload; + testcase( n==3 ); + testcase( n==4 ); + if( n<4 ) n = 4; + *pnSize = n; +- spaceLeft = nPayload; +- pPrior = pCell; +- }else{ +- int mn = pPage->minLocal; +- n = mn + (nPayload - mn) % (pPage->pBt->usableSize - 4); +- testcase( n==pPage->maxLocal ); +- testcase( n==pPage->maxLocal+1 ); +- if( n > pPage->maxLocal ) n = mn; +- spaceLeft = n; +- *pnSize = n + nHeader + 4; +- pPrior = &pCell[nHeader+n]; ++ assert( nSrc<=nPayload ); ++ testcase( nSrc<nPayload ); ++ memcpy(pPayload, pSrc, nSrc); ++ memset(pPayload+nSrc, 0, nPayload-nSrc); ++ return SQLITE_OK; + } +- pPayload = &pCell[nHeader]; + ++ /* If we reach this point, it means that some of the content will need ++ ** to spill onto overflow pages. ++ */ ++ mn = pPage->minLocal; ++ n = mn + (nPayload - mn) % (pPage->pBt->usableSize - 4); ++ testcase( n==pPage->maxLocal ); ++ testcase( n==pPage->maxLocal+1 ); ++ if( n > pPage->maxLocal ) n = mn; ++ spaceLeft = n; ++ *pnSize = n + nHeader + 4; ++ pPrior = &pCell[nHeader+n]; ++ pToRelease = 0; ++ pgnoOvfl = 0; ++ pBt = pPage->pBt; ++ + /* At this point variables should be set as follows: + ** + ** nPayload Total payload size in bytes +@@ -65844,8 +69368,35 @@ + #endif + + /* Write the payload into the local Cell and any extra into overflow pages */ +- while( nPayload>0 ){ ++ while( 1 ){ ++ n = nPayload; ++ if( n>spaceLeft ) n = spaceLeft; ++ ++ /* If pToRelease is not zero than pPayload points into the data area ++ ** of pToRelease. Make sure pToRelease is still writeable. */ ++ assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) ); ++ ++ /* If pPayload is part of the data area of pPage, then make sure pPage ++ ** is still writeable */ ++ assert( pPayload<pPage->aData || pPayload>=&pPage->aData[pBt->pageSize] ++ || sqlite3PagerIswriteable(pPage->pDbPage) ); ++ ++ if( nSrc>=n ){ ++ memcpy(pPayload, pSrc, n); ++ }else if( nSrc>0 ){ ++ n = nSrc; ++ memcpy(pPayload, pSrc, n); ++ }else{ ++ memset(pPayload, 0, n); ++ } ++ nPayload -= n; ++ if( nPayload<=0 ) break; ++ pPayload += n; ++ pSrc += n; ++ nSrc -= n; ++ spaceLeft -= n; + if( spaceLeft==0 ){ ++ MemPage *pOvfl = 0; + #ifndef SQLITE_OMIT_AUTOVACUUM + Pgno pgnoPtrmap = pgnoOvfl; /* Overflow page pointer-map entry page */ + if( pBt->autoVacuum ){ +@@ -65898,30 +69449,6 @@ + pPayload = &pOvfl->aData[4]; + spaceLeft = pBt->usableSize - 4; + } +- n = nPayload; +- if( n>spaceLeft ) n = spaceLeft; +- +- /* If pToRelease is not zero than pPayload points into the data area +- ** of pToRelease. Make sure pToRelease is still writeable. */ +- assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) ); +- +- /* If pPayload is part of the data area of pPage, then make sure pPage +- ** is still writeable */ +- assert( pPayload<pPage->aData || pPayload>=&pPage->aData[pBt->pageSize] +- || sqlite3PagerIswriteable(pPage->pDbPage) ); +- +- if( nSrc>0 ){ +- if( n>nSrc ) n = nSrc; +- assert( pSrc ); +- memcpy(pPayload, pSrc, n); +- }else{ +- memset(pPayload, 0, n); +- } +- nPayload -= n; +- pPayload += n; +- pSrc += n; +- nSrc -= n; +- spaceLeft -= n; + } + releasePage(pToRelease); + return SQLITE_OK; +@@ -65953,7 +69480,7 @@ + hdr = pPage->hdrOffset; + testcase( pc==get2byte(&data[hdr+5]) ); + testcase( pc+sz==pPage->pBt->usableSize ); +- if( pc < (u32)get2byte(&data[hdr+5]) || pc+sz > pPage->pBt->usableSize ){ ++ if( pc+sz > pPage->pBt->usableSize ){ + *pRC = SQLITE_CORRUPT_BKPT; + return; + } +@@ -66820,10 +70347,8 @@ + + nMaxCells*sizeof(u16) /* b.szCell */ + + pBt->pageSize; /* aSpace1 */ + +- /* EVIDENCE-OF: R-28375-38319 SQLite will never request a scratch buffer +- ** that is more than 6 times the database page size. */ + assert( szScratch<=6*(int)pBt->pageSize ); +- b.apCell = sqlite3ScratchMalloc( szScratch ); ++ b.apCell = sqlite3StackAllocRaw(0, szScratch ); + if( b.apCell==0 ){ + rc = SQLITE_NOMEM_BKPT; + goto balance_cleanup; +@@ -66868,7 +70393,7 @@ + } + + /* Load b.apCell[] with pointers to all cells in pOld. If pOld +- ** constains overflow cells, include them in the b.apCell[] array ++ ** contains overflow cells, include them in the b.apCell[] array + ** in the correct spot. + ** + ** Note that when there are multiple overflow cells, it is always the +@@ -67401,7 +70926,7 @@ + ** Cleanup before returning. + */ + balance_cleanup: +- sqlite3ScratchFree(b.apCell); ++ sqlite3StackFree(0, b.apCell); + for(i=0; i<nOld; i++){ + releasePage(apOld[i]); + } +@@ -67500,7 +71025,7 @@ + + do { + int iPage = pCur->iPage; +- MemPage *pPage = pCur->apPage[iPage]; ++ MemPage *pPage = pCur->pPage; + + if( iPage==0 ){ + if( pPage->nOverflow ){ +@@ -67516,7 +71041,9 @@ + pCur->iPage = 1; + pCur->ix = 0; + pCur->aiIdx[0] = 0; +- assert( pCur->apPage[1]->nOverflow ); ++ pCur->apPage[0] = pPage; ++ pCur->pPage = pCur->apPage[1]; ++ assert( pCur->pPage->nOverflow ); + } + }else{ + break; +@@ -67596,6 +71123,7 @@ + releasePage(pPage); + pCur->iPage--; + assert( pCur->iPage>=0 ); ++ pCur->pPage = pCur->apPage[pCur->iPage]; + } + }while( rc==SQLITE_OK ); + +@@ -67605,8 +71133,96 @@ + return rc; + } + ++/* Overwrite content from pX into pDest. Only do the write if the ++** content is different from what is already there. ++*/ ++static int btreeOverwriteContent( ++ MemPage *pPage, /* MemPage on which writing will occur */ ++ u8 *pDest, /* Pointer to the place to start writing */ ++ const BtreePayload *pX, /* Source of data to write */ ++ int iOffset, /* Offset of first byte to write */ ++ int iAmt /* Number of bytes to be written */ ++){ ++ int nData = pX->nData - iOffset; ++ if( nData<=0 ){ ++ /* Overwritting with zeros */ ++ int i; ++ for(i=0; i<iAmt && pDest[i]==0; i++){} ++ if( i<iAmt ){ ++ int rc = sqlite3PagerWrite(pPage->pDbPage); ++ if( rc ) return rc; ++ memset(pDest + i, 0, iAmt - i); ++ } ++ }else{ ++ if( nData<iAmt ){ ++ /* Mixed read data and zeros at the end. Make a recursive call ++ ** to write the zeros then fall through to write the real data */ ++ int rc = btreeOverwriteContent(pPage, pDest+nData, pX, iOffset+nData, ++ iAmt-nData); ++ if( rc ) return rc; ++ iAmt = nData; ++ } ++ if( memcmp(pDest, ((u8*)pX->pData) + iOffset, iAmt)!=0 ){ ++ int rc = sqlite3PagerWrite(pPage->pDbPage); ++ if( rc ) return rc; ++ memcpy(pDest, ((u8*)pX->pData) + iOffset, iAmt); ++ } ++ } ++ return SQLITE_OK; ++} + + /* ++** Overwrite the cell that cursor pCur is pointing to with fresh content ++** contained in pX. ++*/ ++static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){ ++ int iOffset; /* Next byte of pX->pData to write */ ++ int nTotal = pX->nData + pX->nZero; /* Total bytes of to write */ ++ int rc; /* Return code */ ++ MemPage *pPage = pCur->pPage; /* Page being written */ ++ BtShared *pBt; /* Btree */ ++ Pgno ovflPgno; /* Next overflow page to write */ ++ u32 ovflPageSize; /* Size to write on overflow page */ ++ ++ if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd ){ ++ return SQLITE_CORRUPT_BKPT; ++ } ++ /* Overwrite the local portion first */ ++ rc = btreeOverwriteContent(pPage, pCur->info.pPayload, pX, ++ 0, pCur->info.nLocal); ++ if( rc ) return rc; ++ if( pCur->info.nLocal==nTotal ) return SQLITE_OK; ++ ++ /* Now overwrite the overflow pages */ ++ iOffset = pCur->info.nLocal; ++ assert( nTotal>=0 ); ++ assert( iOffset>=0 ); ++ ovflPgno = get4byte(pCur->info.pPayload + iOffset); ++ pBt = pPage->pBt; ++ ovflPageSize = pBt->usableSize - 4; ++ do{ ++ rc = btreeGetPage(pBt, ovflPgno, &pPage, 0); ++ if( rc ) return rc; ++ if( sqlite3PagerPageRefcount(pPage->pDbPage)!=1 ){ ++ rc = SQLITE_CORRUPT_BKPT; ++ }else{ ++ if( iOffset+ovflPageSize<(u32)nTotal ){ ++ ovflPgno = get4byte(pPage->aData); ++ }else{ ++ ovflPageSize = nTotal - iOffset; ++ } ++ rc = btreeOverwriteContent(pPage, pPage->aData+4, pX, ++ iOffset, ovflPageSize); ++ } ++ sqlite3PagerUnref(pPage->pDbPage); ++ if( rc ) return rc; ++ iOffset += ovflPageSize; ++ }while( iOffset<nTotal ); ++ return SQLITE_OK; ++} ++ ++ ++/* + ** Insert a new record into the BTree. The content of the new record + ** is described by the pX object. The pCur cursor is used only to + ** define what table the record should be inserted into, and is left +@@ -67695,39 +71311,90 @@ + invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0); + + /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing +- ** to a row with the same key as the new entry being inserted. */ +- assert( (flags & BTREE_SAVEPOSITION)==0 || +- ((pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey) ); ++ ** to a row with the same key as the new entry being inserted. ++ */ ++#ifdef SQLITE_DEBUG ++ if( flags & BTREE_SAVEPOSITION ){ ++ assert( pCur->curFlags & BTCF_ValidNKey ); ++ assert( pX->nKey==pCur->info.nKey ); ++ assert( pCur->info.nSize!=0 ); ++ assert( loc==0 ); ++ } ++#endif + +- /* If the cursor is currently on the last row and we are appending a +- ** new row onto the end, set the "loc" to avoid an unnecessary +- ** btreeMoveto() call */ ++ /* On the other hand, BTREE_SAVEPOSITION==0 does not imply ++ ** that the cursor is not pointing to a row to be overwritten. ++ ** So do a complete check. ++ */ + if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey ){ +- loc = 0; ++ /* The cursor is pointing to the entry that is to be ++ ** overwritten */ ++ assert( pX->nData>=0 && pX->nZero>=0 ); ++ if( pCur->info.nSize!=0 ++ && pCur->info.nPayload==(u32)pX->nData+pX->nZero ++ ){ ++ /* New entry is the same size as the old. Do an overwrite */ ++ return btreeOverwriteCell(pCur, pX); ++ } ++ assert( loc==0 ); + }else if( loc==0 ){ ++ /* The cursor is *not* pointing to the cell to be overwritten, nor ++ ** to an adjacent cell. Move the cursor so that it is pointing either ++ ** to the cell to be overwritten or an adjacent cell. ++ */ + rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, flags!=0, &loc); + if( rc ) return rc; + } +- }else if( loc==0 && (flags & BTREE_SAVEPOSITION)==0 ){ +- if( pX->nMem ){ +- UnpackedRecord r; +- r.pKeyInfo = pCur->pKeyInfo; +- r.aMem = pX->aMem; +- r.nField = pX->nMem; +- r.default_rc = 0; +- r.errCode = 0; +- r.r1 = 0; +- r.r2 = 0; +- r.eqSeen = 0; +- rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, flags!=0, &loc); +- }else{ +- rc = btreeMoveto(pCur, pX->pKey, pX->nKey, flags!=0, &loc); ++ }else{ ++ /* This is an index or a WITHOUT ROWID table */ ++ ++ /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing ++ ** to a row with the same key as the new entry being inserted. ++ */ ++ assert( (flags & BTREE_SAVEPOSITION)==0 || loc==0 ); ++ ++ /* If the cursor is not already pointing either to the cell to be ++ ** overwritten, or if a new cell is being inserted, if the cursor is ++ ** not pointing to an immediately adjacent cell, then move the cursor ++ ** so that it does. ++ */ ++ if( loc==0 && (flags & BTREE_SAVEPOSITION)==0 ){ ++ if( pX->nMem ){ ++ UnpackedRecord r; ++ r.pKeyInfo = pCur->pKeyInfo; ++ r.aMem = pX->aMem; ++ r.nField = pX->nMem; ++ r.default_rc = 0; ++ r.errCode = 0; ++ r.r1 = 0; ++ r.r2 = 0; ++ r.eqSeen = 0; ++ rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, flags!=0, &loc); ++ }else{ ++ rc = btreeMoveto(pCur, pX->pKey, pX->nKey, flags!=0, &loc); ++ } ++ if( rc ) return rc; + } +- if( rc ) return rc; ++ ++ /* If the cursor is currently pointing to an entry to be overwritten ++ ** and the new content is the same as as the old, then use the ++ ** overwrite optimization. ++ */ ++ if( loc==0 ){ ++ getCellInfo(pCur); ++ if( pCur->info.nKey==pX->nKey ){ ++ BtreePayload x2; ++ x2.pData = pX->pKey; ++ x2.nData = pX->nKey; ++ x2.nZero = 0; ++ return btreeOverwriteCell(pCur, &x2); ++ } ++ } ++ + } + assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) ); + +- pPage = pCur->apPage[pCur->iPage]; ++ pPage = pCur->pPage; + assert( pPage->intKey || pX->nKey>=0 ); + assert( pPage->leaf || !pPage->intKey ); + +@@ -67814,10 +71481,10 @@ + ** fails. Internal data structure corruption will result otherwise. + ** Also, set the cursor state to invalid. This stops saveCursorPosition() + ** from trying to save the current position of the cursor. */ +- pCur->apPage[pCur->iPage]->nOverflow = 0; ++ pCur->pPage->nOverflow = 0; + pCur->eState = CURSOR_INVALID; + if( (flags & BTREE_SAVEPOSITION) && rc==SQLITE_OK ){ +- rc = moveToRoot(pCur); ++ btreeReleaseAllCursorPages(pCur); + if( pCur->pKeyInfo ){ + assert( pCur->pKey==0 ); + pCur->pKey = sqlite3Malloc( pX->nKey ); +@@ -67831,7 +71498,7 @@ + pCur->nKey = pX->nKey; + } + } +- assert( pCur->apPage[pCur->iPage]->nOverflow==0 ); ++ assert( pCur->iPage<0 || pCur->pPage->nOverflow==0 ); + + end_insert: + return rc; +@@ -67872,13 +71539,13 @@ + assert( pCur->curFlags & BTCF_WriteFlag ); + assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); + assert( !hasReadConflicts(p, pCur->pgnoRoot) ); +- assert( pCur->ix<pCur->apPage[pCur->iPage]->nCell ); ++ assert( pCur->ix<pCur->pPage->nCell ); + assert( pCur->eState==CURSOR_VALID ); + assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 ); + + iCellDepth = pCur->iPage; + iCellIdx = pCur->ix; +- pPage = pCur->apPage[iCellDepth]; ++ pPage = pCur->pPage; + pCell = findCell(pPage, iCellIdx); + + /* If the bPreserve flag is set to true, then the cursor position must +@@ -67944,11 +71611,16 @@ + ** node. The cell from the leaf node needs to be moved to the internal + ** node to replace the deleted cell. */ + if( !pPage->leaf ){ +- MemPage *pLeaf = pCur->apPage[pCur->iPage]; ++ MemPage *pLeaf = pCur->pPage; + int nCell; +- Pgno n = pCur->apPage[iCellDepth+1]->pgno; ++ Pgno n; + unsigned char *pTmp; + ++ if( iCellDepth<pCur->iPage-1 ){ ++ n = pCur->apPage[iCellDepth+1]->pgno; ++ }else{ ++ n = pCur->pPage->pgno; ++ } + pCell = findCell(pLeaf, pLeaf->nCell-1); + if( pCell<&pLeaf->aData[4] ) return SQLITE_CORRUPT_BKPT; + nCell = pLeaf->xCellSize(pLeaf, pCell); +@@ -67980,9 +71652,12 @@ + ** well. */ + rc = balance(pCur); + if( rc==SQLITE_OK && pCur->iPage>iCellDepth ){ ++ releasePageNotNull(pCur->pPage); ++ pCur->iPage--; + while( pCur->iPage>iCellDepth ){ + releasePage(pCur->apPage[pCur->iPage--]); + } ++ pCur->pPage = pCur->apPage[pCur->iPage]; + rc = balance(pCur); + } + +@@ -67989,7 +71664,7 @@ + if( rc==SQLITE_OK ){ + if( bSkipnext ){ + assert( bPreserve && (pCur->iPage==iCellDepth || CORRUPT_DB) ); +- assert( pPage==pCur->apPage[pCur->iPage] || CORRUPT_DB ); ++ assert( pPage==pCur->pPage || CORRUPT_DB ); + assert( (pPage->nCell>0 || CORRUPT_DB) && iCellIdx<=pPage->nCell ); + pCur->eState = CURSOR_SKIPNEXT; + if( iCellIdx>=pPage->nCell ){ +@@ -68001,8 +71676,10 @@ + }else{ + rc = moveToRoot(pCur); + if( bPreserve ){ ++ btreeReleaseAllCursorPages(pCur); + pCur->eState = CURSOR_REQUIRESEEK; + } ++ if( rc==SQLITE_EMPTY ) rc = SQLITE_OK; + } + } + return rc; +@@ -68467,11 +72144,11 @@ + i64 nEntry = 0; /* Value to return in *pnEntry */ + int rc; /* Return code */ + +- if( pCur->pgnoRoot==0 ){ ++ rc = moveToRoot(pCur); ++ if( rc==SQLITE_EMPTY ){ + *pnEntry = 0; + return SQLITE_OK; + } +- rc = moveToRoot(pCur); + + /* Unless an error occurs, the following loop runs one iteration for each + ** page in the B-Tree structure (not including overflow pages). +@@ -68484,7 +72161,7 @@ + ** this page contains countable entries. Increment the entry counter + ** accordingly. + */ +- pPage = pCur->apPage[pCur->iPage]; ++ pPage = pCur->pPage; + if( pPage->leaf || !pPage->intKey ){ + nEntry += pPage->nCell; + } +@@ -68507,10 +72184,10 @@ + return moveToRoot(pCur); + } + moveToParent(pCur); +- }while ( pCur->ix>=pCur->apPage[pCur->iPage]->nCell ); ++ }while ( pCur->ix>=pCur->pPage->nCell ); + + pCur->ix++; +- pPage = pCur->apPage[pCur->iPage]; ++ pPage = pCur->pPage; + } + + /* Descend to the child node of the cell that the cursor currently +@@ -68552,14 +72229,14 @@ + pCheck->nErr++; + va_start(ap, zFormat); + if( pCheck->errMsg.nChar ){ +- sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1); ++ sqlite3_str_append(&pCheck->errMsg, "\n", 1); + } + if( pCheck->zPfx ){ +- sqlite3XPrintf(&pCheck->errMsg, pCheck->zPfx, pCheck->v1, pCheck->v2); ++ sqlite3_str_appendf(&pCheck->errMsg, pCheck->zPfx, pCheck->v1, pCheck->v2); + } +- sqlite3VXPrintf(&pCheck->errMsg, zFormat, ap); ++ sqlite3_str_vappendf(&pCheck->errMsg, zFormat, ap); + va_end(ap); +- if( pCheck->errMsg.accError==STRACCUM_NOMEM ){ ++ if( pCheck->errMsg.accError==SQLITE_NOMEM ){ + pCheck->mallocFailed = 1; + } + } +@@ -68594,8 +72271,7 @@ + ** Also check that the page number is in bounds. + */ + static int checkRef(IntegrityCk *pCheck, Pgno iPage){ +- if( iPage==0 ) return 1; +- if( iPage>pCheck->nPage ){ ++ if( iPage>pCheck->nPage || iPage==0 ){ + checkAppendMsg(pCheck, "invalid page number %d", iPage); + return 1; + } +@@ -68650,17 +72326,12 @@ + ){ + int i; + int expected = N; +- int iFirst = iPage; +- while( N-- > 0 && pCheck->mxErr ){ ++ int nErrAtStart = pCheck->nErr; ++ while( iPage!=0 && pCheck->mxErr ){ + DbPage *pOvflPage; + unsigned char *pOvflData; +- if( iPage<1 ){ +- checkAppendMsg(pCheck, +- "%d of %d pages missing from overflow list starting at %d", +- N+1, expected, iFirst); +- break; +- } + if( checkRef(pCheck, iPage) ) break; ++ N--; + if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage, 0) ){ + checkAppendMsg(pCheck, "failed to get page %d", iPage); + break; +@@ -68704,11 +72375,13 @@ + #endif + iPage = get4byte(pOvflData); + sqlite3PagerUnref(pOvflPage); +- +- if( isFreeList && N<(iPage!=0) ){ +- checkAppendMsg(pCheck, "free-page count in header is too small"); +- } + } ++ 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 */ + +@@ -69101,6 +72774,24 @@ + + /* Check all the tables. + */ ++#ifndef SQLITE_OMIT_AUTOVACUUM ++ if( pBt->autoVacuum ){ ++ int mx = 0; ++ int 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" ++ ); ++ } ++#endif + testcase( pBt->db->flags & SQLITE_CellSizeCk ); + pBt->db->flags &= ~SQLITE_CellSizeCk; + for(i=0; (int)i<nRoot && sCheck.mxErr; i++){ +@@ -69143,11 +72834,11 @@ + sqlite3PageFree(sCheck.heap); + sqlite3_free(sCheck.aPgRef); + if( sCheck.mallocFailed ){ +- sqlite3StrAccumReset(&sCheck.errMsg); ++ sqlite3_str_reset(&sCheck.errMsg); + sCheck.nErr++; + } + *pnErr = sCheck.nErr; +- if( sCheck.nErr==0 ) sqlite3StrAccumReset(&sCheck.errMsg); ++ if( sCheck.nErr==0 ) sqlite3_str_reset(&sCheck.errMsg); + /* Make sure this analysis did not leave any unref() pages. */ + assert( nRef==sqlite3PagerRefcount(pBt->pPager) ); + sqlite3BtreeLeave(p); +@@ -69351,7 +73042,7 @@ + && pCsr->pBt->inTransaction==TRANS_WRITE ); + assert( hasSharedCacheTableLock(pCsr->pBtree, pCsr->pgnoRoot, 0, 2) ); + assert( !hasReadConflicts(pCsr->pBtree, pCsr->pgnoRoot) ); +- assert( pCsr->apPage[pCsr->iPage]->intKey ); ++ assert( pCsr->pPage->intKey ); + + return accessPayload(pCsr, offset, amt, (unsigned char *)z, 1); + } +@@ -69382,11 +73073,11 @@ + pBt->btsFlags &= ~BTS_NO_WAL; + if( iVersion==1 ) pBt->btsFlags |= BTS_NO_WAL; + +- rc = sqlite3BtreeBeginTrans(pBtree, 0); ++ rc = sqlite3BtreeBeginTrans(pBtree, 0, 0); + if( rc==SQLITE_OK ){ + u8 *aData = pBt->pPage1->aData; + if( aData[18]!=(u8)iVersion || aData[19]!=(u8)iVersion ){ +- rc = sqlite3BtreeBeginTrans(pBtree, 2); ++ rc = sqlite3BtreeBeginTrans(pBtree, 2, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); + if( rc==SQLITE_OK ){ +@@ -69826,7 +73517,7 @@ + ** before this function exits. + */ + if( rc==SQLITE_OK && 0==sqlite3BtreeIsInReadTrans(p->pSrc) ){ +- rc = sqlite3BtreeBeginTrans(p->pSrc, 0); ++ rc = sqlite3BtreeBeginTrans(p->pSrc, 0, 0); + bCloseTrans = 1; + } + +@@ -69842,10 +73533,10 @@ + + /* Lock the destination database, if it is not locked already. */ + if( SQLITE_OK==rc && p->bDestLocked==0 +- && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2)) ++ && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2, ++ (int*)&p->iDestSchema)) + ){ + p->bDestLocked = 1; +- sqlite3BtreeGetMeta(p->pDest, BTREE_SCHEMA_VERSION, &p->iDestSchema); + } + + /* Do not allow backup if the destination database is in WAL mode +@@ -70289,8 +73980,7 @@ + + if( p->flags & MEM_Null ){ + /* Cannot be both MEM_Null and some other type */ +- assert( (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob +- |MEM_RowSet|MEM_Frame|MEM_Agg|MEM_Zero))==0 ); ++ assert( (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob|MEM_Agg))==0 ); + + /* If MEM_Null is set, then either the value is a pure NULL (the usual + ** case) or it is a pointer set using sqlite3_bind_pointer() or +@@ -70340,6 +74030,51 @@ + } + #endif + ++#ifdef SQLITE_DEBUG ++/* ++** Check that string value of pMem agrees with its integer or real value. ++** ++** A single int or real value always converts to the same strings. But ++** many different strings can be converted into the same int or real. ++** If a table contains a numeric value and an index is based on the ++** corresponding string value, then it is important that the string be ++** derived from the numeric value, not the other way around, to ensure ++** that the index and table are consistent. See ticket ++** https://www.sqlite.org/src/info/343634942dd54ab (2018-01-31) for ++** an example. ++** ++** This routine looks at pMem to verify that if it has both a numeric ++** representation and a string representation then the string rep has ++** been derived from the numeric and not the other way around. It returns ++** true if everything is ok and false if there is a problem. ++** ++** This routine is for use inside of assert() statements only. ++*/ ++SQLITE_PRIVATE int sqlite3VdbeMemConsistentDualRep(Mem *p){ ++ char zBuf[100]; ++ char *z; ++ int i, j, incr; ++ if( (p->flags & MEM_Str)==0 ) return 1; ++ if( (p->flags & (MEM_Int|MEM_Real))==0 ) return 1; ++ if( p->flags & MEM_Int ){ ++ sqlite3_snprintf(sizeof(zBuf),zBuf,"%lld",p->u.i); ++ }else{ ++ sqlite3_snprintf(sizeof(zBuf),zBuf,"%!.15g",p->u.r); ++ } ++ z = p->z; ++ i = j = 0; ++ incr = 1; ++ if( p->enc!=SQLITE_UTF8 ){ ++ incr = 2; ++ if( p->enc==SQLITE_UTF16BE ) z++; ++ } ++ while( zBuf[j] ){ ++ if( zBuf[j++]!=z[i] ) return 0; ++ i += incr; ++ } ++ return 1; ++} ++#endif /* SQLITE_DEBUG */ + + /* + ** If pMem is an object with a valid string representation, this routine +@@ -70358,7 +74093,7 @@ + #ifndef SQLITE_OMIT_UTF16 + int rc; + #endif +- assert( (pMem->flags&MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pMem) ); + assert( desiredEnc==SQLITE_UTF8 || desiredEnc==SQLITE_UTF16LE + || desiredEnc==SQLITE_UTF16BE ); + if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){ +@@ -70391,7 +74126,7 @@ + */ + SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ + assert( sqlite3VdbeCheckMemInvariants(pMem) ); +- assert( (pMem->flags&MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pMem) ); + testcase( pMem->db==0 ); + + /* If the bPreserve flag is set to true, then the memory cell must already +@@ -70402,7 +74137,7 @@ + assert( pMem->szMalloc==0 + || pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) ); + if( n<32 ) n = 32; +- if( bPreserve && pMem->szMalloc>0 && pMem->z==pMem->zMalloc ){ ++ if( pMem->szMalloc>0 && bPreserve && pMem->z==pMem->zMalloc ){ + pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n); + bPreserve = 0; + }else{ +@@ -70418,7 +74153,8 @@ + pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc); + } + +- if( bPreserve && pMem->z && ALWAYS(pMem->z!=pMem->zMalloc) ){ ++ if( bPreserve && pMem->z ){ ++ assert( pMem->z!=pMem->zMalloc ); + memcpy(pMem->zMalloc, pMem->z, pMem->n); + } + if( (pMem->flags&MEM_Dyn)!=0 ){ +@@ -70457,6 +74193,20 @@ + } + + /* ++** It is already known that pMem contains an unterminated string. ++** Add the zero terminator. ++*/ ++static SQLITE_NOINLINE int vdbeMemAddTerminator(Mem *pMem){ ++ if( sqlite3VdbeMemGrow(pMem, pMem->n+2, 1) ){ ++ return SQLITE_NOMEM_BKPT; ++ } ++ pMem->z[pMem->n] = 0; ++ pMem->z[pMem->n+1] = 0; ++ pMem->flags |= MEM_Term; ++ return SQLITE_OK; ++} ++ ++/* + ** Change pMem so that its MEM_Str or MEM_Blob value is stored in + ** MEM.zMalloc, where it can be safely written. + ** +@@ -70464,16 +74214,12 @@ + */ + SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){ + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); +- assert( (pMem->flags&MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pMem) ); + if( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ){ + if( ExpandBlob(pMem) ) return SQLITE_NOMEM; + if( pMem->szMalloc==0 || pMem->z!=pMem->zMalloc ){ +- if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){ +- return SQLITE_NOMEM_BKPT; +- } +- pMem->z[pMem->n] = 0; +- pMem->z[pMem->n+1] = 0; +- pMem->flags |= MEM_Term; ++ int rc = vdbeMemAddTerminator(pMem); ++ if( rc ) return rc; + } + } + pMem->flags &= ~MEM_Ephem; +@@ -70493,7 +74239,7 @@ + int nByte; + assert( pMem->flags & MEM_Zero ); + assert( pMem->flags&MEM_Blob ); +- assert( (pMem->flags&MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pMem) ); + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + + /* Set nByte to the number of bytes required to store the expanded blob. */ +@@ -70513,20 +74259,6 @@ + #endif + + /* +-** It is already known that pMem contains an unterminated string. +-** Add the zero terminator. +-*/ +-static SQLITE_NOINLINE int vdbeMemAddTerminator(Mem *pMem){ +- if( sqlite3VdbeMemGrow(pMem, pMem->n+2, 1) ){ +- return SQLITE_NOMEM_BKPT; +- } +- pMem->z[pMem->n] = 0; +- pMem->z[pMem->n+1] = 0; +- pMem->flags |= MEM_Term; +- return SQLITE_OK; +-} +- +-/* + ** Make sure the given Mem is \u0000 terminated. + */ + SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem *pMem){ +@@ -70562,7 +74294,7 @@ + assert( !(fg&MEM_Zero) ); + assert( !(fg&(MEM_Str|MEM_Blob)) ); + assert( fg&(MEM_Int|MEM_Real) ); +- assert( (pMem->flags&MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pMem) ); + assert( EIGHT_BYTE_ALIGNMENT(pMem) ); + + +@@ -70583,7 +74315,8 @@ + assert( fg & MEM_Real ); + sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->u.r); + } +- pMem->n = sqlite3Strlen30(pMem->z); ++ assert( pMem->z!=0 ); ++ pMem->n = sqlite3Strlen30NN(pMem->z); + pMem->enc = SQLITE_UTF8; + pMem->flags |= MEM_Str|MEM_Term; + if( bForce ) pMem->flags &= ~(MEM_Int|MEM_Real); +@@ -70600,29 +74333,56 @@ + ** otherwise. + */ + SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){ +- int rc = SQLITE_OK; +- if( ALWAYS(pFunc && pFunc->xFinalize) ){ +- sqlite3_context ctx; +- Mem t; +- assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef ); +- assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); +- memset(&ctx, 0, sizeof(ctx)); +- memset(&t, 0, sizeof(t)); +- t.flags = MEM_Null; +- t.db = pMem->db; +- ctx.pOut = &t; +- ctx.pMem = pMem; +- ctx.pFunc = pFunc; +- pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */ +- assert( (pMem->flags & MEM_Dyn)==0 ); +- if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc); +- memcpy(pMem, &t, sizeof(t)); +- rc = ctx.isError; +- } +- return rc; ++ sqlite3_context ctx; ++ Mem t; ++ assert( pFunc!=0 ); ++ assert( pFunc->xFinalize!=0 ); ++ assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef ); ++ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); ++ memset(&ctx, 0, sizeof(ctx)); ++ memset(&t, 0, sizeof(t)); ++ t.flags = MEM_Null; ++ t.db = pMem->db; ++ ctx.pOut = &t; ++ ctx.pMem = pMem; ++ ctx.pFunc = pFunc; ++ pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */ ++ assert( (pMem->flags & MEM_Dyn)==0 ); ++ if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc); ++ memcpy(pMem, &t, sizeof(t)); ++ return ctx.isError; + } + + /* ++** Memory cell pAccum contains the context of an aggregate function. ++** This routine calls the xValue method for that function and stores ++** the results in memory cell pMem. ++** ++** SQLITE_ERROR is returned if xValue() reports an error. SQLITE_OK ++** otherwise. ++*/ ++#ifndef SQLITE_OMIT_WINDOWFUNC ++SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem *pAccum, Mem *pOut, FuncDef *pFunc){ ++ sqlite3_context ctx; ++ Mem t; ++ assert( pFunc!=0 ); ++ assert( pFunc->xValue!=0 ); ++ assert( (pAccum->flags & MEM_Null)!=0 || pFunc==pAccum->u.pDef ); ++ assert( pAccum->db==0 || sqlite3_mutex_held(pAccum->db->mutex) ); ++ memset(&ctx, 0, sizeof(ctx)); ++ memset(&t, 0, sizeof(t)); ++ t.flags = MEM_Null; ++ t.db = pAccum->db; ++ sqlite3VdbeMemSetNull(pOut); ++ ctx.pOut = pOut; ++ ctx.pMem = pAccum; ++ ctx.pFunc = pFunc; ++ pFunc->xValue(&ctx); ++ return ctx.isError; ++} ++#endif /* SQLITE_OMIT_WINDOWFUNC */ ++ ++/* + ** If the memory cell contains a value that must be freed by + ** invoking the external callback in Mem.xDel, then this routine + ** will free that value. It also sets Mem.flags to MEM_Null. +@@ -70640,15 +74400,8 @@ + testcase( p->flags & MEM_Dyn ); + } + if( p->flags&MEM_Dyn ){ +- assert( (p->flags&MEM_RowSet)==0 ); + assert( p->xDel!=SQLITE_DYNAMIC && p->xDel!=0 ); + p->xDel((void *)p->z); +- }else if( p->flags&MEM_RowSet ){ +- sqlite3RowSetClear(p->u.pRowSet); +- }else if( p->flags&MEM_Frame ){ +- VdbeFrame *pFrame = p->u.pFrame; +- pFrame->pParent = pFrame->v->pDelFrame; +- pFrame->v->pDelFrame = pFrame; + } + p->flags = MEM_Null; + } +@@ -70780,6 +74533,16 @@ + } + + /* ++** Return 1 if pMem represents true, and return 0 if pMem represents false. ++** Return the value ifNull if pMem is NULL. ++*/ ++SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem *pMem, int ifNull){ ++ if( pMem->flags & MEM_Int ) return pMem->u.i!=0; ++ if( pMem->flags & MEM_Null ) return ifNull; ++ return sqlite3VdbeRealValue(pMem)!=0.0; ++} ++ ++/* + ** The MEM structure is already a MEM_Real. Try to also make it a + ** MEM_Int if we can. + */ +@@ -70786,7 +74549,7 @@ + SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem *pMem){ + i64 ix; + assert( pMem->flags & MEM_Real ); +- assert( (pMem->flags & MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pMem) ); + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + assert( EIGHT_BYTE_ALIGNMENT(pMem) ); + +@@ -70813,7 +74576,7 @@ + */ + SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem *pMem){ + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); +- assert( (pMem->flags & MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pMem) ); + assert( EIGHT_BYTE_ALIGNMENT(pMem) ); + + pMem->u.i = sqlite3VdbeIntValue(pMem); +@@ -70834,6 +74597,18 @@ + return SQLITE_OK; + } + ++/* Compare a floating point value to an integer. Return true if the two ++** values are the same within the precision of the floating point value. ++** ++** For some versions of GCC on 32-bit machines, if you do the more obvious ++** comparison of "r1==(double)i" you sometimes get an answer of false even ++** though the r1 and (double)i values are bit-for-bit the same. ++*/ ++static int sqlite3RealSameAsInt(double r1, sqlite3_int64 i){ ++ double r2 = (double)i; ++ return memcmp(&r1, &r2, sizeof(r1))==0; ++} ++ + /* + ** Convert pMem so that it has types MEM_Real or MEM_Int or both. + ** Invalidate any prior representations. +@@ -70844,14 +74619,21 @@ + */ + SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){ + if( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ){ ++ int rc; + assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 ); + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); +- if( 0==sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc) ){ ++ rc = sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc); ++ if( rc==0 ){ + MemSetTypeFlag(pMem, MEM_Int); + }else{ +- pMem->u.r = sqlite3VdbeRealValue(pMem); +- MemSetTypeFlag(pMem, MEM_Real); +- sqlite3VdbeIntegerAffinity(pMem); ++ i64 i = pMem->u.i; ++ sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc); ++ if( rc==1 && sqlite3RealSameAsInt(pMem->u.r, i) ){ ++ pMem->u.i = i; ++ MemSetTypeFlag(pMem, MEM_Int); ++ }else{ ++ MemSetTypeFlag(pMem, MEM_Real); ++ } + } + } + assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 ); +@@ -70978,7 +74760,7 @@ + } + + /* A no-op destructor */ +-static void sqlite3NoopDestructor(void *p){ UNUSED_PARAMETER(p); } ++SQLITE_PRIVATE void sqlite3NoopDestructor(void *p){ UNUSED_PARAMETER(p); } + + /* + ** Set the value stored in *pMem should already be a NULL. +@@ -71012,26 +74794,36 @@ + } + #endif + ++#ifdef SQLITE_DEBUG + /* ++** Return true if the Mem holds a RowSet object. This routine is intended ++** for use inside of assert() statements. ++*/ ++SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem *pMem){ ++ return (pMem->flags&(MEM_Blob|MEM_Dyn))==(MEM_Blob|MEM_Dyn) ++ && pMem->xDel==sqlite3RowSetDelete; ++} ++#endif ++ ++/* + ** Delete any previous value and set the value of pMem to be an + ** empty boolean index. ++** ++** Return SQLITE_OK on success and SQLITE_NOMEM if a memory allocation ++** error occurs. + */ +-SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem *pMem){ ++SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem *pMem){ + sqlite3 *db = pMem->db; ++ RowSet *p; + assert( db!=0 ); +- assert( (pMem->flags & MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pMem) ); + sqlite3VdbeMemRelease(pMem); +- pMem->zMalloc = sqlite3DbMallocRawNN(db, 64); +- if( db->mallocFailed ){ +- pMem->flags = MEM_Null; +- pMem->szMalloc = 0; +- }else{ +- assert( pMem->zMalloc ); +- pMem->szMalloc = sqlite3DbMallocSize(db, pMem->zMalloc); +- pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc, pMem->szMalloc); +- assert( pMem->u.pRowSet!=0 ); +- pMem->flags = MEM_RowSet; +- } ++ p = sqlite3RowSetInit(db); ++ if( p==0 ) return SQLITE_NOMEM; ++ pMem->z = (char*)p; ++ pMem->flags = MEM_Blob|MEM_Dyn; ++ pMem->xDel = sqlite3RowSetDelete; ++ return SQLITE_OK; + } + + /* +@@ -71064,7 +74856,21 @@ + Mem *pX; + for(i=0, pX=pVdbe->aMem; i<pVdbe->nMem; i++, pX++){ + if( pX->pScopyFrom==pMem ){ +- pX->flags |= MEM_Undefined; ++ /* If pX is marked as a shallow copy of pMem, then verify that ++ ** no significant changes have been made to pX since the OP_SCopy. ++ ** A significant change would indicated a missed call to this ++ ** function for pX. Minor changes, such as adding or removing a ++ ** dual type, are allowed, as long as the underlying value is the ++ ** same. */ ++ u16 mFlags = pMem->flags & pX->flags & pX->mScopyFlags; ++ assert( (mFlags&MEM_Int)==0 || pMem->u.i==pX->u.i ); ++ assert( (mFlags&MEM_Real)==0 || pMem->u.r==pX->u.r ); ++ assert( (mFlags&MEM_Str)==0 || (pMem->n==pX->n && pMem->z==pX->z) ); ++ assert( (mFlags&MEM_Blob)==0 || sqlite3BlobCompare(pMem,pX)==0 ); ++ ++ /* pMem is the register that is changing. But also mark pX as ++ ** undefined so that we can quickly detect the shallow-copy error */ ++ pX->flags = MEM_Undefined; + pX->pScopyFrom = 0; + } + } +@@ -71085,7 +74891,7 @@ + sqlite3VdbeMemShallowCopy(pTo, pFrom, eType); + } + SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){ +- assert( (pFrom->flags & MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pFrom) ); + assert( pTo->db==pFrom->db ); + if( VdbeMemDynamic(pTo) ){ vdbeClrCopy(pTo,pFrom,srcType); return; } + memcpy(pTo, pFrom, MEMCELLSIZE); +@@ -71103,7 +74909,7 @@ + SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){ + int rc = SQLITE_OK; + +- assert( (pFrom->flags & MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pFrom) ); + if( VdbeMemDynamic(pTo) ) vdbeMemClearExternAndSetNull(pTo); + memcpy(pTo, pFrom, MEMCELLSIZE); + pTo->flags &= ~MEM_Dyn; +@@ -71161,7 +74967,7 @@ + u16 flags = 0; /* New value for pMem->flags */ + + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); +- assert( (pMem->flags & MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pMem) ); + + /* If z is a NULL pointer, set pMem to contain an SQL NULL. */ + if( !z ){ +@@ -71178,7 +74984,7 @@ + if( nByte<0 ){ + assert( enc!=0 ); + if( enc==SQLITE_UTF8 ){ +- nByte = sqlite3Strlen30(z); ++ nByte = 0x7fffffff & (int)strlen(z); + if( nByte>iLimit ) nByte = iLimit+1; + }else{ + for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){} +@@ -71256,12 +75062,11 @@ + ){ + int rc; + pMem->flags = MEM_Null; +- if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+2)) ){ ++ if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+1)) ){ + rc = sqlite3BtreePayload(pCur, offset, amt, pMem->z); + if( rc==SQLITE_OK ){ +- pMem->z[amt] = 0; +- pMem->z[amt+1] = 0; +- pMem->flags = MEM_Blob|MEM_Term; ++ pMem->z[amt] = 0; /* Overrun area used when reading malformed records */ ++ pMem->flags = MEM_Blob; + pMem->n = (int)amt; + }else{ + sqlite3VdbeMemRelease(pMem); +@@ -71284,7 +75089,7 @@ + + /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert() + ** that both the BtShared and database handle mutexes are held. */ +- assert( (pMem->flags & MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pMem) ); + zData = (char *)sqlite3BtreePayloadFetch(pCur, &available); + assert( zData!=0 ); + +@@ -71308,7 +75113,7 @@ + assert( pVal!=0 ); + assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) ); + assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) ); +- assert( (pVal->flags & MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pVal) ); + assert( (pVal->flags & (MEM_Null))==0 ); + if( pVal->flags & (MEM_Blob|MEM_Str) ){ + if( ExpandBlob(pVal) ) return 0; +@@ -71330,6 +75135,7 @@ + assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0 + || pVal->db->mallocFailed ); + if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){ ++ assert( sqlite3VdbeMemConsistentDualRep(pVal) ); + return pVal->z; + }else{ + return 0; +@@ -71350,8 +75156,9 @@ + if( !pVal ) return 0; + assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) ); + assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) ); +- assert( (pVal->flags & MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pVal) ); + if( (pVal->flags&(MEM_Str|MEM_Term))==(MEM_Str|MEM_Term) && pVal->enc==enc ){ ++ assert( sqlite3VdbeMemConsistentDualRep(pVal) ); + return pVal->z; + } + if( pVal->flags&MEM_Null ){ +@@ -71410,7 +75217,7 @@ + if( pRec ){ + pRec->pKeyInfo = sqlite3KeyInfoOfIndex(p->pParse, pIdx); + if( pRec->pKeyInfo ){ +- assert( pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField==nCol ); ++ assert( pRec->pKeyInfo->nAllField==nCol ); + assert( pRec->pKeyInfo->enc==ENC(db) ); + pRec->aMem = (Mem *)((u8*)pRec + ROUND8(sizeof(UnpackedRecord))); + for(i=0; i<nCol; i++){ +@@ -71567,7 +75374,11 @@ + + assert( pExpr!=0 ); + while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft; ++#if defined(SQLITE_ENABLE_STAT3_OR_STAT4) ++ if( op==TK_REGISTER ) op = pExpr->op2; ++#else + if( NEVER(op==TK_REGISTER) ) op = pExpr->op2; ++#endif + + /* Compressed expressions only appear when parsing the DEFAULT clause + ** on a table column definition, and hence only when pCtx==0. This +@@ -71651,18 +75462,25 @@ + 0, SQLITE_DYNAMIC); + } + #endif +- + #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + else if( op==TK_FUNCTION && pCtx!=0 ){ + rc = valueFromFunction(db, pExpr, enc, affinity, &pVal, pCtx); + } + #endif ++ else if( op==TK_TRUEFALSE ){ ++ pVal = valueNew(db, pCtx); ++ pVal->flags = MEM_Int; ++ pVal->u.i = pExpr->u.zToken[4]==0; ++ } + + *ppVal = pVal; + return rc; + + no_mem: +- sqlite3OomFault(db); ++#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 ++ if( pCtx==0 || pCtx->pParse->nErr==0 ) ++#endif ++ sqlite3OomFault(db); + sqlite3DbFree(db, zVal); + assert( *ppVal==0 ); + #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +@@ -71905,11 +75723,11 @@ + int iCol, /* Column to extract */ + sqlite3_value **ppVal /* OUT: Extracted value */ + ){ +- u32 t; /* a column type code */ ++ u32 t = 0; /* a column type code */ + int nHdr; /* Size of the header in the record */ + int iHdr; /* Next unread header byte */ + int iField; /* Next unread data byte */ +- int szField; /* Size of the current data field */ ++ int szField = 0; /* Size of the current data field */ + int i; /* Column index */ + u8 *a = (u8*)pRec; /* Typecast byte array */ + Mem *pMem = *ppVal; /* Write result into this Mem object */ +@@ -71946,7 +75764,7 @@ + SQLITE_PRIVATE void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){ + if( pRec ){ + int i; +- int nCol = pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField; ++ int nCol = pRec->pKeyInfo->nAllField; + Mem *aMem = pRec->aMem; + sqlite3 *db = aMem[0].db; + for(i=0; i<nCol; i++){ +@@ -72042,10 +75860,12 @@ + db->pVdbe = p; + p->magic = VDBE_MAGIC_INIT; + p->pParse = pParse; ++ pParse->pVdbe = p; + assert( pParse->aLabel==0 ); + assert( pParse->nLabel==0 ); + assert( pParse->nOpAlloc==0 ); + assert( pParse->szOpAlloc==0 ); ++ sqlite3VdbeAddOp2(p, OP_Init, 0, 1); + return p; + } + +@@ -72071,6 +75891,13 @@ + } + assert( p->zSql==0 ); + p->zSql = sqlite3DbStrNDup(p->db, z, n); ++#ifdef SQLITE_ENABLE_NORMALIZE ++ assert( p->zNormSql==0 ); ++ if( p->zSql && (prepFlags & SQLITE_PREPARE_NORMALIZE)!=0 ){ ++ sqlite3Normalize(p, p->zSql, n, prepFlags); ++ assert( p->zNormSql!=0 || p->db->mallocFailed ); ++ } ++#endif + } + + /* +@@ -72092,6 +75919,11 @@ + zTmp = pA->zSql; + pA->zSql = pB->zSql; + pB->zSql = zTmp; ++#ifdef SQLITE_ENABLE_NORMALIZE ++ zTmp = pA->zNormSql; ++ pA->zNormSql = pB->zNormSql; ++ pB->zNormSql = zTmp; ++#endif + pB->expmask = pA->expmask; + pB->prepFlags = pA->prepFlags; + memcpy(pB->aCounter, pA->aCounter, sizeof(pB->aCounter)); +@@ -72200,14 +76032,6 @@ + #endif + #ifdef SQLITE_DEBUG + if( p->db->flags & SQLITE_VdbeAddopTrace ){ +- int jj, kk; +- Parse *pParse = p->pParse; +- for(jj=kk=0; jj<pParse->nColCache; jj++){ +- struct yColCache *x = pParse->aColCache + jj; +- printf(" r[%d]={%d:%d}", x->iReg, x->iTable, x->iColumn); +- kk++; +- } +- if( kk ) printf("\n"); + sqlite3VdbePrintOp(0, i, &p->aOp[i]); + test_addop_breakpoint(); + } +@@ -72310,7 +76134,50 @@ + return sqlite3VdbeAddOp4(p, op, p1, p2, p3, p4copy, p4type); + } + ++#ifndef SQLITE_OMIT_EXPLAIN + /* ++** Return the address of the current EXPLAIN QUERY PLAN baseline. ++** 0 means "none". ++*/ ++SQLITE_PRIVATE int sqlite3VdbeExplainParent(Parse *pParse){ ++ VdbeOp *pOp; ++ if( pParse->addrExplain==0 ) return 0; ++ pOp = sqlite3VdbeGetOp(pParse->pVdbe, pParse->addrExplain); ++ return pOp->p2; ++} ++ ++/* ++** 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. ++*/ ++SQLITE_PRIVATE void sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){ ++ if( pParse->explain==2 ){ ++ char *zMsg; ++ Vdbe *v; ++ va_list ap; ++ int iThis; ++ va_start(ap, zFmt); ++ zMsg = sqlite3VMPrintf(pParse->db, zFmt, ap); ++ va_end(ap); ++ v = pParse->pVdbe; ++ iThis = v->nOp; ++ sqlite3VdbeAddOp4(v, OP_Explain, iThis, pParse->addrExplain, 0, ++ zMsg, P4_DYNAMIC); ++ if( bPush) pParse->addrExplain = iThis; ++ } ++} ++ ++/* ++** Pop the EXPLAIN QUERY PLAN stack one level. ++*/ ++SQLITE_PRIVATE void sqlite3VdbeExplainPop(Parse *pParse){ ++ pParse->addrExplain = sqlite3VdbeExplainParent(pParse); ++} ++#endif /* SQLITE_OMIT_EXPLAIN */ ++ ++/* + ** Add an OP_ParseSchema opcode. This routine is broken out from + ** sqlite3VdbeAddOp4() since it needs to also needs to mark all btrees + ** as having been used. +@@ -72399,6 +76266,12 @@ + assert( j<p->nLabel ); + assert( j>=0 ); + if( p->aLabel ){ ++#ifdef SQLITE_DEBUG ++ if( p->db->flags & SQLITE_VdbeAddopTrace ){ ++ printf("RESOLVE LABEL %d to %d\n", x, v->nOp); ++ } ++#endif ++ assert( p->aLabel[j]==(-1) ); /* Labels may only be resolved once */ + p->aLabel[j] = v->nOp; + } + } +@@ -72499,7 +76372,8 @@ + ** * OP_VUpdate + ** * OP_VRename + ** * OP_FkCounter with P2==0 (immediate foreign key constraint) +-** * OP_CreateTable and OP_InitCoroutine (for CREATE TABLE AS SELECT ...) ++** * OP_CreateBtree/BTREE_INTKEY and OP_InitCoroutine ++** (for CREATE TABLE AS SELECT ...) + ** + ** Then check that the value of Parse.mayAbort is true if an + ** ABORT may be thrown, or false otherwise. Return true if it does +@@ -72527,7 +76401,7 @@ + hasAbort = 1; + break; + } +- if( opcode==OP_CreateTable ) hasCreateTable = 1; ++ if( opcode==OP_CreateBtree && pOp->p3==BTREE_INTKEY ) hasCreateTable = 1; + if( opcode==OP_InitCoroutine ) hasInitCoroutine = 1; + #ifndef SQLITE_OMIT_FOREIGN_KEY + if( opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1 ){ +@@ -72547,7 +76421,33 @@ + } + #endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */ + ++#ifdef SQLITE_DEBUG + /* ++** Increment the nWrite counter in the VDBE if the cursor is not an ++** ephemeral cursor, or if the cursor argument is NULL. ++*/ ++SQLITE_PRIVATE void sqlite3VdbeIncrWriteCounter(Vdbe *p, VdbeCursor *pC){ ++ if( pC==0 ++ || (pC->eCurType!=CURTYPE_SORTER ++ && pC->eCurType!=CURTYPE_PSEUDO ++ && !pC->isEphemeral) ++ ){ ++ p->nWrite++; ++ } ++} ++#endif ++ ++#ifdef SQLITE_DEBUG ++/* ++** Assert if an Abort at this point in time might result in a corrupt ++** database. ++*/ ++SQLITE_PRIVATE void sqlite3VdbeAssertAbortable(Vdbe *p){ ++ assert( p->nWrite==0 || p->usesStmtJournal ); ++} ++#endif ++ ++/* + ** This routine is called after all opcodes have been inserted. It loops + ** through all the opcodes and fixes up some details. + ** +@@ -72606,6 +76506,25 @@ + p->bIsReader = 1; + break; + } ++ case OP_Next: ++ case OP_SorterNext: { ++ pOp->p4.xAdvance = sqlite3BtreeNext; ++ pOp->p4type = P4_ADVANCE; ++ /* The code generator never codes any of these opcodes as a jump ++ ** to a label. They are always coded as a jump backwards to a ++ ** known address */ ++ assert( pOp->p2>=0 ); ++ break; ++ } ++ case OP_Prev: { ++ pOp->p4.xAdvance = sqlite3BtreePrevious; ++ pOp->p4type = P4_ADVANCE; ++ /* The code generator never codes any of these opcodes as a jump ++ ** to a label. They are always coded as a jump backwards to a ++ ** known address */ ++ assert( pOp->p2>=0 ); ++ break; ++ } + #ifndef SQLITE_OMIT_VIRTUALTABLE + case OP_VUpdate: { + if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2; +@@ -72617,27 +76536,25 @@ + assert( pOp[-1].opcode==OP_Integer ); + n = pOp[-1].p1; + if( n>nMaxArgs ) nMaxArgs = n; +- break; ++ /* Fall through into the default case */ + } + #endif +- case OP_Next: +- case OP_NextIfOpen: +- case OP_SorterNext: { +- pOp->p4.xAdvance = sqlite3BtreeNext; +- pOp->p4type = P4_ADVANCE; ++ 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; + } +- case OP_Prev: +- case OP_PrevIfOpen: { +- pOp->p4.xAdvance = sqlite3BtreePrevious; +- pOp->p4type = P4_ADVANCE; +- break; +- } + } +- if( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 && pOp->p2<0 ){ +- assert( ADDR(pOp->p2)<pParse->nLabel ); +- pOp->p2 = aLabel[ADDR(pOp->p2)]; +- } ++ /* 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 || pOp->p2>=0); + } + if( pOp==p->aOp ) break; + pOp--; +@@ -72688,6 +76605,17 @@ + #endif + + /* ++** Generate code (a single OP_Abortable opcode) that will ++** verify that the VDBE program can safely call Abort in the current ++** context. ++*/ ++#if defined(SQLITE_DEBUG) ++SQLITE_PRIVATE void sqlite3VdbeVerifyAbortable(Vdbe *p, int onError){ ++ if( onError==OE_Abort ) sqlite3VdbeAddOp0(p, OP_Abortable); ++} ++#endif ++ ++/* + ** This function returns a pointer to the array of opcodes associated with + ** the Vdbe passed as the first argument. It is the callers responsibility + ** to arrange for the returned array to be eventually freed using the +@@ -72853,6 +76781,7 @@ + case P4_REAL: + case P4_INT64: + case P4_DYNAMIC: ++ case P4_DYNBLOB: + case P4_INTARRAY: { + sqlite3DbFree(db, p4); + break; +@@ -73230,23 +77159,23 @@ + const char *zOp = 0; + switch( pExpr->op ){ + case TK_STRING: +- sqlite3XPrintf(p, "%Q", pExpr->u.zToken); ++ sqlite3_str_appendf(p, "%Q", pExpr->u.zToken); + break; + case TK_INTEGER: +- sqlite3XPrintf(p, "%d", pExpr->u.iValue); ++ sqlite3_str_appendf(p, "%d", pExpr->u.iValue); + break; + case TK_NULL: +- sqlite3XPrintf(p, "NULL"); ++ sqlite3_str_appendf(p, "NULL"); + break; + case TK_REGISTER: { +- sqlite3XPrintf(p, "r[%d]", pExpr->iTable); ++ sqlite3_str_appendf(p, "r[%d]", pExpr->iTable); + break; + } + case TK_COLUMN: { + if( pExpr->iColumn<0 ){ +- sqlite3XPrintf(p, "rowid"); ++ sqlite3_str_appendf(p, "rowid"); + }else{ +- sqlite3XPrintf(p, "c%d", (int)pExpr->iColumn); ++ sqlite3_str_appendf(p, "c%d", (int)pExpr->iColumn); + } + break; + } +@@ -73278,18 +77207,18 @@ + case TK_NOTNULL: zOp = "NOTNULL"; break; + + default: +- sqlite3XPrintf(p, "%s", "expr"); ++ sqlite3_str_appendf(p, "%s", "expr"); + break; + } + + if( zOp ){ +- sqlite3XPrintf(p, "%s(", zOp); ++ sqlite3_str_appendf(p, "%s(", zOp); + displayP4Expr(p, pExpr->pLeft); + if( pExpr->pRight ){ +- sqlite3StrAccumAppend(p, ",", 1); ++ sqlite3_str_append(p, ",", 1); + displayP4Expr(p, pExpr->pRight); + } +- sqlite3StrAccumAppend(p, ")", 1); ++ sqlite3_str_append(p, ")", 1); + } + } + #endif /* VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) */ +@@ -73310,14 +77239,15 @@ + int j; + KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; + assert( pKeyInfo->aSortOrder!=0 ); +- sqlite3XPrintf(&x, "k(%d", pKeyInfo->nField); +- for(j=0; j<pKeyInfo->nField; j++){ ++ sqlite3_str_appendf(&x, "k(%d", pKeyInfo->nKeyField); ++ for(j=0; j<pKeyInfo->nKeyField; j++){ + CollSeq *pColl = pKeyInfo->aColl[j]; + const char *zColl = pColl ? pColl->zName : ""; + if( strcmp(zColl, "BINARY")==0 ) zColl = "B"; +- sqlite3XPrintf(&x, ",%s%s", pKeyInfo->aSortOrder[j] ? "-" : "", zColl); ++ sqlite3_str_appendf(&x, ",%s%s", ++ pKeyInfo->aSortOrder[j] ? "-" : "", zColl); + } +- sqlite3StrAccumAppend(&x, ")", 1); ++ sqlite3_str_append(&x, ")", 1); + break; + } + #ifdef SQLITE_ENABLE_CURSOR_HINTS +@@ -73328,31 +77258,31 @@ + #endif + case P4_COLLSEQ: { + CollSeq *pColl = pOp->p4.pColl; +- sqlite3XPrintf(&x, "(%.20s)", pColl->zName); ++ sqlite3_str_appendf(&x, "(%.20s)", pColl->zName); + break; + } + case P4_FUNCDEF: { + FuncDef *pDef = pOp->p4.pFunc; +- sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg); ++ sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg); + break; + } + #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) + case P4_FUNCCTX: { + FuncDef *pDef = pOp->p4.pCtx->pFunc; +- sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg); ++ sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg); + break; + } + #endif + case P4_INT64: { +- sqlite3XPrintf(&x, "%lld", *pOp->p4.pI64); ++ sqlite3_str_appendf(&x, "%lld", *pOp->p4.pI64); + break; + } + case P4_INT32: { +- sqlite3XPrintf(&x, "%d", pOp->p4.i); ++ sqlite3_str_appendf(&x, "%d", pOp->p4.i); + break; + } + case P4_REAL: { +- sqlite3XPrintf(&x, "%.16g", *pOp->p4.pReal); ++ sqlite3_str_appendf(&x, "%.16g", *pOp->p4.pReal); + break; + } + case P4_MEM: { +@@ -73360,9 +77290,9 @@ + if( pMem->flags & MEM_Str ){ + zP4 = pMem->z; + }else if( pMem->flags & MEM_Int ){ +- sqlite3XPrintf(&x, "%lld", pMem->u.i); ++ sqlite3_str_appendf(&x, "%lld", pMem->u.i); + }else if( pMem->flags & MEM_Real ){ +- sqlite3XPrintf(&x, "%.16g", pMem->u.r); ++ sqlite3_str_appendf(&x, "%.16g", pMem->u.r); + }else if( pMem->flags & MEM_Null ){ + zP4 = "NULL"; + }else{ +@@ -73374,7 +77304,7 @@ + #ifndef SQLITE_OMIT_VIRTUALTABLE + case P4_VTAB: { + sqlite3_vtab *pVtab = pOp->p4.pVtab->pVtab; +- sqlite3XPrintf(&x, "vtab:%p", pVtab); ++ sqlite3_str_appendf(&x, "vtab:%p", pVtab); + break; + } + #endif +@@ -73383,23 +77313,24 @@ + int *ai = pOp->p4.ai; + int n = ai[0]; /* The first element of an INTARRAY is always the + ** count of the number of elements to follow */ +- for(i=1; i<n; i++){ +- sqlite3XPrintf(&x, ",%d", ai[i]); ++ for(i=1; i<=n; i++){ ++ sqlite3_str_appendf(&x, ",%d", ai[i]); + } + zTemp[0] = '['; +- sqlite3StrAccumAppend(&x, "]", 1); ++ sqlite3_str_append(&x, "]", 1); + break; + } + case P4_SUBPROGRAM: { +- sqlite3XPrintf(&x, "program"); ++ sqlite3_str_appendf(&x, "program"); + break; + } ++ case P4_DYNBLOB: + case P4_ADVANCE: { + zTemp[0] = 0; + break; + } + case P4_TABLE: { +- sqlite3XPrintf(&x, "%s", pOp->p4.pTab->zName); ++ sqlite3_str_appendf(&x, "%s", pOp->p4.pTab->zName); + break; + } + default: { +@@ -73500,7 +77431,7 @@ + /* + ** Print a single opcode. This routine is used for debugging only. + */ +-SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){ ++SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, VdbeOp *pOp){ + char *zP4; + char zPtr[50]; + char zCom[100]; +@@ -73569,9 +77500,8 @@ + */ + testcase( p->flags & MEM_Agg ); + testcase( p->flags & MEM_Dyn ); +- testcase( p->flags & MEM_Frame ); +- testcase( p->flags & MEM_RowSet ); +- if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){ ++ testcase( p->xDel==sqlite3VdbeFrameMemDel ); ++ if( p->flags&(MEM_Agg|MEM_Dyn) ){ + sqlite3VdbeMemRelease(p); + }else if( p->szMalloc ){ + sqlite3DbFreeNN(db, p->zMalloc); +@@ -73583,7 +77513,36 @@ + } + } + ++#ifdef SQLITE_DEBUG + /* ++** Verify that pFrame is a valid VdbeFrame pointer. Return true if it is ++** and false if something is wrong. ++** ++** This routine is intended for use inside of assert() statements only. ++*/ ++SQLITE_PRIVATE int sqlite3VdbeFrameIsValid(VdbeFrame *pFrame){ ++ if( pFrame->iFrameMagic!=SQLITE_FRAME_MAGIC ) return 0; ++ return 1; ++} ++#endif ++ ++ ++/* ++** This is a destructor on a Mem object (which is really an sqlite3_value) ++** that deletes the Frame object that is attached to it as a blob. ++** ++** This routine does not delete the Frame right away. It merely adds the ++** frame to a list of frames to be deleted when the Vdbe halts. ++*/ ++SQLITE_PRIVATE void sqlite3VdbeFrameMemDel(void *pArg){ ++ VdbeFrame *pFrame = (VdbeFrame*)pArg; ++ assert( sqlite3VdbeFrameIsValid(pFrame) ); ++ pFrame->pParent = pFrame->v->pDelFrame; ++ pFrame->v->pDelFrame = pFrame; ++} ++ ++ ++/* + ** Delete a VdbeFrame object and its contents. VdbeFrame objects are + ** allocated by the OP_Program opcode in sqlite3VdbeExec(). + */ +@@ -73591,6 +77550,7 @@ + int i; + Mem *aMem = VdbeFrameMem(p); + VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem]; ++ assert( sqlite3VdbeFrameIsValid(p) ); + for(i=0; i<p->nChildCsr; i++){ + sqlite3VdbeFreeCursor(p->v, apCsr[i]); + } +@@ -73611,6 +77571,9 @@ + ** p->explain==2, only OP_Explain instructions are listed and these + ** are shown in a different format. p->explain==2 is used to implement + ** EXPLAIN QUERY PLAN. ++** 2018-04-24: In p->explain==2 mode, the OP_Init opcodes of triggers ++** are also shown, so that the boundaries between the main program and ++** each trigger are clear. + ** + ** When p->explain==1, first the main program is listed, then each of + ** the trigger subprograms are listed one by one. +@@ -73626,6 +77589,8 @@ + int i; /* Loop counter */ + int rc = SQLITE_OK; /* Return code */ + Mem *pMem = &p->aMem[1]; /* First Mem of result set */ ++ int bListSubprogs = (p->explain==1 || (db->flags & SQLITE_TriggerEQP)!=0); ++ Op *pOp = 0; + + assert( p->explain ); + assert( p->magic==VDBE_MAGIC_RUN ); +@@ -73638,7 +77603,7 @@ + releaseMemArray(pMem, 8); + p->pResultSet = 0; + +- if( p->rc==SQLITE_NOMEM_BKPT ){ ++ if( p->rc==SQLITE_NOMEM ){ + /* This happens if a malloc() inside a call to sqlite3_column_text() or + ** sqlite3_column_text16() failed. */ + sqlite3OomFault(db); +@@ -73653,7 +77618,7 @@ + ** encountered, but p->pc will eventually catch up to nRow. + */ + nRow = p->nOp; +- if( p->explain==1 ){ ++ if( bListSubprogs ){ + /* The first 8 memory cells are used for the result set. So we will + ** commandeer the 9th cell to use as storage for an array of pointers + ** to trigger subprograms. The VDBE is guaranteed to have at least 9 +@@ -73671,19 +77636,13 @@ + } + } + +- do{ ++ while(1){ /* Loop exits via break */ + i = p->pc++; +- }while( i<nRow && p->explain==2 && p->aOp[i].opcode!=OP_Explain ); +- if( i>=nRow ){ +- p->rc = SQLITE_OK; +- rc = SQLITE_DONE; +- }else if( db->u1.isInterrupted ){ +- p->rc = SQLITE_INTERRUPT; +- rc = SQLITE_ERROR; +- sqlite3VdbeError(p, sqlite3ErrStr(p->rc)); +- }else{ +- char *zP4; +- Op *pOp; ++ if( i>=nRow ){ ++ p->rc = SQLITE_OK; ++ rc = SQLITE_DONE; ++ break; ++ } + if( i<p->nOp ){ + /* The output line number is small enough that we are still in the + ** main program. */ +@@ -73698,94 +77657,113 @@ + } + pOp = &apSub[j]->aOp[i]; + } +- if( p->explain==1 ){ +- pMem->flags = MEM_Int; +- pMem->u.i = i; /* Program counter */ +- pMem++; +- +- pMem->flags = MEM_Static|MEM_Str|MEM_Term; +- pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */ +- assert( pMem->z!=0 ); +- pMem->n = sqlite3Strlen30(pMem->z); +- pMem->enc = SQLITE_UTF8; +- pMem++; + +- /* When an OP_Program opcode is encounter (the only opcode that has +- ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms +- ** kept in p->aMem[9].z to hold the new program - assuming this subprogram +- ** has not already been seen. +- */ +- if( pOp->p4type==P4_SUBPROGRAM ){ +- int nByte = (nSub+1)*sizeof(SubProgram*); +- int j; +- for(j=0; j<nSub; j++){ +- if( apSub[j]==pOp->p4.pProgram ) break; ++ /* When an OP_Program opcode is encounter (the only opcode that has ++ ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms ++ ** kept in p->aMem[9].z to hold the new program - assuming this subprogram ++ ** has not already been seen. ++ */ ++ if( bListSubprogs && pOp->p4type==P4_SUBPROGRAM ){ ++ int nByte = (nSub+1)*sizeof(SubProgram*); ++ int j; ++ for(j=0; j<nSub; j++){ ++ if( apSub[j]==pOp->p4.pProgram ) break; ++ } ++ if( j==nSub ){ ++ p->rc = sqlite3VdbeMemGrow(pSub, nByte, nSub!=0); ++ if( p->rc!=SQLITE_OK ){ ++ rc = SQLITE_ERROR; ++ break; + } +- if( j==nSub && SQLITE_OK==sqlite3VdbeMemGrow(pSub, nByte, nSub!=0) ){ +- apSub = (SubProgram **)pSub->z; +- apSub[nSub++] = pOp->p4.pProgram; +- pSub->flags |= MEM_Blob; +- pSub->n = nSub*sizeof(SubProgram*); +- } ++ apSub = (SubProgram **)pSub->z; ++ apSub[nSub++] = pOp->p4.pProgram; ++ pSub->flags |= MEM_Blob; ++ pSub->n = nSub*sizeof(SubProgram*); ++ nRow += pOp->p4.pProgram->nOp; + } + } ++ if( p->explain<2 ) break; ++ if( pOp->opcode==OP_Explain ) break; ++ if( pOp->opcode==OP_Init && p->pc>1 ) break; ++ } + +- pMem->flags = MEM_Int; +- pMem->u.i = pOp->p1; /* P1 */ +- pMem++; ++ if( rc==SQLITE_OK ){ ++ if( db->u1.isInterrupted ){ ++ p->rc = SQLITE_INTERRUPT; ++ rc = SQLITE_ERROR; ++ sqlite3VdbeError(p, sqlite3ErrStr(p->rc)); ++ }else{ ++ char *zP4; ++ if( p->explain==1 ){ ++ pMem->flags = MEM_Int; ++ pMem->u.i = i; /* Program counter */ ++ pMem++; ++ ++ pMem->flags = MEM_Static|MEM_Str|MEM_Term; ++ pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */ ++ assert( pMem->z!=0 ); ++ pMem->n = sqlite3Strlen30(pMem->z); ++ pMem->enc = SQLITE_UTF8; ++ pMem++; ++ } + +- pMem->flags = MEM_Int; +- pMem->u.i = pOp->p2; /* P2 */ +- pMem++; ++ pMem->flags = MEM_Int; ++ pMem->u.i = pOp->p1; /* P1 */ ++ pMem++; + +- pMem->flags = MEM_Int; +- pMem->u.i = pOp->p3; /* P3 */ +- pMem++; ++ pMem->flags = MEM_Int; ++ pMem->u.i = pOp->p2; /* P2 */ ++ pMem++; + +- if( sqlite3VdbeMemClearAndResize(pMem, 100) ){ /* P4 */ +- assert( p->db->mallocFailed ); +- return SQLITE_ERROR; +- } +- pMem->flags = MEM_Str|MEM_Term; +- zP4 = displayP4(pOp, pMem->z, pMem->szMalloc); +- if( zP4!=pMem->z ){ +- pMem->n = 0; +- sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0); +- }else{ +- assert( pMem->z!=0 ); +- pMem->n = sqlite3Strlen30(pMem->z); +- pMem->enc = SQLITE_UTF8; +- } +- pMem++; ++ pMem->flags = MEM_Int; ++ pMem->u.i = pOp->p3; /* P3 */ ++ pMem++; + +- if( p->explain==1 ){ +- if( sqlite3VdbeMemClearAndResize(pMem, 4) ){ ++ if( sqlite3VdbeMemClearAndResize(pMem, 100) ){ /* P4 */ + assert( p->db->mallocFailed ); + return SQLITE_ERROR; + } + pMem->flags = MEM_Str|MEM_Term; +- pMem->n = 2; +- sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */ +- pMem->enc = SQLITE_UTF8; ++ zP4 = displayP4(pOp, pMem->z, pMem->szMalloc); ++ if( zP4!=pMem->z ){ ++ pMem->n = 0; ++ sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0); ++ }else{ ++ assert( pMem->z!=0 ); ++ pMem->n = sqlite3Strlen30(pMem->z); ++ pMem->enc = SQLITE_UTF8; ++ } + pMem++; +- ++ ++ if( p->explain==1 ){ ++ if( sqlite3VdbeMemClearAndResize(pMem, 4) ){ ++ assert( p->db->mallocFailed ); ++ return SQLITE_ERROR; ++ } ++ pMem->flags = MEM_Str|MEM_Term; ++ pMem->n = 2; ++ sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */ ++ pMem->enc = SQLITE_UTF8; ++ pMem++; ++ + #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS +- if( sqlite3VdbeMemClearAndResize(pMem, 500) ){ +- assert( p->db->mallocFailed ); +- return SQLITE_ERROR; +- } +- pMem->flags = MEM_Str|MEM_Term; +- pMem->n = displayComment(pOp, zP4, pMem->z, 500); +- pMem->enc = SQLITE_UTF8; ++ if( sqlite3VdbeMemClearAndResize(pMem, 500) ){ ++ assert( p->db->mallocFailed ); ++ return SQLITE_ERROR; ++ } ++ pMem->flags = MEM_Str|MEM_Term; ++ pMem->n = displayComment(pOp, zP4, pMem->z, 500); ++ pMem->enc = SQLITE_UTF8; + #else +- pMem->flags = MEM_Null; /* Comment */ ++ pMem->flags = MEM_Null; /* Comment */ + #endif ++ } ++ ++ p->nResColumn = 8 - 4*(p->explain-1); ++ p->pResultSet = &p->aMem[1]; ++ p->rc = SQLITE_OK; ++ rc = SQLITE_ROW; + } +- +- p->nResColumn = 8 - 4*(p->explain-1); +- p->pResultSet = &p->aMem[1]; +- p->rc = SQLITE_OK; +- rc = SQLITE_ROW; + } + return rc; + } +@@ -74148,27 +78126,6 @@ + } + + /* +-** Clean up the VM after a single run. +-*/ +-static void Cleanup(Vdbe *p){ +- sqlite3 *db = p->db; +- +-#ifdef SQLITE_DEBUG +- /* Execute assert() statements to ensure that the Vdbe.apCsr[] and +- ** Vdbe.aMem[] arrays have already been cleaned up. */ +- int i; +- if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 ); +- if( p->aMem ){ +- for(i=0; i<p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined ); +- } +-#endif +- +- sqlite3DbFree(db, p->zErrMsg); +- p->zErrMsg = 0; +- p->pResultSet = 0; +-} +- +-/* + ** Set the number of result columns that will be returned by this SQL + ** statement. This is now set at compile time, rather than during + ** execution of the vdbe program so that sqlite3_column_count() can +@@ -74276,6 +78233,7 @@ + pPager = sqlite3BtreePager(pBt); + if( db->aDb[i].safety_level!=PAGER_SYNCHRONOUS_OFF + && aMJNeeded[sqlite3PagerGetJournalMode(pPager)] ++ && sqlite3PagerIsMemdb(pPager)==0 + ){ + assert( i!=1 ); + nTrans++; +@@ -74876,6 +78834,10 @@ + ** VDBE_MAGIC_INIT. + */ + SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ ++#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) ++ int i; ++#endif ++ + sqlite3 *db; + db = p->db; + +@@ -74885,7 +78847,7 @@ + */ + sqlite3VdbeHalt(p); + +- /* If the VDBE has be run even partially, then transfer the error code ++ /* If the VDBE has been run even partially, then transfer the error code + ** and error message from the VDBE into the main database structure. But + ** if the VDBE has just been set to run but has not actually executed any + ** instructions yet, leave the main database error information unchanged. +@@ -74893,8 +78855,6 @@ + if( p->pc>=0 ){ + vdbeInvokeSqllog(p); + sqlite3VdbeTransferError(p); +- sqlite3DbFree(db, p->zErrMsg); +- p->zErrMsg = 0; + if( p->runOnlyOnce ) p->expired = 1; + }else if( p->rc && p->expired ){ + /* The expired flag was set on the VDBE before the first call +@@ -74902,13 +78862,24 @@ + ** called), set the database error in this case as well. + */ + sqlite3ErrorWithMsg(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg); +- sqlite3DbFree(db, p->zErrMsg); +- p->zErrMsg = 0; + } + +- /* Reclaim all memory used by the VDBE ++ /* Reset register contents and reclaim error message memory. + */ +- Cleanup(p); ++#ifdef SQLITE_DEBUG ++ /* Execute assert() statements to ensure that the Vdbe.apCsr[] and ++ ** Vdbe.aMem[] arrays have already been cleaned up. */ ++ if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 ); ++ if( p->aMem ){ ++ for(i=0; i<p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined ); ++ } ++#endif ++ sqlite3DbFree(db, p->zErrMsg); ++ p->zErrMsg = 0; ++ p->pResultSet = 0; ++#ifdef SQLITE_DEBUG ++ p->nWrite = 0; ++#endif + + /* Save profiling information from this VDBE run. + */ +@@ -74916,7 +78887,6 @@ + { + FILE *out = fopen("vdbe_profile.out", "a"); + if( out ){ +- int i; + fprintf(out, "---- "); + for(i=0; i<p->nOp; i++){ + fprintf(out, "%02x", p->aOp[i].opcode); +@@ -75025,6 +78995,9 @@ + vdbeFreeOpArray(db, p->aOp, p->nOp); + sqlite3DbFree(db, p->aColName); + sqlite3DbFree(db, p->zSql); ++#ifdef SQLITE_ENABLE_NORMALIZE ++ sqlite3DbFree(db, p->zNormSql); ++#endif + #ifdef SQLITE_ENABLE_STMT_SCANSTATUS + { + int i; +@@ -75042,7 +79015,7 @@ + SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){ + sqlite3 *db; + +- if( NEVER(p==0) ) return; ++ assert( p!=0 ); + db = p->db; + assert( sqlite3_mutex_held(db->mutex) ); + sqlite3VdbeClearObject(db, p); +@@ -75129,20 +79102,19 @@ + */ + SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor **pp, int *piCol){ + VdbeCursor *p = *pp; +- if( p->eCurType==CURTYPE_BTREE ){ +- if( p->deferredMoveto ){ +- int iMap; +- if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 ){ +- *pp = p->pAltCursor; +- *piCol = iMap - 1; +- return SQLITE_OK; +- } +- return handleDeferredMoveto(p); ++ assert( p->eCurType==CURTYPE_BTREE || p->eCurType==CURTYPE_PSEUDO ); ++ if( p->deferredMoveto ){ ++ int iMap; ++ if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 ){ ++ *pp = p->pAltCursor; ++ *piCol = iMap - 1; ++ return SQLITE_OK; + } +- if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){ +- return handleMovedCursor(p); +- } ++ return handleDeferredMoveto(p); + } ++ if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){ ++ return handleMovedCursor(p); ++ } + return SQLITE_OK; + } + +@@ -75439,7 +79411,13 @@ + Mem *pMem /* Memory cell to write value into */ + ){ + switch( serial_type ){ +- case 10: /* Reserved for future use */ ++ case 10: { /* Internal use only: NULL with virtual table ++ ** UPDATE no-change flag set */ ++ pMem->flags = MEM_Null|MEM_Zero; ++ pMem->n = 0; ++ pMem->u.nZero = 0; ++ break; ++ } + case 11: /* Reserved for future use */ + case 0: { /* Null */ + /* EVIDENCE-OF: R-24078-09375 Value is a NULL. */ +@@ -75537,13 +79515,13 @@ + ){ + UnpackedRecord *p; /* Unpacked record to return */ + int nByte; /* Number of bytes required for *p */ +- nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nField+1); ++ nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nKeyField+1); + p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte); + if( !p ) return 0; + p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))]; + assert( pKeyInfo->aSortOrder!=0 ); + p->pKeyInfo = pKeyInfo; +- p->nField = pKeyInfo->nField + 1; ++ p->nField = pKeyInfo->nKeyField + 1; + return p; + } + +@@ -75583,7 +79561,7 @@ + pMem++; + if( (++u)>=p->nField ) break; + } +- assert( u<=pKeyInfo->nField + 1 ); ++ assert( u<=pKeyInfo->nKeyField + 1 ); + p->nField = u; + } + +@@ -75632,9 +79610,9 @@ + idx1 = getVarint32(aKey1, szHdr1); + if( szHdr1>98307 ) return SQLITE_CORRUPT; + d1 = szHdr1; +- assert( pKeyInfo->nField+pKeyInfo->nXField>=pPKey2->nField || CORRUPT_DB ); ++ assert( pKeyInfo->nAllField>=pPKey2->nField || CORRUPT_DB ); + assert( pKeyInfo->aSortOrder!=0 ); +- assert( pKeyInfo->nField>0 ); ++ assert( pKeyInfo->nKeyField>0 ); + assert( idx1<=szHdr1 || CORRUPT_DB ); + do{ + u32 serial_type1; +@@ -75696,12 +79674,12 @@ + /* + ** Count the number of fields (a.k.a. columns) in the record given by + ** pKey,nKey. The verify that this count is less than or equal to the +-** limit given by pKeyInfo->nField + pKeyInfo->nXField. ++** limit given by pKeyInfo->nAllField. + ** + ** If this constraint is not satisfied, it means that the high-speed + ** vdbeRecordCompareInt() and vdbeRecordCompareString() routines will + ** not work correctly. If this assert() ever fires, it probably means +-** that the KeyInfo.nField or KeyInfo.nXField values were computed ++** that the KeyInfo.nKeyField or KeyInfo.nAllField values were computed + ** incorrectly. + */ + static void vdbeAssertFieldCountWithinLimits( +@@ -75722,7 +79700,7 @@ + idx += getVarint32(aKey+idx, notUsed); + nField++; + } +- assert( nField <= pKeyInfo->nField+pKeyInfo->nXField ); ++ assert( nField <= pKeyInfo->nAllField ); + } + #else + # define vdbeAssertFieldCountWithinLimits(A,B,C) +@@ -75784,7 +79762,7 @@ + ** is less than, equal to, or greater than the second, respectively. + ** If one blob is a prefix of the other, then the shorter is the lessor. + */ +-static SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem *pB2){ ++SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem *pB2){ + int c; + int n1 = pB1->n; + int n2 = pB2->n; +@@ -75827,13 +79805,10 @@ + i64 y; + double s; + if( r<-9223372036854775808.0 ) return +1; +- if( r>9223372036854775807.0 ) return -1; ++ if( r>=9223372036854775808.0 ) return -1; + y = (i64)r; + if( i<y ) return -1; +- if( i>y ){ +- if( y==SMALLEST_INT64 && r>0.0 ) return -1; +- return +1; +- } ++ if( i>y ) return +1; + s = (double)i; + if( s<r ) return -1; + if( s>r ) return +1; +@@ -75857,7 +79832,7 @@ + f1 = pMem1->flags; + f2 = pMem2->flags; + combined_flags = f1|f2; +- assert( (combined_flags & MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pMem1) && !sqlite3VdbeMemIsRowSet(pMem2) ); + + /* If one value is NULL, it is less than the other. If both values + ** are NULL, return 0. +@@ -76002,7 +79977,7 @@ + u32 idx1; /* Offset of first type in header */ + int rc = 0; /* Return value */ + Mem *pRhs = pPKey2->aMem; /* Next field of pPKey2 to compare */ +- KeyInfo *pKeyInfo = pPKey2->pKeyInfo; ++ KeyInfo *pKeyInfo; + const unsigned char *aKey1 = (const unsigned char *)pKey1; + Mem mem1; + +@@ -76027,10 +80002,10 @@ + } + + VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */ +- assert( pPKey2->pKeyInfo->nField+pPKey2->pKeyInfo->nXField>=pPKey2->nField ++ assert( pPKey2->pKeyInfo->nAllField>=pPKey2->nField + || CORRUPT_DB ); + assert( pPKey2->pKeyInfo->aSortOrder!=0 ); +- assert( pPKey2->pKeyInfo->nField>0 ); ++ assert( pPKey2->pKeyInfo->nKeyField>0 ); + assert( idx1<=szHdr1 || CORRUPT_DB ); + do{ + u32 serial_type; +@@ -76097,7 +80072,7 @@ + if( (d1+mem1.n) > (unsigned)nKey1 ){ + pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT; + return 0; /* Corruption */ +- }else if( pKeyInfo->aColl[i] ){ ++ }else if( (pKeyInfo = pPKey2->pKeyInfo)->aColl[i] ){ + mem1.enc = pKeyInfo->enc; + mem1.db = pKeyInfo->db; + mem1.flags = MEM_Str; +@@ -76148,7 +80123,7 @@ + } + + if( rc!=0 ){ +- if( pKeyInfo->aSortOrder[i] ){ ++ if( pPKey2->pKeyInfo->aSortOrder[i] ){ + rc = -rc; + } + assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, rc) ); +@@ -76157,10 +80132,11 @@ + } + + i++; ++ if( i==pPKey2->nField ) break; + pRhs++; + d1 += sqlite3VdbeSerialTypeLen(serial_type); + idx1 += sqlite3VarintLen(serial_type); +- }while( idx1<(unsigned)szHdr1 && i<pPKey2->nField && d1<=(unsigned)nKey1 ); ++ }while( idx1<(unsigned)szHdr1 && d1<=(unsigned)nKey1 ); + + /* No memory allocation is ever used on mem1. Prove this using + ** the following assert(). If the assert() fails, it indicates a +@@ -76172,7 +80148,7 @@ + ** value. */ + assert( CORRUPT_DB + || vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, pPKey2->default_rc) +- || pKeyInfo->db->mallocFailed ++ || pPKey2->pKeyInfo->db->mallocFailed + ); + pPKey2->eqSeen = 1; + return pPKey2->default_rc; +@@ -76363,7 +80339,7 @@ + ** The easiest way to enforce this limit is to consider only records with + ** 13 fields or less. If the first field is an integer, the maximum legal + ** header size is (12*5 + 1 + 1) bytes. */ +- if( (p->pKeyInfo->nField + p->pKeyInfo->nXField)<=13 ){ ++ if( p->pKeyInfo->nAllField<=13 ){ + int flags = p->aMem[0].flags; + if( p->pKeyInfo->aSortOrder[0] ){ + p->r1 = 1; +@@ -76423,7 +80399,9 @@ + (void)getVarint32((u8*)m.z, szHdr); + testcase( szHdr==3 ); + testcase( szHdr==m.n ); +- if( unlikely(szHdr<3 || (int)szHdr>m.n) ){ ++ testcase( szHdr>0x7fffffff ); ++ assert( m.n>=0 ); ++ if( unlikely(szHdr<3 || szHdr>(unsigned)m.n) ){ + goto idx_rowid_corruption; + } + +@@ -76498,7 +80476,7 @@ + if( rc ){ + return rc; + } +- *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked); ++ *res = sqlite3VdbeRecordCompareWithSkip(m.n, m.z, pUnpacked, 0); + sqlite3VdbeMemRelease(&m); + return SQLITE_OK; + } +@@ -76530,11 +80508,19 @@ + ** programs obsolete. Removing user-defined functions or collating + ** sequences, or changing an authorization function are the types of + ** things that make prepared statements obsolete. ++** ++** If iCode is 1, then expiration is advisory. The statement should ++** be reprepared before being restarted, but if it is already running ++** it is allowed to run to completion. ++** ++** Internally, this function just sets the Vdbe.expired flag on all ++** prepared statements. The flag is set to 1 for an immediate expiration ++** and set to 2 for an advisory expiration. + */ +-SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3 *db){ ++SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3 *db, int iCode){ + Vdbe *p; + for(p = db->pVdbe; p; p=p->pNext){ +- p->expired = 1; ++ p->expired = iCode+1; + } + } + +@@ -76698,7 +80684,7 @@ + preupdate.iNewReg = iReg; + preupdate.keyinfo.db = db; + preupdate.keyinfo.enc = ENC(db); +- preupdate.keyinfo.nField = pTab->nCol; ++ preupdate.keyinfo.nKeyField = pTab->nCol; + preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder; + preupdate.iKey1 = iKey1; + preupdate.iKey2 = iKey2; +@@ -76708,8 +80694,8 @@ + db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2); + db->pPreUpdate = 0; + sqlite3DbFree(db, preupdate.aRecord); +- vdbeFreeUnpacked(db, preupdate.keyinfo.nField+1, preupdate.pUnpacked); +- vdbeFreeUnpacked(db, preupdate.keyinfo.nField+1, preupdate.pNewUnpacked); ++ vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pUnpacked); ++ vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pNewUnpacked); + if( preupdate.aNew ){ + int i; + for(i=0; i<pCsr->nField; i++){ +@@ -76992,6 +80978,11 @@ + return aType[pVal->flags&MEM_AffMask]; + } + ++/* Return true if a parameter to xUpdate represents an unchanged column */ ++SQLITE_API int sqlite3_value_nochange(sqlite3_value *pVal){ ++ return (pVal->flags&(MEM_Null|MEM_Zero))==(MEM_Null|MEM_Zero); ++} ++ + /* Make a copy of an sqlite3_value object + */ + SQLITE_API sqlite3_value *sqlite3_value_dup(const sqlite3_value *pOrig){ +@@ -77091,7 +81082,6 @@ + SQLITE_API void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + pCtx->isError = SQLITE_ERROR; +- pCtx->fErrorOrAux = 1; + sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF8, SQLITE_TRANSIENT); + } + #ifndef SQLITE_OMIT_UTF16 +@@ -77098,7 +81088,6 @@ + SQLITE_API void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + pCtx->isError = SQLITE_ERROR; +- pCtx->fErrorOrAux = 1; + sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT); + } + #endif +@@ -77122,7 +81111,8 @@ + ){ + Mem *pOut = pCtx->pOut; + assert( sqlite3_mutex_held(pOut->db->mutex) ); +- sqlite3VdbeMemSetNull(pOut); ++ sqlite3VdbeMemRelease(pOut); ++ pOut->flags = MEM_Null; + sqlite3VdbeMemSetPointer(pOut, pPtr, zPType, xDestructor); + } + SQLITE_API void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){ +@@ -77203,8 +81193,7 @@ + return SQLITE_OK; + } + SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ +- pCtx->isError = errCode; +- pCtx->fErrorOrAux = 1; ++ pCtx->isError = errCode ? errCode : -1; + #ifdef SQLITE_DEBUG + if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode; + #endif +@@ -77218,7 +81207,6 @@ + SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + pCtx->isError = SQLITE_TOOBIG; +- pCtx->fErrorOrAux = 1; + sqlite3VdbeMemSetStr(pCtx->pOut, "string or blob too big", -1, + SQLITE_UTF8, SQLITE_STATIC); + } +@@ -77228,7 +81216,6 @@ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + sqlite3VdbeMemSetNull(pCtx->pOut); + pCtx->isError = SQLITE_NOMEM_BKPT; +- pCtx->fErrorOrAux = 1; + sqlite3OomFault(pCtx->pOut->db); + } + +@@ -77247,7 +81234,7 @@ + sqlite3BtreeEnter(pBt); + nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt)); + sqlite3BtreeLeave(pBt); +- if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){ ++ if( nEntry>0 && db->xWalCallback && rc==SQLITE_OK ){ + rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zDbSName, nEntry); + } + } +@@ -77357,7 +81344,7 @@ + if( rc!=SQLITE_ROW ) checkProfileCallback(db, p); + #endif + +- if( rc==SQLITE_DONE ){ ++ if( rc==SQLITE_DONE && db->autoCommit ){ + assert( p->rc==SQLITE_OK ); + p->rc = doWalCallbacks(db); + if( p->rc!=SQLITE_OK ){ +@@ -77401,7 +81388,6 @@ + */ + SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){ + int rc = SQLITE_OK; /* Result from sqlite3Step() */ +- int rc2 = SQLITE_OK; /* Result from sqlite3Reprepare() */ + Vdbe *v = (Vdbe*)pStmt; /* the prepared statement */ + int cnt = 0; /* Counter to prevent infinite loop of reprepares */ + sqlite3 *db; /* The database connection */ +@@ -77415,32 +81401,31 @@ + while( (rc = sqlite3Step(v))==SQLITE_SCHEMA + && cnt++ < SQLITE_MAX_SCHEMA_RETRY ){ + int savedPc = v->pc; +- rc2 = rc = sqlite3Reprepare(v); +- if( rc!=SQLITE_OK) break; ++ rc = sqlite3Reprepare(v); ++ if( rc!=SQLITE_OK ){ ++ /* This case occurs after failing to recompile an sql statement. ++ ** The error message from the SQL compiler has already been loaded ++ ** into the database handle. This block copies the error message ++ ** from the database handle into the statement and sets the statement ++ ** program counter to 0 to ensure that when the statement is ++ ** finalized or reset the parser error message is available via ++ ** sqlite3_errmsg() and sqlite3_errcode(). ++ */ ++ const char *zErr = (const char *)sqlite3_value_text(db->pErr); ++ sqlite3DbFree(db, v->zErrMsg); ++ if( !db->mallocFailed ){ ++ v->zErrMsg = sqlite3DbStrDup(db, zErr); ++ v->rc = rc = sqlite3ApiExit(db, rc); ++ } else { ++ v->zErrMsg = 0; ++ v->rc = rc = SQLITE_NOMEM_BKPT; ++ } ++ break; ++ } + sqlite3_reset(pStmt); + if( savedPc>=0 ) v->doingRerun = 1; + assert( v->expired==0 ); + } +- if( rc2!=SQLITE_OK ){ +- /* This case occurs after failing to recompile an sql statement. +- ** The error message from the SQL compiler has already been loaded +- ** into the database handle. This block copies the error message +- ** from the database handle into the statement and sets the statement +- ** program counter to 0 to ensure that when the statement is +- ** finalized or reset the parser error message is available via +- ** sqlite3_errmsg() and sqlite3_errcode(). +- */ +- const char *zErr = (const char *)sqlite3_value_text(db->pErr); +- sqlite3DbFree(db, v->zErrMsg); +- if( !db->mallocFailed ){ +- v->zErrMsg = sqlite3DbStrDup(db, zErr); +- v->rc = rc2; +- } else { +- v->zErrMsg = 0; +- v->rc = rc = SQLITE_NOMEM_BKPT; +- } +- } +- rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; + } +@@ -77471,6 +81456,25 @@ + } + + /* ++** If this routine is invoked from within an xColumn method of a virtual ++** table, then it returns true if and only if the the call is during an ++** UPDATE operation and the value of the column will not be modified ++** by the UPDATE. ++** ++** If this routine is called from any context other than within the ++** xColumn method of a virtual table, then the return value is meaningless ++** and arbitrary. ++** ++** Virtual table implements might use this routine to optimize their ++** performance by substituting a NULL result, or some other light-weight ++** value, as a signal to the xUpdate routine that the column is unchanged. ++*/ ++SQLITE_API int sqlite3_vtab_nochange(sqlite3_context *p){ ++ assert( p ); ++ return sqlite3_value_nochange(p->pOut); ++} ++ ++/* + ** Return the current time for a statement. If the current time + ** is requested more than once within the same run of a single prepared + ** statement, the exact same time is returned for each invocation regardless +@@ -77494,28 +81498,6 @@ + } + + /* +-** The following is the implementation of an SQL function that always +-** fails with an error message stating that the function is used in the +-** wrong context. The sqlite3_overload_function() API might construct +-** SQL function that use this routine so that the functions will exist +-** for name resolution but are actually overloaded by the xFindFunction +-** method of virtual tables. +-*/ +-SQLITE_PRIVATE void sqlite3InvalidFunction( +- sqlite3_context *context, /* The function calling context */ +- int NotUsed, /* Number of arguments to the function */ +- sqlite3_value **NotUsed2 /* Value of each argument */ +-){ +- const char *zName = context->pFunc->zName; +- char *zErr; +- UNUSED_PARAMETER2(NotUsed, NotUsed2); +- zErr = sqlite3_mprintf( +- "unable to use function %s in the requested context", zName); +- sqlite3_result_error(context, zErr, -1); +- sqlite3_free(zErr); +-} +- +-/* + ** Create a new aggregate context for p and return a pointer to + ** its pMem->z element. + */ +@@ -77618,10 +81600,7 @@ + pAuxData->iAuxArg = iArg; + pAuxData->pNextAux = pVdbe->pAuxData; + pVdbe->pAuxData = pAuxData; +- if( pCtx->fErrorOrAux==0 ){ +- pCtx->isError = 0; +- pCtx->fErrorOrAux = 1; +- } ++ if( pCtx->isError==0 ) pCtx->isError = -1; + }else if( pAuxData->xDeleteAux ){ + pAuxData->xDeleteAux(pAuxData->pAux); + } +@@ -77701,7 +81680,7 @@ + /* .xDel = */ (void(*)(void*))0, + #ifdef SQLITE_DEBUG + /* .pScopyFrom = */ (Mem*)0, +- /* .pFiller = */ (void*)0, ++ /* .mScopyFlags= */ 0, + #endif + }; + return &nullMem; +@@ -78377,7 +82356,9 @@ + Vdbe *pVdbe = (Vdbe*)pStmt; + u32 v; + #ifdef SQLITE_ENABLE_API_ARMOR +- if( !pStmt ){ ++ if( !pStmt ++ || (op!=SQLITE_STMTSTATUS_MEMUSED && (op<0||op>=ArraySize(pVdbe->aCounter))) ++ ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +@@ -78431,6 +82412,16 @@ + #endif + } + ++#ifdef SQLITE_ENABLE_NORMALIZE ++/* ++** Return the normalized SQL associated with a prepared statement. ++*/ ++SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt){ ++ Vdbe *p = (Vdbe *)pStmt; ++ return p ? p->zNormSql : 0; ++} ++#endif /* SQLITE_ENABLE_NORMALIZE */ ++ + #ifdef SQLITE_ENABLE_PREUPDATE_HOOK + /* + ** Allocate and populate an UnpackedRecord structure based on the serialized +@@ -78446,7 +82437,7 @@ + + pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo); + if( pRet ){ +- memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nField+1)); ++ memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nKeyField+1)); + sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, pRet); + } + return pRet; +@@ -78519,7 +82510,7 @@ + */ + SQLITE_API int sqlite3_preupdate_count(sqlite3 *db){ + PreUpdate *p = db->pPreUpdate; +- return (p ? p->keyinfo.nField : 0); ++ return (p ? p->keyinfo.nKeyField : 0); + } + #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ + +@@ -78772,7 +82763,7 @@ + Mem *pVar; /* Value of a host parameter */ + StrAccum out; /* Accumulate the output here */ + #ifndef SQLITE_OMIT_UTF16 +- Mem utf8; /* Used to convert UTF16 parameters into UTF8 for display */ ++ Mem utf8; /* Used to convert UTF16 into UTF8 for display */ + #endif + char zBase[100]; /* Initial working space */ + +@@ -78783,17 +82774,17 @@ + while( *zRawSql ){ + const char *zStart = zRawSql; + while( *(zRawSql++)!='\n' && *zRawSql ); +- sqlite3StrAccumAppend(&out, "-- ", 3); ++ sqlite3_str_append(&out, "-- ", 3); + assert( (zRawSql - zStart) > 0 ); +- sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart)); ++ sqlite3_str_append(&out, zStart, (int)(zRawSql-zStart)); + } + }else if( p->nVar==0 ){ +- sqlite3StrAccumAppend(&out, zRawSql, sqlite3Strlen30(zRawSql)); ++ sqlite3_str_append(&out, zRawSql, sqlite3Strlen30(zRawSql)); + }else{ + while( zRawSql[0] ){ + n = findNextHostParameter(zRawSql, &nToken); + assert( n>0 ); +- sqlite3StrAccumAppend(&out, zRawSql, n); ++ sqlite3_str_append(&out, zRawSql, n); + zRawSql += n; + assert( zRawSql[0] || nToken==0 ); + if( nToken==0 ) break; +@@ -78819,11 +82810,11 @@ + assert( idx>0 && idx<=p->nVar ); + pVar = &p->aVar[idx-1]; + if( pVar->flags & MEM_Null ){ +- sqlite3StrAccumAppend(&out, "NULL", 4); ++ sqlite3_str_append(&out, "NULL", 4); + }else if( pVar->flags & MEM_Int ){ +- sqlite3XPrintf(&out, "%lld", pVar->u.i); ++ sqlite3_str_appendf(&out, "%lld", pVar->u.i); + }else if( pVar->flags & MEM_Real ){ +- sqlite3XPrintf(&out, "%!.15g", pVar->u.r); ++ sqlite3_str_appendf(&out, "%!.15g", pVar->u.r); + }else if( pVar->flags & MEM_Str ){ + int nOut; /* Number of bytes of the string text to include in output */ + #ifndef SQLITE_OMIT_UTF16 +@@ -78833,7 +82824,7 @@ + utf8.db = db; + sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC); + if( SQLITE_NOMEM==sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8) ){ +- out.accError = STRACCUM_NOMEM; ++ out.accError = SQLITE_NOMEM; + out.nAlloc = 0; + } + pVar = &utf8; +@@ -78846,10 +82837,10 @@ + while( nOut<pVar->n && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; } + } + #endif +- sqlite3XPrintf(&out, "'%.*q'", nOut, pVar->z); ++ sqlite3_str_appendf(&out, "'%.*q'", nOut, pVar->z); + #ifdef SQLITE_TRACE_SIZE_LIMIT + if( nOut<pVar->n ){ +- sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut); ++ sqlite3_str_appendf(&out, "/*+%d bytes*/", pVar->n-nOut); + } + #endif + #ifndef SQLITE_OMIT_UTF16 +@@ -78856,28 +82847,28 @@ + if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8); + #endif + }else if( pVar->flags & MEM_Zero ){ +- sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero); ++ sqlite3_str_appendf(&out, "zeroblob(%d)", pVar->u.nZero); + }else{ + int nOut; /* Number of bytes of the blob to include in output */ + assert( pVar->flags & MEM_Blob ); +- sqlite3StrAccumAppend(&out, "x'", 2); ++ sqlite3_str_append(&out, "x'", 2); + nOut = pVar->n; + #ifdef SQLITE_TRACE_SIZE_LIMIT + if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT; + #endif + for(i=0; i<nOut; i++){ +- sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff); ++ sqlite3_str_appendf(&out, "%02x", pVar->z[i]&0xff); + } +- sqlite3StrAccumAppend(&out, "'", 1); ++ sqlite3_str_append(&out, "'", 1); + #ifdef SQLITE_TRACE_SIZE_LIMIT + if( nOut<pVar->n ){ +- sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut); ++ sqlite3_str_appendf(&out, "/*+%d bytes*/", pVar->n-nOut); + } + #endif + } + } + } +- if( out.accError ) sqlite3StrAccumReset(&out); ++ if( out.accError ) sqlite3_str_reset(&out); + return sqlite3StrAccumFinish(&out); + } + +@@ -79009,32 +83000,56 @@ + ** feature is used for test suite validation only and does not appear an + ** production builds. + ** +-** M is an integer, 2 or 3, that indices how many different ways the +-** branch can go. It is usually 2. "I" is the direction the branch +-** goes. 0 means falls through. 1 means branch is taken. 2 means the +-** second alternative branch is taken. ++** M is an integer between 2 and 4. 2 indicates a ordinary two-way ++** branch (I=0 means fall through and I=1 means taken). 3 indicates ++** a 3-way branch where the third way is when one of the operands is ++** NULL. 4 indicates the OP_Jump instruction which has three destinations ++** depending on whether the first operand is less than, equal to, or greater ++** than the second. + ** + ** iSrcLine is the source code line (from the __LINE__ macro) that +-** generated the VDBE instruction. This instrumentation assumes that all +-** source code is in a single file (the amalgamation). Special values 1 +-** and 2 for the iSrcLine parameter mean that this particular branch is +-** always taken or never taken, respectively. ++** generated the VDBE instruction combined with flag bits. The source ++** code line number is in the lower 24 bits of iSrcLine and the upper ++** 8 bytes are flags. The lower three bits of the flags indicate ++** values for I that should never occur. For example, if the branch is ++** always taken, the flags should be 0x05 since the fall-through and ++** alternate branch are never taken. If a branch is never taken then ++** flags should be 0x06 since only the fall-through approach is allowed. ++** ++** Bit 0x04 of the flags indicates an OP_Jump opcode that is only ++** interested in equal or not-equal. In other words, I==0 and I==2 ++** should be treated the same. ++** ++** Since only a line number is retained, not the filename, this macro ++** only works for amalgamation builds. But that is ok, since these macros ++** should be no-ops except for special builds used to measure test coverage. + */ + #if !defined(SQLITE_VDBE_COVERAGE) + # define VdbeBranchTaken(I,M) + #else + # define VdbeBranchTaken(I,M) vdbeTakeBranch(pOp->iSrcLine,I,M) +- static void vdbeTakeBranch(int iSrcLine, u8 I, u8 M){ +- if( iSrcLine<=2 && ALWAYS(iSrcLine>0) ){ +- M = iSrcLine; +- /* Assert the truth of VdbeCoverageAlwaysTaken() and +- ** VdbeCoverageNeverTaken() */ +- assert( (M & I)==I ); +- }else{ +- if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/ +- sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg, +- iSrcLine,I,M); ++ static void vdbeTakeBranch(u32 iSrcLine, u8 I, u8 M){ ++ u8 mNever; ++ assert( I<=2 ); /* 0: fall through, 1: taken, 2: alternate taken */ ++ assert( M<=4 ); /* 2: two-way branch, 3: three-way branch, 4: OP_Jump */ ++ assert( I<M ); /* I can only be 2 if M is 3 or 4 */ ++ /* Transform I from a integer [0,1,2] into a bitmask of [1,2,4] */ ++ I = 1<<I; ++ /* The upper 8 bits of iSrcLine are flags. The lower three bits of ++ ** the flags indicate directions that the branch can never go. If ++ ** a branch really does go in one of those directions, assert right ++ ** away. */ ++ mNever = iSrcLine >> 24; ++ assert( (I & mNever)==0 ); ++ if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/ ++ I |= mNever; ++ if( M==2 ) I |= 0x04; ++ if( M==4 ){ ++ I |= 0x08; ++ if( (mNever&0x08)!=0 && (I&0x05)!=0) I |= 0x05; /*NO_TEST*/ + } ++ sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg, ++ iSrcLine&0xffffff, I, M); + } + #endif + +@@ -79151,6 +83166,11 @@ + pRec->flags |= MEM_Real; + if( bTryForInt ) sqlite3VdbeIntegerAffinity(pRec); + } ++ /* TEXT->NUMERIC is many->one. Hence, it is important to invalidate the ++ ** string representation after computing a numeric equivalent, because the ++ ** string representation might not be the canonical representation for the ++ ** numeric value. Ticket [343634942dd54ab57b7024] 2018-01-31. */ ++ pRec->flags &= ~MEM_Str; + } + + /* +@@ -79241,7 +83261,7 @@ + if( sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc)==0 ){ + return 0; + } +- if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==SQLITE_OK ){ ++ if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==0 ){ + return MEM_Int; + } + return MEM_Real; +@@ -79351,7 +83371,7 @@ + if( p->flags & MEM_Undefined ){ + printf(" undefined"); + }else if( p->flags & MEM_Null ){ +- printf(" NULL"); ++ printf(p->flags & MEM_Zero ? " NULL-nochng" : " NULL"); + }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ + printf(" si:%lld", p->u.i); + }else if( p->flags & MEM_Int ){ +@@ -79360,7 +83380,7 @@ + }else if( p->flags & MEM_Real ){ + printf(" r:%g", p->u.r); + #endif +- }else if( p->flags & MEM_RowSet ){ ++ }else if( sqlite3VdbeMemIsRowSet(p) ){ + printf(" (rowset)"); + }else{ + char zBuf[200]; +@@ -79619,7 +83639,7 @@ + + assert( pOp>=aOp && pOp<&aOp[p->nOp]); + #ifdef VDBE_PROFILE +- start = sqlite3Hwtime(); ++ start = sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime(); + #endif + nVmStep++; + #ifdef SQLITE_ENABLE_STMT_SCANSTATUS +@@ -79886,6 +83906,9 @@ + */ + case OP_HaltIfNull: { /* in3 */ + pIn3 = &aMem[pOp->p3]; ++#ifdef SQLITE_DEBUG ++ if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); } ++#endif + if( (pIn3->flags & MEM_Null)==0 ) break; + /* Fall through into OP_Halt */ + } +@@ -79925,6 +83948,9 @@ + int pcx; + + pcx = (int)(pOp - aOp); ++#ifdef SQLITE_DEBUG ++ if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); } ++#endif + if( pOp->p1==SQLITE_OK && p->pFrame ){ + /* Halt the sub-program. Return control to the parent frame. */ + pFrame = p->pFrame; +@@ -80108,6 +84134,9 @@ + assert( pOp->p3<=(p->nMem+1 - p->nCursor) ); + pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null; + pOut->n = 0; ++#ifdef SQLITE_DEBUG ++ pOut->uTemp = 0; ++#endif + while( cnt>0 ){ + pOut++; + memAboutToChange(p, pOut); +@@ -80229,6 +84258,7 @@ + pOut = &aMem[pOp->p2]; + assert( pOut!=pIn1 ); + while( 1 ){ ++ memAboutToChange(p, pOut); + sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); + Deephemeralize(pOut); + #ifdef SQLITE_DEBUG +@@ -80261,7 +84291,8 @@ + assert( pOut!=pIn1 ); + sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); + #ifdef SQLITE_DEBUG +- if( pOut->pScopyFrom==0 ) pOut->pScopyFrom = pIn1; ++ pOut->pScopyFrom = pIn1; ++ pOut->mScopyFlags = pIn1->flags; + #endif + break; + } +@@ -80895,7 +84926,12 @@ + if( (flags1 | flags3)&MEM_Str ){ + if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ + applyNumericAffinity(pIn1,0); +- testcase( flags3!=pIn3->flags ); /* Possible if pIn1==pIn3 */ ++ assert( flags3==pIn3->flags ); ++ /* testcase( flags3!=pIn3->flags ); ++ ** this used to be possible with pIn1==pIn3, but not since ++ ** the column cache was removed. The following assignment ++ ** is essentially a no-op. But, it provides defense-in-depth ++ ** in case our analysis is incorrect, so it is left in. */ + flags3 = pIn3->flags; + } + if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ +@@ -80931,13 +84967,23 @@ + res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl); + } + compare_op: +- switch( pOp->opcode ){ +- case OP_Eq: res2 = res==0; break; +- case OP_Ne: res2 = res; break; +- case OP_Lt: res2 = res<0; break; +- case OP_Le: res2 = res<=0; break; +- case OP_Gt: res2 = res>0; break; +- default: res2 = res>=0; break; ++ /* At this point, res is negative, zero, or positive if reg[P1] is ++ ** less than, equal to, or greater than reg[P3], respectively. Compute ++ ** the answer to this operator in res2, depending on what the comparison ++ ** operator actually is. The next block of code depends on the fact ++ ** that the 6 comparison operators are consecutive integers in this ++ ** order: NE, EQ, GT, LE, LT, GE */ ++ assert( OP_Eq==OP_Ne+1 ); assert( OP_Gt==OP_Ne+2 ); assert( OP_Le==OP_Ne+3 ); ++ assert( OP_Lt==OP_Ne+4 ); assert( OP_Ge==OP_Ne+5 ); ++ if( res<0 ){ /* ne, eq, gt, le, lt, ge */ ++ static const unsigned char aLTb[] = { 1, 0, 0, 1, 1, 0 }; ++ res2 = aLTb[pOp->opcode - OP_Ne]; ++ }else if( res==0 ){ ++ static const unsigned char aEQb[] = { 0, 1, 0, 1, 0, 1 }; ++ res2 = aEQb[pOp->opcode - OP_Ne]; ++ }else{ ++ static const unsigned char aGTb[] = { 1, 0, 1, 0, 0, 1 }; ++ res2 = aGTb[pOp->opcode - OP_Ne]; + } + + /* Undo any changes made by applyAffinity() to the input registers. */ +@@ -80949,7 +84995,6 @@ + if( pOp->p5 & SQLITE_STOREP2 ){ + pOut = &aMem[pOp->p2]; + iCompare = res; +- res2 = res2!=0; /* For this path res2 must be exactly 0 or 1 */ + if( (pOp->p5 & SQLITE_KEEPNULL)!=0 ){ + /* The KEEPNULL flag prevents OP_Eq from overwriting a NULL with 1 + ** and prevents OP_Ne from overwriting NULL with 0. This flag +@@ -81080,7 +85125,7 @@ + assert( memIsValid(&aMem[p2+idx]) ); + REGISTER_TRACE(p1+idx, &aMem[p1+idx]); + REGISTER_TRACE(p2+idx, &aMem[p2+idx]); +- assert( i<pKeyInfo->nField ); ++ assert( i<pKeyInfo->nKeyField ); + pColl = pKeyInfo->aColl[i]; + bRev = pKeyInfo->aSortOrder[i]; + iCompare = sqlite3MemCompare(&aMem[p1+idx], &aMem[p2+idx], pColl); +@@ -81100,11 +85145,11 @@ + */ + case OP_Jump: { /* jump */ + if( iCompare<0 ){ +- VdbeBranchTaken(0,3); pOp = &aOp[pOp->p1 - 1]; ++ VdbeBranchTaken(0,4); pOp = &aOp[pOp->p1 - 1]; + }else if( iCompare==0 ){ +- VdbeBranchTaken(1,3); pOp = &aOp[pOp->p2 - 1]; ++ VdbeBranchTaken(1,4); pOp = &aOp[pOp->p2 - 1]; + }else{ +- VdbeBranchTaken(2,3); pOp = &aOp[pOp->p3 - 1]; ++ VdbeBranchTaken(2,4); pOp = &aOp[pOp->p3 - 1]; + } + break; + } +@@ -81134,18 +85179,8 @@ + int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ + int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ + +- pIn1 = &aMem[pOp->p1]; +- if( pIn1->flags & MEM_Null ){ +- v1 = 2; +- }else{ +- v1 = sqlite3VdbeIntValue(pIn1)!=0; +- } +- pIn2 = &aMem[pOp->p2]; +- if( pIn2->flags & MEM_Null ){ +- v2 = 2; +- }else{ +- v2 = sqlite3VdbeIntValue(pIn2)!=0; +- } ++ v1 = sqlite3VdbeBooleanValue(&aMem[pOp->p1], 2); ++ v2 = sqlite3VdbeBooleanValue(&aMem[pOp->p2], 2); + if( pOp->opcode==OP_And ){ + static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 }; + v1 = and_logic[v1*3+v2]; +@@ -81163,6 +85198,35 @@ + break; + } + ++/* Opcode: IsTrue P1 P2 P3 P4 * ++** Synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 ++** ++** This opcode implements the IS TRUE, IS FALSE, IS NOT TRUE, and ++** IS NOT FALSE operators. ++** ++** Interpret the value in register P1 as a boolean value. Store that ++** boolean (a 0 or 1) in register P2. Or if the value in register P1 is ++** NULL, then the P3 is stored in register P2. Invert the answer if P4 ++** is 1. ++** ++** The logic is summarized like this: ++** ++** <ul> ++** <li> If P3==0 and P4==0 then r[P2] := r[P1] IS TRUE ++** <li> If P3==1 and P4==1 then r[P2] := r[P1] IS FALSE ++** <li> If P3==0 and P4==1 then r[P2] := r[P1] IS NOT TRUE ++** <li> If P3==1 and P4==0 then r[P2] := r[P1] IS NOT FALSE ++** </ul> ++*/ ++case OP_IsTrue: { /* in1, out2 */ ++ assert( pOp->p4type==P4_INT32 ); ++ assert( pOp->p4.i==0 || pOp->p4.i==1 ); ++ assert( pOp->p3==0 || pOp->p3==1 ); ++ sqlite3VdbeMemSetInt64(&aMem[pOp->p2], ++ sqlite3VdbeBooleanValue(&aMem[pOp->p1], pOp->p3) ^ pOp->p4.i); ++ break; ++} ++ + /* Opcode: Not P1 P2 * * * + ** Synopsis: r[P2]= !r[P1] + ** +@@ -81173,16 +85237,16 @@ + case OP_Not: { /* same as TK_NOT, in1, out2 */ + pIn1 = &aMem[pOp->p1]; + pOut = &aMem[pOp->p2]; +- sqlite3VdbeMemSetNull(pOut); + if( (pIn1->flags & MEM_Null)==0 ){ +- pOut->flags = MEM_Int; +- pOut->u.i = !sqlite3VdbeIntValue(pIn1); ++ sqlite3VdbeMemSetInt64(pOut, !sqlite3VdbeBooleanValue(pIn1,0)); ++ }else{ ++ sqlite3VdbeMemSetNull(pOut); + } + break; + } + + /* Opcode: BitNot P1 P2 * * * +-** Synopsis: r[P1]= ~r[P1] ++** Synopsis: r[P2]= ~r[P1] + ** + ** Interpret the content of register P1 as an integer. Store the + ** ones-complement of the P1 value into register P2. If P1 holds +@@ -81243,6 +85307,14 @@ + ** is considered true if it is numeric and non-zero. If the value + ** in P1 is NULL then take the jump if and only if P3 is non-zero. + */ ++case OP_If: { /* jump, in1 */ ++ int c; ++ c = sqlite3VdbeBooleanValue(&aMem[pOp->p1], pOp->p3); ++ VdbeBranchTaken(c!=0, 2); ++ if( c ) goto jump_to_p2; ++ break; ++} ++ + /* Opcode: IfNot P1 P2 P3 * * + ** + ** Jump to P2 if the value in register P1 is False. The value +@@ -81249,24 +85321,11 @@ + ** is considered false if it has a numeric value of zero. If the value + ** in P1 is NULL then take the jump if and only if P3 is non-zero. + */ +-case OP_If: /* jump, in1 */ + case OP_IfNot: { /* jump, in1 */ + int c; +- pIn1 = &aMem[pOp->p1]; +- if( pIn1->flags & MEM_Null ){ +- c = pOp->p3; +- }else{ +-#ifdef SQLITE_OMIT_FLOATING_POINT +- c = sqlite3VdbeIntValue(pIn1)!=0; +-#else +- c = sqlite3VdbeRealValue(pIn1)!=0.0; +-#endif +- if( pOp->opcode==OP_IfNot ) c = !c; +- } ++ c = !sqlite3VdbeBooleanValue(&aMem[pOp->p1], !pOp->p3); + VdbeBranchTaken(c!=0, 2); +- if( c ){ +- goto jump_to_p2; +- } ++ if( c ) goto jump_to_p2; + break; + } + +@@ -81316,6 +85375,36 @@ + break; + } + ++#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC ++/* Opcode: Offset P1 P2 P3 * * ++** Synopsis: r[P3] = sqlite_offset(P1) ++** ++** Store in register r[P3] the byte offset into the database file that is the ++** start of the payload for the record at which that cursor P1 is currently ++** pointing. ++** ++** P2 is the column number for the argument to the sqlite_offset() function. ++** This opcode does not use P2 itself, but the P2 value is used by the ++** code generator. The P1, P2, and P3 operands to this opcode are the ++** same as for OP_Column. ++** ++** This opcode is only available if SQLite is compiled with the ++** -DSQLITE_ENABLE_OFFSET_SQL_FUNC option. ++*/ ++case OP_Offset: { /* out3 */ ++ VdbeCursor *pC; /* The VDBE cursor */ ++ assert( pOp->p1>=0 && pOp->p1<p->nCursor ); ++ pC = p->apCsr[pOp->p1]; ++ pOut = &p->aMem[pOp->p3]; ++ if( NEVER(pC==0) || pC->eCurType!=CURTYPE_BTREE ){ ++ sqlite3VdbeMemSetNull(pOut); ++ }else{ ++ sqlite3VdbeMemSetInt64(pOut, sqlite3BtreeOffset(pC->uc.pCursor)); ++ } ++ break; ++} ++#endif /* SQLITE_ENABLE_OFFSET_SQL_FUNC */ ++ + /* Opcode: Column P1 P2 P3 P4 P5 + ** Synopsis: r[P3]=PX + ** +@@ -81353,9 +85442,7 @@ + const u8 *zData; /* Part of the record being decoded */ + const u8 *zHdr; /* Next unparsed byte of the header */ + const u8 *zEndHdr; /* Pointer to first byte after the header */ +- u32 offset; /* Offset into the data */ + u64 offset64; /* 64-bit offset */ +- u32 avail; /* Number of bytes of available data */ + u32 t; /* A type code from the record header */ + Mem *pReg; /* PseudoTable input register */ + +@@ -81382,11 +85469,13 @@ + if( pC->cacheStatus!=p->cacheCtr ){ /*OPTIMIZATION-IF-FALSE*/ + if( pC->nullRow ){ + if( pC->eCurType==CURTYPE_PSEUDO ){ +- assert( pC->uc.pseudoTableReg>0 ); +- pReg = &aMem[pC->uc.pseudoTableReg]; ++ /* For the special case of as pseudo-cursor, the seekResult field ++ ** identifies the register that holds the record */ ++ assert( pC->seekResult>0 ); ++ pReg = &aMem[pC->seekResult]; + assert( pReg->flags & MEM_Blob ); + assert( memIsValid(pReg) ); +- pC->payloadSize = pC->szRow = avail = pReg->n; ++ pC->payloadSize = pC->szRow = pReg->n; + pC->aRow = (u8*)pReg->z; + }else{ + sqlite3VdbeMemSetNull(pDest); +@@ -81398,23 +85487,19 @@ + assert( pCrsr ); + assert( sqlite3BtreeCursorIsValid(pCrsr) ); + pC->payloadSize = sqlite3BtreePayloadSize(pCrsr); +- pC->aRow = sqlite3BtreePayloadFetch(pCrsr, &avail); +- assert( avail<=65536 ); /* Maximum page size is 64KiB */ +- if( pC->payloadSize <= (u32)avail ){ +- pC->szRow = pC->payloadSize; +- }else if( pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ ++ pC->aRow = sqlite3BtreePayloadFetch(pCrsr, &pC->szRow); ++ assert( pC->szRow<=pC->payloadSize ); ++ assert( pC->szRow<=65536 ); /* Maximum page size is 64KiB */ ++ if( pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ + goto too_big; +- }else{ +- pC->szRow = avail; + } + } + pC->cacheStatus = p->cacheCtr; +- pC->iHdrOffset = getVarint32(pC->aRow, offset); ++ pC->iHdrOffset = getVarint32(pC->aRow, aOffset[0]); + pC->nHdrParsed = 0; +- aOffset[0] = offset; + + +- if( avail<offset ){ /*OPTIMIZATION-IF-FALSE*/ ++ if( pC->szRow<aOffset[0] ){ /*OPTIMIZATION-IF-FALSE*/ + /* pC->aRow does not have to hold the entire row, but it does at least + ** need to cover the header of the record. If pC->aRow does not contain + ** the complete header, then set it to zero, forcing the header to be +@@ -81431,17 +85516,26 @@ + ** 3-byte type for each of the maximum of 32768 columns plus three + ** extra bytes for the header length itself. 32768*3 + 3 = 98307. + */ +- if( offset > 98307 || offset > pC->payloadSize ){ +- rc = SQLITE_CORRUPT_BKPT; +- goto abort_due_to_error; ++ if( aOffset[0] > 98307 || aOffset[0] > pC->payloadSize ){ ++ goto op_column_corrupt; + } +- }else if( offset>0 ){ /*OPTIMIZATION-IF-TRUE*/ +- /* The following goto is an optimization. It can be omitted and +- ** everything will still work. But OP_Column is measurably faster +- ** by skipping the subsequent conditional, which is always true. ++ }else{ ++ /* This is an optimization. By skipping over the first few tests ++ ** (ex: pC->nHdrParsed<=p2) in the next section, we achieve a ++ ** measurable performance gain. ++ ** ++ ** This branch is taken even if aOffset[0]==0. Such a record is never ++ ** generated by SQLite, and could be considered corruption, but we ++ ** accept it for historical reasons. When aOffset[0]==0, the code this ++ ** branch jumps to reads past the end of the record, but never more ++ ** than a few bytes. Even if the record occurs at the end of the page ++ ** content area, the "page header" comes after the page content and so ++ ** this overread is harmless. Similar overreads can occur for a corrupt ++ ** database file. + */ + zData = pC->aRow; + assert( pC->nHdrParsed<=p2 ); /* Conditional skipped */ ++ testcase( aOffset[0]==0 ); + goto op_column_read_header; + } + } +@@ -81470,6 +85564,7 @@ + offset64 = aOffset[i]; + zHdr = zData + pC->iHdrOffset; + zEndHdr = zData + aOffset[0]; ++ testcase( zHdr>=zEndHdr ); + do{ + if( (t = zHdr[0])<0x80 ){ + zHdr++; +@@ -81490,9 +85585,13 @@ + if( (zHdr>=zEndHdr && (zHdr>zEndHdr || offset64!=pC->payloadSize)) + || (offset64 > pC->payloadSize) + ){ +- if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem); +- rc = SQLITE_CORRUPT_BKPT; +- goto abort_due_to_error; ++ if( aOffset[0]==0 ){ ++ i = 0; ++ zHdr = zEndHdr; ++ }else{ ++ if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem); ++ goto op_column_corrupt; ++ } + } + + pC->nHdrParsed = i; +@@ -81586,6 +85685,15 @@ + UPDATE_MAX_BLOBSIZE(pDest); + REGISTER_TRACE(pOp->p3, pDest); + break; ++ ++op_column_corrupt: ++ if( aOp[0].p3>0 ){ ++ pOp = &aOp[aOp[0].p3-1]; ++ break; ++ }else{ ++ rc = SQLITE_CORRUPT_BKPT; ++ goto abort_due_to_error; ++ } + } + + /* Opcode: Affinity P1 P2 * P4 * +@@ -81710,9 +85818,18 @@ + pRec = pLast; + do{ + assert( memIsValid(pRec) ); +- pRec->uTemp = serial_type = sqlite3VdbeSerialType(pRec, file_format, &len); ++ serial_type = sqlite3VdbeSerialType(pRec, file_format, &len); + if( pRec->flags & MEM_Zero ){ +- if( nData ){ ++ if( serial_type==0 ){ ++ /* Values with MEM_Null and MEM_Zero are created by xColumn virtual ++ ** table methods that never invoke sqlite3_result_xxxxx() while ++ ** computing an unchanging column value in an UPDATE statement. ++ ** Give such values a special internal-use-only serial-type of 10 ++ ** so that they can be passed through to xUpdate and have ++ ** a true sqlite3_value_nochange(). */ ++ assert( pOp->p5==OPFLAG_NOCHNG_MAGIC || CORRUPT_DB ); ++ serial_type = 10; ++ }else if( nData ){ + if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem; + }else{ + nZero += pRec->u.nZero; +@@ -81723,6 +85840,7 @@ + testcase( serial_type==127 ); + testcase( serial_type==128 ); + nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type); ++ pRec->uTemp = serial_type; + if( pRec==pData0 ) break; + pRec--; + }while(1); +@@ -81743,9 +85861,6 @@ + if( nVarint<sqlite3VarintLen(nHdr) ) nHdr++; + } + nByte = nHdr+nData; +- if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){ +- goto too_big; +- } + + /* Make sure the output register has a buffer large enough to store + ** the new record. The output register (pOp->p3) is not allowed to +@@ -81752,8 +85867,19 @@ + ** be one of the input registers (because the following call to + ** sqlite3VdbeMemClearAndResize() could clobber the value before it is used). + */ +- if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){ +- goto no_mem; ++ if( nByte+nZero<=pOut->szMalloc ){ ++ /* The output register is already large enough to hold the record. ++ ** No error checks or buffer enlargement is required */ ++ pOut->z = pOut->zMalloc; ++ }else{ ++ /* Need to make sure that the output is not too big and then enlarge ++ ** the output register to hold the full result */ ++ if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){ ++ goto too_big; ++ } ++ if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){ ++ goto no_mem; ++ } + } + zNewRecord = (u8 *)pOut->z; + +@@ -81926,7 +86052,7 @@ + int isSchemaChange; + iSavepoint = db->nSavepoint - iSavepoint - 1; + if( p1==SAVEPOINT_ROLLBACK ){ +- isSchemaChange = (db->flags & SQLITE_InternChanges)!=0; ++ isSchemaChange = (db->mDbFlags & DBFLAG_SchemaChange)!=0; + for(ii=0; ii<db->nDb; ii++){ + rc = sqlite3BtreeTripAllCursors(db->aDb[ii].pBt, + SQLITE_ABORT_ROLLBACK, +@@ -81943,9 +86069,9 @@ + } + } + if( isSchemaChange ){ +- sqlite3ExpirePreparedStatements(db); ++ sqlite3ExpirePreparedStatements(db, 0); + sqlite3ResetAllSchemasOfConnection(db); +- db->flags = (db->flags | SQLITE_InternChanges); ++ db->mDbFlags |= DBFLAG_SchemaChange; + } + } + +@@ -82085,8 +86211,7 @@ + */ + case OP_Transaction: { + Btree *pBt; +- int iMeta; +- int iGen; ++ int iMeta = 0; + + assert( p->bIsReader ); + assert( p->readOnly==0 || pOp->p2==0 ); +@@ -82099,7 +86224,7 @@ + pBt = db->aDb[pOp->p1].pBt; + + if( pBt ){ +- rc = sqlite3BtreeBeginTrans(pBt, pOp->p2); ++ rc = sqlite3BtreeBeginTrans(pBt, pOp->p2, &iMeta); + testcase( rc==SQLITE_BUSY_SNAPSHOT ); + testcase( rc==SQLITE_BUSY_RECOVERY ); + if( rc!=SQLITE_OK ){ +@@ -82132,19 +86257,17 @@ + p->nStmtDefCons = db->nDeferredCons; + p->nStmtDefImmCons = db->nDeferredImmCons; + } +- +- /* Gather the schema version number for checking: ++ } ++ assert( pOp->p5==0 || pOp->p4type==P4_INT32 ); ++ if( pOp->p5 ++ && (iMeta!=pOp->p3 ++ || db->aDb[pOp->p1].pSchema->iGeneration!=pOp->p4.i) ++ ){ ++ /* + ** IMPLEMENTATION-OF: R-03189-51135 As each SQL statement runs, the schema + ** version is checked to ensure that the schema has not changed since the + ** SQL statement was prepared. + */ +- sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta); +- iGen = db->aDb[pOp->p1].pSchema->iGeneration; +- }else{ +- iGen = iMeta = 0; +- } +- assert( pOp->p5==0 || pOp->p4type==P4_INT32 ); +- if( pOp->p5 && (iMeta!=pOp->p3 || iGen!=pOp->p4.i) ){ + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed"); + /* If the schema-cookie from the database file matches the cookie +@@ -82213,6 +86336,8 @@ + */ + case OP_SetCookie: { + Db *pDb; ++ ++ sqlite3VdbeIncrWriteCounter(p, 0); + assert( pOp->p2<SQLITE_N_BTREE_META ); + assert( pOp->p1>=0 && pOp->p1<db->nDb ); + assert( DbMaskTest(p->btreeMask, pOp->p1) ); +@@ -82225,7 +86350,7 @@ + if( pOp->p2==BTREE_SCHEMA_VERSION ){ + /* When the schema cookie changes, record the new cookie internally */ + pDb->pSchema->schema_cookie = pOp->p3; +- db->flags |= SQLITE_InternChanges; ++ db->mDbFlags |= DBFLAG_SchemaChange; + }else if( pOp->p2==BTREE_FILE_FORMAT ){ + /* Record changes in the file format */ + pDb->pSchema->file_format = pOp->p3; +@@ -82233,7 +86358,7 @@ + if( pOp->p1==1 ){ + /* Invalidate all prepared statements whenever the TEMP database + ** schema is changed. Ticket #1644 */ +- sqlite3ExpirePreparedStatements(db); ++ sqlite3ExpirePreparedStatements(db, 0); + p->expired = 0; + } + if( rc ) goto abort_due_to_error; +@@ -82251,23 +86376,20 @@ + ** values need not be contiguous but all P1 values should be small integers. + ** It is an error for P1 to be negative. + ** +-** If P5!=0 then use the content of register P2 as the root page, not +-** the value of P2 itself. ++** Allowed P5 bits: ++** <ul> ++** <li> <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for ++** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT ++** of OP_SeekLE/OP_IdxGT) ++** </ul> + ** +-** There will be a read lock on the database whenever there is an +-** open cursor. If the database was unlocked prior to this instruction +-** then a read lock is acquired as part of this instruction. A read +-** lock allows other processes to read the database but prohibits +-** any other process from modifying the database. The read lock is +-** released when all cursors are closed. If this instruction attempts +-** to get a read lock but fails, the script terminates with an +-** SQLITE_BUSY error code. +-** + ** The P4 value may be either an integer (P4_INT32) or a pointer to + ** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo +-** structure, then said structure defines the content and collating +-** sequence of the index being opened. Otherwise, if P4 is an integer +-** value, it is set to the number of columns in the table. ++** object, then table being opened must be an [index b-tree] where the ++** KeyInfo object defines the content and collating ++** sequence of that index b-tree. Otherwise, if P4 is an integer ++** value, then the table being opened must be a [table b-tree] with a ++** number of columns no less than the value of P4. + ** + ** See also: OpenWrite, ReopenIdx + */ +@@ -82274,36 +86396,58 @@ + /* Opcode: ReopenIdx P1 P2 P3 P4 P5 + ** Synopsis: root=P2 iDb=P3 + ** +-** The ReopenIdx opcode works exactly like ReadOpen except that it first +-** checks to see if the cursor on P1 is already open with a root page +-** number of P2 and if it is this opcode becomes a no-op. In other words, ++** The ReopenIdx opcode works like OP_OpenRead except that it first ++** checks to see if the cursor on P1 is already open on the same ++** b-tree and if it is this opcode becomes a no-op. In other words, + ** if the cursor is already open, do not reopen it. + ** +-** The ReopenIdx opcode may only be used with P5==0 and with P4 being +-** a P4_KEYINFO object. Furthermore, the P3 value must be the same as +-** every other ReopenIdx or OpenRead for the same cursor number. ++** The ReopenIdx opcode may only be used with P5==0 or P5==OPFLAG_SEEKEQ ++** and with P4 being a P4_KEYINFO object. Furthermore, the P3 value must ++** be the same as every other ReopenIdx or OpenRead for the same cursor ++** number. + ** +-** See the OpenRead opcode documentation for additional information. ++** Allowed P5 bits: ++** <ul> ++** <li> <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for ++** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT ++** of OP_SeekLE/OP_IdxGT) ++** </ul> ++** ++** See also: OP_OpenRead, OP_OpenWrite + */ + /* Opcode: OpenWrite P1 P2 P3 P4 P5 + ** Synopsis: root=P2 iDb=P3 + ** + ** Open a read/write cursor named P1 on the table or index whose root +-** page is P2. Or if P5!=0 use the content of register P2 to find the +-** root page. ++** page is P2 (or whose root page is held in register P2 if the ++** OPFLAG_P2ISREG bit is set in P5 - see below). + ** + ** The P4 value may be either an integer (P4_INT32) or a pointer to + ** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo +-** structure, then said structure defines the content and collating +-** sequence of the index being opened. Otherwise, if P4 is an integer +-** value, it is set to the number of columns in the table, or to the +-** largest index of any column of the table that is actually used. ++** object, then table being opened must be an [index b-tree] where the ++** KeyInfo object defines the content and collating ++** sequence of that index b-tree. Otherwise, if P4 is an integer ++** value, then the table being opened must be a [table b-tree] with a ++** number of columns no less than the value of P4. + ** +-** This instruction works just like OpenRead except that it opens the cursor +-** in read/write mode. For a given table, there can be one or more read-only +-** cursors or a single read/write cursor but not both. ++** Allowed P5 bits: ++** <ul> ++** <li> <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for ++** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT ++** of OP_SeekLE/OP_IdxGT) ++** <li> <b>0x08 OPFLAG_FORDELETE</b>: This cursor is used only to seek ++** and subsequently delete entries in an index btree. This is a ++** hint to the storage engine that the storage engine is allowed to ++** ignore. The hint is not used by the official SQLite b*tree storage ++** engine, but is used by COMDB2. ++** <li> <b>0x10 OPFLAG_P2ISREG</b>: Use the content of register P2 ++** as the root page, not the value of P2 itself. ++** </ul> + ** +-** See also OpenRead. ++** This instruction works like OpenRead except that it opens the cursor ++** in read/write mode. ++** ++** See also: OP_OpenRead, OP_ReopenIdx + */ + case OP_ReopenIdx: { + int nField; +@@ -82332,7 +86476,7 @@ + assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx + || p->readOnly==0 ); + +- if( p->expired ){ ++ if( p->expired==1 ){ + rc = SQLITE_ABORT_ROLLBACK; + goto abort_due_to_error; + } +@@ -82359,12 +86503,13 @@ + if( pOp->p5 & OPFLAG_P2ISREG ){ + assert( p2>0 ); + assert( p2<=(p->nMem+1 - p->nCursor) ); ++ assert( pOp->opcode==OP_OpenWrite ); + pIn2 = &aMem[p2]; + assert( memIsValid(pIn2) ); + assert( (pIn2->flags & MEM_Int)!=0 ); + sqlite3VdbeMemIntegerify(pIn2); + p2 = (int)pIn2->u.i; +- /* The p2 value always comes from a prior OP_CreateTable opcode and ++ /* The p2 value always comes from a prior OP_CreateBtree opcode and + ** that opcode will always set the p2 value to 2 or more or else fail. + ** If there were a failure, the prepared statement would have halted + ** before reaching this instruction. */ +@@ -82374,7 +86519,7 @@ + pKeyInfo = pOp->p4.pKeyInfo; + assert( pKeyInfo->enc==ENC(db) ); + assert( pKeyInfo->db==db ); +- nField = pKeyInfo->nField+pKeyInfo->nXField; ++ nField = pKeyInfo->nAllField; + }else if( pOp->p4type==P4_INT32 ){ + nField = pOp->p4.i; + } +@@ -82487,7 +86632,7 @@ + rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBtx, + BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags); + if( rc==SQLITE_OK ){ +- rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1); ++ rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1, 0); + } + if( rc==SQLITE_OK ){ + /* If a transient index is required, create it by calling +@@ -82585,8 +86730,13 @@ + pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, CURTYPE_PSEUDO); + if( pCx==0 ) goto no_mem; + pCx->nullRow = 1; +- pCx->uc.pseudoTableReg = pOp->p2; ++ pCx->seekResult = pOp->p2; + pCx->isTable = 1; ++ /* Give this pseudo-cursor a fake BtCursor pointer so that pCx ++ ** can be safely passed to sqlite3VdbeCursorMoveto(). This avoids a test ++ ** for pCx->eCurType==CURTYPE_BTREE inside of sqlite3VdbeCursorMoveto() ++ ** which is a performance optimization */ ++ pCx->uc.pCursor = sqlite3BtreeFakeValidCursor(); + assert( pOp->p5==0 ); + break; + } +@@ -82709,10 +86859,10 @@ + ** + ** See also: Found, NotFound, SeekGt, SeekGe, SeekLt + */ +-case OP_SeekLT: /* jump, in3 */ +-case OP_SeekLE: /* jump, in3 */ +-case OP_SeekGE: /* jump, in3 */ +-case OP_SeekGT: { /* jump, in3 */ ++case OP_SeekLT: /* jump, in3, group */ ++case OP_SeekLE: /* jump, in3, group */ ++case OP_SeekGE: /* jump, in3, group */ ++case OP_SeekGT: { /* jump, in3, group */ + int res; /* Comparison result */ + int oc; /* Opcode */ + VdbeCursor *pC; /* The cursor to seek */ +@@ -82890,6 +87040,25 @@ + break; + } + ++/* Opcode: SeekHit P1 P2 * * * ++** Synopsis: seekHit=P2 ++** ++** Set the seekHit flag on cursor P1 to the value in P2. ++** The seekHit flag is used by the IfNoHope opcode. ++** ++** P1 must be a valid b-tree cursor. P2 must be a boolean value, ++** either 0 or 1. ++*/ ++case OP_SeekHit: { ++ VdbeCursor *pC; ++ assert( pOp->p1>=0 && pOp->p1<p->nCursor ); ++ pC = p->apCsr[pOp->p1]; ++ assert( pC!=0 ); ++ assert( pOp->p2==0 || pOp->p2==1 ); ++ pC->seekHit = pOp->p2 & 1; ++ break; ++} ++ + /* Opcode: Found P1 P2 P3 P4 * + ** Synopsis: key=r[P3@P4] + ** +@@ -82924,8 +87093,35 @@ + ** advanced in either direction. In other words, the Next and Prev + ** opcodes do not work after this operation. + ** +-** See also: Found, NotExists, NoConflict ++** See also: Found, NotExists, NoConflict, IfNoHope + */ ++/* Opcode: IfNoHope P1 P2 P3 P4 * ++** Synopsis: key=r[P3@P4] ++** ++** Register P3 is the first of P4 registers that form an unpacked ++** record. ++** ++** Cursor P1 is on an index btree. If the seekHit flag is set on P1, then ++** this opcode is a no-op. But if the seekHit flag of P1 is clear, then ++** check to see if there is any entry in P1 that matches the ++** prefix identified by P3 and P4. If no entry matches the prefix, ++** jump to P2. Otherwise fall through. ++** ++** This opcode behaves like OP_NotFound if the seekHit ++** flag is clear and it behaves like OP_Noop if the seekHit flag is set. ++** ++** This opcode is used in IN clause processing for a multi-column key. ++** If an IN clause is attached to an element of the key other than the ++** left-most element, and if there are no matches on the most recent ++** seek over the whole key, then it might be that one of the key element ++** to the left is prohibiting a match, and hence there is "no hope" of ++** any match regardless of how many IN clause elements are checked. ++** In such a case, we abandon the IN clause search early, using this ++** opcode. The opcode name comes from the fact that the ++** jump is taken if there is "no hope" of achieving a match. ++** ++** See also: NotFound, SeekHit ++*/ + /* Opcode: NoConflict P1 P2 P3 P4 * + ** Synopsis: key=r[P3@P4] + ** +@@ -82949,6 +87145,14 @@ + ** + ** See also: NotFound, Found, NotExists + */ ++case OP_IfNoHope: { /* jump, in3 */ ++ VdbeCursor *pC; ++ assert( pOp->p1>=0 && pOp->p1<p->nCursor ); ++ pC = p->apCsr[pOp->p1]; ++ assert( pC!=0 ); ++ if( pC->seekHit ) break; ++ /* Fall through into OP_NotFound */ ++} + case OP_NoConflict: /* jump, in3 */ + case OP_NotFound: /* jump, in3 */ + case OP_Found: { /* jump, in3 */ +@@ -83086,18 +87290,26 @@ + + pIn3 = &aMem[pOp->p3]; + if( (pIn3->flags & MEM_Int)==0 ){ ++ /* Make sure pIn3->u.i contains a valid integer representation of ++ ** the key value, but do not change the datatype of the register, as ++ ** other parts of the perpared statement might be depending on the ++ ** current datatype. */ ++ u16 origFlags = pIn3->flags; ++ int isNotInt; + applyAffinity(pIn3, SQLITE_AFF_NUMERIC, encoding); +- if( (pIn3->flags & MEM_Int)==0 ) goto jump_to_p2; ++ isNotInt = (pIn3->flags & MEM_Int)==0; ++ pIn3->flags = origFlags; ++ if( isNotInt ) goto jump_to_p2; + } + /* Fall through into OP_NotExists */ + case OP_NotExists: /* jump, in3 */ + pIn3 = &aMem[pOp->p3]; +- assert( pIn3->flags & MEM_Int ); ++ assert( (pIn3->flags & MEM_Int)!=0 || pOp->opcode==OP_SeekRowid ); + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + #ifdef SQLITE_DEBUG +- pC->seekOp = 0; ++ pC->seekOp = OP_SeekRowid; + #endif + assert( pC->isTable ); + assert( pC->eCurType==CURTYPE_BTREE ); +@@ -83172,6 +87384,7 @@ + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); ++ assert( pC->isTable ); + assert( pC->eCurType==CURTYPE_BTREE ); + assert( pC->uc.pCursor!=0 ); + { +@@ -83328,10 +87541,8 @@ + int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */ + const char *zDb; /* database name - used by the update hook */ + Table *pTab; /* Table structure - used by update and pre-update hooks */ +- int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */ + BtreePayload x; /* Payload to be inserted */ + +- op = 0; + pData = &aMem[pOp->p2]; + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + assert( memIsValid(pData) ); +@@ -83342,6 +87553,7 @@ + assert( (pOp->p5 & OPFLAG_ISNOOP) || pC->isTable ); + assert( pOp->p4type==P4_TABLE || pOp->p4type>=P4_STATIC ); + REGISTER_TRACE(pOp->p2, pData); ++ sqlite3VdbeIncrWriteCounter(p, pC); + + if( pOp->opcode==OP_Insert ){ + pKey = &aMem[pOp->p3]; +@@ -83359,19 +87571,21 @@ + zDb = db->aDb[pC->iDb].zDbSName; + pTab = pOp->p4.pTab; + assert( (pOp->p5 & OPFLAG_ISNOOP) || HasRowid(pTab) ); +- op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); + }else{ +- pTab = 0; /* Not needed. Silence a compiler warning. */ ++ pTab = 0; + zDb = 0; /* Not needed. Silence a compiler warning. */ + } + + #ifdef SQLITE_ENABLE_PREUPDATE_HOOK + /* Invoke the pre-update hook, if any */ +- if( db->xPreUpdateCallback +- && pOp->p4type==P4_TABLE +- && !(pOp->p5 & OPFLAG_ISUPDATE) +- ){ +- sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, x.nKey, pOp->p2); ++ if( pTab ){ ++ if( db->xPreUpdateCallback && !(pOp->p5 & OPFLAG_ISUPDATE) ){ ++ sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, x.nKey,pOp->p2); ++ } ++ if( db->xUpdateCallback==0 || pTab->aCol==0 ){ ++ /* Prevent post-update hook from running in cases when it should not */ ++ pTab = 0; ++ } + } + if( pOp->p5 & OPFLAG_ISNOOP ) break; + #endif +@@ -83378,14 +87592,9 @@ + + if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; + if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = x.nKey; +- if( pData->flags & MEM_Null ){ +- x.pData = 0; +- x.nData = 0; +- }else{ +- assert( pData->flags & (MEM_Blob|MEM_Str) ); +- x.pData = pData->z; +- x.nData = pData->n; +- } ++ assert( pData->flags & (MEM_Blob|MEM_Str) ); ++ x.pData = pData->z; ++ x.nData = pData->n; + seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0); + if( pData->flags & MEM_Zero ){ + x.nZero = pData->u.nZero; +@@ -83401,8 +87610,12 @@ + + /* Invoke the update-hook if required. */ + if( rc ) goto abort_due_to_error; +- if( db->xUpdateCallback && op ){ +- db->xUpdateCallback(db->pUpdateArg, op, zDb, pTab->zName, x.nKey); ++ if( pTab ){ ++ assert( db->xUpdateCallback!=0 ); ++ assert( pTab->aCol!=0 ); ++ db->xUpdateCallback(db->pUpdateArg, ++ (pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT, ++ zDb, pTab->zName, x.nKey); + } + break; + } +@@ -83455,6 +87668,7 @@ + assert( pC->eCurType==CURTYPE_BTREE ); + assert( pC->uc.pCursor!=0 ); + assert( pC->deferredMoveto==0 ); ++ sqlite3VdbeIncrWriteCounter(p, pC); + + #ifdef SQLITE_DEBUG + if( pOp->p4type==P4_TABLE && HasRowid(pOp->p4.pTab) && pOp->p5==0 ){ +@@ -83623,10 +87837,10 @@ + ** If the P1 cursor must be pointing to a valid row (not a NULL row) + ** of a real table, not a pseudo-table. + ** +-** If P3!=0 then this opcode is allowed to make an ephermeral pointer ++** If P3!=0 then this opcode is allowed to make an ephemeral pointer + ** into the database page. That means that the content of the output + ** register will be invalidated as soon as the cursor moves - including +-** moves caused by other cursors that "save" the the current cursors ++** moves caused by other cursors that "save" the current cursors + ** position in order that they can write to the same table. If P3==0 + ** then a copy of the data is made into memory. P3!=0 is faster, but + ** P3==0 is safer. +@@ -83749,11 +87963,24 @@ + assert( pC->uc.pCursor!=0 ); + sqlite3BtreeClearCursor(pC->uc.pCursor); + } ++#ifdef SQLITE_DEBUG ++ if( pC->seekOp==0 ) pC->seekOp = OP_NullRow; ++#endif + break; + } + +-/* Opcode: Last P1 P2 P3 * * ++/* Opcode: SeekEnd P1 * * * * + ** ++** Position cursor P1 at the end of the btree for the purpose of ++** appending a new entry onto the btree. ++** ++** It is assumed that the cursor is used only for appending and so ++** if the cursor is valid, then the cursor must already be pointing ++** at the end of the btree and so no changes are made to ++** the cursor. ++*/ ++/* Opcode: Last P1 P2 * * * ++** + ** The next use of the Rowid or Column or Prev instruction for P1 + ** will refer to the last entry in the database table or index. + ** If the table or index is empty and P2>0, then jump immediately to P2. +@@ -83763,14 +87990,8 @@ + ** This opcode leaves the cursor configured to move in reverse order, + ** from the end toward the beginning. In other words, the cursor is + ** configured to use Prev, not Next. +-** +-** If P3 is -1, then the cursor is positioned at the end of the btree +-** for the purpose of appending a new entry onto the btree. In that +-** case P2 must be 0. It is assumed that the cursor is used only for +-** appending and so if the cursor is valid, then the cursor must already +-** be pointing at the end of the btree and so no changes are made to +-** the cursor. + */ ++case OP_SeekEnd: + case OP_Last: { /* jump */ + VdbeCursor *pC; + BtCursor *pCrsr; +@@ -83783,23 +88004,25 @@ + pCrsr = pC->uc.pCursor; + res = 0; + assert( pCrsr!=0 ); +- pC->seekResult = pOp->p3; + #ifdef SQLITE_DEBUG +- pC->seekOp = OP_Last; ++ pC->seekOp = pOp->opcode; + #endif +- if( pOp->p3==0 || !sqlite3BtreeCursorIsValidNN(pCrsr) ){ +- rc = sqlite3BtreeLast(pCrsr, &res); +- pC->nullRow = (u8)res; +- pC->deferredMoveto = 0; +- pC->cacheStatus = CACHE_STALE; +- if( rc ) goto abort_due_to_error; +- if( pOp->p2>0 ){ +- VdbeBranchTaken(res!=0,2); +- if( res ) goto jump_to_p2; ++ if( pOp->opcode==OP_SeekEnd ){ ++ assert( pOp->p2==0 ); ++ pC->seekResult = -1; ++ if( sqlite3BtreeCursorIsValidNN(pCrsr) ){ ++ break; + } +- }else{ +- assert( pOp->p2==0 ); + } ++ rc = sqlite3BtreeLast(pCrsr, &res); ++ pC->nullRow = (u8)res; ++ pC->deferredMoveto = 0; ++ pC->cacheStatus = CACHE_STALE; ++ if( rc ) goto abort_due_to_error; ++ if( pOp->p2>0 ){ ++ VdbeBranchTaken(res!=0,2); ++ if( res ) goto jump_to_p2; ++ } + break; + } + +@@ -83861,7 +88084,7 @@ + p->aCounter[SQLITE_STMTSTATUS_SORT]++; + /* Fall through into OP_Rewind */ + } +-/* Opcode: Rewind P1 P2 * * * ++/* Opcode: Rewind P1 P2 * * P5 + ** + ** The next use of the Rowid or Column or Next instruction for P1 + ** will refer to the first entry in the database table or index. +@@ -83869,6 +88092,10 @@ + ** If the table or index is not empty, fall through to the following + ** instruction. + ** ++** If P5 is non-zero and the table is not empty, then the "skip-next" ++** flag is set on the cursor so that the next OP_Next instruction ++** executed on it is a no-op. ++** + ** This opcode leaves the cursor configured to move in forward order, + ** from the beginning toward the end. In other words, the cursor is + ** configured to use Next, not Prev. +@@ -83893,6 +88120,9 @@ + pCrsr = pC->uc.pCursor; + assert( pCrsr ); + rc = sqlite3BtreeFirst(pCrsr, &res); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( pOp->p5 ) sqlite3BtreeSkipNext(pCrsr); ++#endif + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; + } +@@ -83929,13 +88159,8 @@ + ** If P5 is positive and the jump is taken, then event counter + ** number P5-1 in the prepared statement is incremented. + ** +-** See also: Prev, NextIfOpen ++** See also: Prev + */ +-/* Opcode: NextIfOpen P1 P2 P3 P4 P5 +-** +-** This opcode works just like Next except that if cursor P1 is not +-** open it behaves a no-op. +-*/ + /* Opcode: Prev P1 P2 P3 P4 P5 + ** + ** Back up cursor P1 so that it points to the previous key/data pair in its +@@ -83962,11 +88187,6 @@ + ** If P5 is positive and the jump is taken, then event counter + ** number P5-1 in the prepared statement is incremented. + */ +-/* Opcode: PrevIfOpen P1 P2 P3 P4 P5 +-** +-** This opcode works just like Prev except that if cursor P1 is not +-** open it behaves a no-op. +-*/ + /* Opcode: SorterNext P1 P2 * * P5 + ** + ** This opcode works just like OP_Next except that P1 must be a +@@ -83981,10 +88201,6 @@ + assert( isSorter(pC) ); + rc = sqlite3VdbeSorterNext(db, pC); + goto next_tail; +-case OP_PrevIfOpen: /* jump */ +-case OP_NextIfOpen: /* jump */ +- if( p->apCsr[pOp->p1]==0 ) break; +- /* Fall through */ + case OP_Prev: /* jump */ + case OP_Next: /* jump */ + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); +@@ -83995,17 +88211,17 @@ + assert( pC->eCurType==CURTYPE_BTREE ); + assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext ); + assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious ); +- assert( pOp->opcode!=OP_NextIfOpen || pOp->p4.xAdvance==sqlite3BtreeNext ); +- assert( pOp->opcode!=OP_PrevIfOpen || pOp->p4.xAdvance==sqlite3BtreePrevious); + +- /* The Next opcode is only used after SeekGT, SeekGE, and Rewind. ++ /* The Next opcode is only used after SeekGT, SeekGE, Rewind, and Found. + ** The Prev opcode is only used after SeekLT, SeekLE, and Last. */ +- assert( pOp->opcode!=OP_Next || pOp->opcode!=OP_NextIfOpen ++ assert( pOp->opcode!=OP_Next + || pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE +- || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found); +- assert( pOp->opcode!=OP_Prev || pOp->opcode!=OP_PrevIfOpen ++ || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found ++ || pC->seekOp==OP_NullRow); ++ assert( pOp->opcode!=OP_Prev + || pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE +- || pC->seekOp==OP_Last ); ++ || pC->seekOp==OP_Last ++ || pC->seekOp==OP_NullRow); + + rc = pOp->p4.xAdvance(pC->uc.pCursor, pOp->p3); + next_tail: +@@ -84067,6 +88283,7 @@ + + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + pC = p->apCsr[pOp->p1]; ++ sqlite3VdbeIncrWriteCounter(p, pC); + assert( pC!=0 ); + assert( isSorter(pC)==(pOp->opcode==OP_SorterInsert) ); + pIn2 = &aMem[pOp->p2]; +@@ -84113,6 +88330,7 @@ + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( pC->eCurType==CURTYPE_BTREE ); ++ sqlite3VdbeIncrWriteCounter(p, pC); + pCrsr = pC->uc.pCursor; + assert( pCrsr!=0 ); + assert( pOp->p5==0 ); +@@ -84286,7 +88504,13 @@ + } + r.aMem = &aMem[pOp->p3]; + #ifdef SQLITE_DEBUG +- { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); } ++ { ++ int i; ++ for(i=0; i<r.nField; i++){ ++ assert( memIsValid(&r.aMem[i]) ); ++ REGISTER_TRACE(pOp->p3+i, &aMem[pOp->p3+i]); ++ } ++ } + #endif + res = 0; /* Not needed. Only used to silence a warning. */ + rc = sqlite3VdbeIdxKeyCompare(db, pC, &r, &res); +@@ -84335,6 +88559,7 @@ + int iMoved; + int iDb; + ++ sqlite3VdbeIncrWriteCounter(p, 0); + assert( p->readOnly==0 ); + assert( pOp->p1>1 ); + pOut = out2Prerelease(p, pOp); +@@ -84384,6 +88609,7 @@ + case OP_Clear: { + int nChange; + ++ sqlite3VdbeIncrWriteCounter(p, 0); + nChange = 0; + assert( p->readOnly==0 ); + assert( DbMaskTest(p->btreeMask, pOp->p2) ); +@@ -84427,50 +88653,29 @@ + break; + } + +-/* Opcode: CreateTable P1 P2 * * * +-** Synopsis: r[P2]=root iDb=P1 ++/* Opcode: CreateBtree P1 P2 P3 * * ++** Synopsis: r[P2]=root iDb=P1 flags=P3 + ** +-** Allocate a new table in the main database file if P1==0 or in the +-** auxiliary database file if P1==1 or in an attached database if +-** P1>1. Write the root page number of the new table into +-** register P2 +-** +-** The difference between a table and an index is this: A table must +-** have a 4-byte integer key and can have arbitrary data. An index +-** has an arbitrary key but no data. +-** +-** See also: CreateIndex ++** Allocate a new b-tree in the main database file if P1==0 or in the ++** TEMP database file if P1==1 or in an attached database if ++** P1>1. The P3 argument must be 1 (BTREE_INTKEY) for a rowid table ++** it must be 2 (BTREE_BLOBKEY) for an index or WITHOUT ROWID table. ++** The root page number of the new b-tree is stored in register P2. + */ +-/* Opcode: CreateIndex P1 P2 * * * +-** Synopsis: r[P2]=root iDb=P1 +-** +-** Allocate a new index in the main database file if P1==0 or in the +-** auxiliary database file if P1==1 or in an attached database if +-** P1>1. Write the root page number of the new table into +-** register P2. +-** +-** See documentation on OP_CreateTable for additional information. +-*/ +-case OP_CreateIndex: /* out2 */ +-case OP_CreateTable: { /* out2 */ ++case OP_CreateBtree: { /* out2 */ + int pgno; +- int flags; + Db *pDb; + ++ sqlite3VdbeIncrWriteCounter(p, 0); + pOut = out2Prerelease(p, pOp); + pgno = 0; ++ assert( pOp->p3==BTREE_INTKEY || pOp->p3==BTREE_BLOBKEY ); + assert( pOp->p1>=0 && pOp->p1<db->nDb ); + assert( DbMaskTest(p->btreeMask, pOp->p1) ); + assert( p->readOnly==0 ); + pDb = &db->aDb[pOp->p1]; + assert( pDb->pBt!=0 ); +- if( pOp->opcode==OP_CreateTable ){ +- /* flags = BTREE_INTKEY; */ +- flags = BTREE_INTKEY; +- }else{ +- flags = BTREE_BLOBKEY; +- } +- rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags); ++ rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, pOp->p3); + if( rc ) goto abort_due_to_error; + pOut->u.i = pgno; + break; +@@ -84481,6 +88686,7 @@ + ** Run the SQL statement or statements specified in the P4 string. + */ + case OP_SqlExec: { ++ sqlite3VdbeIncrWriteCounter(p, 0); + db->nSqlExec++; + rc = sqlite3_exec(db, pOp->p4.z, 0, 0, 0); + db->nSqlExec--; +@@ -84491,7 +88697,8 @@ + /* Opcode: ParseSchema P1 * * P4 * + ** + ** Read and parse all entries from the SQLITE_MASTER table of database P1 +-** that match the WHERE clause P4. ++** that match the WHERE clause P4. If P4 is a NULL pointer, then the ++** entire schema for P1 is reparsed. + ** + ** This opcode invokes the parser to create a new virtual machine, + ** then runs the new virtual machine. It is thus a re-entrant opcode. +@@ -84515,11 +88722,22 @@ + iDb = pOp->p1; + assert( iDb>=0 && iDb<db->nDb ); + assert( DbHasProperty(db, iDb, DB_SchemaLoaded) ); +- /* Used to be a conditional */ { ++ ++#ifndef SQLITE_OMIT_ALTERTABLE ++ if( pOp->p4.z==0 ){ ++ sqlite3SchemaClear(db->aDb[iDb].pSchema); ++ db->mDbFlags &= ~DBFLAG_SchemaKnownOk; ++ rc = sqlite3InitOne(db, iDb, &p->zErrMsg, INITFLAG_AlterTable); ++ db->mDbFlags |= DBFLAG_SchemaChange; ++ p->expired = 0; ++ }else ++#endif ++ { + zMaster = MASTER_NAME; + initData.db = db; +- initData.iDb = pOp->p1; ++ initData.iDb = iDb; + initData.pzErrMsg = &p->zErrMsg; ++ initData.mInitFlags = 0; + zSql = sqlite3MPrintf(db, + "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid", + db->aDb[iDb].zDbSName, zMaster, pOp->p4.z); +@@ -84570,6 +88788,7 @@ + ** schema consistent with what is on disk. + */ + case OP_DropTable: { ++ sqlite3VdbeIncrWriteCounter(p, 0); + sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p4.z); + break; + } +@@ -84583,6 +88802,7 @@ + ** schema consistent with what is on disk. + */ + case OP_DropIndex: { ++ sqlite3VdbeIncrWriteCounter(p, 0); + sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p4.z); + break; + } +@@ -84596,6 +88816,7 @@ + ** schema consistent with what is on disk. + */ + case OP_DropTrigger: { ++ sqlite3VdbeIncrWriteCounter(p, 0); + sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p4.z); + break; + } +@@ -84632,7 +88853,7 @@ + nRoot = pOp->p2; + aRoot = pOp->p4.ai; + assert( nRoot>0 ); +- assert( aRoot[nRoot]==0 ); ++ assert( aRoot[0]==nRoot ); + assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); + pnErr = &aMem[pOp->p3]; + assert( (pnErr->flags & MEM_Int)!=0 ); +@@ -84640,7 +88861,7 @@ + pIn1 = &aMem[pOp->p1]; + assert( pOp->p5<db->nDb ); + assert( DbMaskTest(p->btreeMask, pOp->p5) ); +- z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot, ++ z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, &aRoot[1], nRoot, + (int)pnErr->u.i+1, &nErr); + sqlite3VdbeMemSetNull(pIn1); + if( nErr==0 ){ +@@ -84669,11 +88890,11 @@ + pIn1 = &aMem[pOp->p1]; + pIn2 = &aMem[pOp->p2]; + assert( (pIn2->flags & MEM_Int)!=0 ); +- if( (pIn1->flags & MEM_RowSet)==0 ){ +- sqlite3VdbeMemSetRowSet(pIn1); +- if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem; ++ if( (pIn1->flags & MEM_Blob)==0 ){ ++ if( sqlite3VdbeMemSetRowSet(pIn1) ) goto no_mem; + } +- sqlite3RowSetInsert(pIn1->u.pRowSet, pIn2->u.i); ++ assert( sqlite3VdbeMemIsRowSet(pIn1) ); ++ sqlite3RowSetInsert((RowSet*)pIn1->z, pIn2->u.i); + break; + } + +@@ -84689,8 +88910,9 @@ + i64 val; + + pIn1 = &aMem[pOp->p1]; +- if( (pIn1->flags & MEM_RowSet)==0 +- || sqlite3RowSetNext(pIn1->u.pRowSet, &val)==0 ++ assert( (pIn1->flags & MEM_Blob)==0 || sqlite3VdbeMemIsRowSet(pIn1) ); ++ if( (pIn1->flags & MEM_Blob)==0 ++ || sqlite3RowSetNext((RowSet*)pIn1->z, &val)==0 + ){ + /* The boolean index is empty */ + sqlite3VdbeMemSetNull(pIn1); +@@ -84739,20 +88961,19 @@ + /* If there is anything other than a rowset object in memory cell P1, + ** delete it now and initialize P1 with an empty rowset + */ +- if( (pIn1->flags & MEM_RowSet)==0 ){ +- sqlite3VdbeMemSetRowSet(pIn1); +- if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem; ++ if( (pIn1->flags & MEM_Blob)==0 ){ ++ if( sqlite3VdbeMemSetRowSet(pIn1) ) goto no_mem; + } +- ++ assert( sqlite3VdbeMemIsRowSet(pIn1) ); + assert( pOp->p4type==P4_INT32 ); + assert( iSet==-1 || iSet>=0 ); + if( iSet ){ +- exists = sqlite3RowSetTest(pIn1->u.pRowSet, iSet, pIn3->u.i); ++ exists = sqlite3RowSetTest((RowSet*)pIn1->z, iSet, pIn3->u.i); + VdbeBranchTaken(exists!=0,2); + if( exists ) goto jump_to_p2; + } + if( iSet>=0 ){ +- sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i); ++ sqlite3RowSetInsert((RowSet*)pIn1->z, pIn3->u.i); + } + break; + } +@@ -84816,7 +89037,7 @@ + ** of the current program, and the memory required at runtime to execute + ** the trigger program. If this trigger has been fired before, then pRt + ** is already allocated. Otherwise, it must be initialized. */ +- if( (pRt->flags&MEM_Frame)==0 ){ ++ if( (pRt->flags&MEM_Blob)==0 ){ + /* SubProgram.nMem is set to the number of memory cells used by the + ** program stored in SubProgram.aOp. As well as these, one memory + ** cell is required for each cursor used by the program. Set local +@@ -84834,8 +89055,10 @@ + goto no_mem; + } + sqlite3VdbeMemRelease(pRt); +- pRt->flags = MEM_Frame; +- pRt->u.pFrame = pFrame; ++ pRt->flags = MEM_Blob|MEM_Dyn; ++ pRt->z = (char*)pFrame; ++ pRt->n = nByte; ++ pRt->xDel = sqlite3VdbeFrameMemDel; + + pFrame->v = p; + pFrame->nChildMem = nMem; +@@ -84851,6 +89074,9 @@ + #ifdef SQLITE_ENABLE_STMT_SCANSTATUS + pFrame->anExec = p->anExec; + #endif ++#ifdef SQLITE_DEBUG ++ pFrame->iFrameMagic = SQLITE_FRAME_MAGIC; ++#endif + + pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem]; + for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){ +@@ -84858,7 +89084,8 @@ + pMem->db = db; + } + }else{ +- pFrame = pRt->u.pFrame; ++ pFrame = (VdbeFrame*)pRt->z; ++ assert( pRt->xDel==sqlite3VdbeFrameMemDel ); + assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem + || (pProgram->nCsr==0 && pProgram->nMem+1==pFrame->nChildMem) ); + assert( pProgram->nCsr==pFrame->nChildCsr ); +@@ -85087,24 +89314,35 @@ + } + + +-/* Opcode: AggStep0 * P2 P3 P4 P5 ++/* Opcode: AggStep * P2 P3 P4 P5 + ** Synopsis: accum=r[P3] step(r[P2@P5]) + ** +-** Execute the step function for an aggregate. The +-** function has P5 arguments. P4 is a pointer to the FuncDef +-** structure that specifies the function. Register P3 is the ++** Execute the xStep function for an aggregate. ++** The function has P5 arguments. P4 is a pointer to the ++** FuncDef structure that specifies the function. Register P3 is the + ** accumulator. + ** + ** The P5 arguments are taken from register P2 and its + ** successors. + */ +-/* Opcode: AggStep * P2 P3 P4 P5 ++/* Opcode: AggInverse * P2 P3 P4 P5 ++** Synopsis: accum=r[P3] inverse(r[P2@P5]) ++** ++** Execute the xInverse function for an aggregate. ++** The function has P5 arguments. P4 is a pointer to the ++** FuncDef structure that specifies the function. Register P3 is the ++** accumulator. ++** ++** The P5 arguments are taken from register P2 and its ++** successors. ++*/ ++/* Opcode: AggStep1 P1 P2 P3 P4 P5 + ** Synopsis: accum=r[P3] step(r[P2@P5]) + ** +-** Execute the step function for an aggregate. The +-** function has P5 arguments. P4 is a pointer to an sqlite3_context +-** object that is used to run the function. Register P3 is +-** as the accumulator. ++** Execute the xStep (if P1==0) or xInverse (if P1!=0) function for an ++** aggregate. The function has P5 arguments. P4 is a pointer to the ++** FuncDef structure that specifies the function. Register P3 is the ++** accumulator. + ** + ** The P5 arguments are taken from register P2 and its + ** successors. +@@ -85115,7 +89353,8 @@ + ** sqlite3_context only happens once, instead of on each call to the + ** step function. + */ +-case OP_AggStep0: { ++case OP_AggInverse: ++case OP_AggStep: { + int n; + sqlite3_context *pCtx; + +@@ -85124,28 +89363,47 @@ + assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); + assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) ); + assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n ); +- pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); ++ pCtx = sqlite3DbMallocRawNN(db, n*sizeof(sqlite3_value*) + ++ (sizeof(pCtx[0]) + sizeof(Mem) - sizeof(sqlite3_value*))); + if( pCtx==0 ) goto no_mem; + pCtx->pMem = 0; ++ pCtx->pOut = (Mem*)&(pCtx->argv[n]); ++ sqlite3VdbeMemInit(pCtx->pOut, db, MEM_Null); + pCtx->pFunc = pOp->p4.pFunc; + pCtx->iOp = (int)(pOp - aOp); + pCtx->pVdbe = p; ++ pCtx->skipFlag = 0; ++ pCtx->isError = 0; + pCtx->argc = n; + pOp->p4type = P4_FUNCCTX; + pOp->p4.pCtx = pCtx; +- pOp->opcode = OP_AggStep; ++ ++ /* OP_AggInverse must have P1==1 and OP_AggStep must have P1==0 */ ++ assert( pOp->p1==(pOp->opcode==OP_AggInverse) ); ++ ++ pOp->opcode = OP_AggStep1; + /* Fall through into OP_AggStep */ + } +-case OP_AggStep: { ++case OP_AggStep1: { + int i; + sqlite3_context *pCtx; + Mem *pMem; +- Mem t; + + assert( pOp->p4type==P4_FUNCCTX ); + pCtx = pOp->p4.pCtx; + pMem = &aMem[pOp->p3]; + ++#ifdef SQLITE_DEBUG ++ if( pOp->p1 ){ ++ /* This is an OP_AggInverse call. Verify that xStep has always ++ ** been called at least once prior to any xInverse call. */ ++ assert( pMem->uTemp==0x1122e0e3 ); ++ }else{ ++ /* This is an OP_AggStep call. Mark it as such. */ ++ pMem->uTemp = 0x1122e0e3; ++ } ++#endif ++ + /* If this function is inside of a trigger, the register array in aMem[] + ** might change from one evaluation to the next. The next block of code + ** checks to see if the register array has changed, and if so it +@@ -85163,26 +89421,34 @@ + #endif + + pMem->n++; +- sqlite3VdbeMemInit(&t, db, MEM_Null); +- pCtx->pOut = &t; +- pCtx->fErrorOrAux = 0; +- pCtx->skipFlag = 0; ++ assert( pCtx->pOut->flags==MEM_Null ); ++ assert( pCtx->isError==0 ); ++ assert( pCtx->skipFlag==0 ); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( pOp->p1 ){ ++ (pCtx->pFunc->xInverse)(pCtx,pCtx->argc,pCtx->argv); ++ }else ++#endif + (pCtx->pFunc->xSFunc)(pCtx,pCtx->argc,pCtx->argv); /* IMP: R-24505-23230 */ +- if( pCtx->fErrorOrAux ){ +- if( pCtx->isError ){ +- sqlite3VdbeError(p, "%s", sqlite3_value_text(&t)); ++ ++ if( pCtx->isError ){ ++ if( pCtx->isError>0 ){ ++ sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut)); + rc = pCtx->isError; + } +- sqlite3VdbeMemRelease(&t); ++ if( pCtx->skipFlag ){ ++ assert( pOp[-1].opcode==OP_CollSeq ); ++ i = pOp[-1].p1; ++ if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1); ++ pCtx->skipFlag = 0; ++ } ++ sqlite3VdbeMemRelease(pCtx->pOut); ++ pCtx->pOut->flags = MEM_Null; ++ pCtx->isError = 0; + if( rc ) goto abort_due_to_error; +- }else{ +- assert( t.flags==MEM_Null ); + } +- if( pCtx->skipFlag ){ +- assert( pOp[-1].opcode==OP_CollSeq ); +- i = pOp[-1].p1; +- if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1); +- } ++ assert( pCtx->pOut->flags==MEM_Null ); ++ assert( pCtx->skipFlag==0 ); + break; + } + +@@ -85189,22 +89455,46 @@ + /* Opcode: AggFinal P1 P2 * P4 * + ** Synopsis: accum=r[P1] N=P2 + ** +-** Execute the finalizer function for an aggregate. P1 is +-** the memory location that is the accumulator for the aggregate. ++** P1 is the memory location that is the accumulator for an aggregate ++** or window function. Execute the finalizer function ++** for an aggregate and store the result in P1. + ** + ** P2 is the number of arguments that the step function takes and + ** P4 is a pointer to the FuncDef for this function. The P2 + ** argument is not used by this opcode. It is only there to disambiguate + ** functions that can take varying numbers of arguments. The +-** P4 argument is only needed for the degenerate case where ++** P4 argument is only needed for the case where + ** the step function was not previously called. + */ ++/* Opcode: AggValue * P2 P3 P4 * ++** Synopsis: r[P3]=value N=P2 ++** ++** Invoke the xValue() function and store the result in register P3. ++** ++** P2 is the number of arguments that the step function takes and ++** P4 is a pointer to the FuncDef for this function. The P2 ++** argument is not used by this opcode. It is only there to disambiguate ++** functions that can take varying numbers of arguments. The ++** P4 argument is only needed for the case where ++** the step function was not previously called. ++*/ ++case OP_AggValue: + case OP_AggFinal: { + Mem *pMem; + assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); ++ assert( pOp->p3==0 || pOp->opcode==OP_AggValue ); + pMem = &aMem[pOp->p1]; + assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 ); +- rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( pOp->p3 ){ ++ rc = sqlite3VdbeMemAggValue(pMem, &aMem[pOp->p3], pOp->p4.pFunc); ++ pMem = &aMem[pOp->p3]; ++ }else ++#endif ++ { ++ rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc); ++ } ++ + if( rc ){ + sqlite3VdbeError(p, "%s", sqlite3_value_text(pMem)); + goto abort_due_to_error; +@@ -85399,7 +89689,7 @@ + } + #endif + +-/* Opcode: Expire P1 * * * * ++/* Opcode: Expire P1 P2 * * * + ** + ** Cause precompiled statements to expire. When an expired statement + ** is executed using sqlite3_step() it will either automatically +@@ -85408,12 +89698,19 @@ + ** + ** If P1 is 0, then all SQL statements become expired. If P1 is non-zero, + ** then only the currently executing statement is expired. ++** ++** If P2 is 0, then SQL statements are expired immediately. If P2 is 1, ++** then running SQL statements are allowed to continue to run to completion. ++** The P2==1 case occurs when a CREATE INDEX or similar schema change happens ++** that might help the statement run faster but which does not affect the ++** correctness of operation. + */ + case OP_Expire: { ++ assert( pOp->p2==0 || pOp->p2==1 ); + if( !pOp->p1 ){ +- sqlite3ExpirePreparedStatements(db); ++ sqlite3ExpirePreparedStatements(db, pOp->p2); + }else{ +- p->expired = 1; ++ p->expired = pOp->p2+1; + } + break; + } +@@ -85627,12 +89924,19 @@ + #endif /* SQLITE_OMIT_VIRTUALTABLE */ + + #ifndef SQLITE_OMIT_VIRTUALTABLE +-/* Opcode: VColumn P1 P2 P3 * * ++/* Opcode: VColumn P1 P2 P3 * P5 + ** Synopsis: r[P3]=vcolumn(P2) + ** +-** Store the value of the P2-th column of +-** the row of the virtual-table that the +-** P1 cursor is pointing to into register P3. ++** Store in register P3 the value of the P2-th column of ++** the current row of the virtual-table of cursor P1. ++** ++** If the VColumn opcode is being used to fetch the value of ++** an unchanging column during an UPDATE operation, then the P5 ++** value is OPFLAG_NOCHNG. This will cause the sqlite3_vtab_nochange() ++** function to return true inside the xColumn method of the virtual ++** table implementation. The P5 column might also contain other ++** bits (OPFLAG_LENGTHARG or OPFLAG_TYPEOFARG) but those bits are ++** unused by OP_VColumn. + */ + case OP_VColumn: { + sqlite3_vtab *pVtab; +@@ -85654,10 +89958,18 @@ + assert( pModule->xColumn ); + memset(&sContext, 0, sizeof(sContext)); + sContext.pOut = pDest; +- MemSetTypeFlag(pDest, MEM_Null); ++ testcase( (pOp->p5 & OPFLAG_NOCHNG)==0 && pOp->p5!=0 ); ++ if( pOp->p5 & OPFLAG_NOCHNG ){ ++ sqlite3VdbeMemSetNull(pDest); ++ pDest->flags = MEM_Null|MEM_Zero; ++ pDest->u.nZero = 0; ++ }else{ ++ MemSetTypeFlag(pDest, MEM_Null); ++ } + rc = pModule->xColumn(pCur->uc.pVCur, &sContext, pOp->p2); + sqlite3VtabImportErrmsg(p, pVtab); +- if( sContext.isError ){ ++ if( sContext.isError>0 ){ ++ sqlite3VdbeError(p, "%s", sqlite3_value_text(pDest)); + rc = sContext.isError; + } + sqlite3VdbeChangeEncoding(pDest, encoding); +@@ -85724,7 +90036,10 @@ + case OP_VRename: { + sqlite3_vtab *pVtab; + Mem *pName; +- ++ int isLegacy; ++ ++ isLegacy = (db->flags & SQLITE_LegacyAlter); ++ db->flags |= SQLITE_LegacyAlter; + pVtab = pOp->p4.pVtab->pVtab; + pName = &aMem[pOp->p1]; + assert( pVtab->pModule->xRename ); +@@ -85738,6 +90053,7 @@ + rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8); + if( rc ) goto abort_due_to_error; + rc = pVtab->pModule->xRename(pVtab, pName->z); ++ if( isLegacy==0 ) db->flags &= ~SQLITE_LegacyAlter; + sqlite3VtabImportErrmsg(p, pVtab); + p->expired = 0; + if( rc ) goto abort_due_to_error; +@@ -85786,6 +90102,8 @@ + || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace + ); + assert( p->readOnly==0 ); ++ if( db->mallocFailed ) goto no_mem; ++ sqlite3VdbeIncrWriteCounter(p, 0); + pVtab = pOp->p4.pVtab->pVtab; + if( pVtab==0 || NEVER(pVtab->pModule==0) ){ + rc = SQLITE_LOCKED; +@@ -85906,8 +90224,8 @@ + ** + ** See also: Function0, AggStep, AggFinal + */ +-case OP_PureFunc0: +-case OP_Function0: { ++case OP_PureFunc0: /* group */ ++case OP_Function0: { /* group */ + int n; + sqlite3_context *pCtx; + +@@ -85922,6 +90240,7 @@ + pCtx->pFunc = pOp->p4.pFunc; + pCtx->iOp = (int)(pOp - aOp); + pCtx->pVdbe = p; ++ pCtx->isError = 0; + pCtx->argc = n; + pOp->p4type = P4_FUNCCTX; + pOp->p4.pCtx = pCtx; +@@ -85930,8 +90249,8 @@ + pOp->opcode += 2; + /* Fall through into OP_Function */ + } +-case OP_PureFunc: +-case OP_Function: { ++case OP_PureFunc: /* group */ ++case OP_Function: { /* group */ + int i; + sqlite3_context *pCtx; + +@@ -85956,16 +90275,17 @@ + } + #endif + MemSetTypeFlag(pOut, MEM_Null); +- pCtx->fErrorOrAux = 0; ++ assert( pCtx->isError==0 ); + (*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */ + + /* If the function returned an error, throw an exception */ +- if( pCtx->fErrorOrAux ){ +- if( pCtx->isError ){ ++ if( pCtx->isError ){ ++ if( pCtx->isError>0 ){ + sqlite3VdbeError(p, "%s", sqlite3_value_text(pOut)); + rc = pCtx->isError; + } + sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1); ++ pCtx->isError = 0; + if( rc ) goto abort_due_to_error; + } + +@@ -85980,8 +90300,14 @@ + break; + } + +- +-/* Opcode: Init P1 P2 * P4 * ++/* Opcode: Trace P1 P2 * P4 * ++** ++** Write P4 on the statement trace output if statement tracing is ++** enabled. ++** ++** Operand P1 must be 0x7fffffff and P2 must positive. ++*/ ++/* Opcode: Init P1 P2 P3 P4 * + ** Synopsis: Start at P2 + ** + ** Programs contain a single instance of this opcode as the very first +@@ -85995,10 +90321,16 @@ + ** + ** Increment the value of P1 so that OP_Once opcodes will jump the + ** first time they are evaluated for this run. ++** ++** If P3 is not zero, then it is an address to jump to if an SQLITE_CORRUPT ++** error is encountered. + */ ++case OP_Trace: + case OP_Init: { /* jump */ ++ int i; ++#ifndef SQLITE_OMIT_TRACE + char *zTrace; +- int i; ++#endif + + /* If the P4 argument is not NULL, then it must be an SQL comment string. + ** The "--" string is broken up to prevent false-positives with srcck1.c. +@@ -86010,8 +90342,10 @@ + ** sqlite3_expanded_sql(P) otherwise. + */ + assert( pOp->p4.z==0 || strncmp(pOp->p4.z, "-" "- ", 3)==0 ); +- assert( pOp==p->aOp ); /* Always instruction 0 */ + ++ /* OP_Init is always instruction 0 */ ++ assert( pOp==p->aOp || pOp->opcode==OP_Trace ); ++ + #ifndef SQLITE_OMIT_TRACE + if( (db->mTrace & (SQLITE_TRACE_STMT|SQLITE_TRACE_LEGACY))!=0 + && !p->doingRerun +@@ -86053,6 +90387,7 @@ + #endif /* SQLITE_OMIT_TRACE */ + assert( pOp->p2>0 ); + if( pOp->p1>=sqlite3GlobalConfig.iOnceResetThreshold ){ ++ if( pOp->opcode==OP_Trace ) break; + for(i=1; i<p->nOp; i++){ + if( p->aOp[i].opcode==OP_Once ) p->aOp[i].p1 = 0; + } +@@ -86086,6 +90421,22 @@ + } + #endif /* SQLITE_ENABLE_CURSOR_HINTS */ + ++#ifdef SQLITE_DEBUG ++/* Opcode: Abortable * * * * * ++** ++** Verify that an Abort can happen. Assert if an Abort at this point ++** might cause database corruption. This opcode only appears in debugging ++** builds. ++** ++** An Abort is safe if either there have been no writes, or if there is ++** an active statement journal. ++*/ ++case OP_Abortable: { ++ sqlite3VdbeAssertAbortable(p); ++ break; ++} ++#endif ++ + /* Opcode: Noop * * * * * + ** + ** Do nothing. This instruction is often useful as a jump +@@ -86097,8 +90448,9 @@ + ** This opcode records information from the optimizer. It is the + ** the same as a no-op. This opcodesnever appears in a real VM program. + */ +-default: { /* This is really OP_Noop and OP_Explain */ ++default: { /* This is really OP_Noop, OP_Explain */ + assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain ); ++ + break; + } + +@@ -86112,7 +90464,7 @@ + + #ifdef VDBE_PROFILE + { +- u64 endTime = sqlite3Hwtime(); ++ u64 endTime = sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime(); + if( endTime>start ) pOrigOp->cycles += endTime - start; + pOrigOp->cnt++; + } +@@ -86269,11 +90621,12 @@ + v->aMem[1].u.i = iRow; + + /* If the statement has been run before (and is paused at the OP_ResultRow) +- ** then back it up to the point where it does the OP_SeekRowid. This could ++ ** then back it up to the point where it does the OP_NotExists. This could + ** have been down with an extra OP_Goto, but simply setting the program + ** counter is faster. */ +- if( v->pc>3 ){ +- v->pc = 3; ++ if( v->pc>4 ){ ++ v->pc = 4; ++ assert( v->aOp[v->pc].opcode==OP_NotExists ); + rc = sqlite3VdbeExec(v); + }else{ + rc = sqlite3_step(p->pStmt); +@@ -86335,8 +90688,8 @@ + int rc = SQLITE_OK; + char *zErr = 0; + Table *pTab; +- Parse *pParse = 0; + Incrblob *pBlob = 0; ++ Parse sParse; + + #ifdef SQLITE_ENABLE_API_ARMOR + if( ppBlob==0 ){ +@@ -86354,37 +90707,34 @@ + sqlite3_mutex_enter(db->mutex); + + pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob)); +- if( !pBlob ) goto blob_open_out; +- pParse = sqlite3StackAllocRaw(db, sizeof(*pParse)); +- if( !pParse ) goto blob_open_out; +- + do { +- memset(pParse, 0, sizeof(Parse)); +- pParse->db = db; ++ memset(&sParse, 0, sizeof(Parse)); ++ if( !pBlob ) goto blob_open_out; ++ sParse.db = db; + sqlite3DbFree(db, zErr); + zErr = 0; + + sqlite3BtreeEnterAll(db); +- pTab = sqlite3LocateTable(pParse, 0, zTable, zDb); ++ pTab = sqlite3LocateTable(&sParse, 0, zTable, zDb); + if( pTab && IsVirtual(pTab) ){ + pTab = 0; +- sqlite3ErrorMsg(pParse, "cannot open virtual table: %s", zTable); ++ sqlite3ErrorMsg(&sParse, "cannot open virtual table: %s", zTable); + } + if( pTab && !HasRowid(pTab) ){ + pTab = 0; +- sqlite3ErrorMsg(pParse, "cannot open table without rowid: %s", zTable); ++ sqlite3ErrorMsg(&sParse, "cannot open table without rowid: %s", zTable); + } + #ifndef SQLITE_OMIT_VIEW + if( pTab && pTab->pSelect ){ + pTab = 0; +- sqlite3ErrorMsg(pParse, "cannot open view: %s", zTable); ++ sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable); + } + #endif + if( !pTab ){ +- if( pParse->zErrMsg ){ ++ if( sParse.zErrMsg ){ + sqlite3DbFree(db, zErr); +- zErr = pParse->zErrMsg; +- pParse->zErrMsg = 0; ++ zErr = sParse.zErrMsg; ++ sParse.zErrMsg = 0; + } + rc = SQLITE_ERROR; + sqlite3BtreeLeaveAll(db); +@@ -86448,7 +90798,7 @@ + } + } + +- pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(pParse); ++ pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(&sParse); + assert( pBlob->pStmt || db->mallocFailed ); + if( pBlob->pStmt ){ + +@@ -86484,7 +90834,8 @@ + sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, wrFlag, + pTab->pSchema->schema_cookie, + pTab->pSchema->iGeneration); +- sqlite3VdbeChangeP5(v, 1); ++ sqlite3VdbeChangeP5(v, 1); ++ assert( sqlite3VdbeCurrentAddr(v)==2 || db->mallocFailed ); + aOp = sqlite3VdbeAddOpList(v, ArraySize(openBlob), openBlob, iLn); + + /* Make sure a mutex is held on the table to be accessed */ +@@ -86499,7 +90850,7 @@ + aOp[0].p1 = iDb; + aOp[0].p2 = pTab->tnum; + aOp[0].p3 = wrFlag; +- sqlite3VdbeChangeP4(v, 1, pTab->zName, P4_TRANSIENT); ++ sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT); + } + if( db->mallocFailed==0 ){ + #endif +@@ -86521,10 +90872,10 @@ + aOp[1].p4.i = pTab->nCol+1; + aOp[3].p2 = pTab->nCol; + +- pParse->nVar = 0; +- pParse->nMem = 1; +- pParse->nTab = 1; +- sqlite3VdbeMakeReady(v, pParse); ++ sParse.nVar = 0; ++ sParse.nMem = 1; ++ sParse.nTab = 1; ++ sqlite3VdbeMakeReady(v, &sParse); + } + } + +@@ -86546,8 +90897,7 @@ + } + sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr); + sqlite3DbFree(db, zErr); +- sqlite3ParserReset(pParse); +- sqlite3StackFree(db, pParse); ++ sqlite3ParserReset(&sParse); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; +@@ -87541,7 +91891,7 @@ + } + + if( res==0 ){ +- if( pTask->pSorter->pKeyInfo->nField>1 ){ ++ if( pTask->pSorter->pKeyInfo->nKeyField>1 ){ + res = vdbeSorterCompareTail( + pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 + ); +@@ -87610,7 +91960,7 @@ + } + + if( res==0 ){ +- if( pTask->pSorter->pKeyInfo->nField>1 ){ ++ if( pTask->pSorter->pKeyInfo->nKeyField>1 ){ + res = vdbeSorterCompareTail( + pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 + ); +@@ -87625,7 +91975,7 @@ + /* + ** Initialize the temporary index cursor just opened as a sorter cursor. + ** +-** Usually, the sorter module uses the value of (pCsr->pKeyInfo->nField) ++** Usually, the sorter module uses the value of (pCsr->pKeyInfo->nKeyField) + ** to determine the number of fields that should be compared from the + ** records being sorted. However, if the value passed as argument nField + ** is non-zero and the sorter is able to guarantee a stable sort, nField +@@ -87678,7 +92028,7 @@ + + assert( pCsr->pKeyInfo && pCsr->pBtx==0 ); + assert( pCsr->eCurType==CURTYPE_SORTER ); +- szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nField-1)*sizeof(CollSeq*); ++ szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nKeyField-1)*sizeof(CollSeq*); + sz = sizeof(VdbeSorter) + nWorker * sizeof(SortSubtask); + + pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo); +@@ -87690,8 +92040,7 @@ + memcpy(pKeyInfo, pCsr->pKeyInfo, szKeyInfo); + pKeyInfo->db = 0; + if( nField && nWorker==0 ){ +- pKeyInfo->nXField += (pKeyInfo->nField - nField); +- pKeyInfo->nField = nField; ++ pKeyInfo->nKeyField = nField; + } + pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt); + pSorter->nTask = nWorker + 1; +@@ -87719,11 +92068,9 @@ + mxCache = MIN(mxCache, SQLITE_MAX_PMASZ); + pSorter->mxPmaSize = MAX(pSorter->mnPmaSize, (int)mxCache); + +- /* EVIDENCE-OF: R-26747-61719 When the application provides any amount of +- ** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary +- ** large heap allocations. +- */ +- if( sqlite3GlobalConfig.pScratch==0 ){ ++ /* Avoid large memory allocations if the application has requested ++ ** SQLITE_CONFIG_SMALL_MALLOC. */ ++ if( sqlite3GlobalConfig.bSmallMalloc==0 ){ + assert( pSorter->iMemory==0 ); + pSorter->nMemory = pgsz; + pSorter->list.aMemory = (u8*)sqlite3Malloc(pgsz); +@@ -87731,7 +92078,7 @@ + } + } + +- if( (pKeyInfo->nField+pKeyInfo->nXField)<13 ++ if( pKeyInfo->nAllField<13 + && (pKeyInfo->aColl[0]==0 || pKeyInfo->aColl[0]==db->pDfltColl) + ){ + pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT; +@@ -88046,7 +92393,7 @@ + if( pTask->pUnpacked==0 ){ + pTask->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pTask->pSorter->pKeyInfo); + if( pTask->pUnpacked==0 ) return SQLITE_NOMEM_BKPT; +- pTask->pUnpacked->nField = pTask->pSorter->pKeyInfo->nField; ++ pTask->pUnpacked->nField = pTask->pSorter->pKeyInfo->nKeyField; + pTask->pUnpacked->errCode = 0; + } + return SQLITE_OK; +@@ -88828,8 +93175,12 @@ + ){ + int rc = SQLITE_OK; /* Return code */ + int i; /* For looping over PmaReader objects */ +- int nTree = pMerger->nTree; ++ int nTree; /* Number of subtrees to merge */ + ++ /* Failure to allocate the merge would have been detected prior to ++ ** invoking this routine */ ++ assert( pMerger!=0 ); ++ + /* eMode is always INCRINIT_NORMAL in single-threaded mode */ + assert( SQLITE_MAX_WORKER_THREADS>0 || eMode==INCRINIT_NORMAL ); + +@@ -88837,6 +93188,7 @@ + assert( pMerger->pTask==0 ); + pMerger->pTask = pTask; + ++ nTree = pMerger->nTree; + for(i=0; i<nTree; i++){ + if( SQLITE_MAX_WORKER_THREADS>0 && eMode==INCRINIT_ROOT ){ + /* PmaReaders should be normally initialized in order, as if they are +@@ -89570,7 +93922,8 @@ + int iChunkOffset; + FileChunk *pChunk; + +-#ifdef SQLITE_ENABLE_ATOMIC_WRITE ++#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \ ++ || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) + if( (iAmt+iOfst)>p->endpoint.iOffset ){ + return SQLITE_IOERR_SHORT_READ; + } +@@ -89689,7 +94042,8 @@ + ** atomic-write optimization. In this case the first 28 bytes of the + ** journal file may be written as part of committing the transaction. */ + assert( iOfst==p->endpoint.iOffset || iOfst==0 ); +-#ifdef SQLITE_ENABLE_ATOMIC_WRITE ++#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \ ++ || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) + if( iOfst==0 && p->pFirst ){ + assert( p->nChunkSize>iAmt ); + memcpy((u8*)p->pFirst->zChunk, zBuf, iAmt); +@@ -89858,17 +94212,31 @@ + sqlite3JournalOpen(0, 0, pJfd, 0, -1); + } + +-#ifdef SQLITE_ENABLE_ATOMIC_WRITE ++#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \ ++ || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) + /* + ** If the argument p points to a MemJournal structure that is not an + ** in-memory-only journal file (i.e. is one that was opened with a +ve +-** nSpill parameter), and the underlying file has not yet been created, +-** create it now. ++** nSpill parameter or as SQLITE_OPEN_MAIN_JOURNAL), and the underlying ++** file has not yet been created, create it now. + */ +-SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *p){ ++SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *pJfd){ + int rc = SQLITE_OK; +- if( p->pMethods==&MemJournalMethods && ((MemJournal*)p)->nSpill>0 ){ +- rc = memjrnlCreateFile((MemJournal*)p); ++ MemJournal *p = (MemJournal*)pJfd; ++ if( p->pMethod==&MemJournalMethods && ( ++#ifdef SQLITE_ENABLE_ATOMIC_WRITE ++ p->nSpill>0 ++#else ++ /* While this appears to not be possible without ATOMIC_WRITE, the ++ ** paths are complex, so it seems prudent to leave the test in as ++ ** a NEVER(), in case our analysis is subtly flawed. */ ++ NEVER(p->nSpill>0) ++#endif ++#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE ++ || (p->flags & SQLITE_OPEN_MAIN_JOURNAL) ++#endif ++ )){ ++ rc = memjrnlCreateFile(p); + } + return rc; + } +@@ -89935,18 +94303,30 @@ + int rc; + testcase( ExprHasProperty(pExpr, EP_TokenOnly) ); + testcase( ExprHasProperty(pExpr, EP_Reduced) ); +- rc = pWalker->xExprCallback(pWalker, pExpr); +- if( rc ) return rc & WRC_Abort; +- if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){ +- if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort; +- assert( pExpr->x.pList==0 || pExpr->pRight==0 ); +- if( pExpr->pRight ){ +- if( walkExpr(pWalker, pExpr->pRight) ) return WRC_Abort; +- }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){ +- if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort; +- }else if( pExpr->x.pList ){ +- if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort; ++ while(1){ ++ rc = pWalker->xExprCallback(pWalker, pExpr); ++ if( rc ) return rc & WRC_Abort; ++ if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){ ++ if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort; ++ assert( pExpr->x.pList==0 || pExpr->pRight==0 ); ++ if( pExpr->pRight ){ ++ pExpr = pExpr->pRight; ++ continue; ++ }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){ ++ if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort; ++ }else if( pExpr->x.pList ){ ++ if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort; ++ } ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( ExprHasProperty(pExpr, EP_WinFunc) ){ ++ Window *pWin = pExpr->y.pWin; ++ if( sqlite3WalkExprList(pWalker, pWin->pPartition) ) return WRC_Abort; ++ if( sqlite3WalkExprList(pWalker, pWin->pOrderBy) ) return WRC_Abort; ++ if( sqlite3WalkExpr(pWalker, pWin->pFilter) ) return WRC_Abort; ++ } ++#endif + } ++ break; + } + return WRC_Continue; + } +@@ -89982,7 +94362,6 @@ + if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort; + if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort; + if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort; +- if( sqlite3WalkExpr(pWalker, p->pOffset) ) return WRC_Abort; + return WRC_Continue; + } + +@@ -89999,17 +94378,16 @@ + struct SrcList_item *pItem; + + pSrc = p->pSrc; +- if( ALWAYS(pSrc) ){ +- for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){ +- if( pItem->pSelect && sqlite3WalkSelect(pWalker, pItem->pSelect) ){ +- return WRC_Abort; +- } +- if( pItem->fg.isTabFunc +- && sqlite3WalkExprList(pWalker, pItem->u1.pFuncArg) +- ){ +- return WRC_Abort; +- } ++ assert( pSrc!=0 ); ++ for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){ ++ if( pItem->pSelect && sqlite3WalkSelect(pWalker, pItem->pSelect) ){ ++ return WRC_Abort; + } ++ if( pItem->fg.isTabFunc ++ && sqlite3WalkExprList(pWalker, pItem->u1.pFuncArg) ++ ){ ++ return WRC_Abort; ++ } + } + return WRC_Continue; + } +@@ -90130,29 +94508,31 @@ + assert( pOrig!=0 ); + db = pParse->db; + pDup = sqlite3ExprDup(db, pOrig, 0); +- if( pDup==0 ) return; +- if( zType[0]!='G' ) incrAggFunctionDepth(pDup, nSubquery); +- if( pExpr->op==TK_COLLATE ){ +- pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken); +- } +- ExprSetProperty(pDup, EP_Alias); ++ if( pDup!=0 ){ ++ if( zType[0]!='G' ) incrAggFunctionDepth(pDup, nSubquery); ++ if( pExpr->op==TK_COLLATE ){ ++ pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken); ++ } ++ ExprSetProperty(pDup, EP_Alias); + +- /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This +- ** prevents ExprDelete() from deleting the Expr structure itself, +- ** allowing it to be repopulated by the memcpy() on the following line. +- ** The pExpr->u.zToken might point into memory that will be freed by the +- ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to +- ** make a copy of the token before doing the sqlite3DbFree(). +- */ +- ExprSetProperty(pExpr, EP_Static); +- sqlite3ExprDelete(db, pExpr); +- memcpy(pExpr, pDup, sizeof(*pExpr)); +- if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){ +- assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 ); +- pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken); +- pExpr->flags |= EP_MemToken; ++ /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This ++ ** prevents ExprDelete() from deleting the Expr structure itself, ++ ** allowing it to be repopulated by the memcpy() on the following line. ++ ** The pExpr->u.zToken might point into memory that will be freed by the ++ ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to ++ ** make a copy of the token before doing the sqlite3DbFree(). ++ */ ++ ExprSetProperty(pExpr, EP_Static); ++ sqlite3ExprDelete(db, pExpr); ++ memcpy(pExpr, pDup, sizeof(*pExpr)); ++ if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){ ++ assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 ); ++ pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken); ++ pExpr->flags |= EP_MemToken; ++ } ++ sqlite3DbFree(db, pDup); + } +- sqlite3DbFree(db, pDup); ++ ExprSetProperty(pExpr, EP_Alias); + } + + +@@ -90212,7 +94592,7 @@ + ** (even if X is implied). + ** pExpr->iTable Set to the cursor number for the table obtained + ** from pSrcList. +-** pExpr->pTab Points to the Table structure of X.Y (even if ++** pExpr->y.pTab Points to the Table structure of X.Y (even if + ** X and/or Y are implied.) + ** pExpr->iColumn Set to the column number within the table. + ** pExpr->op Set to TK_COLUMN. +@@ -90246,7 +94626,7 @@ + struct SrcList_item *pMatch = 0; /* The matching pSrcList item */ + NameContext *pTopNC = pNC; /* First namecontext in the list */ + Schema *pSchema = 0; /* Schema of the expression */ +- int isTrigger = 0; /* True if resolved to a trigger column */ ++ int eNewExprOp = TK_COLUMN; /* New value for pExpr->op on success */ + Table *pTab = 0; /* Table hold the row */ + Column *pCol; /* A column of pTab */ + +@@ -90256,7 +94636,6 @@ + + /* Initialize the node to no-match */ + pExpr->iTable = -1; +- pExpr->pTab = 0; + ExprSetVVAProperty(pExpr, EP_NoReduce); + + /* Translate the schema name in zDb into a pointer to the corresponding +@@ -90317,6 +94696,9 @@ + if( sqlite3StrICmp(zTabName, zTab)!=0 ){ + continue; + } ++ if( IN_RENAME_OBJECT && pItem->zAlias ){ ++ sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab); ++ } + } + if( 0==(cntTab++) ){ + pMatch = pItem; +@@ -90341,32 +94723,45 @@ + } + if( pMatch ){ + pExpr->iTable = pMatch->iCursor; +- pExpr->pTab = pMatch->pTab; ++ pExpr->y.pTab = pMatch->pTab; + /* RIGHT JOIN not (yet) supported */ + assert( (pMatch->fg.jointype & JT_RIGHT)==0 ); + if( (pMatch->fg.jointype & JT_LEFT)!=0 ){ + ExprSetProperty(pExpr, EP_CanBeNull); + } +- pSchema = pExpr->pTab->pSchema; ++ pSchema = pExpr->y.pTab->pSchema; + } + } /* if( pSrcList ) */ + +-#ifndef SQLITE_OMIT_TRIGGER ++#if !defined(SQLITE_OMIT_TRIGGER) || !defined(SQLITE_OMIT_UPSERT) + /* If we have not already resolved the name, then maybe +- ** it is a new.* or old.* trigger argument reference ++ ** it is a new.* or old.* trigger argument reference. Or ++ ** maybe it is an excluded.* from an upsert. + */ +- if( zDb==0 && zTab!=0 && cntTab==0 && pParse->pTriggerTab!=0 ){ +- int op = pParse->eTriggerOp; +- assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT ); +- if( op!=TK_DELETE && sqlite3StrICmp("new",zTab) == 0 ){ +- pExpr->iTable = 1; +- pTab = pParse->pTriggerTab; +- }else if( op!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){ +- pExpr->iTable = 0; +- pTab = pParse->pTriggerTab; +- }else{ +- pTab = 0; ++ if( zDb==0 && zTab!=0 && cntTab==0 ){ ++ 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( op!=TK_DELETE && sqlite3StrICmp("new",zTab) == 0 ){ ++ pExpr->iTable = 1; ++ pTab = pParse->pTriggerTab; ++ }else if( op!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){ ++ pExpr->iTable = 0; ++ pTab = pParse->pTriggerTab; ++ } + } ++#endif /* SQLITE_OMIT_TRIGGER */ ++#ifndef SQLITE_OMIT_UPSERT ++ if( (pNC->ncFlags & NC_UUpsert)!=0 ){ ++ Upsert *pUpsert = pNC->uNC.pUpsert; ++ if( pUpsert && sqlite3StrICmp("excluded",zTab)==0 ){ ++ pTab = pUpsert->pUpsertSrc->a[0].pTab; ++ pExpr->iTable = 2; ++ } ++ } ++#endif /* SQLITE_OMIT_UPSERT */ + + if( pTab ){ + int iCol; +@@ -90386,24 +94781,42 @@ + } + if( iCol<pTab->nCol ){ + cnt++; +- if( iCol<0 ){ +- pExpr->affinity = SQLITE_AFF_INTEGER; +- }else if( pExpr->iTable==0 ){ +- testcase( iCol==31 ); +- testcase( iCol==32 ); +- pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol)); +- }else{ +- testcase( iCol==31 ); +- testcase( iCol==32 ); +- pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol)); ++#ifndef SQLITE_OMIT_UPSERT ++ if( pExpr->iTable==2 ){ ++ testcase( iCol==(-1) ); ++ if( IN_RENAME_OBJECT ){ ++ pExpr->iColumn = iCol; ++ pExpr->y.pTab = pTab; ++ eNewExprOp = TK_COLUMN; ++ }else{ ++ pExpr->iTable = pNC->uNC.pUpsert->regData + iCol; ++ eNewExprOp = TK_REGISTER; ++ ExprSetProperty(pExpr, EP_Alias); ++ } ++ }else ++#endif /* SQLITE_OMIT_UPSERT */ ++ { ++#ifndef SQLITE_OMIT_TRIGGER ++ if( iCol<0 ){ ++ pExpr->affinity = SQLITE_AFF_INTEGER; ++ }else if( pExpr->iTable==0 ){ ++ testcase( iCol==31 ); ++ testcase( iCol==32 ); ++ pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol)); ++ }else{ ++ testcase( iCol==31 ); ++ testcase( iCol==32 ); ++ pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol)); ++ } ++ pExpr->y.pTab = pTab; ++ pExpr->iColumn = (i16)iCol; ++ eNewExprOp = TK_TRIGGER; ++#endif /* SQLITE_OMIT_TRIGGER */ + } +- pExpr->iColumn = (i16)iCol; +- pExpr->pTab = pTab; +- isTrigger = 1; + } + } + } +-#endif /* !defined(SQLITE_OMIT_TRIGGER) */ ++#endif /* !defined(SQLITE_OMIT_TRIGGER) || !defined(SQLITE_OMIT_UPSERT) */ + + /* + ** Perhaps the name is a reference to the ROWID +@@ -90438,10 +94851,12 @@ + ** is supported for backwards compatibility only. Hence, we issue a warning + ** on sqlite3_log() whenever the capability is used. + */ +- if( (pEList = pNC->pEList)!=0 ++ if( (pNC->ncFlags & NC_UEList)!=0 ++ && cnt==0 + && zTab==0 +- && cnt==0 + ){ ++ pEList = pNC->uNC.pEList; ++ assert( pEList!=0 ); + for(j=0; j<pEList->nExpr; j++){ + char *zAs = pEList->a[j].zName; + if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ +@@ -90462,6 +94877,9 @@ + cnt = 1; + pMatch = 0; + assert( zTab==0 && zDb==0 ); ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameTokenRemap(pParse, 0, (void*)pExpr); ++ } + goto lookupname_end; + } + } +@@ -90486,10 +94904,16 @@ + ** Because no reference was made to outer contexts, the pNC->nRef + ** fields are not changed in any context. + */ +- if( cnt==0 && zTab==0 && ExprHasProperty(pExpr,EP_DblQuoted) ){ +- pExpr->op = TK_STRING; +- pExpr->pTab = 0; +- return WRC_Prune; ++ if( cnt==0 && zTab==0 ){ ++ assert( pExpr->op==TK_ID ); ++ if( ExprHasProperty(pExpr,EP_DblQuoted) ){ ++ pExpr->op = TK_STRING; ++ pExpr->y.pTab = 0; ++ return WRC_Prune; ++ } ++ if( sqlite3ExprIdToTrueFalse(pExpr) ){ ++ return WRC_Prune; ++ } + } + + /* +@@ -90532,7 +94956,7 @@ + pExpr->pLeft = 0; + sqlite3ExprDelete(db, pExpr->pRight); + pExpr->pRight = 0; +- pExpr->op = (isTrigger ? TK_TRIGGER : TK_COLUMN); ++ pExpr->op = eNewExprOp; + ExprSetProperty(pExpr, EP_Leaf); + lookupname_end: + if( cnt==1 ){ +@@ -90562,9 +94986,9 @@ + Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0); + if( p ){ + struct SrcList_item *pItem = &pSrc->a[iSrc]; +- p->pTab = pItem->pTab; ++ p->y.pTab = pItem->pTab; + p->iTable = pItem->iCursor; +- if( p->pTab->iPKey==iCol ){ ++ if( p->y.pTab->iPKey==iCol ){ + p->iColumn = -1; + }else{ + p->iColumn = (ynVar)iCol; +@@ -90651,9 +95075,10 @@ + SrcList *pSrcList = pNC->pSrcList; + struct SrcList_item *pItem; + assert( pSrcList && pSrcList->nSrc==1 ); +- pItem = pSrcList->a; ++ pItem = pSrcList->a; ++ assert( HasRowid(pItem->pTab) && pItem->pTab->pSelect==0 ); + pExpr->op = TK_COLUMN; +- pExpr->pTab = pItem->pTab; ++ pExpr->y.pTab = pItem->pTab; + pExpr->iTable = pItem->iCursor; + pExpr->iColumn = -1; + pExpr->affinity = SQLITE_AFF_INTEGER; +@@ -90682,18 +95107,23 @@ + zTable = 0; + zColumn = pExpr->u.zToken; + }else{ ++ Expr *pLeft = pExpr->pLeft; + notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr); + pRight = pExpr->pRight; + if( pRight->op==TK_ID ){ + zDb = 0; +- zTable = pExpr->pLeft->u.zToken; +- zColumn = pRight->u.zToken; + }else{ + assert( pRight->op==TK_DOT ); +- zDb = pExpr->pLeft->u.zToken; +- zTable = pRight->pLeft->u.zToken; +- zColumn = pRight->pRight->u.zToken; ++ zDb = pLeft->u.zToken; ++ pLeft = pRight->pLeft; ++ pRight = pRight->pRight; + } ++ zTable = pLeft->u.zToken; ++ zColumn = pRight->u.zToken; ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameTokenRemap(pParse, (void*)pExpr, (void*)pRight); ++ sqlite3RenameTokenRemap(pParse, (void*)&pExpr->y.pTab, (void*)pLeft); ++ } + } + return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr); + } +@@ -90774,41 +95204,105 @@ + notValid(pParse, pNC, "non-deterministic functions", + NC_IdxExpr|NC_PartIdx); + } ++ if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0 ++ && pParse->nested==0 ++ && sqlite3Config.bInternalFunctions==0 ++ ){ ++ /* Internal-use-only functions are disallowed unless the ++ ** SQL is being compiled using sqlite3NestedParse() */ ++ no_such_func = 1; ++ pDef = 0; ++ } + } +- if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ +- sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); +- pNC->nErr++; +- is_agg = 0; +- }else if( no_such_func && pParse->db->init.busy==0 ++ ++ if( 0==IN_RENAME_OBJECT ){ ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ assert( is_agg==0 || (pDef->funcFlags & SQLITE_FUNC_MINMAX) ++ || (pDef->xValue==0 && pDef->xInverse==0) ++ || (pDef->xValue && pDef->xInverse && pDef->xSFunc && pDef->xFinalize) ++ ); ++ if( pDef && pDef->xValue==0 && ExprHasProperty(pExpr, EP_WinFunc) ){ ++ sqlite3ErrorMsg(pParse, ++ "%.*s() may not be used as a window function", nId, zId ++ ); ++ pNC->nErr++; ++ }else if( ++ (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) ++ || (is_agg && (pDef->funcFlags&SQLITE_FUNC_WINDOW) && !pExpr->y.pWin) ++ || (is_agg && pExpr->y.pWin && (pNC->ncFlags & NC_AllowWin)==0) ++ ){ ++ const char *zType; ++ if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->y.pWin ){ ++ zType = "window"; ++ }else{ ++ zType = "aggregate"; ++ } ++ sqlite3ErrorMsg(pParse, "misuse of %s function %.*s()",zType,nId,zId); ++ pNC->nErr++; ++ is_agg = 0; ++ } ++#else ++ if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) ){ ++ sqlite3ErrorMsg(pParse,"misuse of aggregate function %.*s()",nId,zId); ++ pNC->nErr++; ++ is_agg = 0; ++ } ++#endif ++ else if( no_such_func && pParse->db->init.busy==0 + #ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION +- && pParse->explain==0 ++ && pParse->explain==0 + #endif +- ){ +- sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId); +- pNC->nErr++; +- }else if( wrong_num_args ){ +- sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()", +- nId, zId); +- pNC->nErr++; ++ ){ ++ sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId); ++ pNC->nErr++; ++ }else if( wrong_num_args ){ ++ sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()", ++ nId, zId); ++ pNC->nErr++; ++ } ++ if( is_agg ){ ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ pNC->ncFlags &= ~(pExpr->y.pWin ? NC_AllowWin : NC_AllowAgg); ++#else ++ pNC->ncFlags &= ~NC_AllowAgg; ++#endif ++ } + } +- if( is_agg ) pNC->ncFlags &= ~NC_AllowAgg; + sqlite3WalkExprList(pWalker, pList); + if( is_agg ){ +- NameContext *pNC2 = pNC; +- pExpr->op = TK_AGG_FUNCTION; +- pExpr->op2 = 0; +- while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){ +- pExpr->op2++; +- pNC2 = pNC2->pNext; +- } +- assert( pDef!=0 ); +- if( pNC2 ){ +- assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg ); +- testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 ); +- pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( pExpr->y.pWin ){ ++ Select *pSel = pNC->pWinSelect; ++ sqlite3WalkExprList(pWalker, pExpr->y.pWin->pPartition); ++ sqlite3WalkExprList(pWalker, pExpr->y.pWin->pOrderBy); ++ sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter); ++ sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->y.pWin, pDef); ++ if( 0==pSel->pWin ++ || 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->y.pWin) ++ ){ ++ pExpr->y.pWin->pNextWin = pSel->pWin; ++ pSel->pWin = pExpr->y.pWin; ++ } ++ pNC->ncFlags |= NC_AllowWin; ++ }else ++#endif /* SQLITE_OMIT_WINDOWFUNC */ ++ { ++ NameContext *pNC2 = pNC; ++ pExpr->op = TK_AGG_FUNCTION; ++ pExpr->op2 = 0; ++ while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){ ++ pExpr->op2++; ++ pNC2 = pNC2->pNext; ++ } ++ assert( pDef!=0 ); ++ if( pNC2 ){ ++ assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg ); ++ testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 ); ++ pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX); + ++ } ++ pNC->ncFlags |= NC_AllowAgg; + } +- pNC->ncFlags |= NC_AllowAgg; + } + /* FIX ME: Compute pExpr->affinity based on the expected return + ** type of the function +@@ -90837,6 +95331,23 @@ + notValid(pParse, pNC, "parameters", NC_IsCheck|NC_PartIdx|NC_IdxExpr); + break; + } ++ case TK_IS: ++ case TK_ISNOT: { ++ Expr *pRight; ++ assert( !ExprHasProperty(pExpr, EP_Reduced) ); ++ /* Handle special cases of "x IS TRUE", "x IS FALSE", "x IS NOT TRUE", ++ ** and "x IS NOT FALSE". */ ++ if( (pRight = pExpr->pRight)->op==TK_ID ){ ++ int rc = resolveExprStep(pWalker, pRight); ++ if( rc==WRC_Abort ) return WRC_Abort; ++ if( pRight->op==TK_TRUEFALSE ){ ++ pExpr->op2 = pExpr->op; ++ pExpr->op = TK_TRUTH; ++ return WRC_Continue; ++ } ++ } ++ /* Fall thru */ ++ } + case TK_BETWEEN: + case TK_EQ: + case TK_NE: +@@ -90843,9 +95354,7 @@ + case TK_LT: + case TK_LE: + case TK_GT: +- case TK_GE: +- case TK_IS: +- case TK_ISNOT: { ++ case TK_GE: { + int nLeft, nRight; + if( pParse->db->mallocFailed ) break; + assert( pExpr->pLeft!=0 ); +@@ -90948,8 +95457,8 @@ + memset(&nc, 0, sizeof(nc)); + nc.pParse = pParse; + nc.pSrcList = pSelect->pSrc; +- nc.pEList = pEList; +- nc.ncFlags = NC_AllowAgg; ++ nc.uNC.pEList = pEList; ++ nc.ncFlags = NC_AllowAgg|NC_UEList; + nc.nErr = 0; + db = pParse->db; + savedSuppErr = db->suppressErr; +@@ -91014,12 +95523,10 @@ + pOrderBy = pSelect->pOrderBy; + if( pOrderBy==0 ) return 0; + db = pParse->db; +-#if SQLITE_MAX_COLUMN + if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ + sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause"); + return 1; + } +-#endif + for(i=0; i<pOrderBy->nExpr; i++){ + pOrderBy->a[i].done = 0; + } +@@ -91111,12 +95618,10 @@ + struct ExprList_item *pItem; + + if( pOrderBy==0 || pParse->db->mallocFailed ) return 0; +-#if SQLITE_MAX_COLUMN + if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ + sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType); + return 1; + } +-#endif + pEList = pSelect->pEList; + assert( pEList!=0 ); /* sqlite3SelectNew() guarantees this */ + for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){ +@@ -91198,6 +95703,19 @@ + } + for(j=0; j<pSelect->pEList->nExpr; j++){ + if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){ ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( ExprHasProperty(pE, EP_WinFunc) ){ ++ /* Since this window function is being changed into a reference ++ ** to the same window function the result set, remove the instance ++ ** of this window function from the Select.pWin list. */ ++ Window **pp; ++ for(pp=&pSelect->pWin; *pp; pp=&(*pp)->pNextWin){ ++ if( *pp==pE->y.pWin ){ ++ *pp = (*pp)->pNextWin; ++ } ++ } ++ } ++#endif + pItem->u.x.iOrderByCol = j+1; + } + } +@@ -91254,8 +95772,8 @@ + */ + memset(&sNC, 0, sizeof(sNC)); + sNC.pParse = pParse; +- if( sqlite3ResolveExprNames(&sNC, p->pLimit) || +- sqlite3ResolveExprNames(&sNC, p->pOffset) ){ ++ sNC.pWinSelect = p; ++ if( sqlite3ResolveExprNames(&sNC, p->pLimit) ){ + return WRC_Abort; + } + +@@ -91303,12 +95821,13 @@ + /* Set up the local name-context to pass to sqlite3ResolveExprNames() to + ** resolve the result-set expression list. + */ +- sNC.ncFlags = NC_AllowAgg; ++ sNC.ncFlags = NC_AllowAgg|NC_AllowWin; + sNC.pSrcList = p->pSrc; + sNC.pNext = pOuterNC; + + /* Resolve names in the result set. */ + if( sqlite3ResolveExprListNames(&sNC, p->pEList) ) return WRC_Abort; ++ sNC.ncFlags &= ~NC_AllowWin; + + /* If there are no aggregate functions in the result-set, and no GROUP BY + ** expression, do not allow aggregates in any of the other expressions. +@@ -91337,7 +95856,9 @@ + ** Minor point: If this is the case, then the expression will be + ** re-evaluated for each reference to it. + */ +- sNC.pEList = p->pEList; ++ assert( (sNC.ncFlags & (NC_UAggInfo|NC_UUpsert))==0 ); ++ sNC.uNC.pEList = p->pEList; ++ sNC.ncFlags |= NC_UEList; + if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort; + if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort; + +@@ -91355,7 +95876,7 @@ + ** outer queries + */ + sNC.pNext = 0; +- sNC.ncFlags |= NC_AllowAgg; ++ sNC.ncFlags |= NC_AllowAgg|NC_AllowWin; + + /* If this is a converted compound query, move the ORDER BY clause from + ** the sub-query back to the parent query. At this point each term +@@ -91386,6 +95907,7 @@ + if( db->mallocFailed ){ + return WRC_Abort; + } ++ sNC.ncFlags &= ~NC_AllowWin; + + /* Resolve the GROUP BY clause. At the same time, make sure + ** the GROUP BY clause does not contain aggregate functions. +@@ -91570,7 +96092,7 @@ + Table *pTab, /* The table being referenced */ + int type, /* NC_IsCheck or NC_PartIdx or NC_IdxExpr */ + Expr *pExpr, /* Expression to resolve. May be NULL. */ +- ExprList *pList /* Expression list to resolve. May be NUL. */ ++ ExprList *pList /* Expression list to resolve. May be NULL. */ + ){ + SrcList sSrc; /* Fake SrcList for pParse->pNewTable */ + NameContext sNC; /* Name context for pParse->pNewTable */ +@@ -91651,8 +96173,8 @@ + return sqlite3AffinityType(pExpr->u.zToken, 0); + } + #endif +- if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->pTab ){ +- return sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn); ++ if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->y.pTab ){ ++ return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn); + } + if( op==TK_SELECT_COLUMN ){ + assert( pExpr->pLeft->flags&EP_xIsSelect ); +@@ -91717,6 +96239,11 @@ + ** Return the collation sequence for the expression pExpr. If + ** there is no defined collating sequence, return NULL. + ** ++** See also: sqlite3ExprNNCollSeq() ++** ++** The sqlite3ExprNNCollSeq() works the same exact that it returns the ++** default collation if pExpr has no defined collation. ++** + ** The collating sequence might be determined by a COLLATE operator + ** or by the presence of a column with a defined collating sequence. + ** COLLATE operators take first precedence. Left operands take +@@ -91729,27 +96256,27 @@ + while( p ){ + int op = p->op; + if( p->flags & EP_Generic ) break; +- if( op==TK_CAST || op==TK_UPLUS ){ +- p = p->pLeft; +- continue; +- } +- if( op==TK_COLLATE || (op==TK_REGISTER && p->op2==TK_COLLATE) ){ +- pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken); +- break; +- } + if( (op==TK_AGG_COLUMN || op==TK_COLUMN + || op==TK_REGISTER || op==TK_TRIGGER) +- && p->pTab!=0 ++ && p->y.pTab!=0 + ){ +- /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally ++ /* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally + ** a TK_COLUMN but was previously evaluated and cached in a register */ + int j = p->iColumn; + if( j>=0 ){ +- const char *zColl = p->pTab->aCol[j].zColl; ++ const char *zColl = p->y.pTab->aCol[j].zColl; + pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); + } + break; + } ++ if( op==TK_CAST || op==TK_UPLUS ){ ++ p = p->pLeft; ++ continue; ++ } ++ if( op==TK_COLLATE || (op==TK_REGISTER && p->op2==TK_COLLATE) ){ ++ pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken); ++ break; ++ } + if( p->flags & EP_Collate ){ + if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){ + p = p->pLeft; +@@ -91782,6 +96309,32 @@ + } + + /* ++** Return the collation sequence for the expression pExpr. If ++** there is no defined collating sequence, return a pointer to the ++** defautl collation sequence. ++** ++** See also: sqlite3ExprCollSeq() ++** ++** The sqlite3ExprCollSeq() routine works the same except that it ++** returns NULL if there is no defined collation. ++*/ ++SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr){ ++ CollSeq *p = sqlite3ExprCollSeq(pParse, pExpr); ++ if( p==0 ) p = pParse->db->pDfltColl; ++ assert( p!=0 ); ++ return p; ++} ++ ++/* ++** Return TRUE if the two expressions have equivalent collating sequences. ++*/ ++SQLITE_PRIVATE int sqlite3ExprCollSeqMatch(Parse *pParse, Expr *pE1, Expr *pE2){ ++ CollSeq *pColl1 = sqlite3ExprNNCollSeq(pParse, pE1); ++ CollSeq *pColl2 = sqlite3ExprNNCollSeq(pParse, pE2); ++ return sqlite3StrICmp(pColl1->zName, pColl2->zName)==0; ++} ++ ++/* + ** pExpr is an operand of a comparison operator. aff2 is the + ** type affinity of the other operand. This routine returns the + ** type affinity that should be used for the comparison operator. +@@ -92143,7 +96696,6 @@ + Expr *pL, *pR; + int r1, r2; + assert( i>=0 && i<nLeft ); +- if( i>0 ) sqlite3ExprCachePush(pParse); + r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, ®Free1); + r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, ®Free2); + codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5); +@@ -92155,7 +96707,6 @@ + testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); + sqlite3ReleaseTempReg(pParse, regFree1); + sqlite3ReleaseTempReg(pParse, regFree2); +- if( i>0 ) sqlite3ExprCachePop(pParse); + if( i==nLeft-1 ){ + break; + } +@@ -92220,16 +96771,15 @@ + } + } + } +-static void heightOfSelect(Select *p, int *pnHeight){ +- if( p ){ ++static void heightOfSelect(Select *pSelect, int *pnHeight){ ++ Select *p; ++ for(p=pSelect; p; p=p->pPrior){ + heightOfExpr(p->pWhere, pnHeight); + heightOfExpr(p->pHaving, pnHeight); + heightOfExpr(p->pLimit, pnHeight); +- heightOfExpr(p->pOffset, pnHeight); + heightOfExprList(p->pEList, pnHeight); + heightOfExprList(p->pGroupBy, pnHeight); + heightOfExprList(p->pOrderBy, pnHeight); +- heightOfSelect(p->pPrior, pnHeight); + } + } + +@@ -92368,7 +96918,7 @@ + ){ + Token x; + x.z = zToken; +- x.n = zToken ? sqlite3Strlen30(zToken) : 0; ++ x.n = sqlite3Strlen30(zToken); + return sqlite3ExprAlloc(db, op, &x, 0); + } + +@@ -92504,7 +97054,12 @@ + ** Construct a new expression node for a function with multiple + ** arguments. + */ +-SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){ ++SQLITE_PRIVATE Expr *sqlite3ExprFunction( ++ Parse *pParse, /* Parsing context */ ++ ExprList *pList, /* Argument list */ ++ Token *pToken, /* Name of the function */ ++ int eDistinct /* SF_Distinct or SF_ALL or 0 */ ++){ + Expr *pNew; + sqlite3 *db = pParse->db; + assert( pToken ); +@@ -92513,9 +97068,14 @@ + sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */ + return 0; + } ++ if( pList && pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ ++ sqlite3ErrorMsg(pParse, "too many arguments on function %T", pToken); ++ } + pNew->x.pList = pList; ++ ExprSetProperty(pNew, EP_HasFunc); + assert( !ExprHasProperty(pNew, EP_xIsSelect) ); + sqlite3ExprSetHeightAndFlags(pParse, pNew); ++ if( eDistinct==SF_Distinct ) ExprSetProperty(pNew, EP_Distinct); + return pNew; + } + +@@ -92607,6 +97167,10 @@ + assert( p!=0 ); + /* Sanity check: Assert that the IntValue is non-negative if it exists */ + assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 ); ++ ++ assert( !ExprHasProperty(p, EP_WinFunc) || p->y.pWin!=0 || db->mallocFailed ); ++ assert( p->op!=TK_FUNCTION || ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ++ || p->y.pWin==0 || ExprHasProperty(p, EP_WinFunc) ); + #ifdef SQLITE_DEBUG + if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){ + assert( p->pLeft==0 ); +@@ -92625,6 +97189,10 @@ + }else{ + sqlite3ExprListDelete(db, p->x.pList); + } ++ if( ExprHasProperty(p, EP_WinFunc) ){ ++ assert( p->op==TK_FUNCTION ); ++ sqlite3WindowDelete(db, p->y.pWin); ++ } + } + if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken); + if( !ExprHasProperty(p, EP_Static) ){ +@@ -92673,7 +97241,7 @@ + ** Note that with flags==EXPRDUP_REDUCE, this routines works on full-size + ** (unreduced) Expr objects as they or originally constructed by the parser. + ** During expression analysis, extra information is computed and moved into +-** later parts of teh Expr object and that extra information might get chopped ++** later parts of the Expr object and that extra information might get chopped + ** off if the expression is reduced. Note also that it does not work to + ** make an EXPRDUP_REDUCE copy of a reduced expression. It is only legal + ** to reduce a pristine expression tree from the parser. The implementation +@@ -92685,7 +97253,11 @@ + assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */ + assert( EXPR_FULLSIZE<=0xfff ); + assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 ); +- if( 0==flags || p->op==TK_SELECT_COLUMN ){ ++ if( 0==flags || p->op==TK_SELECT_COLUMN ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ || ExprHasProperty(p, EP_WinFunc) ++#endif ++ ){ + nSize = EXPR_FULLSIZE; + }else{ + assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); +@@ -92710,7 +97282,7 @@ + static int dupedExprNodeSize(Expr *p, int flags){ + int nByte = dupedExprStructSize(p, flags) & 0xfff; + if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ +- nByte += sqlite3Strlen30(p->u.zToken)+1; ++ nByte += sqlite3Strlen30NN(p->u.zToken)+1; + } + return ROUND8(nByte); + } +@@ -92813,7 +97385,7 @@ + } + + /* Fill in pNew->pLeft and pNew->pRight. */ +- if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){ ++ if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly|EP_WinFunc) ){ + zAlloc += dupedExprNodeSize(p, dupFlags); + if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){ + pNew->pLeft = p->pLeft ? +@@ -92821,6 +97393,12 @@ + pNew->pRight = p->pRight ? + exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0; + } ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( ExprHasProperty(p, EP_WinFunc) ){ ++ pNew->y.pWin = sqlite3WindowDup(db, pNew, p->y.pWin); ++ assert( ExprHasProperty(pNew, EP_WinFunc) ); ++ } ++#endif /* SQLITE_OMIT_WINDOWFUNC */ + if( pzBuffer ){ + *pzBuffer = zAlloc; + } +@@ -92895,10 +97473,9 @@ + Expr *pPriorSelectCol = 0; + assert( db!=0 ); + if( p==0 ) return 0; +- pNew = sqlite3DbMallocRawNN(db, +- sizeof(*pNew)+sizeof(pNew->a[0])*(p->nExpr-1) ); ++ pNew = sqlite3DbMallocRawNN(db, sqlite3DbMallocSize(db, p)); + if( pNew==0 ) return 0; +- pNew->nAlloc = pNew->nExpr = p->nExpr; ++ pNew->nExpr = p->nExpr; + pItem = pNew->a; + pOldItem = p->a; + for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){ +@@ -92926,6 +97503,7 @@ + pItem->sortOrder = pOldItem->sortOrder; + pItem->done = 0; + pItem->bSpanIsTab = pOldItem->bSpanIsTab; ++ pItem->bSorterRef = pOldItem->bSorterRef; + pItem->u = pOldItem->u; + } + return pNew; +@@ -93024,7 +97602,6 @@ + pNew->pNext = pNext; + pNew->pPrior = 0; + pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags); +- pNew->pOffset = sqlite3ExprDup(db, p->pOffset, flags); + pNew->iLimit = 0; + pNew->iOffset = 0; + pNew->selFlags = p->selFlags & ~SF_UsesEphemeral; +@@ -93032,7 +97609,11 @@ + pNew->addrOpenEphm[1] = -1; + pNew->nSelectRow = p->nSelectRow; + pNew->pWith = withDup(db, p->pWith); +- sqlite3SelectSetName(pNew, p->zSelName); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ pNew->pWin = 0; ++ pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn); ++#endif ++ pNew->selId = p->selId; + *pp = pNew; + pp = &pNew->pPrior; + pNext = pNew; +@@ -93052,6 +97633,13 @@ + ** Add a new element to the end of an expression list. If pList is + ** initially NULL, then create a new expression list. + ** ++** The pList argument must be either NULL or a pointer to an ExprList ++** obtained from a prior call to sqlite3ExprListAppend(). This routine ++** may not be used with an ExprList obtained from sqlite3ExprListDup(). ++** Reason: This routine assumes that the number of slots in pList->a[] ++** is a power of two. That is true for sqlite3ExprListAppend() returns ++** but is not necessarily true from the return value of sqlite3ExprListDup(). ++** + ** If a memory allocation error occurs, the entire list is freed and + ** NULL is returned. If non-NULL is returned, then it is guaranteed + ** that the new entry was successfully appended. +@@ -93070,16 +97658,14 @@ + goto no_mem; + } + pList->nExpr = 0; +- pList->nAlloc = 1; +- }else if( pList->nExpr==pList->nAlloc ){ ++ }else if( (pList->nExpr & (pList->nExpr-1))==0 ){ + ExprList *pNew; + pNew = sqlite3DbRealloc(db, pList, +- sizeof(*pList)+(2*pList->nAlloc - 1)*sizeof(pList->a[0])); ++ sizeof(*pList)+(2*pList->nExpr - 1)*sizeof(pList->a[0])); + if( pNew==0 ){ + goto no_mem; + } + pList = pNew; +- pList->nAlloc *= 2; + } + pItem = &pList->a[pList->nExpr++]; + assert( offsetof(struct ExprList_item,zName)==sizeof(pItem->pExpr) ); +@@ -93199,6 +97785,9 @@ + assert( pItem->zName==0 ); + pItem->zName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n); + if( dequote ) sqlite3Dequote(pItem->zName); ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameTokenMap(pParse, (void*)pItem->zName, pName); ++ } + } + } + +@@ -93213,7 +97802,8 @@ + SQLITE_PRIVATE void sqlite3ExprListSetSpan( + Parse *pParse, /* Parsing context */ + ExprList *pList, /* List to which to add the span. */ +- ExprSpan *pSpan /* The span to be added */ ++ const char *zStart, /* Start of the span */ ++ const char *zEnd /* End of the span */ + ){ + sqlite3 *db = pParse->db; + assert( pList!=0 || db->mallocFailed!=0 ); +@@ -93220,10 +97810,8 @@ + if( pList ){ + struct ExprList_item *pItem = &pList->a[pList->nExpr-1]; + assert( pList->nExpr>0 ); +- assert( db->mallocFailed || pItem->pExpr==pSpan->pExpr ); + sqlite3DbFree(db, pItem->zSpan); +- pItem->zSpan = sqlite3DbStrNDup(db, (char*)pSpan->zStart, +- (int)(pSpan->zEnd - pSpan->zStart)); ++ pItem->zSpan = sqlite3DbSpanDup(db, zStart, zEnd); + } + } + +@@ -93270,17 +97858,57 @@ + SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList *pList){ + int i; + u32 m = 0; +- if( pList ){ +- for(i=0; i<pList->nExpr; i++){ +- Expr *pExpr = pList->a[i].pExpr; +- assert( pExpr!=0 ); +- m |= pExpr->flags; +- } ++ assert( pList!=0 ); ++ for(i=0; i<pList->nExpr; i++){ ++ Expr *pExpr = pList->a[i].pExpr; ++ assert( pExpr!=0 ); ++ m |= pExpr->flags; + } + return m; + } + + /* ++** This is a SELECT-node callback for the expression walker that ++** always "fails". By "fail" in this case, we mean set ++** pWalker->eCode to zero and abort. ++** ++** This callback is used by multiple expression walkers. ++*/ ++SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker *pWalker, Select *NotUsed){ ++ UNUSED_PARAMETER(NotUsed); ++ pWalker->eCode = 0; ++ return WRC_Abort; ++} ++ ++/* ++** If the input expression is an ID with the name "true" or "false" ++** then convert it into an TK_TRUEFALSE term. Return non-zero if ++** the conversion happened, and zero if the expression is unaltered. ++*/ ++SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr *pExpr){ ++ assert( pExpr->op==TK_ID || pExpr->op==TK_STRING ); ++ if( sqlite3StrICmp(pExpr->u.zToken, "true")==0 ++ || sqlite3StrICmp(pExpr->u.zToken, "false")==0 ++ ){ ++ pExpr->op = TK_TRUEFALSE; ++ return 1; ++ } ++ return 0; ++} ++ ++/* ++** The argument must be a TK_TRUEFALSE Expr node. Return 1 if it is TRUE ++** and 0 if it is FALSE. ++*/ ++SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr *pExpr){ ++ assert( pExpr->op==TK_TRUEFALSE ); ++ assert( sqlite3StrICmp(pExpr->u.zToken,"true")==0 ++ || sqlite3StrICmp(pExpr->u.zToken,"false")==0 ); ++ return pExpr->u.zToken[4]==0; ++} ++ ++ ++/* + ** These routines are Walker callbacks used to check expressions to + ** see if they are "constant" for some definition of constant. The + ** Walker.eCode value determines the type of "constant" we are looking +@@ -93327,6 +97955,12 @@ + return WRC_Abort; + } + case TK_ID: ++ /* Convert "true" or "false" in a DEFAULT clause into the ++ ** appropriate TK_TRUEFALSE operator */ ++ if( sqlite3ExprIdToTrueFalse(pExpr) ){ ++ return WRC_Prune; ++ } ++ /* Fall thru */ + case TK_COLUMN: + case TK_AGG_FUNCTION: + case TK_AGG_COLUMN: +@@ -93334,11 +97968,16 @@ + testcase( pExpr->op==TK_COLUMN ); + testcase( pExpr->op==TK_AGG_FUNCTION ); + testcase( pExpr->op==TK_AGG_COLUMN ); ++ if( ExprHasProperty(pExpr, EP_FixedCol) && pWalker->eCode!=2 ){ ++ return WRC_Continue; ++ } + if( pWalker->eCode==3 && pExpr->iTable==pWalker->u.iCur ){ + return WRC_Continue; + } + /* Fall through */ + case TK_IF_NULL_ROW: ++ case TK_REGISTER: ++ testcase( pExpr->op==TK_REGISTER ); + testcase( pExpr->op==TK_IF_NULL_ROW ); + pWalker->eCode = 0; + return WRC_Abort; +@@ -93356,21 +97995,16 @@ + } + /* Fall through */ + default: +- testcase( pExpr->op==TK_SELECT ); /* selectNodeIsConstant will disallow */ +- testcase( pExpr->op==TK_EXISTS ); /* selectNodeIsConstant will disallow */ ++ testcase( pExpr->op==TK_SELECT ); /* sqlite3SelectWalkFail() disallows */ ++ testcase( pExpr->op==TK_EXISTS ); /* sqlite3SelectWalkFail() disallows */ + return WRC_Continue; + } + } +-static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){ +- UNUSED_PARAMETER(NotUsed); +- pWalker->eCode = 0; +- return WRC_Abort; +-} + static int exprIsConst(Expr *p, int initFlag, int iCur){ + Walker w; + w.eCode = initFlag; + w.xExprCallback = exprNodeIsConstant; +- w.xSelectCallback = selectNodeIsConstant; ++ w.xSelectCallback = sqlite3SelectWalkFail; + #ifdef SQLITE_DEBUG + w.xSelectCallback2 = sqlite3SelectWalkAssert2; + #endif +@@ -93392,10 +98026,17 @@ + } + + /* +-** Walk an expression tree. Return non-zero if the expression is constant +-** that does no originate from the ON or USING clauses of a join. +-** Return 0 if it involves variables or function calls or terms from +-** an ON or USING clause. ++** Walk an expression tree. Return non-zero if ++** ++** (1) the expression is constant, and ++** (2) the expression does originate in the ON or USING clause ++** of a LEFT JOIN, and ++** (3) the expression does not contain any EP_FixedCol TK_COLUMN ++** operands created by the constant propagation optimization. ++** ++** When this routine returns true, it indicates that the expression ++** can be added to the pParse->pConstExpr list and evaluated once when ++** the prepared statement starts up. See sqlite3ExprCodeAtInit(). + */ + SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr *p){ + return exprIsConst(p, 2, 0); +@@ -93424,8 +98065,8 @@ + for(i=0; i<pGroupBy->nExpr; i++){ + Expr *p = pGroupBy->a[i].pExpr; + if( sqlite3ExprCompare(0, pExpr, p, -1)<2 ){ +- CollSeq *pColl = sqlite3ExprCollSeq(pWalker->pParse, p); +- if( pColl==0 || sqlite3_stricmp("BINARY", pColl->zName)==0 ){ ++ CollSeq *pColl = sqlite3ExprNNCollSeq(pWalker->pParse, p); ++ if( sqlite3IsBinary(pColl) ){ + return WRC_Prune; + } + } +@@ -93493,7 +98134,7 @@ + Walker w; + w.eCode = 1; + w.xExprCallback = sqlite3ExprWalkNoop; +- w.xSelectCallback = selectNodeIsConstant; ++ w.xSelectCallback = sqlite3SelectWalkFail; + #ifdef SQLITE_DEBUG + w.xSelectCallback2 = sqlite3SelectWalkAssert2; + #endif +@@ -93566,9 +98207,9 @@ + case TK_BLOB: + return 0; + case TK_COLUMN: +- assert( p->pTab!=0 ); + return ExprHasProperty(p, EP_CanBeNull) || +- (p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0); ++ p->y.pTab==0 || /* Reference to column of index on expression */ ++ (p->iColumn>=0 && p->y.pTab->aCol[p->iColumn].notNull==0); + default: + return 1; + } +@@ -93623,6 +98264,14 @@ + if( sqlite3StrICmp(z, "OID")==0 ) return 1; + return 0; + } ++#ifdef SQLITE_ENABLE_NORMALIZE ++SQLITE_PRIVATE int sqlite3IsRowidN(const char *z, int n){ ++ if( sqlite3StrNICmp(z, "_ROWID_", n)==0 ) return 1; ++ if( sqlite3StrNICmp(z, "ROWID", n)==0 ) return 1; ++ if( sqlite3StrNICmp(z, "OID", n)==0 ) return 1; ++ return 0; ++} ++#endif + + /* + ** pX is the RHS of an IN operator. If pX is a SELECT statement +@@ -93649,7 +98298,6 @@ + } + assert( p->pGroupBy==0 ); /* Has no GROUP BY clause */ + if( p->pLimit ) return 0; /* Has no LIMIT clause */ +- assert( p->pOffset==0 ); /* No LIMIT means no OFFSET */ + if( p->pWhere ) return 0; /* Has no WHERE clause */ + pSrc = p->pSrc; + assert( pSrc!=0 ); +@@ -93739,16 +98387,15 @@ + ** pX->iTable made to point to the ephemeral table instead of an + ** existing table. + ** +-** The inFlags parameter must contain exactly one of the bits +-** IN_INDEX_MEMBERSHIP or IN_INDEX_LOOP. If inFlags contains +-** IN_INDEX_MEMBERSHIP, then the generated table will be used for a +-** fast membership test. When the IN_INDEX_LOOP bit is set, the +-** IN index will be used to loop over all values of the RHS of the +-** IN operator. ++** The inFlags parameter must contain, at a minimum, one of the bits ++** IN_INDEX_MEMBERSHIP or IN_INDEX_LOOP but not both. If inFlags contains ++** IN_INDEX_MEMBERSHIP, then the generated table will be used for a fast ++** membership test. When the IN_INDEX_LOOP bit is set, the IN index will ++** be used to loop over all values of the RHS of the IN operator. + ** + ** When IN_INDEX_LOOP is used (and the b-tree will be used to iterate + ** through the set members) then the b-tree must not contain duplicates. +-** An epheremal table must be used unless the selected columns are guaranteed ++** An epheremal table will be created unless the selected columns are guaranteed + ** to be unique - either because it is an INTEGER PRIMARY KEY or due to + ** a UNIQUE constraint or index. + ** +@@ -93849,7 +98496,8 @@ + + sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); + eType = IN_INDEX_ROWID; +- ++ ExplainQueryPlan((pParse, 0, ++ "USING ROWID SEARCH ON TABLE %s FOR IN-OPERATOR",pTab->zName)); + sqlite3VdbeJumpHere(v, iAddr); + }else{ + Index *pIdx; /* Iterator variable */ +@@ -93928,11 +98576,8 @@ + if( colUsed==(MASKBIT(nExpr)-1) ){ + /* If we reach this point, that means the index pIdx is usable */ + int iAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); +-#ifndef SQLITE_OMIT_EXPLAIN +- sqlite3VdbeAddOp4(v, OP_Explain, 0, 0, 0, +- sqlite3MPrintf(db, "USING INDEX %s FOR IN-OPERATOR",pIdx->zName), +- P4_DYNAMIC); +-#endif ++ ExplainQueryPlan((pParse, 0, ++ "USING INDEX %s FOR IN-OPERATOR",pIdx->zName)); + sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb); + sqlite3VdbeSetP4KeyInfo(pParse, pIdx); + VdbeComment((v, "%s", pIdx->zName)); +@@ -94111,7 +98756,6 @@ + int rReg = 0; /* Register storing resulting */ + Vdbe *v = sqlite3GetVdbe(pParse); + if( NEVER(v==0) ) return 0; +- sqlite3ExprCachePush(pParse); + + /* The evaluation of the IN/EXISTS/SELECT must be repeated every time it + ** is encountered if any of the following is true: +@@ -94127,17 +98771,6 @@ + jmpIfDynamic = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); + } + +-#ifndef SQLITE_OMIT_EXPLAIN +- if( pParse->explain==2 ){ +- char *zMsg = sqlite3MPrintf(pParse->db, "EXECUTE %s%s SUBQUERY %d", +- jmpIfDynamic>=0?"":"CORRELATED ", +- pExpr->op==TK_IN?"LIST":"SCALAR", +- pParse->iNextSelectId +- ); +- sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); +- } +-#endif +- + switch( pExpr->op ){ + case TK_IN: { + int addr; /* Address of OP_OpenEphemeral instruction */ +@@ -94175,6 +98808,9 @@ + Select *pSelect = pExpr->x.pSelect; + ExprList *pEList = pSelect->pEList; + ++ ExplainQueryPlan((pParse, 1, "%sLIST SUBQUERY", ++ jmpIfDynamic>=0?"":"CORRELATED " ++ )); + assert( !isRowid ); + /* If the LHS and RHS of the IN operator do not match, that + ** error will have been caught long before we reach this point. */ +@@ -94216,7 +98852,6 @@ + ExprList *pList = pExpr->x.pList; + struct ExprList_item *pItem; + int r1, r2, r3; +- + affinity = sqlite3ExprAffinity(pLeft); + if( !affinity ){ + affinity = SQLITE_AFF_BLOB; +@@ -94229,7 +98864,7 @@ + /* Loop through each expression in <exprlist>. */ + r1 = sqlite3GetTempReg(pParse); + r2 = sqlite3GetTempReg(pParse); +- if( isRowid ) sqlite3VdbeAddOp2(v, OP_Null, 0, r2); ++ if( isRowid ) sqlite3VdbeAddOp4(v, OP_Blob, 0, r2, 0, "", P4_STATIC); + for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){ + Expr *pE2 = pItem->pExpr; + int iValToIns; +@@ -94256,7 +98891,6 @@ + sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3); + }else{ + sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); +- sqlite3ExprCacheAffinityChange(pParse, r3, 1); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pExpr->iTable, r2, r3, 1); + } + } +@@ -94289,6 +98923,7 @@ + Select *pSel; /* SELECT statement to encode */ + SelectDest dest; /* How to deal with SELECT result */ + int nReg; /* Registers to allocate */ ++ Expr *pLimit; /* New limit expression */ + + testcase( pExpr->op==TK_EXISTS ); + testcase( pExpr->op==TK_SELECT ); +@@ -94296,6 +98931,8 @@ + assert( ExprHasProperty(pExpr, EP_xIsSelect) ); + + pSel = pExpr->x.pSelect; ++ ExplainQueryPlan((pParse, 1, "%sSCALAR SUBQUERY", ++ jmpIfDynamic>=0?"":"CORRELATED ")); + nReg = pExpr->op==TK_SELECT ? pSel->pEList->nExpr : 1; + sqlite3SelectDestInit(&dest, 0, pParse->nMem+1); + pParse->nMem += nReg; +@@ -94310,11 +98947,14 @@ + sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm); + VdbeComment((v, "Init EXISTS result")); + } +- sqlite3ExprDelete(pParse->db, pSel->pLimit); +- pSel->pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER, +- &sqlite3IntTokens[1], 0); ++ pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[1], 0); ++ if( pSel->pLimit ){ ++ sqlite3ExprDelete(pParse->db, pSel->pLimit->pLeft); ++ pSel->pLimit->pLeft = pLimit; ++ }else{ ++ pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0); ++ } + pSel->iLimit = 0; +- pSel->selFlags &= ~SF_MultiValue; + if( sqlite3Select(pParse, pSel, &dest) ){ + return 0; + } +@@ -94331,7 +98971,6 @@ + if( jmpIfDynamic>=0 ){ + sqlite3VdbeJumpHere(v, jmpIfDynamic); + } +- sqlite3ExprCachePop(pParse); + + return rReg; + } +@@ -94450,7 +99089,6 @@ + ** aiMap[] array contains a mapping from the original LHS field order to + ** the field order that matches the RHS index. + */ +- sqlite3ExprCachePush(pParse); + rLhsOrig = exprCodeVector(pParse, pLeft, &iDummy); + for(i=0; i<nVector && aiMap[i]==i; i++){} /* Are LHS fields reordered? */ + if( i==nVector ){ +@@ -94609,7 +99247,6 @@ + + sqlite3ExprCodeIN_finished: + if( rLhs!=rLhsOrig ) sqlite3ReleaseTempReg(pParse, rLhs); +- sqlite3ExprCachePop(pParse); + VdbeComment((v, "end IN expr")); + sqlite3ExprCodeIN_oom_error: + sqlite3DbFree(pParse->db, aiMap); +@@ -94657,7 +99294,7 @@ + const char *z = pExpr->u.zToken; + assert( z!=0 ); + c = sqlite3DecOrHexToI64(z, &value); +- if( c==1 || (c==2 && !negFlag) || (negFlag && value==SMALLEST_INT64)){ ++ if( (c==3 && !negFlag) || (c==2) || (negFlag && value==SMALLEST_INT64)){ + #ifdef SQLITE_OMIT_FLOATING_POINT + sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z); + #else +@@ -94671,152 +99308,13 @@ + } + #endif + }else{ +- if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; } ++ if( negFlag ){ value = c==3 ? SMALLEST_INT64 : -value; } + sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, iMem, 0, (u8*)&value, P4_INT64); + } + } + } + +-/* +-** Erase column-cache entry number i +-*/ +-static void cacheEntryClear(Parse *pParse, int i){ +- if( pParse->aColCache[i].tempReg ){ +- if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){ +- pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg; +- } +- } +- pParse->nColCache--; +- if( i<pParse->nColCache ){ +- pParse->aColCache[i] = pParse->aColCache[pParse->nColCache]; +- } +-} + +- +-/* +-** Record in the column cache that a particular column from a +-** particular table is stored in a particular register. +-*/ +-SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){ +- int i; +- int minLru; +- int idxLru; +- struct yColCache *p; +- +- /* Unless an error has occurred, register numbers are always positive. */ +- assert( iReg>0 || pParse->nErr || pParse->db->mallocFailed ); +- assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */ +- +- /* The SQLITE_ColumnCache flag disables the column cache. This is used +- ** for testing only - to verify that SQLite always gets the same answer +- ** with and without the column cache. +- */ +- if( OptimizationDisabled(pParse->db, SQLITE_ColumnCache) ) return; +- +- /* First replace any existing entry. +- ** +- ** Actually, the way the column cache is currently used, we are guaranteed +- ** that the object will never already be in cache. Verify this guarantee. +- */ +-#ifndef NDEBUG +- for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){ +- assert( p->iTable!=iTab || p->iColumn!=iCol ); +- } +-#endif +- +- /* If the cache is already full, delete the least recently used entry */ +- if( pParse->nColCache>=SQLITE_N_COLCACHE ){ +- minLru = 0x7fffffff; +- idxLru = -1; +- for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ +- if( p->lru<minLru ){ +- idxLru = i; +- minLru = p->lru; +- } +- } +- p = &pParse->aColCache[idxLru]; +- }else{ +- p = &pParse->aColCache[pParse->nColCache++]; +- } +- +- /* Add the new entry to the end of the cache */ +- p->iLevel = pParse->iCacheLevel; +- p->iTable = iTab; +- p->iColumn = iCol; +- p->iReg = iReg; +- p->tempReg = 0; +- p->lru = pParse->iCacheCnt++; +-} +- +-/* +-** Indicate that registers between iReg..iReg+nReg-1 are being overwritten. +-** Purge the range of registers from the column cache. +-*/ +-SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){ +- int i = 0; +- while( i<pParse->nColCache ){ +- struct yColCache *p = &pParse->aColCache[i]; +- if( p->iReg >= iReg && p->iReg < iReg+nReg ){ +- cacheEntryClear(pParse, i); +- }else{ +- i++; +- } +- } +-} +- +-/* +-** Remember the current column cache context. Any new entries added +-** added to the column cache after this call are removed when the +-** corresponding pop occurs. +-*/ +-SQLITE_PRIVATE void sqlite3ExprCachePush(Parse *pParse){ +- pParse->iCacheLevel++; +-#ifdef SQLITE_DEBUG +- if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ +- printf("PUSH to %d\n", pParse->iCacheLevel); +- } +-#endif +-} +- +-/* +-** Remove from the column cache any entries that were added since the +-** the previous sqlite3ExprCachePush operation. In other words, restore +-** the cache to the state it was in prior the most recent Push. +-*/ +-SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse){ +- int i = 0; +- assert( pParse->iCacheLevel>=1 ); +- pParse->iCacheLevel--; +-#ifdef SQLITE_DEBUG +- if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ +- printf("POP to %d\n", pParse->iCacheLevel); +- } +-#endif +- while( i<pParse->nColCache ){ +- if( pParse->aColCache[i].iLevel>pParse->iCacheLevel ){ +- cacheEntryClear(pParse, i); +- }else{ +- i++; +- } +- } +-} +- +-/* +-** When a cached column is reused, make sure that its register is +-** no longer available as a temp register. ticket #3879: that same +-** register might be in the cache in multiple places, so be sure to +-** get them all. +-*/ +-static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){ +- int i; +- struct yColCache *p; +- for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){ +- if( p->iReg==iReg ){ +- p->tempReg = 0; +- } +- } +-} +- + /* Generate code that will load into register regOut a value that is + ** appropriate for the iIdxCol-th column of index pIdx. + */ +@@ -94871,13 +99369,8 @@ + + /* + ** Generate code that will extract the iColumn-th column from +-** table pTab and store the column value in a register. ++** table pTab and store the column value in register iReg. + ** +-** An effort is made to store the column value in register iReg. This +-** is not garanteeed for GetColumn() - the result can be stored in +-** any register. But the result is guaranteed to land in register iReg +-** for GetColumnToReg(). +-** + ** There must be an open cursor to pTab in iTable when this routine + ** is called. If iColumn<0 then code is generated that extracts the rowid. + */ +@@ -94890,97 +99383,24 @@ + u8 p5 /* P5 value for OP_Column + FLAGS */ + ){ + Vdbe *v = pParse->pVdbe; +- int i; +- struct yColCache *p; +- +- for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){ +- if( p->iTable==iTable && p->iColumn==iColumn ){ +- p->lru = pParse->iCacheCnt++; +- sqlite3ExprCachePinRegister(pParse, p->iReg); +- return p->iReg; +- } +- } + assert( v!=0 ); + sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg); + if( p5 ){ + sqlite3VdbeChangeP5(v, p5); +- }else{ +- sqlite3ExprCacheStore(pParse, iTable, iColumn, iReg); + } + return iReg; + } +-SQLITE_PRIVATE void sqlite3ExprCodeGetColumnToReg( +- Parse *pParse, /* Parsing and code generating context */ +- Table *pTab, /* Description of the table we are reading from */ +- int iColumn, /* Index of the table column */ +- int iTable, /* The cursor pointing to the table */ +- int iReg /* Store results here */ +-){ +- int r1 = sqlite3ExprCodeGetColumn(pParse, pTab, iColumn, iTable, iReg, 0); +- if( r1!=iReg ) sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, r1, iReg); +-} + +- + /* +-** Clear all column cache entries. +-*/ +-SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){ +- int i; +- +-#ifdef SQLITE_DEBUG +- if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ +- printf("CLEAR\n"); +- } +-#endif +- for(i=0; i<pParse->nColCache; i++){ +- if( pParse->aColCache[i].tempReg +- && pParse->nTempReg<ArraySize(pParse->aTempReg) +- ){ +- pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg; +- } +- } +- pParse->nColCache = 0; +-} +- +-/* +-** Record the fact that an affinity change has occurred on iCount +-** registers starting with iStart. +-*/ +-SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){ +- sqlite3ExprCacheRemove(pParse, iStart, iCount); +-} +- +-/* + ** Generate code to move content from registers iFrom...iFrom+nReg-1 +-** over to iTo..iTo+nReg-1. Keep the column cache up-to-date. ++** over to iTo..iTo+nReg-1. + */ + SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){ + assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo ); + sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg); +- sqlite3ExprCacheRemove(pParse, iFrom, nReg); + } + +-#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) + /* +-** Return true if any register in the range iFrom..iTo (inclusive) +-** is used as part of the column cache. +-** +-** This routine is used within assert() and testcase() macros only +-** and does not appear in a normal build. +-*/ +-static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){ +- int i; +- struct yColCache *p; +- for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){ +- int r = p->iReg; +- if( r>=iFrom && r<=iTo ) return 1; /*NO_TEST*/ +- } +- return 0; +-} +-#endif /* SQLITE_DEBUG || SQLITE_COVERAGE_TEST */ +- +- +-/* + ** Convert a scalar expression node to a TK_REGISTER referencing + ** register iReg. The caller must ensure that iReg already contains + ** the correct value for the expression. +@@ -95055,6 +99475,7 @@ + return 0; + } + ++expr_code_doover: + if( pExpr==0 ){ + op = TK_NULL; + }else{ +@@ -95076,6 +99497,28 @@ + } + case TK_COLUMN: { + int iTab = pExpr->iTable; ++ if( ExprHasProperty(pExpr, EP_FixedCol) ){ ++ /* This COLUMN expression is really a constant due to WHERE clause ++ ** constraints, and that constant is coded by the pExpr->pLeft ++ ** expresssion. However, make sure the constant has the correct ++ ** datatype by applying the Affinity of the table column to the ++ ** constant. ++ */ ++ int iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target); ++ int aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn); ++ if( aff!=SQLITE_AFF_BLOB ){ ++ static const char zAff[] = "B\000C\000D\000E"; ++ assert( SQLITE_AFF_BLOB=='A' ); ++ assert( SQLITE_AFF_TEXT=='B' ); ++ if( iReg!=target ){ ++ sqlite3VdbeAddOp2(v, OP_SCopy, iReg, target); ++ iReg = target; ++ } ++ sqlite3VdbeAddOp4(v, OP_Affinity, iReg, 1, 0, ++ &zAff[(aff-'B')*2], P4_STATIC); ++ } ++ return iReg; ++ } + if( iTab<0 ){ + if( pParse->iSelfTab<0 ){ + /* Generating CHECK constraints or inserting into partial index */ +@@ -95086,7 +99529,7 @@ + iTab = pParse->iSelfTab - 1; + } + } +- return sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, ++ return sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab, + pExpr->iColumn, iTab, target, + pExpr->op2); + } +@@ -95094,6 +99537,10 @@ + codeInteger(pParse, pExpr, 0, target); + return target; + } ++ case TK_TRUEFALSE: { ++ sqlite3VdbeAddOp2(v, OP_Integer, sqlite3ExprTruthValue(pExpr), target); ++ return target; ++ } + #ifndef SQLITE_OMIT_FLOATING_POINT + case TK_FLOAT: { + assert( !ExprHasProperty(pExpr, EP_IntValue) ); +@@ -95152,8 +99599,6 @@ + } + sqlite3VdbeAddOp2(v, OP_Cast, target, + sqlite3AffinityType(pExpr->u.zToken, 0)); +- testcase( usedAsColumnCache(pParse, inReg, inReg) ); +- sqlite3ExprCacheAffinityChange(pParse, inReg, 1); + return inReg; + } + #endif /* SQLITE_OMIT_CAST */ +@@ -95249,6 +99694,18 @@ + sqlite3VdbeAddOp2(v, op, r1, inReg); + break; + } ++ case TK_TRUTH: { ++ int isTrue; /* IS TRUE or IS NOT TRUE */ ++ int bNormal; /* IS TRUE or IS FALSE */ ++ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); ++ testcase( regFree1==0 ); ++ isTrue = sqlite3ExprTruthValue(pExpr->pRight); ++ bNormal = pExpr->op2==TK_IS; ++ testcase( isTrue && bNormal); ++ testcase( !isTrue && bNormal); ++ sqlite3VdbeAddOp4Int(v, OP_IsTrue, r1, inReg, !isTrue, isTrue ^ bNormal); ++ break; ++ } + case TK_ISNULL: + case TK_NOTNULL: { + int addr; +@@ -95285,6 +99742,12 @@ + u8 enc = ENC(db); /* The text encoding used by this database */ + CollSeq *pColl = 0; /* A collating sequence */ + ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( ExprHasProperty(pExpr, EP_WinFunc) ){ ++ return pExpr->y.pWin->regResult; ++ } ++#endif ++ + if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){ + /* SQL functions can be expensive. So try to move constant functions + ** out of the inner loop, even if that means an extra OP_Copy. */ +@@ -95321,10 +99784,7 @@ + for(i=1; i<nFarg; i++){ + sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce); + VdbeCoverage(v); +- sqlite3ExprCacheRemove(pParse, target, 1); +- sqlite3ExprCachePush(pParse); + sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target); +- sqlite3ExprCachePop(pParse); + } + sqlite3VdbeResolveLabel(v, endCoalesce); + break; +@@ -95390,10 +99850,8 @@ + } + } + +- sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */ + sqlite3ExprCodeExprList(pParse, pFarg, r1, 0, + SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR); +- sqlite3ExprCachePop(pParse); /* Ticket 2ea2425d34be */ + }else{ + r1 = 0; + } +@@ -95410,7 +99868,7 @@ + ** "glob(B,A). We want to use the A in "A glob B" to test + ** for function overloading. But we use the B term in "glob(B,A)". + */ +- if( nFarg>=2 && (pExpr->flags & EP_InfixFunc) ){ ++ if( nFarg>=2 && ExprHasProperty(pExpr, EP_InfixFunc) ){ + pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[1].pExpr); + }else if( nFarg>0 ){ + pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr); +@@ -95420,9 +99878,21 @@ + if( !pColl ) pColl = db->pDfltColl; + sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); + } +- sqlite3VdbeAddOp4(v, pParse->iSelfTab ? OP_PureFunc0 : OP_Function0, +- constMask, r1, target, (char*)pDef, P4_FUNCDEF); +- sqlite3VdbeChangeP5(v, (u8)nFarg); ++#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC ++ if( pDef->funcFlags & SQLITE_FUNC_OFFSET ){ ++ Expr *pArg = pFarg->a[0].pExpr; ++ if( pArg->op==TK_COLUMN ){ ++ sqlite3VdbeAddOp3(v, OP_Offset, pArg->iTable, pArg->iColumn, target); ++ }else{ ++ sqlite3VdbeAddOp2(v, OP_Null, 0, target); ++ } ++ }else ++#endif ++ { ++ sqlite3VdbeAddOp4(v, pParse->iSelfTab ? OP_PureFunc0 : OP_Function0, ++ constMask, r1, target, (char*)pDef, P4_FUNCDEF); ++ sqlite3VdbeChangeP5(v, (u8)nFarg); ++ } + if( nFarg && constMask==0 ){ + sqlite3ReleaseTempRange(pParse, r1, nFarg); + } +@@ -95487,7 +99957,8 @@ + case TK_SPAN: + case TK_COLLATE: + case TK_UPLUS: { +- return sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); ++ pExpr = pExpr->pLeft; ++ goto expr_code_doover; /* 2018-04-28: Prevent deep recursion. OSSFuzz. */ + } + + case TK_TRIGGER: { +@@ -95516,7 +99987,7 @@ + ** p1==1 -> old.a p1==4 -> new.a + ** p1==2 -> old.b p1==5 -> new.b + */ +- Table *pTab = pExpr->pTab; ++ Table *pTab = pExpr->y.pTab; + int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn; + + assert( pExpr->iTable==0 || pExpr->iTable==1 ); +@@ -95525,10 +99996,9 @@ + assert( p1>=0 && p1<(pTab->nCol*2+2) ); + + sqlite3VdbeAddOp2(v, OP_Param, p1, target); +- VdbeComment((v, "%s.%s -> $%d", ++ VdbeComment((v, "r[%d]=%s.%s", target, + (pExpr->iTable ? "new" : "old"), +- (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName), +- target ++ (pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[pExpr->iColumn].zName) + )); + + #ifndef SQLITE_OMIT_FLOATING_POINT +@@ -95554,9 +100024,7 @@ + case TK_IF_NULL_ROW: { + int addrINR; + addrINR = sqlite3VdbeAddOp1(v, OP_IfNullRow, pExpr->iTable); +- sqlite3ExprCachePush(pParse); + inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); +- sqlite3ExprCachePop(pParse); + sqlite3VdbeJumpHere(v, addrINR); + sqlite3VdbeChangeP3(v, addrINR, inReg); + break; +@@ -95593,7 +100061,6 @@ + Expr opCompare; /* The X==Ei expression */ + Expr *pX; /* The X expression */ + Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */ +- VVA_ONLY( int iCacheLevel = pParse->iCacheLevel; ) + + assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList ); + assert(pExpr->x.pList->nExpr > 0); +@@ -95617,7 +100084,6 @@ + regFree1 = 0; + } + for(i=0; i<nExpr-1; i=i+2){ +- sqlite3ExprCachePush(pParse); + if( pX ){ + assert( pTest!=0 ); + opCompare.pRight = aListelem[i].pExpr; +@@ -95630,18 +100096,13 @@ + testcase( aListelem[i+1].pExpr->op==TK_COLUMN ); + sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target); + sqlite3VdbeGoto(v, endLabel); +- sqlite3ExprCachePop(pParse); + sqlite3VdbeResolveLabel(v, nextCase); + } + if( (nExpr&1)!=0 ){ +- sqlite3ExprCachePush(pParse); + sqlite3ExprCode(pParse, pEList->a[nExpr-1].pExpr, target); +- sqlite3ExprCachePop(pParse); + }else{ + sqlite3VdbeAddOp2(v, OP_Null, 0, target); + } +- assert( pParse->db->mallocFailed || pParse->nErr>0 +- || pParse->iCacheLevel==iCacheLevel ); + sqlite3VdbeResolveLabel(v, endLabel); + break; + } +@@ -95791,7 +100252,7 @@ + ** might choose to code the expression at initialization time. + */ + SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){ +- if( pParse->okConstFactor && sqlite3ExprIsConstant(pExpr) ){ ++ if( pParse->okConstFactor && sqlite3ExprIsConstantNotJoin(pExpr) ){ + sqlite3ExprCodeAtInit(pParse, pExpr, target); + }else{ + sqlite3ExprCode(pParse, pExpr, target); +@@ -95826,7 +100287,9 @@ + ** Generate code that pushes the value of every element of the given + ** expression list into a sequence of registers beginning at target. + ** +-** Return the number of elements evaluated. ++** Return the number of elements evaluated. The number returned will ++** usually be pList->nExpr but might be reduced if SQLITE_ECEL_OMITREF ++** is defined. + ** + ** The SQLITE_ECEL_DUP flag prevents the arguments from being + ** filled using OP_SCopy. OP_Copy must be used instead. +@@ -95837,6 +100300,8 @@ + ** The SQLITE_ECEL_REF flag means that expressions in the list with + ** ExprList.a[].u.x.iOrderByCol>0 have already been evaluated and stored + ** in registers at srcReg, and so the value can be copied from there. ++** If SQLITE_ECEL_OMITREF is also set, then the values with u.x.iOrderByCol>0 ++** are simply omitted rather than being copied from srcReg. + */ + SQLITE_PRIVATE int sqlite3ExprCodeExprList( + Parse *pParse, /* Parsing context */ +@@ -95856,6 +100321,12 @@ + if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR; + for(pItem=pList->a, i=0; i<n; i++, pItem++){ + Expr *pExpr = pItem->pExpr; ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ if( pItem->bSorterRef ){ ++ i--; ++ n--; ++ }else ++#endif + if( (flags & SQLITE_ECEL_REF)!=0 && (j = pItem->u.x.iOrderByCol)>0 ){ + if( flags & SQLITE_ECEL_OMITREF ){ + i--; +@@ -95863,7 +100334,9 @@ + }else{ + sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i); + } +- }else if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){ ++ }else if( (flags & SQLITE_ECEL_FACTOR)!=0 ++ && sqlite3ExprIsConstantNotJoin(pExpr) ++ ){ + sqlite3ExprCodeAtInit(pParse, pExpr, target+i); + }else{ + int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i); +@@ -95989,18 +100462,14 @@ + int d2 = sqlite3VdbeMakeLabel(v); + testcase( jumpIfNull==0 ); + sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL); +- sqlite3ExprCachePush(pParse); + sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); + sqlite3VdbeResolveLabel(v, d2); +- sqlite3ExprCachePop(pParse); + break; + } + case TK_OR: { + testcase( jumpIfNull==0 ); + sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); +- sqlite3ExprCachePush(pParse); + sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); +- sqlite3ExprCachePop(pParse); + break; + } + case TK_NOT: { +@@ -96008,6 +100477,23 @@ + sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); + break; + } ++ case TK_TRUTH: { ++ int isNot; /* IS NOT TRUE or IS NOT FALSE */ ++ int isTrue; /* IS TRUE or IS NOT TRUE */ ++ testcase( jumpIfNull==0 ); ++ isNot = pExpr->op2==TK_ISNOT; ++ isTrue = sqlite3ExprTruthValue(pExpr->pRight); ++ testcase( isTrue && isNot ); ++ testcase( !isTrue && isNot ); ++ if( isTrue ^ isNot ){ ++ sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, ++ isNot ? SQLITE_JUMPIFNULL : 0); ++ }else{ ++ sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, ++ isNot ? SQLITE_JUMPIFNULL : 0); ++ } ++ break; ++ } + case TK_IS: + case TK_ISNOT: + testcase( op==TK_IS ); +@@ -96142,9 +100628,7 @@ + case TK_AND: { + testcase( jumpIfNull==0 ); + sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); +- sqlite3ExprCachePush(pParse); + sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); +- sqlite3ExprCachePop(pParse); + break; + } + case TK_OR: { +@@ -96151,10 +100635,8 @@ + int d2 = sqlite3VdbeMakeLabel(v); + testcase( jumpIfNull==0 ); + sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL); +- sqlite3ExprCachePush(pParse); + sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); + sqlite3VdbeResolveLabel(v, d2); +- sqlite3ExprCachePop(pParse); + break; + } + case TK_NOT: { +@@ -96162,6 +100644,26 @@ + sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); + break; + } ++ case TK_TRUTH: { ++ int isNot; /* IS NOT TRUE or IS NOT FALSE */ ++ int isTrue; /* IS TRUE or IS NOT TRUE */ ++ testcase( jumpIfNull==0 ); ++ isNot = pExpr->op2==TK_ISNOT; ++ isTrue = sqlite3ExprTruthValue(pExpr->pRight); ++ testcase( isTrue && isNot ); ++ testcase( !isTrue && isNot ); ++ if( isTrue ^ isNot ){ ++ /* IS TRUE and IS NOT FALSE */ ++ sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, ++ isNot ? 0 : SQLITE_JUMPIFNULL); ++ ++ }else{ ++ /* IS FALSE and IS NOT TRUE */ ++ sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, ++ isNot ? 0 : SQLITE_JUMPIFNULL); ++ } ++ break; ++ } + case TK_IS: + case TK_ISNOT: + testcase( pExpr->op==TK_IS ); +@@ -96347,17 +100849,35 @@ + if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){ + if( pA->op==TK_FUNCTION ){ + if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2; ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ /* Justification for the assert(): ++ ** window functions have p->op==TK_FUNCTION but aggregate functions ++ ** have p->op==TK_AGG_FUNCTION. So any comparison between an aggregate ++ ** function and a window function should have failed before reaching ++ ** this point. And, it is not possible to have a window function and ++ ** a scalar function with the same name and number of arguments. So ++ ** if we reach this point, either A and B both window functions or ++ ** neither are a window functions. */ ++ assert( ExprHasProperty(pA,EP_WinFunc)==ExprHasProperty(pB,EP_WinFunc) ); ++ if( ExprHasProperty(pA,EP_WinFunc) ){ ++ if( sqlite3WindowCompare(pParse,pA->y.pWin,pB->y.pWin)!=0 ) return 2; ++ } ++#endif ++ }else if( pA->op==TK_COLLATE ){ ++ if( sqlite3_stricmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2; + }else if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ +- return pA->op==TK_COLLATE ? 1 : 2; ++ return 2; + } + } + if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; + if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){ + if( combinedFlags & EP_xIsSelect ) return 2; +- if( sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2; ++ if( (combinedFlags & EP_FixedCol)==0 ++ && sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2; + if( sqlite3ExprCompare(pParse, pA->pRight, pB->pRight, iTab) ) return 2; + if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2; +- if( ALWAYS((combinedFlags & EP_Reduced)==0) && pA->op!=TK_STRING ){ ++ assert( (combinedFlags & EP_Reduced)==0 ); ++ if( pA->op!=TK_STRING && pA->op!=TK_TRUEFALSE ){ + if( pA->iColumn!=pB->iColumn ) return 2; + if( pA->iTable!=pB->iTable + && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2; +@@ -96450,6 +100970,102 @@ + } + + /* ++** This is the Expr node callback for sqlite3ExprImpliesNotNullRow(). ++** If the expression node requires that the table at pWalker->iCur ++** have one or more non-NULL column, then set pWalker->eCode to 1 and abort. ++** ++** This routine controls an optimization. False positives (setting ++** pWalker->eCode to 1 when it should not be) are deadly, but false-negatives ++** (never setting pWalker->eCode) is a harmless missed optimization. ++*/ ++static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ ++ testcase( pExpr->op==TK_AGG_COLUMN ); ++ testcase( pExpr->op==TK_AGG_FUNCTION ); ++ if( ExprHasProperty(pExpr, EP_FromJoin) ) return WRC_Prune; ++ switch( pExpr->op ){ ++ case TK_ISNOT: ++ case TK_NOT: ++ case TK_ISNULL: ++ case TK_IS: ++ case TK_OR: ++ case TK_CASE: ++ case TK_IN: ++ case TK_FUNCTION: ++ testcase( pExpr->op==TK_ISNOT ); ++ testcase( pExpr->op==TK_NOT ); ++ testcase( pExpr->op==TK_ISNULL ); ++ testcase( pExpr->op==TK_IS ); ++ testcase( pExpr->op==TK_OR ); ++ testcase( pExpr->op==TK_CASE ); ++ testcase( pExpr->op==TK_IN ); ++ testcase( pExpr->op==TK_FUNCTION ); ++ return WRC_Prune; ++ case TK_COLUMN: ++ if( pWalker->u.iCur==pExpr->iTable ){ ++ pWalker->eCode = 1; ++ return WRC_Abort; ++ } ++ return WRC_Prune; ++ ++ /* Virtual tables are allowed to use constraints like x=NULL. So ++ ** a term of the form x=y does not prove that y is not null if x ++ ** is the column of a virtual table */ ++ case TK_EQ: ++ case TK_NE: ++ case TK_LT: ++ case TK_LE: ++ case TK_GT: ++ case TK_GE: ++ testcase( pExpr->op==TK_EQ ); ++ testcase( pExpr->op==TK_NE ); ++ testcase( pExpr->op==TK_LT ); ++ testcase( pExpr->op==TK_LE ); ++ testcase( pExpr->op==TK_GT ); ++ testcase( pExpr->op==TK_GE ); ++ if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->y.pTab)) ++ || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->y.pTab)) ++ ){ ++ return WRC_Prune; ++ } ++ default: ++ return WRC_Continue; ++ } ++} ++ ++/* ++** Return true (non-zero) if expression p can only be true if at least ++** one column of table iTab is non-null. In other words, return true ++** if expression p will always be NULL or false if every column of iTab ++** is NULL. ++** ++** False negatives are acceptable. In other words, it is ok to return ++** zero even if expression p will never be true of every column of iTab ++** is NULL. A false negative is merely a missed optimization opportunity. ++** ++** False positives are not allowed, however. A false positive may result ++** in an incorrect answer. ++** ++** Terms of p that are marked with EP_FromJoin (and hence that come from ++** the ON or USING clauses of LEFT JOINS) are excluded from the analysis. ++** ++** This routine is used to check if a LEFT JOIN can be converted into ++** an ordinary JOIN. The p argument is the WHERE clause. If the WHERE ++** clause requires that some column of the right table of the LEFT JOIN ++** be non-NULL, then the LEFT JOIN can be safely converted into an ++** ordinary join. ++*/ ++SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){ ++ Walker w; ++ w.xExprCallback = impliesNotNullRow; ++ w.xSelectCallback = 0; ++ w.xSelectCallback2 = 0; ++ w.eCode = 0; ++ w.u.iCur = iTab; ++ sqlite3WalkExpr(&w, p); ++ return w.eCode; ++} ++ ++/* + ** An instance of the following structure is used by the tree walker + ** to determine if an expression can be evaluated by reference to the + ** index only, without having to do a search for the corresponding +@@ -96604,8 +101220,9 @@ + NameContext *pNC = pWalker->u.pNC; + Parse *pParse = pNC->pParse; + SrcList *pSrcList = pNC->pSrcList; +- AggInfo *pAggInfo = pNC->pAggInfo; ++ AggInfo *pAggInfo = pNC->uNC.pAggInfo; + ++ assert( pNC->ncFlags & NC_UAggInfo ); + switch( pExpr->op ){ + case TK_AGG_COLUMN: + case TK_COLUMN: { +@@ -96637,7 +101254,7 @@ + && (k = addAggInfoColumn(pParse->db, pAggInfo))>=0 + ){ + pCol = &pAggInfo->aCol[k]; +- pCol->pTab = pExpr->pTab; ++ pCol->pTab = pExpr->y.pTab; + pCol->iTable = pExpr->iTable; + pCol->iColumn = pExpr->iColumn; + pCol->iMem = ++pParse->nMem; +@@ -96783,21 +101400,9 @@ + /* + ** Deallocate a register, making available for reuse for some other + ** purpose. +-** +-** If a register is currently being used by the column cache, then +-** the deallocation is deferred until the column cache line that uses +-** the register becomes stale. + */ + SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ + if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){ +- int i; +- struct yColCache *p; +- for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){ +- if( p->iReg==iReg ){ +- p->tempReg = 1; +- return; +- } +- } + pParse->aTempReg[pParse->nTempReg++] = iReg; + } + } +@@ -96811,7 +101416,6 @@ + i = pParse->iRangeReg; + n = pParse->nRangeReg; + if( nReg<=n ){ +- assert( !usedAsColumnCache(pParse, i, i+n-1) ); + pParse->iRangeReg += nReg; + pParse->nRangeReg -= nReg; + }else{ +@@ -96825,7 +101429,6 @@ + sqlite3ReleaseTempReg(pParse, iReg); + return; + } +- sqlite3ExprCacheRemove(pParse, iReg, nReg); + if( nReg>pParse->nRangeReg ){ + pParse->nRangeReg = nReg; + pParse->iRangeReg = iReg; +@@ -96887,369 +101490,66 @@ + */ + #ifndef SQLITE_OMIT_ALTERTABLE + +- + /* +-** This function is used by SQL generated to implement the +-** ALTER TABLE command. The first argument is the text of a CREATE TABLE or +-** CREATE INDEX command. The second is a table name. The table name in +-** the CREATE TABLE or CREATE INDEX statement is replaced with the third +-** argument and the result returned. Examples: ++** Parameter zName is the name of a table that is about to be altered ++** (either with ALTER TABLE ... RENAME TO or ALTER TABLE ... ADD COLUMN). ++** If the table is a system table, this function leaves an error message ++** in pParse->zErr (system tables may not be altered) and returns non-zero. + ** +-** sqlite_rename_table('CREATE TABLE abc(a, b, c)', 'def') +-** -> 'CREATE TABLE def(a, b, c)' +-** +-** sqlite_rename_table('CREATE INDEX i ON abc(a)', 'def') +-** -> 'CREATE INDEX i ON def(a, b, c)' ++** Or, if zName is not a system table, zero is returned. + */ +-static void renameTableFunc( +- sqlite3_context *context, +- int NotUsed, +- sqlite3_value **argv +-){ +- unsigned char const *zSql = sqlite3_value_text(argv[0]); +- unsigned char const *zTableName = sqlite3_value_text(argv[1]); +- +- int token; +- Token tname; +- unsigned char const *zCsr = zSql; +- int len = 0; +- char *zRet; +- +- sqlite3 *db = sqlite3_context_db_handle(context); +- +- UNUSED_PARAMETER(NotUsed); +- +- /* The principle used to locate the table name in the CREATE TABLE +- ** statement is that the table name is the first non-space token that +- ** is immediately followed by a TK_LP or TK_USING token. +- */ +- if( zSql ){ +- do { +- if( !*zCsr ){ +- /* Ran out of input before finding an opening bracket. Return NULL. */ +- return; +- } +- +- /* Store the token that zCsr points to in tname. */ +- tname.z = (char*)zCsr; +- tname.n = len; +- +- /* Advance zCsr to the next token. Store that token type in 'token', +- ** and its length in 'len' (to be used next iteration of this loop). +- */ +- do { +- zCsr += len; +- len = sqlite3GetToken(zCsr, &token); +- } while( token==TK_SPACE ); +- assert( len>0 ); +- } while( token!=TK_LP && token!=TK_USING ); +- +- zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql), +- zSql, zTableName, tname.z+tname.n); +- sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); ++static int isSystemTable(Parse *pParse, const char *zName){ ++ if( 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ ++ sqlite3ErrorMsg(pParse, "table %s may not be altered", zName); ++ return 1; + } ++ return 0; + } + + /* +-** This C function implements an SQL user function that is used by SQL code +-** generated by the ALTER TABLE ... RENAME command to modify the definition +-** of any foreign key constraints that use the table being renamed as the +-** parent table. It is passed three arguments: +-** +-** 1) The complete text of the CREATE TABLE statement being modified, +-** 2) The old name of the table being renamed, and +-** 3) The new name of the table being renamed. +-** +-** It returns the new CREATE TABLE statement. For example: +-** +-** sqlite_rename_parent('CREATE TABLE t1(a REFERENCES t2)', 't2', 't3') +-** -> 'CREATE TABLE t1(a REFERENCES t3)' ++** Generate code to verify that the schemas of database zDb and, if ++** bTemp is not true, database "temp", can still be parsed. This is ++** called at the end of the generation of an ALTER TABLE ... RENAME ... ++** statement to ensure that the operation has not rendered any schema ++** objects unusable. + */ +-#ifndef SQLITE_OMIT_FOREIGN_KEY +-static void renameParentFunc( +- sqlite3_context *context, +- int NotUsed, +- sqlite3_value **argv +-){ +- sqlite3 *db = sqlite3_context_db_handle(context); +- char *zOutput = 0; +- char *zResult; +- unsigned char const *zInput = sqlite3_value_text(argv[0]); +- unsigned char const *zOld = sqlite3_value_text(argv[1]); +- unsigned char const *zNew = sqlite3_value_text(argv[2]); ++static void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){ ++ sqlite3NestedParse(pParse, ++ "SELECT 1 " ++ "FROM \"%w\".%s " ++ "WHERE name NOT LIKE 'sqlite_%%'" ++ " AND sql NOT LIKE 'create virtual%%'" ++ " AND sqlite_rename_test(%Q, sql, type, name, %d)=NULL ", ++ zDb, MASTER_NAME, ++ zDb, bTemp ++ ); + +- unsigned const char *z; /* Pointer to token */ +- int n; /* Length of token z */ +- int token; /* Type of token */ +- +- UNUSED_PARAMETER(NotUsed); +- if( zInput==0 || zOld==0 ) return; +- for(z=zInput; *z; z=z+n){ +- n = sqlite3GetToken(z, &token); +- if( token==TK_REFERENCES ){ +- char *zParent; +- do { +- z += n; +- n = sqlite3GetToken(z, &token); +- }while( token==TK_SPACE ); +- +- if( token==TK_ILLEGAL ) break; +- zParent = sqlite3DbStrNDup(db, (const char *)z, n); +- if( zParent==0 ) break; +- sqlite3Dequote(zParent); +- if( 0==sqlite3StrICmp((const char *)zOld, zParent) ){ +- char *zOut = sqlite3MPrintf(db, "%s%.*s\"%w\"", +- (zOutput?zOutput:""), (int)(z-zInput), zInput, (const char *)zNew +- ); +- sqlite3DbFree(db, zOutput); +- zOutput = zOut; +- zInput = &z[n]; +- } +- sqlite3DbFree(db, zParent); +- } ++ if( bTemp==0 ){ ++ sqlite3NestedParse(pParse, ++ "SELECT 1 " ++ "FROM temp.%s " ++ "WHERE name NOT LIKE 'sqlite_%%'" ++ " AND sql NOT LIKE 'create virtual%%'" ++ " AND sqlite_rename_test(%Q, sql, type, name, 1)=NULL ", ++ MASTER_NAME, zDb ++ ); + } +- +- zResult = sqlite3MPrintf(db, "%s%s", (zOutput?zOutput:""), zInput), +- sqlite3_result_text(context, zResult, -1, SQLITE_DYNAMIC); +- sqlite3DbFree(db, zOutput); + } +-#endif + +-#ifndef SQLITE_OMIT_TRIGGER +-/* This function is used by SQL generated to implement the +-** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER +-** statement. The second is a table name. The table name in the CREATE +-** TRIGGER statement is replaced with the third argument and the result +-** returned. This is analagous to renameTableFunc() above, except for CREATE +-** TRIGGER, not CREATE INDEX and CREATE TABLE. +-*/ +-static void renameTriggerFunc( +- sqlite3_context *context, +- int NotUsed, +- sqlite3_value **argv +-){ +- unsigned char const *zSql = sqlite3_value_text(argv[0]); +- unsigned char const *zTableName = sqlite3_value_text(argv[1]); +- +- int token; +- Token tname; +- int dist = 3; +- unsigned char const *zCsr = zSql; +- int len = 0; +- char *zRet; +- sqlite3 *db = sqlite3_context_db_handle(context); +- +- UNUSED_PARAMETER(NotUsed); +- +- /* The principle used to locate the table name in the CREATE TRIGGER +- ** statement is that the table name is the first token that is immediately +- ** preceded by either TK_ON or TK_DOT and immediately followed by one +- ** of TK_WHEN, TK_BEGIN or TK_FOR. +- */ +- if( zSql ){ +- do { +- +- if( !*zCsr ){ +- /* Ran out of input before finding the table name. Return NULL. */ +- return; +- } +- +- /* Store the token that zCsr points to in tname. */ +- tname.z = (char*)zCsr; +- tname.n = len; +- +- /* Advance zCsr to the next token. Store that token type in 'token', +- ** and its length in 'len' (to be used next iteration of this loop). +- */ +- do { +- zCsr += len; +- len = sqlite3GetToken(zCsr, &token); +- }while( token==TK_SPACE ); +- assert( len>0 ); +- +- /* Variable 'dist' stores the number of tokens read since the most +- ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN +- ** token is read and 'dist' equals 2, the condition stated above +- ** to be met. +- ** +- ** Note that ON cannot be a database, table or column name, so +- ** there is no need to worry about syntax like +- ** "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc. +- */ +- dist++; +- if( token==TK_DOT || token==TK_ON ){ +- dist = 0; +- } +- } while( dist!=2 || (token!=TK_WHEN && token!=TK_FOR && token!=TK_BEGIN) ); +- +- /* Variable tname now contains the token that is the old table-name +- ** in the CREATE TRIGGER statement. +- */ +- zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql), +- zSql, zTableName, tname.z+tname.n); +- sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); +- } +-} +-#endif /* !SQLITE_OMIT_TRIGGER */ +- + /* +-** Register built-in functions used to help implement ALTER TABLE ++** Generate code to reload the schema for database iDb. And, if iDb!=1, for ++** the temp database as well. + */ +-SQLITE_PRIVATE void sqlite3AlterFunctions(void){ +- static FuncDef aAlterTableFuncs[] = { +- FUNCTION(sqlite_rename_table, 2, 0, 0, renameTableFunc), +-#ifndef SQLITE_OMIT_TRIGGER +- FUNCTION(sqlite_rename_trigger, 2, 0, 0, renameTriggerFunc), +-#endif +-#ifndef SQLITE_OMIT_FOREIGN_KEY +- FUNCTION(sqlite_rename_parent, 3, 0, 0, renameParentFunc), +-#endif +- }; +- sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs)); +-} +- +-/* +-** This function is used to create the text of expressions of the form: +-** +-** name=<constant1> OR name=<constant2> OR ... +-** +-** If argument zWhere is NULL, then a pointer string containing the text +-** "name=<constant>" is returned, where <constant> is the quoted version +-** of the string passed as argument zConstant. The returned buffer is +-** allocated using sqlite3DbMalloc(). It is the responsibility of the +-** caller to ensure that it is eventually freed. +-** +-** If argument zWhere is not NULL, then the string returned is +-** "<where> OR name=<constant>", where <where> is the contents of zWhere. +-** In this case zWhere is passed to sqlite3DbFree() before returning. +-** +-*/ +-static char *whereOrName(sqlite3 *db, char *zWhere, char *zConstant){ +- char *zNew; +- if( !zWhere ){ +- zNew = sqlite3MPrintf(db, "name=%Q", zConstant); +- }else{ +- zNew = sqlite3MPrintf(db, "%s OR name=%Q", zWhere, zConstant); +- sqlite3DbFree(db, zWhere); ++static void renameReloadSchema(Parse *pParse, int iDb){ ++ Vdbe *v = pParse->pVdbe; ++ if( v ){ ++ sqlite3ChangeCookie(pParse, iDb); ++ sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iDb, 0); ++ if( iDb!=1 ) sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, 1, 0); + } +- return zNew; + } + +-#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) + /* +-** Generate the text of a WHERE expression which can be used to select all +-** tables that have foreign key constraints that refer to table pTab (i.e. +-** constraints for which pTab is the parent table) from the sqlite_master +-** table. +-*/ +-static char *whereForeignKeys(Parse *pParse, Table *pTab){ +- FKey *p; +- char *zWhere = 0; +- for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ +- zWhere = whereOrName(pParse->db, zWhere, p->pFrom->zName); +- } +- return zWhere; +-} +-#endif +- +-/* +-** Generate the text of a WHERE expression which can be used to select all +-** temporary triggers on table pTab from the sqlite_temp_master table. If +-** table pTab has no temporary triggers, or is itself stored in the +-** temporary database, NULL is returned. +-*/ +-static char *whereTempTriggers(Parse *pParse, Table *pTab){ +- Trigger *pTrig; +- char *zWhere = 0; +- const Schema *pTempSchema = pParse->db->aDb[1].pSchema; /* Temp db schema */ +- +- /* If the table is not located in the temp-db (in which case NULL is +- ** returned, loop through the tables list of triggers. For each trigger +- ** that is not part of the temp-db schema, add a clause to the WHERE +- ** expression being built up in zWhere. +- */ +- if( pTab->pSchema!=pTempSchema ){ +- sqlite3 *db = pParse->db; +- for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){ +- if( pTrig->pSchema==pTempSchema ){ +- zWhere = whereOrName(db, zWhere, pTrig->zName); +- } +- } +- } +- if( zWhere ){ +- char *zNew = sqlite3MPrintf(pParse->db, "type='trigger' AND (%s)", zWhere); +- sqlite3DbFree(pParse->db, zWhere); +- zWhere = zNew; +- } +- return zWhere; +-} +- +-/* +-** Generate code to drop and reload the internal representation of table +-** pTab from the database, including triggers and temporary triggers. +-** Argument zName is the name of the table in the database schema at +-** the time the generated code is executed. This can be different from +-** pTab->zName if this function is being called to code part of an +-** "ALTER TABLE RENAME TO" statement. +-*/ +-static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){ +- Vdbe *v; +- char *zWhere; +- int iDb; /* Index of database containing pTab */ +-#ifndef SQLITE_OMIT_TRIGGER +- Trigger *pTrig; +-#endif +- +- v = sqlite3GetVdbe(pParse); +- if( NEVER(v==0) ) return; +- assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); +- iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); +- assert( iDb>=0 ); +- +-#ifndef SQLITE_OMIT_TRIGGER +- /* Drop any table triggers from the internal schema. */ +- for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){ +- int iTrigDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); +- assert( iTrigDb==iDb || iTrigDb==1 ); +- sqlite3VdbeAddOp4(v, OP_DropTrigger, iTrigDb, 0, 0, pTrig->zName, 0); +- } +-#endif +- +- /* Drop the table and index from the internal schema. */ +- sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0); +- +- /* Reload the table, index and permanent trigger schemas. */ +- zWhere = sqlite3MPrintf(pParse->db, "tbl_name=%Q", zName); +- if( !zWhere ) return; +- sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere); +- +-#ifndef SQLITE_OMIT_TRIGGER +- /* Now, if the table is not stored in the temp database, reload any temp +- ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined. +- */ +- if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){ +- sqlite3VdbeAddParseSchemaOp(v, 1, zWhere); +- } +-#endif +-} +- +-/* +-** Parameter zName is the name of a table that is about to be altered +-** (either with ALTER TABLE ... RENAME TO or ALTER TABLE ... ADD COLUMN). +-** If the table is a system table, this function leaves an error message +-** in pParse->zErr (system tables may not be altered) and returns non-zero. +-** +-** Or, if zName is not a system table, zero is returned. +-*/ +-static int isSystemTable(Parse *pParse, const char *zName){ +- if( 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ +- sqlite3ErrorMsg(pParse, "table %s may not be altered", zName); +- return 1; +- } +- return 0; +-} +- +-/* + ** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy" + ** command. + */ +@@ -97266,13 +101566,10 @@ + int nTabName; /* Number of UTF-8 characters in zTabName */ + const char *zTabName; /* Original name of the table */ + Vdbe *v; +-#ifndef SQLITE_OMIT_TRIGGER +- char *zWhere = 0; /* Where clause to locate temp triggers */ +-#endif + VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */ +- int savedDbFlags; /* Saved value of db->flags */ ++ u32 savedDbFlags; /* Saved value of db->mDbFlags */ + +- savedDbFlags = db->flags; ++ savedDbFlags = db->mDbFlags; + if( NEVER(db->mallocFailed) ) goto exit_rename_table; + assert( pSrc->nSrc==1 ); + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); +@@ -97281,7 +101578,7 @@ + if( !pTab ) goto exit_rename_table; + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + zDb = db->aDb[iDb].zDbSName; +- db->flags |= SQLITE_PreferBuiltin; ++ db->mDbFlags |= DBFLAG_PreferBuiltin; + + /* Get a NULL terminated version of the new table name. */ + zName = sqlite3NameFromToken(db, pName); +@@ -97341,52 +101638,25 @@ + if( v==0 ){ + goto exit_rename_table; + } +- sqlite3BeginWriteOperation(pParse, pVTab!=0, iDb); +- sqlite3ChangeCookie(pParse, iDb); + +- /* If this is a virtual table, invoke the xRename() function if +- ** one is defined. The xRename() callback will modify the names +- ** of any resources used by the v-table implementation (including other +- ** SQLite tables) that are identified by the name of the virtual table. +- */ +-#ifndef SQLITE_OMIT_VIRTUALTABLE +- if( pVTab ){ +- int i = ++pParse->nMem; +- sqlite3VdbeLoadString(v, i, zName); +- sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB); +- sqlite3MayAbort(pParse); +- } +-#endif +- + /* figure out how many UTF-8 characters are in zName */ + zTabName = pTab->zName; + nTabName = sqlite3Utf8CharLen(zTabName, -1); + +-#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) +- if( db->flags&SQLITE_ForeignKeys ){ +- /* If foreign-key support is enabled, rewrite the CREATE TABLE +- ** statements corresponding to all child tables of foreign key constraints +- ** for which the renamed table is the parent table. */ +- if( (zWhere=whereForeignKeys(pParse, pTab))!=0 ){ +- sqlite3NestedParse(pParse, +- "UPDATE \"%w\".%s SET " +- "sql = sqlite_rename_parent(sql, %Q, %Q) " +- "WHERE %s;", zDb, MASTER_NAME, zTabName, zName, zWhere); +- sqlite3DbFree(db, zWhere); +- } +- } +-#endif ++ /* Rewrite all CREATE TABLE, INDEX, TRIGGER or VIEW statements in ++ ** the schema to use the new table name. */ ++ sqlite3NestedParse(pParse, ++ "UPDATE \"%w\".%s SET " ++ "sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, %d) " ++ "WHERE (type!='index' OR tbl_name=%Q COLLATE nocase)" ++ "AND name NOT LIKE 'sqlite_%%'" ++ , zDb, MASTER_NAME, zDb, zTabName, zName, (iDb==1), zTabName ++ ); + +- /* Modify the sqlite_master table to use the new table name. */ ++ /* Update the tbl_name and name columns of the sqlite_master table ++ ** as required. */ + sqlite3NestedParse(pParse, + "UPDATE %Q.%s SET " +-#ifdef SQLITE_OMIT_TRIGGER +- "sql = sqlite_rename_table(sql, %Q), " +-#else +- "sql = CASE " +- "WHEN type = 'trigger' THEN sqlite_rename_trigger(sql, %Q)" +- "ELSE sqlite_rename_table(sql, %Q) END, " +-#endif + "tbl_name = %Q, " + "name = CASE " + "WHEN type='table' THEN %Q " +@@ -97395,11 +101665,9 @@ + "ELSE name END " + "WHERE tbl_name=%Q COLLATE nocase AND " + "(type='table' OR type='index' OR type='trigger');", +- zDb, MASTER_NAME, zName, zName, zName, +-#ifndef SQLITE_OMIT_TRIGGER +- zName, +-#endif +- zName, nTabName, zTabName ++ zDb, MASTER_NAME, ++ zName, zName, zName, ++ nTabName, zTabName + ); + + #ifndef SQLITE_OMIT_AUTOINCREMENT +@@ -97413,40 +101681,42 @@ + } + #endif + +-#ifndef SQLITE_OMIT_TRIGGER +- /* If there are TEMP triggers on this table, modify the sqlite_temp_master +- ** table. Don't do this if the table being ALTERed is itself located in +- ** the temp database. +- */ +- if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){ ++ /* If the table being renamed is not itself part of the temp database, ++ ** edit view and trigger definitions within the temp database ++ ** as required. */ ++ if( iDb!=1 ){ + sqlite3NestedParse(pParse, + "UPDATE sqlite_temp_master SET " +- "sql = sqlite_rename_trigger(sql, %Q), " +- "tbl_name = %Q " +- "WHERE %s;", zName, zName, zWhere); +- sqlite3DbFree(db, zWhere); ++ "sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, 1), " ++ "tbl_name = " ++ "CASE WHEN tbl_name=%Q COLLATE nocase AND " ++ " sqlite_rename_test(%Q, sql, type, name, 1) " ++ "THEN %Q ELSE tbl_name END " ++ "WHERE type IN ('view', 'trigger')" ++ , zDb, zTabName, zName, zTabName, zDb, zName); + } +-#endif + +-#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) +- if( db->flags&SQLITE_ForeignKeys ){ +- FKey *p; +- for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ +- Table *pFrom = p->pFrom; +- if( pFrom!=pTab ){ +- reloadTableSchema(pParse, p->pFrom, pFrom->zName); +- } +- } ++ /* If this is a virtual table, invoke the xRename() function if ++ ** one is defined. The xRename() callback will modify the names ++ ** of any resources used by the v-table implementation (including other ++ ** SQLite tables) that are identified by the name of the virtual table. ++ */ ++#ifndef SQLITE_OMIT_VIRTUALTABLE ++ if( pVTab ){ ++ int i = ++pParse->nMem; ++ sqlite3VdbeLoadString(v, i, zName); ++ sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB); ++ sqlite3MayAbort(pParse); + } + #endif + +- /* Drop and reload the internal table schema. */ +- reloadTableSchema(pParse, pTab, zName); ++ renameReloadSchema(pParse, iDb); ++ renameTestSchema(pParse, zDb, iDb==1); + + exit_rename_table: + sqlite3SrcListDelete(db, pSrc); + sqlite3DbFree(db, zName); +- db->flags = savedDbFlags; ++ db->mDbFlags = savedDbFlags; + } + + /* +@@ -97467,12 +101737,11 @@ + Column *pCol; /* The new column */ + Expr *pDflt; /* Default value for the new column */ + sqlite3 *db; /* The database connection; */ +- Vdbe *v = pParse->pVdbe; /* The prepared statement under construction */ ++ Vdbe *v; /* The prepared statement under construction */ + int r1; /* Temporary registers */ + + db = pParse->db; + if( pParse->nErr || db->mallocFailed ) return; +- assert( v!=0 ); + pNew = pParse->pNewTable; + assert( pNew ); + +@@ -97547,11 +101816,11 @@ + zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n); + if( zCol ){ + char *zEnd = &zCol[pColDef->n-1]; +- int savedDbFlags = db->flags; ++ u32 savedDbFlags = db->mDbFlags; + while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){ + *zEnd-- = '\0'; + } +- db->flags |= SQLITE_PreferBuiltin; ++ db->mDbFlags |= DBFLAG_PreferBuiltin; + sqlite3NestedParse(pParse, + "UPDATE \"%w\".%s SET " + "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) " +@@ -97560,7 +101829,7 @@ + zTab + ); + sqlite3DbFree(db, zCol); +- db->flags = savedDbFlags; ++ db->mDbFlags = savedDbFlags; + } + + /* Make sure the schema version is at least 3. But do not upgrade +@@ -97567,17 +101836,20 @@ + ** from less than 3 to 4, as that will corrupt any preexisting DESC + ** index. + */ +- r1 = sqlite3GetTempReg(pParse); +- sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); +- sqlite3VdbeUsesBtree(v, iDb); +- sqlite3VdbeAddOp2(v, OP_AddImm, r1, -2); +- sqlite3VdbeAddOp2(v, OP_IfPos, r1, sqlite3VdbeCurrentAddr(v)+2); +- VdbeCoverage(v); +- sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, 3); +- sqlite3ReleaseTempReg(pParse, r1); ++ v = sqlite3GetVdbe(pParse); ++ if( v ){ ++ r1 = sqlite3GetTempReg(pParse); ++ sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); ++ sqlite3VdbeUsesBtree(v, iDb); ++ sqlite3VdbeAddOp2(v, OP_AddImm, r1, -2); ++ sqlite3VdbeAddOp2(v, OP_IfPos, r1, sqlite3VdbeCurrentAddr(v)+2); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, 3); ++ sqlite3ReleaseTempReg(pParse, r1); ++ } + +- /* Reload the schema of the modified table. */ +- reloadTableSchema(pParse, pTab, pTab->zName); ++ /* Reload the table definition */ ++ renameReloadSchema(pParse, iDb); + } + + /* +@@ -97598,7 +101870,6 @@ + SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ + Table *pNew; + Table *pTab; +- Vdbe *v; + int iDb; + int i; + int nAlloc; +@@ -97662,16 +101933,1146 @@ + pNew->addColOffset = pTab->addColOffset; + pNew->nTabRef = 1; + +- /* Begin a transaction and increment the schema cookie. */ +- sqlite3BeginWriteOperation(pParse, 0, iDb); +- v = sqlite3GetVdbe(pParse); +- if( !v ) goto exit_begin_add_column; +- sqlite3ChangeCookie(pParse, iDb); +- + exit_begin_add_column: + sqlite3SrcListDelete(db, pSrc); + return; + } ++ ++/* ++** Parameter pTab is the subject of an ALTER TABLE ... RENAME COLUMN ++** command. This function checks if the table is a view or virtual ++** table (columns of views or virtual tables may not be renamed). If so, ++** it loads an error message into pParse and returns non-zero. ++** ++** Or, if pTab is not a view or virtual table, zero is returned. ++*/ ++#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) ++static int isRealTable(Parse *pParse, Table *pTab){ ++ const char *zType = 0; ++#ifndef SQLITE_OMIT_VIEW ++ if( pTab->pSelect ){ ++ zType = "view"; ++ } ++#endif ++#ifndef SQLITE_OMIT_VIRTUALTABLE ++ if( IsVirtual(pTab) ){ ++ zType = "virtual table"; ++ } ++#endif ++ if( zType ){ ++ sqlite3ErrorMsg( ++ pParse, "cannot rename columns of %s \"%s\"", zType, pTab->zName ++ ); ++ return 1; ++ } ++ return 0; ++} ++#else /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */ ++# define isRealTable(x,y) (0) ++#endif ++ ++/* ++** Handles the following parser reduction: ++** ++** cmd ::= ALTER TABLE pSrc RENAME COLUMN pOld TO pNew ++*/ ++SQLITE_PRIVATE void sqlite3AlterRenameColumn( ++ Parse *pParse, /* Parsing context */ ++ SrcList *pSrc, /* Table being altered. pSrc->nSrc==1 */ ++ Token *pOld, /* Name of column being changed */ ++ Token *pNew /* New column name */ ++){ ++ sqlite3 *db = pParse->db; /* Database connection */ ++ Table *pTab; /* Table being updated */ ++ int iCol; /* Index of column being renamed */ ++ char *zOld = 0; /* Old column name */ ++ char *zNew = 0; /* New column name */ ++ const char *zDb; /* Name of schema containing the table */ ++ int iSchema; /* Index of the schema */ ++ int bQuote; /* True to quote the new name */ ++ ++ /* Locate the table to be altered */ ++ pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); ++ if( !pTab ) goto exit_rename_column; ++ ++ /* Cannot alter a system table */ ++ if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ) goto exit_rename_column; ++ if( SQLITE_OK!=isRealTable(pParse, pTab) ) goto exit_rename_column; ++ ++ /* Which schema holds the table to be altered */ ++ iSchema = sqlite3SchemaToIndex(db, pTab->pSchema); ++ assert( iSchema>=0 ); ++ zDb = db->aDb[iSchema].zDbSName; ++ ++#ifndef SQLITE_OMIT_AUTHORIZATION ++ /* Invoke the authorization callback. */ ++ if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ ++ goto exit_rename_column; ++ } ++#endif ++ ++ /* Make sure the old name really is a column name in the table to be ++ ** altered. Set iCol to be the index of the column being renamed */ ++ zOld = sqlite3NameFromToken(db, pOld); ++ if( !zOld ) goto exit_rename_column; ++ for(iCol=0; iCol<pTab->nCol; iCol++){ ++ if( 0==sqlite3StrICmp(pTab->aCol[iCol].zName, zOld) ) break; ++ } ++ if( iCol==pTab->nCol ){ ++ sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zOld); ++ goto exit_rename_column; ++ } ++ ++ /* Do the rename operation using a recursive UPDATE statement that ++ ** uses the sqlite_rename_column() SQL function to compute the new ++ ** CREATE statement text for the sqlite_master table. ++ */ ++ zNew = sqlite3NameFromToken(db, pNew); ++ if( !zNew ) goto exit_rename_column; ++ assert( pNew->n>0 ); ++ bQuote = sqlite3Isquote(pNew->z[0]); ++ sqlite3NestedParse(pParse, ++ "UPDATE \"%w\".%s SET " ++ "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, %d) " ++ "WHERE name NOT LIKE 'sqlite_%%' AND (type != 'index' OR tbl_name = %Q)" ++ " AND sql NOT LIKE 'create virtual%%'", ++ zDb, MASTER_NAME, ++ zDb, pTab->zName, iCol, zNew, bQuote, iSchema==1, ++ pTab->zName ++ ); ++ ++ sqlite3NestedParse(pParse, ++ "UPDATE temp.%s SET " ++ "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, 1) " ++ "WHERE type IN ('trigger', 'view')", ++ MASTER_NAME, ++ zDb, pTab->zName, iCol, zNew, bQuote ++ ); ++ ++ /* Drop and reload the database schema. */ ++ renameReloadSchema(pParse, iSchema); ++ renameTestSchema(pParse, zDb, iSchema==1); ++ ++ exit_rename_column: ++ sqlite3SrcListDelete(db, pSrc); ++ sqlite3DbFree(db, zOld); ++ sqlite3DbFree(db, zNew); ++ return; ++} ++ ++/* ++** Each RenameToken object maps an element of the parse tree into ++** the token that generated that element. The parse tree element ++** might be one of: ++** ++** * A pointer to an Expr that represents an ID ++** * The name of a table column in Column.zName ++** ++** A list of RenameToken objects can be constructed during parsing. ++** Each new object is created by sqlite3RenameTokenMap(). ++** As the parse tree is transformed, the sqlite3RenameTokenRemap() ++** routine is used to keep the mapping current. ++** ++** After the parse finishes, renameTokenFind() routine can be used ++** to look up the actual token value that created some element in ++** the parse tree. ++*/ ++struct RenameToken { ++ void *p; /* Parse tree element created by token t */ ++ Token t; /* The token that created parse tree element p */ ++ RenameToken *pNext; /* Next is a list of all RenameToken objects */ ++}; ++ ++/* ++** The context of an ALTER TABLE RENAME COLUMN operation that gets passed ++** down into the Walker. ++*/ ++typedef struct RenameCtx RenameCtx; ++struct RenameCtx { ++ RenameToken *pList; /* List of tokens to overwrite */ ++ int nList; /* Number of tokens in pList */ ++ int iCol; /* Index of column being renamed */ ++ Table *pTab; /* Table being ALTERed */ ++ const char *zOld; /* Old column name */ ++}; ++ ++#ifdef SQLITE_DEBUG ++/* ++** This function is only for debugging. It performs two tasks: ++** ++** 1. Checks that pointer pPtr does not already appear in the ++** rename-token list. ++** ++** 2. Dereferences each pointer in the rename-token list. ++** ++** The second is most effective when debugging under valgrind or ++** address-sanitizer or similar. If any of these pointers no longer ++** point to valid objects, an exception is raised by the memory-checking ++** tool. ++** ++** The point of this is to prevent comparisons of invalid pointer values. ++** Even though this always seems to work, it is undefined according to the ++** C standard. Example of undefined comparison: ++** ++** sqlite3_free(x); ++** if( x==y ) ... ++** ++** Technically, as x no longer points into a valid object or to the byte ++** following a valid object, it may not be used in comparison operations. ++*/ ++static void renameTokenCheckAll(Parse *pParse, void *pPtr){ ++ if( pParse->nErr==0 && pParse->db->mallocFailed==0 ){ ++ RenameToken *p; ++ u8 i = 0; ++ for(p=pParse->pRename; p; p=p->pNext){ ++ if( p->p ){ ++ assert( p->p!=pPtr ); ++ i += *(u8*)(p->p); ++ } ++ } ++ } ++} ++#else ++# define renameTokenCheckAll(x,y) ++#endif ++ ++/* ++** Remember that the parser tree element pPtr was created using ++** the token pToken. ++** ++** In other words, construct a new RenameToken object and add it ++** to the list of RenameToken objects currently being built up ++** in pParse->pRename. ++** ++** The pPtr argument is returned so that this routine can be used ++** with tail recursion in tokenExpr() routine, for a small performance ++** improvement. ++*/ ++SQLITE_PRIVATE void *sqlite3RenameTokenMap(Parse *pParse, void *pPtr, Token *pToken){ ++ RenameToken *pNew; ++ assert( pPtr || pParse->db->mallocFailed ); ++ renameTokenCheckAll(pParse, pPtr); ++ pNew = sqlite3DbMallocZero(pParse->db, sizeof(RenameToken)); ++ if( pNew ){ ++ pNew->p = pPtr; ++ pNew->t = *pToken; ++ pNew->pNext = pParse->pRename; ++ pParse->pRename = pNew; ++ } ++ ++ return pPtr; ++} ++ ++/* ++** It is assumed that there is already a RenameToken object associated ++** with parse tree element pFrom. This function remaps the associated token ++** to parse tree element pTo. ++*/ ++SQLITE_PRIVATE void sqlite3RenameTokenRemap(Parse *pParse, void *pTo, void *pFrom){ ++ RenameToken *p; ++ renameTokenCheckAll(pParse, pTo); ++ for(p=pParse->pRename; p; p=p->pNext){ ++ if( p->p==pFrom ){ ++ p->p = pTo; ++ break; ++ } ++ } ++} ++ ++/* ++** Walker callback used by sqlite3RenameExprUnmap(). ++*/ ++static int renameUnmapExprCb(Walker *pWalker, Expr *pExpr){ ++ Parse *pParse = pWalker->pParse; ++ sqlite3RenameTokenRemap(pParse, 0, (void*)pExpr); ++ return WRC_Continue; ++} ++ ++/* ++** Remove all nodes that are part of expression pExpr from the rename list. ++*/ ++SQLITE_PRIVATE void sqlite3RenameExprUnmap(Parse *pParse, Expr *pExpr){ ++ Walker sWalker; ++ memset(&sWalker, 0, sizeof(Walker)); ++ sWalker.pParse = pParse; ++ sWalker.xExprCallback = renameUnmapExprCb; ++ sqlite3WalkExpr(&sWalker, pExpr); ++} ++ ++/* ++** Remove all nodes that are part of expression-list pEList from the ++** rename list. ++*/ ++SQLITE_PRIVATE void sqlite3RenameExprlistUnmap(Parse *pParse, ExprList *pEList){ ++ if( pEList ){ ++ int i; ++ Walker sWalker; ++ memset(&sWalker, 0, sizeof(Walker)); ++ sWalker.pParse = pParse; ++ sWalker.xExprCallback = renameUnmapExprCb; ++ sqlite3WalkExprList(&sWalker, pEList); ++ for(i=0; i<pEList->nExpr; i++){ ++ sqlite3RenameTokenRemap(pParse, 0, (void*)pEList->a[i].zName); ++ } ++ } ++} ++ ++/* ++** Free the list of RenameToken objects given in the second argument ++*/ ++static void renameTokenFree(sqlite3 *db, RenameToken *pToken){ ++ RenameToken *pNext; ++ RenameToken *p; ++ for(p=pToken; p; p=pNext){ ++ pNext = p->pNext; ++ sqlite3DbFree(db, p); ++ } ++} ++ ++/* ++** Search the Parse object passed as the first argument for a RenameToken ++** object associated with parse tree element pPtr. If found, remove it ++** from the Parse object and add it to the list maintained by the ++** RenameCtx object passed as the second argument. ++*/ ++static void renameTokenFind(Parse *pParse, struct RenameCtx *pCtx, void *pPtr){ ++ RenameToken **pp; ++ assert( pPtr!=0 ); ++ for(pp=&pParse->pRename; (*pp); pp=&(*pp)->pNext){ ++ if( (*pp)->p==pPtr ){ ++ RenameToken *pToken = *pp; ++ *pp = pToken->pNext; ++ pToken->pNext = pCtx->pList; ++ pCtx->pList = pToken; ++ pCtx->nList++; ++ break; ++ } ++ } ++} ++ ++/* ++** This is a Walker select callback. It does nothing. It is only required ++** because without a dummy callback, sqlite3WalkExpr() and similar do not ++** descend into sub-select statements. ++*/ ++static int renameColumnSelectCb(Walker *pWalker, Select *p){ ++ UNUSED_PARAMETER(pWalker); ++ UNUSED_PARAMETER(p); ++ return WRC_Continue; ++} ++ ++/* ++** This is a Walker expression callback. ++** ++** For every TK_COLUMN node in the expression tree, search to see ++** if the column being references is the column being renamed by an ++** ALTER TABLE statement. If it is, then attach its associated ++** RenameToken object to the list of RenameToken objects being ++** constructed in RenameCtx object at pWalker->u.pRename. ++*/ ++static int renameColumnExprCb(Walker *pWalker, Expr *pExpr){ ++ RenameCtx *p = pWalker->u.pRename; ++ if( pExpr->op==TK_TRIGGER ++ && pExpr->iColumn==p->iCol ++ && pWalker->pParse->pTriggerTab==p->pTab ++ ){ ++ renameTokenFind(pWalker->pParse, p, (void*)pExpr); ++ }else if( pExpr->op==TK_COLUMN ++ && pExpr->iColumn==p->iCol ++ && p->pTab==pExpr->y.pTab ++ ){ ++ renameTokenFind(pWalker->pParse, p, (void*)pExpr); ++ } ++ return WRC_Continue; ++} ++ ++/* ++** The RenameCtx contains a list of tokens that reference a column that ++** is being renamed by an ALTER TABLE statement. Return the "last" ++** RenameToken in the RenameCtx and remove that RenameToken from the ++** RenameContext. "Last" means the last RenameToken encountered when ++** the input SQL is parsed from left to right. Repeated calls to this routine ++** return all column name tokens in the order that they are encountered ++** in the SQL statement. ++*/ ++static RenameToken *renameColumnTokenNext(RenameCtx *pCtx){ ++ RenameToken *pBest = pCtx->pList; ++ RenameToken *pToken; ++ RenameToken **pp; ++ ++ for(pToken=pBest->pNext; pToken; pToken=pToken->pNext){ ++ if( pToken->t.z>pBest->t.z ) pBest = pToken; ++ } ++ for(pp=&pCtx->pList; *pp!=pBest; pp=&(*pp)->pNext); ++ *pp = pBest->pNext; ++ ++ return pBest; ++} ++ ++/* ++** An error occured while parsing or otherwise processing a database ++** object (either pParse->pNewTable, pNewIndex or pNewTrigger) as part of an ++** ALTER TABLE RENAME COLUMN program. The error message emitted by the ++** sub-routine is currently stored in pParse->zErrMsg. This function ++** adds context to the error message and then stores it in pCtx. ++*/ ++static void renameColumnParseError( ++ sqlite3_context *pCtx, ++ int bPost, ++ sqlite3_value *pType, ++ sqlite3_value *pObject, ++ Parse *pParse ++){ ++ const char *zT = (const char*)sqlite3_value_text(pType); ++ const char *zN = (const char*)sqlite3_value_text(pObject); ++ char *zErr; ++ ++ zErr = sqlite3_mprintf("error in %s %s%s: %s", ++ zT, zN, (bPost ? " after rename" : ""), ++ pParse->zErrMsg ++ ); ++ sqlite3_result_error(pCtx, zErr, -1); ++ sqlite3_free(zErr); ++} ++ ++/* ++** For each name in the the expression-list pEList (i.e. each ++** pEList->a[i].zName) that matches the string in zOld, extract the ++** corresponding rename-token from Parse object pParse and add it ++** to the RenameCtx pCtx. ++*/ ++static void renameColumnElistNames( ++ Parse *pParse, ++ RenameCtx *pCtx, ++ ExprList *pEList, ++ const char *zOld ++){ ++ if( pEList ){ ++ int i; ++ for(i=0; i<pEList->nExpr; i++){ ++ char *zName = pEList->a[i].zName; ++ if( 0==sqlite3_stricmp(zName, zOld) ){ ++ renameTokenFind(pParse, pCtx, (void*)zName); ++ } ++ } ++ } ++} ++ ++/* ++** For each name in the the id-list pIdList (i.e. each pIdList->a[i].zName) ++** that matches the string in zOld, extract the corresponding rename-token ++** from Parse object pParse and add it to the RenameCtx pCtx. ++*/ ++static void renameColumnIdlistNames( ++ Parse *pParse, ++ RenameCtx *pCtx, ++ IdList *pIdList, ++ const char *zOld ++){ ++ if( pIdList ){ ++ int i; ++ for(i=0; i<pIdList->nId; i++){ ++ char *zName = pIdList->a[i].zName; ++ if( 0==sqlite3_stricmp(zName, zOld) ){ ++ renameTokenFind(pParse, pCtx, (void*)zName); ++ } ++ } ++ } ++} ++ ++/* ++** Parse the SQL statement zSql using Parse object (*p). The Parse object ++** is initialized by this function before it is used. ++*/ ++static int renameParseSql( ++ Parse *p, /* Memory to use for Parse object */ ++ const char *zDb, /* Name of schema SQL belongs to */ ++ int bTable, /* 1 -> RENAME TABLE, 0 -> RENAME COLUMN */ ++ sqlite3 *db, /* Database handle */ ++ const char *zSql, /* SQL to parse */ ++ int bTemp /* True if SQL is from temp schema */ ++){ ++ int rc; ++ char *zErr = 0; ++ ++ db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb); ++ ++ /* Parse the SQL statement passed as the first argument. If no error ++ ** occurs and the parse does not result in a new table, index or ++ ** trigger object, the database must be corrupt. */ ++ memset(p, 0, sizeof(Parse)); ++ p->eParseMode = (bTable ? PARSE_MODE_RENAME_TABLE : PARSE_MODE_RENAME_COLUMN); ++ p->db = db; ++ p->nQueryLoop = 1; ++ rc = sqlite3RunParser(p, zSql, &zErr); ++ assert( p->zErrMsg==0 ); ++ assert( rc!=SQLITE_OK || zErr==0 ); ++ assert( (0!=p->pNewTable) + (0!=p->pNewIndex) + (0!=p->pNewTrigger)<2 ); ++ p->zErrMsg = zErr; ++ if( db->mallocFailed ) rc = SQLITE_NOMEM; ++ if( rc==SQLITE_OK ++ && p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0 ++ ){ ++ rc = SQLITE_CORRUPT_BKPT; ++ } ++ ++#ifdef SQLITE_DEBUG ++ /* Ensure that all mappings in the Parse.pRename list really do map to ++ ** a part of the input string. */ ++ if( rc==SQLITE_OK ){ ++ int nSql = sqlite3Strlen30(zSql); ++ RenameToken *pToken; ++ for(pToken=p->pRename; pToken; pToken=pToken->pNext){ ++ assert( pToken->t.z>=zSql && &pToken->t.z[pToken->t.n]<=&zSql[nSql] ); ++ } ++ } ++#endif ++ ++ db->init.iDb = 0; ++ return rc; ++} ++ ++/* ++** This function edits SQL statement zSql, replacing each token identified ++** by the linked list pRename with the text of zNew. If argument bQuote is ++** true, then zNew is always quoted first. If no error occurs, the result ++** is loaded into context object pCtx as the result. ++** ++** Or, if an error occurs (i.e. an OOM condition), an error is left in ++** pCtx and an SQLite error code returned. ++*/ ++static int renameEditSql( ++ sqlite3_context *pCtx, /* Return result here */ ++ RenameCtx *pRename, /* Rename context */ ++ const char *zSql, /* SQL statement to edit */ ++ const char *zNew, /* New token text */ ++ int bQuote /* True to always quote token */ ++){ ++ int nNew = sqlite3Strlen30(zNew); ++ int nSql = sqlite3Strlen30(zSql); ++ sqlite3 *db = sqlite3_context_db_handle(pCtx); ++ int rc = SQLITE_OK; ++ char *zQuot; ++ char *zOut; ++ int nQuot; ++ ++ /* Set zQuot to point to a buffer containing a quoted copy of the ++ ** identifier zNew. If the corresponding identifier in the original ++ ** ALTER TABLE statement was quoted (bQuote==1), then set zNew to ++ ** point to zQuot so that all substitutions are made using the ++ ** quoted version of the new column name. */ ++ zQuot = sqlite3MPrintf(db, "\"%w\"", zNew); ++ if( zQuot==0 ){ ++ return SQLITE_NOMEM; ++ }else{ ++ nQuot = sqlite3Strlen30(zQuot); ++ } ++ if( bQuote ){ ++ zNew = zQuot; ++ nNew = nQuot; ++ } ++ ++ /* At this point pRename->pList contains a list of RenameToken objects ++ ** corresponding to all tokens in the input SQL that must be replaced ++ ** with the new column name. All that remains is to construct and ++ ** return the edited SQL string. */ ++ assert( nQuot>=nNew ); ++ zOut = sqlite3DbMallocZero(db, nSql + pRename->nList*nQuot + 1); ++ if( zOut ){ ++ int nOut = nSql; ++ memcpy(zOut, zSql, nSql); ++ while( pRename->pList ){ ++ int iOff; /* Offset of token to replace in zOut */ ++ RenameToken *pBest = renameColumnTokenNext(pRename); ++ ++ u32 nReplace; ++ const char *zReplace; ++ if( sqlite3IsIdChar(*pBest->t.z) ){ ++ nReplace = nNew; ++ zReplace = zNew; ++ }else{ ++ nReplace = nQuot; ++ zReplace = zQuot; ++ } ++ ++ iOff = pBest->t.z - zSql; ++ if( pBest->t.n!=nReplace ){ ++ memmove(&zOut[iOff + nReplace], &zOut[iOff + pBest->t.n], ++ nOut - (iOff + pBest->t.n) ++ ); ++ nOut += nReplace - pBest->t.n; ++ zOut[nOut] = '\0'; ++ } ++ memcpy(&zOut[iOff], zReplace, nReplace); ++ sqlite3DbFree(db, pBest); ++ } ++ ++ sqlite3_result_text(pCtx, zOut, -1, SQLITE_TRANSIENT); ++ sqlite3DbFree(db, zOut); ++ }else{ ++ 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, const char *zDb){ ++ sqlite3 *db = pParse->db; ++ Trigger *pNew = pParse->pNewTrigger; ++ TriggerStep *pStep; ++ NameContext sNC; ++ int rc = SQLITE_OK; ++ ++ memset(&sNC, 0, sizeof(sNC)); ++ sNC.pParse = pParse; ++ assert( pNew->pTabSchema ); ++ pParse->pTriggerTab = sqlite3FindTable(db, pNew->table, ++ db->aDb[sqlite3SchemaToIndex(db, pNew->pTabSchema)].zDbSName ++ ); ++ pParse->eTriggerOp = pNew->op; ++ /* ALWAYS() because if the table of the trigger does not exist, the ++ ** error would have been hit before this point */ ++ if( ALWAYS(pParse->pTriggerTab) ){ ++ rc = sqlite3ViewGetColumnNames(pParse, pParse->pTriggerTab); ++ } ++ ++ /* Resolve symbols in WHEN clause */ ++ if( rc==SQLITE_OK && pNew->pWhen ){ ++ rc = sqlite3ResolveExprNames(&sNC, pNew->pWhen); ++ } ++ ++ for(pStep=pNew->step_list; rc==SQLITE_OK && pStep; pStep=pStep->pNext){ ++ if( pStep->pSelect ){ ++ sqlite3SelectPrep(pParse, pStep->pSelect, &sNC); ++ if( pParse->nErr ) rc = pParse->rc; ++ } ++ if( rc==SQLITE_OK && pStep->zTarget ){ ++ Table *pTarget = sqlite3LocateTable(pParse, 0, pStep->zTarget, zDb); ++ if( pTarget==0 ){ ++ rc = SQLITE_ERROR; ++ }else if( SQLITE_OK==(rc = sqlite3ViewGetColumnNames(pParse, pTarget)) ){ ++ SrcList sSrc; ++ memset(&sSrc, 0, sizeof(sSrc)); ++ sSrc.nSrc = 1; ++ sSrc.a[0].zName = pStep->zTarget; ++ sSrc.a[0].pTab = pTarget; ++ sNC.pSrcList = &sSrc; ++ if( pStep->pWhere ){ ++ rc = sqlite3ResolveExprNames(&sNC, pStep->pWhere); ++ } ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3ResolveExprListNames(&sNC, pStep->pExprList); ++ } ++ assert( !pStep->pUpsert || (!pStep->pWhere && !pStep->pExprList) ); ++ if( pStep->pUpsert ){ ++ Upsert *pUpsert = pStep->pUpsert; ++ assert( rc==SQLITE_OK ); ++ pUpsert->pUpsertSrc = &sSrc; ++ sNC.uNC.pUpsert = pUpsert; ++ sNC.ncFlags = NC_UUpsert; ++ rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget); ++ if( rc==SQLITE_OK ){ ++ ExprList *pUpsertSet = pUpsert->pUpsertSet; ++ rc = sqlite3ResolveExprListNames(&sNC, pUpsertSet); ++ } ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertWhere); ++ } ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere); ++ } ++ sNC.ncFlags = 0; ++ } ++ } ++ } ++ } ++ return rc; ++} ++ ++/* ++** Invoke sqlite3WalkExpr() or sqlite3WalkSelect() on all Select or Expr ++** objects that are part of the trigger passed as the second argument. ++*/ ++static void renameWalkTrigger(Walker *pWalker, Trigger *pTrigger){ ++ TriggerStep *pStep; ++ ++ /* Find tokens to edit in WHEN clause */ ++ sqlite3WalkExpr(pWalker, pTrigger->pWhen); ++ ++ /* Find tokens to edit in trigger steps */ ++ for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){ ++ sqlite3WalkSelect(pWalker, pStep->pSelect); ++ sqlite3WalkExpr(pWalker, pStep->pWhere); ++ sqlite3WalkExprList(pWalker, pStep->pExprList); ++ if( pStep->pUpsert ){ ++ Upsert *pUpsert = pStep->pUpsert; ++ sqlite3WalkExprList(pWalker, pUpsert->pUpsertTarget); ++ sqlite3WalkExprList(pWalker, pUpsert->pUpsertSet); ++ sqlite3WalkExpr(pWalker, pUpsert->pUpsertWhere); ++ sqlite3WalkExpr(pWalker, pUpsert->pUpsertTargetWhere); ++ } ++ } ++} ++ ++/* ++** Free the contents of Parse object (*pParse). Do not free the memory ++** occupied by the Parse object itself. ++*/ ++static void renameParseCleanup(Parse *pParse){ ++ sqlite3 *db = pParse->db; ++ if( pParse->pVdbe ){ ++ sqlite3VdbeFinalize(pParse->pVdbe); ++ } ++ sqlite3DeleteTable(db, pParse->pNewTable); ++ if( pParse->pNewIndex ) sqlite3FreeIndex(db, pParse->pNewIndex); ++ sqlite3DeleteTrigger(db, pParse->pNewTrigger); ++ sqlite3DbFree(db, pParse->zErrMsg); ++ renameTokenFree(db, pParse->pRename); ++ sqlite3ParserReset(pParse); ++} ++ ++/* ++** SQL function: ++** ++** sqlite_rename_column(zSql, iCol, bQuote, zNew, zTable, zOld) ++** ++** 0. zSql: SQL statement to rewrite ++** 1. type: Type of object ("table", "view" etc.) ++** 2. object: Name of object ++** 3. Database: Database name (e.g. "main") ++** 4. Table: Table name ++** 5. iCol: Index of column to rename ++** 6. zNew: New column name ++** 7. bQuote: Non-zero if the new column name should be quoted. ++** 8. bTemp: True if zSql comes from temp schema ++** ++** Do a column rename operation on the CREATE statement given in zSql. ++** The iCol-th column (left-most is 0) of table zTable is renamed from zCol ++** into zNew. The name should be quoted if bQuote is true. ++** ++** This function is used internally by the ALTER TABLE RENAME COLUMN command. ++** It is only accessible to SQL created using sqlite3NestedParse(). It is ++** not reachable from ordinary SQL passed into sqlite3_prepare(). ++*/ ++static void renameColumnFunc( ++ sqlite3_context *context, ++ int NotUsed, ++ sqlite3_value **argv ++){ ++ sqlite3 *db = sqlite3_context_db_handle(context); ++ RenameCtx sCtx; ++ const char *zSql = (const char*)sqlite3_value_text(argv[0]); ++ const char *zDb = (const char*)sqlite3_value_text(argv[3]); ++ const char *zTable = (const char*)sqlite3_value_text(argv[4]); ++ int iCol = sqlite3_value_int(argv[5]); ++ const char *zNew = (const char*)sqlite3_value_text(argv[6]); ++ int bQuote = sqlite3_value_int(argv[7]); ++ int bTemp = sqlite3_value_int(argv[8]); ++ const char *zOld; ++ int rc; ++ Parse sParse; ++ Walker sWalker; ++ Index *pIdx; ++ int i; ++ Table *pTab; ++#ifndef SQLITE_OMIT_AUTHORIZATION ++ sqlite3_xauth xAuth = db->xAuth; ++#endif ++ ++ UNUSED_PARAMETER(NotUsed); ++ if( zSql==0 ) return; ++ if( zTable==0 ) return; ++ if( zNew==0 ) return; ++ if( iCol<0 ) return; ++ sqlite3BtreeEnterAll(db); ++ pTab = sqlite3FindTable(db, zTable, zDb); ++ if( pTab==0 || iCol>=pTab->nCol ){ ++ sqlite3BtreeLeaveAll(db); ++ return; ++ } ++ zOld = pTab->aCol[iCol].zName; ++ memset(&sCtx, 0, sizeof(sCtx)); ++ sCtx.iCol = ((iCol==pTab->iPKey) ? -1 : iCol); ++ ++#ifndef SQLITE_OMIT_AUTHORIZATION ++ db->xAuth = 0; ++#endif ++ rc = renameParseSql(&sParse, zDb, 0, db, zSql, bTemp); ++ ++ /* Find tokens that need to be replaced. */ ++ memset(&sWalker, 0, sizeof(Walker)); ++ sWalker.pParse = &sParse; ++ sWalker.xExprCallback = renameColumnExprCb; ++ sWalker.xSelectCallback = renameColumnSelectCb; ++ sWalker.u.pRename = &sCtx; ++ ++ sCtx.pTab = pTab; ++ if( rc!=SQLITE_OK ) goto renameColumnFunc_done; ++ if( sParse.pNewTable ){ ++ Select *pSelect = sParse.pNewTable->pSelect; ++ if( pSelect ){ ++ sParse.rc = SQLITE_OK; ++ sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, 0); ++ rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc); ++ if( rc==SQLITE_OK ){ ++ sqlite3WalkSelect(&sWalker, pSelect); ++ } ++ if( rc!=SQLITE_OK ) goto renameColumnFunc_done; ++ }else{ ++ /* A regular table */ ++ int bFKOnly = sqlite3_stricmp(zTable, sParse.pNewTable->zName); ++ FKey *pFKey; ++ assert( sParse.pNewTable->pSelect==0 ); ++ sCtx.pTab = sParse.pNewTable; ++ if( bFKOnly==0 ){ ++ renameTokenFind( ++ &sParse, &sCtx, (void*)sParse.pNewTable->aCol[iCol].zName ++ ); ++ if( sCtx.iCol<0 ){ ++ renameTokenFind(&sParse, &sCtx, (void*)&sParse.pNewTable->iPKey); ++ } ++ sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck); ++ for(pIdx=sParse.pNewTable->pIndex; pIdx; pIdx=pIdx->pNext){ ++ sqlite3WalkExprList(&sWalker, pIdx->aColExpr); ++ } ++ } ++ ++ for(pFKey=sParse.pNewTable->pFKey; pFKey; pFKey=pFKey->pNextFrom){ ++ for(i=0; i<pFKey->nCol; i++){ ++ if( bFKOnly==0 && pFKey->aCol[i].iFrom==iCol ){ ++ renameTokenFind(&sParse, &sCtx, (void*)&pFKey->aCol[i]); ++ } ++ if( 0==sqlite3_stricmp(pFKey->zTo, zTable) ++ && 0==sqlite3_stricmp(pFKey->aCol[i].zCol, zOld) ++ ){ ++ renameTokenFind(&sParse, &sCtx, (void*)pFKey->aCol[i].zCol); ++ } ++ } ++ } ++ } ++ }else if( sParse.pNewIndex ){ ++ sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr); ++ sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere); ++ }else{ ++ /* A trigger */ ++ TriggerStep *pStep; ++ rc = renameResolveTrigger(&sParse, (bTemp ? 0 : zDb)); ++ if( rc!=SQLITE_OK ) goto renameColumnFunc_done; ++ ++ for(pStep=sParse.pNewTrigger->step_list; pStep; pStep=pStep->pNext){ ++ if( pStep->zTarget ){ ++ Table *pTarget = sqlite3LocateTable(&sParse, 0, pStep->zTarget, zDb); ++ if( pTarget==pTab ){ ++ if( pStep->pUpsert ){ ++ ExprList *pUpsertSet = pStep->pUpsert->pUpsertSet; ++ renameColumnElistNames(&sParse, &sCtx, pUpsertSet, zOld); ++ } ++ renameColumnIdlistNames(&sParse, &sCtx, pStep->pIdList, zOld); ++ renameColumnElistNames(&sParse, &sCtx, pStep->pExprList, zOld); ++ } ++ } ++ } ++ ++ ++ /* Find tokens to edit in UPDATE OF clause */ ++ if( sParse.pTriggerTab==pTab ){ ++ renameColumnIdlistNames(&sParse, &sCtx,sParse.pNewTrigger->pColumns,zOld); ++ } ++ ++ /* Find tokens to edit in various expressions and selects */ ++ renameWalkTrigger(&sWalker, sParse.pNewTrigger); ++ } ++ ++ assert( rc==SQLITE_OK ); ++ rc = renameEditSql(context, &sCtx, zSql, zNew, bQuote); ++ ++renameColumnFunc_done: ++ if( rc!=SQLITE_OK ){ ++ if( sParse.zErrMsg ){ ++ renameColumnParseError(context, 0, argv[1], argv[2], &sParse); ++ }else{ ++ sqlite3_result_error_code(context, rc); ++ } ++ } ++ ++ renameParseCleanup(&sParse); ++ renameTokenFree(db, sCtx.pList); ++#ifndef SQLITE_OMIT_AUTHORIZATION ++ db->xAuth = xAuth; ++#endif ++ sqlite3BtreeLeaveAll(db); ++} ++ ++/* ++** Walker expression callback used by "RENAME TABLE". ++*/ ++static int renameTableExprCb(Walker *pWalker, Expr *pExpr){ ++ RenameCtx *p = pWalker->u.pRename; ++ if( pExpr->op==TK_COLUMN && p->pTab==pExpr->y.pTab ){ ++ renameTokenFind(pWalker->pParse, p, (void*)&pExpr->y.pTab); ++ } ++ return WRC_Continue; ++} ++ ++/* ++** Walker select callback used by "RENAME TABLE". ++*/ ++static int renameTableSelectCb(Walker *pWalker, Select *pSelect){ ++ int i; ++ RenameCtx *p = pWalker->u.pRename; ++ SrcList *pSrc = pSelect->pSrc; ++ for(i=0; i<pSrc->nSrc; i++){ ++ struct SrcList_item *pItem = &pSrc->a[i]; ++ if( pItem->pTab==p->pTab ){ ++ renameTokenFind(pWalker->pParse, p, pItem->zName); ++ } ++ } ++ ++ return WRC_Continue; ++} ++ ++ ++/* ++** This C function implements an SQL user function that is used by SQL code ++** generated by the ALTER TABLE ... RENAME command to modify the definition ++** of any foreign key constraints that use the table being renamed as the ++** parent table. It is passed three arguments: ++** ++** 0: The database containing the table being renamed. ++** 1. type: Type of object ("table", "view" etc.) ++** 2. object: Name of object ++** 3: The complete text of the schema statement being modified, ++** 4: The old name of the table being renamed, and ++** 5: The new name of the table being renamed. ++** 6: True if the schema statement comes from the temp db. ++** ++** It returns the new schema statement. For example: ++** ++** sqlite_rename_table('main', 'CREATE TABLE t1(a REFERENCES t2)','t2','t3',0) ++** -> 'CREATE TABLE t1(a REFERENCES t3)' ++*/ ++static void renameTableFunc( ++ sqlite3_context *context, ++ int NotUsed, ++ sqlite3_value **argv ++){ ++ sqlite3 *db = sqlite3_context_db_handle(context); ++ const char *zDb = (const char*)sqlite3_value_text(argv[0]); ++ const char *zInput = (const char*)sqlite3_value_text(argv[3]); ++ const char *zOld = (const char*)sqlite3_value_text(argv[4]); ++ const char *zNew = (const char*)sqlite3_value_text(argv[5]); ++ int bTemp = sqlite3_value_int(argv[6]); ++ UNUSED_PARAMETER(NotUsed); ++ ++ if( zInput && zOld && zNew ){ ++ Parse sParse; ++ int rc; ++ int bQuote = 1; ++ RenameCtx sCtx; ++ Walker sWalker; ++ ++#ifndef SQLITE_OMIT_AUTHORIZATION ++ sqlite3_xauth xAuth = db->xAuth; ++ db->xAuth = 0; ++#endif ++ ++ sqlite3BtreeEnterAll(db); ++ ++ memset(&sCtx, 0, sizeof(RenameCtx)); ++ sCtx.pTab = sqlite3FindTable(db, zOld, zDb); ++ memset(&sWalker, 0, sizeof(Walker)); ++ sWalker.pParse = &sParse; ++ sWalker.xExprCallback = renameTableExprCb; ++ sWalker.xSelectCallback = renameTableSelectCb; ++ sWalker.u.pRename = &sCtx; ++ ++ rc = renameParseSql(&sParse, zDb, 1, db, zInput, bTemp); ++ ++ if( rc==SQLITE_OK ){ ++ int isLegacy = (db->flags & SQLITE_LegacyAlter); ++ if( sParse.pNewTable ){ ++ Table *pTab = sParse.pNewTable; ++ ++ if( pTab->pSelect ){ ++ if( isLegacy==0 ){ ++ NameContext sNC; ++ memset(&sNC, 0, sizeof(sNC)); ++ sNC.pParse = &sParse; ++ ++ sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC); ++ if( sParse.nErr ) rc = sParse.rc; ++ sqlite3WalkSelect(&sWalker, pTab->pSelect); ++ } ++ }else{ ++ /* Modify any FK definitions to point to the new table. */ ++#ifndef SQLITE_OMIT_FOREIGN_KEY ++ if( isLegacy==0 || (db->flags & SQLITE_ForeignKeys) ){ ++ FKey *pFKey; ++ for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){ ++ if( sqlite3_stricmp(pFKey->zTo, zOld)==0 ){ ++ renameTokenFind(&sParse, &sCtx, (void*)pFKey->zTo); ++ } ++ } ++ } ++#endif ++ ++ /* If this is the table being altered, fix any table refs in CHECK ++ ** expressions. Also update the name that appears right after the ++ ** "CREATE [VIRTUAL] TABLE" bit. */ ++ if( sqlite3_stricmp(zOld, pTab->zName)==0 ){ ++ sCtx.pTab = pTab; ++ if( isLegacy==0 ){ ++ sqlite3WalkExprList(&sWalker, pTab->pCheck); ++ } ++ renameTokenFind(&sParse, &sCtx, pTab->zName); ++ } ++ } ++ } ++ ++ else if( sParse.pNewIndex ){ ++ renameTokenFind(&sParse, &sCtx, sParse.pNewIndex->zName); ++ if( isLegacy==0 ){ ++ sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere); ++ } ++ } ++ ++#ifndef SQLITE_OMIT_TRIGGER ++ else{ ++ Trigger *pTrigger = sParse.pNewTrigger; ++ TriggerStep *pStep; ++ if( 0==sqlite3_stricmp(sParse.pNewTrigger->table, zOld) ++ && sCtx.pTab->pSchema==pTrigger->pTabSchema ++ ){ ++ renameTokenFind(&sParse, &sCtx, sParse.pNewTrigger->table); ++ } ++ ++ if( isLegacy==0 ){ ++ rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb); ++ if( rc==SQLITE_OK ){ ++ renameWalkTrigger(&sWalker, pTrigger); ++ for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){ ++ if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){ ++ renameTokenFind(&sParse, &sCtx, pStep->zTarget); ++ } ++ } ++ } ++ } ++ } ++#endif ++ } ++ ++ if( rc==SQLITE_OK ){ ++ rc = renameEditSql(context, &sCtx, zInput, zNew, bQuote); ++ } ++ if( rc!=SQLITE_OK ){ ++ if( sParse.zErrMsg ){ ++ renameColumnParseError(context, 0, argv[1], argv[2], &sParse); ++ }else{ ++ sqlite3_result_error_code(context, rc); ++ } ++ } ++ ++ renameParseCleanup(&sParse); ++ renameTokenFree(db, sCtx.pList); ++ sqlite3BtreeLeaveAll(db); ++#ifndef SQLITE_OMIT_AUTHORIZATION ++ db->xAuth = xAuth; ++#endif ++ } ++ ++ return; ++} ++ ++/* ++** An SQL user function that checks that there are no parse or symbol ++** resolution problems in a CREATE TRIGGER|TABLE|VIEW|INDEX statement. ++** After an ALTER TABLE .. RENAME operation is performed and the schema ++** reloaded, this function is called on each SQL statement in the schema ++** to ensure that it is still usable. ++** ++** 0: Database name ("main", "temp" etc.). ++** 1: SQL statement. ++** 2: Object type ("view", "table", "trigger" or "index"). ++** 3: Object name. ++** 4: True if object is from temp schema. ++** ++** Unless it finds an error, this function normally returns NULL. However, it ++** returns integer value 1 if: ++** ++** * the SQL argument creates a trigger, and ++** * the table that the trigger is attached to is in database zDb. ++*/ ++static void renameTableTest( ++ sqlite3_context *context, ++ int NotUsed, ++ sqlite3_value **argv ++){ ++ sqlite3 *db = sqlite3_context_db_handle(context); ++ char const *zDb = (const char*)sqlite3_value_text(argv[0]); ++ char const *zInput = (const char*)sqlite3_value_text(argv[1]); ++ int bTemp = sqlite3_value_int(argv[4]); ++ int isLegacy = (db->flags & SQLITE_LegacyAlter); ++ ++#ifndef SQLITE_OMIT_AUTHORIZATION ++ sqlite3_xauth xAuth = db->xAuth; ++ db->xAuth = 0; ++#endif ++ ++ UNUSED_PARAMETER(NotUsed); ++ if( zDb && zInput ){ ++ int rc; ++ Parse sParse; ++ rc = renameParseSql(&sParse, zDb, 1, db, zInput, bTemp); ++ if( rc==SQLITE_OK ){ ++ if( isLegacy==0 && sParse.pNewTable && sParse.pNewTable->pSelect ){ ++ NameContext sNC; ++ memset(&sNC, 0, sizeof(sNC)); ++ sNC.pParse = &sParse; ++ sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, &sNC); ++ if( sParse.nErr ) rc = sParse.rc; ++ } ++ ++ else if( sParse.pNewTrigger ){ ++ if( isLegacy==0 ){ ++ rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb); ++ } ++ if( rc==SQLITE_OK ){ ++ int i1 = sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema); ++ int i2 = sqlite3FindDbName(db, zDb); ++ if( i1==i2 ) sqlite3_result_int(context, 1); ++ } ++ } ++ } ++ ++ if( rc!=SQLITE_OK ){ ++ renameColumnParseError(context, 1, argv[2], argv[3], &sParse); ++ } ++ renameParseCleanup(&sParse); ++ } ++ ++#ifndef SQLITE_OMIT_AUTHORIZATION ++ db->xAuth = xAuth; ++#endif ++} ++ ++/* ++** Register built-in functions used to help implement ALTER TABLE ++*/ ++SQLITE_PRIVATE void sqlite3AlterFunctions(void){ ++ static FuncDef aAlterTableFuncs[] = { ++ INTERNAL_FUNCTION(sqlite_rename_column, 9, renameColumnFunc), ++ INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc), ++ INTERNAL_FUNCTION(sqlite_rename_test, 5, renameTableTest), ++ }; ++ sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs)); ++} + #endif /* SQLITE_ALTER_TABLE */ + + /************** End of alter.c ***********************************************/ +@@ -97912,6 +103313,10 @@ + "DELETE FROM %Q.%s WHERE %s=%Q", + pDb->zDbSName, zTab, zWhereType, zWhere + ); ++#ifdef SQLITE_ENABLE_PREUPDATE_HOOK ++ }else if( db->xPreUpdateCallback ){ ++ sqlite3NestedParse(pParse, "DELETE FROM %Q.%s", pDb->zDbSName, zTab); ++#endif + }else{ + /* The sqlite_stat[134] table already exists. Delete all rows. */ + sqlite3VdbeAddOp2(v, OP_Clear, aRoot[i], iDb); +@@ -98159,6 +103564,7 @@ + 0, /* pNext */ + statInit, /* xSFunc */ + 0, /* xFinalize */ ++ 0, 0, /* xValue, xInverse */ + "stat_init", /* zName */ + {0} + }; +@@ -98475,6 +103881,7 @@ + 0, /* pNext */ + statPush, /* xSFunc */ + 0, /* xFinalize */ ++ 0, 0, /* xValue, xInverse */ + "stat_push", /* zName */ + {0} + }; +@@ -98626,6 +104033,7 @@ + 0, /* pNext */ + statGet, /* xSFunc */ + 0, /* xFinalize */ ++ 0, 0, /* xValue, xInverse */ + "stat_get", /* zName */ + {0} + }; +@@ -98676,6 +104084,9 @@ + 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); +@@ -98686,7 +104097,7 @@ + /* Do not gather statistics on views or virtual tables */ + return; + } +- if( sqlite3_strlike("sqlite_%", pTab->zName, 0)==0 ){ ++ if( sqlite3_strlike("sqlite\\_%", pTab->zName, '\\')==0 ){ + /* Do not gather statistics on system tables */ + return; + } +@@ -98701,6 +104112,18 @@ + } + #endif + ++#ifdef SQLITE_ENABLE_PREUPDATE_HOOK ++ if( db->xPreUpdateCallback ){ ++ pStat1 = (Table*)sqlite3DbMallocZero(db, sizeof(Table) + 13); ++ if( pStat1==0 ) return; ++ pStat1->zName = (char*)&pStat1[1]; ++ memcpy(pStat1->zName, "sqlite_stat1", 13); ++ pStat1->nCol = 3; ++ pStat1->iPKey = -1; ++ sqlite3VdbeAddOp4(pParse->pVdbe, OP_Noop, 0, 0, 0,(char*)pStat1,P4_DYNBLOB); ++ } ++#endif ++ + /* Establish a read-lock on the table at the shared-cache level. + ** Open a read-only cursor on the table. Also allocate a cursor number + ** to use for scanning indexes (iIdxCur). No index cursor is opened at +@@ -98902,6 +104325,9 @@ + sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0); + sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid); + sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid); ++#ifdef SQLITE_ENABLE_PREUPDATE_HOOK ++ sqlite3VdbeChangeP4(v, -1, (char*)pStat1, P4_TABLE); ++#endif + sqlite3VdbeChangeP5(v, OPFLAG_APPEND); + + /* Add the entries to the stat3 or stat4 table. */ +@@ -98927,10 +104353,7 @@ + callStatGet(v, regStat4, STAT_GET_NLT, regLt); + callStatGet(v, regStat4, STAT_GET_NDLT, regDLt); + sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0); +- /* We know that the regSampleRowid row exists because it was read by +- ** the previous loop. Thus the not-found jump of seekOp will never +- ** be taken */ +- VdbeCoverageNeverTaken(v); ++ VdbeCoverage(v); + #ifdef SQLITE_ENABLE_STAT3 + sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iTabCur, 0, regSample); + #else +@@ -98965,6 +104388,9 @@ + sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid); + sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid); + sqlite3VdbeChangeP5(v, OPFLAG_APPEND); ++#ifdef SQLITE_ENABLE_PREUPDATE_HOOK ++ sqlite3VdbeChangeP4(v, -1, (char*)pStat1, P4_TABLE); ++#endif + sqlite3VdbeJumpHere(v, jZeroRows); + } + } +@@ -99567,7 +104993,7 @@ + + /* Load the statistics from the sqlite_stat4 table. */ + #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +- if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){ ++ if( rc==SQLITE_OK ){ + db->lookaside.bDisable++; + rc = loadStat4(db, sInfo.zDatabase); + db->lookaside.bDisable--; +@@ -99647,6 +105073,10 @@ + ** + ** If the optional "KEY z" syntax is omitted, an SQL NULL is passed as the + ** third argument. ++** ++** If the db->init.reopenMemdb flags is set, then instead of attaching a ++** new database, close the database on db->init.iDb and reopen it as an ++** empty MemDB. + */ + static void attachFunc( + sqlite3_context *context, +@@ -99667,70 +105097,86 @@ + sqlite3_vfs *pVfs; + + UNUSED_PARAMETER(NotUsed); +- + zFile = (const char *)sqlite3_value_text(argv[0]); + zName = (const char *)sqlite3_value_text(argv[1]); + if( zFile==0 ) zFile = ""; + if( zName==0 ) zName = ""; + +- /* Check for the following errors: +- ** +- ** * Too many attached databases, +- ** * Transaction currently open +- ** * Specified database name already being used. +- */ +- if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){ +- zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d", +- db->aLimit[SQLITE_LIMIT_ATTACHED] +- ); +- goto attach_error; +- } +- if( !db->autoCommit ){ +- zErrDyn = sqlite3MPrintf(db, "cannot ATTACH database within transaction"); +- goto attach_error; +- } +- for(i=0; i<db->nDb; i++){ +- char *z = db->aDb[i].zDbSName; +- assert( z && zName ); +- if( sqlite3StrICmp(z, zName)==0 ){ +- zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName); ++#ifdef SQLITE_ENABLE_DESERIALIZE ++# define REOPEN_AS_MEMDB(db) (db->init.reopenMemdb) ++#else ++# define REOPEN_AS_MEMDB(db) (0) ++#endif ++ ++ if( REOPEN_AS_MEMDB(db) ){ ++ /* This is not a real ATTACH. Instead, this routine is being called ++ ** from sqlite3_deserialize() to close database db->init.iDb and ++ ** reopen it as a MemDB */ ++ pVfs = sqlite3_vfs_find("memdb"); ++ if( pVfs==0 ) return; ++ pNew = &db->aDb[db->init.iDb]; ++ if( pNew->pBt ) sqlite3BtreeClose(pNew->pBt); ++ pNew->pBt = 0; ++ pNew->pSchema = 0; ++ rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNew->pBt, 0, SQLITE_OPEN_MAIN_DB); ++ }else{ ++ /* This is a real ATTACH ++ ** ++ ** Check for the following errors: ++ ** ++ ** * Too many attached databases, ++ ** * Transaction currently open ++ ** * Specified database name already being used. ++ */ ++ if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){ ++ zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d", ++ db->aLimit[SQLITE_LIMIT_ATTACHED] ++ ); + goto attach_error; + } ++ for(i=0; i<db->nDb; i++){ ++ char *z = db->aDb[i].zDbSName; ++ assert( z && zName ); ++ if( sqlite3StrICmp(z, zName)==0 ){ ++ zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName); ++ goto attach_error; ++ } ++ } ++ ++ /* Allocate the new entry in the db->aDb[] array and initialize the schema ++ ** hash tables. ++ */ ++ if( db->aDb==db->aDbStatic ){ ++ aNew = sqlite3DbMallocRawNN(db, sizeof(db->aDb[0])*3 ); ++ if( aNew==0 ) return; ++ memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); ++ }else{ ++ aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); ++ if( aNew==0 ) return; ++ } ++ db->aDb = aNew; ++ pNew = &db->aDb[db->nDb]; ++ memset(pNew, 0, sizeof(*pNew)); ++ ++ /* Open the database file. If the btree is successfully opened, use ++ ** it to obtain the database schema. At this point the schema may ++ ** or may not be initialized. ++ */ ++ flags = db->openFlags; ++ rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr); ++ if( rc!=SQLITE_OK ){ ++ if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); ++ sqlite3_result_error(context, zErr, -1); ++ sqlite3_free(zErr); ++ return; ++ } ++ assert( pVfs ); ++ flags |= SQLITE_OPEN_MAIN_DB; ++ rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags); ++ sqlite3_free( zPath ); ++ db->nDb++; + } +- +- /* Allocate the new entry in the db->aDb[] array and initialize the schema +- ** hash tables. +- */ +- if( db->aDb==db->aDbStatic ){ +- aNew = sqlite3DbMallocRawNN(db, sizeof(db->aDb[0])*3 ); +- if( aNew==0 ) return; +- memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); +- }else{ +- aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); +- if( aNew==0 ) return; +- } +- db->aDb = aNew; +- pNew = &db->aDb[db->nDb]; +- memset(pNew, 0, sizeof(*pNew)); +- +- /* Open the database file. If the btree is successfully opened, use +- ** it to obtain the database schema. At this point the schema may +- ** or may not be initialized. +- */ +- flags = db->openFlags; +- rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr); +- if( rc!=SQLITE_OK ){ +- if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); +- sqlite3_result_error(context, zErr, -1); +- sqlite3_free(zErr); +- return; +- } +- assert( pVfs ); +- flags |= SQLITE_OPEN_MAIN_DB; +- rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags); +- sqlite3_free( zPath ); +- db->nDb++; +- db->skipBtreeMutex = 0; ++ db->noSharedCache = 0; + if( rc==SQLITE_CONSTRAINT ){ + rc = SQLITE_ERROR; + zErrDyn = sqlite3MPrintf(db, "database is already attached"); +@@ -99756,7 +105202,7 @@ + sqlite3BtreeLeave(pNew->pBt); + } + pNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1; +- pNew->zDbSName = sqlite3DbStrDup(db, zName); ++ if( !REOPEN_AS_MEMDB(db) ) pNew->zDbSName = sqlite3DbStrDup(db, zName); + if( rc==SQLITE_OK && pNew->zDbSName==0 ){ + rc = SQLITE_NOMEM_BKPT; + } +@@ -99796,13 +105242,16 @@ + + /* If the file was opened successfully, read the schema for the new database. + ** If this fails, or if opening the file failed, then close the file and +- ** remove the entry from the db->aDb[] array. i.e. put everything back the way +- ** we found it. ++ ** remove the entry from the db->aDb[] array. i.e. put everything back the ++ ** way we found it. + */ + if( rc==SQLITE_OK ){ + sqlite3BtreeEnterAll(db); ++ db->init.iDb = 0; ++ db->mDbFlags &= ~(DBFLAG_SchemaKnownOk); + rc = sqlite3Init(db, &zErrDyn); + sqlite3BtreeLeaveAll(db); ++ assert( zErrDyn==0 || rc!=SQLITE_OK ); + } + #ifdef SQLITE_USER_AUTHENTICATION + if( rc==SQLITE_OK ){ +@@ -99814,22 +105263,24 @@ + } + #endif + if( rc ){ +- int iDb = db->nDb - 1; +- assert( iDb>=2 ); +- if( db->aDb[iDb].pBt ){ +- sqlite3BtreeClose(db->aDb[iDb].pBt); +- db->aDb[iDb].pBt = 0; +- db->aDb[iDb].pSchema = 0; ++ if( !REOPEN_AS_MEMDB(db) ){ ++ int iDb = db->nDb - 1; ++ assert( iDb>=2 ); ++ if( db->aDb[iDb].pBt ){ ++ sqlite3BtreeClose(db->aDb[iDb].pBt); ++ db->aDb[iDb].pBt = 0; ++ db->aDb[iDb].pSchema = 0; ++ } ++ sqlite3ResetAllSchemasOfConnection(db); ++ db->nDb = iDb; ++ if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ ++ sqlite3OomFault(db); ++ sqlite3DbFree(db, zErrDyn); ++ zErrDyn = sqlite3MPrintf(db, "out of memory"); ++ }else if( zErrDyn==0 ){ ++ zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile); ++ } + } +- sqlite3ResetAllSchemasOfConnection(db); +- db->nDb = iDb; +- if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ +- sqlite3OomFault(db); +- sqlite3DbFree(db, zErrDyn); +- zErrDyn = sqlite3MPrintf(db, "out of memory"); +- }else if( zErrDyn==0 ){ +- zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile); +- } + goto attach_error; + } + +@@ -99880,11 +105331,6 @@ + sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName); + goto detach_error; + } +- if( !db->autoCommit ){ +- sqlite3_snprintf(sizeof(zErr), zErr, +- "cannot DETACH database within transaction"); +- goto detach_error; +- } + if( sqlite3BtreeIsInReadTrans(pDb->pBt) || sqlite3BtreeIsInBackup(pDb->pBt) ){ + sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName); + goto detach_error; +@@ -99986,6 +105432,7 @@ + 0, /* pNext */ + detachFunc, /* xSFunc */ + 0, /* xFinalize */ ++ 0, 0, /* xValue, xInverse */ + "sqlite_detach", /* zName */ + {0} + }; +@@ -100005,6 +105452,7 @@ + 0, /* pNext */ + attachFunc, /* xSFunc */ + 0, /* xFinalize */ ++ 0, 0, /* xValue, xInverse */ + "sqlite_attach", /* zName */ + {0} + }; +@@ -100075,6 +105523,9 @@ + if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1; + if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1; + #endif ++ if( pItem->fg.isTabFunc && sqlite3FixExprList(pFix, pItem->u1.pFuncArg) ){ ++ return 1; ++ } + } + return 0; + } +@@ -100105,8 +105556,13 @@ + if( sqlite3FixExpr(pFix, pSelect->pLimit) ){ + return 1; + } +- if( sqlite3FixExpr(pFix, pSelect->pOffset) ){ +- return 1; ++ if( pSelect->pWith ){ ++ int i; ++ for(i=0; i<pSelect->pWith->nCte; i++){ ++ if( sqlite3FixSelect(pFix, pSelect->pWith->a[i].pSelect) ){ ++ return 1; ++ } ++ } + } + pSelect = pSelect->pPrior; + } +@@ -100169,6 +105625,18 @@ + if( sqlite3FixExprList(pFix, pStep->pExprList) ){ + return 1; + } ++#ifndef SQLITE_OMIT_UPSERT ++ if( pStep->pUpsert ){ ++ Upsert *pUp = pStep->pUpsert; ++ if( sqlite3FixExprList(pFix, pUp->pUpsertTarget) ++ || sqlite3FixExpr(pFix, pUp->pUpsertTargetWhere) ++ || sqlite3FixExprList(pFix, pUp->pUpsertSet) ++ || sqlite3FixExpr(pFix, pUp->pUpsertWhere) ++ ){ ++ return 1; ++ } ++ } ++#endif + pStep = pStep->pNext; + } + return 0; +@@ -100257,7 +105725,7 @@ + sqlite3_mutex_enter(db->mutex); + db->xAuth = (sqlite3_xauth)xAuth; + db->pAuthArg = pArg; +- sqlite3ExpirePreparedStatements(db); ++ sqlite3ExpirePreparedStatements(db, 0); + sqlite3_mutex_leave(db->mutex); + return SQLITE_OK; + } +@@ -100297,11 +105765,9 @@ + #endif + ); + if( rc==SQLITE_DENY ){ +- if( db->nDb>2 || iDb!=0 ){ +- sqlite3ErrorMsg(pParse, "access to %s.%s.%s is prohibited",zDb,zTab,zCol); +- }else{ +- sqlite3ErrorMsg(pParse, "access to %s.%s is prohibited", zTab, zCol); +- } ++ char *z = sqlite3_mprintf("%s.%s", zTab, zCol); ++ if( db->nDb>2 || iDb!=0 ) z = sqlite3_mprintf("%s.%z", zDb, z); ++ sqlite3ErrorMsg(pParse, "access to %z is prohibited", z); + pParse->rc = SQLITE_AUTH; + }else if( rc!=SQLITE_IGNORE && rc!=SQLITE_OK ){ + sqliteAuthBadReturnCode(pParse); +@@ -100331,6 +105797,8 @@ + int iDb; /* The index of the database the expression refers to */ + int iCol; /* Index of column in table */ + ++ assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER ); ++ assert( !IN_RENAME_OBJECT || db->xAuth==0 ); + if( db->xAuth==0 ) return; + iDb = sqlite3SchemaToIndex(pParse->db, pSchema); + if( iDb<0 ){ +@@ -100339,7 +105807,6 @@ + return; + } + +- assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER ); + if( pExpr->op==TK_TRIGGER ){ + pTab = pParse->pTriggerTab; + }else{ +@@ -100388,7 +105855,8 @@ + /* Don't do any authorization checks if the database is initialising + ** or if the parser is being invoked from within sqlite3_declare_vtab. + */ +- if( db->init.busy || IN_DECLARE_VTAB ){ ++ assert( !IN_RENAME_OBJECT || db->xAuth==0 ); ++ if( db->init.busy || IN_SPECIAL_PARSE ){ + return SQLITE_OK; + } + +@@ -100680,7 +106148,6 @@ + /* Get the VDBE program ready for execution + */ + if( v && pParse->nErr==0 && !db->mallocFailed ){ +- assert( pParse->iCacheLevel==0 ); /* Disables and re-enables match */ + /* A minimum of one cursor is required if autoincrement is used + * See ticket [a696379c1f08866] */ + if( pParse->pAinc!=0 && pParse->nTab==0 ) pParse->nTab = 1; +@@ -100798,29 +106265,30 @@ + const char *zDbase /* Name of the database. Might be NULL */ + ){ + Table *p; ++ sqlite3 *db = pParse->db; + + /* Read the database schema. If an error occurs, leave an error message + ** and code in pParse and return NULL. */ +- if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ ++ if( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 ++ && SQLITE_OK!=sqlite3ReadSchema(pParse) ++ ){ + return 0; + } + +- p = sqlite3FindTable(pParse->db, zName, zDbase); ++ p = sqlite3FindTable(db, zName, zDbase); + if( p==0 ){ + const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table"; + #ifndef SQLITE_OMIT_VIRTUALTABLE +- if( sqlite3FindDbName(pParse->db, zDbase)<1 ){ +- /* If zName is the not the name of a table in the schema created using +- ** CREATE, then check to see if it is the name of an virtual table that +- ** can be an eponymous virtual table. */ +- Module *pMod = (Module*)sqlite3HashFind(&pParse->db->aModule, zName); +- if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){ +- pMod = sqlite3PragmaVtabRegister(pParse->db, zName); +- } +- if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){ +- return pMod->pEpoTab; +- } ++ /* If zName is the not the name of a table in the schema created using ++ ** CREATE, then check to see if it is the name of an virtual table that ++ ** can be an eponymous virtual table. */ ++ Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName); ++ if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){ ++ pMod = sqlite3PragmaVtabRegister(db, zName); + } ++ if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){ ++ return pMod->pEpoTab; ++ } + #endif + if( (flags & LOCATE_NOERR)==0 ){ + if( zDbase ){ +@@ -100892,7 +106360,7 @@ + /* + ** Reclaim the memory used by an index + */ +-static void freeIndex(sqlite3 *db, Index *p){ ++SQLITE_PRIVATE void sqlite3FreeIndex(sqlite3 *db, Index *p){ + #ifndef SQLITE_OMIT_ANALYZE + sqlite3DeleteIndexSamples(db, p); + #endif +@@ -100932,9 +106400,9 @@ + p->pNext = pIndex->pNext; + } + } +- freeIndex(db, pIndex); ++ sqlite3FreeIndex(db, pIndex); + } +- db->flags |= SQLITE_InternChanges; ++ db->mDbFlags |= DBFLAG_SchemaChange; + } + + /* +@@ -100969,28 +106437,27 @@ + + /* + ** Reset the schema for the database at index iDb. Also reset the +-** TEMP schema. ++** TEMP schema. The reset is deferred if db->nSchemaLock is not zero. ++** Deferred resets may be run by calling with iDb<0. + */ + SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3 *db, int iDb){ +- Db *pDb; ++ int i; + assert( iDb<db->nDb ); + +- /* Case 1: Reset the single schema identified by iDb */ +- pDb = &db->aDb[iDb]; +- assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); +- assert( pDb->pSchema!=0 ); +- sqlite3SchemaClear(pDb->pSchema); ++ if( iDb>=0 ){ ++ assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); ++ DbSetProperty(db, iDb, DB_ResetWanted); ++ DbSetProperty(db, 1, DB_ResetWanted); ++ db->mDbFlags &= ~DBFLAG_SchemaKnownOk; ++ } + +- /* If any database other than TEMP is reset, then also reset TEMP +- ** since TEMP might be holding triggers that reference tables in the +- ** other database. +- */ +- if( iDb!=1 ){ +- pDb = &db->aDb[1]; +- assert( pDb->pSchema!=0 ); +- sqlite3SchemaClear(pDb->pSchema); ++ if( db->nSchemaLock==0 ){ ++ for(i=0; i<db->nDb; i++){ ++ if( DbHasProperty(db, i, DB_ResetWanted) ){ ++ sqlite3SchemaClear(db->aDb[i].pSchema); ++ } ++ } + } +- return; + } + + /* +@@ -101003,13 +106470,19 @@ + for(i=0; i<db->nDb; i++){ + Db *pDb = &db->aDb[i]; + if( pDb->pSchema ){ +- sqlite3SchemaClear(pDb->pSchema); ++ if( db->nSchemaLock==0 ){ ++ sqlite3SchemaClear(pDb->pSchema); ++ }else{ ++ DbSetProperty(db, i, DB_ResetWanted); ++ } + } + } +- db->flags &= ~SQLITE_InternChanges; ++ db->mDbFlags &= ~(DBFLAG_SchemaChange|DBFLAG_SchemaKnownOk); + sqlite3VtabUnlockList(db); + sqlite3BtreeLeaveAll(db); +- sqlite3CollapseDatabaseArray(db); ++ if( db->nSchemaLock==0 ){ ++ sqlite3CollapseDatabaseArray(db); ++ } + } + + /* +@@ -101016,7 +106489,7 @@ + ** This routine is called when a commit occurs. + */ + SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3 *db){ +- db->flags &= ~SQLITE_InternChanges; ++ db->mDbFlags &= ~DBFLAG_SchemaChange; + } + + /* +@@ -101054,13 +106527,16 @@ + */ + static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){ + Index *pIndex, *pNext; +- TESTONLY( int nLookaside; ) /* Used to verify lookaside not used for schema */ + ++#ifdef SQLITE_DEBUG + /* Record the number of outstanding lookaside allocations in schema Tables + ** prior to doing any free() operations. Since schema Tables do not use + ** lookaside, this number should not change. */ +- TESTONLY( nLookaside = (db && (pTable->tabFlags & TF_Ephemeral)==0) ? +- db->lookaside.nOut : 0 ); ++ int nLookaside = 0; ++ if( db && (pTable->tabFlags & TF_Ephemeral)==0 ){ ++ nLookaside = sqlite3LookasideUsed(db, 0); ++ } ++#endif + + /* Delete all indices associated with this table. */ + for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ +@@ -101075,7 +106551,7 @@ + assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); + assert( pOld==pIndex || pOld==0 ); + } +- freeIndex(db, pIndex); ++ sqlite3FreeIndex(db, pIndex); + } + + /* Delete any foreign keys attached to this table. */ +@@ -101083,6 +106559,12 @@ + + /* Delete the Table structure itself. + */ ++#ifdef SQLITE_ENABLE_NORMALIZE ++ if( pTable->pColHash ){ ++ sqlite3HashClear(pTable->pColHash); ++ sqlite3_free(pTable->pColHash); ++ } ++#endif + sqlite3DeleteColumnNames(db, pTable); + sqlite3DbFree(db, pTable->zName); + sqlite3DbFree(db, pTable->zColAff); +@@ -101094,7 +106576,7 @@ + sqlite3DbFree(db, pTable); + + /* Verify that no lookaside memory was used by schema tables */ +- assert( nLookaside==0 || nLookaside==db->lookaside.nOut ); ++ assert( nLookaside==0 || nLookaside==sqlite3LookasideUsed(db,0) ); + } + SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ + /* Do not delete the table until the reference count reaches zero. */ +@@ -101120,7 +106602,7 @@ + pDb = &db->aDb[iDb]; + p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, 0); + sqlite3DeleteTable(db, p); +- db->flags |= SQLITE_InternChanges; ++ db->mDbFlags |= DBFLAG_SchemaChange; + } + + /* +@@ -101233,7 +106715,8 @@ + return -1; + } + }else{ +- assert( db->init.iDb==0 || db->init.busy || (db->flags & SQLITE_Vacuum)!=0); ++ assert( db->init.iDb==0 || db->init.busy || IN_RENAME_OBJECT ++ || (db->mDbFlags & DBFLAG_Vacuum)!=0); + iDb = db->init.iDb; + *pUnqual = pName1; + } +@@ -101241,6 +106724,20 @@ + } + + /* ++** True if PRAGMA writable_schema is ON ++*/ ++SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3 *db){ ++ testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==0 ); ++ testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))== ++ SQLITE_WriteSchema ); ++ testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))== ++ SQLITE_Defensive ); ++ testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))== ++ (SQLITE_WriteSchema|SQLITE_Defensive) ); ++ return (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==SQLITE_WriteSchema; ++} ++ ++/* + ** This routine is used to check if the UTF-8 string zName is a legal + ** unqualified name for a new schema object (table, index, view or + ** trigger). All names are legal except those that begin with the string +@@ -101249,7 +106746,7 @@ + */ + SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *pParse, const char *zName){ + if( !pParse->db->init.busy && pParse->nested==0 +- && (pParse->db->flags & SQLITE_WriteSchema)==0 ++ && sqlite3WritableSchema(pParse->db)==0 + && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ + sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName); + return SQLITE_ERROR; +@@ -101327,6 +106824,9 @@ + } + if( !OMIT_TEMPDB && isTemp ) iDb = 1; + zName = sqlite3NameFromToken(db, pName); ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameTokenMap(pParse, (void*)zName, pName); ++ } + } + pParse->sNameToken = *pName; + if( zName==0 ) return; +@@ -101362,7 +106862,7 @@ + ** and types will be used, so there is no need to test for namespace + ** collisions. + */ +- if( !IN_DECLARE_VTAB ){ ++ if( !IN_SPECIAL_PARSE ){ + char *zDb = db->aDb[iDb].zDbSName; + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ + goto begin_table_error; +@@ -101465,7 +106965,8 @@ + }else + #endif + { +- pParse->addrCrTab = sqlite3VdbeAddOp2(v, OP_CreateTable, iDb, reg2); ++ pParse->addrCrTab = ++ sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, reg2, BTREE_INTKEY); + } + sqlite3OpenMasterTable(pParse, iDb); + sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1); +@@ -101514,14 +107015,13 @@ + Column *pCol; + sqlite3 *db = pParse->db; + if( (p = pParse->pNewTable)==0 ) return; +-#if SQLITE_MAX_COLUMN + if( p->nCol+1>db->aLimit[SQLITE_LIMIT_COLUMN] ){ + sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName); + return; + } +-#endif + z = sqlite3DbMallocRaw(db, pName->n + pType->n + 2); + if( z==0 ) return; ++ if( IN_RENAME_OBJECT ) sqlite3RenameTokenMap(pParse, (void*)z, pName); + memcpy(z, pName->z, pName->n); + z[pName->n] = 0; + sqlite3Dequote(z); +@@ -101548,15 +107048,20 @@ + + if( pType->n==0 ){ + /* If there is no type specified, columns have the default affinity +- ** 'BLOB'. */ ++ ** 'BLOB' with a default size of 4 bytes. */ + pCol->affinity = SQLITE_AFF_BLOB; + pCol->szEst = 1; ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ if( 4>=sqlite3GlobalConfig.szSorterRef ){ ++ pCol->colFlags |= COLFLAG_SORTERREF; ++ } ++#endif + }else{ + zType = z + sqlite3Strlen30(z) + 1; + memcpy(zType, pType->z, pType->n); + zType[pType->n] = 0; + sqlite3Dequote(zType); +- pCol->affinity = sqlite3AffinityType(zType, &pCol->szEst); ++ pCol->affinity = sqlite3AffinityType(zType, pCol); + pCol->colFlags |= COLFLAG_HASTYPE; + } + p->nCol++; +@@ -101571,10 +107076,24 @@ + */ + SQLITE_PRIVATE void sqlite3AddNotNull(Parse *pParse, int onError){ + Table *p; ++ Column *pCol; + p = pParse->pNewTable; + if( p==0 || NEVER(p->nCol<1) ) return; +- p->aCol[p->nCol-1].notNull = (u8)onError; ++ pCol = &p->aCol[p->nCol-1]; ++ pCol->notNull = (u8)onError; + p->tabFlags |= TF_HasNotNull; ++ ++ /* Set the uniqNotNull flag on any UNIQUE or PK indexes already created ++ ** on this column. */ ++ if( pCol->colFlags & COLFLAG_UNIQUE ){ ++ Index *pIdx; ++ for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){ ++ assert( pIdx->nKeyCol==1 && pIdx->onError!=OE_None ); ++ if( pIdx->aiColumn[0]==p->nCol-1 ){ ++ pIdx->uniqNotNull = 1; ++ } ++ } ++ } + } + + /* +@@ -101602,7 +107121,7 @@ + ** If none of the substrings in the above table are found, + ** SQLITE_AFF_NUMERIC is returned. + */ +-SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn, u8 *pszEst){ ++SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn, Column *pCol){ + u32 h = 0; + char aff = SQLITE_AFF_NUMERIC; + const char *zChar = 0; +@@ -101639,27 +107158,32 @@ + } + } + +- /* If pszEst is not NULL, store an estimate of the field size. The ++ /* If pCol is not NULL, store an estimate of the field size. The + ** estimate is scaled so that the size of an integer is 1. */ +- if( pszEst ){ +- *pszEst = 1; /* default size is approx 4 bytes */ ++ if( pCol ){ ++ int v = 0; /* default size is approx 4 bytes */ + if( aff<SQLITE_AFF_NUMERIC ){ + if( zChar ){ + while( zChar[0] ){ + if( sqlite3Isdigit(zChar[0]) ){ +- int v = 0; ++ /* BLOB(k), VARCHAR(k), CHAR(k) -> r=(k/4+1) */ + sqlite3GetInt32(zChar, &v); +- v = v/4 + 1; +- if( v>255 ) v = 255; +- *pszEst = v; /* BLOB(k), VARCHAR(k), CHAR(k) -> r=(k/4+1) */ + break; + } + zChar++; + } + }else{ +- *pszEst = 5; /* BLOB, TEXT, CLOB -> r=5 (approx 20 bytes)*/ ++ v = 16; /* BLOB, TEXT, CLOB -> r=5 (approx 20 bytes)*/ + } + } ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ if( v>=sqlite3GlobalConfig.szSorterRef ){ ++ pCol->colFlags |= COLFLAG_SORTERREF; ++ } ++#endif ++ v = v/4 + 1; ++ if( v>255 ) v = 255; ++ pCol->szEst = v; + } + return aff; + } +@@ -101674,7 +107198,12 @@ + ** This routine is called by the parser while in the middle of + ** parsing a CREATE TABLE statement. + */ +-SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse *pParse, ExprSpan *pSpan){ ++SQLITE_PRIVATE void sqlite3AddDefaultValue( ++ Parse *pParse, /* Parsing context */ ++ Expr *pExpr, /* The parsed expression of the default value */ ++ const char *zStart, /* Start of the default value text */ ++ const char *zEnd /* First character past end of defaut value text */ ++){ + Table *p; + Column *pCol; + sqlite3 *db = pParse->db; +@@ -101681,27 +107210,28 @@ + p = pParse->pNewTable; + if( p!=0 ){ + pCol = &(p->aCol[p->nCol-1]); +- if( !sqlite3ExprIsConstantOrFunction(pSpan->pExpr, db->init.busy) ){ ++ if( !sqlite3ExprIsConstantOrFunction(pExpr, db->init.busy) ){ + sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant", + pCol->zName); + }else{ + /* A copy of pExpr is used instead of the original, as pExpr contains +- ** tokens that point to volatile memory. The 'span' of the expression +- ** is required by pragma table_info. ++ ** tokens that point to volatile memory. + */ + Expr x; + sqlite3ExprDelete(db, pCol->pDflt); + memset(&x, 0, sizeof(x)); + x.op = TK_SPAN; +- x.u.zToken = sqlite3DbStrNDup(db, (char*)pSpan->zStart, +- (int)(pSpan->zEnd - pSpan->zStart)); +- x.pLeft = pSpan->pExpr; ++ x.u.zToken = sqlite3DbSpanDup(db, zStart, zEnd); ++ x.pLeft = pExpr; + x.flags = EP_Skip; + pCol->pDflt = sqlite3ExprDup(db, &x, EXPRDUP_REDUCE); + sqlite3DbFree(db, x.u.zToken); + } + } +- sqlite3ExprDelete(db, pSpan->pExpr); ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameExprUnmap(pParse, pExpr); ++ } ++ sqlite3ExprDelete(db, pExpr); + } + + /* +@@ -101792,6 +107322,9 @@ + && sqlite3StrICmp(sqlite3ColumnType(pCol,""), "INTEGER")==0 + && sortOrder!=SQLITE_SO_DESC + ){ ++ if( IN_RENAME_OBJECT && pList ){ ++ sqlite3RenameTokenRemap(pParse, &pTab->iPKey, pList->a[0].pExpr); ++ } + pTab->iPKey = iCol; + pTab->keyConf = (u8)onError; + assert( autoInc==0 || autoInc==1 ); +@@ -101932,7 +107465,7 @@ + Vdbe *v = pParse->pVdbe; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, +- db->aDb[iDb].pSchema->schema_cookie+1); ++ (int)(1+(unsigned)db->aDb[iDb].pSchema->schema_cookie)); + } + + /* +@@ -102117,6 +107650,31 @@ + return 0; + } + ++/* Recompute the colNotIdxed field of the Index. ++** ++** colNotIdxed is a bitmask that has a 0 bit representing each indexed ++** columns that are within the first 63 columns of the table. The ++** high-order bit of colNotIdxed is always 1. All unindexed columns ++** of the table have a 1. ++** ++** The colNotIdxed mask is AND-ed with the SrcList.a[].colUsed mask ++** to determine if the index is covering index. ++*/ ++static void recomputeColumnsNotIndexed(Index *pIdx){ ++ Bitmask m = 0; ++ int j; ++ for(j=pIdx->nColumn-1; j>=0; j--){ ++ int x = pIdx->aiColumn[j]; ++ if( x>=0 ){ ++ testcase( x==BMS-1 ); ++ testcase( x==BMS-2 ); ++ if( x<BMS-1 ) m |= MASKBIT(x); ++ } ++ } ++ pIdx->colNotIdxed = ~m; ++ assert( (pIdx->colNotIdxed>>63)==1 ); ++} ++ + /* + ** This routine runs at the end of parsing a CREATE TABLE statement that + ** has a WITHOUT ROWID clause. The job of this routine is to convert both +@@ -102125,9 +107683,8 @@ + ** Changes include: + ** + ** (1) Set all columns of the PRIMARY KEY schema object to be NOT NULL. +-** (2) Convert the OP_CreateTable into an OP_CreateIndex. There is +-** no rowid btree for a WITHOUT ROWID. Instead, the canonical +-** data storage is a covering index btree. ++** (2) Convert P3 parameter of the OP_CreateBtree from BTREE_INTKEY ++** into BTREE_BLOBKEY. + ** (3) Bypass the creation of the sqlite_master table entry + ** for the PRIMARY KEY as the primary key index is now + ** identified by the sqlite_master table entry of the table itself. +@@ -102135,7 +107692,7 @@ + ** schema to the rootpage from the main table. + ** (5) Add all table columns to the PRIMARY KEY Index object + ** so that the PRIMARY KEY is a covering index. The surplus +-** columns are part of KeyInfo.nXField and are not used for ++** columns are part of KeyInfo.nAllField and are not used for + ** sorting or lookup or uniqueness checks. + ** (6) Replace the rowid tail on all automatically generated UNIQUE + ** indices with the PRIMARY KEY columns. +@@ -102160,17 +107717,12 @@ + } + } + +- /* The remaining transformations only apply to b-tree tables, not to +- ** virtual tables */ +- if( IN_DECLARE_VTAB ) return; +- +- /* Convert the OP_CreateTable opcode that would normally create the +- ** root-page for the table into an OP_CreateIndex opcode. The index +- ** created will become the PRIMARY KEY index. ++ /* Convert the P3 operand of the OP_CreateBtree opcode from BTREE_INTKEY ++ ** into BTREE_BLOBKEY. + */ + if( pParse->addrCrTab ){ + assert( v ); +- sqlite3VdbeChangeOpcode(v, pParse->addrCrTab, OP_CreateIndex); ++ sqlite3VdbeChangeP3(v, pParse->addrCrTab, BTREE_BLOBKEY); + } + + /* Locate the PRIMARY KEY index. Or, if this table was originally +@@ -102187,7 +107739,7 @@ + assert( pParse->pNewTable==pTab ); + sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0, + SQLITE_IDXTYPE_PRIMARYKEY); +- if( db->mallocFailed ) return; ++ if( db->mallocFailed || pParse->nErr ) return; + pPk = sqlite3PrimaryKeyIndex(pTab); + pTab->iPKey = -1; + }else{ +@@ -102267,9 +107819,40 @@ + }else{ + pPk->nColumn = pTab->nCol; + } ++ recomputeColumnsNotIndexed(pPk); + } + ++#ifndef SQLITE_OMIT_VIRTUALTABLE + /* ++** Return true if zName is a shadow table name in the current database ++** connection. ++** ++** zName is temporarily modified while this routine is running, but is ++** restored to its original value prior to this routine returning. ++*/ ++static int isShadowTableName(sqlite3 *db, char *zName){ ++ char *zTail; /* Pointer to the last "_" in zName */ ++ Table *pTab; /* Table that zName is a shadow of */ ++ Module *pMod; /* Module for the virtual table */ ++ ++ zTail = strrchr(zName, '_'); ++ if( zTail==0 ) return 0; ++ *zTail = 0; ++ pTab = sqlite3FindTable(db, zName, 0); ++ *zTail = '_'; ++ if( pTab==0 ) return 0; ++ if( !IsVirtual(pTab) ) return 0; ++ pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]); ++ if( pMod==0 ) return 0; ++ if( pMod->pModule->iVersion<3 ) return 0; ++ if( pMod->pModule->xShadowName==0 ) return 0; ++ return pMod->pModule->xShadowName(zTail+1); ++} ++#else ++# define isShadowTableName(x,y) 0 ++#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ ++ ++/* + ** This routine is called to report the final ")" that terminates + ** a CREATE TABLE statement. + ** +@@ -102308,7 +107891,9 @@ + p = pParse->pNewTable; + if( p==0 ) return; + +- assert( !db->init.busy || !pSelect ); ++ if( pSelect==0 && isShadowTableName(db, p->zName) ){ ++ p->tabFlags |= TF_Shadow; ++ } + + /* If the db->init.busy is 1 it means we are reading the SQL off the + ** "sqlite_master" or "sqlite_temp_master" table on the disk. +@@ -102320,6 +107905,10 @@ + ** table itself. So mark it read-only. + */ + if( db->init.busy ){ ++ if( pSelect ){ ++ sqlite3ErrorMsg(pParse, ""); ++ return; ++ } + p->tnum = db->init.newTnum; + if( p->tnum==1 ) p->tabFlags |= TF_Readonly; + } +@@ -102420,10 +108009,6 @@ + pParse->nTab = 2; + addrTop = sqlite3VdbeCurrentAddr(v) + 1; + sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); +- sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); +- sqlite3Select(pParse, pSelect, &dest); +- sqlite3VdbeEndCoroutine(v, regYield); +- sqlite3VdbeJumpHere(v, addrTop - 1); + if( pParse->nErr ) return; + pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect); + if( pSelTab==0 ) return; +@@ -102433,6 +108018,11 @@ + pSelTab->nCol = 0; + pSelTab->aCol = 0; + sqlite3DeleteTable(db, pSelTab); ++ sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); ++ sqlite3Select(pParse, pSelect, &dest); ++ if( pParse->nErr ) return; ++ sqlite3VdbeEndCoroutine(v, regYield); ++ sqlite3VdbeJumpHere(v, addrTop - 1); + addrInsLoop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); + VdbeCoverage(v); + sqlite3VdbeAddOp3(v, OP_MakeRecord, dest.iSdst, dest.nSdst, regRec); +@@ -102510,7 +108100,7 @@ + return; + } + pParse->pNewTable = 0; +- db->flags |= SQLITE_InternChanges; ++ db->mDbFlags |= DBFLAG_SchemaChange; + + #ifndef SQLITE_OMIT_ALTERTABLE + if( !p->pSelect ){ +@@ -102567,7 +108157,12 @@ + ** allocated rather than point to the input string - which means that + ** they will persist after the current sqlite3_exec() call returns. + */ +- p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); ++ if( IN_RENAME_OBJECT ){ ++ p->pSelect = pSelect; ++ pSelect = 0; ++ }else{ ++ p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); ++ } + p->pCheck = sqlite3ExprListDup(db, pCNames, EXPRDUP_REDUCE); + if( db->mallocFailed ) goto create_view_fail; + +@@ -102575,7 +108170,7 @@ + ** the end. + */ + sEnd = pParse->sLastToken; +- assert( sEnd.z[0]!=0 ); ++ assert( sEnd.z[0]!=0 || sEnd.n==0 ); + if( sEnd.z[0]!=';' ){ + sEnd.z += sEnd.n; + } +@@ -102592,6 +108187,9 @@ + + create_view_fail: + sqlite3SelectDelete(db, pSelect); ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameExprlistUnmap(pParse, pCNames); ++ } + sqlite3ExprListDelete(db, pCNames); + return; + } +@@ -102609,6 +108207,9 @@ + int nErr = 0; /* Number of errors encountered */ + int n; /* Temporarily holds the number of cursors assigned */ + sqlite3 *db = pParse->db; /* Database connection for malloc errors */ ++#ifndef SQLITE_OMIT_VIRTUALTABLE ++ int rc; ++#endif + #ifndef SQLITE_OMIT_AUTHORIZATION + sqlite3_xauth xAuth; /* Saved xAuth pointer */ + #endif +@@ -102616,8 +108217,11 @@ + assert( pTable ); + + #ifndef SQLITE_OMIT_VIRTUALTABLE +- if( sqlite3VtabCallConnect(pParse, pTable) ){ +- return SQLITE_ERROR; ++ db->nSchemaLock++; ++ rc = sqlite3VtabCallConnect(pParse, pTable); ++ db->nSchemaLock--; ++ if( rc ){ ++ return 1; + } + if( IsVirtual(pTable) ) return 0; + #endif +@@ -102659,6 +108263,10 @@ + assert( pTable->pSelect ); + pSel = sqlite3SelectDup(db, pTable->pSelect, 0); + if( pSel ){ ++#ifndef SQLITE_OMIT_ALTERTABLE ++ u8 eParseMode = pParse->eParseMode; ++ pParse->eParseMode = PARSE_MODE_NORMAL; ++#endif + n = pParse->nTab; + sqlite3SrcListAssignCursors(pParse, pSel->pSrc); + pTable->nCol = -1; +@@ -102704,10 +108312,18 @@ + sqlite3DeleteTable(db, pSelTab); + sqlite3SelectDelete(db, pSel); + db->lookaside.bDisable--; ++#ifndef SQLITE_OMIT_ALTERTABLE ++ pParse->eParseMode = eParseMode; ++#endif + } else { + nErr++; + } + pTable->pSchema->schemaFlags |= DB_UnresetViews; ++ if( db->mallocFailed ){ ++ sqlite3DeleteColumnNames(db, pTable); ++ pTable->aCol = 0; ++ pTable->nCol = 0; ++ } + #endif /* SQLITE_OMIT_VIEW */ + return nErr; + } +@@ -102786,7 +108402,7 @@ + static void destroyRootPage(Parse *pParse, int iTable, int iDb){ + Vdbe *v = sqlite3GetVdbe(pParse); + int r1 = sqlite3GetTempReg(pParse); +- assert( iTable>1 ); ++ if( iTable<2 ) sqlite3ErrorMsg(pParse, "corrupt schema"); + sqlite3VdbeAddOp3(v, OP_Destroy, iTable, r1, iDb); + sqlite3MayAbort(pParse); + #ifndef SQLITE_OMIT_AUTOVACUUM +@@ -102813,14 +108429,6 @@ + ** is also added (this can happen with an auto-vacuum database). + */ + static void destroyTable(Parse *pParse, Table *pTab){ +-#ifdef SQLITE_OMIT_AUTOVACUUM +- Index *pIdx; +- int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); +- destroyRootPage(pParse, pTab->tnum, iDb); +- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ +- destroyRootPage(pParse, pIdx->tnum, iDb); +- } +-#else + /* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM + ** is not defined), then it is important to call OP_Destroy on the + ** table and index root-pages in order, starting with the numerically +@@ -102863,7 +108471,6 @@ + iDestroyed = iLargest; + } + } +-#endif + } + + /* +@@ -103055,8 +108662,10 @@ + v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3BeginWriteOperation(pParse, 1, iDb); +- sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName); +- sqlite3FkDropTable(pParse, pName, pTab); ++ if( !isView ){ ++ sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName); ++ sqlite3FkDropTable(pParse, pName, pTab); ++ } + sqlite3CodeDropTable(pParse, pTab, iDb, isView); + } + +@@ -103131,6 +108740,9 @@ + pFKey->pNextFrom = p->pFKey; + z = (char*)&pFKey->aCol[nCol]; + pFKey->zTo = z; ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameTokenMap(pParse, (void*)z, pTo); ++ } + memcpy(z, pTo->z, pTo->n); + z[pTo->n] = 0; + sqlite3Dequote(z); +@@ -103153,6 +108765,9 @@ + pFromCol->a[i].zName); + goto fk_end; + } ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameTokenRemap(pParse, &pFKey->aCol[i], pFromCol->a[i].zName); ++ } + } + } + if( pToCol ){ +@@ -103159,6 +108774,9 @@ + for(i=0; i<nCol; i++){ + int n = sqlite3Strlen30(pToCol->a[i].zName); + pFKey->aCol[i].zCol = z; ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameTokenRemap(pParse, z, pToCol->a[i].zName); ++ } + memcpy(z, pToCol->a[i].zName, n); + z[n] = 0; + z += n+1; +@@ -103267,6 +108885,7 @@ + sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); + addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); VdbeCoverage(v); + regRecord = sqlite3GetTempReg(pParse); ++ sqlite3MultiWrite(pParse); + + sqlite3GenerateIndexKey(pParse,pIndex,iTab,regRecord,0,&iPartIdxLabel,0,0); + sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord); +@@ -103280,17 +108899,18 @@ + + addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v); + if( IsUniqueIndex(pIndex) ){ +- int j2 = sqlite3VdbeCurrentAddr(v) + 3; +- sqlite3VdbeGoto(v, j2); ++ int j2 = sqlite3VdbeGoto(v, 1); + addr2 = sqlite3VdbeCurrentAddr(v); ++ sqlite3VdbeVerifyAbortable(v, OE_Abort); + sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord, + pIndex->nKeyCol); VdbeCoverage(v); + sqlite3UniqueConstraint(pParse, OE_Abort, pIndex); ++ sqlite3VdbeJumpHere(v, j2); + }else{ + addr2 = sqlite3VdbeCurrentAddr(v); + } + sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx); +- sqlite3VdbeAddOp3(v, OP_Last, iIdx, 0, -1); ++ sqlite3VdbeAddOp1(v, OP_SeekEnd, iIdx); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord); + sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); + sqlite3ReleaseTempReg(pParse, regRecord); +@@ -103448,7 +109068,11 @@ + #if SQLITE_USER_AUTHENTICATION + && sqlite3UserAuthTable(pTab->zName)==0 + #endif +- && sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0 ){ ++#ifdef SQLITE_ALLOW_SQLITE_MASTER_INDEX ++ && sqlite3StrICmp(&pTab->zName[7],"master")!=0 ++#endif ++ && sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0 ++ ){ + sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName); + goto exit_create_index; + } +@@ -103485,21 +109109,23 @@ + if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ + goto exit_create_index; + } +- if( !db->init.busy ){ +- if( sqlite3FindTable(db, zName, 0)!=0 ){ +- sqlite3ErrorMsg(pParse, "there is already a table named %s", zName); ++ if( !IN_RENAME_OBJECT ){ ++ if( !db->init.busy ){ ++ if( sqlite3FindTable(db, zName, 0)!=0 ){ ++ sqlite3ErrorMsg(pParse, "there is already a table named %s", zName); ++ goto exit_create_index; ++ } ++ } ++ if( sqlite3FindIndex(db, zName, pDb->zDbSName)!=0 ){ ++ if( !ifNotExist ){ ++ sqlite3ErrorMsg(pParse, "index %s already exists", zName); ++ }else{ ++ assert( !db->init.busy ); ++ sqlite3CodeVerifySchema(pParse, iDb); ++ } + goto exit_create_index; + } + } +- if( sqlite3FindIndex(db, zName, pDb->zDbSName)!=0 ){ +- if( !ifNotExist ){ +- sqlite3ErrorMsg(pParse, "index %s already exists", zName); +- }else{ +- assert( !db->init.busy ); +- sqlite3CodeVerifySchema(pParse, iDb); +- } +- goto exit_create_index; +- } + }else{ + int n; + Index *pLoop; +@@ -103514,13 +109140,13 @@ + ** The following statement converts "sqlite3_autoindex..." into + ** "sqlite3_butoindex..." in order to make the names distinct. + ** The "vtab_err.test" test demonstrates the need of this statement. */ +- if( IN_DECLARE_VTAB ) zName[7]++; ++ if( IN_SPECIAL_PARSE ) zName[7]++; + } + + /* Check for authorization to create an index. + */ + #ifndef SQLITE_OMIT_AUTHORIZATION +- { ++ if( !IN_RENAME_OBJECT ){ + const char *zDb = pDb->zDbSName; + if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iDb), 0, zDb) ){ + goto exit_create_index; +@@ -103539,7 +109165,9 @@ + */ + if( pList==0 ){ + Token prevCol; +- sqlite3TokenInit(&prevCol, pTab->aCol[pTab->nCol-1].zName); ++ Column *pCol = &pTab->aCol[pTab->nCol-1]; ++ pCol->colFlags |= COLFLAG_UNIQUE; ++ sqlite3TokenInit(&prevCol, pCol->zName); + pList = sqlite3ExprListAppend(pParse, 0, + sqlite3ExprAlloc(db, TK_ID, &prevCol, 0)); + if( pList==0 ) goto exit_create_index; +@@ -103605,7 +109233,12 @@ + ** TODO: Issue a warning if the table primary key is used as part of the + ** index key. + */ +- for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){ ++ pListItem = pList->a; ++ if( IN_RENAME_OBJECT ){ ++ pIndex->aColExpr = pList; ++ pList = 0; ++ } ++ for(i=0; i<pIndex->nKeyCol; i++, pListItem++){ + Expr *pCExpr; /* The i-th index expression */ + int requestedSortOrder; /* ASC or DESC on the i-th expression */ + const char *zColl; /* Collation sequence name */ +@@ -103621,12 +109254,8 @@ + goto exit_create_index; + } + if( pIndex->aColExpr==0 ){ +- ExprList *pCopy = sqlite3ExprListDup(db, pList, 0); +- pIndex->aColExpr = pCopy; +- if( !db->mallocFailed ){ +- assert( pCopy!=0 ); +- pListItem = &pCopy->a[i]; +- } ++ pIndex->aColExpr = pList; ++ pList = 0; + } + j = XN_EXPR; + pIndex->aiColumn[i] = XN_EXPR; +@@ -103692,6 +109321,7 @@ + ** it as a covering index */ + assert( HasRowid(pTab) + || pTab->iPKey<0 || sqlite3ColumnOfIndex(pIndex, pTab->iPKey)>=0 ); ++ recomputeColumnsNotIndexed(pIndex); + if( pTblName!=0 && pIndex->nColumn>=pTab->nCol ){ + pIndex->isCovering = 1; + for(j=0; j<pTab->nCol; j++){ +@@ -103764,98 +109394,101 @@ + } + } + +- /* Link the new Index structure to its table and to the other +- ** in-memory database structures. +- */ +- assert( pParse->nErr==0 ); +- if( db->init.busy ){ +- Index *p; +- assert( !IN_DECLARE_VTAB ); +- assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); +- p = sqlite3HashInsert(&pIndex->pSchema->idxHash, +- pIndex->zName, pIndex); +- if( p ){ +- assert( p==pIndex ); /* Malloc must have failed */ +- sqlite3OomFault(db); +- goto exit_create_index; ++ if( !IN_RENAME_OBJECT ){ ++ ++ /* Link the new Index structure to its table and to the other ++ ** in-memory database structures. ++ */ ++ assert( pParse->nErr==0 ); ++ if( db->init.busy ){ ++ Index *p; ++ assert( !IN_SPECIAL_PARSE ); ++ assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); ++ p = sqlite3HashInsert(&pIndex->pSchema->idxHash, ++ pIndex->zName, pIndex); ++ if( p ){ ++ assert( p==pIndex ); /* Malloc must have failed */ ++ sqlite3OomFault(db); ++ goto exit_create_index; ++ } ++ db->mDbFlags |= DBFLAG_SchemaChange; ++ if( pTblName!=0 ){ ++ pIndex->tnum = db->init.newTnum; ++ } + } +- db->flags |= SQLITE_InternChanges; +- if( pTblName!=0 ){ +- pIndex->tnum = db->init.newTnum; +- } +- } + +- /* If this is the initial CREATE INDEX statement (or CREATE TABLE if the +- ** index is an implied index for a UNIQUE or PRIMARY KEY constraint) then +- ** emit code to allocate the index rootpage on disk and make an entry for +- ** the index in the sqlite_master table and populate the index with +- ** content. But, do not do this if we are simply reading the sqlite_master +- ** table to parse the schema, or if this index is the PRIMARY KEY index +- ** of a WITHOUT ROWID table. +- ** +- ** If pTblName==0 it means this index is generated as an implied PRIMARY KEY +- ** or UNIQUE index in a CREATE TABLE statement. Since the table +- ** has just been created, it contains no data and the index initialization +- ** step can be skipped. +- */ +- else if( HasRowid(pTab) || pTblName!=0 ){ +- Vdbe *v; +- char *zStmt; +- int iMem = ++pParse->nMem; ++ /* If this is the initial CREATE INDEX statement (or CREATE TABLE if the ++ ** index is an implied index for a UNIQUE or PRIMARY KEY constraint) then ++ ** emit code to allocate the index rootpage on disk and make an entry for ++ ** the index in the sqlite_master table and populate the index with ++ ** content. But, do not do this if we are simply reading the sqlite_master ++ ** table to parse the schema, or if this index is the PRIMARY KEY index ++ ** of a WITHOUT ROWID table. ++ ** ++ ** If pTblName==0 it means this index is generated as an implied PRIMARY KEY ++ ** or UNIQUE index in a CREATE TABLE statement. Since the table ++ ** has just been created, it contains no data and the index initialization ++ ** step can be skipped. ++ */ ++ else if( HasRowid(pTab) || pTblName!=0 ){ ++ Vdbe *v; ++ char *zStmt; ++ int iMem = ++pParse->nMem; + +- v = sqlite3GetVdbe(pParse); +- if( v==0 ) goto exit_create_index; ++ v = sqlite3GetVdbe(pParse); ++ if( v==0 ) goto exit_create_index; + +- sqlite3BeginWriteOperation(pParse, 1, iDb); ++ sqlite3BeginWriteOperation(pParse, 1, iDb); + +- /* Create the rootpage for the index using CreateIndex. But before +- ** doing so, code a Noop instruction and store its address in +- ** Index.tnum. This is required in case this index is actually a +- ** PRIMARY KEY and the table is actually a WITHOUT ROWID table. In +- ** that case the convertToWithoutRowidTable() routine will replace +- ** the Noop with a Goto to jump over the VDBE code generated below. */ +- pIndex->tnum = sqlite3VdbeAddOp0(v, OP_Noop); +- sqlite3VdbeAddOp2(v, OP_CreateIndex, iDb, iMem); ++ /* Create the rootpage for the index using CreateIndex. But before ++ ** doing so, code a Noop instruction and store its address in ++ ** Index.tnum. This is required in case this index is actually a ++ ** PRIMARY KEY and the table is actually a WITHOUT ROWID table. In ++ ** that case the convertToWithoutRowidTable() routine will replace ++ ** the Noop with a Goto to jump over the VDBE code generated below. */ ++ pIndex->tnum = sqlite3VdbeAddOp0(v, OP_Noop); ++ sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, iMem, BTREE_BLOBKEY); + +- /* Gather the complete text of the CREATE INDEX statement into +- ** the zStmt variable +- */ +- if( pStart ){ +- int n = (int)(pParse->sLastToken.z - pName->z) + pParse->sLastToken.n; +- if( pName->z[n-1]==';' ) n--; +- /* A named index with an explicit CREATE INDEX statement */ +- zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s", +- onError==OE_None ? "" : " UNIQUE", n, pName->z); +- }else{ +- /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */ +- /* zStmt = sqlite3MPrintf(""); */ +- zStmt = 0; +- } ++ /* Gather the complete text of the CREATE INDEX statement into ++ ** the zStmt variable ++ */ ++ if( pStart ){ ++ int n = (int)(pParse->sLastToken.z - pName->z) + pParse->sLastToken.n; ++ if( pName->z[n-1]==';' ) n--; ++ /* A named index with an explicit CREATE INDEX statement */ ++ zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s", ++ onError==OE_None ? "" : " UNIQUE", n, pName->z); ++ }else{ ++ /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */ ++ /* zStmt = sqlite3MPrintf(""); */ ++ zStmt = 0; ++ } + +- /* Add an entry in sqlite_master for this index +- */ +- sqlite3NestedParse(pParse, +- "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);", +- db->aDb[iDb].zDbSName, MASTER_NAME, +- pIndex->zName, +- pTab->zName, +- iMem, +- zStmt +- ); +- sqlite3DbFree(db, zStmt); ++ /* Add an entry in sqlite_master for this index ++ */ ++ sqlite3NestedParse(pParse, ++ "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);", ++ db->aDb[iDb].zDbSName, MASTER_NAME, ++ pIndex->zName, ++ pTab->zName, ++ iMem, ++ zStmt ++ ); ++ sqlite3DbFree(db, zStmt); + +- /* Fill the index with data and reparse the schema. Code an OP_Expire +- ** to invalidate all pre-compiled statements. +- */ +- if( pTblName ){ +- sqlite3RefillIndex(pParse, pIndex, iMem); +- sqlite3ChangeCookie(pParse, iDb); +- sqlite3VdbeAddParseSchemaOp(v, iDb, +- sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName)); +- sqlite3VdbeAddOp0(v, OP_Expire); ++ /* Fill the index with data and reparse the schema. Code an OP_Expire ++ ** to invalidate all pre-compiled statements. ++ */ ++ if( pTblName ){ ++ sqlite3RefillIndex(pParse, pIndex, iMem); ++ sqlite3ChangeCookie(pParse, iDb); ++ sqlite3VdbeAddParseSchemaOp(v, iDb, ++ sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName)); ++ sqlite3VdbeAddOp2(v, OP_Expire, 0, 1); ++ } ++ ++ sqlite3VdbeJumpHere(v, pIndex->tnum); + } +- +- sqlite3VdbeJumpHere(v, pIndex->tnum); + } + + /* When adding an index to the list of indices for a table, make +@@ -103879,10 +109512,15 @@ + } + pIndex = 0; + } ++ else if( IN_RENAME_OBJECT ){ ++ assert( pParse->pNewIndex==0 ); ++ pParse->pNewIndex = pIndex; ++ pIndex = 0; ++ } + + /* Clean up before exiting */ + exit_create_index: +- if( pIndex ) freeIndex(db, pIndex); ++ if( pIndex ) sqlite3FreeIndex(db, pIndex); + sqlite3ExprDelete(db, pPIWhere); + sqlite3ExprListDelete(db, pList); + sqlite3SrcListDelete(db, pTblName); +@@ -104051,7 +109689,8 @@ + ** + ** A new IdList is returned, or NULL if malloc() fails. + */ +-SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3 *db, IdList *pList, Token *pToken){ ++SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token *pToken){ ++ sqlite3 *db = pParse->db; + int i; + if( pList==0 ){ + pList = sqlite3DbMallocZero(db, sizeof(IdList) ); +@@ -104069,6 +109708,9 @@ + return 0; + } + pList->a[i].zName = sqlite3NameFromToken(db, pToken); ++ if( IN_RENAME_OBJECT && pList->a[i].zName ){ ++ sqlite3RenameTokenMap(pParse, (void*)pList->a[i].zName, pToken); ++ } + return pList; + } + +@@ -104310,10 +109952,17 @@ + goto append_from_error; + } + p = sqlite3SrcListAppend(db, p, pTable, pDatabase); +- if( p==0 || NEVER(p->nSrc==0) ){ ++ if( p==0 ){ + goto append_from_error; + } ++ assert( p->nSrc>0 ); + pItem = &p->a[p->nSrc-1]; ++ assert( (pTable==0)==(pDatabase==0) ); ++ assert( pItem->zName==0 || pDatabase!=0 ); ++ if( IN_RENAME_OBJECT && pItem->zName ){ ++ Token *pToken = (ALWAYS(pDatabase) && pDatabase->z) ? pDatabase : pTable; ++ sqlite3RenameTokenMap(pParse, pItem->zName, pToken); ++ } + assert( pAlias!=0 ); + if( pAlias->n ){ + pItem->zAlias = sqlite3NameFromToken(db, pAlias); +@@ -104337,8 +109986,10 @@ + */ + SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){ + assert( pIndexedBy!=0 ); +- if( p && ALWAYS(p->nSrc>0) ){ +- struct SrcList_item *pItem = &p->a[p->nSrc-1]; ++ if( p && pIndexedBy->n>0 ){ ++ struct SrcList_item *pItem; ++ assert( p->nSrc>0 ); ++ pItem = &p->a[p->nSrc-1]; + assert( pItem->fg.notIndexed==0 ); + assert( pItem->fg.isIndexedBy==0 ); + assert( pItem->fg.isTabFunc==0 ); +@@ -104348,7 +109999,7 @@ + pItem->fg.notIndexed = 1; + }else{ + pItem->u1.zIndexedBy = sqlite3NameFromToken(pParse->db, pIndexedBy); +- pItem->fg.isIndexedBy = (pItem->u1.zIndexedBy!=0); ++ pItem->fg.isIndexedBy = 1; + } + } + } +@@ -104622,16 +110273,16 @@ + + sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, 200); + if( pIdx->aColExpr ){ +- sqlite3XPrintf(&errMsg, "index '%q'", pIdx->zName); ++ sqlite3_str_appendf(&errMsg, "index '%q'", pIdx->zName); + }else{ + for(j=0; j<pIdx->nKeyCol; j++){ + char *zCol; + assert( pIdx->aiColumn[j]>=0 ); + zCol = pTab->aCol[pIdx->aiColumn[j]].zName; +- if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2); +- sqlite3StrAccumAppendAll(&errMsg, pTab->zName); +- sqlite3StrAccumAppend(&errMsg, ".", 1); +- sqlite3StrAccumAppendAll(&errMsg, zCol); ++ if( j ) sqlite3_str_append(&errMsg, ", ", 2); ++ sqlite3_str_appendall(&errMsg, pTab->zName); ++ sqlite3_str_append(&errMsg, ".", 1); ++ sqlite3_str_appendall(&errMsg, zCol); + } + } + zErr = sqlite3StrAccumFinish(&errMsg); +@@ -104819,6 +110470,18 @@ + pKey->aSortOrder[i] = pIdx->aSortOrder[i]; + } + if( pParse->nErr ){ ++ assert( pParse->rc==SQLITE_ERROR_MISSING_COLLSEQ ); ++ if( pIdx->bNoQuery==0 ){ ++ /* Deactivate the index because it contains an unknown collating ++ ** sequence. The only way to reactive the index is to reload the ++ ** schema. Adding the missing collating sequence later does not ++ ** reactive the index. The application had the chance to register ++ ** the missing index using the collation-needed callback. For ++ ** simplicity, SQLite will not give the application a second chance. ++ */ ++ pIdx->bNoQuery = 1; ++ pParse->rc = SQLITE_ERROR_RETRY; ++ } + sqlite3KeyInfoUnref(pKey); + pKey = 0; + } +@@ -105004,6 +110667,7 @@ + assert( !p || p->xCmp ); + if( p==0 ){ + sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName); ++ pParse->rc = SQLITE_ERROR_MISSING_COLLSEQ; + } + return p; + } +@@ -105193,6 +110857,21 @@ + } + return 0; + } ++#ifdef SQLITE_ENABLE_NORMALIZE ++SQLITE_PRIVATE FuncDef *sqlite3FunctionSearchN( ++ int h, /* Hash of the name */ ++ const char *zFunc, /* Name of function */ ++ int nFunc /* Length of the name */ ++){ ++ FuncDef *p; ++ for(p=sqlite3BuiltinFunctions.a[h]; p; p=p->u.pHash){ ++ if( sqlite3StrNICmp(p->zName, zFunc, nFunc)==0 ){ ++ return p; ++ } ++ } ++ return 0; ++} ++#endif /* SQLITE_ENABLE_NORMALIZE */ + + /* + ** Insert a new FuncDef into a FuncDefHash hash table. +@@ -105206,7 +110885,7 @@ + FuncDef *pOther; + const char *zName = aDef[i].zName; + int nName = sqlite3Strlen30(zName); +- int h = (zName[0] + nName) % SQLITE_FUNC_HASH_SZ; ++ int h = SQLITE_FUNC_HASH(zName[0], nName); + assert( zName[0]>='a' && zName[0]<='z' ); + pOther = functionSearch(h, zName); + if( pOther ){ +@@ -105273,7 +110952,7 @@ + + /* If no match is found, search the built-in functions. + ** +- ** If the SQLITE_PreferBuiltin flag is set, then search the built-in ++ ** If the DBFLAG_PreferBuiltin flag is set, then search the built-in + ** functions even if a prior app-defined function was found. And give + ** priority to built-in functions. + ** +@@ -105283,9 +110962,9 @@ + ** new function. But the FuncDefs for built-in functions are read-only. + ** So we must not search for built-ins when creating a new function. + */ +- if( !createFlag && (pBest==0 || (db->flags & SQLITE_PreferBuiltin)!=0) ){ ++ if( !createFlag && (pBest==0 || (db->mDbFlags & DBFLAG_PreferBuiltin)!=0) ){ + bestScore = 0; +- h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % SQLITE_FUNC_HASH_SZ; ++ h = SQLITE_FUNC_HASH(sqlite3UpperToLower[(u8)zName[0]], nName); + p = functionSearch(h, zName); + while( p ){ + int score = matchQuality(p, nArg, enc); +@@ -105304,10 +110983,12 @@ + if( createFlag && bestScore<FUNC_PERFECT_MATCH && + (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){ + FuncDef *pOther; ++ u8 *z; + pBest->zName = (const char*)&pBest[1]; + pBest->nArg = (u16)nArg; + pBest->funcFlags = enc; + memcpy((char*)&pBest[1], zName, nName+1); ++ for(z=(u8*)pBest->zName; *z; z++) *z = sqlite3UpperToLower[*z]; + pOther = (FuncDef*)sqlite3HashInsert(&db->aFunc, pBest->zName, pBest); + if( pOther==pBest ){ + sqlite3DbFree(db, pBest); +@@ -105356,8 +111037,8 @@ + pSchema->pSeqTab = 0; + if( pSchema->schemaFlags & DB_SchemaLoaded ){ + pSchema->iGeneration++; +- pSchema->schemaFlags &= ~DB_SchemaLoaded; + } ++ pSchema->schemaFlags &= ~(DB_SchemaLoaded|DB_ResetWanted); + } + + /* +@@ -105431,6 +111112,39 @@ + return pTab; + } + ++/* Return true if table pTab is read-only. ++** ++** A table is read-only if any of the following are true: ++** ++** 1) It is a virtual table and no implementation of the xUpdate method ++** has been provided ++** ++** 2) It is a system table (i.e. sqlite_master), this call is not ++** part of a nested parse and writable_schema pragma has not ++** been specified ++** ++** 3) The table is a shadow table, the database connection is in ++** defensive mode, and the current sqlite3_prepare() ++** is for a top-level SQL statement. ++*/ ++static int tabIsReadOnly(Parse *pParse, Table *pTab){ ++ sqlite3 *db; ++ if( IsVirtual(pTab) ){ ++ return sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0; ++ } ++ if( (pTab->tabFlags & (TF_Readonly|TF_Shadow))==0 ) return 0; ++ db = pParse->db; ++ if( (pTab->tabFlags & TF_Readonly)!=0 ){ ++ return sqlite3WritableSchema(db)==0 && pParse->nested==0; ++ } ++ assert( pTab->tabFlags & TF_Shadow ); ++ return (db->flags & SQLITE_Defensive)!=0 ++#ifndef SQLITE_OMIT_VIRTUALTABLE ++ && db->pVtabCtx==0 ++#endif ++ && db->nVdbeExec==0; ++} ++ + /* + ** Check to make sure the given table is writable. If it is not + ** writable, generate an error message and return 1. If it is +@@ -105437,26 +111151,10 @@ + ** writable return 0; + */ + SQLITE_PRIVATE int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){ +- /* A table is not writable under the following circumstances: +- ** +- ** 1) It is a virtual table and no implementation of the xUpdate method +- ** has been provided, or +- ** 2) It is a system table (i.e. sqlite_master), this call is not +- ** part of a nested parse and writable_schema pragma has not +- ** been specified. +- ** +- ** In either case leave an error message in pParse and return non-zero. +- */ +- if( ( IsVirtual(pTab) +- && sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 ) +- || ( (pTab->tabFlags & TF_Readonly)!=0 +- && (pParse->db->flags & SQLITE_WriteSchema)==0 +- && pParse->nested==0 ) +- ){ ++ if( tabIsReadOnly(pParse, pTab) ){ + sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName); + return 1; + } +- + #ifndef SQLITE_OMIT_VIEW + if( !viewOk && pTab->pSelect ){ + sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName); +@@ -105477,6 +111175,8 @@ + Parse *pParse, /* Parsing context */ + Table *pView, /* View definition */ + Expr *pWhere, /* Optional WHERE clause to be added */ ++ ExprList *pOrderBy, /* Optional ORDER BY clause */ ++ Expr *pLimit, /* Optional LIMIT clause */ + int iCur /* Cursor number for ephemeral table */ + ){ + SelectDest dest; +@@ -105493,8 +111193,8 @@ + assert( pFrom->a[0].pOn==0 ); + assert( pFrom->a[0].pUsing==0 ); + } +- pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, +- SF_IncludeHidden, 0, 0); ++ pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, pOrderBy, ++ SF_IncludeHidden, pLimit); + sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur); + sqlite3Select(pParse, pSel, &dest); + sqlite3SelectDelete(db, pSel); +@@ -105516,21 +111216,23 @@ + Expr *pWhere, /* The WHERE clause. May be null */ + ExprList *pOrderBy, /* The ORDER BY clause. May be null */ + Expr *pLimit, /* The LIMIT clause. May be null */ +- Expr *pOffset, /* The OFFSET clause. May be null */ + char *zStmtType /* Either DELETE or UPDATE. For err msgs. */ + ){ +- Expr *pWhereRowid = NULL; /* WHERE rowid .. */ ++ sqlite3 *db = pParse->db; ++ Expr *pLhs = NULL; /* LHS of IN(SELECT...) operator */ + Expr *pInClause = NULL; /* WHERE rowid IN ( select ) */ +- Expr *pSelectRowid = NULL; /* SELECT rowid ... */ + ExprList *pEList = NULL; /* Expression list contaning only pSelectRowid */ + SrcList *pSelectSrc = NULL; /* SELECT rowid FROM x ... (dup of pSrc) */ + Select *pSelect = NULL; /* Complete SELECT tree */ ++ Table *pTab; + + /* Check that there isn't an ORDER BY without a LIMIT clause. + */ +- if( pOrderBy && (pLimit == 0) ) { ++ if( pOrderBy && pLimit==0 ) { + sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType); +- goto limit_where_cleanup; ++ sqlite3ExprDelete(pParse->db, pWhere); ++ sqlite3ExprListDelete(pParse->db, pOrderBy); ++ return 0; + } + + /* We only need to generate a select expression if there +@@ -105537,8 +111239,6 @@ + ** is a limit/offset term to enforce. + */ + if( pLimit == 0 ) { +- /* if pLimit is null, pOffset will always be null as well. */ +- assert( pOffset == 0 ); + return pWhere; + } + +@@ -105551,36 +111251,47 @@ + ** ); + */ + +- pSelectRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0); +- if( pSelectRowid == 0 ) goto limit_where_cleanup; +- pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid); +- if( pEList == 0 ) goto limit_where_cleanup; ++ pTab = pSrc->a[0].pTab; ++ if( HasRowid(pTab) ){ ++ pLhs = sqlite3PExpr(pParse, TK_ROW, 0, 0); ++ pEList = sqlite3ExprListAppend( ++ pParse, 0, sqlite3PExpr(pParse, TK_ROW, 0, 0) ++ ); ++ }else{ ++ Index *pPk = sqlite3PrimaryKeyIndex(pTab); ++ if( pPk->nKeyCol==1 ){ ++ const char *zName = pTab->aCol[pPk->aiColumn[0]].zName; ++ pLhs = sqlite3Expr(db, TK_ID, zName); ++ pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ID, zName)); ++ }else{ ++ int i; ++ for(i=0; i<pPk->nKeyCol; i++){ ++ Expr *p = sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zName); ++ pEList = sqlite3ExprListAppend(pParse, pEList, p); ++ } ++ pLhs = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); ++ if( pLhs ){ ++ pLhs->x.pList = sqlite3ExprListDup(db, pEList, 0); ++ } ++ } ++ } + + /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree + ** and the SELECT subtree. */ ++ pSrc->a[0].pTab = 0; + pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc, 0); +- if( pSelectSrc == 0 ) { +- sqlite3ExprListDelete(pParse->db, pEList); +- goto limit_where_cleanup; +- } ++ pSrc->a[0].pTab = pTab; ++ pSrc->a[0].pIBIndex = 0; + + /* generate the SELECT expression tree. */ +- pSelect = sqlite3SelectNew(pParse,pEList,pSelectSrc,pWhere,0,0, +- pOrderBy,0,pLimit,pOffset); +- if( pSelect == 0 ) return 0; ++ pSelect = sqlite3SelectNew(pParse, pEList, pSelectSrc, pWhere, 0 ,0, ++ pOrderBy,0,pLimit ++ ); + + /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */ +- pWhereRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0); +- pInClause = pWhereRowid ? sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0) : 0; ++ pInClause = sqlite3PExpr(pParse, TK_IN, pLhs, 0); + sqlite3PExprAddSelect(pParse, pInClause, pSelect); + return pInClause; +- +-limit_where_cleanup: +- sqlite3ExprDelete(pParse->db, pWhere); +- sqlite3ExprListDelete(pParse->db, pOrderBy); +- sqlite3ExprDelete(pParse->db, pLimit); +- sqlite3ExprDelete(pParse->db, pOffset); +- return 0; + } + #endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) */ + /* && !defined(SQLITE_OMIT_SUBQUERY) */ +@@ -105595,7 +111306,9 @@ + SQLITE_PRIVATE void sqlite3DeleteFrom( + Parse *pParse, /* The parser context */ + SrcList *pTabList, /* The table from which we should delete things */ +- Expr *pWhere /* The WHERE clause. May be null */ ++ Expr *pWhere, /* The WHERE clause. May be null */ ++ ExprList *pOrderBy, /* ORDER BY clause. May be null */ ++ Expr *pLimit /* LIMIT clause. May be null */ + ){ + Vdbe *v; /* The virtual database engine */ + Table *pTab; /* The table from which records will be deleted */ +@@ -105610,7 +111323,7 @@ + AuthContext sContext; /* Authorization context */ + NameContext sNC; /* Name context to resolve expressions in */ + int iDb; /* Database number */ +- int memCnt = -1; /* Memory cell used for change counting */ ++ int memCnt = 0; /* Memory cell used for change counting */ + int rcauth; /* Value returned by authorization callback */ + int eOnePass; /* ONEPASS_OFF or _SINGLE or _MULTI */ + int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */ +@@ -105640,6 +111353,7 @@ + } + assert( pTabList->nSrc==1 ); + ++ + /* Locate the table which we want to delete. This table has to be + ** put in an SrcList structure because some of the subroutines we + ** will be calling are designed to work with multiple tables and expect +@@ -105654,16 +111368,26 @@ + #ifndef SQLITE_OMIT_TRIGGER + pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); + isView = pTab->pSelect!=0; +- bComplex = pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0); + #else + # define pTrigger 0 + # define isView 0 + #endif ++ bComplex = pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0); + #ifdef SQLITE_OMIT_VIEW + # undef isView + # define isView 0 + #endif + ++#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT ++ if( !isView ){ ++ pWhere = sqlite3LimitWhere( ++ pParse, pTabList, pWhere, pOrderBy, pLimit, "DELETE" ++ ); ++ pOrderBy = 0; ++ pLimit = 0; ++ } ++#endif ++ + /* If pTab is really a view, make sure it has been initialized. + */ + if( sqlite3ViewGetColumnNames(pParse, pTab) ){ +@@ -105704,7 +111428,7 @@ + goto delete_from_cleanup; + } + if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); +- sqlite3BeginWriteOperation(pParse, 1, iDb); ++ sqlite3BeginWriteOperation(pParse, bComplex, iDb); + + /* If we are trying to delete from a view, realize that view into + ** an ephemeral table. +@@ -105711,8 +111435,12 @@ + */ + #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) + if( isView ){ +- sqlite3MaterializeView(pParse, pTab, pWhere, iTabCur); ++ sqlite3MaterializeView(pParse, pTab, ++ pWhere, pOrderBy, pLimit, iTabCur ++ ); + iDataCur = iIdxCur = iTabCur; ++ pOrderBy = 0; ++ pLimit = 0; + } + #endif + +@@ -105728,7 +111456,10 @@ + /* Initialize the counter of the number of rows deleted, if + ** we are counting rows. + */ +- if( db->flags & SQLITE_CountRows ){ ++ if( (db->flags & SQLITE_CountRows)!=0 ++ && !pParse->nested ++ && !pParse->pTriggerTab ++ ){ + memCnt = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt); + } +@@ -105756,7 +111487,7 @@ + assert( !isView ); + sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName); + if( HasRowid(pTab) ){ +- sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt, ++ sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt ? memCnt : -1, + pTab->zName, P4_STATIC); + } + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ +@@ -105801,9 +111532,10 @@ + eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); + assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI ); + assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF ); ++ if( eOnePass!=ONEPASS_SINGLE ) sqlite3MultiWrite(pParse); + + /* Keep track of the number of rows to be deleted */ +- if( db->flags & SQLITE_CountRows ){ ++ if( memCnt ){ + sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1); + } + +@@ -105816,9 +111548,8 @@ + } + iKey = iPk; + }else{ +- iKey = pParse->nMem + 1; +- iKey = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iTabCur, iKey, 0); +- if( iKey>pParse->nMem ) pParse->nMem = iKey; ++ iKey = ++pParse->nMem; ++ sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, -1, iKey); + } + + if( eOnePass!=ONEPASS_OFF ){ +@@ -105889,7 +111620,11 @@ + } + }else if( pPk ){ + addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v); +- sqlite3VdbeAddOp2(v, OP_RowData, iEphCur, iKey); ++ if( IsVirtual(pTab) ){ ++ sqlite3VdbeAddOp3(v, OP_Column, iEphCur, 0, iKey); ++ }else{ ++ sqlite3VdbeAddOp2(v, OP_RowData, iEphCur, iKey); ++ } + assert( nKey==0 ); /* OP_Found will use a composite key */ + }else{ + addrLoop = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, 0, iKey); +@@ -105902,13 +111637,16 @@ + if( IsVirtual(pTab) ){ + const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); + sqlite3VtabMakeWritable(pParse, pTab); +- sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB); +- sqlite3VdbeChangeP5(v, OE_Abort); + assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE ); + sqlite3MayAbort(pParse); +- if( eOnePass==ONEPASS_SINGLE && sqlite3IsToplevel(pParse) ){ +- pParse->isMultiWrite = 0; ++ if( eOnePass==ONEPASS_SINGLE ){ ++ sqlite3VdbeAddOp1(v, OP_Close, iTabCur); ++ if( sqlite3IsToplevel(pParse) ){ ++ pParse->isMultiWrite = 0; ++ } + } ++ sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB); ++ sqlite3VdbeChangeP5(v, OE_Abort); + }else + #endif + { +@@ -105942,7 +111680,7 @@ + ** generating code because of a call to sqlite3NestedParse(), do not + ** invoke the callback function. + */ +- if( (db->flags&SQLITE_CountRows) && !pParse->nested && !pParse->pTriggerTab ){ ++ if( memCnt ){ + sqlite3VdbeAddOp2(v, OP_ResultRow, memCnt, 1); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC); +@@ -105952,6 +111690,10 @@ + sqlite3AuthContextPop(&sContext); + sqlite3SrcListDelete(db, pTabList); + sqlite3ExprDelete(db, pWhere); ++#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) ++ sqlite3ExprListDelete(db, pOrderBy); ++ sqlite3ExprDelete(db, pLimit); ++#endif + sqlite3DbFree(db, aToOpen); + return; + } +@@ -106109,7 +111851,7 @@ + u8 p5 = 0; + sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek); + sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0)); +- if( pParse->nested==0 ){ ++ if( pParse->nested==0 || 0==sqlite3_stricmp(pTab->zName, "sqlite_stat1") ){ + sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE); + } + if( eMode!=ONEPASS_OFF ){ +@@ -106240,7 +111982,6 @@ + if( pIdx->pPartIdxWhere ){ + *piPartIdxLabel = sqlite3VdbeMakeLabel(v); + pParse->iSelfTab = iDataCur + 1; +- sqlite3ExprCachePush(pParse); + sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel, + SQLITE_JUMPIFNULL); + pParse->iSelfTab = 0; +@@ -106287,7 +112028,6 @@ + SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse *pParse, int iLabel){ + if( iLabel ){ + sqlite3VdbeResolveLabel(pParse->pVdbe, iLabel); +- sqlite3ExprCachePop(pParse); + } + } + +@@ -106330,6 +112070,8 @@ + ** iteration of the aggregate loop. + */ + static void sqlite3SkipAccumulatorLoad(sqlite3_context *context){ ++ assert( context->isError<=0 ); ++ context->isError = -1; + context->skipFlag = 1; + } + +@@ -106396,8 +112138,6 @@ + int argc, + sqlite3_value **argv + ){ +- int len; +- + assert( argc==1 ); + UNUSED_PARAMETER(argc); + switch( sqlite3_value_type(argv[0]) ){ +@@ -106409,13 +112149,17 @@ + } + case SQLITE_TEXT: { + const unsigned char *z = sqlite3_value_text(argv[0]); ++ const unsigned char *z0; ++ unsigned char c; + if( z==0 ) return; +- len = 0; +- while( *z ){ +- len++; +- SQLITE_SKIP_UTF8(z); ++ z0 = z; ++ while( (c = *z)!=0 ){ ++ z++; ++ if( c>=0xc0 ){ ++ while( (*z & 0xc0)==0x80 ){ z++; z0++; } ++ } + } +- sqlite3_result_int(context, len); ++ sqlite3_result_int(context, (int)(z-z0)); + break; + } + default: { +@@ -106542,7 +112286,7 @@ + x.apArg = argv+1; + sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); + str.printfFlags = SQLITE_PRINTF_SQLFUNC; +- sqlite3XPrintf(&str, zFormat, &x); ++ sqlite3_str_appendf(&str, zFormat, &x); + n = str.nChar; + sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n, + SQLITE_DYNAMIC); +@@ -106993,16 +112737,20 @@ + ** c or cx. + */ + if( c<=0x80 ){ +- u32 cx; ++ char zStop[3]; + int bMatch; + if( noCase ){ +- cx = sqlite3Toupper(c); +- c = sqlite3Tolower(c); ++ zStop[0] = sqlite3Toupper(c); ++ zStop[1] = sqlite3Tolower(c); ++ zStop[2] = 0; + }else{ +- cx = c; ++ zStop[0] = c; ++ zStop[1] = 0; + } +- while( (c2 = *(zString++))!=0 ){ +- if( c2!=c && c2!=cx ) continue; ++ while(1){ ++ zString += strcspn((const char*)zString, zStop); ++ if( zString[0]==0 ) break; ++ zString++; + bMatch = patternCompare(zPattern,zString,pInfo,matchOther); + if( bMatch!=SQLITE_NOMATCH ) return bMatch; + } +@@ -107160,7 +112908,8 @@ + #ifdef SQLITE_TEST + sqlite3_like_count++; + #endif +- sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape)==SQLITE_MATCH); ++ sqlite3_result_int(context, ++ patternCompare(zB, zA, pInfo, escape)==SQLITE_MATCH); + } + } + +@@ -107485,6 +113234,8 @@ + i64 nOut; /* Maximum size of zOut */ + int loopLimit; /* Last zStr[] that might match zPattern[] */ + int i, j; /* Loop counters */ ++ unsigned cntExpand; /* Number zOut expansions */ ++ sqlite3 *db = sqlite3_context_db_handle(context); + + assert( argc==3 ); + UNUSED_PARAMETER(argc); +@@ -107516,33 +113267,40 @@ + return; + } + loopLimit = nStr - nPattern; ++ cntExpand = 0; + for(i=j=0; i<=loopLimit; i++){ + if( zStr[i]!=zPattern[0] || memcmp(&zStr[i], zPattern, nPattern) ){ + zOut[j++] = zStr[i]; + }else{ +- u8 *zOld; +- sqlite3 *db = sqlite3_context_db_handle(context); +- nOut += nRep - nPattern; +- testcase( nOut-1==db->aLimit[SQLITE_LIMIT_LENGTH] ); +- testcase( nOut-2==db->aLimit[SQLITE_LIMIT_LENGTH] ); +- if( nOut-1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ +- sqlite3_result_error_toobig(context); +- sqlite3_free(zOut); +- return; ++ if( nRep>nPattern ){ ++ nOut += nRep - nPattern; ++ testcase( nOut-1==db->aLimit[SQLITE_LIMIT_LENGTH] ); ++ testcase( nOut-2==db->aLimit[SQLITE_LIMIT_LENGTH] ); ++ if( nOut-1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ ++ sqlite3_result_error_toobig(context); ++ sqlite3_free(zOut); ++ return; ++ } ++ cntExpand++; ++ if( (cntExpand&(cntExpand-1))==0 ){ ++ /* Grow the size of the output buffer only on substitutions ++ ** whose index is a power of two: 1, 2, 4, 8, 16, 32, ... */ ++ u8 *zOld; ++ zOld = zOut; ++ zOut = sqlite3_realloc64(zOut, (int)nOut + (nOut - nStr - 1)); ++ if( zOut==0 ){ ++ sqlite3_result_error_nomem(context); ++ sqlite3_free(zOld); ++ return; ++ } ++ } + } +- zOld = zOut; +- zOut = sqlite3_realloc64(zOut, (int)nOut); +- if( zOut==0 ){ +- sqlite3_result_error_nomem(context); +- sqlite3_free(zOld); +- return; +- } + memcpy(&zOut[j], zRep, nRep); + j += nRep; + i += nPattern-1; + } + } +- assert( j+nStr-i+1==nOut ); ++ assert( j+nStr-i+1<=nOut ); + memcpy(&zOut[j], &zStr[i], nStr-i); + j += nStr - i; + assert( j<=nOut ); +@@ -107782,7 +113540,7 @@ + i64 v = sqlite3_value_int64(argv[0]); + p->rSum += v; + if( (p->approx|p->overflow)==0 && sqlite3AddInt64(&p->iSum, v) ){ +- p->overflow = 1; ++ p->approx = p->overflow = 1; + } + }else{ + p->rSum += sqlite3_value_double(argv[0]); +@@ -107790,6 +113548,32 @@ + } + } + } ++#ifndef SQLITE_OMIT_WINDOWFUNC ++static void sumInverse(sqlite3_context *context, int argc, sqlite3_value**argv){ ++ SumCtx *p; ++ int type; ++ assert( argc==1 ); ++ UNUSED_PARAMETER(argc); ++ p = sqlite3_aggregate_context(context, sizeof(*p)); ++ type = sqlite3_value_numeric_type(argv[0]); ++ /* p is always non-NULL because sumStep() will have been called first ++ ** to initialize it */ ++ if( ALWAYS(p) && type!=SQLITE_NULL ){ ++ assert( p->cnt>0 ); ++ p->cnt--; ++ assert( type==SQLITE_INTEGER || p->approx ); ++ if( type==SQLITE_INTEGER && p->approx==0 ){ ++ i64 v = sqlite3_value_int64(argv[0]); ++ p->rSum -= v; ++ p->iSum -= v; ++ }else{ ++ p->rSum -= sqlite3_value_double(argv[0]); ++ } ++ } ++} ++#else ++# define sumInverse 0 ++#endif /* SQLITE_OMIT_WINDOWFUNC */ + static void sumFinalize(sqlite3_context *context){ + SumCtx *p; + p = sqlite3_aggregate_context(context, 0); +@@ -107824,6 +113608,9 @@ + typedef struct CountCtx CountCtx; + struct CountCtx { + i64 n; ++#ifdef SQLITE_DEBUG ++ int bInverse; /* True if xInverse() ever called */ ++#endif + }; + + /* +@@ -107841,7 +113628,7 @@ + ** sure it still operates correctly, verify that its count agrees with our + ** internal count when using count(*) and when the total count can be + ** expressed as a 32-bit integer. */ +- assert( argc==1 || p==0 || p->n>0x7fffffff ++ assert( argc==1 || p==0 || p->n>0x7fffffff || p->bInverse + || p->n==sqlite3_aggregate_count(context) ); + #endif + } +@@ -107850,6 +113637,21 @@ + p = sqlite3_aggregate_context(context, 0); + sqlite3_result_int64(context, p ? p->n : 0); + } ++#ifndef SQLITE_OMIT_WINDOWFUNC ++static void countInverse(sqlite3_context *ctx, int argc, sqlite3_value **argv){ ++ CountCtx *p; ++ p = sqlite3_aggregate_context(ctx, sizeof(*p)); ++ /* p is always non-NULL since countStep() will have been called first */ ++ if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0])) && ALWAYS(p) ){ ++ p->n--; ++#ifdef SQLITE_DEBUG ++ p->bInverse = 1; ++#endif ++ } ++} ++#else ++# define countInverse 0 ++#endif /* SQLITE_OMIT_WINDOWFUNC */ + + /* + ** Routines to implement min() and max() aggregate functions. +@@ -107866,7 +113668,7 @@ + pBest = (Mem *)sqlite3_aggregate_context(context, sizeof(*pBest)); + if( !pBest ) return; + +- if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ ++ if( sqlite3_value_type(pArg)==SQLITE_NULL ){ + if( pBest->flags ) sqlite3SkipAccumulatorLoad(context); + }else if( pBest->flags ){ + int max; +@@ -107892,7 +113694,7 @@ + sqlite3VdbeMemCopy(pBest, pArg); + } + } +-static void minMaxFinalize(sqlite3_context *context){ ++static void minMaxValueFinalize(sqlite3_context *context, int bValue){ + sqlite3_value *pRes; + pRes = (sqlite3_value *)sqlite3_aggregate_context(context, 0); + if( pRes ){ +@@ -107899,9 +113701,19 @@ + if( pRes->flags ){ + sqlite3_result_value(context, pRes); + } +- sqlite3VdbeMemRelease(pRes); ++ if( bValue==0 ) sqlite3VdbeMemRelease(pRes); + } + } ++#ifndef SQLITE_OMIT_WINDOWFUNC ++static void minMaxValue(sqlite3_context *context){ ++ minMaxValueFinalize(context, 1); ++} ++#else ++# define minMaxValue 0 ++#endif /* SQLITE_OMIT_WINDOWFUNC */ ++static void minMaxFinalize(sqlite3_context *context){ ++ minMaxValueFinalize(context, 0); ++} + + /* + ** group_concat(EXPR, ?SEPARATOR?) +@@ -107931,20 +113743,52 @@ + zSep = ","; + nSep = 1; + } +- if( zSep ) sqlite3StrAccumAppend(pAccum, zSep, nSep); ++ if( zSep ) sqlite3_str_append(pAccum, zSep, nSep); + } + zVal = (char*)sqlite3_value_text(argv[0]); + nVal = sqlite3_value_bytes(argv[0]); +- if( zVal ) sqlite3StrAccumAppend(pAccum, zVal, nVal); ++ if( zVal ) sqlite3_str_append(pAccum, zVal, nVal); + } + } ++#ifndef SQLITE_OMIT_WINDOWFUNC ++static void groupConcatInverse( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ int n; ++ StrAccum *pAccum; ++ assert( argc==1 || argc==2 ); ++ if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; ++ pAccum = (StrAccum*)sqlite3_aggregate_context(context, sizeof(*pAccum)); ++ /* pAccum is always non-NULL since groupConcatStep() will have always ++ ** run frist to initialize it */ ++ if( ALWAYS(pAccum) ){ ++ n = sqlite3_value_bytes(argv[0]); ++ if( argc==2 ){ ++ n += sqlite3_value_bytes(argv[1]); ++ }else{ ++ n++; ++ } ++ if( n>=(int)pAccum->nChar ){ ++ pAccum->nChar = 0; ++ }else{ ++ pAccum->nChar -= n; ++ memmove(pAccum->zText, &pAccum->zText[n], pAccum->nChar); ++ } ++ if( pAccum->nChar==0 ) pAccum->mxAlloc = 0; ++ } ++} ++#else ++# define groupConcatInverse 0 ++#endif /* SQLITE_OMIT_WINDOWFUNC */ + static void groupConcatFinalize(sqlite3_context *context){ + StrAccum *pAccum; + pAccum = sqlite3_aggregate_context(context, 0); + if( pAccum ){ +- if( pAccum->accError==STRACCUM_TOOBIG ){ ++ if( pAccum->accError==SQLITE_TOOBIG ){ + sqlite3_result_error_toobig(context); +- }else if( pAccum->accError==STRACCUM_NOMEM ){ ++ }else if( pAccum->accError==SQLITE_NOMEM ){ + sqlite3_result_error_nomem(context); + }else{ + sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1, +@@ -107952,6 +113796,24 @@ + } + } + } ++#ifndef SQLITE_OMIT_WINDOWFUNC ++static void groupConcatValue(sqlite3_context *context){ ++ sqlite3_str *pAccum; ++ pAccum = (sqlite3_str*)sqlite3_aggregate_context(context, 0); ++ if( pAccum ){ ++ if( pAccum->accError==SQLITE_TOOBIG ){ ++ sqlite3_result_error_toobig(context); ++ }else if( pAccum->accError==SQLITE_NOMEM ){ ++ sqlite3_result_error_nomem(context); ++ }else{ ++ const char *zText = sqlite3_str_value(pAccum); ++ sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT); ++ } ++ } ++} ++#else ++# define groupConcatValue 0 ++#endif /* SQLITE_OMIT_WINDOWFUNC */ + + /* + ** This routine does per-connection function registration. Most +@@ -107989,10 +113851,10 @@ + }else{ + pInfo = (struct compareInfo*)&likeInfoNorm; + } +- sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0); +- sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0); ++ sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0, 0, 0); ++ sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0, 0, 0); + sqlite3CreateFunc(db, "glob", 2, SQLITE_UTF8, +- (struct compareInfo*)&globInfo, likeFunc, 0, 0, 0); ++ (struct compareInfo*)&globInfo, likeFunc, 0, 0, 0, 0, 0); + setLikeOptFlag(db, "glob", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE); + setLikeOptFlag(db, "like", + caseSensitive ? (SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE) : SQLITE_FUNC_LIKE); +@@ -108001,10 +113863,15 @@ + /* + ** pExpr points to an expression which implements a function. If + ** it is appropriate to apply the LIKE optimization to that function +-** then set aWc[0] through aWc[2] to the wildcard characters and +-** return TRUE. If the function is not a LIKE-style function then +-** return FALSE. ++** then set aWc[0] through aWc[2] to the wildcard characters and the ++** escape character and then return TRUE. If the function is not a ++** LIKE-style function then return FALSE. + ** ++** The expression "a LIKE b ESCAPE c" is only considered a valid LIKE ++** operator if c is a string literal that is exactly one byte in length. ++** That one byte is stored in aWc[3]. aWc[3] is set to zero if there is ++** no ESCAPE clause. ++** + ** *pIsNocase is set to true if uppercase and lowercase are equivalent for + ** the function (default for LIKE). If the function makes the distinction + ** between uppercase and lowercase (as does GLOB) then *pIsNocase is set to +@@ -108012,17 +113879,26 @@ + */ + SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){ + FuncDef *pDef; +- if( pExpr->op!=TK_FUNCTION +- || !pExpr->x.pList +- || pExpr->x.pList->nExpr!=2 +- ){ ++ int nExpr; ++ if( pExpr->op!=TK_FUNCTION || !pExpr->x.pList ){ + return 0; + } + assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); +- pDef = sqlite3FindFunction(db, pExpr->u.zToken, 2, SQLITE_UTF8, 0); ++ nExpr = pExpr->x.pList->nExpr; ++ pDef = sqlite3FindFunction(db, pExpr->u.zToken, nExpr, SQLITE_UTF8, 0); + if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_FUNC_LIKE)==0 ){ + return 0; + } ++ if( nExpr<3 ){ ++ aWc[3] = 0; ++ }else{ ++ Expr *pEscape = pExpr->x.pList->a[2].pExpr; ++ char *zEscape; ++ if( pEscape->op!=TK_STRING ) return 0; ++ zEscape = pEscape->u.zToken; ++ if( zEscape[0]==0 || zEscape[1]!=0 ) return 0; ++ aWc[3] = zEscape[0]; ++ } + + /* The memcpy() statement assumes that the wildcard characters are + ** the first three statements in the compareInfo structure. The +@@ -108075,6 +113951,10 @@ + #ifdef SQLITE_DEBUG + FUNCTION2(affinity, 1, 0, 0, noopFunc, SQLITE_FUNC_AFFINITY), + #endif ++#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC ++ FUNCTION2(sqlite_offset, 1, 0, 0, noopFunc, SQLITE_FUNC_OFFSET| ++ SQLITE_FUNC_TYPEOF), ++#endif + FUNCTION(ltrim, 1, 1, 0, trimFunc ), + FUNCTION(ltrim, 2, 1, 0, trimFunc ), + FUNCTION(rtrim, 1, 2, 0, trimFunc ), +@@ -108083,11 +113963,11 @@ + FUNCTION(trim, 2, 3, 0, trimFunc ), + FUNCTION(min, -1, 0, 1, minmaxFunc ), + FUNCTION(min, 0, 0, 1, 0 ), +- AGGREGATE2(min, 1, 0, 1, minmaxStep, minMaxFinalize, ++ WAGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize, minMaxValue, 0, + SQLITE_FUNC_MINMAX ), + FUNCTION(max, -1, 1, 1, minmaxFunc ), + FUNCTION(max, 0, 1, 1, 0 ), +- AGGREGATE2(max, 1, 1, 1, minmaxStep, minMaxFinalize, ++ WAGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize, minMaxValue, 0, + SQLITE_FUNC_MINMAX ), + FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF), + FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH), +@@ -108118,14 +113998,17 @@ + FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ), + FUNCTION(substr, 2, 0, 0, substrFunc ), + FUNCTION(substr, 3, 0, 0, substrFunc ), +- AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ), +- AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ), +- AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ), +- AGGREGATE2(count, 0, 0, 0, countStep, countFinalize, +- SQLITE_FUNC_COUNT ), +- AGGREGATE(count, 1, 0, 0, countStep, countFinalize ), +- AGGREGATE(group_concat, 1, 0, 0, groupConcatStep, groupConcatFinalize), +- AGGREGATE(group_concat, 2, 0, 0, groupConcatStep, groupConcatFinalize), ++ WAGGREGATE(sum, 1,0,0, sumStep, sumFinalize, sumFinalize, sumInverse, 0), ++ WAGGREGATE(total, 1,0,0, sumStep,totalFinalize,totalFinalize,sumInverse, 0), ++ WAGGREGATE(avg, 1,0,0, sumStep, avgFinalize, avgFinalize, sumInverse, 0), ++ WAGGREGATE(count, 0,0,0, countStep, ++ countFinalize, countFinalize, countInverse, SQLITE_FUNC_COUNT ), ++ WAGGREGATE(count, 1,0,0, countStep, ++ countFinalize, countFinalize, countInverse, 0 ), ++ WAGGREGATE(group_concat, 1, 0, 0, groupConcatStep, ++ groupConcatFinalize, groupConcatValue, groupConcatInverse, 0), ++ WAGGREGATE(group_concat, 2, 0, 0, groupConcatStep, ++ groupConcatFinalize, groupConcatValue, groupConcatInverse, 0), + + LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), + #ifdef SQLITE_CASE_SENSITIVE_LIKE +@@ -108145,6 +114028,7 @@ + #ifndef SQLITE_OMIT_ALTERTABLE + sqlite3AlterFunctions(); + #endif ++ sqlite3WindowFunctions(); + #if defined(SQLITE_ENABLE_STAT3) || defined(SQLITE_ENABLE_STAT4) + sqlite3AnalyzeFunctions(); + #endif +@@ -108503,6 +114387,12 @@ + int iCur = pParse->nTab - 1; /* Cursor number to use */ + int iOk = sqlite3VdbeMakeLabel(v); /* jump here if parent key found */ + ++ sqlite3VdbeVerifyAbortable(v, ++ (!pFKey->isDeferred ++ && !(pParse->db->flags & SQLITE_DeferFKs) ++ && !pParse->pToplevel ++ && !pParse->isMultiWrite) ? OE_Abort : OE_Ignore); ++ + /* If nIncr is less than zero, then check at runtime if there are any + ** outstanding constraints to resolve. If there are not, there is no need + ** to check if deleting this row resolves any outstanding violations. +@@ -108668,7 +114558,7 @@ + ){ + Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0); + if( pExpr ){ +- pExpr->pTab = pTab; ++ pExpr->y.pTab = pTab; + pExpr->iTable = iCursor; + pExpr->iColumn = iCol; + } +@@ -108876,11 +114766,12 @@ + */ + SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){ + sqlite3 *db = pParse->db; +- if( (db->flags&SQLITE_ForeignKeys) && !IsVirtual(pTab) && !pTab->pSelect ){ ++ if( (db->flags&SQLITE_ForeignKeys) && !IsVirtual(pTab) ){ + int iSkip = 0; + Vdbe *v = sqlite3GetVdbe(pParse); + + assert( v ); /* VDBE has already been allocated */ ++ assert( pTab->pSelect==0 ); /* Not a view */ + if( sqlite3FkReferences(pTab)==0 ){ + /* Search for a deferred foreign key constraint for which this table + ** is the child table. If one cannot be found, return without +@@ -108897,7 +114788,7 @@ + } + + pParse->disableTriggers = 1; +- sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0); ++ sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0, 0, 0); + pParse->disableTriggers = 0; + + /* If the DELETE has generated immediate foreign key constraint +@@ -108910,6 +114801,7 @@ + ** constraints are violated. + */ + if( (db->flags & SQLITE_DeferFKs)==0 ){ ++ sqlite3VdbeVerifyAbortable(v, OE_Abort); + sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2); + VdbeCoverage(v); + sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, +@@ -109455,7 +115347,7 @@ + sqlite3ExprListAppend(pParse, 0, pRaise), + sqlite3SrcListAppend(db, 0, &tFrom, 0), + pWhere, +- 0, 0, 0, 0, 0, 0 ++ 0, 0, 0, 0, 0 + ); + pWhere = 0; + } +@@ -109742,7 +115634,8 @@ + }while( i>=0 && zColAff[i]==SQLITE_AFF_BLOB ); + pTab->zColAff = zColAff; + } +- i = sqlite3Strlen30(zColAff); ++ assert( zColAff!=0 ); ++ i = sqlite3Strlen30NN(zColAff); + if( i ){ + if( iReg ){ + sqlite3VdbeAddOp4(v, OP_Affinity, iReg, i, 0, zColAff, i); +@@ -109806,11 +115699,12 @@ + ** first use of table pTab. On 2nd and subsequent uses, the original + ** AutoincInfo structure is used. + ** +-** Three memory locations are allocated: ++** Four consecutive registers are allocated: + ** +-** (1) Register to hold the name of the pTab table. +-** (2) Register to hold the maximum ROWID of pTab. +-** (3) Register to hold the rowid in sqlite_sequence of pTab ++** (1) The name of the pTab table. ++** (2) The maximum ROWID of pTab. ++** (3) The rowid in sqlite_sequence of pTab ++** (4) The original value of the max ROWID in pTab, or NULL if none + ** + ** The 2nd register is the one that is returned. That is all the + ** insert routine needs to know about. +@@ -109821,12 +115715,27 @@ + Table *pTab /* The table we are writing to */ + ){ + int memId = 0; /* Register holding maximum rowid */ ++ assert( pParse->db->aDb[iDb].pSchema!=0 ); + if( (pTab->tabFlags & TF_Autoincrement)!=0 +- && (pParse->db->flags & SQLITE_Vacuum)==0 ++ && (pParse->db->mDbFlags & DBFLAG_Vacuum)==0 + ){ + Parse *pToplevel = sqlite3ParseToplevel(pParse); + AutoincInfo *pInfo; ++ Table *pSeqTab = pParse->db->aDb[iDb].pSchema->pSeqTab; + ++ /* Verify that the sqlite_sequence table exists and is an ordinary ++ ** rowid table with exactly two columns. ++ ** Ticket d8dc2b3a58cd5dc2918a1d4acb 2018-05-23 */ ++ if( pSeqTab==0 ++ || !HasRowid(pSeqTab) ++ || IsVirtual(pSeqTab) ++ || pSeqTab->nCol!=2 ++ ){ ++ pParse->nErr++; ++ pParse->rc = SQLITE_CORRUPT_SEQUENCE; ++ return 0; ++ } ++ + pInfo = pToplevel->pAinc; + while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; } + if( pInfo==0 ){ +@@ -109838,7 +115747,7 @@ + pInfo->iDb = iDb; + pToplevel->nMem++; /* Register to hold name of table */ + pInfo->regCtr = ++pToplevel->nMem; /* Max rowid register */ +- pToplevel->nMem++; /* Rowid in sqlite_sequence */ ++ pToplevel->nMem +=2; /* Rowid in sqlite_sequence + orig max val */ + } + memId = pInfo->regCtr; + } +@@ -109866,15 +115775,17 @@ + static const int iLn = VDBE_OFFSET_LINENO(2); + static const VdbeOpList autoInc[] = { + /* 0 */ {OP_Null, 0, 0, 0}, +- /* 1 */ {OP_Rewind, 0, 9, 0}, ++ /* 1 */ {OP_Rewind, 0, 10, 0}, + /* 2 */ {OP_Column, 0, 0, 0}, +- /* 3 */ {OP_Ne, 0, 7, 0}, ++ /* 3 */ {OP_Ne, 0, 9, 0}, + /* 4 */ {OP_Rowid, 0, 0, 0}, + /* 5 */ {OP_Column, 0, 1, 0}, +- /* 6 */ {OP_Goto, 0, 9, 0}, +- /* 7 */ {OP_Next, 0, 2, 0}, +- /* 8 */ {OP_Integer, 0, 0, 0}, +- /* 9 */ {OP_Close, 0, 0, 0} ++ /* 6 */ {OP_AddImm, 0, 0, 0}, ++ /* 7 */ {OP_Copy, 0, 0, 0}, ++ /* 8 */ {OP_Goto, 0, 11, 0}, ++ /* 9 */ {OP_Next, 0, 2, 0}, ++ /* 10 */ {OP_Integer, 0, 0, 0}, ++ /* 11 */ {OP_Close, 0, 0, 0} + }; + VdbeOp *aOp; + pDb = &db->aDb[p->iDb]; +@@ -109885,7 +115796,7 @@ + aOp = sqlite3VdbeAddOpList(v, ArraySize(autoInc), autoInc, iLn); + if( aOp==0 ) break; + aOp[0].p2 = memId; +- aOp[0].p3 = memId+1; ++ aOp[0].p3 = memId+2; + aOp[2].p3 = memId; + aOp[3].p1 = memId-1; + aOp[3].p3 = memId; +@@ -109892,7 +115803,10 @@ + aOp[3].p5 = SQLITE_JUMPIFNULL; + aOp[4].p2 = memId+1; + aOp[5].p3 = memId; +- aOp[8].p2 = memId; ++ aOp[6].p1 = memId; ++ aOp[7].p2 = memId+2; ++ aOp[7].p1 = memId; ++ aOp[10].p2 = memId; + } + } + +@@ -109939,6 +115853,8 @@ + + iRec = sqlite3GetTempReg(pParse); + assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); ++ sqlite3VdbeAddOp3(v, OP_Le, memId+2, sqlite3VdbeCurrentAddr(v)+7, memId); ++ VdbeCoverage(v); + sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); + aOp = sqlite3VdbeAddOpList(v, ArraySize(autoIncEnd), autoIncEnd, iLn); + if( aOp==0 ) break; +@@ -110076,11 +115992,11 @@ + SrcList *pTabList, /* Name of table into which we are inserting */ + Select *pSelect, /* A SELECT statement to use as the data source */ + IdList *pColumn, /* Column names corresponding to IDLIST. */ +- int onError /* How to handle constraint errors */ ++ int onError, /* How to handle constraint errors */ ++ Upsert *pUpsert /* ON CONFLICT clauses for upsert, or NULL */ + ){ + sqlite3 *db; /* The main database structure */ + Table *pTab; /* The table to insert into. aka TABLE */ +- char *zTab; /* Name of the table into which we are inserting */ + int i, j; /* Loop counters */ + Vdbe *v; /* Generate code into this virtual machine */ + Index *pIdx; /* For looping over indices of the table */ +@@ -110136,8 +116052,6 @@ + /* Locate the table into which we will be inserting new information. + */ + assert( pTabList->nSrc==1 ); +- zTab = pTabList->a[0].zName; +- if( NEVER(zTab==0) ) goto insert_cleanup; + pTab = sqlite3SrcListLookup(pParse, pTabList); + if( pTab==0 ){ + goto insert_cleanup; +@@ -110374,7 +116288,10 @@ + + /* Initialize the count of rows to be inserted + */ +- if( db->flags & SQLITE_CountRows ){ ++ if( (db->flags & SQLITE_CountRows)!=0 ++ && !pParse->nested ++ && !pParse->pTriggerTab ++ ){ + regRowCount = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); + } +@@ -110394,7 +116311,20 @@ + pParse->nMem += pIdx->nColumn; + } + } ++#ifndef SQLITE_OMIT_UPSERT ++ if( pUpsert ){ ++ pTabList->a[0].iCursor = iDataCur; ++ pUpsert->pUpsertSrc = pTabList; ++ pUpsert->regData = regData; ++ pUpsert->iDataCur = iDataCur; ++ pUpsert->iIdxCur = iIdxCur; ++ if( pUpsert->pUpsertTarget ){ ++ sqlite3UpsertAnalyzeTarget(pParse, pTabList, pUpsert); ++ } ++ } ++#endif + ++ + /* This is the top of the main insertion loop */ + if( useTempTable ){ + /* This block codes the top of loop only. The complete loop is the +@@ -110508,7 +116438,8 @@ + VdbeOp *pOp; + sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regRowid); + pOp = sqlite3VdbeGetOp(v, -1); +- if( ALWAYS(pOp) && pOp->opcode==OP_Null && !IsVirtual(pTab) ){ ++ assert( pOp!=0 ); ++ if( pOp->opcode==OP_Null && !IsVirtual(pTab) ){ + appendFlag = 1; + pOp->opcode = OP_NewRowid; + pOp->p1 = iDataCur; +@@ -110595,7 +116526,7 @@ + int isReplace; /* Set to true if constraints may cause a replace */ + int bUseSeek; /* True to use OPFLAG_SEEKRESULT */ + sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, +- regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0 ++ regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0, pUpsert + ); + sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0); + +@@ -110618,7 +116549,7 @@ + + /* Update the count of rows that are inserted + */ +- if( (db->flags & SQLITE_CountRows)!=0 ){ ++ if( regRowCount ){ + sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); + } + +@@ -110655,7 +116586,7 @@ + ** generating code because of a call to sqlite3NestedParse(), do not + ** invoke the callback function. + */ +- if( (db->flags&SQLITE_CountRows) && !pParse->nested && !pParse->pTriggerTab ){ ++ if( regRowCount ){ + sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC); +@@ -110664,6 +116595,7 @@ + insert_cleanup: + sqlite3SrcListDelete(db, pTabList); + sqlite3ExprListDelete(db, pList); ++ sqlite3UpsertDelete(db, pUpsert); + sqlite3SelectDelete(db, pSelect); + sqlite3IdListDelete(db, pColumn); + sqlite3DbFree(db, aRegIdx); +@@ -110683,14 +116615,15 @@ + #endif + + /* +-** Meanings of bits in of pWalker->eCode for checkConstraintUnchanged() ++** Meanings of bits in of pWalker->eCode for ++** sqlite3ExprReferencesUpdatedColumn() + */ + #define CKCNSTRNT_COLUMN 0x01 /* CHECK constraint uses a changing column */ + #define CKCNSTRNT_ROWID 0x02 /* CHECK constraint references the ROWID */ + +-/* This is the Walker callback from checkConstraintUnchanged(). Set +-** bit 0x01 of pWalker->eCode if +-** pWalker->eCode to 0 if this expression node references any of the ++/* This is the Walker callback from sqlite3ExprReferencesUpdatedColumn(). ++* Set bit 0x01 of pWalker->eCode if pWalker->eCode to 0 and if this ++** expression node references any of the + ** columns that are being modifed by an UPDATE statement. + */ + static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){ +@@ -110712,12 +116645,21 @@ + ** only columns that are modified by the UPDATE are those for which + ** aiChng[i]>=0, and also the ROWID is modified if chngRowid is true. + ** +-** Return true if CHECK constraint pExpr does not use any of the ++** Return true if CHECK constraint pExpr uses any of the + ** changing columns (or the rowid if it is changing). In other words, +-** return true if this CHECK constraint can be skipped when validating ++** return true if this CHECK constraint must be validated for + ** the new row in the UPDATE statement. ++** ++** 2018-09-15: pExpr might also be an expression for an index-on-expressions. ++** The operation of this routine is the same - return true if an only if ++** the expression uses one or more of columns identified by the second and ++** third arguments. + */ +-static int checkConstraintUnchanged(Expr *pExpr, int *aiChng, int chngRowid){ ++SQLITE_PRIVATE int sqlite3ExprReferencesUpdatedColumn( ++ Expr *pExpr, /* The expression to be checked */ ++ int *aiChng, /* aiChng[x]>=0 if column x changed by the UPDATE */ ++ int chngRowid /* True if UPDATE changes the rowid */ ++){ + Walker w; + memset(&w, 0, sizeof(w)); + w.eCode = 0; +@@ -110732,7 +116674,7 @@ + testcase( w.eCode==CKCNSTRNT_COLUMN ); + testcase( w.eCode==CKCNSTRNT_ROWID ); + testcase( w.eCode==(CKCNSTRNT_ROWID|CKCNSTRNT_COLUMN) ); +- return !w.eCode; ++ return w.eCode!=0; + } + + /* +@@ -110830,7 +116772,8 @@ + u8 overrideError, /* Override onError to this if not OE_Default */ + int ignoreDest, /* Jump to this label on an OE_Ignore resolution */ + int *pbMayReplace, /* OUT: Set to true if constraint may cause a replace */ +- int *aiChng /* column i is unchanged if aiChng[i]<0 */ ++ int *aiChng, /* column i is unchanged if aiChng[i]<0 */ ++ Upsert *pUpsert /* ON CONFLICT clauses, if any. NULL otherwise */ + ){ + Vdbe *v; /* VDBE under constrution */ + Index *pIdx; /* Pointer to one of the indices */ +@@ -110843,10 +116786,13 @@ + int addr1; /* Address of jump instruction */ + int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */ + int nPkField; /* Number of fields in PRIMARY KEY. 1 for ROWID tables */ +- int ipkTop = 0; /* Top of the rowid change constraint check */ +- int ipkBottom = 0; /* Bottom of the rowid change constraint check */ ++ Index *pUpIdx = 0; /* Index to which to apply the upsert */ + u8 isUpdate; /* True if this is an UPDATE operation */ + u8 bAffinityDone = 0; /* True if the OP_Affinity operation has been run */ ++ int upsertBypass = 0; /* Address of Goto to bypass upsert subroutine */ ++ int upsertJump = 0; /* Address of Goto that jumps into upsert subroutine */ ++ int ipkTop = 0; /* Top of the IPK uniqueness check */ ++ int ipkBottom = 0; /* OP_Goto at the end of the IPK uniqueness check */ + + isUpdate = regOldData!=0; + db = pParse->db; +@@ -110934,8 +116880,15 @@ + for(i=0; i<pCheck->nExpr; i++){ + int allOk; + Expr *pExpr = pCheck->a[i].pExpr; +- if( aiChng && checkConstraintUnchanged(pExpr, aiChng, pkChng) ) continue; ++ if( aiChng ++ && !sqlite3ExprReferencesUpdatedColumn(pExpr, aiChng, pkChng) ++ ){ ++ /* The check constraints do not reference any of the columns being ++ ** updated so there is no point it verifying the check constraint */ ++ continue; ++ } + allOk = sqlite3VdbeMakeLabel(v); ++ sqlite3VdbeVerifyAbortable(v, onError); + sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL); + if( onError==OE_Ignore ){ + sqlite3VdbeGoto(v, ignoreDest); +@@ -110953,6 +116906,50 @@ + } + #endif /* !defined(SQLITE_OMIT_CHECK) */ + ++ /* UNIQUE and PRIMARY KEY constraints should be handled in the following ++ ** order: ++ ** ++ ** (1) OE_Update ++ ** (2) OE_Abort, OE_Fail, OE_Rollback, OE_Ignore ++ ** (3) OE_Replace ++ ** ++ ** OE_Fail and OE_Ignore must happen before any changes are made. ++ ** OE_Update guarantees that only a single row will change, so it ++ ** must happen before OE_Replace. Technically, OE_Abort and OE_Rollback ++ ** could happen in any order, but they are grouped up front for ++ ** convenience. ++ ** ++ ** 2018-08-14: Ticket https://www.sqlite.org/src/info/908f001483982c43 ++ ** The order of constraints used to have OE_Update as (2) and OE_Abort ++ ** and so forth as (1). But apparently PostgreSQL checks the OE_Update ++ ** constraint before any others, so it had to be moved. ++ ** ++ ** Constraint checking code is generated in this order: ++ ** (A) The rowid constraint ++ ** (B) Unique index constraints that do not have OE_Replace as their ++ ** default conflict resolution strategy ++ ** (C) Unique index that do use OE_Replace by default. ++ ** ++ ** The ordering of (2) and (3) is accomplished by making sure the linked ++ ** list of indexes attached to a table puts all OE_Replace indexes last ++ ** in the list. See sqlite3CreateIndex() for where that happens. ++ */ ++ ++ if( pUpsert ){ ++ if( pUpsert->pUpsertTarget==0 ){ ++ /* An ON CONFLICT DO NOTHING clause, without a constraint-target. ++ ** Make all unique constraint resolution be OE_Ignore */ ++ assert( pUpsert->pUpsertSet==0 ); ++ overrideError = OE_Ignore; ++ pUpsert = 0; ++ }else if( (pUpIdx = pUpsert->pUpsertIdx)!=0 ){ ++ /* If the constraint-target uniqueness check must be run first. ++ ** Jump to that uniqueness check now */ ++ upsertJump = sqlite3VdbeAddOp0(v, OP_Goto); ++ VdbeComment((v, "UPSERT constraint goes first")); ++ } ++ } ++ + /* If rowid is changing, make sure the new rowid does not previously + ** exist in the table. + */ +@@ -110967,6 +116964,28 @@ + onError = OE_Abort; + } + ++ /* figure out whether or not upsert applies in this case */ ++ if( pUpsert && pUpsert->pUpsertIdx==0 ){ ++ if( pUpsert->pUpsertSet==0 ){ ++ onError = OE_Ignore; /* DO NOTHING is the same as INSERT OR IGNORE */ ++ }else{ ++ onError = OE_Update; /* DO UPDATE */ ++ } ++ } ++ ++ /* If the response to a rowid conflict is REPLACE but the response ++ ** to some other UNIQUE constraint is FAIL or IGNORE, then we need ++ ** to defer the running of the rowid conflict checking until after ++ ** the UNIQUE constraints have run. ++ */ ++ if( onError==OE_Replace /* IPK rule is REPLACE */ ++ && onError!=overrideError /* Rules for other contraints are different */ ++ && pTab->pIndex /* There exist other constraints */ ++ ){ ++ ipkTop = sqlite3VdbeAddOp0(v, OP_Goto)+1; ++ VdbeComment((v, "defer IPK REPLACE until last")); ++ } ++ + if( isUpdate ){ + /* pkChng!=0 does not mean that the rowid has changed, only that + ** it might have changed. Skip the conflict logic below if the rowid +@@ -110976,26 +116995,13 @@ + VdbeCoverage(v); + } + +- /* If the response to a rowid conflict is REPLACE but the response +- ** to some other UNIQUE constraint is FAIL or IGNORE, then we need +- ** to defer the running of the rowid conflict checking until after +- ** the UNIQUE constraints have run. +- */ +- if( onError==OE_Replace && overrideError!=OE_Replace ){ +- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ +- if( pIdx->onError==OE_Ignore || pIdx->onError==OE_Fail ){ +- ipkTop = sqlite3VdbeAddOp0(v, OP_Goto); +- break; +- } +- } +- } +- + /* Check to see if the new rowid already exists in the table. Skip + ** the following conflict logic if it does not. */ ++ VdbeNoopComment((v, "uniqueness check for ROWID")); ++ sqlite3VdbeVerifyAbortable(v, onError); + sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData); + VdbeCoverage(v); + +- /* Generate code that deals with a rowid collision */ + switch( onError ){ + default: { + onError = OE_Abort; +@@ -111004,6 +117010,9 @@ + case OE_Rollback: + case OE_Abort: + case OE_Fail: { ++ testcase( onError==OE_Rollback ); ++ testcase( onError==OE_Abort ); ++ testcase( onError==OE_Fail ); + sqlite3RowidConstraint(pParse, onError, pTab); + break; + } +@@ -111040,14 +117049,13 @@ + regNewData, 1, 0, OE_Replace, 1, -1); + }else{ + #ifdef SQLITE_ENABLE_PREUPDATE_HOOK +- if( HasRowid(pTab) ){ +- /* This OP_Delete opcode fires the pre-update-hook only. It does +- ** not modify the b-tree. It is more efficient to let the coming +- ** OP_Insert replace the existing entry than it is to delete the +- ** existing entry and then insert a new one. */ +- sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, OPFLAG_ISNOOP); +- sqlite3VdbeAppendP4(v, pTab, P4_TABLE); +- } ++ assert( HasRowid(pTab) ); ++ /* This OP_Delete opcode fires the pre-update-hook only. It does ++ ** not modify the b-tree. It is more efficient to let the coming ++ ** OP_Insert replace the existing entry than it is to delete the ++ ** existing entry and then insert a new one. */ ++ sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, OPFLAG_ISNOOP); ++ sqlite3VdbeAppendP4(v, pTab, P4_TABLE); + #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ + if( pTab->pIndex ){ + sqlite3MultiWrite(pParse); +@@ -111057,8 +117065,14 @@ + seenReplace = 1; + break; + } ++#ifndef SQLITE_OMIT_UPSERT ++ case OE_Update: { ++ sqlite3UpsertDoUpdate(pParse, pUpsert, pTab, 0, iDataCur); ++ /* Fall through */ ++ } ++#endif + case OE_Ignore: { +- /*assert( seenReplace==0 );*/ ++ testcase( onError==OE_Ignore ); + sqlite3VdbeGoto(v, ignoreDest); + break; + } +@@ -111066,7 +117080,7 @@ + sqlite3VdbeResolveLabel(v, addrRowidOk); + if( ipkTop ){ + ipkBottom = sqlite3VdbeAddOp0(v, OP_Goto); +- sqlite3VdbeJumpHere(v, ipkTop); ++ sqlite3VdbeJumpHere(v, ipkTop-1); + } + } + +@@ -111084,13 +117098,22 @@ + int addrUniqueOk; /* Jump here if the UNIQUE constraint is satisfied */ + + if( aRegIdx[ix]==0 ) continue; /* Skip indices that do not change */ +- if( bAffinityDone==0 ){ ++ if( pUpIdx==pIdx ){ ++ addrUniqueOk = upsertJump+1; ++ upsertBypass = sqlite3VdbeGoto(v, 0); ++ VdbeComment((v, "Skip upsert subroutine")); ++ sqlite3VdbeJumpHere(v, upsertJump); ++ }else{ ++ addrUniqueOk = sqlite3VdbeMakeLabel(v); ++ } ++ if( bAffinityDone==0 && (pUpIdx==0 || pUpIdx==pIdx) ){ + sqlite3TableAffinity(v, pTab, regNewData+1); + bAffinityDone = 1; + } ++ VdbeNoopComment((v, "uniqueness check for %s", pIdx->zName)); + iThisCur = iIdxCur+ix; +- addrUniqueOk = sqlite3VdbeMakeLabel(v); + ++ + /* Skip partial indices for which the WHERE clause is not true */ + if( pIdx->pPartIdxWhere ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[ix]); +@@ -111149,6 +117172,15 @@ + onError = OE_Abort; + } + ++ /* Figure out if the upsert clause applies to this index */ ++ if( pUpIdx==pIdx ){ ++ if( pUpsert->pUpsertSet==0 ){ ++ onError = OE_Ignore; /* DO NOTHING is the same as INSERT OR IGNORE */ ++ }else{ ++ onError = OE_Update; /* DO UPDATE */ ++ } ++ } ++ + /* Collision detection may be omitted if all of the following are true: + ** (1) The conflict resolution algorithm is REPLACE + ** (2) The table is a WITHOUT ROWID table +@@ -111169,6 +117201,7 @@ + } + + /* Check to see if the new index entry will be unique */ ++ sqlite3VdbeVerifyAbortable(v, onError); + sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk, + regIdx, pIdx->nKeyCol); VdbeCoverage(v); + +@@ -111230,15 +117263,25 @@ + + /* Generate code that executes if the new index entry is not unique */ + assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail +- || onError==OE_Ignore || onError==OE_Replace ); ++ || onError==OE_Ignore || onError==OE_Replace || onError==OE_Update ); + switch( onError ){ + case OE_Rollback: + case OE_Abort: + case OE_Fail: { ++ testcase( onError==OE_Rollback ); ++ testcase( onError==OE_Abort ); ++ testcase( onError==OE_Fail ); + sqlite3UniqueConstraint(pParse, onError, pIdx); + break; + } ++#ifndef SQLITE_OMIT_UPSERT ++ case OE_Update: { ++ sqlite3UpsertDoUpdate(pParse, pUpsert, pTab, pIdx, iIdxCur+ix); ++ /* Fall through */ ++ } ++#endif + case OE_Ignore: { ++ testcase( onError==OE_Ignore ); + sqlite3VdbeGoto(v, ignoreDest); + break; + } +@@ -111245,10 +117288,12 @@ + default: { + Trigger *pTrigger = 0; + assert( onError==OE_Replace ); +- sqlite3MultiWrite(pParse); + if( db->flags&SQLITE_RecTriggers ){ + pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); + } ++ if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){ ++ sqlite3MultiWrite(pParse); ++ } + sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, + regR, nPkField, 0, OE_Replace, + (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur); +@@ -111256,14 +117301,22 @@ + break; + } + } +- sqlite3VdbeResolveLabel(v, addrUniqueOk); ++ if( pUpIdx==pIdx ){ ++ sqlite3VdbeGoto(v, upsertJump+1); ++ sqlite3VdbeJumpHere(v, upsertBypass); ++ }else{ ++ sqlite3VdbeResolveLabel(v, addrUniqueOk); ++ } + if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField); + } ++ ++ /* If the IPK constraint is a REPLACE, run it last */ + if( ipkTop ){ + sqlite3VdbeGoto(v, ipkTop+1); ++ VdbeComment((v, "Do IPK REPLACE")); + sqlite3VdbeJumpHere(v, ipkBottom); + } +- ++ + *pbMayReplace = seenReplace; + VdbeModuleComment((v, "END: GenCnstCks(%d)", seenReplace)); + } +@@ -111359,7 +117412,6 @@ + sqlite3SetMakeRecordP5(v, pTab); + if( !bAffinityDone ){ + sqlite3TableAffinity(v, pTab, 0); +- sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol); + } + if( pParse->nested ){ + pik_flags = 0; +@@ -111605,7 +117657,6 @@ + if( pSelect->pLimit ){ + return 0; /* SELECT may not have a LIMIT clause */ + } +- assert( pSelect->pOffset==0 ); /* Must be so if pLimit==0 */ + if( pSelect->pPrior ){ + return 0; /* SELECT may not be a compound query */ + } +@@ -111655,7 +117706,7 @@ + Column *pDestCol = &pDest->aCol[i]; + Column *pSrcCol = &pSrc->aCol[i]; + #ifdef SQLITE_ENABLE_HIDDEN_COLUMNS +- if( (db->flags & SQLITE_Vacuum)==0 ++ if( (db->mDbFlags & DBFLAG_Vacuum)==0 + && (pDestCol->colFlags | pSrcCol->colFlags) & COLFLAG_HIDDEN + ){ + return 0; /* Neither table may have __hidden__ columns */ +@@ -111731,7 +117782,7 @@ + regRowid = sqlite3GetTempReg(pParse); + sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite); + assert( HasRowid(pDest) || destHasUniqueIdx ); +- if( (db->flags & SQLITE_Vacuum)==0 && ( ++ if( (db->mDbFlags & DBFLAG_Vacuum)==0 && ( + (pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */ + || destHasUniqueIdx /* (2) */ + || (onError!=OE_Abort && onError!=OE_Rollback) /* (3) */ +@@ -111738,8 +117789,8 @@ + )){ + /* In some circumstances, we are able to run the xfer optimization + ** only if the destination table is initially empty. Unless the +- ** SQLITE_Vacuum flag is set, this block generates code to make +- ** that determination. If SQLITE_Vacuum is set, then the destination ++ ** DBFLAG_Vacuum flag is set, this block generates code to make ++ ** that determination. If DBFLAG_Vacuum is set, then the destination + ** table is always empty. + ** + ** Conditions under which the destination must be empty: +@@ -111763,6 +117814,7 @@ + emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); + if( pDest->iPKey>=0 ){ + addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); ++ sqlite3VdbeVerifyAbortable(v, onError); + addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid); + VdbeCoverage(v); + sqlite3RowidConstraint(pParse, onError, pDest); +@@ -111775,8 +117827,8 @@ + assert( (pDest->tabFlags & TF_Autoincrement)==0 ); + } + sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1); +- if( db->flags & SQLITE_Vacuum ){ +- sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1); ++ if( db->mDbFlags & DBFLAG_Vacuum ){ ++ sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest); + insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID| + OPFLAG_APPEND|OPFLAG_USESEEKRESULT; + }else{ +@@ -111807,13 +117859,13 @@ + VdbeComment((v, "%s", pDestIdx->zName)); + addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); + sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1); +- if( db->flags & SQLITE_Vacuum ){ ++ if( db->mDbFlags & DBFLAG_Vacuum ){ + /* This INSERT command is part of a VACUUM operation, which guarantees + ** that the destination table is empty. If all indexed columns use + ** collation sequence BINARY, then it can also be assumed that the + ** index will be populated by inserting keys in strictly sorted + ** order. In this case, instead of seeking within the b-tree as part +- ** of every OP_IdxInsert opcode, an OP_Last is added before the ++ ** of every OP_IdxInsert opcode, an OP_SeekEnd is added before the + ** OP_IdxInsert to seek to the point within the b-tree where each key + ** should be inserted. This is faster. + ** +@@ -111828,7 +117880,7 @@ + } + if( i==pSrcIdx->nColumn ){ + idxInsFlags = OPFLAG_USESEEKRESULT; +- sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1); ++ sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest); + } + } + if( !HasRowid(pSrc) && pDestIdx->idxType==2 ){ +@@ -112159,7 +118211,7 @@ + int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*, + const char*,const char*),void*); + void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*)); +- char * (*snprintf)(int,char*,const char*,...); ++ char * (*xsnprintf)(int,char*,const char*,...); + int (*step)(sqlite3_stmt*); + int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*, + char const**,char const**,int*,int*,int*); +@@ -112271,7 +118323,7 @@ + int (*uri_boolean)(const char*,const char*,int); + sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64); + const char *(*uri_parameter)(const char*,const char*); +- char *(*vsnprintf)(int,char*,const char*,va_list); ++ char *(*xvsnprintf)(int,char*,const char*,va_list); + int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*); + /* Version 3.8.7 and later */ + int (*auto_extension)(void(*)(void)); +@@ -112317,6 +118369,33 @@ + int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*)); + void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*)); + void *(*value_pointer)(sqlite3_value*,const char*); ++ int (*vtab_nochange)(sqlite3_context*); ++ int (*value_nochange)(sqlite3_value*); ++ const char *(*vtab_collation)(sqlite3_index_info*,int); ++ /* Version 3.24.0 and later */ ++ int (*keyword_count)(void); ++ int (*keyword_name)(int,const char**,int*); ++ int (*keyword_check)(const char*,int); ++ sqlite3_str *(*str_new)(sqlite3*); ++ char *(*str_finish)(sqlite3_str*); ++ void (*str_appendf)(sqlite3_str*, const char *zFormat, ...); ++ void (*str_vappendf)(sqlite3_str*, const char *zFormat, va_list); ++ void (*str_append)(sqlite3_str*, const char *zIn, int N); ++ void (*str_appendall)(sqlite3_str*, const char *zIn); ++ void (*str_appendchar)(sqlite3_str*, int N, char C); ++ void (*str_reset)(sqlite3_str*); ++ int (*str_errcode)(sqlite3_str*); ++ int (*str_length)(sqlite3_str*); ++ char *(*str_value)(sqlite3_str*); ++ /* Version 3.25.0 and later */ ++ int (*create_window_function)(sqlite3*,const char*,int,int,void*, ++ void (*xStep)(sqlite3_context*,int,sqlite3_value**), ++ void (*xFinal)(sqlite3_context*), ++ void (*xValue)(sqlite3_context*), ++ void (*xInv)(sqlite3_context*,int,sqlite3_value**), ++ void(*xDestroy)(void*)); ++ /* Version 3.26.0 and later */ ++ const char *(*normalized_sql)(sqlite3_stmt*); + }; + + /* +@@ -112443,7 +118522,7 @@ + #define sqlite3_rollback_hook sqlite3_api->rollback_hook + #define sqlite3_set_authorizer sqlite3_api->set_authorizer + #define sqlite3_set_auxdata sqlite3_api->set_auxdata +-#define sqlite3_snprintf sqlite3_api->snprintf ++#define sqlite3_snprintf sqlite3_api->xsnprintf + #define sqlite3_step sqlite3_api->step + #define sqlite3_table_column_metadata sqlite3_api->table_column_metadata + #define sqlite3_thread_cleanup sqlite3_api->thread_cleanup +@@ -112467,7 +118546,7 @@ + #define sqlite3_value_text16le sqlite3_api->value_text16le + #define sqlite3_value_type sqlite3_api->value_type + #define sqlite3_vmprintf sqlite3_api->vmprintf +-#define sqlite3_vsnprintf sqlite3_api->vsnprintf ++#define sqlite3_vsnprintf sqlite3_api->xvsnprintf + #define sqlite3_overload_function sqlite3_api->overload_function + #define sqlite3_prepare_v2 sqlite3_api->prepare_v2 + #define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 +@@ -112543,7 +118622,7 @@ + #define sqlite3_uri_boolean sqlite3_api->uri_boolean + #define sqlite3_uri_int64 sqlite3_api->uri_int64 + #define sqlite3_uri_parameter sqlite3_api->uri_parameter +-#define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf ++#define sqlite3_uri_vsnprintf sqlite3_api->xvsnprintf + #define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2 + /* Version 3.8.7 and later */ + #define sqlite3_auto_extension sqlite3_api->auto_extension +@@ -112583,6 +118662,29 @@ + #define sqlite3_bind_pointer sqlite3_api->bind_pointer + #define sqlite3_result_pointer sqlite3_api->result_pointer + #define sqlite3_value_pointer sqlite3_api->value_pointer ++/* Version 3.22.0 and later */ ++#define sqlite3_vtab_nochange sqlite3_api->vtab_nochange ++#define sqlite3_value_nochange sqlite3_api->value_nochange ++#define sqlite3_vtab_collation sqlite3_api->vtab_collation ++/* Version 3.24.0 and later */ ++#define sqlite3_keyword_count sqlite3_api->keyword_count ++#define sqlite3_keyword_name sqlite3_api->keyword_name ++#define sqlite3_keyword_check sqlite3_api->keyword_check ++#define sqlite3_str_new sqlite3_api->str_new ++#define sqlite3_str_finish sqlite3_api->str_finish ++#define sqlite3_str_appendf sqlite3_api->str_appendf ++#define sqlite3_str_vappendf sqlite3_api->str_vappendf ++#define sqlite3_str_append sqlite3_api->str_append ++#define sqlite3_str_appendall sqlite3_api->str_appendall ++#define sqlite3_str_appendchar sqlite3_api->str_appendchar ++#define sqlite3_str_reset sqlite3_api->str_reset ++#define sqlite3_str_errcode sqlite3_api->str_errcode ++#define sqlite3_str_length sqlite3_api->str_length ++#define sqlite3_str_value sqlite3_api->str_value ++/* Version 3.25.0 and later */ ++#define sqlite3_create_window_function sqlite3_api->create_window_function ++/* Version 3.26.0 and later */ ++#define sqlite3_normalized_sql sqlite3_api->normalized_sql + #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ + + #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) +@@ -112671,6 +118773,7 @@ + # define sqlite3_declare_vtab 0 + # define sqlite3_vtab_config 0 + # define sqlite3_vtab_on_conflict 0 ++# define sqlite3_vtab_collation 0 + #endif + + #ifdef SQLITE_OMIT_SHARED_CACHE +@@ -113017,7 +119120,34 @@ + sqlite3_prepare16_v3, + sqlite3_bind_pointer, + sqlite3_result_pointer, +- sqlite3_value_pointer ++ sqlite3_value_pointer, ++ /* Version 3.22.0 and later */ ++ sqlite3_vtab_nochange, ++ sqlite3_value_nochange, ++ sqlite3_vtab_collation, ++ /* Version 3.24.0 and later */ ++ sqlite3_keyword_count, ++ sqlite3_keyword_name, ++ sqlite3_keyword_check, ++ sqlite3_str_new, ++ sqlite3_str_finish, ++ sqlite3_str_appendf, ++ sqlite3_str_vappendf, ++ sqlite3_str_append, ++ sqlite3_str_appendall, ++ sqlite3_str_appendchar, ++ sqlite3_str_reset, ++ sqlite3_str_errcode, ++ sqlite3_str_length, ++ sqlite3_str_value, ++ /* Version 3.25.0 and later */ ++ sqlite3_create_window_function, ++ /* Version 3.26.0 and later */ ++#ifdef SQLITE_ENABLE_NORMALIZE ++ sqlite3_normalized_sql ++#else ++ 0 ++#endif + }; + + /* +@@ -113467,10 +119597,9 @@ + #define PragTyp_ACTIVATE_EXTENSIONS 40 + #define PragTyp_HEXKEY 41 + #define PragTyp_KEY 42 +-#define PragTyp_REKEY 43 +-#define PragTyp_LOCK_STATUS 44 +-#define PragTyp_PARSER_TRACE 45 +-#define PragTyp_STATS 46 ++#define PragTyp_LOCK_STATUS 43 ++#define PragTyp_PARSER_TRACE 44 ++#define PragTyp_STATS 45 + + /* Property flags associated with various pragma. */ + #define PragFlg_NeedSchema 0x01 /* Force schema load before running */ +@@ -113487,21 +119616,22 @@ + ** result column is different from the name of the pragma + */ + static const char *const pragCName[] = { +- /* 0 */ "cache_size", /* Used by: default_cache_size */ +- /* 1 */ "cid", /* Used by: table_info */ +- /* 2 */ "name", +- /* 3 */ "type", +- /* 4 */ "notnull", +- /* 5 */ "dflt_value", +- /* 6 */ "pk", +- /* 7 */ "tbl", /* Used by: stats */ +- /* 8 */ "idx", +- /* 9 */ "wdth", +- /* 10 */ "hght", +- /* 11 */ "flgs", +- /* 12 */ "seqno", /* Used by: index_info */ +- /* 13 */ "cid", +- /* 14 */ "name", ++ /* 0 */ "id", /* Used by: foreign_key_list */ ++ /* 1 */ "seq", ++ /* 2 */ "table", ++ /* 3 */ "from", ++ /* 4 */ "to", ++ /* 5 */ "on_update", ++ /* 6 */ "on_delete", ++ /* 7 */ "match", ++ /* 8 */ "cid", /* Used by: table_xinfo */ ++ /* 9 */ "name", ++ /* 10 */ "type", ++ /* 11 */ "notnull", ++ /* 12 */ "dflt_value", ++ /* 13 */ "pk", ++ /* 14 */ "hidden", ++ /* table_info reuses 8 */ + /* 15 */ "seqno", /* Used by: index_xinfo */ + /* 16 */ "cid", + /* 17 */ "name", +@@ -113508,37 +119638,35 @@ + /* 18 */ "desc", + /* 19 */ "coll", + /* 20 */ "key", +- /* 21 */ "seq", /* Used by: index_list */ +- /* 22 */ "name", +- /* 23 */ "unique", +- /* 24 */ "origin", +- /* 25 */ "partial", +- /* 26 */ "seq", /* Used by: database_list */ ++ /* 21 */ "tbl", /* Used by: stats */ ++ /* 22 */ "idx", ++ /* 23 */ "wdth", ++ /* 24 */ "hght", ++ /* 25 */ "flgs", ++ /* 26 */ "seq", /* Used by: index_list */ + /* 27 */ "name", +- /* 28 */ "file", +- /* 29 */ "name", /* Used by: function_list */ +- /* 30 */ "builtin", +- /* 31 */ "name", /* Used by: module_list pragma_list */ +- /* 32 */ "seq", /* Used by: collation_list */ +- /* 33 */ "name", +- /* 34 */ "id", /* Used by: foreign_key_list */ +- /* 35 */ "seq", +- /* 36 */ "table", +- /* 37 */ "from", +- /* 38 */ "to", +- /* 39 */ "on_update", +- /* 40 */ "on_delete", +- /* 41 */ "match", +- /* 42 */ "table", /* Used by: foreign_key_check */ +- /* 43 */ "rowid", +- /* 44 */ "parent", +- /* 45 */ "fkid", +- /* 46 */ "busy", /* Used by: wal_checkpoint */ +- /* 47 */ "log", +- /* 48 */ "checkpointed", +- /* 49 */ "timeout", /* Used by: busy_timeout */ +- /* 50 */ "database", /* Used by: lock_status */ +- /* 51 */ "status", ++ /* 28 */ "unique", ++ /* 29 */ "origin", ++ /* 30 */ "partial", ++ /* 31 */ "table", /* Used by: foreign_key_check */ ++ /* 32 */ "rowid", ++ /* 33 */ "parent", ++ /* 34 */ "fkid", ++ /* index_info reuses 15 */ ++ /* 35 */ "seq", /* Used by: database_list */ ++ /* 36 */ "name", ++ /* 37 */ "file", ++ /* 38 */ "busy", /* Used by: wal_checkpoint */ ++ /* 39 */ "log", ++ /* 40 */ "checkpointed", ++ /* 41 */ "name", /* Used by: function_list */ ++ /* 42 */ "builtin", ++ /* collation_list reuses 26 */ ++ /* 43 */ "database", /* Used by: lock_status */ ++ /* 44 */ "status", ++ /* 45 */ "cache_size", /* Used by: default_cache_size */ ++ /* module_list pragma_list reuses 9 */ ++ /* 46 */ "timeout", /* Used by: busy_timeout */ + }; + + /* Definitions of all built-in pragmas */ +@@ -113548,7 +119676,7 @@ + u8 mPragFlg; /* Zero or more PragFlg_XXX values */ + u8 iPragCName; /* Start of column names in pragCName[] */ + u8 nPragCName; /* Num of col names. 0 means use pragma name */ +- u32 iArg; /* Extra argument */ ++ u64 iArg; /* Extra argument */ + } PragmaName; + static const PragmaName aPragmaName[] = { + #if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) +@@ -113584,7 +119712,7 @@ + {/* zName: */ "busy_timeout", + /* ePragTyp: */ PragTyp_BUSY_TIMEOUT, + /* ePragFlg: */ PragFlg_Result0, +- /* ColNames: */ 49, 1, ++ /* ColNames: */ 46, 1, + /* iArg: */ 0 }, + #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) + {/* zName: */ "cache_size", +@@ -113621,7 +119749,7 @@ + {/* zName: */ "collation_list", + /* ePragTyp: */ PragTyp_COLLATION_LIST, + /* ePragFlg: */ PragFlg_Result0, +- /* ColNames: */ 32, 2, ++ /* ColNames: */ 26, 2, + /* iArg: */ 0 }, + #endif + #if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS) +@@ -113656,7 +119784,7 @@ + {/* zName: */ "database_list", + /* ePragTyp: */ PragTyp_DATABASE_LIST, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0, +- /* ColNames: */ 26, 3, ++ /* ColNames: */ 35, 3, + /* iArg: */ 0 }, + #endif + #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) +@@ -113663,7 +119791,7 @@ + {/* zName: */ "default_cache_size", + /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, +- /* ColNames: */ 0, 1, ++ /* ColNames: */ 45, 1, + /* iArg: */ 0 }, + #endif + #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) +@@ -113693,7 +119821,7 @@ + {/* zName: */ "foreign_key_check", + /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0, +- /* ColNames: */ 42, 4, ++ /* ColNames: */ 31, 4, + /* iArg: */ 0 }, + #endif + #if !defined(SQLITE_OMIT_FOREIGN_KEY) +@@ -113700,7 +119828,7 @@ + {/* zName: */ "foreign_key_list", + /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, +- /* ColNames: */ 34, 8, ++ /* ColNames: */ 0, 8, + /* iArg: */ 0 }, + #endif + #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) +@@ -113736,7 +119864,7 @@ + {/* zName: */ "function_list", + /* ePragTyp: */ PragTyp_FUNCTION_LIST, + /* ePragFlg: */ PragFlg_Result0, +- /* ColNames: */ 29, 2, ++ /* ColNames: */ 41, 2, + /* iArg: */ 0 }, + #endif + #endif +@@ -113745,12 +119873,12 @@ + /* ePragTyp: */ PragTyp_HEXKEY, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, +- /* iArg: */ 0 }, ++ /* iArg: */ 2 }, + {/* zName: */ "hexrekey", + /* ePragTyp: */ PragTyp_HEXKEY, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, +- /* iArg: */ 0 }, ++ /* iArg: */ 3 }, + #endif + #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + #if !defined(SQLITE_OMIT_CHECK) +@@ -113772,12 +119900,12 @@ + {/* zName: */ "index_info", + /* ePragTyp: */ PragTyp_INDEX_INFO, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, +- /* ColNames: */ 12, 3, ++ /* ColNames: */ 15, 3, + /* iArg: */ 0 }, + {/* zName: */ "index_list", + /* ePragTyp: */ PragTyp_INDEX_LIST, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, +- /* ColNames: */ 21, 5, ++ /* ColNames: */ 26, 5, + /* iArg: */ 0 }, + {/* zName: */ "index_xinfo", + /* ePragTyp: */ PragTyp_INDEX_INFO, +@@ -113812,6 +119940,11 @@ + /* iArg: */ 0 }, + #endif + #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) ++ {/* zName: */ "legacy_alter_table", ++ /* ePragTyp: */ PragTyp_FLAG, ++ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, ++ /* ColNames: */ 0, 0, ++ /* iArg: */ SQLITE_LegacyAlter }, + {/* zName: */ "legacy_file_format", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, +@@ -113829,7 +119962,7 @@ + {/* zName: */ "lock_status", + /* ePragTyp: */ PragTyp_LOCK_STATUS, + /* ePragFlg: */ PragFlg_Result0, +- /* ColNames: */ 50, 2, ++ /* ColNames: */ 43, 2, + /* iArg: */ 0 }, + #endif + #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) +@@ -113855,7 +119988,7 @@ + {/* zName: */ "module_list", + /* ePragTyp: */ PragTyp_MODULE_LIST, + /* ePragFlg: */ PragFlg_Result0, +- /* ColNames: */ 31, 1, ++ /* ColNames: */ 9, 1, + /* iArg: */ 0 }, + #endif + #endif +@@ -113888,7 +120021,7 @@ + {/* zName: */ "pragma_list", + /* ePragTyp: */ PragTyp_PRAGMA_LIST, + /* ePragFlg: */ PragFlg_Result0, +- /* ColNames: */ 31, 1, ++ /* ColNames: */ 9, 1, + /* iArg: */ 0 }, + #endif + #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) +@@ -113919,10 +120052,10 @@ + #endif + #if defined(SQLITE_HAS_CODEC) + {/* zName: */ "rekey", +- /* ePragTyp: */ PragTyp_REKEY, ++ /* ePragTyp: */ PragTyp_KEY, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, +- /* iArg: */ 0 }, ++ /* iArg: */ 1 }, + #endif + #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + {/* zName: */ "reverse_unordered_selects", +@@ -113975,7 +120108,7 @@ + {/* zName: */ "stats", + /* ePragTyp: */ PragTyp_STATS, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, +- /* ColNames: */ 7, 5, ++ /* ColNames: */ 21, 5, + /* iArg: */ 0 }, + #endif + #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) +@@ -113989,8 +120122,13 @@ + {/* zName: */ "table_info", + /* ePragTyp: */ PragTyp_TABLE_INFO, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, +- /* ColNames: */ 1, 6, ++ /* ColNames: */ 8, 6, + /* iArg: */ 0 }, ++ {/* zName: */ "table_xinfo", ++ /* ePragTyp: */ PragTyp_TABLE_INFO, ++ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, ++ /* ColNames: */ 8, 7, ++ /* iArg: */ 1 }, + #endif + #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) + {/* zName: */ "temp_store", +@@ -114004,6 +120142,18 @@ + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, + #endif ++#if defined(SQLITE_HAS_CODEC) ++ {/* zName: */ "textkey", ++ /* ePragTyp: */ PragTyp_KEY, ++ /* ePragFlg: */ 0, ++ /* ColNames: */ 0, 0, ++ /* iArg: */ 4 }, ++ {/* zName: */ "textrekey", ++ /* ePragTyp: */ PragTyp_KEY, ++ /* ePragFlg: */ 0, ++ /* ColNames: */ 0, 0, ++ /* iArg: */ 5 }, ++#endif + {/* zName: */ "threads", + /* ePragTyp: */ PragTyp_THREADS, + /* ePragFlg: */ PragFlg_Result0, +@@ -114054,7 +120204,7 @@ + {/* zName: */ "wal_checkpoint", + /* ePragTyp: */ PragTyp_WAL_CHECKPOINT, + /* ePragFlg: */ PragFlg_NeedSchema, +- /* ColNames: */ 46, 3, ++ /* ColNames: */ 38, 3, + /* iArg: */ 0 }, + #endif + #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) +@@ -114062,10 +120212,10 @@ + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, + /* ColNames: */ 0, 0, +- /* iArg: */ SQLITE_WriteSchema }, ++ /* iArg: */ SQLITE_WriteSchema|SQLITE_NoSchemaError }, + #endif + }; +-/* Number of pragmas: 60 on by default, 77 total. */ ++/* Number of pragmas: 62 on by default, 81 total. */ + + /************** End of pragma.h **********************************************/ + /************** Continuing where we left off in pragma.c *********************/ +@@ -114338,16 +120488,16 @@ + /* + ** Helper subroutine for PRAGMA integrity_check: + ** +-** Generate code to output a single-column result row with the result +-** held in register regResult. Decrement the result count and halt if +-** the maximum number of result rows have been issued. ++** Generate code to output a single-column result row with a value of the ++** string held in register 3. Decrement the result count in register 1 ++** and halt if the maximum number of result rows have been issued. + */ +-static int integrityCheckResultRow(Vdbe *v, int regResult){ ++static int integrityCheckResultRow(Vdbe *v){ + int addr; +- sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 1); ++ sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1); + addr = sqlite3VdbeAddOp3(v, OP_IfPos, 1, sqlite3VdbeCurrentAddr(v)+2, 1); + VdbeCoverage(v); +- sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); ++ sqlite3VdbeAddOp0(v, OP_Halt); + return addr; + } + +@@ -115077,7 +121227,7 @@ + setPragmaResultColumnNames(v, pPragma); + returnSingleInt(v, (db->flags & pPragma->iArg)!=0 ); + }else{ +- int mask = pPragma->iArg; /* Mask of bits to set or clear. */ ++ u64 mask = pPragma->iArg; /* Mask of bits to set or clear. */ + if( db->autoCommit==0 ){ + /* Foreign key support may not be enabled or disabled while not + ** in auto-commit mode. */ +@@ -115120,20 +121270,23 @@ + ** type: Column declaration type. + ** notnull: True if 'NOT NULL' is part of column declaration + ** dflt_value: The default value for the column, if any. ++ ** pk: Non-zero for PK fields. + */ + case PragTyp_TABLE_INFO: if( zRight ){ + Table *pTab; + pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb); + if( pTab ){ ++ int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); + int i, k; + int nHidden = 0; + Column *pCol; + Index *pPk = sqlite3PrimaryKeyIndex(pTab); +- pParse->nMem = 6; +- sqlite3CodeVerifySchema(pParse, iDb); ++ pParse->nMem = 7; ++ sqlite3CodeVerifySchema(pParse, iTabDb); + sqlite3ViewGetColumnNames(pParse, pTab); + for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){ +- if( IsHiddenColumn(pCol) ){ ++ int isHidden = IsHiddenColumn(pCol); ++ if( isHidden && pPragma->iArg==0 ){ + nHidden++; + continue; + } +@@ -115145,13 +121298,14 @@ + for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){} + } + assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN ); +- sqlite3VdbeMultiLoad(v, 1, "issisi", ++ sqlite3VdbeMultiLoad(v, 1, pPragma->iArg ? "issisii" : "issisi", + i-nHidden, + pCol->zName, + sqlite3ColumnType(pCol,""), + pCol->notNull ? 1 : 0, + pCol->pDflt ? pCol->pDflt->u.zToken : 0, +- k); ++ k, ++ isHidden); + } + } + } +@@ -115189,6 +121343,7 @@ + Table *pTab; + pIdx = sqlite3FindIndex(db, zRight, zDb); + if( pIdx ){ ++ int iIdxDb = sqlite3SchemaToIndex(db, pIdx->pSchema); + int i; + int mx; + if( pPragma->iArg ){ +@@ -115201,7 +121356,7 @@ + pParse->nMem = 3; + } + pTab = pIdx->pTable; +- sqlite3CodeVerifySchema(pParse, iDb); ++ sqlite3CodeVerifySchema(pParse, iIdxDb); + assert( pParse->nMem<=pPragma->nPragCName ); + for(i=0; i<mx; i++){ + i16 cnum = pIdx->aiColumn[i]; +@@ -115225,8 +121380,9 @@ + int i; + pTab = sqlite3FindTable(db, zRight, zDb); + if( pTab ){ ++ int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); + pParse->nMem = 5; +- sqlite3CodeVerifySchema(pParse, iDb); ++ sqlite3CodeVerifySchema(pParse, iTabDb); + for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){ + const char *azOrigin[] = { "c", "u", "pk" }; + sqlite3VdbeMultiLoad(v, 1, "isisi", +@@ -115273,14 +121429,13 @@ + pParse->nMem = 2; + for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){ + for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash ){ ++ if( p->funcFlags & SQLITE_FUNC_INTERNAL ) continue; + sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 1); +- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); + } + } + for(j=sqliteHashFirst(&db->aFunc); j; j=sqliteHashNext(j)){ + p = (FuncDef*)sqliteHashData(j); + sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 0); +- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); + } + } + break; +@@ -115292,7 +121447,6 @@ + for(j=sqliteHashFirst(&db->aModule); j; j=sqliteHashNext(j)){ + Module *pMod = (Module*)sqliteHashData(j); + sqlite3VdbeMultiLoad(v, 1, "s", pMod->zName); +- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); + } + } + break; +@@ -115302,7 +121456,6 @@ + int i; + for(i=0; i<ArraySize(aPragmaName); i++){ + sqlite3VdbeMultiLoad(v, 1, "s", aPragmaName[i].zName); +- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); + } + } + break; +@@ -115318,9 +121471,10 @@ + if( pTab ){ + pFK = pTab->pFKey; + if( pFK ){ ++ int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); + int i = 0; + pParse->nMem = 8; +- sqlite3CodeVerifySchema(pParse, iDb); ++ sqlite3CodeVerifySchema(pParse, iTabDb); + while(pFK){ + int j; + for(j=0; j<pFK->nCol; j++){ +@@ -115365,9 +121519,9 @@ + pParse->nMem += 4; + regKey = ++pParse->nMem; + regRow = ++pParse->nMem; +- sqlite3CodeVerifySchema(pParse, iDb); + k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash); + while( k ){ ++ int iTabDb; + if( zRight ){ + pTab = sqlite3LocateTable(pParse, 0, zRight, zDb); + k = 0; +@@ -115376,21 +121530,23 @@ + k = sqliteHashNext(k); + } + if( pTab==0 || pTab->pFKey==0 ) continue; +- sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); ++ iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); ++ sqlite3CodeVerifySchema(pParse, iTabDb); ++ sqlite3TableLock(pParse, iTabDb, pTab->tnum, 0, pTab->zName); + if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow; +- sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead); ++ sqlite3OpenTable(pParse, 0, iTabDb, pTab, OP_OpenRead); + sqlite3VdbeLoadString(v, regResult, pTab->zName); + for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ + pParent = sqlite3FindTable(db, pFK->zTo, zDb); + if( pParent==0 ) continue; + pIdx = 0; +- sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName); ++ sqlite3TableLock(pParse, iTabDb, pParent->tnum, 0, pParent->zName); + x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0); + if( x==0 ){ + if( pIdx==0 ){ +- sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead); ++ sqlite3OpenTable(pParse, i, iTabDb, pParent, OP_OpenRead); + }else{ +- sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb); ++ sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iTabDb); + sqlite3VdbeSetP4KeyInfo(pParse, pIdx); + } + }else{ +@@ -115528,12 +121684,11 @@ + + /* Do an integrity check on each database file */ + for(i=0; i<db->nDb; i++){ +- HashElem *x; +- Hash *pTbls; +- int *aRoot; +- int cnt = 0; +- int mxIdx = 0; +- int nIdx; ++ HashElem *x; /* For looping over tables in the schema */ ++ Hash *pTbls; /* Set of all tables in the schema */ ++ int *aRoot; /* Array of root page numbers of all btrees */ ++ 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; +@@ -115548,8 +121703,9 @@ + assert( sqlite3SchemaMutexHeld(db, i, 0) ); + pTbls = &db->aDb[i].pSchema->tblHash; + for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ +- Table *pTab = sqliteHashData(x); +- Index *pIdx; ++ Table *pTab = sqliteHashData(x); /* Current table */ ++ Index *pIdx; /* An index on pTab */ ++ int nIdx; /* Number of indexes on pTab */ + if( HasRowid(pTab) ) cnt++; + for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; } + if( nIdx>mxIdx ) mxIdx = nIdx; +@@ -115559,12 +121715,12 @@ + for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ + Table *pTab = sqliteHashData(x); + Index *pIdx; +- if( HasRowid(pTab) ) aRoot[cnt++] = pTab->tnum; ++ if( HasRowid(pTab) ) aRoot[++cnt] = pTab->tnum; + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ +- aRoot[cnt++] = pIdx->tnum; ++ aRoot[++cnt] = pIdx->tnum; + } + } +- aRoot[cnt] = 0; ++ aRoot[0] = cnt; + + /* Make sure sufficient number of registers have been allocated */ + pParse->nMem = MAX( pParse->nMem, 8+mxIdx ); +@@ -115577,9 +121733,8 @@ + sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, + sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zDbSName), + P4_DYNAMIC); +- sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1); +- sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2); +- integrityCheckResultRow(v, 2); ++ sqlite3VdbeAddOp3(v, OP_Concat, 2, 3, 3); ++ integrityCheckResultRow(v); + sqlite3VdbeJumpHere(v, addr); + + /* Make sure all the indices are constructed correctly. +@@ -115593,16 +121748,12 @@ + int r1 = -1; + + if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */ +- if( pTab->pCheck==0 +- && (pTab->tabFlags & TF_HasNotNull)==0 +- && (pTab->pIndex==0 || isQuick) +- ){ +- continue; /* No additional checks needed for this table */ +- } + pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); +- sqlite3ExprCacheClear(pParse); + sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0, + 1, 0, &iDataCur, &iIdxCur); ++ /* reg[7] counts the number of entries in the table. ++ ** reg[8+i] counts the number of entries in the i-th index ++ */ + sqlite3VdbeAddOp2(v, OP_Integer, 0, 7); + for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ + sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */ +@@ -115611,6 +121762,11 @@ + assert( sqlite3NoTempsInRange(pParse,1,7+j) ); + sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v); + loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1); ++ if( !isQuick ){ ++ /* Sanity check on record header decoding */ ++ sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nCol-1, 3); ++ sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG); ++ } + /* Verify that all NOT NULL columns really are NOT NULL */ + for(j=0; j<pTab->nCol; j++){ + char *zErr; +@@ -115623,7 +121779,7 @@ + zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName, + pTab->aCol[j].zName); + sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); +- integrityCheckResultRow(v, 3); ++ integrityCheckResultRow(v); + sqlite3VdbeJumpHere(v, jmp2); + } + /* Verify CHECK constraints */ +@@ -115635,7 +121791,6 @@ + char *zErr; + int k; + pParse->iSelfTab = iDataCur + 1; +- sqlite3ExprCachePush(pParse); + for(k=pCheck->nExpr-1; k>0; k--){ + sqlite3ExprIfFalse(pParse, pCheck->a[k].pExpr, addrCkFault, 0); + } +@@ -115646,57 +121801,58 @@ + zErr = sqlite3MPrintf(db, "CHECK constraint failed in %s", + pTab->zName); + sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); +- integrityCheckResultRow(v, 3); ++ integrityCheckResultRow(v); + sqlite3VdbeResolveLabel(v, addrCkOk); +- sqlite3ExprCachePop(pParse); + } + sqlite3ExprListDelete(db, pCheck); + } +- /* Validate index entries for the current row */ +- for(j=0, pIdx=pTab->pIndex; pIdx && !isQuick; pIdx=pIdx->pNext, j++){ +- int jmp2, jmp3, jmp4, jmp5; +- int ckUniq = sqlite3VdbeMakeLabel(v); +- if( pPk==pIdx ) continue; +- r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3, +- pPrior, r1); +- pPrior = pIdx; +- sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1); /* increment entry count */ +- /* Verify that an index entry exists for the current table row */ +- jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1, +- pIdx->nColumn); VdbeCoverage(v); +- sqlite3VdbeLoadString(v, 3, "row "); +- sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3); +- 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, 3); +- sqlite3VdbeJumpHere(v, jmp2); +- /* For UNIQUE indexes, verify that only one entry exists with the +- ** current key. The entry is unique if (1) any column is NULL +- ** or (2) the next entry has a different key */ +- if( IsUniqueIndex(pIdx) ){ +- int uniqOk = sqlite3VdbeMakeLabel(v); +- int jmp6; +- int kk; +- for(kk=0; kk<pIdx->nKeyCol; kk++){ +- int iCol = pIdx->aiColumn[kk]; +- assert( iCol!=XN_ROWID && iCol<pTab->nCol ); +- if( iCol>=0 && pTab->aCol[iCol].notNull ) continue; +- sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk); +- VdbeCoverage(v); ++ if( !isQuick ){ /* Omit the remaining tests for quick_check */ ++ /* Validate index entries for the current row */ ++ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ ++ int jmp2, jmp3, jmp4, jmp5; ++ int ckUniq = sqlite3VdbeMakeLabel(v); ++ if( pPk==pIdx ) continue; ++ r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3, ++ pPrior, r1); ++ pPrior = pIdx; ++ sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1);/* increment entry count */ ++ /* Verify that an index entry exists for the current table row */ ++ jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1, ++ pIdx->nColumn); VdbeCoverage(v); ++ sqlite3VdbeLoadString(v, 3, "row "); ++ sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3); ++ 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); ++ /* For UNIQUE indexes, verify that only one entry exists with the ++ ** current key. The entry is unique if (1) any column is NULL ++ ** or (2) the next entry has a different key */ ++ if( IsUniqueIndex(pIdx) ){ ++ int uniqOk = sqlite3VdbeMakeLabel(v); ++ int jmp6; ++ int kk; ++ for(kk=0; kk<pIdx->nKeyCol; kk++){ ++ int iCol = pIdx->aiColumn[kk]; ++ assert( iCol!=XN_ROWID && iCol<pTab->nCol ); ++ if( iCol>=0 && pTab->aCol[iCol].notNull ) continue; ++ sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk); ++ VdbeCoverage(v); ++ } ++ jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v); ++ sqlite3VdbeGoto(v, uniqOk); ++ sqlite3VdbeJumpHere(v, jmp6); ++ sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1, ++ pIdx->nKeyCol); VdbeCoverage(v); ++ sqlite3VdbeLoadString(v, 3, "non-unique entry in index "); ++ sqlite3VdbeGoto(v, jmp5); ++ sqlite3VdbeResolveLabel(v, uniqOk); + } +- jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v); +- sqlite3VdbeGoto(v, uniqOk); +- sqlite3VdbeJumpHere(v, jmp6); +- sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1, +- pIdx->nKeyCol); VdbeCoverage(v); +- sqlite3VdbeLoadString(v, 3, "non-unique entry in index "); +- sqlite3VdbeGoto(v, jmp5); +- sqlite3VdbeResolveLabel(v, uniqOk); ++ sqlite3VdbeJumpHere(v, jmp4); ++ sqlite3ResolvePartIdxLabel(pParse, jmp3); + } +- sqlite3VdbeJumpHere(v, jmp4); +- sqlite3ResolvePartIdxLabel(pParse, jmp3); + } + sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v); + sqlite3VdbeJumpHere(v, loopTop-1); +@@ -115708,9 +121864,9 @@ + sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3); + addr = sqlite3VdbeAddOp3(v, OP_Eq, 8+j, 0, 3); VdbeCoverage(v); + sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); +- sqlite3VdbeLoadString(v, 3, pIdx->zName); +- sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7); +- integrityCheckResultRow(v, 7); ++ sqlite3VdbeLoadString(v, 4, pIdx->zName); ++ sqlite3VdbeAddOp3(v, OP_Concat, 4, 2, 3); ++ integrityCheckResultRow(v); + sqlite3VdbeJumpHere(v, addr); + } + } +@@ -115724,6 +121880,9 @@ + { OP_IfNotZero, 1, 4, 0}, /* 1 */ + { OP_String8, 0, 3, 0}, /* 2 */ + { OP_ResultRow, 3, 1, 0}, /* 3 */ ++ { OP_Halt, 0, 0, 0}, /* 4 */ ++ { OP_String8, 0, 3, 0}, /* 5 */ ++ { OP_Goto, 0, 3, 0}, /* 6 */ + }; + VdbeOp *aOp; + +@@ -115732,7 +121891,10 @@ + aOp[0].p2 = 1-mxErr; + aOp[2].p4type = P4_STATIC; + aOp[2].p4.z = "ok"; ++ aOp[5].p4type = P4_STATIC; ++ aOp[5].p4.z = (char*)sqlite3ErrStr(SQLITE_CORRUPT); + } ++ sqlite3VdbeChangeP3(v, 0, sqlite3VdbeCurrentAddr(v)-2); + } + } + break; +@@ -116153,14 +122315,26 @@ + #endif + + #ifdef SQLITE_HAS_CODEC ++ /* Pragma iArg ++ ** ---------- ------ ++ ** key 0 ++ ** rekey 1 ++ ** hexkey 2 ++ ** hexrekey 3 ++ ** textkey 4 ++ ** textrekey 5 ++ */ + case PragTyp_KEY: { +- if( zRight ) sqlite3_key_v2(db, zDb, zRight, sqlite3Strlen30(zRight)); ++ if( zRight ){ ++ int n = pPragma->iArg<4 ? sqlite3Strlen30(zRight) : -1; ++ if( (pPragma->iArg & 1)==0 ){ ++ sqlite3_key_v2(db, zDb, zRight, n); ++ }else{ ++ sqlite3_rekey_v2(db, zDb, zRight, n); ++ } ++ } + break; + } +- case PragTyp_REKEY: { +- if( zRight ) sqlite3_rekey_v2(db, zDb, zRight, sqlite3Strlen30(zRight)); +- break; +- } + case PragTyp_HEXKEY: { + if( zRight ){ + u8 iByte; +@@ -116170,7 +122344,7 @@ + iByte = (iByte<<4) + sqlite3HexToInt(zRight[i]); + if( (i&1)!=0 ) zKey[i/2] = iByte; + } +- if( (zLeft[3] & 0xf)==0xb ){ ++ if( (pPragma->iArg & 1)==0 ){ + sqlite3_key_v2(db, zDb, zKey, i/2); + }else{ + sqlite3_rekey_v2(db, zDb, zKey, i/2); +@@ -116252,26 +122426,25 @@ + UNUSED_PARAMETER(argc); + UNUSED_PARAMETER(argv); + sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); +- sqlite3StrAccumAppendAll(&acc, "CREATE TABLE x"); ++ sqlite3_str_appendall(&acc, "CREATE TABLE x"); + for(i=0, j=pPragma->iPragCName; i<pPragma->nPragCName; i++, j++){ +- sqlite3XPrintf(&acc, "%c\"%s\"", cSep, pragCName[j]); ++ sqlite3_str_appendf(&acc, "%c\"%s\"", cSep, pragCName[j]); + cSep = ','; + } + if( i==0 ){ +- sqlite3XPrintf(&acc, "(\"%s\"", pPragma->zName); +- cSep = ','; ++ sqlite3_str_appendf(&acc, "(\"%s\"", pPragma->zName); + i++; + } + j = 0; + if( pPragma->mPragFlg & PragFlg_Result1 ){ +- sqlite3StrAccumAppendAll(&acc, ",arg HIDDEN"); ++ sqlite3_str_appendall(&acc, ",arg HIDDEN"); + j++; + } + if( pPragma->mPragFlg & (PragFlg_SchemaOpt|PragFlg_SchemaReq) ){ +- sqlite3StrAccumAppendAll(&acc, ",schema HIDDEN"); ++ sqlite3_str_appendall(&acc, ",schema HIDDEN"); + j++; + } +- sqlite3StrAccumAppend(&acc, ")", 1); ++ sqlite3_str_append(&acc, ")", 1); + sqlite3StrAccumFinish(&acc); + assert( strlen(zBuf) < sizeof(zBuf)-1 ); + rc = sqlite3_declare_vtab(db, zBuf); +@@ -116423,13 +122596,13 @@ + } + } + sqlite3StrAccumInit(&acc, 0, 0, 0, pTab->db->aLimit[SQLITE_LIMIT_SQL_LENGTH]); +- sqlite3StrAccumAppendAll(&acc, "PRAGMA "); ++ sqlite3_str_appendall(&acc, "PRAGMA "); + if( pCsr->azArg[1] ){ +- sqlite3XPrintf(&acc, "%Q.", pCsr->azArg[1]); ++ sqlite3_str_appendf(&acc, "%Q.", pCsr->azArg[1]); + } +- sqlite3StrAccumAppendAll(&acc, pTab->pName->zName); ++ sqlite3_str_appendall(&acc, pTab->pName->zName); + if( pCsr->azArg[0] ){ +- sqlite3XPrintf(&acc, "=%Q", pCsr->azArg[0]); ++ sqlite3_str_appendf(&acc, "=%Q", pCsr->azArg[0]); + } + zSql = sqlite3StrAccumFinish(&acc); + if( zSql==0 ) return SQLITE_NOMEM; +@@ -116501,7 +122674,8 @@ + 0, /* xRename - rename the table */ + 0, /* xSavepoint */ + 0, /* xRelease */ +- 0 /* xRollbackTo */ ++ 0, /* xRollbackTo */ ++ 0 /* xShadowName */ + }; + + /* +@@ -116552,15 +122726,23 @@ + const char *zExtra /* Error information */ + ){ + sqlite3 *db = pData->db; +- if( !db->mallocFailed && (db->flags & SQLITE_WriteSchema)==0 ){ ++ if( db->mallocFailed ){ ++ pData->rc = SQLITE_NOMEM_BKPT; ++ }else if( pData->pzErrMsg[0]!=0 ){ ++ /* A error message has already been generated. Do not overwrite it */ ++ }else if( pData->mInitFlags & INITFLAG_AlterTable ){ ++ *pData->pzErrMsg = sqlite3DbStrDup(db, zExtra); ++ pData->rc = SQLITE_ERROR; ++ }else if( db->flags & SQLITE_WriteSchema ){ ++ pData->rc = SQLITE_CORRUPT_BKPT; ++ }else{ + char *z; + if( zObj==0 ) zObj = "?"; + z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj); +- if( zExtra ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra); +- sqlite3DbFree(db, *pData->pzErrMsg); ++ if( zExtra && zExtra[0] ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra); + *pData->pzErrMsg = z; ++ pData->rc = SQLITE_CORRUPT_BKPT; + } +- pData->rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_CORRUPT_BKPT; + } + + /* +@@ -116612,7 +122794,7 @@ + rc = db->errCode; + assert( (rc&0xFF)==(rcp&0xFF) ); + db->init.iDb = saved_iDb; +- assert( saved_iDb==0 || (db->flags & SQLITE_Vacuum)!=0 ); ++ /* assert( saved_iDb==0 || (db->mDbFlags & DBFLAG_Vacuum)!=0 ); */ + if( SQLITE_OK!=rc ){ + if( db->init.orphanTrigger ){ + assert( iDb==1 ); +@@ -116659,7 +122841,7 @@ + ** auxiliary databases. Return one of the SQLITE_ error codes to + ** indicate success or failure. + */ +-static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ ++SQLITE_PRIVATE int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){ + int rc; + int i; + #ifndef SQLITE_OMIT_DEPRECATED +@@ -116672,11 +122854,14 @@ + const char *zMasterName; + int openedTransaction = 0; + ++ assert( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 ); + assert( iDb>=0 && iDb<db->nDb ); + assert( db->aDb[iDb].pSchema ); + assert( sqlite3_mutex_held(db->mutex) ); + assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); + ++ db->init.busy = 1; ++ + /* Construct the in-memory representation schema tables (sqlite_master or + ** sqlite_temp_master) by invoking the parser directly. The appropriate + ** table name will be inserted automatically by the parser so we can just +@@ -116685,12 +122870,13 @@ + azArg[0] = zMasterName = SCHEMA_TABLE(iDb); + azArg[1] = "1"; + azArg[2] = "CREATE TABLE x(type text,name text,tbl_name text," +- "rootpage integer,sql text)"; ++ "rootpage int,sql text)"; + azArg[3] = 0; + initData.db = db; + initData.iDb = iDb; + initData.rc = SQLITE_OK; + initData.pzErrMsg = pzErrMsg; ++ initData.mInitFlags = mFlags; + sqlite3InitCallback(&initData, 3, (char **)azArg, 0); + if( initData.rc ){ + rc = initData.rc; +@@ -116701,10 +122887,10 @@ + */ + pDb = &db->aDb[iDb]; + if( pDb->pBt==0 ){ +- if( !OMIT_TEMPDB && ALWAYS(iDb==1) ){ +- DbSetProperty(db, 1, DB_SchemaLoaded); +- } +- return SQLITE_OK; ++ assert( iDb==1 ); ++ DbSetProperty(db, 1, DB_SchemaLoaded); ++ rc = SQLITE_OK; ++ goto error_out; + } + + /* If there is not already a read-only (or read-write) transaction opened +@@ -116712,7 +122898,7 @@ + ** will be closed before this function returns. */ + sqlite3BtreeEnter(pDb->pBt); + if( !sqlite3BtreeIsInReadTrans(pDb->pBt) ){ +- rc = sqlite3BtreeBeginTrans(pDb->pBt, 0); ++ rc = sqlite3BtreeBeginTrans(pDb->pBt, 0, 0); + if( rc!=SQLITE_OK ){ + sqlite3SetString(pzErrMsg, db, sqlite3ErrStr(rc)); + goto initone_error_out; +@@ -116740,6 +122926,9 @@ + for(i=0; i<ArraySize(meta); i++){ + sqlite3BtreeGetMeta(pDb->pBt, i+1, (u32 *)&meta[i]); + } ++ if( (db->flags & SQLITE_ResetDatabase)!=0 ){ ++ memset(meta, 0, sizeof(meta)); ++ } + pDb->pSchema->schema_cookie = meta[BTREE_SCHEMA_VERSION-1]; + + /* If opening a non-empty database, check the text encoding. For the +@@ -116839,8 +123028,8 @@ + rc = SQLITE_NOMEM_BKPT; + sqlite3ResetAllSchemasOfConnection(db); + } +- if( rc==SQLITE_OK || (db->flags&SQLITE_WriteSchema)){ +- /* Black magic: If the SQLITE_WriteSchema flag is set, then consider ++ if( rc==SQLITE_OK || (db->flags&SQLITE_NoSchemaError)){ ++ /* Black magic: If the SQLITE_NoSchemaError flag is set, then consider + ** the schema loaded, even if errors occurred. In this situation the + ** current sqlite3_prepare() operation will fail, but the following one + ** will attempt to compile the supplied statement against whatever subset +@@ -116863,9 +123052,13 @@ + sqlite3BtreeLeave(pDb->pBt); + + error_out: +- if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ +- sqlite3OomFault(db); ++ if( rc ){ ++ if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ ++ sqlite3OomFault(db); ++ } ++ sqlite3ResetOneSchema(db, iDb); + } ++ db->init.busy = 0; + return rc; + } + +@@ -116881,42 +123074,30 @@ + */ + SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){ + int i, rc; +- int commit_internal = !(db->flags&SQLITE_InternChanges); ++ int commit_internal = !(db->mDbFlags&DBFLAG_SchemaChange); + + assert( sqlite3_mutex_held(db->mutex) ); + assert( sqlite3BtreeHoldsMutex(db->aDb[0].pBt) ); + assert( db->init.busy==0 ); +- rc = SQLITE_OK; +- db->init.busy = 1; + ENC(db) = SCHEMA_ENC(db); +- for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ +- if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue; +- rc = sqlite3InitOne(db, i, pzErrMsg); +- if( rc ){ +- sqlite3ResetOneSchema(db, i); +- } ++ assert( db->nDb>0 ); ++ /* Do the main schema first */ ++ if( !DbHasProperty(db, 0, DB_SchemaLoaded) ){ ++ rc = sqlite3InitOne(db, 0, pzErrMsg, 0); ++ if( rc ) return rc; + } +- +- /* Once all the other databases have been initialized, load the schema +- ** for the TEMP database. This is loaded last, as the TEMP database +- ** schema may contain references to objects in other databases. +- */ +-#ifndef SQLITE_OMIT_TEMPDB +- assert( db->nDb>1 ); +- if( rc==SQLITE_OK && !DbHasProperty(db, 1, DB_SchemaLoaded) ){ +- rc = sqlite3InitOne(db, 1, pzErrMsg); +- if( rc ){ +- sqlite3ResetOneSchema(db, 1); ++ /* All other schemas after the main schema. The "temp" schema must be last */ ++ for(i=db->nDb-1; i>0; i--){ ++ assert( i==1 || sqlite3BtreeHoldsMutex(db->aDb[i].pBt) ); ++ if( !DbHasProperty(db, i, DB_SchemaLoaded) ){ ++ rc = sqlite3InitOne(db, i, pzErrMsg, 0); ++ if( rc ) return rc; + } + } +-#endif +- +- db->init.busy = 0; +- if( rc==SQLITE_OK && commit_internal ){ ++ if( commit_internal ){ + sqlite3CommitInternalChanges(db); + } +- +- return rc; ++ return SQLITE_OK; + } + + /* +@@ -116929,11 +123110,13 @@ + assert( sqlite3_mutex_held(db->mutex) ); + if( !db->init.busy ){ + rc = sqlite3Init(db, &pParse->zErrMsg); ++ if( rc!=SQLITE_OK ){ ++ pParse->rc = rc; ++ pParse->nErr++; ++ }else if( db->noSharedCache ){ ++ db->mDbFlags |= DBFLAG_SchemaKnownOk; ++ } + } +- if( rc!=SQLITE_OK ){ +- pParse->rc = rc; +- pParse->nErr++; +- } + return rc; + } + +@@ -116960,7 +123143,7 @@ + ** on the b-tree database, open one now. If a transaction is opened, it + ** will be closed immediately after reading the meta-value. */ + if( !sqlite3BtreeIsInReadTrans(pBt) ){ +- rc = sqlite3BtreeBeginTrans(pBt, 0); ++ rc = sqlite3BtreeBeginTrans(pBt, 0, 0); + if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ + sqlite3OomFault(db); + } +@@ -117007,7 +123190,8 @@ + */ + assert( sqlite3_mutex_held(db->mutex) ); + if( pSchema ){ +- for(i=0; ALWAYS(i<db->nDb); i++){ ++ for(i=0; 1; i++){ ++ assert( i<db->nDb ); + if( db->aDb[i].pSchema==pSchema ){ + break; + } +@@ -117021,16 +123205,14 @@ + ** Free all memory allocations in the pParse object + */ + SQLITE_PRIVATE void sqlite3ParserReset(Parse *pParse){ +- if( pParse ){ +- sqlite3 *db = pParse->db; +- sqlite3DbFree(db, pParse->aLabel); +- sqlite3ExprListDelete(db, pParse->pConstExpr); +- if( db ){ +- assert( db->lookaside.bDisable >= pParse->disableLookaside ); +- db->lookaside.bDisable -= pParse->disableLookaside; +- } +- pParse->disableLookaside = 0; ++ sqlite3 *db = pParse->db; ++ sqlite3DbFree(db, pParse->aLabel); ++ sqlite3ExprListDelete(db, pParse->pConstExpr); ++ if( db ){ ++ assert( db->lookaside.bDisable >= pParse->disableLookaside ); ++ db->lookaside.bDisable -= pParse->disableLookaside; + } ++ pParse->disableLookaside = 0; + } + + /* +@@ -117144,7 +123326,7 @@ + if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){ + static const char * const azColName[] = { + "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment", +- "selectid", "order", "from", "detail" ++ "id", "parent", "notused", "detail" + }; + int iFirst, mx; + if( sParse.explain==2 ){ +@@ -117190,8 +123372,6 @@ + end_prepare: + + sqlite3ParserReset(&sParse); +- rc = sqlite3ApiExit(db, rc); +- assert( (rc&db->errMask)==rc ); + return rc; + } + static int sqlite3LockAndPrepare( +@@ -117204,6 +123384,7 @@ + const char **pzTail /* OUT: End of parsed string */ + ){ + int rc; ++ int cnt = 0; + + #ifdef SQLITE_ENABLE_API_ARMOR + if( ppStmt==0 ) return SQLITE_MISUSE_BKPT; +@@ -117214,18 +123395,310 @@ + } + sqlite3_mutex_enter(db->mutex); + sqlite3BtreeEnterAll(db); +- rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail); +- if( rc==SQLITE_SCHEMA ){ +- sqlite3_finalize(*ppStmt); ++ do{ ++ /* Make multiple attempts to compile the SQL, until it either succeeds ++ ** or encounters a permanent error. A schema problem after one schema ++ ** reset is considered a permanent error. */ + rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail); +- } ++ assert( rc==SQLITE_OK || *ppStmt==0 ); ++ }while( rc==SQLITE_ERROR_RETRY ++ || (rc==SQLITE_SCHEMA && (sqlite3ResetOneSchema(db,-1), cnt++)==0) ); + sqlite3BtreeLeaveAll(db); ++ rc = sqlite3ApiExit(db, rc); ++ assert( (rc&db->errMask)==rc ); + sqlite3_mutex_leave(db->mutex); +- assert( rc==SQLITE_OK || *ppStmt==0 ); + return rc; + } + ++#ifdef SQLITE_ENABLE_NORMALIZE + /* ++** Checks if the specified token is a table, column, or function name, ++** based on the databases associated with the statement being prepared. ++** If the function fails, zero is returned and pRc is filled with the ++** error code. ++*/ ++static int shouldTreatAsIdentifier( ++ sqlite3 *db, /* Database handle. */ ++ const char *zToken, /* Pointer to start of token to be checked */ ++ int nToken, /* Length of token to be checked */ ++ int *pRc /* Pointer to error code upon failure */ ++){ ++ int bFound = 0; /* Non-zero if token is an identifier name. */ ++ int i, j; /* Database and column loop indexes. */ ++ Schema *pSchema; /* Schema for current database. */ ++ Hash *pHash; /* Hash table of tables for current database. */ ++ HashElem *e; /* Hash element for hash table iteration. */ ++ Table *pTab; /* Database table for columns being checked. */ ++ ++ if( sqlite3IsRowidN(zToken, nToken) ){ ++ return 1; ++ } ++ if( nToken>0 ){ ++ int hash = SQLITE_FUNC_HASH(sqlite3UpperToLower[(u8)zToken[0]], nToken); ++ if( sqlite3FunctionSearchN(hash, zToken, nToken) ) return 1; ++ } ++ assert( db!=0 ); ++ sqlite3_mutex_enter(db->mutex); ++ sqlite3BtreeEnterAll(db); ++ for(i=0; i<db->nDb; i++){ ++ pHash = &db->aFunc; ++ if( sqlite3HashFindN(pHash, zToken, nToken) ){ ++ bFound = 1; ++ break; ++ } ++ pSchema = db->aDb[i].pSchema; ++ if( pSchema==0 ) continue; ++ pHash = &pSchema->tblHash; ++ if( sqlite3HashFindN(pHash, zToken, nToken) ){ ++ bFound = 1; ++ break; ++ } ++ for(e=sqliteHashFirst(pHash); e; e=sqliteHashNext(e)){ ++ pTab = sqliteHashData(e); ++ if( pTab==0 ) continue; ++ pHash = pTab->pColHash; ++ if( pHash==0 ){ ++ pTab->pColHash = pHash = sqlite3_malloc(sizeof(Hash)); ++ if( pHash ){ ++ sqlite3HashInit(pHash); ++ for(j=0; j<pTab->nCol; j++){ ++ Column *pCol = &pTab->aCol[j]; ++ sqlite3HashInsert(pHash, pCol->zName, pCol); ++ } ++ }else{ ++ *pRc = SQLITE_NOMEM_BKPT; ++ bFound = 0; ++ goto done; ++ } ++ } ++ if( pHash && sqlite3HashFindN(pHash, zToken, nToken) ){ ++ bFound = 1; ++ goto done; ++ } ++ } ++ } ++done: ++ sqlite3BtreeLeaveAll(db); ++ sqlite3_mutex_leave(db->mutex); ++ return bFound; ++} ++ ++/* ++** Attempt to estimate the final output buffer size needed for the fully ++** normalized version of the specified SQL string. This should take into ++** account any potential expansion that could occur (e.g. via IN clauses ++** being expanded, etc). This size returned is the total number of bytes ++** including the NUL terminator. ++*/ ++static int estimateNormalizedSize( ++ const char *zSql, /* The original SQL string */ ++ int nSql, /* Length of original SQL string */ ++ u8 prepFlags /* The flags passed to sqlite3_prepare_v3() */ ++){ ++ int nOut = nSql + 4; ++ const char *z = zSql; ++ while( nOut<nSql*5 ){ ++ while( z[0]!=0 && z[0]!='I' && z[0]!='i' ){ z++; } ++ if( z[0]==0 ) break; ++ z++; ++ if( z[0]!='N' && z[0]!='n' ) break; ++ z++; ++ while( sqlite3Isspace(z[0]) ){ z++; } ++ if( z[0]!='(' ) break; ++ z++; ++ nOut += 5; /* ?,?,? */ ++ } ++ return nOut; ++} ++ ++/* ++** Copy the current token into the output buffer while dealing with quoted ++** identifiers. By default, all letters will be converted into lowercase. ++** If the bUpper flag is set, uppercase will be used. The piOut argument ++** will be used to update the target index into the output string. ++*/ ++static void copyNormalizedToken( ++ const char *zSql, /* The original SQL string */ ++ int iIn, /* Current index into the original SQL string */ ++ int nToken, /* Number of bytes in the current token */ ++ int tokenFlags, /* Flags returned by the tokenizer */ ++ char *zOut, /* The output string */ ++ int *piOut /* Pointer to target index into the output string */ ++){ ++ int bQuoted = tokenFlags & SQLITE_TOKEN_QUOTED; ++ int bKeyword = tokenFlags & SQLITE_TOKEN_KEYWORD; ++ int j = *piOut, k = 0; ++ for(; k<nToken; k++){ ++ if( bQuoted ){ ++ if( k==0 && iIn>0 ){ ++ zOut[j++] = '"'; ++ continue; ++ }else if( k==nToken-1 ){ ++ zOut[j++] = '"'; ++ continue; ++ } ++ } ++ if( bKeyword ){ ++ zOut[j++] = sqlite3Toupper(zSql[iIn+k]); ++ }else{ ++ zOut[j++] = sqlite3Tolower(zSql[iIn+k]); ++ } ++ } ++ *piOut = j; ++} ++ ++/* ++** Perform normalization of the SQL contained in the prepared statement and ++** store the result in the zNormSql field. The schema for the associated ++** databases are consulted while performing the normalization in order to ++** determine if a token appears to be an identifier. All identifiers are ++** left intact in the normalized SQL and all literals are replaced with a ++** single '?'. ++*/ ++SQLITE_PRIVATE void sqlite3Normalize( ++ Vdbe *pVdbe, /* VM being reprepared */ ++ const char *zSql, /* The original SQL string */ ++ int nSql, /* Size of the input string in bytes */ ++ u8 prepFlags /* The flags passed to sqlite3_prepare_v3() */ ++){ ++ sqlite3 *db; /* Database handle. */ ++ char *z; /* The output string */ ++ int nZ; /* Size of the output string in bytes */ ++ int i; /* Next character to read from zSql[] */ ++ int j; /* Next character to fill in on z[] */ ++ int tokenType = 0; /* Type of the next token */ ++ int prevTokenType = 0; /* Type of the previous token, except spaces */ ++ int n; /* Size of the next token */ ++ int nParen = 0; /* Nesting level of parenthesis */ ++ Hash inHash; /* Table of parenthesis levels to output index. */ ++ ++ db = sqlite3VdbeDb(pVdbe); ++ assert( db!=0 ); ++ assert( pVdbe->zNormSql==0 ); ++ if( zSql==0 ) return; ++ nZ = estimateNormalizedSize(zSql, nSql, prepFlags); ++ z = sqlite3DbMallocRawNN(db, nZ); ++ if( z==0 ) return; ++ sqlite3HashInit(&inHash); ++ for(i=j=0; i<nSql && zSql[i]; i+=n){ ++ int flags = 0; ++ if( tokenType!=TK_SPACE ) prevTokenType = tokenType; ++ n = sqlite3GetTokenNormalized((unsigned char*)zSql+i, &tokenType, &flags); ++ switch( tokenType ){ ++ case TK_SPACE: { ++ break; ++ } ++ case TK_ILLEGAL: { ++ sqlite3DbFree(db, z); ++ sqlite3HashClear(&inHash); ++ return; ++ } ++ case TK_STRING: ++ case TK_INTEGER: ++ case TK_FLOAT: ++ case TK_VARIABLE: ++ case TK_BLOB: { ++ z[j++] = '?'; ++ break; ++ } ++ case TK_LP: ++ case TK_RP: { ++ if( tokenType==TK_LP ){ ++ nParen++; ++ if( prevTokenType==TK_IN ){ ++ assert( nParen<nSql ); ++ sqlite3HashInsert(&inHash, zSql+nParen, SQLITE_INT_TO_PTR(j)); ++ } ++ }else{ ++ int jj; ++ assert( nParen<nSql ); ++ jj = SQLITE_PTR_TO_INT(sqlite3HashFind(&inHash, zSql+nParen)); ++ if( jj>0 ){ ++ sqlite3HashInsert(&inHash, zSql+nParen, 0); ++ assert( jj+6<nZ ); ++ memcpy(z+jj+1, "?,?,?", 5); ++ j = jj+6; ++ assert( nZ-1-j>=0 ); ++ assert( nZ-1-j<nZ ); ++ memset(z+j, 0, nZ-1-j); ++ } ++ nParen--; ++ } ++ assert( nParen>=0 ); ++ /* Fall through */ ++ } ++ case TK_MINUS: ++ case TK_SEMI: ++ case TK_PLUS: ++ case TK_STAR: ++ case TK_SLASH: ++ case TK_REM: ++ case TK_EQ: ++ case TK_LE: ++ case TK_NE: ++ case TK_LSHIFT: ++ case TK_LT: ++ case TK_RSHIFT: ++ case TK_GT: ++ case TK_GE: ++ case TK_BITOR: ++ case TK_CONCAT: ++ case TK_COMMA: ++ case TK_BITAND: ++ case TK_BITNOT: ++ case TK_DOT: ++ case TK_IN: ++ case TK_IS: ++ case TK_NOT: ++ case TK_NULL: ++ case TK_ID: { ++ if( tokenType==TK_NULL ){ ++ if( prevTokenType==TK_IS || prevTokenType==TK_NOT ){ ++ /* NULL is a keyword in this case, not a literal value */ ++ }else{ ++ /* Here the NULL is a literal value */ ++ z[j++] = '?'; ++ break; ++ } ++ } ++ if( j>0 && sqlite3IsIdChar(z[j-1]) && sqlite3IsIdChar(zSql[i]) ){ ++ z[j++] = ' '; ++ } ++ if( tokenType==TK_ID ){ ++ int i2 = i, n2 = n, rc = SQLITE_OK; ++ if( nParen>0 ){ ++ assert( nParen<nSql ); ++ sqlite3HashInsert(&inHash, zSql+nParen, 0); ++ } ++ if( flags&SQLITE_TOKEN_QUOTED ){ i2++; n2-=2; } ++ if( shouldTreatAsIdentifier(db, zSql+i2, n2, &rc)==0 ){ ++ if( rc!=SQLITE_OK ){ ++ sqlite3DbFree(db, z); ++ sqlite3HashClear(&inHash); ++ return; ++ } ++ if( sqlite3_keyword_check(zSql+i2, n2)==0 ){ ++ z[j++] = '?'; ++ break; ++ } ++ } ++ } ++ copyNormalizedToken(zSql, i, n, flags, z, &j); ++ break; ++ } ++ } ++ } ++ assert( j<nZ && "one" ); ++ while( j>0 && z[j-1]==' ' ){ j--; } ++ if( j>0 && z[j-1]!=';' ){ z[j++] = ';'; } ++ z[j] = 0; ++ assert( j<nZ && "two" ); ++ pVdbe->zNormSql = z; ++ sqlite3HashClear(&inHash); ++} ++#endif /* SQLITE_ENABLE_NORMALIZE */ ++ ++/* + ** Rerun the compilation of a statement after a schema change. + ** + ** If the statement is successfully recompiled, return SQLITE_OK. Otherwise, +@@ -117455,8 +123928,7 @@ + /***/ int sqlite3SelectTrace = 0; + # define SELECTTRACE(K,P,S,X) \ + if(sqlite3SelectTrace&(K)) \ +- sqlite3DebugPrintf("%*s%s.%p: ",(P)->nSelectIndent*2-2,"",\ +- (S)->zSelName,(S)),\ ++ sqlite3DebugPrintf("%u/%d/%p: ",(S)->selId,(P)->addrExplain,(S)),\ + sqlite3DebugPrintf X + #else + # define SELECTTRACE(K,P,S,X) +@@ -117479,6 +123951,20 @@ + /* + ** An instance of the following object is used to record information about + ** the ORDER BY (or GROUP BY) clause of query is being coded. ++** ++** The aDefer[] array is used by the sorter-references optimization. For ++** example, assuming there is no index that can be used for the ORDER BY, ++** for the query: ++** ++** SELECT a, bigblob FROM t1 ORDER BY a LIMIT 10; ++** ++** it may be more efficient to add just the "a" values to the sorter, and ++** retrieve the associated "bigblob" values directly from table t1 as the ++** 10 smallest "a" values are extracted from the sorter. ++** ++** When the sorter-reference optimization is used, there is one entry in the ++** aDefer[] array for each database table that may be read as values are ++** extracted from the sorter. + */ + typedef struct SortCtx SortCtx; + struct SortCtx { +@@ -117489,8 +123975,17 @@ + int labelBkOut; /* Start label for the block-output subroutine */ + int addrSortIndex; /* Address of the OP_SorterOpen or OP_OpenEphemeral */ + int labelDone; /* Jump here when done, ex: LIMIT reached */ ++ int labelOBLopt; /* Jump here when sorter is full */ + u8 sortFlags; /* Zero or more SORTFLAG_* bits */ +- u8 bOrderedInnerLoop; /* ORDER BY correctly sorts the inner loop */ ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ u8 nDefer; /* Number of valid entries in aDefer[] */ ++ struct DeferredCsr { ++ Table *pTab; /* Table definition */ ++ int iCsr; /* Cursor number for table */ ++ int nKey; /* Number of PK columns for table pTab (>=1) */ ++ } aDefer[4]; ++#endif ++ struct RowLoadInfo *pDeferredRowLoad; /* Deferred row loading info or NULL */ + }; + #define SORTFLAG_UseSorter 0x01 /* Use SorterOpen instead of OpenEphemeral */ + +@@ -117508,8 +124003,12 @@ + sqlite3ExprDelete(db, p->pHaving); + sqlite3ExprListDelete(db, p->pOrderBy); + sqlite3ExprDelete(db, p->pLimit); +- sqlite3ExprDelete(db, p->pOffset); +- if( p->pWith ) sqlite3WithDelete(db, p->pWith); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( OK_IF_ALWAYS_TRUE(p->pWinDefn) ){ ++ sqlite3WindowListDelete(db, p->pWinDefn); ++ } ++#endif ++ if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith); + if( bFree ) sqlite3DbFreeNN(db, p); + p = pPrior; + bFree = 1; +@@ -117541,8 +124040,7 @@ + Expr *pHaving, /* the HAVING clause */ + ExprList *pOrderBy, /* the ORDER BY clause */ + u32 selFlags, /* Flag parameters, such as SF_Distinct */ +- Expr *pLimit, /* LIMIT value. NULL means not used */ +- Expr *pOffset /* OFFSET value. NULL means no offset */ ++ Expr *pLimit /* LIMIT value. NULL means not used */ + ){ + Select *pNew; + Select standin; +@@ -117552,7 +124050,8 @@ + pNew = &standin; + } + if( pEList==0 ){ +- pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(pParse->db,TK_ASTERISK,0)); ++ pEList = sqlite3ExprListAppend(pParse, 0, ++ sqlite3Expr(pParse->db,TK_ASTERISK,0)); + } + pNew->pEList = pEList; + pNew->op = TK_SELECT; +@@ -117559,9 +124058,7 @@ + pNew->selFlags = selFlags; + pNew->iLimit = 0; + pNew->iOffset = 0; +-#if SELECTTRACE_ENABLED +- pNew->zSelName[0] = 0; +-#endif ++ pNew->selId = ++pParse->nSelect; + pNew->addrOpenEphm[0] = -1; + pNew->addrOpenEphm[1] = -1; + pNew->nSelectRow = 0; +@@ -117574,9 +124071,11 @@ + pNew->pPrior = 0; + pNew->pNext = 0; + pNew->pLimit = pLimit; +- pNew->pOffset = pOffset; + pNew->pWith = 0; +- assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 || pParse->db->mallocFailed!=0 ); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ pNew->pWin = 0; ++ pNew->pWinDefn = 0; ++#endif + if( pParse->db->mallocFailed ) { + clearSelect(pParse->db, pNew, pNew!=&standin); + pNew = 0; +@@ -117587,23 +124086,12 @@ + return pNew; + } + +-#if SELECTTRACE_ENABLED +-/* +-** Set the name of a Select object +-*/ +-SQLITE_PRIVATE void sqlite3SelectSetName(Select *p, const char *zName){ +- if( p && zName ){ +- sqlite3_snprintf(sizeof(p->zSelName), p->zSelName, "%s", zName); +- } +-} +-#endif + +- + /* + ** Delete the given Select structure and all of its substructures. + */ + SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3 *db, Select *p){ +- if( p ) clearSelect(db, p, 1); ++ if( OK_IF_ALWAYS_TRUE(p) ) clearSelect(db, p, 1); + } + + /* +@@ -117820,6 +124308,29 @@ + } + } + ++/* Undo the work of setJoinExpr(). In the expression tree p, convert every ++** term that is marked with EP_FromJoin and iRightJoinTable==iTable into ++** an ordinary term that omits the EP_FromJoin mark. ++** ++** This happens when a LEFT JOIN is simplified into an ordinary JOIN. ++*/ ++static void unsetJoinExpr(Expr *p, int iTable){ ++ while( p ){ ++ if( ExprHasProperty(p, EP_FromJoin) ++ && (iTable<0 || p->iRightJoinTable==iTable) ){ ++ ExprClearProperty(p, EP_FromJoin); ++ } ++ if( p->op==TK_FUNCTION && p->x.pList ){ ++ int i; ++ for(i=0; i<p->x.pList->nExpr; i++){ ++ unsetJoinExpr(p->x.pList->a[i].pExpr, iTable); ++ } ++ } ++ unsetJoinExpr(p->pLeft, iTable); ++ p = p->pRight; ++ } ++} ++ + /* + ** This routine processes the join information for a SELECT statement. + ** ON and USING clauses are converted into extra terms of the WHERE clause. +@@ -117844,11 +124355,10 @@ + pLeft = &pSrc->a[0]; + pRight = &pLeft[1]; + for(i=0; i<pSrc->nSrc-1; i++, pRight++, pLeft++){ +- Table *pLeftTab = pLeft->pTab; + Table *pRightTab = pRight->pTab; + int isOuter; + +- if( NEVER(pLeftTab==0 || pRightTab==0) ) continue; ++ if( NEVER(pLeft->pTab==0 || pRightTab==0) ) continue; + isOuter = (pRight->fg.jointype & JT_OUTER)!=0; + + /* When the NATURAL keyword is present, add WHERE clause terms for +@@ -117922,15 +124432,63 @@ + return 0; + } + +-/* Forward reference */ +-static KeyInfo *keyInfoFromExprList( +- Parse *pParse, /* Parsing context */ +- ExprList *pList, /* Form the KeyInfo object from this ExprList */ +- int iStart, /* Begin with this column of pList */ +- int nExtra /* Add this many extra columns to the end */ +-); ++/* ++** An instance of this object holds information (beyond pParse and pSelect) ++** needed to load the next result row that is to be added to the sorter. ++*/ ++typedef struct RowLoadInfo RowLoadInfo; ++struct RowLoadInfo { ++ int regResult; /* Store results in array of registers here */ ++ u8 ecelFlags; /* Flag argument to ExprCodeExprList() */ ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ ExprList *pExtra; /* Extra columns needed by sorter refs */ ++ int regExtraResult; /* Where to load the extra columns */ ++#endif ++}; + + /* ++** This routine does the work of loading query data into an array of ++** registers so that it can be added to the sorter. ++*/ ++static void innerLoopLoadRow( ++ Parse *pParse, /* Statement under construction */ ++ Select *pSelect, /* The query being coded */ ++ RowLoadInfo *pInfo /* Info needed to complete the row load */ ++){ ++ sqlite3ExprCodeExprList(pParse, pSelect->pEList, pInfo->regResult, ++ 0, pInfo->ecelFlags); ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ if( pInfo->pExtra ){ ++ sqlite3ExprCodeExprList(pParse, pInfo->pExtra, pInfo->regExtraResult, 0, 0); ++ sqlite3ExprListDelete(pParse->db, pInfo->pExtra); ++ } ++#endif ++} ++ ++/* ++** Code the OP_MakeRecord instruction that generates the entry to be ++** added into the sorter. ++** ++** Return the register in which the result is stored. ++*/ ++static int makeSorterRecord( ++ Parse *pParse, ++ SortCtx *pSort, ++ Select *pSelect, ++ int regBase, ++ int nBase ++){ ++ int nOBSat = pSort->nOBSat; ++ Vdbe *v = pParse->pVdbe; ++ int regOut = ++pParse->nMem; ++ if( pSort->pDeferredRowLoad ){ ++ innerLoopLoadRow(pParse, pSelect, pSort->pDeferredRowLoad); ++ } ++ sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regOut); ++ return regOut; ++} ++ ++/* + ** Generate code that will push the record in registers regData + ** through regData+nData-1 onto the sorter. + */ +@@ -117940,7 +124498,7 @@ + Select *pSelect, /* The whole SELECT statement */ + int regData, /* First register holding data to be sorted */ + int regOrigData, /* First register holding data before packing */ +- int nData, /* Number of elements in the data array */ ++ int nData, /* Number of elements in the regData data array */ + int nPrefixReg /* No. of reg prior to regData available for use */ + ){ + Vdbe *v = pParse->pVdbe; /* Stmt under construction */ +@@ -117948,16 +124506,32 @@ + int nExpr = pSort->pOrderBy->nExpr; /* No. of ORDER BY terms */ + int nBase = nExpr + bSeq + nData; /* Fields in sorter record */ + int regBase; /* Regs for sorter record */ +- int regRecord = ++pParse->nMem; /* Assembled sorter record */ ++ int regRecord = 0; /* Assembled sorter record */ + int nOBSat = pSort->nOBSat; /* ORDER BY terms to skip */ + int op; /* Opcode to add sorter record to sorter */ + int iLimit; /* LIMIT counter */ ++ int iSkip = 0; /* End of the sorter insert loop */ + + assert( bSeq==0 || bSeq==1 ); ++ ++ /* Three cases: ++ ** (1) The data to be sorted has already been packed into a Record ++ ** by a prior OP_MakeRecord. In this case nData==1 and regData ++ ** will be completely unrelated to regOrigData. ++ ** (2) All output columns are included in the sort record. In that ++ ** case regData==regOrigData. ++ ** (3) Some output columns are omitted from the sort record due to ++ ** the SQLITE_ENABLE_SORTER_REFERENCE optimization, or due to the ++ ** SQLITE_ECEL_OMITREF optimization, or due to the ++ ** SortCtx.pDeferredRowLoad optimiation. In any of these cases ++ ** regOrigData is 0 to prevent this routine from trying to copy ++ ** values that might not yet exist. ++ */ + assert( nData==1 || regData==regOrigData || regOrigData==0 ); ++ + if( nPrefixReg ){ + assert( nPrefixReg==nExpr+bSeq ); +- regBase = regData - nExpr - bSeq; ++ regBase = regData - nPrefixReg; + }else{ + regBase = pParse->nMem + 1; + pParse->nMem += nBase; +@@ -117973,7 +124547,6 @@ + if( nPrefixReg==0 && nData>0 ){ + sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData); + } +- sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regRecord); + if( nOBSat>0 ){ + int regPrevKey; /* The first nOBSat columns of the previous row */ + int addrFirst; /* Address of the OP_IfNot opcode */ +@@ -117982,6 +124555,7 @@ + int nKey; /* Number of sorting key columns, including OP_Sequence */ + KeyInfo *pKI; /* Original KeyInfo on the sorter table */ + ++ regRecord = makeSorterRecord(pParse, pSort, pSelect, regBase, nBase); + regPrevKey = pParse->nMem+1; + pParse->nMem += pSort->nOBSat; + nKey = nExpr - pSort->nOBSat + bSeq; +@@ -117996,11 +124570,11 @@ + if( pParse->db->mallocFailed ) return; + pOp->p2 = nKey + nData; + pKI = pOp->p4.pKeyInfo; +- memset(pKI->aSortOrder, 0, pKI->nField); /* Makes OP_Jump below testable */ ++ memset(pKI->aSortOrder, 0, pKI->nKeyField); /* Makes OP_Jump testable */ + sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO); +- testcase( pKI->nXField>2 ); +- pOp->p4.pKeyInfo = keyInfoFromExprList(pParse, pSort->pOrderBy, nOBSat, +- pKI->nXField-1); ++ testcase( pKI->nAllField > pKI->nKeyField+2 ); ++ pOp->p4.pKeyInfo = sqlite3KeyInfoFromExprList(pParse,pSort->pOrderBy,nOBSat, ++ pKI->nAllField-pKI->nKeyField-1); + addrJmp = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v); + pSort->labelBkOut = sqlite3VdbeMakeLabel(v); +@@ -118015,6 +124589,34 @@ + sqlite3ExprCodeMove(pParse, regBase, regPrevKey, pSort->nOBSat); + sqlite3VdbeJumpHere(v, addrJmp); + } ++ if( iLimit ){ ++ /* At this point the values for the new sorter entry are stored ++ ** in an array of registers. They need to be composed into a record ++ ** and inserted into the sorter if either (a) there are currently ++ ** less than LIMIT+OFFSET items or (b) the new record is smaller than ++ ** the largest record currently in the sorter. If (b) is true and there ++ ** are already LIMIT+OFFSET items in the sorter, delete the largest ++ ** entry before inserting the new one. This way there are never more ++ ** than LIMIT+OFFSET items in the sorter. ++ ** ++ ** If the new record does not need to be inserted into the sorter, ++ ** jump to the next iteration of the loop. If the pSort->labelOBLopt ++ ** value is not zero, then it is a label of where to jump. Otherwise, ++ ** just bypass the row insert logic. See the header comment on the ++ ** sqlite3WhereOrderByLimitOptLabel() function for additional info. ++ */ ++ int iCsr = pSort->iECursor; ++ sqlite3VdbeAddOp2(v, OP_IfNotZero, iLimit, sqlite3VdbeCurrentAddr(v)+4); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp2(v, OP_Last, iCsr, 0); ++ iSkip = sqlite3VdbeAddOp4Int(v, OP_IdxLE, ++ iCsr, 0, regBase+nOBSat, nExpr-nOBSat); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp1(v, OP_Delete, iCsr); ++ } ++ if( regRecord==0 ){ ++ regRecord = makeSorterRecord(pParse, pSort, pSelect, regBase, nBase); ++ } + if( pSort->sortFlags & SORTFLAG_UseSorter ){ + op = OP_SorterInsert; + }else{ +@@ -118022,33 +124624,9 @@ + } + sqlite3VdbeAddOp4Int(v, op, pSort->iECursor, regRecord, + regBase+nOBSat, nBase-nOBSat); +- if( iLimit ){ +- int addr; +- int r1 = 0; +- /* Fill the sorter until it contains LIMIT+OFFSET entries. (The iLimit +- ** register is initialized with value of LIMIT+OFFSET.) After the sorter +- ** fills up, delete the least entry in the sorter after each insert. +- ** Thus we never hold more than the LIMIT+OFFSET rows in memory at once */ +- addr = sqlite3VdbeAddOp1(v, OP_IfNotZero, iLimit); VdbeCoverage(v); +- sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor); +- if( pSort->bOrderedInnerLoop ){ +- r1 = ++pParse->nMem; +- sqlite3VdbeAddOp3(v, OP_Column, pSort->iECursor, nExpr, r1); +- VdbeComment((v, "seq")); +- } +- sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor); +- if( pSort->bOrderedInnerLoop ){ +- /* If the inner loop is driven by an index such that values from +- ** the same iteration of the inner loop are in sorted order, then +- ** immediately jump to the next iteration of an inner loop if the +- ** entry from the current iteration does not fit into the top +- ** LIMIT+OFFSET entries of the sorter. */ +- int iBrk = sqlite3VdbeCurrentAddr(v) + 2; +- sqlite3VdbeAddOp3(v, OP_Eq, regBase+nExpr, iBrk, r1); +- sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); +- VdbeCoverage(v); +- } +- sqlite3VdbeJumpHere(v, addr); ++ if( iSkip ){ ++ sqlite3VdbeChangeP2(v, iSkip, ++ pSort->labelOBLopt ? pSort->labelOBLopt : sqlite3VdbeCurrentAddr(v)); + } + } + +@@ -118094,20 +124672,100 @@ + sqlite3ReleaseTempReg(pParse, r1); + } + ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES + /* ++** This function is called as part of inner-loop generation for a SELECT ++** statement with an ORDER BY that is not optimized by an index. It ++** determines the expressions, if any, that the sorter-reference ++** optimization should be used for. The sorter-reference optimization ++** is used for SELECT queries like: ++** ++** SELECT a, bigblob FROM t1 ORDER BY a LIMIT 10 ++** ++** If the optimization is used for expression "bigblob", then instead of ++** storing values read from that column in the sorter records, the PK of ++** the row from table t1 is stored instead. Then, as records are extracted from ++** the sorter to return to the user, the required value of bigblob is ++** retrieved directly from table t1. If the values are very large, this ++** can be more efficient than storing them directly in the sorter records. ++** ++** The ExprList_item.bSorterRef flag is set for each expression in pEList ++** for which the sorter-reference optimization should be enabled. ++** Additionally, the pSort->aDefer[] array is populated with entries ++** for all cursors required to evaluate all selected expressions. Finally. ++** output variable (*ppExtra) is set to an expression list containing ++** expressions for all extra PK values that should be stored in the ++** sorter records. ++*/ ++static void selectExprDefer( ++ Parse *pParse, /* Leave any error here */ ++ SortCtx *pSort, /* Sorter context */ ++ ExprList *pEList, /* Expressions destined for sorter */ ++ ExprList **ppExtra /* Expressions to append to sorter record */ ++){ ++ int i; ++ int nDefer = 0; ++ ExprList *pExtra = 0; ++ for(i=0; i<pEList->nExpr; i++){ ++ struct ExprList_item *pItem = &pEList->a[i]; ++ if( pItem->u.x.iOrderByCol==0 ){ ++ Expr *pExpr = pItem->pExpr; ++ Table *pTab = pExpr->y.pTab; ++ if( pExpr->op==TK_COLUMN && pExpr->iColumn>=0 && pTab && !IsVirtual(pTab) ++ && (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF) ++ ){ ++ int j; ++ for(j=0; j<nDefer; j++){ ++ if( pSort->aDefer[j].iCsr==pExpr->iTable ) break; ++ } ++ if( j==nDefer ){ ++ if( nDefer==ArraySize(pSort->aDefer) ){ ++ continue; ++ }else{ ++ int nKey = 1; ++ int k; ++ Index *pPk = 0; ++ if( !HasRowid(pTab) ){ ++ pPk = sqlite3PrimaryKeyIndex(pTab); ++ nKey = pPk->nKeyCol; ++ } ++ for(k=0; k<nKey; k++){ ++ Expr *pNew = sqlite3PExpr(pParse, TK_COLUMN, 0, 0); ++ if( pNew ){ ++ pNew->iTable = pExpr->iTable; ++ pNew->y.pTab = pExpr->y.pTab; ++ pNew->iColumn = pPk ? pPk->aiColumn[k] : -1; ++ pExtra = sqlite3ExprListAppend(pParse, pExtra, pNew); ++ } ++ } ++ pSort->aDefer[nDefer].pTab = pExpr->y.pTab; ++ pSort->aDefer[nDefer].iCsr = pExpr->iTable; ++ pSort->aDefer[nDefer].nKey = nKey; ++ nDefer++; ++ } ++ } ++ pItem->bSorterRef = 1; ++ } ++ } ++ } ++ pSort->nDefer = (u8)nDefer; ++ *ppExtra = pExtra; ++} ++#endif ++ ++/* + ** This routine generates the code for the inside of the inner loop + ** of a SELECT. + ** +-** If srcTab is negative, then the pEList expressions ++** If srcTab is negative, then the p->pEList expressions + ** are evaluated in order to get the data for this row. If srcTab is +-** zero or more, then data is pulled from srcTab and pEList is used only ++** zero or more, then data is pulled from srcTab and p->pEList is used only + ** to get the number of columns and the collation sequence for each column. + */ + static void selectInnerLoop( + Parse *pParse, /* The parser context */ + Select *p, /* The complete select statement being coded */ +- ExprList *pEList, /* List of values being extracted */ +- int srcTab, /* Pull data from this table */ ++ int srcTab, /* Pull data from this table if non-negative */ + SortCtx *pSort, /* If not NULL, info on how to process ORDER BY */ + DistinctCtx *pDistinct, /* If not NULL, info on how to process DISTINCT */ + SelectDest *pDest, /* How to dispose of the results */ +@@ -118121,6 +124779,7 @@ + int iParm = pDest->iSDParm; /* First argument to disposal method */ + int nResultCol; /* Number of result columns */ + int nPrefixReg = 0; /* Number of extra registers before regResult */ ++ RowLoadInfo sRowLoadInfo; /* Info for deferred row loading */ + + /* Usually, regResult is the first cell in an array of memory cells + ** containing the current result row. In this case regOrig is set to the +@@ -118131,7 +124790,7 @@ + int regOrig; /* Start of memory holding full result (or 0) */ + + assert( v ); +- assert( pEList!=0 ); ++ assert( p->pEList!=0 ); + hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP; + if( pSort && pSort->pOrderBy==0 ) pSort = 0; + if( pSort==0 && !hasDistinct ){ +@@ -118141,7 +124800,7 @@ + + /* Pull the requested columns. + */ +- nResultCol = pEList->nExpr; ++ nResultCol = p->pEList->nExpr; + + if( pDest->iSdst==0 ){ + if( pSort ){ +@@ -118164,13 +124823,17 @@ + if( srcTab>=0 ){ + for(i=0; i<nResultCol; i++){ + sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i); +- VdbeComment((v, "%s", pEList->a[i].zName)); ++ VdbeComment((v, "%s", p->pEList->a[i].zName)); + } + }else if( eDest!=SRT_Exists ){ ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ ExprList *pExtra = 0; ++#endif + /* If the destination is an EXISTS(...) expression, the actual + ** values returned by the SELECT are not required. + */ +- u8 ecelFlags; ++ u8 ecelFlags; /* "ecel" is an abbreviation of "ExprCodeExprList" */ ++ ExprList *pEList; + if( eDest==SRT_Mem || eDest==SRT_Output || eDest==SRT_Coroutine ){ + ecelFlags = SQLITE_ECEL_DUP; + }else{ +@@ -118177,24 +124840,75 @@ + ecelFlags = 0; + } + if( pSort && hasDistinct==0 && eDest!=SRT_EphemTab && eDest!=SRT_Table ){ +- /* For each expression in pEList that is a copy of an expression in ++ /* For each expression in p->pEList that is a copy of an expression in + ** the ORDER BY clause (pSort->pOrderBy), set the associated + ** iOrderByCol value to one more than the index of the ORDER BY + ** expression within the sort-key that pushOntoSorter() will generate. +- ** This allows the pEList field to be omitted from the sorted record, ++ ** This allows the p->pEList field to be omitted from the sorted record, + ** saving space and CPU cycles. */ + ecelFlags |= (SQLITE_ECEL_OMITREF|SQLITE_ECEL_REF); ++ + for(i=pSort->nOBSat; i<pSort->pOrderBy->nExpr; i++){ + int j; + if( (j = pSort->pOrderBy->a[i].u.x.iOrderByCol)>0 ){ +- pEList->a[j-1].u.x.iOrderByCol = i+1-pSort->nOBSat; ++ p->pEList->a[j-1].u.x.iOrderByCol = i+1-pSort->nOBSat; + } + } +- regOrig = 0; ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ selectExprDefer(pParse, pSort, p->pEList, &pExtra); ++ if( pExtra && pParse->db->mallocFailed==0 ){ ++ /* If there are any extra PK columns to add to the sorter records, ++ ** allocate extra memory cells and adjust the OpenEphemeral ++ ** instruction to account for the larger records. This is only ++ ** required if there are one or more WITHOUT ROWID tables with ++ ** composite primary keys in the SortCtx.aDefer[] array. */ ++ VdbeOp *pOp = sqlite3VdbeGetOp(v, pSort->addrSortIndex); ++ pOp->p2 += (pExtra->nExpr - pSort->nDefer); ++ pOp->p4.pKeyInfo->nAllField += (pExtra->nExpr - pSort->nDefer); ++ pParse->nMem += pExtra->nExpr; ++ } ++#endif ++ ++ /* Adjust nResultCol to account for columns that are omitted ++ ** from the sorter by the optimizations in this branch */ ++ pEList = p->pEList; ++ for(i=0; i<pEList->nExpr; i++){ ++ if( pEList->a[i].u.x.iOrderByCol>0 ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ || pEList->a[i].bSorterRef ++#endif ++ ){ ++ nResultCol--; ++ regOrig = 0; ++ } ++ } ++ ++ testcase( regOrig ); ++ testcase( eDest==SRT_Set ); ++ testcase( eDest==SRT_Mem ); ++ testcase( eDest==SRT_Coroutine ); ++ testcase( eDest==SRT_Output ); + assert( eDest==SRT_Set || eDest==SRT_Mem + || eDest==SRT_Coroutine || eDest==SRT_Output ); + } +- nResultCol = sqlite3ExprCodeExprList(pParse,pEList,regResult,0,ecelFlags); ++ sRowLoadInfo.regResult = regResult; ++ sRowLoadInfo.ecelFlags = ecelFlags; ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ sRowLoadInfo.pExtra = pExtra; ++ sRowLoadInfo.regExtraResult = regResult + nResultCol; ++ if( pExtra ) nResultCol += pExtra->nExpr; ++#endif ++ if( p->iLimit ++ && (ecelFlags & SQLITE_ECEL_OMITREF)!=0 ++ && nPrefixReg>0 ++ ){ ++ assert( pSort!=0 ); ++ assert( hasDistinct==0 ); ++ pSort->pDeferredRowLoad = &sRowLoadInfo; ++ regOrig = 0; ++ }else{ ++ innerLoopLoadRow(pParse, p, &sRowLoadInfo); ++ } + } + + /* If the DISTINCT keyword was present on the SELECT statement +@@ -118226,7 +124940,7 @@ + + iJump = sqlite3VdbeCurrentAddr(v) + nResultCol; + for(i=0; i<nResultCol; i++){ +- CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[i].pExpr); ++ CollSeq *pColl = sqlite3ExprCollSeq(pParse, p->pEList->a[i].pExpr); + if( i<nResultCol-1 ){ + sqlite3VdbeAddOp3(v, OP_Ne, regResult+i, iJump, regPrev+i); + VdbeCoverage(v); +@@ -118310,7 +125024,8 @@ + } + #endif + if( pSort ){ +- pushOntoSorter(pParse, pSort, p, r1+nPrefixReg,regResult,1,nPrefixReg); ++ assert( regResult==regOrig ); ++ pushOntoSorter(pParse, pSort, p, r1+nPrefixReg, regOrig, 1, nPrefixReg); + }else{ + int r2 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2); +@@ -118340,7 +125055,6 @@ + assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol ); + sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol, + r1, pDest->zAffSdst, nResultCol); +- sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol); + sqlite3ReleaseTempReg(pParse, r1); + } +@@ -118384,7 +125098,6 @@ + sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); + }else{ + sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nResultCol); +- sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol); + } + break; + } +@@ -118469,8 +125182,8 @@ + KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra); + if( p ){ + p->aSortOrder = (u8*)&p->aColl[N+X]; +- p->nField = (u16)N; +- p->nXField = (u16)X; ++ p->nKeyField = (u16)N; ++ p->nAllField = (u16)(N+X); + p->enc = ENC(db); + p->db = db; + p->nRef = 1; +@@ -118527,7 +125240,7 @@ + ** function is responsible for seeing that this structure is eventually + ** freed. + */ +-static KeyInfo *keyInfoFromExprList( ++SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoFromExprList( + Parse *pParse, /* Parsing context */ + ExprList *pList, /* Form the KeyInfo object from this ExprList */ + int iStart, /* Begin with this column of pList */ +@@ -118544,10 +125257,7 @@ + if( pInfo ){ + assert( sqlite3KeyInfoIsWriteable(pInfo) ); + for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){ +- CollSeq *pColl; +- pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr); +- if( !pColl ) pColl = db->pDfltColl; +- pInfo->aColl[i-iStart] = pColl; ++ pInfo->aColl[i-iStart] = sqlite3ExprNNCollSeq(pParse, pItem->pExpr); + pInfo->aSortOrder[i-iStart] = pItem->sortOrder; + } + } +@@ -118580,11 +125290,7 @@ + ** is determined by the zUsage argument. + */ + static void explainTempTable(Parse *pParse, const char *zUsage){ +- if( pParse->explain==2 ){ +- Vdbe *v = pParse->pVdbe; +- char *zMsg = sqlite3MPrintf(pParse->db, "USE TEMP B-TREE FOR %s", zUsage); +- sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); +- } ++ ExplainQueryPlan((pParse, 0, "USE TEMP B-TREE FOR %s", zUsage)); + } + + /* +@@ -118602,42 +125308,6 @@ + # define explainSetInteger(y,z) + #endif + +-#if !defined(SQLITE_OMIT_EXPLAIN) && !defined(SQLITE_OMIT_COMPOUND_SELECT) +-/* +-** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function +-** is a no-op. Otherwise, it adds a single row of output to the EQP result, +-** where the caption is of one of the two forms: +-** +-** "COMPOSITE SUBQUERIES iSub1 and iSub2 (op)" +-** "COMPOSITE SUBQUERIES iSub1 and iSub2 USING TEMP B-TREE (op)" +-** +-** where iSub1 and iSub2 are the integers passed as the corresponding +-** function parameters, and op is the text representation of the parameter +-** of the same name. The parameter "op" must be one of TK_UNION, TK_EXCEPT, +-** TK_INTERSECT or TK_ALL. The first form is used if argument bUseTmp is +-** false, or the second form if it is true. +-*/ +-static void explainComposite( +- Parse *pParse, /* Parse context */ +- int op, /* One of TK_UNION, TK_EXCEPT etc. */ +- int iSub1, /* Subquery id 1 */ +- int iSub2, /* Subquery id 2 */ +- int bUseTmp /* True if a temp table was used */ +-){ +- assert( op==TK_UNION || op==TK_EXCEPT || op==TK_INTERSECT || op==TK_ALL ); +- if( pParse->explain==2 ){ +- Vdbe *v = pParse->pVdbe; +- char *zMsg = sqlite3MPrintf( +- pParse->db, "COMPOUND SUBQUERIES %d AND %d %s(%s)", iSub1, iSub2, +- bUseTmp?"USING TEMP B-TREE ":"", selectOpName(op) +- ); +- sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); +- } +-} +-#else +-/* No-op versions of the explainXXX() functions and macros. */ +-# define explainComposite(v,w,x,y,z) +-#endif + + /* + ** If the inner loop was generated using a non-null pOrderBy argument, +@@ -118655,7 +125325,7 @@ + Vdbe *v = pParse->pVdbe; /* The prepared statement */ + int addrBreak = pSort->labelDone; /* Jump here to exit loop */ + int addrContinue = sqlite3VdbeMakeLabel(v); /* Jump here for next cycle */ +- int addr; ++ int addr; /* Top of output loop. Jump for Next. */ + int addrOnce = 0; + int iTab; + ExprList *pOrderBy = pSort->pOrderBy; +@@ -118664,11 +125334,11 @@ + int regRow; + int regRowid; + int iCol; +- int nKey; ++ int nKey; /* Number of key columns in sorter record */ + int iSortTab; /* Sorter cursor to read from */ +- int nSortData; /* Trailing values to read from sorter */ + int i; + int bSeq; /* True if sorter record includes seq. no. */ ++ int nRefKey = 0; + struct ExprList_item *aOutEx = p->pEList->a; + + assert( addrBreak<0 ); +@@ -118677,15 +125347,24 @@ + sqlite3VdbeGoto(v, addrBreak); + sqlite3VdbeResolveLabel(v, pSort->labelBkOut); + } ++ ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ /* Open any cursors needed for sorter-reference expressions */ ++ for(i=0; i<pSort->nDefer; i++){ ++ Table *pTab = pSort->aDefer[i].pTab; ++ int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); ++ sqlite3OpenTable(pParse, pSort->aDefer[i].iCsr, iDb, pTab, OP_OpenRead); ++ nRefKey = MAX(nRefKey, pSort->aDefer[i].nKey); ++ } ++#endif ++ + iTab = pSort->iECursor; + if( eDest==SRT_Output || eDest==SRT_Coroutine || eDest==SRT_Mem ){ + regRowid = 0; + regRow = pDest->iSdst; +- nSortData = nColumn; + }else{ + regRowid = sqlite3GetTempReg(pParse); + regRow = sqlite3GetTempRange(pParse, nColumn); +- nSortData = nColumn; + } + nKey = pOrderBy->nExpr - pSort->nOBSat; + if( pSort->sortFlags & SORTFLAG_UseSorter ){ +@@ -118694,7 +125373,8 @@ + if( pSort->labelBkOut ){ + addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); + } +- sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut, nKey+1+nSortData); ++ sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut, ++ nKey+1+nColumn+nRefKey); + if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); + addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak); + VdbeCoverage(v); +@@ -118707,16 +125387,60 @@ + iSortTab = iTab; + bSeq = 1; + } +- for(i=0, iCol=nKey+bSeq; i<nSortData; i++){ +- int iRead; +- if( aOutEx[i].u.x.iOrderByCol ){ +- iRead = aOutEx[i].u.x.iOrderByCol-1; +- }else{ +- iRead = iCol++; ++ for(i=0, iCol=nKey+bSeq-1; i<nColumn; i++){ ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ if( aOutEx[i].bSorterRef ) continue; ++#endif ++ if( aOutEx[i].u.x.iOrderByCol==0 ) iCol++; ++ } ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ if( pSort->nDefer ){ ++ int iKey = iCol+1; ++ int regKey = sqlite3GetTempRange(pParse, nRefKey); ++ ++ for(i=0; i<pSort->nDefer; i++){ ++ int iCsr = pSort->aDefer[i].iCsr; ++ Table *pTab = pSort->aDefer[i].pTab; ++ int nKey = pSort->aDefer[i].nKey; ++ ++ sqlite3VdbeAddOp1(v, OP_NullRow, iCsr); ++ if( HasRowid(pTab) ){ ++ sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iKey++, regKey); ++ sqlite3VdbeAddOp3(v, OP_SeekRowid, iCsr, ++ sqlite3VdbeCurrentAddr(v)+1, regKey); ++ }else{ ++ int k; ++ int iJmp; ++ assert( sqlite3PrimaryKeyIndex(pTab)->nKeyCol==nKey ); ++ for(k=0; k<nKey; k++){ ++ sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iKey++, regKey+k); ++ } ++ iJmp = sqlite3VdbeCurrentAddr(v); ++ sqlite3VdbeAddOp4Int(v, OP_SeekGE, iCsr, iJmp+2, regKey, nKey); ++ sqlite3VdbeAddOp4Int(v, OP_IdxLE, iCsr, iJmp+3, regKey, nKey); ++ sqlite3VdbeAddOp1(v, OP_NullRow, iCsr); ++ } + } +- sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i); +- VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan)); ++ sqlite3ReleaseTempRange(pParse, regKey, nRefKey); + } ++#endif ++ for(i=nColumn-1; i>=0; i--){ ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ if( aOutEx[i].bSorterRef ){ ++ sqlite3ExprCode(pParse, aOutEx[i].pExpr, regRow+i); ++ }else ++#endif ++ { ++ int iRead; ++ if( aOutEx[i].u.x.iOrderByCol ){ ++ iRead = aOutEx[i].u.x.iOrderByCol-1; ++ }else{ ++ iRead = iCol--; ++ } ++ sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i); ++ VdbeComment((v, "%s", aOutEx[i].zName?aOutEx[i].zName : aOutEx[i].zSpan)); ++ } ++ } + switch( eDest ){ + case SRT_Table: + case SRT_EphemTab: { +@@ -118730,7 +125454,6 @@ + assert( nColumn==sqlite3Strlen30(pDest->zAffSdst) ); + sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, nColumn, regRowid, + pDest->zAffSdst, nColumn); +- sqlite3ExprCacheAffinityChange(pParse, regRow, nColumn); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, regRowid, regRow, nColumn); + break; + } +@@ -118745,7 +125468,6 @@ + testcase( eDest==SRT_Coroutine ); + if( eDest==SRT_Output ){ + sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iSdst, nColumn); +- sqlite3ExprCacheAffinityChange(pParse, pDest->iSdst, nColumn); + }else{ + sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); + } +@@ -118797,23 +125519,23 @@ + ** the SQLITE_ENABLE_COLUMN_METADATA compile-time option is used. + */ + #ifdef SQLITE_ENABLE_COLUMN_METADATA +-# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,C,D,E,F) ++# define columnType(A,B,C,D,E) columnTypeImpl(A,B,C,D,E) + #else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */ +-# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F) ++# define columnType(A,B,C,D,E) columnTypeImpl(A,B) + #endif + static const char *columnTypeImpl( + NameContext *pNC, ++#ifndef SQLITE_ENABLE_COLUMN_METADATA ++ Expr *pExpr ++#else + Expr *pExpr, +-#ifdef SQLITE_ENABLE_COLUMN_METADATA + const char **pzOrigDb, + const char **pzOrigTab, +- const char **pzOrigCol, ++ const char **pzOrigCol + #endif +- u8 *pEstWidth + ){ + char const *zType = 0; + int j; +- u8 estWidth = 1; + #ifdef SQLITE_ENABLE_COLUMN_METADATA + char const *zOrigDb = 0; + char const *zOrigTab = 0; +@@ -118822,8 +125544,9 @@ + + assert( pExpr!=0 ); + assert( pNC->pSrcList!=0 ); ++ assert( pExpr->op!=TK_AGG_COLUMN ); /* This routine runes before aggregates ++ ** are processed */ + switch( pExpr->op ){ +- case TK_AGG_COLUMN: + case TK_COLUMN: { + /* The expression is a column. Locate the table the column is being + ** extracted from in NameContext.pSrcList. This table may be real +@@ -118832,8 +125555,6 @@ + Table *pTab = 0; /* Table structure column is extracted from */ + Select *pS = 0; /* Select the column is extracted from */ + int iCol = pExpr->iColumn; /* Index of column in pTab */ +- testcase( pExpr->op==TK_AGG_COLUMN ); +- testcase( pExpr->op==TK_COLUMN ); + while( pNC && !pTab ){ + SrcList *pTabList = pNC->pSrcList; + for(j=0;j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++); +@@ -118866,7 +125587,7 @@ + break; + } + +- assert( pTab && pExpr->pTab==pTab ); ++ assert( pTab && pExpr->y.pTab==pTab ); + if( pS ){ + /* The "table" is actually a sub-select or a view in the FROM clause + ** of the SELECT statement. Return the declaration type and origin +@@ -118882,14 +125603,14 @@ + sNC.pSrcList = pS->pSrc; + sNC.pNext = pNC; + sNC.pParse = pNC->pParse; +- zType = columnType(&sNC, p,&zOrigDb,&zOrigTab,&zOrigCol, &estWidth); ++ zType = columnType(&sNC, p,&zOrigDb,&zOrigTab,&zOrigCol); + } +- }else if( pTab->pSchema ){ +- /* A real table */ ++ }else{ ++ /* A real table or a CTE table */ + assert( !pS ); ++#ifdef SQLITE_ENABLE_COLUMN_METADATA + if( iCol<0 ) iCol = pTab->iPKey; +- assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) ); +-#ifdef SQLITE_ENABLE_COLUMN_METADATA ++ assert( iCol==XN_ROWID || (iCol>=0 && iCol<pTab->nCol) ); + if( iCol<0 ){ + zType = "INTEGER"; + zOrigCol = "rowid"; +@@ -118896,19 +125617,18 @@ + }else{ + zOrigCol = pTab->aCol[iCol].zName; + zType = sqlite3ColumnType(&pTab->aCol[iCol],0); +- estWidth = pTab->aCol[iCol].szEst; + } + zOrigTab = pTab->zName; +- if( pNC->pParse ){ ++ if( pNC->pParse && pTab->pSchema ){ + int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema); + zOrigDb = pNC->pParse->db->aDb[iDb].zDbSName; + } + #else ++ assert( iCol==XN_ROWID || (iCol>=0 && iCol<pTab->nCol) ); + if( iCol<0 ){ + zType = "INTEGER"; + }else{ + zType = sqlite3ColumnType(&pTab->aCol[iCol],0); +- estWidth = pTab->aCol[iCol].szEst; + } + #endif + } +@@ -118927,7 +125647,7 @@ + sNC.pSrcList = pS->pSrc; + sNC.pNext = pNC; + sNC.pParse = pNC->pParse; +- zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, &estWidth); ++ zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol); + break; + } + #endif +@@ -118941,7 +125661,6 @@ + *pzOrigCol = zOrigCol; + } + #endif +- if( pEstWidth ) *pEstWidth = estWidth; + return zType; + } + +@@ -118968,7 +125687,7 @@ + const char *zOrigDb = 0; + const char *zOrigTab = 0; + const char *zOrigCol = 0; +- zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, 0); ++ zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol); + + /* The vdbe must make its own copy of the column-type and other + ** column specific strings, in case the schema is reset before this +@@ -118978,7 +125697,7 @@ + sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT); + sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT); + #else +- zType = columnType(&sNC, p, 0, 0, 0, 0); ++ zType = columnType(&sNC, p, 0, 0, 0); + #endif + sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT); + } +@@ -119008,9 +125727,9 @@ + ** other words, the zSpan of the result expression. + ** + ** short=ON, full=OFF: (This is the default setting). If the result +-** refers directly to a table column, then the result +-** column name is just the table column name: COLUMN. +-** Otherwise use zSpan. ++** refers directly to a table column, then the ++** result column name is just the table column ++** name: COLUMN. Otherwise use zSpan. + ** + ** full=ON, short=ANY: If the result refers directly to a table column, + ** then the result column name with the table name +@@ -119036,9 +125755,10 @@ + } + #endif + +- if( pParse->colNamesSet || db->mallocFailed ) return; ++ if( pParse->colNamesSet ) return; + /* Column names are determined by the left-most term of a compound select */ + while( pSelect->pPrior ) pSelect = pSelect->pPrior; ++ SELECTTRACE(1,pParse,pSelect,("generating column names\n")); + pTabList = pSelect->pSrc; + pEList = pSelect->pEList; + assert( v!=0 ); +@@ -119051,6 +125771,8 @@ + Expr *p = pEList->a[i].pExpr; + + assert( p!=0 ); ++ assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */ ++ assert( p->op!=TK_COLUMN || p->y.pTab!=0 ); /* Covering idx not yet coded */ + if( pEList->a[i].zName ){ + /* An AS clause always takes first priority */ + char *zName = pEList->a[i].zName; +@@ -119058,7 +125780,7 @@ + }else if( srcName && p->op==TK_COLUMN ){ + char *zCol; + int iCol = p->iColumn; +- pTab = p->pTab; ++ pTab = p->y.pTab; + assert( pTab!=0 ); + if( iCol<0 ) iCol = pTab->iPKey; + assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) ); +@@ -119125,6 +125847,7 @@ + nCol = pEList->nExpr; + aCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol); + testcase( aCol==0 ); ++ if( nCol>32767 ) nCol = 32767; + }else{ + nCol = 0; + aCol = 0; +@@ -119144,10 +125867,12 @@ + pColExpr = pColExpr->pRight; + assert( pColExpr!=0 ); + } +- if( pColExpr->op==TK_COLUMN && pColExpr->pTab!=0 ){ ++ assert( pColExpr->op!=TK_AGG_COLUMN ); ++ if( pColExpr->op==TK_COLUMN ){ + /* For columns use the column name name */ + int iCol = pColExpr->iColumn; +- Table *pTab = pColExpr->pTab; ++ Table *pTab = pColExpr->y.pTab; ++ assert( pTab!=0 ); + if( iCol<0 ) iCol = pTab->iPKey; + zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid"; + }else if( pColExpr->op==TK_ID ){ +@@ -119219,7 +125944,6 @@ + int i; + Expr *p; + struct ExprList_item *a; +- u64 szAll = 0; + + assert( pSelect!=0 ); + assert( (pSelect->selFlags & SF_Resolved)!=0 ); +@@ -119232,10 +125956,11 @@ + const char *zType; + int n, m; + p = a[i].pExpr; +- zType = columnType(&sNC, p, 0, 0, 0, &pCol->szEst); +- szAll += pCol->szEst; ++ zType = columnType(&sNC, p, 0, 0, 0); ++ /* pCol->szEst = ... // Column size est for SELECT tables never used */ + pCol->affinity = sqlite3ExprAffinity(p); +- if( zType && (m = sqlite3Strlen30(zType))>0 ){ ++ if( zType ){ ++ m = sqlite3Strlen30(zType); + n = sqlite3Strlen30(pCol->zName); + pCol->zName = sqlite3DbReallocOrFree(db, pCol->zName, n+m+2); + if( pCol->zName ){ +@@ -119249,7 +125974,7 @@ + pCol->zColl = sqlite3DbStrDup(db, pColl->zName); + } + } +- pTab->szTabRow = sqlite3LogEst(szAll*4); ++ pTab->szTabRow = 1; /* Any non-zero value works */ + } + + /* +@@ -119292,25 +126017,22 @@ + ** Get a VDBE for the given parser context. Create a new one if necessary. + ** If an error occurs, return NULL and leave a message in pParse. + */ +-static SQLITE_NOINLINE Vdbe *allocVdbe(Parse *pParse){ +- Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(pParse); +- if( v ) sqlite3VdbeAddOp2(v, OP_Init, 0, 1); ++SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse *pParse){ ++ if( pParse->pVdbe ){ ++ return pParse->pVdbe; ++ } + if( pParse->pToplevel==0 + && OptimizationEnabled(pParse->db,SQLITE_FactorOutConst) + ){ + pParse->okConstFactor = 1; + } +- return v; ++ return sqlite3VdbeCreate(pParse); + } +-SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse *pParse){ +- Vdbe *v = pParse->pVdbe; +- return v ? v : allocVdbe(pParse); +-} + + + /* + ** Compute the iLimit and iOffset fields of the SELECT based on the +-** pLimit and pOffset expressions. pLimit and pOffset hold the expressions ++** pLimit expressions. pLimit->pLeft and pLimit->pRight hold the expressions + ** that appear in the original SQL statement after the LIMIT and OFFSET + ** keywords. Or NULL if those keywords are omitted. iLimit and iOffset + ** are the integer memory register numbers for counters used to compute +@@ -119318,8 +126040,8 @@ + ** iLimit and iOffset are negative. + ** + ** This routine changes the values of iLimit and iOffset only if +-** a limit or offset is defined by pLimit and pOffset. iLimit and +-** iOffset should have been preset to appropriate default values (zero) ++** a limit or offset is defined by pLimit->pLeft and pLimit->pRight. iLimit ++** and iOffset should have been preset to appropriate default values (zero) + ** prior to calling this routine. + ** + ** The iOffset register (if it exists) is initialized to the value +@@ -119326,7 +126048,7 @@ + ** of the OFFSET. The iLimit register is initialized to LIMIT. Register + ** iOffset+1 is initialized to LIMIT+OFFSET. + ** +-** Only if pLimit!=0 or pOffset!=0 do the limit registers get ++** Only if pLimit->pLeft!=0 do the limit registers get + ** redefined. The UNION ALL operator uses this property to force + ** the reuse of the same limit and offset registers across multiple + ** SELECT statements. +@@ -119336,6 +126058,8 @@ + int iLimit = 0; + int iOffset; + int n; ++ Expr *pLimit = p->pLimit; ++ + if( p->iLimit ) return; + + /* +@@ -119344,13 +126068,13 @@ + ** The current implementation interprets "LIMIT 0" to mean + ** no rows. + */ +- sqlite3ExprCacheClear(pParse); +- assert( p->pOffset==0 || p->pLimit!=0 ); +- if( p->pLimit ){ ++ if( pLimit ){ ++ assert( pLimit->op==TK_LIMIT ); ++ assert( pLimit->pLeft!=0 ); + p->iLimit = iLimit = ++pParse->nMem; + v = sqlite3GetVdbe(pParse); + assert( v!=0 ); +- if( sqlite3ExprIsInteger(p->pLimit, &n) ){ ++ if( sqlite3ExprIsInteger(pLimit->pLeft, &n) ){ + sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit); + VdbeComment((v, "LIMIT counter")); + if( n==0 ){ +@@ -119360,15 +126084,15 @@ + p->selFlags |= SF_FixedLimit; + } + }else{ +- sqlite3ExprCode(pParse, p->pLimit, iLimit); ++ sqlite3ExprCode(pParse, pLimit->pLeft, iLimit); + sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeCoverage(v); + VdbeComment((v, "LIMIT counter")); + sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, iBreak); VdbeCoverage(v); + } +- if( p->pOffset ){ ++ if( pLimit->pRight ){ + p->iOffset = iOffset = ++pParse->nMem; + pParse->nMem++; /* Allocate an extra register for limit+offset */ +- sqlite3ExprCode(pParse, p->pOffset, iOffset); ++ sqlite3ExprCode(pParse, pLimit->pRight, iOffset); + sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v); + VdbeComment((v, "OFFSET counter")); + sqlite3VdbeAddOp3(v, OP_OffsetLimit, iLimit, iOffset+1, iOffset); +@@ -119498,9 +126222,16 @@ + int i; /* Loop counter */ + int rc; /* Result code */ + ExprList *pOrderBy; /* The ORDER BY clause */ +- Expr *pLimit, *pOffset; /* Saved LIMIT and OFFSET */ ++ Expr *pLimit; /* Saved LIMIT and OFFSET */ + int regLimit, regOffset; /* Registers used by LIMIT and OFFSET */ + ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( p->pWin ){ ++ sqlite3ErrorMsg(pParse, "cannot use window functions in recursive queries"); ++ return; ++ } ++#endif ++ + /* Obtain authorization to do a recursive query */ + if( sqlite3AuthCheck(pParse, SQLITE_RECURSIVE, 0, 0, 0) ) return; + +@@ -119509,10 +126240,9 @@ + p->nSelectRow = 320; /* 4 billion rows */ + computeLimitRegisters(pParse, p, addrBreak); + pLimit = p->pLimit; +- pOffset = p->pOffset; + regLimit = p->iLimit; + regOffset = p->iOffset; +- p->pLimit = p->pOffset = 0; ++ p->pLimit = 0; + p->iLimit = p->iOffset = 0; + pOrderBy = p->pOrderBy; + +@@ -119558,6 +126288,7 @@ + + /* Store the results of the setup-query in Queue. */ + pSetup->pNext = 0; ++ ExplainQueryPlan((pParse, 1, "SETUP")); + rc = sqlite3Select(pParse, pSetup, &destQueue); + pSetup->pNext = p; + if( rc ) goto end_of_recursive_query; +@@ -119577,7 +126308,7 @@ + /* Output the single row in Current */ + addrCont = sqlite3VdbeMakeLabel(v); + codeOffset(v, regOffset, addrCont); +- selectInnerLoop(pParse, p, p->pEList, iCurrent, ++ selectInnerLoop(pParse, p, iCurrent, + 0, 0, pDest, addrCont, addrBreak); + if( regLimit ){ + sqlite3VdbeAddOp2(v, OP_DecrJumpZero, regLimit, addrBreak); +@@ -119592,6 +126323,7 @@ + sqlite3ErrorMsg(pParse, "recursive aggregate queries not supported"); + }else{ + p->pPrior = 0; ++ ExplainQueryPlan((pParse, 1, "RECURSIVE STEP")); + sqlite3Select(pParse, p, &destQueue); + assert( p->pPrior==0 ); + p->pPrior = pSetup; +@@ -119605,7 +126337,6 @@ + sqlite3ExprListDelete(pParse->db, p->pOrderBy); + p->pOrderBy = pOrderBy; + p->pLimit = pLimit; +- p->pOffset = pOffset; + return; + } + #endif /* SQLITE_OMIT_CTE */ +@@ -119624,9 +126355,14 @@ + ** on a VALUES clause. + ** + ** Because the Select object originates from a VALUES clause: +-** (1) It has no LIMIT or OFFSET ++** (1) There is no LIMIT or OFFSET or else there is a LIMIT of exactly 1 + ** (2) All terms are UNION ALL + ** (3) There is no ORDER BY clause ++** ++** The "LIMIT of exactly 1" case of condition (1) comes about when a VALUES ++** clause occurs within scalar expression (ex: "SELECT (VALUES(1),(2),(3))"). ++** The sqlite3CodeSubselect will have added the LIMIT 1 clause in tht case. ++** Since the limit is exactly 1, we only need to evalutes the left-most VALUES. + */ + static int multiSelectValues( + Parse *pParse, /* Parsing context */ +@@ -119633,27 +126369,24 @@ + Select *p, /* The right-most of SELECTs to be coded */ + SelectDest *pDest /* What to do with query results */ + ){ +- Select *pPrior; + int nRow = 1; + int rc = 0; ++ int bShowAll = p->pLimit==0; + assert( p->selFlags & SF_MultiValue ); + do{ + assert( p->selFlags & SF_Values ); + assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) ); +- assert( p->pLimit==0 ); +- assert( p->pOffset==0 ); + assert( p->pNext==0 || p->pEList->nExpr==p->pNext->pEList->nExpr ); + if( p->pPrior==0 ) break; + assert( p->pPrior->pNext==p ); + p = p->pPrior; +- nRow++; ++ nRow += bShowAll; + }while(1); ++ ExplainQueryPlan((pParse, 0, "SCAN %d CONSTANT ROW%s", nRow, ++ nRow==1 ? "" : "S")); + while( p ){ +- pPrior = p->pPrior; +- p->pPrior = 0; +- rc = sqlite3Select(pParse, p, pDest); +- p->pPrior = pPrior; +- if( rc ) break; ++ selectInnerLoop(pParse, p, -1, 0, 0, pDest, 1, 1); ++ if( !bShowAll ) break; + p->nSelectRow = nRow; + p = p->pNext; + } +@@ -119702,10 +126435,6 @@ + SelectDest dest; /* Alternative data destination */ + Select *pDelete = 0; /* Chain of simple selects to delete */ + sqlite3 *db; /* Database connection */ +-#ifndef SQLITE_OMIT_EXPLAIN +- int iSub1 = 0; /* EQP id of left-hand query */ +- int iSub2 = 0; /* EQP id of right-hand query */ +-#endif + + /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only + ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT. +@@ -119715,18 +126444,12 @@ + db = pParse->db; + pPrior = p->pPrior; + dest = *pDest; +- if( pPrior->pOrderBy ){ +- sqlite3ErrorMsg(pParse,"ORDER BY clause should come after %s not before", +- selectOpName(p->op)); ++ if( pPrior->pOrderBy || pPrior->pLimit ){ ++ sqlite3ErrorMsg(pParse,"%s clause should come after %s not before", ++ pPrior->pOrderBy!=0 ? "ORDER BY" : "LIMIT", selectOpName(p->op)); + rc = 1; + goto multi_select_end; + } +- if( pPrior->pLimit ){ +- sqlite3ErrorMsg(pParse,"LIMIT clause should come after %s not before", +- selectOpName(p->op)); +- rc = 1; +- goto multi_select_end; +- } + + v = sqlite3GetVdbe(pParse); + assert( v!=0 ); /* The VDBE already created by calling function */ +@@ -119762,226 +126485,231 @@ + */ + if( p->pOrderBy ){ + return multiSelectOrderBy(pParse, p, pDest); +- }else ++ }else{ + +- /* Generate code for the left and right SELECT statements. +- */ +- switch( p->op ){ +- case TK_ALL: { +- int addr = 0; +- int nLimit; +- assert( !pPrior->pLimit ); +- pPrior->iLimit = p->iLimit; +- pPrior->iOffset = p->iOffset; +- pPrior->pLimit = p->pLimit; +- pPrior->pOffset = p->pOffset; +- explainSetInteger(iSub1, pParse->iNextSelectId); +- rc = sqlite3Select(pParse, pPrior, &dest); +- p->pLimit = 0; +- p->pOffset = 0; +- if( rc ){ +- goto multi_select_end; ++#ifndef SQLITE_OMIT_EXPLAIN ++ if( pPrior->pPrior==0 ){ ++ ExplainQueryPlan((pParse, 1, "COMPOUND QUERY")); ++ ExplainQueryPlan((pParse, 1, "LEFT-MOST SUBQUERY")); ++ } ++#endif ++ ++ /* Generate code for the left and right SELECT statements. ++ */ ++ switch( p->op ){ ++ case TK_ALL: { ++ int addr = 0; ++ int nLimit; ++ assert( !pPrior->pLimit ); ++ pPrior->iLimit = p->iLimit; ++ pPrior->iOffset = p->iOffset; ++ pPrior->pLimit = p->pLimit; ++ rc = sqlite3Select(pParse, pPrior, &dest); ++ p->pLimit = 0; ++ if( rc ){ ++ goto multi_select_end; ++ } ++ p->pPrior = 0; ++ p->iLimit = pPrior->iLimit; ++ p->iOffset = pPrior->iOffset; ++ if( p->iLimit ){ ++ addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); ++ VdbeComment((v, "Jump ahead if LIMIT reached")); ++ if( p->iOffset ){ ++ sqlite3VdbeAddOp3(v, OP_OffsetLimit, ++ p->iLimit, p->iOffset+1, p->iOffset); ++ } ++ } ++ ExplainQueryPlan((pParse, 1, "UNION ALL")); ++ rc = sqlite3Select(pParse, p, &dest); ++ testcase( rc!=SQLITE_OK ); ++ pDelete = p->pPrior; ++ p->pPrior = pPrior; ++ p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); ++ if( pPrior->pLimit ++ && sqlite3ExprIsInteger(pPrior->pLimit->pLeft, &nLimit) ++ && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit) ++ ){ ++ p->nSelectRow = sqlite3LogEst((u64)nLimit); ++ } ++ if( addr ){ ++ sqlite3VdbeJumpHere(v, addr); ++ } ++ break; + } +- p->pPrior = 0; +- p->iLimit = pPrior->iLimit; +- p->iOffset = pPrior->iOffset; +- if( p->iLimit ){ +- addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); +- VdbeComment((v, "Jump ahead if LIMIT reached")); +- if( p->iOffset ){ +- sqlite3VdbeAddOp3(v, OP_OffsetLimit, +- p->iLimit, p->iOffset+1, p->iOffset); ++ case TK_EXCEPT: ++ case TK_UNION: { ++ int unionTab; /* Cursor number of the temp table holding result */ ++ u8 op = 0; /* One of the SRT_ operations to apply to self */ ++ int priorOp; /* The SRT_ operation to apply to prior selects */ ++ Expr *pLimit; /* Saved values of p->nLimit */ ++ int addr; ++ SelectDest uniondest; ++ ++ testcase( p->op==TK_EXCEPT ); ++ testcase( p->op==TK_UNION ); ++ priorOp = SRT_Union; ++ if( dest.eDest==priorOp ){ ++ /* We can reuse a temporary table generated by a SELECT to our ++ ** right. ++ */ ++ assert( p->pLimit==0 ); /* Not allowed on leftward elements */ ++ unionTab = dest.iSDParm; ++ }else{ ++ /* We will need to create our own temporary table to hold the ++ ** intermediate results. ++ */ ++ unionTab = pParse->nTab++; ++ assert( p->pOrderBy==0 ); ++ addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0); ++ assert( p->addrOpenEphm[0] == -1 ); ++ p->addrOpenEphm[0] = addr; ++ findRightmost(p)->selFlags |= SF_UsesEphemeral; ++ assert( p->pEList ); + } ++ ++ /* Code the SELECT statements to our left ++ */ ++ assert( !pPrior->pOrderBy ); ++ sqlite3SelectDestInit(&uniondest, priorOp, unionTab); ++ rc = sqlite3Select(pParse, pPrior, &uniondest); ++ if( rc ){ ++ goto multi_select_end; ++ } ++ ++ /* Code the current SELECT statement ++ */ ++ if( p->op==TK_EXCEPT ){ ++ op = SRT_Except; ++ }else{ ++ assert( p->op==TK_UNION ); ++ op = SRT_Union; ++ } ++ p->pPrior = 0; ++ pLimit = p->pLimit; ++ p->pLimit = 0; ++ uniondest.eDest = op; ++ ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", ++ selectOpName(p->op))); ++ rc = sqlite3Select(pParse, p, &uniondest); ++ testcase( rc!=SQLITE_OK ); ++ /* Query flattening in sqlite3Select() might refill p->pOrderBy. ++ ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */ ++ sqlite3ExprListDelete(db, p->pOrderBy); ++ pDelete = p->pPrior; ++ p->pPrior = pPrior; ++ p->pOrderBy = 0; ++ if( p->op==TK_UNION ){ ++ p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); ++ } ++ sqlite3ExprDelete(db, p->pLimit); ++ p->pLimit = pLimit; ++ p->iLimit = 0; ++ p->iOffset = 0; ++ ++ /* Convert the data in the temporary table into whatever form ++ ** it is that we currently need. ++ */ ++ assert( unionTab==dest.iSDParm || dest.eDest!=priorOp ); ++ if( dest.eDest!=priorOp ){ ++ int iCont, iBreak, iStart; ++ assert( p->pEList ); ++ iBreak = sqlite3VdbeMakeLabel(v); ++ iCont = sqlite3VdbeMakeLabel(v); ++ computeLimitRegisters(pParse, p, iBreak); ++ sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v); ++ iStart = sqlite3VdbeCurrentAddr(v); ++ selectInnerLoop(pParse, p, unionTab, ++ 0, 0, &dest, iCont, iBreak); ++ sqlite3VdbeResolveLabel(v, iCont); ++ sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v); ++ sqlite3VdbeResolveLabel(v, iBreak); ++ sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); ++ } ++ break; + } +- explainSetInteger(iSub2, pParse->iNextSelectId); +- rc = sqlite3Select(pParse, p, &dest); +- testcase( rc!=SQLITE_OK ); +- pDelete = p->pPrior; +- p->pPrior = pPrior; +- p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); +- if( pPrior->pLimit +- && sqlite3ExprIsInteger(pPrior->pLimit, &nLimit) +- && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit) +- ){ +- p->nSelectRow = sqlite3LogEst((u64)nLimit); +- } +- if( addr ){ +- sqlite3VdbeJumpHere(v, addr); +- } +- break; +- } +- case TK_EXCEPT: +- case TK_UNION: { +- int unionTab; /* Cursor number of the temporary table holding result */ +- u8 op = 0; /* One of the SRT_ operations to apply to self */ +- int priorOp; /* The SRT_ operation to apply to prior selects */ +- Expr *pLimit, *pOffset; /* Saved values of p->nLimit and p->nOffset */ +- int addr; +- SelectDest uniondest; +- +- testcase( p->op==TK_EXCEPT ); +- testcase( p->op==TK_UNION ); +- priorOp = SRT_Union; +- if( dest.eDest==priorOp ){ +- /* We can reuse a temporary table generated by a SELECT to our +- ** right. ++ default: assert( p->op==TK_INTERSECT ); { ++ int tab1, tab2; ++ int iCont, iBreak, iStart; ++ Expr *pLimit; ++ int addr; ++ SelectDest intersectdest; ++ int r1; ++ ++ /* INTERSECT is different from the others since it requires ++ ** two temporary tables. Hence it has its own case. Begin ++ ** by allocating the tables we will need. + */ +- assert( p->pLimit==0 ); /* Not allowed on leftward elements */ +- assert( p->pOffset==0 ); /* Not allowed on leftward elements */ +- unionTab = dest.iSDParm; +- }else{ +- /* We will need to create our own temporary table to hold the +- ** intermediate results. +- */ +- unionTab = pParse->nTab++; ++ tab1 = pParse->nTab++; ++ tab2 = pParse->nTab++; + assert( p->pOrderBy==0 ); +- addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0); ++ ++ addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0); + assert( p->addrOpenEphm[0] == -1 ); + p->addrOpenEphm[0] = addr; + findRightmost(p)->selFlags |= SF_UsesEphemeral; + assert( p->pEList ); +- } +- +- /* Code the SELECT statements to our left +- */ +- assert( !pPrior->pOrderBy ); +- sqlite3SelectDestInit(&uniondest, priorOp, unionTab); +- explainSetInteger(iSub1, pParse->iNextSelectId); +- rc = sqlite3Select(pParse, pPrior, &uniondest); +- if( rc ){ +- goto multi_select_end; +- } +- +- /* Code the current SELECT statement +- */ +- if( p->op==TK_EXCEPT ){ +- op = SRT_Except; +- }else{ +- assert( p->op==TK_UNION ); +- op = SRT_Union; +- } +- p->pPrior = 0; +- pLimit = p->pLimit; +- p->pLimit = 0; +- pOffset = p->pOffset; +- p->pOffset = 0; +- uniondest.eDest = op; +- explainSetInteger(iSub2, pParse->iNextSelectId); +- rc = sqlite3Select(pParse, p, &uniondest); +- testcase( rc!=SQLITE_OK ); +- /* Query flattening in sqlite3Select() might refill p->pOrderBy. +- ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */ +- sqlite3ExprListDelete(db, p->pOrderBy); +- pDelete = p->pPrior; +- p->pPrior = pPrior; +- p->pOrderBy = 0; +- if( p->op==TK_UNION ){ +- p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); +- } +- sqlite3ExprDelete(db, p->pLimit); +- p->pLimit = pLimit; +- p->pOffset = pOffset; +- p->iLimit = 0; +- p->iOffset = 0; +- +- /* Convert the data in the temporary table into whatever form +- ** it is that we currently need. +- */ +- assert( unionTab==dest.iSDParm || dest.eDest!=priorOp ); +- if( dest.eDest!=priorOp ){ +- int iCont, iBreak, iStart; ++ ++ /* Code the SELECTs to our left into temporary table "tab1". ++ */ ++ sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1); ++ rc = sqlite3Select(pParse, pPrior, &intersectdest); ++ if( rc ){ ++ goto multi_select_end; ++ } ++ ++ /* Code the current SELECT into temporary table "tab2" ++ */ ++ addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0); ++ assert( p->addrOpenEphm[1] == -1 ); ++ p->addrOpenEphm[1] = addr; ++ p->pPrior = 0; ++ pLimit = p->pLimit; ++ p->pLimit = 0; ++ intersectdest.iSDParm = tab2; ++ ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", ++ selectOpName(p->op))); ++ rc = sqlite3Select(pParse, p, &intersectdest); ++ testcase( rc!=SQLITE_OK ); ++ pDelete = p->pPrior; ++ p->pPrior = pPrior; ++ if( p->nSelectRow>pPrior->nSelectRow ){ ++ p->nSelectRow = pPrior->nSelectRow; ++ } ++ sqlite3ExprDelete(db, p->pLimit); ++ p->pLimit = pLimit; ++ ++ /* Generate code to take the intersection of the two temporary ++ ** tables. ++ */ + assert( p->pEList ); + iBreak = sqlite3VdbeMakeLabel(v); + iCont = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, iBreak); +- sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v); +- iStart = sqlite3VdbeCurrentAddr(v); +- selectInnerLoop(pParse, p, p->pEList, unionTab, ++ sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v); ++ r1 = sqlite3GetTempReg(pParse); ++ iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1); ++ sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); ++ VdbeCoverage(v); ++ sqlite3ReleaseTempReg(pParse, r1); ++ selectInnerLoop(pParse, p, tab1, + 0, 0, &dest, iCont, iBreak); + sqlite3VdbeResolveLabel(v, iCont); +- sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v); ++ sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v); + sqlite3VdbeResolveLabel(v, iBreak); +- sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); ++ sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); ++ sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); ++ break; + } +- break; + } +- default: assert( p->op==TK_INTERSECT ); { +- int tab1, tab2; +- int iCont, iBreak, iStart; +- Expr *pLimit, *pOffset; +- int addr; +- SelectDest intersectdest; +- int r1; +- +- /* INTERSECT is different from the others since it requires +- ** two temporary tables. Hence it has its own case. Begin +- ** by allocating the tables we will need. +- */ +- tab1 = pParse->nTab++; +- tab2 = pParse->nTab++; +- assert( p->pOrderBy==0 ); +- +- addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0); +- assert( p->addrOpenEphm[0] == -1 ); +- p->addrOpenEphm[0] = addr; +- findRightmost(p)->selFlags |= SF_UsesEphemeral; +- assert( p->pEList ); +- +- /* Code the SELECTs to our left into temporary table "tab1". +- */ +- sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1); +- explainSetInteger(iSub1, pParse->iNextSelectId); +- rc = sqlite3Select(pParse, pPrior, &intersectdest); +- if( rc ){ +- goto multi_select_end; +- } +- +- /* Code the current SELECT into temporary table "tab2" +- */ +- addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0); +- assert( p->addrOpenEphm[1] == -1 ); +- p->addrOpenEphm[1] = addr; +- p->pPrior = 0; +- pLimit = p->pLimit; +- p->pLimit = 0; +- pOffset = p->pOffset; +- p->pOffset = 0; +- intersectdest.iSDParm = tab2; +- explainSetInteger(iSub2, pParse->iNextSelectId); +- rc = sqlite3Select(pParse, p, &intersectdest); +- testcase( rc!=SQLITE_OK ); +- pDelete = p->pPrior; +- p->pPrior = pPrior; +- if( p->nSelectRow>pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow; +- sqlite3ExprDelete(db, p->pLimit); +- p->pLimit = pLimit; +- p->pOffset = pOffset; +- +- /* Generate code to take the intersection of the two temporary +- ** tables. +- */ +- assert( p->pEList ); +- iBreak = sqlite3VdbeMakeLabel(v); +- iCont = sqlite3VdbeMakeLabel(v); +- computeLimitRegisters(pParse, p, iBreak); +- sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v); +- r1 = sqlite3GetTempReg(pParse); +- iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1); +- sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); VdbeCoverage(v); +- sqlite3ReleaseTempReg(pParse, r1); +- selectInnerLoop(pParse, p, p->pEList, tab1, +- 0, 0, &dest, iCont, iBreak); +- sqlite3VdbeResolveLabel(v, iCont); +- sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v); +- sqlite3VdbeResolveLabel(v, iBreak); +- sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); +- sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); +- break; ++ ++ #ifndef SQLITE_OMIT_EXPLAIN ++ if( p->pNext==0 ){ ++ ExplainQueryPlanPop(pParse); + } ++ #endif + } +- +- explainComposite(pParse, p->op, iSub1, iSub2, p->op!=TK_ALL); +- ++ + /* Compute collating sequences used by + ** temporary tables needed to implement the compound select. + ** Attach the KeyInfo structure to all temporary tables. +@@ -120132,7 +126860,6 @@ + r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, + r1, pDest->zAffSdst, pIn->nSdst); +- sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1, + pIn->iSdst, pIn->nSdst); + sqlite3ReleaseTempReg(pParse, r1); +@@ -120175,7 +126902,6 @@ + default: { + assert( pDest->eDest==SRT_Output ); + sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iSdst, pIn->nSdst); +- sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst); + break; + } + } +@@ -120319,10 +127045,6 @@ + ExprList *pOrderBy; /* The ORDER BY clause */ + int nOrderBy; /* Number of terms in the ORDER BY clause */ + int *aPermute; /* Mapping from ORDER BY terms to result set columns */ +-#ifndef SQLITE_OMIT_EXPLAIN +- int iSub1; /* EQP id of left-hand query */ +- int iSub2; /* EQP id of right-hand query */ +-#endif + + assert( p->pOrderBy!=0 ); + assert( pKeyDup==0 ); /* "Managed" code needs this. Ticket #3382. */ +@@ -120434,8 +127156,6 @@ + } + sqlite3ExprDelete(db, p->pLimit); + p->pLimit = 0; +- sqlite3ExprDelete(db, p->pOffset); +- p->pOffset = 0; + + regAddrA = ++pParse->nMem; + regAddrB = ++pParse->nMem; +@@ -120444,6 +127164,8 @@ + sqlite3SelectDestInit(&destA, SRT_Coroutine, regAddrA); + sqlite3SelectDestInit(&destB, SRT_Coroutine, regAddrB); + ++ ExplainQueryPlan((pParse, 1, "MERGE (%s)", selectOpName(p->op))); ++ + /* Generate a coroutine to evaluate the SELECT statement to the + ** left of the compound operator - the "A" select. + */ +@@ -120451,7 +127173,7 @@ + addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA); + VdbeComment((v, "left SELECT")); + pPrior->iLimit = regLimitA; +- explainSetInteger(iSub1, pParse->iNextSelectId); ++ ExplainQueryPlan((pParse, 1, "LEFT")); + sqlite3Select(pParse, pPrior, &destA); + sqlite3VdbeEndCoroutine(v, regAddrA); + sqlite3VdbeJumpHere(v, addr1); +@@ -120466,7 +127188,7 @@ + savedOffset = p->iOffset; + p->iLimit = regLimitB; + p->iOffset = 0; +- explainSetInteger(iSub2, pParse->iNextSelectId); ++ ExplainQueryPlan((pParse, 1, "RIGHT")); + sqlite3Select(pParse, p, &destB); + p->iLimit = savedLimit; + p->iOffset = savedOffset; +@@ -120578,7 +127300,7 @@ + + /*** TBD: Insert subroutine calls to close cursors on incomplete + **** subqueries ****/ +- explainComposite(pParse, p->op, iSub1, iSub2, 0); ++ ExplainQueryPlanPop(pParse); + return pParse->nErr!=0; + } + #endif +@@ -120621,7 +127343,9 @@ + Expr *pExpr /* Expr in which substitution occurs */ + ){ + if( pExpr==0 ) return 0; +- if( ExprHasProperty(pExpr, EP_FromJoin) && pExpr->iRightJoinTable==pSubst->iTable ){ ++ if( ExprHasProperty(pExpr, EP_FromJoin) ++ && pExpr->iRightJoinTable==pSubst->iTable ++ ){ + pExpr->iRightJoinTable = pSubst->iNewTable; + } + if( pExpr->op==TK_COLUMN && pExpr->iTable==pSubst->iTable ){ +@@ -120632,7 +127356,7 @@ + Expr *pCopy = pSubst->pEList->a[pExpr->iColumn].pExpr; + Expr ifNullRow; + assert( pSubst->pEList!=0 && pExpr->iColumn<pSubst->pEList->nExpr ); +- assert( pExpr->pLeft==0 && pExpr->pRight==0 ); ++ assert( pExpr->pRight==0 ); + if( sqlite3ExprIsVector(pCopy) ){ + sqlite3VectorErrorMsg(pSubst->pParse, pCopy); + }else{ +@@ -120734,69 +127458,75 @@ + ** exist on the table t1, a complete scan of the data might be + ** avoided. + ** +-** Flattening is only attempted if all of the following are true: ++** Flattening is subject to the following constraints: + ** +-** (1) The subquery and the outer query do not both use aggregates. ++** (**) We no longer attempt to flatten aggregate subqueries. Was: ++** The subquery and the outer query cannot both be aggregates. + ** +-** (2) The subquery is not an aggregate or (2a) the outer query is not a join +-** and (2b) the outer query does not use subqueries other than the one +-** FROM-clause subquery that is a candidate for flattening. (2b is +-** due to ticket [2f7170d73bf9abf80] from 2015-02-09.) ++** (**) We no longer attempt to flatten aggregate subqueries. Was: ++** (2) If the subquery is an aggregate then ++** (2a) the outer query must not be a join and ++** (2b) the outer query must not use subqueries ++** other than the one FROM-clause subquery that is a candidate ++** for flattening. (This is due to ticket [2f7170d73bf9abf80] ++** from 2015-02-09.) + ** +-** (3) The subquery is not the right operand of a LEFT JOIN +-** or (a) the subquery is not itself a join and (b) the FROM clause +-** of the subquery does not contain a virtual table and (c) the +-** outer query is not an aggregate. ++** (3) If the subquery is the right operand of a LEFT JOIN then ++** (3a) the subquery may not be a join and ++** (3b) the FROM clause of the subquery may not contain a virtual ++** table and ++** (3c) the outer query may not be an aggregate. + ** +-** (4) The subquery is not DISTINCT. ++** (4) The subquery can not be DISTINCT. + ** + ** (**) At one point restrictions (4) and (5) defined a subset of DISTINCT + ** sub-queries that were excluded from this optimization. Restriction + ** (4) has since been expanded to exclude all DISTINCT subqueries. + ** +-** (6) The subquery does not use aggregates or the outer query is not +-** DISTINCT. ++** (**) We no longer attempt to flatten aggregate subqueries. Was: ++** If the subquery is aggregate, the outer query may not be DISTINCT. + ** +-** (7) The subquery has a FROM clause. TODO: For subqueries without ++** (7) The subquery must have a FROM clause. TODO: For subqueries without + ** A FROM clause, consider adding a FROM clause with the special + ** table sqlite_once that consists of a single row containing a + ** single NULL. + ** +-** (8) The subquery does not use LIMIT or the outer query is not a join. ++** (8) If the subquery uses LIMIT then the outer query may not be a join. + ** +-** (9) The subquery does not use LIMIT or the outer query does not use +-** aggregates. ++** (9) If the subquery uses LIMIT then the outer query may not be aggregate. + ** + ** (**) Restriction (10) was removed from the code on 2005-02-05 but we + ** accidently carried the comment forward until 2014-09-15. Original +-** text: "The subquery does not use aggregates or the outer query +-** does not use LIMIT." ++** constraint: "If the subquery is aggregate then the outer query ++** may not use LIMIT." + ** +-** (11) The subquery and the outer query do not both have ORDER BY clauses. ++** (11) The subquery and the outer query may not both have ORDER BY clauses. + ** + ** (**) Not implemented. Subsumed into restriction (3). Was previously + ** a separate restriction deriving from ticket #350. + ** +-** (13) The subquery and outer query do not both use LIMIT. ++** (13) The subquery and outer query may not both use LIMIT. + ** +-** (14) The subquery does not use OFFSET. ++** (14) The subquery may not use OFFSET. + ** +-** (15) The outer query is not part of a compound select or the +-** subquery does not have a LIMIT clause. ++** (15) If the outer query is part of a compound select, then the ++** subquery may not use LIMIT. + ** (See ticket #2339 and ticket [02a8e81d44]). + ** +-** (16) The outer query is not an aggregate or the subquery does +-** not contain ORDER BY. (Ticket #2942) This used to not matter ++** (16) If the outer query is aggregate, then the subquery may not ++** use ORDER BY. (Ticket #2942) This used to not matter + ** until we introduced the group_concat() function. + ** +-** (17) The sub-query is not a compound select, or it is a UNION ALL +-** compound clause made up entirely of non-aggregate queries, and +-** the parent query: ++** (17) If the subquery is a compound select, then ++** (17a) all compound operators must be a UNION ALL, and ++** (17b) no terms within the subquery compound may be aggregate ++** or DISTINCT, and ++** (17c) every term within the subquery compound must have a FROM clause ++** (17d) the outer query may not be ++** (17d1) aggregate, or ++** (17d2) DISTINCT, or ++** (17d3) a join. + ** +-** * is not itself part of a compound select, +-** * is not an aggregate or DISTINCT query, and +-** * is not a join +-** + ** 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 +@@ -120811,10 +127541,10 @@ + ** syntax error and return a detailed message. + ** + ** (18) If the sub-query is a compound select, then all terms of the +-** ORDER by clause of the parent must be simple references to ++** ORDER BY clause of the parent must be simple references to + ** columns of the sub-query. + ** +-** (19) The subquery does not use LIMIT or the outer query does not ++** (19) If the subquery uses LIMIT then the outer query may not + ** have a WHERE clause. + ** + ** (20) If the sub-query is a compound select, then it must not use +@@ -120823,25 +127553,31 @@ + ** appear as unmodified result columns in the outer query. But we + ** have other optimizations in mind to deal with that case. + ** +-** (21) The subquery does not use LIMIT or the outer query is not ++** (21) If the subquery uses LIMIT then the outer query may not be + ** DISTINCT. (See ticket [752e1646fc]). + ** +-** (22) The subquery is not a recursive CTE. ++** (22) The subquery may not be a recursive CTE. + ** +-** (23) The parent is not a recursive CTE, or the sub-query is not a +-** compound query. This restriction is because transforming the ++** (**) Subsumed into restriction (17d3). Was: If the outer query is ++** a recursive CTE, then the sub-query may not be a compound query. ++** This restriction is because transforming the + ** parent to a compound query confuses the code that handles + ** recursive queries in multiSelect(). + ** +-** (24) The subquery is not an aggregate that uses the built-in min() or ++** (**) We no longer attempt to flatten aggregate subqueries. Was: ++** The subquery may not be an aggregate that uses the built-in min() or + ** or max() functions. (Without this restriction, a query like: + ** "SELECT x FROM (SELECT max(y), x FROM t1)" would not necessarily + ** return the value X for which Y was maximal.) + ** ++** (25) If either the subquery or the parent query contains a window ++** function in the select list or ORDER BY clause, flattening ++** is not attempted. + ** ++** + ** In this routine, the "p" parameter is a pointer to the outer query. + ** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query +-** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates. ++** uses aggregates. + ** + ** If flattening is not attempted, this routine is a no-op and returns 0. + ** If flattening is attempted this routine returns 1. +@@ -120853,8 +127589,7 @@ + Parse *pParse, /* Parsing context */ + Select *p, /* The parent or outer SELECT statement */ + int iFrom, /* Index in p->pSrc->a[] of the inner subquery */ +- int isAgg, /* True if outer SELECT uses aggregate functions */ +- int subqueryIsAgg /* True if the subquery uses aggregate functions */ ++ int isAgg /* True if outer SELECT uses aggregate functions */ + ){ + const char *zSavedAuthContext = pParse->zAuthContext; + Select *pParent; /* Current UNION ALL term of the other query */ +@@ -120873,7 +127608,7 @@ + /* Check to see if flattening is permitted. Return 0 if not. + */ + assert( p!=0 ); +- assert( p->pPrior==0 ); /* Unable to flatten compound queries */ ++ assert( p->pPrior==0 ); + if( OptimizationDisabled(db, SQLITE_QueryFlattener) ) return 0; + pSrc = p->pSrc; + assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc ); +@@ -120881,17 +127616,11 @@ + iParent = pSubitem->iCursor; + pSub = pSubitem->pSelect; + assert( pSub!=0 ); +- if( subqueryIsAgg ){ +- if( isAgg ) return 0; /* Restriction (1) */ +- if( pSrc->nSrc>1 ) return 0; /* Restriction (2a) */ +- if( (p->pWhere && ExprHasProperty(p->pWhere,EP_Subquery)) +- || (sqlite3ExprListFlags(p->pEList) & EP_Subquery)!=0 +- || (sqlite3ExprListFlags(p->pOrderBy) & EP_Subquery)!=0 +- ){ +- return 0; /* Restriction (2b) */ +- } +- } + ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( p->pWin || pSub->pWin ) return 0; /* Restriction (25) */ ++#endif ++ + pSubSrc = pSub->pSrc; + assert( pSubSrc ); + /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants, +@@ -120900,18 +127629,15 @@ + ** became arbitrary expressions, we were forced to add restrictions (13) + ** and (14). */ + if( pSub->pLimit && p->pLimit ) return 0; /* Restriction (13) */ +- if( pSub->pOffset ) return 0; /* Restriction (14) */ ++ if( pSub->pLimit && pSub->pLimit->pRight ) return 0; /* Restriction (14) */ + if( (p->selFlags & SF_Compound)!=0 && pSub->pLimit ){ + return 0; /* Restriction (15) */ + } + if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */ +- if( pSub->selFlags & SF_Distinct ) return 0; /* Restriction (5) */ ++ if( pSub->selFlags & SF_Distinct ) return 0; /* Restriction (4) */ + if( pSub->pLimit && (pSrc->nSrc>1 || isAgg) ){ + return 0; /* Restrictions (8)(9) */ + } +- if( (p->selFlags & SF_Distinct)!=0 && subqueryIsAgg ){ +- return 0; /* Restriction (6) */ +- } + if( p->pOrderBy && pSub->pOrderBy ){ + return 0; /* Restriction (11) */ + } +@@ -120920,18 +127646,14 @@ + if( pSub->pLimit && (p->selFlags & SF_Distinct)!=0 ){ + return 0; /* Restriction (21) */ + } +- testcase( pSub->selFlags & SF_Recursive ); +- testcase( pSub->selFlags & SF_MinMaxAgg ); +- if( pSub->selFlags & (SF_Recursive|SF_MinMaxAgg) ){ +- return 0; /* Restrictions (22) and (24) */ ++ if( pSub->selFlags & (SF_Recursive) ){ ++ return 0; /* Restrictions (22) */ + } +- if( (p->selFlags & SF_Recursive) && pSub->pPrior ){ +- return 0; /* Restriction (23) */ +- } + + /* + ** If the subquery is the right operand of a LEFT JOIN, then the +- ** subquery may not be a join itself. Example of why this is not allowed: ++ ** subquery may not be a join itself (3a). Example of why this is not ++ ** allowed: + ** + ** t1 LEFT OUTER JOIN (t2 JOIN t3) + ** +@@ -120942,9 +127664,9 @@ + ** which is not at all the same thing. + ** + ** If the subquery is the right operand of a LEFT JOIN, then the outer +- ** query cannot be an aggregate. This is an artifact of the way aggregates +- ** are processed - there is no mechanism to determine if the LEFT JOIN +- ** table should be all-NULL. ++ ** query cannot be an aggregate. (3c) This is an artifact of the way ++ ** aggregates are processed - there is no mechanism to determine if ++ ** the LEFT JOIN table should be all-NULL. + ** + ** See also tickets #306, #350, and #3300. + */ +@@ -120951,19 +127673,21 @@ + if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){ + isLeftJoin = 1; + if( pSubSrc->nSrc>1 || isAgg || IsVirtual(pSubSrc->a[0].pTab) ){ +- return 0; /* Restriction (3) */ ++ /* (3a) (3c) (3b) */ ++ return 0; + } + } + #ifdef SQLITE_EXTRA_IFNULLROW + else if( iFrom>0 && !isAgg ){ + /* Setting isLeftJoin to -1 causes OP_IfNullRow opcodes to be generated for +- ** every reference to any result column from subquery in a join, even though +- ** they are not necessary. This will stress-test the OP_IfNullRow opcode. */ ++ ** every reference to any result column from subquery in a join, even ++ ** though they are not necessary. This will stress-test the OP_IfNullRow ++ ** opcode. */ + isLeftJoin = -1; + } + #endif + +- /* Restriction 17: If the sub-query is a compound SELECT, then it must ++ /* Restriction (17): If the sub-query is a compound SELECT, then it must + ** use only the UNION ALL operator. And none of the simple select queries + ** that make up the compound SELECT are allowed to be aggregate or distinct + ** queries. +@@ -120970,10 +127694,10 @@ + */ + if( pSub->pPrior ){ + if( pSub->pOrderBy ){ +- return 0; /* Restriction 20 */ ++ return 0; /* Restriction (20) */ + } + if( isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){ +- return 0; ++ return 0; /* (17d1), (17d2), or (17d3) */ + } + for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){ + testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ); +@@ -120980,9 +127704,9 @@ + testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate ); + assert( pSub->pSrc!=0 ); + assert( pSub->pEList->nExpr==pSub1->pEList->nExpr ); +- if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0 +- || (pSub1->pPrior && pSub1->op!=TK_ALL) +- || pSub1->pSrc->nSrc<1 ++ if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0 /* (17b) */ ++ || (pSub1->pPrior && pSub1->op!=TK_ALL) /* (17a) */ ++ || pSub1->pSrc->nSrc<1 /* (17c) */ + ){ + return 0; + } +@@ -120989,7 +127713,7 @@ + testcase( pSub1->pSrc->nSrc>1 ); + } + +- /* Restriction 18. */ ++ /* Restriction (18). */ + if( p->pOrderBy ){ + int ii; + for(ii=0; ii<p->pOrderBy->nExpr; ii++){ +@@ -120998,9 +127722,17 @@ + } + } + ++ /* Ex-restriction (23): ++ ** The only way that the recursive part of a CTE can contain a compound ++ ** subquery is for the subquery to be one term of a join. But if the ++ ** subquery is a join, then the flattening has already been stopped by ++ ** restriction (17d3) ++ */ ++ assert( (p->selFlags & SF_Recursive)==0 || pSub->pPrior==0 ); ++ + /***** If we reach this point, flattening is permitted. *****/ +- SELECTTRACE(1,pParse,p,("flatten %s.%p from term %d\n", +- pSub->zSelName, pSub, iFrom)); ++ SELECTTRACE(1,pParse,p,("flatten %u.%p from term %d\n", ++ pSub->selId, pSub, iFrom)); + + /* Authorize the subquery */ + pParse->zAuthContext = pSubitem->zName; +@@ -121045,16 +127777,12 @@ + Select *pNew; + ExprList *pOrderBy = p->pOrderBy; + Expr *pLimit = p->pLimit; +- Expr *pOffset = p->pOffset; + Select *pPrior = p->pPrior; + p->pOrderBy = 0; + p->pSrc = 0; + p->pPrior = 0; + p->pLimit = 0; +- p->pOffset = 0; + pNew = sqlite3SelectDup(db, p, 0); +- sqlite3SelectSetName(pNew, pSub->zSelName); +- p->pOffset = pOffset; + p->pLimit = pLimit; + p->pOrderBy = pOrderBy; + p->pSrc = pSrc; +@@ -121066,9 +127794,8 @@ + if( pPrior ) pPrior->pNext = pNew; + pNew->pNext = p; + p->pPrior = pNew; +- SELECTTRACE(2,pParse,p, +- ("compound-subquery flattener creates %s.%p as peer\n", +- pNew->zSelName, pNew)); ++ SELECTTRACE(2,pParse,p,("compound-subquery flattener" ++ " creates %u as peer\n",pNew->selId)); + } + if( db->mallocFailed ) return 1; + } +@@ -121202,7 +127929,6 @@ + pOrderBy->a[i].u.x.iOrderByCol = 0; + } + assert( pParent->pOrderBy==0 ); +- assert( pSub->pPrior==0 ); + pParent->pOrderBy = pOrderBy; + pSub->pOrderBy = 0; + } +@@ -121210,18 +127936,7 @@ + if( isLeftJoin>0 ){ + setJoinExpr(pWhere, iNewParent); + } +- if( subqueryIsAgg ){ +- assert( pParent->pHaving==0 ); +- pParent->pHaving = pParent->pWhere; +- pParent->pWhere = pWhere; +- pParent->pHaving = sqlite3ExprAnd(db, +- sqlite3ExprDup(db, pSub->pHaving, 0), pParent->pHaving +- ); +- assert( pParent->pGroupBy==0 ); +- pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0); +- }else{ +- pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere); +- } ++ pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere); + if( db->mallocFailed==0 ){ + SubstContext x; + x.pParse = pParse; +@@ -121265,8 +127980,184 @@ + } + #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ + ++/* ++** A structure to keep track of all of the column values that are fixed to ++** a known value due to WHERE clause constraints of the form COLUMN=VALUE. ++*/ ++typedef struct WhereConst WhereConst; ++struct WhereConst { ++ Parse *pParse; /* Parsing context */ ++ int nConst; /* Number for COLUMN=CONSTANT terms */ ++ int nChng; /* Number of times a constant is propagated */ ++ Expr **apExpr; /* [i*2] is COLUMN and [i*2+1] is VALUE */ ++}; + ++/* ++** Add a new entry to the pConst object. Except, do not add duplicate ++** pColumn entires. ++*/ ++static void constInsert( ++ WhereConst *pConst, /* The WhereConst into which we are inserting */ ++ Expr *pColumn, /* The COLUMN part of the constraint */ ++ Expr *pValue /* The VALUE part of the constraint */ ++){ ++ int i; ++ assert( pColumn->op==TK_COLUMN ); + ++ /* 2018-10-25 ticket [cf5ed20f] ++ ** Make sure the same pColumn is not inserted more than once */ ++ for(i=0; i<pConst->nConst; i++){ ++ const Expr *pExpr = pConst->apExpr[i*2]; ++ assert( pExpr->op==TK_COLUMN ); ++ if( pExpr->iTable==pColumn->iTable ++ && pExpr->iColumn==pColumn->iColumn ++ ){ ++ return; /* Already present. Return without doing anything. */ ++ } ++ } ++ ++ pConst->nConst++; ++ pConst->apExpr = sqlite3DbReallocOrFree(pConst->pParse->db, pConst->apExpr, ++ pConst->nConst*2*sizeof(Expr*)); ++ if( pConst->apExpr==0 ){ ++ pConst->nConst = 0; ++ }else{ ++ if( ExprHasProperty(pValue, EP_FixedCol) ) pValue = pValue->pLeft; ++ pConst->apExpr[pConst->nConst*2-2] = pColumn; ++ pConst->apExpr[pConst->nConst*2-1] = pValue; ++ } ++} ++ ++/* ++** Find all terms of COLUMN=VALUE or VALUE=COLUMN in pExpr where VALUE ++** is a constant expression and where the term must be true because it ++** is part of the AND-connected terms of the expression. For each term ++** found, add it to the pConst structure. ++*/ ++static void findConstInWhere(WhereConst *pConst, Expr *pExpr){ ++ Expr *pRight, *pLeft; ++ if( pExpr==0 ) return; ++ if( ExprHasProperty(pExpr, EP_FromJoin) ) return; ++ if( pExpr->op==TK_AND ){ ++ findConstInWhere(pConst, pExpr->pRight); ++ findConstInWhere(pConst, pExpr->pLeft); ++ return; ++ } ++ if( pExpr->op!=TK_EQ ) return; ++ pRight = pExpr->pRight; ++ pLeft = pExpr->pLeft; ++ assert( pRight!=0 ); ++ assert( pLeft!=0 ); ++ if( pRight->op==TK_COLUMN ++ && !ExprHasProperty(pRight, EP_FixedCol) ++ && sqlite3ExprIsConstant(pLeft) ++ && sqlite3IsBinary(sqlite3BinaryCompareCollSeq(pConst->pParse,pLeft,pRight)) ++ ){ ++ constInsert(pConst, pRight, pLeft); ++ }else ++ if( pLeft->op==TK_COLUMN ++ && !ExprHasProperty(pLeft, EP_FixedCol) ++ && sqlite3ExprIsConstant(pRight) ++ && sqlite3IsBinary(sqlite3BinaryCompareCollSeq(pConst->pParse,pLeft,pRight)) ++ ){ ++ constInsert(pConst, pLeft, pRight); ++ } ++} ++ ++/* ++** This is a Walker expression callback. pExpr is a candidate expression ++** to be replaced by a value. If pExpr is equivalent to one of the ++** columns named in pWalker->u.pConst, then overwrite it with its ++** corresponding value. ++*/ ++static int propagateConstantExprRewrite(Walker *pWalker, Expr *pExpr){ ++ int i; ++ WhereConst *pConst; ++ if( pExpr->op!=TK_COLUMN ) return WRC_Continue; ++ if( ExprHasProperty(pExpr, EP_FixedCol) ) return WRC_Continue; ++ pConst = pWalker->u.pConst; ++ for(i=0; i<pConst->nConst; i++){ ++ Expr *pColumn = pConst->apExpr[i*2]; ++ if( pColumn==pExpr ) continue; ++ if( pColumn->iTable!=pExpr->iTable ) continue; ++ if( pColumn->iColumn!=pExpr->iColumn ) continue; ++ /* A match is found. Add the EP_FixedCol property */ ++ pConst->nChng++; ++ ExprClearProperty(pExpr, EP_Leaf); ++ ExprSetProperty(pExpr, EP_FixedCol); ++ assert( pExpr->pLeft==0 ); ++ pExpr->pLeft = sqlite3ExprDup(pConst->pParse->db, pConst->apExpr[i*2+1], 0); ++ break; ++ } ++ return WRC_Prune; ++} ++ ++/* ++** The WHERE-clause constant propagation optimization. ++** ++** If the WHERE clause contains terms of the form COLUMN=CONSTANT or ++** CONSTANT=COLUMN that must be tree (in other words, if the terms top-level ++** AND-connected terms that are not part of a ON clause from a LEFT JOIN) ++** then throughout the query replace all other occurrences of COLUMN ++** with CONSTANT within the WHERE clause. ++** ++** For example, the query: ++** ++** SELECT * FROM t1, t2, t3 WHERE t1.a=39 AND t2.b=t1.a AND t3.c=t2.b ++** ++** Is transformed into ++** ++** SELECT * FROM t1, t2, t3 WHERE t1.a=39 AND t2.b=39 AND t3.c=39 ++** ++** Return true if any transformations where made and false if not. ++** ++** Implementation note: Constant propagation is tricky due to affinity ++** and collating sequence interactions. Consider this example: ++** ++** CREATE TABLE t1(a INT,b TEXT); ++** INSERT INTO t1 VALUES(123,'0123'); ++** SELECT * FROM t1 WHERE a=123 AND b=a; ++** SELECT * FROM t1 WHERE a=123 AND b=123; ++** ++** The two SELECT statements above should return different answers. b=a ++** is alway true because the comparison uses numeric affinity, but b=123 ++** is false because it uses text affinity and '0123' is not the same as '123'. ++** To work around this, the expression tree is not actually changed from ++** "b=a" to "b=123" but rather the "a" in "b=a" is tagged with EP_FixedCol ++** and the "123" value is hung off of the pLeft pointer. Code generator ++** routines know to generate the constant "123" instead of looking up the ++** column value. Also, to avoid collation problems, this optimization is ++** only attempted if the "a=123" term uses the default BINARY collation. ++*/ ++static int propagateConstants( ++ Parse *pParse, /* The parsing context */ ++ Select *p /* The query in which to propagate constants */ ++){ ++ WhereConst x; ++ Walker w; ++ int nChng = 0; ++ x.pParse = pParse; ++ do{ ++ x.nConst = 0; ++ x.nChng = 0; ++ x.apExpr = 0; ++ findConstInWhere(&x, p->pWhere); ++ if( x.nConst ){ ++ memset(&w, 0, sizeof(w)); ++ w.pParse = pParse; ++ w.xExprCallback = propagateConstantExprRewrite; ++ w.xSelectCallback = sqlite3SelectWalkNoop; ++ w.xSelectCallback2 = 0; ++ w.walkerDepth = 0; ++ w.u.pConst = &x; ++ sqlite3WalkExpr(&w, p->pWhere); ++ sqlite3DbFree(x.pParse->db, x.apExpr); ++ nChng += x.nChng; ++ } ++ }while( x.nChng ); ++ return nChng; ++} ++ + #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) + /* + ** Make copies of relevant WHERE clause terms of the outer query into +@@ -121284,22 +128175,40 @@ + ** + ** Do not attempt this optimization if: + ** +-** (1) The inner query is an aggregate. (In that case, we'd really want +-** to copy the outer WHERE-clause terms onto the HAVING clause of the +-** inner query. But they probably won't help there so do not bother.) ++** (1) (** This restriction was removed on 2017-09-29. We used to ++** disallow this optimization for aggregate subqueries, but now ++** it is allowed by putting the extra terms on the HAVING clause. ++** The added HAVING clause is pointless if the subquery lacks ++** a GROUP BY clause. But such a HAVING clause is also harmless ++** so there does not appear to be any reason to add extra logic ++** to suppress it. **) + ** + ** (2) The inner query is the recursive part of a common table expression. + ** + ** (3) The inner query has a LIMIT clause (since the changes to the WHERE +-** close would change the meaning of the LIMIT). ++** clause would change the meaning of the LIMIT). + ** +-** (4) The inner query is the right operand of a LEFT JOIN. (The caller +-** enforces this restriction since this routine does not have enough +-** information to know.) ++** (4) The inner query is the right operand of a LEFT JOIN and the ++** expression to be pushed down does not come from the ON clause ++** on that LEFT JOIN. + ** + ** (5) The WHERE clause expression originates in the ON or USING clause +-** of a LEFT JOIN. ++** of a LEFT JOIN where iCursor is not the right-hand table of that ++** left join. An example: + ** ++** SELECT * ++** FROM (SELECT 1 AS a1 UNION ALL SELECT 2) AS aa ++** JOIN (SELECT 1 AS b2 UNION ALL SELECT 2) AS bb ON (a1=b2) ++** LEFT JOIN (SELECT 8 AS c3 UNION ALL SELECT 9) AS cc ON (b2=2); ++** ++** The correct answer is three rows: (1,1,NULL),(2,2,8),(2,2,9). ++** But if the (b2=2) term were to be pushed down into the bb subquery, ++** then the (1,1,NULL) row would be suppressed. ++** ++** (6) The inner query features one or more window-functions (since ++** changes to the WHERE clause of the inner query could change the ++** window over which window functions are calculated). ++** + ** Return 0 if no changes are made and non-zero if one or more WHERE clause + ** terms are duplicated into the subquery. + */ +@@ -121307,33 +128216,54 @@ + Parse *pParse, /* Parse context (for malloc() and error reporting) */ + Select *pSubq, /* The subquery whose WHERE clause is to be augmented */ + Expr *pWhere, /* The WHERE clause of the outer query */ +- int iCursor /* Cursor number of the subquery */ ++ int iCursor, /* Cursor number of the subquery */ ++ int isLeftJoin /* True if pSubq is the right term of a LEFT JOIN */ + ){ + Expr *pNew; + int nChng = 0; +- Select *pX; /* For looping over compound SELECTs in pSubq */ + if( pWhere==0 ) return 0; +- for(pX=pSubq; pX; pX=pX->pPrior){ +- if( (pX->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){ +- testcase( pX->selFlags & SF_Aggregate ); +- testcase( pX->selFlags & SF_Recursive ); +- testcase( pX!=pSubq ); +- return 0; /* restrictions (1) and (2) */ ++ if( pSubq->selFlags & SF_Recursive ) return 0; /* restriction (2) */ ++ ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( pSubq->pWin ) return 0; /* restriction (6) */ ++#endif ++ ++#ifdef SQLITE_DEBUG ++ /* Only the first term of a compound can have a WITH clause. But make ++ ** sure no other terms are marked SF_Recursive in case something changes ++ ** in the future. ++ */ ++ { ++ Select *pX; ++ for(pX=pSubq; pX; pX=pX->pPrior){ ++ assert( (pX->selFlags & (SF_Recursive))==0 ); + } + } ++#endif ++ + if( pSubq->pLimit!=0 ){ + return 0; /* restriction (3) */ + } + while( pWhere->op==TK_AND ){ +- nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, iCursor); ++ nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, ++ iCursor, isLeftJoin); + pWhere = pWhere->pLeft; + } +- if( ExprHasProperty(pWhere,EP_FromJoin) ) return 0; /* restriction 5 */ ++ if( isLeftJoin ++ && (ExprHasProperty(pWhere,EP_FromJoin)==0 ++ || pWhere->iRightJoinTable!=iCursor) ++ ){ ++ return 0; /* restriction (4) */ ++ } ++ if( ExprHasProperty(pWhere,EP_FromJoin) && pWhere->iRightJoinTable!=iCursor ){ ++ return 0; /* restriction (5) */ ++ } + if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){ + nChng++; + while( pSubq ){ + SubstContext x; + pNew = sqlite3ExprDup(pParse->db, pWhere, 0); ++ unsetJoinExpr(pNew, -1); + x.pParse = pParse; + x.iTable = iCursor; + x.iNewTable = iCursor; +@@ -121340,7 +128270,11 @@ + x.isLeftJoin = 0; + x.pEList = pSubq->pEList; + pNew = substExpr(&x, pNew); +- pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew); ++ if( pSubq->selFlags & SF_Aggregate ){ ++ pSubq->pHaving = sqlite3ExprAnd(pParse->db, pSubq->pHaving, pNew); ++ }else{ ++ pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew); ++ } + pSubq = pSubq->pPrior; + } + } +@@ -121349,42 +128283,44 @@ + #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ + + /* +-** Based on the contents of the AggInfo structure indicated by the first +-** argument, this function checks if the following are true: ++** The pFunc is the only aggregate function in the query. Check to see ++** if the query is a candidate for the min/max optimization. + ** +-** * the query contains just a single aggregate function, +-** * the aggregate function is either min() or max(), and +-** * the argument to the aggregate function is a column value. ++** If 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 ++** and return either WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX depending on ++** whether pFunc is a min() or max() function. + ** +-** If all of the above are true, then WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX +-** is returned as appropriate. Also, *ppMinMax is set to point to the +-** list of arguments passed to the aggregate before returning. ++** If the query is not a candidate for the min/max optimization, return ++** WHERE_ORDERBY_NORMAL (which must be zero). + ** +-** Or, if the conditions above are not met, *ppMinMax is set to 0 and +-** WHERE_ORDERBY_NORMAL is returned. ++** This routine must be called after aggregate functions have been ++** located but before their arguments have been subjected to aggregate ++** analysis. + */ +-static u8 minMaxQuery(AggInfo *pAggInfo, ExprList **ppMinMax){ +- int eRet = WHERE_ORDERBY_NORMAL; /* Return value */ ++static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){ ++ int eRet = WHERE_ORDERBY_NORMAL; /* Return value */ ++ ExprList *pEList = pFunc->x.pList; /* Arguments to agg function */ ++ const char *zFunc; /* Name of aggregate function pFunc */ ++ ExprList *pOrderBy; ++ u8 sortOrder; + +- *ppMinMax = 0; +- if( pAggInfo->nFunc==1 ){ +- Expr *pExpr = pAggInfo->aFunc[0].pExpr; /* Aggregate function */ +- ExprList *pEList = pExpr->x.pList; /* Arguments to agg function */ +- +- assert( pExpr->op==TK_AGG_FUNCTION ); +- if( pEList && pEList->nExpr==1 && pEList->a[0].pExpr->op==TK_AGG_COLUMN ){ +- const char *zFunc = pExpr->u.zToken; +- if( sqlite3StrICmp(zFunc, "min")==0 ){ +- eRet = WHERE_ORDERBY_MIN; +- *ppMinMax = pEList; +- }else if( sqlite3StrICmp(zFunc, "max")==0 ){ +- eRet = WHERE_ORDERBY_MAX; +- *ppMinMax = pEList; +- } +- } ++ assert( *ppMinMax==0 ); ++ assert( pFunc->op==TK_AGG_FUNCTION ); ++ if( pEList==0 || pEList->nExpr!=1 ) return eRet; ++ zFunc = pFunc->u.zToken; ++ if( sqlite3StrICmp(zFunc, "min")==0 ){ ++ eRet = WHERE_ORDERBY_MIN; ++ sortOrder = SQLITE_SO_ASC; ++ }else if( sqlite3StrICmp(zFunc, "max")==0 ){ ++ eRet = WHERE_ORDERBY_MAX; ++ sortOrder = SQLITE_SO_DESC; ++ }else{ ++ return eRet; + } +- +- assert( *ppMinMax==0 || (*ppMinMax)->nExpr==1 ); ++ *ppMinMax = pOrderBy = sqlite3ExprListDup(db, pEList, 0); ++ assert( pOrderBy!=0 || db->mallocFailed ); ++ if( pOrderBy ) pOrderBy->a[0].sortOrder = sortOrder; + return eRet; + } + +@@ -121515,7 +128451,6 @@ + assert( pNew->pPrior!=0 ); + pNew->pPrior->pNext = pNew; + pNew->pLimit = 0; +- pNew->pOffset = 0; + return WRC_Continue; + } + +@@ -121668,7 +128603,8 @@ + ); + return SQLITE_ERROR; + } +- assert( pTab->nTabRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nTabRef==2 )); ++ assert( pTab->nTabRef==1 || ++ ((pSel->selFlags&SF_Recursive) && pTab->nTabRef==2 )); + + pCte->zCteErr = "circular reference: %s"; + pSavedWith = pParse->pWith; +@@ -121725,7 +128661,7 @@ + */ + static void selectPopWith(Walker *pWalker, Select *p){ + Parse *pParse = pWalker->pParse; +- if( pParse->pWith && p->pPrior==0 ){ ++ if( OK_IF_ALWAYS_TRUE(pParse->pWith) && p->pPrior==0 ){ + With *pWith = findRightmost(p)->pWith; + if( pWith!=0 ){ + assert( pParse->pWith==pWith ); +@@ -121738,6 +128674,35 @@ + #endif + + /* ++** The SrcList_item structure passed as the second argument represents a ++** sub-query in the FROM clause of a SELECT statement. This function ++** allocates and populates the SrcList_item.pTab object. If successful, ++** SQLITE_OK is returned. Otherwise, if an OOM error is encountered, ++** SQLITE_NOMEM. ++*/ ++SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse *pParse, struct SrcList_item *pFrom){ ++ Select *pSel = pFrom->pSelect; ++ Table *pTab; ++ ++ assert( pSel ); ++ pFrom->pTab = pTab = sqlite3DbMallocZero(pParse->db, sizeof(Table)); ++ if( pTab==0 ) return SQLITE_NOMEM; ++ pTab->nTabRef = 1; ++ if( pFrom->zAlias ){ ++ pTab->zName = sqlite3DbStrDup(pParse->db, pFrom->zAlias); ++ }else{ ++ pTab->zName = sqlite3MPrintf(pParse->db, "subquery_%u", pSel->selId); ++ } ++ while( pSel->pPrior ){ pSel = pSel->pPrior; } ++ sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol); ++ pTab->iPKey = -1; ++ pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); ++ pTab->tabFlags |= TF_Ephemeral; ++ ++ return SQLITE_OK; ++} ++ ++/* + ** This routine is a Walker callback for "expanding" a SELECT statement. + ** "Expanding" means to do the following: + ** +@@ -121770,19 +128735,19 @@ + sqlite3 *db = pParse->db; + Expr *pE, *pRight, *pExpr; + u16 selFlags = p->selFlags; ++ u32 elistFlags = 0; + + p->selFlags |= SF_Expanded; + if( db->mallocFailed ){ + return WRC_Abort; + } +- if( NEVER(p->pSrc==0) || (selFlags & SF_Expanded)!=0 ){ ++ assert( p->pSrc!=0 ); ++ if( (selFlags & SF_Expanded)!=0 ){ + return WRC_Prune; + } + pTabList = p->pSrc; + pEList = p->pEList; +- if( p->pWith ){ +- sqlite3WithPush(pParse, p->pWith, 0); +- } ++ sqlite3WithPush(pParse, p->pWith, 0); + + /* Make sure cursor numbers have been assigned to all entries in + ** the FROM clause of the SELECT statement. +@@ -121809,15 +128774,7 @@ + assert( pSel!=0 ); + assert( pFrom->pTab==0 ); + if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort; +- pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); +- if( pTab==0 ) return WRC_Abort; +- pTab->nTabRef = 1; +- pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab); +- while( pSel->pPrior ){ pSel = pSel->pPrior; } +- sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol); +- pTab->iPKey = -1; +- pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); +- pTab->tabFlags |= TF_Ephemeral; ++ if( sqlite3ExpandSubquery(pParse, pFrom) ) return WRC_Abort; + #endif + }else{ + /* An ordinary table or view name in the FROM clause */ +@@ -121840,7 +128797,6 @@ + if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort; + assert( pFrom->pSelect==0 ); + pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0); +- sqlite3SelectSetName(pFrom->pSelect, pTab->zName); + nCol = pTab->nCol; + pTab->nCol = -1; + sqlite3WalkSelect(pWalker, pFrom->pSelect); +@@ -121878,6 +128834,7 @@ + assert( pE->op!=TK_DOT || pE->pRight!=0 ); + assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) ); + if( pE->op==TK_DOT && pE->pRight->op==TK_ASTERISK ) break; ++ elistFlags |= pE->flags; + } + if( k<pEList->nExpr ){ + /* +@@ -121893,6 +128850,7 @@ + + for(k=0; k<pEList->nExpr; k++){ + pE = a[k].pExpr; ++ elistFlags |= pE->flags; + pRight = pE->pRight; + assert( pE->op!=TK_DOT || pRight!=0 ); + if( pE->op!=TK_ASTERISK +@@ -122022,12 +128980,15 @@ + sqlite3ExprListDelete(db, pEList); + p->pEList = pNew; + } +-#if SQLITE_MAX_COLUMN +- if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ +- sqlite3ErrorMsg(pParse, "too many columns in result set"); +- return WRC_Abort; ++ if( p->pEList ){ ++ if( p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ ++ sqlite3ErrorMsg(pParse, "too many columns in result set"); ++ return WRC_Abort; ++ } ++ if( (elistFlags & (EP_HasFunc|EP_Subquery))!=0 ){ ++ p->selFlags |= SF_ComplexResult; ++ } + } +-#endif + return WRC_Continue; + } + +@@ -122081,7 +129042,7 @@ + Walker w; + w.xExprCallback = sqlite3ExprWalkNoop; + w.pParse = pParse; +- if( pParse->hasCompound ){ ++ if( OK_IF_ALWAYS_TRUE(pParse->hasCompound) ){ + w.xSelectCallback = convertCompoundSelectToSubquery; + w.xSelectCallback2 = 0; + sqlite3WalkSelect(&w, pSelect); +@@ -122113,7 +129074,7 @@ + struct SrcList_item *pFrom; + + assert( p->selFlags & SF_Resolved ); +- assert( (p->selFlags & SF_HasTypeInfo)==0 ); ++ if( p->selFlags & SF_HasTypeInfo ) return; + p->selFlags |= SF_HasTypeInfo; + pParse = pWalker->pParse; + pTabList = p->pSrc; +@@ -122169,15 +129130,13 @@ + Select *p, /* The SELECT statement being coded. */ + NameContext *pOuterNC /* Name context for container */ + ){ +- sqlite3 *db; +- if( NEVER(p==0) ) return; +- db = pParse->db; +- if( db->mallocFailed ) return; ++ assert( p!=0 || pParse->db->mallocFailed ); ++ if( pParse->db->mallocFailed ) return; + if( p->selFlags & SF_HasTypeInfo ) return; + sqlite3SelectExpand(pParse, p); +- if( pParse->nErr || db->mallocFailed ) return; ++ if( pParse->nErr || pParse->db->mallocFailed ) return; + sqlite3ResolveSelectNames(pParse, p, pOuterNC); +- if( pParse->nErr || db->mallocFailed ) return; ++ if( pParse->nErr || pParse->db->mallocFailed ) return; + sqlite3SelectAddTypeInfo(pParse, p); + } + +@@ -122218,7 +129177,7 @@ + "argument"); + pFunc->iDistinct = -1; + }else{ +- KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->x.pList, 0, 0); ++ KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pE->x.pList,0,0); + sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0, + (char*)pKeyInfo, P4_KEYINFO); + } +@@ -122242,11 +129201,17 @@ + } + } + ++ + /* + ** Update the accumulator memory cells for an aggregate based on + ** the current cursor position. ++** ++** If regAcc is non-zero and there are no min() or max() aggregates ++** in pAggInfo, then only populate the pAggInfo->nAccumulator accumulator ++** registers i register regAcc contains 0. The caller will take care ++** of setting and clearing regAcc. + */ +-static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ ++static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){ + Vdbe *v = pParse->pVdbe; + int i; + int regHit = 0; +@@ -122289,36 +129254,24 @@ + if( regHit==0 && pAggInfo->nAccumulator ) regHit = ++pParse->nMem; + sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0, (char *)pColl, P4_COLLSEQ); + } +- sqlite3VdbeAddOp3(v, OP_AggStep0, 0, regAgg, pF->iMem); ++ sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, pF->iMem); + sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); + sqlite3VdbeChangeP5(v, (u8)nArg); +- sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg); + sqlite3ReleaseTempRange(pParse, regAgg, nArg); + if( addrNext ){ + sqlite3VdbeResolveLabel(v, addrNext); +- sqlite3ExprCacheClear(pParse); + } + } +- +- /* Before populating the accumulator registers, clear the column cache. +- ** Otherwise, if any of the required column values are already present +- ** in registers, sqlite3ExprCode() may use OP_SCopy to copy the value +- ** to pC->iMem. But by the time the value is used, the original register +- ** may have been used, invalidating the underlying buffer holding the +- ** text or blob value. See ticket [883034dcb5]. +- ** +- ** Another solution would be to change the OP_SCopy used to copy cached +- ** values to an OP_Copy. +- */ ++ if( regHit==0 && pAggInfo->nAccumulator ){ ++ regHit = regAcc; ++ } + if( regHit ){ + addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); VdbeCoverage(v); + } +- sqlite3ExprCacheClear(pParse); + for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){ + sqlite3ExprCode(pParse, pC->pExpr, pC->iMem); + } + pAggInfo->directMode = 0; +- sqlite3ExprCacheClear(pParse); + if( addrHitTest ){ + sqlite3VdbeJumpHere(v, addrHitTest); + } +@@ -122336,14 +129289,11 @@ + ){ + if( pParse->explain==2 ){ + int bCover = (pIdx!=0 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pIdx))); +- char *zEqp = sqlite3MPrintf(pParse->db, "SCAN TABLE %s%s%s", ++ sqlite3VdbeExplain(pParse, 0, "SCAN TABLE %s%s%s", + pTab->zName, + bCover ? " USING COVERING INDEX " : "", + bCover ? pIdx->zName : "" + ); +- sqlite3VdbeAddOp4( +- pParse->pVdbe, OP_Explain, pParse->iSelectId, 0, 0, zEqp, P4_DYNAMIC +- ); + } + } + #else +@@ -122351,14 +129301,6 @@ + #endif + + /* +-** Context object for havingToWhereExprCb(). +-*/ +-struct HavingToWhereCtx { +- Expr **ppWhere; +- ExprList *pGroupBy; +-}; +- +-/* + ** sqlite3WalkExpr() callback used by havingToWhere(). + ** + ** If the node passed to the callback is a TK_AND node, return +@@ -122371,15 +129313,16 @@ + */ + static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){ + if( pExpr->op!=TK_AND ){ +- struct HavingToWhereCtx *p = pWalker->u.pHavingCtx; +- if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, p->pGroupBy) ){ ++ Select *pS = pWalker->u.pSelect; ++ if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy) ){ + sqlite3 *db = pWalker->pParse->db; + Expr *pNew = sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[1], 0); + if( pNew ){ +- Expr *pWhere = *(p->ppWhere); ++ Expr *pWhere = pS->pWhere; + SWAP(Expr, *pNew, *pExpr); + pNew = sqlite3ExprAnd(db, pWhere, pNew); +- *(p->ppWhere) = pNew; ++ pS->pWhere = pNew; ++ pWalker->eCode = 1; + } + } + return WRC_Prune; +@@ -122402,23 +129345,19 @@ + ** entirely of constants and expressions that are also GROUP BY terms that + ** use the "BINARY" collation sequence. + */ +-static void havingToWhere( +- Parse *pParse, +- ExprList *pGroupBy, +- Expr *pHaving, +- Expr **ppWhere +-){ +- struct HavingToWhereCtx sCtx; ++static void havingToWhere(Parse *pParse, Select *p){ + Walker sWalker; +- +- sCtx.ppWhere = ppWhere; +- sCtx.pGroupBy = pGroupBy; +- + memset(&sWalker, 0, sizeof(sWalker)); + sWalker.pParse = pParse; + sWalker.xExprCallback = havingToWhereExprCb; +- sWalker.u.pHavingCtx = &sCtx; +- sqlite3WalkExpr(&sWalker, pHaving); ++ sWalker.u.pSelect = p; ++ sqlite3WalkExpr(&sWalker, p->pHaving); ++#if SELECTTRACE_ENABLED ++ if( sWalker.eCode && (sqlite3SelectTrace & 0x100)!=0 ){ ++ SELECTTRACE(0x100,pParse,p,("Move HAVING terms into WHERE:\n")); ++ sqlite3TreeViewSelect(0, p, 0); ++ } ++#endif + } + + /* +@@ -122462,6 +129401,7 @@ + ** The transformation only works if all of the following are true: + ** + ** * The subquery is a UNION ALL of two or more terms ++** * The subquery does not have a LIMIT clause + ** * There is no WHERE or GROUP BY or HAVING clauses on the subqueries + ** * The outer query is a simple count(*) + ** +@@ -122472,24 +129412,25 @@ + Expr *pExpr; + Expr *pCount; + sqlite3 *db; +- if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate query */ ++ if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate */ + if( p->pEList->nExpr!=1 ) return 0; /* Single result column */ + pExpr = p->pEList->a[0].pExpr; + if( pExpr->op!=TK_AGG_FUNCTION ) return 0; /* Result is an aggregate */ +- if( sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0; /* Must be count() */ ++ if( sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0; /* Is count() */ + if( pExpr->x.pList!=0 ) return 0; /* Must be count(*) */ +- if( p->pSrc->nSrc!=1 ) return 0; /* One table in the FROM clause */ ++ 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 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 terms */ ++ pSub = pSub->pPrior; /* Repeat over compound */ + }while( pSub ); + +- /* If we reach this point, that means it is OK to perform the transformation */ ++ /* If we reach this point then it is OK to perform the transformation */ + + db = pParse->db; + pCount = pExpr; +@@ -122564,13 +129505,11 @@ + AggInfo sAggInfo; /* Information used by aggregate queries */ + int iEnd; /* Address of the end of the query */ + sqlite3 *db; /* The database connection */ ++ ExprList *pMinMaxOrderBy = 0; /* Added ORDER BY for min/max queries */ ++ u8 minMaxFlag; /* Flag for min/max queries */ + +-#ifndef SQLITE_OMIT_EXPLAIN +- int iRestoreSelectId = pParse->iSelectId; +- pParse->iSelectId = pParse->iNextSelectId++; +-#endif +- + db = pParse->db; ++ v = sqlite3GetVdbe(pParse); + if( p==0 || db->mallocFailed || pParse->nErr ){ + return 1; + } +@@ -122577,8 +129516,7 @@ + if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; + memset(&sAggInfo, 0, sizeof(sAggInfo)); + #if SELECTTRACE_ENABLED +- pParse->nSelectIndent++; +- SELECTTRACE(1,pParse,p, ("begin processing:\n")); ++ SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->addrExplain)); + if( sqlite3SelectTrace & 0x100 ){ + sqlite3TreeViewSelect(0, p, 0); + } +@@ -122600,37 +129538,60 @@ + p->selFlags &= ~SF_Distinct; + } + sqlite3SelectPrep(pParse, p, 0); +- memset(&sSort, 0, sizeof(sSort)); +- sSort.pOrderBy = p->pOrderBy; +- pTabList = p->pSrc; + if( pParse->nErr || db->mallocFailed ){ + goto select_end; + } + assert( p->pEList!=0 ); +- isAgg = (p->selFlags & SF_Aggregate)!=0; + #if SELECTTRACE_ENABLED +- if( sqlite3SelectTrace & 0x100 ){ +- SELECTTRACE(0x100,pParse,p, ("after name resolution:\n")); ++ if( sqlite3SelectTrace & 0x104 ){ ++ SELECTTRACE(0x104,pParse,p, ("after name resolution:\n")); + sqlite3TreeViewSelect(0, p, 0); + } + #endif + +- /* Get a pointer the VDBE under construction, allocating a new VDBE if one +- ** does not already exist */ +- v = sqlite3GetVdbe(pParse); +- if( v==0 ) goto select_end; + if( pDest->eDest==SRT_Output ){ + generateColumnNames(pParse, p); + } + +- /* Try to flatten subqueries in the FROM clause up into the main query ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( sqlite3WindowRewrite(pParse, p) ){ ++ goto select_end; ++ } ++#if SELECTTRACE_ENABLED ++ if( sqlite3SelectTrace & 0x108 ){ ++ SELECTTRACE(0x104,pParse,p, ("after window rewrite:\n")); ++ sqlite3TreeViewSelect(0, p, 0); ++ } ++#endif ++#endif /* SQLITE_OMIT_WINDOWFUNC */ ++ pTabList = p->pSrc; ++ isAgg = (p->selFlags & SF_Aggregate)!=0; ++ memset(&sSort, 0, sizeof(sSort)); ++ sSort.pOrderBy = p->pOrderBy; ++ ++ /* Try to various optimizations (flattening subqueries, and strength ++ ** reduction of join operators) in the FROM clause up into the main query + */ + #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) + for(i=0; !p->pPrior && i<pTabList->nSrc; i++){ + struct SrcList_item *pItem = &pTabList->a[i]; + Select *pSub = pItem->pSelect; +- int isAggSub; + Table *pTab = pItem->pTab; ++ ++ /* Convert LEFT JOIN into JOIN if there are terms of the right table ++ ** of the LEFT JOIN used in the WHERE clause. ++ */ ++ if( (pItem->fg.jointype & JT_LEFT)!=0 ++ && sqlite3ExprImpliesNonNullRow(p->pWhere, pItem->iCursor) ++ && OptimizationEnabled(db, SQLITE_SimplifyJoin) ++ ){ ++ SELECTTRACE(0x100,pParse,p, ++ ("LEFT-JOIN simplifies to JOIN on term %d\n",i)); ++ pItem->fg.jointype &= ~(JT_LEFT|JT_OUTER); ++ unsetJoinExpr(p->pWhere, pItem->iCursor); ++ } ++ ++ /* No futher action if this term of the FROM clause is no a subquery */ + if( pSub==0 ) continue; + + /* Catch mismatch in the declared columns of a view and the number of +@@ -122641,13 +129602,45 @@ + goto select_end; + } + +- isAggSub = (pSub->selFlags & SF_Aggregate)!=0; +- if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){ ++ /* Do not try to flatten an aggregate subquery. ++ ** ++ ** Flattening an aggregate subquery is only possible if the outer query ++ ** is not a join. But if the outer query is not a join, then the subquery ++ ** will be implemented as a co-routine and there is no advantage to ++ ** flattening in that case. ++ */ ++ if( (pSub->selFlags & SF_Aggregate)!=0 ) continue; ++ assert( pSub->pGroupBy==0 ); ++ ++ /* If the outer query contains a "complex" result set (that is, ++ ** if the result set of the outer query uses functions or subqueries) ++ ** and if the subquery contains an ORDER BY clause and if ++ ** it will be implemented as a co-routine, then do not flatten. This ++ ** restriction allows SQL constructs like this: ++ ** ++ ** SELECT expensive_function(x) ++ ** FROM (SELECT x FROM tab ORDER BY y LIMIT 10); ++ ** ++ ** The expensive_function() is only computed on the 10 rows that ++ ** are output, rather than every row of the table. ++ ** ++ ** The requirement that the outer query have a complex result set ++ ** means that flattening does occur on simpler SQL constraints without ++ ** the expensive_function() like: ++ ** ++ ** SELECT x FROM (SELECT x FROM tab ORDER BY y LIMIT 10); ++ */ ++ if( pSub->pOrderBy!=0 ++ && i==0 ++ && (p->selFlags & SF_ComplexResult)!=0 ++ && (pTabList->nSrc==1 ++ || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0) ++ ){ ++ continue; ++ } ++ ++ if( flattenSubquery(pParse, p, i, isAgg) ){ + /* This subquery can be absorbed into its parent. */ +- if( isAggSub ){ +- isAgg = 1; +- p->selFlags |= SF_Aggregate; +- } + i = -1; + } + pTabList = p->pSrc; +@@ -122664,15 +129657,46 @@ + */ + if( p->pPrior ){ + rc = multiSelect(pParse, p, pDest); +- explainSetInteger(pParse->iSelectId, iRestoreSelectId); + #if SELECTTRACE_ENABLED +- SELECTTRACE(1,pParse,p,("end compound-select processing\n")); +- pParse->nSelectIndent--; ++ SELECTTRACE(0x1,pParse,p,("end compound-select processing\n")); ++ if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){ ++ sqlite3TreeViewSelect(0, p, 0); ++ } + #endif ++ if( p->pNext==0 ) ExplainQueryPlanPop(pParse); + return rc; + } + #endif + ++ /* Do the WHERE-clause constant propagation optimization if this is ++ ** a join. No need to speed time on this operation for non-join queries ++ ** as the equivalent optimization will be handled by query planner in ++ ** sqlite3WhereBegin(). ++ */ ++ if( pTabList->nSrc>1 ++ && OptimizationEnabled(db, SQLITE_PropagateConst) ++ && propagateConstants(pParse, p) ++ ){ ++#if SELECTTRACE_ENABLED ++ if( sqlite3SelectTrace & 0x100 ){ ++ SELECTTRACE(0x100,pParse,p,("After constant propagation:\n")); ++ sqlite3TreeViewSelect(0, p, 0); ++ } ++#endif ++ }else{ ++ SELECTTRACE(0x100,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 +@@ -122681,10 +129705,14 @@ + struct SrcList_item *pItem = &pTabList->a[i]; + SelectDest dest; + Select *pSub; ++#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) ++ const char *zSavedAuthContext; ++#endif + +- /* Issue SQLITE_READ authorizations with a fake column name for any tables that +- ** are referenced but from which no values are extracted. Examples of where these +- ** kinds of null SQLITE_READ authorizations would occur: ++ /* Issue SQLITE_READ authorizations with a fake column name for any ++ ** tables that are referenced but from which no values are extracted. ++ ** Examples of where these kinds of null SQLITE_READ authorizations ++ ** would occur: + ** + ** SELECT count(*) FROM t1; -- SQLITE_READ t1."" + ** SELECT t1.* FROM t1, t2; -- SQLITE_READ t2."" +@@ -122692,10 +129720,10 @@ + ** The fake column name is an empty string. It is possible for a table to + ** have a column named by the empty string, in which case there is no way to + ** distinguish between an unreferenced table and an actual reference to the +- ** "" column. The original design was for the fake column name to be a NULL, ++ ** "" column. The original design was for the fake column name to be a NULL, + ** which would be unambiguous. But legacy authorization callbacks might +- ** assume the column name is non-NULL and segfault. The use of an empty string +- ** for the fake column name seems safer. ++ ** assume the column name is non-NULL and segfault. The use of an empty ++ ** string for the fake column name seems safer. + */ + if( pItem->colUsed==0 ){ + sqlite3AuthCheck(pParse, SQLITE_READ, pItem->zName, "", pItem->zDatabase); +@@ -122736,27 +129764,29 @@ + /* Make copies of constant WHERE-clause terms in the outer query down + ** inside the subquery. This can help the subquery to run more efficiently. + */ +- if( (pItem->fg.jointype & JT_OUTER)==0 +- && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor) ++ if( OptimizationEnabled(db, SQLITE_PushDown) ++ && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor, ++ (pItem->fg.jointype & JT_OUTER)!=0) + ){ + #if SELECTTRACE_ENABLED + if( sqlite3SelectTrace & 0x100 ){ +- SELECTTRACE(0x100,pParse,p,("After WHERE-clause push-down:\n")); ++ SELECTTRACE(0x100,pParse,p, ++ ("After WHERE-clause push-down into subquery %d:\n", pSub->selId)); + sqlite3TreeViewSelect(0, p, 0); + } + #endif ++ }else{ ++ SELECTTRACE(0x100,pParse,p,("Push-down not possible\n")); + } + ++ zSavedAuthContext = pParse->zAuthContext; ++ pParse->zAuthContext = pItem->zName; ++ + /* Generate code to implement the subquery + ** +- ** The subquery is implemented as a co-routine if all of these are true: +- ** (1) The subquery is guaranteed to be the outer loop (so that it +- ** does not need to be computed more than once) +- ** (2) The ALL keyword after SELECT is omitted. (Applications are +- ** allowed to say "SELECT ALL" instead of just "SELECT" to disable +- ** the use of co-routines.) +- ** (3) Co-routines are not disabled using sqlite3_test_control() +- ** with SQLITE_TESTCTRL_OPTIMIZATIONS. ++ ** The subquery is implemented as a co-routine if the subquery is ++ ** guaranteed to be the outer loop (so that it does not need to be ++ ** computed more than once) + ** + ** TODO: Are there other reasons beside (1) to use a co-routine + ** implementation? +@@ -122764,19 +129794,18 @@ + if( i==0 + && (pTabList->nSrc==1 + || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0) /* (1) */ +- && (p->selFlags & SF_All)==0 /* (2) */ +- && OptimizationEnabled(db, SQLITE_SubqCoroutine) /* (3) */ + ){ + /* Implement a co-routine that will return a single row of the result + ** set on each invocation. + */ + int addrTop = sqlite3VdbeCurrentAddr(v)+1; ++ + pItem->regReturn = ++pParse->nMem; + sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop); + VdbeComment((v, "%s", pItem->pTab->zName)); + pItem->addrFillSub = addrTop; + sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn); +- explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); ++ ExplainQueryPlan((pParse, 1, "CO-ROUTINE %u", pSub->selId)); + sqlite3Select(pParse, pSub, &dest); + pItem->pTab->nRowLogEst = pSub->nSelectRow; + pItem->fg.viaCoroutine = 1; +@@ -122811,12 +129840,11 @@ + pPrior = isSelfJoinView(pTabList, pItem); + if( pPrior ){ + sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor); +- explainSetInteger(pItem->iSelectId, pPrior->iSelectId); + assert( pPrior->pSelect!=0 ); + pSub->nSelectRow = pPrior->pSelect->nSelectRow; + }else{ + sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); +- explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); ++ ExplainQueryPlan((pParse, 1, "MATERIALIZE %u", pSub->selId)); + sqlite3Select(pParse, pSub, &dest); + } + pItem->pTab->nRowLogEst = pSub->nSelectRow; +@@ -122828,6 +129856,7 @@ + } + if( db->mallocFailed ) goto select_end; + pParse->nHeight -= sqlite3SelectExprHeight(p); ++ pParse->zAuthContext = zSavedAuthContext; + #endif + } + +@@ -122846,16 +129875,6 @@ + } + #endif + +-#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 +- + /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and + ** if the select-list is the same as the ORDER BY list, then this query + ** can be rewritten as a GROUP BY. In other words, this: +@@ -122899,7 +129918,8 @@ + */ + if( sSort.pOrderBy ){ + KeyInfo *pKeyInfo; +- pKeyInfo = keyInfoFromExprList(pParse, sSort.pOrderBy, 0, pEList->nExpr); ++ pKeyInfo = sqlite3KeyInfoFromExprList( ++ pParse, sSort.pOrderBy, 0, pEList->nExpr); + sSort.iECursor = pParse->nTab++; + sSort.addrSortIndex = + sqlite3VdbeAddOp4(v, OP_OpenEphemeral, +@@ -122933,9 +129953,9 @@ + if( p->selFlags & SF_Distinct ){ + sDistinct.tabTnct = pParse->nTab++; + sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, +- sDistinct.tabTnct, 0, 0, +- (char*)keyInfoFromExprList(pParse, p->pEList,0,0), +- P4_KEYINFO); ++ sDistinct.tabTnct, 0, 0, ++ (char*)sqlite3KeyInfoFromExprList(pParse, p->pEList,0,0), ++ P4_KEYINFO); + sqlite3VdbeChangeP5(v, BTREE_UNORDERED); + sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED; + }else{ +@@ -122944,11 +129964,19 @@ + + if( !isAgg && pGroupBy==0 ){ + /* No aggregate functions and no GROUP BY clause */ +- u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0); ++ u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0) ++ | (p->selFlags & SF_FixedLimit); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ Window *pWin = p->pWin; /* Master window object (or NULL) */ ++ if( pWin ){ ++ sqlite3WindowCodeInit(pParse, pWin); ++ } ++#endif + assert( WHERE_USE_LIMIT==SF_FixedLimit ); +- wctrlFlags |= p->selFlags & SF_FixedLimit; + ++ + /* Begin the database scan. */ ++ SELECTTRACE(1,pParse,p,("WhereBegin\n")); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy, + p->pEList, wctrlFlags, p->nSelectRow); + if( pWInfo==0 ) goto select_end; +@@ -122960,7 +129988,7 @@ + } + if( sSort.pOrderBy ){ + sSort.nOBSat = sqlite3WhereIsOrdered(pWInfo); +- sSort.bOrderedInnerLoop = sqlite3WhereOrderedInnerLoop(pWInfo); ++ sSort.labelOBLopt = sqlite3WhereOrderByLimitOptLabel(pWInfo); + if( sSort.nOBSat==sSort.pOrderBy->nExpr ){ + sSort.pOrderBy = 0; + } +@@ -122974,14 +130002,37 @@ + sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex); + } + +- /* Use the standard inner loop. */ +- selectInnerLoop(pParse, p, pEList, -1, &sSort, &sDistinct, pDest, +- sqlite3WhereContinueLabel(pWInfo), +- sqlite3WhereBreakLabel(pWInfo)); ++ assert( p->pEList==pEList ); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( pWin ){ ++ int addrGosub = sqlite3VdbeMakeLabel(v); ++ int iCont = sqlite3VdbeMakeLabel(v); ++ int iBreak = sqlite3VdbeMakeLabel(v); ++ int regGosub = ++pParse->nMem; + +- /* End the database scan loop. +- */ +- sqlite3WhereEnd(pWInfo); ++ sqlite3WindowCodeStep(pParse, p, pWInfo, regGosub, addrGosub); ++ ++ sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak); ++ sqlite3VdbeResolveLabel(v, addrGosub); ++ VdbeNoopComment((v, "inner-loop subroutine")); ++ sSort.labelOBLopt = 0; ++ selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, iCont, iBreak); ++ sqlite3VdbeResolveLabel(v, iCont); ++ sqlite3VdbeAddOp1(v, OP_Return, regGosub); ++ VdbeComment((v, "end inner-loop subroutine")); ++ sqlite3VdbeResolveLabel(v, iBreak); ++ }else ++#endif /* SQLITE_OMIT_WINDOWFUNC */ ++ { ++ /* Use the standard inner loop. */ ++ selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, ++ sqlite3WhereContinueLabel(pWInfo), ++ sqlite3WhereBreakLabel(pWInfo)); ++ ++ /* End the database scan loop. ++ */ ++ sqlite3WhereEnd(pWInfo); ++ } + }else{ + /* This case when there exist aggregate functions or a GROUP BY clause + ** or both */ +@@ -123040,7 +130091,8 @@ + memset(&sNC, 0, sizeof(sNC)); + sNC.pParse = pParse; + sNC.pSrcList = pTabList; +- sNC.pAggInfo = &sAggInfo; ++ sNC.uNC.pAggInfo = &sAggInfo; ++ VVA_ONLY( sNC.ncFlags = NC_UAggInfo; ) + sAggInfo.mnReg = pParse->nMem+1; + sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr : 0; + sAggInfo.pGroupBy = pGroupBy; +@@ -123049,12 +130101,19 @@ + if( pHaving ){ + if( pGroupBy ){ + assert( pWhere==p->pWhere ); +- havingToWhere(pParse, pGroupBy, pHaving, &p->pWhere); ++ assert( pHaving==p->pHaving ); ++ assert( pGroupBy==p->pGroupBy ); ++ havingToWhere(pParse, p); + pWhere = p->pWhere; + } + sqlite3ExprAnalyzeAggregates(&sNC, pHaving); + } + sAggInfo.nAccumulator = sAggInfo.nColumn; ++ if( p->pGroupBy==0 && p->pHaving==0 && sAggInfo.nFunc==1 ){ ++ minMaxFlag = minMaxQuery(db, sAggInfo.aFunc[0].pExpr, &pMinMaxOrderBy); ++ }else{ ++ minMaxFlag = WHERE_ORDERBY_NORMAL; ++ } + for(i=0; i<sAggInfo.nFunc; i++){ + assert( !ExprHasProperty(sAggInfo.aFunc[i].pExpr, EP_xIsSelect) ); + sNC.ncFlags |= NC_InAggFunc; +@@ -123063,7 +130122,25 @@ + } + sAggInfo.mxReg = pParse->nMem; + if( db->mallocFailed ) goto select_end; ++#if SELECTTRACE_ENABLED ++ if( sqlite3SelectTrace & 0x400 ){ ++ int ii; ++ SELECTTRACE(0x400,pParse,p,("After aggregate analysis:\n")); ++ sqlite3TreeViewSelect(0, p, 0); ++ for(ii=0; ii<sAggInfo.nColumn; ii++){ ++ sqlite3DebugPrintf("agg-column[%d] iMem=%d\n", ++ ii, sAggInfo.aCol[ii].iMem); ++ sqlite3TreeViewExpr(0, sAggInfo.aCol[ii].pExpr, 0); ++ } ++ for(ii=0; ii<sAggInfo.nFunc; ii++){ ++ sqlite3DebugPrintf("agg-func[%d]: iMem=%d\n", ++ ii, sAggInfo.aFunc[ii].iMem); ++ sqlite3TreeViewExpr(0, sAggInfo.aFunc[ii].pExpr, 0); ++ } ++ } ++#endif + ++ + /* Processing for aggregates with GROUP BY is very different and + ** much more complex than aggregates without a GROUP BY. + */ +@@ -123084,7 +130161,7 @@ + ** will be converted into a Noop. + */ + sAggInfo.sortingIdx = pParse->nTab++; +- pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0, sAggInfo.nColumn); ++ pKeyInfo = sqlite3KeyInfoFromExprList(pParse,pGroupBy,0,sAggInfo.nColumn); + addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen, + sAggInfo.sortingIdx, sAggInfo.nSortingColumn, + 0, (char*)pKeyInfo, P4_KEYINFO); +@@ -123103,8 +130180,6 @@ + pParse->nMem += pGroupBy->nExpr; + sqlite3VdbeAddOp2(v, OP_Integer, 0, iAbortFlag); + VdbeComment((v, "clear abort flag")); +- sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag); +- VdbeComment((v, "indicate accumulator empty")); + sqlite3VdbeAddOp3(v, OP_Null, 0, iAMem, iAMem+pGroupBy->nExpr-1); + + /* Begin a loop that will extract all source rows in GROUP BY order. +@@ -123113,6 +130188,7 @@ + ** in the right order to begin with. + */ + sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); ++ SELECTTRACE(1,pParse,p,("WhereBegin\n")); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0, + WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0), 0 + ); +@@ -123149,7 +130225,6 @@ + } + } + regBase = sqlite3GetTempRange(pParse, nCol); +- sqlite3ExprCacheClear(pParse); + sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0, 0); + j = nGroupBy; + for(i=0; i<sAggInfo.nColumn; i++){ +@@ -123156,8 +130231,8 @@ + struct AggInfo_col *pCol = &sAggInfo.aCol[i]; + if( pCol->iSorterColumn>=j ){ + int r1 = j + regBase; +- sqlite3ExprCodeGetColumnToReg(pParse, +- pCol->pTab, pCol->iColumn, pCol->iTable, r1); ++ sqlite3ExprCodeGetColumnOfTable(v, ++ pCol->pTab, pCol->iTable, pCol->iColumn, r1); + j++; + } + } +@@ -123173,8 +130248,6 @@ + sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd); + VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v); + sAggInfo.useSortingIdx = 1; +- sqlite3ExprCacheClear(pParse); +- + } + + /* If the index or temporary table used by the GROUP BY sort +@@ -123197,7 +130270,6 @@ + ** from the previous row currently stored in a0, a1, a2... + */ + addrTopOfLoop = sqlite3VdbeCurrentAddr(v); +- sqlite3ExprCacheClear(pParse); + if( groupBySort ){ + sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx, + sortOut, sortPTab); +@@ -123236,7 +130308,7 @@ + ** the current row + */ + sqlite3VdbeJumpHere(v, addr1); +- updateAccumulator(pParse, &sAggInfo); ++ updateAccumulator(pParse, iUseFlag, &sAggInfo); + sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag); + VdbeComment((v, "indicate data in accumulator")); + +@@ -123278,7 +130350,7 @@ + sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); + finalizeAggFunctions(pParse, &sAggInfo); + sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL); +- selectInnerLoop(pParse, p, p->pEList, -1, &sSort, ++ selectInnerLoop(pParse, p, -1, &sSort, + &sDistinct, pDest, + addrOutputRow+1, addrSetAbort); + sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); +@@ -123288,11 +130360,12 @@ + */ + sqlite3VdbeResolveLabel(v, addrReset); + resetAccumulator(pParse, &sAggInfo); ++ sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag); ++ VdbeComment((v, "indicate accumulator empty")); + sqlite3VdbeAddOp1(v, OP_Return, regReset); + + } /* endif pGroupBy. Begin aggregate queries without GROUP BY: */ + else { +- ExprList *pDel = 0; + #ifndef SQLITE_OMIT_BTREECOUNT + Table *pTab; + if( (pTab = isSimpleCount(p, &sAggInfo))!=0 ){ +@@ -123354,67 +130427,50 @@ + }else + #endif /* SQLITE_OMIT_BTREECOUNT */ + { +- /* Check if the query is of one of the following forms: +- ** +- ** SELECT min(x) FROM ... +- ** SELECT max(x) FROM ... +- ** +- ** If it is, then ask the code in where.c to attempt to sort results +- ** as if there was an "ORDER ON x" or "ORDER ON x DESC" clause. +- ** If where.c is able to produce results sorted in this order, then +- ** add vdbe code to break out of the processing loop after the +- ** first iteration (since the first iteration of the loop is +- ** guaranteed to operate on the row with the minimum or maximum +- ** value of x, the only row required). +- ** +- ** A special flag must be passed to sqlite3WhereBegin() to slightly +- ** modify behavior as follows: +- ** +- ** + If the query is a "SELECT min(x)", then the loop coded by +- ** where.c should not iterate over any values with a NULL value +- ** for x. +- ** +- ** + The optimizer code in where.c (the thing that decides which +- ** index or indices to use) should place a different priority on +- ** satisfying the 'ORDER BY' clause than it does in other cases. +- ** Refer to code and comments in where.c for details. +- */ +- ExprList *pMinMax = 0; +- u8 flag = WHERE_ORDERBY_NORMAL; +- +- assert( p->pGroupBy==0 ); +- assert( flag==0 ); +- if( p->pHaving==0 ){ +- flag = minMaxQuery(&sAggInfo, &pMinMax); +- } +- assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) ); ++ int regAcc = 0; /* "populate accumulators" flag */ + +- if( flag ){ +- pMinMax = sqlite3ExprListDup(db, pMinMax, 0); +- pDel = pMinMax; +- assert( db->mallocFailed || pMinMax!=0 ); +- if( !db->mallocFailed ){ +- pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0; +- pMinMax->a[0].pExpr->op = TK_COLUMN; ++ /* If there are accumulator registers but no min() or max() functions, ++ ** allocate register regAcc. Register regAcc will contain 0 the first ++ ** time the inner loop runs, and 1 thereafter. The code generated ++ ** by updateAccumulator() only updates the accumulator registers if ++ ** regAcc contains 0. */ ++ if( sAggInfo.nAccumulator ){ ++ for(i=0; i<sAggInfo.nFunc; i++){ ++ if( sAggInfo.aFunc[i].pFunc->funcFlags&SQLITE_FUNC_NEEDCOLL ) break; + } ++ if( i==sAggInfo.nFunc ){ ++ regAcc = ++pParse->nMem; ++ sqlite3VdbeAddOp2(v, OP_Integer, 0, regAcc); ++ } + } +- ++ + /* This case runs if the aggregate has no GROUP BY clause. The + ** processing is much simpler since there is only a single row + ** of output. + */ ++ assert( p->pGroupBy==0 ); + resetAccumulator(pParse, &sAggInfo); +- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMax, 0,flag,0); ++ ++ /* If this query is a candidate for the min/max optimization, then ++ ** minMaxFlag will have been previously set to either ++ ** WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX and pMinMaxOrderBy will ++ ** be an appropriate ORDER BY expression for the optimization. ++ */ ++ assert( minMaxFlag==WHERE_ORDERBY_NORMAL || pMinMaxOrderBy!=0 ); ++ assert( pMinMaxOrderBy==0 || pMinMaxOrderBy->nExpr==1 ); ++ ++ SELECTTRACE(1,pParse,p,("WhereBegin\n")); ++ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy, ++ 0, minMaxFlag, 0); + if( pWInfo==0 ){ +- sqlite3ExprListDelete(db, pDel); + goto select_end; + } +- updateAccumulator(pParse, &sAggInfo); +- assert( pMinMax==0 || pMinMax->nExpr==1 ); ++ updateAccumulator(pParse, regAcc, &sAggInfo); ++ if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc); + if( sqlite3WhereIsOrdered(pWInfo)>0 ){ + sqlite3VdbeGoto(v, sqlite3WhereBreakLabel(pWInfo)); + VdbeComment((v, "%s() by index", +- (flag==WHERE_ORDERBY_MIN?"min":"max"))); ++ (minMaxFlag==WHERE_ORDERBY_MIN?"min":"max"))); + } + sqlite3WhereEnd(pWInfo); + finalizeAggFunctions(pParse, &sAggInfo); +@@ -123422,9 +130478,8 @@ + + sSort.pOrderBy = 0; + sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL); +- selectInnerLoop(pParse, p, p->pEList, -1, 0, 0, ++ selectInnerLoop(pParse, p, -1, 0, 0, + pDest, addrEnd, addrEnd); +- sqlite3ExprListDelete(db, pDel); + } + sqlite3VdbeResolveLabel(v, addrEnd); + +@@ -123440,6 +130495,7 @@ + if( sSort.pOrderBy ){ + explainTempTable(pParse, + sSort.nOBSat>0 ? "RIGHT PART OF ORDER BY":"ORDER BY"); ++ assert( p->pEList==pEList ); + generateSortTail(pParse, p, &sSort, pEList->nExpr, pDest); + } + +@@ -123455,14 +130511,16 @@ + ** successful coding of the SELECT. + */ + select_end: +- explainSetInteger(pParse->iSelectId, iRestoreSelectId); +- ++ sqlite3ExprListDelete(db, pMinMaxOrderBy); + sqlite3DbFree(db, sAggInfo.aCol); + sqlite3DbFree(db, sAggInfo.aFunc); + #if SELECTTRACE_ENABLED +- SELECTTRACE(1,pParse,p,("end processing\n")); +- pParse->nSelectIndent--; ++ SELECTTRACE(0x1,pParse,p,("end processing\n")); ++ if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){ ++ sqlite3TreeViewSelect(0, p, 0); ++ } + #endif ++ ExplainQueryPlanPop(pParse); + return rc; + } + +@@ -123696,6 +130754,8 @@ + sqlite3ExprListDelete(db, pTmp->pExprList); + sqlite3SelectDelete(db, pTmp->pSelect); + sqlite3IdListDelete(db, pTmp->pIdList); ++ sqlite3UpsertDelete(db, pTmp->pUpsert); ++ sqlite3DbFree(db, pTmp->zSpan); + + sqlite3DbFree(db, pTmp); + } +@@ -123850,14 +130910,16 @@ + goto trigger_cleanup; + } + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); +- 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); ++ 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; + } +- goto trigger_cleanup; + } + + /* Do not create a trigger on a system table */ +@@ -123881,7 +130943,7 @@ + } + + #ifndef SQLITE_OMIT_AUTHORIZATION +- { ++ if( !IN_RENAME_OBJECT ){ + int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); + int code = SQLITE_CREATE_TRIGGER; + const char *zDb = db->aDb[iTabDb].zDbSName; +@@ -123915,8 +130977,15 @@ + pTrigger->pTabSchema = pTab->pSchema; + pTrigger->op = (u8)op; + pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER; +- pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); +- pTrigger->pColumns = sqlite3IdListDup(db, pColumns); ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameTokenRemap(pParse, pTrigger->table, pTableName->a[0].zName); ++ pTrigger->pWhen = pWhen; ++ pWhen = 0; ++ }else{ ++ pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); ++ } ++ pTrigger->pColumns = pColumns; ++ pColumns = 0; + assert( pParse->pNewTrigger==0 ); + pParse->pNewTrigger = pTrigger; + +@@ -123965,6 +131034,14 @@ + goto triggerfinish_cleanup; + } + ++#ifndef SQLITE_OMIT_ALTERTABLE ++ if( IN_RENAME_OBJECT ){ ++ assert( !db->init.busy ); ++ pParse->pNewTrigger = pTrig; ++ pTrig = 0; ++ }else ++#endif ++ + /* if we are not initializing, + ** build the sqlite_master entry + */ +@@ -124006,11 +131083,22 @@ + + triggerfinish_cleanup: + sqlite3DeleteTrigger(db, pTrig); +- assert( !pParse->pNewTrigger ); ++ assert( IN_RENAME_OBJECT || !pParse->pNewTrigger ); + sqlite3DeleteTriggerStep(db, pStepList); + } + + /* ++** Duplicate a range of text from an SQL statement, then convert all ++** whitespace characters into ordinary space characters. ++*/ ++static char *triggerSpanDup(sqlite3 *db, const char *zStart, const char *zEnd){ ++ char *z = sqlite3DbSpanDup(db, zStart, zEnd); ++ int i; ++ if( z ) for(i=0; z[i]; i++) if( sqlite3Isspace(z[i]) ) z[i] = ' '; ++ return z; ++} ++ ++/* + ** Turn a SELECT statement (that the pSelect parameter points to) into + ** a trigger step. Return a pointer to a TriggerStep structure. + ** +@@ -124017,7 +131105,12 @@ + ** The parser calls this routine when it finds a SELECT statement in + ** body of a TRIGGER. + */ +-SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelect){ ++SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep( ++ sqlite3 *db, /* Database connection */ ++ Select *pSelect, /* The SELECT statement */ ++ const char *zStart, /* Start of SQL text */ ++ const char *zEnd /* End of SQL text */ ++){ + TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); + if( pTriggerStep==0 ) { + sqlite3SelectDelete(db, pSelect); +@@ -124026,6 +131119,7 @@ + pTriggerStep->op = TK_SELECT; + pTriggerStep->pSelect = pSelect; + pTriggerStep->orconf = OE_Default; ++ pTriggerStep->zSpan = triggerSpanDup(db, zStart, zEnd); + return pTriggerStep; + } + +@@ -124036,10 +131130,13 @@ + ** If an OOM error occurs, NULL is returned and db->mallocFailed is set. + */ + static TriggerStep *triggerStepAllocate( +- sqlite3 *db, /* Database connection */ ++ Parse *pParse, /* Parser context */ + u8 op, /* Trigger opcode */ +- Token *pName /* The target name */ ++ Token *pName, /* The target name */ ++ const char *zStart, /* Start of SQL text */ ++ const char *zEnd /* End of SQL text */ + ){ ++ sqlite3 *db = pParse->db; + TriggerStep *pTriggerStep; + + pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n + 1); +@@ -124049,6 +131146,10 @@ + sqlite3Dequote(z); + pTriggerStep->zTarget = z; + pTriggerStep->op = op; ++ pTriggerStep->zSpan = triggerSpanDup(db, zStart, zEnd); ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameTokenMap(pParse, pTriggerStep->zTarget, pName); ++ } + } + return pTriggerStep; + } +@@ -124061,23 +131162,36 @@ + ** body of a trigger. + */ + SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep( +- sqlite3 *db, /* The database connection */ ++ Parse *pParse, /* Parser */ + Token *pTableName, /* Name of the table into which we insert */ + IdList *pColumn, /* List of columns in pTableName to insert into */ + Select *pSelect, /* A SELECT statement that supplies values */ +- u8 orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ ++ u8 orconf, /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ ++ Upsert *pUpsert, /* ON CONFLICT clauses for upsert */ ++ const char *zStart, /* Start of SQL text */ ++ const char *zEnd /* End of SQL text */ + ){ ++ sqlite3 *db = pParse->db; + TriggerStep *pTriggerStep; + + assert(pSelect != 0 || db->mallocFailed); + +- pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName); ++ pTriggerStep = triggerStepAllocate(pParse, TK_INSERT, pTableName,zStart,zEnd); + if( pTriggerStep ){ +- pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); ++ if( IN_RENAME_OBJECT ){ ++ pTriggerStep->pSelect = pSelect; ++ pSelect = 0; ++ }else{ ++ pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); ++ } + pTriggerStep->pIdList = pColumn; ++ pTriggerStep->pUpsert = pUpsert; + pTriggerStep->orconf = orconf; + }else{ ++ testcase( pColumn ); + sqlite3IdListDelete(db, pColumn); ++ testcase( pUpsert ); ++ sqlite3UpsertDelete(db, pUpsert); + } + sqlite3SelectDelete(db, pSelect); + +@@ -124090,18 +131204,28 @@ + ** sees an UPDATE statement inside the body of a CREATE TRIGGER. + */ + SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep( +- sqlite3 *db, /* The database connection */ ++ Parse *pParse, /* Parser */ + Token *pTableName, /* Name of the table to be updated */ + ExprList *pEList, /* The SET clause: list of column and new values */ + Expr *pWhere, /* The WHERE clause */ +- u8 orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */ ++ u8 orconf, /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */ ++ const char *zStart, /* Start of SQL text */ ++ const char *zEnd /* End of SQL text */ + ){ ++ sqlite3 *db = pParse->db; + TriggerStep *pTriggerStep; + +- pTriggerStep = triggerStepAllocate(db, TK_UPDATE, pTableName); ++ pTriggerStep = triggerStepAllocate(pParse, TK_UPDATE, pTableName,zStart,zEnd); + if( pTriggerStep ){ +- pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE); +- pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); ++ if( IN_RENAME_OBJECT ){ ++ pTriggerStep->pExprList = pEList; ++ pTriggerStep->pWhere = pWhere; ++ pEList = 0; ++ pWhere = 0; ++ }else{ ++ pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE); ++ pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); ++ } + pTriggerStep->orconf = orconf; + } + sqlite3ExprListDelete(db, pEList); +@@ -124115,15 +131239,23 @@ + ** sees a DELETE statement inside the body of a CREATE TRIGGER. + */ + SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep( +- sqlite3 *db, /* Database connection */ ++ Parse *pParse, /* Parser */ + Token *pTableName, /* The table from which rows are deleted */ +- Expr *pWhere /* The WHERE clause */ ++ Expr *pWhere, /* The WHERE clause */ ++ const char *zStart, /* Start of SQL text */ ++ const char *zEnd /* End of SQL text */ + ){ ++ sqlite3 *db = pParse->db; + TriggerStep *pTriggerStep; + +- pTriggerStep = triggerStepAllocate(db, TK_DELETE, pTableName); ++ pTriggerStep = triggerStepAllocate(pParse, TK_DELETE, pTableName,zStart,zEnd); + if( pTriggerStep ){ +- pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); ++ if( IN_RENAME_OBJECT ){ ++ pTriggerStep->pWhere = pWhere; ++ pWhere = 0; ++ }else{ ++ pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); ++ } + pTriggerStep->orconf = OE_Default; + } + sqlite3ExprDelete(db, pWhere); +@@ -124256,7 +131388,7 @@ + *pp = (*pp)->pNext; + } + sqlite3DeleteTrigger(db, pTrigger); +- db->flags |= SQLITE_InternChanges; ++ db->mDbFlags |= DBFLAG_SchemaChange; + } + } + +@@ -124376,6 +131508,14 @@ + pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf; + assert( pParse->okConstFactor==0 ); + ++#ifndef SQLITE_OMIT_TRACE ++ if( pStep->zSpan ){ ++ sqlite3VdbeAddOp4(v, OP_Trace, 0x7fffffff, 1, 0, ++ sqlite3MPrintf(db, "-- %s", pStep->zSpan), ++ P4_DYNAMIC); ++ } ++#endif ++ + switch( pStep->op ){ + case TK_UPDATE: { + sqlite3Update(pParse, +@@ -124382,7 +131522,7 @@ + targetSrcList(pParse, pStep), + sqlite3ExprListDup(db, pStep->pExprList, 0), + sqlite3ExprDup(db, pStep->pWhere, 0), +- pParse->eOrconf ++ pParse->eOrconf, 0, 0, 0 + ); + break; + } +@@ -124391,7 +131531,8 @@ + targetSrcList(pParse, pStep), + sqlite3SelectDup(db, pStep->pSelect, 0), + sqlite3IdListDup(db, pStep->pIdList), +- pParse->eOrconf ++ pParse->eOrconf, ++ sqlite3UpsertDup(db, pStep->pUpsert) + ); + break; + } +@@ -124398,7 +131539,7 @@ + case TK_DELETE: { + sqlite3DeleteFrom(pParse, + targetSrcList(pParse, pStep), +- sqlite3ExprDup(db, pStep->pWhere, 0) ++ sqlite3ExprDup(db, pStep->pWhere, 0), 0, 0 + ); + break; + } +@@ -124516,9 +131657,11 @@ + pTab->zName + )); + #ifndef SQLITE_OMIT_TRACE +- sqlite3VdbeChangeP4(v, -1, +- sqlite3MPrintf(db, "-- TRIGGER %s", pTrigger->zName), P4_DYNAMIC +- ); ++ if( pTrigger->zName ){ ++ sqlite3VdbeChangeP4(v, -1, ++ sqlite3MPrintf(db, "-- TRIGGER %s", pTrigger->zName), P4_DYNAMIC ++ ); ++ } + #endif + + /* If one was specified, code the WHEN clause. If it evaluates to false +@@ -124546,7 +131689,7 @@ + VdbeComment((v, "End: %s.%s", pTrigger->zName, onErrorText(orconf))); + + transferParseError(pParse, pSubParse); +- if( db->mallocFailed==0 ){ ++ if( db->mallocFailed==0 && pParse->nErr==0 ){ + pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pTop->nMaxArg); + } + pProgram->nMem = pSubParse->nMem; +@@ -124854,6 +131997,57 @@ + } + + /* ++** Check to see if column iCol of index pIdx references any of the ++** columns defined by aXRef and chngRowid. Return true if it does ++** and false if not. This is an optimization. False-positives are a ++** performance degradation, but false-negatives can result in a corrupt ++** index and incorrect answers. ++** ++** aXRef[j] will be non-negative if column j of the original table is ++** being updated. chngRowid will be true if the rowid of the table is ++** being updated. ++*/ ++static int indexColumnIsBeingUpdated( ++ Index *pIdx, /* The index to check */ ++ int iCol, /* Which column of the index to check */ ++ int *aXRef, /* aXRef[j]>=0 if column j is being updated */ ++ int chngRowid /* true if the rowid is being updated */ ++){ ++ i16 iIdxCol = pIdx->aiColumn[iCol]; ++ assert( iIdxCol!=XN_ROWID ); /* Cannot index rowid */ ++ if( iIdxCol>=0 ){ ++ return aXRef[iIdxCol]>=0; ++ } ++ assert( iIdxCol==XN_EXPR ); ++ assert( pIdx->aColExpr!=0 ); ++ assert( pIdx->aColExpr->a[iCol].pExpr!=0 ); ++ return sqlite3ExprReferencesUpdatedColumn(pIdx->aColExpr->a[iCol].pExpr, ++ aXRef,chngRowid); ++} ++ ++/* ++** Check to see if index pIdx is a partial index whose conditional ++** expression might change values due to an UPDATE. Return true if ++** the index is subject to change and false if the index is guaranteed ++** to be unchanged. This is an optimization. False-positives are a ++** performance degradation, but false-negatives can result in a corrupt ++** index and incorrect answers. ++** ++** aXRef[j] will be non-negative if column j of the original table is ++** being updated. chngRowid will be true if the rowid of the table is ++** being updated. ++*/ ++static int indexWhereClauseMightChange( ++ Index *pIdx, /* The index to check */ ++ int *aXRef, /* aXRef[j]>=0 if column j is being updated */ ++ int chngRowid /* true if the rowid is being updated */ ++){ ++ if( pIdx->pPartIdxWhere==0 ) return 0; ++ return sqlite3ExprReferencesUpdatedColumn(pIdx->pPartIdxWhere, ++ aXRef, chngRowid); ++} ++ ++/* + ** Process an UPDATE statement. + ** + ** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL; +@@ -124865,7 +132059,10 @@ + SrcList *pTabList, /* The table in which we should change things */ + ExprList *pChanges, /* Things to be changed */ + Expr *pWhere, /* The WHERE clause. May be null */ +- int onError /* How to handle constraint errors */ ++ int onError, /* How to handle constraint errors */ ++ ExprList *pOrderBy, /* ORDER BY clause. May be null */ ++ Expr *pLimit, /* LIMIT clause. May be null */ ++ Upsert *pUpsert /* ON CONFLICT clause, or null */ + ){ + int i, j; /* Loop counters */ + Table *pTab; /* The table to be updated */ +@@ -124950,6 +132147,16 @@ + # define isView 0 + #endif + ++#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT ++ if( !isView ){ ++ pWhere = sqlite3LimitWhere( ++ pParse, pTabList, pWhere, pOrderBy, pLimit, "UPDATE" ++ ); ++ pOrderBy = 0; ++ pLimit = 0; ++ } ++#endif ++ + if( sqlite3ViewGetColumnNames(pParse, pTab) ){ + goto update_cleanup; + } +@@ -124962,16 +132169,23 @@ + ** need to occur right after the database cursor. So go ahead and + ** allocate enough space, just in case. + */ +- pTabList->a[0].iCursor = iBaseCur = iDataCur = pParse->nTab++; ++ iBaseCur = iDataCur = pParse->nTab++; + iIdxCur = iDataCur+1; + pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); ++ testcase( pPk!=0 && pPk!=pTab->pIndex ); + for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ +- if( IsPrimaryKeyIndex(pIdx) && pPk!=0 ){ ++ if( pPk==pIdx ){ + iDataCur = pParse->nTab; +- pTabList->a[0].iCursor = iDataCur; + } + pParse->nTab++; + } ++ if( pUpsert ){ ++ /* On an UPSERT, reuse the same cursors already opened by INSERT */ ++ iDataCur = pUpsert->iDataCur; ++ iIdxCur = pUpsert->iIdxCur; ++ pParse->nTab = iBaseCur; ++ } ++ pTabList->a[0].iCursor = iDataCur; + + /* Allocate space for aXRef[], aRegIdx[], and aToOpen[]. + ** Initialize aXRef[] and aToOpen[] to their default values. +@@ -124988,6 +132202,8 @@ + memset(&sNC, 0, sizeof(sNC)); + sNC.pParse = pParse; + sNC.pSrcList = pTabList; ++ sNC.uNC.pUpsert = pUpsert; ++ sNC.ncFlags = NC_UUpsert; + + /* Resolve the column names in all the expressions of the + ** of the UPDATE statement. Also find the column index +@@ -125054,19 +132270,18 @@ + /* There is one entry in the aRegIdx[] array for each index on the table + ** being updated. Fill in aRegIdx[] with a register number that will hold + ** the key for accessing each index. +- ** +- ** FIXME: Be smarter about omitting indexes that use expressions. + */ + for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ + int reg; +- if( chngKey || hasFK>1 || pIdx->pPartIdxWhere || pIdx==pPk ){ ++ if( chngKey || hasFK>1 || pIdx==pPk ++ || indexWhereClauseMightChange(pIdx,aXRef,chngRowid) ++ ){ + reg = ++pParse->nMem; + pParse->nMem += pIdx->nColumn; + }else{ + reg = 0; + for(i=0; i<pIdx->nKeyCol; i++){ +- i16 iIdxCol = pIdx->aiColumn[i]; +- if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){ ++ if( indexColumnIsBeingUpdated(pIdx, i, aXRef, chngRowid) ){ + reg = ++pParse->nMem; + pParse->nMem += pIdx->nColumn; + if( (onError==OE_Replace) +@@ -125091,7 +132306,7 @@ + v = sqlite3GetVdbe(pParse); + if( v==0 ) goto update_cleanup; + if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); +- sqlite3BeginWriteOperation(pParse, 1, iDb); ++ sqlite3BeginWriteOperation(pParse, pTrigger || hasFK, iDb); + + /* Allocate required registers. */ + if( !IsVirtual(pTab) ){ +@@ -125118,7 +132333,11 @@ + */ + #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) + if( isView ){ +- sqlite3MaterializeView(pParse, pTab, pWhere, iDataCur); ++ sqlite3MaterializeView(pParse, pTab, ++ pWhere, pOrderBy, pLimit, iDataCur ++ ); ++ pOrderBy = 0; ++ pLimit = 0; + } + #endif + +@@ -125138,8 +132357,16 @@ + } + #endif + +- /* Initialize the count of updated rows */ +- if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab ){ ++ /* Jump to labelBreak to abandon further processing of this UPDATE */ ++ labelContinue = labelBreak = sqlite3VdbeMakeLabel(v); ++ ++ /* Not an UPSERT. Normal processing. Begin by ++ ** initialize the count of updated rows */ ++ if( (db->flags&SQLITE_CountRows)!=0 ++ && !pParse->pTriggerTab ++ && !pParse->nested ++ && pUpsert==0 ++ ){ + regRowCount = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); + } +@@ -125152,46 +132379,61 @@ + iPk = pParse->nMem+1; + pParse->nMem += nPk; + regKey = ++pParse->nMem; +- iEph = pParse->nTab++; +- +- sqlite3VdbeAddOp2(v, OP_Null, 0, iPk); +- addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk); +- sqlite3VdbeSetP4KeyInfo(pParse, pPk); ++ if( pUpsert==0 ){ ++ iEph = pParse->nTab++; ++ sqlite3VdbeAddOp3(v, OP_Null, 0, iPk, iPk+nPk-1); ++ addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk); ++ sqlite3VdbeSetP4KeyInfo(pParse, pPk); ++ } + } +- +- /* 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|WHERE_SEEK_UNIQ_TABLE; +- if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){ +- flags |= WHERE_ONEPASS_MULTIROW; ++ ++ if( pUpsert ){ ++ /* If this is an UPSERT, then all cursors have already been opened by ++ ** the outer INSERT and the data cursor should be pointing at the row ++ ** that is to be updated. So bypass the code that searches for the ++ ** row(s) to be updated. ++ */ ++ pWInfo = 0; ++ eOnePass = ONEPASS_SINGLE; ++ sqlite3ExprIfFalse(pParse, pWhere, labelBreak, SQLITE_JUMPIFNULL); ++ }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|WHERE_SEEK_UNIQ_TABLE; ++ if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){ ++ flags |= WHERE_ONEPASS_MULTIROW; ++ } ++ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 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 ++ ** updated. Otherwise, if there is an index on "b", statements like ++ ** the following could create an infinite loop: ++ ** ++ ** UPDATE t1 SET b=b+1 WHERE b>? ++ ** ++ ** Fall back to ONEPASS_OFF if where.c has selected a ONEPASS_MULTI ++ ** strategy that uses an index for which one or more columns are being ++ ** updated. */ ++ eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); ++ if( eOnePass!=ONEPASS_SINGLE ){ ++ sqlite3MultiWrite(pParse); ++ if( eOnePass==ONEPASS_MULTI ){ ++ int iCur = aiCurOnePass[1]; ++ if( iCur>=0 && iCur!=iDataCur && aToOpen[iCur-iBaseCur] ){ ++ eOnePass = ONEPASS_OFF; ++ } ++ assert( iCur!=iDataCur || !HasRowid(pTab) ); ++ } ++ } + } +- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 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 +- ** updated. Otherwise, if there is an index on "b", statements like +- ** the following could create an infinite loop: +- ** +- ** UPDATE t1 SET b=b+1 WHERE b>? +- ** +- ** Fall back to ONEPASS_OFF if where.c has selected a ONEPASS_MULTI +- ** strategy that uses an index for which one or more columns are being +- ** updated. */ +- eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); +- if( eOnePass==ONEPASS_MULTI ){ +- int iCur = aiCurOnePass[1]; +- if( iCur>=0 && iCur!=iDataCur && aToOpen[iCur-iBaseCur] ){ +- eOnePass = ONEPASS_OFF; +- } +- assert( iCur!=iDataCur || !HasRowid(pTab) ); +- } +- + if( HasRowid(pTab) ){ + /* Read the rowid of the current row of the WHERE scan. In ONEPASS_OFF + ** mode, write the rowid into the FIFO. In either of the one-pass modes, +@@ -125211,7 +132453,7 @@ + sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur,pPk->aiColumn[i],iPk+i); + } + if( eOnePass ){ +- sqlite3VdbeChangeToNoop(v, addrOpen); ++ if( addrOpen ) sqlite3VdbeChangeToNoop(v, addrOpen); + nKey = nPk; + regKey = iPk; + }else{ +@@ -125221,59 +132463,58 @@ + } + } + +- if( eOnePass!=ONEPASS_MULTI ){ +- sqlite3WhereEnd(pWInfo); +- } +- +- labelBreak = sqlite3VdbeMakeLabel(v); +- if( !isView ){ +- int addrOnce = 0; +- +- /* Open every index that needs updating. */ +- if( eOnePass!=ONEPASS_OFF ){ +- if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0; +- if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0; ++ if( pUpsert==0 ){ ++ if( eOnePass!=ONEPASS_MULTI ){ ++ sqlite3WhereEnd(pWInfo); + } +- +- if( eOnePass==ONEPASS_MULTI && (nIdx-(aiCurOnePass[1]>=0))>0 ){ +- addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); ++ ++ if( !isView ){ ++ int addrOnce = 0; ++ ++ /* Open every index that needs updating. */ ++ if( eOnePass!=ONEPASS_OFF ){ ++ if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0; ++ if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0; ++ } ++ ++ if( eOnePass==ONEPASS_MULTI && (nIdx-(aiCurOnePass[1]>=0))>0 ){ ++ addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); ++ } ++ sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur, ++ aToOpen, 0, 0); ++ if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); + } +- sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur, aToOpen, +- 0, 0); +- if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); +- } +- +- /* Top of the update loop */ +- if( eOnePass!=ONEPASS_OFF ){ +- if( !isView && aiCurOnePass[0]!=iDataCur && aiCurOnePass[1]!=iDataCur ){ +- assert( pPk ); +- sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey); +- VdbeCoverageNeverTaken(v); +- } +- if( eOnePass==ONEPASS_SINGLE ){ +- labelContinue = labelBreak; ++ ++ /* Top of the update loop */ ++ if( eOnePass!=ONEPASS_OFF ){ ++ if( !isView && aiCurOnePass[0]!=iDataCur && aiCurOnePass[1]!=iDataCur ){ ++ assert( pPk ); ++ sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey,nKey); ++ VdbeCoverage(v); ++ } ++ if( eOnePass!=ONEPASS_SINGLE ){ ++ labelContinue = sqlite3VdbeMakeLabel(v); ++ } ++ sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak); ++ VdbeCoverageIf(v, pPk==0); ++ VdbeCoverageIf(v, pPk!=0); ++ }else if( pPk ){ ++ labelContinue = sqlite3VdbeMakeLabel(v); ++ sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v); ++ addrTop = sqlite3VdbeAddOp2(v, OP_RowData, iEph, regKey); ++ sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0); ++ VdbeCoverage(v); + }else{ +- labelContinue = sqlite3VdbeMakeLabel(v); ++ labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet,labelBreak, ++ regOldRowid); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid); ++ VdbeCoverage(v); + } +- sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak); +- VdbeCoverageIf(v, pPk==0); +- VdbeCoverageIf(v, pPk!=0); +- }else if( pPk ){ +- labelContinue = sqlite3VdbeMakeLabel(v); +- sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v); +- addrTop = sqlite3VdbeAddOp2(v, OP_RowData, iEph, regKey); +- sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0); +- VdbeCoverage(v); +- }else{ +- labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, labelBreak, +- regOldRowid); +- VdbeCoverage(v); +- sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid); +- VdbeCoverage(v); + } + +- /* If the record number will change, set register regNewRowid to +- ** contain the new value. If the record number is not being modified, ++ /* If the rowid value will change, set register regNewRowid to ++ ** contain the new value. If the rowid is not being modified, + ** then regNewRowid is the same register as regOldRowid, which is + ** already populated. */ + assert( chngKey || pTrigger || hasFK || regOldRowid==regNewRowid ); +@@ -125336,7 +132577,7 @@ + */ + testcase( i==31 ); + testcase( i==32 ); +- sqlite3ExprCodeGetColumnToReg(pParse, pTab, i, iDataCur, regNew+i); ++ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i); + }else{ + sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); + } +@@ -125365,10 +132606,14 @@ + VdbeCoverage(v); + } + +- /* If it did not delete it, the row-trigger may still have modified ++ /* After-BEFORE-trigger-reload-loop: ++ ** If it did not delete it, the BEFORE trigger may still have modified + ** some of the columns of the row being updated. Load the values for +- ** all columns not modified by the update statement into their +- ** registers in case this has happened. ++ ** all columns not modified by the update statement into their registers ++ ** in case this has happened. Only unmodified columns are reloaded. ++ ** The values computed for modified columns use the values before the ++ ** BEFORE trigger runs. See test case trigger1-18.0 (added 2018-04-26) ++ ** for an example. + */ + for(i=0; i<pTab->nCol; i++){ + if( aXRef[i]<0 && i!=pTab->iPKey ){ +@@ -125384,7 +132629,7 @@ + assert( regOldRowid>0 ); + sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, + regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace, +- aXRef); ++ aXRef, 0); + + /* Do FK constraint checks. */ + if( hasFK ){ +@@ -125454,7 +132699,7 @@ + + /* Increment the row counter + */ +- if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab){ ++ if( regRowCount ){ + sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); + } + +@@ -125481,16 +132726,15 @@ + ** maximum rowid counter values recorded while inserting into + ** autoincrement tables. + */ +- if( pParse->nested==0 && pParse->pTriggerTab==0 ){ ++ if( pParse->nested==0 && pParse->pTriggerTab==0 && pUpsert==0 ){ + sqlite3AutoincrementEnd(pParse); + } + + /* +- ** Return the number of rows that were changed. If this routine is +- ** generating code because of a call to sqlite3NestedParse(), do not +- ** invoke the callback function. ++ ** Return the number of rows that were changed, if we are tracking ++ ** that information. + */ +- if( (db->flags&SQLITE_CountRows) && !pParse->pTriggerTab && !pParse->nested ){ ++ if( regRowCount ){ + sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", SQLITE_STATIC); +@@ -125502,6 +132746,10 @@ + sqlite3SrcListDelete(db, pTabList); + sqlite3ExprListDelete(db, pChanges); + sqlite3ExprDelete(db, pWhere); ++#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) ++ sqlite3ExprListDelete(db, pOrderBy); ++ sqlite3ExprDelete(db, pLimit); ++#endif + return; + } + /* Make sure "isView" and other macros defined above are undefined. Otherwise +@@ -125558,10 +132806,10 @@ + int regRowid; /* Register for ephem table rowid */ + int iCsr = pSrc->a[0].iCursor; /* Cursor used for virtual table scan */ + int aDummy[2]; /* Unused arg for sqlite3WhereOkOnePass() */ +- int bOnePass; /* True to use onepass strategy */ ++ int eOnePass; /* True to use onepass strategy */ + int addr; /* Address of OP_OpenEphemeral */ + +- /* Allocate nArg registers to martial the arguments to VUpdate. Then ++ /* Allocate nArg registers in which to gather the arguments for VUpdate. Then + ** create and open the ephemeral table in which the records created from + ** these arguments will be temporarily stored. */ + assert( v ); +@@ -125577,40 +132825,58 @@ + if( pWInfo==0 ) return; + + /* Populate the argument registers. */ +- sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg); +- if( pRowid ){ +- sqlite3ExprCode(pParse, pRowid, regArg+1); +- }else{ +- sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg+1); +- } + for(i=0; i<pTab->nCol; i++){ + if( aXRef[i]>=0 ){ + sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i); + }else{ + sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i); ++ sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG);/* Enable sqlite3_vtab_nochange() */ + } + } ++ if( HasRowid(pTab) ){ ++ sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg); ++ if( pRowid ){ ++ sqlite3ExprCode(pParse, pRowid, regArg+1); ++ }else{ ++ sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg+1); ++ } ++ }else{ ++ Index *pPk; /* PRIMARY KEY index */ ++ i16 iPk; /* PRIMARY KEY column */ ++ pPk = sqlite3PrimaryKeyIndex(pTab); ++ assert( pPk!=0 ); ++ assert( pPk->nKeyCol==1 ); ++ iPk = pPk->aiColumn[0]; ++ sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, iPk, regArg); ++ sqlite3VdbeAddOp2(v, OP_SCopy, regArg+2+iPk, regArg+1); ++ } + +- bOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy); ++ eOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy); + +- if( bOnePass ){ ++ /* There is no ONEPASS_MULTI on virtual tables */ ++ assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE ); ++ ++ if( eOnePass ){ + /* If using the onepass strategy, no-op out the OP_OpenEphemeral coded +- ** above. Also, if this is a top-level parse (not a trigger), clear the +- ** multi-write flag so that the VM does not open a statement journal */ ++ ** above. */ + sqlite3VdbeChangeToNoop(v, addr); +- if( sqlite3IsToplevel(pParse) ){ +- pParse->isMultiWrite = 0; +- } ++ sqlite3VdbeAddOp1(v, OP_Close, iCsr); + }else{ + /* Create a record from the argument register contents and insert it into + ** the ephemeral table. */ ++ sqlite3MultiWrite(pParse); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regArg, nArg, regRec); ++#ifdef SQLITE_DEBUG ++ /* Signal an assert() within OP_MakeRecord that it is allowed to ++ ** accept no-change records with serial_type 10 */ ++ sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC); ++#endif + sqlite3VdbeAddOp2(v, OP_NewRowid, ephemTab, regRowid); + sqlite3VdbeAddOp3(v, OP_Insert, ephemTab, regRec, regRowid); + } + + +- if( bOnePass==0 ){ ++ if( eOnePass==ONEPASS_OFF ){ + /* End the virtual table scan */ + sqlite3WhereEnd(pWInfo); + +@@ -125630,7 +132896,7 @@ + + /* End of the ephemeral table scan. Or, if using the onepass strategy, + ** jump to here if the scan visited zero rows. */ +- if( bOnePass==0 ){ ++ if( eOnePass==ONEPASS_OFF ){ + sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v); + sqlite3VdbeJumpHere(v, addr); + sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); +@@ -125641,6 +132907,261 @@ + #endif /* SQLITE_OMIT_VIRTUALTABLE */ + + /************** End of update.c **********************************************/ ++/************** Begin file upsert.c ******************************************/ ++/* ++** 2018-04-12 ++** ++** The author disclaims copyright to this source code. In place of ++** a legal notice, here is a blessing: ++** ++** May you do good and not evil. ++** May you find forgiveness for yourself and forgive others. ++** May you share freely, never taking more than you give. ++** ++************************************************************************* ++** This file contains code to implement various aspects of UPSERT ++** processing and handling of the Upsert object. ++*/ ++/* #include "sqliteInt.h" */ ++ ++#ifndef SQLITE_OMIT_UPSERT ++/* ++** Free a list of Upsert objects ++*/ ++SQLITE_PRIVATE void sqlite3UpsertDelete(sqlite3 *db, Upsert *p){ ++ if( p ){ ++ sqlite3ExprListDelete(db, p->pUpsertTarget); ++ sqlite3ExprDelete(db, p->pUpsertTargetWhere); ++ sqlite3ExprListDelete(db, p->pUpsertSet); ++ sqlite3ExprDelete(db, p->pUpsertWhere); ++ sqlite3DbFree(db, p); ++ } ++} ++ ++/* ++** Duplicate an Upsert object. ++*/ ++SQLITE_PRIVATE Upsert *sqlite3UpsertDup(sqlite3 *db, Upsert *p){ ++ if( p==0 ) return 0; ++ return sqlite3UpsertNew(db, ++ sqlite3ExprListDup(db, p->pUpsertTarget, 0), ++ sqlite3ExprDup(db, p->pUpsertTargetWhere, 0), ++ sqlite3ExprListDup(db, p->pUpsertSet, 0), ++ sqlite3ExprDup(db, p->pUpsertWhere, 0) ++ ); ++} ++ ++/* ++** Create a new Upsert object. ++*/ ++SQLITE_PRIVATE Upsert *sqlite3UpsertNew( ++ sqlite3 *db, /* Determines which memory allocator to use */ ++ ExprList *pTarget, /* Target argument to ON CONFLICT, or NULL */ ++ Expr *pTargetWhere, /* Optional WHERE clause on the target */ ++ ExprList *pSet, /* UPDATE columns, or NULL for a DO NOTHING */ ++ Expr *pWhere /* WHERE clause for the ON CONFLICT UPDATE */ ++){ ++ Upsert *pNew; ++ pNew = sqlite3DbMallocRaw(db, sizeof(Upsert)); ++ if( pNew==0 ){ ++ sqlite3ExprListDelete(db, pTarget); ++ sqlite3ExprDelete(db, pTargetWhere); ++ sqlite3ExprListDelete(db, pSet); ++ sqlite3ExprDelete(db, pWhere); ++ return 0; ++ }else{ ++ pNew->pUpsertTarget = pTarget; ++ pNew->pUpsertTargetWhere = pTargetWhere; ++ pNew->pUpsertSet = pSet; ++ pNew->pUpsertWhere = pWhere; ++ pNew->pUpsertIdx = 0; ++ } ++ return pNew; ++} ++ ++/* ++** Analyze the ON CONFLICT clause described by pUpsert. Resolve all ++** symbols in the conflict-target. ++** ++** Return SQLITE_OK if everything works, or an error code is something ++** is wrong. ++*/ ++SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget( ++ Parse *pParse, /* The parsing context */ ++ SrcList *pTabList, /* Table into which we are inserting */ ++ Upsert *pUpsert /* The ON CONFLICT clauses */ ++){ ++ Table *pTab; /* That table into which we are inserting */ ++ int rc; /* Result code */ ++ int iCursor; /* Cursor used by pTab */ ++ Index *pIdx; /* One of the indexes of pTab */ ++ ExprList *pTarget; /* The conflict-target clause */ ++ Expr *pTerm; /* One term of the conflict-target clause */ ++ NameContext sNC; /* Context for resolving symbolic names */ ++ Expr sCol[2]; /* Index column converted into an Expr */ ++ ++ assert( pTabList->nSrc==1 ); ++ assert( pTabList->a[0].pTab!=0 ); ++ assert( pUpsert!=0 ); ++ assert( pUpsert->pUpsertTarget!=0 ); ++ ++ /* Resolve all symbolic names in the conflict-target clause, which ++ ** includes both the list of columns and the optional partial-index ++ ** WHERE clause. ++ */ ++ memset(&sNC, 0, sizeof(sNC)); ++ sNC.pParse = pParse; ++ sNC.pSrcList = pTabList; ++ rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget); ++ if( rc ) return rc; ++ rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere); ++ if( rc ) return rc; ++ ++ /* Check to see if the conflict target matches the rowid. */ ++ pTab = pTabList->a[0].pTab; ++ pTarget = pUpsert->pUpsertTarget; ++ iCursor = pTabList->a[0].iCursor; ++ if( HasRowid(pTab) ++ && pTarget->nExpr==1 ++ && (pTerm = pTarget->a[0].pExpr)->op==TK_COLUMN ++ && pTerm->iColumn==XN_ROWID ++ ){ ++ /* The conflict-target is the rowid of the primary table */ ++ assert( pUpsert->pUpsertIdx==0 ); ++ return SQLITE_OK; ++ } ++ ++ /* Initialize sCol[0..1] to be an expression parse tree for a ++ ** single column of an index. The sCol[0] node will be the TK_COLLATE ++ ** operator and sCol[1] will be the TK_COLUMN operator. Code below ++ ** will populate the specific collation and column number values ++ ** prior to comparing against the conflict-target expression. ++ */ ++ memset(sCol, 0, sizeof(sCol)); ++ sCol[0].op = TK_COLLATE; ++ sCol[0].pLeft = &sCol[1]; ++ sCol[1].op = TK_COLUMN; ++ sCol[1].iTable = pTabList->a[0].iCursor; ++ ++ /* Check for matches against other indexes */ ++ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ ++ int ii, jj, nn; ++ if( !IsUniqueIndex(pIdx) ) continue; ++ if( pTarget->nExpr!=pIdx->nKeyCol ) continue; ++ if( pIdx->pPartIdxWhere ){ ++ if( pUpsert->pUpsertTargetWhere==0 ) continue; ++ if( sqlite3ExprCompare(pParse, pUpsert->pUpsertTargetWhere, ++ pIdx->pPartIdxWhere, iCursor)!=0 ){ ++ continue; ++ } ++ } ++ nn = pIdx->nKeyCol; ++ for(ii=0; ii<nn; ii++){ ++ Expr *pExpr; ++ sCol[0].u.zToken = (char*)pIdx->azColl[ii]; ++ if( pIdx->aiColumn[ii]==XN_EXPR ){ ++ assert( pIdx->aColExpr!=0 ); ++ assert( pIdx->aColExpr->nExpr>ii ); ++ pExpr = pIdx->aColExpr->a[ii].pExpr; ++ if( pExpr->op!=TK_COLLATE ){ ++ sCol[0].pLeft = pExpr; ++ pExpr = &sCol[0]; ++ } ++ }else{ ++ sCol[0].pLeft = &sCol[1]; ++ sCol[1].iColumn = pIdx->aiColumn[ii]; ++ pExpr = &sCol[0]; ++ } ++ for(jj=0; jj<nn; jj++){ ++ if( sqlite3ExprCompare(pParse, pTarget->a[jj].pExpr, pExpr,iCursor)<2 ){ ++ break; /* Column ii of the index matches column jj of target */ ++ } ++ } ++ if( jj>=nn ){ ++ /* The target contains no match for column jj of the index */ ++ break; ++ } ++ } ++ if( ii<nn ){ ++ /* Column ii of the index did not match any term of the conflict target. ++ ** Continue the search with the next index. */ ++ continue; ++ } ++ pUpsert->pUpsertIdx = pIdx; ++ return SQLITE_OK; ++ } ++ sqlite3ErrorMsg(pParse, "ON CONFLICT clause does not match any " ++ "PRIMARY KEY or UNIQUE constraint"); ++ return SQLITE_ERROR; ++} ++ ++/* ++** Generate bytecode that does an UPDATE as part of an upsert. ++** ++** If pIdx is NULL, then the UNIQUE constraint that failed was the IPK. ++** In this case parameter iCur is a cursor open on the table b-tree that ++** currently points to the conflicting table row. Otherwise, if pIdx ++** is not NULL, then pIdx is the constraint that failed and iCur is a ++** cursor points to the conflicting row. ++*/ ++SQLITE_PRIVATE void sqlite3UpsertDoUpdate( ++ Parse *pParse, /* The parsing and code-generating context */ ++ Upsert *pUpsert, /* The ON CONFLICT clause for the upsert */ ++ Table *pTab, /* The table being updated */ ++ Index *pIdx, /* The UNIQUE constraint that failed */ ++ int iCur /* Cursor for pIdx (or pTab if pIdx==NULL) */ ++){ ++ Vdbe *v = pParse->pVdbe; ++ sqlite3 *db = pParse->db; ++ SrcList *pSrc; /* FROM clause for the UPDATE */ ++ int iDataCur; ++ ++ assert( v!=0 ); ++ assert( pUpsert!=0 ); ++ VdbeNoopComment((v, "Begin DO UPDATE of UPSERT")); ++ iDataCur = pUpsert->iDataCur; ++ if( pIdx && iCur!=iDataCur ){ ++ if( HasRowid(pTab) ){ ++ int regRowid = sqlite3GetTempReg(pParse); ++ sqlite3VdbeAddOp2(v, OP_IdxRowid, iCur, regRowid); ++ sqlite3VdbeAddOp3(v, OP_SeekRowid, iDataCur, 0, regRowid); ++ VdbeCoverage(v); ++ sqlite3ReleaseTempReg(pParse, regRowid); ++ }else{ ++ Index *pPk = sqlite3PrimaryKeyIndex(pTab); ++ int nPk = pPk->nKeyCol; ++ int iPk = pParse->nMem+1; ++ int i; ++ pParse->nMem += nPk; ++ for(i=0; i<nPk; i++){ ++ int k; ++ assert( pPk->aiColumn[i]>=0 ); ++ k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]); ++ sqlite3VdbeAddOp3(v, OP_Column, iCur, k, iPk+i); ++ VdbeComment((v, "%s.%s", pIdx->zName, ++ pTab->aCol[pPk->aiColumn[i]].zName)); ++ } ++ sqlite3VdbeVerifyAbortable(v, OE_Abort); ++ i = sqlite3VdbeAddOp4Int(v, OP_Found, iDataCur, 0, iPk, nPk); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CORRUPT, OE_Abort, 0, ++ "corrupt database", P4_STATIC); ++ sqlite3VdbeJumpHere(v, i); ++ } ++ } ++ /* pUpsert does not own pUpsertSrc - the outer INSERT statement does. So ++ ** we have to make a copy before passing it down into sqlite3Update() */ ++ pSrc = sqlite3SrcListDup(db, pUpsert->pUpsertSrc, 0); ++ sqlite3Update(pParse, pSrc, pUpsert->pUpsertSet, ++ pUpsert->pUpsertWhere, OE_Abort, 0, 0, pUpsert); ++ pUpsert->pUpsertSet = 0; /* Will have been deleted by sqlite3Update() */ ++ pUpsert->pUpsertWhere = 0; /* Will have been deleted by sqlite3Update() */ ++ VdbeNoopComment((v, "End DO UPDATE of UPSERT")); ++} ++ ++#endif /* SQLITE_OMIT_UPSERT */ ++ ++/************** End of upsert.c **********************************************/ + /************** Begin file vacuum.c ******************************************/ + /* + ** 2003 April 6 +@@ -125683,8 +133204,14 @@ + while( SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){ + const char *zSubSql = (const char*)sqlite3_column_text(pStmt,0); + assert( sqlite3_strnicmp(zSql,"SELECT",6)==0 ); +- if( zSubSql ){ +- assert( zSubSql[0]!='S' ); ++ /* The secondary SQL must be one of CREATE TABLE, CREATE INDEX, ++ ** or INSERT. Historically there have been attacks that first ++ ** corrupt the sqlite_master.sql field with other kinds of statements ++ ** then run VACUUM to get those statements to execute at inappropriate ++ ** times. */ ++ if( zSubSql ++ && (strncmp(zSubSql,"CRE",3)==0 || strncmp(zSubSql,"INS",3)==0) ++ ){ + rc = execSql(db, pzErrMsg, zSubSql); + if( rc!=SQLITE_OK ) break; + } +@@ -125774,7 +133301,8 @@ + int rc = SQLITE_OK; /* Return code from service routines */ + Btree *pMain; /* The database being vacuumed */ + Btree *pTemp; /* The temporary database we vacuum into */ +- int saved_flags; /* Saved value of the db->flags */ ++ u16 saved_mDbFlags; /* Saved value of db->mDbFlags */ ++ u32 saved_flags; /* Saved value of db->flags */ + int saved_nChange; /* Saved value of db->nChange */ + int saved_nTotalChange; /* Saved value of db->nTotalChange */ + u8 saved_mTrace; /* Saved trace settings */ +@@ -125797,12 +133325,14 @@ + ** restored before returning. Then set the writable-schema flag, and + ** disable CHECK and foreign key constraints. */ + saved_flags = db->flags; ++ saved_mDbFlags = db->mDbFlags; + saved_nChange = db->nChange; + saved_nTotalChange = db->nTotalChange; + saved_mTrace = db->mTrace; +- db->flags |= (SQLITE_WriteSchema | SQLITE_IgnoreChecks +- | SQLITE_PreferBuiltin | SQLITE_Vacuum); +- db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder | SQLITE_CountRows); ++ db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks; ++ db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum; ++ db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder ++ | SQLITE_Defensive | SQLITE_CountRows); + db->mTrace = 0; + + zDbMain = db->aDb[iDb].zDbSName; +@@ -125860,7 +133390,7 @@ + */ + rc = execSql(db, pzErrMsg, "BEGIN"); + if( rc!=SQLITE_OK ) goto end_of_vacuum; +- rc = sqlite3BtreeBeginTrans(pMain, 2); ++ rc = sqlite3BtreeBeginTrans(pMain, 2, 0); + if( rc!=SQLITE_OK ) goto end_of_vacuum; + + /* Do not attempt to change the page size for a WAL database */ +@@ -125895,7 +133425,7 @@ + if( rc!=SQLITE_OK ) goto end_of_vacuum; + rc = execSqlF(db, pzErrMsg, + "SELECT sql FROM \"%w\".sqlite_master" +- " WHERE type='index' AND length(sql)>10", ++ " WHERE type='index'", + zDbMain + ); + if( rc!=SQLITE_OK ) goto end_of_vacuum; +@@ -125912,8 +133442,8 @@ + "WHERE type='table'AND coalesce(rootpage,1)>0", + zDbMain + ); +- assert( (db->flags & SQLITE_Vacuum)!=0 ); +- db->flags &= ~SQLITE_Vacuum; ++ assert( (db->mDbFlags & DBFLAG_Vacuum)!=0 ); ++ db->mDbFlags &= ~DBFLAG_Vacuum; + if( rc!=SQLITE_OK ) goto end_of_vacuum; + + /* Copy the triggers, views, and virtual tables from the main database +@@ -125981,6 +133511,7 @@ + end_of_vacuum: + /* Restore the original value of db->flags */ + db->init.iDb = 0; ++ db->mDbFlags = saved_mDbFlags; + db->flags = saved_flags; + db->nChange = saved_nChange; + db->nTotalChange = saved_nTotalChange; +@@ -126057,8 +133588,10 @@ + ){ + Module *pMod; + int nName = sqlite3Strlen30(zName); +- pMod = (Module *)sqlite3DbMallocRawNN(db, sizeof(Module) + nName + 1); +- if( pMod ){ ++ pMod = (Module *)sqlite3Malloc(sizeof(Module) + nName + 1); ++ if( pMod==0 ){ ++ sqlite3OomFault(db); ++ }else{ + Module *pDel; + char *zCopy = (char *)(&pMod[1]); + memcpy(zCopy, zName, nName+1); +@@ -126275,7 +133808,7 @@ + assert( sqlite3_mutex_held(db->mutex) ); + + if( p ){ +- sqlite3ExpirePreparedStatements(db); ++ sqlite3ExpirePreparedStatements(db, 0); + do { + VTable *pNext = p->pNext; + sqlite3VtabUnlock(p); +@@ -126341,7 +133874,6 @@ + Token *pModuleName, /* Name of the module for the virtual table */ + int ifNotExists /* No error if the table already exists */ + ){ +- int iDb; /* The database the table is being created in */ + Table *pTable; /* The new virtual table */ + sqlite3 *db; /* Database connection */ + +@@ -126351,8 +133883,6 @@ + assert( 0==pTable->pIndex ); + + db = pParse->db; +- iDb = sqlite3SchemaToIndex(db, pTable->pSchema); +- assert( iDb>=0 ); + + assert( pTable->nModuleArg==0 ); + addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName)); +@@ -126372,6 +133902,8 @@ + ** The second call, to obtain permission to create the table, is made now. + */ + if( pTable->azModuleArg ){ ++ int iDb = sqlite3SchemaToIndex(db, pTable->pSchema); ++ assert( iDb>=0 ); /* The database the table is being created in */ + sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName, + pTable->azModuleArg[0], pParse->db->aDb[iDb].zDbSName); + } +@@ -126533,13 +134065,14 @@ + } + } + +- zModuleName = sqlite3MPrintf(db, "%s", pTab->zName); ++ zModuleName = sqlite3DbStrDup(db, pTab->zName); + if( !zModuleName ){ + return SQLITE_NOMEM_BKPT; + } + +- pVTable = sqlite3DbMallocZero(db, sizeof(VTable)); ++ pVTable = sqlite3MallocZero(sizeof(VTable)); + if( !pVTable ){ ++ sqlite3OomFault(db); + sqlite3DbFree(db, zModuleName); + return SQLITE_NOMEM_BKPT; + } +@@ -126659,6 +134192,7 @@ + rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr); + if( rc!=SQLITE_OK ){ + sqlite3ErrorMsg(pParse, "%s", zErr); ++ pParse->rc = rc; + } + sqlite3DbFree(db, zErr); + } +@@ -126748,10 +134282,10 @@ + */ + SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ + VtabCtx *pCtx; +- Parse *pParse; + int rc = SQLITE_OK; + Table *pTab; + char *zErr = 0; ++ Parse sParse; + + #ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) || zCreateTable==0 ){ +@@ -126768,56 +134302,56 @@ + pTab = pCtx->pTab; + assert( IsVirtual(pTab) ); + +- pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); +- if( pParse==0 ){ +- rc = SQLITE_NOMEM_BKPT; +- }else{ +- pParse->declareVtab = 1; +- pParse->db = db; +- pParse->nQueryLoop = 1; +- +- if( SQLITE_OK==sqlite3RunParser(pParse, zCreateTable, &zErr) +- && pParse->pNewTable +- && !db->mallocFailed +- && !pParse->pNewTable->pSelect +- && !IsVirtual(pParse->pNewTable) +- ){ +- if( !pTab->aCol ){ +- Table *pNew = pParse->pNewTable; +- Index *pIdx; +- pTab->aCol = pNew->aCol; +- pTab->nCol = pNew->nCol; +- pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid); +- pNew->nCol = 0; +- pNew->aCol = 0; +- assert( pTab->pIndex==0 ); +- if( !HasRowid(pNew) && pCtx->pVTable->pMod->pModule->xUpdate!=0 ){ +- rc = SQLITE_ERROR; +- } +- pIdx = pNew->pIndex; +- if( pIdx ){ +- assert( pIdx->pNext==0 ); +- pTab->pIndex = pIdx; +- pNew->pIndex = 0; +- pIdx->pTable = pTab; +- } ++ memset(&sParse, 0, sizeof(sParse)); ++ sParse.eParseMode = PARSE_MODE_DECLARE_VTAB; ++ sParse.db = db; ++ sParse.nQueryLoop = 1; ++ if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable, &zErr) ++ && sParse.pNewTable ++ && !db->mallocFailed ++ && !sParse.pNewTable->pSelect ++ && !IsVirtual(sParse.pNewTable) ++ ){ ++ if( !pTab->aCol ){ ++ Table *pNew = sParse.pNewTable; ++ Index *pIdx; ++ pTab->aCol = pNew->aCol; ++ pTab->nCol = pNew->nCol; ++ pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid); ++ pNew->nCol = 0; ++ pNew->aCol = 0; ++ assert( pTab->pIndex==0 ); ++ assert( HasRowid(pNew) || sqlite3PrimaryKeyIndex(pNew)!=0 ); ++ if( !HasRowid(pNew) ++ && pCtx->pVTable->pMod->pModule->xUpdate!=0 ++ && sqlite3PrimaryKeyIndex(pNew)->nKeyCol!=1 ++ ){ ++ /* WITHOUT ROWID virtual tables must either be read-only (xUpdate==0) ++ ** or else must have a single-column PRIMARY KEY */ ++ rc = SQLITE_ERROR; + } +- pCtx->bDeclared = 1; +- }else{ +- sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr); +- sqlite3DbFree(db, zErr); +- rc = SQLITE_ERROR; ++ pIdx = pNew->pIndex; ++ if( pIdx ){ ++ assert( pIdx->pNext==0 ); ++ pTab->pIndex = pIdx; ++ pNew->pIndex = 0; ++ pIdx->pTable = pTab; ++ } + } +- pParse->declareVtab = 0; +- +- if( pParse->pVdbe ){ +- sqlite3VdbeFinalize(pParse->pVdbe); +- } +- sqlite3DeleteTable(db, pParse->pNewTable); +- sqlite3ParserReset(pParse); +- sqlite3StackFree(db, pParse); ++ pCtx->bDeclared = 1; ++ }else{ ++ sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr); ++ sqlite3DbFree(db, zErr); ++ rc = SQLITE_ERROR; + } ++ sParse.eParseMode = PARSE_MODE_NORMAL; + ++ if( sParse.pVdbe ){ ++ sqlite3VdbeFinalize(sParse.pVdbe); ++ } ++ sqlite3DeleteTable(db, sParse.pNewTable); ++ sqlite3ParserReset(&sParse); ++ + assert( (rc&0xff)==rc ); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); +@@ -127060,14 +134594,11 @@ + void *pArg = 0; + FuncDef *pNew; + int rc = 0; +- char *zLowerName; +- unsigned char *z; + +- + /* Check to see the left operand is a column in a virtual table */ + if( NEVER(pExpr==0) ) return pDef; + if( pExpr->op!=TK_COLUMN ) return pDef; +- pTab = pExpr->pTab; ++ pTab = pExpr->y.pTab; + if( pTab==0 ) return pDef; + if( !IsVirtual(pTab) ) return pDef; + pVtab = sqlite3GetVTable(db, pTab)->pVtab; +@@ -127077,16 +134608,22 @@ + if( pMod->xFindFunction==0 ) return pDef; + + /* Call the xFindFunction method on the virtual table implementation +- ** to see if the implementation wants to overload this function ++ ** to see if the implementation wants to overload this function. ++ ** ++ ** Though undocumented, we have historically always invoked xFindFunction ++ ** with an all lower-case function name. Continue in this tradition to ++ ** avoid any chance of an incompatibility. + */ +- zLowerName = sqlite3DbStrDup(db, pDef->zName); +- if( zLowerName ){ +- for(z=(unsigned char*)zLowerName; *z; z++){ +- *z = sqlite3UpperToLower[*z]; ++#ifdef SQLITE_DEBUG ++ { ++ int i; ++ for(i=0; pDef->zName[i]; i++){ ++ unsigned char x = (unsigned char)pDef->zName[i]; ++ assert( x==sqlite3UpperToLower[x] ); + } +- rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xSFunc, &pArg); +- sqlite3DbFree(db, zLowerName); + } ++#endif ++ rc = pMod->xFindFunction(pVtab, nArg, pDef->zName, &xSFunc, &pArg); + if( rc==0 ){ + return pDef; + } +@@ -127298,7 +134835,7 @@ + ** Trace output macros + */ + #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) +-/***/ int sqlite3WhereTrace; ++/***/ extern int sqlite3WhereTrace; + #endif + #if defined(SQLITE_DEBUG) \ + && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE)) +@@ -127361,6 +134898,8 @@ + struct InLoop { + int iCur; /* The VDBE cursor used by this IN operator */ + int addrInTop; /* Top of the IN loop */ ++ int iBase; /* Base register of multi-key index record */ ++ int nPrefix; /* Number of prior entires in the key */ + u8 eEndLoopOp; /* IN Loop terminator. OP_Next or OP_Prev */ + } *aInLoop; /* Information about each nested IN operator */ + } in; /* Used when pWLoop->wsFlags&WHERE_IN_ABLE */ +@@ -127599,6 +135138,7 @@ + WhereInfo *pWInfo; /* WHERE clause processing context */ + WhereClause *pOuter; /* Outer conjunction */ + u8 op; /* Split operator. TK_AND or TK_OR */ ++ u8 hasOr; /* True if any a[].eOperator is WO_OR */ + int nTerm; /* Number of terms */ + int nSlot; /* Number of entries in a[] */ + WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */ +@@ -127678,6 +135218,7 @@ + int nRecValid; /* Number of valid fields currently in pRec */ + #endif + unsigned int bldFlags; /* SQLITE_BLDF_* flags */ ++ unsigned int iPlanLimit; /* Search limiter */ + }; + + /* Allowed values for WhereLoopBuider.bldFlags */ +@@ -127684,6 +135225,26 @@ + #define SQLITE_BLDF_INDEXED 0x0001 /* An index is used */ + #define SQLITE_BLDF_UNIQUE 0x0002 /* All keys of a UNIQUE index used */ + ++/* The WhereLoopBuilder.iPlanLimit is used to limit the number of ++** index+constraint combinations the query planner will consider for a ++** particular query. If this parameter is unlimited, then certain ++** pathological queries can spend excess time in the sqlite3WhereBegin() ++** routine. The limit is high enough that is should not impact real-world ++** queries. ++** ++** SQLITE_QUERY_PLANNER_LIMIT is the baseline limit. The limit is ++** increased by SQLITE_QUERY_PLANNER_LIMIT_INCR before each term of the FROM ++** clause is processed, so that every table in a join is guaranteed to be ++** able to propose a some index+constraint combinations even if the initial ++** baseline limit was exhausted by prior tables of the join. ++*/ ++#ifndef SQLITE_QUERY_PLANNER_LIMIT ++# define SQLITE_QUERY_PLANNER_LIMIT 20000 ++#endif ++#ifndef SQLITE_QUERY_PLANNER_LIMIT_INCR ++# define SQLITE_QUERY_PLANNER_LIMIT_INCR 1000 ++#endif ++ + /* + ** The WHERE clause processing routine has two halves. The + ** first part does the start of the WHERE loop and the second +@@ -127746,12 +135307,10 @@ + Parse *pParse, /* Parse context */ + SrcList *pTabList, /* Table list this loop refers to */ + WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ +- int iLevel, /* Value for "level" column of output */ +- int iFrom, /* Value for "from" column of output */ + u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ + ); + #else +-# define sqlite3WhereExplainOneScan(u,v,w,x,y,z) 0 ++# define sqlite3WhereExplainOneScan(u,v,w,x) 0 + #endif /* SQLITE_OMIT_EXPLAIN */ + #ifdef SQLITE_ENABLE_STMT_SCANSTATUS + SQLITE_PRIVATE void sqlite3WhereAddScanStatus( +@@ -127774,6 +135333,7 @@ + SQLITE_PRIVATE void sqlite3WhereClauseClear(WhereClause*); + SQLITE_PRIVATE void sqlite3WhereSplit(WhereClause*,Expr*,u8); + SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet*, Expr*); ++SQLITE_PRIVATE Bitmask sqlite3WhereExprUsageNN(WhereMaskSet*, Expr*); + SQLITE_PRIVATE Bitmask sqlite3WhereExprListUsage(WhereMaskSet*, ExprList*); + SQLITE_PRIVATE void sqlite3WhereExprAnalyze(SrcList*, WhereClause*); + SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*); +@@ -127794,7 +135354,6 @@ + ** WO_LE == SQLITE_INDEX_CONSTRAINT_LE + ** WO_GT == SQLITE_INDEX_CONSTRAINT_GT + ** WO_GE == SQLITE_INDEX_CONSTRAINT_GE +-** WO_MATCH == SQLITE_INDEX_CONSTRAINT_MATCH + */ + #define WO_IN 0x0001 + #define WO_EQ 0x0002 +@@ -127802,7 +135361,7 @@ + #define WO_LE (WO_EQ<<(TK_LE-TK_EQ)) + #define WO_GT (WO_EQ<<(TK_GT-TK_EQ)) + #define WO_GE (WO_EQ<<(TK_GE-TK_EQ)) +-#define WO_MATCH 0x0040 ++#define WO_AUX 0x0040 /* Op useful to virtual tables only */ + #define WO_IS 0x0080 + #define WO_ISNULL 0x0100 + #define WO_OR 0x0200 /* Two or more OR-connected terms */ +@@ -127837,6 +135396,7 @@ + #define WHERE_SKIPSCAN 0x00008000 /* Uses the skip-scan algorithm */ + #define WHERE_UNQ_WANTED 0x00010000 /* WHERE_ONEROW would have been helpful*/ + #define WHERE_PARTIALIDX 0x00020000 /* The automatic index is partial */ ++#define WHERE_IN_EARLYOUT 0x00040000 /* Perhaps quit IN loops early */ + + /************** End of whereInt.h ********************************************/ + /************** Continuing where we left off in wherecode.c ******************/ +@@ -127872,23 +135432,23 @@ + int i; + + assert( nTerm>=1 ); +- if( bAnd ) sqlite3StrAccumAppend(pStr, " AND ", 5); ++ if( bAnd ) sqlite3_str_append(pStr, " AND ", 5); + +- if( nTerm>1 ) sqlite3StrAccumAppend(pStr, "(", 1); ++ if( nTerm>1 ) sqlite3_str_append(pStr, "(", 1); + for(i=0; i<nTerm; i++){ +- if( i ) sqlite3StrAccumAppend(pStr, ",", 1); +- sqlite3StrAccumAppendAll(pStr, explainIndexColumnName(pIdx, iTerm+i)); ++ if( i ) sqlite3_str_append(pStr, ",", 1); ++ sqlite3_str_appendall(pStr, explainIndexColumnName(pIdx, iTerm+i)); + } +- if( nTerm>1 ) sqlite3StrAccumAppend(pStr, ")", 1); ++ if( nTerm>1 ) sqlite3_str_append(pStr, ")", 1); + +- sqlite3StrAccumAppend(pStr, zOp, 1); ++ sqlite3_str_append(pStr, zOp, 1); + +- if( nTerm>1 ) sqlite3StrAccumAppend(pStr, "(", 1); ++ if( nTerm>1 ) sqlite3_str_append(pStr, "(", 1); + for(i=0; i<nTerm; i++){ +- if( i ) sqlite3StrAccumAppend(pStr, ",", 1); +- sqlite3StrAccumAppend(pStr, "?", 1); ++ if( i ) sqlite3_str_append(pStr, ",", 1); ++ sqlite3_str_append(pStr, "?", 1); + } +- if( nTerm>1 ) sqlite3StrAccumAppend(pStr, ")", 1); ++ if( nTerm>1 ) sqlite3_str_append(pStr, ")", 1); + } + + /* +@@ -127912,11 +135472,11 @@ + int i, j; + + if( nEq==0 && (pLoop->wsFlags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ) return; +- sqlite3StrAccumAppend(pStr, " (", 2); ++ sqlite3_str_append(pStr, " (", 2); + for(i=0; i<nEq; i++){ + const char *z = explainIndexColumnName(pIndex, i); +- if( i ) sqlite3StrAccumAppend(pStr, " AND ", 5); +- sqlite3XPrintf(pStr, i>=nSkip ? "%s=?" : "ANY(%s)", z); ++ if( i ) sqlite3_str_append(pStr, " AND ", 5); ++ sqlite3_str_appendf(pStr, i>=nSkip ? "%s=?" : "ANY(%s)", z); + } + + j = i; +@@ -127927,7 +135487,7 @@ + if( pLoop->wsFlags&WHERE_TOP_LIMIT ){ + explainAppendTerm(pStr, pIndex, pLoop->u.btree.nTop, j, i, "<"); + } +- sqlite3StrAccumAppend(pStr, ")", 1); ++ sqlite3_str_append(pStr, ")", 1); + } + + /* +@@ -127943,19 +135503,16 @@ + Parse *pParse, /* Parse context */ + SrcList *pTabList, /* Table list this loop refers to */ + WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ +- int iLevel, /* Value for "level" column of output */ +- int iFrom, /* Value for "from" column of output */ + u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ + ){ + int ret = 0; + #if !defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_STMT_SCANSTATUS) +- if( pParse->explain==2 ) ++ if( sqlite3ParseToplevel(pParse)->explain==2 ) + #endif + { + struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom]; + Vdbe *v = pParse->pVdbe; /* VM being constructed */ + sqlite3 *db = pParse->db; /* Database handle */ +- int iId = pParse->iSelectId; /* Select id (left-most output column) */ + int isSearch; /* True for a SEARCH. False for SCAN. */ + WhereLoop *pLoop; /* The controlling WhereLoop object */ + u32 flags; /* Flags that describe this loop */ +@@ -127972,15 +135529,15 @@ + || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX)); + + sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); +- sqlite3StrAccumAppendAll(&str, isSearch ? "SEARCH" : "SCAN"); ++ sqlite3_str_appendall(&str, isSearch ? "SEARCH" : "SCAN"); + if( pItem->pSelect ){ +- sqlite3XPrintf(&str, " SUBQUERY %d", pItem->iSelectId); ++ sqlite3_str_appendf(&str, " SUBQUERY %u", pItem->pSelect->selId); + }else{ +- sqlite3XPrintf(&str, " TABLE %s", pItem->zName); ++ sqlite3_str_appendf(&str, " TABLE %s", pItem->zName); + } + + if( pItem->zAlias ){ +- sqlite3XPrintf(&str, " AS %s", pItem->zAlias); ++ sqlite3_str_appendf(&str, " AS %s", pItem->zAlias); + } + if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){ + const char *zFmt = 0; +@@ -128003,8 +135560,8 @@ + zFmt = "INDEX %s"; + } + if( zFmt ){ +- sqlite3StrAccumAppend(&str, " USING ", 7); +- sqlite3XPrintf(&str, zFmt, pIdx->zName); ++ sqlite3_str_append(&str, " USING ", 7); ++ sqlite3_str_appendf(&str, zFmt, pIdx->zName); + explainIndexRange(&str, pLoop); + } + }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){ +@@ -128019,23 +135576,26 @@ + assert( flags&WHERE_TOP_LIMIT); + zRangeOp = "<"; + } +- sqlite3XPrintf(&str, " USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp); ++ sqlite3_str_appendf(&str, ++ " USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp); + } + #ifndef SQLITE_OMIT_VIRTUALTABLE + else if( (flags & WHERE_VIRTUALTABLE)!=0 ){ +- sqlite3XPrintf(&str, " VIRTUAL TABLE INDEX %d:%s", ++ sqlite3_str_appendf(&str, " VIRTUAL TABLE INDEX %d:%s", + pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr); + } + #endif + #ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS + if( pLoop->nOut>=10 ){ +- sqlite3XPrintf(&str, " (~%llu rows)", sqlite3LogEstToInt(pLoop->nOut)); ++ sqlite3_str_appendf(&str, " (~%llu rows)", ++ sqlite3LogEstToInt(pLoop->nOut)); + }else{ +- sqlite3StrAccumAppend(&str, " (~1 row)", 9); ++ sqlite3_str_append(&str, " (~1 row)", 9); + } + #endif + zMsg = sqlite3StrAccumFinish(&str); +- ret = sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg,P4_DYNAMIC); ++ ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v), ++ pParse->addrExplain, 0, zMsg,P4_DYNAMIC); + } + return ret; + } +@@ -128115,8 +135675,8 @@ + */ + static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){ + int nLoop = 0; +- while( ALWAYS(pTerm!=0) +- && (pTerm->wtFlags & TERM_CODED)==0 ++ assert( pTerm!=0 ); ++ while( (pTerm->wtFlags & TERM_CODED)==0 + && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin)) + && (pLevel->notReady & pTerm->prereqAll)==0 + ){ +@@ -128127,6 +135687,7 @@ + } + if( pTerm->iParent<0 ) break; + pTerm = &pTerm->pWC->a[pTerm->iParent]; ++ assert( pTerm!=0 ); + pTerm->nChild--; + if( pTerm->nChild!=0 ) break; + nLoop++; +@@ -128167,7 +135728,6 @@ + /* Code the OP_Affinity opcode if there is anything left to do. */ + if( n>0 ){ + sqlite3VdbeAddOp4(v, OP_Affinity, base, n, 0, zAff, n); +- sqlite3ExprCacheAffinityChange(pParse, base, n); + } + } + +@@ -128197,7 +135757,103 @@ + } + } + ++ + /* ++** pX is an expression of the form: (vector) IN (SELECT ...) ++** In other words, it is a vector IN operator with a SELECT clause on the ++** LHS. But not all terms in the vector are indexable and the terms might ++** not be in the correct order for indexing. ++** ++** This routine makes a copy of the input pX expression and then adjusts ++** the vector on the LHS with corresponding changes to the SELECT so that ++** the vector contains only index terms and those terms are in the correct ++** order. The modified IN expression is returned. The caller is responsible ++** for deleting the returned expression. ++** ++** Example: ++** ++** CREATE TABLE t1(a,b,c,d,e,f); ++** CREATE INDEX t1x1 ON t1(e,c); ++** SELECT * FROM t1 WHERE (a,b,c,d,e) IN (SELECT v,w,x,y,z FROM t2) ++** \_______________________________________/ ++** The pX expression ++** ++** Since only columns e and c can be used with the index, in that order, ++** the modified IN expression that is returned will be: ++** ++** (e,c) IN (SELECT z,x FROM t2) ++** ++** The reduced pX is different from the original (obviously) and thus is ++** only used for indexing, to improve performance. The original unaltered ++** IN expression must also be run on each output row for correctness. ++*/ ++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 = sqlite3ExprDup(db, pX, 0); ++ if( db->mallocFailed==0 ){ ++ ExprList *pOrigRhs = pNew->x.pSelect->pEList; /* Original unmodified RHS */ ++ ExprList *pOrigLhs = pNew->pLeft->x.pList; /* 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 */ ++ ++ for(i=iEq; i<pLoop->nLTerm; i++){ ++ if( pLoop->aLTerm[i]->pExpr==pX ){ ++ int iField = pLoop->aLTerm[i]->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 + ** term can be either X=expr or X IN (...). pTerm is the term to be + ** coded. +@@ -128259,68 +135915,23 @@ + } + } + for(i=iEq;i<pLoop->nLTerm; i++){ +- if( ALWAYS(pLoop->aLTerm[i]) && pLoop->aLTerm[i]->pExpr==pX ) nEq++; ++ assert( pLoop->aLTerm[i]!=0 ); ++ if( pLoop->aLTerm[i]->pExpr==pX ) nEq++; + } + + if( (pX->flags & EP_xIsSelect)==0 || pX->x.pSelect->pEList->nExpr==1 ){ + eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0); + }else{ +- Select *pSelect = pX->x.pSelect; + sqlite3 *db = pParse->db; +- u16 savedDbOptFlags = db->dbOptFlags; +- ExprList *pOrigRhs = pSelect->pEList; +- ExprList *pOrigLhs = pX->pLeft->x.pList; +- ExprList *pRhs = 0; /* New Select.pEList for RHS */ +- ExprList *pLhs = 0; /* New pX->pLeft vector */ ++ pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX); + +- for(i=iEq;i<pLoop->nLTerm; i++){ +- if( pLoop->aLTerm[i]->pExpr==pX ){ +- int iField = pLoop->aLTerm[i]->iField - 1; +- Expr *pNewRhs = sqlite3ExprDup(db, pOrigRhs->a[iField].pExpr, 0); +- Expr *pNewLhs = sqlite3ExprDup(db, pOrigLhs->a[iField].pExpr, 0); +- +- pRhs = sqlite3ExprListAppend(pParse, pRhs, pNewRhs); +- pLhs = sqlite3ExprListAppend(pParse, pLhs, pNewLhs); +- } +- } + if( !db->mallocFailed ){ +- Expr *pLeft = pX->pLeft; +- +- 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; +- } +- } +- +- /* 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. */ +- if( pLhs->nExpr==1 ){ +- pX->pLeft = pLhs->a[0].pExpr; +- }else{ +- pLeft->x.pList = pLhs; +- aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int) * nEq); +- testcase( aiMap==0 ); +- } +- pSelect->pEList = pRhs; +- db->dbOptFlags |= SQLITE_QueryFlattener; ++ aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq); + eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap); +- db->dbOptFlags = savedDbOptFlags; +- testcase( aiMap!=0 && aiMap[0]!=0 ); +- pSelect->pEList = pOrigRhs; +- pLeft->x.pList = pOrigLhs; +- pX->pLeft = pLeft; ++ pTerm->pExpr->iTable = pX->iTable; + } +- sqlite3ExprListDelete(pParse->db, pLhs); +- sqlite3ExprListDelete(pParse->db, pRhs); ++ sqlite3ExprDelete(db, pX); ++ pX = pTerm->pExpr; + } + + if( eType==IN_INDEX_INDEX_DESC ){ +@@ -128360,7 +135971,14 @@ + sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v); + if( i==iEq ){ + pIn->iCur = iTab; +- pIn->eEndLoopOp = bRev ? OP_PrevIfOpen : OP_NextIfOpen; ++ pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next; ++ if( iEq>0 && (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ){ ++ pIn->iBase = iReg - i; ++ pIn->nPrefix = i; ++ pLoop->wsFlags |= WHERE_IN_EARLYOUT; ++ }else{ ++ pIn->nPrefix = 0; ++ } + }else{ + pIn->eEndLoopOp = OP_Noop; + } +@@ -128615,7 +136233,7 @@ + pWalker->eCode = 1; + }else if( pExpr->op==TK_FUNCTION ){ + int d1; +- char d2[3]; ++ char d2[4]; + if( 0==sqlite3IsLikeFunction(pWalker->pParse->db, pExpr, &d1, d2) ){ + pWalker->eCode = 1; + } +@@ -128647,11 +136265,8 @@ + struct CCurHint *pHint = pWalker->u.pCCurHint; + if( pExpr->op==TK_COLUMN ){ + if( pExpr->iTable!=pHint->iTabCur ){ +- Vdbe *v = pWalker->pParse->pVdbe; + int reg = ++pWalker->pParse->nMem; /* Register for column value */ +- sqlite3ExprCodeGetColumnOfTable( +- v, pExpr->pTab, pExpr->iTable, pExpr->iColumn, reg +- ); ++ sqlite3ExprCode(pWalker->pParse, pExpr, reg); + pExpr->op = TK_REGISTER; + pExpr->iTable = reg; + }else if( pHint->pIdx!=0 ){ +@@ -128838,7 +136453,7 @@ + */ + static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){ + assert( nReg>0 ); +- if( sqlite3ExprIsVector(p) ){ ++ if( p && sqlite3ExprIsVector(p) ){ + #ifndef SQLITE_OMIT_SUBQUERY + if( (p->flags & EP_xIsSelect) ){ + Vdbe *v = pParse->pVdbe; +@@ -128883,7 +136498,7 @@ + pExpr->op = TK_COLUMN; + pExpr->iTable = pX->iIdxCur; + pExpr->iColumn = pX->iIdxCol; +- pExpr->pTab = 0; ++ pExpr->y.pTab = 0; + return WRC_Prune; + }else{ + return WRC_Continue; +@@ -128891,9 +136506,9 @@ + } + + /* +-** For an indexes on expression X, locate every instance of expression X in pExpr +-** and change that subexpression into a reference to the appropriate column of +-** the index. ++** For an indexes on expression X, locate every instance of expression X ++** in pExpr and change that subexpression into a reference to the appropriate ++** column of the index. + */ + static void whereIndexExprTrans( + Index *pIdx, /* The Index */ +@@ -128984,6 +136599,9 @@ + ** initialize a memory cell that records if this table matches any + ** row of the left table of the join. + */ ++ assert( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE) ++ || pLevel->iFrom>0 || (pTabItem[0].fg.jointype & JT_LEFT)==0 ++ ); + if( pLevel->iFrom>0 && (pTabItem[0].fg.jointype & JT_LEFT)!=0 ){ + pLevel->iLeftJoin = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin); +@@ -129001,7 +136619,7 @@ + sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub); + pLevel->p2 = sqlite3VdbeAddOp2(v, OP_Yield, regYield, addrBrk); + VdbeCoverage(v); +- VdbeComment((v, "next row of \"%s\"", pTabItem->pTab->zName)); ++ VdbeComment((v, "next row of %s", pTabItem->pTab->zName)); + pLevel->op = OP_Goto; + }else + +@@ -129015,7 +136633,6 @@ + int nConstraint = pLoop->nLTerm; + int iIn; /* Counter for IN constraints */ + +- sqlite3ExprCachePush(pParse); + iReg = sqlite3GetTempRange(pParse, nConstraint+2); + addrNotFound = pLevel->addrBrk; + for(j=0; j<nConstraint; j++){ +@@ -129088,7 +136705,6 @@ + ** + ** sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2); + */ +- sqlite3ExprCachePop(pParse); + }else + #endif /* SQLITE_OMIT_VIRTUALTABLE */ + +@@ -129112,9 +136728,6 @@ + addrNxt = pLevel->addrNxt; + sqlite3VdbeAddOp3(v, OP_SeekRowid, iCur, addrNxt, iRowidReg); + VdbeCoverage(v); +- sqlite3ExprCacheAffinityChange(pParse, iRowidReg, 1); +- sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); +- VdbeComment((v, "pk")); + pLevel->op = OP_Noop; + }else if( (pLoop->wsFlags & WHERE_IPK)!=0 + && (pLoop->wsFlags & WHERE_COLUMN_RANGE)!=0 +@@ -129164,7 +136777,15 @@ + if( sqlite3ExprIsVector(pX->pRight) ){ + r1 = rTemp = sqlite3GetTempReg(pParse); + codeExprOrVector(pParse, pX->pRight, r1, 1); +- op = aMoveOp[(pX->op - TK_GT) | 0x0001]; ++ testcase( pX->op==TK_GT ); ++ testcase( pX->op==TK_GE ); ++ testcase( pX->op==TK_LT ); ++ testcase( pX->op==TK_LE ); ++ op = aMoveOp[((pX->op - TK_GT - 1) & 0x3) | 0x1]; ++ assert( pX->op!=TK_GT || op==OP_SeekGE ); ++ assert( pX->op!=TK_GE || op==OP_SeekGE ); ++ assert( pX->op!=TK_LT || op==OP_SeekLE ); ++ assert( pX->op!=TK_LE || op==OP_SeekLE ); + }else{ + r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp); + disableTerm(pLevel, pStart); +@@ -129176,7 +136797,6 @@ + VdbeCoverageIf(v, pX->op==TK_LE); + VdbeCoverageIf(v, pX->op==TK_LT); + VdbeCoverageIf(v, pX->op==TK_GE); +- sqlite3ExprCacheAffinityChange(pParse, r1, 1); + sqlite3ReleaseTempReg(pParse, rTemp); + }else{ + sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrHalt); +@@ -129211,7 +136831,6 @@ + if( testOp!=OP_Noop ){ + iRowidReg = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg); +- sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); + sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg); + VdbeCoverageIf(v, testOp==OP_Le); + VdbeCoverageIf(v, testOp==OP_Lt); +@@ -129416,6 +137035,9 @@ + ** above has already left the cursor sitting on the correct row, + ** so no further seeking is needed */ + }else{ ++ if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){ ++ sqlite3VdbeAddOp1(v, OP_SeekHit, iIdxCur); ++ } + op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; + assert( op!=0 ); + sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); +@@ -129434,7 +137056,6 @@ + nConstraint = nEq; + if( pRangeEnd ){ + Expr *pRight = pRangeEnd->pExpr->pRight; +- sqlite3ExprCacheRemove(pParse, regBase+nEq, 1); + codeExprOrVector(pParse, pRight, regBase+nEq, nTop); + whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd); + if( (pRangeEnd->wtFlags & TERM_VNULL)==0 +@@ -129478,6 +137099,10 @@ + testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE ); + } + ++ if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){ ++ sqlite3VdbeAddOp2(v, OP_SeekHit, iIdxCur, 1); ++ } ++ + /* Seek the table cursor, if required */ + if( omitTable ){ + /* pIdx is a covering index. No need to access the main table. */ +@@ -129488,7 +137113,6 @@ + )){ + iRowidReg = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg); +- sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); + sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg); + VdbeCoverage(v); + }else{ +@@ -129508,10 +137132,17 @@ + /* If pIdx is an index on one or more expressions, then look through + ** all the expressions in pWInfo and try to transform matching expressions + ** into reference to index columns. ++ ** ++ ** Do not do this for the RHS of a LEFT JOIN. This is because the ++ ** expression may be evaluated after OP_NullRow has been executed on ++ ** the cursor. In this case it is important to do the full evaluation, ++ ** as the result of the expression may not be NULL, even if all table ++ ** column values are. https://www.sqlite.org/src/info/7fa8049685b50b5a + */ +- whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo); ++ if( pLevel->iLeftJoin==0 ){ ++ whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo); ++ } + +- + /* Record the instruction used to terminate the loop. */ + if( pLoop->wsFlags & WHERE_ONEROW ){ + pLevel->op = OP_Noop; +@@ -129666,7 +137297,6 @@ + for(iTerm=0; iTerm<pWC->nTerm; iTerm++){ + Expr *pExpr = pWC->a[iTerm].pExpr; + if( &pWC->a[iTerm] == pTerm ) continue; +- if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; + testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL ); + testcase( pWC->a[iTerm].wtFlags & TERM_CODED ); + if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED))!=0 ) continue; +@@ -129685,6 +137315,7 @@ + ** sub-WHERE clause is to to invoke the main loop body as a subroutine. + */ + wctrlFlags = WHERE_OR_SUBCLAUSE | (pWInfo->wctrlFlags & WHERE_SEEK_TABLE); ++ ExplainQueryPlan((pParse, 1, "MULTI-INDEX OR")); + for(ii=0; ii<pOrWc->nTerm; ii++){ + WhereTerm *pOrTerm = &pOrWc->a[ii]; + if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){ +@@ -129691,7 +137322,10 @@ + WhereInfo *pSubWInfo; /* Info for single OR-term scan */ + Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */ + int jmp1 = 0; /* Address of jump operation */ +- if( pAndExpr && !ExprHasProperty(pOrExpr, EP_FromJoin) ){ ++ assert( (pTabItem[0].fg.jointype & JT_LEFT)==0 ++ || ExprHasProperty(pOrExpr, EP_FromJoin) ++ ); ++ if( pAndExpr ){ + pAndExpr->pLeft = pOrExpr; + pOrExpr = pAndExpr; + } +@@ -129703,7 +137337,7 @@ + if( pSubWInfo ){ + WhereLoop *pSubLoop; + int addrExplain = sqlite3WhereExplainOneScan( +- pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0 ++ pParse, pOrTab, &pSubWInfo->a[0], 0 + ); + sqlite3WhereAddScanStatus(v, pOrTab, &pSubWInfo->a[0], addrExplain); + +@@ -129713,23 +137347,23 @@ + ** row will be skipped in subsequent sub-WHERE clauses. + */ + if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ +- int r; + int iSet = ((ii==pOrWc->nTerm-1)?-1:ii); + if( HasRowid(pTab) ){ +- r = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, regRowid, 0); ++ sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, -1, regRowid); + jmp1 = sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, 0, +- r,iSet); ++ regRowid, iSet); + VdbeCoverage(v); + }else{ + Index *pPk = sqlite3PrimaryKeyIndex(pTab); + int nPk = pPk->nKeyCol; + int iPk; ++ int r; + + /* Read the PK into an array of temp registers. */ + r = sqlite3GetTempRange(pParse, nPk); + for(iPk=0; iPk<nPk; iPk++){ + int iCol = pPk->aiColumn[iPk]; +- sqlite3ExprCodeGetColumnToReg(pParse, pTab, iCol, iCur, r+iPk); ++ sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol, r+iPk); + } + + /* Check if the temp table already contains this key. If so, +@@ -129802,6 +137436,7 @@ + } + } + } ++ ExplainQueryPlanPop(pParse); + pLevel->u.pCovidx = pCov; + if( pCov ) pLevel->iIdxCur = iCovCur; + if( pAndExpr ){ +@@ -129874,7 +137509,7 @@ + } + pE = pTerm->pExpr; + assert( pE!=0 ); +- if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){ ++ if( (pTabItem->fg.jointype&JT_LEFT) && !ExprHasProperty(pE,EP_FromJoin) ){ + continue; + } + +@@ -129887,7 +137522,7 @@ + continue; + } + +- if( pTerm->wtFlags & TERM_LIKECOND ){ ++ if( (pTerm->wtFlags & TERM_LIKECOND)!=0 ){ + /* If the TERM_LIKECOND flag is set, that means that the range search + ** is sufficient to guarantee that the LIKE operator is true, so we + ** can skip the call to the like(A,B) function. But this only works +@@ -129897,8 +137532,9 @@ + continue; + #else + u32 x = pLevel->iLikeRepCntr; +- assert( x>0 ); +- skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)?OP_IfNot:OP_If, (int)(x>>1)); ++ if( x>0 ){ ++ skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)?OP_IfNot:OP_If,(int)(x>>1)); ++ } + VdbeCoverage(v); + #endif + } +@@ -129938,6 +137574,12 @@ + WO_EQ|WO_IN|WO_IS, 0); + if( pAlt==0 ) continue; + if( pAlt->wtFlags & (TERM_CODED) ) continue; ++ if( (pAlt->eOperator & WO_IN) ++ && (pAlt->pExpr->flags & EP_xIsSelect) ++ && (pAlt->pExpr->x.pSelect->pEList->nExpr>1) ++ ){ ++ continue; ++ } + testcase( pAlt->eOperator & WO_EQ ); + testcase( pAlt->eOperator & WO_IS ); + testcase( pAlt->eOperator & WO_IN ); +@@ -129954,7 +137596,6 @@ + pLevel->addrFirst = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin); + VdbeComment((v, "record LEFT JOIN hit")); +- sqlite3ExprCacheClear(pParse); + for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){ + testcase( pTerm->wtFlags & TERM_VIRTUAL ); + testcase( pTerm->wtFlags & TERM_CODED ); +@@ -130170,18 +137811,18 @@ + int *pisComplete, /* True if the only wildcard is % in the last character */ + int *pnoCase /* True if uppercase is equivalent to lowercase */ + ){ +- const char *z = 0; /* String on RHS of LIKE operator */ ++ const u8 *z = 0; /* String on RHS of LIKE operator */ + Expr *pRight, *pLeft; /* Right and left size of LIKE operator */ + ExprList *pList; /* List of operands to the LIKE operator */ +- int c; /* One character in z[] */ ++ u8 c; /* One character in z[] */ + int cnt; /* Number of non-wildcard prefix characters */ +- char wc[3]; /* Wildcard characters */ ++ u8 wc[4]; /* Wildcard characters */ + sqlite3 *db = pParse->db; /* Database connection */ + sqlite3_value *pVal = 0; + int op; /* Opcode of pRight */ + int rc; /* Result code to return */ + +- if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, wc) ){ ++ if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, (char*)wc) ){ + return 0; + } + #ifdef SQLITE_EBCDIC +@@ -130197,41 +137838,78 @@ + int iCol = pRight->iColumn; + pVal = sqlite3VdbeGetBoundValue(pReprepare, iCol, SQLITE_AFF_BLOB); + if( pVal && sqlite3_value_type(pVal)==SQLITE_TEXT ){ +- z = (char *)sqlite3_value_text(pVal); ++ z = sqlite3_value_text(pVal); + } + sqlite3VdbeSetVarmask(pParse->pVdbe, iCol); + assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER ); + }else if( op==TK_STRING ){ +- z = pRight->u.zToken; ++ z = (u8*)pRight->u.zToken; + } + if( z ){ + +- /* If the RHS begins with a digit or a minus sign, then the LHS must +- ** be an ordinary column (not a virtual table column) with TEXT affinity. +- ** Otherwise the LHS might be numeric and "lhs >= rhs" would be false +- ** even though "lhs LIKE rhs" is true. But if the RHS does not start +- ** with a digit or '-', then "lhs LIKE rhs" will always be false if +- ** the LHS is numeric and so the optimization still works. +- */ +- if( sqlite3Isdigit(z[0]) || z[0]=='-' ){ +- if( pLeft->op!=TK_COLUMN +- || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT +- || IsVirtual(pLeft->pTab) /* Value might be numeric */ +- ){ +- sqlite3ValueFree(pVal); +- return 0; +- } +- } ++ /* Count the number of prefix characters prior to the first wildcard */ + cnt = 0; + while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ + cnt++; ++ if( c==wc[3] && z[cnt]!=0 ) cnt++; + } +- if( cnt!=0 && 255!=(u8)z[cnt-1] ){ ++ ++ /* The optimization is possible only if (1) the pattern does not begin ++ ** with a wildcard and if (2) the non-wildcard prefix does not end with ++ ** an (illegal 0xff) character, or (3) the pattern does not consist of ++ ** a single escape character. The second condition is necessary so ++ ** that we can increment the prefix key to find an upper bound for the ++ ** range search. The third is because the caller assumes that the pattern ++ ** consists of at least one character after all escapes have been ++ ** removed. */ ++ if( cnt!=0 && 255!=(u8)z[cnt-1] && (cnt>1 || z[0]!=wc[3]) ){ + Expr *pPrefix; ++ ++ /* A "complete" match if the pattern ends with "*" or "%" */ + *pisComplete = c==wc[0] && z[cnt+1]==0; +- pPrefix = sqlite3Expr(db, TK_STRING, z); +- if( pPrefix ) pPrefix->u.zToken[cnt] = 0; ++ ++ /* Get the pattern prefix. Remove all escapes from the prefix. */ ++ pPrefix = sqlite3Expr(db, TK_STRING, (char*)z); ++ if( pPrefix ){ ++ int iFrom, iTo; ++ char *zNew = pPrefix->u.zToken; ++ zNew[cnt] = 0; ++ for(iFrom=iTo=0; iFrom<cnt; iFrom++){ ++ if( zNew[iFrom]==wc[3] ) iFrom++; ++ zNew[iTo++] = zNew[iFrom]; ++ } ++ zNew[iTo] = 0; ++ ++ /* If the RHS begins with a digit or a minus sign, then the LHS must be ++ ** an ordinary column (not a virtual table column) with TEXT affinity. ++ ** Otherwise the LHS might be numeric and "lhs >= rhs" would be false ++ ** even though "lhs LIKE rhs" is true. But if the RHS does not start ++ ** with a digit or '-', then "lhs LIKE rhs" will always be false if ++ ** the LHS is numeric and so the optimization still works. ++ ** ++ ** 2018-09-10 ticket c94369cae9b561b1f996d0054bfab11389f9d033 ++ ** The RHS pattern must not be '/%' because the termination condition ++ ** will then become "x<'0'" and if the affinity is numeric, will then ++ ** be converted into "x<0", which is incorrect. ++ */ ++ if( sqlite3Isdigit(zNew[0]) ++ || zNew[0]=='-' ++ || (zNew[0]+1=='0' && iTo==1) ++ ){ ++ if( pLeft->op!=TK_COLUMN ++ || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT ++ || IsVirtual(pLeft->y.pTab) /* Value might be numeric */ ++ ){ ++ sqlite3ExprDelete(db, pPrefix); ++ sqlite3ValueFree(pVal); ++ return 0; ++ } ++ } ++ } + *ppPrefix = pPrefix; ++ ++ /* If the RHS pattern is a bound parameter, make arrangements to ++ ** reprepare the statement when that parameter is rebound */ + if( op==TK_VARIABLE ){ + Vdbe *v = pParse->pVdbe; + sqlite3VdbeSetVarmask(v, pRight->iColumn); +@@ -130262,48 +137940,123 @@ + + #ifndef SQLITE_OMIT_VIRTUALTABLE + /* +-** Check to see if the given expression is of the form ++** Check to see if the pExpr expression is a form that needs to be passed ++** to the xBestIndex method of virtual tables. Forms of interest include: + ** +-** column OP expr ++** Expression Virtual Table Operator ++** ----------------------- --------------------------------- ++** 1. column MATCH expr SQLITE_INDEX_CONSTRAINT_MATCH ++** 2. column GLOB expr SQLITE_INDEX_CONSTRAINT_GLOB ++** 3. column LIKE expr SQLITE_INDEX_CONSTRAINT_LIKE ++** 4. column REGEXP expr SQLITE_INDEX_CONSTRAINT_REGEXP ++** 5. column != expr SQLITE_INDEX_CONSTRAINT_NE ++** 6. expr != column SQLITE_INDEX_CONSTRAINT_NE ++** 7. column IS NOT expr SQLITE_INDEX_CONSTRAINT_ISNOT ++** 8. expr IS NOT column SQLITE_INDEX_CONSTRAINT_ISNOT ++** 9. column IS NOT NULL SQLITE_INDEX_CONSTRAINT_ISNOTNULL + ** +-** where OP is one of MATCH, GLOB, LIKE or REGEXP and "column" is a +-** column of a virtual table. ++** In every case, "column" must be a column of a virtual table. If there ++** is a match, set *ppLeft to the "column" expression, set *ppRight to the ++** "expr" expression (even though in forms (6) and (8) the column is on the ++** right and the expression is on the left). Also set *peOp2 to the ++** appropriate virtual table operator. The return value is 1 or 2 if there ++** is a match. The usual return is 1, but if the RHS is also a column ++** of virtual table in forms (5) or (7) then return 2. + ** +-** If it is then return TRUE. If not, return FALSE. ++** If the expression matches none of the patterns above, return 0. + */ +-static int isMatchOfColumn( ++static int isAuxiliaryVtabOperator( ++ sqlite3 *db, /* Parsing context */ + Expr *pExpr, /* Test this expression */ +- unsigned char *peOp2 /* OUT: 0 for MATCH, or else an op2 value */ ++ unsigned char *peOp2, /* OUT: 0 for MATCH, or else an op2 value */ ++ Expr **ppLeft, /* Column expression to left of MATCH/op2 */ ++ Expr **ppRight /* Expression to left of MATCH/op2 */ + ){ +- static const struct Op2 { +- const char *zOp; +- unsigned char eOp2; +- } aOp[] = { +- { "match", SQLITE_INDEX_CONSTRAINT_MATCH }, +- { "glob", SQLITE_INDEX_CONSTRAINT_GLOB }, +- { "like", SQLITE_INDEX_CONSTRAINT_LIKE }, +- { "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP } +- }; +- ExprList *pList; +- Expr *pCol; /* Column reference */ +- int i; ++ if( pExpr->op==TK_FUNCTION ){ ++ static const struct Op2 { ++ const char *zOp; ++ unsigned char eOp2; ++ } aOp[] = { ++ { "match", SQLITE_INDEX_CONSTRAINT_MATCH }, ++ { "glob", SQLITE_INDEX_CONSTRAINT_GLOB }, ++ { "like", SQLITE_INDEX_CONSTRAINT_LIKE }, ++ { "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP } ++ }; ++ ExprList *pList; ++ Expr *pCol; /* Column reference */ ++ int i; + +- if( pExpr->op!=TK_FUNCTION ){ +- return 0; +- } +- pList = pExpr->x.pList; +- if( pList==0 || pList->nExpr!=2 ){ +- return 0; +- } +- pCol = pList->a[1].pExpr; +- if( pCol->op!=TK_COLUMN || !IsVirtual(pCol->pTab) ){ +- return 0; +- } +- for(i=0; i<ArraySize(aOp); i++){ +- if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){ +- *peOp2 = aOp[i].eOp2; +- return 1; ++ pList = pExpr->x.pList; ++ if( pList==0 || pList->nExpr!=2 ){ ++ return 0; + } ++ ++ /* Built-in operators MATCH, GLOB, LIKE, and REGEXP attach to a ++ ** virtual table on their second argument, which is the same as ++ ** the left-hand side operand in their in-fix form. ++ ** ++ ** vtab_column MATCH expression ++ ** MATCH(expression,vtab_column) ++ */ ++ pCol = pList->a[1].pExpr; ++ if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){ ++ for(i=0; i<ArraySize(aOp); i++){ ++ if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){ ++ *peOp2 = aOp[i].eOp2; ++ *ppRight = pList->a[0].pExpr; ++ *ppLeft = pCol; ++ return 1; ++ } ++ } ++ } ++ ++ /* We can also match against the first column of overloaded ++ ** functions where xFindFunction returns a value of at least ++ ** SQLITE_INDEX_CONSTRAINT_FUNCTION. ++ ** ++ ** OVERLOADED(vtab_column,expression) ++ ** ++ ** Historically, xFindFunction expected to see lower-case function ++ ** names. But for this use case, xFindFunction is expected to deal ++ ** with function names in an arbitrary case. ++ */ ++ pCol = pList->a[0].pExpr; ++ if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){ ++ sqlite3_vtab *pVtab; ++ sqlite3_module *pMod; ++ void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**); ++ void *pNotUsed; ++ pVtab = sqlite3GetVTable(db, pCol->y.pTab)->pVtab; ++ assert( pVtab!=0 ); ++ assert( pVtab->pModule!=0 ); ++ pMod = (sqlite3_module *)pVtab->pModule; ++ if( pMod->xFindFunction!=0 ){ ++ i = pMod->xFindFunction(pVtab,2, pExpr->u.zToken, &xNotUsed, &pNotUsed); ++ if( i>=SQLITE_INDEX_CONSTRAINT_FUNCTION ){ ++ *peOp2 = i; ++ *ppRight = pList->a[1].pExpr; ++ *ppLeft = pCol; ++ return 1; ++ } ++ } ++ } ++ }else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){ ++ int res = 0; ++ Expr *pLeft = pExpr->pLeft; ++ Expr *pRight = pExpr->pRight; ++ if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->y.pTab) ){ ++ res++; ++ } ++ if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->y.pTab) ){ ++ res++; ++ SWAP(Expr*, pLeft, pRight); ++ } ++ *ppLeft = pLeft; ++ *ppRight = pRight; ++ if( pExpr->op==TK_NE ) *peOp2 = SQLITE_INDEX_CONSTRAINT_NE; ++ if( pExpr->op==TK_ISNOT ) *peOp2 = SQLITE_INDEX_CONSTRAINT_ISNOT; ++ if( pExpr->op==TK_NOTNULL ) *peOp2 = SQLITE_INDEX_CONSTRAINT_ISNOTNULL; ++ return res; + } + return 0; + } +@@ -130554,7 +138307,7 @@ + for(j=0, pAndTerm=pAndWC->a; j<pAndWC->nTerm; j++, pAndTerm++){ + assert( pAndTerm->pExpr ); + if( allowedOp(pAndTerm->pExpr->op) +- || pAndTerm->eOperator==WO_MATCH ++ || pAndTerm->eOperator==WO_AUX + ){ + b |= sqlite3WhereGetMask(&pWInfo->sMaskSet, pAndTerm->leftCursor); + } +@@ -130586,7 +138339,12 @@ + ** empty. + */ + pOrInfo->indexable = indexable; +- pTerm->eOperator = indexable==0 ? 0 : WO_OR; ++ if( indexable ){ ++ pTerm->eOperator = WO_OR; ++ pWC->hasOr = 1; ++ }else{ ++ pTerm->eOperator = WO_OR; ++ } + + /* For a two-way OR, attempt to implementation case 2. + */ +@@ -130727,12 +138485,11 @@ + idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC); + testcase( idxNew==0 ); + exprAnalyze(pSrc, pWC, idxNew); +- pTerm = &pWC->a[idxTerm]; ++ /* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm where used again */ + markTermAsChild(pWC, idxNew, idxTerm); + }else{ + sqlite3ExprListDelete(db, pList); + } +- pTerm->eOperator = WO_NOOP; /* case 1 trumps case 3 */ + } + } + } +@@ -130756,7 +138513,6 @@ + static int termIsEquivalence(Parse *pParse, Expr *pExpr){ + char aff1, aff2; + CollSeq *pColl; +- const char *zColl1, *zColl2; + if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0; + if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0; + if( ExprHasProperty(pExpr, EP_FromJoin) ) return 0; +@@ -130768,12 +138524,8 @@ + return 0; + } + pColl = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight); +- if( pColl==0 || sqlite3StrICmp(pColl->zName, "BINARY")==0 ) return 1; +- pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft); +- zColl1 = pColl ? pColl->zName : 0; +- pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight); +- zColl2 = pColl ? pColl->zName : 0; +- return sqlite3_stricmp(zColl1, zColl2)==0; ++ if( sqlite3IsBinary(pColl) ) return 1; ++ return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight); + } + + /* +@@ -130795,6 +138547,9 @@ + for(i=0; i<pSrc->nSrc; i++){ + mask |= exprSelectUsage(pMaskSet, pSrc->a[i].pSelect); + mask |= sqlite3WhereExprUsage(pMaskSet, pSrc->a[i].pOn); ++ if( pSrc->a[i].fg.isTabFunc ){ ++ mask |= sqlite3WhereExprListUsage(pMaskSet, pSrc->a[i].u1.pFuncArg); ++ } + } + } + pS = pS->pPrior; +@@ -130902,7 +138657,7 @@ + int op; /* Top-level operator. pExpr->op */ + Parse *pParse = pWInfo->pParse; /* Parsing context */ + sqlite3 *db = pParse->db; /* Database connection */ +- unsigned char eOp2; /* op2 value for LIKE/REGEXP/GLOB */ ++ unsigned char eOp2 = 0; /* op2 value for LIKE/REGEXP/GLOB */ + int nLeft; /* Number of elements on left side vector */ + + if( db->mallocFailed ){ +@@ -130928,7 +138683,7 @@ + pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->pRight); + } + pMaskSet->bVarSelect = 0; +- prereqAll = sqlite3WhereExprUsage(pMaskSet, pExpr); ++ prereqAll = sqlite3WhereExprUsageNN(pMaskSet, pExpr); + if( pMaskSet->bVarSelect ) pTerm->wtFlags |= TERM_VARSELECT; + if( ExprHasProperty(pExpr, EP_FromJoin) ){ + Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->iRightJoinTable); +@@ -131110,7 +138865,7 @@ + } + *pC = c + 1; + } +- zCollSeqName = noCase ? "NOCASE" : "BINARY"; ++ zCollSeqName = noCase ? "NOCASE" : sqlite3StrBINARY; + pNewExpr1 = sqlite3ExprDup(db, pLeft, 0); + pNewExpr1 = sqlite3PExpr(pParse, TK_GE, + sqlite3ExprAddCollateString(pParse,pNewExpr1,zCollSeqName), +@@ -131136,41 +138891,46 @@ + #endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */ + + #ifndef SQLITE_OMIT_VIRTUALTABLE +- /* Add a WO_MATCH auxiliary term to the constraint set if the +- ** current expression is of the form: column MATCH expr. ++ /* Add a WO_AUX auxiliary term to the constraint set if the ++ ** current expression is of the form "column OP expr" where OP ++ ** is an operator that gets passed into virtual tables but which is ++ ** not normally optimized for ordinary tables. In other words, OP ++ ** is one of MATCH, LIKE, GLOB, REGEXP, !=, IS, IS NOT, or NOT NULL. + ** This information is used by the xBestIndex methods of + ** virtual tables. The native query optimizer does not attempt + ** to do anything with MATCH functions. + */ +- if( pWC->op==TK_AND && isMatchOfColumn(pExpr, &eOp2) ){ +- int idxNew; +- Expr *pRight, *pLeft; +- WhereTerm *pNewTerm; +- Bitmask prereqColumn, prereqExpr; ++ if( pWC->op==TK_AND ){ ++ Expr *pRight = 0, *pLeft = 0; ++ int res = isAuxiliaryVtabOperator(db, pExpr, &eOp2, &pLeft, &pRight); ++ while( res-- > 0 ){ ++ int idxNew; ++ WhereTerm *pNewTerm; ++ Bitmask prereqColumn, prereqExpr; + +- pRight = pExpr->x.pList->a[0].pExpr; +- pLeft = pExpr->x.pList->a[1].pExpr; +- prereqExpr = sqlite3WhereExprUsage(pMaskSet, pRight); +- prereqColumn = sqlite3WhereExprUsage(pMaskSet, pLeft); +- if( (prereqExpr & prereqColumn)==0 ){ +- Expr *pNewExpr; +- pNewExpr = sqlite3PExpr(pParse, TK_MATCH, +- 0, sqlite3ExprDup(db, pRight, 0)); +- if( ExprHasProperty(pExpr, EP_FromJoin) && pNewExpr ){ +- ExprSetProperty(pNewExpr, EP_FromJoin); ++ prereqExpr = sqlite3WhereExprUsage(pMaskSet, pRight); ++ prereqColumn = sqlite3WhereExprUsage(pMaskSet, pLeft); ++ if( (prereqExpr & prereqColumn)==0 ){ ++ Expr *pNewExpr; ++ pNewExpr = sqlite3PExpr(pParse, TK_MATCH, ++ 0, sqlite3ExprDup(db, pRight, 0)); ++ if( ExprHasProperty(pExpr, EP_FromJoin) && pNewExpr ){ ++ ExprSetProperty(pNewExpr, EP_FromJoin); ++ } ++ idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); ++ testcase( idxNew==0 ); ++ pNewTerm = &pWC->a[idxNew]; ++ pNewTerm->prereqRight = prereqExpr; ++ pNewTerm->leftCursor = pLeft->iTable; ++ pNewTerm->u.leftColumn = pLeft->iColumn; ++ pNewTerm->eOperator = WO_AUX; ++ pNewTerm->eMatchOp = eOp2; ++ markTermAsChild(pWC, idxNew, idxTerm); ++ pTerm = &pWC->a[idxTerm]; ++ pTerm->wtFlags |= TERM_COPIED; ++ pNewTerm->prereqAll = pTerm->prereqAll; + } +- idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); +- testcase( idxNew==0 ); +- pNewTerm = &pWC->a[idxNew]; +- pNewTerm->prereqRight = prereqExpr; +- pNewTerm->leftCursor = pLeft->iTable; +- pNewTerm->u.leftColumn = pLeft->iColumn; +- pNewTerm->eOperator = WO_MATCH; +- pNewTerm->eMatchOp = eOp2; +- markTermAsChild(pWC, idxNew, idxTerm); +- pTerm = &pWC->a[idxTerm]; +- pTerm->wtFlags |= TERM_COPIED; +- pNewTerm->prereqAll = pTerm->prereqAll; ++ SWAP(Expr*, pLeft, pRight); + } + } + #endif /* SQLITE_OMIT_VIRTUALTABLE */ +@@ -131202,7 +138962,7 @@ + exprAnalyze(pSrc, pWC, idxNew); + } + pTerm = &pWC->a[idxTerm]; +- pTerm->wtFlags = TERM_CODED|TERM_VIRTUAL; /* Disable the original */ ++ pTerm->wtFlags |= TERM_CODED|TERM_VIRTUAL; /* Disable the original */ + pTerm->eOperator = 0; + } + +@@ -131239,6 +138999,7 @@ + if( pExpr->op==TK_NOTNULL + && pExpr->pLeft->op==TK_COLUMN + && pExpr->pLeft->iColumn>=0 ++ && !ExprHasProperty(pExpr, EP_FromJoin) + && OptimizationEnabled(db, SQLITE_Stat34) + ){ + Expr *pNewExpr; +@@ -131316,6 +139077,7 @@ + WhereInfo *pWInfo /* The WHERE processing context */ + ){ + pWC->pWInfo = pWInfo; ++ pWC->hasOr = 0; + pWC->pOuter = 0; + pWC->nTerm = 0; + pWC->nSlot = ArraySize(pWC->aStatic); +@@ -131352,17 +139114,18 @@ + ** a bitmask indicating which tables are used in that expression + ** tree. + */ +-SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){ ++SQLITE_PRIVATE Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){ + Bitmask mask; +- if( p==0 ) return 0; +- if( p->op==TK_COLUMN ){ ++ if( p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){ + return sqlite3WhereGetMask(pMaskSet, p->iTable); ++ }else if( ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ ++ assert( p->op!=TK_IF_NULL_ROW ); ++ return 0; + } + mask = (p->op==TK_IF_NULL_ROW) ? sqlite3WhereGetMask(pMaskSet, p->iTable) : 0; +- assert( !ExprHasProperty(p, EP_TokenOnly) ); +- if( p->pLeft ) mask |= sqlite3WhereExprUsage(pMaskSet, p->pLeft); ++ if( p->pLeft ) mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pLeft); + if( p->pRight ){ +- mask |= sqlite3WhereExprUsage(pMaskSet, p->pRight); ++ mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pRight); + assert( p->x.pList==0 ); + }else if( ExprHasProperty(p, EP_xIsSelect) ){ + if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1; +@@ -131372,6 +139135,9 @@ + } + return mask; + } ++SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){ ++ return p ? sqlite3WhereExprUsageNN(pMaskSet,p) : 0; ++} + SQLITE_PRIVATE Bitmask sqlite3WhereExprListUsage(WhereMaskSet *pMaskSet, ExprList *pList){ + int i; + Bitmask mask = 0; +@@ -131425,6 +139191,7 @@ + pArgs = pItem->u1.pFuncArg; + if( pArgs==0 ) return; + for(j=k=0; j<pArgs->nExpr; j++){ ++ Expr *pRhs; + while( k<pTab->nCol && (pTab->aCol[k].colFlags & COLFLAG_HIDDEN)==0 ){k++;} + if( k>=pTab->nCol ){ + sqlite3ErrorMsg(pParse, "too many arguments on %s() - max %d", +@@ -131435,9 +139202,10 @@ + if( pColRef==0 ) return; + pColRef->iTable = pItem->iCursor; + pColRef->iColumn = k++; +- pColRef->pTab = pTab; +- pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, +- sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0)); ++ pColRef->y.pTab = pTab; ++ pRhs = sqlite3PExpr(pParse, TK_UPLUS, ++ sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0); ++ pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs); + whereClauseInsert(pWC, pTerm, TERM_DYNAMIC); + } + } +@@ -131465,6 +139233,21 @@ + /* #include "sqliteInt.h" */ + /* #include "whereInt.h" */ + ++/* ++** Extra information appended to the end of sqlite3_index_info but not ++** visible to the xBestIndex function, at least not directly. The ++** sqlite3_vtab_collation() interface knows how to reach it, however. ++** ++** This object is not an API and can be changed from one release to the ++** next. As long as allocateIndexInfo() and sqlite3_vtab_collation() ++** agree on the structure, all will be well. ++*/ ++typedef struct HiddenIndexInfo HiddenIndexInfo; ++struct HiddenIndexInfo { ++ WhereClause *pWC; /* The Where clause being analyzed */ ++ Parse *pParse; /* The parsing context */ ++}; ++ + /* Forward declaration of methods */ + static int whereLoopResize(sqlite3*, WhereLoop*, int); + +@@ -131498,15 +139281,38 @@ + } + + /* +-** Return TRUE if the innermost loop of the WHERE clause implementation +-** returns rows in ORDER BY order for complete run of the inner loop. ++** In the ORDER BY LIMIT optimization, if the inner-most loop is known ++** to emit rows in increasing order, and if the last row emitted by the ++** inner-most loop did not fit within the sorter, then we can skip all ++** subsequent rows for the current iteration of the inner loop (because they ++** will not fit in the sorter either) and continue with the second inner ++** loop - the loop immediately outside the inner-most. + ** +-** Across multiple iterations of outer loops, the output rows need not be +-** sorted. As long as rows are sorted for just the innermost loop, this +-** routine can return TRUE. ++** When a row does not fit in the sorter (because the sorter already ++** holds LIMIT+OFFSET rows that are smaller), then a jump is made to the ++** label returned by this function. ++** ++** If the ORDER BY LIMIT optimization applies, the jump destination should ++** be the continuation for the second-inner-most loop. If the ORDER BY ++** LIMIT optimization does not apply, then the jump destination should ++** be the continuation for the inner-most loop. ++** ++** It is always safe for this routine to return the continuation of the ++** inner-most loop, in the sense that a correct answer will result. ++** Returning the continuation the second inner loop is an optimization ++** that might make the code run a little faster, but should not change ++** the final answer. + */ +-SQLITE_PRIVATE int sqlite3WhereOrderedInnerLoop(WhereInfo *pWInfo){ +- return pWInfo->bOrderedInnerLoop; ++SQLITE_PRIVATE int sqlite3WhereOrderByLimitOptLabel(WhereInfo *pWInfo){ ++ WhereLevel *pInner; ++ if( !pWInfo->bOrderedInnerLoop ){ ++ /* The ORDER BY LIMIT optimization does not apply. Jump to the ++ ** continuation of the inner-most loop. */ ++ return pWInfo->iContinue; ++ } ++ pInner = &pWInfo->a[pWInfo->nLevel-1]; ++ assert( pInner->addrNxt!=0 ); ++ return pInner->addrNxt; + } + + /* +@@ -131849,8 +139655,8 @@ + && p->iColumn==pIdx->aiColumn[iCol] + && p->iTable==iBase + ){ +- CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr); +- if( pColl && 0==sqlite3StrICmp(pColl->zName, zColl) ){ ++ CollSeq *pColl = sqlite3ExprNNCollSeq(pParse, pList->a[i].pExpr); ++ if( 0==sqlite3StrICmp(pColl->zName, zColl) ){ + return i; + } + } +@@ -132233,7 +140039,6 @@ + VdbeComment((v, "for %s", pTable->zName)); + + /* Fill the automatic index with content */ +- sqlite3ExprCachePush(pParse); + pTabItem = &pWC->pWInfo->pTabList->a[pLevel->iFrom]; + if( pTabItem->fg.viaCoroutine ){ + int regYield = pTabItem->regReturn; +@@ -132241,7 +140046,7 @@ + sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub); + addrTop = sqlite3VdbeAddOp1(v, OP_Yield, regYield); + VdbeCoverage(v); +- VdbeComment((v, "next row of \"%s\"", pTabItem->pTab->zName)); ++ VdbeComment((v, "next row of %s", pTabItem->pTab->zName)); + }else{ + addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v); + } +@@ -132263,7 +140068,6 @@ + translateColumnToCopy(pParse, addrTop, pLevel->iTabCur, + pTabItem->regResult, 1); + sqlite3VdbeGoto(v, addrTop); +- pTabItem->fg.viaCoroutine = 0; + }else{ + sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v); + } +@@ -132270,7 +140074,6 @@ + sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX); + sqlite3VdbeJumpHere(v, addrTop); + sqlite3ReleaseTempReg(pParse, regRecord); +- sqlite3ExprCachePop(pParse); + + /* Jump here when skipping the initialization */ + sqlite3VdbeJumpHere(v, addrInit); +@@ -132287,11 +140090,11 @@ + ** by passing the pointer returned by this function to sqlite3_free(). + */ + static sqlite3_index_info *allocateIndexInfo( +- Parse *pParse, +- WhereClause *pWC, ++ Parse *pParse, /* The parsing context */ ++ WhereClause *pWC, /* The WHERE clause being analyzed */ + Bitmask mUnusable, /* Ignore terms with these prereqs */ +- struct SrcList_item *pSrc, +- ExprList *pOrderBy, ++ struct SrcList_item *pSrc, /* The FROM clause term that is the vtab */ ++ ExprList *pOrderBy, /* The ORDER BY clause */ + u16 *pmNoOmit /* Mask of terms not to omit */ + ){ + int i, j; +@@ -132299,6 +140102,7 @@ + struct sqlite3_index_constraint *pIdxCons; + struct sqlite3_index_orderby *pIdxOrderBy; + struct sqlite3_index_constraint_usage *pUsage; ++ struct HiddenIndexInfo *pHidden; + WhereTerm *pTerm; + int nOrderBy; + sqlite3_index_info *pIdxInfo; +@@ -132314,7 +140118,7 @@ + testcase( pTerm->eOperator & WO_ISNULL ); + testcase( pTerm->eOperator & WO_IS ); + testcase( pTerm->eOperator & WO_ALL ); +- if( (pTerm->eOperator & ~(WO_ISNULL|WO_EQUIV|WO_IS))==0 ) continue; ++ if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue; + if( pTerm->wtFlags & TERM_VNULL ) continue; + assert( pTerm->u.leftColumn>=(-1) ); + nTerm++; +@@ -132340,7 +140144,7 @@ + */ + pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo) + + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm +- + sizeof(*pIdxOrderBy)*nOrderBy ); ++ + sizeof(*pIdxOrderBy)*nOrderBy + sizeof(*pHidden) ); + if( pIdxInfo==0 ){ + sqlite3ErrorMsg(pParse, "out of memory"); + return 0; +@@ -132351,7 +140155,8 @@ + ** changing them. We have to do some funky casting in order to + ** initialize those fields. + */ +- pIdxCons = (struct sqlite3_index_constraint*)&pIdxInfo[1]; ++ pHidden = (struct HiddenIndexInfo*)&pIdxInfo[1]; ++ pIdxCons = (struct sqlite3_index_constraint*)&pHidden[1]; + pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm]; + pUsage = (struct sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy]; + *(int*)&pIdxInfo->nConstraint = nTerm; +@@ -132361,8 +140166,10 @@ + *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage = + pUsage; + ++ pHidden->pWC = pWC; ++ pHidden->pParse = pParse; + for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ +- u8 op; ++ u16 op; + if( pTerm->leftCursor != pSrc->iCursor ) continue; + if( pTerm->prereqRight & mUnusable ) continue; + assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); +@@ -132370,34 +140177,54 @@ + testcase( pTerm->eOperator & WO_IS ); + testcase( pTerm->eOperator & WO_ISNULL ); + testcase( pTerm->eOperator & WO_ALL ); +- if( (pTerm->eOperator & ~(WO_ISNULL|WO_EQUIV|WO_IS))==0 ) continue; ++ if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue; + if( pTerm->wtFlags & TERM_VNULL ) continue; ++ if( (pSrc->fg.jointype & JT_LEFT)!=0 ++ && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) ++ && (pTerm->eOperator & (WO_IS|WO_ISNULL)) ++ ){ ++ /* An "IS" term in the WHERE clause where the virtual table is the rhs ++ ** of a LEFT JOIN. Do not pass this term to the virtual table ++ ** implementation, as this can lead to incorrect results from SQL such ++ ** as: ++ ** ++ ** "LEFT JOIN vtab WHERE vtab.col IS NULL" */ ++ testcase( pTerm->eOperator & WO_ISNULL ); ++ testcase( pTerm->eOperator & WO_IS ); ++ continue; ++ } + assert( pTerm->u.leftColumn>=(-1) ); + pIdxCons[j].iColumn = pTerm->u.leftColumn; + pIdxCons[j].iTermOffset = i; +- op = (u8)pTerm->eOperator & WO_ALL; ++ op = pTerm->eOperator & WO_ALL; + if( op==WO_IN ) op = WO_EQ; +- if( op==WO_MATCH ){ +- op = pTerm->eMatchOp; +- } +- pIdxCons[j].op = op; +- /* The direct assignment in the previous line is possible only because +- ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The +- ** following asserts verify this fact. */ +- assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); +- assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT ); +- assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE ); +- assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT ); +- assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); +- assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH ); +- assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) ); ++ if( op==WO_AUX ){ ++ pIdxCons[j].op = pTerm->eMatchOp; ++ }else if( op & (WO_ISNULL|WO_IS) ){ ++ if( op==WO_ISNULL ){ ++ pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_ISNULL; ++ }else{ ++ pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_IS; ++ } ++ }else{ ++ pIdxCons[j].op = (u8)op; ++ /* The direct assignment in the previous line is possible only because ++ ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The ++ ** following asserts verify this fact. */ ++ assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); ++ assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT ); ++ assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE ); ++ assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT ); ++ assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); ++ assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) ); + +- if( op & (WO_LT|WO_LE|WO_GT|WO_GE) +- && sqlite3ExprIsVector(pTerm->pExpr->pRight) +- ){ +- if( i<16 ) mNoOmit |= (1 << i); +- if( op==WO_LT ) pIdxCons[j].op = WO_LE; +- if( op==WO_GT ) pIdxCons[j].op = WO_GE; ++ if( op & (WO_LT|WO_LE|WO_GT|WO_GE) ++ && sqlite3ExprIsVector(pTerm->pExpr->pRight) ++ ){ ++ if( i<16 ) mNoOmit |= (1 << i); ++ if( op==WO_LT ) pIdxCons[j].op = WO_LE; ++ if( op==WO_GT ) pIdxCons[j].op = WO_GE; ++ } + } + + j++; +@@ -132418,9 +140245,11 @@ + ** method of the virtual table with the sqlite3_index_info object that + ** comes in as the 3rd argument to this function. + ** +-** If an error occurs, pParse is populated with an error message and a +-** non-zero value is returned. Otherwise, 0 is returned and the output +-** part of the sqlite3_index_info structure is left populated. ++** If an error occurs, pParse is populated with an error message and an ++** appropriate error code is returned. A return of SQLITE_CONSTRAINT from ++** xBestIndex is not considered an error. SQLITE_CONSTRAINT indicates that ++** the current configuration of "unusable" flags in sqlite3_index_info can ++** not result in a valid plan. + ** + ** Whether or not an error is returned, it is the responsibility of the + ** caller to eventually free p->idxStr if p->needToFreeIdxStr indicates +@@ -132434,7 +140263,7 @@ + rc = pVtab->pModule->xBestIndex(pVtab, p); + TRACE_IDX_OUTPUTS(p); + +- if( rc!=SQLITE_OK ){ ++ if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT ){ + if( rc==SQLITE_NOMEM ){ + sqlite3OomFault(pParse->db); + }else if( !pVtab->zErrMsg ){ +@@ -132445,19 +140274,7 @@ + } + sqlite3_free(pVtab->zErrMsg); + pVtab->zErrMsg = 0; +- +-#if 0 +- /* This error is now caught by the caller. +- ** Search for "xBestIndex malfunction" below */ +- for(i=0; i<p->nConstraint; i++){ +- if( !p->aConstraint[i].usable && p->aConstraintUsage[i].argvIndex>0 ){ +- sqlite3ErrorMsg(pParse, +- "table %s: xBestIndex returned an invalid plan", pTab->zName); +- } +- } +-#endif +- +- return pParse->nErr; ++ return rc; + } + #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */ + +@@ -132857,7 +140674,9 @@ + Index *p = pLoop->u.btree.pIndex; + int nEq = pLoop->u.btree.nEq; + +- if( p->nSample>0 && nEq<p->nSampleCol ){ ++ if( p->nSample>0 && nEq<p->nSampleCol ++ && OptimizationEnabled(pParse->db, SQLITE_Stat34) ++ ){ + if( nEq==pBuilder->nRecValid ){ + UnpackedRecord *pRec = pBuilder->pRec; + tRowcnt a[2]; +@@ -133303,22 +141122,21 @@ + ** Free a WhereInfo structure + */ + static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ +- if( ALWAYS(pWInfo) ){ +- int i; +- for(i=0; i<pWInfo->nLevel; i++){ +- WhereLevel *pLevel = &pWInfo->a[i]; +- if( pLevel->pWLoop && (pLevel->pWLoop->wsFlags & WHERE_IN_ABLE) ){ +- sqlite3DbFree(db, pLevel->u.in.aInLoop); +- } ++ int i; ++ assert( pWInfo!=0 ); ++ for(i=0; i<pWInfo->nLevel; i++){ ++ WhereLevel *pLevel = &pWInfo->a[i]; ++ if( pLevel->pWLoop && (pLevel->pWLoop->wsFlags & WHERE_IN_ABLE) ){ ++ sqlite3DbFree(db, pLevel->u.in.aInLoop); + } +- sqlite3WhereClauseClear(&pWInfo->sWC); +- while( pWInfo->pLoops ){ +- WhereLoop *p = pWInfo->pLoops; +- pWInfo->pLoops = p->pNextLoop; +- whereLoopDelete(db, p); +- } +- sqlite3DbFreeNN(db, pWInfo); + } ++ sqlite3WhereClauseClear(&pWInfo->sWC); ++ while( pWInfo->pLoops ){ ++ WhereLoop *p = pWInfo->pLoops; ++ pWInfo->pLoops = p->pNextLoop; ++ whereLoopDelete(db, p); ++ } ++ sqlite3DbFreeNN(db, pWInfo); + } + + /* +@@ -133325,18 +141143,19 @@ + ** Return TRUE if all of the following are true: + ** + ** (1) X has the same or lower cost that Y +-** (2) X is a proper subset of Y +-** (3) X skips at least as many columns as Y ++** (2) X uses fewer WHERE clause terms than Y ++** (3) Every WHERE clause term used by X is also used by Y ++** (4) X skips at least as many columns as Y ++** (5) If X is a covering index, than Y is too + ** +-** By "proper subset" we mean that X uses fewer WHERE clause terms +-** than Y and that every WHERE clause term used by X is also used +-** by Y. +-** ++** Conditions (2) and (3) mean that X is a "proper subset" of Y. + ** If X is a proper subset of Y then Y is a better choice and ought + ** to have a lower cost. This routine returns TRUE when that cost +-** relationship is inverted and needs to be adjusted. The third rule ++** relationship is inverted and needs to be adjusted. Constraint (4) + ** was added because if X uses skip-scan less than Y it still might +-** deserve a lower cost even if it is a proper subset of Y. ++** deserve a lower cost even if it is a proper subset of Y. Constraint (5) ++** was added because a covering index probably deserves to have a lower cost ++** than a non-covering index even if it is a proper subset. + */ + static int whereLoopCheaperProperSubset( + const WhereLoop *pX, /* First WhereLoop to compare */ +@@ -133358,6 +141177,10 @@ + } + if( j<0 ) return 0; /* X not a subset of Y since term X[i] not used by Y */ + } ++ if( (pX->wsFlags&WHERE_IDX_ONLY)!=0 ++ && (pY->wsFlags&WHERE_IDX_ONLY)==0 ){ ++ return 0; /* Constraint (5) */ ++ } + return 1; /* All conditions meet */ + } + +@@ -133506,6 +141329,14 @@ + sqlite3 *db = pWInfo->pParse->db; + int rc; + ++ /* Stop the search once we hit the query planner search limit */ ++ if( pBuilder->iPlanLimit==0 ){ ++ WHERETRACE(0xffffffff,("=== query planner search limit reached ===\n")); ++ if( pBuilder->pOrSet ) pBuilder->pOrSet->n = 0; ++ return SQLITE_DONE; ++ } ++ pBuilder->iPlanLimit--; ++ + /* If pBuilder->pOrSet is defined, then only keep track of the costs + ** and prereqs. + */ +@@ -133790,8 +141621,8 @@ + + pNew = pBuilder->pNew; + if( db->mallocFailed ) return SQLITE_NOMEM_BKPT; +- WHERETRACE(0x800, ("BEGIN addBtreeIdx(%s), nEq=%d\n", +- pProbe->zName, pNew->u.btree.nEq)); ++ WHERETRACE(0x800, ("BEGIN %s.addBtreeIdx(%s), nEq=%d\n", ++ pProbe->pTable->zName,pProbe->zName, pNew->u.btree.nEq)); + + assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 ); + assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 ); +@@ -133837,15 +141668,12 @@ + ** to mix with a lower range bound from some other source */ + if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue; + +- /* Do not allow IS constraints from the WHERE clause to be used by the ++ /* Do not allow constraints from the WHERE clause to be used by the + ** right table of a LEFT JOIN. Only constraints in the ON clause are + ** allowed */ + if( (pSrc->fg.jointype & JT_LEFT)!=0 + && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) +- && (eOp & (WO_IS|WO_ISNULL))!=0 + ){ +- testcase( eOp & WO_IS ); +- testcase( eOp & WO_ISNULL ); + continue; + } + +@@ -133871,7 +141699,6 @@ + + if( eOp & WO_IN ){ + Expr *pExpr = pTerm->pExpr; +- pNew->wsFlags |= WHERE_COLUMN_IN; + if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + /* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */ + int i; +@@ -133891,17 +141718,55 @@ + assert( nIn>0 ); /* RHS always has 2 or more terms... The parser + ** changes "x IN (?)" into "x=?". */ + } ++ if( pProbe->hasStat1 ){ ++ LogEst M, logK, safetyMargin; ++ /* Let: ++ ** N = the total number of rows in the table ++ ** K = the number of entries on the RHS of the IN operator ++ ** M = the number of rows in the table that match terms to the ++ ** to the left in the same index. If the IN operator is on ++ ** the left-most index column, M==N. ++ ** ++ ** Given the definitions above, it is better to omit the IN operator ++ ** from the index lookup and instead do a scan of the M elements, ++ ** testing each scanned row against the IN operator separately, if: ++ ** ++ ** M*log(K) < K*log(N) ++ ** ++ ** Our estimates for M, K, and N might be inaccurate, so we build in ++ ** a safety margin of 2 (LogEst: 10) that favors using the IN operator ++ ** with the index, as using an index has better worst-case behavior. ++ ** If we do not have real sqlite_stat1 data, always prefer to use ++ ** the index. ++ */ ++ M = pProbe->aiRowLogEst[saved_nEq]; ++ logK = estLog(nIn); ++ safetyMargin = 10; /* TUNING: extra weight for indexed IN */ ++ if( M + logK + safetyMargin < nIn + rLogSize ){ ++ WHERETRACE(0x40, ++ ("Scan preferred over IN operator on column %d of \"%s\" (%d<%d)\n", ++ saved_nEq, pProbe->zName, M+logK+10, nIn+rLogSize)); ++ continue; ++ }else{ ++ WHERETRACE(0x40, ++ ("IN operator preferred on column %d of \"%s\" (%d>=%d)\n", ++ saved_nEq, pProbe->zName, M+logK+10, nIn+rLogSize)); ++ } ++ } ++ pNew->wsFlags |= WHERE_COLUMN_IN; + }else if( eOp & (WO_EQ|WO_IS) ){ + int iCol = pProbe->aiColumn[saved_nEq]; + pNew->wsFlags |= WHERE_COLUMN_EQ; + assert( saved_nEq==pNew->u.btree.nEq ); + if( iCol==XN_ROWID +- || (iCol>0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1) ++ || (iCol>=0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1) + ){ +- if( iCol>=0 && pProbe->uniqNotNull==0 ){ ++ if( iCol==XN_ROWID || pProbe->uniqNotNull ++ || (pProbe->nKeyCol==1 && pProbe->onError && eOp==WO_EQ) ++ ){ ++ pNew->wsFlags |= WHERE_ONEROW; ++ }else{ + pNew->wsFlags |= WHERE_UNQ_WANTED; +- }else{ +- pNew->wsFlags |= WHERE_ONEROW; + } + } + }else if( eOp & WO_ISNULL ){ +@@ -133967,6 +141832,7 @@ + && pProbe->nSample + && pNew->u.btree.nEq<=pProbe->nSampleCol + && ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect)) ++ && OptimizationEnabled(db, SQLITE_Stat34) + ){ + Expr *pExpr = pTerm->pExpr; + if( (eOp & (WO_EQ|WO_ISNULL|WO_IS))!=0 ){ +@@ -134055,6 +141921,7 @@ + if( saved_nEq==saved_nSkip + && saved_nEq+1<pProbe->nKeyCol + && pProbe->noSkipScan==0 ++ && OptimizationEnabled(db, SQLITE_SkipScan) + && pProbe->aiRowLogEst[saved_nEq+1]>=42 /* TUNING: Minimum for skip-scan */ + && (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK + ){ +@@ -134075,8 +141942,8 @@ + pNew->wsFlags = saved_wsFlags; + } + +- WHERETRACE(0x800, ("END addBtreeIdx(%s), nEq=%d, rc=%d\n", +- pProbe->zName, saved_nEq, rc)); ++ WHERETRACE(0x800, ("END %s.addBtreeIdx(%s), nEq=%d, rc=%d\n", ++ pProbe->pTable->zName, pProbe->zName, saved_nEq, rc)); + return rc; + } + +@@ -134109,7 +141976,7 @@ + }else if( (aColExpr = pIndex->aColExpr)!=0 ){ + for(jj=0; jj<pIndex->nKeyCol; jj++){ + if( pIndex->aiColumn[jj]!=XN_EXPR ) continue; +- if( sqlite3ExprCompare(0, pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){ ++ if( sqlite3ExprCompareSkip(pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){ + return 1; + } + } +@@ -134118,24 +141985,6 @@ + return 0; + } + +-/* +-** Return a bitmask where 1s indicate that the corresponding column of +-** the table is used by an index. Only the first 63 columns are considered. +-*/ +-static Bitmask columnsInIndex(Index *pIdx){ +- Bitmask m = 0; +- int j; +- for(j=pIdx->nColumn-1; j>=0; j--){ +- int x = pIdx->aiColumn[j]; +- if( x>=0 ){ +- testcase( x==BMS-1 ); +- testcase( x==BMS-2 ); +- if( x<BMS-1 ) m |= MASKBIT(x); +- } +- } +- return m; +-} +- + /* Check to see if a partial index with pPartIndexWhere can be used + ** in the current query. Return true if it can be and false if not. + */ +@@ -134280,14 +142129,16 @@ + /* TUNING: One-time cost for computing the automatic index is + ** estimated to be X*N*log2(N) where N is the number of rows in + ** the table being indexed and where X is 7 (LogEst=28) for normal +- ** tables or 1.375 (LogEst=4) for views and subqueries. The value ++ ** tables or 0.5 (LogEst=-10) for views and subqueries. The value + ** of X is smaller for views and subqueries so that the query planner + ** will be more aggressive about generating automatic indexes for + ** those objects, since there is no opportunity to add schema + ** indexes on subqueries and views. */ +- pNew->rSetup = rLogSize + rSize + 4; ++ pNew->rSetup = rLogSize + rSize; + if( pTab->pSelect==0 && (pTab->tabFlags & TF_Ephemeral)==0 ){ +- pNew->rSetup += 24; ++ pNew->rSetup += 28; ++ }else{ ++ pNew->rSetup -= 10; + } + ApplyCostMultiplier(pNew->rSetup, pTab->costMult); + if( pNew->rSetup<0 ) pNew->rSetup = 0; +@@ -134305,14 +142156,17 @@ + } + #endif /* SQLITE_OMIT_AUTOMATIC_INDEX */ + +- /* Loop over all indices +- */ +- for(; rc==SQLITE_OK && pProbe; pProbe=pProbe->pNext, iSortIdx++){ ++ /* Loop over all indices. If there was an INDEXED BY clause, then only ++ ** consider index pProbe. */ ++ for(; rc==SQLITE_OK && pProbe; ++ pProbe=(pSrc->pIBIndex ? 0 : pProbe->pNext), iSortIdx++ ++ ){ + if( pProbe->pPartIdxWhere!=0 + && !whereUsablePartialIndex(pSrc->iCursor, pWC, pProbe->pPartIdxWhere) ){ + testcase( pNew->iTab!=pSrc->iCursor ); /* See ticket [98d973b8f5] */ + continue; /* Partial index inappropriate for this query */ + } ++ if( pProbe->bNoQuery ) continue; + rSize = pProbe->aiRowLogEst[0]; + pNew->u.btree.nEq = 0; + pNew->u.btree.nBtm = 0; +@@ -134346,7 +142200,7 @@ + pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED; + m = 0; + }else{ +- m = pSrc->colUsed & ~columnsInIndex(pProbe); ++ m = pSrc->colUsed & pProbe->colNotIdxed; + pNew->wsFlags = (m==0) ? (WHERE_IDX_ONLY|WHERE_INDEXED) : WHERE_INDEXED; + } + +@@ -134417,10 +142271,6 @@ + pBuilder->nRecValid = 0; + pBuilder->pRec = 0; + #endif +- +- /* If there was an INDEXED BY clause, then only that one index is +- ** considered. */ +- if( pSrc->pIBIndex ) break; + } + return rc; + } +@@ -134497,7 +142347,17 @@ + + /* Invoke the virtual table xBestIndex() method */ + rc = vtabBestIndex(pParse, pSrc->pTab, pIdxInfo); +- if( rc ) return rc; ++ if( rc ){ ++ if( rc==SQLITE_CONSTRAINT ){ ++ /* If the xBestIndex method returns SQLITE_CONSTRAINT, that means ++ ** that the particular combination of parameters provided is unusable. ++ ** Make no entries in the loop table. ++ */ ++ WHERETRACE(0xffff, (" ^^^^--- non-viable plan rejected!\n")); ++ return SQLITE_OK; ++ } ++ return rc; ++ } + + mxTerm = -1; + assert( pNew->nLSlot>=nConstraint ); +@@ -134515,9 +142375,9 @@ + || pNew->aLTerm[iTerm]!=0 + || pIdxCons->usable==0 + ){ +- rc = SQLITE_ERROR; + sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName); +- return rc; ++ testcase( pIdxInfo->needToFreeIdxStr ); ++ return SQLITE_ERROR; + } + testcase( iTerm==nConstraint-1 ); + testcase( j==0 ); +@@ -134545,6 +142405,15 @@ + pNew->u.vtab.omitMask &= ~mNoOmit; + + pNew->nLTerm = mxTerm+1; ++ for(i=0; i<=mxTerm; i++){ ++ if( pNew->aLTerm[i]==0 ){ ++ /* The non-zero argvIdx values must be contiguous. Raise an ++ ** error if they are not */ ++ sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName); ++ testcase( pIdxInfo->needToFreeIdxStr ); ++ return SQLITE_ERROR; ++ } ++ } + assert( pNew->nLTerm<=pNew->nLSlot ); + pNew->u.vtab.idxNum = pIdxInfo->idxNum; + pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr; +@@ -134575,6 +142444,27 @@ + return rc; + } + ++/* ++** If this function is invoked from within an xBestIndex() callback, it ++** returns a pointer to a buffer containing the name of the collation ++** sequence associated with element iCons of the sqlite3_index_info.aConstraint ++** array. Or, if iCons is out of range or there is no active xBestIndex ++** call, return NULL. ++*/ ++SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info *pIdxInfo, int iCons){ ++ HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; ++ const char *zRet = 0; ++ if( iCons>=0 && iCons<pIdxInfo->nConstraint ){ ++ CollSeq *pC = 0; ++ int iTerm = pIdxInfo->aConstraint[iCons].iTermOffset; ++ Expr *pX = pHidden->pWC->a[iTerm].pExpr; ++ if( pX->pLeft ){ ++ pC = sqlite3BinaryCompareCollSeq(pHidden->pParse, pX->pLeft, pX->pRight); ++ } ++ zRet = (pC ? pC->zName : sqlite3StrBINARY); ++ } ++ return zRet; ++} + + /* + ** Add all WhereLoop objects for a table of the join identified by +@@ -134639,6 +142529,7 @@ + } + + /* First call xBestIndex() with all constraints usable. */ ++ WHERETRACE(0x800, ("BEGIN %s.addVirtual()\n", pSrc->pTab->zName)); + WHERETRACE(0x40, (" VirtualOne: all usable\n")); + rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn); + +@@ -134714,6 +142605,7 @@ + + if( p->needToFreeIdxStr ) sqlite3_free(p->idxStr); + sqlite3DbFreeNN(pParse->db, p); ++ WHERETRACE(0x800, ("END %s.addVirtual(), rc=%d\n", pSrc->pTab->zName, rc)); + return rc; + } + #endif /* SQLITE_OMIT_VIRTUALTABLE */ +@@ -134861,9 +142753,11 @@ + /* Loop over the tables in the join, from left to right */ + pNew = pBuilder->pNew; + whereLoopInit(pNew); ++ pBuilder->iPlanLimit = SQLITE_QUERY_PLANNER_LIMIT; + for(iTab=0, pItem=pTabList->a; pItem<pEnd; iTab++, pItem++){ + Bitmask mUnusable = 0; + pNew->iTab = iTab; ++ pBuilder->iPlanLimit += SQLITE_QUERY_PLANNER_LIMIT_INCR; + pNew->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor); + if( ((pItem->fg.jointype|priorJointype) & (JT_LEFT|JT_CROSS))!=0 ){ + /* This condition is true when pItem is the FROM clause term on the +@@ -134885,11 +142779,19 @@ + { + rc = whereLoopAddBtree(pBuilder, mPrereq); + } +- if( rc==SQLITE_OK ){ ++ if( rc==SQLITE_OK && pBuilder->pWC->hasOr ){ + rc = whereLoopAddOr(pBuilder, mPrereq, mUnusable); + } + mPrior |= pNew->maskSelf; +- if( rc || db->mallocFailed ) break; ++ if( rc || db->mallocFailed ){ ++ if( rc==SQLITE_DONE ){ ++ /* We hit the query planner search limit set by iPlanLimit */ ++ sqlite3_log(SQLITE_WARNING, "abbreviated query algorithm search"); ++ rc = SQLITE_OK; ++ }else{ ++ break; ++ } ++ } + } + + whereLoopClear(db, pNew); +@@ -135019,14 +142921,10 @@ + if( j>=pLoop->nLTerm ) continue; + } + if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 && pOBExpr->iColumn>=0 ){ +- const char *z1, *z2; +- pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr); +- if( !pColl ) pColl = db->pDfltColl; +- z1 = pColl->zName; +- pColl = sqlite3ExprCollSeq(pWInfo->pParse, pTerm->pExpr); +- if( !pColl ) pColl = db->pDfltColl; +- z2 = pColl->zName; +- if( sqlite3StrICmp(z1, z2)!=0 ) continue; ++ if( sqlite3ExprCollSeqMatch(pWInfo->pParse, ++ pOrderBy->a[i].pExpr, pTerm->pExpr)==0 ){ ++ continue; ++ } + testcase( pTerm->pExpr->op==TK_IS ); + } + obSat |= MASKBIT(i); +@@ -135098,7 +142996,7 @@ + if( pIndex ){ + iColumn = pIndex->aiColumn[j]; + revIdx = pIndex->aSortOrder[j]; +- if( iColumn==pIndex->pTable->iPKey ) iColumn = -1; ++ if( iColumn==pIndex->pTable->iPKey ) iColumn = XN_ROWID; + }else{ + iColumn = XN_ROWID; + revIdx = 0; +@@ -135125,19 +143023,18 @@ + testcase( wctrlFlags & WHERE_GROUPBY ); + testcase( wctrlFlags & WHERE_DISTINCTBY ); + if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0; +- if( iColumn>=(-1) ){ ++ if( iColumn>=XN_ROWID ){ + if( pOBExpr->op!=TK_COLUMN ) continue; + if( pOBExpr->iTable!=iCur ) continue; + if( pOBExpr->iColumn!=iColumn ) continue; + }else{ +- if( sqlite3ExprCompare(0, +- pOBExpr,pIndex->aColExpr->a[j].pExpr,iCur) ){ ++ Expr *pIdxExpr = pIndex->aColExpr->a[j].pExpr; ++ if( sqlite3ExprCompareSkip(pOBExpr, pIdxExpr, iCur) ){ + continue; + } + } +- if( iColumn>=0 ){ +- pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr); +- if( !pColl ) pColl = db->pDfltColl; ++ if( iColumn!=XN_ROWID ){ ++ pColl = sqlite3ExprNNCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr); + if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue; + } + pLoop->u.btree.nIdxCol = j+1; +@@ -135397,12 +143294,15 @@ + + if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue; + if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue; +- if( (pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 && pFrom->nRow<10 ){ ++ if( (pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 && pFrom->nRow<3 ){ + /* Do not use an automatic index if the this loop is expected +- ** to run less than 2 times. */ ++ ** to run less than 1.25 times. It is tempting to also exclude ++ ** automatic index usage on an outer loop, but sometimes an automatic ++ ** index is useful in the outer loop of a correlated subquery. */ + assert( 10==sqlite3LogEst(2) ); + continue; + } ++ + /* At this point, pWLoop is a candidate to be the next loop. + ** Compute its cost */ + rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow); +@@ -135422,7 +143322,11 @@ + pWInfo, nRowEst, nOrderBy, isOrdered + ); + } +- rCost = sqlite3LogEstAdd(rUnsorted, aSortCost[isOrdered]); ++ /* TUNING: Add a small extra penalty (5) to sorting as an ++ ** extra encouragment to the query planner to select a plan ++ ** where the rows emerge in the correct order without any sorting ++ ** required. */ ++ rCost = sqlite3LogEstAdd(rUnsorted, aSortCost[isOrdered]) + 5; + + WHERETRACE(0x002, + ("---- sort cost=%-3d (%d/%d) increases cost %3d to %-3d\n", +@@ -135612,6 +143516,7 @@ + pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; + } + } ++ pWInfo->bOrderedInnerLoop = 0; + if( pWInfo->pOrderBy ){ + if( pWInfo->wctrlFlags & WHERE_DISTINCTBY ){ + if( pFrom->isOrdered==pWInfo->pOrderBy->nExpr ){ +@@ -135723,7 +143628,7 @@ + } + if( j!=pIdx->nKeyCol ) continue; + pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_ONEROW|WHERE_INDEXED; +- if( pIdx->isCovering || (pItem->colUsed & ~columnsInIndex(pIdx))==0 ){ ++ if( pIdx->isCovering || (pItem->colUsed & pIdx->colNotIdxed)==0 ){ + pLoop->wsFlags |= WHERE_IDX_ONLY; + } + pLoop->nLTerm = j; +@@ -135774,6 +143679,7 @@ + memset(&w, 0, sizeof(w)); + w.eCode = 1; + w.xExprCallback = exprNodeIsDeterministic; ++ w.xSelectCallback = sqlite3SelectWalkFail; + sqlite3WalkExpr(&w, p); + return w.eCode; + } +@@ -135983,37 +143889,39 @@ + if( wctrlFlags & WHERE_WANT_DISTINCT ){ + pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; + } +- } +- +- /* Assign a bit from the bitmask to every term in the FROM clause. +- ** +- ** The N-th term of the FROM clause is assigned a bitmask of 1<<N. +- ** +- ** The rule of the previous sentence ensures thta if X is the bitmask for +- ** a table T, then X-1 is the bitmask for all other tables to the left of T. +- ** Knowing the bitmask for all tables to the left of a left join is +- ** important. Ticket #3015. +- ** +- ** Note that bitmasks are created for all pTabList->nSrc tables in +- ** pTabList, not just the first nTabList tables. nTabList is normally +- ** equal to pTabList->nSrc but might be shortened to 1 if the +- ** WHERE_OR_SUBCLAUSE flag is set. +- */ +- for(ii=0; ii<pTabList->nSrc; ii++){ +- createMask(pMaskSet, pTabList->a[ii].iCursor); +- sqlite3WhereTabFuncArgs(pParse, &pTabList->a[ii], &pWInfo->sWC); +- } +-#ifdef SQLITE_DEBUG +- { +- Bitmask mx = 0; +- for(ii=0; ii<pTabList->nSrc; ii++){ +- Bitmask m = sqlite3WhereGetMask(pMaskSet, pTabList->a[ii].iCursor); +- assert( m>=mx ); +- mx = m; ++ ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW")); ++ }else{ ++ /* Assign a bit from the bitmask to every term in the FROM clause. ++ ** ++ ** The N-th term of the FROM clause is assigned a bitmask of 1<<N. ++ ** ++ ** The rule of the previous sentence ensures thta if X is the bitmask for ++ ** a table T, then X-1 is the bitmask for all other tables to the left of T. ++ ** Knowing the bitmask for all tables to the left of a left join is ++ ** important. Ticket #3015. ++ ** ++ ** Note that bitmasks are created for all pTabList->nSrc tables in ++ ** pTabList, not just the first nTabList tables. nTabList is normally ++ ** equal to pTabList->nSrc but might be shortened to 1 if the ++ ** WHERE_OR_SUBCLAUSE flag is set. ++ */ ++ ii = 0; ++ do{ ++ createMask(pMaskSet, pTabList->a[ii].iCursor); ++ sqlite3WhereTabFuncArgs(pParse, &pTabList->a[ii], &pWInfo->sWC); ++ }while( (++ii)<pTabList->nSrc ); ++ #ifdef SQLITE_DEBUG ++ { ++ Bitmask mx = 0; ++ for(ii=0; ii<pTabList->nSrc; ii++){ ++ Bitmask m = sqlite3WhereGetMask(pMaskSet, pTabList->a[ii].iCursor); ++ assert( m>=mx ); ++ mx = m; ++ } + } ++ #endif + } +-#endif +- ++ + /* Analyze all of the subexpressions. */ + sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC); + if( db->mallocFailed ) goto whereBeginError; +@@ -136031,6 +143939,7 @@ + */ + for(ii=0; ii<sWLB.pWC->nTerm; 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; +@@ -136118,35 +144027,80 @@ + } + } + #endif +- /* Attempt to omit tables from the join that do not effect the result */ ++ ++ /* Attempt to omit tables from the join that do not affect the result. ++ ** For a table to not affect the result, the following must be true: ++ ** ++ ** 1) The query must not be an aggregate. ++ ** 2) The table must be the RHS of a LEFT JOIN. ++ ** 3) Either the query must be DISTINCT, or else the ON or USING clause ++ ** must contain a constraint that limits the scan of the table to ++ ** at most a single row. ++ ** 4) The table must not be referenced by any part of the query apart ++ ** from its own USING or ON clause. ++ ** ++ ** For example, given: ++ ** ++ ** CREATE TABLE t1(ipk INTEGER PRIMARY KEY, v1); ++ ** CREATE TABLE t2(ipk INTEGER PRIMARY KEY, v2); ++ ** CREATE TABLE t3(ipk INTEGER PRIMARY KEY, v3); ++ ** ++ ** then table t2 can be omitted from the following: ++ ** ++ ** SELECT v1, v3 FROM t1 ++ ** LEFT JOIN t2 USING (t1.ipk=t2.ipk) ++ ** LEFT JOIN t3 USING (t1.ipk=t3.ipk) ++ ** ++ ** or from: ++ ** ++ ** SELECT DISTINCT v1, v3 FROM t1 ++ ** LEFT JOIN t2 ++ ** LEFT JOIN t3 USING (t1.ipk=t3.ipk) ++ */ ++ notReady = ~(Bitmask)0; + if( pWInfo->nLevel>=2 +- && pResultSet!=0 ++ && pResultSet!=0 /* guarantees condition (1) above */ + && OptimizationEnabled(db, SQLITE_OmitNoopJoin) + ){ ++ int i; + Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet); + if( sWLB.pOrderBy ){ + tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy); + } +- while( pWInfo->nLevel>=2 ){ ++ for(i=pWInfo->nLevel-1; i>=1; i--){ + WhereTerm *pTerm, *pEnd; +- pLoop = pWInfo->a[pWInfo->nLevel-1].pWLoop; +- if( (pWInfo->pTabList->a[pLoop->iTab].fg.jointype & JT_LEFT)==0 ) break; ++ struct SrcList_item *pItem; ++ pLoop = pWInfo->a[i].pWLoop; ++ pItem = &pWInfo->pTabList->a[pLoop->iTab]; ++ if( (pItem->fg.jointype & JT_LEFT)==0 ) continue; + if( (wctrlFlags & WHERE_WANT_DISTINCT)==0 + && (pLoop->wsFlags & WHERE_ONEROW)==0 + ){ +- break; ++ continue; + } +- if( (tabUsed & pLoop->maskSelf)!=0 ) break; ++ if( (tabUsed & pLoop->maskSelf)!=0 ) continue; + pEnd = sWLB.pWC->a + sWLB.pWC->nTerm; + for(pTerm=sWLB.pWC->a; pTerm<pEnd; pTerm++){ +- if( (pTerm->prereqAll & pLoop->maskSelf)!=0 +- && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) +- ){ +- break; ++ if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){ ++ if( !ExprHasProperty(pTerm->pExpr, EP_FromJoin) ++ || pTerm->pExpr->iRightJoinTable!=pItem->iCursor ++ ){ ++ break; ++ } + } + } +- if( pTerm<pEnd ) break; ++ if( pTerm<pEnd ) continue; + WHERETRACE(0xffff, ("-> drop loop %c not used\n", pLoop->cId)); ++ notReady &= ~pLoop->maskSelf; ++ for(pTerm=sWLB.pWC->a; pTerm<pEnd; pTerm++){ ++ if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){ ++ pTerm->wtFlags |= TERM_CODED; ++ } ++ } ++ if( i!=pWInfo->nLevel-1 ){ ++ int nByte = (pWInfo->nLevel-1-i) * sizeof(WhereLevel); ++ memmove(&pWInfo->a[i], &pWInfo->a[i+1], nByte); ++ } + pWInfo->nLevel--; + nTabList--; + } +@@ -136156,15 +144110,32 @@ + + /* If the caller is an UPDATE or DELETE statement that is requesting + ** to use a one-pass algorithm, determine if this is appropriate. ++ ** ++ ** A one-pass approach can be used if the caller has requested one ++ ** and either (a) the scan visits at most one row or (b) each ++ ** of the following are true: ++ ** ++ ** * the caller has indicated that a one-pass approach can be used ++ ** with multiple rows (by setting WHERE_ONEPASS_MULTIROW), and ++ ** * the table is not a virtual table, and ++ ** * either the scan does not use the OR optimization or the caller ++ ** is a DELETE operation (WHERE_DUPLICATES_OK is only specified ++ ** for DELETE). ++ ** ++ ** The last qualification is because an UPDATE statement uses ++ ** WhereInfo.aiCurOnePass[1] to determine whether or not it really can ++ ** use a one-pass approach, and this is not set accurately for scans ++ ** that use the OR optimization. + */ + assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 ); + if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 ){ + int wsFlags = pWInfo->a[0].pWLoop->wsFlags; + int bOnerow = (wsFlags & WHERE_ONEROW)!=0; +- if( bOnerow +- || ((wctrlFlags & WHERE_ONEPASS_MULTIROW)!=0 +- && 0==(wsFlags & WHERE_VIRTUALTABLE)) +- ){ ++ if( bOnerow || ( ++ 0!=(wctrlFlags & WHERE_ONEPASS_MULTIROW) ++ && 0==(wsFlags & WHERE_VIRTUALTABLE) ++ && (0==(wsFlags & WHERE_MULTI_OR) || (wctrlFlags & WHERE_DUPLICATES_OK)) ++ )){ + pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI; + if( HasRowid(pTabList->a[0].pTab) && (wsFlags & WHERE_IDX_ONLY) ){ + if( wctrlFlags & WHERE_ONEPASS_MULTIROW ){ +@@ -136236,7 +144207,7 @@ + Index *pIx = pLoop->u.btree.pIndex; + int iIndexCur; + int op = OP_OpenRead; +- /* iAuxArg is always set if to a positive value if ONEPASS is possible */ ++ /* iAuxArg is always set to a positive value if ONEPASS is possible */ + assert( iAuxArg!=0 || (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 ); + if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIx) + && (wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 +@@ -136301,7 +144272,6 @@ + ** loop below generates code for a single nested loop of the VM + ** program. + */ +- notReady = ~(Bitmask)0; + for(ii=0; ii<nTabList; ii++){ + int addrExplain; + int wsFlags; +@@ -136315,7 +144285,7 @@ + } + #endif + addrExplain = sqlite3WhereExplainOneScan( +- pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags ++ pParse, pTabList, pLevel, wctrlFlags + ); + pLevel->addrBody = sqlite3VdbeCurrentAddr(v); + notReady = sqlite3WhereCodeOneLoopStart(pWInfo, ii, notReady); +@@ -136339,6 +144309,26 @@ + } + + /* ++** Part of sqlite3WhereEnd() will rewrite opcodes to reference the ++** index rather than the main table. In SQLITE_DEBUG mode, we want ++** to trace those changes if PRAGMA vdbe_addoptrace=on. This routine ++** does that. ++*/ ++#ifndef SQLITE_DEBUG ++# define OpcodeRewriteTrace(D,K,P) /* no-op */ ++#else ++# define OpcodeRewriteTrace(D,K,P) sqlite3WhereOpcodeRewriteTrace(D,K,P) ++ static void sqlite3WhereOpcodeRewriteTrace( ++ sqlite3 *db, ++ int pc, ++ VdbeOp *pOp ++ ){ ++ if( (db->flags & SQLITE_VdbeAddopTrace)==0 ) return; ++ sqlite3VdbePrintOp(0, pc, pOp); ++ } ++#endif ++ ++/* + ** Generate the end of the WHERE loop. See comments on + ** sqlite3WhereBegin() for additional information. + */ +@@ -136354,7 +144344,6 @@ + /* Generate loop termination code. + */ + VdbeModuleComment((v, "End WHERE-core")); +- sqlite3ExprCacheClear(pParse); + for(i=pWInfo->nLevel-1; i>=0; i--){ + int addr; + pLevel = &pWInfo->a[i]; +@@ -136365,6 +144354,7 @@ + Index *pIdx; + int n; + if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED ++ && i==pWInfo->nLevel-1 /* Ticket [ef9318757b152e3] 2017-10-21 */ + && (pLoop->wsFlags & WHERE_INDEXED)!=0 + && (pIdx = pLoop->u.btree.pIndex)->hasStat1 + && (n = pLoop->u.btree.nIdxCol)>0 +@@ -136404,10 +144394,17 @@ + for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){ + sqlite3VdbeJumpHere(v, pIn->addrInTop+1); + if( pIn->eEndLoopOp!=OP_Noop ){ ++ if( pIn->nPrefix ){ ++ assert( pLoop->wsFlags & WHERE_IN_EARLYOUT ); ++ sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur, ++ sqlite3VdbeCurrentAddr(v)+2, ++ pIn->iBase, pIn->nPrefix); ++ VdbeCoverage(v); ++ } + sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop); + VdbeCoverage(v); +- VdbeCoverageIf(v, pIn->eEndLoopOp==OP_PrevIfOpen); +- VdbeCoverageIf(v, pIn->eEndLoopOp==OP_NextIfOpen); ++ VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Prev); ++ VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Next); + } + sqlite3VdbeJumpHere(v, pIn->addrInTop-1); + } +@@ -136431,7 +144428,8 @@ + addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v); + assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 ); + if( (ws & WHERE_IDX_ONLY)==0 ){ +- sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor); ++ assert( pLevel->iTabCur==pTabList->a[pLevel->iFrom].iCursor ); ++ sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur); + } + if( (ws & WHERE_INDEXED) + || ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx) +@@ -136497,10 +144495,19 @@ + ){ + last = sqlite3VdbeCurrentAddr(v); + k = pLevel->addrBody; ++#ifdef SQLITE_DEBUG ++ if( db->flags & SQLITE_VdbeAddopTrace ){ ++ printf("TRANSLATE opcodes in range %d..%d\n", k, last-1); ++ } ++#endif + pOp = sqlite3VdbeGetOp(v, k); + for(; k<last; k++, pOp++){ + if( pOp->p1!=pLevel->iTabCur ) continue; +- if( pOp->opcode==OP_Column ){ ++ if( pOp->opcode==OP_Column ++#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC ++ || pOp->opcode==OP_Offset ++#endif ++ ){ + int x = pOp->p2; + assert( pIdx->pTable==pTab ); + if( !HasRowid(pTab) ){ +@@ -136512,6 +144519,7 @@ + if( x>=0 ){ + pOp->p2 = x; + pOp->p1 = pLevel->iIdxCur; ++ OpcodeRewriteTrace(db, k, pOp); + } + assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || x>=0 + || pWInfo->eOnePass ); +@@ -136518,10 +144526,15 @@ + }else if( pOp->opcode==OP_Rowid ){ + pOp->p1 = pLevel->iIdxCur; + pOp->opcode = OP_IdxRowid; ++ OpcodeRewriteTrace(db, k, pOp); + }else if( pOp->opcode==OP_IfNullRow ){ + pOp->p1 = pLevel->iIdxCur; ++ OpcodeRewriteTrace(db, k, pOp); + } + } ++#ifdef SQLITE_DEBUG ++ if( db->flags & SQLITE_VdbeAddopTrace ) printf("TRANSLATE complete\n"); ++#endif + } + } + +@@ -136533,6 +144546,2263 @@ + } + + /************** End of where.c ***********************************************/ ++/************** Begin file window.c ******************************************/ ++/* ++** 2018 May 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. ++** ++************************************************************************* ++*/ ++/* #include "sqliteInt.h" */ ++ ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ ++/* ++** SELECT REWRITING ++** ++** Any SELECT statement that contains one or more window functions in ++** either the select list or ORDER BY clause (the only two places window ++** functions may be used) is transformed by function sqlite3WindowRewrite() ++** in order to support window function processing. For example, with the ++** schema: ++** ++** CREATE TABLE t1(a, b, c, d, e, f, g); ++** ++** the statement: ++** ++** SELECT a+1, max(b) OVER (PARTITION BY c ORDER BY d) FROM t1 ORDER BY e; ++** ++** is transformed to: ++** ++** SELECT a+1, max(b) OVER (PARTITION BY c ORDER BY d) FROM ( ++** SELECT a, e, c, d, b FROM t1 ORDER BY c, d ++** ) ORDER BY e; ++** ++** The flattening optimization is disabled when processing this transformed ++** SELECT statement. This allows the implementation of the window function ++** (in this case max()) to process rows sorted in order of (c, d), which ++** makes things easier for obvious reasons. More generally: ++** ++** * FROM, WHERE, GROUP BY and HAVING clauses are all moved to ++** the sub-query. ++** ++** * ORDER BY, LIMIT and OFFSET remain part of the parent query. ++** ++** * Terminals from each of the expression trees that make up the ++** select-list and ORDER BY expressions in the parent query are ++** selected by the sub-query. For the purposes of the transformation, ++** terminals are column references and aggregate functions. ++** ++** If there is more than one window function in the SELECT that uses ++** the same window declaration (the OVER bit), then a single scan may ++** be used to process more than one window function. For example: ++** ++** SELECT max(b) OVER (PARTITION BY c ORDER BY d), ++** min(e) OVER (PARTITION BY c ORDER BY d) ++** FROM t1; ++** ++** is transformed in the same way as the example above. However: ++** ++** SELECT max(b) OVER (PARTITION BY c ORDER BY d), ++** min(e) OVER (PARTITION BY a ORDER BY b) ++** FROM t1; ++** ++** Must be transformed to: ++** ++** SELECT max(b) OVER (PARTITION BY c ORDER BY d) FROM ( ++** SELECT e, min(e) OVER (PARTITION BY a ORDER BY b), c, d, b FROM ++** SELECT a, e, c, d, b FROM t1 ORDER BY a, b ++** ) ORDER BY c, d ++** ) ORDER BY e; ++** ++** so that both min() and max() may process rows in the order defined by ++** their respective window declarations. ++** ++** INTERFACE WITH SELECT.C ++** ++** When processing the rewritten SELECT statement, code in select.c calls ++** sqlite3WhereBegin() to begin iterating through the results of the ++** sub-query, which is always implemented as a co-routine. It then calls ++** sqlite3WindowCodeStep() to process rows and finish the scan by calling ++** sqlite3WhereEnd(). ++** ++** sqlite3WindowCodeStep() generates VM code so that, for each row returned ++** by the sub-query a sub-routine (OP_Gosub) coded by select.c is invoked. ++** When the sub-routine is invoked: ++** ++** * The results of all window-functions for the row are stored ++** in the associated Window.regResult registers. ++** ++** * The required terminal values are stored in the current row of ++** temp table Window.iEphCsr. ++** ++** In some cases, depending on the window frame and the specific window ++** functions invoked, sqlite3WindowCodeStep() caches each entire partition ++** in a temp table before returning any rows. In other cases it does not. ++** This detail is encapsulated within this file, the code generated by ++** select.c is the same in either case. ++** ++** BUILT-IN WINDOW FUNCTIONS ++** ++** This implementation features the following built-in window functions: ++** ++** row_number() ++** rank() ++** dense_rank() ++** percent_rank() ++** cume_dist() ++** ntile(N) ++** lead(expr [, offset [, default]]) ++** lag(expr [, offset [, default]]) ++** first_value(expr) ++** last_value(expr) ++** nth_value(expr, N) ++** ++** These are the same built-in window functions supported by Postgres. ++** Although the behaviour of aggregate window functions (functions that ++** can be used as either aggregates or window funtions) allows them to ++** be implemented using an API, built-in window functions are much more ++** esoteric. Additionally, some window functions (e.g. nth_value()) ++** may only be implemented by caching the entire partition in memory. ++** As such, some built-in window functions use the same API as aggregate ++** window functions and some are implemented directly using VDBE ++** instructions. Additionally, for those functions that use the API, the ++** window frame is sometimes modified before the SELECT statement is ++** rewritten. For example, regardless of the specified window frame, the ++** row_number() function always uses: ++** ++** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++** ++** See sqlite3WindowUpdate() for details. ++** ++** As well as some of the built-in window functions, aggregate window ++** functions min() and max() are implemented using VDBE instructions if ++** the start of the window frame is declared as anything other than ++** UNBOUNDED PRECEDING. ++*/ ++ ++/* ++** Implementation of built-in window function row_number(). Assumes that the ++** window frame has been coerced to: ++** ++** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++*/ ++static void row_numberStepFunc( ++ sqlite3_context *pCtx, ++ int nArg, ++ sqlite3_value **apArg ++){ ++ i64 *p = (i64*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p ) (*p)++; ++ UNUSED_PARAMETER(nArg); ++ UNUSED_PARAMETER(apArg); ++} ++static void row_numberValueFunc(sqlite3_context *pCtx){ ++ i64 *p = (i64*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ sqlite3_result_int64(pCtx, (p ? *p : 0)); ++} ++ ++/* ++** Context object type used by rank(), dense_rank(), percent_rank() and ++** cume_dist(). ++*/ ++struct CallCount { ++ i64 nValue; ++ i64 nStep; ++ i64 nTotal; ++}; ++ ++/* ++** Implementation of built-in window function dense_rank(). Assumes that ++** the window frame has been set to: ++** ++** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++*/ ++static void dense_rankStepFunc( ++ sqlite3_context *pCtx, ++ int nArg, ++ sqlite3_value **apArg ++){ ++ struct CallCount *p; ++ p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p ) p->nStep = 1; ++ UNUSED_PARAMETER(nArg); ++ UNUSED_PARAMETER(apArg); ++} ++static void dense_rankValueFunc(sqlite3_context *pCtx){ ++ struct CallCount *p; ++ p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p ){ ++ if( p->nStep ){ ++ p->nValue++; ++ p->nStep = 0; ++ } ++ sqlite3_result_int64(pCtx, p->nValue); ++ } ++} ++ ++/* ++** Implementation of built-in window function rank(). Assumes that ++** the window frame has been set to: ++** ++** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++*/ ++static void rankStepFunc( ++ sqlite3_context *pCtx, ++ int nArg, ++ sqlite3_value **apArg ++){ ++ struct CallCount *p; ++ p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p ){ ++ p->nStep++; ++ if( p->nValue==0 ){ ++ p->nValue = p->nStep; ++ } ++ } ++ UNUSED_PARAMETER(nArg); ++ UNUSED_PARAMETER(apArg); ++} ++static void rankValueFunc(sqlite3_context *pCtx){ ++ struct CallCount *p; ++ p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p ){ ++ sqlite3_result_int64(pCtx, p->nValue); ++ p->nValue = 0; ++ } ++} ++ ++/* ++** Implementation of built-in window function percent_rank(). Assumes that ++** the window frame has been set to: ++** ++** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++*/ ++static void percent_rankStepFunc( ++ sqlite3_context *pCtx, ++ int nArg, ++ sqlite3_value **apArg ++){ ++ struct CallCount *p; ++ UNUSED_PARAMETER(nArg); assert( nArg==1 ); ++ ++ p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p ){ ++ if( p->nTotal==0 ){ ++ p->nTotal = sqlite3_value_int64(apArg[0]); ++ } ++ p->nStep++; ++ if( p->nValue==0 ){ ++ p->nValue = p->nStep; ++ } ++ } ++} ++static void percent_rankValueFunc(sqlite3_context *pCtx){ ++ struct CallCount *p; ++ p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p ){ ++ if( p->nTotal>1 ){ ++ double r = (double)(p->nValue-1) / (double)(p->nTotal-1); ++ sqlite3_result_double(pCtx, r); ++ }else{ ++ sqlite3_result_double(pCtx, 0.0); ++ } ++ p->nValue = 0; ++ } ++} ++ ++/* ++** Implementation of built-in window function cume_dist(). Assumes that ++** the window frame has been set to: ++** ++** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++*/ ++static void cume_distStepFunc( ++ sqlite3_context *pCtx, ++ int nArg, ++ sqlite3_value **apArg ++){ ++ struct CallCount *p; ++ assert( nArg==1 ); UNUSED_PARAMETER(nArg); ++ ++ p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p ){ ++ if( p->nTotal==0 ){ ++ p->nTotal = sqlite3_value_int64(apArg[0]); ++ } ++ p->nStep++; ++ } ++} ++static void cume_distValueFunc(sqlite3_context *pCtx){ ++ struct CallCount *p; ++ p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p && p->nTotal ){ ++ double r = (double)(p->nStep) / (double)(p->nTotal); ++ sqlite3_result_double(pCtx, r); ++ } ++} ++ ++/* ++** Context object for ntile() window function. ++*/ ++struct NtileCtx { ++ i64 nTotal; /* Total rows in partition */ ++ i64 nParam; /* Parameter passed to ntile(N) */ ++ i64 iRow; /* Current row */ ++}; ++ ++/* ++** Implementation of ntile(). This assumes that the window frame has ++** been coerced to: ++** ++** ROWS UNBOUNDED PRECEDING AND CURRENT ROW ++*/ ++static void ntileStepFunc( ++ sqlite3_context *pCtx, ++ int nArg, ++ sqlite3_value **apArg ++){ ++ struct NtileCtx *p; ++ assert( nArg==2 ); UNUSED_PARAMETER(nArg); ++ p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p ){ ++ if( p->nTotal==0 ){ ++ p->nParam = sqlite3_value_int64(apArg[0]); ++ p->nTotal = sqlite3_value_int64(apArg[1]); ++ if( p->nParam<=0 ){ ++ sqlite3_result_error( ++ pCtx, "argument of ntile must be a positive integer", -1 ++ ); ++ } ++ } ++ p->iRow++; ++ } ++} ++static void ntileValueFunc(sqlite3_context *pCtx){ ++ struct NtileCtx *p; ++ p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p && p->nParam>0 ){ ++ int nSize = (p->nTotal / p->nParam); ++ if( nSize==0 ){ ++ sqlite3_result_int64(pCtx, p->iRow); ++ }else{ ++ i64 nLarge = p->nTotal - p->nParam*nSize; ++ i64 iSmall = nLarge*(nSize+1); ++ i64 iRow = p->iRow-1; ++ ++ assert( (nLarge*(nSize+1) + (p->nParam-nLarge)*nSize)==p->nTotal ); ++ ++ if( iRow<iSmall ){ ++ sqlite3_result_int64(pCtx, 1 + iRow/(nSize+1)); ++ }else{ ++ sqlite3_result_int64(pCtx, 1 + nLarge + (iRow-iSmall)/nSize); ++ } ++ } ++ } ++} ++ ++/* ++** Context object for last_value() window function. ++*/ ++struct LastValueCtx { ++ sqlite3_value *pVal; ++ int nVal; ++}; ++ ++/* ++** Implementation of last_value(). ++*/ ++static void last_valueStepFunc( ++ sqlite3_context *pCtx, ++ int nArg, ++ sqlite3_value **apArg ++){ ++ struct LastValueCtx *p; ++ UNUSED_PARAMETER(nArg); ++ p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p ){ ++ sqlite3_value_free(p->pVal); ++ p->pVal = sqlite3_value_dup(apArg[0]); ++ if( p->pVal==0 ){ ++ sqlite3_result_error_nomem(pCtx); ++ }else{ ++ p->nVal++; ++ } ++ } ++} ++static void last_valueInvFunc( ++ sqlite3_context *pCtx, ++ int nArg, ++ sqlite3_value **apArg ++){ ++ struct LastValueCtx *p; ++ UNUSED_PARAMETER(nArg); ++ UNUSED_PARAMETER(apArg); ++ p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( ALWAYS(p) ){ ++ p->nVal--; ++ if( p->nVal==0 ){ ++ sqlite3_value_free(p->pVal); ++ p->pVal = 0; ++ } ++ } ++} ++static void last_valueValueFunc(sqlite3_context *pCtx){ ++ struct LastValueCtx *p; ++ p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p && p->pVal ){ ++ sqlite3_result_value(pCtx, p->pVal); ++ } ++} ++static void last_valueFinalizeFunc(sqlite3_context *pCtx){ ++ struct LastValueCtx *p; ++ p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p && p->pVal ){ ++ sqlite3_result_value(pCtx, p->pVal); ++ sqlite3_value_free(p->pVal); ++ p->pVal = 0; ++ } ++} ++ ++/* ++** Static names for the built-in window function names. These static ++** names are used, rather than string literals, so that FuncDef objects ++** can be associated with a particular window function by direct ++** comparison of the zName pointer. Example: ++** ++** if( pFuncDef->zName==row_valueName ){ ... } ++*/ ++static const char row_numberName[] = "row_number"; ++static const char dense_rankName[] = "dense_rank"; ++static const char rankName[] = "rank"; ++static const char percent_rankName[] = "percent_rank"; ++static const char cume_distName[] = "cume_dist"; ++static const char ntileName[] = "ntile"; ++static const char last_valueName[] = "last_value"; ++static const char nth_valueName[] = "nth_value"; ++static const char first_valueName[] = "first_value"; ++static const char leadName[] = "lead"; ++static const char lagName[] = "lag"; ++ ++/* ++** No-op implementations of xStep() and xFinalize(). Used as place-holders ++** for built-in window functions that never call those interfaces. ++** ++** The noopValueFunc() is called but is expected to do nothing. The ++** noopStepFunc() is never called, and so it is marked with NO_TEST to ++** let the test coverage routine know not to expect this function to be ++** invoked. ++*/ ++static void noopStepFunc( /*NO_TEST*/ ++ sqlite3_context *p, /*NO_TEST*/ ++ int n, /*NO_TEST*/ ++ sqlite3_value **a /*NO_TEST*/ ++){ /*NO_TEST*/ ++ UNUSED_PARAMETER(p); /*NO_TEST*/ ++ UNUSED_PARAMETER(n); /*NO_TEST*/ ++ UNUSED_PARAMETER(a); /*NO_TEST*/ ++ assert(0); /*NO_TEST*/ ++} /*NO_TEST*/ ++static void noopValueFunc(sqlite3_context *p){ UNUSED_PARAMETER(p); /*no-op*/ } ++ ++/* Window functions that use all window interfaces: xStep, xFinal, ++** xValue, and xInverse */ ++#define WINDOWFUNCALL(name,nArg,extra) { \ ++ nArg, (SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \ ++ name ## StepFunc, name ## FinalizeFunc, name ## ValueFunc, \ ++ name ## InvFunc, name ## Name, {0} \ ++} ++ ++/* Window functions that are implemented using bytecode and thus have ++** no-op routines for their methods */ ++#define WINDOWFUNCNOOP(name,nArg,extra) { \ ++ nArg, (SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \ ++ noopStepFunc, noopValueFunc, noopValueFunc, \ ++ noopStepFunc, name ## Name, {0} \ ++} ++ ++/* Window functions that use all window interfaces: xStep, the ++** same routine for xFinalize and xValue and which never call ++** xInverse. */ ++#define WINDOWFUNCX(name,nArg,extra) { \ ++ nArg, (SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \ ++ name ## StepFunc, name ## ValueFunc, name ## ValueFunc, \ ++ noopStepFunc, name ## Name, {0} \ ++} ++ ++ ++/* ++** Register those built-in window functions that are not also aggregates. ++*/ ++SQLITE_PRIVATE void sqlite3WindowFunctions(void){ ++ static FuncDef aWindowFuncs[] = { ++ WINDOWFUNCX(row_number, 0, 0), ++ WINDOWFUNCX(dense_rank, 0, 0), ++ WINDOWFUNCX(rank, 0, 0), ++ WINDOWFUNCX(percent_rank, 0, SQLITE_FUNC_WINDOW_SIZE), ++ WINDOWFUNCX(cume_dist, 0, SQLITE_FUNC_WINDOW_SIZE), ++ WINDOWFUNCX(ntile, 1, SQLITE_FUNC_WINDOW_SIZE), ++ WINDOWFUNCALL(last_value, 1, 0), ++ WINDOWFUNCNOOP(nth_value, 2, 0), ++ WINDOWFUNCNOOP(first_value, 1, 0), ++ WINDOWFUNCNOOP(lead, 1, 0), ++ WINDOWFUNCNOOP(lead, 2, 0), ++ WINDOWFUNCNOOP(lead, 3, 0), ++ WINDOWFUNCNOOP(lag, 1, 0), ++ WINDOWFUNCNOOP(lag, 2, 0), ++ WINDOWFUNCNOOP(lag, 3, 0), ++ }; ++ sqlite3InsertBuiltinFuncs(aWindowFuncs, ArraySize(aWindowFuncs)); ++} ++ ++/* ++** This function is called immediately after resolving the function name ++** for a window function within a SELECT statement. Argument pList is a ++** linked list of WINDOW definitions for the current SELECT statement. ++** Argument pFunc is the function definition just resolved and pWin ++** is the Window object representing the associated OVER clause. This ++** function updates the contents of pWin as follows: ++** ++** * If the OVER clause refered to a named window (as in "max(x) OVER win"), ++** search list pList for a matching WINDOW definition, and update pWin ++** accordingly. If no such WINDOW clause can be found, leave an error ++** in pParse. ++** ++** * If the function is a built-in window function that requires the ++** window to be coerced (see "BUILT-IN WINDOW FUNCTIONS" at the top ++** of this file), pWin is updated here. ++*/ ++SQLITE_PRIVATE void sqlite3WindowUpdate( ++ Parse *pParse, ++ Window *pList, /* List of named windows for this SELECT */ ++ Window *pWin, /* Window frame to update */ ++ FuncDef *pFunc /* Window function definition */ ++){ ++ if( pWin->zName && pWin->eType==0 ){ ++ Window *p; ++ for(p=pList; p; p=p->pNextWin){ ++ if( sqlite3StrICmp(p->zName, pWin->zName)==0 ) break; ++ } ++ if( p==0 ){ ++ sqlite3ErrorMsg(pParse, "no such window: %s", pWin->zName); ++ return; ++ } ++ pWin->pPartition = sqlite3ExprListDup(pParse->db, p->pPartition, 0); ++ pWin->pOrderBy = sqlite3ExprListDup(pParse->db, p->pOrderBy, 0); ++ pWin->pStart = sqlite3ExprDup(pParse->db, p->pStart, 0); ++ pWin->pEnd = sqlite3ExprDup(pParse->db, p->pEnd, 0); ++ pWin->eStart = p->eStart; ++ pWin->eEnd = p->eEnd; ++ pWin->eType = p->eType; ++ } ++ if( pFunc->funcFlags & SQLITE_FUNC_WINDOW ){ ++ sqlite3 *db = pParse->db; ++ if( pWin->pFilter ){ ++ sqlite3ErrorMsg(pParse, ++ "FILTER clause may only be used with aggregate window functions" ++ ); ++ }else ++ if( pFunc->zName==row_numberName || pFunc->zName==ntileName ){ ++ sqlite3ExprDelete(db, pWin->pStart); ++ sqlite3ExprDelete(db, pWin->pEnd); ++ pWin->pStart = pWin->pEnd = 0; ++ pWin->eType = TK_ROWS; ++ pWin->eStart = TK_UNBOUNDED; ++ pWin->eEnd = TK_CURRENT; ++ }else ++ ++ if( pFunc->zName==dense_rankName || pFunc->zName==rankName ++ || pFunc->zName==percent_rankName || pFunc->zName==cume_distName ++ ){ ++ sqlite3ExprDelete(db, pWin->pStart); ++ sqlite3ExprDelete(db, pWin->pEnd); ++ pWin->pStart = pWin->pEnd = 0; ++ pWin->eType = TK_RANGE; ++ pWin->eStart = TK_UNBOUNDED; ++ pWin->eEnd = TK_CURRENT; ++ } ++ } ++ pWin->pFunc = pFunc; ++} ++ ++/* ++** Context object passed through sqlite3WalkExprList() to ++** selectWindowRewriteExprCb() by selectWindowRewriteEList(). ++*/ ++typedef struct WindowRewrite WindowRewrite; ++struct WindowRewrite { ++ Window *pWin; ++ SrcList *pSrc; ++ ExprList *pSub; ++ Select *pSubSelect; /* Current sub-select, if any */ ++}; ++ ++/* ++** Callback function used by selectWindowRewriteEList(). If necessary, ++** this function appends to the output expression-list and updates ++** expression (*ppExpr) in place. ++*/ ++static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){ ++ struct WindowRewrite *p = pWalker->u.pRewrite; ++ Parse *pParse = pWalker->pParse; ++ ++ /* If this function is being called from within a scalar sub-select ++ ** that used by the SELECT statement being processed, only process ++ ** TK_COLUMN expressions that refer to it (the outer SELECT). Do ++ ** not process aggregates or window functions at all, as they belong ++ ** to the scalar sub-select. */ ++ if( p->pSubSelect ){ ++ if( pExpr->op!=TK_COLUMN ){ ++ return WRC_Continue; ++ }else{ ++ int nSrc = p->pSrc->nSrc; ++ int i; ++ for(i=0; i<nSrc; i++){ ++ if( pExpr->iTable==p->pSrc->a[i].iCursor ) break; ++ } ++ if( i==nSrc ) return WRC_Continue; ++ } ++ } ++ ++ switch( pExpr->op ){ ++ ++ case TK_FUNCTION: ++ if( !ExprHasProperty(pExpr, EP_WinFunc) ){ ++ break; ++ }else{ ++ Window *pWin; ++ for(pWin=p->pWin; pWin; pWin=pWin->pNextWin){ ++ if( pExpr->y.pWin==pWin ){ ++ assert( pWin->pOwner==pExpr ); ++ return WRC_Prune; ++ } ++ } ++ } ++ /* Fall through. */ ++ ++ case TK_AGG_FUNCTION: ++ case TK_COLUMN: { ++ Expr *pDup = sqlite3ExprDup(pParse->db, pExpr, 0); ++ p->pSub = sqlite3ExprListAppend(pParse, p->pSub, pDup); ++ if( p->pSub ){ ++ assert( ExprHasProperty(pExpr, EP_Static)==0 ); ++ ExprSetProperty(pExpr, EP_Static); ++ sqlite3ExprDelete(pParse->db, pExpr); ++ ExprClearProperty(pExpr, EP_Static); ++ memset(pExpr, 0, sizeof(Expr)); ++ ++ pExpr->op = TK_COLUMN; ++ pExpr->iColumn = p->pSub->nExpr-1; ++ pExpr->iTable = p->pWin->iEphCsr; ++ } ++ ++ break; ++ } ++ ++ default: /* no-op */ ++ break; ++ } ++ ++ return WRC_Continue; ++} ++static int selectWindowRewriteSelectCb(Walker *pWalker, Select *pSelect){ ++ struct WindowRewrite *p = pWalker->u.pRewrite; ++ Select *pSave = p->pSubSelect; ++ if( pSave==pSelect ){ ++ return WRC_Continue; ++ }else{ ++ p->pSubSelect = pSelect; ++ sqlite3WalkSelect(pWalker, pSelect); ++ p->pSubSelect = pSave; ++ } ++ return WRC_Prune; ++} ++ ++ ++/* ++** Iterate through each expression in expression-list pEList. For each: ++** ++** * TK_COLUMN, ++** * aggregate function, or ++** * window function with a Window object that is not a member of the ++** Window list passed as the second argument (pWin). ++** ++** Append the node to output expression-list (*ppSub). And replace it ++** with a TK_COLUMN that reads the (N-1)th element of table ++** pWin->iEphCsr, where N is the number of elements in (*ppSub) after ++** appending the new one. ++*/ ++static void selectWindowRewriteEList( ++ Parse *pParse, ++ Window *pWin, ++ SrcList *pSrc, ++ ExprList *pEList, /* Rewrite expressions in this list */ ++ ExprList **ppSub /* IN/OUT: Sub-select expression-list */ ++){ ++ Walker sWalker; ++ WindowRewrite sRewrite; ++ ++ memset(&sWalker, 0, sizeof(Walker)); ++ memset(&sRewrite, 0, sizeof(WindowRewrite)); ++ ++ sRewrite.pSub = *ppSub; ++ sRewrite.pWin = pWin; ++ sRewrite.pSrc = pSrc; ++ ++ sWalker.pParse = pParse; ++ sWalker.xExprCallback = selectWindowRewriteExprCb; ++ sWalker.xSelectCallback = selectWindowRewriteSelectCb; ++ sWalker.u.pRewrite = &sRewrite; ++ ++ (void)sqlite3WalkExprList(&sWalker, pEList); ++ ++ *ppSub = sRewrite.pSub; ++} ++ ++/* ++** Append a copy of each expression in expression-list pAppend to ++** expression list pList. Return a pointer to the result list. ++*/ ++static ExprList *exprListAppendList( ++ Parse *pParse, /* Parsing context */ ++ ExprList *pList, /* List to which to append. Might be NULL */ ++ ExprList *pAppend /* List of values to append. Might be NULL */ ++){ ++ if( pAppend ){ ++ int i; ++ int nInit = pList ? pList->nExpr : 0; ++ for(i=0; i<pAppend->nExpr; i++){ ++ Expr *pDup = sqlite3ExprDup(pParse->db, pAppend->a[i].pExpr, 0); ++ pList = sqlite3ExprListAppend(pParse, pList, pDup); ++ if( pList ) pList->a[nInit+i].sortOrder = pAppend->a[i].sortOrder; ++ } ++ } ++ return pList; ++} ++ ++/* ++** If the SELECT statement passed as the second argument does not invoke ++** any SQL window functions, this function is a no-op. Otherwise, it ++** rewrites the SELECT statement so that window function xStep functions ++** are invoked in the correct order as described under "SELECT REWRITING" ++** at the top of this file. ++*/ ++SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){ ++ int rc = SQLITE_OK; ++ if( p->pWin && p->pPrior==0 ){ ++ Vdbe *v = sqlite3GetVdbe(pParse); ++ sqlite3 *db = pParse->db; ++ Select *pSub = 0; /* The subquery */ ++ SrcList *pSrc = p->pSrc; ++ Expr *pWhere = p->pWhere; ++ ExprList *pGroupBy = p->pGroupBy; ++ Expr *pHaving = p->pHaving; ++ ExprList *pSort = 0; ++ ++ ExprList *pSublist = 0; /* Expression list for sub-query */ ++ Window *pMWin = p->pWin; /* Master window object */ ++ Window *pWin; /* Window object iterator */ ++ ++ p->pSrc = 0; ++ p->pWhere = 0; ++ p->pGroupBy = 0; ++ p->pHaving = 0; ++ ++ /* Create the ORDER BY clause for the sub-select. This is the concatenation ++ ** of the window PARTITION and ORDER BY clauses. Then, if this makes it ++ ** redundant, remove the ORDER BY from the parent SELECT. */ ++ pSort = sqlite3ExprListDup(db, pMWin->pPartition, 0); ++ pSort = exprListAppendList(pParse, pSort, pMWin->pOrderBy); ++ if( pSort && p->pOrderBy ){ ++ if( sqlite3ExprListCompare(pSort, p->pOrderBy, -1)==0 ){ ++ sqlite3ExprListDelete(db, p->pOrderBy); ++ p->pOrderBy = 0; ++ } ++ } ++ ++ /* Assign a cursor number for the ephemeral table used to buffer rows. ++ ** The OpenEphemeral instruction is coded later, after it is known how ++ ** many columns the table will have. */ ++ pMWin->iEphCsr = pParse->nTab++; ++ ++ selectWindowRewriteEList(pParse, pMWin, pSrc, p->pEList, &pSublist); ++ selectWindowRewriteEList(pParse, pMWin, pSrc, p->pOrderBy, &pSublist); ++ pMWin->nBufferCol = (pSublist ? pSublist->nExpr : 0); ++ ++ /* Append the PARTITION BY and ORDER BY expressions to the to the ++ ** sub-select expression list. They are required to figure out where ++ ** boundaries for partitions and sets of peer rows lie. */ ++ pSublist = exprListAppendList(pParse, pSublist, pMWin->pPartition); ++ pSublist = exprListAppendList(pParse, pSublist, pMWin->pOrderBy); ++ ++ /* Append the arguments passed to each window function to the ++ ** sub-select expression list. Also allocate two registers for each ++ ** window function - one for the accumulator, another for interim ++ ** results. */ ++ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ ++ pWin->iArgCol = (pSublist ? pSublist->nExpr : 0); ++ pSublist = exprListAppendList(pParse, pSublist, pWin->pOwner->x.pList); ++ if( pWin->pFilter ){ ++ Expr *pFilter = sqlite3ExprDup(db, pWin->pFilter, 0); ++ pSublist = sqlite3ExprListAppend(pParse, pSublist, pFilter); ++ } ++ pWin->regAccum = ++pParse->nMem; ++ pWin->regResult = ++pParse->nMem; ++ sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum); ++ } ++ ++ /* If there is no ORDER BY or PARTITION BY clause, and the window ++ ** function accepts zero arguments, and there are no other columns ++ ** selected (e.g. "SELECT row_number() OVER () FROM t1"), it is possible ++ ** that pSublist is still NULL here. Add a constant expression here to ++ ** keep everything legal in this case. ++ */ ++ if( pSublist==0 ){ ++ pSublist = sqlite3ExprListAppend(pParse, 0, ++ sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0) ++ ); ++ } ++ ++ pSub = sqlite3SelectNew( ++ pParse, pSublist, pSrc, pWhere, pGroupBy, pHaving, pSort, 0, 0 ++ ); ++ p->pSrc = sqlite3SrcListAppend(db, 0, 0, 0); ++ assert( p->pSrc || db->mallocFailed ); ++ if( p->pSrc ){ ++ p->pSrc->a[0].pSelect = pSub; ++ sqlite3SrcListAssignCursors(pParse, p->pSrc); ++ if( sqlite3ExpandSubquery(pParse, &p->pSrc->a[0]) ){ ++ rc = SQLITE_NOMEM; ++ }else{ ++ pSub->selFlags |= SF_Expanded; ++ p->selFlags &= ~SF_Aggregate; ++ sqlite3SelectPrep(pParse, pSub, 0); ++ } ++ ++ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pMWin->iEphCsr, pSublist->nExpr); ++ }else{ ++ sqlite3SelectDelete(db, pSub); ++ } ++ if( db->mallocFailed ) rc = SQLITE_NOMEM; ++ } ++ ++ return rc; ++} ++ ++/* ++** Free the Window object passed as the second argument. ++*/ ++SQLITE_PRIVATE void sqlite3WindowDelete(sqlite3 *db, Window *p){ ++ if( p ){ ++ sqlite3ExprDelete(db, p->pFilter); ++ sqlite3ExprListDelete(db, p->pPartition); ++ sqlite3ExprListDelete(db, p->pOrderBy); ++ sqlite3ExprDelete(db, p->pEnd); ++ sqlite3ExprDelete(db, p->pStart); ++ sqlite3DbFree(db, p->zName); ++ sqlite3DbFree(db, p); ++ } ++} ++ ++/* ++** Free the linked list of Window objects starting at the second argument. ++*/ ++SQLITE_PRIVATE void sqlite3WindowListDelete(sqlite3 *db, Window *p){ ++ while( p ){ ++ Window *pNext = p->pNextWin; ++ sqlite3WindowDelete(db, p); ++ p = pNext; ++ } ++} ++ ++/* ++** The argument expression is an PRECEDING or FOLLOWING offset. The ++** value should be a non-negative integer. If the value is not a ++** constant, change it to NULL. The fact that it is then a non-negative ++** integer will be caught later. But it is important not to leave ++** variable values in the expression tree. ++*/ ++static Expr *sqlite3WindowOffsetExpr(Parse *pParse, Expr *pExpr){ ++ if( 0==sqlite3ExprIsConstant(pExpr) ){ ++ sqlite3ExprDelete(pParse->db, pExpr); ++ pExpr = sqlite3ExprAlloc(pParse->db, TK_NULL, 0, 0); ++ } ++ return pExpr; ++} ++ ++/* ++** Allocate and return a new Window object describing a Window Definition. ++*/ ++SQLITE_PRIVATE Window *sqlite3WindowAlloc( ++ Parse *pParse, /* Parsing context */ ++ int eType, /* Frame type. TK_RANGE or TK_ROWS */ ++ int eStart, /* Start type: CURRENT, PRECEDING, FOLLOWING, UNBOUNDED */ ++ Expr *pStart, /* Start window size if TK_PRECEDING or FOLLOWING */ ++ int eEnd, /* End type: CURRENT, FOLLOWING, TK_UNBOUNDED, PRECEDING */ ++ Expr *pEnd /* End window size if TK_FOLLOWING or PRECEDING */ ++){ ++ Window *pWin = 0; ++ ++ /* Parser assures the following: */ ++ assert( eType==TK_RANGE || eType==TK_ROWS ); ++ assert( eStart==TK_CURRENT || eStart==TK_PRECEDING ++ || eStart==TK_UNBOUNDED || eStart==TK_FOLLOWING ); ++ assert( eEnd==TK_CURRENT || eEnd==TK_FOLLOWING ++ || eEnd==TK_UNBOUNDED || eEnd==TK_PRECEDING ); ++ assert( (eStart==TK_PRECEDING || eStart==TK_FOLLOWING)==(pStart!=0) ); ++ assert( (eEnd==TK_FOLLOWING || eEnd==TK_PRECEDING)==(pEnd!=0) ); ++ ++ ++ /* If a frame is declared "RANGE" (not "ROWS"), then it may not use ++ ** either "<expr> PRECEDING" or "<expr> FOLLOWING". ++ */ ++ if( eType==TK_RANGE && (pStart!=0 || pEnd!=0) ){ ++ sqlite3ErrorMsg(pParse, "RANGE must use only UNBOUNDED or CURRENT ROW"); ++ goto windowAllocErr; ++ } ++ ++ /* Additionally, the ++ ** starting boundary type may not occur earlier in the following list than ++ ** the ending boundary type: ++ ** ++ ** UNBOUNDED PRECEDING ++ ** <expr> PRECEDING ++ ** CURRENT ROW ++ ** <expr> FOLLOWING ++ ** UNBOUNDED FOLLOWING ++ ** ++ ** The parser ensures that "UNBOUNDED PRECEDING" cannot be used as an ending ++ ** boundary, and than "UNBOUNDED FOLLOWING" cannot be used as a starting ++ ** frame boundary. ++ */ ++ if( (eStart==TK_CURRENT && eEnd==TK_PRECEDING) ++ || (eStart==TK_FOLLOWING && (eEnd==TK_PRECEDING || eEnd==TK_CURRENT)) ++ ){ ++ sqlite3ErrorMsg(pParse, "unsupported frame delimiter for ROWS"); ++ goto windowAllocErr; ++ } ++ ++ pWin = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); ++ if( pWin==0 ) goto windowAllocErr; ++ pWin->eType = eType; ++ pWin->eStart = eStart; ++ pWin->eEnd = eEnd; ++ pWin->pEnd = sqlite3WindowOffsetExpr(pParse, pEnd); ++ pWin->pStart = sqlite3WindowOffsetExpr(pParse, pStart); ++ return pWin; ++ ++windowAllocErr: ++ sqlite3ExprDelete(pParse->db, pEnd); ++ sqlite3ExprDelete(pParse->db, pStart); ++ return 0; ++} ++ ++/* ++** Attach window object pWin to expression p. ++*/ ++SQLITE_PRIVATE void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){ ++ if( p ){ ++ assert( p->op==TK_FUNCTION ); ++ /* This routine is only called for the parser. If pWin was not ++ ** allocated due to an OOM, then the parser would fail before ever ++ ** invoking this routine */ ++ if( ALWAYS(pWin) ){ ++ p->y.pWin = pWin; ++ ExprSetProperty(p, EP_WinFunc); ++ pWin->pOwner = p; ++ if( p->flags & EP_Distinct ){ ++ sqlite3ErrorMsg(pParse, ++ "DISTINCT is not supported for window functions"); ++ } ++ } ++ }else{ ++ sqlite3WindowDelete(pParse->db, pWin); ++ } ++} ++ ++/* ++** Return 0 if the two window objects are identical, or non-zero otherwise. ++** Identical window objects can be processed in a single scan. ++*/ ++SQLITE_PRIVATE int sqlite3WindowCompare(Parse *pParse, Window *p1, Window *p2){ ++ if( p1->eType!=p2->eType ) return 1; ++ if( p1->eStart!=p2->eStart ) return 1; ++ if( p1->eEnd!=p2->eEnd ) return 1; ++ if( sqlite3ExprCompare(pParse, p1->pStart, p2->pStart, -1) ) return 1; ++ if( sqlite3ExprCompare(pParse, p1->pEnd, p2->pEnd, -1) ) return 1; ++ if( sqlite3ExprListCompare(p1->pPartition, p2->pPartition, -1) ) return 1; ++ if( sqlite3ExprListCompare(p1->pOrderBy, p2->pOrderBy, -1) ) return 1; ++ return 0; ++} ++ ++ ++/* ++** This is called by code in select.c before it calls sqlite3WhereBegin() ++** to begin iterating through the sub-query results. It is used to allocate ++** and initialize registers and cursors used by sqlite3WindowCodeStep(). ++*/ ++SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse *pParse, Window *pMWin){ ++ Window *pWin; ++ Vdbe *v = sqlite3GetVdbe(pParse); ++ int nPart = (pMWin->pPartition ? pMWin->pPartition->nExpr : 0); ++ nPart += (pMWin->pOrderBy ? pMWin->pOrderBy->nExpr : 0); ++ if( nPart ){ ++ pMWin->regPart = pParse->nMem+1; ++ pParse->nMem += nPart; ++ sqlite3VdbeAddOp3(v, OP_Null, 0, pMWin->regPart, pMWin->regPart+nPart-1); ++ } ++ ++ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ ++ FuncDef *p = pWin->pFunc; ++ if( (p->funcFlags & SQLITE_FUNC_MINMAX) && pWin->eStart!=TK_UNBOUNDED ){ ++ /* The inline versions of min() and max() require a single ephemeral ++ ** table and 3 registers. The registers are used as follows: ++ ** ++ ** regApp+0: slot to copy min()/max() argument to for MakeRecord ++ ** regApp+1: integer value used to ensure keys are unique ++ ** regApp+2: output of MakeRecord ++ */ ++ ExprList *pList = pWin->pOwner->x.pList; ++ KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pList, 0, 0); ++ pWin->csrApp = pParse->nTab++; ++ pWin->regApp = pParse->nMem+1; ++ pParse->nMem += 3; ++ if( pKeyInfo && pWin->pFunc->zName[1]=='i' ){ ++ assert( pKeyInfo->aSortOrder[0]==0 ); ++ pKeyInfo->aSortOrder[0] = 1; ++ } ++ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pWin->csrApp, 2); ++ sqlite3VdbeAppendP4(v, pKeyInfo, P4_KEYINFO); ++ sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1); ++ } ++ else if( p->zName==nth_valueName || p->zName==first_valueName ){ ++ /* Allocate two registers at pWin->regApp. These will be used to ++ ** store the start and end index of the current frame. */ ++ assert( pMWin->iEphCsr ); ++ pWin->regApp = pParse->nMem+1; ++ pWin->csrApp = pParse->nTab++; ++ pParse->nMem += 2; ++ sqlite3VdbeAddOp2(v, OP_OpenDup, pWin->csrApp, pMWin->iEphCsr); ++ } ++ else if( p->zName==leadName || p->zName==lagName ){ ++ assert( pMWin->iEphCsr ); ++ pWin->csrApp = pParse->nTab++; ++ sqlite3VdbeAddOp2(v, OP_OpenDup, pWin->csrApp, pMWin->iEphCsr); ++ } ++ } ++} ++ ++/* ++** A "PRECEDING <expr>" (eCond==0) or "FOLLOWING <expr>" (eCond==1) or the ++** value of the second argument to nth_value() (eCond==2) has just been ++** evaluated and the result left in register reg. This function generates VM ++** code to check that the value is a non-negative integer and throws an ++** exception if it is not. ++*/ ++static void windowCheckIntValue(Parse *pParse, int reg, int eCond){ ++ static const char *azErr[] = { ++ "frame starting offset must be a non-negative integer", ++ "frame ending offset must be a non-negative integer", ++ "second argument to nth_value must be a positive integer" ++ }; ++ static int aOp[] = { OP_Ge, OP_Ge, OP_Gt }; ++ Vdbe *v = sqlite3GetVdbe(pParse); ++ int regZero = sqlite3GetTempReg(pParse); ++ assert( eCond==0 || eCond==1 || eCond==2 ); ++ sqlite3VdbeAddOp2(v, OP_Integer, 0, regZero); ++ sqlite3VdbeAddOp2(v, OP_MustBeInt, reg, sqlite3VdbeCurrentAddr(v)+2); ++ VdbeCoverageIf(v, eCond==0); ++ VdbeCoverageIf(v, eCond==1); ++ VdbeCoverageIf(v, eCond==2); ++ sqlite3VdbeAddOp3(v, aOp[eCond], regZero, sqlite3VdbeCurrentAddr(v)+2, reg); ++ VdbeCoverageNeverNullIf(v, eCond==0); ++ VdbeCoverageNeverNullIf(v, eCond==1); ++ VdbeCoverageNeverNullIf(v, eCond==2); ++ sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_ERROR, OE_Abort); ++ sqlite3VdbeAppendP4(v, (void*)azErr[eCond], P4_STATIC); ++ sqlite3ReleaseTempReg(pParse, regZero); ++} ++ ++/* ++** Return the number of arguments passed to the window-function associated ++** with the object passed as the only argument to this function. ++*/ ++static int windowArgCount(Window *pWin){ ++ ExprList *pList = pWin->pOwner->x.pList; ++ return (pList ? pList->nExpr : 0); ++} ++ ++/* ++** Generate VM code to invoke either xStep() (if bInverse is 0) or ++** xInverse (if bInverse is non-zero) for each window function in the ++** linked list starting at pMWin. Or, for built-in window functions ++** that do not use the standard function API, generate the required ++** inline VM code. ++** ++** If argument csr is greater than or equal to 0, then argument reg is ++** the first register in an array of registers guaranteed to be large ++** enough to hold the array of arguments for each function. In this case ++** the arguments are extracted from the current row of csr into the ++** array of registers before invoking OP_AggStep or OP_AggInverse ++** ++** Or, if csr is less than zero, then the array of registers at reg is ++** already populated with all columns from the current row of the sub-query. ++** ++** If argument regPartSize is non-zero, then it is a register containing the ++** number of rows in the current partition. ++*/ ++static void windowAggStep( ++ Parse *pParse, ++ Window *pMWin, /* Linked list of window functions */ ++ int csr, /* Read arguments from this cursor */ ++ int bInverse, /* True to invoke xInverse instead of xStep */ ++ int reg, /* Array of registers */ ++ int regPartSize /* Register containing size of partition */ ++){ ++ Vdbe *v = sqlite3GetVdbe(pParse); ++ Window *pWin; ++ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ ++ int flags = pWin->pFunc->funcFlags; ++ int regArg; ++ int nArg = windowArgCount(pWin); ++ ++ if( csr>=0 ){ ++ int i; ++ for(i=0; i<nArg; i++){ ++ sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+i, reg+i); ++ } ++ regArg = reg; ++ if( flags & SQLITE_FUNC_WINDOW_SIZE ){ ++ if( nArg==0 ){ ++ regArg = regPartSize; ++ }else{ ++ sqlite3VdbeAddOp2(v, OP_SCopy, regPartSize, reg+nArg); ++ } ++ nArg++; ++ } ++ }else{ ++ assert( !(flags & SQLITE_FUNC_WINDOW_SIZE) ); ++ regArg = reg + pWin->iArgCol; ++ } ++ ++ if( (pWin->pFunc->funcFlags & SQLITE_FUNC_MINMAX) ++ && pWin->eStart!=TK_UNBOUNDED ++ ){ ++ int addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regArg); ++ VdbeCoverage(v); ++ if( bInverse==0 ){ ++ sqlite3VdbeAddOp2(v, OP_AddImm, pWin->regApp+1, 1); ++ sqlite3VdbeAddOp2(v, OP_SCopy, regArg, pWin->regApp); ++ sqlite3VdbeAddOp3(v, OP_MakeRecord, pWin->regApp, 2, pWin->regApp+2); ++ sqlite3VdbeAddOp2(v, OP_IdxInsert, pWin->csrApp, pWin->regApp+2); ++ }else{ ++ sqlite3VdbeAddOp4Int(v, OP_SeekGE, pWin->csrApp, 0, regArg, 1); ++ VdbeCoverageNeverTaken(v); ++ sqlite3VdbeAddOp1(v, OP_Delete, pWin->csrApp); ++ sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); ++ } ++ sqlite3VdbeJumpHere(v, addrIsNull); ++ }else if( pWin->regApp ){ ++ assert( pWin->pFunc->zName==nth_valueName ++ || pWin->pFunc->zName==first_valueName ++ ); ++ assert( bInverse==0 || bInverse==1 ); ++ sqlite3VdbeAddOp2(v, OP_AddImm, pWin->regApp+1-bInverse, 1); ++ }else if( pWin->pFunc->zName==leadName ++ || pWin->pFunc->zName==lagName ++ ){ ++ /* no-op */ ++ }else{ ++ int addrIf = 0; ++ if( pWin->pFilter ){ ++ int regTmp; ++ assert( nArg==0 || nArg==pWin->pOwner->x.pList->nExpr ); ++ assert( nArg || pWin->pOwner->x.pList==0 ); ++ if( csr>0 ){ ++ regTmp = sqlite3GetTempReg(pParse); ++ sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp); ++ }else{ ++ regTmp = regArg + nArg; ++ } ++ addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1); ++ VdbeCoverage(v); ++ if( csr>0 ){ ++ sqlite3ReleaseTempReg(pParse, regTmp); ++ } ++ } ++ if( pWin->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ ++ CollSeq *pColl; ++ assert( nArg>0 ); ++ pColl = sqlite3ExprNNCollSeq(pParse, pWin->pOwner->x.pList->a[0].pExpr); ++ sqlite3VdbeAddOp4(v, OP_CollSeq, 0,0,0, (const char*)pColl, P4_COLLSEQ); ++ } ++ sqlite3VdbeAddOp3(v, bInverse? OP_AggInverse : OP_AggStep, ++ bInverse, regArg, pWin->regAccum); ++ sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF); ++ sqlite3VdbeChangeP5(v, (u8)nArg); ++ if( addrIf ) sqlite3VdbeJumpHere(v, addrIf); ++ } ++ } ++} ++ ++/* ++** Generate VM code to invoke either xValue() (bFinal==0) or xFinalize() ++** (bFinal==1) for each window function in the linked list starting at ++** pMWin. Or, for built-in window-functions that do not use the standard ++** API, generate the equivalent VM code. ++*/ ++static void windowAggFinal(Parse *pParse, Window *pMWin, int bFinal){ ++ Vdbe *v = sqlite3GetVdbe(pParse); ++ Window *pWin; ++ ++ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ ++ if( (pWin->pFunc->funcFlags & SQLITE_FUNC_MINMAX) ++ && pWin->eStart!=TK_UNBOUNDED ++ ){ ++ sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult); ++ sqlite3VdbeAddOp1(v, OP_Last, pWin->csrApp); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp3(v, OP_Column, pWin->csrApp, 0, pWin->regResult); ++ sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); ++ if( bFinal ){ ++ sqlite3VdbeAddOp1(v, OP_ResetSorter, pWin->csrApp); ++ } ++ }else if( pWin->regApp ){ ++ }else{ ++ if( bFinal ){ ++ sqlite3VdbeAddOp2(v, OP_AggFinal, pWin->regAccum, windowArgCount(pWin)); ++ sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF); ++ sqlite3VdbeAddOp2(v, OP_Copy, pWin->regAccum, pWin->regResult); ++ sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum); ++ }else{ ++ sqlite3VdbeAddOp3(v, OP_AggValue, pWin->regAccum, windowArgCount(pWin), ++ pWin->regResult); ++ sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF); ++ } ++ } ++ } ++} ++ ++/* ++** This function generates VM code to invoke the sub-routine at address ++** lblFlushPart once for each partition with the entire partition cached in ++** the Window.iEphCsr temp table. ++*/ ++static void windowPartitionCache( ++ Parse *pParse, ++ Select *p, /* The rewritten SELECT statement */ ++ WhereInfo *pWInfo, /* WhereInfo to call WhereEnd() on */ ++ int regFlushPart, /* Register to use with Gosub lblFlushPart */ ++ int lblFlushPart, /* Subroutine to Gosub to */ ++ int *pRegSize /* OUT: Register containing partition size */ ++){ ++ Window *pMWin = p->pWin; ++ Vdbe *v = sqlite3GetVdbe(pParse); ++ int iSubCsr = p->pSrc->a[0].iCursor; ++ int nSub = p->pSrc->a[0].pTab->nCol; ++ int k; ++ ++ int reg = pParse->nMem+1; ++ int regRecord = reg+nSub; ++ int regRowid = regRecord+1; ++ ++ *pRegSize = regRowid; ++ pParse->nMem += nSub + 2; ++ ++ /* Load the column values for the row returned by the sub-select ++ ** into an array of registers starting at reg. */ ++ for(k=0; k<nSub; k++){ ++ sqlite3VdbeAddOp3(v, OP_Column, iSubCsr, k, reg+k); ++ } ++ sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, nSub, regRecord); ++ ++ /* Check if this is the start of a new partition. If so, call the ++ ** flush_partition sub-routine. */ ++ if( pMWin->pPartition ){ ++ int addr; ++ ExprList *pPart = pMWin->pPartition; ++ int nPart = pPart->nExpr; ++ int regNewPart = reg + pMWin->nBufferCol; ++ KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pPart, 0, 0); ++ ++ addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPart, pMWin->regPart,nPart); ++ sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO); ++ sqlite3VdbeAddOp3(v, OP_Jump, addr+2, addr+4, addr+2); ++ VdbeCoverageEqNe(v); ++ sqlite3VdbeAddOp3(v, OP_Copy, regNewPart, pMWin->regPart, nPart-1); ++ sqlite3VdbeAddOp2(v, OP_Gosub, regFlushPart, lblFlushPart); ++ VdbeComment((v, "call flush_partition")); ++ } ++ ++ /* Buffer the current row in the ephemeral table. */ ++ sqlite3VdbeAddOp2(v, OP_NewRowid, pMWin->iEphCsr, regRowid); ++ sqlite3VdbeAddOp3(v, OP_Insert, pMWin->iEphCsr, regRecord, regRowid); ++ ++ /* End of the input loop */ ++ sqlite3WhereEnd(pWInfo); ++ ++ /* Invoke "flush_partition" to deal with the final (or only) partition */ ++ sqlite3VdbeAddOp2(v, OP_Gosub, regFlushPart, lblFlushPart); ++ VdbeComment((v, "call flush_partition")); ++} ++ ++/* ++** Invoke the sub-routine at regGosub (generated by code in select.c) to ++** return the current row of Window.iEphCsr. If all window functions are ++** aggregate window functions that use the standard API, a single ++** OP_Gosub instruction is all that this routine generates. Extra VM code ++** for per-row processing is only generated for the following built-in window ++** functions: ++** ++** nth_value() ++** first_value() ++** lag() ++** lead() ++*/ ++static void windowReturnOneRow( ++ Parse *pParse, ++ Window *pMWin, ++ int regGosub, ++ int addrGosub ++){ ++ Vdbe *v = sqlite3GetVdbe(pParse); ++ Window *pWin; ++ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ ++ FuncDef *pFunc = pWin->pFunc; ++ if( pFunc->zName==nth_valueName ++ || pFunc->zName==first_valueName ++ ){ ++ int csr = pWin->csrApp; ++ int lbl = sqlite3VdbeMakeLabel(v); ++ int tmpReg = sqlite3GetTempReg(pParse); ++ sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult); ++ ++ if( pFunc->zName==nth_valueName ){ ++ sqlite3VdbeAddOp3(v, OP_Column, pMWin->iEphCsr, pWin->iArgCol+1,tmpReg); ++ windowCheckIntValue(pParse, tmpReg, 2); ++ }else{ ++ sqlite3VdbeAddOp2(v, OP_Integer, 1, tmpReg); ++ } ++ sqlite3VdbeAddOp3(v, OP_Add, tmpReg, pWin->regApp, tmpReg); ++ sqlite3VdbeAddOp3(v, OP_Gt, pWin->regApp+1, lbl, tmpReg); ++ VdbeCoverageNeverNull(v); ++ sqlite3VdbeAddOp3(v, OP_SeekRowid, csr, 0, tmpReg); ++ VdbeCoverageNeverTaken(v); ++ sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol, pWin->regResult); ++ sqlite3VdbeResolveLabel(v, lbl); ++ sqlite3ReleaseTempReg(pParse, tmpReg); ++ } ++ else if( pFunc->zName==leadName || pFunc->zName==lagName ){ ++ int nArg = pWin->pOwner->x.pList->nExpr; ++ int iEph = pMWin->iEphCsr; ++ int csr = pWin->csrApp; ++ int lbl = sqlite3VdbeMakeLabel(v); ++ int tmpReg = sqlite3GetTempReg(pParse); ++ ++ if( nArg<3 ){ ++ sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult); ++ }else{ ++ sqlite3VdbeAddOp3(v, OP_Column, iEph, pWin->iArgCol+2, pWin->regResult); ++ } ++ sqlite3VdbeAddOp2(v, OP_Rowid, iEph, tmpReg); ++ if( nArg<2 ){ ++ int val = (pFunc->zName==leadName ? 1 : -1); ++ sqlite3VdbeAddOp2(v, OP_AddImm, tmpReg, val); ++ }else{ ++ int op = (pFunc->zName==leadName ? OP_Add : OP_Subtract); ++ int tmpReg2 = sqlite3GetTempReg(pParse); ++ sqlite3VdbeAddOp3(v, OP_Column, iEph, pWin->iArgCol+1, tmpReg2); ++ sqlite3VdbeAddOp3(v, op, tmpReg2, tmpReg, tmpReg); ++ sqlite3ReleaseTempReg(pParse, tmpReg2); ++ } ++ ++ sqlite3VdbeAddOp3(v, OP_SeekRowid, csr, lbl, tmpReg); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol, pWin->regResult); ++ sqlite3VdbeResolveLabel(v, lbl); ++ sqlite3ReleaseTempReg(pParse, tmpReg); ++ } ++ } ++ sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub); ++} ++ ++/* ++** Invoke the code generated by windowReturnOneRow() and, optionally, the ++** xInverse() function for each window function, for one or more rows ++** from the Window.iEphCsr temp table. This routine generates VM code ++** similar to: ++** ++** while( regCtr>0 ){ ++** regCtr--; ++** windowReturnOneRow() ++** if( bInverse ){ ++** AggInverse ++** } ++** Next (Window.iEphCsr) ++** } ++*/ ++static void windowReturnRows( ++ Parse *pParse, ++ Window *pMWin, /* List of window functions */ ++ int regCtr, /* Register containing number of rows */ ++ int regGosub, /* Register for Gosub addrGosub */ ++ int addrGosub, /* Address of sub-routine for ReturnOneRow */ ++ int regInvArg, /* Array of registers for xInverse args */ ++ int regInvSize /* Register containing size of partition */ ++){ ++ int addr; ++ Vdbe *v = sqlite3GetVdbe(pParse); ++ windowAggFinal(pParse, pMWin, 0); ++ addr = sqlite3VdbeAddOp3(v, OP_IfPos, regCtr, sqlite3VdbeCurrentAddr(v)+2 ,1); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); ++ windowReturnOneRow(pParse, pMWin, regGosub, addrGosub); ++ if( regInvArg ){ ++ windowAggStep(pParse, pMWin, pMWin->iEphCsr, 1, regInvArg, regInvSize); ++ } ++ sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, addr); ++ VdbeCoverage(v); ++ sqlite3VdbeJumpHere(v, addr+1); /* The OP_Goto */ ++} ++ ++/* ++** Generate code to set the accumulator register for each window function ++** in the linked list passed as the second argument to NULL. And perform ++** any equivalent initialization required by any built-in window functions ++** in the list. ++*/ ++static int windowInitAccum(Parse *pParse, Window *pMWin){ ++ Vdbe *v = sqlite3GetVdbe(pParse); ++ int regArg; ++ int nArg = 0; ++ Window *pWin; ++ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ ++ FuncDef *pFunc = pWin->pFunc; ++ sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum); ++ nArg = MAX(nArg, windowArgCount(pWin)); ++ if( pFunc->zName==nth_valueName ++ || pFunc->zName==first_valueName ++ ){ ++ sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp); ++ sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1); ++ } ++ ++ if( (pFunc->funcFlags & SQLITE_FUNC_MINMAX) && pWin->csrApp ){ ++ assert( pWin->eStart!=TK_UNBOUNDED ); ++ sqlite3VdbeAddOp1(v, OP_ResetSorter, pWin->csrApp); ++ sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1); ++ } ++ } ++ regArg = pParse->nMem+1; ++ pParse->nMem += nArg; ++ return regArg; ++} ++ ++ ++/* ++** This function does the work of sqlite3WindowCodeStep() for all "ROWS" ++** window frame types except for "BETWEEN UNBOUNDED PRECEDING AND CURRENT ++** ROW". Pseudo-code for each follows. ++** ++** ROWS BETWEEN <expr1> PRECEDING AND <expr2> FOLLOWING ++** ++** ... ++** if( new partition ){ ++** Gosub flush_partition ++** } ++** Insert (record in eph-table) ++** sqlite3WhereEnd() ++** Gosub flush_partition ++** ++** flush_partition: ++** Once { ++** OpenDup (iEphCsr -> csrStart) ++** OpenDup (iEphCsr -> csrEnd) ++** } ++** regStart = <expr1> // PRECEDING expression ++** regEnd = <expr2> // FOLLOWING expression ++** if( regStart<0 || regEnd<0 ){ error! } ++** Rewind (csr,csrStart,csrEnd) // if EOF goto flush_partition_done ++** Next(csrEnd) // if EOF skip Aggstep ++** Aggstep (csrEnd) ++** if( (regEnd--)<=0 ){ ++** AggFinal (xValue) ++** Gosub addrGosub ++** Next(csr) // if EOF goto flush_partition_done ++** if( (regStart--)<=0 ){ ++** AggInverse (csrStart) ++** Next(csrStart) ++** } ++** } ++** flush_partition_done: ++** ResetSorter (csr) ++** Return ++** ++** ROWS BETWEEN <expr> PRECEDING AND CURRENT ROW ++** ROWS BETWEEN CURRENT ROW AND <expr> FOLLOWING ++** ROWS BETWEEN UNBOUNDED PRECEDING AND <expr> FOLLOWING ++** ++** These are similar to the above. For "CURRENT ROW", intialize the ++** register to 0. For "UNBOUNDED PRECEDING" to infinity. ++** ++** ROWS BETWEEN <expr> PRECEDING AND UNBOUNDED FOLLOWING ++** ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ++** ++** Rewind (csr,csrStart,csrEnd) // if EOF goto flush_partition_done ++** while( 1 ){ ++** Next(csrEnd) // Exit while(1) at EOF ++** Aggstep (csrEnd) ++** } ++** while( 1 ){ ++** AggFinal (xValue) ++** Gosub addrGosub ++** Next(csr) // if EOF goto flush_partition_done ++** if( (regStart--)<=0 ){ ++** AggInverse (csrStart) ++** Next(csrStart) ++** } ++** } ++** ++** For the "CURRENT ROW AND UNBOUNDED FOLLOWING" case, the final if() ++** condition is always true (as if regStart were initialized to 0). ++** ++** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ++** ++** This is the only RANGE case handled by this routine. It modifies the ++** second while( 1 ) loop in "ROWS BETWEEN CURRENT ... UNBOUNDED..." to ++** be: ++** ++** while( 1 ){ ++** AggFinal (xValue) ++** while( 1 ){ ++** regPeer++ ++** Gosub addrGosub ++** Next(csr) // if EOF goto flush_partition_done ++** if( new peer ) break; ++** } ++** while( (regPeer--)>0 ){ ++** AggInverse (csrStart) ++** Next(csrStart) ++** } ++** } ++** ++** ROWS BETWEEN <expr> FOLLOWING AND <expr> FOLLOWING ++** ++** regEnd = regEnd - regStart ++** Rewind (csr,csrStart,csrEnd) // if EOF goto flush_partition_done ++** Aggstep (csrEnd) ++** Next(csrEnd) // if EOF fall-through ++** if( (regEnd--)<=0 ){ ++** if( (regStart--)<=0 ){ ++** AggFinal (xValue) ++** Gosub addrGosub ++** Next(csr) // if EOF goto flush_partition_done ++** } ++** AggInverse (csrStart) ++** Next (csrStart) ++** } ++** ++** ROWS BETWEEN <expr> PRECEDING AND <expr> PRECEDING ++** ++** Replace the bit after "Rewind" in the above with: ++** ++** if( (regEnd--)<=0 ){ ++** AggStep (csrEnd) ++** Next (csrEnd) ++** } ++** AggFinal (xValue) ++** Gosub addrGosub ++** Next(csr) // if EOF goto flush_partition_done ++** if( (regStart--)<=0 ){ ++** AggInverse (csr2) ++** Next (csr2) ++** } ++** ++*/ ++static void windowCodeRowExprStep( ++ Parse *pParse, ++ Select *p, ++ WhereInfo *pWInfo, ++ int regGosub, ++ int addrGosub ++){ ++ Window *pMWin = p->pWin; ++ Vdbe *v = sqlite3GetVdbe(pParse); ++ int regFlushPart; /* Register for "Gosub flush_partition" */ ++ int lblFlushPart; /* Label for "Gosub flush_partition" */ ++ int lblFlushDone; /* Label for "Gosub flush_partition_done" */ ++ ++ int regArg; ++ int addr; ++ int csrStart = pParse->nTab++; ++ int csrEnd = pParse->nTab++; ++ int regStart; /* Value of <expr> PRECEDING */ ++ int regEnd; /* Value of <expr> FOLLOWING */ ++ int addrGoto; ++ int addrTop; ++ int addrIfPos1 = 0; ++ int addrIfPos2 = 0; ++ int regSize = 0; ++ ++ assert( pMWin->eStart==TK_PRECEDING ++ || pMWin->eStart==TK_CURRENT ++ || pMWin->eStart==TK_FOLLOWING ++ || pMWin->eStart==TK_UNBOUNDED ++ ); ++ assert( pMWin->eEnd==TK_FOLLOWING ++ || pMWin->eEnd==TK_CURRENT ++ || pMWin->eEnd==TK_UNBOUNDED ++ || pMWin->eEnd==TK_PRECEDING ++ ); ++ ++ /* Allocate register and label for the "flush_partition" sub-routine. */ ++ regFlushPart = ++pParse->nMem; ++ lblFlushPart = sqlite3VdbeMakeLabel(v); ++ lblFlushDone = sqlite3VdbeMakeLabel(v); ++ ++ regStart = ++pParse->nMem; ++ regEnd = ++pParse->nMem; ++ ++ windowPartitionCache(pParse, p, pWInfo, regFlushPart, lblFlushPart, ®Size); ++ ++ addrGoto = sqlite3VdbeAddOp0(v, OP_Goto); ++ ++ /* Start of "flush_partition" */ ++ sqlite3VdbeResolveLabel(v, lblFlushPart); ++ sqlite3VdbeAddOp2(v, OP_Once, 0, sqlite3VdbeCurrentAddr(v)+3); ++ VdbeCoverage(v); ++ VdbeComment((v, "Flush_partition subroutine")); ++ sqlite3VdbeAddOp2(v, OP_OpenDup, csrStart, pMWin->iEphCsr); ++ sqlite3VdbeAddOp2(v, OP_OpenDup, csrEnd, pMWin->iEphCsr); ++ ++ /* If either regStart or regEnd are not non-negative integers, throw ++ ** an exception. */ ++ if( pMWin->pStart ){ ++ sqlite3ExprCode(pParse, pMWin->pStart, regStart); ++ windowCheckIntValue(pParse, regStart, 0); ++ } ++ if( pMWin->pEnd ){ ++ sqlite3ExprCode(pParse, pMWin->pEnd, regEnd); ++ windowCheckIntValue(pParse, regEnd, 1); ++ } ++ ++ /* If this is "ROWS <expr1> FOLLOWING AND ROWS <expr2> FOLLOWING", do: ++ ** ++ ** if( regEnd<regStart ){ ++ ** // The frame always consists of 0 rows ++ ** regStart = regSize; ++ ** } ++ ** regEnd = regEnd - regStart; ++ */ ++ if( pMWin->pEnd && pMWin->eStart==TK_FOLLOWING ){ ++ assert( pMWin->pStart!=0 ); ++ assert( pMWin->eEnd==TK_FOLLOWING ); ++ sqlite3VdbeAddOp3(v, OP_Ge, regStart, sqlite3VdbeCurrentAddr(v)+2, regEnd); ++ VdbeCoverageNeverNull(v); ++ sqlite3VdbeAddOp2(v, OP_Copy, regSize, regStart); ++ sqlite3VdbeAddOp3(v, OP_Subtract, regStart, regEnd, regEnd); ++ } ++ ++ if( pMWin->pStart && pMWin->eEnd==TK_PRECEDING ){ ++ assert( pMWin->pEnd!=0 ); ++ assert( pMWin->eStart==TK_PRECEDING ); ++ sqlite3VdbeAddOp3(v, OP_Le, regStart, sqlite3VdbeCurrentAddr(v)+3, regEnd); ++ VdbeCoverageNeverNull(v); ++ sqlite3VdbeAddOp2(v, OP_Copy, regSize, regStart); ++ sqlite3VdbeAddOp2(v, OP_Copy, regSize, regEnd); ++ } ++ ++ /* Initialize the accumulator register for each window function to NULL */ ++ regArg = windowInitAccum(pParse, pMWin); ++ ++ sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr, lblFlushDone); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp2(v, OP_Rewind, csrStart, lblFlushDone); ++ VdbeCoverageNeverTaken(v); ++ sqlite3VdbeChangeP5(v, 1); ++ sqlite3VdbeAddOp2(v, OP_Rewind, csrEnd, lblFlushDone); ++ VdbeCoverageNeverTaken(v); ++ sqlite3VdbeChangeP5(v, 1); ++ ++ /* Invoke AggStep function for each window function using the row that ++ ** csrEnd currently points to. Or, if csrEnd is already at EOF, ++ ** do nothing. */ ++ addrTop = sqlite3VdbeCurrentAddr(v); ++ if( pMWin->eEnd==TK_PRECEDING ){ ++ addrIfPos1 = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0 , 1); ++ VdbeCoverage(v); ++ } ++ sqlite3VdbeAddOp2(v, OP_Next, csrEnd, sqlite3VdbeCurrentAddr(v)+2); ++ VdbeCoverage(v); ++ addr = sqlite3VdbeAddOp0(v, OP_Goto); ++ windowAggStep(pParse, pMWin, csrEnd, 0, regArg, regSize); ++ if( pMWin->eEnd==TK_UNBOUNDED ){ ++ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop); ++ sqlite3VdbeJumpHere(v, addr); ++ addrTop = sqlite3VdbeCurrentAddr(v); ++ }else{ ++ sqlite3VdbeJumpHere(v, addr); ++ if( pMWin->eEnd==TK_PRECEDING ){ ++ sqlite3VdbeJumpHere(v, addrIfPos1); ++ } ++ } ++ ++ if( pMWin->eEnd==TK_FOLLOWING ){ ++ addrIfPos1 = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0 , 1); ++ VdbeCoverage(v); ++ } ++ if( pMWin->eStart==TK_FOLLOWING ){ ++ addrIfPos2 = sqlite3VdbeAddOp3(v, OP_IfPos, regStart, 0 , 1); ++ VdbeCoverage(v); ++ } ++ windowAggFinal(pParse, pMWin, 0); ++ windowReturnOneRow(pParse, pMWin, regGosub, addrGosub); ++ sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)+2); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp2(v, OP_Goto, 0, lblFlushDone); ++ if( pMWin->eStart==TK_FOLLOWING ){ ++ sqlite3VdbeJumpHere(v, addrIfPos2); ++ } ++ ++ if( pMWin->eStart==TK_CURRENT ++ || pMWin->eStart==TK_PRECEDING ++ || pMWin->eStart==TK_FOLLOWING ++ ){ ++ int lblSkipInverse = sqlite3VdbeMakeLabel(v);; ++ if( pMWin->eStart==TK_PRECEDING ){ ++ sqlite3VdbeAddOp3(v, OP_IfPos, regStart, lblSkipInverse, 1); ++ VdbeCoverage(v); ++ } ++ if( pMWin->eStart==TK_FOLLOWING ){ ++ sqlite3VdbeAddOp2(v, OP_Next, csrStart, sqlite3VdbeCurrentAddr(v)+2); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp2(v, OP_Goto, 0, lblSkipInverse); ++ }else{ ++ sqlite3VdbeAddOp2(v, OP_Next, csrStart, sqlite3VdbeCurrentAddr(v)+1); ++ VdbeCoverageAlwaysTaken(v); ++ } ++ windowAggStep(pParse, pMWin, csrStart, 1, regArg, regSize); ++ sqlite3VdbeResolveLabel(v, lblSkipInverse); ++ } ++ if( pMWin->eEnd==TK_FOLLOWING ){ ++ sqlite3VdbeJumpHere(v, addrIfPos1); ++ } ++ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop); ++ ++ /* flush_partition_done: */ ++ sqlite3VdbeResolveLabel(v, lblFlushDone); ++ sqlite3VdbeAddOp1(v, OP_ResetSorter, pMWin->iEphCsr); ++ sqlite3VdbeAddOp1(v, OP_Return, regFlushPart); ++ VdbeComment((v, "end flush_partition subroutine")); ++ ++ /* Jump to here to skip over flush_partition */ ++ sqlite3VdbeJumpHere(v, addrGoto); ++} ++ ++/* ++** This function does the work of sqlite3WindowCodeStep() for cases that ++** would normally be handled by windowCodeDefaultStep() when there are ++** one or more built-in window-functions that require the entire partition ++** to be cached in a temp table before any rows can be returned. Additionally. ++** "RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING" is always handled by ++** this function. ++** ++** Pseudo-code corresponding to the VM code generated by this function ++** for each type of window follows. ++** ++** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++** ++** flush_partition: ++** Once { ++** OpenDup (iEphCsr -> csrLead) ++** } ++** Integer ctr 0 ++** foreach row (csrLead){ ++** if( new peer ){ ++** AggFinal (xValue) ++** for(i=0; i<ctr; i++){ ++** Gosub addrGosub ++** Next iEphCsr ++** } ++** Integer ctr 0 ++** } ++** AggStep (csrLead) ++** Incr ctr ++** } ++** ++** AggFinal (xFinalize) ++** for(i=0; i<ctr; i++){ ++** Gosub addrGosub ++** Next iEphCsr ++** } ++** ++** ResetSorter (csr) ++** Return ++** ++** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++** ++** As above, except that the "if( new peer )" branch is always taken. ++** ++** RANGE BETWEEN CURRENT ROW AND CURRENT ROW ++** ++** As above, except that each of the for() loops becomes: ++** ++** for(i=0; i<ctr; i++){ ++** Gosub addrGosub ++** AggInverse (iEphCsr) ++** Next iEphCsr ++** } ++** ++** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ++** ++** flush_partition: ++** Once { ++** OpenDup (iEphCsr -> csrLead) ++** } ++** foreach row (csrLead) { ++** AggStep (csrLead) ++** } ++** foreach row (iEphCsr) { ++** Gosub addrGosub ++** } ++** ++** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ++** ++** flush_partition: ++** Once { ++** OpenDup (iEphCsr -> csrLead) ++** } ++** foreach row (csrLead){ ++** AggStep (csrLead) ++** } ++** Rewind (csrLead) ++** Integer ctr 0 ++** foreach row (csrLead){ ++** if( new peer ){ ++** AggFinal (xValue) ++** for(i=0; i<ctr; i++){ ++** Gosub addrGosub ++** AggInverse (iEphCsr) ++** Next iEphCsr ++** } ++** Integer ctr 0 ++** } ++** Incr ctr ++** } ++** ++** AggFinal (xFinalize) ++** for(i=0; i<ctr; i++){ ++** Gosub addrGosub ++** Next iEphCsr ++** } ++** ++** ResetSorter (csr) ++** Return ++*/ ++static void windowCodeCacheStep( ++ Parse *pParse, ++ Select *p, ++ WhereInfo *pWInfo, ++ int regGosub, ++ int addrGosub ++){ ++ Window *pMWin = p->pWin; ++ Vdbe *v = sqlite3GetVdbe(pParse); ++ int k; ++ int addr; ++ ExprList *pPart = pMWin->pPartition; ++ ExprList *pOrderBy = pMWin->pOrderBy; ++ int nPeer = pOrderBy ? pOrderBy->nExpr : 0; ++ int regNewPeer; ++ ++ int addrGoto; /* Address of Goto used to jump flush_par.. */ ++ int addrNext; /* Jump here for next iteration of loop */ ++ int regFlushPart; ++ int lblFlushPart; ++ int csrLead; ++ int regCtr; ++ int regArg; /* Register array to martial function args */ ++ int regSize; ++ int lblEmpty; ++ int bReverse = pMWin->pOrderBy && pMWin->eStart==TK_CURRENT ++ && pMWin->eEnd==TK_UNBOUNDED; ++ ++ assert( (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_CURRENT) ++ || (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_UNBOUNDED) ++ || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_CURRENT) ++ || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED) ++ ); ++ ++ lblEmpty = sqlite3VdbeMakeLabel(v); ++ regNewPeer = pParse->nMem+1; ++ pParse->nMem += nPeer; ++ ++ /* Allocate register and label for the "flush_partition" sub-routine. */ ++ regFlushPart = ++pParse->nMem; ++ lblFlushPart = sqlite3VdbeMakeLabel(v); ++ ++ csrLead = pParse->nTab++; ++ regCtr = ++pParse->nMem; ++ ++ windowPartitionCache(pParse, p, pWInfo, regFlushPart, lblFlushPart, ®Size); ++ addrGoto = sqlite3VdbeAddOp0(v, OP_Goto); ++ ++ /* Start of "flush_partition" */ ++ sqlite3VdbeResolveLabel(v, lblFlushPart); ++ sqlite3VdbeAddOp2(v, OP_Once, 0, sqlite3VdbeCurrentAddr(v)+2); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp2(v, OP_OpenDup, csrLead, pMWin->iEphCsr); ++ ++ /* Initialize the accumulator register for each window function to NULL */ ++ regArg = windowInitAccum(pParse, pMWin); ++ ++ sqlite3VdbeAddOp2(v, OP_Integer, 0, regCtr); ++ sqlite3VdbeAddOp2(v, OP_Rewind, csrLead, lblEmpty); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr, lblEmpty); ++ VdbeCoverageNeverTaken(v); ++ ++ if( bReverse ){ ++ int addr2 = sqlite3VdbeCurrentAddr(v); ++ windowAggStep(pParse, pMWin, csrLead, 0, regArg, regSize); ++ sqlite3VdbeAddOp2(v, OP_Next, csrLead, addr2); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp2(v, OP_Rewind, csrLead, lblEmpty); ++ VdbeCoverageNeverTaken(v); ++ } ++ addrNext = sqlite3VdbeCurrentAddr(v); ++ ++ if( pOrderBy && (pMWin->eEnd==TK_CURRENT || pMWin->eStart==TK_CURRENT) ){ ++ int bCurrent = (pMWin->eStart==TK_CURRENT); ++ int addrJump = 0; /* Address of OP_Jump below */ ++ if( pMWin->eType==TK_RANGE ){ ++ int iOff = pMWin->nBufferCol + (pPart ? pPart->nExpr : 0); ++ int regPeer = pMWin->regPart + (pPart ? pPart->nExpr : 0); ++ KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pOrderBy, 0, 0); ++ for(k=0; k<nPeer; k++){ ++ sqlite3VdbeAddOp3(v, OP_Column, csrLead, iOff+k, regNewPeer+k); ++ } ++ addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPeer, regPeer, nPeer); ++ sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO); ++ addrJump = sqlite3VdbeAddOp3(v, OP_Jump, addr+2, 0, addr+2); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp3(v, OP_Copy, regNewPeer, regPeer, nPeer-1); ++ } ++ ++ windowReturnRows(pParse, pMWin, regCtr, regGosub, addrGosub, ++ (bCurrent ? regArg : 0), (bCurrent ? regSize : 0) ++ ); ++ if( addrJump ) sqlite3VdbeJumpHere(v, addrJump); ++ } ++ ++ if( bReverse==0 ){ ++ windowAggStep(pParse, pMWin, csrLead, 0, regArg, regSize); ++ } ++ sqlite3VdbeAddOp2(v, OP_AddImm, regCtr, 1); ++ sqlite3VdbeAddOp2(v, OP_Next, csrLead, addrNext); ++ VdbeCoverage(v); ++ ++ windowReturnRows(pParse, pMWin, regCtr, regGosub, addrGosub, 0, 0); ++ ++ sqlite3VdbeResolveLabel(v, lblEmpty); ++ sqlite3VdbeAddOp1(v, OP_ResetSorter, pMWin->iEphCsr); ++ sqlite3VdbeAddOp1(v, OP_Return, regFlushPart); ++ ++ /* Jump to here to skip over flush_partition */ ++ sqlite3VdbeJumpHere(v, addrGoto); ++} ++ ++ ++/* ++** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++** ++** ... ++** if( new partition ){ ++** AggFinal (xFinalize) ++** Gosub addrGosub ++** ResetSorter eph-table ++** } ++** else if( new peer ){ ++** AggFinal (xValue) ++** Gosub addrGosub ++** ResetSorter eph-table ++** } ++** AggStep ++** Insert (record into eph-table) ++** sqlite3WhereEnd() ++** AggFinal (xFinalize) ++** Gosub addrGosub ++** ++** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ++** ++** As above, except take no action for a "new peer". Invoke ++** the sub-routine once only for each partition. ++** ++** RANGE BETWEEN CURRENT ROW AND CURRENT ROW ++** ++** As above, except that the "new peer" condition is handled in the ++** same way as "new partition" (so there is no "else if" block). ++** ++** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++** ++** As above, except assume every row is a "new peer". ++*/ ++static void windowCodeDefaultStep( ++ Parse *pParse, ++ Select *p, ++ WhereInfo *pWInfo, ++ int regGosub, ++ int addrGosub ++){ ++ Window *pMWin = p->pWin; ++ Vdbe *v = sqlite3GetVdbe(pParse); ++ int k; ++ int iSubCsr = p->pSrc->a[0].iCursor; ++ int nSub = p->pSrc->a[0].pTab->nCol; ++ int reg = pParse->nMem+1; ++ int regRecord = reg+nSub; ++ int regRowid = regRecord+1; ++ int addr; ++ ExprList *pPart = pMWin->pPartition; ++ ExprList *pOrderBy = pMWin->pOrderBy; ++ ++ assert( pMWin->eType==TK_RANGE ++ || (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_CURRENT) ++ ); ++ ++ assert( (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_CURRENT) ++ || (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_UNBOUNDED) ++ || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_CURRENT) ++ || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED && !pOrderBy) ++ ); ++ ++ if( pMWin->eEnd==TK_UNBOUNDED ){ ++ pOrderBy = 0; ++ } ++ ++ pParse->nMem += nSub + 2; ++ ++ /* Load the individual column values of the row returned by ++ ** the sub-select into an array of registers. */ ++ for(k=0; k<nSub; k++){ ++ sqlite3VdbeAddOp3(v, OP_Column, iSubCsr, k, reg+k); ++ } ++ ++ /* Check if this is the start of a new partition or peer group. */ ++ if( pPart || pOrderBy ){ ++ int nPart = (pPart ? pPart->nExpr : 0); ++ int addrGoto = 0; ++ int addrJump = 0; ++ int nPeer = (pOrderBy ? pOrderBy->nExpr : 0); ++ ++ if( pPart ){ ++ int regNewPart = reg + pMWin->nBufferCol; ++ KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pPart, 0, 0); ++ addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPart, pMWin->regPart,nPart); ++ sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO); ++ addrJump = sqlite3VdbeAddOp3(v, OP_Jump, addr+2, 0, addr+2); ++ VdbeCoverageEqNe(v); ++ windowAggFinal(pParse, pMWin, 1); ++ if( pOrderBy ){ ++ addrGoto = sqlite3VdbeAddOp0(v, OP_Goto); ++ } ++ } ++ ++ if( pOrderBy ){ ++ int regNewPeer = reg + pMWin->nBufferCol + nPart; ++ int regPeer = pMWin->regPart + nPart; ++ ++ if( addrJump ) sqlite3VdbeJumpHere(v, addrJump); ++ if( pMWin->eType==TK_RANGE ){ ++ KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pOrderBy, 0, 0); ++ addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPeer, regPeer, nPeer); ++ sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO); ++ addrJump = sqlite3VdbeAddOp3(v, OP_Jump, addr+2, 0, addr+2); ++ VdbeCoverage(v); ++ }else{ ++ addrJump = 0; ++ } ++ windowAggFinal(pParse, pMWin, pMWin->eStart==TK_CURRENT); ++ if( addrGoto ) sqlite3VdbeJumpHere(v, addrGoto); ++ } ++ ++ sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr,sqlite3VdbeCurrentAddr(v)+3); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub); ++ sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)-1); ++ VdbeCoverage(v); ++ ++ sqlite3VdbeAddOp1(v, OP_ResetSorter, pMWin->iEphCsr); ++ sqlite3VdbeAddOp3( ++ v, OP_Copy, reg+pMWin->nBufferCol, pMWin->regPart, nPart+nPeer-1 ++ ); ++ ++ if( addrJump ) sqlite3VdbeJumpHere(v, addrJump); ++ } ++ ++ /* Invoke step function for window functions */ ++ windowAggStep(pParse, pMWin, -1, 0, reg, 0); ++ ++ /* Buffer the current row in the ephemeral table. */ ++ if( pMWin->nBufferCol>0 ){ ++ sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, pMWin->nBufferCol, regRecord); ++ }else{ ++ sqlite3VdbeAddOp2(v, OP_Blob, 0, regRecord); ++ sqlite3VdbeAppendP4(v, (void*)"", 0); ++ } ++ sqlite3VdbeAddOp2(v, OP_NewRowid, pMWin->iEphCsr, regRowid); ++ sqlite3VdbeAddOp3(v, OP_Insert, pMWin->iEphCsr, regRecord, regRowid); ++ ++ /* End the database scan loop. */ ++ sqlite3WhereEnd(pWInfo); ++ ++ windowAggFinal(pParse, pMWin, 1); ++ sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr,sqlite3VdbeCurrentAddr(v)+3); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub); ++ sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)-1); ++ VdbeCoverage(v); ++} ++ ++/* ++** Allocate and return a duplicate of the Window object indicated by the ++** third argument. Set the Window.pOwner field of the new object to ++** pOwner. ++*/ ++SQLITE_PRIVATE Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){ ++ Window *pNew = 0; ++ if( ALWAYS(p) ){ ++ pNew = sqlite3DbMallocZero(db, sizeof(Window)); ++ if( pNew ){ ++ pNew->zName = sqlite3DbStrDup(db, p->zName); ++ pNew->pFilter = sqlite3ExprDup(db, p->pFilter, 0); ++ pNew->pPartition = sqlite3ExprListDup(db, p->pPartition, 0); ++ pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, 0); ++ pNew->eType = p->eType; ++ pNew->eEnd = p->eEnd; ++ pNew->eStart = p->eStart; ++ pNew->pStart = sqlite3ExprDup(db, p->pStart, 0); ++ pNew->pEnd = sqlite3ExprDup(db, p->pEnd, 0); ++ pNew->pOwner = pOwner; ++ } ++ } ++ return pNew; ++} ++ ++/* ++** Return a copy of the linked list of Window objects passed as the ++** second argument. ++*/ ++SQLITE_PRIVATE Window *sqlite3WindowListDup(sqlite3 *db, Window *p){ ++ Window *pWin; ++ Window *pRet = 0; ++ Window **pp = &pRet; ++ ++ for(pWin=p; pWin; pWin=pWin->pNextWin){ ++ *pp = sqlite3WindowDup(db, 0, pWin); ++ if( *pp==0 ) break; ++ pp = &((*pp)->pNextWin); ++ } ++ ++ return pRet; ++} ++ ++/* ++** sqlite3WhereBegin() has already been called for the SELECT statement ++** passed as the second argument when this function is invoked. It generates ++** code to populate the Window.regResult register for each window function and ++** invoke the sub-routine at instruction addrGosub once for each row. ++** This function calls sqlite3WhereEnd() before returning. ++*/ ++SQLITE_PRIVATE void sqlite3WindowCodeStep( ++ Parse *pParse, /* Parse context */ ++ Select *p, /* Rewritten SELECT statement */ ++ WhereInfo *pWInfo, /* Context returned by sqlite3WhereBegin() */ ++ int regGosub, /* Register for OP_Gosub */ ++ int addrGosub /* OP_Gosub here to return each row */ ++){ ++ Window *pMWin = p->pWin; ++ ++ /* There are three different functions that may be used to do the work ++ ** of this one, depending on the window frame and the specific built-in ++ ** window functions used (if any). ++ ** ++ ** windowCodeRowExprStep() handles all "ROWS" window frames, except for: ++ ** ++ ** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++ ** ++ ** The exception is because windowCodeRowExprStep() implements all window ++ ** frame types by caching the entire partition in a temp table, and ++ ** "ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW" is easy enough to ++ ** implement without such a cache. ++ ** ++ ** windowCodeCacheStep() is used for: ++ ** ++ ** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ++ ** ++ ** It is also used for anything not handled by windowCodeRowExprStep() ++ ** that invokes a built-in window function that requires the entire ++ ** partition to be cached in a temp table before any rows are returned ++ ** (e.g. nth_value() or percent_rank()). ++ ** ++ ** Finally, assuming there is no built-in window function that requires ++ ** the partition to be cached, windowCodeDefaultStep() is used for: ++ ** ++ ** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++ ** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ++ ** RANGE BETWEEN CURRENT ROW AND CURRENT ROW ++ ** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++ ** ++ ** windowCodeDefaultStep() is the only one of the three functions that ++ ** does not cache each partition in a temp table before beginning to ++ ** return rows. ++ */ ++ if( pMWin->eType==TK_ROWS ++ && (pMWin->eStart!=TK_UNBOUNDED||pMWin->eEnd!=TK_CURRENT||!pMWin->pOrderBy) ++ ){ ++ VdbeModuleComment((pParse->pVdbe, "Begin RowExprStep()")); ++ windowCodeRowExprStep(pParse, p, pWInfo, regGosub, addrGosub); ++ }else{ ++ Window *pWin; ++ int bCache = 0; /* True to use CacheStep() */ ++ ++ if( pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED ){ ++ bCache = 1; ++ }else{ ++ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ ++ FuncDef *pFunc = pWin->pFunc; ++ if( (pFunc->funcFlags & SQLITE_FUNC_WINDOW_SIZE) ++ || (pFunc->zName==nth_valueName) ++ || (pFunc->zName==first_valueName) ++ || (pFunc->zName==leadName) ++ || (pFunc->zName==lagName) ++ ){ ++ bCache = 1; ++ break; ++ } ++ } ++ } ++ ++ /* Otherwise, call windowCodeDefaultStep(). */ ++ if( bCache ){ ++ VdbeModuleComment((pParse->pVdbe, "Begin CacheStep()")); ++ windowCodeCacheStep(pParse, p, pWInfo, regGosub, addrGosub); ++ }else{ ++ VdbeModuleComment((pParse->pVdbe, "Begin DefaultStep()")); ++ windowCodeDefaultStep(pParse, p, pWInfo, regGosub, addrGosub); ++ } ++ } ++} ++ ++#endif /* SQLITE_OMIT_WINDOWFUNC */ ++ ++/************** End of window.c **********************************************/ + /************** Begin file parse.c *******************************************/ + /* + ** 2000-05-29 +@@ -136559,6 +146829,7 @@ + ** input grammar file: + */ + /* #include <stdio.h> */ ++/* #include <assert.h> */ + /************ Begin %include sections from the grammar ************************/ + + /* #include "sqliteInt.h" */ +@@ -136600,15 +146871,6 @@ + #define YYMALLOCARGTYPE u64 + + /* +-** An instance of this structure holds information about the +-** LIMIT clause of a SELECT statement. +-*/ +-struct LimitVal { +- Expr *pLimit; /* The LIMIT expression. NULL if there is no limit */ +- Expr *pOffset; /* The OFFSET expression. NULL if there is none */ +-}; +- +-/* + ** An instance of the following structure describes the event of a + ** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT, + ** TK_DELETE, or TK_INSTEAD. If the event is of the form +@@ -136619,6 +146881,8 @@ + */ + struct TrigEvent { int a; IdList * b; }; + ++struct FrameBound { int eType; Expr *pExpr; }; ++ + /* + ** Disable lookaside memory allocation for objects that might be + ** shared across database connections. +@@ -136651,26 +146915,26 @@ + } + } + +- /* This is a utility routine used to set the ExprSpan.zStart and +- ** ExprSpan.zEnd values of pOut so that the span covers the complete +- ** range of text beginning with pStart and going to the end of pEnd. +- */ +- static void spanSet(ExprSpan *pOut, Token *pStart, Token *pEnd){ +- pOut->zStart = pStart->z; +- pOut->zEnd = &pEnd->z[pEnd->n]; +- } + + /* Construct a new Expr object from a single identifier. Use the + ** new Expr to populate pOut. Set the span of pOut to be the identifier + ** that created the expression. + */ +- static void spanExpr(ExprSpan *pOut, Parse *pParse, int op, Token t){ ++ static Expr *tokenExpr(Parse *pParse, int op, Token t){ + Expr *p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)+t.n+1); + if( p ){ +- memset(p, 0, sizeof(Expr)); ++ /* memset(p, 0, sizeof(Expr)); */ + p->op = (u8)op; ++ p->affinity = 0; + p->flags = EP_Leaf; + p->iAgg = -1; ++ p->pLeft = p->pRight = 0; ++ p->x.pList = 0; ++ p->pAggInfo = 0; ++ p->y.pTab = 0; ++ p->op2 = 0; ++ p->iTable = 0; ++ p->iColumn = 0; + p->u.zToken = (char*)&p[1]; + memcpy(p->u.zToken, t.z, t.n); + p->u.zToken[t.n] = 0; +@@ -136681,51 +146945,19 @@ + #if SQLITE_MAX_EXPR_DEPTH>0 + p->nHeight = 1; + #endif ++ if( IN_RENAME_OBJECT ){ ++ return (Expr*)sqlite3RenameTokenMap(pParse, (void*)p, &t); ++ } + } +- pOut->pExpr = p; +- pOut->zStart = t.z; +- pOut->zEnd = &t.z[t.n]; ++ return p; + } + +- /* This routine constructs a binary expression node out of two ExprSpan +- ** objects and uses the result to populate a new ExprSpan object. +- */ +- static void spanBinaryExpr( +- Parse *pParse, /* The parsing context. Errors accumulate here */ +- int op, /* The binary operation */ +- ExprSpan *pLeft, /* The left operand, and output */ +- ExprSpan *pRight /* The right operand */ +- ){ +- pLeft->pExpr = sqlite3PExpr(pParse, op, pLeft->pExpr, pRight->pExpr); +- pLeft->zEnd = pRight->zEnd; +- } + +- /* If doNot is true, then add a TK_NOT Expr-node wrapper around the +- ** outside of *ppExpr. +- */ +- static void exprNot(Parse *pParse, int doNot, ExprSpan *pSpan){ +- if( doNot ){ +- pSpan->pExpr = sqlite3PExpr(pParse, TK_NOT, pSpan->pExpr, 0); +- } +- } +- +- /* Construct an expression node for a unary postfix operator +- */ +- static void spanUnaryPostfix( +- Parse *pParse, /* Parsing context to record errors */ +- int op, /* The operator */ +- ExprSpan *pOperand, /* The operand, and output */ +- Token *pPostOp /* The operand token for setting the span */ +- ){ +- pOperand->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0); +- pOperand->zEnd = &pPostOp->z[pPostOp->n]; +- } +- + /* A routine to convert a binary TK_IS or TK_ISNOT expression into a + ** unary TK_ISNULL or TK_NOTNULL expression. */ + static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){ + sqlite3 *db = pParse->db; +- if( pA && pY && pY->op==TK_NULL ){ ++ if( pA && pY && pY->op==TK_NULL && !IN_RENAME_OBJECT ){ + pA->op = (u8)op; + sqlite3ExprDelete(db, pA->pRight); + pA->pRight = 0; +@@ -136732,20 +146964,6 @@ + } + } + +- /* Construct an expression node for a unary prefix operator +- */ +- static void spanUnaryPrefix( +- ExprSpan *pOut, /* Write the new expression node here */ +- Parse *pParse, /* Parsing context to record errors */ +- int op, /* The operator */ +- ExprSpan *pOperand, /* The operand */ +- Token *pPreOp /* The operand token for setting the span */ +- ){ +- pOut->zStart = pPreOp->z; +- pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0); +- pOut->zEnd = pOperand->zEnd; +- } +- + /* Add a single new term to an ExprList that is used to store a + ** list of identifiers. Report an error if the ID list contains + ** a COLLATE clause or an ASC or DESC keyword, except ignore the +@@ -136808,64 +147026,78 @@ + ** zero the stack is dynamically sized using realloc() + ** sqlite3ParserARG_SDECL A static variable declaration for the %extra_argument + ** sqlite3ParserARG_PDECL A parameter declaration for the %extra_argument ++** sqlite3ParserARG_PARAM Code to pass %extra_argument as a subroutine parameter + ** sqlite3ParserARG_STORE Code to store %extra_argument into yypParser + ** sqlite3ParserARG_FETCH Code to extract %extra_argument from yypParser ++** sqlite3ParserCTX_* As sqlite3ParserARG_ except for %extra_context + ** YYERRORSYMBOL is the code number of the error symbol. If not + ** defined, then do no error processing. + ** YYNSTATE the combined number of states. + ** YYNRULE the number of rules in the grammar ++** YYNTOKEN Number of terminal symbols + ** YY_MAX_SHIFT Maximum value for shift actions + ** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions + ** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions +-** YY_MIN_REDUCE Maximum value for reduce actions + ** YY_ERROR_ACTION The yy_action[] code for syntax error + ** YY_ACCEPT_ACTION The yy_action[] code for accept + ** YY_NO_ACTION The yy_action[] code for no-op ++** YY_MIN_REDUCE Minimum value for reduce actions ++** YY_MAX_REDUCE Maximum value for reduce actions + */ + #ifndef INTERFACE + # define INTERFACE 1 + #endif + /************* Begin control #defines *****************************************/ +-#define YYCODETYPE unsigned char +-#define YYNOCODE 252 ++#define YYCODETYPE unsigned short int ++#define YYNOCODE 277 + #define YYACTIONTYPE unsigned short int +-#define YYWILDCARD 69 ++#define YYWILDCARD 91 + #define sqlite3ParserTOKENTYPE Token + typedef union { + int yyinit; + sqlite3ParserTOKENTYPE yy0; +- Expr* yy72; +- TriggerStep* yy145; +- ExprList* yy148; +- SrcList* yy185; +- ExprSpan yy190; +- int yy194; +- Select* yy243; +- IdList* yy254; +- With* yy285; +- struct TrigEvent yy332; +- struct LimitVal yy354; +- struct {int value; int mask;} yy497; ++ Expr* yy18; ++ struct TrigEvent yy34; ++ IdList* yy48; ++ int yy70; ++ struct {int value; int mask;} yy111; ++ struct FrameBound yy119; ++ SrcList* yy135; ++ TriggerStep* yy207; ++ Window* yy327; ++ Upsert* yy340; ++ const char* yy392; ++ ExprList* yy420; ++ With* yy449; ++ Select* yy489; + } YYMINORTYPE; + #ifndef YYSTACKDEPTH + #define YYSTACKDEPTH 100 + #endif +-#define sqlite3ParserARG_SDECL Parse *pParse; +-#define sqlite3ParserARG_PDECL ,Parse *pParse +-#define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse +-#define sqlite3ParserARG_STORE yypParser->pParse = pParse ++#define sqlite3ParserARG_SDECL ++#define sqlite3ParserARG_PDECL ++#define sqlite3ParserARG_PARAM ++#define sqlite3ParserARG_FETCH ++#define sqlite3ParserARG_STORE ++#define sqlite3ParserCTX_SDECL Parse *pParse; ++#define sqlite3ParserCTX_PDECL ,Parse *pParse ++#define sqlite3ParserCTX_PARAM ,pParse ++#define sqlite3ParserCTX_FETCH Parse *pParse=yypParser->pParse; ++#define sqlite3ParserCTX_STORE yypParser->pParse=pParse; + #define YYFALLBACK 1 +-#define YYNSTATE 455 +-#define YYNRULE 329 +-#define YY_MAX_SHIFT 454 +-#define YY_MIN_SHIFTREDUCE 664 +-#define YY_MAX_SHIFTREDUCE 992 +-#define YY_MIN_REDUCE 993 +-#define YY_MAX_REDUCE 1321 +-#define YY_ERROR_ACTION 1322 +-#define YY_ACCEPT_ACTION 1323 +-#define YY_NO_ACTION 1324 ++#define YYNSTATE 521 ++#define YYNRULE 367 ++#define YYNTOKEN 155 ++#define YY_MAX_SHIFT 520 ++#define YY_MIN_SHIFTREDUCE 756 ++#define YY_MAX_SHIFTREDUCE 1122 ++#define YY_ERROR_ACTION 1123 ++#define YY_ACCEPT_ACTION 1124 ++#define YY_NO_ACTION 1125 ++#define YY_MIN_REDUCE 1126 ++#define YY_MAX_REDUCE 1492 + /************* End control #defines *******************************************/ ++#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) + + /* Define the yytestcase() macro to be a no-op if is not already defined + ** otherwise. +@@ -136894,9 +147126,6 @@ + ** N between YY_MIN_SHIFTREDUCE Shift to an arbitrary state then + ** and YY_MAX_SHIFTREDUCE reduce by rule N-YY_MIN_SHIFTREDUCE. + ** +-** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE +-** and YY_MAX_REDUCE +-** + ** N == YY_ERROR_ACTION A syntax error has occurred. + ** + ** N == YY_ACCEPT_ACTION The parser accepts its input. +@@ -136904,6 +147133,9 @@ + ** N == YY_NO_ACTION No such action. Denotes unused + ** slots in the yy_action[] table. + ** ++** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE ++** and YY_MAX_REDUCE ++** + ** The action table is constructed as a single large table named yy_action[]. + ** Given state S and lookahead X, the action is computed as either: + ** +@@ -136910,19 +147142,13 @@ + ** (A) N = yy_action[ yy_shift_ofst[S] + X ] + ** (B) N = yy_default[S] + ** +-** The (A) formula is preferred. The B formula is used instead if: +-** (1) The yy_shift_ofst[S]+X value is out of range, or +-** (2) yy_lookahead[yy_shift_ofst[S]+X] is not equal to X, or +-** (3) yy_shift_ofst[S] equal YY_SHIFT_USE_DFLT. +-** (Implementation note: YY_SHIFT_USE_DFLT is chosen so that +-** YY_SHIFT_USE_DFLT+X will be out of range for all possible lookaheads X. +-** Hence only tests (1) and (2) need to be evaluated.) ++** The (A) formula is preferred. The B formula is used instead if ++** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X. + ** + ** The formulas above are for computing the action when the lookahead is + ** a terminal symbol. If the lookahead is a non-terminal (as occurs after + ** a reduce action) then the yy_reduce_ofst[] array is used in place of +-** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of +-** YY_SHIFT_USE_DFLT. ++** the yy_shift_ofst[] array. + ** + ** The following are the tables generated in this section: + ** +@@ -136936,463 +147162,568 @@ + ** yy_default[] Default action for each state. + ** + *********** Begin parsing tables **********************************************/ +-#define YY_ACTTAB_COUNT (1565) ++#define YY_ACTTAB_COUNT (2009) + static const YYACTIONTYPE yy_action[] = { +- /* 0 */ 324, 410, 342, 747, 747, 203, 939, 353, 969, 98, +- /* 10 */ 98, 98, 98, 91, 96, 96, 96, 96, 95, 95, +- /* 20 */ 94, 94, 94, 93, 350, 1323, 155, 155, 2, 808, +- /* 30 */ 971, 971, 98, 98, 98, 98, 20, 96, 96, 96, +- /* 40 */ 96, 95, 95, 94, 94, 94, 93, 350, 92, 89, +- /* 50 */ 178, 99, 100, 90, 847, 850, 839, 839, 97, 97, +- /* 60 */ 98, 98, 98, 98, 350, 96, 96, 96, 96, 95, +- /* 70 */ 95, 94, 94, 94, 93, 350, 324, 339, 969, 262, +- /* 80 */ 364, 251, 212, 169, 287, 404, 282, 403, 199, 786, +- /* 90 */ 242, 411, 21, 950, 378, 280, 93, 350, 787, 95, +- /* 100 */ 95, 94, 94, 94, 93, 350, 971, 971, 96, 96, +- /* 110 */ 96, 96, 95, 95, 94, 94, 94, 93, 350, 808, +- /* 120 */ 328, 242, 411, 1235, 826, 1235, 132, 99, 100, 90, +- /* 130 */ 847, 850, 839, 839, 97, 97, 98, 98, 98, 98, +- /* 140 */ 449, 96, 96, 96, 96, 95, 95, 94, 94, 94, +- /* 150 */ 93, 350, 324, 819, 348, 347, 120, 818, 120, 75, +- /* 160 */ 52, 52, 950, 951, 952, 1084, 977, 146, 360, 262, +- /* 170 */ 369, 261, 950, 975, 954, 976, 92, 89, 178, 370, +- /* 180 */ 230, 370, 971, 971, 1141, 360, 359, 101, 818, 818, +- /* 190 */ 820, 383, 24, 1286, 380, 427, 412, 368, 978, 379, +- /* 200 */ 978, 1032, 324, 99, 100, 90, 847, 850, 839, 839, +- /* 210 */ 97, 97, 98, 98, 98, 98, 372, 96, 96, 96, +- /* 220 */ 96, 95, 95, 94, 94, 94, 93, 350, 950, 132, +- /* 230 */ 890, 449, 971, 971, 890, 60, 94, 94, 94, 93, +- /* 240 */ 350, 950, 951, 952, 954, 103, 360, 950, 384, 333, +- /* 250 */ 697, 52, 52, 99, 100, 90, 847, 850, 839, 839, +- /* 260 */ 97, 97, 98, 98, 98, 98, 1022, 96, 96, 96, +- /* 270 */ 96, 95, 95, 94, 94, 94, 93, 350, 324, 454, +- /* 280 */ 995, 449, 227, 61, 157, 243, 343, 114, 1025, 1211, +- /* 290 */ 147, 826, 950, 372, 1071, 950, 319, 950, 951, 952, +- /* 300 */ 194, 10, 10, 401, 398, 397, 1211, 1213, 971, 971, +- /* 310 */ 757, 171, 170, 157, 396, 336, 950, 951, 952, 697, +- /* 320 */ 819, 310, 153, 950, 818, 320, 82, 23, 80, 99, +- /* 330 */ 100, 90, 847, 850, 839, 839, 97, 97, 98, 98, +- /* 340 */ 98, 98, 888, 96, 96, 96, 96, 95, 95, 94, +- /* 350 */ 94, 94, 93, 350, 324, 818, 818, 820, 277, 231, +- /* 360 */ 300, 950, 951, 952, 950, 951, 952, 1211, 194, 25, +- /* 370 */ 449, 401, 398, 397, 950, 354, 300, 449, 950, 74, +- /* 380 */ 449, 1, 396, 132, 971, 971, 950, 224, 224, 808, +- /* 390 */ 10, 10, 950, 951, 952, 1290, 132, 52, 52, 414, +- /* 400 */ 52, 52, 1063, 1063, 338, 99, 100, 90, 847, 850, +- /* 410 */ 839, 839, 97, 97, 98, 98, 98, 98, 1114, 96, +- /* 420 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 350, +- /* 430 */ 324, 1113, 427, 417, 701, 427, 426, 1260, 1260, 262, +- /* 440 */ 369, 261, 950, 950, 951, 952, 752, 950, 951, 952, +- /* 450 */ 449, 751, 449, 1058, 1037, 950, 951, 952, 442, 706, +- /* 460 */ 971, 971, 1058, 393, 92, 89, 178, 446, 446, 446, +- /* 470 */ 51, 51, 52, 52, 438, 773, 1024, 92, 89, 178, +- /* 480 */ 172, 99, 100, 90, 847, 850, 839, 839, 97, 97, +- /* 490 */ 98, 98, 98, 98, 198, 96, 96, 96, 96, 95, +- /* 500 */ 95, 94, 94, 94, 93, 350, 324, 427, 407, 909, +- /* 510 */ 694, 950, 951, 952, 92, 89, 178, 224, 224, 157, +- /* 520 */ 241, 221, 418, 299, 771, 910, 415, 374, 449, 414, +- /* 530 */ 58, 323, 1061, 1061, 1242, 378, 971, 971, 378, 772, +- /* 540 */ 448, 911, 362, 735, 296, 681, 9, 9, 52, 52, +- /* 550 */ 234, 329, 234, 256, 416, 736, 280, 99, 100, 90, +- /* 560 */ 847, 850, 839, 839, 97, 97, 98, 98, 98, 98, +- /* 570 */ 449, 96, 96, 96, 96, 95, 95, 94, 94, 94, +- /* 580 */ 93, 350, 324, 422, 72, 449, 827, 120, 367, 449, +- /* 590 */ 10, 10, 5, 301, 203, 449, 177, 969, 253, 419, +- /* 600 */ 255, 771, 200, 175, 233, 10, 10, 836, 836, 36, +- /* 610 */ 36, 1289, 971, 971, 724, 37, 37, 348, 347, 424, +- /* 620 */ 203, 260, 771, 969, 232, 930, 1316, 870, 337, 1316, +- /* 630 */ 421, 848, 851, 99, 100, 90, 847, 850, 839, 839, +- /* 640 */ 97, 97, 98, 98, 98, 98, 268, 96, 96, 96, +- /* 650 */ 96, 95, 95, 94, 94, 94, 93, 350, 324, 840, +- /* 660 */ 449, 978, 813, 978, 1200, 449, 909, 969, 715, 349, +- /* 670 */ 349, 349, 928, 177, 449, 930, 1317, 254, 198, 1317, +- /* 680 */ 12, 12, 910, 402, 449, 27, 27, 250, 971, 971, +- /* 690 */ 118, 716, 162, 969, 38, 38, 268, 176, 911, 771, +- /* 700 */ 432, 1265, 939, 353, 39, 39, 316, 991, 324, 99, +- /* 710 */ 100, 90, 847, 850, 839, 839, 97, 97, 98, 98, +- /* 720 */ 98, 98, 928, 96, 96, 96, 96, 95, 95, 94, +- /* 730 */ 94, 94, 93, 350, 449, 329, 449, 357, 971, 971, +- /* 740 */ 1041, 316, 929, 340, 893, 893, 386, 669, 670, 671, +- /* 750 */ 275, 1318, 317, 992, 40, 40, 41, 41, 268, 99, +- /* 760 */ 100, 90, 847, 850, 839, 839, 97, 97, 98, 98, +- /* 770 */ 98, 98, 449, 96, 96, 96, 96, 95, 95, 94, +- /* 780 */ 94, 94, 93, 350, 324, 449, 355, 449, 992, 449, +- /* 790 */ 1016, 330, 42, 42, 786, 270, 449, 273, 449, 228, +- /* 800 */ 449, 298, 449, 787, 449, 28, 28, 29, 29, 31, +- /* 810 */ 31, 449, 1141, 449, 971, 971, 43, 43, 44, 44, +- /* 820 */ 45, 45, 11, 11, 46, 46, 887, 78, 887, 268, +- /* 830 */ 268, 105, 105, 47, 47, 99, 100, 90, 847, 850, +- /* 840 */ 839, 839, 97, 97, 98, 98, 98, 98, 449, 96, +- /* 850 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 350, +- /* 860 */ 324, 449, 117, 449, 1073, 158, 449, 691, 48, 48, +- /* 870 */ 229, 1241, 449, 1250, 449, 414, 449, 334, 449, 245, +- /* 880 */ 449, 33, 33, 49, 49, 449, 50, 50, 246, 1141, +- /* 890 */ 971, 971, 34, 34, 122, 122, 123, 123, 124, 124, +- /* 900 */ 56, 56, 268, 81, 249, 35, 35, 197, 196, 195, +- /* 910 */ 324, 99, 100, 90, 847, 850, 839, 839, 97, 97, +- /* 920 */ 98, 98, 98, 98, 449, 96, 96, 96, 96, 95, +- /* 930 */ 95, 94, 94, 94, 93, 350, 449, 691, 449, 1141, +- /* 940 */ 971, 971, 968, 1207, 106, 106, 268, 1209, 268, 1266, +- /* 950 */ 2, 886, 268, 886, 335, 1040, 53, 53, 107, 107, +- /* 960 */ 324, 99, 100, 90, 847, 850, 839, 839, 97, 97, +- /* 970 */ 98, 98, 98, 98, 449, 96, 96, 96, 96, 95, +- /* 980 */ 95, 94, 94, 94, 93, 350, 449, 1070, 449, 1066, +- /* 990 */ 971, 971, 1039, 267, 108, 108, 445, 330, 331, 133, +- /* 1000 */ 223, 175, 301, 225, 385, 1255, 104, 104, 121, 121, +- /* 1010 */ 324, 99, 88, 90, 847, 850, 839, 839, 97, 97, +- /* 1020 */ 98, 98, 98, 98, 1141, 96, 96, 96, 96, 95, +- /* 1030 */ 95, 94, 94, 94, 93, 350, 449, 346, 449, 167, +- /* 1040 */ 971, 971, 925, 810, 371, 318, 202, 202, 373, 263, +- /* 1050 */ 394, 202, 74, 208, 721, 722, 119, 119, 112, 112, +- /* 1060 */ 324, 406, 100, 90, 847, 850, 839, 839, 97, 97, +- /* 1070 */ 98, 98, 98, 98, 449, 96, 96, 96, 96, 95, +- /* 1080 */ 95, 94, 94, 94, 93, 350, 449, 752, 449, 344, +- /* 1090 */ 971, 971, 751, 278, 111, 111, 74, 714, 713, 704, +- /* 1100 */ 286, 877, 749, 1279, 257, 77, 109, 109, 110, 110, +- /* 1110 */ 1230, 285, 1134, 90, 847, 850, 839, 839, 97, 97, +- /* 1120 */ 98, 98, 98, 98, 1233, 96, 96, 96, 96, 95, +- /* 1130 */ 95, 94, 94, 94, 93, 350, 86, 444, 449, 3, +- /* 1140 */ 1193, 449, 1069, 132, 351, 120, 1013, 86, 444, 780, +- /* 1150 */ 3, 1091, 202, 376, 447, 351, 1229, 120, 55, 55, +- /* 1160 */ 449, 57, 57, 822, 873, 447, 449, 208, 449, 704, +- /* 1170 */ 449, 877, 237, 433, 435, 120, 439, 428, 361, 120, +- /* 1180 */ 54, 54, 132, 449, 433, 826, 52, 52, 26, 26, +- /* 1190 */ 30, 30, 381, 132, 408, 443, 826, 689, 264, 389, +- /* 1200 */ 116, 269, 272, 32, 32, 83, 84, 120, 274, 120, +- /* 1210 */ 120, 276, 85, 351, 451, 450, 83, 84, 818, 1054, +- /* 1220 */ 1038, 427, 429, 85, 351, 451, 450, 120, 120, 818, +- /* 1230 */ 377, 218, 281, 822, 1107, 1140, 86, 444, 409, 3, +- /* 1240 */ 1087, 1098, 430, 431, 351, 302, 303, 1146, 1021, 818, +- /* 1250 */ 818, 820, 821, 19, 447, 1015, 1004, 1003, 1005, 1273, +- /* 1260 */ 818, 818, 820, 821, 19, 289, 159, 291, 293, 7, +- /* 1270 */ 315, 173, 259, 433, 1129, 363, 252, 1232, 375, 1037, +- /* 1280 */ 295, 434, 168, 986, 399, 826, 284, 1204, 1203, 205, +- /* 1290 */ 1276, 308, 1249, 86, 444, 983, 3, 1247, 332, 144, +- /* 1300 */ 130, 351, 72, 135, 59, 83, 84, 756, 137, 365, +- /* 1310 */ 1126, 447, 85, 351, 451, 450, 139, 226, 818, 140, +- /* 1320 */ 156, 62, 314, 314, 313, 215, 311, 366, 392, 678, +- /* 1330 */ 433, 185, 141, 1234, 142, 160, 148, 1136, 1198, 382, +- /* 1340 */ 189, 67, 826, 180, 388, 248, 1218, 1099, 219, 818, +- /* 1350 */ 818, 820, 821, 19, 247, 190, 266, 154, 390, 271, +- /* 1360 */ 191, 192, 83, 84, 1006, 405, 1057, 182, 321, 85, +- /* 1370 */ 351, 451, 450, 1056, 183, 818, 341, 132, 181, 706, +- /* 1380 */ 1055, 420, 76, 444, 1029, 3, 322, 1028, 283, 1048, +- /* 1390 */ 351, 1095, 1027, 1288, 1047, 71, 204, 6, 288, 290, +- /* 1400 */ 447, 1096, 1094, 1093, 79, 292, 818, 818, 820, 821, +- /* 1410 */ 19, 294, 297, 437, 345, 441, 102, 1184, 1077, 433, +- /* 1420 */ 238, 425, 73, 305, 239, 304, 325, 240, 423, 306, +- /* 1430 */ 307, 826, 213, 1012, 22, 945, 452, 214, 216, 217, +- /* 1440 */ 453, 1001, 115, 996, 125, 126, 235, 127, 665, 352, +- /* 1450 */ 326, 83, 84, 358, 166, 244, 179, 327, 85, 351, +- /* 1460 */ 451, 450, 134, 356, 818, 113, 885, 806, 883, 136, +- /* 1470 */ 128, 138, 738, 258, 184, 899, 143, 145, 63, 64, +- /* 1480 */ 65, 66, 129, 902, 187, 186, 898, 8, 13, 188, +- /* 1490 */ 265, 891, 149, 202, 980, 818, 818, 820, 821, 19, +- /* 1500 */ 150, 387, 161, 680, 285, 391, 151, 395, 400, 193, +- /* 1510 */ 68, 14, 236, 279, 15, 69, 717, 825, 131, 824, +- /* 1520 */ 853, 70, 746, 16, 413, 750, 4, 174, 220, 222, +- /* 1530 */ 152, 779, 857, 774, 201, 77, 74, 868, 17, 854, +- /* 1540 */ 852, 908, 18, 907, 207, 206, 934, 163, 436, 210, +- /* 1550 */ 935, 164, 209, 165, 440, 856, 823, 690, 87, 211, +- /* 1560 */ 309, 312, 1281, 940, 1280, ++ /* 0 */ 368, 105, 102, 197, 105, 102, 197, 515, 1124, 1, ++ /* 10 */ 1, 520, 2, 1128, 515, 1192, 1171, 1456, 275, 370, ++ /* 20 */ 127, 1389, 1197, 1197, 1192, 1166, 178, 1205, 64, 64, ++ /* 30 */ 477, 887, 322, 428, 348, 37, 37, 808, 362, 888, ++ /* 40 */ 509, 509, 509, 112, 113, 103, 1100, 1100, 953, 956, ++ /* 50 */ 946, 946, 110, 110, 111, 111, 111, 111, 365, 252, ++ /* 60 */ 252, 515, 252, 252, 497, 515, 309, 515, 459, 515, ++ /* 70 */ 1079, 491, 512, 478, 6, 512, 809, 134, 498, 228, ++ /* 80 */ 194, 428, 37, 37, 515, 208, 64, 64, 64, 64, ++ /* 90 */ 13, 13, 109, 109, 109, 109, 108, 108, 107, 107, ++ /* 100 */ 107, 106, 401, 258, 381, 13, 13, 398, 397, 428, ++ /* 110 */ 252, 252, 370, 476, 405, 1104, 1079, 1080, 1081, 386, ++ /* 120 */ 1106, 390, 497, 512, 497, 1423, 1419, 304, 1105, 307, ++ /* 130 */ 1256, 496, 370, 499, 16, 16, 112, 113, 103, 1100, ++ /* 140 */ 1100, 953, 956, 946, 946, 110, 110, 111, 111, 111, ++ /* 150 */ 111, 262, 1107, 495, 1107, 401, 112, 113, 103, 1100, ++ /* 160 */ 1100, 953, 956, 946, 946, 110, 110, 111, 111, 111, ++ /* 170 */ 111, 129, 1425, 343, 1420, 339, 1059, 492, 1057, 263, ++ /* 180 */ 73, 105, 102, 197, 994, 109, 109, 109, 109, 108, ++ /* 190 */ 108, 107, 107, 107, 106, 401, 370, 111, 111, 111, ++ /* 200 */ 111, 104, 492, 89, 1432, 109, 109, 109, 109, 108, ++ /* 210 */ 108, 107, 107, 107, 106, 401, 111, 111, 111, 111, ++ /* 220 */ 112, 113, 103, 1100, 1100, 953, 956, 946, 946, 110, ++ /* 230 */ 110, 111, 111, 111, 111, 109, 109, 109, 109, 108, ++ /* 240 */ 108, 107, 107, 107, 106, 401, 114, 108, 108, 107, ++ /* 250 */ 107, 107, 106, 401, 109, 109, 109, 109, 108, 108, ++ /* 260 */ 107, 107, 107, 106, 401, 152, 399, 399, 399, 109, ++ /* 270 */ 109, 109, 109, 108, 108, 107, 107, 107, 106, 401, ++ /* 280 */ 178, 493, 1412, 434, 1037, 1486, 1079, 515, 1486, 370, ++ /* 290 */ 421, 297, 357, 412, 74, 1079, 109, 109, 109, 109, ++ /* 300 */ 108, 108, 107, 107, 107, 106, 401, 1413, 37, 37, ++ /* 310 */ 1431, 274, 506, 112, 113, 103, 1100, 1100, 953, 956, ++ /* 320 */ 946, 946, 110, 110, 111, 111, 111, 111, 1436, 520, ++ /* 330 */ 2, 1128, 1079, 1080, 1081, 430, 275, 1079, 127, 366, ++ /* 340 */ 933, 1079, 1080, 1081, 220, 1205, 913, 458, 455, 454, ++ /* 350 */ 392, 167, 515, 1035, 152, 445, 924, 453, 152, 874, ++ /* 360 */ 923, 289, 109, 109, 109, 109, 108, 108, 107, 107, ++ /* 370 */ 107, 106, 401, 13, 13, 261, 853, 252, 252, 227, ++ /* 380 */ 106, 401, 370, 1079, 1080, 1081, 311, 388, 1079, 296, ++ /* 390 */ 512, 923, 923, 925, 231, 323, 1255, 1388, 1423, 490, ++ /* 400 */ 274, 506, 12, 208, 274, 506, 112, 113, 103, 1100, ++ /* 410 */ 1100, 953, 956, 946, 946, 110, 110, 111, 111, 111, ++ /* 420 */ 111, 1440, 286, 1128, 288, 1079, 1097, 247, 275, 1098, ++ /* 430 */ 127, 387, 405, 389, 1079, 1080, 1081, 1205, 159, 238, ++ /* 440 */ 255, 321, 461, 316, 460, 225, 790, 105, 102, 197, ++ /* 450 */ 513, 314, 842, 842, 445, 109, 109, 109, 109, 108, ++ /* 460 */ 108, 107, 107, 107, 106, 401, 515, 514, 515, 252, ++ /* 470 */ 252, 1079, 1080, 1081, 435, 370, 1098, 933, 1460, 794, ++ /* 480 */ 274, 506, 512, 105, 102, 197, 336, 63, 63, 64, ++ /* 490 */ 64, 27, 790, 924, 287, 208, 1354, 923, 515, 112, ++ /* 500 */ 113, 103, 1100, 1100, 953, 956, 946, 946, 110, 110, ++ /* 510 */ 111, 111, 111, 111, 107, 107, 107, 106, 401, 49, ++ /* 520 */ 49, 515, 28, 1079, 405, 497, 421, 297, 923, 923, ++ /* 530 */ 925, 186, 468, 1079, 467, 999, 999, 442, 515, 1079, ++ /* 540 */ 334, 515, 45, 45, 1083, 342, 173, 168, 109, 109, ++ /* 550 */ 109, 109, 108, 108, 107, 107, 107, 106, 401, 13, ++ /* 560 */ 13, 205, 13, 13, 252, 252, 1195, 1195, 370, 1079, ++ /* 570 */ 1080, 1081, 787, 265, 5, 359, 494, 512, 469, 1079, ++ /* 580 */ 1080, 1081, 398, 397, 1079, 1079, 1080, 1081, 3, 282, ++ /* 590 */ 1079, 1083, 112, 113, 103, 1100, 1100, 953, 956, 946, ++ /* 600 */ 946, 110, 110, 111, 111, 111, 111, 252, 252, 1015, ++ /* 610 */ 220, 1079, 873, 458, 455, 454, 943, 943, 954, 957, ++ /* 620 */ 512, 252, 252, 453, 1016, 1079, 445, 1107, 1209, 1107, ++ /* 630 */ 1079, 1080, 1081, 515, 512, 426, 1079, 1080, 1081, 1017, ++ /* 640 */ 512, 109, 109, 109, 109, 108, 108, 107, 107, 107, ++ /* 650 */ 106, 401, 1052, 515, 50, 50, 515, 1079, 1080, 1081, ++ /* 660 */ 828, 370, 1051, 379, 411, 1064, 1358, 207, 408, 773, ++ /* 670 */ 829, 1079, 1080, 1081, 64, 64, 322, 64, 64, 1302, ++ /* 680 */ 947, 411, 410, 1358, 1360, 112, 113, 103, 1100, 1100, ++ /* 690 */ 953, 956, 946, 946, 110, 110, 111, 111, 111, 111, ++ /* 700 */ 294, 482, 515, 1037, 1487, 515, 434, 1487, 354, 1120, ++ /* 710 */ 483, 996, 913, 485, 466, 996, 132, 178, 33, 450, ++ /* 720 */ 1203, 136, 406, 64, 64, 479, 64, 64, 419, 369, ++ /* 730 */ 283, 1146, 252, 252, 109, 109, 109, 109, 108, 108, ++ /* 740 */ 107, 107, 107, 106, 401, 512, 224, 440, 411, 266, ++ /* 750 */ 1358, 266, 252, 252, 370, 296, 416, 284, 934, 396, ++ /* 760 */ 976, 470, 400, 252, 252, 512, 9, 473, 231, 500, ++ /* 770 */ 354, 1036, 1035, 1488, 355, 374, 512, 1121, 112, 113, ++ /* 780 */ 103, 1100, 1100, 953, 956, 946, 946, 110, 110, 111, ++ /* 790 */ 111, 111, 111, 252, 252, 1015, 515, 1347, 295, 252, ++ /* 800 */ 252, 252, 252, 1098, 375, 249, 512, 445, 872, 322, ++ /* 810 */ 1016, 480, 512, 195, 512, 434, 273, 15, 15, 515, ++ /* 820 */ 314, 515, 95, 515, 93, 1017, 367, 109, 109, 109, ++ /* 830 */ 109, 108, 108, 107, 107, 107, 106, 401, 515, 1121, ++ /* 840 */ 39, 39, 51, 51, 52, 52, 503, 370, 515, 1204, ++ /* 850 */ 1098, 918, 439, 341, 133, 436, 223, 222, 221, 53, ++ /* 860 */ 53, 322, 1400, 761, 762, 763, 515, 370, 88, 54, ++ /* 870 */ 54, 112, 113, 103, 1100, 1100, 953, 956, 946, 946, ++ /* 880 */ 110, 110, 111, 111, 111, 111, 407, 55, 55, 196, ++ /* 890 */ 515, 112, 113, 103, 1100, 1100, 953, 956, 946, 946, ++ /* 900 */ 110, 110, 111, 111, 111, 111, 135, 264, 1149, 376, ++ /* 910 */ 515, 40, 40, 515, 872, 515, 993, 515, 993, 116, ++ /* 920 */ 109, 109, 109, 109, 108, 108, 107, 107, 107, 106, ++ /* 930 */ 401, 41, 41, 515, 43, 43, 44, 44, 56, 56, ++ /* 940 */ 109, 109, 109, 109, 108, 108, 107, 107, 107, 106, ++ /* 950 */ 401, 515, 379, 515, 57, 57, 515, 799, 515, 379, ++ /* 960 */ 515, 445, 200, 515, 323, 515, 1397, 515, 1459, 515, ++ /* 970 */ 1287, 817, 58, 58, 14, 14, 515, 59, 59, 118, ++ /* 980 */ 118, 60, 60, 515, 46, 46, 61, 61, 62, 62, ++ /* 990 */ 47, 47, 515, 190, 189, 91, 515, 140, 140, 515, ++ /* 1000 */ 394, 515, 277, 1200, 141, 141, 515, 1115, 515, 992, ++ /* 1010 */ 515, 992, 515, 69, 69, 370, 278, 48, 48, 259, ++ /* 1020 */ 65, 65, 119, 119, 246, 246, 260, 66, 66, 120, ++ /* 1030 */ 120, 121, 121, 117, 117, 370, 515, 512, 383, 112, ++ /* 1040 */ 113, 103, 1100, 1100, 953, 956, 946, 946, 110, 110, ++ /* 1050 */ 111, 111, 111, 111, 515, 872, 515, 139, 139, 112, ++ /* 1060 */ 113, 103, 1100, 1100, 953, 956, 946, 946, 110, 110, ++ /* 1070 */ 111, 111, 111, 111, 1287, 138, 138, 125, 125, 515, ++ /* 1080 */ 12, 515, 281, 1287, 515, 445, 131, 1287, 109, 109, ++ /* 1090 */ 109, 109, 108, 108, 107, 107, 107, 106, 401, 515, ++ /* 1100 */ 124, 124, 122, 122, 515, 123, 123, 515, 109, 109, ++ /* 1110 */ 109, 109, 108, 108, 107, 107, 107, 106, 401, 515, ++ /* 1120 */ 68, 68, 463, 783, 515, 70, 70, 302, 67, 67, ++ /* 1130 */ 1032, 253, 253, 356, 1287, 191, 196, 1433, 465, 1301, ++ /* 1140 */ 38, 38, 384, 94, 512, 42, 42, 177, 848, 274, ++ /* 1150 */ 506, 385, 420, 847, 1356, 441, 508, 376, 377, 153, ++ /* 1160 */ 423, 872, 432, 370, 224, 251, 194, 887, 182, 293, ++ /* 1170 */ 783, 848, 88, 254, 466, 888, 847, 915, 807, 806, ++ /* 1180 */ 230, 1241, 910, 370, 17, 413, 797, 112, 113, 103, ++ /* 1190 */ 1100, 1100, 953, 956, 946, 946, 110, 110, 111, 111, ++ /* 1200 */ 111, 111, 395, 814, 815, 1175, 983, 112, 101, 103, ++ /* 1210 */ 1100, 1100, 953, 956, 946, 946, 110, 110, 111, 111, ++ /* 1220 */ 111, 111, 375, 422, 427, 429, 298, 230, 230, 88, ++ /* 1230 */ 1240, 451, 312, 797, 226, 88, 109, 109, 109, 109, ++ /* 1240 */ 108, 108, 107, 107, 107, 106, 401, 86, 433, 979, ++ /* 1250 */ 927, 881, 226, 983, 230, 415, 109, 109, 109, 109, ++ /* 1260 */ 108, 108, 107, 107, 107, 106, 401, 320, 845, 781, ++ /* 1270 */ 846, 100, 130, 100, 1403, 290, 370, 319, 1377, 1376, ++ /* 1280 */ 437, 1449, 299, 1237, 303, 306, 308, 310, 1188, 1174, ++ /* 1290 */ 1173, 1172, 315, 324, 325, 1228, 370, 927, 1249, 271, ++ /* 1300 */ 1286, 113, 103, 1100, 1100, 953, 956, 946, 946, 110, ++ /* 1310 */ 110, 111, 111, 111, 111, 1224, 1235, 502, 501, 1292, ++ /* 1320 */ 1221, 1155, 103, 1100, 1100, 953, 956, 946, 946, 110, ++ /* 1330 */ 110, 111, 111, 111, 111, 1148, 1137, 1136, 1138, 1443, ++ /* 1340 */ 446, 244, 184, 98, 507, 188, 4, 353, 327, 109, ++ /* 1350 */ 109, 109, 109, 108, 108, 107, 107, 107, 106, 401, ++ /* 1360 */ 510, 329, 331, 199, 414, 456, 292, 285, 318, 109, ++ /* 1370 */ 109, 109, 109, 108, 108, 107, 107, 107, 106, 401, ++ /* 1380 */ 11, 1271, 1279, 402, 361, 192, 1171, 1351, 431, 505, ++ /* 1390 */ 346, 1350, 333, 98, 507, 504, 4, 187, 1446, 1115, ++ /* 1400 */ 233, 1396, 155, 1394, 1112, 152, 72, 75, 378, 425, ++ /* 1410 */ 510, 165, 149, 157, 933, 1276, 86, 30, 1268, 417, ++ /* 1420 */ 96, 96, 8, 160, 161, 162, 163, 97, 418, 402, ++ /* 1430 */ 517, 516, 449, 402, 923, 210, 358, 424, 1282, 438, ++ /* 1440 */ 169, 214, 360, 1345, 80, 504, 31, 444, 1365, 301, ++ /* 1450 */ 245, 274, 506, 216, 174, 305, 488, 447, 217, 462, ++ /* 1460 */ 1139, 487, 218, 363, 933, 923, 923, 925, 926, 24, ++ /* 1470 */ 96, 96, 1191, 1190, 1189, 391, 1182, 97, 1163, 402, ++ /* 1480 */ 517, 516, 799, 364, 923, 1162, 317, 1161, 98, 507, ++ /* 1490 */ 1181, 4, 1458, 472, 393, 269, 270, 475, 481, 1232, ++ /* 1500 */ 85, 1233, 326, 328, 232, 510, 495, 1231, 330, 98, ++ /* 1510 */ 507, 1230, 4, 486, 335, 923, 923, 925, 926, 24, ++ /* 1520 */ 1435, 1068, 404, 181, 336, 256, 510, 115, 402, 332, ++ /* 1530 */ 352, 352, 351, 241, 349, 1214, 1414, 770, 338, 10, ++ /* 1540 */ 504, 340, 272, 92, 1331, 1213, 87, 183, 484, 402, ++ /* 1550 */ 201, 488, 280, 239, 344, 345, 489, 1145, 29, 933, ++ /* 1560 */ 279, 504, 1074, 518, 240, 96, 96, 242, 243, 519, ++ /* 1570 */ 1134, 1129, 97, 154, 402, 517, 516, 372, 373, 923, ++ /* 1580 */ 933, 142, 143, 128, 1381, 267, 96, 96, 852, 757, ++ /* 1590 */ 203, 144, 403, 97, 1382, 402, 517, 516, 204, 1380, ++ /* 1600 */ 923, 146, 1379, 1159, 1158, 71, 1156, 276, 202, 185, ++ /* 1610 */ 923, 923, 925, 926, 24, 198, 257, 126, 991, 989, ++ /* 1620 */ 907, 98, 507, 156, 4, 145, 158, 206, 831, 209, ++ /* 1630 */ 291, 923, 923, 925, 926, 24, 1005, 911, 510, 164, ++ /* 1640 */ 147, 380, 371, 382, 166, 76, 77, 274, 506, 148, ++ /* 1650 */ 78, 79, 1008, 211, 212, 1004, 137, 213, 18, 300, ++ /* 1660 */ 230, 402, 997, 1109, 443, 215, 32, 170, 171, 772, ++ /* 1670 */ 409, 448, 319, 504, 219, 172, 452, 81, 19, 457, ++ /* 1680 */ 313, 20, 82, 268, 488, 150, 810, 179, 83, 487, ++ /* 1690 */ 464, 151, 933, 180, 959, 84, 1040, 34, 96, 96, ++ /* 1700 */ 471, 1041, 35, 474, 193, 97, 248, 402, 517, 516, ++ /* 1710 */ 1068, 404, 923, 250, 256, 880, 229, 175, 875, 352, ++ /* 1720 */ 352, 351, 241, 349, 100, 21, 770, 22, 1054, 1056, ++ /* 1730 */ 7, 98, 507, 1045, 4, 337, 1058, 23, 974, 201, ++ /* 1740 */ 176, 280, 88, 923, 923, 925, 926, 24, 510, 279, ++ /* 1750 */ 960, 958, 962, 1014, 963, 1013, 235, 234, 25, 36, ++ /* 1760 */ 99, 90, 507, 928, 4, 511, 350, 782, 26, 841, ++ /* 1770 */ 236, 402, 347, 1069, 237, 1125, 1125, 1451, 510, 203, ++ /* 1780 */ 1450, 1125, 1125, 504, 1125, 1125, 1125, 204, 1125, 1125, ++ /* 1790 */ 146, 1125, 1125, 1125, 1125, 1125, 1125, 202, 1125, 1125, ++ /* 1800 */ 1125, 402, 933, 1125, 1125, 1125, 1125, 1125, 96, 96, ++ /* 1810 */ 1125, 1125, 1125, 504, 1125, 97, 1125, 402, 517, 516, ++ /* 1820 */ 1125, 1125, 923, 1125, 1125, 1125, 1125, 1125, 1125, 1125, ++ /* 1830 */ 1125, 371, 933, 1125, 1125, 1125, 274, 506, 96, 96, ++ /* 1840 */ 1125, 1125, 1125, 1125, 1125, 97, 1125, 402, 517, 516, ++ /* 1850 */ 1125, 1125, 923, 923, 923, 925, 926, 24, 1125, 409, ++ /* 1860 */ 1125, 1125, 1125, 256, 1125, 1125, 1125, 1125, 352, 352, ++ /* 1870 */ 351, 241, 349, 1125, 1125, 770, 1125, 1125, 1125, 1125, ++ /* 1880 */ 1125, 1125, 1125, 923, 923, 925, 926, 24, 201, 1125, ++ /* 1890 */ 280, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 279, 1125, ++ /* 1900 */ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, ++ /* 1910 */ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, ++ /* 1920 */ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 203, 1125, ++ /* 1930 */ 1125, 1125, 1125, 1125, 1125, 1125, 204, 1125, 1125, 146, ++ /* 1940 */ 1125, 1125, 1125, 1125, 1125, 1125, 202, 1125, 1125, 1125, ++ /* 1950 */ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, ++ /* 1960 */ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, ++ /* 1970 */ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, ++ /* 1980 */ 371, 1125, 1125, 1125, 1125, 274, 506, 1125, 1125, 1125, ++ /* 1990 */ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, ++ /* 2000 */ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 409, + }; + static const YYCODETYPE yy_lookahead[] = { +- /* 0 */ 19, 115, 19, 117, 118, 24, 1, 2, 27, 79, +- /* 10 */ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, +- /* 20 */ 90, 91, 92, 93, 94, 144, 145, 146, 147, 58, +- /* 30 */ 49, 50, 79, 80, 81, 82, 22, 84, 85, 86, +- /* 40 */ 87, 88, 89, 90, 91, 92, 93, 94, 221, 222, +- /* 50 */ 223, 70, 71, 72, 73, 74, 75, 76, 77, 78, +- /* 60 */ 79, 80, 81, 82, 94, 84, 85, 86, 87, 88, +- /* 70 */ 89, 90, 91, 92, 93, 94, 19, 94, 97, 108, +- /* 80 */ 109, 110, 99, 100, 101, 102, 103, 104, 105, 32, +- /* 90 */ 119, 120, 78, 27, 152, 112, 93, 94, 41, 88, +- /* 100 */ 89, 90, 91, 92, 93, 94, 49, 50, 84, 85, +- /* 110 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 58, +- /* 120 */ 157, 119, 120, 163, 68, 163, 65, 70, 71, 72, +- /* 130 */ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, +- /* 140 */ 152, 84, 85, 86, 87, 88, 89, 90, 91, 92, +- /* 150 */ 93, 94, 19, 97, 88, 89, 196, 101, 196, 26, +- /* 160 */ 172, 173, 96, 97, 98, 210, 100, 22, 152, 108, +- /* 170 */ 109, 110, 27, 107, 27, 109, 221, 222, 223, 219, +- /* 180 */ 238, 219, 49, 50, 152, 169, 170, 54, 132, 133, +- /* 190 */ 134, 228, 232, 171, 231, 207, 208, 237, 132, 237, +- /* 200 */ 134, 179, 19, 70, 71, 72, 73, 74, 75, 76, +- /* 210 */ 77, 78, 79, 80, 81, 82, 152, 84, 85, 86, +- /* 220 */ 87, 88, 89, 90, 91, 92, 93, 94, 27, 65, +- /* 230 */ 30, 152, 49, 50, 34, 52, 90, 91, 92, 93, +- /* 240 */ 94, 96, 97, 98, 97, 22, 230, 27, 48, 217, +- /* 250 */ 27, 172, 173, 70, 71, 72, 73, 74, 75, 76, +- /* 260 */ 77, 78, 79, 80, 81, 82, 172, 84, 85, 86, +- /* 270 */ 87, 88, 89, 90, 91, 92, 93, 94, 19, 148, +- /* 280 */ 149, 152, 218, 24, 152, 154, 207, 156, 172, 152, +- /* 290 */ 22, 68, 27, 152, 163, 27, 164, 96, 97, 98, +- /* 300 */ 99, 172, 173, 102, 103, 104, 169, 170, 49, 50, +- /* 310 */ 90, 88, 89, 152, 113, 186, 96, 97, 98, 96, +- /* 320 */ 97, 160, 57, 27, 101, 164, 137, 196, 139, 70, +- /* 330 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, +- /* 340 */ 81, 82, 11, 84, 85, 86, 87, 88, 89, 90, +- /* 350 */ 91, 92, 93, 94, 19, 132, 133, 134, 23, 218, +- /* 360 */ 152, 96, 97, 98, 96, 97, 98, 230, 99, 22, +- /* 370 */ 152, 102, 103, 104, 27, 244, 152, 152, 27, 26, +- /* 380 */ 152, 22, 113, 65, 49, 50, 27, 194, 195, 58, +- /* 390 */ 172, 173, 96, 97, 98, 185, 65, 172, 173, 206, +- /* 400 */ 172, 173, 190, 191, 186, 70, 71, 72, 73, 74, +- /* 410 */ 75, 76, 77, 78, 79, 80, 81, 82, 175, 84, +- /* 420 */ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, +- /* 430 */ 19, 175, 207, 208, 23, 207, 208, 119, 120, 108, +- /* 440 */ 109, 110, 27, 96, 97, 98, 116, 96, 97, 98, +- /* 450 */ 152, 121, 152, 179, 180, 96, 97, 98, 250, 106, +- /* 460 */ 49, 50, 188, 19, 221, 222, 223, 168, 169, 170, +- /* 470 */ 172, 173, 172, 173, 250, 124, 172, 221, 222, 223, +- /* 480 */ 26, 70, 71, 72, 73, 74, 75, 76, 77, 78, +- /* 490 */ 79, 80, 81, 82, 50, 84, 85, 86, 87, 88, +- /* 500 */ 89, 90, 91, 92, 93, 94, 19, 207, 208, 12, +- /* 510 */ 23, 96, 97, 98, 221, 222, 223, 194, 195, 152, +- /* 520 */ 199, 23, 19, 225, 26, 28, 152, 152, 152, 206, +- /* 530 */ 209, 164, 190, 191, 241, 152, 49, 50, 152, 124, +- /* 540 */ 152, 44, 219, 46, 152, 21, 172, 173, 172, 173, +- /* 550 */ 183, 107, 185, 16, 163, 58, 112, 70, 71, 72, +- /* 560 */ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, +- /* 570 */ 152, 84, 85, 86, 87, 88, 89, 90, 91, 92, +- /* 580 */ 93, 94, 19, 207, 130, 152, 23, 196, 64, 152, +- /* 590 */ 172, 173, 22, 152, 24, 152, 98, 27, 61, 96, +- /* 600 */ 63, 26, 211, 212, 186, 172, 173, 49, 50, 172, +- /* 610 */ 173, 23, 49, 50, 26, 172, 173, 88, 89, 186, +- /* 620 */ 24, 238, 124, 27, 238, 22, 23, 103, 187, 26, +- /* 630 */ 152, 73, 74, 70, 71, 72, 73, 74, 75, 76, +- /* 640 */ 77, 78, 79, 80, 81, 82, 152, 84, 85, 86, +- /* 650 */ 87, 88, 89, 90, 91, 92, 93, 94, 19, 101, +- /* 660 */ 152, 132, 23, 134, 140, 152, 12, 97, 36, 168, +- /* 670 */ 169, 170, 69, 98, 152, 22, 23, 140, 50, 26, +- /* 680 */ 172, 173, 28, 51, 152, 172, 173, 193, 49, 50, +- /* 690 */ 22, 59, 24, 97, 172, 173, 152, 152, 44, 124, +- /* 700 */ 46, 0, 1, 2, 172, 173, 22, 23, 19, 70, +- /* 710 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, +- /* 720 */ 81, 82, 69, 84, 85, 86, 87, 88, 89, 90, +- /* 730 */ 91, 92, 93, 94, 152, 107, 152, 193, 49, 50, +- /* 740 */ 181, 22, 23, 111, 108, 109, 110, 7, 8, 9, +- /* 750 */ 16, 247, 248, 69, 172, 173, 172, 173, 152, 70, +- /* 760 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, +- /* 770 */ 81, 82, 152, 84, 85, 86, 87, 88, 89, 90, +- /* 780 */ 91, 92, 93, 94, 19, 152, 242, 152, 69, 152, +- /* 790 */ 166, 167, 172, 173, 32, 61, 152, 63, 152, 193, +- /* 800 */ 152, 152, 152, 41, 152, 172, 173, 172, 173, 172, +- /* 810 */ 173, 152, 152, 152, 49, 50, 172, 173, 172, 173, +- /* 820 */ 172, 173, 172, 173, 172, 173, 132, 138, 134, 152, +- /* 830 */ 152, 172, 173, 172, 173, 70, 71, 72, 73, 74, +- /* 840 */ 75, 76, 77, 78, 79, 80, 81, 82, 152, 84, +- /* 850 */ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, +- /* 860 */ 19, 152, 22, 152, 195, 24, 152, 27, 172, 173, +- /* 870 */ 193, 193, 152, 152, 152, 206, 152, 217, 152, 152, +- /* 880 */ 152, 172, 173, 172, 173, 152, 172, 173, 152, 152, +- /* 890 */ 49, 50, 172, 173, 172, 173, 172, 173, 172, 173, +- /* 900 */ 172, 173, 152, 138, 152, 172, 173, 108, 109, 110, +- /* 910 */ 19, 70, 71, 72, 73, 74, 75, 76, 77, 78, +- /* 920 */ 79, 80, 81, 82, 152, 84, 85, 86, 87, 88, +- /* 930 */ 89, 90, 91, 92, 93, 94, 152, 97, 152, 152, +- /* 940 */ 49, 50, 26, 193, 172, 173, 152, 152, 152, 146, +- /* 950 */ 147, 132, 152, 134, 217, 181, 172, 173, 172, 173, +- /* 960 */ 19, 70, 71, 72, 73, 74, 75, 76, 77, 78, +- /* 970 */ 79, 80, 81, 82, 152, 84, 85, 86, 87, 88, +- /* 980 */ 89, 90, 91, 92, 93, 94, 152, 193, 152, 193, +- /* 990 */ 49, 50, 181, 193, 172, 173, 166, 167, 245, 246, +- /* 1000 */ 211, 212, 152, 22, 217, 152, 172, 173, 172, 173, +- /* 1010 */ 19, 70, 71, 72, 73, 74, 75, 76, 77, 78, +- /* 1020 */ 79, 80, 81, 82, 152, 84, 85, 86, 87, 88, +- /* 1030 */ 89, 90, 91, 92, 93, 94, 152, 187, 152, 123, +- /* 1040 */ 49, 50, 23, 23, 23, 26, 26, 26, 23, 23, +- /* 1050 */ 23, 26, 26, 26, 7, 8, 172, 173, 172, 173, +- /* 1060 */ 19, 90, 71, 72, 73, 74, 75, 76, 77, 78, +- /* 1070 */ 79, 80, 81, 82, 152, 84, 85, 86, 87, 88, +- /* 1080 */ 89, 90, 91, 92, 93, 94, 152, 116, 152, 217, +- /* 1090 */ 49, 50, 121, 23, 172, 173, 26, 100, 101, 27, +- /* 1100 */ 101, 27, 23, 122, 152, 26, 172, 173, 172, 173, +- /* 1110 */ 152, 112, 163, 72, 73, 74, 75, 76, 77, 78, +- /* 1120 */ 79, 80, 81, 82, 163, 84, 85, 86, 87, 88, +- /* 1130 */ 89, 90, 91, 92, 93, 94, 19, 20, 152, 22, +- /* 1140 */ 23, 152, 163, 65, 27, 196, 163, 19, 20, 23, +- /* 1150 */ 22, 213, 26, 19, 37, 27, 152, 196, 172, 173, +- /* 1160 */ 152, 172, 173, 27, 23, 37, 152, 26, 152, 97, +- /* 1170 */ 152, 97, 210, 56, 163, 196, 163, 163, 100, 196, +- /* 1180 */ 172, 173, 65, 152, 56, 68, 172, 173, 172, 173, +- /* 1190 */ 172, 173, 152, 65, 163, 163, 68, 23, 152, 234, +- /* 1200 */ 26, 152, 152, 172, 173, 88, 89, 196, 152, 196, +- /* 1210 */ 196, 152, 95, 96, 97, 98, 88, 89, 101, 152, +- /* 1220 */ 152, 207, 208, 95, 96, 97, 98, 196, 196, 101, +- /* 1230 */ 96, 233, 152, 97, 152, 152, 19, 20, 207, 22, +- /* 1240 */ 152, 152, 152, 191, 27, 152, 152, 152, 152, 132, +- /* 1250 */ 133, 134, 135, 136, 37, 152, 152, 152, 152, 152, +- /* 1260 */ 132, 133, 134, 135, 136, 210, 197, 210, 210, 198, +- /* 1270 */ 150, 184, 239, 56, 201, 214, 214, 201, 239, 180, +- /* 1280 */ 214, 227, 198, 38, 176, 68, 175, 175, 175, 122, +- /* 1290 */ 155, 200, 159, 19, 20, 40, 22, 159, 159, 22, +- /* 1300 */ 70, 27, 130, 243, 240, 88, 89, 90, 189, 18, +- /* 1310 */ 201, 37, 95, 96, 97, 98, 192, 5, 101, 192, +- /* 1320 */ 220, 240, 10, 11, 12, 13, 14, 159, 18, 17, +- /* 1330 */ 56, 158, 192, 201, 192, 220, 189, 189, 201, 159, +- /* 1340 */ 158, 137, 68, 31, 45, 33, 236, 159, 159, 132, +- /* 1350 */ 133, 134, 135, 136, 42, 158, 235, 22, 177, 159, +- /* 1360 */ 158, 158, 88, 89, 159, 107, 174, 55, 177, 95, +- /* 1370 */ 96, 97, 98, 174, 62, 101, 47, 65, 66, 106, +- /* 1380 */ 174, 125, 19, 20, 174, 22, 177, 176, 174, 182, +- /* 1390 */ 27, 216, 174, 174, 182, 107, 159, 22, 215, 215, +- /* 1400 */ 37, 216, 216, 216, 137, 215, 132, 133, 134, 135, +- /* 1410 */ 136, 215, 159, 177, 94, 177, 129, 224, 205, 56, +- /* 1420 */ 226, 126, 128, 203, 229, 204, 114, 229, 127, 202, +- /* 1430 */ 201, 68, 25, 162, 26, 13, 161, 153, 153, 6, +- /* 1440 */ 151, 151, 178, 151, 165, 165, 178, 165, 4, 3, +- /* 1450 */ 249, 88, 89, 141, 22, 142, 15, 249, 95, 96, +- /* 1460 */ 97, 98, 246, 67, 101, 16, 23, 120, 23, 131, +- /* 1470 */ 111, 123, 20, 16, 125, 1, 123, 131, 78, 78, +- /* 1480 */ 78, 78, 111, 96, 122, 35, 1, 5, 22, 107, +- /* 1490 */ 140, 53, 53, 26, 60, 132, 133, 134, 135, 136, +- /* 1500 */ 107, 43, 24, 20, 112, 19, 22, 52, 52, 105, +- /* 1510 */ 22, 22, 52, 23, 22, 22, 29, 23, 39, 23, +- /* 1520 */ 23, 26, 116, 22, 26, 23, 22, 122, 23, 23, +- /* 1530 */ 22, 96, 11, 124, 35, 26, 26, 23, 35, 23, +- /* 1540 */ 23, 23, 35, 23, 22, 26, 23, 22, 24, 122, +- /* 1550 */ 23, 22, 26, 22, 24, 23, 23, 23, 22, 122, +- /* 1560 */ 23, 15, 122, 1, 122, ++ /* 0 */ 184, 238, 239, 240, 238, 239, 240, 163, 155, 156, ++ /* 10 */ 157, 158, 159, 160, 163, 191, 192, 183, 165, 19, ++ /* 20 */ 167, 258, 202, 203, 200, 191, 163, 174, 184, 185, ++ /* 30 */ 174, 31, 163, 163, 171, 184, 185, 35, 175, 39, ++ /* 40 */ 179, 180, 181, 43, 44, 45, 46, 47, 48, 49, ++ /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 184, 206, ++ /* 60 */ 207, 163, 206, 207, 220, 163, 16, 163, 66, 163, ++ /* 70 */ 59, 270, 219, 229, 273, 219, 74, 208, 174, 223, ++ /* 80 */ 224, 163, 184, 185, 163, 232, 184, 185, 184, 185, ++ /* 90 */ 184, 185, 92, 93, 94, 95, 96, 97, 98, 99, ++ /* 100 */ 100, 101, 102, 233, 198, 184, 185, 96, 97, 163, ++ /* 110 */ 206, 207, 19, 163, 261, 104, 105, 106, 107, 198, ++ /* 120 */ 109, 119, 220, 219, 220, 274, 275, 77, 117, 79, ++ /* 130 */ 187, 229, 19, 229, 184, 185, 43, 44, 45, 46, ++ /* 140 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, ++ /* 150 */ 57, 233, 141, 134, 143, 102, 43, 44, 45, 46, ++ /* 160 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, ++ /* 170 */ 57, 152, 274, 216, 276, 218, 83, 163, 85, 233, ++ /* 180 */ 67, 238, 239, 240, 11, 92, 93, 94, 95, 96, ++ /* 190 */ 97, 98, 99, 100, 101, 102, 19, 54, 55, 56, ++ /* 200 */ 57, 58, 163, 26, 163, 92, 93, 94, 95, 96, ++ /* 210 */ 97, 98, 99, 100, 101, 102, 54, 55, 56, 57, ++ /* 220 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, ++ /* 230 */ 53, 54, 55, 56, 57, 92, 93, 94, 95, 96, ++ /* 240 */ 97, 98, 99, 100, 101, 102, 69, 96, 97, 98, ++ /* 250 */ 99, 100, 101, 102, 92, 93, 94, 95, 96, 97, ++ /* 260 */ 98, 99, 100, 101, 102, 81, 179, 180, 181, 92, ++ /* 270 */ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, ++ /* 280 */ 163, 267, 268, 163, 22, 23, 59, 163, 26, 19, ++ /* 290 */ 117, 118, 175, 109, 24, 59, 92, 93, 94, 95, ++ /* 300 */ 96, 97, 98, 99, 100, 101, 102, 268, 184, 185, ++ /* 310 */ 269, 127, 128, 43, 44, 45, 46, 47, 48, 49, ++ /* 320 */ 50, 51, 52, 53, 54, 55, 56, 57, 157, 158, ++ /* 330 */ 159, 160, 105, 106, 107, 163, 165, 59, 167, 184, ++ /* 340 */ 90, 105, 106, 107, 108, 174, 73, 111, 112, 113, ++ /* 350 */ 19, 22, 163, 91, 81, 163, 106, 121, 81, 132, ++ /* 360 */ 110, 16, 92, 93, 94, 95, 96, 97, 98, 99, ++ /* 370 */ 100, 101, 102, 184, 185, 255, 98, 206, 207, 26, ++ /* 380 */ 101, 102, 19, 105, 106, 107, 23, 198, 59, 116, ++ /* 390 */ 219, 141, 142, 143, 24, 163, 187, 205, 274, 275, ++ /* 400 */ 127, 128, 182, 232, 127, 128, 43, 44, 45, 46, ++ /* 410 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, ++ /* 420 */ 57, 158, 77, 160, 79, 59, 26, 182, 165, 59, ++ /* 430 */ 167, 199, 261, 102, 105, 106, 107, 174, 72, 108, ++ /* 440 */ 109, 110, 111, 112, 113, 114, 59, 238, 239, 240, ++ /* 450 */ 123, 120, 125, 126, 163, 92, 93, 94, 95, 96, ++ /* 460 */ 97, 98, 99, 100, 101, 102, 163, 163, 163, 206, ++ /* 470 */ 207, 105, 106, 107, 254, 19, 106, 90, 197, 23, ++ /* 480 */ 127, 128, 219, 238, 239, 240, 22, 184, 185, 184, ++ /* 490 */ 185, 22, 105, 106, 149, 232, 205, 110, 163, 43, ++ /* 500 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, ++ /* 510 */ 54, 55, 56, 57, 98, 99, 100, 101, 102, 184, ++ /* 520 */ 185, 163, 53, 59, 261, 220, 117, 118, 141, 142, ++ /* 530 */ 143, 131, 174, 59, 229, 116, 117, 118, 163, 59, ++ /* 540 */ 163, 163, 184, 185, 59, 242, 72, 22, 92, 93, ++ /* 550 */ 94, 95, 96, 97, 98, 99, 100, 101, 102, 184, ++ /* 560 */ 185, 24, 184, 185, 206, 207, 202, 203, 19, 105, ++ /* 570 */ 106, 107, 23, 198, 22, 174, 198, 219, 220, 105, ++ /* 580 */ 106, 107, 96, 97, 59, 105, 106, 107, 22, 174, ++ /* 590 */ 59, 106, 43, 44, 45, 46, 47, 48, 49, 50, ++ /* 600 */ 51, 52, 53, 54, 55, 56, 57, 206, 207, 12, ++ /* 610 */ 108, 59, 132, 111, 112, 113, 46, 47, 48, 49, ++ /* 620 */ 219, 206, 207, 121, 27, 59, 163, 141, 207, 143, ++ /* 630 */ 105, 106, 107, 163, 219, 234, 105, 106, 107, 42, ++ /* 640 */ 219, 92, 93, 94, 95, 96, 97, 98, 99, 100, ++ /* 650 */ 101, 102, 76, 163, 184, 185, 163, 105, 106, 107, ++ /* 660 */ 63, 19, 86, 163, 163, 23, 163, 130, 205, 21, ++ /* 670 */ 73, 105, 106, 107, 184, 185, 163, 184, 185, 237, ++ /* 680 */ 110, 180, 181, 180, 181, 43, 44, 45, 46, 47, ++ /* 690 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, ++ /* 700 */ 174, 163, 163, 22, 23, 163, 163, 26, 22, 23, ++ /* 710 */ 220, 29, 73, 220, 272, 33, 22, 163, 24, 19, ++ /* 720 */ 174, 208, 259, 184, 185, 19, 184, 185, 80, 175, ++ /* 730 */ 230, 174, 206, 207, 92, 93, 94, 95, 96, 97, ++ /* 740 */ 98, 99, 100, 101, 102, 219, 46, 65, 247, 195, ++ /* 750 */ 247, 197, 206, 207, 19, 116, 117, 118, 23, 220, ++ /* 760 */ 112, 174, 220, 206, 207, 219, 22, 174, 24, 174, ++ /* 770 */ 22, 23, 91, 264, 265, 168, 219, 91, 43, 44, ++ /* 780 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, ++ /* 790 */ 55, 56, 57, 206, 207, 12, 163, 149, 255, 206, ++ /* 800 */ 207, 206, 207, 59, 104, 23, 219, 163, 26, 163, ++ /* 810 */ 27, 105, 219, 163, 219, 163, 211, 184, 185, 163, ++ /* 820 */ 120, 163, 146, 163, 148, 42, 221, 92, 93, 94, ++ /* 830 */ 95, 96, 97, 98, 99, 100, 101, 102, 163, 91, ++ /* 840 */ 184, 185, 184, 185, 184, 185, 63, 19, 163, 205, ++ /* 850 */ 106, 23, 245, 163, 208, 248, 116, 117, 118, 184, ++ /* 860 */ 185, 163, 163, 7, 8, 9, 163, 19, 26, 184, ++ /* 870 */ 185, 43, 44, 45, 46, 47, 48, 49, 50, 51, ++ /* 880 */ 52, 53, 54, 55, 56, 57, 163, 184, 185, 107, ++ /* 890 */ 163, 43, 44, 45, 46, 47, 48, 49, 50, 51, ++ /* 900 */ 52, 53, 54, 55, 56, 57, 208, 255, 177, 178, ++ /* 910 */ 163, 184, 185, 163, 132, 163, 141, 163, 143, 22, ++ /* 920 */ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, ++ /* 930 */ 102, 184, 185, 163, 184, 185, 184, 185, 184, 185, ++ /* 940 */ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, ++ /* 950 */ 102, 163, 163, 163, 184, 185, 163, 115, 163, 163, ++ /* 960 */ 163, 163, 15, 163, 163, 163, 163, 163, 23, 163, ++ /* 970 */ 163, 26, 184, 185, 184, 185, 163, 184, 185, 184, ++ /* 980 */ 185, 184, 185, 163, 184, 185, 184, 185, 184, 185, ++ /* 990 */ 184, 185, 163, 96, 97, 147, 163, 184, 185, 163, ++ /* 1000 */ 199, 163, 163, 205, 184, 185, 163, 60, 163, 141, ++ /* 1010 */ 163, 143, 163, 184, 185, 19, 163, 184, 185, 230, ++ /* 1020 */ 184, 185, 184, 185, 206, 207, 230, 184, 185, 184, ++ /* 1030 */ 185, 184, 185, 184, 185, 19, 163, 219, 231, 43, ++ /* 1040 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, ++ /* 1050 */ 54, 55, 56, 57, 163, 26, 163, 184, 185, 43, ++ /* 1060 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, ++ /* 1070 */ 54, 55, 56, 57, 163, 184, 185, 184, 185, 163, ++ /* 1080 */ 182, 163, 163, 163, 163, 163, 22, 163, 92, 93, ++ /* 1090 */ 94, 95, 96, 97, 98, 99, 100, 101, 102, 163, ++ /* 1100 */ 184, 185, 184, 185, 163, 184, 185, 163, 92, 93, ++ /* 1110 */ 94, 95, 96, 97, 98, 99, 100, 101, 102, 163, ++ /* 1120 */ 184, 185, 98, 59, 163, 184, 185, 205, 184, 185, ++ /* 1130 */ 23, 206, 207, 26, 163, 26, 107, 153, 154, 237, ++ /* 1140 */ 184, 185, 231, 147, 219, 184, 185, 249, 124, 127, ++ /* 1150 */ 128, 231, 254, 129, 163, 231, 177, 178, 262, 263, ++ /* 1160 */ 118, 132, 19, 19, 46, 223, 224, 31, 24, 23, ++ /* 1170 */ 106, 124, 26, 22, 272, 39, 129, 23, 109, 110, ++ /* 1180 */ 26, 163, 140, 19, 22, 234, 59, 43, 44, 45, ++ /* 1190 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, ++ /* 1200 */ 56, 57, 231, 7, 8, 193, 59, 43, 44, 45, ++ /* 1210 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, ++ /* 1220 */ 56, 57, 104, 61, 23, 23, 23, 26, 26, 26, ++ /* 1230 */ 163, 23, 23, 106, 26, 26, 92, 93, 94, 95, ++ /* 1240 */ 96, 97, 98, 99, 100, 101, 102, 138, 105, 23, ++ /* 1250 */ 59, 23, 26, 106, 26, 163, 92, 93, 94, 95, ++ /* 1260 */ 96, 97, 98, 99, 100, 101, 102, 110, 23, 23, ++ /* 1270 */ 23, 26, 26, 26, 163, 163, 19, 120, 163, 163, ++ /* 1280 */ 163, 130, 163, 163, 163, 163, 163, 163, 163, 193, ++ /* 1290 */ 193, 163, 163, 163, 163, 225, 19, 106, 163, 222, ++ /* 1300 */ 163, 44, 45, 46, 47, 48, 49, 50, 51, 52, ++ /* 1310 */ 53, 54, 55, 56, 57, 163, 163, 203, 163, 163, ++ /* 1320 */ 222, 163, 45, 46, 47, 48, 49, 50, 51, 52, ++ /* 1330 */ 53, 54, 55, 56, 57, 163, 163, 163, 163, 163, ++ /* 1340 */ 251, 250, 209, 19, 20, 182, 22, 161, 222, 92, ++ /* 1350 */ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, ++ /* 1360 */ 36, 222, 222, 260, 226, 188, 256, 226, 187, 92, ++ /* 1370 */ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, ++ /* 1380 */ 210, 213, 213, 59, 213, 196, 192, 187, 256, 244, ++ /* 1390 */ 212, 187, 226, 19, 20, 71, 22, 210, 166, 60, ++ /* 1400 */ 130, 170, 260, 170, 38, 81, 257, 257, 170, 104, ++ /* 1410 */ 36, 22, 43, 201, 90, 236, 138, 235, 213, 18, ++ /* 1420 */ 96, 97, 48, 204, 204, 204, 204, 103, 170, 105, ++ /* 1430 */ 106, 107, 18, 59, 110, 169, 213, 213, 201, 170, ++ /* 1440 */ 201, 169, 236, 213, 146, 71, 235, 62, 253, 252, ++ /* 1450 */ 170, 127, 128, 169, 22, 170, 82, 189, 169, 104, ++ /* 1460 */ 170, 87, 169, 189, 90, 141, 142, 143, 144, 145, ++ /* 1470 */ 96, 97, 186, 186, 186, 64, 194, 103, 186, 105, ++ /* 1480 */ 106, 107, 115, 189, 110, 188, 186, 186, 19, 20, ++ /* 1490 */ 194, 22, 186, 189, 102, 246, 246, 189, 133, 228, ++ /* 1500 */ 104, 228, 227, 227, 170, 36, 134, 228, 227, 19, ++ /* 1510 */ 20, 228, 22, 84, 271, 141, 142, 143, 144, 145, ++ /* 1520 */ 0, 1, 2, 216, 22, 5, 36, 137, 59, 227, ++ /* 1530 */ 10, 11, 12, 13, 14, 217, 269, 17, 216, 22, ++ /* 1540 */ 71, 170, 243, 146, 241, 217, 136, 215, 135, 59, ++ /* 1550 */ 30, 82, 32, 25, 214, 213, 87, 173, 26, 90, ++ /* 1560 */ 40, 71, 13, 172, 164, 96, 97, 164, 6, 162, ++ /* 1570 */ 162, 162, 103, 263, 105, 106, 107, 266, 266, 110, ++ /* 1580 */ 90, 176, 176, 190, 182, 190, 96, 97, 98, 4, ++ /* 1590 */ 70, 176, 3, 103, 182, 105, 106, 107, 78, 182, ++ /* 1600 */ 110, 81, 182, 182, 182, 182, 182, 151, 88, 22, ++ /* 1610 */ 141, 142, 143, 144, 145, 15, 89, 16, 23, 23, ++ /* 1620 */ 128, 19, 20, 139, 22, 119, 131, 24, 20, 133, ++ /* 1630 */ 16, 141, 142, 143, 144, 145, 1, 140, 36, 131, ++ /* 1640 */ 119, 61, 122, 37, 139, 53, 53, 127, 128, 119, ++ /* 1650 */ 53, 53, 105, 34, 130, 1, 5, 104, 22, 149, ++ /* 1660 */ 26, 59, 68, 75, 41, 130, 24, 68, 104, 20, ++ /* 1670 */ 150, 19, 120, 71, 114, 22, 67, 22, 22, 67, ++ /* 1680 */ 23, 22, 22, 67, 82, 37, 28, 23, 138, 87, ++ /* 1690 */ 22, 153, 90, 23, 23, 26, 23, 22, 96, 97, ++ /* 1700 */ 24, 23, 22, 24, 130, 103, 23, 105, 106, 107, ++ /* 1710 */ 1, 2, 110, 23, 5, 105, 34, 22, 132, 10, ++ /* 1720 */ 11, 12, 13, 14, 26, 34, 17, 34, 85, 83, ++ /* 1730 */ 44, 19, 20, 23, 22, 24, 75, 34, 23, 30, ++ /* 1740 */ 26, 32, 26, 141, 142, 143, 144, 145, 36, 40, ++ /* 1750 */ 23, 23, 23, 23, 11, 23, 22, 26, 22, 22, ++ /* 1760 */ 22, 19, 20, 23, 22, 26, 15, 23, 22, 124, ++ /* 1770 */ 130, 59, 23, 1, 130, 277, 277, 130, 36, 70, ++ /* 1780 */ 130, 277, 277, 71, 277, 277, 277, 78, 277, 277, ++ /* 1790 */ 81, 277, 277, 277, 277, 277, 277, 88, 277, 277, ++ /* 1800 */ 277, 59, 90, 277, 277, 277, 277, 277, 96, 97, ++ /* 1810 */ 277, 277, 277, 71, 277, 103, 277, 105, 106, 107, ++ /* 1820 */ 277, 277, 110, 277, 277, 277, 277, 277, 277, 277, ++ /* 1830 */ 277, 122, 90, 277, 277, 277, 127, 128, 96, 97, ++ /* 1840 */ 277, 277, 277, 277, 277, 103, 277, 105, 106, 107, ++ /* 1850 */ 277, 277, 110, 141, 142, 143, 144, 145, 277, 150, ++ /* 1860 */ 277, 277, 277, 5, 277, 277, 277, 277, 10, 11, ++ /* 1870 */ 12, 13, 14, 277, 277, 17, 277, 277, 277, 277, ++ /* 1880 */ 277, 277, 277, 141, 142, 143, 144, 145, 30, 277, ++ /* 1890 */ 32, 277, 277, 277, 277, 277, 277, 277, 40, 277, ++ /* 1900 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, ++ /* 1910 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, ++ /* 1920 */ 277, 277, 277, 277, 277, 277, 277, 277, 70, 277, ++ /* 1930 */ 277, 277, 277, 277, 277, 277, 78, 277, 277, 81, ++ /* 1940 */ 277, 277, 277, 277, 277, 277, 88, 277, 277, 277, ++ /* 1950 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, ++ /* 1960 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, ++ /* 1970 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, ++ /* 1980 */ 122, 277, 277, 277, 277, 127, 128, 277, 277, 277, ++ /* 1990 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, ++ /* 2000 */ 277, 277, 277, 277, 277, 277, 277, 277, 150, 277, ++ /* 2010 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, + }; +-#define YY_SHIFT_USE_DFLT (1565) +-#define YY_SHIFT_COUNT (454) +-#define YY_SHIFT_MIN (-114) +-#define YY_SHIFT_MAX (1562) +-static const short yy_shift_ofst[] = { +- /* 0 */ 5, 1117, 1312, 1128, 1274, 1274, 1274, 1274, 61, -19, +- /* 10 */ 57, 57, 183, 1274, 1274, 1274, 1274, 1274, 1274, 1274, +- /* 20 */ 66, 66, 201, -29, 331, 318, 133, 259, 335, 411, +- /* 30 */ 487, 563, 639, 689, 765, 841, 891, 891, 891, 891, +- /* 40 */ 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, +- /* 50 */ 891, 891, 891, 941, 891, 991, 1041, 1041, 1217, 1274, +- /* 60 */ 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, +- /* 70 */ 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, +- /* 80 */ 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, +- /* 90 */ 1363, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, +- /* 100 */ 1274, 1274, 1274, 1274, -70, -47, -47, -47, -47, -47, +- /* 110 */ 24, 11, 146, 296, 524, 444, 529, 529, 296, 3, +- /* 120 */ 2, -30, 1565, 1565, 1565, -17, -17, -17, 145, 145, +- /* 130 */ 497, 497, 265, 603, 653, 296, 296, 296, 296, 296, +- /* 140 */ 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, +- /* 150 */ 296, 296, 296, 296, 296, 701, 1078, 147, 147, 2, +- /* 160 */ 164, 164, 164, 164, 164, 164, 1565, 1565, 1565, 223, +- /* 170 */ 56, 56, 268, 269, 220, 347, 351, 415, 359, 296, +- /* 180 */ 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, +- /* 190 */ 296, 296, 296, 296, 296, 632, 632, 632, 296, 296, +- /* 200 */ 498, 296, 296, 296, 570, 296, 296, 654, 296, 296, +- /* 210 */ 296, 296, 296, 296, 296, 296, 296, 296, 636, 200, +- /* 220 */ 596, 596, 596, 575, -114, 971, 740, 454, 503, 503, +- /* 230 */ 1134, 454, 1134, 353, 588, 628, 762, 503, 189, 762, +- /* 240 */ 762, 916, 330, 668, 1245, 1167, 1167, 1255, 1255, 1167, +- /* 250 */ 1277, 1230, 1172, 1291, 1291, 1291, 1291, 1167, 1310, 1172, +- /* 260 */ 1277, 1230, 1230, 1172, 1167, 1310, 1204, 1299, 1167, 1167, +- /* 270 */ 1310, 1335, 1167, 1310, 1167, 1310, 1335, 1258, 1258, 1258, +- /* 280 */ 1329, 1335, 1258, 1273, 1258, 1329, 1258, 1258, 1256, 1288, +- /* 290 */ 1256, 1288, 1256, 1288, 1256, 1288, 1167, 1375, 1167, 1267, +- /* 300 */ 1335, 1320, 1320, 1335, 1287, 1295, 1294, 1301, 1172, 1407, +- /* 310 */ 1408, 1422, 1422, 1433, 1433, 1433, 1565, 1565, 1565, 1565, +- /* 320 */ 1565, 1565, 1565, 1565, 558, 537, 684, 719, 734, 799, +- /* 330 */ 840, 1019, 14, 1020, 1021, 1025, 1026, 1027, 1070, 1072, +- /* 340 */ 997, 1047, 999, 1079, 1126, 1074, 1141, 694, 819, 1174, +- /* 350 */ 1136, 981, 1444, 1446, 1432, 1313, 1441, 1396, 1449, 1443, +- /* 360 */ 1445, 1347, 1338, 1359, 1348, 1452, 1349, 1457, 1474, 1353, +- /* 370 */ 1346, 1400, 1401, 1402, 1403, 1371, 1387, 1450, 1362, 1485, +- /* 380 */ 1482, 1466, 1382, 1350, 1438, 1467, 1439, 1434, 1458, 1393, +- /* 390 */ 1478, 1483, 1486, 1392, 1404, 1484, 1455, 1488, 1489, 1490, +- /* 400 */ 1492, 1456, 1487, 1493, 1460, 1479, 1494, 1496, 1497, 1495, +- /* 410 */ 1406, 1501, 1502, 1504, 1498, 1405, 1505, 1506, 1435, 1499, +- /* 420 */ 1508, 1409, 1509, 1503, 1510, 1507, 1514, 1509, 1516, 1517, +- /* 430 */ 1518, 1519, 1520, 1522, 1521, 1523, 1525, 1524, 1526, 1527, +- /* 440 */ 1529, 1530, 1526, 1532, 1531, 1533, 1534, 1536, 1427, 1437, +- /* 450 */ 1440, 1442, 1537, 1546, 1562, ++#define YY_SHIFT_COUNT (520) ++#define YY_SHIFT_MIN (0) ++#define YY_SHIFT_MAX (1858) ++static const unsigned short int yy_shift_ofst[] = { ++ /* 0 */ 1709, 1520, 1858, 1324, 1324, 277, 1374, 1469, 1602, 1712, ++ /* 10 */ 1712, 1712, 273, 0, 0, 113, 1016, 1712, 1712, 1712, ++ /* 20 */ 1712, 1712, 1712, 1712, 1712, 1712, 1712, 11, 11, 236, ++ /* 30 */ 184, 277, 277, 277, 277, 277, 277, 93, 177, 270, ++ /* 40 */ 363, 456, 549, 642, 735, 828, 848, 996, 1144, 1016, ++ /* 50 */ 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, ++ /* 60 */ 1016, 1016, 1016, 1016, 1016, 1016, 1164, 1016, 1257, 1277, ++ /* 70 */ 1277, 1490, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, ++ /* 80 */ 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, ++ /* 90 */ 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, ++ /* 100 */ 1712, 1712, 1712, 1742, 1712, 1712, 1712, 1712, 1712, 1712, ++ /* 110 */ 1712, 1712, 1712, 1712, 1712, 1712, 1712, 143, 162, 162, ++ /* 120 */ 162, 162, 162, 204, 151, 416, 531, 648, 700, 531, ++ /* 130 */ 486, 486, 531, 353, 353, 353, 353, 409, 279, 53, ++ /* 140 */ 2009, 2009, 331, 331, 331, 329, 366, 329, 329, 597, ++ /* 150 */ 597, 464, 474, 262, 681, 531, 531, 531, 531, 531, ++ /* 160 */ 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, ++ /* 170 */ 531, 531, 531, 531, 531, 531, 531, 173, 485, 984, ++ /* 180 */ 984, 576, 485, 19, 1022, 2009, 2009, 2009, 387, 250, ++ /* 190 */ 250, 525, 502, 278, 552, 227, 480, 566, 531, 531, ++ /* 200 */ 531, 531, 531, 531, 531, 531, 531, 531, 639, 531, ++ /* 210 */ 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, ++ /* 220 */ 531, 2, 2, 2, 531, 531, 531, 531, 782, 531, ++ /* 230 */ 531, 531, 744, 531, 531, 783, 531, 531, 531, 531, ++ /* 240 */ 531, 531, 531, 531, 419, 682, 327, 370, 370, 370, ++ /* 250 */ 370, 1029, 327, 327, 1024, 897, 856, 947, 1109, 706, ++ /* 260 */ 706, 1143, 1109, 1109, 1143, 842, 945, 1118, 1136, 1136, ++ /* 270 */ 1136, 706, 676, 400, 1047, 694, 1339, 1270, 1270, 1366, ++ /* 280 */ 1366, 1270, 1305, 1389, 1369, 1278, 1401, 1401, 1401, 1401, ++ /* 290 */ 1270, 1414, 1278, 1278, 1305, 1389, 1369, 1369, 1278, 1270, ++ /* 300 */ 1414, 1298, 1385, 1270, 1414, 1432, 1270, 1414, 1270, 1414, ++ /* 310 */ 1432, 1355, 1355, 1355, 1411, 1432, 1355, 1367, 1355, 1411, ++ /* 320 */ 1355, 1355, 1432, 1392, 1392, 1432, 1365, 1396, 1365, 1396, ++ /* 330 */ 1365, 1396, 1365, 1396, 1270, 1372, 1429, 1502, 1390, 1372, ++ /* 340 */ 1517, 1270, 1397, 1390, 1410, 1413, 1278, 1528, 1532, 1549, ++ /* 350 */ 1549, 1562, 1562, 1562, 2009, 2009, 2009, 2009, 2009, 2009, ++ /* 360 */ 2009, 2009, 2009, 2009, 2009, 2009, 2009, 2009, 2009, 2009, ++ /* 370 */ 570, 345, 686, 748, 50, 740, 1064, 1107, 469, 537, ++ /* 380 */ 1042, 1146, 1162, 1154, 1201, 1202, 1203, 1208, 1209, 1127, ++ /* 390 */ 1069, 1196, 1157, 1147, 1226, 1228, 1245, 775, 868, 1246, ++ /* 400 */ 1247, 1191, 1151, 1585, 1589, 1587, 1456, 1600, 1527, 1601, ++ /* 410 */ 1595, 1596, 1492, 1484, 1506, 1603, 1495, 1608, 1496, 1614, ++ /* 420 */ 1635, 1508, 1497, 1521, 1580, 1606, 1505, 1592, 1593, 1597, ++ /* 430 */ 1598, 1530, 1547, 1619, 1524, 1654, 1651, 1636, 1553, 1510, ++ /* 440 */ 1594, 1634, 1599, 1588, 1623, 1535, 1564, 1642, 1649, 1652, ++ /* 450 */ 1552, 1560, 1653, 1609, 1655, 1656, 1657, 1659, 1612, 1658, ++ /* 460 */ 1660, 1616, 1648, 1664, 1550, 1668, 1538, 1670, 1671, 1669, ++ /* 470 */ 1673, 1675, 1676, 1678, 1680, 1679, 1574, 1683, 1690, 1610, ++ /* 480 */ 1682, 1695, 1586, 1698, 1691, 1698, 1693, 1643, 1661, 1646, ++ /* 490 */ 1686, 1710, 1711, 1714, 1716, 1703, 1715, 1698, 1727, 1728, ++ /* 500 */ 1729, 1730, 1731, 1732, 1734, 1743, 1736, 1737, 1740, 1744, ++ /* 510 */ 1738, 1746, 1739, 1645, 1640, 1644, 1647, 1650, 1749, 1751, ++ /* 520 */ 1772, + }; +-#define YY_REDUCE_USE_DFLT (-174) +-#define YY_REDUCE_COUNT (323) +-#define YY_REDUCE_MIN (-173) +-#define YY_REDUCE_MAX (1292) ++#define YY_REDUCE_COUNT (369) ++#define YY_REDUCE_MIN (-237) ++#define YY_REDUCE_MAX (1424) + static const short yy_reduce_ofst[] = { +- /* 0 */ -119, 1014, 131, 1031, -12, 225, 228, 300, -40, -45, +- /* 10 */ 243, 256, 293, 129, 218, 418, 79, 376, 433, 298, +- /* 20 */ 16, 137, 367, 323, -38, 391, -173, -173, -173, -173, +- /* 30 */ -173, -173, -173, -173, -173, -173, -173, -173, -173, -173, +- /* 40 */ -173, -173, -173, -173, -173, -173, -173, -173, -173, -173, +- /* 50 */ -173, -173, -173, -173, -173, -173, -173, -173, 374, 437, +- /* 60 */ 443, 508, 513, 522, 532, 582, 584, 620, 633, 635, +- /* 70 */ 637, 644, 646, 648, 650, 652, 659, 661, 696, 709, +- /* 80 */ 711, 714, 720, 722, 724, 726, 728, 733, 772, 784, +- /* 90 */ 786, 822, 834, 836, 884, 886, 922, 934, 936, 986, +- /* 100 */ 989, 1008, 1016, 1018, -173, -173, -173, -173, -173, -173, +- /* 110 */ -173, -173, -173, 544, -37, 274, 299, 501, 161, -173, +- /* 120 */ 193, -173, -173, -173, -173, 22, 22, 22, 64, 141, +- /* 130 */ 212, 342, 208, 504, 504, 132, 494, 606, 677, 678, +- /* 140 */ 750, 794, 796, -58, 32, 383, 660, 737, 386, 787, +- /* 150 */ 800, 441, 872, 224, 850, 803, 949, 624, 830, 669, +- /* 160 */ 961, 979, 983, 1011, 1013, 1032, 753, 789, 321, 94, +- /* 170 */ 116, 304, 375, 210, 388, 392, 478, 545, 649, 721, +- /* 180 */ 727, 736, 752, 795, 853, 952, 958, 1004, 1040, 1046, +- /* 190 */ 1049, 1050, 1056, 1059, 1067, 559, 774, 811, 1068, 1080, +- /* 200 */ 938, 1082, 1083, 1088, 962, 1089, 1090, 1052, 1093, 1094, +- /* 210 */ 1095, 388, 1096, 1103, 1104, 1105, 1106, 1107, 965, 998, +- /* 220 */ 1055, 1057, 1058, 938, 1069, 1071, 1120, 1073, 1061, 1062, +- /* 230 */ 1033, 1076, 1039, 1108, 1087, 1099, 1111, 1066, 1054, 1112, +- /* 240 */ 1113, 1091, 1084, 1135, 1060, 1133, 1138, 1064, 1081, 1139, +- /* 250 */ 1100, 1119, 1109, 1124, 1127, 1140, 1142, 1168, 1173, 1132, +- /* 260 */ 1115, 1147, 1148, 1137, 1180, 1182, 1110, 1121, 1188, 1189, +- /* 270 */ 1197, 1181, 1200, 1202, 1205, 1203, 1191, 1192, 1199, 1206, +- /* 280 */ 1207, 1209, 1210, 1211, 1214, 1212, 1218, 1219, 1175, 1183, +- /* 290 */ 1185, 1184, 1186, 1190, 1187, 1196, 1237, 1193, 1253, 1194, +- /* 300 */ 1236, 1195, 1198, 1238, 1213, 1221, 1220, 1227, 1229, 1271, +- /* 310 */ 1275, 1284, 1285, 1289, 1290, 1292, 1201, 1208, 1216, 1279, +- /* 320 */ 1280, 1264, 1268, 1282, ++ /* 0 */ -147, 171, 263, -96, 358, -144, -149, -102, 124, -156, ++ /* 10 */ -98, 305, 401, -57, 209, -237, 245, -94, -79, 189, ++ /* 20 */ 375, 490, 493, 378, 303, 539, 542, 501, 503, 554, ++ /* 30 */ 415, 526, 546, 557, 587, 593, 595, -234, -234, -234, ++ /* 40 */ -234, -234, -234, -234, -234, -234, -234, -234, -234, -234, ++ /* 50 */ -234, -234, -234, -234, -234, -234, -234, -234, -234, -234, ++ /* 60 */ -234, -234, -234, -234, -234, -234, -234, -234, -234, -234, ++ /* 70 */ -234, -50, 335, 470, 633, 656, 658, 660, 675, 685, ++ /* 80 */ 703, 727, 747, 750, 752, 754, 770, 788, 790, 793, ++ /* 90 */ 795, 797, 800, 802, 804, 806, 813, 820, 829, 833, ++ /* 100 */ 836, 838, 843, 845, 847, 849, 873, 891, 893, 916, ++ /* 110 */ 918, 921, 936, 941, 944, 956, 961, -234, -234, -234, ++ /* 120 */ -234, -234, -234, -234, -234, -234, 463, 607, -176, 14, ++ /* 130 */ -139, 87, -137, 818, 925, 818, 925, 898, -234, -234, ++ /* 140 */ -234, -234, -166, -166, -166, -130, -131, -82, -54, -180, ++ /* 150 */ 364, 41, 513, 509, 509, 117, 500, 789, 796, 646, ++ /* 160 */ 192, 291, 644, 798, 120, 807, 543, 911, 920, 652, ++ /* 170 */ 924, 922, 232, 698, 801, 971, 39, 220, 731, 442, ++ /* 180 */ 902, -199, 979, -43, 421, 896, 942, 605, -184, -126, ++ /* 190 */ 155, 172, 281, 304, 377, 538, 650, 690, 699, 723, ++ /* 200 */ 803, 839, 853, 919, 991, 1018, 1067, 1092, 951, 1111, ++ /* 210 */ 1112, 1115, 1116, 1117, 1119, 1120, 1121, 1122, 1123, 1124, ++ /* 220 */ 1125, 1012, 1096, 1097, 1128, 1129, 1130, 1131, 1070, 1135, ++ /* 230 */ 1137, 1152, 1077, 1153, 1155, 1114, 1156, 304, 1158, 1172, ++ /* 240 */ 1173, 1174, 1175, 1176, 1089, 1091, 1133, 1098, 1126, 1139, ++ /* 250 */ 1140, 1070, 1133, 1133, 1170, 1163, 1186, 1103, 1168, 1138, ++ /* 260 */ 1141, 1110, 1169, 1171, 1132, 1177, 1189, 1194, 1181, 1200, ++ /* 270 */ 1204, 1166, 1145, 1178, 1187, 1232, 1142, 1231, 1233, 1149, ++ /* 280 */ 1150, 1238, 1179, 1182, 1212, 1205, 1219, 1220, 1221, 1222, ++ /* 290 */ 1258, 1266, 1223, 1224, 1206, 1211, 1237, 1239, 1230, 1269, ++ /* 300 */ 1272, 1195, 1197, 1280, 1284, 1268, 1285, 1289, 1290, 1293, ++ /* 310 */ 1274, 1286, 1287, 1288, 1282, 1294, 1292, 1297, 1300, 1296, ++ /* 320 */ 1301, 1306, 1304, 1249, 1250, 1308, 1271, 1275, 1273, 1276, ++ /* 330 */ 1279, 1281, 1283, 1302, 1334, 1307, 1243, 1267, 1318, 1322, ++ /* 340 */ 1303, 1371, 1299, 1328, 1332, 1340, 1342, 1384, 1391, 1400, ++ /* 350 */ 1403, 1407, 1408, 1409, 1311, 1312, 1310, 1405, 1402, 1412, ++ /* 360 */ 1417, 1420, 1406, 1393, 1395, 1421, 1422, 1423, 1424, 1415, + }; + static const YYACTIONTYPE yy_default[] = { +- /* 0 */ 1270, 1260, 1260, 1260, 1193, 1193, 1193, 1193, 1260, 1088, +- /* 10 */ 1117, 1117, 1244, 1322, 1322, 1322, 1322, 1322, 1322, 1192, +- /* 20 */ 1322, 1322, 1322, 1322, 1260, 1092, 1123, 1322, 1322, 1322, +- /* 30 */ 1322, 1194, 1195, 1322, 1322, 1322, 1243, 1245, 1133, 1132, +- /* 40 */ 1131, 1130, 1226, 1104, 1128, 1121, 1125, 1194, 1188, 1189, +- /* 50 */ 1187, 1191, 1195, 1322, 1124, 1158, 1172, 1157, 1322, 1322, +- /* 60 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, +- /* 70 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, +- /* 80 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, +- /* 90 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, +- /* 100 */ 1322, 1322, 1322, 1322, 1166, 1171, 1178, 1170, 1167, 1160, +- /* 110 */ 1159, 1161, 1162, 1322, 1011, 1059, 1322, 1322, 1322, 1163, +- /* 120 */ 1322, 1164, 1175, 1174, 1173, 1251, 1278, 1277, 1322, 1322, +- /* 130 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, +- /* 140 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, +- /* 150 */ 1322, 1322, 1322, 1322, 1322, 1270, 1260, 1017, 1017, 1322, +- /* 160 */ 1260, 1260, 1260, 1260, 1260, 1260, 1256, 1092, 1083, 1322, +- /* 170 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, +- /* 180 */ 1248, 1246, 1322, 1208, 1322, 1322, 1322, 1322, 1322, 1322, +- /* 190 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, +- /* 200 */ 1322, 1322, 1322, 1322, 1088, 1322, 1322, 1322, 1322, 1322, +- /* 210 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1272, 1322, 1221, +- /* 220 */ 1088, 1088, 1088, 1090, 1072, 1082, 997, 1127, 1106, 1106, +- /* 230 */ 1311, 1127, 1311, 1034, 1292, 1031, 1117, 1106, 1190, 1117, +- /* 240 */ 1117, 1089, 1082, 1322, 1314, 1097, 1097, 1313, 1313, 1097, +- /* 250 */ 1138, 1062, 1127, 1068, 1068, 1068, 1068, 1097, 1008, 1127, +- /* 260 */ 1138, 1062, 1062, 1127, 1097, 1008, 1225, 1308, 1097, 1097, +- /* 270 */ 1008, 1201, 1097, 1008, 1097, 1008, 1201, 1060, 1060, 1060, +- /* 280 */ 1049, 1201, 1060, 1034, 1060, 1049, 1060, 1060, 1110, 1105, +- /* 290 */ 1110, 1105, 1110, 1105, 1110, 1105, 1097, 1196, 1097, 1322, +- /* 300 */ 1201, 1205, 1205, 1201, 1122, 1111, 1120, 1118, 1127, 1014, +- /* 310 */ 1052, 1275, 1275, 1271, 1271, 1271, 1319, 1319, 1256, 1287, +- /* 320 */ 1287, 1036, 1036, 1287, 1322, 1322, 1322, 1322, 1322, 1322, +- /* 330 */ 1282, 1322, 1210, 1322, 1322, 1322, 1322, 1322, 1322, 1322, +- /* 340 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, +- /* 350 */ 1322, 1143, 1322, 993, 1253, 1322, 1322, 1252, 1322, 1322, +- /* 360 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, +- /* 370 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1310, 1322, +- /* 380 */ 1322, 1322, 1322, 1322, 1322, 1224, 1223, 1322, 1322, 1322, +- /* 390 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, +- /* 400 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, +- /* 410 */ 1074, 1322, 1322, 1322, 1296, 1322, 1322, 1322, 1322, 1322, +- /* 420 */ 1322, 1322, 1119, 1322, 1112, 1322, 1322, 1301, 1322, 1322, +- /* 430 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1262, 1322, +- /* 440 */ 1322, 1322, 1261, 1322, 1322, 1322, 1322, 1322, 1145, 1322, +- /* 450 */ 1144, 1148, 1322, 1002, 1322, ++ /* 0 */ 1492, 1492, 1492, 1340, 1123, 1229, 1123, 1123, 1123, 1340, ++ /* 10 */ 1340, 1340, 1123, 1259, 1259, 1391, 1154, 1123, 1123, 1123, ++ /* 20 */ 1123, 1123, 1123, 1123, 1339, 1123, 1123, 1123, 1123, 1123, ++ /* 30 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1265, 1123, ++ /* 40 */ 1123, 1123, 1123, 1123, 1341, 1342, 1123, 1123, 1123, 1390, ++ /* 50 */ 1392, 1275, 1274, 1273, 1272, 1373, 1246, 1270, 1263, 1267, ++ /* 60 */ 1335, 1336, 1334, 1338, 1342, 1341, 1123, 1266, 1306, 1320, ++ /* 70 */ 1305, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 80 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 90 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 100 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 110 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1314, 1319, 1325, ++ /* 120 */ 1318, 1315, 1308, 1307, 1309, 1310, 1123, 1144, 1193, 1123, ++ /* 130 */ 1123, 1123, 1123, 1409, 1408, 1123, 1123, 1154, 1311, 1312, ++ /* 140 */ 1322, 1321, 1398, 1448, 1447, 1123, 1123, 1123, 1123, 1123, ++ /* 150 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 160 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 170 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1154, 1150, 1300, ++ /* 180 */ 1299, 1418, 1150, 1253, 1123, 1404, 1229, 1220, 1123, 1123, ++ /* 190 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 200 */ 1123, 1395, 1393, 1123, 1355, 1123, 1123, 1123, 1123, 1123, ++ /* 210 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 220 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 230 */ 1123, 1123, 1225, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 240 */ 1123, 1123, 1123, 1442, 1123, 1368, 1207, 1225, 1225, 1225, ++ /* 250 */ 1225, 1227, 1208, 1206, 1219, 1154, 1130, 1484, 1269, 1248, ++ /* 260 */ 1248, 1481, 1269, 1269, 1481, 1168, 1462, 1165, 1259, 1259, ++ /* 270 */ 1259, 1248, 1337, 1226, 1219, 1123, 1484, 1234, 1234, 1483, ++ /* 280 */ 1483, 1234, 1278, 1284, 1196, 1269, 1202, 1202, 1202, 1202, ++ /* 290 */ 1234, 1141, 1269, 1269, 1278, 1284, 1196, 1196, 1269, 1234, ++ /* 300 */ 1141, 1372, 1478, 1234, 1141, 1348, 1234, 1141, 1234, 1141, ++ /* 310 */ 1348, 1194, 1194, 1194, 1183, 1348, 1194, 1168, 1194, 1183, ++ /* 320 */ 1194, 1194, 1348, 1352, 1352, 1348, 1252, 1247, 1252, 1247, ++ /* 330 */ 1252, 1247, 1252, 1247, 1234, 1253, 1417, 1123, 1264, 1253, ++ /* 340 */ 1343, 1234, 1123, 1264, 1262, 1260, 1269, 1147, 1186, 1445, ++ /* 350 */ 1445, 1441, 1441, 1441, 1489, 1489, 1404, 1457, 1154, 1154, ++ /* 360 */ 1154, 1154, 1457, 1170, 1170, 1154, 1154, 1154, 1154, 1457, ++ /* 370 */ 1123, 1123, 1123, 1123, 1123, 1123, 1452, 1123, 1357, 1238, ++ /* 380 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 390 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 400 */ 1123, 1123, 1289, 1123, 1126, 1401, 1123, 1123, 1399, 1123, ++ /* 410 */ 1123, 1123, 1123, 1123, 1123, 1239, 1123, 1123, 1123, 1123, ++ /* 420 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 430 */ 1123, 1123, 1123, 1123, 1480, 1123, 1123, 1123, 1123, 1123, ++ /* 440 */ 1123, 1371, 1370, 1123, 1123, 1236, 1123, 1123, 1123, 1123, ++ /* 450 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 460 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 470 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 480 */ 1123, 1123, 1123, 1261, 1123, 1416, 1123, 1123, 1123, 1123, ++ /* 490 */ 1123, 1123, 1123, 1430, 1254, 1123, 1123, 1471, 1123, 1123, ++ /* 500 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 510 */ 1123, 1123, 1466, 1210, 1291, 1123, 1290, 1294, 1123, 1135, ++ /* 520 */ 1123, + }; + /********** End of lemon-generated parsing tables *****************************/ + +@@ -137414,73 +147745,95 @@ + static const YYCODETYPE yyFallback[] = { + 0, /* $ => nothing */ + 0, /* SEMI => nothing */ +- 27, /* EXPLAIN => ID */ +- 27, /* QUERY => ID */ +- 27, /* PLAN => ID */ +- 27, /* BEGIN => ID */ ++ 59, /* EXPLAIN => ID */ ++ 59, /* QUERY => ID */ ++ 59, /* PLAN => ID */ ++ 59, /* BEGIN => ID */ + 0, /* TRANSACTION => nothing */ +- 27, /* DEFERRED => ID */ +- 27, /* IMMEDIATE => ID */ +- 27, /* EXCLUSIVE => ID */ ++ 59, /* DEFERRED => ID */ ++ 59, /* IMMEDIATE => ID */ ++ 59, /* EXCLUSIVE => ID */ + 0, /* COMMIT => nothing */ +- 27, /* END => ID */ +- 27, /* ROLLBACK => ID */ +- 27, /* SAVEPOINT => ID */ +- 27, /* RELEASE => ID */ ++ 59, /* END => ID */ ++ 59, /* ROLLBACK => ID */ ++ 59, /* SAVEPOINT => ID */ ++ 59, /* RELEASE => ID */ + 0, /* TO => nothing */ + 0, /* TABLE => nothing */ + 0, /* CREATE => nothing */ +- 27, /* IF => ID */ ++ 59, /* IF => ID */ + 0, /* NOT => nothing */ + 0, /* EXISTS => nothing */ +- 27, /* TEMP => ID */ ++ 59, /* TEMP => ID */ + 0, /* LP => nothing */ + 0, /* RP => nothing */ + 0, /* AS => nothing */ +- 27, /* WITHOUT => ID */ ++ 59, /* WITHOUT => ID */ + 0, /* COMMA => nothing */ ++ 59, /* ABORT => ID */ ++ 59, /* ACTION => ID */ ++ 59, /* AFTER => ID */ ++ 59, /* ANALYZE => ID */ ++ 59, /* ASC => ID */ ++ 59, /* ATTACH => ID */ ++ 59, /* BEFORE => ID */ ++ 59, /* BY => ID */ ++ 59, /* CASCADE => ID */ ++ 59, /* CAST => ID */ ++ 59, /* CONFLICT => ID */ ++ 59, /* DATABASE => ID */ ++ 59, /* DESC => ID */ ++ 59, /* DETACH => ID */ ++ 59, /* EACH => ID */ ++ 59, /* FAIL => ID */ ++ 0, /* OR => nothing */ ++ 0, /* AND => nothing */ ++ 0, /* IS => nothing */ ++ 59, /* MATCH => ID */ ++ 59, /* LIKE_KW => ID */ ++ 0, /* BETWEEN => nothing */ ++ 0, /* IN => nothing */ ++ 0, /* ISNULL => nothing */ ++ 0, /* NOTNULL => nothing */ ++ 0, /* NE => nothing */ ++ 0, /* EQ => nothing */ ++ 0, /* GT => nothing */ ++ 0, /* LE => nothing */ ++ 0, /* LT => nothing */ ++ 0, /* GE => nothing */ ++ 0, /* ESCAPE => nothing */ + 0, /* ID => nothing */ +- 27, /* ABORT => ID */ +- 27, /* ACTION => ID */ +- 27, /* AFTER => ID */ +- 27, /* ANALYZE => ID */ +- 27, /* ASC => ID */ +- 27, /* ATTACH => ID */ +- 27, /* BEFORE => ID */ +- 27, /* BY => ID */ +- 27, /* CASCADE => ID */ +- 27, /* CAST => ID */ +- 27, /* COLUMNKW => ID */ +- 27, /* CONFLICT => ID */ +- 27, /* DATABASE => ID */ +- 27, /* DESC => ID */ +- 27, /* DETACH => ID */ +- 27, /* EACH => ID */ +- 27, /* FAIL => ID */ +- 27, /* FOR => ID */ +- 27, /* IGNORE => ID */ +- 27, /* INITIALLY => ID */ +- 27, /* INSTEAD => ID */ +- 27, /* LIKE_KW => ID */ +- 27, /* MATCH => ID */ +- 27, /* NO => ID */ +- 27, /* KEY => ID */ +- 27, /* OF => ID */ +- 27, /* OFFSET => ID */ +- 27, /* PRAGMA => ID */ +- 27, /* RAISE => ID */ +- 27, /* RECURSIVE => ID */ +- 27, /* REPLACE => ID */ +- 27, /* RESTRICT => ID */ +- 27, /* ROW => ID */ +- 27, /* TRIGGER => ID */ +- 27, /* VACUUM => ID */ +- 27, /* VIEW => ID */ +- 27, /* VIRTUAL => ID */ +- 27, /* WITH => ID */ +- 27, /* REINDEX => ID */ +- 27, /* RENAME => ID */ +- 27, /* CTIME_KW => ID */ ++ 59, /* COLUMNKW => ID */ ++ 59, /* DO => ID */ ++ 59, /* FOR => ID */ ++ 59, /* IGNORE => ID */ ++ 59, /* INITIALLY => ID */ ++ 59, /* INSTEAD => ID */ ++ 59, /* NO => ID */ ++ 59, /* KEY => ID */ ++ 59, /* OF => ID */ ++ 59, /* OFFSET => ID */ ++ 59, /* PRAGMA => ID */ ++ 59, /* RAISE => ID */ ++ 59, /* RECURSIVE => ID */ ++ 59, /* REPLACE => ID */ ++ 59, /* RESTRICT => ID */ ++ 59, /* ROW => ID */ ++ 59, /* ROWS => ID */ ++ 59, /* TRIGGER => ID */ ++ 59, /* VACUUM => ID */ ++ 59, /* VIEW => ID */ ++ 59, /* VIRTUAL => ID */ ++ 59, /* WITH => ID */ ++ 59, /* CURRENT => ID */ ++ 59, /* FOLLOWING => ID */ ++ 59, /* PARTITION => ID */ ++ 59, /* PRECEDING => ID */ ++ 59, /* RANGE => ID */ ++ 59, /* UNBOUNDED => ID */ ++ 59, /* REINDEX => ID */ ++ 59, /* RENAME => ID */ ++ 59, /* CTIME_KW => ID */ + }; + #endif /* YYFALLBACK */ + +@@ -137520,6 +147873,7 @@ + int yyerrcnt; /* Shifts left before out of the error */ + #endif + sqlite3ParserARG_SDECL /* A place to hold %extra_argument */ ++ sqlite3ParserCTX_SDECL /* A place to hold %extra_context */ + #if YYSTACKDEPTH<=0 + int yystksz; /* Current side of the stack */ + yyStackEntry *yystack; /* The parser's stack */ +@@ -137563,75 +147917,289 @@ + } + #endif /* NDEBUG */ + +-#ifndef NDEBUG ++#if defined(YYCOVERAGE) || !defined(NDEBUG) + /* For tracing shifts, the names of all terminals and nonterminals + ** are required. The following table supplies these names */ + static const char *const yyTokenName[] = { +- "$", "SEMI", "EXPLAIN", "QUERY", +- "PLAN", "BEGIN", "TRANSACTION", "DEFERRED", +- "IMMEDIATE", "EXCLUSIVE", "COMMIT", "END", +- "ROLLBACK", "SAVEPOINT", "RELEASE", "TO", +- "TABLE", "CREATE", "IF", "NOT", +- "EXISTS", "TEMP", "LP", "RP", +- "AS", "WITHOUT", "COMMA", "ID", +- "ABORT", "ACTION", "AFTER", "ANALYZE", +- "ASC", "ATTACH", "BEFORE", "BY", +- "CASCADE", "CAST", "COLUMNKW", "CONFLICT", +- "DATABASE", "DESC", "DETACH", "EACH", +- "FAIL", "FOR", "IGNORE", "INITIALLY", +- "INSTEAD", "LIKE_KW", "MATCH", "NO", +- "KEY", "OF", "OFFSET", "PRAGMA", +- "RAISE", "RECURSIVE", "REPLACE", "RESTRICT", +- "ROW", "TRIGGER", "VACUUM", "VIEW", +- "VIRTUAL", "WITH", "REINDEX", "RENAME", +- "CTIME_KW", "ANY", "OR", "AND", +- "IS", "BETWEEN", "IN", "ISNULL", +- "NOTNULL", "NE", "EQ", "GT", +- "LE", "LT", "GE", "ESCAPE", +- "BITAND", "BITOR", "LSHIFT", "RSHIFT", +- "PLUS", "MINUS", "STAR", "SLASH", +- "REM", "CONCAT", "COLLATE", "BITNOT", +- "INDEXED", "STRING", "JOIN_KW", "CONSTRAINT", +- "DEFAULT", "NULL", "PRIMARY", "UNIQUE", +- "CHECK", "REFERENCES", "AUTOINCR", "ON", +- "INSERT", "DELETE", "UPDATE", "SET", +- "DEFERRABLE", "FOREIGN", "DROP", "UNION", +- "ALL", "EXCEPT", "INTERSECT", "SELECT", +- "VALUES", "DISTINCT", "DOT", "FROM", +- "JOIN", "USING", "ORDER", "GROUP", +- "HAVING", "LIMIT", "WHERE", "INTO", +- "FLOAT", "BLOB", "INTEGER", "VARIABLE", +- "CASE", "WHEN", "THEN", "ELSE", +- "INDEX", "ALTER", "ADD", "error", +- "input", "cmdlist", "ecmd", "explain", +- "cmdx", "cmd", "transtype", "trans_opt", +- "nm", "savepoint_opt", "create_table", "create_table_args", +- "createkw", "temp", "ifnotexists", "dbnm", +- "columnlist", "conslist_opt", "table_options", "select", +- "columnname", "carglist", "typetoken", "typename", +- "signed", "plus_num", "minus_num", "ccons", +- "term", "expr", "onconf", "sortorder", +- "autoinc", "eidlist_opt", "refargs", "defer_subclause", +- "refarg", "refact", "init_deferred_pred_opt", "conslist", +- "tconscomma", "tcons", "sortlist", "eidlist", +- "defer_subclause_opt", "orconf", "resolvetype", "raisetype", +- "ifexists", "fullname", "selectnowith", "oneselect", +- "with", "multiselect_op", "distinct", "selcollist", +- "from", "where_opt", "groupby_opt", "having_opt", +- "orderby_opt", "limit_opt", "values", "nexprlist", +- "exprlist", "sclp", "as", "seltablist", +- "stl_prefix", "joinop", "indexed_opt", "on_opt", +- "using_opt", "idlist", "setlist", "insert_cmd", +- "idlist_opt", "likeop", "between_op", "in_op", +- "paren_exprlist", "case_operand", "case_exprlist", "case_else", +- "uniqueflag", "collate", "nmnum", "trigger_decl", +- "trigger_cmd_list", "trigger_time", "trigger_event", "foreach_clause", +- "when_clause", "trigger_cmd", "trnm", "tridxby", +- "database_kw_opt", "key_opt", "add_column_fullname", "kwcolumn_opt", +- "create_vtab", "vtabarglist", "vtabarg", "vtabargtoken", +- "lp", "anylist", "wqlist", ++ /* 0 */ "$", ++ /* 1 */ "SEMI", ++ /* 2 */ "EXPLAIN", ++ /* 3 */ "QUERY", ++ /* 4 */ "PLAN", ++ /* 5 */ "BEGIN", ++ /* 6 */ "TRANSACTION", ++ /* 7 */ "DEFERRED", ++ /* 8 */ "IMMEDIATE", ++ /* 9 */ "EXCLUSIVE", ++ /* 10 */ "COMMIT", ++ /* 11 */ "END", ++ /* 12 */ "ROLLBACK", ++ /* 13 */ "SAVEPOINT", ++ /* 14 */ "RELEASE", ++ /* 15 */ "TO", ++ /* 16 */ "TABLE", ++ /* 17 */ "CREATE", ++ /* 18 */ "IF", ++ /* 19 */ "NOT", ++ /* 20 */ "EXISTS", ++ /* 21 */ "TEMP", ++ /* 22 */ "LP", ++ /* 23 */ "RP", ++ /* 24 */ "AS", ++ /* 25 */ "WITHOUT", ++ /* 26 */ "COMMA", ++ /* 27 */ "ABORT", ++ /* 28 */ "ACTION", ++ /* 29 */ "AFTER", ++ /* 30 */ "ANALYZE", ++ /* 31 */ "ASC", ++ /* 32 */ "ATTACH", ++ /* 33 */ "BEFORE", ++ /* 34 */ "BY", ++ /* 35 */ "CASCADE", ++ /* 36 */ "CAST", ++ /* 37 */ "CONFLICT", ++ /* 38 */ "DATABASE", ++ /* 39 */ "DESC", ++ /* 40 */ "DETACH", ++ /* 41 */ "EACH", ++ /* 42 */ "FAIL", ++ /* 43 */ "OR", ++ /* 44 */ "AND", ++ /* 45 */ "IS", ++ /* 46 */ "MATCH", ++ /* 47 */ "LIKE_KW", ++ /* 48 */ "BETWEEN", ++ /* 49 */ "IN", ++ /* 50 */ "ISNULL", ++ /* 51 */ "NOTNULL", ++ /* 52 */ "NE", ++ /* 53 */ "EQ", ++ /* 54 */ "GT", ++ /* 55 */ "LE", ++ /* 56 */ "LT", ++ /* 57 */ "GE", ++ /* 58 */ "ESCAPE", ++ /* 59 */ "ID", ++ /* 60 */ "COLUMNKW", ++ /* 61 */ "DO", ++ /* 62 */ "FOR", ++ /* 63 */ "IGNORE", ++ /* 64 */ "INITIALLY", ++ /* 65 */ "INSTEAD", ++ /* 66 */ "NO", ++ /* 67 */ "KEY", ++ /* 68 */ "OF", ++ /* 69 */ "OFFSET", ++ /* 70 */ "PRAGMA", ++ /* 71 */ "RAISE", ++ /* 72 */ "RECURSIVE", ++ /* 73 */ "REPLACE", ++ /* 74 */ "RESTRICT", ++ /* 75 */ "ROW", ++ /* 76 */ "ROWS", ++ /* 77 */ "TRIGGER", ++ /* 78 */ "VACUUM", ++ /* 79 */ "VIEW", ++ /* 80 */ "VIRTUAL", ++ /* 81 */ "WITH", ++ /* 82 */ "CURRENT", ++ /* 83 */ "FOLLOWING", ++ /* 84 */ "PARTITION", ++ /* 85 */ "PRECEDING", ++ /* 86 */ "RANGE", ++ /* 87 */ "UNBOUNDED", ++ /* 88 */ "REINDEX", ++ /* 89 */ "RENAME", ++ /* 90 */ "CTIME_KW", ++ /* 91 */ "ANY", ++ /* 92 */ "BITAND", ++ /* 93 */ "BITOR", ++ /* 94 */ "LSHIFT", ++ /* 95 */ "RSHIFT", ++ /* 96 */ "PLUS", ++ /* 97 */ "MINUS", ++ /* 98 */ "STAR", ++ /* 99 */ "SLASH", ++ /* 100 */ "REM", ++ /* 101 */ "CONCAT", ++ /* 102 */ "COLLATE", ++ /* 103 */ "BITNOT", ++ /* 104 */ "ON", ++ /* 105 */ "INDEXED", ++ /* 106 */ "STRING", ++ /* 107 */ "JOIN_KW", ++ /* 108 */ "CONSTRAINT", ++ /* 109 */ "DEFAULT", ++ /* 110 */ "NULL", ++ /* 111 */ "PRIMARY", ++ /* 112 */ "UNIQUE", ++ /* 113 */ "CHECK", ++ /* 114 */ "REFERENCES", ++ /* 115 */ "AUTOINCR", ++ /* 116 */ "INSERT", ++ /* 117 */ "DELETE", ++ /* 118 */ "UPDATE", ++ /* 119 */ "SET", ++ /* 120 */ "DEFERRABLE", ++ /* 121 */ "FOREIGN", ++ /* 122 */ "DROP", ++ /* 123 */ "UNION", ++ /* 124 */ "ALL", ++ /* 125 */ "EXCEPT", ++ /* 126 */ "INTERSECT", ++ /* 127 */ "SELECT", ++ /* 128 */ "VALUES", ++ /* 129 */ "DISTINCT", ++ /* 130 */ "DOT", ++ /* 131 */ "FROM", ++ /* 132 */ "JOIN", ++ /* 133 */ "USING", ++ /* 134 */ "ORDER", ++ /* 135 */ "GROUP", ++ /* 136 */ "HAVING", ++ /* 137 */ "LIMIT", ++ /* 138 */ "WHERE", ++ /* 139 */ "INTO", ++ /* 140 */ "NOTHING", ++ /* 141 */ "FLOAT", ++ /* 142 */ "BLOB", ++ /* 143 */ "INTEGER", ++ /* 144 */ "VARIABLE", ++ /* 145 */ "CASE", ++ /* 146 */ "WHEN", ++ /* 147 */ "THEN", ++ /* 148 */ "ELSE", ++ /* 149 */ "INDEX", ++ /* 150 */ "ALTER", ++ /* 151 */ "ADD", ++ /* 152 */ "WINDOW", ++ /* 153 */ "OVER", ++ /* 154 */ "FILTER", ++ /* 155 */ "input", ++ /* 156 */ "cmdlist", ++ /* 157 */ "ecmd", ++ /* 158 */ "cmdx", ++ /* 159 */ "explain", ++ /* 160 */ "cmd", ++ /* 161 */ "transtype", ++ /* 162 */ "trans_opt", ++ /* 163 */ "nm", ++ /* 164 */ "savepoint_opt", ++ /* 165 */ "create_table", ++ /* 166 */ "create_table_args", ++ /* 167 */ "createkw", ++ /* 168 */ "temp", ++ /* 169 */ "ifnotexists", ++ /* 170 */ "dbnm", ++ /* 171 */ "columnlist", ++ /* 172 */ "conslist_opt", ++ /* 173 */ "table_options", ++ /* 174 */ "select", ++ /* 175 */ "columnname", ++ /* 176 */ "carglist", ++ /* 177 */ "typetoken", ++ /* 178 */ "typename", ++ /* 179 */ "signed", ++ /* 180 */ "plus_num", ++ /* 181 */ "minus_num", ++ /* 182 */ "scanpt", ++ /* 183 */ "ccons", ++ /* 184 */ "term", ++ /* 185 */ "expr", ++ /* 186 */ "onconf", ++ /* 187 */ "sortorder", ++ /* 188 */ "autoinc", ++ /* 189 */ "eidlist_opt", ++ /* 190 */ "refargs", ++ /* 191 */ "defer_subclause", ++ /* 192 */ "refarg", ++ /* 193 */ "refact", ++ /* 194 */ "init_deferred_pred_opt", ++ /* 195 */ "conslist", ++ /* 196 */ "tconscomma", ++ /* 197 */ "tcons", ++ /* 198 */ "sortlist", ++ /* 199 */ "eidlist", ++ /* 200 */ "defer_subclause_opt", ++ /* 201 */ "orconf", ++ /* 202 */ "resolvetype", ++ /* 203 */ "raisetype", ++ /* 204 */ "ifexists", ++ /* 205 */ "fullname", ++ /* 206 */ "selectnowith", ++ /* 207 */ "oneselect", ++ /* 208 */ "wqlist", ++ /* 209 */ "multiselect_op", ++ /* 210 */ "distinct", ++ /* 211 */ "selcollist", ++ /* 212 */ "from", ++ /* 213 */ "where_opt", ++ /* 214 */ "groupby_opt", ++ /* 215 */ "having_opt", ++ /* 216 */ "orderby_opt", ++ /* 217 */ "limit_opt", ++ /* 218 */ "window_clause", ++ /* 219 */ "values", ++ /* 220 */ "nexprlist", ++ /* 221 */ "sclp", ++ /* 222 */ "as", ++ /* 223 */ "seltablist", ++ /* 224 */ "stl_prefix", ++ /* 225 */ "joinop", ++ /* 226 */ "indexed_opt", ++ /* 227 */ "on_opt", ++ /* 228 */ "using_opt", ++ /* 229 */ "exprlist", ++ /* 230 */ "xfullname", ++ /* 231 */ "idlist", ++ /* 232 */ "with", ++ /* 233 */ "setlist", ++ /* 234 */ "insert_cmd", ++ /* 235 */ "idlist_opt", ++ /* 236 */ "upsert", ++ /* 237 */ "over_clause", ++ /* 238 */ "likeop", ++ /* 239 */ "between_op", ++ /* 240 */ "in_op", ++ /* 241 */ "paren_exprlist", ++ /* 242 */ "case_operand", ++ /* 243 */ "case_exprlist", ++ /* 244 */ "case_else", ++ /* 245 */ "uniqueflag", ++ /* 246 */ "collate", ++ /* 247 */ "nmnum", ++ /* 248 */ "trigger_decl", ++ /* 249 */ "trigger_cmd_list", ++ /* 250 */ "trigger_time", ++ /* 251 */ "trigger_event", ++ /* 252 */ "foreach_clause", ++ /* 253 */ "when_clause", ++ /* 254 */ "trigger_cmd", ++ /* 255 */ "trnm", ++ /* 256 */ "tridxby", ++ /* 257 */ "database_kw_opt", ++ /* 258 */ "key_opt", ++ /* 259 */ "add_column_fullname", ++ /* 260 */ "kwcolumn_opt", ++ /* 261 */ "create_vtab", ++ /* 262 */ "vtabarglist", ++ /* 263 */ "vtabarg", ++ /* 264 */ "vtabargtoken", ++ /* 265 */ "lp", ++ /* 266 */ "anylist", ++ /* 267 */ "windowdefn_list", ++ /* 268 */ "windowdefn", ++ /* 269 */ "window", ++ /* 270 */ "frame_opt", ++ /* 271 */ "part_opt", ++ /* 272 */ "filter_opt", ++ /* 273 */ "range_or_rows", ++ /* 274 */ "frame_bound", ++ /* 275 */ "frame_bound_s", ++ /* 276 */ "frame_bound_e", + }; +-#endif /* NDEBUG */ ++#endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */ + + #ifndef NDEBUG + /* For tracing reduce actions, the names of all rules are required. +@@ -137665,307 +148233,345 @@ + /* 25 */ "typetoken ::= typename LP signed RP", + /* 26 */ "typetoken ::= typename LP signed COMMA signed RP", + /* 27 */ "typename ::= typename ID|STRING", +- /* 28 */ "ccons ::= CONSTRAINT nm", +- /* 29 */ "ccons ::= DEFAULT term", +- /* 30 */ "ccons ::= DEFAULT LP expr RP", +- /* 31 */ "ccons ::= DEFAULT PLUS term", +- /* 32 */ "ccons ::= DEFAULT MINUS term", +- /* 33 */ "ccons ::= DEFAULT ID|INDEXED", +- /* 34 */ "ccons ::= NOT NULL onconf", +- /* 35 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc", +- /* 36 */ "ccons ::= UNIQUE onconf", +- /* 37 */ "ccons ::= CHECK LP expr RP", +- /* 38 */ "ccons ::= REFERENCES nm eidlist_opt refargs", +- /* 39 */ "ccons ::= defer_subclause", +- /* 40 */ "ccons ::= COLLATE ID|STRING", +- /* 41 */ "autoinc ::=", +- /* 42 */ "autoinc ::= AUTOINCR", +- /* 43 */ "refargs ::=", +- /* 44 */ "refargs ::= refargs refarg", +- /* 45 */ "refarg ::= MATCH nm", +- /* 46 */ "refarg ::= ON INSERT refact", +- /* 47 */ "refarg ::= ON DELETE refact", +- /* 48 */ "refarg ::= ON UPDATE refact", +- /* 49 */ "refact ::= SET NULL", +- /* 50 */ "refact ::= SET DEFAULT", +- /* 51 */ "refact ::= CASCADE", +- /* 52 */ "refact ::= RESTRICT", +- /* 53 */ "refact ::= NO ACTION", +- /* 54 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt", +- /* 55 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt", +- /* 56 */ "init_deferred_pred_opt ::=", +- /* 57 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED", +- /* 58 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE", +- /* 59 */ "conslist_opt ::=", +- /* 60 */ "tconscomma ::= COMMA", +- /* 61 */ "tcons ::= CONSTRAINT nm", +- /* 62 */ "tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf", +- /* 63 */ "tcons ::= UNIQUE LP sortlist RP onconf", +- /* 64 */ "tcons ::= CHECK LP expr RP onconf", +- /* 65 */ "tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt", +- /* 66 */ "defer_subclause_opt ::=", +- /* 67 */ "onconf ::=", +- /* 68 */ "onconf ::= ON CONFLICT resolvetype", +- /* 69 */ "orconf ::=", +- /* 70 */ "orconf ::= OR resolvetype", +- /* 71 */ "resolvetype ::= IGNORE", +- /* 72 */ "resolvetype ::= REPLACE", +- /* 73 */ "cmd ::= DROP TABLE ifexists fullname", +- /* 74 */ "ifexists ::= IF EXISTS", +- /* 75 */ "ifexists ::=", +- /* 76 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select", +- /* 77 */ "cmd ::= DROP VIEW ifexists fullname", +- /* 78 */ "cmd ::= select", +- /* 79 */ "select ::= with selectnowith", +- /* 80 */ "selectnowith ::= selectnowith multiselect_op oneselect", +- /* 81 */ "multiselect_op ::= UNION", +- /* 82 */ "multiselect_op ::= UNION ALL", +- /* 83 */ "multiselect_op ::= EXCEPT|INTERSECT", +- /* 84 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", +- /* 85 */ "values ::= VALUES LP nexprlist RP", +- /* 86 */ "values ::= values COMMA LP exprlist RP", +- /* 87 */ "distinct ::= DISTINCT", +- /* 88 */ "distinct ::= ALL", +- /* 89 */ "distinct ::=", +- /* 90 */ "sclp ::=", +- /* 91 */ "selcollist ::= sclp expr as", +- /* 92 */ "selcollist ::= sclp STAR", +- /* 93 */ "selcollist ::= sclp nm DOT STAR", +- /* 94 */ "as ::= AS nm", +- /* 95 */ "as ::=", +- /* 96 */ "from ::=", +- /* 97 */ "from ::= FROM seltablist", +- /* 98 */ "stl_prefix ::= seltablist joinop", +- /* 99 */ "stl_prefix ::=", +- /* 100 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt", +- /* 101 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt", +- /* 102 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt", +- /* 103 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt", +- /* 104 */ "dbnm ::=", +- /* 105 */ "dbnm ::= DOT nm", +- /* 106 */ "fullname ::= nm dbnm", +- /* 107 */ "joinop ::= COMMA|JOIN", +- /* 108 */ "joinop ::= JOIN_KW JOIN", +- /* 109 */ "joinop ::= JOIN_KW nm JOIN", +- /* 110 */ "joinop ::= JOIN_KW nm nm JOIN", +- /* 111 */ "on_opt ::= ON expr", +- /* 112 */ "on_opt ::=", +- /* 113 */ "indexed_opt ::=", +- /* 114 */ "indexed_opt ::= INDEXED BY nm", +- /* 115 */ "indexed_opt ::= NOT INDEXED", +- /* 116 */ "using_opt ::= USING LP idlist RP", +- /* 117 */ "using_opt ::=", +- /* 118 */ "orderby_opt ::=", +- /* 119 */ "orderby_opt ::= ORDER BY sortlist", +- /* 120 */ "sortlist ::= sortlist COMMA expr sortorder", +- /* 121 */ "sortlist ::= expr sortorder", +- /* 122 */ "sortorder ::= ASC", +- /* 123 */ "sortorder ::= DESC", +- /* 124 */ "sortorder ::=", +- /* 125 */ "groupby_opt ::=", +- /* 126 */ "groupby_opt ::= GROUP BY nexprlist", +- /* 127 */ "having_opt ::=", +- /* 128 */ "having_opt ::= HAVING expr", +- /* 129 */ "limit_opt ::=", +- /* 130 */ "limit_opt ::= LIMIT expr", +- /* 131 */ "limit_opt ::= LIMIT expr OFFSET expr", +- /* 132 */ "limit_opt ::= LIMIT expr COMMA expr", +- /* 133 */ "cmd ::= with DELETE FROM fullname indexed_opt where_opt", +- /* 134 */ "where_opt ::=", +- /* 135 */ "where_opt ::= WHERE expr", +- /* 136 */ "cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt", +- /* 137 */ "setlist ::= setlist COMMA nm EQ expr", +- /* 138 */ "setlist ::= setlist COMMA LP idlist RP EQ expr", +- /* 139 */ "setlist ::= nm EQ expr", +- /* 140 */ "setlist ::= LP idlist RP EQ expr", +- /* 141 */ "cmd ::= with insert_cmd INTO fullname idlist_opt select", +- /* 142 */ "cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES", +- /* 143 */ "insert_cmd ::= INSERT orconf", +- /* 144 */ "insert_cmd ::= REPLACE", +- /* 145 */ "idlist_opt ::=", +- /* 146 */ "idlist_opt ::= LP idlist RP", +- /* 147 */ "idlist ::= idlist COMMA nm", +- /* 148 */ "idlist ::= nm", +- /* 149 */ "expr ::= LP expr RP", +- /* 150 */ "expr ::= ID|INDEXED", +- /* 151 */ "expr ::= JOIN_KW", +- /* 152 */ "expr ::= nm DOT nm", +- /* 153 */ "expr ::= nm DOT nm DOT nm", +- /* 154 */ "term ::= NULL|FLOAT|BLOB", +- /* 155 */ "term ::= STRING", +- /* 156 */ "term ::= INTEGER", +- /* 157 */ "expr ::= VARIABLE", +- /* 158 */ "expr ::= expr COLLATE ID|STRING", +- /* 159 */ "expr ::= CAST LP expr AS typetoken RP", +- /* 160 */ "expr ::= ID|INDEXED LP distinct exprlist RP", +- /* 161 */ "expr ::= ID|INDEXED LP STAR RP", +- /* 162 */ "term ::= CTIME_KW", +- /* 163 */ "expr ::= LP nexprlist COMMA expr RP", +- /* 164 */ "expr ::= expr AND expr", +- /* 165 */ "expr ::= expr OR expr", +- /* 166 */ "expr ::= expr LT|GT|GE|LE expr", +- /* 167 */ "expr ::= expr EQ|NE expr", +- /* 168 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", +- /* 169 */ "expr ::= expr PLUS|MINUS expr", +- /* 170 */ "expr ::= expr STAR|SLASH|REM expr", +- /* 171 */ "expr ::= expr CONCAT expr", +- /* 172 */ "likeop ::= NOT LIKE_KW|MATCH", +- /* 173 */ "expr ::= expr likeop expr", +- /* 174 */ "expr ::= expr likeop expr ESCAPE expr", +- /* 175 */ "expr ::= expr ISNULL|NOTNULL", +- /* 176 */ "expr ::= expr NOT NULL", +- /* 177 */ "expr ::= expr IS expr", +- /* 178 */ "expr ::= expr IS NOT expr", +- /* 179 */ "expr ::= NOT expr", +- /* 180 */ "expr ::= BITNOT expr", +- /* 181 */ "expr ::= MINUS expr", +- /* 182 */ "expr ::= PLUS expr", +- /* 183 */ "between_op ::= BETWEEN", +- /* 184 */ "between_op ::= NOT BETWEEN", +- /* 185 */ "expr ::= expr between_op expr AND expr", +- /* 186 */ "in_op ::= IN", +- /* 187 */ "in_op ::= NOT IN", +- /* 188 */ "expr ::= expr in_op LP exprlist RP", +- /* 189 */ "expr ::= LP select RP", +- /* 190 */ "expr ::= expr in_op LP select RP", +- /* 191 */ "expr ::= expr in_op nm dbnm paren_exprlist", +- /* 192 */ "expr ::= EXISTS LP select RP", +- /* 193 */ "expr ::= CASE case_operand case_exprlist case_else END", +- /* 194 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", +- /* 195 */ "case_exprlist ::= WHEN expr THEN expr", +- /* 196 */ "case_else ::= ELSE expr", +- /* 197 */ "case_else ::=", +- /* 198 */ "case_operand ::= expr", +- /* 199 */ "case_operand ::=", +- /* 200 */ "exprlist ::=", +- /* 201 */ "nexprlist ::= nexprlist COMMA expr", +- /* 202 */ "nexprlist ::= expr", +- /* 203 */ "paren_exprlist ::=", +- /* 204 */ "paren_exprlist ::= LP exprlist RP", +- /* 205 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", +- /* 206 */ "uniqueflag ::= UNIQUE", +- /* 207 */ "uniqueflag ::=", +- /* 208 */ "eidlist_opt ::=", +- /* 209 */ "eidlist_opt ::= LP eidlist RP", +- /* 210 */ "eidlist ::= eidlist COMMA nm collate sortorder", +- /* 211 */ "eidlist ::= nm collate sortorder", +- /* 212 */ "collate ::=", +- /* 213 */ "collate ::= COLLATE ID|STRING", +- /* 214 */ "cmd ::= DROP INDEX ifexists fullname", +- /* 215 */ "cmd ::= VACUUM", +- /* 216 */ "cmd ::= VACUUM nm", +- /* 217 */ "cmd ::= PRAGMA nm dbnm", +- /* 218 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", +- /* 219 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", +- /* 220 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", +- /* 221 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", +- /* 222 */ "plus_num ::= PLUS INTEGER|FLOAT", +- /* 223 */ "minus_num ::= MINUS INTEGER|FLOAT", +- /* 224 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", +- /* 225 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", +- /* 226 */ "trigger_time ::= BEFORE|AFTER", +- /* 227 */ "trigger_time ::= INSTEAD OF", +- /* 228 */ "trigger_time ::=", +- /* 229 */ "trigger_event ::= DELETE|INSERT", +- /* 230 */ "trigger_event ::= UPDATE", +- /* 231 */ "trigger_event ::= UPDATE OF idlist", +- /* 232 */ "when_clause ::=", +- /* 233 */ "when_clause ::= WHEN expr", +- /* 234 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", +- /* 235 */ "trigger_cmd_list ::= trigger_cmd SEMI", +- /* 236 */ "trnm ::= nm DOT nm", +- /* 237 */ "tridxby ::= INDEXED BY nm", +- /* 238 */ "tridxby ::= NOT INDEXED", +- /* 239 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", +- /* 240 */ "trigger_cmd ::= insert_cmd INTO trnm idlist_opt select", +- /* 241 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", +- /* 242 */ "trigger_cmd ::= select", +- /* 243 */ "expr ::= RAISE LP IGNORE RP", +- /* 244 */ "expr ::= RAISE LP raisetype COMMA nm RP", +- /* 245 */ "raisetype ::= ROLLBACK", +- /* 246 */ "raisetype ::= ABORT", +- /* 247 */ "raisetype ::= FAIL", +- /* 248 */ "cmd ::= DROP TRIGGER ifexists fullname", +- /* 249 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", +- /* 250 */ "cmd ::= DETACH database_kw_opt expr", +- /* 251 */ "key_opt ::=", +- /* 252 */ "key_opt ::= KEY expr", +- /* 253 */ "cmd ::= REINDEX", +- /* 254 */ "cmd ::= REINDEX nm dbnm", +- /* 255 */ "cmd ::= ANALYZE", +- /* 256 */ "cmd ::= ANALYZE nm dbnm", +- /* 257 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", +- /* 258 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", +- /* 259 */ "add_column_fullname ::= fullname", +- /* 260 */ "cmd ::= create_vtab", +- /* 261 */ "cmd ::= create_vtab LP vtabarglist RP", +- /* 262 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", +- /* 263 */ "vtabarg ::=", +- /* 264 */ "vtabargtoken ::= ANY", +- /* 265 */ "vtabargtoken ::= lp anylist RP", +- /* 266 */ "lp ::= LP", +- /* 267 */ "with ::=", +- /* 268 */ "with ::= WITH wqlist", +- /* 269 */ "with ::= WITH RECURSIVE wqlist", +- /* 270 */ "wqlist ::= nm eidlist_opt AS LP select RP", +- /* 271 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", +- /* 272 */ "input ::= cmdlist", +- /* 273 */ "cmdlist ::= cmdlist ecmd", +- /* 274 */ "cmdlist ::= ecmd", +- /* 275 */ "ecmd ::= SEMI", +- /* 276 */ "ecmd ::= explain cmdx SEMI", +- /* 277 */ "explain ::=", +- /* 278 */ "trans_opt ::=", +- /* 279 */ "trans_opt ::= TRANSACTION", +- /* 280 */ "trans_opt ::= TRANSACTION nm", +- /* 281 */ "savepoint_opt ::= SAVEPOINT", +- /* 282 */ "savepoint_opt ::=", +- /* 283 */ "cmd ::= create_table create_table_args", +- /* 284 */ "columnlist ::= columnlist COMMA columnname carglist", +- /* 285 */ "columnlist ::= columnname carglist", +- /* 286 */ "nm ::= ID|INDEXED", +- /* 287 */ "nm ::= STRING", +- /* 288 */ "nm ::= JOIN_KW", +- /* 289 */ "typetoken ::= typename", +- /* 290 */ "typename ::= ID|STRING", +- /* 291 */ "signed ::= plus_num", +- /* 292 */ "signed ::= minus_num", +- /* 293 */ "carglist ::= carglist ccons", +- /* 294 */ "carglist ::=", +- /* 295 */ "ccons ::= NULL onconf", +- /* 296 */ "conslist_opt ::= COMMA conslist", +- /* 297 */ "conslist ::= conslist tconscomma tcons", +- /* 298 */ "conslist ::= tcons", +- /* 299 */ "tconscomma ::=", +- /* 300 */ "defer_subclause_opt ::= defer_subclause", +- /* 301 */ "resolvetype ::= raisetype", +- /* 302 */ "selectnowith ::= oneselect", +- /* 303 */ "oneselect ::= values", +- /* 304 */ "sclp ::= selcollist COMMA", +- /* 305 */ "as ::= ID|STRING", +- /* 306 */ "expr ::= term", +- /* 307 */ "likeop ::= LIKE_KW|MATCH", +- /* 308 */ "exprlist ::= nexprlist", +- /* 309 */ "nmnum ::= plus_num", +- /* 310 */ "nmnum ::= nm", +- /* 311 */ "nmnum ::= ON", +- /* 312 */ "nmnum ::= DELETE", +- /* 313 */ "nmnum ::= DEFAULT", +- /* 314 */ "plus_num ::= INTEGER|FLOAT", +- /* 315 */ "foreach_clause ::=", +- /* 316 */ "foreach_clause ::= FOR EACH ROW", +- /* 317 */ "trnm ::= nm", +- /* 318 */ "tridxby ::=", +- /* 319 */ "database_kw_opt ::= DATABASE", +- /* 320 */ "database_kw_opt ::=", +- /* 321 */ "kwcolumn_opt ::=", +- /* 322 */ "kwcolumn_opt ::= COLUMNKW", +- /* 323 */ "vtabarglist ::= vtabarg", +- /* 324 */ "vtabarglist ::= vtabarglist COMMA vtabarg", +- /* 325 */ "vtabarg ::= vtabarg vtabargtoken", +- /* 326 */ "anylist ::=", +- /* 327 */ "anylist ::= anylist LP anylist RP", +- /* 328 */ "anylist ::= anylist ANY", ++ /* 28 */ "scanpt ::=", ++ /* 29 */ "ccons ::= CONSTRAINT nm", ++ /* 30 */ "ccons ::= DEFAULT scanpt term scanpt", ++ /* 31 */ "ccons ::= DEFAULT LP expr RP", ++ /* 32 */ "ccons ::= DEFAULT PLUS term scanpt", ++ /* 33 */ "ccons ::= DEFAULT MINUS term scanpt", ++ /* 34 */ "ccons ::= DEFAULT scanpt ID|INDEXED", ++ /* 35 */ "ccons ::= NOT NULL onconf", ++ /* 36 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc", ++ /* 37 */ "ccons ::= UNIQUE onconf", ++ /* 38 */ "ccons ::= CHECK LP expr RP", ++ /* 39 */ "ccons ::= REFERENCES nm eidlist_opt refargs", ++ /* 40 */ "ccons ::= defer_subclause", ++ /* 41 */ "ccons ::= COLLATE ID|STRING", ++ /* 42 */ "autoinc ::=", ++ /* 43 */ "autoinc ::= AUTOINCR", ++ /* 44 */ "refargs ::=", ++ /* 45 */ "refargs ::= refargs refarg", ++ /* 46 */ "refarg ::= MATCH nm", ++ /* 47 */ "refarg ::= ON INSERT refact", ++ /* 48 */ "refarg ::= ON DELETE refact", ++ /* 49 */ "refarg ::= ON UPDATE refact", ++ /* 50 */ "refact ::= SET NULL", ++ /* 51 */ "refact ::= SET DEFAULT", ++ /* 52 */ "refact ::= CASCADE", ++ /* 53 */ "refact ::= RESTRICT", ++ /* 54 */ "refact ::= NO ACTION", ++ /* 55 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt", ++ /* 56 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt", ++ /* 57 */ "init_deferred_pred_opt ::=", ++ /* 58 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED", ++ /* 59 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE", ++ /* 60 */ "conslist_opt ::=", ++ /* 61 */ "tconscomma ::= COMMA", ++ /* 62 */ "tcons ::= CONSTRAINT nm", ++ /* 63 */ "tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf", ++ /* 64 */ "tcons ::= UNIQUE LP sortlist RP onconf", ++ /* 65 */ "tcons ::= CHECK LP expr RP onconf", ++ /* 66 */ "tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt", ++ /* 67 */ "defer_subclause_opt ::=", ++ /* 68 */ "onconf ::=", ++ /* 69 */ "onconf ::= ON CONFLICT resolvetype", ++ /* 70 */ "orconf ::=", ++ /* 71 */ "orconf ::= OR resolvetype", ++ /* 72 */ "resolvetype ::= IGNORE", ++ /* 73 */ "resolvetype ::= REPLACE", ++ /* 74 */ "cmd ::= DROP TABLE ifexists fullname", ++ /* 75 */ "ifexists ::= IF EXISTS", ++ /* 76 */ "ifexists ::=", ++ /* 77 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select", ++ /* 78 */ "cmd ::= DROP VIEW ifexists fullname", ++ /* 79 */ "cmd ::= select", ++ /* 80 */ "select ::= WITH wqlist selectnowith", ++ /* 81 */ "select ::= WITH RECURSIVE wqlist selectnowith", ++ /* 82 */ "select ::= selectnowith", ++ /* 83 */ "selectnowith ::= selectnowith multiselect_op oneselect", ++ /* 84 */ "multiselect_op ::= UNION", ++ /* 85 */ "multiselect_op ::= UNION ALL", ++ /* 86 */ "multiselect_op ::= EXCEPT|INTERSECT", ++ /* 87 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", ++ /* 88 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt", ++ /* 89 */ "values ::= VALUES LP nexprlist RP", ++ /* 90 */ "values ::= values COMMA LP nexprlist RP", ++ /* 91 */ "distinct ::= DISTINCT", ++ /* 92 */ "distinct ::= ALL", ++ /* 93 */ "distinct ::=", ++ /* 94 */ "sclp ::=", ++ /* 95 */ "selcollist ::= sclp scanpt expr scanpt as", ++ /* 96 */ "selcollist ::= sclp scanpt STAR", ++ /* 97 */ "selcollist ::= sclp scanpt nm DOT STAR", ++ /* 98 */ "as ::= AS nm", ++ /* 99 */ "as ::=", ++ /* 100 */ "from ::=", ++ /* 101 */ "from ::= FROM seltablist", ++ /* 102 */ "stl_prefix ::= seltablist joinop", ++ /* 103 */ "stl_prefix ::=", ++ /* 104 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt", ++ /* 105 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt", ++ /* 106 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt", ++ /* 107 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt", ++ /* 108 */ "dbnm ::=", ++ /* 109 */ "dbnm ::= DOT nm", ++ /* 110 */ "fullname ::= nm", ++ /* 111 */ "fullname ::= nm DOT nm", ++ /* 112 */ "xfullname ::= nm", ++ /* 113 */ "xfullname ::= nm DOT nm", ++ /* 114 */ "xfullname ::= nm DOT nm AS nm", ++ /* 115 */ "xfullname ::= nm AS nm", ++ /* 116 */ "joinop ::= COMMA|JOIN", ++ /* 117 */ "joinop ::= JOIN_KW JOIN", ++ /* 118 */ "joinop ::= JOIN_KW nm JOIN", ++ /* 119 */ "joinop ::= JOIN_KW nm nm JOIN", ++ /* 120 */ "on_opt ::= ON expr", ++ /* 121 */ "on_opt ::=", ++ /* 122 */ "indexed_opt ::=", ++ /* 123 */ "indexed_opt ::= INDEXED BY nm", ++ /* 124 */ "indexed_opt ::= NOT INDEXED", ++ /* 125 */ "using_opt ::= USING LP idlist RP", ++ /* 126 */ "using_opt ::=", ++ /* 127 */ "orderby_opt ::=", ++ /* 128 */ "orderby_opt ::= ORDER BY sortlist", ++ /* 129 */ "sortlist ::= sortlist COMMA expr sortorder", ++ /* 130 */ "sortlist ::= expr sortorder", ++ /* 131 */ "sortorder ::= ASC", ++ /* 132 */ "sortorder ::= DESC", ++ /* 133 */ "sortorder ::=", ++ /* 134 */ "groupby_opt ::=", ++ /* 135 */ "groupby_opt ::= GROUP BY nexprlist", ++ /* 136 */ "having_opt ::=", ++ /* 137 */ "having_opt ::= HAVING expr", ++ /* 138 */ "limit_opt ::=", ++ /* 139 */ "limit_opt ::= LIMIT expr", ++ /* 140 */ "limit_opt ::= LIMIT expr OFFSET expr", ++ /* 141 */ "limit_opt ::= LIMIT expr COMMA expr", ++ /* 142 */ "cmd ::= with DELETE FROM xfullname indexed_opt where_opt", ++ /* 143 */ "where_opt ::=", ++ /* 144 */ "where_opt ::= WHERE expr", ++ /* 145 */ "cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt", ++ /* 146 */ "setlist ::= setlist COMMA nm EQ expr", ++ /* 147 */ "setlist ::= setlist COMMA LP idlist RP EQ expr", ++ /* 148 */ "setlist ::= nm EQ expr", ++ /* 149 */ "setlist ::= LP idlist RP EQ expr", ++ /* 150 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert", ++ /* 151 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES", ++ /* 152 */ "upsert ::=", ++ /* 153 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt", ++ /* 154 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING", ++ /* 155 */ "upsert ::= ON CONFLICT DO NOTHING", ++ /* 156 */ "insert_cmd ::= INSERT orconf", ++ /* 157 */ "insert_cmd ::= REPLACE", ++ /* 158 */ "idlist_opt ::=", ++ /* 159 */ "idlist_opt ::= LP idlist RP", ++ /* 160 */ "idlist ::= idlist COMMA nm", ++ /* 161 */ "idlist ::= nm", ++ /* 162 */ "expr ::= LP expr RP", ++ /* 163 */ "expr ::= ID|INDEXED", ++ /* 164 */ "expr ::= JOIN_KW", ++ /* 165 */ "expr ::= nm DOT nm", ++ /* 166 */ "expr ::= nm DOT nm DOT nm", ++ /* 167 */ "term ::= NULL|FLOAT|BLOB", ++ /* 168 */ "term ::= STRING", ++ /* 169 */ "term ::= INTEGER", ++ /* 170 */ "expr ::= VARIABLE", ++ /* 171 */ "expr ::= expr COLLATE ID|STRING", ++ /* 172 */ "expr ::= CAST LP expr AS typetoken RP", ++ /* 173 */ "expr ::= ID|INDEXED LP distinct exprlist RP", ++ /* 174 */ "expr ::= ID|INDEXED LP STAR RP", ++ /* 175 */ "expr ::= ID|INDEXED LP distinct exprlist RP over_clause", ++ /* 176 */ "expr ::= ID|INDEXED LP STAR RP over_clause", ++ /* 177 */ "term ::= CTIME_KW", ++ /* 178 */ "expr ::= LP nexprlist COMMA expr RP", ++ /* 179 */ "expr ::= expr AND expr", ++ /* 180 */ "expr ::= expr OR expr", ++ /* 181 */ "expr ::= expr LT|GT|GE|LE expr", ++ /* 182 */ "expr ::= expr EQ|NE expr", ++ /* 183 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", ++ /* 184 */ "expr ::= expr PLUS|MINUS expr", ++ /* 185 */ "expr ::= expr STAR|SLASH|REM expr", ++ /* 186 */ "expr ::= expr CONCAT expr", ++ /* 187 */ "likeop ::= NOT LIKE_KW|MATCH", ++ /* 188 */ "expr ::= expr likeop expr", ++ /* 189 */ "expr ::= expr likeop expr ESCAPE expr", ++ /* 190 */ "expr ::= expr ISNULL|NOTNULL", ++ /* 191 */ "expr ::= expr NOT NULL", ++ /* 192 */ "expr ::= expr IS expr", ++ /* 193 */ "expr ::= expr IS NOT expr", ++ /* 194 */ "expr ::= NOT expr", ++ /* 195 */ "expr ::= BITNOT expr", ++ /* 196 */ "expr ::= PLUS|MINUS expr", ++ /* 197 */ "between_op ::= BETWEEN", ++ /* 198 */ "between_op ::= NOT BETWEEN", ++ /* 199 */ "expr ::= expr between_op expr AND expr", ++ /* 200 */ "in_op ::= IN", ++ /* 201 */ "in_op ::= NOT IN", ++ /* 202 */ "expr ::= expr in_op LP exprlist RP", ++ /* 203 */ "expr ::= LP select RP", ++ /* 204 */ "expr ::= expr in_op LP select RP", ++ /* 205 */ "expr ::= expr in_op nm dbnm paren_exprlist", ++ /* 206 */ "expr ::= EXISTS LP select RP", ++ /* 207 */ "expr ::= CASE case_operand case_exprlist case_else END", ++ /* 208 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", ++ /* 209 */ "case_exprlist ::= WHEN expr THEN expr", ++ /* 210 */ "case_else ::= ELSE expr", ++ /* 211 */ "case_else ::=", ++ /* 212 */ "case_operand ::= expr", ++ /* 213 */ "case_operand ::=", ++ /* 214 */ "exprlist ::=", ++ /* 215 */ "nexprlist ::= nexprlist COMMA expr", ++ /* 216 */ "nexprlist ::= expr", ++ /* 217 */ "paren_exprlist ::=", ++ /* 218 */ "paren_exprlist ::= LP exprlist RP", ++ /* 219 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", ++ /* 220 */ "uniqueflag ::= UNIQUE", ++ /* 221 */ "uniqueflag ::=", ++ /* 222 */ "eidlist_opt ::=", ++ /* 223 */ "eidlist_opt ::= LP eidlist RP", ++ /* 224 */ "eidlist ::= eidlist COMMA nm collate sortorder", ++ /* 225 */ "eidlist ::= nm collate sortorder", ++ /* 226 */ "collate ::=", ++ /* 227 */ "collate ::= COLLATE ID|STRING", ++ /* 228 */ "cmd ::= DROP INDEX ifexists fullname", ++ /* 229 */ "cmd ::= VACUUM", ++ /* 230 */ "cmd ::= VACUUM nm", ++ /* 231 */ "cmd ::= PRAGMA nm dbnm", ++ /* 232 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", ++ /* 233 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", ++ /* 234 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", ++ /* 235 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", ++ /* 236 */ "plus_num ::= PLUS INTEGER|FLOAT", ++ /* 237 */ "minus_num ::= MINUS INTEGER|FLOAT", ++ /* 238 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", ++ /* 239 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", ++ /* 240 */ "trigger_time ::= BEFORE|AFTER", ++ /* 241 */ "trigger_time ::= INSTEAD OF", ++ /* 242 */ "trigger_time ::=", ++ /* 243 */ "trigger_event ::= DELETE|INSERT", ++ /* 244 */ "trigger_event ::= UPDATE", ++ /* 245 */ "trigger_event ::= UPDATE OF idlist", ++ /* 246 */ "when_clause ::=", ++ /* 247 */ "when_clause ::= WHEN expr", ++ /* 248 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", ++ /* 249 */ "trigger_cmd_list ::= trigger_cmd SEMI", ++ /* 250 */ "trnm ::= nm DOT nm", ++ /* 251 */ "tridxby ::= INDEXED BY nm", ++ /* 252 */ "tridxby ::= NOT INDEXED", ++ /* 253 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt", ++ /* 254 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt", ++ /* 255 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt", ++ /* 256 */ "trigger_cmd ::= scanpt select scanpt", ++ /* 257 */ "expr ::= RAISE LP IGNORE RP", ++ /* 258 */ "expr ::= RAISE LP raisetype COMMA nm RP", ++ /* 259 */ "raisetype ::= ROLLBACK", ++ /* 260 */ "raisetype ::= ABORT", ++ /* 261 */ "raisetype ::= FAIL", ++ /* 262 */ "cmd ::= DROP TRIGGER ifexists fullname", ++ /* 263 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", ++ /* 264 */ "cmd ::= DETACH database_kw_opt expr", ++ /* 265 */ "key_opt ::=", ++ /* 266 */ "key_opt ::= KEY expr", ++ /* 267 */ "cmd ::= REINDEX", ++ /* 268 */ "cmd ::= REINDEX nm dbnm", ++ /* 269 */ "cmd ::= ANALYZE", ++ /* 270 */ "cmd ::= ANALYZE nm dbnm", ++ /* 271 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", ++ /* 272 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", ++ /* 273 */ "add_column_fullname ::= fullname", ++ /* 274 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm", ++ /* 275 */ "cmd ::= create_vtab", ++ /* 276 */ "cmd ::= create_vtab LP vtabarglist RP", ++ /* 277 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", ++ /* 278 */ "vtabarg ::=", ++ /* 279 */ "vtabargtoken ::= ANY", ++ /* 280 */ "vtabargtoken ::= lp anylist RP", ++ /* 281 */ "lp ::= LP", ++ /* 282 */ "with ::= WITH wqlist", ++ /* 283 */ "with ::= WITH RECURSIVE wqlist", ++ /* 284 */ "wqlist ::= nm eidlist_opt AS LP select RP", ++ /* 285 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", ++ /* 286 */ "windowdefn_list ::= windowdefn", ++ /* 287 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn", ++ /* 288 */ "windowdefn ::= nm AS window", ++ /* 289 */ "window ::= LP part_opt orderby_opt frame_opt RP", ++ /* 290 */ "part_opt ::= PARTITION BY nexprlist", ++ /* 291 */ "part_opt ::=", ++ /* 292 */ "frame_opt ::=", ++ /* 293 */ "frame_opt ::= range_or_rows frame_bound_s", ++ /* 294 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e", ++ /* 295 */ "range_or_rows ::= RANGE", ++ /* 296 */ "range_or_rows ::= ROWS", ++ /* 297 */ "frame_bound_s ::= frame_bound", ++ /* 298 */ "frame_bound_s ::= UNBOUNDED PRECEDING", ++ /* 299 */ "frame_bound_e ::= frame_bound", ++ /* 300 */ "frame_bound_e ::= UNBOUNDED FOLLOWING", ++ /* 301 */ "frame_bound ::= expr PRECEDING", ++ /* 302 */ "frame_bound ::= CURRENT ROW", ++ /* 303 */ "frame_bound ::= expr FOLLOWING", ++ /* 304 */ "window_clause ::= WINDOW windowdefn_list", ++ /* 305 */ "over_clause ::= filter_opt OVER window", ++ /* 306 */ "over_clause ::= filter_opt OVER nm", ++ /* 307 */ "filter_opt ::=", ++ /* 308 */ "filter_opt ::= FILTER LP WHERE expr RP", ++ /* 309 */ "input ::= cmdlist", ++ /* 310 */ "cmdlist ::= cmdlist ecmd", ++ /* 311 */ "cmdlist ::= ecmd", ++ /* 312 */ "ecmd ::= SEMI", ++ /* 313 */ "ecmd ::= cmdx SEMI", ++ /* 314 */ "ecmd ::= explain cmdx", ++ /* 315 */ "trans_opt ::=", ++ /* 316 */ "trans_opt ::= TRANSACTION", ++ /* 317 */ "trans_opt ::= TRANSACTION nm", ++ /* 318 */ "savepoint_opt ::= SAVEPOINT", ++ /* 319 */ "savepoint_opt ::=", ++ /* 320 */ "cmd ::= create_table create_table_args", ++ /* 321 */ "columnlist ::= columnlist COMMA columnname carglist", ++ /* 322 */ "columnlist ::= columnname carglist", ++ /* 323 */ "nm ::= ID|INDEXED", ++ /* 324 */ "nm ::= STRING", ++ /* 325 */ "nm ::= JOIN_KW", ++ /* 326 */ "typetoken ::= typename", ++ /* 327 */ "typename ::= ID|STRING", ++ /* 328 */ "signed ::= plus_num", ++ /* 329 */ "signed ::= minus_num", ++ /* 330 */ "carglist ::= carglist ccons", ++ /* 331 */ "carglist ::=", ++ /* 332 */ "ccons ::= NULL onconf", ++ /* 333 */ "conslist_opt ::= COMMA conslist", ++ /* 334 */ "conslist ::= conslist tconscomma tcons", ++ /* 335 */ "conslist ::= tcons", ++ /* 336 */ "tconscomma ::=", ++ /* 337 */ "defer_subclause_opt ::= defer_subclause", ++ /* 338 */ "resolvetype ::= raisetype", ++ /* 339 */ "selectnowith ::= oneselect", ++ /* 340 */ "oneselect ::= values", ++ /* 341 */ "sclp ::= selcollist COMMA", ++ /* 342 */ "as ::= ID|STRING", ++ /* 343 */ "expr ::= term", ++ /* 344 */ "likeop ::= LIKE_KW|MATCH", ++ /* 345 */ "exprlist ::= nexprlist", ++ /* 346 */ "nmnum ::= plus_num", ++ /* 347 */ "nmnum ::= nm", ++ /* 348 */ "nmnum ::= ON", ++ /* 349 */ "nmnum ::= DELETE", ++ /* 350 */ "nmnum ::= DEFAULT", ++ /* 351 */ "plus_num ::= INTEGER|FLOAT", ++ /* 352 */ "foreach_clause ::=", ++ /* 353 */ "foreach_clause ::= FOR EACH ROW", ++ /* 354 */ "trnm ::= nm", ++ /* 355 */ "tridxby ::=", ++ /* 356 */ "database_kw_opt ::= DATABASE", ++ /* 357 */ "database_kw_opt ::=", ++ /* 358 */ "kwcolumn_opt ::=", ++ /* 359 */ "kwcolumn_opt ::= COLUMNKW", ++ /* 360 */ "vtabarglist ::= vtabarg", ++ /* 361 */ "vtabarglist ::= vtabarglist COMMA vtabarg", ++ /* 362 */ "vtabarg ::= vtabarg vtabargtoken", ++ /* 363 */ "anylist ::=", ++ /* 364 */ "anylist ::= anylist LP anylist RP", ++ /* 365 */ "anylist ::= anylist ANY", ++ /* 366 */ "with ::=", + }; + #endif /* NDEBUG */ + +@@ -138014,28 +148620,29 @@ + + /* Initialize a new parser that has already been allocated. + */ +-SQLITE_PRIVATE void sqlite3ParserInit(void *yypParser){ +- yyParser *pParser = (yyParser*)yypParser; ++SQLITE_PRIVATE void sqlite3ParserInit(void *yypRawParser sqlite3ParserCTX_PDECL){ ++ yyParser *yypParser = (yyParser*)yypRawParser; ++ sqlite3ParserCTX_STORE + #ifdef YYTRACKMAXSTACKDEPTH +- pParser->yyhwm = 0; ++ yypParser->yyhwm = 0; + #endif + #if YYSTACKDEPTH<=0 +- pParser->yytos = NULL; +- pParser->yystack = NULL; +- pParser->yystksz = 0; +- if( yyGrowStack(pParser) ){ +- pParser->yystack = &pParser->yystk0; +- pParser->yystksz = 1; ++ yypParser->yytos = NULL; ++ yypParser->yystack = NULL; ++ yypParser->yystksz = 0; ++ if( yyGrowStack(yypParser) ){ ++ yypParser->yystack = &yypParser->yystk0; ++ yypParser->yystksz = 1; + } + #endif + #ifndef YYNOERRORRECOVERY +- pParser->yyerrcnt = -1; ++ yypParser->yyerrcnt = -1; + #endif +- pParser->yytos = pParser->yystack; +- pParser->yystack[0].stateno = 0; +- pParser->yystack[0].major = 0; ++ yypParser->yytos = yypParser->yystack; ++ yypParser->yystack[0].stateno = 0; ++ yypParser->yystack[0].major = 0; + #if YYSTACKDEPTH>0 +- pParser->yystackEnd = &pParser->yystack[YYSTACKDEPTH-1]; ++ yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1]; + #endif + } + +@@ -138052,11 +148659,14 @@ + ** A pointer to a parser. This pointer is used in subsequent calls + ** to sqlite3Parser and sqlite3ParserFree. + */ +-SQLITE_PRIVATE void *sqlite3ParserAlloc(void *(*mallocProc)(YYMALLOCARGTYPE)){ +- yyParser *pParser; +- pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); +- if( pParser ) sqlite3ParserInit(pParser); +- return pParser; ++SQLITE_PRIVATE void *sqlite3ParserAlloc(void *(*mallocProc)(YYMALLOCARGTYPE) sqlite3ParserCTX_PDECL){ ++ yyParser *yypParser; ++ yypParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); ++ if( yypParser ){ ++ sqlite3ParserCTX_STORE ++ sqlite3ParserInit(yypParser sqlite3ParserCTX_PARAM); ++ } ++ return (void*)yypParser; + } + #endif /* sqlite3Parser_ENGINEALWAYSONSTACK */ + +@@ -138073,7 +148683,8 @@ + YYCODETYPE yymajor, /* Type code for object to destroy */ + YYMINORTYPE *yypminor /* The object to be destroyed */ + ){ +- sqlite3ParserARG_FETCH; ++ sqlite3ParserARG_FETCH ++ sqlite3ParserCTX_FETCH + switch( yymajor ){ + /* Here is inserted the actions which take place when a + ** terminal or non-terminal is destroyed. This can happen +@@ -138086,79 +148697,98 @@ + ** inside the C code. + */ + /********* Begin destructor definitions ***************************************/ +- case 163: /* select */ +- case 194: /* selectnowith */ +- case 195: /* oneselect */ +- case 206: /* values */ ++ case 174: /* select */ ++ case 206: /* selectnowith */ ++ case 207: /* oneselect */ ++ case 219: /* values */ + { +-sqlite3SelectDelete(pParse->db, (yypminor->yy243)); ++sqlite3SelectDelete(pParse->db, (yypminor->yy489)); + } + break; +- case 172: /* term */ +- case 173: /* expr */ ++ case 184: /* term */ ++ case 185: /* expr */ ++ case 213: /* where_opt */ ++ case 215: /* having_opt */ ++ case 227: /* on_opt */ ++ case 242: /* case_operand */ ++ case 244: /* case_else */ ++ case 253: /* when_clause */ ++ case 258: /* key_opt */ ++ case 272: /* filter_opt */ + { +-sqlite3ExprDelete(pParse->db, (yypminor->yy190).pExpr); ++sqlite3ExprDelete(pParse->db, (yypminor->yy18)); + } + break; +- case 177: /* eidlist_opt */ +- case 186: /* sortlist */ +- case 187: /* eidlist */ +- case 199: /* selcollist */ +- case 202: /* groupby_opt */ +- case 204: /* orderby_opt */ +- case 207: /* nexprlist */ +- case 208: /* exprlist */ +- case 209: /* sclp */ +- case 218: /* setlist */ +- case 224: /* paren_exprlist */ +- case 226: /* case_exprlist */ ++ case 189: /* eidlist_opt */ ++ case 198: /* sortlist */ ++ case 199: /* eidlist */ ++ case 211: /* selcollist */ ++ case 214: /* groupby_opt */ ++ case 216: /* orderby_opt */ ++ case 220: /* nexprlist */ ++ case 221: /* sclp */ ++ case 229: /* exprlist */ ++ case 233: /* setlist */ ++ case 241: /* paren_exprlist */ ++ case 243: /* case_exprlist */ ++ case 271: /* part_opt */ + { +-sqlite3ExprListDelete(pParse->db, (yypminor->yy148)); ++sqlite3ExprListDelete(pParse->db, (yypminor->yy420)); + } + break; +- case 193: /* fullname */ +- case 200: /* from */ +- case 211: /* seltablist */ +- case 212: /* stl_prefix */ ++ case 205: /* fullname */ ++ case 212: /* from */ ++ case 223: /* seltablist */ ++ case 224: /* stl_prefix */ ++ case 230: /* xfullname */ + { +-sqlite3SrcListDelete(pParse->db, (yypminor->yy185)); ++sqlite3SrcListDelete(pParse->db, (yypminor->yy135)); + } + break; +- case 196: /* with */ +- case 250: /* wqlist */ ++ case 208: /* wqlist */ + { +-sqlite3WithDelete(pParse->db, (yypminor->yy285)); ++sqlite3WithDelete(pParse->db, (yypminor->yy449)); + } + break; +- case 201: /* where_opt */ +- case 203: /* having_opt */ +- case 215: /* on_opt */ +- case 225: /* case_operand */ +- case 227: /* case_else */ +- case 236: /* when_clause */ +- case 241: /* key_opt */ ++ case 218: /* window_clause */ ++ case 267: /* windowdefn_list */ + { +-sqlite3ExprDelete(pParse->db, (yypminor->yy72)); ++sqlite3WindowListDelete(pParse->db, (yypminor->yy327)); + } + break; +- case 216: /* using_opt */ +- case 217: /* idlist */ +- case 220: /* idlist_opt */ ++ case 228: /* using_opt */ ++ case 231: /* idlist */ ++ case 235: /* idlist_opt */ + { +-sqlite3IdListDelete(pParse->db, (yypminor->yy254)); ++sqlite3IdListDelete(pParse->db, (yypminor->yy48)); + } + break; +- case 232: /* trigger_cmd_list */ +- case 237: /* trigger_cmd */ ++ case 237: /* over_clause */ ++ case 268: /* windowdefn */ ++ case 269: /* window */ ++ case 270: /* frame_opt */ + { +-sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy145)); ++sqlite3WindowDelete(pParse->db, (yypminor->yy327)); + } + break; +- case 234: /* trigger_event */ ++ case 249: /* trigger_cmd_list */ ++ case 254: /* trigger_cmd */ + { +-sqlite3IdListDelete(pParse->db, (yypminor->yy332).b); ++sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy207)); + } + break; ++ case 251: /* trigger_event */ ++{ ++sqlite3IdListDelete(pParse->db, (yypminor->yy34).b); ++} ++ break; ++ case 274: /* frame_bound */ ++ case 275: /* frame_bound_s */ ++ case 276: /* frame_bound_e */ ++{ ++sqlite3ExprDelete(pParse->db, (yypminor->yy119).pExpr); ++} ++ break; + /********* End destructor definitions *****************************************/ + default: break; /* If no destructor action specified: do nothing */ + } +@@ -138227,24 +148857,66 @@ + } + #endif + ++/* This array of booleans keeps track of the parser statement ++** coverage. The element yycoverage[X][Y] is set when the parser ++** is in state X and has a lookahead token Y. In a well-tested ++** systems, every element of this matrix should end up being set. ++*/ ++#if defined(YYCOVERAGE) ++static unsigned char yycoverage[YYNSTATE][YYNTOKEN]; ++#endif ++ + /* ++** Write into out a description of every state/lookahead combination that ++** ++** (1) has not been used by the parser, and ++** (2) is not a syntax error. ++** ++** Return the number of missed state/lookahead combinations. ++*/ ++#if defined(YYCOVERAGE) ++SQLITE_PRIVATE int sqlite3ParserCoverage(FILE *out){ ++ int stateno, iLookAhead, i; ++ int nMissed = 0; ++ for(stateno=0; stateno<YYNSTATE; stateno++){ ++ i = yy_shift_ofst[stateno]; ++ for(iLookAhead=0; iLookAhead<YYNTOKEN; iLookAhead++){ ++ if( yy_lookahead[i+iLookAhead]!=iLookAhead ) continue; ++ if( yycoverage[stateno][iLookAhead]==0 ) nMissed++; ++ if( out ){ ++ fprintf(out,"State %d lookahead %s %s\n", stateno, ++ yyTokenName[iLookAhead], ++ yycoverage[stateno][iLookAhead] ? "ok" : "missed"); ++ } ++ } ++ } ++ return nMissed; ++} ++#endif ++ ++/* + ** Find the appropriate action for a parser given the terminal + ** look-ahead token iLookAhead. + */ +-static unsigned int yy_find_shift_action( +- yyParser *pParser, /* The parser */ +- YYCODETYPE iLookAhead /* The look-ahead token */ ++static YYACTIONTYPE yy_find_shift_action( ++ YYCODETYPE iLookAhead, /* The look-ahead token */ ++ YYACTIONTYPE stateno /* Current state number */ + ){ + int i; +- int stateno = pParser->yytos->stateno; +- +- if( stateno>=YY_MIN_REDUCE ) return stateno; ++ ++ if( stateno>YY_MAX_SHIFT ) return stateno; + assert( stateno <= YY_SHIFT_COUNT ); ++#if defined(YYCOVERAGE) ++ yycoverage[stateno][iLookAhead] = 1; ++#endif + do{ + i = yy_shift_ofst[stateno]; ++ assert( i>=0 ); ++ /* assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD ); */ + assert( iLookAhead!=YYNOCODE ); ++ assert( iLookAhead < YYNTOKEN ); + i += iLookAhead; +- if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ ++ if( i>=YY_NLOOKAHEAD || yy_lookahead[i]!=iLookAhead ){ + #ifdef YYFALLBACK + YYCODETYPE iFallback; /* Fallback token */ + if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0]) +@@ -138270,6 +148942,7 @@ + #if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT + j<YY_ACTTAB_COUNT && + #endif ++ j<(int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])) && + yy_lookahead[j]==YYWILDCARD && iLookAhead>0 + ){ + #ifndef NDEBUG +@@ -138294,8 +148967,8 @@ + ** Find the appropriate action for a parser given the non-terminal + ** look-ahead token iLookAhead. + */ +-static int yy_find_reduce_action( +- int stateno, /* Current state number */ ++static YYACTIONTYPE yy_find_reduce_action( ++ YYACTIONTYPE stateno, /* Current state number */ + YYCODETYPE iLookAhead /* The look-ahead token */ + ){ + int i; +@@ -138307,7 +148980,6 @@ + assert( stateno<=YY_REDUCE_COUNT ); + #endif + i = yy_reduce_ofst[stateno]; +- assert( i!=YY_REDUCE_USE_DFLT ); + assert( iLookAhead!=YYNOCODE ); + i += iLookAhead; + #ifdef YYERRORSYMBOL +@@ -138325,7 +148997,8 @@ + ** The following routine is called if the stack overflows. + */ + static void yyStackOverflow(yyParser *yypParser){ +- sqlite3ParserARG_FETCH; ++ sqlite3ParserARG_FETCH ++ sqlite3ParserCTX_FETCH + #ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); +@@ -138338,7 +149011,8 @@ + + sqlite3ErrorMsg(pParse, "parser stack overflow"); + /******** End %stack_overflow code ********************************************/ +- sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument var */ ++ sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument var */ ++ sqlite3ParserCTX_STORE + } + + /* +@@ -138345,20 +149019,21 @@ + ** Print tracing information for a SHIFT action + */ + #ifndef NDEBUG +-static void yyTraceShift(yyParser *yypParser, int yyNewState){ ++static void yyTraceShift(yyParser *yypParser, int yyNewState, const char *zTag){ + if( yyTraceFILE ){ + if( yyNewState<YYNSTATE ){ +- fprintf(yyTraceFILE,"%sShift '%s', go to state %d\n", +- yyTracePrompt,yyTokenName[yypParser->yytos->major], ++ fprintf(yyTraceFILE,"%s%s '%s', go to state %d\n", ++ yyTracePrompt, zTag, yyTokenName[yypParser->yytos->major], + yyNewState); + }else{ +- fprintf(yyTraceFILE,"%sShift '%s'\n", +- yyTracePrompt,yyTokenName[yypParser->yytos->major]); ++ fprintf(yyTraceFILE,"%s%s '%s', pending reduce %d\n", ++ yyTracePrompt, zTag, yyTokenName[yypParser->yytos->major], ++ yyNewState - YY_MIN_REDUCE); + } + } + } + #else +-# define yyTraceShift(X,Y) ++# define yyTraceShift(X,Y,Z) + #endif + + /* +@@ -138366,8 +149041,8 @@ + */ + static void yy_shift( + yyParser *yypParser, /* The parser to be shifted */ +- int yyNewState, /* The new state to shift in */ +- int yyMajor, /* The major token to shift in */ ++ YYACTIONTYPE yyNewState, /* The new state to shift in */ ++ YYCODETYPE yyMajor, /* The major token to shift in */ + sqlite3ParserTOKENTYPE yyMinor /* The minor token to shift in */ + ){ + yyStackEntry *yytos; +@@ -138397,10 +149072,10 @@ + yyNewState += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; + } + yytos = yypParser->yytos; +- yytos->stateno = (YYACTIONTYPE)yyNewState; +- yytos->major = (YYCODETYPE)yyMajor; ++ yytos->stateno = yyNewState; ++ yytos->major = yyMajor; + yytos->minor.yy0 = yyMinor; +- yyTraceShift(yypParser, yyNewState); ++ yyTraceShift(yypParser, yyNewState, "Shift"); + } + + /* The following table contains information about every rule that +@@ -138410,335 +149085,373 @@ + YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ + signed char nrhs; /* Negative of the number of RHS symbols in the rule */ + } yyRuleInfo[] = { +- { 147, -1 }, +- { 147, -3 }, +- { 148, -1 }, +- { 149, -3 }, +- { 150, 0 }, +- { 150, -1 }, +- { 150, -1 }, +- { 150, -1 }, +- { 149, -2 }, +- { 149, -2 }, +- { 149, -2 }, +- { 149, -3 }, +- { 149, -5 }, +- { 154, -6 }, +- { 156, -1 }, +- { 158, 0 }, +- { 158, -3 }, +- { 157, -1 }, +- { 157, 0 }, +- { 155, -5 }, +- { 155, -2 }, +- { 162, 0 }, +- { 162, -2 }, +- { 164, -2 }, +- { 166, 0 }, +- { 166, -4 }, +- { 166, -6 }, +- { 167, -2 }, +- { 171, -2 }, +- { 171, -2 }, +- { 171, -4 }, +- { 171, -3 }, +- { 171, -3 }, +- { 171, -2 }, +- { 171, -3 }, +- { 171, -5 }, +- { 171, -2 }, +- { 171, -4 }, +- { 171, -4 }, +- { 171, -1 }, +- { 171, -2 }, +- { 176, 0 }, +- { 176, -1 }, +- { 178, 0 }, +- { 178, -2 }, +- { 180, -2 }, +- { 180, -3 }, +- { 180, -3 }, +- { 180, -3 }, +- { 181, -2 }, +- { 181, -2 }, +- { 181, -1 }, +- { 181, -1 }, +- { 181, -2 }, +- { 179, -3 }, +- { 179, -2 }, +- { 182, 0 }, +- { 182, -2 }, +- { 182, -2 }, +- { 161, 0 }, +- { 184, -1 }, +- { 185, -2 }, +- { 185, -7 }, +- { 185, -5 }, +- { 185, -5 }, +- { 185, -10 }, +- { 188, 0 }, +- { 174, 0 }, +- { 174, -3 }, +- { 189, 0 }, +- { 189, -2 }, +- { 190, -1 }, +- { 190, -1 }, +- { 149, -4 }, +- { 192, -2 }, +- { 192, 0 }, +- { 149, -9 }, +- { 149, -4 }, +- { 149, -1 }, +- { 163, -2 }, +- { 194, -3 }, +- { 197, -1 }, +- { 197, -2 }, +- { 197, -1 }, +- { 195, -9 }, +- { 206, -4 }, +- { 206, -5 }, +- { 198, -1 }, +- { 198, -1 }, +- { 198, 0 }, +- { 209, 0 }, +- { 199, -3 }, +- { 199, -2 }, +- { 199, -4 }, +- { 210, -2 }, +- { 210, 0 }, +- { 200, 0 }, +- { 200, -2 }, +- { 212, -2 }, +- { 212, 0 }, +- { 211, -7 }, +- { 211, -9 }, +- { 211, -7 }, +- { 211, -7 }, +- { 159, 0 }, +- { 159, -2 }, +- { 193, -2 }, +- { 213, -1 }, +- { 213, -2 }, +- { 213, -3 }, +- { 213, -4 }, +- { 215, -2 }, +- { 215, 0 }, +- { 214, 0 }, +- { 214, -3 }, +- { 214, -2 }, +- { 216, -4 }, +- { 216, 0 }, +- { 204, 0 }, +- { 204, -3 }, +- { 186, -4 }, +- { 186, -2 }, +- { 175, -1 }, +- { 175, -1 }, +- { 175, 0 }, +- { 202, 0 }, +- { 202, -3 }, +- { 203, 0 }, +- { 203, -2 }, +- { 205, 0 }, +- { 205, -2 }, +- { 205, -4 }, +- { 205, -4 }, +- { 149, -6 }, +- { 201, 0 }, +- { 201, -2 }, +- { 149, -8 }, +- { 218, -5 }, +- { 218, -7 }, +- { 218, -3 }, +- { 218, -5 }, +- { 149, -6 }, +- { 149, -7 }, +- { 219, -2 }, +- { 219, -1 }, +- { 220, 0 }, +- { 220, -3 }, +- { 217, -3 }, +- { 217, -1 }, +- { 173, -3 }, +- { 173, -1 }, +- { 173, -1 }, +- { 173, -3 }, +- { 173, -5 }, +- { 172, -1 }, +- { 172, -1 }, +- { 172, -1 }, +- { 173, -1 }, +- { 173, -3 }, +- { 173, -6 }, +- { 173, -5 }, +- { 173, -4 }, +- { 172, -1 }, +- { 173, -5 }, +- { 173, -3 }, +- { 173, -3 }, +- { 173, -3 }, +- { 173, -3 }, +- { 173, -3 }, +- { 173, -3 }, +- { 173, -3 }, +- { 173, -3 }, +- { 221, -2 }, +- { 173, -3 }, +- { 173, -5 }, +- { 173, -2 }, +- { 173, -3 }, +- { 173, -3 }, +- { 173, -4 }, +- { 173, -2 }, +- { 173, -2 }, +- { 173, -2 }, +- { 173, -2 }, +- { 222, -1 }, +- { 222, -2 }, +- { 173, -5 }, +- { 223, -1 }, +- { 223, -2 }, +- { 173, -5 }, +- { 173, -3 }, +- { 173, -5 }, +- { 173, -5 }, +- { 173, -4 }, +- { 173, -5 }, +- { 226, -5 }, +- { 226, -4 }, +- { 227, -2 }, +- { 227, 0 }, +- { 225, -1 }, +- { 225, 0 }, +- { 208, 0 }, +- { 207, -3 }, +- { 207, -1 }, +- { 224, 0 }, +- { 224, -3 }, +- { 149, -12 }, +- { 228, -1 }, +- { 228, 0 }, +- { 177, 0 }, +- { 177, -3 }, +- { 187, -5 }, +- { 187, -3 }, +- { 229, 0 }, +- { 229, -2 }, +- { 149, -4 }, +- { 149, -1 }, +- { 149, -2 }, +- { 149, -3 }, +- { 149, -5 }, +- { 149, -6 }, +- { 149, -5 }, +- { 149, -6 }, +- { 169, -2 }, +- { 170, -2 }, +- { 149, -5 }, +- { 231, -11 }, +- { 233, -1 }, +- { 233, -2 }, +- { 233, 0 }, +- { 234, -1 }, +- { 234, -1 }, +- { 234, -3 }, +- { 236, 0 }, +- { 236, -2 }, +- { 232, -3 }, +- { 232, -2 }, +- { 238, -3 }, +- { 239, -3 }, +- { 239, -2 }, +- { 237, -7 }, +- { 237, -5 }, +- { 237, -5 }, +- { 237, -1 }, +- { 173, -4 }, +- { 173, -6 }, +- { 191, -1 }, +- { 191, -1 }, +- { 191, -1 }, +- { 149, -4 }, +- { 149, -6 }, +- { 149, -3 }, +- { 241, 0 }, +- { 241, -2 }, +- { 149, -1 }, +- { 149, -3 }, +- { 149, -1 }, +- { 149, -3 }, +- { 149, -6 }, +- { 149, -7 }, +- { 242, -1 }, +- { 149, -1 }, +- { 149, -4 }, +- { 244, -8 }, +- { 246, 0 }, +- { 247, -1 }, +- { 247, -3 }, +- { 248, -1 }, +- { 196, 0 }, +- { 196, -2 }, +- { 196, -3 }, +- { 250, -6 }, +- { 250, -8 }, +- { 144, -1 }, +- { 145, -2 }, +- { 145, -1 }, +- { 146, -1 }, +- { 146, -3 }, +- { 147, 0 }, +- { 151, 0 }, +- { 151, -1 }, +- { 151, -2 }, +- { 153, -1 }, +- { 153, 0 }, +- { 149, -2 }, +- { 160, -4 }, +- { 160, -2 }, +- { 152, -1 }, +- { 152, -1 }, +- { 152, -1 }, +- { 166, -1 }, +- { 167, -1 }, +- { 168, -1 }, +- { 168, -1 }, +- { 165, -2 }, +- { 165, 0 }, +- { 171, -2 }, +- { 161, -2 }, +- { 183, -3 }, +- { 183, -1 }, +- { 184, 0 }, +- { 188, -1 }, +- { 190, -1 }, +- { 194, -1 }, +- { 195, -1 }, +- { 209, -2 }, +- { 210, -1 }, +- { 173, -1 }, +- { 221, -1 }, +- { 208, -1 }, +- { 230, -1 }, +- { 230, -1 }, +- { 230, -1 }, +- { 230, -1 }, +- { 230, -1 }, +- { 169, -1 }, +- { 235, 0 }, +- { 235, -3 }, +- { 238, -1 }, +- { 239, 0 }, +- { 240, -1 }, +- { 240, 0 }, +- { 243, 0 }, +- { 243, -1 }, +- { 245, -1 }, +- { 245, -3 }, +- { 246, -2 }, +- { 249, 0 }, +- { 249, -4 }, +- { 249, -2 }, ++ { 159, -1 }, /* (0) explain ::= EXPLAIN */ ++ { 159, -3 }, /* (1) explain ::= EXPLAIN QUERY PLAN */ ++ { 158, -1 }, /* (2) cmdx ::= cmd */ ++ { 160, -3 }, /* (3) cmd ::= BEGIN transtype trans_opt */ ++ { 161, 0 }, /* (4) transtype ::= */ ++ { 161, -1 }, /* (5) transtype ::= DEFERRED */ ++ { 161, -1 }, /* (6) transtype ::= IMMEDIATE */ ++ { 161, -1 }, /* (7) transtype ::= EXCLUSIVE */ ++ { 160, -2 }, /* (8) cmd ::= COMMIT|END trans_opt */ ++ { 160, -2 }, /* (9) cmd ::= ROLLBACK trans_opt */ ++ { 160, -2 }, /* (10) cmd ::= SAVEPOINT nm */ ++ { 160, -3 }, /* (11) cmd ::= RELEASE savepoint_opt nm */ ++ { 160, -5 }, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */ ++ { 165, -6 }, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */ ++ { 167, -1 }, /* (14) createkw ::= CREATE */ ++ { 169, 0 }, /* (15) ifnotexists ::= */ ++ { 169, -3 }, /* (16) ifnotexists ::= IF NOT EXISTS */ ++ { 168, -1 }, /* (17) temp ::= TEMP */ ++ { 168, 0 }, /* (18) temp ::= */ ++ { 166, -5 }, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_options */ ++ { 166, -2 }, /* (20) create_table_args ::= AS select */ ++ { 173, 0 }, /* (21) table_options ::= */ ++ { 173, -2 }, /* (22) table_options ::= WITHOUT nm */ ++ { 175, -2 }, /* (23) columnname ::= nm typetoken */ ++ { 177, 0 }, /* (24) typetoken ::= */ ++ { 177, -4 }, /* (25) typetoken ::= typename LP signed RP */ ++ { 177, -6 }, /* (26) typetoken ::= typename LP signed COMMA signed RP */ ++ { 178, -2 }, /* (27) typename ::= typename ID|STRING */ ++ { 182, 0 }, /* (28) scanpt ::= */ ++ { 183, -2 }, /* (29) ccons ::= CONSTRAINT nm */ ++ { 183, -4 }, /* (30) ccons ::= DEFAULT scanpt term scanpt */ ++ { 183, -4 }, /* (31) ccons ::= DEFAULT LP expr RP */ ++ { 183, -4 }, /* (32) ccons ::= DEFAULT PLUS term scanpt */ ++ { 183, -4 }, /* (33) ccons ::= DEFAULT MINUS term scanpt */ ++ { 183, -3 }, /* (34) ccons ::= DEFAULT scanpt ID|INDEXED */ ++ { 183, -3 }, /* (35) ccons ::= NOT NULL onconf */ ++ { 183, -5 }, /* (36) ccons ::= PRIMARY KEY sortorder onconf autoinc */ ++ { 183, -2 }, /* (37) ccons ::= UNIQUE onconf */ ++ { 183, -4 }, /* (38) ccons ::= CHECK LP expr RP */ ++ { 183, -4 }, /* (39) ccons ::= REFERENCES nm eidlist_opt refargs */ ++ { 183, -1 }, /* (40) ccons ::= defer_subclause */ ++ { 183, -2 }, /* (41) ccons ::= COLLATE ID|STRING */ ++ { 188, 0 }, /* (42) autoinc ::= */ ++ { 188, -1 }, /* (43) autoinc ::= AUTOINCR */ ++ { 190, 0 }, /* (44) refargs ::= */ ++ { 190, -2 }, /* (45) refargs ::= refargs refarg */ ++ { 192, -2 }, /* (46) refarg ::= MATCH nm */ ++ { 192, -3 }, /* (47) refarg ::= ON INSERT refact */ ++ { 192, -3 }, /* (48) refarg ::= ON DELETE refact */ ++ { 192, -3 }, /* (49) refarg ::= ON UPDATE refact */ ++ { 193, -2 }, /* (50) refact ::= SET NULL */ ++ { 193, -2 }, /* (51) refact ::= SET DEFAULT */ ++ { 193, -1 }, /* (52) refact ::= CASCADE */ ++ { 193, -1 }, /* (53) refact ::= RESTRICT */ ++ { 193, -2 }, /* (54) refact ::= NO ACTION */ ++ { 191, -3 }, /* (55) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ ++ { 191, -2 }, /* (56) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ ++ { 194, 0 }, /* (57) init_deferred_pred_opt ::= */ ++ { 194, -2 }, /* (58) init_deferred_pred_opt ::= INITIALLY DEFERRED */ ++ { 194, -2 }, /* (59) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ ++ { 172, 0 }, /* (60) conslist_opt ::= */ ++ { 196, -1 }, /* (61) tconscomma ::= COMMA */ ++ { 197, -2 }, /* (62) tcons ::= CONSTRAINT nm */ ++ { 197, -7 }, /* (63) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ ++ { 197, -5 }, /* (64) tcons ::= UNIQUE LP sortlist RP onconf */ ++ { 197, -5 }, /* (65) tcons ::= CHECK LP expr RP onconf */ ++ { 197, -10 }, /* (66) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ ++ { 200, 0 }, /* (67) defer_subclause_opt ::= */ ++ { 186, 0 }, /* (68) onconf ::= */ ++ { 186, -3 }, /* (69) onconf ::= ON CONFLICT resolvetype */ ++ { 201, 0 }, /* (70) orconf ::= */ ++ { 201, -2 }, /* (71) orconf ::= OR resolvetype */ ++ { 202, -1 }, /* (72) resolvetype ::= IGNORE */ ++ { 202, -1 }, /* (73) resolvetype ::= REPLACE */ ++ { 160, -4 }, /* (74) cmd ::= DROP TABLE ifexists fullname */ ++ { 204, -2 }, /* (75) ifexists ::= IF EXISTS */ ++ { 204, 0 }, /* (76) ifexists ::= */ ++ { 160, -9 }, /* (77) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ ++ { 160, -4 }, /* (78) cmd ::= DROP VIEW ifexists fullname */ ++ { 160, -1 }, /* (79) cmd ::= select */ ++ { 174, -3 }, /* (80) select ::= WITH wqlist selectnowith */ ++ { 174, -4 }, /* (81) select ::= WITH RECURSIVE wqlist selectnowith */ ++ { 174, -1 }, /* (82) select ::= selectnowith */ ++ { 206, -3 }, /* (83) selectnowith ::= selectnowith multiselect_op oneselect */ ++ { 209, -1 }, /* (84) multiselect_op ::= UNION */ ++ { 209, -2 }, /* (85) multiselect_op ::= UNION ALL */ ++ { 209, -1 }, /* (86) multiselect_op ::= EXCEPT|INTERSECT */ ++ { 207, -9 }, /* (87) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ ++ { 207, -10 }, /* (88) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ ++ { 219, -4 }, /* (89) values ::= VALUES LP nexprlist RP */ ++ { 219, -5 }, /* (90) values ::= values COMMA LP nexprlist RP */ ++ { 210, -1 }, /* (91) distinct ::= DISTINCT */ ++ { 210, -1 }, /* (92) distinct ::= ALL */ ++ { 210, 0 }, /* (93) distinct ::= */ ++ { 221, 0 }, /* (94) sclp ::= */ ++ { 211, -5 }, /* (95) selcollist ::= sclp scanpt expr scanpt as */ ++ { 211, -3 }, /* (96) selcollist ::= sclp scanpt STAR */ ++ { 211, -5 }, /* (97) selcollist ::= sclp scanpt nm DOT STAR */ ++ { 222, -2 }, /* (98) as ::= AS nm */ ++ { 222, 0 }, /* (99) as ::= */ ++ { 212, 0 }, /* (100) from ::= */ ++ { 212, -2 }, /* (101) from ::= FROM seltablist */ ++ { 224, -2 }, /* (102) stl_prefix ::= seltablist joinop */ ++ { 224, 0 }, /* (103) stl_prefix ::= */ ++ { 223, -7 }, /* (104) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ ++ { 223, -9 }, /* (105) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */ ++ { 223, -7 }, /* (106) seltablist ::= stl_prefix LP select RP as on_opt using_opt */ ++ { 223, -7 }, /* (107) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ ++ { 170, 0 }, /* (108) dbnm ::= */ ++ { 170, -2 }, /* (109) dbnm ::= DOT nm */ ++ { 205, -1 }, /* (110) fullname ::= nm */ ++ { 205, -3 }, /* (111) fullname ::= nm DOT nm */ ++ { 230, -1 }, /* (112) xfullname ::= nm */ ++ { 230, -3 }, /* (113) xfullname ::= nm DOT nm */ ++ { 230, -5 }, /* (114) xfullname ::= nm DOT nm AS nm */ ++ { 230, -3 }, /* (115) xfullname ::= nm AS nm */ ++ { 225, -1 }, /* (116) joinop ::= COMMA|JOIN */ ++ { 225, -2 }, /* (117) joinop ::= JOIN_KW JOIN */ ++ { 225, -3 }, /* (118) joinop ::= JOIN_KW nm JOIN */ ++ { 225, -4 }, /* (119) joinop ::= JOIN_KW nm nm JOIN */ ++ { 227, -2 }, /* (120) on_opt ::= ON expr */ ++ { 227, 0 }, /* (121) on_opt ::= */ ++ { 226, 0 }, /* (122) indexed_opt ::= */ ++ { 226, -3 }, /* (123) indexed_opt ::= INDEXED BY nm */ ++ { 226, -2 }, /* (124) indexed_opt ::= NOT INDEXED */ ++ { 228, -4 }, /* (125) using_opt ::= USING LP idlist RP */ ++ { 228, 0 }, /* (126) using_opt ::= */ ++ { 216, 0 }, /* (127) orderby_opt ::= */ ++ { 216, -3 }, /* (128) orderby_opt ::= ORDER BY sortlist */ ++ { 198, -4 }, /* (129) sortlist ::= sortlist COMMA expr sortorder */ ++ { 198, -2 }, /* (130) sortlist ::= expr sortorder */ ++ { 187, -1 }, /* (131) sortorder ::= ASC */ ++ { 187, -1 }, /* (132) sortorder ::= DESC */ ++ { 187, 0 }, /* (133) sortorder ::= */ ++ { 214, 0 }, /* (134) groupby_opt ::= */ ++ { 214, -3 }, /* (135) groupby_opt ::= GROUP BY nexprlist */ ++ { 215, 0 }, /* (136) having_opt ::= */ ++ { 215, -2 }, /* (137) having_opt ::= HAVING expr */ ++ { 217, 0 }, /* (138) limit_opt ::= */ ++ { 217, -2 }, /* (139) limit_opt ::= LIMIT expr */ ++ { 217, -4 }, /* (140) limit_opt ::= LIMIT expr OFFSET expr */ ++ { 217, -4 }, /* (141) limit_opt ::= LIMIT expr COMMA expr */ ++ { 160, -6 }, /* (142) cmd ::= with DELETE FROM xfullname indexed_opt where_opt */ ++ { 213, 0 }, /* (143) where_opt ::= */ ++ { 213, -2 }, /* (144) where_opt ::= WHERE expr */ ++ { 160, -8 }, /* (145) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */ ++ { 233, -5 }, /* (146) setlist ::= setlist COMMA nm EQ expr */ ++ { 233, -7 }, /* (147) setlist ::= setlist COMMA LP idlist RP EQ expr */ ++ { 233, -3 }, /* (148) setlist ::= nm EQ expr */ ++ { 233, -5 }, /* (149) setlist ::= LP idlist RP EQ expr */ ++ { 160, -7 }, /* (150) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ ++ { 160, -7 }, /* (151) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */ ++ { 236, 0 }, /* (152) upsert ::= */ ++ { 236, -11 }, /* (153) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */ ++ { 236, -8 }, /* (154) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */ ++ { 236, -4 }, /* (155) upsert ::= ON CONFLICT DO NOTHING */ ++ { 234, -2 }, /* (156) insert_cmd ::= INSERT orconf */ ++ { 234, -1 }, /* (157) insert_cmd ::= REPLACE */ ++ { 235, 0 }, /* (158) idlist_opt ::= */ ++ { 235, -3 }, /* (159) idlist_opt ::= LP idlist RP */ ++ { 231, -3 }, /* (160) idlist ::= idlist COMMA nm */ ++ { 231, -1 }, /* (161) idlist ::= nm */ ++ { 185, -3 }, /* (162) expr ::= LP expr RP */ ++ { 185, -1 }, /* (163) expr ::= ID|INDEXED */ ++ { 185, -1 }, /* (164) expr ::= JOIN_KW */ ++ { 185, -3 }, /* (165) expr ::= nm DOT nm */ ++ { 185, -5 }, /* (166) expr ::= nm DOT nm DOT nm */ ++ { 184, -1 }, /* (167) term ::= NULL|FLOAT|BLOB */ ++ { 184, -1 }, /* (168) term ::= STRING */ ++ { 184, -1 }, /* (169) term ::= INTEGER */ ++ { 185, -1 }, /* (170) expr ::= VARIABLE */ ++ { 185, -3 }, /* (171) expr ::= expr COLLATE ID|STRING */ ++ { 185, -6 }, /* (172) expr ::= CAST LP expr AS typetoken RP */ ++ { 185, -5 }, /* (173) expr ::= ID|INDEXED LP distinct exprlist RP */ ++ { 185, -4 }, /* (174) expr ::= ID|INDEXED LP STAR RP */ ++ { 185, -6 }, /* (175) expr ::= ID|INDEXED LP distinct exprlist RP over_clause */ ++ { 185, -5 }, /* (176) expr ::= ID|INDEXED LP STAR RP over_clause */ ++ { 184, -1 }, /* (177) term ::= CTIME_KW */ ++ { 185, -5 }, /* (178) expr ::= LP nexprlist COMMA expr RP */ ++ { 185, -3 }, /* (179) expr ::= expr AND expr */ ++ { 185, -3 }, /* (180) expr ::= expr OR expr */ ++ { 185, -3 }, /* (181) expr ::= expr LT|GT|GE|LE expr */ ++ { 185, -3 }, /* (182) expr ::= expr EQ|NE expr */ ++ { 185, -3 }, /* (183) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ ++ { 185, -3 }, /* (184) expr ::= expr PLUS|MINUS expr */ ++ { 185, -3 }, /* (185) expr ::= expr STAR|SLASH|REM expr */ ++ { 185, -3 }, /* (186) expr ::= expr CONCAT expr */ ++ { 238, -2 }, /* (187) likeop ::= NOT LIKE_KW|MATCH */ ++ { 185, -3 }, /* (188) expr ::= expr likeop expr */ ++ { 185, -5 }, /* (189) expr ::= expr likeop expr ESCAPE expr */ ++ { 185, -2 }, /* (190) expr ::= expr ISNULL|NOTNULL */ ++ { 185, -3 }, /* (191) expr ::= expr NOT NULL */ ++ { 185, -3 }, /* (192) expr ::= expr IS expr */ ++ { 185, -4 }, /* (193) expr ::= expr IS NOT expr */ ++ { 185, -2 }, /* (194) expr ::= NOT expr */ ++ { 185, -2 }, /* (195) expr ::= BITNOT expr */ ++ { 185, -2 }, /* (196) expr ::= PLUS|MINUS expr */ ++ { 239, -1 }, /* (197) between_op ::= BETWEEN */ ++ { 239, -2 }, /* (198) between_op ::= NOT BETWEEN */ ++ { 185, -5 }, /* (199) expr ::= expr between_op expr AND expr */ ++ { 240, -1 }, /* (200) in_op ::= IN */ ++ { 240, -2 }, /* (201) in_op ::= NOT IN */ ++ { 185, -5 }, /* (202) expr ::= expr in_op LP exprlist RP */ ++ { 185, -3 }, /* (203) expr ::= LP select RP */ ++ { 185, -5 }, /* (204) expr ::= expr in_op LP select RP */ ++ { 185, -5 }, /* (205) expr ::= expr in_op nm dbnm paren_exprlist */ ++ { 185, -4 }, /* (206) expr ::= EXISTS LP select RP */ ++ { 185, -5 }, /* (207) expr ::= CASE case_operand case_exprlist case_else END */ ++ { 243, -5 }, /* (208) case_exprlist ::= case_exprlist WHEN expr THEN expr */ ++ { 243, -4 }, /* (209) case_exprlist ::= WHEN expr THEN expr */ ++ { 244, -2 }, /* (210) case_else ::= ELSE expr */ ++ { 244, 0 }, /* (211) case_else ::= */ ++ { 242, -1 }, /* (212) case_operand ::= expr */ ++ { 242, 0 }, /* (213) case_operand ::= */ ++ { 229, 0 }, /* (214) exprlist ::= */ ++ { 220, -3 }, /* (215) nexprlist ::= nexprlist COMMA expr */ ++ { 220, -1 }, /* (216) nexprlist ::= expr */ ++ { 241, 0 }, /* (217) paren_exprlist ::= */ ++ { 241, -3 }, /* (218) paren_exprlist ::= LP exprlist RP */ ++ { 160, -12 }, /* (219) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ ++ { 245, -1 }, /* (220) uniqueflag ::= UNIQUE */ ++ { 245, 0 }, /* (221) uniqueflag ::= */ ++ { 189, 0 }, /* (222) eidlist_opt ::= */ ++ { 189, -3 }, /* (223) eidlist_opt ::= LP eidlist RP */ ++ { 199, -5 }, /* (224) eidlist ::= eidlist COMMA nm collate sortorder */ ++ { 199, -3 }, /* (225) eidlist ::= nm collate sortorder */ ++ { 246, 0 }, /* (226) collate ::= */ ++ { 246, -2 }, /* (227) collate ::= COLLATE ID|STRING */ ++ { 160, -4 }, /* (228) cmd ::= DROP INDEX ifexists fullname */ ++ { 160, -1 }, /* (229) cmd ::= VACUUM */ ++ { 160, -2 }, /* (230) cmd ::= VACUUM nm */ ++ { 160, -3 }, /* (231) cmd ::= PRAGMA nm dbnm */ ++ { 160, -5 }, /* (232) cmd ::= PRAGMA nm dbnm EQ nmnum */ ++ { 160, -6 }, /* (233) cmd ::= PRAGMA nm dbnm LP nmnum RP */ ++ { 160, -5 }, /* (234) cmd ::= PRAGMA nm dbnm EQ minus_num */ ++ { 160, -6 }, /* (235) cmd ::= PRAGMA nm dbnm LP minus_num RP */ ++ { 180, -2 }, /* (236) plus_num ::= PLUS INTEGER|FLOAT */ ++ { 181, -2 }, /* (237) minus_num ::= MINUS INTEGER|FLOAT */ ++ { 160, -5 }, /* (238) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ ++ { 248, -11 }, /* (239) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ ++ { 250, -1 }, /* (240) trigger_time ::= BEFORE|AFTER */ ++ { 250, -2 }, /* (241) trigger_time ::= INSTEAD OF */ ++ { 250, 0 }, /* (242) trigger_time ::= */ ++ { 251, -1 }, /* (243) trigger_event ::= DELETE|INSERT */ ++ { 251, -1 }, /* (244) trigger_event ::= UPDATE */ ++ { 251, -3 }, /* (245) trigger_event ::= UPDATE OF idlist */ ++ { 253, 0 }, /* (246) when_clause ::= */ ++ { 253, -2 }, /* (247) when_clause ::= WHEN expr */ ++ { 249, -3 }, /* (248) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ ++ { 249, -2 }, /* (249) trigger_cmd_list ::= trigger_cmd SEMI */ ++ { 255, -3 }, /* (250) trnm ::= nm DOT nm */ ++ { 256, -3 }, /* (251) tridxby ::= INDEXED BY nm */ ++ { 256, -2 }, /* (252) tridxby ::= NOT INDEXED */ ++ { 254, -8 }, /* (253) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */ ++ { 254, -8 }, /* (254) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ ++ { 254, -6 }, /* (255) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ ++ { 254, -3 }, /* (256) trigger_cmd ::= scanpt select scanpt */ ++ { 185, -4 }, /* (257) expr ::= RAISE LP IGNORE RP */ ++ { 185, -6 }, /* (258) expr ::= RAISE LP raisetype COMMA nm RP */ ++ { 203, -1 }, /* (259) raisetype ::= ROLLBACK */ ++ { 203, -1 }, /* (260) raisetype ::= ABORT */ ++ { 203, -1 }, /* (261) raisetype ::= FAIL */ ++ { 160, -4 }, /* (262) cmd ::= DROP TRIGGER ifexists fullname */ ++ { 160, -6 }, /* (263) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ ++ { 160, -3 }, /* (264) cmd ::= DETACH database_kw_opt expr */ ++ { 258, 0 }, /* (265) key_opt ::= */ ++ { 258, -2 }, /* (266) key_opt ::= KEY expr */ ++ { 160, -1 }, /* (267) cmd ::= REINDEX */ ++ { 160, -3 }, /* (268) cmd ::= REINDEX nm dbnm */ ++ { 160, -1 }, /* (269) cmd ::= ANALYZE */ ++ { 160, -3 }, /* (270) cmd ::= ANALYZE nm dbnm */ ++ { 160, -6 }, /* (271) cmd ::= ALTER TABLE fullname RENAME TO nm */ ++ { 160, -7 }, /* (272) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ ++ { 259, -1 }, /* (273) add_column_fullname ::= fullname */ ++ { 160, -8 }, /* (274) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ ++ { 160, -1 }, /* (275) cmd ::= create_vtab */ ++ { 160, -4 }, /* (276) cmd ::= create_vtab LP vtabarglist RP */ ++ { 261, -8 }, /* (277) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ ++ { 263, 0 }, /* (278) vtabarg ::= */ ++ { 264, -1 }, /* (279) vtabargtoken ::= ANY */ ++ { 264, -3 }, /* (280) vtabargtoken ::= lp anylist RP */ ++ { 265, -1 }, /* (281) lp ::= LP */ ++ { 232, -2 }, /* (282) with ::= WITH wqlist */ ++ { 232, -3 }, /* (283) with ::= WITH RECURSIVE wqlist */ ++ { 208, -6 }, /* (284) wqlist ::= nm eidlist_opt AS LP select RP */ ++ { 208, -8 }, /* (285) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ ++ { 267, -1 }, /* (286) windowdefn_list ::= windowdefn */ ++ { 267, -3 }, /* (287) windowdefn_list ::= windowdefn_list COMMA windowdefn */ ++ { 268, -3 }, /* (288) windowdefn ::= nm AS window */ ++ { 269, -5 }, /* (289) window ::= LP part_opt orderby_opt frame_opt RP */ ++ { 271, -3 }, /* (290) part_opt ::= PARTITION BY nexprlist */ ++ { 271, 0 }, /* (291) part_opt ::= */ ++ { 270, 0 }, /* (292) frame_opt ::= */ ++ { 270, -2 }, /* (293) frame_opt ::= range_or_rows frame_bound_s */ ++ { 270, -5 }, /* (294) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e */ ++ { 273, -1 }, /* (295) range_or_rows ::= RANGE */ ++ { 273, -1 }, /* (296) range_or_rows ::= ROWS */ ++ { 275, -1 }, /* (297) frame_bound_s ::= frame_bound */ ++ { 275, -2 }, /* (298) frame_bound_s ::= UNBOUNDED PRECEDING */ ++ { 276, -1 }, /* (299) frame_bound_e ::= frame_bound */ ++ { 276, -2 }, /* (300) frame_bound_e ::= UNBOUNDED FOLLOWING */ ++ { 274, -2 }, /* (301) frame_bound ::= expr PRECEDING */ ++ { 274, -2 }, /* (302) frame_bound ::= CURRENT ROW */ ++ { 274, -2 }, /* (303) frame_bound ::= expr FOLLOWING */ ++ { 218, -2 }, /* (304) window_clause ::= WINDOW windowdefn_list */ ++ { 237, -3 }, /* (305) over_clause ::= filter_opt OVER window */ ++ { 237, -3 }, /* (306) over_clause ::= filter_opt OVER nm */ ++ { 272, 0 }, /* (307) filter_opt ::= */ ++ { 272, -5 }, /* (308) filter_opt ::= FILTER LP WHERE expr RP */ ++ { 155, -1 }, /* (309) input ::= cmdlist */ ++ { 156, -2 }, /* (310) cmdlist ::= cmdlist ecmd */ ++ { 156, -1 }, /* (311) cmdlist ::= ecmd */ ++ { 157, -1 }, /* (312) ecmd ::= SEMI */ ++ { 157, -2 }, /* (313) ecmd ::= cmdx SEMI */ ++ { 157, -2 }, /* (314) ecmd ::= explain cmdx */ ++ { 162, 0 }, /* (315) trans_opt ::= */ ++ { 162, -1 }, /* (316) trans_opt ::= TRANSACTION */ ++ { 162, -2 }, /* (317) trans_opt ::= TRANSACTION nm */ ++ { 164, -1 }, /* (318) savepoint_opt ::= SAVEPOINT */ ++ { 164, 0 }, /* (319) savepoint_opt ::= */ ++ { 160, -2 }, /* (320) cmd ::= create_table create_table_args */ ++ { 171, -4 }, /* (321) columnlist ::= columnlist COMMA columnname carglist */ ++ { 171, -2 }, /* (322) columnlist ::= columnname carglist */ ++ { 163, -1 }, /* (323) nm ::= ID|INDEXED */ ++ { 163, -1 }, /* (324) nm ::= STRING */ ++ { 163, -1 }, /* (325) nm ::= JOIN_KW */ ++ { 177, -1 }, /* (326) typetoken ::= typename */ ++ { 178, -1 }, /* (327) typename ::= ID|STRING */ ++ { 179, -1 }, /* (328) signed ::= plus_num */ ++ { 179, -1 }, /* (329) signed ::= minus_num */ ++ { 176, -2 }, /* (330) carglist ::= carglist ccons */ ++ { 176, 0 }, /* (331) carglist ::= */ ++ { 183, -2 }, /* (332) ccons ::= NULL onconf */ ++ { 172, -2 }, /* (333) conslist_opt ::= COMMA conslist */ ++ { 195, -3 }, /* (334) conslist ::= conslist tconscomma tcons */ ++ { 195, -1 }, /* (335) conslist ::= tcons */ ++ { 196, 0 }, /* (336) tconscomma ::= */ ++ { 200, -1 }, /* (337) defer_subclause_opt ::= defer_subclause */ ++ { 202, -1 }, /* (338) resolvetype ::= raisetype */ ++ { 206, -1 }, /* (339) selectnowith ::= oneselect */ ++ { 207, -1 }, /* (340) oneselect ::= values */ ++ { 221, -2 }, /* (341) sclp ::= selcollist COMMA */ ++ { 222, -1 }, /* (342) as ::= ID|STRING */ ++ { 185, -1 }, /* (343) expr ::= term */ ++ { 238, -1 }, /* (344) likeop ::= LIKE_KW|MATCH */ ++ { 229, -1 }, /* (345) exprlist ::= nexprlist */ ++ { 247, -1 }, /* (346) nmnum ::= plus_num */ ++ { 247, -1 }, /* (347) nmnum ::= nm */ ++ { 247, -1 }, /* (348) nmnum ::= ON */ ++ { 247, -1 }, /* (349) nmnum ::= DELETE */ ++ { 247, -1 }, /* (350) nmnum ::= DEFAULT */ ++ { 180, -1 }, /* (351) plus_num ::= INTEGER|FLOAT */ ++ { 252, 0 }, /* (352) foreach_clause ::= */ ++ { 252, -3 }, /* (353) foreach_clause ::= FOR EACH ROW */ ++ { 255, -1 }, /* (354) trnm ::= nm */ ++ { 256, 0 }, /* (355) tridxby ::= */ ++ { 257, -1 }, /* (356) database_kw_opt ::= DATABASE */ ++ { 257, 0 }, /* (357) database_kw_opt ::= */ ++ { 260, 0 }, /* (358) kwcolumn_opt ::= */ ++ { 260, -1 }, /* (359) kwcolumn_opt ::= COLUMNKW */ ++ { 262, -1 }, /* (360) vtabarglist ::= vtabarg */ ++ { 262, -3 }, /* (361) vtabarglist ::= vtabarglist COMMA vtabarg */ ++ { 263, -2 }, /* (362) vtabarg ::= vtabarg vtabargtoken */ ++ { 266, 0 }, /* (363) anylist ::= */ ++ { 266, -4 }, /* (364) anylist ::= anylist LP anylist RP */ ++ { 266, -2 }, /* (365) anylist ::= anylist ANY */ ++ { 232, 0 }, /* (366) with ::= */ + }; + + static void yy_accept(yyParser*); /* Forward Declaration */ +@@ -138746,22 +149459,39 @@ + /* + ** Perform a reduce action and the shift that must immediately + ** follow the reduce. ++** ++** The yyLookahead and yyLookaheadToken parameters provide reduce actions ++** access to the lookahead token (if any). The yyLookahead will be YYNOCODE ++** if the lookahead token has already been consumed. As this procedure is ++** only called from one place, optimizing compilers will in-line it, which ++** means that the extra parameters have no performance impact. + */ +-static void yy_reduce( ++static YYACTIONTYPE yy_reduce( + yyParser *yypParser, /* The parser */ +- unsigned int yyruleno /* Number of the rule by which to reduce */ ++ unsigned int yyruleno, /* Number of the rule by which to reduce */ ++ int yyLookahead, /* Lookahead token, or YYNOCODE if none */ ++ sqlite3ParserTOKENTYPE yyLookaheadToken /* Value of the lookahead token */ ++ sqlite3ParserCTX_PDECL /* %extra_context */ + ){ + int yygoto; /* The next state */ +- int yyact; /* The next action */ ++ YYACTIONTYPE yyact; /* The next action */ + yyStackEntry *yymsp; /* The top of the parser's stack */ + int yysize; /* Amount to pop the stack */ +- sqlite3ParserARG_FETCH; ++ sqlite3ParserARG_FETCH ++ (void)yyLookahead; ++ (void)yyLookaheadToken; + yymsp = yypParser->yytos; + #ifndef NDEBUG + if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ + yysize = yyRuleInfo[yyruleno].nrhs; +- fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt, +- yyRuleName[yyruleno], yymsp[yysize].stateno); ++ if( yysize ){ ++ fprintf(yyTraceFILE, "%sReduce %d [%s], go to state %d.\n", ++ yyTracePrompt, ++ yyruleno, yyRuleName[yyruleno], yymsp[yysize].stateno); ++ }else{ ++ fprintf(yyTraceFILE, "%sReduce %d [%s].\n", ++ yyTracePrompt, yyruleno, yyRuleName[yyruleno]); ++ } + } + #endif /* NDEBUG */ + +@@ -138778,13 +149508,19 @@ + #if YYSTACKDEPTH>0 + if( yypParser->yytos>=yypParser->yystackEnd ){ + yyStackOverflow(yypParser); +- return; ++ /* The call to yyStackOverflow() above pops the stack until it is ++ ** empty, causing the main parser loop to exit. So the return value ++ ** is never used and does not matter. */ ++ return 0; + } + #else + if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){ + if( yyGrowStack(yypParser) ){ + yyStackOverflow(yypParser); +- return; ++ /* The call to yyStackOverflow() above pops the stack until it is ++ ** empty, causing the main parser loop to exit. So the return value ++ ** is never used and does not matter. */ ++ return 0; + } + yymsp = yypParser->yytos; + } +@@ -138812,15 +149548,15 @@ + { sqlite3FinishCoding(pParse); } + break; + case 3: /* cmd ::= BEGIN transtype trans_opt */ +-{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy194);} ++{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy70);} + break; + case 4: /* transtype ::= */ +-{yymsp[1].minor.yy194 = TK_DEFERRED;} ++{yymsp[1].minor.yy70 = TK_DEFERRED;} + break; + case 5: /* transtype ::= DEFERRED */ + case 6: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==6); + case 7: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7); +-{yymsp[0].minor.yy194 = yymsp[0].major; /*A-overwrites-X*/} ++{yymsp[0].minor.yy70 = yymsp[0].major; /*A-overwrites-X*/} + break; + case 8: /* cmd ::= COMMIT|END trans_opt */ + case 9: /* cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==9); +@@ -138843,7 +149579,7 @@ + break; + case 13: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */ + { +- sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy194,0,0,yymsp[-2].minor.yy194); ++ sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy70,0,0,yymsp[-2].minor.yy70); + } + break; + case 14: /* createkw ::= CREATE */ +@@ -138852,38 +149588,38 @@ + case 15: /* ifnotexists ::= */ + case 18: /* temp ::= */ yytestcase(yyruleno==18); + case 21: /* table_options ::= */ yytestcase(yyruleno==21); +- case 41: /* autoinc ::= */ yytestcase(yyruleno==41); +- case 56: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==56); +- case 66: /* defer_subclause_opt ::= */ yytestcase(yyruleno==66); +- case 75: /* ifexists ::= */ yytestcase(yyruleno==75); +- case 89: /* distinct ::= */ yytestcase(yyruleno==89); +- case 212: /* collate ::= */ yytestcase(yyruleno==212); +-{yymsp[1].minor.yy194 = 0;} ++ case 42: /* autoinc ::= */ yytestcase(yyruleno==42); ++ case 57: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==57); ++ case 67: /* defer_subclause_opt ::= */ yytestcase(yyruleno==67); ++ case 76: /* ifexists ::= */ yytestcase(yyruleno==76); ++ case 93: /* distinct ::= */ yytestcase(yyruleno==93); ++ case 226: /* collate ::= */ yytestcase(yyruleno==226); ++{yymsp[1].minor.yy70 = 0;} + break; + case 16: /* ifnotexists ::= IF NOT EXISTS */ +-{yymsp[-2].minor.yy194 = 1;} ++{yymsp[-2].minor.yy70 = 1;} + break; + case 17: /* temp ::= TEMP */ +- case 42: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==42); +-{yymsp[0].minor.yy194 = 1;} ++ case 43: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==43); ++{yymsp[0].minor.yy70 = 1;} + break; + case 19: /* create_table_args ::= LP columnlist conslist_opt RP table_options */ + { +- sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy194,0); ++ sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy70,0); + } + break; + case 20: /* create_table_args ::= AS select */ + { +- sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy243); +- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy243); ++ sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy489); ++ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy489); + } + break; + case 22: /* table_options ::= WITHOUT nm */ + { + if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){ +- yymsp[-1].minor.yy194 = TF_WithoutRowid | TF_NoVisibleRowid; ++ yymsp[-1].minor.yy70 = TF_WithoutRowid | TF_NoVisibleRowid; + }else{ +- yymsp[-1].minor.yy194 = 0; ++ yymsp[-1].minor.yy70 = 0; + sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z); + } + } +@@ -138892,8 +149628,8 @@ + {sqlite3AddColumn(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);} + break; + case 24: /* typetoken ::= */ +- case 59: /* conslist_opt ::= */ yytestcase(yyruleno==59); +- case 95: /* as ::= */ yytestcase(yyruleno==95); ++ case 60: /* conslist_opt ::= */ yytestcase(yyruleno==60); ++ case 99: /* as ::= */ yytestcase(yyruleno==99); + {yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = 0;} + break; + case 25: /* typetoken ::= typename LP signed RP */ +@@ -138909,177 +149645,206 @@ + case 27: /* typename ::= typename ID|STRING */ + {yymsp[-1].minor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);} + break; +- case 28: /* ccons ::= CONSTRAINT nm */ +- case 61: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==61); ++ case 28: /* scanpt ::= */ ++{ ++ assert( yyLookahead!=YYNOCODE ); ++ yymsp[1].minor.yy392 = yyLookaheadToken.z; ++} ++ break; ++ case 29: /* ccons ::= CONSTRAINT nm */ ++ case 62: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==62); + {pParse->constraintName = yymsp[0].minor.yy0;} + break; +- case 29: /* ccons ::= DEFAULT term */ +- case 31: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==31); +-{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy190);} ++ case 30: /* ccons ::= DEFAULT scanpt term scanpt */ ++{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy18,yymsp[-2].minor.yy392,yymsp[0].minor.yy392);} + break; +- case 30: /* ccons ::= DEFAULT LP expr RP */ +-{sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy190);} ++ case 31: /* ccons ::= DEFAULT LP expr RP */ ++{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy18,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);} + break; +- case 32: /* ccons ::= DEFAULT MINUS term */ ++ case 32: /* ccons ::= DEFAULT PLUS term scanpt */ ++{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy18,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy392);} ++ break; ++ case 33: /* ccons ::= DEFAULT MINUS term scanpt */ + { +- ExprSpan v; +- v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy190.pExpr, 0); +- v.zStart = yymsp[-1].minor.yy0.z; +- v.zEnd = yymsp[0].minor.yy190.zEnd; +- sqlite3AddDefaultValue(pParse,&v); ++ Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[-1].minor.yy18, 0); ++ sqlite3AddDefaultValue(pParse,p,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy392); + } + break; +- case 33: /* ccons ::= DEFAULT ID|INDEXED */ ++ case 34: /* ccons ::= DEFAULT scanpt ID|INDEXED */ + { +- ExprSpan v; +- spanExpr(&v, pParse, TK_STRING, yymsp[0].minor.yy0); +- sqlite3AddDefaultValue(pParse,&v); ++ Expr *p = tokenExpr(pParse, TK_STRING, yymsp[0].minor.yy0); ++ if( p ){ ++ sqlite3ExprIdToTrueFalse(p); ++ testcase( p->op==TK_TRUEFALSE && sqlite3ExprTruthValue(p) ); ++ } ++ sqlite3AddDefaultValue(pParse,p,yymsp[0].minor.yy0.z,yymsp[0].minor.yy0.z+yymsp[0].minor.yy0.n); + } + break; +- case 34: /* ccons ::= NOT NULL onconf */ +-{sqlite3AddNotNull(pParse, yymsp[0].minor.yy194);} ++ case 35: /* ccons ::= NOT NULL onconf */ ++{sqlite3AddNotNull(pParse, yymsp[0].minor.yy70);} + break; +- case 35: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ +-{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy194,yymsp[0].minor.yy194,yymsp[-2].minor.yy194);} ++ case 36: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ ++{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy70,yymsp[0].minor.yy70,yymsp[-2].minor.yy70);} + break; +- case 36: /* ccons ::= UNIQUE onconf */ +-{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy194,0,0,0,0, ++ case 37: /* ccons ::= UNIQUE onconf */ ++{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy70,0,0,0,0, + SQLITE_IDXTYPE_UNIQUE);} + break; +- case 37: /* ccons ::= CHECK LP expr RP */ +-{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy190.pExpr);} ++ case 38: /* ccons ::= CHECK LP expr RP */ ++{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy18);} + break; +- case 38: /* ccons ::= REFERENCES nm eidlist_opt refargs */ +-{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy148,yymsp[0].minor.yy194);} ++ case 39: /* ccons ::= REFERENCES nm eidlist_opt refargs */ ++{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy420,yymsp[0].minor.yy70);} + break; +- case 39: /* ccons ::= defer_subclause */ +-{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy194);} ++ case 40: /* ccons ::= defer_subclause */ ++{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy70);} + break; +- case 40: /* ccons ::= COLLATE ID|STRING */ ++ case 41: /* ccons ::= COLLATE ID|STRING */ + {sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);} + break; +- case 43: /* refargs ::= */ +-{ yymsp[1].minor.yy194 = OE_None*0x0101; /* EV: R-19803-45884 */} ++ case 44: /* refargs ::= */ ++{ yymsp[1].minor.yy70 = OE_None*0x0101; /* EV: R-19803-45884 */} + break; +- case 44: /* refargs ::= refargs refarg */ +-{ yymsp[-1].minor.yy194 = (yymsp[-1].minor.yy194 & ~yymsp[0].minor.yy497.mask) | yymsp[0].minor.yy497.value; } ++ case 45: /* refargs ::= refargs refarg */ ++{ yymsp[-1].minor.yy70 = (yymsp[-1].minor.yy70 & ~yymsp[0].minor.yy111.mask) | yymsp[0].minor.yy111.value; } + break; +- case 45: /* refarg ::= MATCH nm */ +-{ yymsp[-1].minor.yy497.value = 0; yymsp[-1].minor.yy497.mask = 0x000000; } ++ case 46: /* refarg ::= MATCH nm */ ++{ yymsp[-1].minor.yy111.value = 0; yymsp[-1].minor.yy111.mask = 0x000000; } + break; +- case 46: /* refarg ::= ON INSERT refact */ +-{ yymsp[-2].minor.yy497.value = 0; yymsp[-2].minor.yy497.mask = 0x000000; } ++ case 47: /* refarg ::= ON INSERT refact */ ++{ yymsp[-2].minor.yy111.value = 0; yymsp[-2].minor.yy111.mask = 0x000000; } + break; +- case 47: /* refarg ::= ON DELETE refact */ +-{ yymsp[-2].minor.yy497.value = yymsp[0].minor.yy194; yymsp[-2].minor.yy497.mask = 0x0000ff; } ++ case 48: /* refarg ::= ON DELETE refact */ ++{ yymsp[-2].minor.yy111.value = yymsp[0].minor.yy70; yymsp[-2].minor.yy111.mask = 0x0000ff; } + break; +- case 48: /* refarg ::= ON UPDATE refact */ +-{ yymsp[-2].minor.yy497.value = yymsp[0].minor.yy194<<8; yymsp[-2].minor.yy497.mask = 0x00ff00; } ++ case 49: /* refarg ::= ON UPDATE refact */ ++{ yymsp[-2].minor.yy111.value = yymsp[0].minor.yy70<<8; yymsp[-2].minor.yy111.mask = 0x00ff00; } + break; +- case 49: /* refact ::= SET NULL */ +-{ yymsp[-1].minor.yy194 = OE_SetNull; /* EV: R-33326-45252 */} ++ case 50: /* refact ::= SET NULL */ ++{ yymsp[-1].minor.yy70 = OE_SetNull; /* EV: R-33326-45252 */} + break; +- case 50: /* refact ::= SET DEFAULT */ +-{ yymsp[-1].minor.yy194 = OE_SetDflt; /* EV: R-33326-45252 */} ++ case 51: /* refact ::= SET DEFAULT */ ++{ yymsp[-1].minor.yy70 = OE_SetDflt; /* EV: R-33326-45252 */} + break; +- case 51: /* refact ::= CASCADE */ +-{ yymsp[0].minor.yy194 = OE_Cascade; /* EV: R-33326-45252 */} ++ case 52: /* refact ::= CASCADE */ ++{ yymsp[0].minor.yy70 = OE_Cascade; /* EV: R-33326-45252 */} + break; +- case 52: /* refact ::= RESTRICT */ +-{ yymsp[0].minor.yy194 = OE_Restrict; /* EV: R-33326-45252 */} ++ case 53: /* refact ::= RESTRICT */ ++{ yymsp[0].minor.yy70 = OE_Restrict; /* EV: R-33326-45252 */} + break; +- case 53: /* refact ::= NO ACTION */ +-{ yymsp[-1].minor.yy194 = OE_None; /* EV: R-33326-45252 */} ++ case 54: /* refact ::= NO ACTION */ ++{ yymsp[-1].minor.yy70 = OE_None; /* EV: R-33326-45252 */} + break; +- case 54: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ +-{yymsp[-2].minor.yy194 = 0;} ++ case 55: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ ++{yymsp[-2].minor.yy70 = 0;} + break; +- case 55: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ +- case 70: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==70); +- case 143: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==143); +-{yymsp[-1].minor.yy194 = yymsp[0].minor.yy194;} ++ case 56: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ ++ case 71: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==71); ++ case 156: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==156); ++{yymsp[-1].minor.yy70 = yymsp[0].minor.yy70;} + break; +- case 57: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ +- case 74: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==74); +- case 184: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==184); +- case 187: /* in_op ::= NOT IN */ yytestcase(yyruleno==187); +- case 213: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==213); +-{yymsp[-1].minor.yy194 = 1;} ++ case 58: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ ++ case 75: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==75); ++ case 198: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==198); ++ case 201: /* in_op ::= NOT IN */ yytestcase(yyruleno==201); ++ case 227: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==227); ++{yymsp[-1].minor.yy70 = 1;} + break; +- case 58: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ +-{yymsp[-1].minor.yy194 = 0;} ++ case 59: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ ++{yymsp[-1].minor.yy70 = 0;} + break; +- case 60: /* tconscomma ::= COMMA */ ++ case 61: /* tconscomma ::= COMMA */ + {pParse->constraintName.n = 0;} + break; +- case 62: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ +-{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy148,yymsp[0].minor.yy194,yymsp[-2].minor.yy194,0);} ++ case 63: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ ++{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy420,yymsp[0].minor.yy70,yymsp[-2].minor.yy70,0);} + break; +- case 63: /* tcons ::= UNIQUE LP sortlist RP onconf */ +-{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy148,yymsp[0].minor.yy194,0,0,0,0, ++ case 64: /* tcons ::= UNIQUE LP sortlist RP onconf */ ++{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy420,yymsp[0].minor.yy70,0,0,0,0, + SQLITE_IDXTYPE_UNIQUE);} + break; +- case 64: /* tcons ::= CHECK LP expr RP onconf */ +-{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy190.pExpr);} ++ case 65: /* tcons ::= CHECK LP expr RP onconf */ ++{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy18);} + break; +- case 65: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ ++ case 66: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ + { +- sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy148, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy148, yymsp[-1].minor.yy194); +- sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy194); ++ sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy420, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy420, yymsp[-1].minor.yy70); ++ sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy70); + } + break; +- case 67: /* onconf ::= */ +- case 69: /* orconf ::= */ yytestcase(yyruleno==69); +-{yymsp[1].minor.yy194 = OE_Default;} ++ case 68: /* onconf ::= */ ++ case 70: /* orconf ::= */ yytestcase(yyruleno==70); ++{yymsp[1].minor.yy70 = OE_Default;} + break; +- case 68: /* onconf ::= ON CONFLICT resolvetype */ +-{yymsp[-2].minor.yy194 = yymsp[0].minor.yy194;} ++ case 69: /* onconf ::= ON CONFLICT resolvetype */ ++{yymsp[-2].minor.yy70 = yymsp[0].minor.yy70;} + break; +- case 71: /* resolvetype ::= IGNORE */ +-{yymsp[0].minor.yy194 = OE_Ignore;} ++ case 72: /* resolvetype ::= IGNORE */ ++{yymsp[0].minor.yy70 = OE_Ignore;} + break; +- case 72: /* resolvetype ::= REPLACE */ +- case 144: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==144); +-{yymsp[0].minor.yy194 = OE_Replace;} ++ case 73: /* resolvetype ::= REPLACE */ ++ case 157: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==157); ++{yymsp[0].minor.yy70 = OE_Replace;} + break; +- case 73: /* cmd ::= DROP TABLE ifexists fullname */ ++ case 74: /* cmd ::= DROP TABLE ifexists fullname */ + { +- sqlite3DropTable(pParse, yymsp[0].minor.yy185, 0, yymsp[-1].minor.yy194); ++ sqlite3DropTable(pParse, yymsp[0].minor.yy135, 0, yymsp[-1].minor.yy70); + } + break; +- case 76: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ ++ case 77: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ + { +- sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy148, yymsp[0].minor.yy243, yymsp[-7].minor.yy194, yymsp[-5].minor.yy194); ++ sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy420, yymsp[0].minor.yy489, yymsp[-7].minor.yy70, yymsp[-5].minor.yy70); + } + break; +- case 77: /* cmd ::= DROP VIEW ifexists fullname */ ++ case 78: /* cmd ::= DROP VIEW ifexists fullname */ + { +- sqlite3DropTable(pParse, yymsp[0].minor.yy185, 1, yymsp[-1].minor.yy194); ++ sqlite3DropTable(pParse, yymsp[0].minor.yy135, 1, yymsp[-1].minor.yy70); + } + break; +- case 78: /* cmd ::= select */ ++ case 79: /* cmd ::= select */ + { + SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0}; +- sqlite3Select(pParse, yymsp[0].minor.yy243, &dest); +- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy243); ++ sqlite3Select(pParse, yymsp[0].minor.yy489, &dest); ++ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy489); + } + break; +- case 79: /* select ::= with selectnowith */ ++ case 80: /* select ::= WITH wqlist selectnowith */ + { +- Select *p = yymsp[0].minor.yy243; ++ Select *p = yymsp[0].minor.yy489; + if( p ){ +- p->pWith = yymsp[-1].minor.yy285; ++ p->pWith = yymsp[-1].minor.yy449; + parserDoubleLinkSelect(pParse, p); + }else{ +- sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy285); ++ sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy449); + } +- yymsp[-1].minor.yy243 = p; /*A-overwrites-W*/ ++ yymsp[-2].minor.yy489 = p; + } + break; +- case 80: /* selectnowith ::= selectnowith multiselect_op oneselect */ ++ case 81: /* select ::= WITH RECURSIVE wqlist selectnowith */ + { +- Select *pRhs = yymsp[0].minor.yy243; +- Select *pLhs = yymsp[-2].minor.yy243; ++ Select *p = yymsp[0].minor.yy489; ++ if( p ){ ++ p->pWith = yymsp[-1].minor.yy449; ++ parserDoubleLinkSelect(pParse, p); ++ }else{ ++ sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy449); ++ } ++ yymsp[-3].minor.yy489 = p; ++} ++ break; ++ case 82: /* select ::= selectnowith */ ++{ ++ Select *p = yymsp[0].minor.yy489; ++ if( p ){ ++ parserDoubleLinkSelect(pParse, p); ++ } ++ yymsp[0].minor.yy489 = p; /*A-overwrites-X*/ ++} ++ break; ++ case 83: /* selectnowith ::= selectnowith multiselect_op oneselect */ ++{ ++ Select *pRhs = yymsp[0].minor.yy489; ++ Select *pLhs = yymsp[-2].minor.yy489; + if( pRhs && pRhs->pPrior ){ + SrcList *pFrom; + Token x; +@@ -139086,162 +149851,145 @@ + x.n = 0; + parserDoubleLinkSelect(pParse, pRhs); + pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0); +- pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0,0); ++ pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0); + } + if( pRhs ){ +- pRhs->op = (u8)yymsp[-1].minor.yy194; ++ pRhs->op = (u8)yymsp[-1].minor.yy70; + pRhs->pPrior = pLhs; + if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue; + pRhs->selFlags &= ~SF_MultiValue; +- if( yymsp[-1].minor.yy194!=TK_ALL ) pParse->hasCompound = 1; ++ if( yymsp[-1].minor.yy70!=TK_ALL ) pParse->hasCompound = 1; + }else{ + sqlite3SelectDelete(pParse->db, pLhs); + } +- yymsp[-2].minor.yy243 = pRhs; ++ yymsp[-2].minor.yy489 = pRhs; + } + break; +- case 81: /* multiselect_op ::= UNION */ +- case 83: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==83); +-{yymsp[0].minor.yy194 = yymsp[0].major; /*A-overwrites-OP*/} ++ case 84: /* multiselect_op ::= UNION */ ++ case 86: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==86); ++{yymsp[0].minor.yy70 = yymsp[0].major; /*A-overwrites-OP*/} + break; +- case 82: /* multiselect_op ::= UNION ALL */ +-{yymsp[-1].minor.yy194 = TK_ALL;} ++ case 85: /* multiselect_op ::= UNION ALL */ ++{yymsp[-1].minor.yy70 = TK_ALL;} + break; +- case 84: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ ++ case 87: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ + { +-#if SELECTTRACE_ENABLED +- Token s = yymsp[-8].minor.yy0; /*A-overwrites-S*/ +-#endif +- yymsp[-8].minor.yy243 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy148,yymsp[-5].minor.yy185,yymsp[-4].minor.yy72,yymsp[-3].minor.yy148,yymsp[-2].minor.yy72,yymsp[-1].minor.yy148,yymsp[-7].minor.yy194,yymsp[0].minor.yy354.pLimit,yymsp[0].minor.yy354.pOffset); +-#if SELECTTRACE_ENABLED +- /* Populate the Select.zSelName[] string that is used to help with +- ** query planner debugging, to differentiate between multiple Select +- ** objects in a complex query. +- ** +- ** If the SELECT keyword is immediately followed by a C-style comment +- ** then extract the first few alphanumeric characters from within that +- ** comment to be the zSelName value. Otherwise, the label is #N where +- ** is an integer that is incremented with each SELECT statement seen. +- */ +- if( yymsp[-8].minor.yy243!=0 ){ +- const char *z = s.z+6; +- int i; +- sqlite3_snprintf(sizeof(yymsp[-8].minor.yy243->zSelName), yymsp[-8].minor.yy243->zSelName, "#%d", +- ++pParse->nSelect); +- while( z[0]==' ' ) z++; +- if( z[0]=='/' && z[1]=='*' ){ +- z += 2; +- while( z[0]==' ' ) z++; +- for(i=0; sqlite3Isalnum(z[i]); i++){} +- sqlite3_snprintf(sizeof(yymsp[-8].minor.yy243->zSelName), yymsp[-8].minor.yy243->zSelName, "%.*s", i, z); +- } ++ yymsp[-8].minor.yy489 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy420,yymsp[-5].minor.yy135,yymsp[-4].minor.yy18,yymsp[-3].minor.yy420,yymsp[-2].minor.yy18,yymsp[-1].minor.yy420,yymsp[-7].minor.yy70,yymsp[0].minor.yy18); ++} ++ break; ++ case 88: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ ++{ ++ yymsp[-9].minor.yy489 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy420,yymsp[-6].minor.yy135,yymsp[-5].minor.yy18,yymsp[-4].minor.yy420,yymsp[-3].minor.yy18,yymsp[-1].minor.yy420,yymsp[-8].minor.yy70,yymsp[0].minor.yy18); ++ if( yymsp[-9].minor.yy489 ){ ++ yymsp[-9].minor.yy489->pWinDefn = yymsp[-2].minor.yy327; ++ }else{ ++ sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy327); + } +-#endif /* SELECTRACE_ENABLED */ + } + break; +- case 85: /* values ::= VALUES LP nexprlist RP */ ++ case 89: /* values ::= VALUES LP nexprlist RP */ + { +- yymsp[-3].minor.yy243 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy148,0,0,0,0,0,SF_Values,0,0); ++ yymsp[-3].minor.yy489 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy420,0,0,0,0,0,SF_Values,0); + } + break; +- case 86: /* values ::= values COMMA LP exprlist RP */ ++ case 90: /* values ::= values COMMA LP nexprlist RP */ + { +- Select *pRight, *pLeft = yymsp[-4].minor.yy243; +- pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy148,0,0,0,0,0,SF_Values|SF_MultiValue,0,0); ++ Select *pRight, *pLeft = yymsp[-4].minor.yy489; ++ pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy420,0,0,0,0,0,SF_Values|SF_MultiValue,0); + if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue; + if( pRight ){ + pRight->op = TK_ALL; + pRight->pPrior = pLeft; +- yymsp[-4].minor.yy243 = pRight; ++ yymsp[-4].minor.yy489 = pRight; + }else{ +- yymsp[-4].minor.yy243 = pLeft; ++ yymsp[-4].minor.yy489 = pLeft; + } + } + break; +- case 87: /* distinct ::= DISTINCT */ +-{yymsp[0].minor.yy194 = SF_Distinct;} ++ case 91: /* distinct ::= DISTINCT */ ++{yymsp[0].minor.yy70 = SF_Distinct;} + break; +- case 88: /* distinct ::= ALL */ +-{yymsp[0].minor.yy194 = SF_All;} ++ case 92: /* distinct ::= ALL */ ++{yymsp[0].minor.yy70 = SF_All;} + break; +- case 90: /* sclp ::= */ +- case 118: /* orderby_opt ::= */ yytestcase(yyruleno==118); +- case 125: /* groupby_opt ::= */ yytestcase(yyruleno==125); +- case 200: /* exprlist ::= */ yytestcase(yyruleno==200); +- case 203: /* paren_exprlist ::= */ yytestcase(yyruleno==203); +- case 208: /* eidlist_opt ::= */ yytestcase(yyruleno==208); +-{yymsp[1].minor.yy148 = 0;} ++ case 94: /* sclp ::= */ ++ case 127: /* orderby_opt ::= */ yytestcase(yyruleno==127); ++ case 134: /* groupby_opt ::= */ yytestcase(yyruleno==134); ++ case 214: /* exprlist ::= */ yytestcase(yyruleno==214); ++ case 217: /* paren_exprlist ::= */ yytestcase(yyruleno==217); ++ case 222: /* eidlist_opt ::= */ yytestcase(yyruleno==222); ++{yymsp[1].minor.yy420 = 0;} + break; +- case 91: /* selcollist ::= sclp expr as */ ++ case 95: /* selcollist ::= sclp scanpt expr scanpt as */ + { +- yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy148, yymsp[-1].minor.yy190.pExpr); +- if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-2].minor.yy148, &yymsp[0].minor.yy0, 1); +- sqlite3ExprListSetSpan(pParse,yymsp[-2].minor.yy148,&yymsp[-1].minor.yy190); ++ yymsp[-4].minor.yy420 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy420, yymsp[-2].minor.yy18); ++ if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy420, &yymsp[0].minor.yy0, 1); ++ sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy420,yymsp[-3].minor.yy392,yymsp[-1].minor.yy392); + } + break; +- case 92: /* selcollist ::= sclp STAR */ ++ case 96: /* selcollist ::= sclp scanpt STAR */ + { + Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0); +- yymsp[-1].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy148, p); ++ yymsp[-2].minor.yy420 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy420, p); + } + break; +- case 93: /* selcollist ::= sclp nm DOT STAR */ ++ case 97: /* selcollist ::= sclp scanpt nm DOT STAR */ + { + Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0); + Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); + Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight); +- yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, pDot); ++ yymsp[-4].minor.yy420 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy420, pDot); + } + break; +- case 94: /* as ::= AS nm */ +- case 105: /* dbnm ::= DOT nm */ yytestcase(yyruleno==105); +- case 222: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==222); +- case 223: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==223); ++ case 98: /* as ::= AS nm */ ++ case 109: /* dbnm ::= DOT nm */ yytestcase(yyruleno==109); ++ case 236: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==236); ++ case 237: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==237); + {yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;} + break; +- case 96: /* from ::= */ +-{yymsp[1].minor.yy185 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy185));} ++ case 100: /* from ::= */ ++{yymsp[1].minor.yy135 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy135));} + break; +- case 97: /* from ::= FROM seltablist */ ++ case 101: /* from ::= FROM seltablist */ + { +- yymsp[-1].minor.yy185 = yymsp[0].minor.yy185; +- sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy185); ++ yymsp[-1].minor.yy135 = yymsp[0].minor.yy135; ++ sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy135); + } + break; +- case 98: /* stl_prefix ::= seltablist joinop */ ++ case 102: /* stl_prefix ::= seltablist joinop */ + { +- if( ALWAYS(yymsp[-1].minor.yy185 && yymsp[-1].minor.yy185->nSrc>0) ) yymsp[-1].minor.yy185->a[yymsp[-1].minor.yy185->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy194; ++ if( ALWAYS(yymsp[-1].minor.yy135 && yymsp[-1].minor.yy135->nSrc>0) ) yymsp[-1].minor.yy135->a[yymsp[-1].minor.yy135->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy70; + } + break; +- case 99: /* stl_prefix ::= */ +-{yymsp[1].minor.yy185 = 0;} ++ case 103: /* stl_prefix ::= */ ++{yymsp[1].minor.yy135 = 0;} + break; +- case 100: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ ++ case 104: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ + { +- yymsp[-6].minor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy185,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy72,yymsp[0].minor.yy254); +- sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy185, &yymsp[-2].minor.yy0); ++ yymsp[-6].minor.yy135 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy135,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy18,yymsp[0].minor.yy48); ++ sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy135, &yymsp[-2].minor.yy0); + } + break; +- case 101: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */ ++ case 105: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */ + { +- yymsp[-8].minor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy185,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy72,yymsp[0].minor.yy254); +- sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy185, yymsp[-4].minor.yy148); ++ yymsp[-8].minor.yy135 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy135,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy18,yymsp[0].minor.yy48); ++ sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy135, yymsp[-4].minor.yy420); + } + break; +- case 102: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */ ++ case 106: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */ + { +- yymsp[-6].minor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy185,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy243,yymsp[-1].minor.yy72,yymsp[0].minor.yy254); ++ yymsp[-6].minor.yy135 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy135,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy489,yymsp[-1].minor.yy18,yymsp[0].minor.yy48); + } + break; +- case 103: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ ++ case 107: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ + { +- if( yymsp[-6].minor.yy185==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy72==0 && yymsp[0].minor.yy254==0 ){ +- yymsp[-6].minor.yy185 = yymsp[-4].minor.yy185; +- }else if( yymsp[-4].minor.yy185->nSrc==1 ){ +- yymsp[-6].minor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy185,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy72,yymsp[0].minor.yy254); +- if( yymsp[-6].minor.yy185 ){ +- struct SrcList_item *pNew = &yymsp[-6].minor.yy185->a[yymsp[-6].minor.yy185->nSrc-1]; +- struct SrcList_item *pOld = yymsp[-4].minor.yy185->a; ++ if( yymsp[-6].minor.yy135==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy18==0 && yymsp[0].minor.yy48==0 ){ ++ yymsp[-6].minor.yy135 = yymsp[-4].minor.yy135; ++ }else if( yymsp[-4].minor.yy135->nSrc==1 ){ ++ yymsp[-6].minor.yy135 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy135,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy18,yymsp[0].minor.yy48); ++ if( yymsp[-6].minor.yy135 ){ ++ struct SrcList_item *pNew = &yymsp[-6].minor.yy135->a[yymsp[-6].minor.yy135->nSrc-1]; ++ struct SrcList_item *pOld = yymsp[-4].minor.yy135->a; + pNew->zName = pOld->zName; + pNew->zDatabase = pOld->zDatabase; + pNew->pSelect = pOld->pSelect; +@@ -139248,199 +149996,240 @@ + pOld->zName = pOld->zDatabase = 0; + pOld->pSelect = 0; + } +- sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy185); ++ sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy135); + }else{ + Select *pSubquery; +- sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy185); +- pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy185,0,0,0,0,SF_NestedFrom,0,0); +- yymsp[-6].minor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy185,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy72,yymsp[0].minor.yy254); ++ sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy135); ++ pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy135,0,0,0,0,SF_NestedFrom,0); ++ yymsp[-6].minor.yy135 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy135,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy18,yymsp[0].minor.yy48); + } + } + break; +- case 104: /* dbnm ::= */ +- case 113: /* indexed_opt ::= */ yytestcase(yyruleno==113); ++ case 108: /* dbnm ::= */ ++ case 122: /* indexed_opt ::= */ yytestcase(yyruleno==122); + {yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;} + break; +- case 106: /* fullname ::= nm dbnm */ +-{yymsp[-1].minor.yy185 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/} ++ case 110: /* fullname ::= nm */ ++{ ++ yylhsminor.yy135 = sqlite3SrcListAppend(pParse->db,0,&yymsp[0].minor.yy0,0); ++ if( IN_RENAME_OBJECT && yylhsminor.yy135 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy135->a[0].zName, &yymsp[0].minor.yy0); ++} ++ yymsp[0].minor.yy135 = yylhsminor.yy135; + break; +- case 107: /* joinop ::= COMMA|JOIN */ +-{ yymsp[0].minor.yy194 = JT_INNER; } ++ case 111: /* fullname ::= nm DOT nm */ ++{ ++ yylhsminor.yy135 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); ++ if( IN_RENAME_OBJECT && yylhsminor.yy135 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy135->a[0].zName, &yymsp[0].minor.yy0); ++} ++ yymsp[-2].minor.yy135 = yylhsminor.yy135; + break; +- case 108: /* joinop ::= JOIN_KW JOIN */ +-{yymsp[-1].minor.yy194 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} ++ case 112: /* xfullname ::= nm */ ++{yymsp[0].minor.yy135 = sqlite3SrcListAppend(pParse->db,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/} + break; +- case 109: /* joinop ::= JOIN_KW nm JOIN */ +-{yymsp[-2].minor.yy194 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/} ++ case 113: /* xfullname ::= nm DOT nm */ ++{yymsp[-2].minor.yy135 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/} + break; +- case 110: /* joinop ::= JOIN_KW nm nm JOIN */ +-{yymsp[-3].minor.yy194 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} ++ case 114: /* xfullname ::= nm DOT nm AS nm */ ++{ ++ yymsp[-4].minor.yy135 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/ ++ if( yymsp[-4].minor.yy135 ) yymsp[-4].minor.yy135->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); ++} + break; +- case 111: /* on_opt ::= ON expr */ +- case 128: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==128); +- case 135: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==135); +- case 196: /* case_else ::= ELSE expr */ yytestcase(yyruleno==196); +-{yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr;} ++ case 115: /* xfullname ::= nm AS nm */ ++{ ++ yymsp[-2].minor.yy135 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/ ++ if( yymsp[-2].minor.yy135 ) yymsp[-2].minor.yy135->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); ++} + break; +- case 112: /* on_opt ::= */ +- case 127: /* having_opt ::= */ yytestcase(yyruleno==127); +- case 134: /* where_opt ::= */ yytestcase(yyruleno==134); +- case 197: /* case_else ::= */ yytestcase(yyruleno==197); +- case 199: /* case_operand ::= */ yytestcase(yyruleno==199); +-{yymsp[1].minor.yy72 = 0;} ++ case 116: /* joinop ::= COMMA|JOIN */ ++{ yymsp[0].minor.yy70 = JT_INNER; } + break; +- case 114: /* indexed_opt ::= INDEXED BY nm */ ++ case 117: /* joinop ::= JOIN_KW JOIN */ ++{yymsp[-1].minor.yy70 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} ++ break; ++ case 118: /* joinop ::= JOIN_KW nm JOIN */ ++{yymsp[-2].minor.yy70 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/} ++ break; ++ case 119: /* joinop ::= JOIN_KW nm nm JOIN */ ++{yymsp[-3].minor.yy70 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} ++ break; ++ case 120: /* on_opt ::= ON expr */ ++ case 137: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==137); ++ case 144: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==144); ++ case 210: /* case_else ::= ELSE expr */ yytestcase(yyruleno==210); ++{yymsp[-1].minor.yy18 = yymsp[0].minor.yy18;} ++ break; ++ case 121: /* on_opt ::= */ ++ case 136: /* having_opt ::= */ yytestcase(yyruleno==136); ++ case 138: /* limit_opt ::= */ yytestcase(yyruleno==138); ++ case 143: /* where_opt ::= */ yytestcase(yyruleno==143); ++ case 211: /* case_else ::= */ yytestcase(yyruleno==211); ++ case 213: /* case_operand ::= */ yytestcase(yyruleno==213); ++{yymsp[1].minor.yy18 = 0;} ++ break; ++ case 123: /* indexed_opt ::= INDEXED BY nm */ + {yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;} + break; +- case 115: /* indexed_opt ::= NOT INDEXED */ ++ case 124: /* indexed_opt ::= NOT INDEXED */ + {yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;} + break; +- case 116: /* using_opt ::= USING LP idlist RP */ +-{yymsp[-3].minor.yy254 = yymsp[-1].minor.yy254;} ++ case 125: /* using_opt ::= USING LP idlist RP */ ++{yymsp[-3].minor.yy48 = yymsp[-1].minor.yy48;} + break; +- case 117: /* using_opt ::= */ +- case 145: /* idlist_opt ::= */ yytestcase(yyruleno==145); +-{yymsp[1].minor.yy254 = 0;} ++ case 126: /* using_opt ::= */ ++ case 158: /* idlist_opt ::= */ yytestcase(yyruleno==158); ++{yymsp[1].minor.yy48 = 0;} + break; +- case 119: /* orderby_opt ::= ORDER BY sortlist */ +- case 126: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==126); +-{yymsp[-2].minor.yy148 = yymsp[0].minor.yy148;} ++ case 128: /* orderby_opt ::= ORDER BY sortlist */ ++ case 135: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==135); ++{yymsp[-2].minor.yy420 = yymsp[0].minor.yy420;} + break; +- case 120: /* sortlist ::= sortlist COMMA expr sortorder */ ++ case 129: /* sortlist ::= sortlist COMMA expr sortorder */ + { +- yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148,yymsp[-1].minor.yy190.pExpr); +- sqlite3ExprListSetSortOrder(yymsp[-3].minor.yy148,yymsp[0].minor.yy194); ++ yymsp[-3].minor.yy420 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy420,yymsp[-1].minor.yy18); ++ sqlite3ExprListSetSortOrder(yymsp[-3].minor.yy420,yymsp[0].minor.yy70); + } + break; +- case 121: /* sortlist ::= expr sortorder */ ++ case 130: /* sortlist ::= expr sortorder */ + { +- yymsp[-1].minor.yy148 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy190.pExpr); /*A-overwrites-Y*/ +- sqlite3ExprListSetSortOrder(yymsp[-1].minor.yy148,yymsp[0].minor.yy194); ++ yymsp[-1].minor.yy420 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy18); /*A-overwrites-Y*/ ++ sqlite3ExprListSetSortOrder(yymsp[-1].minor.yy420,yymsp[0].minor.yy70); + } + break; +- case 122: /* sortorder ::= ASC */ +-{yymsp[0].minor.yy194 = SQLITE_SO_ASC;} ++ case 131: /* sortorder ::= ASC */ ++{yymsp[0].minor.yy70 = SQLITE_SO_ASC;} + break; +- case 123: /* sortorder ::= DESC */ +-{yymsp[0].minor.yy194 = SQLITE_SO_DESC;} ++ case 132: /* sortorder ::= DESC */ ++{yymsp[0].minor.yy70 = SQLITE_SO_DESC;} + break; +- case 124: /* sortorder ::= */ +-{yymsp[1].minor.yy194 = SQLITE_SO_UNDEFINED;} ++ case 133: /* sortorder ::= */ ++{yymsp[1].minor.yy70 = SQLITE_SO_UNDEFINED;} + break; +- case 129: /* limit_opt ::= */ +-{yymsp[1].minor.yy354.pLimit = 0; yymsp[1].minor.yy354.pOffset = 0;} ++ case 139: /* limit_opt ::= LIMIT expr */ ++{yymsp[-1].minor.yy18 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy18,0);} + break; +- case 130: /* limit_opt ::= LIMIT expr */ +-{yymsp[-1].minor.yy354.pLimit = yymsp[0].minor.yy190.pExpr; yymsp[-1].minor.yy354.pOffset = 0;} ++ case 140: /* limit_opt ::= LIMIT expr OFFSET expr */ ++{yymsp[-3].minor.yy18 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy18,yymsp[0].minor.yy18);} + break; +- case 131: /* limit_opt ::= LIMIT expr OFFSET expr */ +-{yymsp[-3].minor.yy354.pLimit = yymsp[-2].minor.yy190.pExpr; yymsp[-3].minor.yy354.pOffset = yymsp[0].minor.yy190.pExpr;} ++ case 141: /* limit_opt ::= LIMIT expr COMMA expr */ ++{yymsp[-3].minor.yy18 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy18,yymsp[-2].minor.yy18);} + break; +- case 132: /* limit_opt ::= LIMIT expr COMMA expr */ +-{yymsp[-3].minor.yy354.pOffset = yymsp[-2].minor.yy190.pExpr; yymsp[-3].minor.yy354.pLimit = yymsp[0].minor.yy190.pExpr;} +- break; +- case 133: /* cmd ::= with DELETE FROM fullname indexed_opt where_opt */ ++ case 142: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt */ + { +- sqlite3WithPush(pParse, yymsp[-5].minor.yy285, 1); +- sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy185, &yymsp[-1].minor.yy0); +- sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy185,yymsp[0].minor.yy72); ++ sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy135, &yymsp[-1].minor.yy0); ++ sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy135,yymsp[0].minor.yy18,0,0); + } + break; +- case 136: /* cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt */ ++ case 145: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */ + { +- sqlite3WithPush(pParse, yymsp[-7].minor.yy285, 1); +- sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy185, &yymsp[-3].minor.yy0); +- sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy148,"set list"); +- sqlite3Update(pParse,yymsp[-4].minor.yy185,yymsp[-1].minor.yy148,yymsp[0].minor.yy72,yymsp[-5].minor.yy194); ++ sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy135, &yymsp[-3].minor.yy0); ++ sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy420,"set list"); ++ sqlite3Update(pParse,yymsp[-4].minor.yy135,yymsp[-1].minor.yy420,yymsp[0].minor.yy18,yymsp[-5].minor.yy70,0,0,0); + } + break; +- case 137: /* setlist ::= setlist COMMA nm EQ expr */ ++ case 146: /* setlist ::= setlist COMMA nm EQ expr */ + { +- yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy148, yymsp[0].minor.yy190.pExpr); +- sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy148, &yymsp[-2].minor.yy0, 1); ++ yymsp[-4].minor.yy420 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy420, yymsp[0].minor.yy18); ++ sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy420, &yymsp[-2].minor.yy0, 1); + } + break; +- case 138: /* setlist ::= setlist COMMA LP idlist RP EQ expr */ ++ case 147: /* setlist ::= setlist COMMA LP idlist RP EQ expr */ + { +- yymsp[-6].minor.yy148 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy148, yymsp[-3].minor.yy254, yymsp[0].minor.yy190.pExpr); ++ yymsp[-6].minor.yy420 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy420, yymsp[-3].minor.yy48, yymsp[0].minor.yy18); + } + break; +- case 139: /* setlist ::= nm EQ expr */ ++ case 148: /* setlist ::= nm EQ expr */ + { +- yylhsminor.yy148 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy190.pExpr); +- sqlite3ExprListSetName(pParse, yylhsminor.yy148, &yymsp[-2].minor.yy0, 1); ++ yylhsminor.yy420 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy18); ++ sqlite3ExprListSetName(pParse, yylhsminor.yy420, &yymsp[-2].minor.yy0, 1); + } +- yymsp[-2].minor.yy148 = yylhsminor.yy148; ++ yymsp[-2].minor.yy420 = yylhsminor.yy420; + break; +- case 140: /* setlist ::= LP idlist RP EQ expr */ ++ case 149: /* setlist ::= LP idlist RP EQ expr */ + { +- yymsp[-4].minor.yy148 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy254, yymsp[0].minor.yy190.pExpr); ++ yymsp[-4].minor.yy420 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy48, yymsp[0].minor.yy18); + } + break; +- case 141: /* cmd ::= with insert_cmd INTO fullname idlist_opt select */ ++ case 150: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ + { +- sqlite3WithPush(pParse, yymsp[-5].minor.yy285, 1); +- sqlite3Insert(pParse, yymsp[-2].minor.yy185, yymsp[0].minor.yy243, yymsp[-1].minor.yy254, yymsp[-4].minor.yy194); ++ sqlite3Insert(pParse, yymsp[-3].minor.yy135, yymsp[-1].minor.yy489, yymsp[-2].minor.yy48, yymsp[-5].minor.yy70, yymsp[0].minor.yy340); + } + break; +- case 142: /* cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES */ ++ case 151: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */ + { +- sqlite3WithPush(pParse, yymsp[-6].minor.yy285, 1); +- sqlite3Insert(pParse, yymsp[-3].minor.yy185, 0, yymsp[-2].minor.yy254, yymsp[-5].minor.yy194); ++ sqlite3Insert(pParse, yymsp[-3].minor.yy135, 0, yymsp[-2].minor.yy48, yymsp[-5].minor.yy70, 0); + } + break; +- case 146: /* idlist_opt ::= LP idlist RP */ +-{yymsp[-2].minor.yy254 = yymsp[-1].minor.yy254;} ++ case 152: /* upsert ::= */ ++{ yymsp[1].minor.yy340 = 0; } + break; +- case 147: /* idlist ::= idlist COMMA nm */ +-{yymsp[-2].minor.yy254 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy254,&yymsp[0].minor.yy0);} ++ case 153: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */ ++{ yymsp[-10].minor.yy340 = sqlite3UpsertNew(pParse->db,yymsp[-7].minor.yy420,yymsp[-5].minor.yy18,yymsp[-1].minor.yy420,yymsp[0].minor.yy18);} + break; +- case 148: /* idlist ::= nm */ +-{yymsp[0].minor.yy254 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} ++ case 154: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */ ++{ yymsp[-7].minor.yy340 = sqlite3UpsertNew(pParse->db,yymsp[-4].minor.yy420,yymsp[-2].minor.yy18,0,0); } + break; +- case 149: /* expr ::= LP expr RP */ +-{spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ yymsp[-2].minor.yy190.pExpr = yymsp[-1].minor.yy190.pExpr;} ++ case 155: /* upsert ::= ON CONFLICT DO NOTHING */ ++{ yymsp[-3].minor.yy340 = sqlite3UpsertNew(pParse->db,0,0,0,0); } + break; +- case 150: /* expr ::= ID|INDEXED */ +- case 151: /* expr ::= JOIN_KW */ yytestcase(yyruleno==151); +-{spanExpr(&yymsp[0].minor.yy190,pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} ++ case 159: /* idlist_opt ::= LP idlist RP */ ++{yymsp[-2].minor.yy48 = yymsp[-1].minor.yy48;} + break; +- case 152: /* expr ::= nm DOT nm */ ++ case 160: /* idlist ::= idlist COMMA nm */ ++{yymsp[-2].minor.yy48 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy48,&yymsp[0].minor.yy0);} ++ break; ++ case 161: /* idlist ::= nm */ ++{yymsp[0].minor.yy48 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} ++ break; ++ case 162: /* expr ::= LP expr RP */ ++{yymsp[-2].minor.yy18 = yymsp[-1].minor.yy18;} ++ break; ++ case 163: /* expr ::= ID|INDEXED */ ++ case 164: /* expr ::= JOIN_KW */ yytestcase(yyruleno==164); ++{yymsp[0].minor.yy18=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} ++ break; ++ case 165: /* expr ::= nm DOT nm */ + { + Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); + Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1); +- spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ +- yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameTokenMap(pParse, (void*)temp2, &yymsp[0].minor.yy0); ++ sqlite3RenameTokenMap(pParse, (void*)temp1, &yymsp[-2].minor.yy0); ++ } ++ yylhsminor.yy18 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); + } ++ yymsp[-2].minor.yy18 = yylhsminor.yy18; + break; +- case 153: /* expr ::= nm DOT nm DOT nm */ ++ case 166: /* expr ::= nm DOT nm DOT nm */ + { + Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-4].minor.yy0, 1); + Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); + Expr *temp3 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1); + Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3); +- spanSet(&yymsp[-4].minor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ +- yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameTokenMap(pParse, (void*)temp3, &yymsp[0].minor.yy0); ++ sqlite3RenameTokenMap(pParse, (void*)temp2, &yymsp[-2].minor.yy0); ++ } ++ yylhsminor.yy18 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); + } ++ yymsp[-4].minor.yy18 = yylhsminor.yy18; + break; +- case 154: /* term ::= NULL|FLOAT|BLOB */ +- case 155: /* term ::= STRING */ yytestcase(yyruleno==155); +-{spanExpr(&yymsp[0].minor.yy190,pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/} ++ case 167: /* term ::= NULL|FLOAT|BLOB */ ++ case 168: /* term ::= STRING */ yytestcase(yyruleno==168); ++{yymsp[0].minor.yy18=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/} + break; +- case 156: /* term ::= INTEGER */ ++ case 169: /* term ::= INTEGER */ + { +- yylhsminor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); +- yylhsminor.yy190.zStart = yymsp[0].minor.yy0.z; +- yylhsminor.yy190.zEnd = yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n; ++ yylhsminor.yy18 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); + } +- yymsp[0].minor.yy190 = yylhsminor.yy190; ++ yymsp[0].minor.yy18 = yylhsminor.yy18; + break; +- case 157: /* expr ::= VARIABLE */ ++ case 170: /* expr ::= VARIABLE */ + { + if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){ + u32 n = yymsp[0].minor.yy0.n; +- spanExpr(&yymsp[0].minor.yy190, pParse, TK_VARIABLE, yymsp[0].minor.yy0); +- sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy190.pExpr, n); ++ yymsp[0].minor.yy18 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0); ++ sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy18, n); + }else{ + /* When doing a nested parse, one can include terms in an expression + ** that look like this: #1 #2 ... These terms refer to registers +@@ -139447,159 +150236,156 @@ + ** in the virtual machine. #N is the N-th register. */ + Token t = yymsp[0].minor.yy0; /*A-overwrites-X*/ + assert( t.n>=2 ); +- spanSet(&yymsp[0].minor.yy190, &t, &t); + if( pParse->nested==0 ){ + sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t); +- yymsp[0].minor.yy190.pExpr = 0; ++ yymsp[0].minor.yy18 = 0; + }else{ +- yymsp[0].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); +- if( yymsp[0].minor.yy190.pExpr ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy190.pExpr->iTable); ++ yymsp[0].minor.yy18 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); ++ if( yymsp[0].minor.yy18 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy18->iTable); + } + } + } + break; +- case 158: /* expr ::= expr COLLATE ID|STRING */ ++ case 171: /* expr ::= expr COLLATE ID|STRING */ + { +- yymsp[-2].minor.yy190.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy190.pExpr, &yymsp[0].minor.yy0, 1); +- yymsp[-2].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; ++ yymsp[-2].minor.yy18 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy18, &yymsp[0].minor.yy0, 1); + } + break; +- case 159: /* expr ::= CAST LP expr AS typetoken RP */ ++ case 172: /* expr ::= CAST LP expr AS typetoken RP */ + { +- spanSet(&yymsp[-5].minor.yy190,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ +- yymsp[-5].minor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); +- sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy190.pExpr, yymsp[-3].minor.yy190.pExpr, 0); ++ yymsp[-5].minor.yy18 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); ++ sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy18, yymsp[-3].minor.yy18, 0); + } + break; +- case 160: /* expr ::= ID|INDEXED LP distinct exprlist RP */ ++ case 173: /* expr ::= ID|INDEXED LP distinct exprlist RP */ + { +- if( yymsp[-1].minor.yy148 && yymsp[-1].minor.yy148->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ +- sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); +- } +- yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy148, &yymsp[-4].minor.yy0); +- spanSet(&yylhsminor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); +- if( yymsp[-2].minor.yy194==SF_Distinct && yylhsminor.yy190.pExpr ){ +- yylhsminor.yy190.pExpr->flags |= EP_Distinct; +- } ++ yylhsminor.yy18 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy420, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy70); + } +- yymsp[-4].minor.yy190 = yylhsminor.yy190; ++ yymsp[-4].minor.yy18 = yylhsminor.yy18; + break; +- case 161: /* expr ::= ID|INDEXED LP STAR RP */ ++ case 174: /* expr ::= ID|INDEXED LP STAR RP */ + { +- yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); +- spanSet(&yylhsminor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); ++ yylhsminor.yy18 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0); + } +- yymsp[-3].minor.yy190 = yylhsminor.yy190; ++ yymsp[-3].minor.yy18 = yylhsminor.yy18; + break; +- case 162: /* term ::= CTIME_KW */ ++ case 175: /* expr ::= ID|INDEXED LP distinct exprlist RP over_clause */ + { +- yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0); +- spanSet(&yylhsminor.yy190, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); ++ yylhsminor.yy18 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy420, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy70); ++ sqlite3WindowAttach(pParse, yylhsminor.yy18, yymsp[0].minor.yy327); + } +- yymsp[0].minor.yy190 = yylhsminor.yy190; ++ yymsp[-5].minor.yy18 = yylhsminor.yy18; + break; +- case 163: /* expr ::= LP nexprlist COMMA expr RP */ ++ case 176: /* expr ::= ID|INDEXED LP STAR RP over_clause */ + { +- ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy148, yymsp[-1].minor.yy190.pExpr); +- yylhsminor.yy190.pExpr = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); +- if( yylhsminor.yy190.pExpr ){ +- yylhsminor.yy190.pExpr->x.pList = pList; +- spanSet(&yylhsminor.yy190, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0); ++ yylhsminor.yy18 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0); ++ sqlite3WindowAttach(pParse, yylhsminor.yy18, yymsp[0].minor.yy327); ++} ++ yymsp[-4].minor.yy18 = yylhsminor.yy18; ++ break; ++ case 177: /* term ::= CTIME_KW */ ++{ ++ yylhsminor.yy18 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0); ++} ++ yymsp[0].minor.yy18 = yylhsminor.yy18; ++ break; ++ case 178: /* expr ::= LP nexprlist COMMA expr RP */ ++{ ++ ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy420, yymsp[-1].minor.yy18); ++ yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); ++ if( yymsp[-4].minor.yy18 ){ ++ yymsp[-4].minor.yy18->x.pList = pList; + }else{ + sqlite3ExprListDelete(pParse->db, pList); + } + } +- yymsp[-4].minor.yy190 = yylhsminor.yy190; + break; +- case 164: /* expr ::= expr AND expr */ +- case 165: /* expr ::= expr OR expr */ yytestcase(yyruleno==165); +- case 166: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==166); +- case 167: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==167); +- case 168: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==168); +- case 169: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==169); +- case 170: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==170); +- case 171: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==171); +-{spanBinaryExpr(pParse,yymsp[-1].major,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190);} ++ case 179: /* expr ::= expr AND expr */ ++ case 180: /* expr ::= expr OR expr */ yytestcase(yyruleno==180); ++ case 181: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==181); ++ case 182: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==182); ++ case 183: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==183); ++ case 184: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==184); ++ case 185: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==185); ++ case 186: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==186); ++{yymsp[-2].minor.yy18=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy18,yymsp[0].minor.yy18);} + break; +- case 172: /* likeop ::= NOT LIKE_KW|MATCH */ ++ case 187: /* likeop ::= NOT LIKE_KW|MATCH */ + {yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/} + break; +- case 173: /* expr ::= expr likeop expr */ ++ case 188: /* expr ::= expr likeop expr */ + { + ExprList *pList; + int bNot = yymsp[-1].minor.yy0.n & 0x80000000; + yymsp[-1].minor.yy0.n &= 0x7fffffff; +- pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy190.pExpr); +- pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy190.pExpr); +- yymsp[-2].minor.yy190.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0); +- exprNot(pParse, bNot, &yymsp[-2].minor.yy190); +- yymsp[-2].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; +- if( yymsp[-2].minor.yy190.pExpr ) yymsp[-2].minor.yy190.pExpr->flags |= EP_InfixFunc; ++ pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy18); ++ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy18); ++ yymsp[-2].minor.yy18 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); ++ if( bNot ) yymsp[-2].minor.yy18 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy18, 0); ++ if( yymsp[-2].minor.yy18 ) yymsp[-2].minor.yy18->flags |= EP_InfixFunc; + } + break; +- case 174: /* expr ::= expr likeop expr ESCAPE expr */ ++ case 189: /* expr ::= expr likeop expr ESCAPE expr */ + { + ExprList *pList; + int bNot = yymsp[-3].minor.yy0.n & 0x80000000; + yymsp[-3].minor.yy0.n &= 0x7fffffff; +- pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); +- pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy190.pExpr); +- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy190.pExpr); +- yymsp[-4].minor.yy190.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0); +- exprNot(pParse, bNot, &yymsp[-4].minor.yy190); +- yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; +- if( yymsp[-4].minor.yy190.pExpr ) yymsp[-4].minor.yy190.pExpr->flags |= EP_InfixFunc; ++ pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy18); ++ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy18); ++ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy18); ++ yymsp[-4].minor.yy18 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0); ++ if( bNot ) yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy18, 0); ++ if( yymsp[-4].minor.yy18 ) yymsp[-4].minor.yy18->flags |= EP_InfixFunc; + } + break; +- case 175: /* expr ::= expr ISNULL|NOTNULL */ +-{spanUnaryPostfix(pParse,yymsp[0].major,&yymsp[-1].minor.yy190,&yymsp[0].minor.yy0);} ++ case 190: /* expr ::= expr ISNULL|NOTNULL */ ++{yymsp[-1].minor.yy18 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy18,0);} + break; +- case 176: /* expr ::= expr NOT NULL */ +-{spanUnaryPostfix(pParse,TK_NOTNULL,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy0);} ++ case 191: /* expr ::= expr NOT NULL */ ++{yymsp[-2].minor.yy18 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy18,0);} + break; +- case 177: /* expr ::= expr IS expr */ ++ case 192: /* expr ::= expr IS expr */ + { +- spanBinaryExpr(pParse,TK_IS,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190); +- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-2].minor.yy190.pExpr, TK_ISNULL); ++ yymsp[-2].minor.yy18 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy18,yymsp[0].minor.yy18); ++ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy18, yymsp[-2].minor.yy18, TK_ISNULL); + } + break; +- case 178: /* expr ::= expr IS NOT expr */ ++ case 193: /* expr ::= expr IS NOT expr */ + { +- spanBinaryExpr(pParse,TK_ISNOT,&yymsp[-3].minor.yy190,&yymsp[0].minor.yy190); +- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-3].minor.yy190.pExpr, TK_NOTNULL); ++ yymsp[-3].minor.yy18 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy18,yymsp[0].minor.yy18); ++ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy18, yymsp[-3].minor.yy18, TK_NOTNULL); + } + break; +- case 179: /* expr ::= NOT expr */ +- case 180: /* expr ::= BITNOT expr */ yytestcase(yyruleno==180); +-{spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,yymsp[-1].major,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} ++ case 194: /* expr ::= NOT expr */ ++ case 195: /* expr ::= BITNOT expr */ yytestcase(yyruleno==195); ++{yymsp[-1].minor.yy18 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy18, 0);/*A-overwrites-B*/} + break; +- case 181: /* expr ::= MINUS expr */ +-{spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UMINUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} ++ case 196: /* expr ::= PLUS|MINUS expr */ ++{ ++ yymsp[-1].minor.yy18 = sqlite3PExpr(pParse, yymsp[-1].major==TK_PLUS ? TK_UPLUS : TK_UMINUS, yymsp[0].minor.yy18, 0); ++ /*A-overwrites-B*/ ++} + break; +- case 182: /* expr ::= PLUS expr */ +-{spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UPLUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} ++ case 197: /* between_op ::= BETWEEN */ ++ case 200: /* in_op ::= IN */ yytestcase(yyruleno==200); ++{yymsp[0].minor.yy70 = 0;} + break; +- case 183: /* between_op ::= BETWEEN */ +- case 186: /* in_op ::= IN */ yytestcase(yyruleno==186); +-{yymsp[0].minor.yy194 = 0;} +- break; +- case 185: /* expr ::= expr between_op expr AND expr */ ++ case 199: /* expr ::= expr between_op expr AND expr */ + { +- ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); +- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy190.pExpr); +- yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy190.pExpr, 0); +- if( yymsp[-4].minor.yy190.pExpr ){ +- yymsp[-4].minor.yy190.pExpr->x.pList = pList; ++ ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy18); ++ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy18); ++ yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy18, 0); ++ if( yymsp[-4].minor.yy18 ){ ++ yymsp[-4].minor.yy18->x.pList = pList; + }else{ + sqlite3ExprListDelete(pParse->db, pList); + } +- exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); +- yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; ++ if( yymsp[-3].minor.yy70 ) yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy18, 0); + } + break; +- case 188: /* expr ::= expr in_op LP exprlist RP */ ++ case 202: /* expr ::= expr in_op LP exprlist RP */ + { +- if( yymsp[-1].minor.yy148==0 ){ ++ if( yymsp[-1].minor.yy420==0 ){ + /* Expressions of the form + ** + ** expr1 IN () +@@ -139608,9 +150394,9 @@ + ** simplify to constants 0 (false) and 1 (true), respectively, + ** regardless of the value of expr1. + */ +- sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy190.pExpr); +- yymsp[-4].minor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[yymsp[-3].minor.yy194],1); +- }else if( yymsp[-1].minor.yy148->nExpr==1 ){ ++ sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy18); ++ yymsp[-4].minor.yy18 = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[yymsp[-3].minor.yy70],1); ++ }else if( yymsp[-1].minor.yy420->nExpr==1 ){ + /* Expressions of the form: + ** + ** expr1 IN (?1) +@@ -139627,9 +150413,9 @@ + ** affinity or the collating sequence to use for comparison. Otherwise, + ** the semantics would be subtly different from IN or NOT IN. + */ +- Expr *pRHS = yymsp[-1].minor.yy148->a[0].pExpr; +- yymsp[-1].minor.yy148->a[0].pExpr = 0; +- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy148); ++ Expr *pRHS = yymsp[-1].minor.yy420->a[0].pExpr; ++ yymsp[-1].minor.yy420->a[0].pExpr = 0; ++ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy420); + /* pRHS cannot be NULL because a malloc error would have been detected + ** before now and control would have never reached this point */ + if( ALWAYS(pRHS) ){ +@@ -139636,192 +150422,190 @@ + pRHS->flags &= ~EP_Collate; + pRHS->flags |= EP_Generic; + } +- yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, yymsp[-3].minor.yy194 ? TK_NE : TK_EQ, yymsp[-4].minor.yy190.pExpr, pRHS); ++ yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, yymsp[-3].minor.yy70 ? TK_NE : TK_EQ, yymsp[-4].minor.yy18, pRHS); + }else{ +- yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0); +- if( yymsp[-4].minor.yy190.pExpr ){ +- yymsp[-4].minor.yy190.pExpr->x.pList = yymsp[-1].minor.yy148; +- sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy190.pExpr); ++ yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy18, 0); ++ if( yymsp[-4].minor.yy18 ){ ++ yymsp[-4].minor.yy18->x.pList = yymsp[-1].minor.yy420; ++ sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy18); + }else{ +- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy148); ++ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy420); + } +- exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); ++ if( yymsp[-3].minor.yy70 ) yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy18, 0); + } +- yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + } + break; +- case 189: /* expr ::= LP select RP */ ++ case 203: /* expr ::= LP select RP */ + { +- spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ +- yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0); +- sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy190.pExpr, yymsp[-1].minor.yy243); ++ yymsp[-2].minor.yy18 = sqlite3PExpr(pParse, TK_SELECT, 0, 0); ++ sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy18, yymsp[-1].minor.yy489); + } + break; +- case 190: /* expr ::= expr in_op LP select RP */ ++ case 204: /* expr ::= expr in_op LP select RP */ + { +- yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0); +- sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, yymsp[-1].minor.yy243); +- exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); +- yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; ++ yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy18, 0); ++ sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy18, yymsp[-1].minor.yy489); ++ if( yymsp[-3].minor.yy70 ) yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy18, 0); + } + break; +- case 191: /* expr ::= expr in_op nm dbnm paren_exprlist */ ++ case 205: /* expr ::= expr in_op nm dbnm paren_exprlist */ + { + SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); +- Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); +- if( yymsp[0].minor.yy148 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy148); +- yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0); +- sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, pSelect); +- exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); +- yymsp[-4].minor.yy190.zEnd = yymsp[-1].minor.yy0.z ? &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n] : &yymsp[-2].minor.yy0.z[yymsp[-2].minor.yy0.n]; ++ Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0); ++ if( yymsp[0].minor.yy420 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy420); ++ yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy18, 0); ++ sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy18, pSelect); ++ if( yymsp[-3].minor.yy70 ) yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy18, 0); + } + break; +- case 192: /* expr ::= EXISTS LP select RP */ ++ case 206: /* expr ::= EXISTS LP select RP */ + { + Expr *p; +- spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ +- p = yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); +- sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy243); ++ p = yymsp[-3].minor.yy18 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); ++ sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy489); + } + break; +- case 193: /* expr ::= CASE case_operand case_exprlist case_else END */ ++ case 207: /* expr ::= CASE case_operand case_exprlist case_else END */ + { +- spanSet(&yymsp[-4].minor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-C*/ +- yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy72, 0); +- if( yymsp[-4].minor.yy190.pExpr ){ +- yymsp[-4].minor.yy190.pExpr->x.pList = yymsp[-1].minor.yy72 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[-1].minor.yy72) : yymsp[-2].minor.yy148; +- sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy190.pExpr); ++ yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy18, 0); ++ if( yymsp[-4].minor.yy18 ){ ++ yymsp[-4].minor.yy18->x.pList = yymsp[-1].minor.yy18 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy420,yymsp[-1].minor.yy18) : yymsp[-2].minor.yy420; ++ sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy18); + }else{ +- sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy148); +- sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy72); ++ sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy420); ++ sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy18); + } + } + break; +- case 194: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ ++ case 208: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ + { +- yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[-2].minor.yy190.pExpr); +- yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[0].minor.yy190.pExpr); ++ yymsp[-4].minor.yy420 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy420, yymsp[-2].minor.yy18); ++ yymsp[-4].minor.yy420 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy420, yymsp[0].minor.yy18); + } + break; +- case 195: /* case_exprlist ::= WHEN expr THEN expr */ ++ case 209: /* case_exprlist ::= WHEN expr THEN expr */ + { +- yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); +- yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, yymsp[0].minor.yy190.pExpr); ++ yymsp[-3].minor.yy420 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy18); ++ yymsp[-3].minor.yy420 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy420, yymsp[0].minor.yy18); + } + break; +- case 198: /* case_operand ::= expr */ +-{yymsp[0].minor.yy72 = yymsp[0].minor.yy190.pExpr; /*A-overwrites-X*/} ++ case 212: /* case_operand ::= expr */ ++{yymsp[0].minor.yy18 = yymsp[0].minor.yy18; /*A-overwrites-X*/} + break; +- case 201: /* nexprlist ::= nexprlist COMMA expr */ +-{yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[0].minor.yy190.pExpr);} ++ case 215: /* nexprlist ::= nexprlist COMMA expr */ ++{yymsp[-2].minor.yy420 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy420,yymsp[0].minor.yy18);} + break; +- case 202: /* nexprlist ::= expr */ +-{yymsp[0].minor.yy148 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy190.pExpr); /*A-overwrites-Y*/} ++ case 216: /* nexprlist ::= expr */ ++{yymsp[0].minor.yy420 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy18); /*A-overwrites-Y*/} + break; +- case 204: /* paren_exprlist ::= LP exprlist RP */ +- case 209: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==209); +-{yymsp[-2].minor.yy148 = yymsp[-1].minor.yy148;} ++ case 218: /* paren_exprlist ::= LP exprlist RP */ ++ case 223: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==223); ++{yymsp[-2].minor.yy420 = yymsp[-1].minor.yy420;} + break; +- case 205: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ ++ case 219: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ + { + sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, +- sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy148, yymsp[-10].minor.yy194, +- &yymsp[-11].minor.yy0, yymsp[0].minor.yy72, SQLITE_SO_ASC, yymsp[-8].minor.yy194, SQLITE_IDXTYPE_APPDEF); ++ sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy420, yymsp[-10].minor.yy70, ++ &yymsp[-11].minor.yy0, yymsp[0].minor.yy18, SQLITE_SO_ASC, yymsp[-8].minor.yy70, SQLITE_IDXTYPE_APPDEF); ++ if( IN_RENAME_OBJECT && pParse->pNewIndex ){ ++ sqlite3RenameTokenMap(pParse, pParse->pNewIndex->zName, &yymsp[-4].minor.yy0); ++ } + } + break; +- case 206: /* uniqueflag ::= UNIQUE */ +- case 246: /* raisetype ::= ABORT */ yytestcase(yyruleno==246); +-{yymsp[0].minor.yy194 = OE_Abort;} ++ case 220: /* uniqueflag ::= UNIQUE */ ++ case 260: /* raisetype ::= ABORT */ yytestcase(yyruleno==260); ++{yymsp[0].minor.yy70 = OE_Abort;} + break; +- case 207: /* uniqueflag ::= */ +-{yymsp[1].minor.yy194 = OE_None;} ++ case 221: /* uniqueflag ::= */ ++{yymsp[1].minor.yy70 = OE_None;} + break; +- case 210: /* eidlist ::= eidlist COMMA nm collate sortorder */ ++ case 224: /* eidlist ::= eidlist COMMA nm collate sortorder */ + { +- yymsp[-4].minor.yy148 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy148, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); ++ yymsp[-4].minor.yy420 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy420, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy70, yymsp[0].minor.yy70); + } + break; +- case 211: /* eidlist ::= nm collate sortorder */ ++ case 225: /* eidlist ::= nm collate sortorder */ + { +- yymsp[-2].minor.yy148 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); /*A-overwrites-Y*/ ++ yymsp[-2].minor.yy420 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy70, yymsp[0].minor.yy70); /*A-overwrites-Y*/ + } + break; +- case 214: /* cmd ::= DROP INDEX ifexists fullname */ +-{sqlite3DropIndex(pParse, yymsp[0].minor.yy185, yymsp[-1].minor.yy194);} ++ case 228: /* cmd ::= DROP INDEX ifexists fullname */ ++{sqlite3DropIndex(pParse, yymsp[0].minor.yy135, yymsp[-1].minor.yy70);} + break; +- case 215: /* cmd ::= VACUUM */ ++ case 229: /* cmd ::= VACUUM */ + {sqlite3Vacuum(pParse,0);} + break; +- case 216: /* cmd ::= VACUUM nm */ ++ case 230: /* cmd ::= VACUUM nm */ + {sqlite3Vacuum(pParse,&yymsp[0].minor.yy0);} + break; +- case 217: /* cmd ::= PRAGMA nm dbnm */ ++ case 231: /* cmd ::= PRAGMA nm dbnm */ + {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} + break; +- case 218: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ ++ case 232: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ + {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);} + break; +- case 219: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ ++ case 233: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ + {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);} + break; +- case 220: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ ++ case 234: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ + {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);} + break; +- case 221: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ ++ case 235: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ + {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);} + break; +- case 224: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ ++ case 238: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ + { + Token all; + all.z = yymsp[-3].minor.yy0.z; + all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n; +- sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy145, &all); ++ sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy207, &all); + } + break; +- case 225: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ ++ case 239: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + { +- sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy194, yymsp[-4].minor.yy332.a, yymsp[-4].minor.yy332.b, yymsp[-2].minor.yy185, yymsp[0].minor.yy72, yymsp[-10].minor.yy194, yymsp[-8].minor.yy194); ++ sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy70, yymsp[-4].minor.yy34.a, yymsp[-4].minor.yy34.b, yymsp[-2].minor.yy135, yymsp[0].minor.yy18, yymsp[-10].minor.yy70, yymsp[-8].minor.yy70); + yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/ + } + break; +- case 226: /* trigger_time ::= BEFORE|AFTER */ +-{ yymsp[0].minor.yy194 = yymsp[0].major; /*A-overwrites-X*/ } ++ case 240: /* trigger_time ::= BEFORE|AFTER */ ++{ yymsp[0].minor.yy70 = yymsp[0].major; /*A-overwrites-X*/ } + break; +- case 227: /* trigger_time ::= INSTEAD OF */ +-{ yymsp[-1].minor.yy194 = TK_INSTEAD;} ++ case 241: /* trigger_time ::= INSTEAD OF */ ++{ yymsp[-1].minor.yy70 = TK_INSTEAD;} + break; +- case 228: /* trigger_time ::= */ +-{ yymsp[1].minor.yy194 = TK_BEFORE; } ++ case 242: /* trigger_time ::= */ ++{ yymsp[1].minor.yy70 = TK_BEFORE; } + break; +- case 229: /* trigger_event ::= DELETE|INSERT */ +- case 230: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==230); +-{yymsp[0].minor.yy332.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy332.b = 0;} ++ case 243: /* trigger_event ::= DELETE|INSERT */ ++ case 244: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==244); ++{yymsp[0].minor.yy34.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy34.b = 0;} + break; +- case 231: /* trigger_event ::= UPDATE OF idlist */ +-{yymsp[-2].minor.yy332.a = TK_UPDATE; yymsp[-2].minor.yy332.b = yymsp[0].minor.yy254;} ++ case 245: /* trigger_event ::= UPDATE OF idlist */ ++{yymsp[-2].minor.yy34.a = TK_UPDATE; yymsp[-2].minor.yy34.b = yymsp[0].minor.yy48;} + break; +- case 232: /* when_clause ::= */ +- case 251: /* key_opt ::= */ yytestcase(yyruleno==251); +-{ yymsp[1].minor.yy72 = 0; } ++ case 246: /* when_clause ::= */ ++ case 265: /* key_opt ::= */ yytestcase(yyruleno==265); ++ case 307: /* filter_opt ::= */ yytestcase(yyruleno==307); ++{ yymsp[1].minor.yy18 = 0; } + break; +- case 233: /* when_clause ::= WHEN expr */ +- case 252: /* key_opt ::= KEY expr */ yytestcase(yyruleno==252); +-{ yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr; } ++ case 247: /* when_clause ::= WHEN expr */ ++ case 266: /* key_opt ::= KEY expr */ yytestcase(yyruleno==266); ++{ yymsp[-1].minor.yy18 = yymsp[0].minor.yy18; } + break; +- case 234: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ ++ case 248: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + { +- assert( yymsp[-2].minor.yy145!=0 ); +- yymsp[-2].minor.yy145->pLast->pNext = yymsp[-1].minor.yy145; +- yymsp[-2].minor.yy145->pLast = yymsp[-1].minor.yy145; ++ assert( yymsp[-2].minor.yy207!=0 ); ++ yymsp[-2].minor.yy207->pLast->pNext = yymsp[-1].minor.yy207; ++ yymsp[-2].minor.yy207->pLast = yymsp[-1].minor.yy207; + } + break; +- case 235: /* trigger_cmd_list ::= trigger_cmd SEMI */ ++ case 249: /* trigger_cmd_list ::= trigger_cmd SEMI */ + { +- assert( yymsp[-1].minor.yy145!=0 ); +- yymsp[-1].minor.yy145->pLast = yymsp[-1].minor.yy145; ++ assert( yymsp[-1].minor.yy207!=0 ); ++ yymsp[-1].minor.yy207->pLast = yymsp[-1].minor.yy207; + } + break; +- case 236: /* trnm ::= nm DOT nm */ ++ case 250: /* trnm ::= nm DOT nm */ + { + yymsp[-2].minor.yy0 = yymsp[0].minor.yy0; + sqlite3ErrorMsg(pParse, +@@ -139829,7 +150613,7 @@ + "statements within triggers"); + } + break; +- case 237: /* tridxby ::= INDEXED BY nm */ ++ case 251: /* tridxby ::= INDEXED BY nm */ + { + sqlite3ErrorMsg(pParse, + "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " +@@ -139836,7 +150620,7 @@ + "within triggers"); + } + break; +- case 238: /* tridxby ::= NOT INDEXED */ ++ case 252: /* tridxby ::= NOT INDEXED */ + { + sqlite3ErrorMsg(pParse, + "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " +@@ -139843,182 +150627,292 @@ + "within triggers"); + } + break; +- case 239: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ +-{yymsp[-6].minor.yy145 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy148, yymsp[0].minor.yy72, yymsp[-5].minor.yy194);} ++ case 253: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */ ++{yylhsminor.yy207 = sqlite3TriggerUpdateStep(pParse, &yymsp[-5].minor.yy0, yymsp[-2].minor.yy420, yymsp[-1].minor.yy18, yymsp[-6].minor.yy70, yymsp[-7].minor.yy0.z, yymsp[0].minor.yy392);} ++ yymsp[-7].minor.yy207 = yylhsminor.yy207; + break; +- case 240: /* trigger_cmd ::= insert_cmd INTO trnm idlist_opt select */ +-{yymsp[-4].minor.yy145 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy254, yymsp[0].minor.yy243, yymsp[-4].minor.yy194);/*A-overwrites-R*/} ++ case 254: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ ++{ ++ yylhsminor.yy207 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy48,yymsp[-2].minor.yy489,yymsp[-6].minor.yy70,yymsp[-1].minor.yy340,yymsp[-7].minor.yy392,yymsp[0].minor.yy392);/*yylhsminor.yy207-overwrites-yymsp[-6].minor.yy70*/ ++} ++ yymsp[-7].minor.yy207 = yylhsminor.yy207; + break; +- case 241: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ +-{yymsp[-4].minor.yy145 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy72);} ++ case 255: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ ++{yylhsminor.yy207 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy18, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy392);} ++ yymsp[-5].minor.yy207 = yylhsminor.yy207; + break; +- case 242: /* trigger_cmd ::= select */ +-{yymsp[0].minor.yy145 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy243); /*A-overwrites-X*/} ++ case 256: /* trigger_cmd ::= scanpt select scanpt */ ++{yylhsminor.yy207 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy489, yymsp[-2].minor.yy392, yymsp[0].minor.yy392); /*yylhsminor.yy207-overwrites-yymsp[-1].minor.yy489*/} ++ yymsp[-2].minor.yy207 = yylhsminor.yy207; + break; +- case 243: /* expr ::= RAISE LP IGNORE RP */ ++ case 257: /* expr ::= RAISE LP IGNORE RP */ + { +- spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ +- yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0); +- if( yymsp[-3].minor.yy190.pExpr ){ +- yymsp[-3].minor.yy190.pExpr->affinity = OE_Ignore; ++ yymsp[-3].minor.yy18 = sqlite3PExpr(pParse, TK_RAISE, 0, 0); ++ if( yymsp[-3].minor.yy18 ){ ++ yymsp[-3].minor.yy18->affinity = OE_Ignore; + } + } + break; +- case 244: /* expr ::= RAISE LP raisetype COMMA nm RP */ ++ case 258: /* expr ::= RAISE LP raisetype COMMA nm RP */ + { +- spanSet(&yymsp[-5].minor.yy190,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ +- yymsp[-5].minor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); +- if( yymsp[-5].minor.yy190.pExpr ) { +- yymsp[-5].minor.yy190.pExpr->affinity = (char)yymsp[-3].minor.yy194; ++ yymsp[-5].minor.yy18 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); ++ if( yymsp[-5].minor.yy18 ) { ++ yymsp[-5].minor.yy18->affinity = (char)yymsp[-3].minor.yy70; + } + } + break; +- case 245: /* raisetype ::= ROLLBACK */ +-{yymsp[0].minor.yy194 = OE_Rollback;} ++ case 259: /* raisetype ::= ROLLBACK */ ++{yymsp[0].minor.yy70 = OE_Rollback;} + break; +- case 247: /* raisetype ::= FAIL */ +-{yymsp[0].minor.yy194 = OE_Fail;} ++ case 261: /* raisetype ::= FAIL */ ++{yymsp[0].minor.yy70 = OE_Fail;} + break; +- case 248: /* cmd ::= DROP TRIGGER ifexists fullname */ ++ case 262: /* cmd ::= DROP TRIGGER ifexists fullname */ + { +- sqlite3DropTrigger(pParse,yymsp[0].minor.yy185,yymsp[-1].minor.yy194); ++ sqlite3DropTrigger(pParse,yymsp[0].minor.yy135,yymsp[-1].minor.yy70); + } + break; +- case 249: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ ++ case 263: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + { +- sqlite3Attach(pParse, yymsp[-3].minor.yy190.pExpr, yymsp[-1].minor.yy190.pExpr, yymsp[0].minor.yy72); ++ sqlite3Attach(pParse, yymsp[-3].minor.yy18, yymsp[-1].minor.yy18, yymsp[0].minor.yy18); + } + break; +- case 250: /* cmd ::= DETACH database_kw_opt expr */ ++ case 264: /* cmd ::= DETACH database_kw_opt expr */ + { +- sqlite3Detach(pParse, yymsp[0].minor.yy190.pExpr); ++ sqlite3Detach(pParse, yymsp[0].minor.yy18); + } + break; +- case 253: /* cmd ::= REINDEX */ ++ case 267: /* cmd ::= REINDEX */ + {sqlite3Reindex(pParse, 0, 0);} + break; +- case 254: /* cmd ::= REINDEX nm dbnm */ ++ case 268: /* cmd ::= REINDEX nm dbnm */ + {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} + break; +- case 255: /* cmd ::= ANALYZE */ ++ case 269: /* cmd ::= ANALYZE */ + {sqlite3Analyze(pParse, 0, 0);} + break; +- case 256: /* cmd ::= ANALYZE nm dbnm */ ++ case 270: /* cmd ::= ANALYZE nm dbnm */ + {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} + break; +- case 257: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ ++ case 271: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ + { +- sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy185,&yymsp[0].minor.yy0); ++ sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy135,&yymsp[0].minor.yy0); + } + break; +- case 258: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ ++ case 272: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ + { + yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n; + sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0); + } + break; +- case 259: /* add_column_fullname ::= fullname */ ++ case 273: /* add_column_fullname ::= fullname */ + { + disableLookaside(pParse); +- sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy185); ++ sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy135); + } + break; +- case 260: /* cmd ::= create_vtab */ ++ case 274: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ ++{ ++ sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy135, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); ++} ++ break; ++ case 275: /* cmd ::= create_vtab */ + {sqlite3VtabFinishParse(pParse,0);} + break; +- case 261: /* cmd ::= create_vtab LP vtabarglist RP */ ++ case 276: /* cmd ::= create_vtab LP vtabarglist RP */ + {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} + break; +- case 262: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ ++ case 277: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + { +- sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy194); ++ sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy70); + } + break; +- case 263: /* vtabarg ::= */ ++ case 278: /* vtabarg ::= */ + {sqlite3VtabArgInit(pParse);} + break; +- case 264: /* vtabargtoken ::= ANY */ +- case 265: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==265); +- case 266: /* lp ::= LP */ yytestcase(yyruleno==266); ++ case 279: /* vtabargtoken ::= ANY */ ++ case 280: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==280); ++ case 281: /* lp ::= LP */ yytestcase(yyruleno==281); + {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} + break; +- case 267: /* with ::= */ +-{yymsp[1].minor.yy285 = 0;} ++ case 282: /* with ::= WITH wqlist */ ++ case 283: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==283); ++{ sqlite3WithPush(pParse, yymsp[0].minor.yy449, 1); } + break; +- case 268: /* with ::= WITH wqlist */ +-{ yymsp[-1].minor.yy285 = yymsp[0].minor.yy285; } ++ case 284: /* wqlist ::= nm eidlist_opt AS LP select RP */ ++{ ++ yymsp[-5].minor.yy449 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy420, yymsp[-1].minor.yy489); /*A-overwrites-X*/ ++} + break; +- case 269: /* with ::= WITH RECURSIVE wqlist */ +-{ yymsp[-2].minor.yy285 = yymsp[0].minor.yy285; } ++ case 285: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ ++{ ++ yymsp[-7].minor.yy449 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy449, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy420, yymsp[-1].minor.yy489); ++} + break; +- case 270: /* wqlist ::= nm eidlist_opt AS LP select RP */ ++ case 286: /* windowdefn_list ::= windowdefn */ ++{ yylhsminor.yy327 = yymsp[0].minor.yy327; } ++ yymsp[0].minor.yy327 = yylhsminor.yy327; ++ break; ++ case 287: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */ + { +- yymsp[-5].minor.yy285 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); /*A-overwrites-X*/ ++ assert( yymsp[0].minor.yy327!=0 ); ++ yymsp[0].minor.yy327->pNextWin = yymsp[-2].minor.yy327; ++ yylhsminor.yy327 = yymsp[0].minor.yy327; + } ++ yymsp[-2].minor.yy327 = yylhsminor.yy327; + break; +- case 271: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ ++ case 288: /* windowdefn ::= nm AS window */ + { +- yymsp[-7].minor.yy285 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy285, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); ++ if( ALWAYS(yymsp[0].minor.yy327) ){ ++ yymsp[0].minor.yy327->zName = sqlite3DbStrNDup(pParse->db, yymsp[-2].minor.yy0.z, yymsp[-2].minor.yy0.n); ++ } ++ yylhsminor.yy327 = yymsp[0].minor.yy327; + } ++ yymsp[-2].minor.yy327 = yylhsminor.yy327; + break; ++ case 289: /* window ::= LP part_opt orderby_opt frame_opt RP */ ++{ ++ yymsp[-4].minor.yy327 = yymsp[-1].minor.yy327; ++ if( ALWAYS(yymsp[-4].minor.yy327) ){ ++ yymsp[-4].minor.yy327->pPartition = yymsp[-3].minor.yy420; ++ yymsp[-4].minor.yy327->pOrderBy = yymsp[-2].minor.yy420; ++ } ++} ++ break; ++ case 290: /* part_opt ::= PARTITION BY nexprlist */ ++{ yymsp[-2].minor.yy420 = yymsp[0].minor.yy420; } ++ break; ++ case 291: /* part_opt ::= */ ++{ yymsp[1].minor.yy420 = 0; } ++ break; ++ case 292: /* frame_opt ::= */ ++{ ++ yymsp[1].minor.yy327 = sqlite3WindowAlloc(pParse, TK_RANGE, TK_UNBOUNDED, 0, TK_CURRENT, 0); ++} ++ break; ++ case 293: /* frame_opt ::= range_or_rows frame_bound_s */ ++{ ++ yylhsminor.yy327 = sqlite3WindowAlloc(pParse, yymsp[-1].minor.yy70, yymsp[0].minor.yy119.eType, yymsp[0].minor.yy119.pExpr, TK_CURRENT, 0); ++} ++ yymsp[-1].minor.yy327 = yylhsminor.yy327; ++ break; ++ case 294: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e */ ++{ ++ yylhsminor.yy327 = sqlite3WindowAlloc(pParse, yymsp[-4].minor.yy70, yymsp[-2].minor.yy119.eType, yymsp[-2].minor.yy119.pExpr, yymsp[0].minor.yy119.eType, yymsp[0].minor.yy119.pExpr); ++} ++ yymsp[-4].minor.yy327 = yylhsminor.yy327; ++ break; ++ case 295: /* range_or_rows ::= RANGE */ ++{ yymsp[0].minor.yy70 = TK_RANGE; } ++ break; ++ case 296: /* range_or_rows ::= ROWS */ ++{ yymsp[0].minor.yy70 = TK_ROWS; } ++ break; ++ case 297: /* frame_bound_s ::= frame_bound */ ++ case 299: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==299); ++{ yylhsminor.yy119 = yymsp[0].minor.yy119; } ++ yymsp[0].minor.yy119 = yylhsminor.yy119; ++ break; ++ case 298: /* frame_bound_s ::= UNBOUNDED PRECEDING */ ++ case 300: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==300); ++{yymsp[-1].minor.yy119.eType = TK_UNBOUNDED; yymsp[-1].minor.yy119.pExpr = 0;} ++ break; ++ case 301: /* frame_bound ::= expr PRECEDING */ ++{ yylhsminor.yy119.eType = TK_PRECEDING; yylhsminor.yy119.pExpr = yymsp[-1].minor.yy18; } ++ yymsp[-1].minor.yy119 = yylhsminor.yy119; ++ break; ++ case 302: /* frame_bound ::= CURRENT ROW */ ++{ yymsp[-1].minor.yy119.eType = TK_CURRENT ; yymsp[-1].minor.yy119.pExpr = 0; } ++ break; ++ case 303: /* frame_bound ::= expr FOLLOWING */ ++{ yylhsminor.yy119.eType = TK_FOLLOWING; yylhsminor.yy119.pExpr = yymsp[-1].minor.yy18; } ++ yymsp[-1].minor.yy119 = yylhsminor.yy119; ++ break; ++ case 304: /* window_clause ::= WINDOW windowdefn_list */ ++{ yymsp[-1].minor.yy327 = yymsp[0].minor.yy327; } ++ break; ++ case 305: /* over_clause ::= filter_opt OVER window */ ++{ ++ yylhsminor.yy327 = yymsp[0].minor.yy327; ++ assert( yylhsminor.yy327!=0 ); ++ yylhsminor.yy327->pFilter = yymsp[-2].minor.yy18; ++} ++ yymsp[-2].minor.yy327 = yylhsminor.yy327; ++ break; ++ case 306: /* over_clause ::= filter_opt OVER nm */ ++{ ++ yylhsminor.yy327 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); ++ if( yylhsminor.yy327 ){ ++ yylhsminor.yy327->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n); ++ yylhsminor.yy327->pFilter = yymsp[-2].minor.yy18; ++ }else{ ++ sqlite3ExprDelete(pParse->db, yymsp[-2].minor.yy18); ++ } ++} ++ yymsp[-2].minor.yy327 = yylhsminor.yy327; ++ break; ++ case 308: /* filter_opt ::= FILTER LP WHERE expr RP */ ++{ yymsp[-4].minor.yy18 = yymsp[-1].minor.yy18; } ++ break; + default: +- /* (272) input ::= cmdlist */ yytestcase(yyruleno==272); +- /* (273) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==273); +- /* (274) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=274); +- /* (275) ecmd ::= SEMI */ yytestcase(yyruleno==275); +- /* (276) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==276); +- /* (277) explain ::= */ yytestcase(yyruleno==277); +- /* (278) trans_opt ::= */ yytestcase(yyruleno==278); +- /* (279) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==279); +- /* (280) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==280); +- /* (281) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==281); +- /* (282) savepoint_opt ::= */ yytestcase(yyruleno==282); +- /* (283) cmd ::= create_table create_table_args */ yytestcase(yyruleno==283); +- /* (284) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==284); +- /* (285) columnlist ::= columnname carglist */ yytestcase(yyruleno==285); +- /* (286) nm ::= ID|INDEXED */ yytestcase(yyruleno==286); +- /* (287) nm ::= STRING */ yytestcase(yyruleno==287); +- /* (288) nm ::= JOIN_KW */ yytestcase(yyruleno==288); +- /* (289) typetoken ::= typename */ yytestcase(yyruleno==289); +- /* (290) typename ::= ID|STRING */ yytestcase(yyruleno==290); +- /* (291) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=291); +- /* (292) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=292); +- /* (293) carglist ::= carglist ccons */ yytestcase(yyruleno==293); +- /* (294) carglist ::= */ yytestcase(yyruleno==294); +- /* (295) ccons ::= NULL onconf */ yytestcase(yyruleno==295); +- /* (296) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==296); +- /* (297) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==297); +- /* (298) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=298); +- /* (299) tconscomma ::= */ yytestcase(yyruleno==299); +- /* (300) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=300); +- /* (301) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=301); +- /* (302) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=302); +- /* (303) oneselect ::= values */ yytestcase(yyruleno==303); +- /* (304) sclp ::= selcollist COMMA */ yytestcase(yyruleno==304); +- /* (305) as ::= ID|STRING */ yytestcase(yyruleno==305); +- /* (306) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=306); +- /* (307) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==307); +- /* (308) exprlist ::= nexprlist */ yytestcase(yyruleno==308); +- /* (309) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=309); +- /* (310) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=310); +- /* (311) nmnum ::= ON */ yytestcase(yyruleno==311); +- /* (312) nmnum ::= DELETE */ yytestcase(yyruleno==312); +- /* (313) nmnum ::= DEFAULT */ yytestcase(yyruleno==313); +- /* (314) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==314); +- /* (315) foreach_clause ::= */ yytestcase(yyruleno==315); +- /* (316) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==316); +- /* (317) trnm ::= nm */ yytestcase(yyruleno==317); +- /* (318) tridxby ::= */ yytestcase(yyruleno==318); +- /* (319) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==319); +- /* (320) database_kw_opt ::= */ yytestcase(yyruleno==320); +- /* (321) kwcolumn_opt ::= */ yytestcase(yyruleno==321); +- /* (322) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==322); +- /* (323) vtabarglist ::= vtabarg */ yytestcase(yyruleno==323); +- /* (324) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==324); +- /* (325) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==325); +- /* (326) anylist ::= */ yytestcase(yyruleno==326); +- /* (327) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==327); +- /* (328) anylist ::= anylist ANY */ yytestcase(yyruleno==328); ++ /* (309) input ::= cmdlist */ yytestcase(yyruleno==309); ++ /* (310) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==310); ++ /* (311) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=311); ++ /* (312) ecmd ::= SEMI */ yytestcase(yyruleno==312); ++ /* (313) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==313); ++ /* (314) ecmd ::= explain cmdx */ yytestcase(yyruleno==314); ++ /* (315) trans_opt ::= */ yytestcase(yyruleno==315); ++ /* (316) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==316); ++ /* (317) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==317); ++ /* (318) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==318); ++ /* (319) savepoint_opt ::= */ yytestcase(yyruleno==319); ++ /* (320) cmd ::= create_table create_table_args */ yytestcase(yyruleno==320); ++ /* (321) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==321); ++ /* (322) columnlist ::= columnname carglist */ yytestcase(yyruleno==322); ++ /* (323) nm ::= ID|INDEXED */ yytestcase(yyruleno==323); ++ /* (324) nm ::= STRING */ yytestcase(yyruleno==324); ++ /* (325) nm ::= JOIN_KW */ yytestcase(yyruleno==325); ++ /* (326) typetoken ::= typename */ yytestcase(yyruleno==326); ++ /* (327) typename ::= ID|STRING */ yytestcase(yyruleno==327); ++ /* (328) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=328); ++ /* (329) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=329); ++ /* (330) carglist ::= carglist ccons */ yytestcase(yyruleno==330); ++ /* (331) carglist ::= */ yytestcase(yyruleno==331); ++ /* (332) ccons ::= NULL onconf */ yytestcase(yyruleno==332); ++ /* (333) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==333); ++ /* (334) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==334); ++ /* (335) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=335); ++ /* (336) tconscomma ::= */ yytestcase(yyruleno==336); ++ /* (337) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=337); ++ /* (338) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=338); ++ /* (339) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=339); ++ /* (340) oneselect ::= values */ yytestcase(yyruleno==340); ++ /* (341) sclp ::= selcollist COMMA */ yytestcase(yyruleno==341); ++ /* (342) as ::= ID|STRING */ yytestcase(yyruleno==342); ++ /* (343) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=343); ++ /* (344) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==344); ++ /* (345) exprlist ::= nexprlist */ yytestcase(yyruleno==345); ++ /* (346) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=346); ++ /* (347) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=347); ++ /* (348) nmnum ::= ON */ yytestcase(yyruleno==348); ++ /* (349) nmnum ::= DELETE */ yytestcase(yyruleno==349); ++ /* (350) nmnum ::= DEFAULT */ yytestcase(yyruleno==350); ++ /* (351) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==351); ++ /* (352) foreach_clause ::= */ yytestcase(yyruleno==352); ++ /* (353) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==353); ++ /* (354) trnm ::= nm */ yytestcase(yyruleno==354); ++ /* (355) tridxby ::= */ yytestcase(yyruleno==355); ++ /* (356) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==356); ++ /* (357) database_kw_opt ::= */ yytestcase(yyruleno==357); ++ /* (358) kwcolumn_opt ::= */ yytestcase(yyruleno==358); ++ /* (359) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==359); ++ /* (360) vtabarglist ::= vtabarg */ yytestcase(yyruleno==360); ++ /* (361) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==361); ++ /* (362) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==362); ++ /* (363) anylist ::= */ yytestcase(yyruleno==363); ++ /* (364) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==364); ++ /* (365) anylist ::= anylist ANY */ yytestcase(yyruleno==365); ++ /* (366) with ::= */ yytestcase(yyruleno==366); + break; + /********** End reduce actions ************************************************/ + }; +@@ -140034,16 +150928,12 @@ + /* It is not possible for a REDUCE to be followed by an error */ + assert( yyact!=YY_ERROR_ACTION ); + +- if( yyact==YY_ACCEPT_ACTION ){ +- yypParser->yytos += yysize; +- yy_accept(yypParser); +- }else{ +- yymsp += yysize+1; +- yypParser->yytos = yymsp; +- yymsp->stateno = (YYACTIONTYPE)yyact; +- yymsp->major = (YYCODETYPE)yygoto; +- yyTraceShift(yypParser, yyact); +- } ++ yymsp += yysize+1; ++ yypParser->yytos = yymsp; ++ yymsp->stateno = (YYACTIONTYPE)yyact; ++ yymsp->major = (YYCODETYPE)yygoto; ++ yyTraceShift(yypParser, yyact, "... then shift"); ++ return yyact; + } + + /* +@@ -140053,7 +150943,8 @@ + static void yy_parse_failed( + yyParser *yypParser /* The parser */ + ){ +- sqlite3ParserARG_FETCH; ++ sqlite3ParserARG_FETCH ++ sqlite3ParserCTX_FETCH + #ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); +@@ -140064,7 +150955,8 @@ + ** parser fails */ + /************ Begin %parse_failure code ***************************************/ + /************ End %parse_failure code *****************************************/ +- sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ ++ sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ ++ sqlite3ParserCTX_STORE + } + #endif /* YYNOERRORRECOVERY */ + +@@ -140076,15 +150968,20 @@ + int yymajor, /* The major type of the error token */ + sqlite3ParserTOKENTYPE yyminor /* The minor type of the error token */ + ){ +- sqlite3ParserARG_FETCH; ++ sqlite3ParserARG_FETCH ++ sqlite3ParserCTX_FETCH + #define TOKEN yyminor + /************ Begin %syntax_error code ****************************************/ + + UNUSED_PARAMETER(yymajor); /* Silence some compiler warnings */ +- assert( TOKEN.z[0] ); /* The tokenizer always gives us a token */ +- sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN); ++ if( TOKEN.z[0] ){ ++ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN); ++ }else{ ++ sqlite3ErrorMsg(pParse, "incomplete input"); ++ } + /************ End %syntax_error code ******************************************/ +- sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ ++ sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ ++ sqlite3ParserCTX_STORE + } + + /* +@@ -140093,7 +150990,8 @@ + static void yy_accept( + yyParser *yypParser /* The parser */ + ){ +- sqlite3ParserARG_FETCH; ++ sqlite3ParserARG_FETCH ++ sqlite3ParserCTX_FETCH + #ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); +@@ -140107,7 +151005,8 @@ + ** parser accepts */ + /*********** Begin %parse_accept code *****************************************/ + /*********** End %parse_accept code *******************************************/ +- sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ ++ sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ ++ sqlite3ParserCTX_STORE + } + + /* The main parser program. +@@ -140136,7 +151035,7 @@ + sqlite3ParserARG_PDECL /* Optional %extra_argument parameter */ + ){ + YYMINORTYPE yyminorunion; +- unsigned int yyact; /* The parser action. */ ++ YYACTIONTYPE yyact; /* The parser action. */ + #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) + int yyendofinput; /* True if we are at the end of input */ + #endif +@@ -140143,31 +151042,44 @@ + #ifdef YYERRORSYMBOL + int yyerrorhit = 0; /* True if yymajor has invoked an error */ + #endif +- yyParser *yypParser; /* The parser */ ++ yyParser *yypParser = (yyParser*)yyp; /* The parser */ ++ sqlite3ParserCTX_FETCH ++ sqlite3ParserARG_STORE + +- yypParser = (yyParser*)yyp; + assert( yypParser->yytos!=0 ); + #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) + yyendofinput = (yymajor==0); + #endif +- sqlite3ParserARG_STORE; + ++ yyact = yypParser->yytos->stateno; + #ifndef NDEBUG + if( yyTraceFILE ){ +- fprintf(yyTraceFILE,"%sInput '%s'\n",yyTracePrompt,yyTokenName[yymajor]); ++ if( yyact < YY_MIN_REDUCE ){ ++ fprintf(yyTraceFILE,"%sInput '%s' in state %d\n", ++ yyTracePrompt,yyTokenName[yymajor],yyact); ++ }else{ ++ fprintf(yyTraceFILE,"%sInput '%s' with pending reduce %d\n", ++ yyTracePrompt,yyTokenName[yymajor],yyact-YY_MIN_REDUCE); ++ } + } + #endif + + do{ +- yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor); +- if( yyact <= YY_MAX_SHIFTREDUCE ){ +- yy_shift(yypParser,yyact,yymajor,yyminor); ++ assert( yyact==yypParser->yytos->stateno ); ++ yyact = yy_find_shift_action((YYCODETYPE)yymajor,yyact); ++ if( yyact >= YY_MIN_REDUCE ){ ++ yyact = yy_reduce(yypParser,yyact-YY_MIN_REDUCE,yymajor, ++ yyminor sqlite3ParserCTX_PARAM); ++ }else if( yyact <= YY_MAX_SHIFTREDUCE ){ ++ yy_shift(yypParser,yyact,(YYCODETYPE)yymajor,yyminor); + #ifndef YYNOERRORRECOVERY + yypParser->yyerrcnt--; + #endif +- yymajor = YYNOCODE; +- }else if( yyact <= YY_MAX_REDUCE ){ +- yy_reduce(yypParser,yyact-YY_MIN_REDUCE); ++ break; ++ }else if( yyact==YY_ACCEPT_ACTION ){ ++ yypParser->yytos--; ++ yy_accept(yypParser); ++ return; + }else{ + assert( yyact == YY_ERROR_ACTION ); + yyminorunion.yy0 = yyminor; +@@ -140214,10 +151126,9 @@ + yymajor = YYNOCODE; + }else{ + while( yypParser->yytos >= yypParser->yystack +- && yymx != YYERRORSYMBOL + && (yyact = yy_find_reduce_action( + yypParser->yytos->stateno, +- YYERRORSYMBOL)) >= YY_MIN_REDUCE ++ YYERRORSYMBOL)) > YY_MAX_SHIFTREDUCE + ){ + yy_pop_parser_stack(yypParser); + } +@@ -140234,6 +151145,8 @@ + } + yypParser->yyerrcnt = 3; + yyerrorhit = 1; ++ if( yymajor==YYNOCODE ) break; ++ yyact = yypParser->yytos->stateno; + #elif defined(YYNOERRORRECOVERY) + /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to + ** do any kind of error recovery. Instead, simply invoke the syntax +@@ -140244,8 +151157,7 @@ + */ + yy_syntax_error(yypParser,yymajor, yyminor); + yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); +- yymajor = YYNOCODE; +- ++ break; + #else /* YYERRORSYMBOL is not defined */ + /* This is what we do if the grammar does not define ERROR: + ** +@@ -140267,10 +151179,10 @@ + yypParser->yyerrcnt = -1; + #endif + } +- yymajor = YYNOCODE; ++ break; + #endif + } +- }while( yymajor!=YYNOCODE && yypParser->yytos>yypParser->yystack ); ++ }while( yypParser->yytos>yypParser->yystack ); + #ifndef NDEBUG + if( yyTraceFILE ){ + yyStackEntry *i; +@@ -140286,6 +151198,21 @@ + return; + } + ++/* ++** Return the fallback token corresponding to canonical token iToken, or ++** 0 if iToken has no fallback. ++*/ ++SQLITE_PRIVATE int sqlite3ParserFallback(int iToken){ ++#ifdef YYFALLBACK ++ if( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ){ ++ return yyFallback[iToken]; ++ } ++#else ++ (void)iToken; ++#endif ++ return 0; ++} ++ + /************** End of parse.c ***********************************************/ + /************** Begin file tokenize.c ****************************************/ + /* +@@ -140344,11 +151271,12 @@ + #define CC_TILDA 25 /* '~' */ + #define CC_DOT 26 /* '.' */ + #define CC_ILLEGAL 27 /* Illegal character */ ++#define CC_NUL 28 /* 0x00 */ + + static const unsigned char aiClass[] = { + #ifdef SQLITE_ASCII + /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ +-/* 0x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 27, 7, 7, 27, 27, ++/* 0x */ 28, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 27, 7, 7, 27, 27, + /* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + /* 2x */ 7, 15, 8, 5, 4, 22, 24, 8, 17, 18, 21, 20, 23, 11, 26, 16, + /* 3x */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 19, 12, 14, 13, 6, +@@ -140447,19 +151375,20 @@ + ** is substantially reduced. This is important for embedded applications + ** on platforms with limited memory. + */ +-/* Hash score: 182 */ +-/* zKWText[] encodes 834 bytes of keyword text in 554 bytes */ ++/* Hash score: 208 */ ++/* zKWText[] encodes 923 bytes of keyword text in 614 bytes */ + /* REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT */ + /* ABLEFTHENDEFERRABLELSEXCEPTRANSACTIONATURALTERAISEXCLUSIVE */ + /* XISTSAVEPOINTERSECTRIGGEREFERENCESCONSTRAINTOFFSETEMPORARY */ +-/* UNIQUERYWITHOUTERELEASEATTACHAVINGROUPDATEBEGINNERECURSIVE */ +-/* BETWEENOTNULLIKECASCADELETECASECOLLATECREATECURRENT_DATEDETACH */ +-/* IMMEDIATEJOINSERTMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMITWHEN */ +-/* WHERENAMEAFTEREPLACEANDEFAULTAUTOINCREMENTCASTCOLUMNCOMMIT */ +-/* CONFLICTCROSSCURRENT_TIMESTAMPRIMARYDEFERREDISTINCTDROPFAIL */ +-/* FROMFULLGLOBYIFISNULLORDERESTRICTRIGHTROLLBACKROWUNIONUSING */ +-/* VACUUMVIEWINITIALLY */ +-static const char zKWText[553] = { ++/* UNIQUERYWITHOUTERELEASEATTACHAVINGROUPDATEBEGINNERANGEBETWEEN */ ++/* OTHINGLOBYCASCADELETECASECOLLATECREATECURRENT_DATEDETACH */ ++/* IMMEDIATEJOINSERTLIKEMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMIT */ ++/* WHENOTNULLWHERECURSIVEAFTERENAMEANDEFAULTAUTOINCREMENTCAST */ ++/* COLUMNCOMMITCONFLICTCROSSCURRENT_TIMESTAMPARTITIONDEFERRED */ ++/* ISTINCTDROPRECEDINGFAILFILTEREPLACEFOLLOWINGFROMFULLIFISNULL */ ++/* ORDERESTRICTOVERIGHTROLLBACKROWSUNBOUNDEDUNIONUSINGVACUUMVIEW */ ++/* INDOWINITIALLYPRIMARY */ ++static const char zKWText[613] = { + 'R','E','I','N','D','E','X','E','D','E','S','C','A','P','E','A','C','H', + 'E','C','K','E','Y','B','E','F','O','R','E','I','G','N','O','R','E','G', + 'E','X','P','L','A','I','N','S','T','E','A','D','D','A','T','A','B','A', +@@ -140472,83 +151401,90 @@ + 'O','F','F','S','E','T','E','M','P','O','R','A','R','Y','U','N','I','Q', + 'U','E','R','Y','W','I','T','H','O','U','T','E','R','E','L','E','A','S', + 'E','A','T','T','A','C','H','A','V','I','N','G','R','O','U','P','D','A', +- 'T','E','B','E','G','I','N','N','E','R','E','C','U','R','S','I','V','E', +- 'B','E','T','W','E','E','N','O','T','N','U','L','L','I','K','E','C','A', +- 'S','C','A','D','E','L','E','T','E','C','A','S','E','C','O','L','L','A', +- 'T','E','C','R','E','A','T','E','C','U','R','R','E','N','T','_','D','A', +- 'T','E','D','E','T','A','C','H','I','M','M','E','D','I','A','T','E','J', +- 'O','I','N','S','E','R','T','M','A','T','C','H','P','L','A','N','A','L', +- 'Y','Z','E','P','R','A','G','M','A','B','O','R','T','V','A','L','U','E', +- 'S','V','I','R','T','U','A','L','I','M','I','T','W','H','E','N','W','H', +- 'E','R','E','N','A','M','E','A','F','T','E','R','E','P','L','A','C','E', +- 'A','N','D','E','F','A','U','L','T','A','U','T','O','I','N','C','R','E', +- 'M','E','N','T','C','A','S','T','C','O','L','U','M','N','C','O','M','M', +- 'I','T','C','O','N','F','L','I','C','T','C','R','O','S','S','C','U','R', +- 'R','E','N','T','_','T','I','M','E','S','T','A','M','P','R','I','M','A', +- 'R','Y','D','E','F','E','R','R','E','D','I','S','T','I','N','C','T','D', +- 'R','O','P','F','A','I','L','F','R','O','M','F','U','L','L','G','L','O', +- 'B','Y','I','F','I','S','N','U','L','L','O','R','D','E','R','E','S','T', +- 'R','I','C','T','R','I','G','H','T','R','O','L','L','B','A','C','K','R', +- 'O','W','U','N','I','O','N','U','S','I','N','G','V','A','C','U','U','M', +- 'V','I','E','W','I','N','I','T','I','A','L','L','Y', ++ 'T','E','B','E','G','I','N','N','E','R','A','N','G','E','B','E','T','W', ++ 'E','E','N','O','T','H','I','N','G','L','O','B','Y','C','A','S','C','A', ++ 'D','E','L','E','T','E','C','A','S','E','C','O','L','L','A','T','E','C', ++ 'R','E','A','T','E','C','U','R','R','E','N','T','_','D','A','T','E','D', ++ 'E','T','A','C','H','I','M','M','E','D','I','A','T','E','J','O','I','N', ++ 'S','E','R','T','L','I','K','E','M','A','T','C','H','P','L','A','N','A', ++ 'L','Y','Z','E','P','R','A','G','M','A','B','O','R','T','V','A','L','U', ++ 'E','S','V','I','R','T','U','A','L','I','M','I','T','W','H','E','N','O', ++ 'T','N','U','L','L','W','H','E','R','E','C','U','R','S','I','V','E','A', ++ 'F','T','E','R','E','N','A','M','E','A','N','D','E','F','A','U','L','T', ++ 'A','U','T','O','I','N','C','R','E','M','E','N','T','C','A','S','T','C', ++ 'O','L','U','M','N','C','O','M','M','I','T','C','O','N','F','L','I','C', ++ 'T','C','R','O','S','S','C','U','R','R','E','N','T','_','T','I','M','E', ++ 'S','T','A','M','P','A','R','T','I','T','I','O','N','D','E','F','E','R', ++ 'R','E','D','I','S','T','I','N','C','T','D','R','O','P','R','E','C','E', ++ 'D','I','N','G','F','A','I','L','F','I','L','T','E','R','E','P','L','A', ++ 'C','E','F','O','L','L','O','W','I','N','G','F','R','O','M','F','U','L', ++ 'L','I','F','I','S','N','U','L','L','O','R','D','E','R','E','S','T','R', ++ 'I','C','T','O','V','E','R','I','G','H','T','R','O','L','L','B','A','C', ++ 'K','R','O','W','S','U','N','B','O','U','N','D','E','D','U','N','I','O', ++ 'N','U','S','I','N','G','V','A','C','U','U','M','V','I','E','W','I','N', ++ 'D','O','W','I','N','I','T','I','A','L','L','Y','P','R','I','M','A','R', ++ 'Y', + }; + /* aKWHash[i] is the hash value for the i-th keyword */ + static const unsigned char aKWHash[127] = { +- 76, 105, 117, 74, 0, 45, 0, 0, 82, 0, 77, 0, 0, +- 42, 12, 78, 15, 0, 116, 85, 54, 112, 0, 19, 0, 0, +- 121, 0, 119, 115, 0, 22, 93, 0, 9, 0, 0, 70, 71, +- 0, 69, 6, 0, 48, 90, 102, 0, 118, 101, 0, 0, 44, +- 0, 103, 24, 0, 17, 0, 122, 53, 23, 0, 5, 110, 25, +- 96, 0, 0, 124, 106, 60, 123, 57, 28, 55, 0, 91, 0, +- 100, 26, 0, 99, 0, 0, 0, 95, 92, 97, 88, 109, 14, +- 39, 108, 0, 81, 0, 18, 89, 111, 32, 0, 120, 80, 113, +- 62, 46, 84, 0, 0, 94, 40, 59, 114, 0, 36, 0, 0, +- 29, 0, 86, 63, 64, 0, 20, 61, 0, 56, ++ 74, 109, 124, 72, 106, 45, 0, 0, 81, 0, 76, 61, 0, ++ 42, 12, 77, 15, 0, 123, 84, 54, 118, 125, 19, 0, 0, ++ 130, 0, 128, 121, 0, 22, 96, 0, 9, 0, 0, 115, 69, ++ 0, 67, 6, 0, 48, 93, 136, 0, 126, 104, 0, 0, 44, ++ 0, 107, 24, 0, 17, 0, 131, 53, 23, 0, 5, 62, 132, ++ 99, 0, 0, 135, 110, 60, 134, 57, 113, 55, 0, 94, 0, ++ 103, 26, 0, 102, 0, 0, 0, 98, 95, 100, 105, 117, 14, ++ 39, 116, 0, 80, 0, 133, 114, 92, 59, 0, 129, 79, 119, ++ 86, 46, 83, 0, 0, 97, 40, 122, 120, 0, 127, 0, 0, ++ 29, 0, 89, 87, 88, 0, 20, 85, 111, 56, + }; + /* aKWNext[] forms the hash collision chain. If aKWHash[i]==0 + ** then the i-th keyword has no more hash collisions. Otherwise, + ** the next keyword with the same hash is aKWHash[i]-1. */ +-static const unsigned char aKWNext[124] = { ++static const unsigned char aKWNext[136] = { + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, + 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 33, 0, 21, 0, 0, 0, 0, 0, 50, +- 0, 43, 3, 47, 0, 0, 0, 0, 30, 0, 58, 0, 38, +- 0, 0, 0, 1, 66, 0, 0, 67, 0, 41, 0, 0, 0, +- 0, 0, 0, 49, 65, 0, 0, 0, 0, 31, 52, 16, 34, +- 10, 0, 0, 0, 0, 0, 0, 0, 11, 72, 79, 0, 8, +- 0, 104, 98, 0, 107, 0, 87, 0, 75, 51, 0, 27, 37, +- 73, 83, 0, 35, 68, 0, 0, ++ 0, 43, 3, 47, 0, 0, 32, 0, 0, 0, 0, 0, 0, ++ 0, 1, 64, 0, 0, 65, 0, 41, 0, 38, 0, 0, 0, ++ 0, 0, 49, 75, 0, 0, 30, 0, 58, 0, 0, 0, 31, ++ 63, 16, 34, 10, 0, 0, 0, 0, 0, 0, 0, 11, 70, ++ 91, 0, 0, 8, 0, 108, 0, 101, 28, 52, 68, 0, 112, ++ 0, 73, 51, 0, 90, 27, 37, 0, 71, 36, 82, 0, 35, ++ 66, 25, 18, 0, 0, 78, + }; + /* aKWLen[i] is the length (in bytes) of the i-th keyword */ +-static const unsigned char aKWLen[124] = { ++static const unsigned char aKWLen[136] = { + 7, 7, 5, 4, 6, 4, 5, 3, 6, 7, 3, 6, 6, + 7, 7, 3, 8, 2, 6, 5, 4, 4, 3, 10, 4, 6, + 11, 6, 2, 7, 5, 5, 9, 6, 9, 9, 7, 10, 10, + 4, 6, 2, 3, 9, 4, 2, 6, 5, 7, 4, 5, 7, +- 6, 6, 5, 6, 5, 5, 9, 7, 7, 3, 2, 4, 4, +- 7, 3, 6, 4, 7, 6, 12, 6, 9, 4, 6, 5, 4, +- 7, 6, 5, 6, 7, 5, 4, 5, 6, 5, 7, 3, 7, +- 13, 2, 2, 4, 6, 6, 8, 5, 17, 12, 7, 8, 8, +- 2, 4, 4, 4, 4, 4, 2, 2, 6, 5, 8, 5, 8, +- 3, 5, 5, 6, 4, 9, 3, ++ 6, 6, 5, 6, 5, 5, 5, 7, 7, 4, 2, 7, 3, ++ 6, 4, 7, 6, 12, 6, 9, 4, 6, 4, 5, 4, 7, ++ 6, 5, 6, 7, 5, 4, 7, 3, 2, 4, 5, 9, 5, ++ 6, 3, 7, 13, 2, 2, 4, 6, 6, 8, 5, 17, 12, ++ 7, 9, 8, 8, 2, 4, 9, 4, 6, 7, 9, 4, 4, ++ 2, 6, 5, 8, 4, 5, 8, 4, 3, 9, 5, 5, 6, ++ 4, 6, 2, 9, 3, 7, + }; + /* aKWOffset[i] is the index into zKWText[] of the start of + ** the text for the i-th keyword. */ +-static const unsigned short int aKWOffset[124] = { ++static const unsigned short int aKWOffset[136] = { + 0, 2, 2, 8, 9, 14, 16, 20, 23, 25, 25, 29, 33, + 36, 41, 46, 48, 53, 54, 59, 62, 65, 67, 69, 78, 81, + 86, 91, 95, 96, 101, 105, 109, 117, 122, 128, 136, 142, 152, + 159, 162, 162, 165, 167, 167, 171, 176, 179, 184, 184, 188, 192, +- 199, 204, 209, 212, 218, 221, 225, 234, 240, 240, 240, 243, 246, +- 250, 251, 255, 261, 265, 272, 278, 290, 296, 305, 307, 313, 318, +- 320, 327, 332, 337, 343, 349, 354, 358, 361, 367, 371, 378, 380, +- 387, 389, 391, 400, 404, 410, 416, 424, 429, 429, 445, 452, 459, +- 460, 467, 471, 475, 479, 483, 486, 488, 490, 496, 500, 508, 513, +- 521, 524, 529, 534, 540, 544, 549, ++ 199, 204, 209, 212, 218, 221, 225, 230, 236, 242, 245, 247, 248, ++ 252, 258, 262, 269, 275, 287, 293, 302, 304, 310, 314, 319, 321, ++ 328, 333, 338, 344, 350, 355, 358, 358, 358, 361, 365, 368, 377, ++ 381, 387, 389, 396, 398, 400, 409, 413, 419, 425, 433, 438, 438, ++ 438, 454, 463, 470, 471, 478, 481, 490, 494, 499, 506, 515, 519, ++ 523, 525, 531, 535, 543, 546, 551, 559, 559, 563, 572, 577, 582, ++ 588, 591, 594, 597, 602, 606, + }; + /* aKWCode[i] is the parser symbol code for the i-th keyword */ +-static const unsigned char aKWCode[124] = { ++static const unsigned char aKWCode[136] = { + TK_REINDEX, TK_INDEXED, TK_INDEX, TK_DESC, TK_ESCAPE, + TK_EACH, TK_CHECK, TK_KEY, TK_BEFORE, TK_FOREIGN, + TK_FOR, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD, +@@ -140560,20 +151496,23 @@ + TK_OFFSET, TK_OF, TK_SET, TK_TEMP, TK_TEMP, + TK_OR, TK_UNIQUE, TK_QUERY, TK_WITHOUT, TK_WITH, + TK_JOIN_KW, TK_RELEASE, TK_ATTACH, TK_HAVING, TK_GROUP, +- TK_UPDATE, TK_BEGIN, TK_JOIN_KW, TK_RECURSIVE, TK_BETWEEN, +- TK_NOTNULL, TK_NOT, TK_NO, TK_NULL, TK_LIKE_KW, +- TK_CASCADE, TK_ASC, TK_DELETE, TK_CASE, TK_COLLATE, +- TK_CREATE, TK_CTIME_KW, TK_DETACH, TK_IMMEDIATE, TK_JOIN, +- TK_INSERT, TK_MATCH, TK_PLAN, TK_ANALYZE, TK_PRAGMA, +- TK_ABORT, TK_VALUES, TK_VIRTUAL, TK_LIMIT, TK_WHEN, +- TK_WHERE, TK_RENAME, TK_AFTER, TK_REPLACE, TK_AND, +- TK_DEFAULT, TK_AUTOINCR, TK_TO, TK_IN, TK_CAST, +- TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_JOIN_KW, TK_CTIME_KW, +- TK_CTIME_KW, TK_PRIMARY, TK_DEFERRED, TK_DISTINCT, TK_IS, +- TK_DROP, TK_FAIL, TK_FROM, TK_JOIN_KW, TK_LIKE_KW, +- TK_BY, TK_IF, TK_ISNULL, TK_ORDER, TK_RESTRICT, +- TK_JOIN_KW, TK_ROLLBACK, TK_ROW, TK_UNION, TK_USING, +- TK_VACUUM, TK_VIEW, TK_INITIALLY, TK_ALL, ++ TK_UPDATE, TK_BEGIN, TK_JOIN_KW, TK_RANGE, TK_BETWEEN, ++ TK_NOTHING, TK_LIKE_KW, TK_BY, TK_CASCADE, TK_ASC, ++ TK_DELETE, TK_CASE, TK_COLLATE, TK_CREATE, TK_CTIME_KW, ++ TK_DETACH, TK_IMMEDIATE, TK_JOIN, TK_INSERT, TK_LIKE_KW, ++ TK_MATCH, TK_PLAN, TK_ANALYZE, TK_PRAGMA, TK_ABORT, ++ TK_VALUES, TK_VIRTUAL, TK_LIMIT, TK_WHEN, TK_NOTNULL, ++ TK_NOT, TK_NO, TK_NULL, TK_WHERE, TK_RECURSIVE, ++ TK_AFTER, TK_RENAME, TK_AND, TK_DEFAULT, TK_AUTOINCR, ++ TK_TO, TK_IN, TK_CAST, TK_COLUMNKW, TK_COMMIT, ++ TK_CONFLICT, TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW, TK_CURRENT, ++ TK_PARTITION, TK_DEFERRED, TK_DISTINCT, TK_IS, TK_DROP, ++ TK_PRECEDING, TK_FAIL, TK_FILTER, TK_REPLACE, TK_FOLLOWING, ++ TK_FROM, TK_JOIN_KW, TK_IF, TK_ISNULL, TK_ORDER, ++ TK_RESTRICT, TK_OVER, TK_JOIN_KW, TK_ROLLBACK, TK_ROWS, ++ TK_ROW, TK_UNBOUNDED, TK_UNION, TK_USING, TK_VACUUM, ++ TK_VIEW, TK_WINDOW, TK_DO, TK_INITIALLY, TK_ALL, ++ TK_PRIMARY, + }; + /* Check to see if z[0..n-1] is a keyword. If it is, write the + ** parser symbol code for that keyword into *pType. Always +@@ -140652,72 +151591,84 @@ + testcase( i==55 ); /* UPDATE */ + testcase( i==56 ); /* BEGIN */ + testcase( i==57 ); /* INNER */ +- testcase( i==58 ); /* RECURSIVE */ ++ testcase( i==58 ); /* RANGE */ + testcase( i==59 ); /* BETWEEN */ +- testcase( i==60 ); /* NOTNULL */ +- testcase( i==61 ); /* NOT */ +- testcase( i==62 ); /* NO */ +- testcase( i==63 ); /* NULL */ +- testcase( i==64 ); /* LIKE */ +- testcase( i==65 ); /* CASCADE */ +- testcase( i==66 ); /* ASC */ +- testcase( i==67 ); /* DELETE */ +- testcase( i==68 ); /* CASE */ +- testcase( i==69 ); /* COLLATE */ +- testcase( i==70 ); /* CREATE */ +- testcase( i==71 ); /* CURRENT_DATE */ +- testcase( i==72 ); /* DETACH */ +- testcase( i==73 ); /* IMMEDIATE */ +- testcase( i==74 ); /* JOIN */ +- testcase( i==75 ); /* INSERT */ +- testcase( i==76 ); /* MATCH */ +- testcase( i==77 ); /* PLAN */ +- testcase( i==78 ); /* ANALYZE */ +- testcase( i==79 ); /* PRAGMA */ +- testcase( i==80 ); /* ABORT */ +- testcase( i==81 ); /* VALUES */ +- testcase( i==82 ); /* VIRTUAL */ +- testcase( i==83 ); /* LIMIT */ +- testcase( i==84 ); /* WHEN */ +- testcase( i==85 ); /* WHERE */ +- testcase( i==86 ); /* RENAME */ +- testcase( i==87 ); /* AFTER */ +- testcase( i==88 ); /* REPLACE */ +- testcase( i==89 ); /* AND */ +- testcase( i==90 ); /* DEFAULT */ +- testcase( i==91 ); /* AUTOINCREMENT */ +- testcase( i==92 ); /* TO */ +- testcase( i==93 ); /* IN */ +- testcase( i==94 ); /* CAST */ +- testcase( i==95 ); /* COLUMN */ +- testcase( i==96 ); /* COMMIT */ +- testcase( i==97 ); /* CONFLICT */ +- testcase( i==98 ); /* CROSS */ +- testcase( i==99 ); /* CURRENT_TIMESTAMP */ +- testcase( i==100 ); /* CURRENT_TIME */ +- testcase( i==101 ); /* PRIMARY */ +- testcase( i==102 ); /* DEFERRED */ +- testcase( i==103 ); /* DISTINCT */ +- testcase( i==104 ); /* IS */ +- testcase( i==105 ); /* DROP */ +- testcase( i==106 ); /* FAIL */ +- testcase( i==107 ); /* FROM */ +- testcase( i==108 ); /* FULL */ +- testcase( i==109 ); /* GLOB */ +- testcase( i==110 ); /* BY */ +- testcase( i==111 ); /* IF */ +- testcase( i==112 ); /* ISNULL */ +- testcase( i==113 ); /* ORDER */ +- testcase( i==114 ); /* RESTRICT */ +- testcase( i==115 ); /* RIGHT */ +- testcase( i==116 ); /* ROLLBACK */ +- testcase( i==117 ); /* ROW */ +- testcase( i==118 ); /* UNION */ +- testcase( i==119 ); /* USING */ +- testcase( i==120 ); /* VACUUM */ +- testcase( i==121 ); /* VIEW */ +- testcase( i==122 ); /* INITIALLY */ +- testcase( i==123 ); /* ALL */ ++ testcase( i==60 ); /* NOTHING */ ++ testcase( i==61 ); /* GLOB */ ++ testcase( i==62 ); /* BY */ ++ testcase( i==63 ); /* CASCADE */ ++ testcase( i==64 ); /* ASC */ ++ testcase( i==65 ); /* DELETE */ ++ testcase( i==66 ); /* CASE */ ++ testcase( i==67 ); /* COLLATE */ ++ testcase( i==68 ); /* CREATE */ ++ testcase( i==69 ); /* CURRENT_DATE */ ++ testcase( i==70 ); /* DETACH */ ++ testcase( i==71 ); /* IMMEDIATE */ ++ testcase( i==72 ); /* JOIN */ ++ testcase( i==73 ); /* INSERT */ ++ testcase( i==74 ); /* LIKE */ ++ testcase( i==75 ); /* MATCH */ ++ testcase( i==76 ); /* PLAN */ ++ testcase( i==77 ); /* ANALYZE */ ++ testcase( i==78 ); /* PRAGMA */ ++ testcase( i==79 ); /* ABORT */ ++ testcase( i==80 ); /* VALUES */ ++ testcase( i==81 ); /* VIRTUAL */ ++ testcase( i==82 ); /* LIMIT */ ++ testcase( i==83 ); /* WHEN */ ++ testcase( i==84 ); /* NOTNULL */ ++ testcase( i==85 ); /* NOT */ ++ testcase( i==86 ); /* NO */ ++ testcase( i==87 ); /* NULL */ ++ testcase( i==88 ); /* WHERE */ ++ testcase( i==89 ); /* RECURSIVE */ ++ testcase( i==90 ); /* AFTER */ ++ testcase( i==91 ); /* RENAME */ ++ testcase( i==92 ); /* AND */ ++ testcase( i==93 ); /* DEFAULT */ ++ testcase( i==94 ); /* AUTOINCREMENT */ ++ testcase( i==95 ); /* TO */ ++ testcase( i==96 ); /* IN */ ++ testcase( i==97 ); /* CAST */ ++ testcase( i==98 ); /* COLUMN */ ++ testcase( i==99 ); /* COMMIT */ ++ testcase( i==100 ); /* CONFLICT */ ++ testcase( i==101 ); /* CROSS */ ++ testcase( i==102 ); /* CURRENT_TIMESTAMP */ ++ testcase( i==103 ); /* CURRENT_TIME */ ++ testcase( i==104 ); /* CURRENT */ ++ testcase( i==105 ); /* PARTITION */ ++ testcase( i==106 ); /* DEFERRED */ ++ testcase( i==107 ); /* DISTINCT */ ++ testcase( i==108 ); /* IS */ ++ testcase( i==109 ); /* DROP */ ++ testcase( i==110 ); /* PRECEDING */ ++ testcase( i==111 ); /* FAIL */ ++ testcase( i==112 ); /* FILTER */ ++ testcase( i==113 ); /* REPLACE */ ++ testcase( i==114 ); /* FOLLOWING */ ++ testcase( i==115 ); /* FROM */ ++ testcase( i==116 ); /* FULL */ ++ testcase( i==117 ); /* IF */ ++ testcase( i==118 ); /* ISNULL */ ++ testcase( i==119 ); /* ORDER */ ++ testcase( i==120 ); /* RESTRICT */ ++ testcase( i==121 ); /* OVER */ ++ testcase( i==122 ); /* RIGHT */ ++ testcase( i==123 ); /* ROLLBACK */ ++ testcase( i==124 ); /* ROWS */ ++ testcase( i==125 ); /* ROW */ ++ testcase( i==126 ); /* UNBOUNDED */ ++ testcase( i==127 ); /* UNION */ ++ testcase( i==128 ); /* USING */ ++ testcase( i==129 ); /* VACUUM */ ++ testcase( i==130 ); /* VIEW */ ++ testcase( i==131 ); /* WINDOW */ ++ testcase( i==132 ); /* DO */ ++ testcase( i==133 ); /* INITIALLY */ ++ testcase( i==134 ); /* ALL */ ++ testcase( i==135 ); /* PRIMARY */ + *pType = aKWCode[i]; + break; + } +@@ -140729,7 +151680,17 @@ + keywordCode((char*)z, n, &id); + return id; + } +-#define SQLITE_N_KEYWORD 124 ++#define SQLITE_N_KEYWORD 136 ++SQLITE_API int sqlite3_keyword_name(int i,const char **pzName,int *pnName){ ++ if( i<0 || i>=SQLITE_N_KEYWORD ) return SQLITE_ERROR; ++ *pzName = zKWText + aKWOffset[i]; ++ *pnName = aKWLen[i]; ++ return SQLITE_OK; ++} ++SQLITE_API int sqlite3_keyword_count(void){ return SQLITE_N_KEYWORD; } ++SQLITE_API int sqlite3_keyword_check(const char *zName, int nName){ ++ return TK_ID!=sqlite3KeywordCode((const u8*)zName, nName); ++} + + /************** End of keywordhash.h *****************************************/ + /************** Continuing where we left off in tokenize.c *******************/ +@@ -140773,13 +151734,87 @@ + #define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40])) + #endif + +-/* Make the IdChar function accessible from ctime.c */ +-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS ++/* Make the IdChar function accessible from ctime.c and alter.c */ + SQLITE_PRIVATE int sqlite3IsIdChar(u8 c){ return IdChar(c); } +-#endif + ++#ifndef SQLITE_OMIT_WINDOWFUNC ++/* ++** Return the id of the next token in string (*pz). Before returning, set ++** (*pz) to point to the byte following the parsed token. ++*/ ++static int getToken(const unsigned char **pz){ ++ const unsigned char *z = *pz; ++ int t; /* Token type to return */ ++ do { ++ z += sqlite3GetToken(z, &t); ++ }while( t==TK_SPACE ); ++ if( t==TK_ID ++ || t==TK_STRING ++ || t==TK_JOIN_KW ++ || t==TK_WINDOW ++ || t==TK_OVER ++ || sqlite3ParserFallback(t)==TK_ID ++ ){ ++ t = TK_ID; ++ } ++ *pz = z; ++ return t; ++} + + /* ++** The following three functions are called immediately after the tokenizer ++** reads the keywords WINDOW, OVER and FILTER, respectively, to determine ++** whether the token should be treated as a keyword or an SQL identifier. ++** This cannot be handled by the usual lemon %fallback method, due to ++** the ambiguity in some constructions. e.g. ++** ++** SELECT sum(x) OVER ... ++** ++** In the above, "OVER" might be a keyword, or it might be an alias for the ++** sum(x) expression. If a "%fallback ID OVER" directive were added to ++** grammar, then SQLite would always treat "OVER" as an alias, making it ++** impossible to call a window-function without a FILTER clause. ++** ++** WINDOW is treated as a keyword if: ++** ++** * the following token is an identifier, or a keyword that can fallback ++** to being an identifier, and ++** * the token after than one is TK_AS. ++** ++** OVER is a keyword if: ++** ++** * the previous token was TK_RP, and ++** * the next token is either TK_LP or an identifier. ++** ++** FILTER is a keyword if: ++** ++** * the previous token was TK_RP, and ++** * the next token is TK_LP. ++*/ ++static int analyzeWindowKeyword(const unsigned char *z){ ++ int t; ++ t = getToken(&z); ++ if( t!=TK_ID ) return TK_ID; ++ t = getToken(&z); ++ if( t!=TK_AS ) return TK_ID; ++ return TK_WINDOW; ++} ++static int analyzeOverKeyword(const unsigned char *z, int lastToken){ ++ if( lastToken==TK_RP ){ ++ int t = getToken(&z); ++ if( t==TK_LP || t==TK_ID ) return TK_OVER; ++ } ++ return TK_ID; ++} ++static int analyzeFilterKeyword(const unsigned char *z, int lastToken){ ++ if( lastToken==TK_RP && getToken(&z)==TK_LP ){ ++ return TK_FILTER; ++ } ++ return TK_ID; ++} ++#endif /* SQLITE_OMIT_WINDOWFUNC */ ++ ++/* + ** Return the length (in bytes) of the token that begins at z[0]. + ** Store the token type in *tokenType before returning. + */ +@@ -141046,6 +152081,10 @@ + i = 1; + break; + } ++ case CC_NUL: { ++ *tokenType = TK_ILLEGAL; ++ return 0; ++ } + default: { + *tokenType = TK_ILLEGAL; + return 1; +@@ -141056,7 +152095,74 @@ + return i; + } + ++#ifdef SQLITE_ENABLE_NORMALIZE + /* ++** Return the length (in bytes) of the token that begins at z[0]. ++** Store the token type in *tokenType before returning. If flags has ++** SQLITE_TOKEN_NORMALIZE flag enabled, use the identifier token type ++** for keywords. Add SQLITE_TOKEN_QUOTED to flags if the token was ++** actually a quoted identifier. Add SQLITE_TOKEN_KEYWORD to flags ++** if the token was recognized as a keyword; this is useful when the ++** SQLITE_TOKEN_NORMALIZE flag is used, because it enables the caller ++** to differentiate between a keyword being treated as an identifier ++** (for normalization purposes) and an actual identifier. ++*/ ++SQLITE_PRIVATE int sqlite3GetTokenNormalized( ++ const unsigned char *z, ++ int *tokenType, ++ int *flags ++){ ++ int n; ++ unsigned char iClass = aiClass[*z]; ++ if( iClass==CC_KYWD ){ ++ int i; ++ for(i=1; aiClass[z[i]]<=CC_KYWD; i++){} ++ if( IdChar(z[i]) ){ ++ /* This token started out using characters that can appear in keywords, ++ ** but z[i] is a character not allowed within keywords, so this must ++ ** be an identifier instead */ ++ i++; ++ while( IdChar(z[i]) ){ i++; } ++ *tokenType = TK_ID; ++ return i; ++ } ++ *tokenType = TK_ID; ++ n = keywordCode((char*)z, i, tokenType); ++ /* If the token is no longer considered to be an identifier, then it is a ++ ** keyword of some kind. Make the token back into an identifier and then ++ ** set the SQLITE_TOKEN_KEYWORD flag. Several non-identifier tokens are ++ ** used verbatim, including IN, IS, NOT, and NULL. */ ++ switch( *tokenType ){ ++ case TK_ID: { ++ /* do nothing, handled by caller */ ++ break; ++ } ++ case TK_IN: ++ case TK_IS: ++ case TK_NOT: ++ case TK_NULL: { ++ *flags |= SQLITE_TOKEN_KEYWORD; ++ break; ++ } ++ default: { ++ *tokenType = TK_ID; ++ *flags |= SQLITE_TOKEN_KEYWORD; ++ break; ++ } ++ } ++ }else{ ++ n = sqlite3GetToken(z, tokenType); ++ /* If the token is considered to be an identifier and the character class ++ ** of the first character is a quote, set the SQLITE_TOKEN_QUOTED flag. */ ++ if( *tokenType==TK_ID && (iClass==CC_QUOTE || iClass==CC_QUOTE2) ){ ++ *flags |= SQLITE_TOKEN_QUOTED; ++ } ++ } ++ return n; ++} ++#endif /* SQLITE_ENABLE_NORMALIZE */ ++ ++/* + ** Run the parser on the given SQL string. The parser structure is + ** passed in. An SQLITE_ status code is returned. If an error occurs + ** then an and attempt is made to write an error message into +@@ -141086,9 +152192,9 @@ + /* sqlite3ParserTrace(stdout, "parser: "); */ + #ifdef sqlite3Parser_ENGINEALWAYSONSTACK + pEngine = &sEngine; +- sqlite3ParserInit(pEngine); ++ sqlite3ParserInit(pEngine, pParse); + #else +- pEngine = sqlite3ParserAlloc(sqlite3Malloc); ++ pEngine = sqlite3ParserAlloc(sqlite3Malloc, pParse); + if( pEngine==0 ){ + sqlite3OomFault(db); + return SQLITE_NOMEM_BKPT; +@@ -141099,47 +152205,64 @@ + assert( pParse->nVar==0 ); + assert( pParse->pVList==0 ); + while( 1 ){ +- if( zSql[0]!=0 ){ +- n = sqlite3GetToken((u8*)zSql, &tokenType); +- mxSqlLen -= n; +- if( mxSqlLen<0 ){ +- pParse->rc = SQLITE_TOOBIG; +- break; +- } +- }else{ +- /* Upon reaching the end of input, call the parser two more times +- ** with tokens TK_SEMI and 0, in that order. */ +- if( lastTokenParsed==TK_SEMI ){ +- tokenType = 0; +- }else if( lastTokenParsed==0 ){ +- break; +- }else{ +- tokenType = TK_SEMI; +- } +- zSql -= n; ++ n = sqlite3GetToken((u8*)zSql, &tokenType); ++ mxSqlLen -= n; ++ if( mxSqlLen<0 ){ ++ pParse->rc = SQLITE_TOOBIG; ++ break; + } ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( tokenType>=TK_WINDOW ){ ++ assert( tokenType==TK_SPACE || tokenType==TK_OVER || tokenType==TK_FILTER ++ || tokenType==TK_ILLEGAL || tokenType==TK_WINDOW ++ ); ++#else + if( tokenType>=TK_SPACE ){ + assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL ); ++#endif /* SQLITE_OMIT_WINDOWFUNC */ + if( db->u1.isInterrupted ){ + pParse->rc = SQLITE_INTERRUPT; + break; + } +- if( tokenType==TK_ILLEGAL ){ ++ if( tokenType==TK_SPACE ){ ++ zSql += n; ++ continue; ++ } ++ if( zSql[0]==0 ){ ++ /* Upon reaching the end of input, call the parser two more times ++ ** with tokens TK_SEMI and 0, in that order. */ ++ if( lastTokenParsed==TK_SEMI ){ ++ tokenType = 0; ++ }else if( lastTokenParsed==0 ){ ++ break; ++ }else{ ++ tokenType = TK_SEMI; ++ } ++ n = 0; ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ }else if( tokenType==TK_WINDOW ){ ++ assert( n==6 ); ++ tokenType = analyzeWindowKeyword((const u8*)&zSql[6]); ++ }else if( tokenType==TK_OVER ){ ++ assert( n==4 ); ++ tokenType = analyzeOverKeyword((const u8*)&zSql[4], lastTokenParsed); ++ }else if( tokenType==TK_FILTER ){ ++ assert( n==6 ); ++ tokenType = analyzeFilterKeyword((const u8*)&zSql[6], lastTokenParsed); ++#endif /* SQLITE_OMIT_WINDOWFUNC */ ++ }else{ + sqlite3ErrorMsg(pParse, "unrecognized token: \"%.*s\"", n, zSql); + break; + } +- zSql += n; +- }else{ +- pParse->sLastToken.z = zSql; +- pParse->sLastToken.n = n; +- sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse); +- lastTokenParsed = tokenType; +- zSql += n; +- if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break; + } ++ pParse->sLastToken.z = zSql; ++ pParse->sLastToken.n = n; ++ sqlite3Parser(pEngine, tokenType, pParse->sLastToken); ++ lastTokenParsed = tokenType; ++ zSql += n; ++ if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break; + } + assert( nErr==0 ); +- pParse->zTail = zSql; + #ifdef YYTRACKMAXSTACKDEPTH + sqlite3_mutex_enter(sqlite3MallocMutex()); + sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK, +@@ -141161,10 +152284,12 @@ + assert( pzErrMsg!=0 ); + if( pParse->zErrMsg ){ + *pzErrMsg = pParse->zErrMsg; +- sqlite3_log(pParse->rc, "%s", *pzErrMsg); ++ sqlite3_log(pParse->rc, "%s in \"%s\"", ++ *pzErrMsg, pParse->zTail); + pParse->zErrMsg = 0; + nErr++; + } ++ pParse->zTail = zSql; + if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){ + sqlite3VdbeDelete(pParse->pVdbe); + pParse->pVdbe = 0; +@@ -141180,7 +152305,7 @@ + sqlite3_free(pParse->apVtabLock); + #endif + +- if( !IN_DECLARE_VTAB ){ ++ if( !IN_SPECIAL_PARSE ){ + /* If the pParse->declareVtab flag is set, do not delete any table + ** structure built up in pParse->pNewTable. The calling code (see vtab.c) + ** will take responsibility for freeing the Table structure. +@@ -141187,9 +152312,11 @@ + */ + sqlite3DeleteTable(db, pParse->pNewTable); + } ++ if( !IN_RENAME_OBJECT ){ ++ sqlite3DeleteTrigger(db, pParse->pNewTrigger); ++ } + + if( pParse->pWithToFree ) sqlite3WithDelete(db, pParse->pWithToFree); +- sqlite3DeleteTrigger(db, pParse->pNewTrigger); + sqlite3DbFree(db, pParse->pVList); + while( pParse->pAinc ){ + AutoincInfo *p = pParse->pAinc; +@@ -141571,6 +152698,10 @@ + */ + /* #include "sqlite3.h" */ + ++#ifdef SQLITE_OMIT_VIRTUALTABLE ++# undef SQLITE_ENABLE_RTREE ++#endif ++ + #if 0 + extern "C" { + #endif /* __cplusplus */ +@@ -141584,7 +152715,7 @@ + /************** End of rtree.h ***********************************************/ + /************** Continuing where we left off in main.c ***********************/ + #endif +-#ifdef SQLITE_ENABLE_ICU ++#if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS) + /************** Include sqliteicu.h in the middle of main.c ******************/ + /************** Begin file sqliteicu.h ***************************************/ + /* +@@ -141640,11 +152771,13 @@ + */ + SQLITE_API const char *sqlite3_libversion(void){ return sqlite3_version; } + +-/* IMPLEMENTATION-OF: R-63124-39300 The sqlite3_sourceid() function returns a ++/* IMPLEMENTATION-OF: R-25063-23286 The sqlite3_sourceid() function returns a + ** pointer to a string constant whose value is the same as the +-** SQLITE_SOURCE_ID C preprocessor macro. ++** SQLITE_SOURCE_ID C preprocessor macro. Except if SQLite is built using ++** an edited copy of the amalgamation, then the last four characters of ++** the hash might be different from SQLITE_SOURCE_ID. + */ +-SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } ++/* SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } */ + + /* IMPLEMENTATION-OF: R-35210-63508 The sqlite3_libversion_number() function + ** returns an integer equal to SQLITE_VERSION_NUMBER. +@@ -141830,7 +152963,12 @@ + sqlite3GlobalConfig.isPCacheInit = 1; + rc = sqlite3OsInit(); + } ++#ifdef SQLITE_ENABLE_DESERIALIZE + if( rc==SQLITE_OK ){ ++ rc = sqlite3MemdbInit(); ++ } ++#endif ++ if( rc==SQLITE_OK ){ + sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage, + sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage); + sqlite3GlobalConfig.isInit = 1; +@@ -141862,7 +153000,7 @@ + #ifndef NDEBUG + #ifndef SQLITE_OMIT_FLOATING_POINT + /* This section of code's only "output" is via assert() statements. */ +- if ( rc==SQLITE_OK ){ ++ if( rc==SQLITE_OK ){ + u64 x = (((u64)1)<<63)-1; + double y; + assert(sizeof(x)==8); +@@ -142029,14 +153167,8 @@ + sqlite3GlobalConfig.bMemstat = va_arg(ap, int); + break; + } +- case SQLITE_CONFIG_SCRATCH: { +- /* EVIDENCE-OF: R-08404-60887 There are three arguments to +- ** SQLITE_CONFIG_SCRATCH: A pointer an 8-byte aligned memory buffer from +- ** which the scratch allocations will be drawn, the size of each scratch +- ** allocation (sz), and the maximum number of scratch allocations (N). */ +- sqlite3GlobalConfig.pScratch = va_arg(ap, void*); +- sqlite3GlobalConfig.szScratch = va_arg(ap, int); +- sqlite3GlobalConfig.nScratch = va_arg(ap, int); ++ case SQLITE_CONFIG_SMALL_MALLOC: { ++ sqlite3GlobalConfig.bSmallMalloc = va_arg(ap, int); + break; + } + case SQLITE_CONFIG_PAGECACHE: { +@@ -142234,6 +153366,17 @@ + break; + } + ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ case SQLITE_CONFIG_SORTERREF_SIZE: { ++ int iVal = va_arg(ap, int); ++ if( iVal<0 ){ ++ iVal = SQLITE_DEFAULT_SORTERREF_SIZE; ++ } ++ sqlite3GlobalConfig.szSorterRef = (u32)iVal; ++ break; ++ } ++#endif /* SQLITE_ENABLE_SORTER_REFERENCES */ ++ + default: { + rc = SQLITE_ERROR; + break; +@@ -142257,7 +153400,8 @@ + static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ + #ifndef SQLITE_OMIT_LOOKASIDE + void *pStart; +- if( db->lookaside.nOut ){ ++ ++ if( sqlite3LookasideUsed(db,0)>0 ){ + return SQLITE_BUSY; + } + /* Free any existing lookaside buffer for this handle before +@@ -142285,6 +153429,7 @@ + pStart = pBuf; + } + db->lookaside.pStart = pStart; ++ db->lookaside.pInit = 0; + db->lookaside.pFree = 0; + db->lookaside.sz = (u16)sz; + if( pStart ){ +@@ -142291,10 +153436,11 @@ + int i; + LookasideSlot *p; + assert( sz > (int)sizeof(LookasideSlot*) ); ++ db->lookaside.nSlot = cnt; + p = (LookasideSlot*)pStart; + for(i=cnt-1; i>=0; i--){ +- p->pNext = db->lookaside.pFree; +- db->lookaside.pFree = p; ++ p->pNext = db->lookaside.pInit; ++ db->lookaside.pInit = p; + p = (LookasideSlot*)&((u8*)p)[sz]; + } + db->lookaside.pEnd = p; +@@ -142305,6 +153451,7 @@ + db->lookaside.pEnd = db; + db->lookaside.bDisable = 1; + db->lookaside.bMalloced = 0; ++ db->lookaside.nSlot = 0; + } + #endif /* SQLITE_OMIT_LOOKASIDE */ + return SQLITE_OK; +@@ -142410,6 +153557,9 @@ + { SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension }, + { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose }, + { SQLITE_DBCONFIG_ENABLE_QPSG, SQLITE_EnableQPSG }, ++ { SQLITE_DBCONFIG_TRIGGER_EQP, SQLITE_TriggerEQP }, ++ { SQLITE_DBCONFIG_RESET_DATABASE, SQLITE_ResetDatabase }, ++ { SQLITE_DBCONFIG_DEFENSIVE, SQLITE_Defensive }, + }; + unsigned int i; + rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ +@@ -142417,7 +153567,7 @@ + if( aFlagOp[i].op==op ){ + int onoff = va_arg(ap, int); + int *pRes = va_arg(ap, int*); +- int oldFlags = db->flags; ++ u32 oldFlags = db->flags; + if( onoff>0 ){ + db->flags |= aFlagOp[i].mask; + }else if( onoff==0 ){ +@@ -142424,7 +153574,7 @@ + db->flags &= ~aFlagOp[i].mask; + } + if( oldFlags!=db->flags ){ +- sqlite3ExpirePreparedStatements(db); ++ sqlite3ExpirePreparedStatements(db, 0); + } + if( pRes ){ + *pRes = (db->flags & aFlagOp[i].mask)!=0; +@@ -142486,6 +153636,15 @@ + } + + /* ++** Return true if CollSeq is the default built-in BINARY. ++*/ ++SQLITE_PRIVATE int sqlite3IsBinary(const CollSeq *p){ ++ assert( p==0 || p->xCmp!=binCollFunc || p->pUser!=0 ++ || strcmp(p->zName,"BINARY")==0 ); ++ return p==0 || (p->xCmp==binCollFunc && p->pUser==0); ++} ++ ++/* + ** Another built-in collating sequence: NOCASE. + ** + ** This collating sequence is intended to be used for "case independent +@@ -142606,7 +153765,7 @@ + sqlite3BtreeEnterAll(db); + for(i=0; i<db->nDb; i++){ + Schema *pSchema = db->aDb[i].pSchema; +- if( db->aDb[i].pSchema ){ ++ if( pSchema ){ + for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){ + Table *pTab = (Table *)sqliteHashData(p); + if( IsVirtual(pTab) ) sqlite3VtabDisconnect(db, pTab); +@@ -142824,7 +153983,7 @@ + sqlite3_mutex_leave(db->mutex); + db->magic = SQLITE_MAGIC_CLOSED; + sqlite3_mutex_free(db->mutex); +- assert( db->lookaside.nOut==0 ); /* Fails on a lookaside memory leak */ ++ assert( sqlite3LookasideUsed(db,0)==0 ); + if( db->lookaside.bMalloced ){ + sqlite3_free(db->lookaside.pStart); + } +@@ -142852,7 +154011,7 @@ + ** the database rollback and schema reset, which can cause false + ** corruption reports in some cases. */ + sqlite3BtreeEnterAll(db); +- schemaChange = (db->flags & SQLITE_InternChanges)!=0 && db->init.busy==0; ++ schemaChange = (db->mDbFlags & DBFLAG_SchemaChange)!=0 && db->init.busy==0; + + for(i=0; i<db->nDb; i++){ + Btree *p = db->aDb[i].pBt; +@@ -142866,8 +154025,8 @@ + sqlite3VtabRollback(db); + sqlite3EndBenignMalloc(); + +- if( (db->flags&SQLITE_InternChanges)!=0 && db->init.busy==0 ){ +- sqlite3ExpirePreparedStatements(db); ++ if( schemaChange ){ ++ sqlite3ExpirePreparedStatements(db, 0); + sqlite3ResetAllSchemasOfConnection(db); + } + sqlite3BtreeLeaveAll(db); +@@ -142895,6 +154054,7 @@ + switch( rc ){ + case SQLITE_OK: zName = "SQLITE_OK"; break; + case SQLITE_ERROR: zName = "SQLITE_ERROR"; break; ++ case SQLITE_ERROR_SNAPSHOT: zName = "SQLITE_ERROR_SNAPSHOT"; break; + case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break; + case SQLITE_PERM: zName = "SQLITE_PERM"; break; + case SQLITE_ABORT: zName = "SQLITE_ABORT"; break; +@@ -142907,9 +154067,10 @@ + case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break; + case SQLITE_READONLY: zName = "SQLITE_READONLY"; break; + case SQLITE_READONLY_RECOVERY: zName = "SQLITE_READONLY_RECOVERY"; break; +- case SQLITE_READONLY_CANTLOCK: zName = "SQLITE_READONLY_CANTLOCK"; break; ++ case SQLITE_READONLY_CANTINIT: zName = "SQLITE_READONLY_CANTINIT"; break; + case SQLITE_READONLY_ROLLBACK: zName = "SQLITE_READONLY_ROLLBACK"; break; + case SQLITE_READONLY_DBMOVED: zName = "SQLITE_READONLY_DBMOVED"; break; ++ case SQLITE_READONLY_DIRECTORY: zName = "SQLITE_READONLY_DIRECTORY";break; + case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break; + case SQLITE_IOERR: zName = "SQLITE_IOERR"; break; + case SQLITE_IOERR_READ: zName = "SQLITE_IOERR_READ"; break; +@@ -143029,6 +154190,8 @@ + /* SQLITE_FORMAT */ 0, + /* SQLITE_RANGE */ "column index out of range", + /* SQLITE_NOTADB */ "file is not a database", ++ /* SQLITE_NOTICE */ "notification message", ++ /* SQLITE_WARNING */ "warning message", + }; + const char *zErr = "unknown error"; + switch( rc ){ +@@ -143036,6 +154199,14 @@ + zErr = "abort due to ROLLBACK"; + break; + } ++ case SQLITE_ROW: { ++ zErr = "another row available"; ++ break; ++ } ++ case SQLITE_DONE: { ++ zErr = "no more rows available"; ++ break; ++ } + default: { + rc &= 0xff; + if( ALWAYS(rc>=0) && rc<ArraySize(aMsg) && aMsg[rc]!=0 ){ +@@ -143052,12 +154223,18 @@ + ** again until a timeout value is reached. The timeout value is + ** an integer number of milliseconds passed in as the first + ** argument. ++** ++** Return non-zero to retry the lock. Return zero to stop trying ++** and cause SQLite to return SQLITE_BUSY. + */ + static int sqliteDefaultBusyCallback( +- void *ptr, /* Database connection */ +- int count /* Number of times table has been busy */ ++ void *ptr, /* Database connection */ ++ int count, /* Number of times table has been busy */ ++ sqlite3_file *pFile /* The file on which the lock occurred */ + ){ + #if SQLITE_OS_WIN || HAVE_USLEEP ++ /* This case is for systems that have support for sleeping for fractions of ++ ** a second. Examples: All windows systems, unix systems with usleep() */ + static const u8 delays[] = + { 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 }; + static const u8 totals[] = +@@ -143064,9 +154241,22 @@ + { 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228 }; + # define NDELAY ArraySize(delays) + sqlite3 *db = (sqlite3 *)ptr; +- int timeout = db->busyTimeout; ++ int tmout = db->busyTimeout; + int delay, prior; + ++#ifdef SQLITE_ENABLE_SETLK_TIMEOUT ++ if( sqlite3OsFileControl(pFile,SQLITE_FCNTL_LOCK_TIMEOUT,&tmout)==SQLITE_OK ){ ++ if( count ){ ++ tmout = 0; ++ sqlite3OsFileControl(pFile, SQLITE_FCNTL_LOCK_TIMEOUT, &tmout); ++ return 0; ++ }else{ ++ return 1; ++ } ++ } ++#else ++ UNUSED_PARAMETER(pFile); ++#endif + assert( count>=0 ); + if( count < NDELAY ){ + delay = delays[count]; +@@ -143075,16 +154265,19 @@ + delay = delays[NDELAY-1]; + prior = totals[NDELAY-1] + delay*(count-(NDELAY-1)); + } +- if( prior + delay > timeout ){ +- delay = timeout - prior; ++ if( prior + delay > tmout ){ ++ delay = tmout - prior; + if( delay<=0 ) return 0; + } + sqlite3OsSleep(db->pVfs, delay*1000); + return 1; + #else ++ /* This case for unix systems that lack usleep() support. Sleeping ++ ** must be done in increments of whole seconds */ + sqlite3 *db = (sqlite3 *)ptr; +- int timeout = ((sqlite3 *)ptr)->busyTimeout; +- if( (count+1)*1000 > timeout ){ ++ int tmout = ((sqlite3 *)ptr)->busyTimeout; ++ UNUSED_PARAMETER(pFile); ++ if( (count+1)*1000 > tmout ){ + return 0; + } + sqlite3OsSleep(db->pVfs, 1000000); +@@ -143095,14 +154288,25 @@ + /* + ** Invoke the given busy handler. + ** +-** This routine is called when an operation failed with a lock. ++** This routine is called when an operation failed to acquire a ++** lock on VFS file pFile. ++** + ** If this routine returns non-zero, the lock is retried. If it + ** returns 0, the operation aborts with an SQLITE_BUSY error. + */ +-SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p){ ++SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p, sqlite3_file *pFile){ + int rc; +- if( NEVER(p==0) || p->xFunc==0 || p->nBusy<0 ) return 0; +- rc = p->xFunc(p->pArg, p->nBusy); ++ if( p->xBusyHandler==0 || p->nBusy<0 ) return 0; ++ if( p->bExtraFileArg ){ ++ /* Add an extra parameter with the pFile pointer to the end of the ++ ** callback argument list */ ++ int (*xTra)(void*,int,sqlite3_file*); ++ xTra = (int(*)(void*,int,sqlite3_file*))p->xBusyHandler; ++ rc = xTra(p->pBusyArg, p->nBusy, pFile); ++ }else{ ++ /* Legacy style busy handler callback */ ++ rc = p->xBusyHandler(p->pBusyArg, p->nBusy); ++ } + if( rc==0 ){ + p->nBusy = -1; + }else{ +@@ -143124,9 +154328,10 @@ + if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; + #endif + sqlite3_mutex_enter(db->mutex); +- db->busyHandler.xFunc = xBusy; +- db->busyHandler.pArg = pArg; ++ db->busyHandler.xBusyHandler = xBusy; ++ db->busyHandler.pBusyArg = pArg; + db->busyHandler.nBusy = 0; ++ db->busyHandler.bExtraFileArg = 0; + db->busyTimeout = 0; + sqlite3_mutex_leave(db->mutex); + return SQLITE_OK; +@@ -143174,8 +154379,10 @@ + if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; + #endif + if( ms>0 ){ +- sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db); ++ sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback, ++ (void*)db); + db->busyTimeout = ms; ++ db->busyHandler.bExtraFileArg = 1; + }else{ + sqlite3_busy_handler(db, 0, 0); + } +@@ -143211,6 +154418,8 @@ + void (*xSFunc)(sqlite3_context*,int,sqlite3_value **), + void (*xStep)(sqlite3_context*,int,sqlite3_value **), + void (*xFinal)(sqlite3_context*), ++ void (*xValue)(sqlite3_context*), ++ void (*xInverse)(sqlite3_context*,int,sqlite3_value **), + FuncDestructor *pDestructor + ){ + FuncDef *p; +@@ -143218,12 +154427,14 @@ + int extraFlags; + + assert( sqlite3_mutex_held(db->mutex) ); +- if( zFunctionName==0 || +- (xSFunc && (xFinal || xStep)) || +- (!xSFunc && (xFinal && !xStep)) || +- (!xSFunc && (!xFinal && xStep)) || +- (nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) || +- (255<(nName = sqlite3Strlen30( zFunctionName))) ){ ++ assert( xValue==0 || xSFunc==0 ); ++ if( zFunctionName==0 /* Must have a valid name */ ++ || (xSFunc!=0 && xFinal!=0) /* Not both xSFunc and xFinal */ ++ || ((xFinal==0)!=(xStep==0)) /* Both or neither of xFinal and xStep */ ++ || ((xValue==0)!=(xInverse==0)) /* Both or neither of xValue, xInverse */ ++ || (nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) ++ || (255<(nName = sqlite3Strlen30( zFunctionName))) ++ ){ + return SQLITE_MISUSE_BKPT; + } + +@@ -143244,10 +154455,10 @@ + }else if( enc==SQLITE_ANY ){ + int rc; + rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8|extraFlags, +- pUserData, xSFunc, xStep, xFinal, pDestructor); ++ pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor); + if( rc==SQLITE_OK ){ + rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE|extraFlags, +- pUserData, xSFunc, xStep, xFinal, pDestructor); ++ pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor); + } + if( rc!=SQLITE_OK ){ + return rc; +@@ -143264,7 +154475,7 @@ + ** operation to continue but invalidate all precompiled statements. + */ + p = sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 0); +- if( p && (p->funcFlags & SQLITE_FUNC_ENCMASK)==enc && p->nArg==nArg ){ ++ if( p && (p->funcFlags & SQLITE_FUNC_ENCMASK)==(u32)enc && p->nArg==nArg ){ + if( db->nVdbeActive ){ + sqlite3ErrorWithMsg(db, SQLITE_BUSY, + "unable to delete/modify user-function due to active statements"); +@@ -143271,7 +154482,7 @@ + assert( !db->mallocFailed ); + return SQLITE_BUSY; + }else{ +- sqlite3ExpirePreparedStatements(db); ++ sqlite3ExpirePreparedStatements(db, 0); + } + } + +@@ -143293,6 +154504,8 @@ + testcase( p->funcFlags & SQLITE_DETERMINISTIC ); + p->xSFunc = xSFunc ? xSFunc : xStep; + p->xFinalize = xFinal; ++ p->xValue = xValue; ++ p->xInverse = xInverse; + p->pUserData = pUserData; + p->nArg = (u16)nArg; + return SQLITE_OK; +@@ -143299,32 +154512,24 @@ + } + + /* +-** Create new user functions. ++** Worker function used by utf-8 APIs that create new functions: ++** ++** sqlite3_create_function() ++** sqlite3_create_function_v2() ++** sqlite3_create_window_function() + */ +-SQLITE_API int sqlite3_create_function( ++static int createFunctionApi( + sqlite3 *db, + const char *zFunc, + int nArg, + int enc, + void *p, +- void (*xSFunc)(sqlite3_context*,int,sqlite3_value **), +- void (*xStep)(sqlite3_context*,int,sqlite3_value **), +- void (*xFinal)(sqlite3_context*) +-){ +- return sqlite3_create_function_v2(db, zFunc, nArg, enc, p, xSFunc, xStep, +- xFinal, 0); +-} +- +-SQLITE_API int sqlite3_create_function_v2( +- sqlite3 *db, +- const char *zFunc, +- int nArg, +- int enc, +- void *p, +- void (*xSFunc)(sqlite3_context*,int,sqlite3_value **), +- void (*xStep)(sqlite3_context*,int,sqlite3_value **), ++ void (*xSFunc)(sqlite3_context*,int,sqlite3_value**), ++ void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*), +- void (*xDestroy)(void *) ++ void (*xValue)(sqlite3_context*), ++ void (*xInverse)(sqlite3_context*,int,sqlite3_value**), ++ void(*xDestroy)(void*) + ){ + int rc = SQLITE_ERROR; + FuncDestructor *pArg = 0; +@@ -143336,19 +154541,23 @@ + #endif + sqlite3_mutex_enter(db->mutex); + if( xDestroy ){ +- pArg = (FuncDestructor *)sqlite3DbMallocZero(db, sizeof(FuncDestructor)); ++ pArg = (FuncDestructor *)sqlite3Malloc(sizeof(FuncDestructor)); + if( !pArg ){ ++ sqlite3OomFault(db); + xDestroy(p); + goto out; + } ++ pArg->nRef = 0; + pArg->xDestroy = xDestroy; + pArg->pUserData = p; + } +- rc = sqlite3CreateFunc(db, zFunc, nArg, enc, p, xSFunc, xStep, xFinal, pArg); ++ rc = sqlite3CreateFunc(db, zFunc, nArg, enc, p, ++ xSFunc, xStep, xFinal, xValue, xInverse, pArg ++ ); + if( pArg && pArg->nRef==0 ){ + assert( rc!=SQLITE_OK ); + xDestroy(p); +- sqlite3DbFree(db, pArg); ++ sqlite3_free(pArg); + } + + out: +@@ -143357,6 +154566,52 @@ + return rc; + } + ++/* ++** Create new user functions. ++*/ ++SQLITE_API int sqlite3_create_function( ++ sqlite3 *db, ++ const char *zFunc, ++ int nArg, ++ int enc, ++ void *p, ++ void (*xSFunc)(sqlite3_context*,int,sqlite3_value **), ++ void (*xStep)(sqlite3_context*,int,sqlite3_value **), ++ void (*xFinal)(sqlite3_context*) ++){ ++ return createFunctionApi(db, zFunc, nArg, enc, p, xSFunc, xStep, ++ xFinal, 0, 0, 0); ++} ++SQLITE_API int sqlite3_create_function_v2( ++ sqlite3 *db, ++ const char *zFunc, ++ int nArg, ++ int enc, ++ void *p, ++ void (*xSFunc)(sqlite3_context*,int,sqlite3_value **), ++ void (*xStep)(sqlite3_context*,int,sqlite3_value **), ++ void (*xFinal)(sqlite3_context*), ++ void (*xDestroy)(void *) ++){ ++ return createFunctionApi(db, zFunc, nArg, enc, p, xSFunc, xStep, ++ xFinal, 0, 0, xDestroy); ++} ++SQLITE_API int sqlite3_create_window_function( ++ sqlite3 *db, ++ const char *zFunc, ++ int nArg, ++ int enc, ++ void *p, ++ void (*xStep)(sqlite3_context*,int,sqlite3_value **), ++ void (*xFinal)(sqlite3_context*), ++ void (*xValue)(sqlite3_context*), ++ void (*xInverse)(sqlite3_context*,int,sqlite3_value **), ++ void (*xDestroy)(void *) ++){ ++ return createFunctionApi(db, zFunc, nArg, enc, p, 0, xStep, ++ xFinal, xValue, xInverse, xDestroy); ++} ++ + #ifndef SQLITE_OMIT_UTF16 + SQLITE_API int sqlite3_create_function16( + sqlite3 *db, +@@ -143377,7 +154632,7 @@ + sqlite3_mutex_enter(db->mutex); + assert( !db->mallocFailed ); + zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1, SQLITE_UTF16NATIVE); +- rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xSFunc,xStep,xFinal,0); ++ rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xSFunc,xStep,xFinal,0,0,0); + sqlite3DbFree(db, zFunc8); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); +@@ -143387,6 +154642,28 @@ + + + /* ++** The following is the implementation of an SQL function that always ++** fails with an error message stating that the function is used in the ++** wrong context. The sqlite3_overload_function() API might construct ++** SQL function that use this routine so that the functions will exist ++** for name resolution but are actually overloaded by the xFindFunction ++** method of virtual tables. ++*/ ++static void sqlite3InvalidFunction( ++ sqlite3_context *context, /* The function calling context */ ++ int NotUsed, /* Number of arguments to the function */ ++ sqlite3_value **NotUsed2 /* Value of each argument */ ++){ ++ const char *zName = (const char*)sqlite3_user_data(context); ++ char *zErr; ++ UNUSED_PARAMETER2(NotUsed, NotUsed2); ++ zErr = sqlite3_mprintf( ++ "unable to use function %s in the requested context", zName); ++ sqlite3_result_error(context, zErr, -1); ++ sqlite3_free(zErr); ++} ++ ++/* + ** Declare that a function has been overloaded by a virtual table. + ** + ** If the function already exists as a regular global function, then +@@ -143403,7 +154680,8 @@ + const char *zName, + int nArg + ){ +- int rc = SQLITE_OK; ++ int rc; ++ char *zCopy; + + #ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) || zName==0 || nArg<-2 ){ +@@ -143411,13 +154689,13 @@ + } + #endif + sqlite3_mutex_enter(db->mutex); +- if( sqlite3FindFunction(db, zName, nArg, SQLITE_UTF8, 0)==0 ){ +- rc = sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8, +- 0, sqlite3InvalidFunction, 0, 0, 0); +- } +- rc = sqlite3ApiExit(db, rc); ++ rc = sqlite3FindFunction(db, zName, nArg, SQLITE_UTF8, 0)!=0; + sqlite3_mutex_leave(db->mutex); +- return rc; ++ if( rc ) return SQLITE_OK; ++ zCopy = sqlite3_mprintf(zName); ++ if( zCopy==0 ) return SQLITE_NOMEM; ++ return sqlite3_create_function_v2(db, zName, nArg, SQLITE_UTF8, ++ zCopy, sqlite3InvalidFunction, 0, 0, sqlite3_free); + } + + #ifndef SQLITE_OMIT_TRACE +@@ -143768,7 +155046,8 @@ + ** checkpointed. If an error is encountered it is returned immediately - + ** no attempt is made to checkpoint any remaining databases. + ** +-** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. ++** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL, RESTART ++** or TRUNCATE. + */ + SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3 *db, int iDb, int eMode, int *pnLog, int *pnCkpt){ + int rc = SQLITE_OK; /* Return code */ +@@ -143978,7 +155257,7 @@ + "unable to delete/modify collation sequence due to active statements"); + return SQLITE_BUSY; + } +- sqlite3ExpirePreparedStatements(db); ++ sqlite3ExpirePreparedStatements(db, 0); + + /* If collation sequence pColl was created directly by a call to + ** sqlite3_create_collation, and not generated by synthCollSeq(), +@@ -144414,6 +155693,7 @@ + }else{ + isThreadsafe = sqlite3GlobalConfig.bFullMutex; + } ++ + if( flags & SQLITE_OPEN_PRIVATECACHE ){ + flags &= ~SQLITE_OPEN_SHAREDCACHE; + }else if( sqlite3GlobalConfig.sharedCacheEnabled ){ +@@ -144446,7 +155726,11 @@ + /* Allocate the sqlite data structure */ + db = sqlite3MallocZero( sizeof(sqlite3) ); + if( db==0 ) goto opendb_out; +- if( isThreadsafe ){ ++ if( isThreadsafe ++#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS ++ || sqlite3GlobalConfig.bCoreMutex ++#endif ++ ){ + db->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); + if( db->mutex==0 ){ + sqlite3_free(db); +@@ -144453,6 +155737,9 @@ + db = 0; + goto opendb_out; + } ++ if( isThreadsafe==0 ){ ++ sqlite3MutexWarnOnContention(db->mutex); ++ } + } + sqlite3_mutex_enter(db->mutex); + db->errMask = 0xff; +@@ -144459,6 +155746,7 @@ + db->nDb = 2; + db->magic = SQLITE_MAGIC_BUSY; + db->aDb = db->aDbStatic; ++ db->lookaside.bDisable = 1; + + assert( sizeof(db->aLimit)==sizeof(aHardLimit) ); + memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit)); +@@ -144499,6 +155787,9 @@ + #if defined(SQLITE_ENABLE_QPSG) + | SQLITE_EnableQPSG + #endif ++#if defined(SQLITE_DEFAULT_DEFENSIVE) ++ | SQLITE_Defensive ++#endif + ; + sqlite3HashInit(&db->aCollSeq); + #ifndef SQLITE_OMIT_VIRTUALTABLE +@@ -144634,7 +155925,7 @@ + } + #endif + +-#ifdef SQLITE_ENABLE_ICU ++#if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS) + if( !db->mallocFailed && rc==SQLITE_OK ){ + rc = sqlite3IcuInit(db); + } +@@ -144646,6 +155937,12 @@ + } + #endif + ++#ifdef SQLITE_ENABLE_DBPAGE_VTAB ++ if( !db->mallocFailed && rc==SQLITE_OK){ ++ rc = sqlite3DbpageRegister(db); ++ } ++#endif ++ + #ifdef SQLITE_ENABLE_DBSTAT_VTAB + if( !db->mallocFailed && rc==SQLITE_OK){ + rc = sqlite3DbstatRegister(db); +@@ -144930,7 +156227,7 @@ + ** 2. Invoke sqlite3_log() to provide the source code location where + ** a low-level error is first detected. + */ +-static int reportError(int iErr, int lineno, const char *zType){ ++SQLITE_PRIVATE int sqlite3ReportError(int iErr, int lineno, const char *zType){ + sqlite3_log(iErr, "%s at line %d of [%.10s]", + zType, lineno, 20+sqlite3_sourceid()); + return iErr; +@@ -144937,15 +156234,15 @@ + } + SQLITE_PRIVATE int sqlite3CorruptError(int lineno){ + testcase( sqlite3GlobalConfig.xLog!=0 ); +- return reportError(SQLITE_CORRUPT, lineno, "database corruption"); ++ return sqlite3ReportError(SQLITE_CORRUPT, lineno, "database corruption"); + } + SQLITE_PRIVATE int sqlite3MisuseError(int lineno){ + testcase( sqlite3GlobalConfig.xLog!=0 ); +- return reportError(SQLITE_MISUSE, lineno, "misuse"); ++ return sqlite3ReportError(SQLITE_MISUSE, lineno, "misuse"); + } + SQLITE_PRIVATE int sqlite3CantopenError(int lineno){ + testcase( sqlite3GlobalConfig.xLog!=0 ); +- return reportError(SQLITE_CANTOPEN, lineno, "cannot open file"); ++ return sqlite3ReportError(SQLITE_CANTOPEN, lineno, "cannot open file"); + } + #ifdef SQLITE_DEBUG + SQLITE_PRIVATE int sqlite3CorruptPgnoError(int lineno, Pgno pgno){ +@@ -144952,15 +156249,15 @@ + char zMsg[100]; + sqlite3_snprintf(sizeof(zMsg), zMsg, "database corruption page %d", pgno); + testcase( sqlite3GlobalConfig.xLog!=0 ); +- return reportError(SQLITE_CORRUPT, lineno, zMsg); ++ return sqlite3ReportError(SQLITE_CORRUPT, lineno, zMsg); + } + SQLITE_PRIVATE int sqlite3NomemError(int lineno){ + testcase( sqlite3GlobalConfig.xLog!=0 ); +- return reportError(SQLITE_NOMEM, lineno, "OOM"); ++ return sqlite3ReportError(SQLITE_NOMEM, lineno, "OOM"); + } + SQLITE_PRIVATE int sqlite3IoerrnomemError(int lineno){ + testcase( sqlite3GlobalConfig.xLog!=0 ); +- return reportError(SQLITE_IOERR_NOMEM, lineno, "I/O OOM error"); ++ return sqlite3ReportError(SQLITE_IOERR_NOMEM, lineno, "I/O OOM error"); + } + #endif + +@@ -145153,10 +156450,11 @@ + }else if( op==SQLITE_FCNTL_JOURNAL_POINTER ){ + *(sqlite3_file**)pArg = sqlite3PagerJrnlFile(pPager); + rc = SQLITE_OK; +- }else if( fd->pMethods ){ ++ }else if( op==SQLITE_FCNTL_DATA_VERSION ){ ++ *(unsigned int*)pArg = sqlite3PagerDataVersion(pPager); ++ rc = SQLITE_OK; ++ }else{ + rc = sqlite3OsFileControl(fd, op, pArg); +- }else{ +- rc = SQLITE_NOTFOUND; + } + sqlite3BtreeLeave(pBtree); + } +@@ -145305,7 +156603,7 @@ + ** This action provides a run-time test to see how the ALWAYS and + ** NEVER macros were defined at compile-time. + ** +- ** The return value is ALWAYS(X). ++ ** The return value is ALWAYS(X) if X is true, or 0 if X is false. + ** + ** The recommended test is X==2. If the return value is 2, that means + ** ALWAYS() and NEVER() are both no-op pass-through macros, which is the +@@ -145328,7 +156626,7 @@ + */ + case SQLITE_TESTCTRL_ALWAYS: { + int x = va_arg(ap,int); +- rc = ALWAYS(x); ++ rc = x ? ALWAYS(x) : 0; + break; + } + +@@ -145377,51 +156675,28 @@ + break; + } + +-#ifdef SQLITE_N_KEYWORD +- /* sqlite3_test_control(SQLITE_TESTCTRL_ISKEYWORD, const char *zWord) ++ /* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff); + ** +- ** If zWord is a keyword recognized by the parser, then return the +- ** number of keywords. Or if zWord is not a keyword, return 0. +- ** +- ** This test feature is only available in the amalgamation since +- ** the SQLITE_N_KEYWORD macro is not defined in this file if SQLite +- ** is built using separate source files. ++ ** If parameter onoff is non-zero, subsequent calls to localtime() ++ ** and its variants fail. If onoff is zero, undo this setting. + */ +- case SQLITE_TESTCTRL_ISKEYWORD: { +- const char *zWord = va_arg(ap, const char*); +- int n = sqlite3Strlen30(zWord); +- rc = (sqlite3KeywordCode((u8*)zWord, n)!=TK_ID) ? SQLITE_N_KEYWORD : 0; ++ case SQLITE_TESTCTRL_LOCALTIME_FAULT: { ++ sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int); + break; + } +-#endif + +- /* sqlite3_test_control(SQLITE_TESTCTRL_SCRATCHMALLOC, sz, &pNew, pFree); ++ /* sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCS, int onoff); + ** +- ** Pass pFree into sqlite3ScratchFree(). +- ** If sz>0 then allocate a scratch buffer into pNew. ++ ** If parameter onoff is non-zero, internal-use-only SQL functions ++ ** are visible to ordinary SQL. This is useful for testing but is ++ ** unsafe because invalid parameters to those internal-use-only functions ++ ** can result in crashes or segfaults. + */ +- case SQLITE_TESTCTRL_SCRATCHMALLOC: { +- void *pFree, **ppNew; +- int sz; +- sz = va_arg(ap, int); +- ppNew = va_arg(ap, void**); +- pFree = va_arg(ap, void*); +- if( sz ) *ppNew = sqlite3ScratchMalloc(sz); +- sqlite3ScratchFree(pFree); ++ case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: { ++ sqlite3GlobalConfig.bInternalFunctions = va_arg(ap, int); + break; + } + +- /* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff); +- ** +- ** If parameter onoff is non-zero, configure the wrappers so that all +- ** subsequent calls to localtime() and variants fail. If onoff is zero, +- ** undo this setting. +- */ +- case SQLITE_TESTCTRL_LOCALTIME_FAULT: { +- sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int); +- break; +- } +- + /* sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, int); + ** + ** Set or clear a flag that indicates that the database file is always well- +@@ -145452,7 +156727,8 @@ + */ + case SQLITE_TESTCTRL_VDBE_COVERAGE: { + #ifdef SQLITE_VDBE_COVERAGE +- typedef void (*branch_callback)(void*,int,u8,u8); ++ typedef void (*branch_callback)(void*,unsigned int, ++ unsigned char,unsigned char); + sqlite3GlobalConfig.xVdbeBranch = va_arg(ap,branch_callback); + sqlite3GlobalConfig.pVdbeBranchArg = va_arg(ap,void*); + #endif +@@ -145504,6 +156780,22 @@ + sqlite3_mutex_leave(db->mutex); + break; + } ++ ++#if defined(YYCOVERAGE) ++ /* sqlite3_test_control(SQLITE_TESTCTRL_PARSER_COVERAGE, FILE *out) ++ ** ++ ** This test control (only available when SQLite is compiled with ++ ** -DYYCOVERAGE) writes a report onto "out" that shows all ++ ** state/lookahead combinations in the parser state machine ++ ** which are never exercised. If any state is missed, make the ++ ** return code SQLITE_ERROR. ++ */ ++ case SQLITE_TESTCTRL_PARSER_COVERAGE: { ++ FILE *out = va_arg(ap, FILE*); ++ if( sqlite3ParserCoverage(out) ) rc = SQLITE_ERROR; ++ break; ++ } ++#endif /* defined(YYCOVERAGE) */ + } + va_end(ap); + #endif /* SQLITE_UNTESTABLE */ +@@ -145552,7 +156844,7 @@ + ){ + const char *z = sqlite3_uri_parameter(zFilename, zParam); + sqlite3_int64 v; +- if( z && sqlite3DecOrHexToI64(z, &v)==SQLITE_OK ){ ++ if( z && sqlite3DecOrHexToI64(z, &v)==0 ){ + bDflt = v; + } + return bDflt; +@@ -145623,7 +156915,7 @@ + if( iDb==0 || iDb>1 ){ + Btree *pBt = db->aDb[iDb].pBt; + if( 0==sqlite3BtreeIsInTrans(pBt) ){ +- rc = sqlite3BtreeBeginTrans(pBt, 0); ++ rc = sqlite3BtreeBeginTrans(pBt, 0, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot); + } +@@ -145658,12 +156950,30 @@ + iDb = sqlite3FindDbName(db, zDb); + if( iDb==0 || iDb>1 ){ + Btree *pBt = db->aDb[iDb].pBt; +- if( 0==sqlite3BtreeIsInReadTrans(pBt) ){ +- rc = sqlite3PagerSnapshotOpen(sqlite3BtreePager(pBt), pSnapshot); ++ if( sqlite3BtreeIsInTrans(pBt)==0 ){ ++ Pager *pPager = sqlite3BtreePager(pBt); ++ int bUnlock = 0; ++ if( sqlite3BtreeIsInReadTrans(pBt) ){ ++ if( db->nVdbeActive==0 ){ ++ rc = sqlite3PagerSnapshotCheck(pPager, pSnapshot); ++ if( rc==SQLITE_OK ){ ++ bUnlock = 1; ++ rc = sqlite3BtreeCommit(pBt); ++ } ++ } ++ }else{ ++ rc = SQLITE_OK; ++ } + if( rc==SQLITE_OK ){ +- rc = sqlite3BtreeBeginTrans(pBt, 0); +- sqlite3PagerSnapshotOpen(sqlite3BtreePager(pBt), 0); ++ rc = sqlite3PagerSnapshotOpen(pPager, pSnapshot); + } ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3BtreeBeginTrans(pBt, 0, 0); ++ sqlite3PagerSnapshotOpen(pPager, 0); ++ } ++ if( bUnlock ){ ++ sqlite3PagerSnapshotUnlock(pPager); ++ } + } + } + } +@@ -145693,7 +157003,7 @@ + if( iDb==0 || iDb>1 ){ + Btree *pBt = db->aDb[iDb].pBt; + if( 0==sqlite3BtreeIsInReadTrans(pBt) ){ +- rc = sqlite3BtreeBeginTrans(pBt, 0); ++ rc = sqlite3BtreeBeginTrans(pBt, 0, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerSnapshotRecover(sqlite3BtreePager(pBt)); + sqlite3BtreeCommit(pBt); +@@ -147261,7 +158571,7 @@ + ); + SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *); + #ifdef SQLITE_TEST +-SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db); ++SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash*); + SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db); + #endif + +@@ -148829,7 +160139,7 @@ + const char *zCsr = zNode; /* Cursor to iterate through node */ + const char *zEnd = &zCsr[nNode];/* End of interior node buffer */ + char *zBuffer = 0; /* Buffer to load terms into */ +- int nAlloc = 0; /* Size of allocated buffer */ ++ i64 nAlloc = 0; /* Size of allocated buffer */ + int isFirstTerm = 1; /* True when processing first term on page */ + sqlite3_int64 iChild; /* Block id of child node to descend to */ + +@@ -148867,14 +160177,14 @@ + zCsr += fts3GetVarint32(zCsr, &nSuffix); + + assert( nPrefix>=0 && nSuffix>=0 ); +- if( &zCsr[nSuffix]>zEnd ){ ++ if( nPrefix>zCsr-zNode || nSuffix>zEnd-zCsr ){ + rc = FTS_CORRUPT_VTAB; + goto finish_scan; + } +- if( nPrefix+nSuffix>nAlloc ){ ++ if( (i64)nPrefix+nSuffix>nAlloc ){ + char *zNew; +- nAlloc = (nPrefix+nSuffix) * 2; +- zNew = (char *)sqlite3_realloc(zBuffer, nAlloc); ++ nAlloc = ((i64)nPrefix+nSuffix) * 2; ++ zNew = (char *)sqlite3_realloc64(zBuffer, nAlloc); + if( !zNew ){ + rc = SQLITE_NOMEM; + goto finish_scan; +@@ -150816,7 +162126,7 @@ + int rc = SQLITE_OK; + UNUSED_PARAMETER(iSavepoint); + assert( ((Fts3Table *)pVtab)->inTransaction ); +- assert( ((Fts3Table *)pVtab)->mxSavepoint < iSavepoint ); ++ assert( ((Fts3Table *)pVtab)->mxSavepoint <= iSavepoint ); + TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint ); + if( ((Fts3Table *)pVtab)->bIgnoreSavepoint==0 ){ + rc = fts3SyncMethod(pVtab); +@@ -150854,8 +162164,23 @@ + return SQLITE_OK; + } + ++/* ++** Return true if zName is the extension on one of the shadow tables used ++** by this module. ++*/ ++static int fts3ShadowName(const char *zName){ ++ static const char *azName[] = { ++ "content", "docsize", "segdir", "segments", "stat", ++ }; ++ unsigned int i; ++ for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){ ++ if( sqlite3_stricmp(zName, azName[i])==0 ) return 1; ++ } ++ return 0; ++} ++ + static const sqlite3_module fts3Module = { +- /* iVersion */ 2, ++ /* iVersion */ 3, + /* xCreate */ fts3CreateMethod, + /* xConnect */ fts3ConnectMethod, + /* xBestIndex */ fts3BestIndexMethod, +@@ -150878,6 +162203,7 @@ + /* xSavepoint */ fts3SavepointMethod, + /* xRelease */ fts3ReleaseMethod, + /* xRollbackTo */ fts3RollbackToMethod, ++ /* xShadowName */ fts3ShadowName, + }; + + /* +@@ -150971,7 +162297,7 @@ + + #ifdef SQLITE_TEST + if( rc==SQLITE_OK ){ +- rc = sqlite3Fts3ExprInitTestInterface(db); ++ rc = sqlite3Fts3ExprInitTestInterface(db, pHash); + } + #endif + +@@ -151158,6 +162484,7 @@ + return rc; + } + ++#ifndef SQLITE_DISABLE_FTS4_DEFERRED + /* + ** This function is called on each phrase after the position lists for + ** any deferred tokens have been loaded into memory. It updates the phrases +@@ -151261,6 +162588,7 @@ + + return SQLITE_OK; + } ++#endif /* SQLITE_DISABLE_FTS4_DEFERRED */ + + /* + ** Maximum number of tokens a phrase may have to be considered for the +@@ -153509,7 +164837,8 @@ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ +- 0 /* xRollbackTo */ ++ 0, /* xRollbackTo */ ++ 0 /* xShadowName */ + }; + int rc; /* Return code */ + +@@ -154632,34 +165961,6 @@ + /* #include <stdio.h> */ + + /* +-** Function to query the hash-table of tokenizers (see README.tokenizers). +-*/ +-static int queryTestTokenizer( +- sqlite3 *db, +- const char *zName, +- const sqlite3_tokenizer_module **pp +-){ +- int rc; +- sqlite3_stmt *pStmt; +- const char zSql[] = "SELECT fts3_tokenizer(?)"; +- +- *pp = 0; +- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); +- if( rc!=SQLITE_OK ){ +- return rc; +- } +- +- sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); +- if( SQLITE_ROW==sqlite3_step(pStmt) ){ +- if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){ +- memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp)); +- } +- } +- +- return sqlite3_finalize(pStmt); +-} +- +-/* + ** Return a pointer to a buffer containing a text representation of the + ** expression passed as the first argument. The buffer is obtained from + ** sqlite3_malloc(). It is the responsibility of the caller to use +@@ -154726,12 +166027,12 @@ + ** + ** SELECT fts3_exprtest('simple', 'Bill col2:Bloggs', 'col1', 'col2'); + */ +-static void fts3ExprTest( ++static void fts3ExprTestCommon( ++ int bRebalance, + sqlite3_context *context, + int argc, + sqlite3_value **argv + ){ +- sqlite3_tokenizer_module const *pModule = 0; + sqlite3_tokenizer *pTokenizer = 0; + int rc; + char **azCol = 0; +@@ -154741,7 +166042,9 @@ + int ii; + Fts3Expr *pExpr; + char *zBuf = 0; +- sqlite3 *db = sqlite3_context_db_handle(context); ++ Fts3Hash *pHash = (Fts3Hash*)sqlite3_user_data(context); ++ const char *zTokenizer = 0; ++ char *zErr = 0; + + if( argc<3 ){ + sqlite3_result_error(context, +@@ -154750,24 +166053,18 @@ + return; + } + +- rc = queryTestTokenizer(db, +- (const char *)sqlite3_value_text(argv[0]), &pModule); +- if( rc==SQLITE_NOMEM ){ +- sqlite3_result_error_nomem(context); +- goto exprtest_out; +- }else if( !pModule ){ +- sqlite3_result_error(context, "No such tokenizer module", -1); +- goto exprtest_out; ++ zTokenizer = (const char*)sqlite3_value_text(argv[0]); ++ rc = sqlite3Fts3InitTokenizer(pHash, zTokenizer, &pTokenizer, &zErr); ++ if( rc!=SQLITE_OK ){ ++ if( rc==SQLITE_NOMEM ){ ++ sqlite3_result_error_nomem(context); ++ }else{ ++ sqlite3_result_error(context, zErr, -1); ++ } ++ sqlite3_free(zErr); ++ return; + } + +- rc = pModule->xCreate(0, 0, &pTokenizer); +- assert( rc==SQLITE_NOMEM || rc==SQLITE_OK ); +- if( rc==SQLITE_NOMEM ){ +- sqlite3_result_error_nomem(context); +- goto exprtest_out; +- } +- pTokenizer->pModule = pModule; +- + zExpr = (const char *)sqlite3_value_text(argv[1]); + nExpr = sqlite3_value_bytes(argv[1]); + nCol = argc-2; +@@ -154780,7 +166077,7 @@ + azCol[ii] = (char *)sqlite3_value_text(argv[ii+2]); + } + +- if( sqlite3_user_data(context) ){ ++ if( bRebalance ){ + char *zDummy = 0; + rc = sqlite3Fts3ExprParse( + pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr, &zDummy +@@ -154806,23 +166103,38 @@ + sqlite3Fts3ExprFree(pExpr); + + exprtest_out: +- if( pModule && pTokenizer ){ +- rc = pModule->xDestroy(pTokenizer); ++ if( pTokenizer ){ ++ rc = pTokenizer->pModule->xDestroy(pTokenizer); + } + sqlite3_free(azCol); + } + ++static void fts3ExprTest( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ fts3ExprTestCommon(0, context, argc, argv); ++} ++static void fts3ExprTestRebalance( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ fts3ExprTestCommon(1, context, argc, argv); ++} ++ + /* + ** Register the query expression parser test function fts3_exprtest() + ** with database connection db. + */ +-SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3* db){ ++SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash *pHash){ + int rc = sqlite3_create_function( +- db, "fts3_exprtest", -1, SQLITE_UTF8, 0, fts3ExprTest, 0, 0 ++ db, "fts3_exprtest", -1, SQLITE_UTF8, (void*)pHash, fts3ExprTest, 0, 0 + ); + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "fts3_exprtest_rebalance", +- -1, SQLITE_UTF8, (void *)1, fts3ExprTest, 0, 0 ++ -1, SQLITE_UTF8, (void*)pHash, fts3ExprTestRebalance, 0, 0 + ); + } + return rc; +@@ -157085,7 +168397,8 @@ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ +- 0 /* xRollbackTo */ ++ 0, /* xRollbackTo */ ++ 0 /* xShadowName */ + }; + int rc; /* Return code */ + +@@ -158473,15 +169786,19 @@ + ** safe (no risk of overread) even if the node data is corrupted. */ + pNext += fts3GetVarint32(pNext, &nPrefix); + pNext += fts3GetVarint32(pNext, &nSuffix); +- if( nPrefix<0 || nSuffix<=0 +- || &pNext[nSuffix]>&pReader->aNode[pReader->nNode] ++ if( nSuffix<=0 ++ || (&pReader->aNode[pReader->nNode] - pNext)<nSuffix ++ || nPrefix>pReader->nTermAlloc + ){ + return FTS_CORRUPT_VTAB; + } + +- if( nPrefix+nSuffix>pReader->nTermAlloc ){ +- int nNew = (nPrefix+nSuffix)*2; +- char *zNew = sqlite3_realloc(pReader->zTerm, nNew); ++ /* Both nPrefix and nSuffix were read by fts3GetVarint32() and so are ++ ** between 0 and 0x7FFFFFFF. But the sum of the two may cause integer ++ ** overflow - hence the (i64) casts. */ ++ if( (i64)nPrefix+nSuffix>(i64)pReader->nTermAlloc ){ ++ i64 nNew = ((i64)nPrefix+nSuffix)*2; ++ char *zNew = sqlite3_realloc64(pReader->zTerm, nNew); + if( !zNew ){ + return SQLITE_NOMEM; + } +@@ -158503,7 +169820,7 @@ + ** b-tree node. And that the final byte of the doclist is 0x00. If either + ** of these statements is untrue, then the data structure is corrupt. + */ +- if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode] ++ if( (&pReader->aNode[pReader->nNode] - pReader->aDoclist)<pReader->nDoclist + || (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1]) + ){ + return FTS_CORRUPT_VTAB; +@@ -159007,6 +170324,7 @@ + sqlite3_bind_blob(pStmt, 2, z, n, SQLITE_STATIC); + sqlite3_step(pStmt); + rc = sqlite3_reset(pStmt); ++ sqlite3_bind_null(pStmt, 2); + } + return rc; + } +@@ -159063,6 +170381,7 @@ + sqlite3_bind_blob(pStmt, 6, zRoot, nRoot, SQLITE_STATIC); + sqlite3_step(pStmt); + rc = sqlite3_reset(pStmt); ++ sqlite3_bind_null(pStmt, 6); + } + return rc; + } +@@ -160542,6 +171861,7 @@ + sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, SQLITE_STATIC); + sqlite3_step(pStmt); + *pRC = sqlite3_reset(pStmt); ++ sqlite3_bind_null(pStmt, 2); + sqlite3_free(a); + } + +@@ -160826,6 +172146,9 @@ + } + p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nSuffix); + ++ if( nPrefix>p->iOff || nSuffix>p->nNode-p->iOff ){ ++ return SQLITE_CORRUPT_VTAB; ++ } + blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc); + if( rc==SQLITE_OK ){ + memcpy(&p->term.a[nPrefix], &p->aNode[p->iOff], nSuffix); +@@ -160833,6 +172156,9 @@ + p->iOff += nSuffix; + if( p->iChild==0 ){ + p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist); ++ if( (p->nNode-p->iOff)<p->nDoclist ){ ++ return SQLITE_CORRUPT_VTAB; ++ } + p->aDoclist = &p->aNode[p->iOff]; + p->iOff += p->nDoclist; + } +@@ -160840,7 +172166,6 @@ + } + + assert( p->iOff<=p->nNode ); +- + return rc; + } + +@@ -161730,6 +173055,7 @@ + sqlite3_bind_int(pChomp, 4, iIdx); + sqlite3_step(pChomp); + rc = sqlite3_reset(pChomp); ++ sqlite3_bind_null(pChomp, 2); + } + } + +@@ -161809,6 +173135,7 @@ + sqlite3_bind_blob(pReplace, 2, pHint->a, pHint->n, SQLITE_STATIC); + sqlite3_step(pReplace); + rc = sqlite3_reset(pReplace); ++ sqlite3_bind_null(pReplace, 2); + } + + return rc; +@@ -162623,7 +173950,6 @@ + ){ + Fts3Table *p = (Fts3Table *)pVtab; + int rc = SQLITE_OK; /* Return Code */ +- int isRemove = 0; /* True for an UPDATE or DELETE */ + u32 *aSzIns = 0; /* Sizes of inserted documents */ + u32 *aSzDel = 0; /* Sizes of deleted documents */ + int nChng = 0; /* Net change in number of documents */ +@@ -162721,7 +174047,6 @@ + if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ + assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER ); + rc = fts3DeleteByRowid(p, apVal[0], &nChng, aSzDel); +- isRemove = 1; + } + + /* If this is an INSERT or UPDATE operation, insert the new record. */ +@@ -162733,7 +174058,7 @@ + rc = FTS_CORRUPT_VTAB; + } + } +- if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){ ++ if( rc==SQLITE_OK ){ + rc = fts3PendingTermsDocid(p, 0, iLangid, *pRowid); + } + if( rc==SQLITE_OK ){ +@@ -165253,6 +176578,2550 @@ + #endif /* !defined(SQLITE_DISABLE_FTS3_UNICODE) */ + + /************** End of fts3_unicode2.c ***************************************/ ++/************** Begin file json1.c *******************************************/ ++/* ++** 2015-08-12 ++** ++** 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 JSON functions. The interface is ++** modeled after MySQL JSON functions: ++** ++** https://dev.mysql.com/doc/refman/5.7/en/json.html ++** ++** For the time being, all JSON is stored as pure text. (We might add ++** a JSONB type in the future which stores a binary encoding of JSON in ++** a BLOB, but there is no support for JSONB in the current implementation. ++** This implementation parses JSON text at 250 MB/s, so it is hard to see ++** how JSONB might improve on that.) ++*/ ++#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1) ++#if !defined(SQLITEINT_H) ++/* #include "sqlite3ext.h" */ ++#endif ++SQLITE_EXTENSION_INIT1 ++/* #include <assert.h> */ ++/* #include <string.h> */ ++/* #include <stdlib.h> */ ++/* #include <stdarg.h> */ ++ ++/* Mark a function parameter as unused, to suppress nuisance compiler ++** warnings. */ ++#ifndef UNUSED_PARAM ++# define UNUSED_PARAM(X) (void)(X) ++#endif ++ ++#ifndef LARGEST_INT64 ++# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32)) ++# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64) ++#endif ++ ++/* ++** Versions of isspace(), isalnum() and isdigit() to which it is safe ++** to pass signed char values. ++*/ ++#ifdef sqlite3Isdigit ++ /* Use the SQLite core versions if this routine is part of the ++ ** SQLite amalgamation */ ++# define safe_isdigit(x) sqlite3Isdigit(x) ++# define safe_isalnum(x) sqlite3Isalnum(x) ++# define safe_isxdigit(x) sqlite3Isxdigit(x) ++#else ++ /* Use the standard library for separate compilation */ ++#include <ctype.h> /* amalgamator: keep */ ++# define safe_isdigit(x) isdigit((unsigned char)(x)) ++# define safe_isalnum(x) isalnum((unsigned char)(x)) ++# define safe_isxdigit(x) isxdigit((unsigned char)(x)) ++#endif ++ ++/* ++** Growing our own isspace() routine this way is twice as fast as ++** the library isspace() function, resulting in a 7% overall performance ++** increase for the parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os). ++*/ ++static const char jsonIsSpace[] = { ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++}; ++#define safe_isspace(x) (jsonIsSpace[(unsigned char)x]) ++ ++#ifndef SQLITE_AMALGAMATION ++ /* Unsigned integer types. These are already defined in the sqliteInt.h, ++ ** but the definitions need to be repeated for separate compilation. */ ++ typedef sqlite3_uint64 u64; ++ typedef unsigned int u32; ++ typedef unsigned short int u16; ++ typedef unsigned char u8; ++#endif ++ ++/* Objects */ ++typedef struct JsonString JsonString; ++typedef struct JsonNode JsonNode; ++typedef struct JsonParse JsonParse; ++ ++/* An instance of this object represents a JSON string ++** under construction. Really, this is a generic string accumulator ++** that can be and is used to create strings other than JSON. ++*/ ++struct JsonString { ++ sqlite3_context *pCtx; /* Function context - put error messages here */ ++ char *zBuf; /* Append JSON content here */ ++ u64 nAlloc; /* Bytes of storage available in zBuf[] */ ++ u64 nUsed; /* Bytes of zBuf[] currently used */ ++ u8 bStatic; /* True if zBuf is static space */ ++ u8 bErr; /* True if an error has been encountered */ ++ char zSpace[100]; /* Initial static space */ ++}; ++ ++/* JSON type values ++*/ ++#define JSON_NULL 0 ++#define JSON_TRUE 1 ++#define JSON_FALSE 2 ++#define JSON_INT 3 ++#define JSON_REAL 4 ++#define JSON_STRING 5 ++#define JSON_ARRAY 6 ++#define JSON_OBJECT 7 ++ ++/* The "subtype" set for JSON values */ ++#define JSON_SUBTYPE 74 /* Ascii for "J" */ ++ ++/* ++** Names of the various JSON types: ++*/ ++static const char * const jsonType[] = { ++ "null", "true", "false", "integer", "real", "text", "array", "object" ++}; ++ ++/* Bit values for the JsonNode.jnFlag field ++*/ ++#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 */ ++ u32 n; /* Bytes of content, or number of sub-nodes */ ++ union { ++ const char *zJContent; /* Content for INT, REAL, and STRING */ ++ u32 iAppend; /* More terms for ARRAY and OBJECT */ ++ u32 iKey; /* Key for ARRAY objects in json_tree() */ ++ u32 iReplace; /* Replacement content for JNODE_REPLACE */ ++ JsonNode *pPatch; /* Node chain of patch for JNODE_PATCH */ ++ } u; ++}; ++ ++/* A completely parsed JSON string ++*/ ++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 ++** descent parser. A depth of 2000 is far deeper than any sane JSON ++** should go. ++*/ ++#define JSON_MAX_DEPTH 2000 ++ ++/************************************************************************** ++** Utility routines for dealing with JsonString objects ++**************************************************************************/ ++ ++/* Set the JsonString object to an empty string ++*/ ++static void jsonZero(JsonString *p){ ++ p->zBuf = p->zSpace; ++ p->nAlloc = sizeof(p->zSpace); ++ p->nUsed = 0; ++ p->bStatic = 1; ++} ++ ++/* Initialize the JsonString object ++*/ ++static void jsonInit(JsonString *p, sqlite3_context *pCtx){ ++ p->pCtx = pCtx; ++ p->bErr = 0; ++ jsonZero(p); ++} ++ ++ ++/* Free all allocated memory and reset the JsonString object back to its ++** initial state. ++*/ ++static void jsonReset(JsonString *p){ ++ if( !p->bStatic ) sqlite3_free(p->zBuf); ++ jsonZero(p); ++} ++ ++ ++/* Report an out-of-memory (OOM) condition ++*/ ++static void jsonOom(JsonString *p){ ++ p->bErr = 1; ++ sqlite3_result_error_nomem(p->pCtx); ++ jsonReset(p); ++} ++ ++/* Enlarge pJson->zBuf so that it can hold at least N more bytes. ++** Return zero on success. Return non-zero on an OOM error ++*/ ++static int jsonGrow(JsonString *p, u32 N){ ++ u64 nTotal = N<p->nAlloc ? p->nAlloc*2 : p->nAlloc+N+10; ++ char *zNew; ++ if( p->bStatic ){ ++ if( p->bErr ) return 1; ++ zNew = sqlite3_malloc64(nTotal); ++ if( zNew==0 ){ ++ jsonOom(p); ++ return SQLITE_NOMEM; ++ } ++ memcpy(zNew, p->zBuf, (size_t)p->nUsed); ++ p->zBuf = zNew; ++ p->bStatic = 0; ++ }else{ ++ zNew = sqlite3_realloc64(p->zBuf, nTotal); ++ if( zNew==0 ){ ++ jsonOom(p); ++ return SQLITE_NOMEM; ++ } ++ p->zBuf = zNew; ++ } ++ p->nAlloc = nTotal; ++ return SQLITE_OK; ++} ++ ++/* Append N bytes from zIn onto the end of the JsonString string. ++*/ ++static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){ ++ if( (N+p->nUsed >= p->nAlloc) && jsonGrow(p,N)!=0 ) return; ++ memcpy(p->zBuf+p->nUsed, zIn, N); ++ p->nUsed += N; ++} ++ ++/* Append formatted text (not to exceed N bytes) to the JsonString. ++*/ ++static void jsonPrintf(int N, JsonString *p, const char *zFormat, ...){ ++ va_list ap; ++ if( (p->nUsed + N >= p->nAlloc) && jsonGrow(p, N) ) return; ++ va_start(ap, zFormat); ++ sqlite3_vsnprintf(N, p->zBuf+p->nUsed, zFormat, ap); ++ va_end(ap); ++ p->nUsed += (int)strlen(p->zBuf+p->nUsed); ++} ++ ++/* Append a single character ++*/ ++static void jsonAppendChar(JsonString *p, char c){ ++ if( p->nUsed>=p->nAlloc && jsonGrow(p,1)!=0 ) return; ++ p->zBuf[p->nUsed++] = c; ++} ++ ++/* Append a comma separator to the output buffer, if the previous ++** character is not '[' or '{'. ++*/ ++static void jsonAppendSeparator(JsonString *p){ ++ char c; ++ if( p->nUsed==0 ) return; ++ c = p->zBuf[p->nUsed-1]; ++ if( c!='[' && c!='{' ) jsonAppendChar(p, ','); ++} ++ ++/* Append the N-byte string in zIn to the end of the JsonString string ++** under construction. Enclose the string in "..." and escape ++** any double-quotes or backslash characters contained within the ++** string. ++*/ ++static void jsonAppendString(JsonString *p, const char *zIn, u32 N){ ++ u32 i; ++ if( (N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0 ) return; ++ p->zBuf[p->nUsed++] = '"'; ++ for(i=0; i<N; i++){ ++ unsigned char c = ((unsigned const char*)zIn)[i]; ++ if( c=='"' || c=='\\' ){ ++ json_simple_escape: ++ if( (p->nUsed+N+3-i > p->nAlloc) && jsonGrow(p,N+3-i)!=0 ) return; ++ p->zBuf[p->nUsed++] = '\\'; ++ }else if( c<=0x1f ){ ++ static const char aSpecial[] = { ++ 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ++ }; ++ assert( sizeof(aSpecial)==32 ); ++ assert( aSpecial['\b']=='b' ); ++ assert( aSpecial['\f']=='f' ); ++ assert( aSpecial['\n']=='n' ); ++ assert( aSpecial['\r']=='r' ); ++ assert( aSpecial['\t']=='t' ); ++ if( aSpecial[c] ){ ++ c = aSpecial[c]; ++ goto json_simple_escape; ++ } ++ if( (p->nUsed+N+7+i > p->nAlloc) && jsonGrow(p,N+7-i)!=0 ) return; ++ p->zBuf[p->nUsed++] = '\\'; ++ p->zBuf[p->nUsed++] = 'u'; ++ p->zBuf[p->nUsed++] = '0'; ++ p->zBuf[p->nUsed++] = '0'; ++ p->zBuf[p->nUsed++] = '0' + (c>>4); ++ 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); ++ u32 n = (u32)sqlite3_value_bytes(pValue); ++ if( sqlite3_value_subtype(pValue)==JSON_SUBTYPE ){ ++ jsonAppendRaw(p, z, n); ++ }else{ ++ jsonAppendString(p, z, n); ++ } ++ break; ++ } ++ default: { ++ if( p->bErr==0 ){ ++ sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1); ++ p->bErr = 2; ++ jsonReset(p); ++ } ++ break; ++ } ++ } ++} ++ ++ ++/* Make the JSON in p the result of the SQL function. ++*/ ++static void jsonResult(JsonString *p){ ++ if( p->bErr==0 ){ ++ sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed, ++ p->bStatic ? SQLITE_TRANSIENT : sqlite3_free, ++ SQLITE_UTF8); ++ jsonZero(p); ++ } ++ assert( p->bStatic ); ++} ++ ++/************************************************************************** ++** Utility routines for dealing with JsonNode and JsonParse objects ++**************************************************************************/ ++ ++/* ++** Return the number of consecutive JsonNode slots need to represent ++** the parsed JSON at pNode. The minimum answer is 1. For ARRAY and ++** OBJECT types, the number might be larger. ++** ++** Appended elements are not counted. The value returned is the number ++** by which the JsonNode counter should increment in order to go to the ++** next peer value. ++*/ ++static u32 jsonNodeSize(JsonNode *pNode){ ++ return pNode->eType>=JSON_ARRAY ? pNode->n+1 : 1; ++} ++ ++/* ++** Reclaim all memory allocated by a JsonParse object. But do not ++** delete the JsonParse object itself. ++*/ ++static void jsonParseReset(JsonParse *pParse){ ++ sqlite3_free(pParse->aNode); ++ pParse->aNode = 0; ++ pParse->nNode = 0; ++ pParse->nAlloc = 0; ++ sqlite3_free(pParse->aUp); ++ pParse->aUp = 0; ++} ++ ++/* ++** Free a JsonParse object that was obtained from sqlite3_malloc(). ++*/ ++static void jsonParseFree(JsonParse *pParse){ ++ jsonParseReset(pParse); ++ sqlite3_free(pParse); ++} ++ ++/* ++** Convert the JsonNode pNode into a pure JSON string and ++** append to pOut. Subsubstructure is also included. Return ++** the number of JsonNode objects that are encoded. ++*/ ++static void jsonRenderNode( ++ JsonNode *pNode, /* The node to render */ ++ JsonString *pOut, /* Write JSON here */ ++ sqlite3_value **aReplace /* Replacement values */ ++){ ++ if( pNode->jnFlags & (JNODE_REPLACE|JNODE_PATCH) ){ ++ if( pNode->jnFlags & JNODE_REPLACE ){ ++ jsonAppendValue(pOut, aReplace[pNode->u.iReplace]); ++ return; ++ } ++ pNode = pNode->u.pPatch; ++ } ++ switch( pNode->eType ){ ++ default: { ++ assert( pNode->eType==JSON_NULL ); ++ jsonAppendRaw(pOut, "null", 4); ++ break; ++ } ++ case JSON_TRUE: { ++ jsonAppendRaw(pOut, "true", 4); ++ break; ++ } ++ case JSON_FALSE: { ++ jsonAppendRaw(pOut, "false", 5); ++ break; ++ } ++ case JSON_STRING: { ++ if( pNode->jnFlags & JNODE_RAW ){ ++ jsonAppendString(pOut, pNode->u.zJContent, pNode->n); ++ break; ++ } ++ /* Fall through into the next case */ ++ } ++ case JSON_REAL: ++ case JSON_INT: { ++ jsonAppendRaw(pOut, pNode->u.zJContent, pNode->n); ++ break; ++ } ++ case JSON_ARRAY: { ++ u32 j = 1; ++ jsonAppendChar(pOut, '['); ++ for(;;){ ++ while( j<=pNode->n ){ ++ if( (pNode[j].jnFlags & JNODE_REMOVE)==0 ){ ++ jsonAppendSeparator(pOut); ++ jsonRenderNode(&pNode[j], pOut, aReplace); ++ } ++ j += jsonNodeSize(&pNode[j]); ++ } ++ if( (pNode->jnFlags & JNODE_APPEND)==0 ) break; ++ pNode = &pNode[pNode->u.iAppend]; ++ j = 1; ++ } ++ jsonAppendChar(pOut, ']'); ++ break; ++ } ++ case JSON_OBJECT: { ++ u32 j = 1; ++ jsonAppendChar(pOut, '{'); ++ for(;;){ ++ while( j<=pNode->n ){ ++ if( (pNode[j+1].jnFlags & JNODE_REMOVE)==0 ){ ++ jsonAppendSeparator(pOut); ++ jsonRenderNode(&pNode[j], pOut, aReplace); ++ jsonAppendChar(pOut, ':'); ++ jsonRenderNode(&pNode[j+1], pOut, aReplace); ++ } ++ j += 1 + jsonNodeSize(&pNode[j+1]); ++ } ++ if( (pNode->jnFlags & JNODE_APPEND)==0 ) break; ++ pNode = &pNode[pNode->u.iAppend]; ++ j = 1; ++ } ++ jsonAppendChar(pOut, '}'); ++ break; ++ } ++ } ++} ++ ++/* ++** Return a JsonNode and all its descendents as a JSON string. ++*/ ++static void jsonReturnJson( ++ JsonNode *pNode, /* Node to return */ ++ sqlite3_context *pCtx, /* Return value for this function */ ++ sqlite3_value **aReplace /* Array of replacement values */ ++){ ++ JsonString s; ++ jsonInit(&s, pCtx); ++ jsonRenderNode(pNode, &s, aReplace); ++ jsonResult(&s); ++ sqlite3_result_subtype(pCtx, JSON_SUBTYPE); ++} ++ ++/* ++** Make the JsonNode the return value of the function. ++*/ ++static void jsonReturn( ++ JsonNode *pNode, /* Node to return */ ++ sqlite3_context *pCtx, /* Return value for this function */ ++ sqlite3_value **aReplace /* Array of replacement values */ ++){ ++ switch( pNode->eType ){ ++ default: { ++ assert( pNode->eType==JSON_NULL ); ++ sqlite3_result_null(pCtx); ++ break; ++ } ++ case JSON_TRUE: { ++ sqlite3_result_int(pCtx, 1); ++ break; ++ } ++ case JSON_FALSE: { ++ sqlite3_result_int(pCtx, 0); ++ break; ++ } ++ case JSON_INT: { ++ sqlite3_int64 i = 0; ++ const char *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: /* fall through to real */; ++ } ++ case JSON_REAL: { ++ double r; ++#ifdef SQLITE_AMALGAMATION ++ const char *z = pNode->u.zJContent; ++ sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8); ++#else ++ 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 ){ ++ 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 */ ++ 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 = pNode->u.zJContent; ++ char *zOut; ++ u32 j; ++ 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 = 0, k; ++ for(k=0; k<4; i++, k++){ ++ assert( i<n-2 ); ++ c = z[i+1]; ++ assert( safe_isxdigit(c) ); ++ if( c<='9' ) v = v*16 + c - '0'; ++ else if( c<='F' ) v = v*16 + c - 'A' + 10; ++ else v = v*16 + c - 'a' + 10; ++ } ++ if( v==0 ) break; ++ if( v<=0x7f ){ ++ zOut[j++] = (char)v; ++ }else if( v<=0x7ff ){ ++ zOut[j++] = (char)(0xc0 | (v>>6)); ++ zOut[j++] = 0x80 | (v&0x3f); ++ }else{ ++ zOut[j++] = (char)(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: { ++ jsonReturnJson(pNode, pCtx, aReplace); ++ break; ++ } ++ } ++} ++ ++/* Forward reference */ ++static int jsonParseAddNode(JsonParse*,u32,u32,const char*); ++ ++/* ++** A macro to hint to the compiler that a function should not be ++** inlined. ++*/ ++#if defined(__GNUC__) ++# define JSON_NOINLINE __attribute__((noinline)) ++#elif defined(_MSC_VER) && _MSC_VER>=1310 ++# define JSON_NOINLINE __declspec(noinline) ++#else ++# define JSON_NOINLINE ++#endif ++ ++ ++static JSON_NOINLINE int jsonParseAddNodeExpand( ++ JsonParse *pParse, /* Append the node to this object */ ++ u32 eType, /* Node type */ ++ u32 n, /* Content size or sub-node count */ ++ const char *zContent /* Content */ ++){ ++ u32 nNew; ++ JsonNode *pNew; ++ assert( pParse->nNode>=pParse->nAlloc ); ++ if( pParse->oom ) return -1; ++ nNew = pParse->nAlloc*2 + 10; ++ pNew = sqlite3_realloc(pParse->aNode, sizeof(JsonNode)*nNew); ++ if( pNew==0 ){ ++ pParse->oom = 1; ++ return -1; ++ } ++ pParse->nAlloc = nNew; ++ pParse->aNode = pNew; ++ assert( pParse->nNode<pParse->nAlloc ); ++ return jsonParseAddNode(pParse, eType, n, zContent); ++} ++ ++/* ++** Create a new JsonNode instance based on the arguments and append that ++** instance to the JsonParse. Return the index in pParse->aNode[] of the ++** new node, or -1 if a memory allocation fails. ++*/ ++static int jsonParseAddNode( ++ JsonParse *pParse, /* Append the node to this object */ ++ u32 eType, /* Node type */ ++ u32 n, /* Content size or sub-node count */ ++ const char *zContent /* Content */ ++){ ++ JsonNode *p; ++ if( pParse->nNode>=pParse->nAlloc ){ ++ return jsonParseAddNodeExpand(pParse, eType, n, zContent); ++ } ++ p = &pParse->aNode[pParse->nNode]; ++ p->eType = (u8)eType; ++ p->jnFlags = 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( !safe_isxdigit(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( safe_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( safe_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( safe_isspace(z[j]) ){ j++; } ++ if( z[j]!=':' ) return -1; ++ j++; ++ x = jsonParseValue(pParse, j); ++ pParse->iDepth--; ++ if( x<0 ) return -1; ++ j = x; ++ while( safe_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; ++ for(j=i+1;;j++){ ++ while( safe_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( safe_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 ++ && !safe_isalnum(z[i+4]) ){ ++ jsonParseAddNode(pParse, JSON_NULL, 0, 0); ++ return i+4; ++ }else if( c=='t' ++ && strncmp(z+i,"true",4)==0 ++ && !safe_isalnum(z[i+4]) ){ ++ jsonParseAddNode(pParse, JSON_TRUE, 0, 0); ++ return i+4; ++ }else if( c=='f' ++ && strncmp(z+i,"false",5)==0 ++ && !safe_isalnum(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. ++** ++** pParse is uninitialized when this routine is called. ++*/ ++static int jsonParse( ++ JsonParse *pParse, /* Initialize and fill this JsonParse object */ ++ sqlite3_context *pCtx, /* Report errors here */ ++ const char *zJson /* Input JSON text to be parsed */ ++){ ++ int i; ++ memset(pParse, 0, sizeof(*pParse)); ++ 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( safe_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); ++ } ++ } ++ jsonParseReset(pParse); ++ return 1; ++ } ++ return 0; ++} ++ ++/* Mark node i of pParse as being a child of iParent. Call recursively ++** to fill in all the descendants of node i. ++*/ ++static void jsonParseFillInParentage(JsonParse *pParse, u32 i, u32 iParent){ ++ JsonNode *pNode = &pParse->aNode[i]; ++ u32 j; ++ pParse->aUp[i] = iParent; ++ switch( pNode->eType ){ ++ case JSON_ARRAY: { ++ for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j)){ ++ jsonParseFillInParentage(pParse, i+j, i); ++ } ++ break; ++ } ++ case JSON_OBJECT: { ++ for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j+1)+1){ ++ pParse->aUp[i+j] = i; ++ jsonParseFillInParentage(pParse, i+j+1, i); ++ } ++ break; ++ } ++ default: { ++ break; ++ } ++ } ++} ++ ++/* ++** Compute the parentage of all nodes in a completed parse. ++*/ ++static int jsonParseFindParents(JsonParse *pParse){ ++ u32 *aUp; ++ assert( pParse->aUp==0 ); ++ aUp = pParse->aUp = sqlite3_malloc( sizeof(u32)*pParse->nNode ); ++ if( aUp==0 ){ ++ pParse->oom = 1; ++ return SQLITE_NOMEM; ++ } ++ jsonParseFillInParentage(pParse, 0, 0); ++ return SQLITE_OK; ++} ++ ++/* ++** Magic number used for the JSON parse cache in sqlite3_get_auxdata() ++*/ ++#define JSON_CACHE_ID (-429938) /* First cache entry */ ++#define JSON_CACHE_SZ 4 /* Max number of cache entries */ ++ ++/* ++** 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]); ++ int nJson = sqlite3_value_bytes(argv[0]); ++ JsonParse *p; ++ JsonParse *pMatch = 0; ++ int iKey; ++ int iMinKey = 0; ++ u32 iMinHold = 0xffffffff; ++ u32 iMaxHold = 0; ++ if( zJson==0 ) return 0; ++ for(iKey=0; iKey<JSON_CACHE_SZ; iKey++){ ++ p = (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID+iKey); ++ if( p==0 ){ ++ iMinKey = iKey; ++ break; ++ } ++ if( pMatch==0 ++ && p->nJson==nJson ++ && memcmp(p->zJson,zJson,nJson)==0 ++ ){ ++ p->nErr = 0; ++ pMatch = p; ++ }else if( p->iHold<iMinHold ){ ++ iMinHold = p->iHold; ++ iMinKey = iKey; ++ } ++ if( p->iHold>iMaxHold ){ ++ iMaxHold = p->iHold; ++ } ++ } ++ if( pMatch ){ ++ pMatch->nErr = 0; ++ pMatch->iHold = iMaxHold+1; ++ return pMatch; ++ } ++ p = sqlite3_malloc( sizeof(*p) + nJson + 1 ); ++ if( p==0 ){ ++ 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){ ++ 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 ++** node. ++** ++** If pApnd!=0, then try to append new nodes to complete zPath if it is ++** possible to do so and if no existing node corresponds to zPath. If ++** new nodes are appended *pApnd is set to 1. ++*/ ++static JsonNode *jsonLookupStep( ++ JsonParse *pParse, /* The JSON to search */ ++ u32 iRoot, /* Begin the search at this node */ ++ const char *zPath, /* The path to search */ ++ int *pApnd, /* Append nodes to complete path if not NULL */ ++ const char **pzErr /* Make *pzErr point to any syntax error in zPath */ ++){ ++ u32 i, j, nKey; ++ const char *zKey; ++ JsonNode *pRoot = &pParse->aNode[iRoot]; ++ if( zPath[0]==0 ) return pRoot; ++ if( zPath[0]=='.' ){ ++ if( pRoot->eType!=JSON_OBJECT ) return 0; ++ zPath++; ++ if( zPath[0]=='"' ){ ++ zKey = zPath + 1; ++ for(i=1; zPath[i] && zPath[i]!='"'; i++){} ++ nKey = i-1; ++ if( zPath[i] ){ ++ i++; ++ }else{ ++ *pzErr = zPath; ++ return 0; ++ } ++ }else{ ++ zKey = zPath; ++ for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){} ++ nKey = i; ++ } ++ if( nKey==0 ){ ++ *pzErr = zPath; ++ return 0; ++ } ++ j = 1; ++ for(;;){ ++ while( j<=pRoot->n ){ ++ if( jsonLabelCompare(pRoot+j, zKey, nKey) ){ ++ return jsonLookupStep(pParse, iRoot+j+1, &zPath[i], pApnd, pzErr); ++ } ++ j++; ++ j += jsonNodeSize(&pRoot[j]); ++ } ++ if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break; ++ iRoot += pRoot->u.iAppend; ++ pRoot = &pParse->aNode[iRoot]; ++ j = 1; ++ } ++ if( pApnd ){ ++ u32 iStart, iLabel; ++ JsonNode *pNode; ++ iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0); ++ iLabel = jsonParseAddNode(pParse, JSON_STRING, i, zPath); ++ zPath += i; ++ pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr); ++ if( pParse->oom ) return 0; ++ if( pNode ){ ++ pRoot = &pParse->aNode[iRoot]; ++ pRoot->u.iAppend = iStart - iRoot; ++ pRoot->jnFlags |= JNODE_APPEND; ++ pParse->aNode[iLabel].jnFlags |= JNODE_RAW; ++ } ++ return pNode; ++ } ++ }else if( zPath[0]=='[' && safe_isdigit(zPath[1]) ){ ++ if( pRoot->eType!=JSON_ARRAY ) return 0; ++ i = 0; ++ j = 1; ++ while( safe_isdigit(zPath[j]) ){ ++ i = i*10 + zPath[j] - '0'; ++ j++; ++ } ++ if( zPath[j]!=']' ){ ++ *pzErr = zPath; ++ return 0; ++ } ++ zPath += j + 1; ++ j = 1; ++ for(;;){ ++ while( j<=pRoot->n && (i>0 || (pRoot[j].jnFlags & JNODE_REMOVE)!=0) ){ ++ if( (pRoot[j].jnFlags & JNODE_REMOVE)==0 ) i--; ++ j += jsonNodeSize(&pRoot[j]); ++ } ++ if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break; ++ iRoot += pRoot->u.iAppend; ++ pRoot = &pParse->aNode[iRoot]; ++ j = 1; ++ } ++ if( j<=pRoot->n ){ ++ return jsonLookupStep(pParse, iRoot+j, zPath, pApnd, pzErr); ++ } ++ if( i==0 && pApnd ){ ++ u32 iStart; ++ JsonNode *pNode; ++ iStart = jsonParseAddNode(pParse, JSON_ARRAY, 1, 0); ++ pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr); ++ if( pParse->oom ) return 0; ++ if( pNode ){ ++ pRoot = &pParse->aNode[iRoot]; ++ pRoot->u.iAppend = iStart - iRoot; ++ pRoot->jnFlags |= JNODE_APPEND; ++ } ++ return pNode; ++ } ++ }else{ ++ *pzErr = zPath; ++ } ++ return 0; ++} ++ ++/* ++** Append content to pParse that will complete zPath. Return a pointer ++** to the inserted node, or return NULL if the append fails. ++*/ ++static JsonNode *jsonLookupAppend( ++ JsonParse *pParse, /* Append content to the JSON parse */ ++ const char *zPath, /* Description of content to append */ ++ int *pApnd, /* Set this flag to 1 */ ++ const char **pzErr /* Make this point to any syntax error */ ++){ ++ *pApnd = 1; ++ if( zPath[0]==0 ){ ++ jsonParseAddNode(pParse, JSON_NULL, 0, 0); ++ return pParse->oom ? 0 : &pParse->aNode[pParse->nNode-1]; ++ } ++ if( zPath[0]=='.' ){ ++ jsonParseAddNode(pParse, JSON_OBJECT, 0, 0); ++ }else if( strncmp(zPath,"[0]",3)==0 ){ ++ jsonParseAddNode(pParse, JSON_ARRAY, 0, 0); ++ }else{ ++ return 0; ++ } ++ if( pParse->oom ) return 0; ++ return jsonLookupStep(pParse, pParse->nNode-1, zPath, pApnd, pzErr); ++} ++ ++/* ++** Return the text of a syntax error message on a JSON path. Space is ++** obtained from sqlite3_malloc(). ++*/ ++static char *jsonPathSyntaxError(const char *zErr){ ++ return sqlite3_mprintf("JSON path error near '%q'", zErr); ++} ++ ++/* ++** Do a node lookup using zPath. Return a pointer to the node on success. ++** Return NULL if not found or if there is an error. ++** ++** On an error, write an error message into pCtx and increment the ++** pParse->nErr counter. ++** ++** If pApnd!=NULL then try to append missing nodes and set *pApnd = 1 if ++** nodes are appended. ++*/ ++static JsonNode *jsonLookup( ++ JsonParse *pParse, /* The JSON to search */ ++ const char *zPath, /* The path to search */ ++ int *pApnd, /* Append nodes to complete path if not NULL */ ++ sqlite3_context *pCtx /* Report errors here, if not NULL */ ++){ ++ const char *zErr = 0; ++ JsonNode *pNode = 0; ++ char *zMsg; ++ ++ if( zPath==0 ) return 0; ++ if( zPath[0]!='$' ){ ++ zErr = zPath; ++ goto lookup_err; ++ } ++ zPath++; ++ pNode = jsonLookupStep(pParse, 0, zPath, pApnd, &zErr); ++ if( zErr==0 ) return pNode; ++ ++lookup_err: ++ pParse->nErr++; ++ assert( zErr!=0 && pCtx!=0 ); ++ zMsg = jsonPathSyntaxError(zErr); ++ if( zMsg ){ ++ sqlite3_result_error(pCtx, zMsg, -1); ++ sqlite3_free(zMsg); ++ }else{ ++ sqlite3_result_error_nomem(pCtx); ++ } ++ return 0; ++} ++ ++ ++/* ++** Report the wrong number of arguments for json_insert(), json_replace() ++** or json_set(). ++*/ ++static void jsonWrongNumArgs( ++ sqlite3_context *pCtx, ++ const char *zFuncName ++){ ++ char *zMsg = sqlite3_mprintf("json_%s() needs an odd number of arguments", ++ zFuncName); ++ sqlite3_result_error(pCtx, zMsg, -1); ++ sqlite3_free(zMsg); ++} ++ ++/* ++** Mark all NULL entries in the Object passed in as JNODE_REMOVE. ++*/ ++static void jsonRemoveAllNulls(JsonNode *pNode){ ++ int i, n; ++ assert( pNode->eType==JSON_OBJECT ); ++ n = pNode->n; ++ for(i=2; i<=n; i += jsonNodeSize(&pNode[i])+1){ ++ switch( pNode[i].eType ){ ++ case JSON_NULL: ++ pNode[i].jnFlags |= JNODE_REMOVE; ++ break; ++ case JSON_OBJECT: ++ jsonRemoveAllNulls(&pNode[i]); ++ break; ++ } ++ } ++} ++ ++ ++/**************************************************************************** ++** SQL functions used for testing and debugging ++****************************************************************************/ ++ ++#ifdef SQLITE_DEBUG ++/* ++** The json_parse(JSON) function returns a string which describes ++** a parse of the JSON provided. Or it returns NULL if JSON is not ++** well-formed. ++*/ ++static void jsonParseFunc( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ JsonString s; /* Output string - not real JSON */ ++ JsonParse x; /* The parse */ ++ u32 i; ++ ++ assert( argc==1 ); ++ if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; ++ jsonParseFindParents(&x); ++ jsonInit(&s, ctx); ++ for(i=0; i<x.nNode; i++){ ++ const char *zType; ++ if( x.aNode[i].jnFlags & JNODE_LABEL ){ ++ assert( x.aNode[i].eType==JSON_STRING ); ++ zType = "label"; ++ }else{ ++ zType = jsonType[x.aNode[i].eType]; ++ } ++ jsonPrintf(100, &s,"node %3u: %7s n=%-4d up=%-4d", ++ i, zType, x.aNode[i].n, x.aUp[i]); ++ if( x.aNode[i].u.zJContent!=0 ){ ++ jsonAppendRaw(&s, " ", 1); ++ jsonAppendRaw(&s, x.aNode[i].u.zJContent, x.aNode[i].n); ++ } ++ jsonAppendRaw(&s, "\n", 1); ++ } ++ jsonParseReset(&x); ++ jsonResult(&s); ++} ++ ++/* ++** The json_test1(JSON) function return true (1) if the input is JSON ++** text generated by another json function. It returns (0) if the input ++** is not known to be JSON. ++*/ ++static void jsonTest1Func( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ UNUSED_PARAM(argc); ++ sqlite3_result_int(ctx, sqlite3_value_subtype(argv[0])==JSON_SUBTYPE); ++} ++#endif /* SQLITE_DEBUG */ ++ ++/**************************************************************************** ++** Scalar SQL function implementations ++****************************************************************************/ ++ ++/* ++** Implementation of the json_QUOTE(VALUE) function. Return a JSON value ++** corresponding to the SQL value input. Mostly this means putting ++** double-quotes around strings and returning the unquoted string "null" ++** when given a NULL input. ++*/ ++static void jsonQuoteFunc( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ JsonString jx; ++ UNUSED_PARAM(argc); ++ ++ jsonInit(&jx, ctx); ++ jsonAppendValue(&jx, argv[0]); ++ jsonResult(&jx); ++ sqlite3_result_subtype(ctx, JSON_SUBTYPE); ++} ++ ++/* ++** Implementation of the json_array(VALUE,...) function. Return a JSON ++** array that contains all values given in arguments. Or if any argument ++** is a BLOB, throw an error. ++*/ ++static void jsonArrayFunc( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ int i; ++ JsonString jx; ++ ++ jsonInit(&jx, ctx); ++ jsonAppendChar(&jx, '['); ++ for(i=0; i<argc; i++){ ++ jsonAppendSeparator(&jx); ++ jsonAppendValue(&jx, argv[i]); ++ } ++ jsonAppendChar(&jx, ']'); ++ jsonResult(&jx); ++ sqlite3_result_subtype(ctx, JSON_SUBTYPE); ++} ++ ++ ++/* ++** json_array_length(JSON) ++** json_array_length(JSON, PATH) ++** ++** Return the number of elements in the top-level JSON array. ++** Return 0 if the input is not a well-formed JSON array. ++*/ ++static void jsonArrayLengthFunc( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ JsonParse *p; /* The parse */ ++ sqlite3_int64 n = 0; ++ u32 i; ++ JsonNode *pNode; ++ ++ p = jsonParseCached(ctx, argv, ctx); ++ if( p==0 ) return; ++ assert( p->nNode ); ++ if( argc==2 ){ ++ const char *zPath = (const char*)sqlite3_value_text(argv[1]); ++ pNode = jsonLookup(p, zPath, 0, ctx); ++ }else{ ++ pNode = p->aNode; ++ } ++ if( pNode==0 ){ ++ return; ++ } ++ if( pNode->eType==JSON_ARRAY ){ ++ assert( (pNode->jnFlags & JNODE_APPEND)==0 ); ++ for(i=1; i<=pNode->n; n++){ ++ i += jsonNodeSize(&pNode[i]); ++ } ++ } ++ sqlite3_result_int64(ctx, n); ++} ++ ++/* ++** json_extract(JSON, PATH, ...) ++** ++** Return the element described by PATH. Return NULL if there is no ++** PATH element. If there are multiple PATHs, then return a JSON array ++** with the result from each path. Throw an error if the JSON or any PATH ++** is malformed. ++*/ ++static void jsonExtractFunc( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ JsonParse *p; /* The parse */ ++ JsonNode *pNode; ++ const char *zPath; ++ JsonString jx; ++ int i; ++ ++ if( argc<2 ) return; ++ p = jsonParseCached(ctx, argv, ctx); ++ if( p==0 ) return; ++ jsonInit(&jx, ctx); ++ jsonAppendChar(&jx, '['); ++ for(i=1; i<argc; i++){ ++ zPath = (const char*)sqlite3_value_text(argv[i]); ++ pNode = jsonLookup(p, zPath, 0, ctx); ++ if( p->nErr ) break; ++ if( argc>2 ){ ++ jsonAppendSeparator(&jx); ++ if( pNode ){ ++ jsonRenderNode(pNode, &jx, 0); ++ }else{ ++ jsonAppendRaw(&jx, "null", 4); ++ } ++ }else if( pNode ){ ++ jsonReturn(pNode, ctx, 0); ++ } ++ } ++ if( argc>2 && i==argc ){ ++ jsonAppendChar(&jx, ']'); ++ jsonResult(&jx); ++ sqlite3_result_subtype(ctx, JSON_SUBTYPE); ++ } ++ jsonReset(&jx); ++} ++ ++/* This is the RFC 7396 MergePatch algorithm. ++*/ ++static JsonNode *jsonMergePatch( ++ JsonParse *pParse, /* The JSON parser that contains the TARGET */ ++ u32 iTarget, /* Node of the TARGET in pParse */ ++ JsonNode *pPatch /* The PATCH */ ++){ ++ u32 i, j; ++ u32 iRoot; ++ JsonNode *pTarget; ++ if( pPatch->eType!=JSON_OBJECT ){ ++ return pPatch; ++ } ++ assert( iTarget>=0 && iTarget<pParse->nNode ); ++ pTarget = &pParse->aNode[iTarget]; ++ assert( (pPatch->jnFlags & JNODE_APPEND)==0 ); ++ if( pTarget->eType!=JSON_OBJECT ){ ++ jsonRemoveAllNulls(pPatch); ++ return pPatch; ++ } ++ iRoot = iTarget; ++ for(i=1; i<pPatch->n; i += jsonNodeSize(&pPatch[i+1])+1){ ++ u32 nKey; ++ const char *zKey; ++ assert( pPatch[i].eType==JSON_STRING ); ++ assert( pPatch[i].jnFlags & JNODE_LABEL ); ++ 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]; ++ if( pNew!=&pTarget[j+1] ){ ++ pTarget[j+1].u.pPatch = pNew; ++ pTarget[j+1].jnFlags |= JNODE_PATCH; ++ } ++ } ++ break; ++ } ++ } ++ if( j>=pTarget->n && pPatch[i+1].eType!=JSON_NULL ){ ++ int iStart, iPatch; ++ iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0); ++ jsonParseAddNode(pParse, JSON_STRING, nKey, zKey); ++ iPatch = jsonParseAddNode(pParse, JSON_TRUE, 0, 0); ++ if( pParse->oom ) return 0; ++ jsonRemoveAllNulls(pPatch); ++ pTarget = &pParse->aNode[iTarget]; ++ pParse->aNode[iRoot].jnFlags |= JNODE_APPEND; ++ pParse->aNode[iRoot].u.iAppend = iStart - iRoot; ++ iRoot = iStart; ++ pParse->aNode[iPatch].jnFlags |= JNODE_PATCH; ++ pParse->aNode[iPatch].u.pPatch = &pPatch[i+1]; ++ } ++ } ++ return pTarget; ++} ++ ++/* ++** Implementation of the json_mergepatch(JSON1,JSON2) function. Return a JSON ++** object that is the result of running the RFC 7396 MergePatch() algorithm ++** on the two arguments. ++*/ ++static void jsonPatchFunc( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ JsonParse x; /* The JSON that is being patched */ ++ JsonParse y; /* The patch */ ++ JsonNode *pResult; /* The result of the merge */ ++ ++ UNUSED_PARAM(argc); ++ if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; ++ if( jsonParse(&y, ctx, (const char*)sqlite3_value_text(argv[1])) ){ ++ jsonParseReset(&x); ++ return; ++ } ++ pResult = jsonMergePatch(&x, 0, y.aNode); ++ assert( pResult!=0 || x.oom ); ++ if( pResult ){ ++ jsonReturnJson(pResult, ctx, 0); ++ }else{ ++ sqlite3_result_error_nomem(ctx); ++ } ++ jsonParseReset(&x); ++ jsonParseReset(&y); ++} ++ ++ ++/* ++** Implementation of the json_object(NAME,VALUE,...) function. Return a JSON ++** object that contains all name/value given in arguments. Or if any name ++** is not a string or if any value is a BLOB, throw an error. ++*/ ++static void jsonObjectFunc( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ int i; ++ JsonString jx; ++ const char *z; ++ u32 n; ++ ++ if( argc&1 ){ ++ sqlite3_result_error(ctx, "json_object() requires an even number " ++ "of arguments", -1); ++ return; ++ } ++ jsonInit(&jx, ctx); ++ jsonAppendChar(&jx, '{'); ++ for(i=0; i<argc; i+=2){ ++ if( sqlite3_value_type(argv[i])!=SQLITE_TEXT ){ ++ sqlite3_result_error(ctx, "json_object() labels must be TEXT", -1); ++ jsonReset(&jx); ++ return; ++ } ++ jsonAppendSeparator(&jx); ++ z = (const char*)sqlite3_value_text(argv[i]); ++ n = (u32)sqlite3_value_bytes(argv[i]); ++ jsonAppendString(&jx, z, n); ++ jsonAppendChar(&jx, ':'); ++ jsonAppendValue(&jx, argv[i+1]); ++ } ++ jsonAppendChar(&jx, '}'); ++ jsonResult(&jx); ++ sqlite3_result_subtype(ctx, JSON_SUBTYPE); ++} ++ ++ ++/* ++** json_remove(JSON, PATH, ...) ++** ++** Remove the named elements from JSON and return the result. malformed ++** JSON or PATH arguments result in an error. ++*/ ++static void jsonRemoveFunc( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ JsonParse x; /* The parse */ ++ JsonNode *pNode; ++ const char *zPath; ++ u32 i; ++ ++ if( argc<1 ) return; ++ if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; ++ assert( x.nNode ); ++ for(i=1; i<(u32)argc; i++){ ++ zPath = (const char*)sqlite3_value_text(argv[i]); ++ if( zPath==0 ) goto remove_done; ++ pNode = jsonLookup(&x, zPath, 0, ctx); ++ if( x.nErr ) goto remove_done; ++ if( pNode ) pNode->jnFlags |= JNODE_REMOVE; ++ } ++ if( (x.aNode[0].jnFlags & JNODE_REMOVE)==0 ){ ++ jsonReturnJson(x.aNode, ctx, 0); ++ } ++remove_done: ++ jsonParseReset(&x); ++} ++ ++/* ++** json_replace(JSON, PATH, VALUE, ...) ++** ++** Replace the value at PATH with VALUE. If PATH does not already exist, ++** this routine is a no-op. If JSON or PATH is malformed, throw an error. ++*/ ++static void jsonReplaceFunc( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ JsonParse x; /* The parse */ ++ JsonNode *pNode; ++ const char *zPath; ++ u32 i; ++ ++ if( argc<1 ) return; ++ if( (argc&1)==0 ) { ++ jsonWrongNumArgs(ctx, "replace"); ++ return; ++ } ++ if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; ++ assert( x.nNode ); ++ for(i=1; i<(u32)argc; i+=2){ ++ zPath = (const char*)sqlite3_value_text(argv[i]); ++ pNode = jsonLookup(&x, zPath, 0, ctx); ++ if( x.nErr ) goto replace_err; ++ if( pNode ){ ++ pNode->jnFlags |= (u8)JNODE_REPLACE; ++ pNode->u.iReplace = i + 1; ++ } ++ } ++ if( x.aNode[0].jnFlags & JNODE_REPLACE ){ ++ sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]); ++ }else{ ++ jsonReturnJson(x.aNode, ctx, argv); ++ } ++replace_err: ++ jsonParseReset(&x); ++} ++ ++/* ++** json_set(JSON, PATH, VALUE, ...) ++** ++** Set the value at PATH to VALUE. Create the PATH if it does not already ++** exist. Overwrite existing values that do exist. ++** If JSON or PATH is malformed, throw an error. ++** ++** json_insert(JSON, PATH, VALUE, ...) ++** ++** Create PATH and initialize it to VALUE. If PATH already exists, this ++** routine is a no-op. If JSON or PATH is malformed, throw an error. ++*/ ++static void jsonSetFunc( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ JsonParse x; /* The parse */ ++ JsonNode *pNode; ++ const char *zPath; ++ u32 i; ++ int bApnd; ++ int bIsSet = *(int*)sqlite3_user_data(ctx); ++ ++ if( argc<1 ) return; ++ if( (argc&1)==0 ) { ++ jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert"); ++ return; ++ } ++ if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; ++ assert( x.nNode ); ++ for(i=1; i<(u32)argc; i+=2){ ++ zPath = (const char*)sqlite3_value_text(argv[i]); ++ bApnd = 0; ++ pNode = jsonLookup(&x, zPath, &bApnd, ctx); ++ if( x.oom ){ ++ sqlite3_result_error_nomem(ctx); ++ goto jsonSetDone; ++ }else if( x.nErr ){ ++ goto jsonSetDone; ++ }else if( pNode && (bApnd || bIsSet) ){ ++ pNode->jnFlags |= (u8)JNODE_REPLACE; ++ pNode->u.iReplace = i + 1; ++ } ++ } ++ if( x.aNode[0].jnFlags & JNODE_REPLACE ){ ++ sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]); ++ }else{ ++ jsonReturnJson(x.aNode, ctx, argv); ++ } ++jsonSetDone: ++ jsonParseReset(&x); ++} ++ ++/* ++** json_type(JSON) ++** json_type(JSON, PATH) ++** ++** Return the top-level "type" of a JSON string. Throw an error if ++** either the JSON or PATH inputs are not well-formed. ++*/ ++static void jsonTypeFunc( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ JsonParse *p; /* The parse */ ++ const char *zPath; ++ JsonNode *pNode; ++ ++ p = jsonParseCached(ctx, argv, ctx); ++ if( p==0 ) return; ++ if( argc==2 ){ ++ zPath = (const char*)sqlite3_value_text(argv[1]); ++ pNode = jsonLookup(p, zPath, 0, ctx); ++ }else{ ++ pNode = p->aNode; ++ } ++ if( pNode ){ ++ 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_PARAM(argc); ++ p = jsonParseCached(ctx, argv, 0); ++ sqlite3_result_int(ctx, p!=0); ++} ++ ++ ++/**************************************************************************** ++** Aggregate SQL function implementations ++****************************************************************************/ ++/* ++** json_group_array(VALUE) ++** ++** Return a JSON array composed of all values in the aggregate. ++*/ ++static void jsonArrayStep( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ JsonString *pStr; ++ UNUSED_PARAM(argc); ++ pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); ++ if( pStr ){ ++ if( pStr->zBuf==0 ){ ++ jsonInit(pStr, ctx); ++ jsonAppendChar(pStr, '['); ++ }else{ ++ jsonAppendChar(pStr, ','); ++ pStr->pCtx = ctx; ++ } ++ jsonAppendValue(pStr, argv[0]); ++ } ++} ++static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){ ++ JsonString *pStr; ++ pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); ++ if( pStr ){ ++ pStr->pCtx = ctx; ++ jsonAppendChar(pStr, ']'); ++ if( pStr->bErr ){ ++ if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); ++ assert( pStr->bStatic ); ++ }else if( isFinal ){ ++ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, ++ pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); ++ pStr->bStatic = 1; ++ }else{ ++ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); ++ pStr->nUsed--; ++ } ++ }else{ ++ sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC); ++ } ++ sqlite3_result_subtype(ctx, JSON_SUBTYPE); ++} ++static void jsonArrayValue(sqlite3_context *ctx){ ++ jsonArrayCompute(ctx, 0); ++} ++static void jsonArrayFinal(sqlite3_context *ctx){ ++ jsonArrayCompute(ctx, 1); ++} ++ ++#ifndef SQLITE_OMIT_WINDOWFUNC ++/* ++** This method works for both json_group_array() and json_group_object(). ++** It works by removing the first element of the group by searching forward ++** to the first comma (",") that is not within a string and deleting all ++** text through that comma. ++*/ ++static void jsonGroupInverse( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ int i; ++ int inStr = 0; ++ char *z; ++ JsonString *pStr; ++ UNUSED_PARAM(argc); ++ UNUSED_PARAM(argv); ++ pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); ++#ifdef NEVER ++ /* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will ++ ** always have been called to initalize it */ ++ if( NEVER(!pStr) ) return; ++#endif ++ z = pStr->zBuf; ++ for(i=1; z[i]!=',' || inStr; i++){ ++ assert( i<pStr->nUsed ); ++ if( z[i]=='"' ){ ++ inStr = !inStr; ++ }else if( z[i]=='\\' ){ ++ i++; ++ } ++ } ++ pStr->nUsed -= i; ++ memmove(&z[1], &z[i+1], (size_t)pStr->nUsed-1); ++} ++#else ++# define jsonGroupInverse 0 ++#endif ++ ++ ++/* ++** json_group_obj(NAME,VALUE) ++** ++** Return a JSON object composed of all names and values in the aggregate. ++*/ ++static void jsonObjectStep( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ JsonString *pStr; ++ const char *z; ++ u32 n; ++ UNUSED_PARAM(argc); ++ pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); ++ if( pStr ){ ++ if( pStr->zBuf==0 ){ ++ jsonInit(pStr, ctx); ++ jsonAppendChar(pStr, '{'); ++ }else{ ++ jsonAppendChar(pStr, ','); ++ pStr->pCtx = ctx; ++ } ++ z = (const char*)sqlite3_value_text(argv[0]); ++ n = (u32)sqlite3_value_bytes(argv[0]); ++ jsonAppendString(pStr, z, n); ++ jsonAppendChar(pStr, ':'); ++ jsonAppendValue(pStr, argv[1]); ++ } ++} ++static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){ ++ JsonString *pStr; ++ pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); ++ if( pStr ){ ++ jsonAppendChar(pStr, '}'); ++ if( pStr->bErr ){ ++ if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); ++ assert( pStr->bStatic ); ++ }else if( isFinal ){ ++ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, ++ pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); ++ pStr->bStatic = 1; ++ }else{ ++ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); ++ pStr->nUsed--; ++ } ++ }else{ ++ sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC); ++ } ++ sqlite3_result_subtype(ctx, JSON_SUBTYPE); ++} ++static void jsonObjectValue(sqlite3_context *ctx){ ++ jsonObjectCompute(ctx, 0); ++} ++static void jsonObjectFinal(sqlite3_context *ctx){ ++ jsonObjectCompute(ctx, 1); ++} ++ ++ ++ ++#ifndef SQLITE_OMIT_VIRTUALTABLE ++/**************************************************************************** ++** The json_each virtual table ++****************************************************************************/ ++typedef struct JsonEachCursor JsonEachCursor; ++struct JsonEachCursor { ++ sqlite3_vtab_cursor base; /* Base class - must be first */ ++ u32 iRowid; /* The rowid */ ++ u32 iBegin; /* The first node of the scan */ ++ u32 i; /* Index in sParse.aNode[] of current row */ ++ u32 iEnd; /* EOF when i equals or exceeds this value */ ++ u8 eType; /* Type of top-level element */ ++ u8 bRecursive; /* True for json_tree(). False for json_each() */ ++ char *zJson; /* Input JSON */ ++ char *zRoot; /* Path by which to filter zJson */ ++ JsonParse sParse; /* Parse of the input JSON */ ++}; ++ ++/* Constructor for the json_each virtual table */ ++static int jsonEachConnect( ++ sqlite3 *db, ++ void *pAux, ++ int argc, const char *const*argv, ++ sqlite3_vtab **ppVtab, ++ char **pzErr ++){ ++ sqlite3_vtab *pNew; ++ int rc; ++ ++/* Column numbers */ ++#define JEACH_KEY 0 ++#define JEACH_VALUE 1 ++#define JEACH_TYPE 2 ++#define JEACH_ATOM 3 ++#define JEACH_ID 4 ++#define JEACH_PARENT 5 ++#define JEACH_FULLKEY 6 ++#define JEACH_PATH 7 ++/* The xBestIndex method assumes that the JSON and ROOT columns are ++** the last two columns in the table. Should this ever changes, be ++** sure to update the xBestIndex method. */ ++#define JEACH_JSON 8 ++#define JEACH_ROOT 9 ++ ++ UNUSED_PARAM(pzErr); ++ UNUSED_PARAM(argv); ++ UNUSED_PARAM(argc); ++ UNUSED_PARAM(pAux); ++ rc = sqlite3_declare_vtab(db, ++ "CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path," ++ "json HIDDEN,root HIDDEN)"); ++ if( rc==SQLITE_OK ){ ++ pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) ); ++ if( pNew==0 ) return SQLITE_NOMEM; ++ memset(pNew, 0, sizeof(*pNew)); ++ } ++ return rc; ++} ++ ++/* destructor for json_each virtual table */ ++static int jsonEachDisconnect(sqlite3_vtab *pVtab){ ++ sqlite3_free(pVtab); ++ return SQLITE_OK; ++} ++ ++/* constructor for a JsonEachCursor object for json_each(). */ ++static int jsonEachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ ++ JsonEachCursor *pCur; ++ ++ UNUSED_PARAM(p); ++ pCur = sqlite3_malloc( sizeof(*pCur) ); ++ if( pCur==0 ) return SQLITE_NOMEM; ++ memset(pCur, 0, sizeof(*pCur)); ++ *ppCursor = &pCur->base; ++ return SQLITE_OK; ++} ++ ++/* constructor for a JsonEachCursor object for json_tree(). */ ++static int jsonEachOpenTree(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ ++ int rc = jsonEachOpenEach(p, ppCursor); ++ if( rc==SQLITE_OK ){ ++ JsonEachCursor *pCur = (JsonEachCursor*)*ppCursor; ++ pCur->bRecursive = 1; ++ } ++ return rc; ++} ++ ++/* Reset a JsonEachCursor back to its original state. Free any memory ++** held. */ ++static void jsonEachCursorReset(JsonEachCursor *p){ ++ sqlite3_free(p->zJson); ++ sqlite3_free(p->zRoot); ++ jsonParseReset(&p->sParse); ++ p->iRowid = 0; ++ p->i = 0; ++ p->iEnd = 0; ++ p->eType = 0; ++ p->zJson = 0; ++ p->zRoot = 0; ++} ++ ++/* Destructor for a jsonEachCursor object */ ++static int jsonEachClose(sqlite3_vtab_cursor *cur){ ++ JsonEachCursor *p = (JsonEachCursor*)cur; ++ jsonEachCursorReset(p); ++ sqlite3_free(cur); ++ return SQLITE_OK; ++} ++ ++/* Return TRUE if the jsonEachCursor object has been advanced off the end ++** of the JSON object */ ++static int jsonEachEof(sqlite3_vtab_cursor *cur){ ++ JsonEachCursor *p = (JsonEachCursor*)cur; ++ return p->i >= p->iEnd; ++} ++ ++/* Advance the cursor to the next element for json_tree() */ ++static int jsonEachNext(sqlite3_vtab_cursor *cur){ ++ JsonEachCursor *p = (JsonEachCursor*)cur; ++ if( p->bRecursive ){ ++ if( p->sParse.aNode[p->i].jnFlags & JNODE_LABEL ) p->i++; ++ p->i++; ++ p->iRowid++; ++ if( p->i<p->iEnd ){ ++ u32 iUp = p->sParse.aUp[p->i]; ++ JsonNode *pUp = &p->sParse.aNode[iUp]; ++ p->eType = pUp->eType; ++ if( pUp->eType==JSON_ARRAY ){ ++ if( iUp==p->i-1 ){ ++ pUp->u.iKey = 0; ++ }else{ ++ pUp->u.iKey++; ++ } ++ } ++ } ++ }else{ ++ switch( p->eType ){ ++ case JSON_ARRAY: { ++ p->i += jsonNodeSize(&p->sParse.aNode[p->i]); ++ p->iRowid++; ++ break; ++ } ++ case JSON_OBJECT: { ++ p->i += 1 + jsonNodeSize(&p->sParse.aNode[p->i+1]); ++ p->iRowid++; ++ break; ++ } ++ default: { ++ p->i = p->iEnd; ++ break; ++ } ++ } ++ } ++ return SQLITE_OK; ++} ++ ++/* Append the name of the path for element i to pStr ++*/ ++static void jsonEachComputePath( ++ JsonEachCursor *p, /* The cursor */ ++ JsonString *pStr, /* Write the path here */ ++ u32 i /* Path to this element */ ++){ ++ JsonNode *pNode, *pUp; ++ u32 iUp; ++ if( i==0 ){ ++ jsonAppendChar(pStr, '$'); ++ return; ++ } ++ iUp = p->sParse.aUp[i]; ++ jsonEachComputePath(p, pStr, iUp); ++ pNode = &p->sParse.aNode[i]; ++ pUp = &p->sParse.aNode[iUp]; ++ if( pUp->eType==JSON_ARRAY ){ ++ jsonPrintf(30, pStr, "[%d]", pUp->u.iKey); ++ }else{ ++ assert( pUp->eType==JSON_OBJECT ); ++ if( (pNode->jnFlags & JNODE_LABEL)==0 ) pNode--; ++ assert( pNode->eType==JSON_STRING ); ++ assert( pNode->jnFlags & JNODE_LABEL ); ++ jsonPrintf(pNode->n+1, pStr, ".%.*s", pNode->n-2, pNode->u.zJContent+1); ++ } ++} ++ ++/* Return the value of a column */ ++static int jsonEachColumn( ++ sqlite3_vtab_cursor *cur, /* The cursor */ ++ sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ ++ int i /* Which column to return */ ++){ ++ JsonEachCursor *p = (JsonEachCursor*)cur; ++ JsonNode *pThis = &p->sParse.aNode[p->i]; ++ switch( i ){ ++ case JEACH_KEY: { ++ if( p->i==0 ) break; ++ if( p->eType==JSON_OBJECT ){ ++ jsonReturn(pThis, ctx, 0); ++ }else if( p->eType==JSON_ARRAY ){ ++ u32 iKey; ++ if( p->bRecursive ){ ++ if( p->iRowid==0 ) break; ++ iKey = p->sParse.aNode[p->sParse.aUp[p->i]].u.iKey; ++ }else{ ++ iKey = p->iRowid; ++ } ++ sqlite3_result_int64(ctx, (sqlite3_int64)iKey); ++ } ++ break; ++ } ++ case JEACH_VALUE: { ++ if( pThis->jnFlags & JNODE_LABEL ) pThis++; ++ jsonReturn(pThis, ctx, 0); ++ break; ++ } ++ case JEACH_TYPE: { ++ if( pThis->jnFlags & JNODE_LABEL ) pThis++; ++ sqlite3_result_text(ctx, jsonType[pThis->eType], -1, SQLITE_STATIC); ++ break; ++ } ++ case JEACH_ATOM: { ++ if( pThis->jnFlags & JNODE_LABEL ) pThis++; ++ if( pThis->eType>=JSON_ARRAY ) break; ++ jsonReturn(pThis, ctx, 0); ++ break; ++ } ++ case JEACH_ID: { ++ sqlite3_result_int64(ctx, ++ (sqlite3_int64)p->i + ((pThis->jnFlags & JNODE_LABEL)!=0)); ++ break; ++ } ++ case JEACH_PARENT: { ++ if( p->i>p->iBegin && p->bRecursive ){ ++ sqlite3_result_int64(ctx, (sqlite3_int64)p->sParse.aUp[p->i]); ++ } ++ break; ++ } ++ case JEACH_FULLKEY: { ++ JsonString x; ++ jsonInit(&x, ctx); ++ if( p->bRecursive ){ ++ jsonEachComputePath(p, &x, p->i); ++ }else{ ++ if( p->zRoot ){ ++ jsonAppendRaw(&x, p->zRoot, (int)strlen(p->zRoot)); ++ }else{ ++ jsonAppendChar(&x, '$'); ++ } ++ if( p->eType==JSON_ARRAY ){ ++ jsonPrintf(30, &x, "[%d]", p->iRowid); ++ }else if( p->eType==JSON_OBJECT ){ ++ jsonPrintf(pThis->n, &x, ".%.*s", pThis->n-2, pThis->u.zJContent+1); ++ } ++ } ++ jsonResult(&x); ++ break; ++ } ++ case JEACH_PATH: { ++ if( p->bRecursive ){ ++ JsonString x; ++ jsonInit(&x, ctx); ++ jsonEachComputePath(p, &x, p->sParse.aUp[p->i]); ++ jsonResult(&x); ++ break; ++ } ++ /* For json_each() path and root are the same so fall through ++ ** into the root case */ ++ } ++ default: { ++ const char *zRoot = p->zRoot; ++ if( zRoot==0 ) zRoot = "$"; ++ sqlite3_result_text(ctx, zRoot, -1, SQLITE_STATIC); ++ break; ++ } ++ case JEACH_JSON: { ++ assert( i==JEACH_JSON ); ++ sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_STATIC); ++ break; ++ } ++ } ++ return SQLITE_OK; ++} ++ ++/* Return the current rowid value */ ++static int jsonEachRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ ++ JsonEachCursor *p = (JsonEachCursor*)cur; ++ *pRowid = p->iRowid; ++ return SQLITE_OK; ++} ++ ++/* The query strategy is to look for an equality constraint on the json ++** column. Without such a constraint, the table cannot operate. idxNum is ++** 1 if the constraint is found, 3 if the constraint and zRoot are found, ++** and 0 otherwise. ++*/ ++static int jsonEachBestIndex( ++ sqlite3_vtab *tab, ++ sqlite3_index_info *pIdxInfo ++){ ++ int i; /* Loop counter or computed array index */ ++ int aIdx[2]; /* Index of constraints for JSON and ROOT */ ++ int unusableMask = 0; /* Mask of unusable JSON and ROOT constraints */ ++ int idxMask = 0; /* Mask of usable == constraints JSON and ROOT */ ++ const struct sqlite3_index_constraint *pConstraint; ++ ++ /* This implementation assumes that JSON and ROOT are the last two ++ ** columns in the table */ ++ assert( JEACH_ROOT == JEACH_JSON+1 ); ++ UNUSED_PARAM(tab); ++ aIdx[0] = aIdx[1] = -1; ++ pConstraint = pIdxInfo->aConstraint; ++ for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ ++ int iCol; ++ int iMask; ++ if( pConstraint->iColumn < JEACH_JSON ) continue; ++ iCol = pConstraint->iColumn - JEACH_JSON; ++ assert( iCol==0 || iCol==1 ); ++ iMask = 1 << iCol; ++ if( pConstraint->usable==0 ){ ++ unusableMask |= iMask; ++ }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ ++ aIdx[iCol] = i; ++ idxMask |= iMask; ++ } ++ } ++ if( (unusableMask & ~idxMask)!=0 ){ ++ /* If there are any unusable constraints on JSON or ROOT, then reject ++ ** this entire plan */ ++ return SQLITE_CONSTRAINT; ++ } ++ if( aIdx[0]<0 ){ ++ /* No JSON input. Leave estimatedCost at the huge value that it was ++ ** initialized to to discourage the query planner from selecting this ++ ** plan. */ ++ pIdxInfo->idxNum = 0; ++ }else{ ++ pIdxInfo->estimatedCost = 1.0; ++ i = aIdx[0]; ++ pIdxInfo->aConstraintUsage[i].argvIndex = 1; ++ pIdxInfo->aConstraintUsage[i].omit = 1; ++ if( aIdx[1]<0 ){ ++ pIdxInfo->idxNum = 1; /* Only JSON supplied. Plan 1 */ ++ }else{ ++ i = aIdx[1]; ++ pIdxInfo->aConstraintUsage[i].argvIndex = 2; ++ pIdxInfo->aConstraintUsage[i].omit = 1; ++ pIdxInfo->idxNum = 3; /* Both JSON and ROOT are supplied. Plan 3 */ ++ } ++ } ++ return SQLITE_OK; ++} ++ ++/* Start a search on a new JSON string */ ++static int jsonEachFilter( ++ sqlite3_vtab_cursor *cur, ++ int idxNum, const char *idxStr, ++ int argc, sqlite3_value **argv ++){ ++ JsonEachCursor *p = (JsonEachCursor*)cur; ++ const char *z; ++ const char *zRoot = 0; ++ sqlite3_int64 n; ++ ++ UNUSED_PARAM(idxStr); ++ UNUSED_PARAM(argc); ++ jsonEachCursorReset(p); ++ if( idxNum==0 ) return SQLITE_OK; ++ z = (const char*)sqlite3_value_text(argv[0]); ++ if( z==0 ) return SQLITE_OK; ++ n = sqlite3_value_bytes(argv[0]); ++ p->zJson = sqlite3_malloc64( n+1 ); ++ if( p->zJson==0 ) return SQLITE_NOMEM; ++ memcpy(p->zJson, z, (size_t)n+1); ++ if( jsonParse(&p->sParse, 0, p->zJson) ){ ++ int rc = SQLITE_NOMEM; ++ if( p->sParse.oom==0 ){ ++ sqlite3_free(cur->pVtab->zErrMsg); ++ cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON"); ++ if( cur->pVtab->zErrMsg ) rc = SQLITE_ERROR; ++ } ++ jsonEachCursorReset(p); ++ return rc; ++ }else if( p->bRecursive && jsonParseFindParents(&p->sParse) ){ ++ jsonEachCursorReset(p); ++ return SQLITE_NOMEM; ++ }else{ ++ JsonNode *pNode = 0; ++ if( idxNum==3 ){ ++ const char *zErr = 0; ++ zRoot = (const char*)sqlite3_value_text(argv[1]); ++ if( zRoot==0 ) return SQLITE_OK; ++ n = sqlite3_value_bytes(argv[1]); ++ p->zRoot = sqlite3_malloc64( n+1 ); ++ if( p->zRoot==0 ) return SQLITE_NOMEM; ++ memcpy(p->zRoot, zRoot, (size_t)n+1); ++ if( zRoot[0]!='$' ){ ++ zErr = zRoot; ++ }else{ ++ pNode = jsonLookupStep(&p->sParse, 0, p->zRoot+1, 0, &zErr); ++ } ++ if( zErr ){ ++ sqlite3_free(cur->pVtab->zErrMsg); ++ cur->pVtab->zErrMsg = jsonPathSyntaxError(zErr); ++ jsonEachCursorReset(p); ++ return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; ++ }else if( pNode==0 ){ ++ return SQLITE_OK; ++ } ++ }else{ ++ pNode = p->sParse.aNode; ++ } ++ p->iBegin = p->i = (int)(pNode - p->sParse.aNode); ++ p->eType = pNode->eType; ++ if( p->eType>=JSON_ARRAY ){ ++ pNode->u.iKey = 0; ++ p->iEnd = p->i + pNode->n + 1; ++ if( p->bRecursive ){ ++ p->eType = p->sParse.aNode[p->sParse.aUp[p->i]].eType; ++ if( p->i>0 && (p->sParse.aNode[p->i-1].jnFlags & JNODE_LABEL)!=0 ){ ++ p->i--; ++ } ++ }else{ ++ p->i++; ++ } ++ }else{ ++ p->iEnd = p->i+1; ++ } ++ } ++ return SQLITE_OK; ++} ++ ++/* The methods of the json_each virtual table */ ++static sqlite3_module jsonEachModule = { ++ 0, /* iVersion */ ++ 0, /* xCreate */ ++ jsonEachConnect, /* xConnect */ ++ jsonEachBestIndex, /* xBestIndex */ ++ jsonEachDisconnect, /* xDisconnect */ ++ 0, /* xDestroy */ ++ jsonEachOpenEach, /* xOpen - open a cursor */ ++ jsonEachClose, /* xClose - close a cursor */ ++ jsonEachFilter, /* xFilter - configure scan constraints */ ++ jsonEachNext, /* xNext - advance a cursor */ ++ jsonEachEof, /* xEof - check for end of scan */ ++ jsonEachColumn, /* xColumn - read data */ ++ jsonEachRowid, /* xRowid - read data */ ++ 0, /* xUpdate */ ++ 0, /* xBegin */ ++ 0, /* xSync */ ++ 0, /* xCommit */ ++ 0, /* xRollback */ ++ 0, /* xFindMethod */ ++ 0, /* xRename */ ++ 0, /* xSavepoint */ ++ 0, /* xRelease */ ++ 0, /* xRollbackTo */ ++ 0 /* xShadowName */ ++}; ++ ++/* The methods of the json_tree virtual table. */ ++static sqlite3_module jsonTreeModule = { ++ 0, /* iVersion */ ++ 0, /* xCreate */ ++ jsonEachConnect, /* xConnect */ ++ jsonEachBestIndex, /* xBestIndex */ ++ jsonEachDisconnect, /* xDisconnect */ ++ 0, /* xDestroy */ ++ jsonEachOpenTree, /* xOpen - open a cursor */ ++ jsonEachClose, /* xClose - close a cursor */ ++ jsonEachFilter, /* xFilter - configure scan constraints */ ++ jsonEachNext, /* xNext - advance a cursor */ ++ jsonEachEof, /* xEof - check for end of scan */ ++ jsonEachColumn, /* xColumn - read data */ ++ jsonEachRowid, /* xRowid - read data */ ++ 0, /* xUpdate */ ++ 0, /* xBegin */ ++ 0, /* xSync */ ++ 0, /* xCommit */ ++ 0, /* xRollback */ ++ 0, /* xFindMethod */ ++ 0, /* xRename */ ++ 0, /* xSavepoint */ ++ 0, /* xRelease */ ++ 0, /* xRollbackTo */ ++ 0 /* xShadowName */ ++}; ++#endif /* SQLITE_OMIT_VIRTUALTABLE */ ++ ++/**************************************************************************** ++** The following routines are the only publically visible identifiers in this ++** file. Call the following routines in order to register the various SQL ++** functions and the virtual table implemented by this file. ++****************************************************************************/ ++ ++SQLITE_PRIVATE int sqlite3Json1Init(sqlite3 *db){ ++ int rc = SQLITE_OK; ++ unsigned int i; ++ static const struct { ++ const char *zName; ++ int nArg; ++ int flag; ++ void (*xFunc)(sqlite3_context*,int,sqlite3_value**); ++ } aFunc[] = { ++ { "json", 1, 0, jsonRemoveFunc }, ++ { "json_array", -1, 0, jsonArrayFunc }, ++ { "json_array_length", 1, 0, jsonArrayLengthFunc }, ++ { "json_array_length", 2, 0, jsonArrayLengthFunc }, ++ { "json_extract", -1, 0, jsonExtractFunc }, ++ { "json_insert", -1, 0, jsonSetFunc }, ++ { "json_object", -1, 0, jsonObjectFunc }, ++ { "json_patch", 2, 0, jsonPatchFunc }, ++ { "json_quote", 1, 0, jsonQuoteFunc }, ++ { "json_remove", -1, 0, jsonRemoveFunc }, ++ { "json_replace", -1, 0, jsonReplaceFunc }, ++ { "json_set", -1, 1, jsonSetFunc }, ++ { "json_type", 1, 0, jsonTypeFunc }, ++ { "json_type", 2, 0, jsonTypeFunc }, ++ { "json_valid", 1, 0, jsonValidFunc }, ++ ++#if SQLITE_DEBUG ++ /* DEBUG and TESTING functions */ ++ { "json_parse", 1, 0, jsonParseFunc }, ++ { "json_test1", 1, 0, jsonTest1Func }, ++#endif ++ }; ++ static const struct { ++ const char *zName; ++ int nArg; ++ void (*xStep)(sqlite3_context*,int,sqlite3_value**); ++ void (*xFinal)(sqlite3_context*); ++ void (*xValue)(sqlite3_context*); ++ } aAgg[] = { ++ { "json_group_array", 1, ++ jsonArrayStep, jsonArrayFinal, jsonArrayValue }, ++ { "json_group_object", 2, ++ jsonObjectStep, jsonObjectFinal, jsonObjectValue }, ++ }; ++#ifndef SQLITE_OMIT_VIRTUALTABLE ++ static const struct { ++ const char *zName; ++ sqlite3_module *pModule; ++ } aMod[] = { ++ { "json_each", &jsonEachModule }, ++ { "json_tree", &jsonTreeModule }, ++ }; ++#endif ++ for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){ ++ rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg, ++ SQLITE_UTF8 | SQLITE_DETERMINISTIC, ++ (void*)&aFunc[i].flag, ++ aFunc[i].xFunc, 0, 0); ++ } ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){ ++ rc = sqlite3_create_window_function(db, aAgg[i].zName, aAgg[i].nArg, ++ SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0, ++ aAgg[i].xStep, aAgg[i].xFinal, ++ aAgg[i].xValue, jsonGroupInverse, 0); ++ } ++#endif ++#ifndef SQLITE_OMIT_VIRTUALTABLE ++ for(i=0; i<sizeof(aMod)/sizeof(aMod[0]) && rc==SQLITE_OK; i++){ ++ rc = sqlite3_create_module(db, aMod[i].zName, aMod[i].pModule, 0); ++ } ++#endif ++ return rc; ++} ++ ++ ++#ifndef SQLITE_CORE ++#ifdef _WIN32 ++__declspec(dllexport) ++#endif ++SQLITE_API int sqlite3_json_init( ++ sqlite3 *db, ++ char **pzErrMsg, ++ const sqlite3_api_routines *pApi ++){ ++ SQLITE_EXTENSION_INIT2(pApi); ++ (void)pzErrMsg; /* Unused parameter */ ++ return sqlite3Json1Init(db); ++} ++#endif ++#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1) */ ++ ++/************** End of json1.c ***********************************************/ + /************** Begin file rtree.c *******************************************/ + /* + ** 2001 September 15 +@@ -165280,7 +179149,7 @@ + ** + ** CREATE TABLE %_node(nodeno INTEGER PRIMARY KEY, data BLOB) + ** CREATE TABLE %_parent(nodeno INTEGER PRIMARY KEY, parentnode INTEGER) +-** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER) ++** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER, ...) + ** + ** The data for each node of the r-tree structure is stored in the %_node + ** table. For each node that is not the root node of the r-tree, there is +@@ -165287,7 +179156,8 @@ + ** an entry in the %_parent table associating the node with its parent. + ** And for each row of data in the table, there is an entry in the %_rowid + ** table that maps from the entries rowid to the id of the node that it +-** is stored on. ++** is stored on. If the r-tree contains auxiliary columns, those are stored ++** on the end of the %_rowid table. + ** + ** The root node of an r-tree always exists, even if the r-tree table is + ** empty. The nodeno of the root node is always 1. All other nodes in the +@@ -165308,7 +179178,8 @@ + ** child page. + */ + +-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RTREE) ++#if !defined(SQLITE_CORE) \ ++ || (defined(SQLITE_ENABLE_RTREE) && !defined(SQLITE_OMIT_VIRTUALTABLE)) + + #ifndef SQLITE_CORE + /* #include "sqlite3ext.h" */ +@@ -165349,6 +179220,9 @@ + /* The rtree may have between 1 and RTREE_MAX_DIMENSIONS dimensions. */ + #define RTREE_MAX_DIMENSIONS 5 + ++/* Maximum number of auxiliary columns */ ++#define RTREE_MAX_AUX_COLUMN 100 ++ + /* Size of hash table Rtree.aHash. This hash table is not expected to + ** ever contain very many entries, so a fixed number of buckets is + ** used. +@@ -165377,6 +179251,8 @@ + u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */ + u8 nBytesPerCell; /* Bytes consumed per cell */ + u8 inWrTrans; /* True if inside write transaction */ ++ u8 nAux; /* # of auxiliary columns in %_rowid */ ++ u8 nAuxNotNull; /* Number of initial not-null aux columns */ + int iDepth; /* Current depth of the r-tree structure */ + char *zDb; /* Name of database containing r-tree table */ + char *zName; /* Name of r-tree table */ +@@ -165383,6 +179259,8 @@ + u32 nBusy; /* Current number of users of this structure */ + i64 nRowEst; /* Estimated number of rows in this table */ + u32 nCursor; /* Number of open cursors */ ++ u32 nNodeRef; /* Number RtreeNodes with positive nRef */ ++ char *zReadAuxSql; /* SQL for statement to read aux data */ + + /* List of nodes removed during a CondenseTree operation. List is + ** linked together via the pointer normally used for hash chains - +@@ -165409,6 +179287,9 @@ + sqlite3_stmt *pWriteParent; + sqlite3_stmt *pDeleteParent; + ++ /* Statement for writing to the "aux:" fields, if there are any */ ++ sqlite3_stmt *pWriteAux; ++ + RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */ + }; + +@@ -165465,7 +179346,7 @@ + ** The smallest possible node-size is (512-64)==448 bytes. And the largest + ** supported cell size is 48 bytes (8 byte rowid + ten 4 byte coordinates). + ** Therefore all non-root nodes must contain at least 3 entries. Since +-** 2^40 is greater than 2^64, an r-tree structure always has a depth of ++** 3^40 is greater than 2^64, an r-tree structure always has a depth of + ** 40 or less. + */ + #define RTREE_MAX_DEPTH 40 +@@ -165485,6 +179366,7 @@ + sqlite3_vtab_cursor base; /* Base class. Must be first */ + u8 atEOF; /* True if at end of search */ + u8 bPoint; /* True if sPoint is valid */ ++ u8 bAuxValid; /* True if pReadAux is valid */ + int iStrategy; /* Copy of idxNum search parameter */ + int nConstraint; /* Number of entries in aConstraint */ + RtreeConstraint *aConstraint; /* Search constraints. */ +@@ -165492,6 +179374,7 @@ + int nPoint; /* Number of slots used in aPoint[] */ + int mxLevel; /* iLevel value for root of the tree */ + RtreeSearchPoint *aPoint; /* Priority queue for search points */ ++ sqlite3_stmt *pReadAux; /* Statement to read aux-data */ + RtreeSearchPoint sPoint; /* Cached next search point */ + RtreeNode *aNode[RTREE_CACHE_SZ]; /* Rtree node cache */ + u32 anQueue[RTREE_MAX_DEPTH+1]; /* Number of queued entries by iLevel */ +@@ -165778,6 +179661,7 @@ + */ + static void nodeReference(RtreeNode *p){ + if( p ){ ++ assert( p->nRef>0 ); + p->nRef++; + } + } +@@ -165845,6 +179729,7 @@ + memset(pNode, 0, sizeof(RtreeNode) + pRtree->iNodeSize); + pNode->zData = (u8 *)&pNode[1]; + pNode->nRef = 1; ++ pRtree->nNodeRef++; + pNode->pParent = pParent; + pNode->isDirty = 1; + nodeReference(pParent); +@@ -165878,10 +179763,10 @@ + /* Check if the requested node is already in the hash table. If so, + ** increase its reference count and return it. + */ +- if( (pNode = nodeHashLookup(pRtree, iNode)) ){ ++ if( (pNode = nodeHashLookup(pRtree, iNode))!=0 ){ + assert( !pParent || !pNode->pParent || pNode->pParent==pParent ); + if( pParent && !pNode->pParent ){ +- nodeReference(pParent); ++ pParent->nRef++; + pNode->pParent = pParent; + } + pNode->nRef++; +@@ -165920,6 +179805,7 @@ + pNode->pParent = pParent; + pNode->zData = (u8 *)&pNode[1]; + pNode->nRef = 1; ++ pRtree->nNodeRef++; + pNode->iNode = iNode; + pNode->isDirty = 0; + pNode->pNext = 0; +@@ -165960,7 +179846,10 @@ + } + *ppNode = pNode; + }else{ +- sqlite3_free(pNode); ++ if( pNode ){ ++ pRtree->nNodeRef--; ++ sqlite3_free(pNode); ++ } + *ppNode = 0; + } + +@@ -166040,6 +179929,7 @@ + sqlite3_step(p); + pNode->isDirty = 0; + rc = sqlite3_reset(p); ++ sqlite3_bind_null(p, 2); + if( pNode->iNode==0 && rc==SQLITE_OK ){ + pNode->iNode = sqlite3_last_insert_rowid(pRtree->db); + nodeHashInsert(pRtree, pNode); +@@ -166056,8 +179946,10 @@ + int rc = SQLITE_OK; + if( pNode ){ + assert( pNode->nRef>0 ); ++ assert( pRtree->nNodeRef>0 ); + pNode->nRef--; + if( pNode->nRef==0 ){ ++ pRtree->nNodeRef--; + if( pNode->iNode==1 ){ + pRtree->iDepth = -1; + } +@@ -166174,8 +180066,9 @@ + pRtree->nBusy--; + if( pRtree->nBusy==0 ){ + pRtree->inWrTrans = 0; +- pRtree->nCursor = 0; ++ assert( pRtree->nCursor==0 ); + nodeBlobReset(pRtree); ++ assert( pRtree->nNodeRef==0 ); + sqlite3_finalize(pRtree->pWriteNode); + sqlite3_finalize(pRtree->pDeleteNode); + sqlite3_finalize(pRtree->pReadRowid); +@@ -166184,6 +180077,8 @@ + sqlite3_finalize(pRtree->pReadParent); + sqlite3_finalize(pRtree->pWriteParent); + sqlite3_finalize(pRtree->pDeleteParent); ++ sqlite3_finalize(pRtree->pWriteAux); ++ sqlite3_free(pRtree->zReadAuxSql); + sqlite3_free(pRtree); + } + } +@@ -166272,6 +180167,7 @@ + RtreeCursor *pCsr = (RtreeCursor *)cur; + assert( pRtree->nCursor>0 ); + freeCursorConstraints(pCsr); ++ sqlite3_finalize(pCsr->pReadAux); + sqlite3_free(pCsr->aPoint); + for(ii=0; ii<RTREE_CACHE_SZ; ii++) nodeRelease(pRtree, pCsr->aNode[ii]); + sqlite3_free(pCsr); +@@ -166643,7 +180539,7 @@ + if( ii<RTREE_CACHE_SZ ){ + assert( pCur->aNode[ii]==0 ); + pCur->aNode[ii] = pCur->aNode[0]; +- }else{ ++ }else{ + nodeRelease(RTREE_OF_CURSOR(pCur), pCur->aNode[0]); + } + pCur->aNode[0] = 0; +@@ -166814,6 +180710,10 @@ + + /* Move to the next entry that matches the configured constraints. */ + RTREE_QUEUE_TRACE(pCsr, "POP-Nx:"); ++ if( pCsr->bAuxValid ){ ++ pCsr->bAuxValid = 0; ++ sqlite3_reset(pCsr->pReadAux); ++ } + rtreeSearchPointPop(pCsr); + rc = rtreeStepToLeaf(pCsr); + return rc; +@@ -166848,7 +180748,7 @@ + if( p==0 ) return SQLITE_OK; + if( i==0 ){ + sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell)); +- }else{ ++ }else if( i<=pRtree->nDim2 ){ + nodeGetCoord(pRtree, pNode, p->iCell, i-1, &c); + #ifndef SQLITE_RTREE_INT_ONLY + if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ +@@ -166859,7 +180759,27 @@ + assert( pRtree->eCoordType==RTREE_COORD_INT32 ); + sqlite3_result_int(ctx, c.i); + } +- } ++ }else{ ++ if( !pCsr->bAuxValid ){ ++ if( pCsr->pReadAux==0 ){ ++ rc = sqlite3_prepare_v3(pRtree->db, pRtree->zReadAuxSql, -1, 0, ++ &pCsr->pReadAux, 0); ++ if( rc ) return rc; ++ } ++ sqlite3_bind_int64(pCsr->pReadAux, 1, ++ nodeGetRowid(pRtree, pNode, p->iCell)); ++ rc = sqlite3_step(pCsr->pReadAux); ++ if( rc==SQLITE_ROW ){ ++ pCsr->bAuxValid = 1; ++ }else{ ++ sqlite3_reset(pCsr->pReadAux); ++ if( rc==SQLITE_DONE ) rc = SQLITE_OK; ++ return rc; ++ } ++ } ++ sqlite3_result_value(ctx, ++ sqlite3_column_value(pCsr->pReadAux, i - pRtree->nDim2 + 1)); ++ } + return SQLITE_OK; + } + +@@ -166937,6 +180857,7 @@ + int ii; + int rc = SQLITE_OK; + int iCell = 0; ++ sqlite3_stmt *pStmt; + + rtreeReference(pRtree); + +@@ -166943,8 +180864,10 @@ + /* Reset the cursor to the same state as rtreeOpen() leaves it in. */ + freeCursorConstraints(pCsr); + sqlite3_free(pCsr->aPoint); ++ pStmt = pCsr->pReadAux; + memset(pCsr, 0, sizeof(RtreeCursor)); + pCsr->base.pVtab = (sqlite3_vtab*)pRtree; ++ pCsr->pReadAux = pStmt; + + pCsr->iStrategy = idxNum; + if( idxNum==1 ){ +@@ -167107,10 +181030,14 @@ + */ + pIdxInfo->estimatedCost = 30.0; + pIdxInfo->estimatedRows = 1; ++ pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE; + return SQLITE_OK; + } + +- if( p->usable && (p->iColumn>0 || p->op==SQLITE_INDEX_CONSTRAINT_MATCH) ){ ++ if( p->usable ++ && ((p->iColumn>0 && p->iColumn<=pRtree->nDim2) ++ || p->op==SQLITE_INDEX_CONSTRAINT_MATCH) ++ ){ + u8 op; + switch( p->op ){ + case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break; +@@ -167277,7 +181204,7 @@ + ){ + int rc; + int ii; +- RtreeNode *pNode; ++ RtreeNode *pNode = 0; + rc = nodeAcquire(pRtree, 1, 0, &pNode); + + for(ii=0; rc==SQLITE_OK && ii<(pRtree->iDepth-iHeight); ii++){ +@@ -167683,7 +181610,7 @@ + }else{ + pLeft = pNode; + pRight = nodeNew(pRtree, pLeft->pParent); +- nodeReference(pLeft); ++ pLeft->nRef++; + } + + if( !pLeft || !pRight ){ +@@ -168092,7 +182019,7 @@ + /* + ** Select a currently unused rowid for a new r-tree record. + */ +-static int newRowid(Rtree *pRtree, i64 *piRowid){ ++static int rtreeNewRowid(Rtree *pRtree, i64 *piRowid){ + int rc; + sqlite3_bind_null(pRtree->pWriteRowid, 1); + sqlite3_bind_null(pRtree->pWriteRowid, 2); +@@ -168109,7 +182036,7 @@ + int rc; /* Return code */ + RtreeNode *pLeaf = 0; /* Leaf node containing record iDelete */ + int iCell; /* Index of iDelete cell in pLeaf */ +- RtreeNode *pRoot; /* Root node of rtree structure */ ++ RtreeNode *pRoot = 0; /* Root node of rtree structure */ + + + /* Obtain a reference to the root node to initialize Rtree.iDepth */ +@@ -168152,7 +182079,7 @@ + */ + if( rc==SQLITE_OK && pRtree->iDepth>0 && NCELL(pRoot)==1 ){ + int rc2; +- RtreeNode *pChild; ++ RtreeNode *pChild = 0; + i64 iChild = nodeGetRowid(pRtree, pRoot, 0); + rc = nodeAcquire(pRtree, iChild, pRoot, &pChild); + if( rc==SQLITE_OK ){ +@@ -168173,6 +182100,7 @@ + rc = reinsertNodeContent(pRtree, pLeaf); + } + pRtree->pDeleted = pLeaf->pNext; ++ pRtree->nNodeRef--; + sqlite3_free(pLeaf); + } + +@@ -168269,7 +182197,7 @@ + static int rtreeUpdate( + sqlite3_vtab *pVtab, + int nData, +- sqlite3_value **azData, ++ sqlite3_value **aData, + sqlite_int64 *pRowid + ){ + Rtree *pRtree = (Rtree *)pVtab; +@@ -168277,6 +182205,12 @@ + RtreeCell cell; /* New cell to insert if nData>1 */ + int bHaveRowid = 0; /* Set to 1 after new rowid is determined */ + ++ if( pRtree->nNodeRef ){ ++ /* Unable to write to the btree while another cursor is reading from it, ++ ** since the write might do a rebalance which would disrupt the read ++ ** cursor. */ ++ return SQLITE_LOCKED_VTAB; ++ } + rtreeReference(pRtree); + assert(nData>=1); + +@@ -168295,8 +182229,10 @@ + */ + if( nData>1 ){ + int ii; ++ int nn = nData - 4; + +- /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. ++ if( nn > pRtree->nDim2 ) nn = pRtree->nDim2; ++ /* Populate the cell.aCoord[] array. The first coordinate is aData[3]. + ** + ** NB: nData can only be less than nDim*2+3 if the rtree is mis-declared + ** with "column" that are interpreted as table constraints. +@@ -168304,13 +182240,12 @@ + ** This problem was discovered after years of use, so we silently ignore + ** these kinds of misdeclared tables to avoid breaking any legacy. + */ +- assert( nData<=(pRtree->nDim2 + 3) ); + + #ifndef SQLITE_RTREE_INT_ONLY + if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ +- for(ii=0; ii<nData-4; ii+=2){ +- cell.aCoord[ii].f = rtreeValueDown(azData[ii+3]); +- cell.aCoord[ii+1].f = rtreeValueUp(azData[ii+4]); ++ for(ii=0; ii<nn; ii+=2){ ++ cell.aCoord[ii].f = rtreeValueDown(aData[ii+3]); ++ cell.aCoord[ii+1].f = rtreeValueUp(aData[ii+4]); + if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){ + rc = rtreeConstraintError(pRtree, ii+1); + goto constraint; +@@ -168319,9 +182254,9 @@ + }else + #endif + { +- for(ii=0; ii<nData-4; ii+=2){ +- cell.aCoord[ii].i = sqlite3_value_int(azData[ii+3]); +- cell.aCoord[ii+1].i = sqlite3_value_int(azData[ii+4]); ++ for(ii=0; ii<nn; ii+=2){ ++ cell.aCoord[ii].i = sqlite3_value_int(aData[ii+3]); ++ cell.aCoord[ii+1].i = sqlite3_value_int(aData[ii+4]); + if( cell.aCoord[ii].i>cell.aCoord[ii+1].i ){ + rc = rtreeConstraintError(pRtree, ii+1); + goto constraint; +@@ -168331,10 +182266,10 @@ + + /* If a rowid value was supplied, check if it is already present in + ** the table. If so, the constraint has failed. */ +- if( sqlite3_value_type(azData[2])!=SQLITE_NULL ){ +- cell.iRowid = sqlite3_value_int64(azData[2]); +- if( sqlite3_value_type(azData[0])==SQLITE_NULL +- || sqlite3_value_int64(azData[0])!=cell.iRowid ++ if( sqlite3_value_type(aData[2])!=SQLITE_NULL ){ ++ cell.iRowid = sqlite3_value_int64(aData[2]); ++ if( sqlite3_value_type(aData[0])==SQLITE_NULL ++ || sqlite3_value_int64(aData[0])!=cell.iRowid + ){ + int steprc; + sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid); +@@ -168353,16 +182288,16 @@ + } + } + +- /* If azData[0] is not an SQL NULL value, it is the rowid of a ++ /* If aData[0] is not an SQL NULL value, it is the rowid of a + ** record to delete from the r-tree table. The following block does + ** just that. + */ +- if( sqlite3_value_type(azData[0])!=SQLITE_NULL ){ +- rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(azData[0])); ++ if( sqlite3_value_type(aData[0])!=SQLITE_NULL ){ ++ rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(aData[0])); + } + +- /* If the azData[] array contains more than one element, elements +- ** (azData[2]..azData[argc-1]) contain a new record to insert into ++ /* If the aData[] array contains more than one element, elements ++ ** (aData[2]..aData[argc-1]) contain a new record to insert into + ** the r-tree structure. + */ + if( rc==SQLITE_OK && nData>1 ){ +@@ -168371,7 +182306,7 @@ + + /* Figure out the rowid of the new row. */ + if( bHaveRowid==0 ){ +- rc = newRowid(pRtree, &cell.iRowid); ++ rc = rtreeNewRowid(pRtree, &cell.iRowid); + } + *pRowid = cell.iRowid; + +@@ -168387,6 +182322,16 @@ + rc = rc2; + } + } ++ if( pRtree->nAux ){ ++ sqlite3_stmt *pUp = pRtree->pWriteAux; ++ int jj; ++ sqlite3_bind_int64(pUp, 1, *pRowid); ++ for(jj=0; jj<pRtree->nAux; jj++){ ++ sqlite3_bind_value(pUp, jj+2, aData[pRtree->nDim2+3+jj]); ++ } ++ sqlite3_step(pUp); ++ rc = sqlite3_reset(pUp); ++ } + } + + constraint: +@@ -168453,7 +182398,7 @@ + */ + static int rtreeSavepoint(sqlite3_vtab *pVtab, int iSavepoint){ + Rtree *pRtree = (Rtree *)pVtab; +- int iwt = pRtree->inWrTrans; ++ u8 iwt = pRtree->inWrTrans; + UNUSED_PARAMETER(iSavepoint); + pRtree->inWrTrans = 0; + nodeBlobReset(pRtree); +@@ -168505,8 +182450,24 @@ + return rc; + } + ++ ++/* ++** Return true if zName is the extension on one of the shadow tables used ++** by this module. ++*/ ++static int rtreeShadowName(const char *zName){ ++ static const char *azName[] = { ++ "node", "parent", "rowid" ++ }; ++ unsigned int i; ++ for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){ ++ if( sqlite3_stricmp(zName, azName[i])==0 ) return 1; ++ } ++ return 0; ++} ++ + static sqlite3_module rtreeModule = { +- 2, /* iVersion */ ++ 3, /* iVersion */ + rtreeCreate, /* xCreate - create a table */ + rtreeConnect, /* xConnect - connect to an existing table */ + rtreeBestIndex, /* xBestIndex - Determine search strategy */ +@@ -168529,6 +182490,7 @@ + rtreeSavepoint, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ ++ rtreeShadowName /* xShadowName */ + }; + + static int rtreeSqlInit( +@@ -168543,18 +182505,18 @@ + #define N_STATEMENT 8 + static const char *azSql[N_STATEMENT] = { + /* Write the xxx_node table */ +- "INSERT OR REPLACE INTO '%q'.'%q_node' VALUES(:1, :2)", +- "DELETE FROM '%q'.'%q_node' WHERE nodeno = :1", ++ "INSERT OR REPLACE INTO '%q'.'%q_node' VALUES(?1, ?2)", ++ "DELETE FROM '%q'.'%q_node' WHERE nodeno = ?1", + + /* Read and write the xxx_rowid table */ +- "SELECT nodeno FROM '%q'.'%q_rowid' WHERE rowid = :1", +- "INSERT OR REPLACE INTO '%q'.'%q_rowid' VALUES(:1, :2)", +- "DELETE FROM '%q'.'%q_rowid' WHERE rowid = :1", ++ "SELECT nodeno FROM '%q'.'%q_rowid' WHERE rowid = ?1", ++ "INSERT OR REPLACE INTO '%q'.'%q_rowid' VALUES(?1, ?2)", ++ "DELETE FROM '%q'.'%q_rowid' WHERE rowid = ?1", + + /* Read and write the xxx_parent table */ +- "SELECT parentnode FROM '%q'.'%q_parent' WHERE nodeno = :1", +- "INSERT OR REPLACE INTO '%q'.'%q_parent' VALUES(:1, :2)", +- "DELETE FROM '%q'.'%q_parent' WHERE nodeno = :1" ++ "SELECT parentnode FROM '%q'.'%q_parent' WHERE nodeno = ?1", ++ "INSERT OR REPLACE INTO '%q'.'%q_parent' VALUES(?1, ?2)", ++ "DELETE FROM '%q'.'%q_parent' WHERE nodeno = ?1" + }; + sqlite3_stmt **appStmt[N_STATEMENT]; + int i; +@@ -168562,14 +182524,25 @@ + pRtree->db = db; + + if( isCreate ){ +- char *zCreate = sqlite3_mprintf( +-"CREATE TABLE \"%w\".\"%w_node\"(nodeno INTEGER PRIMARY KEY, data BLOB);" +-"CREATE TABLE \"%w\".\"%w_rowid\"(rowid INTEGER PRIMARY KEY, nodeno INTEGER);" +-"CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY," +- " parentnode INTEGER);" +-"INSERT INTO '%q'.'%q_node' VALUES(1, zeroblob(%d))", +- zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, pRtree->iNodeSize +- ); ++ char *zCreate; ++ sqlite3_str *p = sqlite3_str_new(db); ++ int ii; ++ sqlite3_str_appendf(p, ++ "CREATE TABLE \"%w\".\"%w_rowid\"(rowid INTEGER PRIMARY KEY,nodeno", ++ zDb, zPrefix); ++ for(ii=0; ii<pRtree->nAux; ii++){ ++ sqlite3_str_appendf(p,",a%d",ii); ++ } ++ sqlite3_str_appendf(p, ++ ");CREATE TABLE \"%w\".\"%w_node\"(nodeno INTEGER PRIMARY KEY,data);", ++ zDb, zPrefix); ++ sqlite3_str_appendf(p, ++ "CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY,parentnode);", ++ zDb, zPrefix); ++ sqlite3_str_appendf(p, ++ "INSERT INTO \"%w\".\"%w_node\"VALUES(1,zeroblob(%d))", ++ zDb, zPrefix, pRtree->iNodeSize); ++ zCreate = sqlite3_str_finish(p); + if( !zCreate ){ + return SQLITE_NOMEM; + } +@@ -168591,7 +182564,17 @@ + + rc = rtreeQueryStat1(db, pRtree); + for(i=0; i<N_STATEMENT && rc==SQLITE_OK; i++){ +- char *zSql = sqlite3_mprintf(azSql[i], zDb, zPrefix); ++ char *zSql; ++ const char *zFormat; ++ if( i!=3 || pRtree->nAux==0 ){ ++ zFormat = azSql[i]; ++ }else { ++ /* An UPSERT is very slightly slower than REPLACE, but it is needed ++ ** if there are auxiliary columns */ ++ zFormat = "INSERT INTO\"%w\".\"%w_rowid\"(rowid,nodeno)VALUES(?1,?2)" ++ "ON CONFLICT(rowid)DO UPDATE SET nodeno=excluded.nodeno"; ++ } ++ zSql = sqlite3_mprintf(zFormat, zDb, zPrefix); + if( zSql ){ + rc = sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_PERSISTENT, + appStmt[i], 0); +@@ -168600,6 +182583,36 @@ + } + sqlite3_free(zSql); + } ++ if( pRtree->nAux ){ ++ pRtree->zReadAuxSql = sqlite3_mprintf( ++ "SELECT * FROM \"%w\".\"%w_rowid\" WHERE rowid=?1", ++ zDb, zPrefix); ++ if( pRtree->zReadAuxSql==0 ){ ++ rc = SQLITE_NOMEM; ++ }else{ ++ sqlite3_str *p = sqlite3_str_new(db); ++ int ii; ++ char *zSql; ++ sqlite3_str_appendf(p, "UPDATE \"%w\".\"%w_rowid\"SET ", zDb, zPrefix); ++ for(ii=0; ii<pRtree->nAux; ii++){ ++ if( ii ) sqlite3_str_append(p, ",", 1); ++ if( ii<pRtree->nAuxNotNull ){ ++ sqlite3_str_appendf(p,"a%d=coalesce(?%d,a%d)",ii,ii+2,ii); ++ }else{ ++ sqlite3_str_appendf(p,"a%d=?%d",ii,ii+2); ++ } ++ } ++ sqlite3_str_appendf(p, " WHERE rowid=?1"); ++ zSql = sqlite3_str_finish(p); ++ if( zSql==0 ){ ++ rc = SQLITE_NOMEM; ++ }else{ ++ rc = sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_PERSISTENT, ++ &pRtree->pWriteAux, 0); ++ sqlite3_free(zSql); ++ } ++ } ++ } + + return rc; + } +@@ -168670,7 +182683,7 @@ + if( rc!=SQLITE_OK ){ + *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); + }else if( pRtree->iNodeSize<(512-64) ){ +- rc = SQLITE_CORRUPT; ++ rc = SQLITE_CORRUPT_VTAB; + *pzErr = sqlite3_mprintf("undersize RTree blobs in \"%q_node\"", + pRtree->zName); + } +@@ -168702,17 +182715,22 @@ + int nDb; /* Length of string argv[1] */ + int nName; /* Length of string argv[2] */ + int eCoordType = (pAux ? RTREE_COORD_INT32 : RTREE_COORD_REAL32); ++ sqlite3_str *pSql; ++ char *zSql; ++ int ii = 4; ++ int iErr; + + const char *aErrMsg[] = { + 0, /* 0 */ + "Wrong number of columns for an rtree table", /* 1 */ + "Too few columns for an rtree table", /* 2 */ +- "Too many columns for an rtree table" /* 3 */ ++ "Too many columns for an rtree table", /* 3 */ ++ "Auxiliary rtree columns must be last" /* 4 */ + }; + +- int iErr = (argc<6) ? 2 : argc>(RTREE_MAX_DIMENSIONS*2+4) ? 3 : argc%2; +- if( aErrMsg[iErr] ){ +- *pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]); ++ assert( RTREE_MAX_AUX_COLUMN<256 ); /* Aux columns counted by a u8 */ ++ if( argc>RTREE_MAX_AUX_COLUMN+3 ){ ++ *pzErr = sqlite3_mprintf("%s", aErrMsg[3]); + return SQLITE_ERROR; + } + +@@ -168730,53 +182748,73 @@ + pRtree->base.pModule = &rtreeModule; + pRtree->zDb = (char *)&pRtree[1]; + pRtree->zName = &pRtree->zDb[nDb+1]; +- pRtree->nDim = (u8)((argc-4)/2); +- pRtree->nDim2 = pRtree->nDim*2; +- pRtree->nBytesPerCell = 8 + pRtree->nDim2*4; + pRtree->eCoordType = (u8)eCoordType; + memcpy(pRtree->zDb, argv[1], nDb); + memcpy(pRtree->zName, argv[2], nName); + +- /* Figure out the node size to use. */ +- rc = getNodeSize(db, pRtree, isCreate, pzErr); + + /* Create/Connect to the underlying relational database schema. If + ** that is successful, call sqlite3_declare_vtab() to configure + ** the r-tree table schema. + */ +- if( rc==SQLITE_OK ){ +- if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){ +- *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); ++ pSql = sqlite3_str_new(db); ++ sqlite3_str_appendf(pSql, "CREATE TABLE x(%s", argv[3]); ++ for(ii=4; ii<argc; ii++){ ++ if( argv[ii][0]=='+' ){ ++ pRtree->nAux++; ++ sqlite3_str_appendf(pSql, ",%s", argv[ii]+1); ++ }else if( pRtree->nAux>0 ){ ++ break; + }else{ +- char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]); +- char *zTmp; +- int ii; +- for(ii=4; zSql && ii<argc; ii++){ +- zTmp = zSql; +- zSql = sqlite3_mprintf("%s, %s", zTmp, argv[ii]); +- sqlite3_free(zTmp); +- } +- if( zSql ){ +- zTmp = zSql; +- zSql = sqlite3_mprintf("%s);", zTmp); +- sqlite3_free(zTmp); +- } +- if( !zSql ){ +- rc = SQLITE_NOMEM; +- }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){ +- *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); +- } +- sqlite3_free(zSql); ++ pRtree->nDim2++; ++ sqlite3_str_appendf(pSql, ",%s", argv[ii]); + } + } +- +- if( rc==SQLITE_OK ){ +- *ppVtab = (sqlite3_vtab *)pRtree; ++ sqlite3_str_appendf(pSql, ");"); ++ zSql = sqlite3_str_finish(pSql); ++ if( !zSql ){ ++ rc = SQLITE_NOMEM; ++ }else if( ii<argc ){ ++ *pzErr = sqlite3_mprintf("%s", aErrMsg[4]); ++ rc = SQLITE_ERROR; ++ }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){ ++ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); ++ } ++ sqlite3_free(zSql); ++ if( rc ) goto rtreeInit_fail; ++ pRtree->nDim = pRtree->nDim2/2; ++ if( pRtree->nDim<1 ){ ++ iErr = 2; ++ }else if( pRtree->nDim2>RTREE_MAX_DIMENSIONS*2 ){ ++ iErr = 3; ++ }else if( pRtree->nDim2 % 2 ){ ++ iErr = 1; + }else{ +- assert( *ppVtab==0 ); +- assert( pRtree->nBusy==1 ); +- rtreeRelease(pRtree); ++ iErr = 0; + } ++ if( iErr ){ ++ *pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]); ++ goto rtreeInit_fail; ++ } ++ pRtree->nBytesPerCell = 8 + pRtree->nDim2*4; ++ ++ /* Figure out the node size to use. */ ++ rc = getNodeSize(db, pRtree, isCreate, pzErr); ++ if( rc ) goto rtreeInit_fail; ++ rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate); ++ if( rc ){ ++ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); ++ goto rtreeInit_fail; ++ } ++ ++ *ppVtab = (sqlite3_vtab *)pRtree; ++ return SQLITE_OK; ++ ++rtreeInit_fail: ++ if( rc==SQLITE_OK ) rc = SQLITE_ERROR; ++ assert( *ppVtab==0 ); ++ assert( pRtree->nBusy==1 ); ++ rtreeRelease(pRtree); + return rc; + } + +@@ -168865,6 +182903,2279 @@ + } + + /* ++** Context object passed between the various routines that make up the ++** implementation of integrity-check function rtreecheck(). ++*/ ++typedef struct RtreeCheck RtreeCheck; ++struct RtreeCheck { ++ sqlite3 *db; /* Database handle */ ++ const char *zDb; /* Database containing rtree table */ ++ const char *zTab; /* Name of rtree table */ ++ int bInt; /* True for rtree_i32 table */ ++ int nDim; /* Number of dimensions for this rtree tbl */ ++ sqlite3_stmt *pGetNode; /* Statement used to retrieve nodes */ ++ sqlite3_stmt *aCheckMapping[2]; /* Statements to query %_parent/%_rowid */ ++ int nLeaf; /* Number of leaf cells in table */ ++ int nNonLeaf; /* Number of non-leaf cells in table */ ++ int rc; /* Return code */ ++ char *zReport; /* Message to report */ ++ int nErr; /* Number of lines in zReport */ ++}; ++ ++#define RTREE_CHECK_MAX_ERROR 100 ++ ++/* ++** Reset SQL statement pStmt. If the sqlite3_reset() call returns an error, ++** and RtreeCheck.rc==SQLITE_OK, set RtreeCheck.rc to the error code. ++*/ ++static void rtreeCheckReset(RtreeCheck *pCheck, sqlite3_stmt *pStmt){ ++ int rc = sqlite3_reset(pStmt); ++ if( pCheck->rc==SQLITE_OK ) pCheck->rc = rc; ++} ++ ++/* ++** The second and subsequent arguments to this function are a format string ++** and printf style arguments. This function formats the string and attempts ++** to compile it as an SQL statement. ++** ++** If successful, a pointer to the new SQL statement is returned. Otherwise, ++** NULL is returned and an error code left in RtreeCheck.rc. ++*/ ++static sqlite3_stmt *rtreeCheckPrepare( ++ RtreeCheck *pCheck, /* RtreeCheck object */ ++ const char *zFmt, ... /* Format string and trailing args */ ++){ ++ va_list ap; ++ char *z; ++ sqlite3_stmt *pRet = 0; ++ ++ va_start(ap, zFmt); ++ z = sqlite3_vmprintf(zFmt, ap); ++ ++ if( pCheck->rc==SQLITE_OK ){ ++ if( z==0 ){ ++ pCheck->rc = SQLITE_NOMEM; ++ }else{ ++ pCheck->rc = sqlite3_prepare_v2(pCheck->db, z, -1, &pRet, 0); ++ } ++ } ++ ++ sqlite3_free(z); ++ va_end(ap); ++ return pRet; ++} ++ ++/* ++** The second and subsequent arguments to this function are a printf() ++** style format string and arguments. This function formats the string and ++** appends it to the report being accumuated in pCheck. ++*/ ++static void rtreeCheckAppendMsg(RtreeCheck *pCheck, const char *zFmt, ...){ ++ va_list ap; ++ va_start(ap, zFmt); ++ if( pCheck->rc==SQLITE_OK && pCheck->nErr<RTREE_CHECK_MAX_ERROR ){ ++ char *z = sqlite3_vmprintf(zFmt, ap); ++ if( z==0 ){ ++ pCheck->rc = SQLITE_NOMEM; ++ }else{ ++ pCheck->zReport = sqlite3_mprintf("%z%s%z", ++ pCheck->zReport, (pCheck->zReport ? "\n" : ""), z ++ ); ++ if( pCheck->zReport==0 ){ ++ pCheck->rc = SQLITE_NOMEM; ++ } ++ } ++ pCheck->nErr++; ++ } ++ va_end(ap); ++} ++ ++/* ++** This function is a no-op if there is already an error code stored ++** in the RtreeCheck object indicated by the first argument. NULL is ++** returned in this case. ++** ++** Otherwise, the contents of rtree table node iNode are loaded from ++** the database and copied into a buffer obtained from sqlite3_malloc(). ++** If no error occurs, a pointer to the buffer is returned and (*pnNode) ++** is set to the size of the buffer in bytes. ++** ++** Or, if an error does occur, NULL is returned and an error code left ++** in the RtreeCheck object. The final value of *pnNode is undefined in ++** this case. ++*/ ++static u8 *rtreeCheckGetNode(RtreeCheck *pCheck, i64 iNode, int *pnNode){ ++ u8 *pRet = 0; /* Return value */ ++ ++ assert( pCheck->rc==SQLITE_OK ); ++ if( pCheck->pGetNode==0 ){ ++ pCheck->pGetNode = rtreeCheckPrepare(pCheck, ++ "SELECT data FROM %Q.'%q_node' WHERE nodeno=?", ++ pCheck->zDb, pCheck->zTab ++ ); ++ } ++ ++ if( pCheck->rc==SQLITE_OK ){ ++ sqlite3_bind_int64(pCheck->pGetNode, 1, iNode); ++ if( sqlite3_step(pCheck->pGetNode)==SQLITE_ROW ){ ++ int nNode = sqlite3_column_bytes(pCheck->pGetNode, 0); ++ const u8 *pNode = (const u8*)sqlite3_column_blob(pCheck->pGetNode, 0); ++ pRet = sqlite3_malloc(nNode); ++ if( pRet==0 ){ ++ pCheck->rc = SQLITE_NOMEM; ++ }else{ ++ memcpy(pRet, pNode, nNode); ++ *pnNode = nNode; ++ } ++ } ++ rtreeCheckReset(pCheck, pCheck->pGetNode); ++ if( pCheck->rc==SQLITE_OK && pRet==0 ){ ++ rtreeCheckAppendMsg(pCheck, "Node %lld missing from database", iNode); ++ } ++ } ++ ++ return pRet; ++} ++ ++/* ++** This function is used to check that the %_parent (if bLeaf==0) or %_rowid ++** (if bLeaf==1) table contains a specified entry. The schemas of the ++** two tables are: ++** ++** CREATE TABLE %_parent(nodeno INTEGER PRIMARY KEY, parentnode INTEGER) ++** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER, ...) ++** ++** In both cases, this function checks that there exists an entry with ++** IPK value iKey and the second column set to iVal. ++** ++*/ ++static void rtreeCheckMapping( ++ RtreeCheck *pCheck, /* RtreeCheck object */ ++ int bLeaf, /* True for a leaf cell, false for interior */ ++ i64 iKey, /* Key for mapping */ ++ i64 iVal /* Expected value for mapping */ ++){ ++ int rc; ++ sqlite3_stmt *pStmt; ++ const char *azSql[2] = { ++ "SELECT parentnode FROM %Q.'%q_parent' WHERE nodeno=?1", ++ "SELECT nodeno FROM %Q.'%q_rowid' WHERE rowid=?1" ++ }; ++ ++ assert( bLeaf==0 || bLeaf==1 ); ++ if( pCheck->aCheckMapping[bLeaf]==0 ){ ++ pCheck->aCheckMapping[bLeaf] = rtreeCheckPrepare(pCheck, ++ azSql[bLeaf], pCheck->zDb, pCheck->zTab ++ ); ++ } ++ if( pCheck->rc!=SQLITE_OK ) return; ++ ++ pStmt = pCheck->aCheckMapping[bLeaf]; ++ sqlite3_bind_int64(pStmt, 1, iKey); ++ rc = sqlite3_step(pStmt); ++ if( rc==SQLITE_DONE ){ ++ rtreeCheckAppendMsg(pCheck, "Mapping (%lld -> %lld) missing from %s table", ++ iKey, iVal, (bLeaf ? "%_rowid" : "%_parent") ++ ); ++ }else if( rc==SQLITE_ROW ){ ++ i64 ii = sqlite3_column_int64(pStmt, 0); ++ if( ii!=iVal ){ ++ rtreeCheckAppendMsg(pCheck, ++ "Found (%lld -> %lld) in %s table, expected (%lld -> %lld)", ++ iKey, ii, (bLeaf ? "%_rowid" : "%_parent"), iKey, iVal ++ ); ++ } ++ } ++ rtreeCheckReset(pCheck, pStmt); ++} ++ ++/* ++** Argument pCell points to an array of coordinates stored on an rtree page. ++** This function checks that the coordinates are internally consistent (no ++** x1>x2 conditions) and adds an error message to the RtreeCheck object ++** if they are not. ++** ++** Additionally, if pParent is not NULL, then it is assumed to point to ++** the array of coordinates on the parent page that bound the page ++** containing pCell. In this case it is also verified that the two ++** sets of coordinates are mutually consistent and an error message added ++** to the RtreeCheck object if they are not. ++*/ ++static void rtreeCheckCellCoord( ++ RtreeCheck *pCheck, ++ i64 iNode, /* Node id to use in error messages */ ++ int iCell, /* Cell number to use in error messages */ ++ u8 *pCell, /* Pointer to cell coordinates */ ++ u8 *pParent /* Pointer to parent coordinates */ ++){ ++ RtreeCoord c1, c2; ++ RtreeCoord p1, p2; ++ int i; ++ ++ for(i=0; i<pCheck->nDim; i++){ ++ readCoord(&pCell[4*2*i], &c1); ++ readCoord(&pCell[4*(2*i + 1)], &c2); ++ ++ /* printf("%e, %e\n", c1.u.f, c2.u.f); */ ++ if( pCheck->bInt ? c1.i>c2.i : c1.f>c2.f ){ ++ rtreeCheckAppendMsg(pCheck, ++ "Dimension %d of cell %d on node %lld is corrupt", i, iCell, iNode ++ ); ++ } ++ ++ if( pParent ){ ++ readCoord(&pParent[4*2*i], &p1); ++ readCoord(&pParent[4*(2*i + 1)], &p2); ++ ++ if( (pCheck->bInt ? c1.i<p1.i : c1.f<p1.f) ++ || (pCheck->bInt ? c2.i>p2.i : c2.f>p2.f) ++ ){ ++ rtreeCheckAppendMsg(pCheck, ++ "Dimension %d of cell %d on node %lld is corrupt relative to parent" ++ , i, iCell, iNode ++ ); ++ } ++ } ++ } ++} ++ ++/* ++** Run rtreecheck() checks on node iNode, which is at depth iDepth within ++** the r-tree structure. Argument aParent points to the array of coordinates ++** that bound node iNode on the parent node. ++** ++** If any problems are discovered, an error message is appended to the ++** report accumulated in the RtreeCheck object. ++*/ ++static void rtreeCheckNode( ++ RtreeCheck *pCheck, ++ int iDepth, /* Depth of iNode (0==leaf) */ ++ u8 *aParent, /* Buffer containing parent coords */ ++ i64 iNode /* Node to check */ ++){ ++ u8 *aNode = 0; ++ int nNode = 0; ++ ++ assert( iNode==1 || aParent!=0 ); ++ assert( pCheck->nDim>0 ); ++ ++ aNode = rtreeCheckGetNode(pCheck, iNode, &nNode); ++ if( aNode ){ ++ if( nNode<4 ){ ++ rtreeCheckAppendMsg(pCheck, ++ "Node %lld is too small (%d bytes)", iNode, nNode ++ ); ++ }else{ ++ int nCell; /* Number of cells on page */ ++ int i; /* Used to iterate through cells */ ++ if( aParent==0 ){ ++ iDepth = readInt16(aNode); ++ if( iDepth>RTREE_MAX_DEPTH ){ ++ rtreeCheckAppendMsg(pCheck, "Rtree depth out of range (%d)", iDepth); ++ sqlite3_free(aNode); ++ return; ++ } ++ } ++ nCell = readInt16(&aNode[2]); ++ if( (4 + nCell*(8 + pCheck->nDim*2*4))>nNode ){ ++ rtreeCheckAppendMsg(pCheck, ++ "Node %lld is too small for cell count of %d (%d bytes)", ++ iNode, nCell, nNode ++ ); ++ }else{ ++ for(i=0; i<nCell; i++){ ++ u8 *pCell = &aNode[4 + i*(8 + pCheck->nDim*2*4)]; ++ i64 iVal = readInt64(pCell); ++ rtreeCheckCellCoord(pCheck, iNode, i, &pCell[8], aParent); ++ ++ if( iDepth>0 ){ ++ rtreeCheckMapping(pCheck, 0, iVal, iNode); ++ rtreeCheckNode(pCheck, iDepth-1, &pCell[8], iVal); ++ pCheck->nNonLeaf++; ++ }else{ ++ rtreeCheckMapping(pCheck, 1, iVal, iNode); ++ pCheck->nLeaf++; ++ } ++ } ++ } ++ } ++ sqlite3_free(aNode); ++ } ++} ++ ++/* ++** The second argument to this function must be either "_rowid" or ++** "_parent". This function checks that the number of entries in the ++** %_rowid or %_parent table is exactly nExpect. If not, it adds ++** an error message to the report in the RtreeCheck object indicated ++** by the first argument. ++*/ ++static void rtreeCheckCount(RtreeCheck *pCheck, const char *zTbl, i64 nExpect){ ++ if( pCheck->rc==SQLITE_OK ){ ++ sqlite3_stmt *pCount; ++ pCount = rtreeCheckPrepare(pCheck, "SELECT count(*) FROM %Q.'%q%s'", ++ pCheck->zDb, pCheck->zTab, zTbl ++ ); ++ if( pCount ){ ++ if( sqlite3_step(pCount)==SQLITE_ROW ){ ++ i64 nActual = sqlite3_column_int64(pCount, 0); ++ if( nActual!=nExpect ){ ++ rtreeCheckAppendMsg(pCheck, "Wrong number of entries in %%%s table" ++ " - expected %lld, actual %lld" , zTbl, nExpect, nActual ++ ); ++ } ++ } ++ pCheck->rc = sqlite3_finalize(pCount); ++ } ++ } ++} ++ ++/* ++** This function does the bulk of the work for the rtree integrity-check. ++** It is called by rtreecheck(), which is the SQL function implementation. ++*/ ++static int rtreeCheckTable( ++ sqlite3 *db, /* Database handle to access db through */ ++ const char *zDb, /* Name of db ("main", "temp" etc.) */ ++ const char *zTab, /* Name of rtree table to check */ ++ char **pzReport /* OUT: sqlite3_malloc'd report text */ ++){ ++ RtreeCheck check; /* Common context for various routines */ ++ sqlite3_stmt *pStmt = 0; /* Used to find column count of rtree table */ ++ int bEnd = 0; /* True if transaction should be closed */ ++ int nAux = 0; /* Number of extra columns. */ ++ ++ /* Initialize the context object */ ++ memset(&check, 0, sizeof(check)); ++ check.db = db; ++ check.zDb = zDb; ++ check.zTab = zTab; ++ ++ /* If there is not already an open transaction, open one now. This is ++ ** to ensure that the queries run as part of this integrity-check operate ++ ** on a consistent snapshot. */ ++ if( sqlite3_get_autocommit(db) ){ ++ check.rc = sqlite3_exec(db, "BEGIN", 0, 0, 0); ++ bEnd = 1; ++ } ++ ++ /* Find the number of auxiliary columns */ ++ if( check.rc==SQLITE_OK ){ ++ pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.'%q_rowid'", zDb, zTab); ++ if( pStmt ){ ++ nAux = sqlite3_column_count(pStmt) - 2; ++ sqlite3_finalize(pStmt); ++ } ++ check.rc = SQLITE_OK; ++ } ++ ++ /* Find number of dimensions in the rtree table. */ ++ pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.%Q", zDb, zTab); ++ if( pStmt ){ ++ int rc; ++ check.nDim = (sqlite3_column_count(pStmt) - 1 - nAux) / 2; ++ if( check.nDim<1 ){ ++ rtreeCheckAppendMsg(&check, "Schema corrupt or not an rtree"); ++ }else if( SQLITE_ROW==sqlite3_step(pStmt) ){ ++ check.bInt = (sqlite3_column_type(pStmt, 1)==SQLITE_INTEGER); ++ } ++ rc = sqlite3_finalize(pStmt); ++ if( rc!=SQLITE_CORRUPT ) check.rc = rc; ++ } ++ ++ /* Do the actual integrity-check */ ++ if( check.nDim>=1 ){ ++ if( check.rc==SQLITE_OK ){ ++ rtreeCheckNode(&check, 0, 0, 1); ++ } ++ rtreeCheckCount(&check, "_rowid", check.nLeaf); ++ rtreeCheckCount(&check, "_parent", check.nNonLeaf); ++ } ++ ++ /* Finalize SQL statements used by the integrity-check */ ++ sqlite3_finalize(check.pGetNode); ++ sqlite3_finalize(check.aCheckMapping[0]); ++ sqlite3_finalize(check.aCheckMapping[1]); ++ ++ /* If one was opened, close the transaction */ ++ if( bEnd ){ ++ int rc = sqlite3_exec(db, "END", 0, 0, 0); ++ if( check.rc==SQLITE_OK ) check.rc = rc; ++ } ++ *pzReport = check.zReport; ++ return check.rc; ++} ++ ++/* ++** Usage: ++** ++** rtreecheck(<rtree-table>); ++** rtreecheck(<database>, <rtree-table>); ++** ++** Invoking this SQL function runs an integrity-check on the named rtree ++** table. The integrity-check verifies the following: ++** ++** 1. For each cell in the r-tree structure (%_node table), that: ++** ++** a) for each dimension, (coord1 <= coord2). ++** ++** b) unless the cell is on the root node, that the cell is bounded ++** by the parent cell on the parent node. ++** ++** c) for leaf nodes, that there is an entry in the %_rowid ++** table corresponding to the cell's rowid value that ++** points to the correct node. ++** ++** d) for cells on non-leaf nodes, that there is an entry in the ++** %_parent table mapping from the cell's child node to the ++** node that it resides on. ++** ++** 2. That there are the same number of entries in the %_rowid table ++** as there are leaf cells in the r-tree structure, and that there ++** is a leaf cell that corresponds to each entry in the %_rowid table. ++** ++** 3. That there are the same number of entries in the %_parent table ++** as there are non-leaf cells in the r-tree structure, and that ++** there is a non-leaf cell that corresponds to each entry in the ++** %_parent table. ++*/ ++static void rtreecheck( ++ sqlite3_context *ctx, ++ int nArg, ++ sqlite3_value **apArg ++){ ++ if( nArg!=1 && nArg!=2 ){ ++ sqlite3_result_error(ctx, ++ "wrong number of arguments to function rtreecheck()", -1 ++ ); ++ }else{ ++ int rc; ++ char *zReport = 0; ++ const char *zDb = (const char*)sqlite3_value_text(apArg[0]); ++ const char *zTab; ++ if( nArg==1 ){ ++ zTab = zDb; ++ zDb = "main"; ++ }else{ ++ zTab = (const char*)sqlite3_value_text(apArg[1]); ++ } ++ rc = rtreeCheckTable(sqlite3_context_db_handle(ctx), zDb, zTab, &zReport); ++ if( rc==SQLITE_OK ){ ++ sqlite3_result_text(ctx, zReport ? zReport : "ok", -1, SQLITE_TRANSIENT); ++ }else{ ++ sqlite3_result_error_code(ctx, rc); ++ } ++ sqlite3_free(zReport); ++ } ++} ++ ++/* Conditionally include the geopoly code */ ++#ifdef SQLITE_ENABLE_GEOPOLY ++/************** Include geopoly.c in the middle of rtree.c *******************/ ++/************** Begin file geopoly.c *****************************************/ ++/* ++** 2018-05-25 ++** ++** The author disclaims copyright to this source code. In place of ++** a legal notice, here is a blessing: ++** ++** May you do good and not evil. ++** May you find forgiveness for yourself and forgive others. ++** May you share freely, never taking more than you give. ++** ++****************************************************************************** ++** ++** This file implements an alternative R-Tree virtual table that ++** uses polygons to express the boundaries of 2-dimensional objects. ++** ++** This file is #include-ed onto the end of "rtree.c" so that it has ++** access to all of the R-Tree internals. ++*/ ++/* #include <stdlib.h> */ ++ ++/* Enable -DGEOPOLY_ENABLE_DEBUG for debugging facilities */ ++#ifdef GEOPOLY_ENABLE_DEBUG ++ static int geo_debug = 0; ++# define GEODEBUG(X) if(geo_debug)printf X ++#else ++# define GEODEBUG(X) ++#endif ++ ++#ifndef JSON_NULL /* The following stuff repeats things found in json1 */ ++/* ++** Versions of isspace(), isalnum() and isdigit() to which it is safe ++** to pass signed char values. ++*/ ++#ifdef sqlite3Isdigit ++ /* Use the SQLite core versions if this routine is part of the ++ ** SQLite amalgamation */ ++# define safe_isdigit(x) sqlite3Isdigit(x) ++# define safe_isalnum(x) sqlite3Isalnum(x) ++# define safe_isxdigit(x) sqlite3Isxdigit(x) ++#else ++ /* Use the standard library for separate compilation */ ++#include <ctype.h> /* amalgamator: keep */ ++# define safe_isdigit(x) isdigit((unsigned char)(x)) ++# define safe_isalnum(x) isalnum((unsigned char)(x)) ++# define safe_isxdigit(x) isxdigit((unsigned char)(x)) ++#endif ++ ++/* ++** Growing our own isspace() routine this way is twice as fast as ++** the library isspace() function. ++*/ ++static const char geopolyIsSpace[] = { ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++}; ++#define safe_isspace(x) (geopolyIsSpace[(unsigned char)x]) ++#endif /* JSON NULL - back to original code */ ++ ++/* Compiler and version */ ++#ifndef GCC_VERSION ++#if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC) ++# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__) ++#else ++# define GCC_VERSION 0 ++#endif ++#endif ++#ifndef MSVC_VERSION ++#if defined(_MSC_VER) && !defined(SQLITE_DISABLE_INTRINSIC) ++# define MSVC_VERSION _MSC_VER ++#else ++# define MSVC_VERSION 0 ++#endif ++#endif ++ ++/* Datatype for coordinates ++*/ ++typedef float GeoCoord; ++ ++/* ++** Internal representation of a polygon. ++** ++** The polygon consists of a sequence of vertexes. There is a line ++** segment between each pair of vertexes, and one final segment from ++** the last vertex back to the first. (This differs from the GeoJSON ++** standard in which the final vertex is a repeat of the first.) ++** ++** The polygon follows the right-hand rule. The area to the right of ++** each segment is "outside" and the area to the left is "inside". ++** ++** The on-disk representation consists of a 4-byte header followed by ++** the values. The 4-byte header is: ++** ++** encoding (1 byte) 0=big-endian, 1=little-endian ++** nvertex (3 bytes) Number of vertexes as a big-endian integer ++** ++** Enough space is allocated for 4 coordinates, to work around over-zealous ++** warnings coming from some compiler (notably, clang). In reality, the size ++** of each GeoPoly memory allocate is adjusted as necessary so that the ++** GeoPoly.a[] array at the end is the appropriate size. ++*/ ++typedef struct GeoPoly GeoPoly; ++struct GeoPoly { ++ int nVertex; /* Number of vertexes */ ++ unsigned char hdr[4]; /* Header for on-disk representation */ ++ GeoCoord a[8]; /* 2*nVertex values. X (longitude) first, then Y */ ++}; ++ ++/* The size of a memory allocation needed for a GeoPoly object sufficient ++** to hold N coordinate pairs. ++*/ ++#define GEOPOLY_SZ(N) (sizeof(GeoPoly) + sizeof(GeoCoord)*2*((N)-4)) ++ ++/* ++** State of a parse of a GeoJSON input. ++*/ ++typedef struct GeoParse GeoParse; ++struct GeoParse { ++ const unsigned char *z; /* Unparsed input */ ++ int nVertex; /* Number of vertexes in a[] */ ++ int nAlloc; /* Space allocated to a[] */ ++ int nErr; /* Number of errors encountered */ ++ GeoCoord *a; /* Array of vertexes. From sqlite3_malloc64() */ ++}; ++ ++/* Do a 4-byte byte swap */ ++static void geopolySwab32(unsigned char *a){ ++ unsigned char t = a[0]; ++ a[0] = a[3]; ++ a[3] = t; ++ t = a[1]; ++ a[1] = a[2]; ++ a[2] = t; ++} ++ ++/* Skip whitespace. Return the next non-whitespace character. */ ++static char geopolySkipSpace(GeoParse *p){ ++ while( safe_isspace(p->z[0]) ) p->z++; ++ return p->z[0]; ++} ++ ++/* Parse out a number. Write the value into *pVal if pVal!=0. ++** return non-zero on success and zero if the next token is not a number. ++*/ ++static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){ ++ char c = geopolySkipSpace(p); ++ const unsigned char *z = p->z; ++ int j = 0; ++ int seenDP = 0; ++ int seenE = 0; ++ if( c=='-' ){ ++ j = 1; ++ c = z[j]; ++ } ++ if( c=='0' && z[j+1]>='0' && z[j+1]<='9' ) return 0; ++ for(;; j++){ ++ c = z[j]; ++ if( safe_isdigit(c) ) continue; ++ if( c=='.' ){ ++ if( z[j-1]=='-' ) return 0; ++ if( seenDP ) return 0; ++ seenDP = 1; ++ continue; ++ } ++ if( c=='e' || c=='E' ){ ++ if( z[j-1]<'0' ) return 0; ++ 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 0; ++ continue; ++ } ++ break; ++ } ++ if( z[j-1]<'0' ) return 0; ++ if( pVal ){ ++#ifdef SQLITE_AMALGAMATION ++ /* The sqlite3AtoF() routine is much much faster than atof(), if it ++ ** is available */ ++ double r; ++ (void)sqlite3AtoF((const char*)p->z, &r, j, SQLITE_UTF8); ++ *pVal = r; ++#else ++ *pVal = (GeoCoord)atof((const char*)p->z); ++#endif ++ } ++ p->z += j; ++ return 1; ++} ++ ++/* ++** If the input is a well-formed JSON array of coordinates with at least ++** four coordinates and where each coordinate is itself a two-value array, ++** then convert the JSON into a GeoPoly object and return a pointer to ++** that object. ++** ++** If any error occurs, return NULL. ++*/ ++static GeoPoly *geopolyParseJson(const unsigned char *z, int *pRc){ ++ GeoParse s; ++ int rc = SQLITE_OK; ++ memset(&s, 0, sizeof(s)); ++ s.z = z; ++ if( geopolySkipSpace(&s)=='[' ){ ++ s.z++; ++ while( geopolySkipSpace(&s)=='[' ){ ++ int ii = 0; ++ char c; ++ s.z++; ++ if( s.nVertex>=s.nAlloc ){ ++ GeoCoord *aNew; ++ s.nAlloc = s.nAlloc*2 + 16; ++ aNew = sqlite3_realloc64(s.a, s.nAlloc*sizeof(GeoCoord)*2 ); ++ if( aNew==0 ){ ++ rc = SQLITE_NOMEM; ++ s.nErr++; ++ break; ++ } ++ s.a = aNew; ++ } ++ while( geopolyParseNumber(&s, ii<=1 ? &s.a[s.nVertex*2+ii] : 0) ){ ++ ii++; ++ if( ii==2 ) s.nVertex++; ++ c = geopolySkipSpace(&s); ++ s.z++; ++ if( c==',' ) continue; ++ if( c==']' && ii>=2 ) break; ++ s.nErr++; ++ rc = SQLITE_ERROR; ++ goto parse_json_err; ++ } ++ if( geopolySkipSpace(&s)==',' ){ ++ s.z++; ++ continue; ++ } ++ break; ++ } ++ if( geopolySkipSpace(&s)==']' ++ && s.nVertex>=4 ++ && s.a[0]==s.a[s.nVertex*2-2] ++ && s.a[1]==s.a[s.nVertex*2-1] ++ && (s.z++, geopolySkipSpace(&s)==0) ++ ){ ++ GeoPoly *pOut; ++ int x = 1; ++ s.nVertex--; /* Remove the redundant vertex at the end */ ++ pOut = sqlite3_malloc64( GEOPOLY_SZ(s.nVertex) ); ++ x = 1; ++ if( pOut==0 ) goto parse_json_err; ++ pOut->nVertex = s.nVertex; ++ memcpy(pOut->a, s.a, s.nVertex*2*sizeof(GeoCoord)); ++ pOut->hdr[0] = *(unsigned char*)&x; ++ pOut->hdr[1] = (s.nVertex>>16)&0xff; ++ pOut->hdr[2] = (s.nVertex>>8)&0xff; ++ pOut->hdr[3] = s.nVertex&0xff; ++ sqlite3_free(s.a); ++ if( pRc ) *pRc = SQLITE_OK; ++ return pOut; ++ }else{ ++ s.nErr++; ++ rc = SQLITE_ERROR; ++ } ++ } ++parse_json_err: ++ if( pRc ) *pRc = rc; ++ sqlite3_free(s.a); ++ return 0; ++} ++ ++/* ++** Given a function parameter, try to interpret it as a polygon, either ++** in the binary format or JSON text. Compute a GeoPoly object and ++** return a pointer to that object. Or if the input is not a well-formed ++** polygon, put an error message in sqlite3_context and return NULL. ++*/ ++static GeoPoly *geopolyFuncParam( ++ sqlite3_context *pCtx, /* Context for error messages */ ++ sqlite3_value *pVal, /* The value to decode */ ++ int *pRc /* Write error here */ ++){ ++ GeoPoly *p = 0; ++ int nByte; ++ if( sqlite3_value_type(pVal)==SQLITE_BLOB ++ && (nByte = sqlite3_value_bytes(pVal))>=(4+6*sizeof(GeoCoord)) ++ ){ ++ const unsigned char *a = sqlite3_value_blob(pVal); ++ int nVertex; ++ nVertex = (a[1]<<16) + (a[2]<<8) + a[3]; ++ if( (a[0]==0 || a[0]==1) ++ && (nVertex*2*sizeof(GeoCoord) + 4)==(unsigned int)nByte ++ ){ ++ p = sqlite3_malloc64( sizeof(*p) + (nVertex-1)*2*sizeof(GeoCoord) ); ++ if( p==0 ){ ++ if( pRc ) *pRc = SQLITE_NOMEM; ++ if( pCtx ) sqlite3_result_error_nomem(pCtx); ++ }else{ ++ int x = 1; ++ p->nVertex = nVertex; ++ memcpy(p->hdr, a, nByte); ++ if( a[0] != *(unsigned char*)&x ){ ++ int ii; ++ for(ii=0; ii<nVertex*2; ii++){ ++ geopolySwab32((unsigned char*)&p->a[ii]); ++ } ++ p->hdr[0] ^= 1; ++ } ++ } ++ } ++ if( pRc ) *pRc = SQLITE_OK; ++ return p; ++ }else if( sqlite3_value_type(pVal)==SQLITE_TEXT ){ ++ const unsigned char *zJson = sqlite3_value_text(pVal); ++ if( zJson==0 ){ ++ if( pRc ) *pRc = SQLITE_NOMEM; ++ return 0; ++ } ++ return geopolyParseJson(zJson, pRc); ++ }else{ ++ if( pRc ) *pRc = SQLITE_ERROR; ++ return 0; ++ } ++} ++ ++/* ++** Implementation of the geopoly_blob(X) function. ++** ++** If the input is a well-formed Geopoly BLOB or JSON string ++** then return the BLOB representation of the polygon. Otherwise ++** return NULL. ++*/ ++static void geopolyBlobFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ GeoPoly *p = geopolyFuncParam(context, argv[0], 0); ++ if( p ){ ++ sqlite3_result_blob(context, p->hdr, ++ 4+8*p->nVertex, SQLITE_TRANSIENT); ++ sqlite3_free(p); ++ } ++} ++ ++/* ++** SQL function: geopoly_json(X) ++** ++** Interpret X as a polygon and render it as a JSON array ++** of coordinates. Or, if X is not a valid polygon, return NULL. ++*/ ++static void geopolyJsonFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ GeoPoly *p = geopolyFuncParam(context, argv[0], 0); ++ if( p ){ ++ sqlite3 *db = sqlite3_context_db_handle(context); ++ sqlite3_str *x = sqlite3_str_new(db); ++ int i; ++ sqlite3_str_append(x, "[", 1); ++ for(i=0; i<p->nVertex; i++){ ++ sqlite3_str_appendf(x, "[%!g,%!g],", p->a[i*2], p->a[i*2+1]); ++ } ++ sqlite3_str_appendf(x, "[%!g,%!g]]", p->a[0], p->a[1]); ++ sqlite3_result_text(context, sqlite3_str_finish(x), -1, sqlite3_free); ++ sqlite3_free(p); ++ } ++} ++ ++/* ++** SQL function: geopoly_svg(X, ....) ++** ++** Interpret X as a polygon and render it as a SVG <polyline>. ++** Additional arguments are added as attributes to the <polyline>. ++*/ ++static void geopolySvgFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ GeoPoly *p = geopolyFuncParam(context, argv[0], 0); ++ if( p ){ ++ sqlite3 *db = sqlite3_context_db_handle(context); ++ sqlite3_str *x = sqlite3_str_new(db); ++ int i; ++ char cSep = '\''; ++ sqlite3_str_appendf(x, "<polyline points="); ++ for(i=0; i<p->nVertex; i++){ ++ sqlite3_str_appendf(x, "%c%g,%g", cSep, p->a[i*2], p->a[i*2+1]); ++ cSep = ' '; ++ } ++ sqlite3_str_appendf(x, " %g,%g'", p->a[0], p->a[1]); ++ for(i=1; i<argc; i++){ ++ const char *z = (const char*)sqlite3_value_text(argv[i]); ++ if( z && z[0] ){ ++ sqlite3_str_appendf(x, " %s", z); ++ } ++ } ++ sqlite3_str_appendf(x, "></polyline>"); ++ sqlite3_result_text(context, sqlite3_str_finish(x), -1, sqlite3_free); ++ sqlite3_free(p); ++ } ++} ++ ++/* ++** SQL Function: geopoly_xform(poly, A, B, C, D, E, F) ++** ++** Transform and/or translate a polygon as follows: ++** ++** x1 = A*x0 + B*y0 + E ++** y1 = C*x0 + D*y0 + F ++** ++** For a translation: ++** ++** geopoly_xform(poly, 1, 0, 0, 1, x-offset, y-offset) ++** ++** Rotate by R around the point (0,0): ++** ++** geopoly_xform(poly, cos(R), sin(R), -sin(R), cos(R), 0, 0) ++*/ ++static void geopolyXformFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ GeoPoly *p = geopolyFuncParam(context, argv[0], 0); ++ double A = sqlite3_value_double(argv[1]); ++ double B = sqlite3_value_double(argv[2]); ++ double C = sqlite3_value_double(argv[3]); ++ double D = sqlite3_value_double(argv[4]); ++ double E = sqlite3_value_double(argv[5]); ++ double F = sqlite3_value_double(argv[6]); ++ GeoCoord x1, y1, x0, y0; ++ int ii; ++ if( p ){ ++ for(ii=0; ii<p->nVertex; ii++){ ++ x0 = p->a[ii*2]; ++ y0 = p->a[ii*2+1]; ++ x1 = (GeoCoord)(A*x0 + B*y0 + E); ++ y1 = (GeoCoord)(C*x0 + D*y0 + F); ++ p->a[ii*2] = x1; ++ p->a[ii*2+1] = y1; ++ } ++ sqlite3_result_blob(context, p->hdr, ++ 4+8*p->nVertex, SQLITE_TRANSIENT); ++ sqlite3_free(p); ++ } ++} ++ ++/* ++** Compute the area enclosed by the polygon. ++** ++** This routine can also be used to detect polygons that rotate in ++** the wrong direction. Polygons are suppose to be counter-clockwise (CCW). ++** This routine returns a negative value for clockwise (CW) polygons. ++*/ ++static double geopolyArea(GeoPoly *p){ ++ double rArea = 0.0; ++ int ii; ++ for(ii=0; ii<p->nVertex-1; ii++){ ++ rArea += (p->a[ii*2] - p->a[ii*2+2]) /* (x0 - x1) */ ++ * (p->a[ii*2+1] + p->a[ii*2+3]) /* (y0 + y1) */ ++ * 0.5; ++ } ++ rArea += (p->a[ii*2] - p->a[0]) /* (xN - x0) */ ++ * (p->a[ii*2+1] + p->a[1]) /* (yN + y0) */ ++ * 0.5; ++ return rArea; ++} ++ ++/* ++** Implementation of the geopoly_area(X) function. ++** ++** If the input is a well-formed Geopoly BLOB then return the area ++** enclosed by the polygon. If the polygon circulates clockwise instead ++** of counterclockwise (as it should) then return the negative of the ++** enclosed area. Otherwise return NULL. ++*/ ++static void geopolyAreaFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ GeoPoly *p = geopolyFuncParam(context, argv[0], 0); ++ if( p ){ ++ sqlite3_result_double(context, geopolyArea(p)); ++ sqlite3_free(p); ++ } ++} ++ ++/* ++** Implementation of the geopoly_ccw(X) function. ++** ++** If the rotation of polygon X is clockwise (incorrect) instead of ++** counter-clockwise (the correct winding order according to RFC7946) ++** then reverse the order of the vertexes in polygon X. ++** ++** In other words, this routine returns a CCW polygon regardless of the ++** winding order of its input. ++** ++** Use this routine to sanitize historical inputs that that sometimes ++** contain polygons that wind in the wrong direction. ++*/ ++static void geopolyCcwFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ GeoPoly *p = geopolyFuncParam(context, argv[0], 0); ++ if( p ){ ++ if( geopolyArea(p)<0.0 ){ ++ int ii, jj; ++ for(ii=2, jj=p->nVertex*2 - 2; ii<jj; ii+=2, jj-=2){ ++ GeoCoord t = p->a[ii]; ++ p->a[ii] = p->a[jj]; ++ p->a[jj] = t; ++ t = p->a[ii+1]; ++ p->a[ii+1] = p->a[jj+1]; ++ p->a[jj+1] = t; ++ } ++ } ++ sqlite3_result_blob(context, p->hdr, ++ 4+8*p->nVertex, SQLITE_TRANSIENT); ++ sqlite3_free(p); ++ } ++} ++ ++#define GEOPOLY_PI 3.1415926535897932385 ++ ++/* Fast approximation for sine(X) for X between -0.5*pi and 2*pi ++*/ ++static double geopolySine(double r){ ++ assert( r>=-0.5*GEOPOLY_PI && r<=2.0*GEOPOLY_PI ); ++ if( r>=1.5*GEOPOLY_PI ){ ++ r -= 2.0*GEOPOLY_PI; ++ } ++ if( r>=0.5*GEOPOLY_PI ){ ++ return -geopolySine(r-GEOPOLY_PI); ++ }else{ ++ double r2 = r*r; ++ double r3 = r2*r; ++ double r5 = r3*r2; ++ return 0.9996949*r - 0.1656700*r3 + 0.0075134*r5; ++ } ++} ++ ++/* ++** Function: geopoly_regular(X,Y,R,N) ++** ++** Construct a simple, convex, regular polygon centered at X, Y ++** with circumradius R and with N sides. ++*/ ++static void geopolyRegularFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ double x = sqlite3_value_double(argv[0]); ++ double y = sqlite3_value_double(argv[1]); ++ double r = sqlite3_value_double(argv[2]); ++ int n = sqlite3_value_int(argv[3]); ++ int i; ++ GeoPoly *p; ++ ++ if( n<3 || r<=0.0 ) return; ++ if( n>1000 ) n = 1000; ++ p = sqlite3_malloc64( sizeof(*p) + (n-1)*2*sizeof(GeoCoord) ); ++ if( p==0 ){ ++ sqlite3_result_error_nomem(context); ++ return; ++ } ++ i = 1; ++ p->hdr[0] = *(unsigned char*)&i; ++ p->hdr[1] = 0; ++ p->hdr[2] = (n>>8)&0xff; ++ p->hdr[3] = n&0xff; ++ for(i=0; i<n; i++){ ++ double rAngle = 2.0*GEOPOLY_PI*i/n; ++ p->a[i*2] = x - r*geopolySine(rAngle-0.5*GEOPOLY_PI); ++ p->a[i*2+1] = y + r*geopolySine(rAngle); ++ } ++ sqlite3_result_blob(context, p->hdr, 4+8*n, SQLITE_TRANSIENT); ++ sqlite3_free(p); ++} ++ ++/* ++** If pPoly is a polygon, compute its bounding box. Then: ++** ++** (1) if aCoord!=0 store the bounding box in aCoord, returning NULL ++** (2) otherwise, compute a GeoPoly for the bounding box and return the ++** new GeoPoly ++** ++** If pPoly is NULL but aCoord is not NULL, then compute a new GeoPoly from ++** the bounding box in aCoord and return a pointer to that GeoPoly. ++*/ ++static GeoPoly *geopolyBBox( ++ sqlite3_context *context, /* For recording the error */ ++ sqlite3_value *pPoly, /* The polygon */ ++ RtreeCoord *aCoord, /* Results here */ ++ int *pRc /* Error code here */ ++){ ++ GeoPoly *pOut = 0; ++ GeoPoly *p; ++ float mnX, mxX, mnY, mxY; ++ if( pPoly==0 && aCoord!=0 ){ ++ p = 0; ++ mnX = aCoord[0].f; ++ mxX = aCoord[1].f; ++ mnY = aCoord[2].f; ++ mxY = aCoord[3].f; ++ goto geopolyBboxFill; ++ }else{ ++ p = geopolyFuncParam(context, pPoly, pRc); ++ } ++ if( p ){ ++ int ii; ++ mnX = mxX = p->a[0]; ++ mnY = mxY = p->a[1]; ++ for(ii=1; ii<p->nVertex; ii++){ ++ double r = p->a[ii*2]; ++ if( r<mnX ) mnX = (float)r; ++ else if( r>mxX ) mxX = (float)r; ++ r = p->a[ii*2+1]; ++ if( r<mnY ) mnY = (float)r; ++ else if( r>mxY ) mxY = (float)r; ++ } ++ if( pRc ) *pRc = SQLITE_OK; ++ if( aCoord==0 ){ ++ geopolyBboxFill: ++ pOut = sqlite3_realloc(p, GEOPOLY_SZ(4)); ++ if( pOut==0 ){ ++ sqlite3_free(p); ++ if( context ) sqlite3_result_error_nomem(context); ++ if( pRc ) *pRc = SQLITE_NOMEM; ++ return 0; ++ } ++ pOut->nVertex = 4; ++ ii = 1; ++ pOut->hdr[0] = *(unsigned char*)ⅈ ++ pOut->hdr[1] = 0; ++ pOut->hdr[2] = 0; ++ pOut->hdr[3] = 4; ++ pOut->a[0] = mnX; ++ pOut->a[1] = mnY; ++ pOut->a[2] = mxX; ++ pOut->a[3] = mnY; ++ pOut->a[4] = mxX; ++ pOut->a[5] = mxY; ++ pOut->a[6] = mnX; ++ pOut->a[7] = mxY; ++ }else{ ++ sqlite3_free(p); ++ aCoord[0].f = mnX; ++ aCoord[1].f = mxX; ++ aCoord[2].f = mnY; ++ aCoord[3].f = mxY; ++ } ++ } ++ return pOut; ++} ++ ++/* ++** Implementation of the geopoly_bbox(X) SQL function. ++*/ ++static void geopolyBBoxFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ GeoPoly *p = geopolyBBox(context, argv[0], 0, 0); ++ if( p ){ ++ sqlite3_result_blob(context, p->hdr, ++ 4+8*p->nVertex, SQLITE_TRANSIENT); ++ sqlite3_free(p); ++ } ++} ++ ++/* ++** State vector for the geopoly_group_bbox() aggregate function. ++*/ ++typedef struct GeoBBox GeoBBox; ++struct GeoBBox { ++ int isInit; ++ RtreeCoord a[4]; ++}; ++ ++ ++/* ++** Implementation of the geopoly_group_bbox(X) aggregate SQL function. ++*/ ++static void geopolyBBoxStep( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ RtreeCoord a[4]; ++ int rc = SQLITE_OK; ++ (void)geopolyBBox(context, argv[0], a, &rc); ++ if( rc==SQLITE_OK ){ ++ GeoBBox *pBBox; ++ pBBox = (GeoBBox*)sqlite3_aggregate_context(context, sizeof(*pBBox)); ++ if( pBBox==0 ) return; ++ if( pBBox->isInit==0 ){ ++ pBBox->isInit = 1; ++ memcpy(pBBox->a, a, sizeof(RtreeCoord)*4); ++ }else{ ++ if( a[0].f < pBBox->a[0].f ) pBBox->a[0] = a[0]; ++ if( a[1].f > pBBox->a[1].f ) pBBox->a[1] = a[1]; ++ if( a[2].f < pBBox->a[2].f ) pBBox->a[2] = a[2]; ++ if( a[3].f > pBBox->a[3].f ) pBBox->a[3] = a[3]; ++ } ++ } ++} ++static void geopolyBBoxFinal( ++ sqlite3_context *context ++){ ++ GeoPoly *p; ++ GeoBBox *pBBox; ++ pBBox = (GeoBBox*)sqlite3_aggregate_context(context, 0); ++ if( pBBox==0 ) return; ++ p = geopolyBBox(context, 0, pBBox->a, 0); ++ if( p ){ ++ sqlite3_result_blob(context, p->hdr, ++ 4+8*p->nVertex, SQLITE_TRANSIENT); ++ sqlite3_free(p); ++ } ++} ++ ++ ++/* ++** Determine if point (x0,y0) is beneath line segment (x1,y1)->(x2,y2). ++** Returns: ++** ++** +2 x0,y0 is on the line segement ++** ++** +1 x0,y0 is beneath line segment ++** ++** 0 x0,y0 is not on or beneath the line segment or the line segment ++** is vertical and x0,y0 is not on the line segment ++** ++** The left-most coordinate min(x1,x2) is not considered to be part of ++** the line segment for the purposes of this analysis. ++*/ ++static int pointBeneathLine( ++ double x0, double y0, ++ double x1, double y1, ++ double x2, double y2 ++){ ++ double y; ++ if( x0==x1 && y0==y1 ) return 2; ++ if( x1<x2 ){ ++ if( x0<=x1 || x0>x2 ) return 0; ++ }else if( x1>x2 ){ ++ if( x0<=x2 || x0>x1 ) return 0; ++ }else{ ++ /* Vertical line segment */ ++ if( x0!=x1 ) return 0; ++ if( y0<y1 && y0<y2 ) return 0; ++ if( y0>y1 && y0>y2 ) return 0; ++ return 2; ++ } ++ y = y1 + (y2-y1)*(x0-x1)/(x2-x1); ++ if( y0==y ) return 2; ++ if( y0<y ) return 1; ++ return 0; ++} ++ ++/* ++** SQL function: geopoly_contains_point(P,X,Y) ++** ++** Return +2 if point X,Y is within polygon P. ++** Return +1 if point X,Y is on the polygon boundary. ++** Return 0 if point X,Y is outside the polygon ++*/ ++static void geopolyContainsPointFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0); ++ double x0 = sqlite3_value_double(argv[1]); ++ double y0 = sqlite3_value_double(argv[2]); ++ int v = 0; ++ int cnt = 0; ++ int ii; ++ if( p1==0 ) return; ++ for(ii=0; ii<p1->nVertex-1; ii++){ ++ v = pointBeneathLine(x0,y0,p1->a[ii*2],p1->a[ii*2+1], ++ p1->a[ii*2+2],p1->a[ii*2+3]); ++ if( v==2 ) break; ++ cnt += v; ++ } ++ if( v!=2 ){ ++ v = pointBeneathLine(x0,y0,p1->a[ii*2],p1->a[ii*2+1], ++ p1->a[0],p1->a[1]); ++ } ++ if( v==2 ){ ++ sqlite3_result_int(context, 1); ++ }else if( ((v+cnt)&1)==0 ){ ++ sqlite3_result_int(context, 0); ++ }else{ ++ sqlite3_result_int(context, 2); ++ } ++ sqlite3_free(p1); ++} ++ ++/* Forward declaration */ ++static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2); ++ ++/* ++** SQL function: geopoly_within(P1,P2) ++** ++** Return +2 if P1 and P2 are the same polygon ++** Return +1 if P2 is contained within P1 ++** Return 0 if any part of P2 is on the outside of P1 ++** ++*/ ++static void geopolyWithinFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0); ++ GeoPoly *p2 = geopolyFuncParam(context, argv[1], 0); ++ if( p1 && p2 ){ ++ int x = geopolyOverlap(p1, p2); ++ if( x<0 ){ ++ sqlite3_result_error_nomem(context); ++ }else{ ++ sqlite3_result_int(context, x==2 ? 1 : x==4 ? 2 : 0); ++ } ++ } ++ sqlite3_free(p1); ++ sqlite3_free(p2); ++} ++ ++/* Objects used by the overlap algorihm. */ ++typedef struct GeoEvent GeoEvent; ++typedef struct GeoSegment GeoSegment; ++typedef struct GeoOverlap GeoOverlap; ++struct GeoEvent { ++ double x; /* X coordinate at which event occurs */ ++ int eType; /* 0 for ADD, 1 for REMOVE */ ++ GeoSegment *pSeg; /* The segment to be added or removed */ ++ GeoEvent *pNext; /* Next event in the sorted list */ ++}; ++struct GeoSegment { ++ double C, B; /* y = C*x + B */ ++ double y; /* Current y value */ ++ float y0; /* Initial y value */ ++ unsigned char side; /* 1 for p1, 2 for p2 */ ++ unsigned int idx; /* Which segment within the side */ ++ GeoSegment *pNext; /* Next segment in a list sorted by y */ ++}; ++struct GeoOverlap { ++ GeoEvent *aEvent; /* Array of all events */ ++ GeoSegment *aSegment; /* Array of all segments */ ++ int nEvent; /* Number of events */ ++ int nSegment; /* Number of segments */ ++}; ++ ++/* ++** Add a single segment and its associated events. ++*/ ++static void geopolyAddOneSegment( ++ GeoOverlap *p, ++ GeoCoord x0, ++ GeoCoord y0, ++ GeoCoord x1, ++ GeoCoord y1, ++ unsigned char side, ++ unsigned int idx ++){ ++ GeoSegment *pSeg; ++ GeoEvent *pEvent; ++ if( x0==x1 ) return; /* Ignore vertical segments */ ++ if( x0>x1 ){ ++ GeoCoord t = x0; ++ x0 = x1; ++ x1 = t; ++ t = y0; ++ y0 = y1; ++ y1 = t; ++ } ++ pSeg = p->aSegment + p->nSegment; ++ p->nSegment++; ++ pSeg->C = (y1-y0)/(x1-x0); ++ pSeg->B = y1 - x1*pSeg->C; ++ pSeg->y0 = y0; ++ pSeg->side = side; ++ pSeg->idx = idx; ++ pEvent = p->aEvent + p->nEvent; ++ p->nEvent++; ++ pEvent->x = x0; ++ pEvent->eType = 0; ++ pEvent->pSeg = pSeg; ++ pEvent = p->aEvent + p->nEvent; ++ p->nEvent++; ++ pEvent->x = x1; ++ pEvent->eType = 1; ++ pEvent->pSeg = pSeg; ++} ++ ++ ++ ++/* ++** Insert all segments and events for polygon pPoly. ++*/ ++static void geopolyAddSegments( ++ GeoOverlap *p, /* Add segments to this Overlap object */ ++ GeoPoly *pPoly, /* Take all segments from this polygon */ ++ unsigned char side /* The side of pPoly */ ++){ ++ unsigned int i; ++ GeoCoord *x; ++ for(i=0; i<(unsigned)pPoly->nVertex-1; i++){ ++ x = pPoly->a + (i*2); ++ geopolyAddOneSegment(p, x[0], x[1], x[2], x[3], side, i); ++ } ++ x = pPoly->a + (i*2); ++ geopolyAddOneSegment(p, x[0], x[1], pPoly->a[0], pPoly->a[1], side, i); ++} ++ ++/* ++** Merge two lists of sorted events by X coordinate ++*/ ++static GeoEvent *geopolyEventMerge(GeoEvent *pLeft, GeoEvent *pRight){ ++ GeoEvent head, *pLast; ++ head.pNext = 0; ++ pLast = &head; ++ while( pRight && pLeft ){ ++ if( pRight->x <= pLeft->x ){ ++ pLast->pNext = pRight; ++ pLast = pRight; ++ pRight = pRight->pNext; ++ }else{ ++ pLast->pNext = pLeft; ++ pLast = pLeft; ++ pLeft = pLeft->pNext; ++ } ++ } ++ pLast->pNext = pRight ? pRight : pLeft; ++ return head.pNext; ++} ++ ++/* ++** Sort an array of nEvent event objects into a list. ++*/ ++static GeoEvent *geopolySortEventsByX(GeoEvent *aEvent, int nEvent){ ++ int mx = 0; ++ int i, j; ++ GeoEvent *p; ++ GeoEvent *a[50]; ++ for(i=0; i<nEvent; i++){ ++ p = &aEvent[i]; ++ p->pNext = 0; ++ for(j=0; j<mx && a[j]; j++){ ++ p = geopolyEventMerge(a[j], p); ++ a[j] = 0; ++ } ++ a[j] = p; ++ if( j>=mx ) mx = j+1; ++ } ++ p = 0; ++ for(i=0; i<mx; i++){ ++ p = geopolyEventMerge(a[i], p); ++ } ++ return p; ++} ++ ++/* ++** Merge two lists of sorted segments by Y, and then by C. ++*/ ++static GeoSegment *geopolySegmentMerge(GeoSegment *pLeft, GeoSegment *pRight){ ++ GeoSegment head, *pLast; ++ head.pNext = 0; ++ pLast = &head; ++ while( pRight && pLeft ){ ++ double r = pRight->y - pLeft->y; ++ if( r==0.0 ) r = pRight->C - pLeft->C; ++ if( r<0.0 ){ ++ pLast->pNext = pRight; ++ pLast = pRight; ++ pRight = pRight->pNext; ++ }else{ ++ pLast->pNext = pLeft; ++ pLast = pLeft; ++ pLeft = pLeft->pNext; ++ } ++ } ++ pLast->pNext = pRight ? pRight : pLeft; ++ return head.pNext; ++} ++ ++/* ++** Sort a list of GeoSegments in order of increasing Y and in the event of ++** a tie, increasing C (slope). ++*/ ++static GeoSegment *geopolySortSegmentsByYAndC(GeoSegment *pList){ ++ int mx = 0; ++ int i; ++ GeoSegment *p; ++ GeoSegment *a[50]; ++ while( pList ){ ++ p = pList; ++ pList = pList->pNext; ++ p->pNext = 0; ++ for(i=0; i<mx && a[i]; i++){ ++ p = geopolySegmentMerge(a[i], p); ++ a[i] = 0; ++ } ++ a[i] = p; ++ if( i>=mx ) mx = i+1; ++ } ++ p = 0; ++ for(i=0; i<mx; i++){ ++ p = geopolySegmentMerge(a[i], p); ++ } ++ return p; ++} ++ ++/* ++** Determine the overlap between two polygons ++*/ ++static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2){ ++ int nVertex = p1->nVertex + p2->nVertex + 2; ++ GeoOverlap *p; ++ int nByte; ++ GeoEvent *pThisEvent; ++ double rX; ++ int rc = 0; ++ int needSort = 0; ++ GeoSegment *pActive = 0; ++ GeoSegment *pSeg; ++ unsigned char aOverlap[4]; ++ ++ nByte = sizeof(GeoEvent)*nVertex*2 ++ + sizeof(GeoSegment)*nVertex ++ + sizeof(GeoOverlap); ++ p = sqlite3_malloc( nByte ); ++ if( p==0 ) return -1; ++ p->aEvent = (GeoEvent*)&p[1]; ++ p->aSegment = (GeoSegment*)&p->aEvent[nVertex*2]; ++ p->nEvent = p->nSegment = 0; ++ geopolyAddSegments(p, p1, 1); ++ geopolyAddSegments(p, p2, 2); ++ pThisEvent = geopolySortEventsByX(p->aEvent, p->nEvent); ++ rX = pThisEvent->x==0.0 ? -1.0 : 0.0; ++ memset(aOverlap, 0, sizeof(aOverlap)); ++ while( pThisEvent ){ ++ if( pThisEvent->x!=rX ){ ++ GeoSegment *pPrev = 0; ++ int iMask = 0; ++ GEODEBUG(("Distinct X: %g\n", pThisEvent->x)); ++ rX = pThisEvent->x; ++ if( needSort ){ ++ GEODEBUG(("SORT\n")); ++ pActive = geopolySortSegmentsByYAndC(pActive); ++ needSort = 0; ++ } ++ for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){ ++ if( pPrev ){ ++ if( pPrev->y!=pSeg->y ){ ++ GEODEBUG(("MASK: %d\n", iMask)); ++ aOverlap[iMask] = 1; ++ } ++ } ++ iMask ^= pSeg->side; ++ pPrev = pSeg; ++ } ++ pPrev = 0; ++ for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){ ++ double y = pSeg->C*rX + pSeg->B; ++ GEODEBUG(("Segment %d.%d %g->%g\n", pSeg->side, pSeg->idx, pSeg->y, y)); ++ pSeg->y = y; ++ if( pPrev ){ ++ if( pPrev->y>pSeg->y && pPrev->side!=pSeg->side ){ ++ rc = 1; ++ GEODEBUG(("Crossing: %d.%d and %d.%d\n", ++ pPrev->side, pPrev->idx, ++ pSeg->side, pSeg->idx)); ++ goto geopolyOverlapDone; ++ }else if( pPrev->y!=pSeg->y ){ ++ GEODEBUG(("MASK: %d\n", iMask)); ++ aOverlap[iMask] = 1; ++ } ++ } ++ iMask ^= pSeg->side; ++ pPrev = pSeg; ++ } ++ } ++ GEODEBUG(("%s %d.%d C=%g B=%g\n", ++ pThisEvent->eType ? "RM " : "ADD", ++ pThisEvent->pSeg->side, pThisEvent->pSeg->idx, ++ pThisEvent->pSeg->C, ++ pThisEvent->pSeg->B)); ++ if( pThisEvent->eType==0 ){ ++ /* Add a segment */ ++ pSeg = pThisEvent->pSeg; ++ pSeg->y = pSeg->y0; ++ pSeg->pNext = pActive; ++ pActive = pSeg; ++ needSort = 1; ++ }else{ ++ /* Remove a segment */ ++ if( pActive==pThisEvent->pSeg ){ ++ pActive = pActive->pNext; ++ }else{ ++ for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){ ++ if( pSeg->pNext==pThisEvent->pSeg ){ ++ pSeg->pNext = pSeg->pNext->pNext; ++ break; ++ } ++ } ++ } ++ } ++ pThisEvent = pThisEvent->pNext; ++ } ++ if( aOverlap[3]==0 ){ ++ rc = 0; ++ }else if( aOverlap[1]!=0 && aOverlap[2]==0 ){ ++ rc = 3; ++ }else if( aOverlap[1]==0 && aOverlap[2]!=0 ){ ++ rc = 2; ++ }else if( aOverlap[1]==0 && aOverlap[2]==0 ){ ++ rc = 4; ++ }else{ ++ rc = 1; ++ } ++ ++geopolyOverlapDone: ++ sqlite3_free(p); ++ return rc; ++} ++ ++/* ++** SQL function: geopoly_overlap(P1,P2) ++** ++** Determine whether or not P1 and P2 overlap. Return value: ++** ++** 0 The two polygons are disjoint ++** 1 They overlap ++** 2 P1 is completely contained within P2 ++** 3 P2 is completely contained within P1 ++** 4 P1 and P2 are the same polygon ++** NULL Either P1 or P2 or both are not valid polygons ++*/ ++static void geopolyOverlapFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0); ++ GeoPoly *p2 = geopolyFuncParam(context, argv[1], 0); ++ if( p1 && p2 ){ ++ int x = geopolyOverlap(p1, p2); ++ if( x<0 ){ ++ sqlite3_result_error_nomem(context); ++ }else{ ++ sqlite3_result_int(context, x); ++ } ++ } ++ sqlite3_free(p1); ++ sqlite3_free(p2); ++} ++ ++/* ++** Enable or disable debugging output ++*/ ++static void geopolyDebugFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++#ifdef GEOPOLY_ENABLE_DEBUG ++ geo_debug = sqlite3_value_int(argv[0]); ++#endif ++} ++ ++/* ++** This function is the implementation of both the xConnect and xCreate ++** methods of the geopoly virtual table. ++** ++** argv[0] -> module name ++** argv[1] -> database name ++** argv[2] -> table name ++** argv[...] -> column names... ++*/ ++static int geopolyInit( ++ sqlite3 *db, /* Database connection */ ++ void *pAux, /* One of the RTREE_COORD_* constants */ ++ int argc, const char *const*argv, /* Parameters to CREATE TABLE statement */ ++ sqlite3_vtab **ppVtab, /* OUT: New virtual table */ ++ char **pzErr, /* OUT: Error message, if any */ ++ int isCreate /* True for xCreate, false for xConnect */ ++){ ++ int rc = SQLITE_OK; ++ Rtree *pRtree; ++ int nDb; /* Length of string argv[1] */ ++ int nName; /* Length of string argv[2] */ ++ sqlite3_str *pSql; ++ char *zSql; ++ int ii; ++ ++ sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); ++ ++ /* Allocate the sqlite3_vtab structure */ ++ nDb = (int)strlen(argv[1]); ++ nName = (int)strlen(argv[2]); ++ pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2); ++ if( !pRtree ){ ++ return SQLITE_NOMEM; ++ } ++ memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2); ++ pRtree->nBusy = 1; ++ pRtree->base.pModule = &rtreeModule; ++ pRtree->zDb = (char *)&pRtree[1]; ++ pRtree->zName = &pRtree->zDb[nDb+1]; ++ pRtree->eCoordType = RTREE_COORD_REAL32; ++ pRtree->nDim = 2; ++ pRtree->nDim2 = 4; ++ memcpy(pRtree->zDb, argv[1], nDb); ++ memcpy(pRtree->zName, argv[2], nName); ++ ++ ++ /* Create/Connect to the underlying relational database schema. If ++ ** that is successful, call sqlite3_declare_vtab() to configure ++ ** the r-tree table schema. ++ */ ++ pSql = sqlite3_str_new(db); ++ sqlite3_str_appendf(pSql, "CREATE TABLE x(_shape"); ++ pRtree->nAux = 1; /* Add one for _shape */ ++ pRtree->nAuxNotNull = 1; /* The _shape column is always not-null */ ++ for(ii=3; ii<argc; ii++){ ++ pRtree->nAux++; ++ sqlite3_str_appendf(pSql, ",%s", argv[ii]); ++ } ++ sqlite3_str_appendf(pSql, ");"); ++ zSql = sqlite3_str_finish(pSql); ++ if( !zSql ){ ++ rc = SQLITE_NOMEM; ++ }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){ ++ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); ++ } ++ sqlite3_free(zSql); ++ if( rc ) goto geopolyInit_fail; ++ pRtree->nBytesPerCell = 8 + pRtree->nDim2*4; ++ ++ /* Figure out the node size to use. */ ++ rc = getNodeSize(db, pRtree, isCreate, pzErr); ++ if( rc ) goto geopolyInit_fail; ++ rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate); ++ if( rc ){ ++ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); ++ goto geopolyInit_fail; ++ } ++ ++ *ppVtab = (sqlite3_vtab *)pRtree; ++ return SQLITE_OK; ++ ++geopolyInit_fail: ++ if( rc==SQLITE_OK ) rc = SQLITE_ERROR; ++ assert( *ppVtab==0 ); ++ assert( pRtree->nBusy==1 ); ++ rtreeRelease(pRtree); ++ return rc; ++} ++ ++ ++/* ++** GEOPOLY virtual table module xCreate method. ++*/ ++static int geopolyCreate( ++ sqlite3 *db, ++ void *pAux, ++ int argc, const char *const*argv, ++ sqlite3_vtab **ppVtab, ++ char **pzErr ++){ ++ return geopolyInit(db, pAux, argc, argv, ppVtab, pzErr, 1); ++} ++ ++/* ++** GEOPOLY virtual table module xConnect method. ++*/ ++static int geopolyConnect( ++ sqlite3 *db, ++ void *pAux, ++ int argc, const char *const*argv, ++ sqlite3_vtab **ppVtab, ++ char **pzErr ++){ ++ return geopolyInit(db, pAux, argc, argv, ppVtab, pzErr, 0); ++} ++ ++ ++/* ++** GEOPOLY virtual table module xFilter method. ++** ++** Query plans: ++** ++** 1 rowid lookup ++** 2 search for objects overlapping the same bounding box ++** that contains polygon argv[0] ++** 3 search for objects overlapping the same bounding box ++** that contains polygon argv[0] ++** 4 full table scan ++*/ ++static int geopolyFilter( ++ sqlite3_vtab_cursor *pVtabCursor, /* The cursor to initialize */ ++ int idxNum, /* Query plan */ ++ const char *idxStr, /* Not Used */ ++ int argc, sqlite3_value **argv /* Parameters to the query plan */ ++){ ++ Rtree *pRtree = (Rtree *)pVtabCursor->pVtab; ++ RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; ++ RtreeNode *pRoot = 0; ++ int rc = SQLITE_OK; ++ int iCell = 0; ++ sqlite3_stmt *pStmt; ++ ++ rtreeReference(pRtree); ++ ++ /* Reset the cursor to the same state as rtreeOpen() leaves it in. */ ++ freeCursorConstraints(pCsr); ++ sqlite3_free(pCsr->aPoint); ++ pStmt = pCsr->pReadAux; ++ memset(pCsr, 0, sizeof(RtreeCursor)); ++ pCsr->base.pVtab = (sqlite3_vtab*)pRtree; ++ pCsr->pReadAux = pStmt; ++ ++ pCsr->iStrategy = idxNum; ++ if( idxNum==1 ){ ++ /* Special case - lookup by rowid. */ ++ RtreeNode *pLeaf; /* Leaf on which the required cell resides */ ++ RtreeSearchPoint *p; /* Search point for the leaf */ ++ i64 iRowid = sqlite3_value_int64(argv[0]); ++ i64 iNode = 0; ++ rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode); ++ if( rc==SQLITE_OK && pLeaf!=0 ){ ++ p = rtreeSearchPointNew(pCsr, RTREE_ZERO, 0); ++ assert( p!=0 ); /* Always returns pCsr->sPoint */ ++ pCsr->aNode[0] = pLeaf; ++ p->id = iNode; ++ p->eWithin = PARTLY_WITHIN; ++ rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &iCell); ++ p->iCell = (u8)iCell; ++ RTREE_QUEUE_TRACE(pCsr, "PUSH-F1:"); ++ }else{ ++ pCsr->atEOF = 1; ++ } ++ }else{ ++ /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array ++ ** with the configured constraints. ++ */ ++ rc = nodeAcquire(pRtree, 1, 0, &pRoot); ++ if( rc==SQLITE_OK && idxNum<=3 ){ ++ RtreeCoord bbox[4]; ++ RtreeConstraint *p; ++ assert( argc==1 ); ++ geopolyBBox(0, argv[0], bbox, &rc); ++ if( rc ){ ++ goto geopoly_filter_end; ++ } ++ pCsr->aConstraint = p = sqlite3_malloc(sizeof(RtreeConstraint)*4); ++ pCsr->nConstraint = 4; ++ if( p==0 ){ ++ rc = SQLITE_NOMEM; ++ }else{ ++ memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*4); ++ memset(pCsr->anQueue, 0, sizeof(u32)*(pRtree->iDepth + 1)); ++ if( idxNum==2 ){ ++ /* Overlap query */ ++ p->op = 'B'; ++ p->iCoord = 0; ++ p->u.rValue = bbox[1].f; ++ p++; ++ p->op = 'D'; ++ p->iCoord = 1; ++ p->u.rValue = bbox[0].f; ++ p++; ++ p->op = 'B'; ++ p->iCoord = 2; ++ p->u.rValue = bbox[3].f; ++ p++; ++ p->op = 'D'; ++ p->iCoord = 3; ++ p->u.rValue = bbox[2].f; ++ }else{ ++ /* Within query */ ++ p->op = 'D'; ++ p->iCoord = 0; ++ p->u.rValue = bbox[0].f; ++ p++; ++ p->op = 'B'; ++ p->iCoord = 1; ++ p->u.rValue = bbox[1].f; ++ p++; ++ p->op = 'D'; ++ p->iCoord = 2; ++ p->u.rValue = bbox[2].f; ++ p++; ++ p->op = 'B'; ++ p->iCoord = 3; ++ p->u.rValue = bbox[3].f; ++ } ++ } ++ } ++ if( rc==SQLITE_OK ){ ++ RtreeSearchPoint *pNew; ++ pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, (u8)(pRtree->iDepth+1)); ++ if( pNew==0 ){ ++ rc = SQLITE_NOMEM; ++ goto geopoly_filter_end; ++ } ++ pNew->id = 1; ++ pNew->iCell = 0; ++ pNew->eWithin = PARTLY_WITHIN; ++ assert( pCsr->bPoint==1 ); ++ pCsr->aNode[0] = pRoot; ++ pRoot = 0; ++ RTREE_QUEUE_TRACE(pCsr, "PUSH-Fm:"); ++ rc = rtreeStepToLeaf(pCsr); ++ } ++ } ++ ++geopoly_filter_end: ++ nodeRelease(pRtree, pRoot); ++ rtreeRelease(pRtree); ++ return rc; ++} ++ ++/* ++** Rtree virtual table module xBestIndex method. There are three ++** table scan strategies to choose from (in order from most to ++** least desirable): ++** ++** idxNum idxStr Strategy ++** ------------------------------------------------ ++** 1 "rowid" Direct lookup by rowid. ++** 2 "rtree" R-tree overlap query using geopoly_overlap() ++** 3 "rtree" R-tree within query using geopoly_within() ++** 4 "fullscan" full-table scan. ++** ------------------------------------------------ ++*/ ++static int geopolyBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ ++ int ii; ++ int iRowidTerm = -1; ++ int iFuncTerm = -1; ++ int idxNum = 0; ++ ++ for(ii=0; ii<pIdxInfo->nConstraint; ii++){ ++ struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii]; ++ if( !p->usable ) continue; ++ if( p->iColumn<0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ ++ iRowidTerm = ii; ++ break; ++ } ++ if( p->iColumn==0 && p->op>=SQLITE_INDEX_CONSTRAINT_FUNCTION ){ ++ /* p->op==SQLITE_INDEX_CONSTRAINT_FUNCTION for geopoly_overlap() ++ ** p->op==(SQLITE_INDEX_CONTRAINT_FUNCTION+1) for geopoly_within(). ++ ** See geopolyFindFunction() */ ++ iFuncTerm = ii; ++ idxNum = p->op - SQLITE_INDEX_CONSTRAINT_FUNCTION + 2; ++ } ++ } ++ ++ if( iRowidTerm>=0 ){ ++ pIdxInfo->idxNum = 1; ++ pIdxInfo->idxStr = "rowid"; ++ pIdxInfo->aConstraintUsage[iRowidTerm].argvIndex = 1; ++ pIdxInfo->aConstraintUsage[iRowidTerm].omit = 1; ++ pIdxInfo->estimatedCost = 30.0; ++ pIdxInfo->estimatedRows = 1; ++ pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE; ++ return SQLITE_OK; ++ } ++ if( iFuncTerm>=0 ){ ++ pIdxInfo->idxNum = idxNum; ++ pIdxInfo->idxStr = "rtree"; ++ pIdxInfo->aConstraintUsage[iFuncTerm].argvIndex = 1; ++ pIdxInfo->aConstraintUsage[iFuncTerm].omit = 0; ++ pIdxInfo->estimatedCost = 300.0; ++ pIdxInfo->estimatedRows = 10; ++ return SQLITE_OK; ++ } ++ pIdxInfo->idxNum = 4; ++ pIdxInfo->idxStr = "fullscan"; ++ pIdxInfo->estimatedCost = 3000000.0; ++ pIdxInfo->estimatedRows = 100000; ++ return SQLITE_OK; ++} ++ ++ ++/* ++** GEOPOLY virtual table module xColumn method. ++*/ ++static int geopolyColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ ++ Rtree *pRtree = (Rtree *)cur->pVtab; ++ RtreeCursor *pCsr = (RtreeCursor *)cur; ++ RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr); ++ int rc = SQLITE_OK; ++ RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc); ++ ++ if( rc ) return rc; ++ if( p==0 ) return SQLITE_OK; ++ if( i==0 && sqlite3_vtab_nochange(ctx) ) return SQLITE_OK; ++ if( i<=pRtree->nAux ){ ++ if( !pCsr->bAuxValid ){ ++ if( pCsr->pReadAux==0 ){ ++ rc = sqlite3_prepare_v3(pRtree->db, pRtree->zReadAuxSql, -1, 0, ++ &pCsr->pReadAux, 0); ++ if( rc ) return rc; ++ } ++ sqlite3_bind_int64(pCsr->pReadAux, 1, ++ nodeGetRowid(pRtree, pNode, p->iCell)); ++ rc = sqlite3_step(pCsr->pReadAux); ++ if( rc==SQLITE_ROW ){ ++ pCsr->bAuxValid = 1; ++ }else{ ++ sqlite3_reset(pCsr->pReadAux); ++ if( rc==SQLITE_DONE ) rc = SQLITE_OK; ++ return rc; ++ } ++ } ++ sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pReadAux, i+2)); ++ } ++ return SQLITE_OK; ++} ++ ++ ++/* ++** The xUpdate method for GEOPOLY module virtual tables. ++** ++** For DELETE: ++** ++** argv[0] = the rowid to be deleted ++** ++** For INSERT: ++** ++** argv[0] = SQL NULL ++** argv[1] = rowid to insert, or an SQL NULL to select automatically ++** argv[2] = _shape column ++** argv[3] = first application-defined column.... ++** ++** For UPDATE: ++** ++** argv[0] = rowid to modify. Never NULL ++** argv[1] = rowid after the change. Never NULL ++** argv[2] = new value for _shape ++** argv[3] = new value for first application-defined column.... ++*/ ++static int geopolyUpdate( ++ sqlite3_vtab *pVtab, ++ int nData, ++ sqlite3_value **aData, ++ sqlite_int64 *pRowid ++){ ++ Rtree *pRtree = (Rtree *)pVtab; ++ int rc = SQLITE_OK; ++ RtreeCell cell; /* New cell to insert if nData>1 */ ++ i64 oldRowid; /* The old rowid */ ++ int oldRowidValid; /* True if oldRowid is valid */ ++ i64 newRowid; /* The new rowid */ ++ int newRowidValid; /* True if newRowid is valid */ ++ int coordChange = 0; /* Change in coordinates */ ++ ++ if( pRtree->nNodeRef ){ ++ /* Unable to write to the btree while another cursor is reading from it, ++ ** since the write might do a rebalance which would disrupt the read ++ ** cursor. */ ++ return SQLITE_LOCKED_VTAB; ++ } ++ rtreeReference(pRtree); ++ assert(nData>=1); ++ ++ oldRowidValid = sqlite3_value_type(aData[0])!=SQLITE_NULL;; ++ oldRowid = oldRowidValid ? sqlite3_value_int64(aData[0]) : 0; ++ newRowidValid = nData>1 && sqlite3_value_type(aData[1])!=SQLITE_NULL; ++ newRowid = newRowidValid ? sqlite3_value_int64(aData[1]) : 0; ++ cell.iRowid = newRowid; ++ ++ if( nData>1 /* not a DELETE */ ++ && (!oldRowidValid /* INSERT */ ++ || !sqlite3_value_nochange(aData[2]) /* UPDATE _shape */ ++ || oldRowid!=newRowid) /* Rowid change */ ++ ){ ++ geopolyBBox(0, aData[2], cell.aCoord, &rc); ++ if( rc ){ ++ if( rc==SQLITE_ERROR ){ ++ pVtab->zErrMsg = ++ sqlite3_mprintf("_shape does not contain a valid polygon"); ++ } ++ goto geopoly_update_end; ++ } ++ coordChange = 1; ++ ++ /* If a rowid value was supplied, check if it is already present in ++ ** the table. If so, the constraint has failed. */ ++ if( newRowidValid && (!oldRowidValid || oldRowid!=newRowid) ){ ++ int steprc; ++ sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid); ++ steprc = sqlite3_step(pRtree->pReadRowid); ++ rc = sqlite3_reset(pRtree->pReadRowid); ++ if( SQLITE_ROW==steprc ){ ++ if( sqlite3_vtab_on_conflict(pRtree->db)==SQLITE_REPLACE ){ ++ rc = rtreeDeleteRowid(pRtree, cell.iRowid); ++ }else{ ++ rc = rtreeConstraintError(pRtree, 0); ++ } ++ } ++ } ++ } ++ ++ /* If aData[0] is not an SQL NULL value, it is the rowid of a ++ ** record to delete from the r-tree table. The following block does ++ ** just that. ++ */ ++ if( rc==SQLITE_OK && (nData==1 || (coordChange && oldRowidValid)) ){ ++ rc = rtreeDeleteRowid(pRtree, oldRowid); ++ } ++ ++ /* If the aData[] array contains more than one element, elements ++ ** (aData[2]..aData[argc-1]) contain a new record to insert into ++ ** the r-tree structure. ++ */ ++ if( rc==SQLITE_OK && nData>1 && coordChange ){ ++ /* Insert the new record into the r-tree */ ++ RtreeNode *pLeaf = 0; ++ if( !newRowidValid ){ ++ rc = rtreeNewRowid(pRtree, &cell.iRowid); ++ } ++ *pRowid = cell.iRowid; ++ if( rc==SQLITE_OK ){ ++ rc = ChooseLeaf(pRtree, &cell, 0, &pLeaf); ++ } ++ if( rc==SQLITE_OK ){ ++ int rc2; ++ pRtree->iReinsertHeight = -1; ++ rc = rtreeInsertCell(pRtree, pLeaf, &cell, 0); ++ rc2 = nodeRelease(pRtree, pLeaf); ++ if( rc==SQLITE_OK ){ ++ rc = rc2; ++ } ++ } ++ } ++ ++ /* Change the data */ ++ if( rc==SQLITE_OK && nData>1 ){ ++ sqlite3_stmt *pUp = pRtree->pWriteAux; ++ int jj; ++ int nChange = 0; ++ sqlite3_bind_int64(pUp, 1, cell.iRowid); ++ assert( pRtree->nAux>=1 ); ++ if( sqlite3_value_nochange(aData[2]) ){ ++ sqlite3_bind_null(pUp, 2); ++ }else{ ++ GeoPoly *p = 0; ++ if( sqlite3_value_type(aData[2])==SQLITE_TEXT ++ && (p = geopolyFuncParam(0, aData[2], &rc))!=0 ++ && rc==SQLITE_OK ++ ){ ++ sqlite3_bind_blob(pUp, 2, p->hdr, 4+8*p->nVertex, SQLITE_TRANSIENT); ++ }else{ ++ sqlite3_bind_value(pUp, 2, aData[2]); ++ } ++ sqlite3_free(p); ++ nChange = 1; ++ } ++ for(jj=1; jj<pRtree->nAux; jj++){ ++ nChange++; ++ sqlite3_bind_value(pUp, jj+2, aData[jj+2]); ++ } ++ if( nChange ){ ++ sqlite3_step(pUp); ++ rc = sqlite3_reset(pUp); ++ } ++ } ++ ++geopoly_update_end: ++ rtreeRelease(pRtree); ++ return rc; ++} ++ ++/* ++** Report that geopoly_overlap() is an overloaded function suitable ++** for use in xBestIndex. ++*/ ++static int geopolyFindFunction( ++ sqlite3_vtab *pVtab, ++ int nArg, ++ const char *zName, ++ void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), ++ void **ppArg ++){ ++ if( sqlite3_stricmp(zName, "geopoly_overlap")==0 ){ ++ *pxFunc = geopolyOverlapFunc; ++ *ppArg = 0; ++ return SQLITE_INDEX_CONSTRAINT_FUNCTION; ++ } ++ if( sqlite3_stricmp(zName, "geopoly_within")==0 ){ ++ *pxFunc = geopolyWithinFunc; ++ *ppArg = 0; ++ return SQLITE_INDEX_CONSTRAINT_FUNCTION+1; ++ } ++ return 0; ++} ++ ++ ++static sqlite3_module geopolyModule = { ++ 3, /* iVersion */ ++ geopolyCreate, /* xCreate - create a table */ ++ geopolyConnect, /* xConnect - connect to an existing table */ ++ geopolyBestIndex, /* xBestIndex - Determine search strategy */ ++ rtreeDisconnect, /* xDisconnect - Disconnect from a table */ ++ rtreeDestroy, /* xDestroy - Drop a table */ ++ rtreeOpen, /* xOpen - open a cursor */ ++ rtreeClose, /* xClose - close a cursor */ ++ geopolyFilter, /* xFilter - configure scan constraints */ ++ rtreeNext, /* xNext - advance a cursor */ ++ rtreeEof, /* xEof */ ++ geopolyColumn, /* xColumn - read data */ ++ rtreeRowid, /* xRowid - read data */ ++ geopolyUpdate, /* xUpdate - write data */ ++ rtreeBeginTransaction, /* xBegin - begin transaction */ ++ rtreeEndTransaction, /* xSync - sync transaction */ ++ rtreeEndTransaction, /* xCommit - commit transaction */ ++ rtreeEndTransaction, /* xRollback - rollback transaction */ ++ geopolyFindFunction, /* xFindFunction - function overloading */ ++ rtreeRename, /* xRename - rename the table */ ++ rtreeSavepoint, /* xSavepoint */ ++ 0, /* xRelease */ ++ 0, /* xRollbackTo */ ++ rtreeShadowName /* xShadowName */ ++}; ++ ++static int sqlite3_geopoly_init(sqlite3 *db){ ++ int rc = SQLITE_OK; ++ static const struct { ++ void (*xFunc)(sqlite3_context*,int,sqlite3_value**); ++ signed char nArg; ++ unsigned char bPure; ++ const char *zName; ++ } aFunc[] = { ++ { geopolyAreaFunc, 1, 1, "geopoly_area" }, ++ { geopolyBlobFunc, 1, 1, "geopoly_blob" }, ++ { geopolyJsonFunc, 1, 1, "geopoly_json" }, ++ { geopolySvgFunc, -1, 1, "geopoly_svg" }, ++ { geopolyWithinFunc, 2, 1, "geopoly_within" }, ++ { geopolyContainsPointFunc, 3, 1, "geopoly_contains_point" }, ++ { geopolyOverlapFunc, 2, 1, "geopoly_overlap" }, ++ { geopolyDebugFunc, 1, 0, "geopoly_debug" }, ++ { geopolyBBoxFunc, 1, 1, "geopoly_bbox" }, ++ { geopolyXformFunc, 7, 1, "geopoly_xform" }, ++ { geopolyRegularFunc, 4, 1, "geopoly_regular" }, ++ { geopolyCcwFunc, 1, 1, "geopoly_ccw" }, ++ }; ++ static const struct { ++ void (*xStep)(sqlite3_context*,int,sqlite3_value**); ++ void (*xFinal)(sqlite3_context*); ++ const char *zName; ++ } aAgg[] = { ++ { geopolyBBoxStep, geopolyBBoxFinal, "geopoly_group_bbox" }, ++ }; ++ int i; ++ for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){ ++ int enc = aFunc[i].bPure ? SQLITE_UTF8|SQLITE_DETERMINISTIC : SQLITE_UTF8; ++ rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg, ++ enc, 0, ++ aFunc[i].xFunc, 0, 0); ++ } ++ for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){ ++ rc = sqlite3_create_function(db, aAgg[i].zName, 1, SQLITE_UTF8, 0, ++ 0, aAgg[i].xStep, aAgg[i].xFinal); ++ } ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3_create_module_v2(db, "geopoly", &geopolyModule, 0, 0); ++ } ++ return rc; ++} ++ ++/************** End of geopoly.c *********************************************/ ++/************** Continuing where we left off in rtree.c **********************/ ++#endif ++ ++/* + ** Register the r-tree module with database handle db. This creates the + ** virtual table module "rtree" and the debugging/analysis scalar + ** function "rtreenode". +@@ -168878,6 +185189,9 @@ + rc = sqlite3_create_function(db, "rtreedepth", 1, utf8, 0,rtreedepth, 0, 0); + } + if( rc==SQLITE_OK ){ ++ rc = sqlite3_create_function(db, "rtreecheck", -1, utf8, 0,rtreecheck, 0,0); ++ } ++ if( rc==SQLITE_OK ){ + #ifdef SQLITE_RTREE_INT_ONLY + void *c = (void *)RTREE_COORD_INT32; + #else +@@ -168889,6 +185203,11 @@ + void *c = (void *)RTREE_COORD_INT32; + rc = sqlite3_create_module_v2(db, "rtree_i32", &rtreeModule, c, 0); + } ++#ifdef SQLITE_ENABLE_GEOPOLY ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3_geopoly_init(db); ++ } ++#endif + + return rc; + } +@@ -169063,7 +185382,9 @@ + ** provide case-independent matching. + */ + +-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) ++#if !defined(SQLITE_CORE) \ ++ || defined(SQLITE_ENABLE_ICU) \ ++ || defined(SQLITE_ENABLE_ICU_COLLATIONS) + + /* Include ICU headers */ + #include <unicode/utypes.h> +@@ -169081,6 +185402,26 @@ + #endif + + /* ++** This function is called when an ICU function called from within ++** the implementation of an SQL scalar function returns an error. ++** ++** The scalar function context passed as the first argument is ++** loaded with an error message based on the following two args. ++*/ ++static void icuFunctionError( ++ sqlite3_context *pCtx, /* SQLite scalar function context */ ++ const char *zName, /* Name of ICU function that failed */ ++ UErrorCode e /* Error code returned by ICU function */ ++){ ++ char zBuf[128]; ++ sqlite3_snprintf(128, zBuf, "ICU error: %s(): %s", zName, u_errorName(e)); ++ zBuf[127] = '\0'; ++ sqlite3_result_error(pCtx, zBuf, -1); ++} ++ ++#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) ++ ++/* + ** Maximum length (in bytes) of the pattern in a LIKE or GLOB + ** operator. + */ +@@ -169137,8 +185478,8 @@ + const uint8_t *zString, /* The UTF-8 string to compare against */ + const UChar32 uEsc /* The escape character */ + ){ +- static const int MATCH_ONE = (UChar32)'_'; +- static const int MATCH_ALL = (UChar32)'%'; ++ static const uint32_t MATCH_ONE = (uint32_t)'_'; ++ static const uint32_t MATCH_ALL = (uint32_t)'%'; + + int prevEscape = 0; /* True if the previous character was uEsc */ + +@@ -169145,7 +185486,7 @@ + while( 1 ){ + + /* Read (and consume) the next character from the input pattern. */ +- UChar32 uPattern; ++ uint32_t uPattern; + SQLITE_ICU_READ_UTF8(zPattern, uPattern); + if( uPattern==0 ) break; + +@@ -169187,16 +185528,16 @@ + if( *zString==0 ) return 0; + SQLITE_ICU_SKIP_UTF8(zString); + +- }else if( !prevEscape && uPattern==uEsc){ ++ }else if( !prevEscape && uPattern==(uint32_t)uEsc){ + /* Case 3. */ + prevEscape = 1; + + }else{ + /* Case 4. */ +- UChar32 uString; ++ uint32_t uString; + SQLITE_ICU_READ_UTF8(zString, uString); +- uString = u_foldCase(uString, U_FOLD_CASE_DEFAULT); +- uPattern = u_foldCase(uPattern, U_FOLD_CASE_DEFAULT); ++ uString = (uint32_t)u_foldCase((UChar32)uString, U_FOLD_CASE_DEFAULT); ++ uPattern = (uint32_t)u_foldCase((UChar32)uPattern, U_FOLD_CASE_DEFAULT); + if( uString!=uPattern ){ + return 0; + } +@@ -169260,24 +185601,6 @@ + } + + /* +-** This function is called when an ICU function called from within +-** the implementation of an SQL scalar function returns an error. +-** +-** The scalar function context passed as the first argument is +-** loaded with an error message based on the following two args. +-*/ +-static void icuFunctionError( +- sqlite3_context *pCtx, /* SQLite scalar function context */ +- const char *zName, /* Name of ICU function that failed */ +- UErrorCode e /* Error code returned by ICU function */ +-){ +- char zBuf[128]; +- sqlite3_snprintf(128, zBuf, "ICU error: %s(): %s", zName, u_errorName(e)); +- zBuf[127] = '\0'; +- sqlite3_result_error(pCtx, zBuf, -1); +-} +- +-/* + ** Function to delete compiled regexp objects. Registered as + ** a destructor function with sqlite3_set_auxdata(). + */ +@@ -169442,6 +185765,8 @@ + assert( 0 ); /* Unreachable */ + } + ++#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) */ ++ + /* + ** Collation sequence destructor function. The pCtx argument points to + ** a UCollator structure previously allocated using ucol_open(). +@@ -169536,6 +185861,7 @@ + void (*xFunc)(sqlite3_context*,int,sqlite3_value**); + } scalars[] = { + {"icu_load_collation", 2, SQLITE_UTF8, 1, icuLoadCollation}, ++#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) + {"regexp", 2, SQLITE_ANY|SQLITE_DETERMINISTIC, 0, icuRegexpFunc}, + {"lower", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16}, + {"lower", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16}, +@@ -169547,10 +185873,10 @@ + {"upper", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 1, icuCaseFunc16}, + {"like", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc}, + {"like", 3, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc}, ++#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) */ + }; + int rc = SQLITE_OK; + int i; +- + + for(i=0; rc==SQLITE_OK && i<(int)(sizeof(scalars)/sizeof(scalars[0])); i++){ + const struct IcuScalar *p = &scalars[i]; +@@ -170293,6 +186619,28 @@ + ); + + /* ++** Configure a limit for the amount of temp space that may be used by ++** the RBU handle passed as the first argument. The new limit is specified ++** in bytes by the second parameter. If it is positive, the limit is updated. ++** If the second parameter to this function is passed zero, then the limit ++** is removed entirely. If the second parameter is negative, the limit is ++** not modified (this is useful for querying the current limit). ++** ++** In all cases the returned value is the current limit in bytes (zero ++** indicates unlimited). ++** ++** If the temp space limit is exceeded during operation, an SQLITE_FULL ++** error is returned. ++*/ ++SQLITE_API sqlite3_int64 sqlite3rbu_temp_size_limit(sqlite3rbu*, sqlite3_int64); ++ ++/* ++** Return the current amount of temp file space, in bytes, currently used by ++** the RBU handle passed as the only argument. ++*/ ++SQLITE_API sqlite3_int64 sqlite3rbu_temp_size(sqlite3rbu*); ++ ++/* + ** Internally, each RBU connection uses a separate SQLite database + ** connection to access the target and rbu update databases. This + ** API allows the application direct access to these database handles. +@@ -170418,7 +186766,7 @@ + ** table exists but is not correctly populated, the value of the *pnOne + ** output variable during stage 1 is undefined. + */ +-SQLITE_API void sqlite3rbu_bp_progress(sqlite3rbu *pRbu, int *pnOne, int *pnTwo); ++SQLITE_API void sqlite3rbu_bp_progress(sqlite3rbu *pRbu, int *pnOne, int*pnTwo); + + /* + ** Obtain an indication as to the current stage of an RBU update or vacuum. +@@ -170528,6 +186876,13 @@ + /* Maximum number of prepared UPDATE statements held by this module */ + #define SQLITE_RBU_UPDATE_CACHESIZE 16 + ++/* Delta checksums disabled by default. Compile with -DRBU_ENABLE_DELTA_CKSUM ++** to enable checksum verification. ++*/ ++#ifndef RBU_ENABLE_DELTA_CKSUM ++# define RBU_ENABLE_DELTA_CKSUM 0 ++#endif ++ + /* + ** Swap two objects of type TYPE. + */ +@@ -170578,6 +186933,10 @@ + ** + ** RBU_STATE_OALSZ: + ** Valid if STAGE==1. The size in bytes of the *-oal file. ++** ++** RBU_STATE_DATATBL: ++** Only valid if STAGE==1. The RBU database name of the table ++** currently being read. + */ + #define RBU_STATE_STAGE 1 + #define RBU_STATE_TBL 2 +@@ -170588,6 +186947,7 @@ + #define RBU_STATE_COOKIE 7 + #define RBU_STATE_OALSZ 8 + #define RBU_STATE_PHASEONESTEP 9 ++#define RBU_STATE_DATATBL 10 + + #define RBU_STAGE_OAL 1 + #define RBU_STAGE_MOVE 2 +@@ -170630,6 +186990,7 @@ + struct RbuState { + int eStage; + char *zTbl; ++ char *zDataTbl; + char *zIdx; + i64 iWalCksum; + int nRow; +@@ -170803,6 +187164,8 @@ + int pgsz; + u8 *aBuf; + i64 iWalCksum; ++ i64 szTemp; /* Current size of all temp files in use */ ++ i64 szTempLimit; /* Total size limit for temp files */ + + /* Used in RBU vacuum mode only */ + int nRbu; /* Number of RBU VFS in the stack */ +@@ -170811,17 +187174,27 @@ + + /* + ** An rbu VFS is implemented using an instance of this structure. ++** ++** Variable pRbu is only non-NULL for automatically created RBU VFS objects. ++** It is NULL for RBU VFS objects created explicitly using ++** sqlite3rbu_create_vfs(). It is used to track the total amount of temp ++** space used by the RBU handle. + */ + struct rbu_vfs { + sqlite3_vfs base; /* rbu VFS shim methods */ + sqlite3_vfs *pRealVfs; /* Underlying VFS */ + sqlite3_mutex *mutex; /* Mutex to protect pMain */ +- rbu_file *pMain; /* Linked list of main db files */ ++ sqlite3rbu *pRbu; /* Owner RBU object */ ++ rbu_file *pMain; /* List of main db files */ ++ rbu_file *pMainRbu; /* List of main db files with pRbu!=0 */ + }; + + /* + ** Each file opened by an rbu VFS is represented by an instance of + ** the following structure. ++** ++** If this is a temporary file (pRbu!=0 && flags&DELETE_ON_CLOSE), variable ++** "sz" is set to the current size of the database file. + */ + struct rbu_file { + sqlite3_file base; /* sqlite3_file methods */ +@@ -170828,6 +187201,7 @@ + sqlite3_file *pReal; /* Underlying file handle */ + rbu_vfs *pRbuVfs; /* Pointer to the rbu_vfs object */ + sqlite3rbu *pRbu; /* Pointer to rbu object (rbu target only) */ ++ i64 sz; /* Size of file in bytes (temp only) */ + + int openFlags; /* Flags this file was opened with */ + u32 iCookie; /* Cookie value for main db files */ +@@ -170841,6 +187215,7 @@ + const char *zWal; /* Wal filename for this main db file */ + rbu_file *pWalFd; /* Wal file descriptor for this main db */ + rbu_file *pMainNext; /* Next MAIN_DB file */ ++ rbu_file *pMainRbuNext; /* Next MAIN_DB file with pRbu!=0 */ + }; + + /* +@@ -170890,6 +187265,7 @@ + return v; + } + ++#if RBU_ENABLE_DELTA_CKSUM + /* + ** Compute a 32-bit checksum on the N-byte buffer. Return the result. + */ +@@ -170924,6 +187300,7 @@ + } + return sum3; + } ++#endif + + /* + ** Apply a delta. +@@ -170954,7 +187331,7 @@ + ){ + unsigned int limit; + unsigned int total = 0; +-#ifndef FOSSIL_OMIT_DELTA_CKSUM_TEST ++#if RBU_ENABLE_DELTA_CKSUM + char *zOrigOut = zOut; + #endif + +@@ -171009,7 +187386,7 @@ + case ';': { + zDelta++; lenDelta--; + zOut[0] = 0; +-#ifndef FOSSIL_OMIT_DELTA_CKSUM_TEST ++#if RBU_ENABLE_DELTA_CKSUM + if( cnt!=rbuDeltaChecksum(zOrigOut, total) ){ + /* ERROR: bad checksum */ + return -1; +@@ -172217,7 +188594,7 @@ + int iCid = sqlite3_column_int(pXInfo, 1); + int bDesc = sqlite3_column_int(pXInfo, 3); + const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4); +- zCols = rbuMPrintf(p, "%z%sc%d %s COLLATE %s", zCols, zComma, ++ zCols = rbuMPrintf(p, "%z%sc%d %s COLLATE %Q", zCols, zComma, + iCid, pIter->azTblType[iCid], zCollate + ); + zPk = rbuMPrintf(p, "%z%sc%d%s", zPk, zComma, iCid, bDesc?" DESC":""); +@@ -172278,7 +188655,7 @@ + ** "PRIMARY KEY" to the imposter table column declaration. */ + zPk = "PRIMARY KEY "; + } +- zSql = rbuMPrintf(p, "%z%s\"%w\" %s %sCOLLATE %s%s", ++ zSql = rbuMPrintf(p, "%z%s\"%w\" %s %sCOLLATE %Q%s", + zSql, zComma, zCol, pIter->azTblType[iCol], zPk, zColl, + (pIter->abNotNull[iCol] ? " NOT NULL" : "") + ); +@@ -172679,6 +189056,7 @@ + static void rbuFreeState(RbuState *p){ + if( p ){ + sqlite3_free(p->zTbl); ++ sqlite3_free(p->zDataTbl); + sqlite3_free(p->zIdx); + sqlite3_free(p); + } +@@ -172749,6 +189127,10 @@ + pRet->nPhaseOneStep = sqlite3_column_int64(pStmt, 1); + break; + ++ case RBU_STATE_DATATBL: ++ pRet->zDataTbl = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc); ++ break; ++ + default: + rc = SQLITE_CORRUPT; + break; +@@ -173523,7 +189905,8 @@ + "(%d, %lld), " + "(%d, %lld), " + "(%d, %lld), " +- "(%d, %lld) ", ++ "(%d, %lld), " ++ "(%d, %Q) ", + p->zStateDb, + RBU_STATE_STAGE, eStage, + RBU_STATE_TBL, p->objiter.zTbl, +@@ -173533,7 +189916,8 @@ + RBU_STATE_CKPT, p->iWalCksum, + RBU_STATE_COOKIE, (i64)pFd->iCookie, + RBU_STATE_OALSZ, p->iOalSz, +- RBU_STATE_PHASEONESTEP, p->nPhaseOneStep ++ RBU_STATE_PHASEONESTEP, p->nPhaseOneStep, ++ RBU_STATE_DATATBL, p->objiter.zDataTbl + ) + ); + assert( pInsert==0 || rc==SQLITE_OK ); +@@ -173789,7 +190173,8 @@ + + while( rc==SQLITE_OK && pIter->zTbl && (pIter->bCleanup + || rbuStrCompare(pIter->zIdx, pState->zIdx) +- || rbuStrCompare(pIter->zTbl, pState->zTbl) ++ || (pState->zDataTbl==0 && rbuStrCompare(pIter->zTbl, pState->zTbl)) ++ || (pState->zDataTbl && rbuStrCompare(pIter->zDataTbl, pState->zDataTbl)) + )){ + rc = rbuObjIterNext(p, pIter); + } +@@ -173841,6 +190226,7 @@ + sqlite3_vfs *pVfs = sqlite3_vfs_find(zRnd); + assert( pVfs ); + p->zVfsName = pVfs->zName; ++ ((rbu_vfs*)pVfs)->pRbu = p; + } + } + +@@ -174213,6 +190599,7 @@ + /* Close the open database handle and VFS object. */ + sqlite3_close(p->dbRbu); + sqlite3_close(p->dbMain); ++ assert( p->szTemp==0 ); + rbuDeleteVfs(p); + sqlite3_free(p->aBuf); + sqlite3_free(p->aFrame); +@@ -174400,6 +190787,7 @@ + */ + + static void rbuUnlockShm(rbu_file *p){ ++ assert( p->openFlags & SQLITE_OPEN_MAIN_DB ); + if( p->pRbu ){ + int (*xShmLock)(sqlite3_file*,int,int,int) = p->pReal->pMethods->xShmLock; + int i; +@@ -174413,6 +190801,81 @@ + } + + /* ++*/ ++static int rbuUpdateTempSize(rbu_file *pFd, sqlite3_int64 nNew){ ++ sqlite3rbu *pRbu = pFd->pRbu; ++ i64 nDiff = nNew - pFd->sz; ++ pRbu->szTemp += nDiff; ++ pFd->sz = nNew; ++ assert( pRbu->szTemp>=0 ); ++ if( pRbu->szTempLimit && pRbu->szTemp>pRbu->szTempLimit ) return SQLITE_FULL; ++ return SQLITE_OK; ++} ++ ++/* ++** Add an item to the main-db lists, if it is not already present. ++** ++** There are two main-db lists. One for all file descriptors, and one ++** for all file descriptors with rbu_file.pDb!=0. If the argument has ++** rbu_file.pDb!=0, then it is assumed to already be present on the ++** main list and is only added to the pDb!=0 list. ++*/ ++static void rbuMainlistAdd(rbu_file *p){ ++ rbu_vfs *pRbuVfs = p->pRbuVfs; ++ rbu_file *pIter; ++ assert( (p->openFlags & SQLITE_OPEN_MAIN_DB) ); ++ sqlite3_mutex_enter(pRbuVfs->mutex); ++ if( p->pRbu==0 ){ ++ for(pIter=pRbuVfs->pMain; pIter; pIter=pIter->pMainNext); ++ p->pMainNext = pRbuVfs->pMain; ++ pRbuVfs->pMain = p; ++ }else{ ++ for(pIter=pRbuVfs->pMainRbu; pIter && pIter!=p; pIter=pIter->pMainRbuNext){} ++ if( pIter==0 ){ ++ p->pMainRbuNext = pRbuVfs->pMainRbu; ++ pRbuVfs->pMainRbu = p; ++ } ++ } ++ sqlite3_mutex_leave(pRbuVfs->mutex); ++} ++ ++/* ++** Remove an item from the main-db lists. ++*/ ++static void rbuMainlistRemove(rbu_file *p){ ++ rbu_file **pp; ++ sqlite3_mutex_enter(p->pRbuVfs->mutex); ++ for(pp=&p->pRbuVfs->pMain; *pp && *pp!=p; pp=&((*pp)->pMainNext)){} ++ if( *pp ) *pp = p->pMainNext; ++ p->pMainNext = 0; ++ for(pp=&p->pRbuVfs->pMainRbu; *pp && *pp!=p; pp=&((*pp)->pMainRbuNext)){} ++ if( *pp ) *pp = p->pMainRbuNext; ++ p->pMainRbuNext = 0; ++ sqlite3_mutex_leave(p->pRbuVfs->mutex); ++} ++ ++/* ++** Given that zWal points to a buffer containing a wal file name passed to ++** either the xOpen() or xAccess() VFS method, search the main-db list for ++** a file-handle opened by the same database connection on the corresponding ++** database file. ++** ++** If parameter bRbu is true, only search for file-descriptors with ++** rbu_file.pDb!=0. ++*/ ++static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal, int bRbu){ ++ rbu_file *pDb; ++ sqlite3_mutex_enter(pRbuVfs->mutex); ++ if( bRbu ){ ++ for(pDb=pRbuVfs->pMainRbu; pDb && pDb->zWal!=zWal; pDb=pDb->pMainRbuNext){} ++ }else{ ++ for(pDb=pRbuVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext){} ++ } ++ sqlite3_mutex_leave(pRbuVfs->mutex); ++ return pDb; ++} ++ ++/* + ** Close an rbu file. + */ + static int rbuVfsClose(sqlite3_file *pFile){ +@@ -174429,14 +190892,14 @@ + sqlite3_free(p->zDel); + + if( p->openFlags & SQLITE_OPEN_MAIN_DB ){ +- rbu_file **pp; +- sqlite3_mutex_enter(p->pRbuVfs->mutex); +- for(pp=&p->pRbuVfs->pMain; *pp!=p; pp=&((*pp)->pMainNext)); +- *pp = p->pMainNext; +- sqlite3_mutex_leave(p->pRbuVfs->mutex); ++ rbuMainlistRemove(p); + rbuUnlockShm(p); + p->pReal->pMethods->xShmUnmap(p->pReal, 0); + } ++ else if( (p->openFlags & SQLITE_OPEN_DELETEONCLOSE) && p->pRbu ){ ++ rbuUpdateTempSize(p, 0); ++ } ++ assert( p->pMainNext==0 && p->pRbuVfs->pMain!=p ); + + /* Close the underlying file handle */ + rc = p->pReal->pMethods->xClose(p->pReal); +@@ -174554,11 +191017,19 @@ + assert( p->openFlags & SQLITE_OPEN_MAIN_DB ); + rc = rbuCaptureDbWrite(p->pRbu, iOfst); + }else{ +- if( pRbu && pRbu->eStage==RBU_STAGE_OAL +- && (p->openFlags & SQLITE_OPEN_WAL) +- && iOfst>=pRbu->iOalSz +- ){ +- pRbu->iOalSz = iAmt + iOfst; ++ if( pRbu ){ ++ if( pRbu->eStage==RBU_STAGE_OAL ++ && (p->openFlags & SQLITE_OPEN_WAL) ++ && iOfst>=pRbu->iOalSz ++ ){ ++ pRbu->iOalSz = iAmt + iOfst; ++ }else if( p->openFlags & SQLITE_OPEN_DELETEONCLOSE ){ ++ i64 szNew = iAmt+iOfst; ++ if( szNew>p->sz ){ ++ rc = rbuUpdateTempSize(p, szNew); ++ if( rc!=SQLITE_OK ) return rc; ++ } ++ } + } + rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst); + if( rc==SQLITE_OK && iOfst==0 && (p->openFlags & SQLITE_OPEN_MAIN_DB) ){ +@@ -174577,6 +191048,10 @@ + */ + static int rbuVfsTruncate(sqlite3_file *pFile, sqlite_int64 size){ + rbu_file *p = (rbu_file*)pFile; ++ if( (p->openFlags & SQLITE_OPEN_DELETEONCLOSE) && p->pRbu ){ ++ int rc = rbuUpdateTempSize(p, size); ++ if( rc!=SQLITE_OK ) return rc; ++ } + return p->pReal->pMethods->xTruncate(p->pReal, size); + } + +@@ -174683,6 +191158,9 @@ + }else if( rc==SQLITE_NOTFOUND ){ + pRbu->pTargetFd = p; + p->pRbu = pRbu; ++ if( p->openFlags & SQLITE_OPEN_MAIN_DB ){ ++ rbuMainlistAdd(p); ++ } + if( p->pWalFd ) p->pWalFd->pRbu = pRbu; + rc = SQLITE_OK; + } +@@ -174844,20 +191322,6 @@ + return rc; + } + +-/* +-** Given that zWal points to a buffer containing a wal file name passed to +-** either the xOpen() or xAccess() VFS method, return a pointer to the +-** file-handle opened by the same database connection on the corresponding +-** database file. +-*/ +-static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal){ +- rbu_file *pDb; +- sqlite3_mutex_enter(pRbuVfs->mutex); +- for(pDb=pRbuVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext){} +- sqlite3_mutex_leave(pRbuVfs->mutex); +- return pDb; +-} +- + /* + ** A main database named zName has just been opened. The following + ** function returns a pointer to a buffer owned by SQLite that contains +@@ -174936,7 +191400,7 @@ + pFd->zWal = rbuMainToWal(zName, flags); + } + else if( flags & SQLITE_OPEN_WAL ){ +- rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName); ++ rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName, 0); + if( pDb ){ + if( pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){ + /* This call is to open a *-wal file. Intead, open the *-oal. This +@@ -174966,6 +191430,8 @@ + pDb->pWalFd = pFd; + } + } ++ }else{ ++ pFd->pRbu = pRbuVfs->pRbu; + } + + if( oflags & SQLITE_OPEN_MAIN_DB +@@ -174986,10 +191452,7 @@ + ** mutex protected linked list of all such files. */ + pFile->pMethods = &rbuvfs_io_methods; + if( flags & SQLITE_OPEN_MAIN_DB ){ +- sqlite3_mutex_enter(pRbuVfs->mutex); +- pFd->pMainNext = pRbuVfs->pMain; +- pRbuVfs->pMain = pFd; +- sqlite3_mutex_leave(pRbuVfs->mutex); ++ rbuMainlistAdd(pFd); + } + }else{ + sqlite3_free(pFd->zDel); +@@ -175037,12 +191500,14 @@ + ** file opened instead. + */ + if( rc==SQLITE_OK && flags==SQLITE_ACCESS_EXISTS ){ +- rbu_file *pDb = rbuFindMaindb(pRbuVfs, zPath); ++ rbu_file *pDb = rbuFindMaindb(pRbuVfs, zPath, 1); + if( pDb && pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){ + if( *pResOut ){ + rc = SQLITE_CANTOPEN; + }else{ +- *pResOut = 1; ++ sqlite3_int64 sz = 0; ++ rc = rbuVfsFileSize(&pDb->base, &sz); ++ *pResOut = (sz>0); + } + } + } +@@ -175231,7 +191696,21 @@ + return rc; + } + ++/* ++** Configure the aggregate temp file size limit for this RBU handle. ++*/ ++SQLITE_API sqlite3_int64 sqlite3rbu_temp_size_limit(sqlite3rbu *pRbu, sqlite3_int64 n){ ++ if( n>=0 ){ ++ pRbu->szTempLimit = n; ++ } ++ return pRbu->szTempLimit; ++} + ++SQLITE_API sqlite3_int64 sqlite3rbu_temp_size(sqlite3rbu *pRbu){ ++ return pRbu->szTemp; ++} ++ ++ + /**************************************************************************/ + + #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RBU) */ +@@ -175434,8 +191913,6 @@ + static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ + int i; + +- pIdxInfo->estimatedCost = 1.0e6; /* Initial cost estimate */ +- + /* Look for a valid schema=? constraint. If found, change the idxNum to + ** 1 and request the value of that constraint be sent to xFilter. And + ** lower the cost estimate to encourage the constrained version to be +@@ -175442,9 +191919,9 @@ + ** used. + */ + for(i=0; i<pIdxInfo->nConstraint; i++){ +- if( pIdxInfo->aConstraint[i].usable==0 ) continue; ++ if( pIdxInfo->aConstraint[i].iColumn!=10 ) continue; ++ if( pIdxInfo->aConstraint[i].usable==0 ) return SQLITE_CONSTRAINT; + if( pIdxInfo->aConstraint[i].op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; +- if( pIdxInfo->aConstraint[i].iColumn!=10 ) continue; + pIdxInfo->idxNum = 1; + pIdxInfo->estimatedCost = 1.0; + pIdxInfo->aConstraintUsage[i].argvIndex = 1; +@@ -175494,7 +191971,7 @@ + return SQLITE_OK; + } + +-static void statClearPage(StatPage *p){ ++static void statClearCells(StatPage *p){ + int i; + if( p->aCell ){ + for(i=0; i<p->nCell; i++){ +@@ -175502,6 +191979,12 @@ + } + sqlite3_free(p->aCell); + } ++ p->nCell = 0; ++ p->aCell = 0; ++} ++ ++static void statClearPage(StatPage *p){ ++ statClearCells(p); + sqlite3PagerUnref(p->pPg); + sqlite3_free(p->zPath); + memset(p, 0, sizeof(StatPage)); +@@ -175564,22 +192047,33 @@ + u8 *aHdr = &aData[p->iPgno==1 ? 100 : 0]; + + p->flags = aHdr[0]; ++ if( p->flags==0x0A || p->flags==0x0D ){ ++ isLeaf = 1; ++ nHdr = 8; ++ }else if( p->flags==0x05 || p->flags==0x02 ){ ++ isLeaf = 0; ++ nHdr = 12; ++ }else{ ++ goto statPageIsCorrupt; ++ } ++ if( p->iPgno==1 ) nHdr += 100; + p->nCell = get2byte(&aHdr[3]); + p->nMxPayload = 0; ++ szPage = sqlite3BtreeGetPageSize(pBt); + +- isLeaf = (p->flags==0x0A || p->flags==0x0D); +- nHdr = 12 - isLeaf*4 + (p->iPgno==1)*100; +- + nUnused = get2byte(&aHdr[5]) - nHdr - 2*p->nCell; + nUnused += (int)aHdr[7]; + iOff = get2byte(&aHdr[1]); + while( iOff ){ ++ int iNext; ++ if( iOff>=szPage ) goto statPageIsCorrupt; + nUnused += get2byte(&aData[iOff+2]); +- iOff = get2byte(&aData[iOff]); ++ iNext = get2byte(&aData[iOff]); ++ if( iNext<iOff+4 && iNext>0 ) goto statPageIsCorrupt; ++ iOff = iNext; + } + p->nUnused = nUnused; + p->iRightChildPg = isLeaf ? 0 : sqlite3Get4byte(&aHdr[8]); +- szPage = sqlite3BtreeGetPageSize(pBt); + + if( p->nCell ){ + int i; /* Used to iterate through cells */ +@@ -175596,6 +192090,7 @@ + StatCell *pCell = &p->aCell[i]; + + iOff = get2byte(&aData[nHdr+i*2]); ++ if( iOff<nHdr || iOff>=szPage ) goto statPageIsCorrupt; + if( !isLeaf ){ + pCell->iChildPg = sqlite3Get4byte(&aData[iOff]); + iOff += 4; +@@ -175612,13 +192107,14 @@ + } + if( nPayload>(u32)p->nMxPayload ) p->nMxPayload = nPayload; + getLocalPayload(nUsable, p->flags, nPayload, &nLocal); ++ if( nLocal<0 ) goto statPageIsCorrupt; + pCell->nLocal = nLocal; +- assert( nLocal>=0 ); + assert( nPayload>=(u32)nLocal ); + assert( nLocal<=(nUsable-35) ); + if( nPayload>(u32)nLocal ){ + int j; + int nOvfl = ((nPayload - nLocal) + nUsable-4 - 1) / (nUsable - 4); ++ if( iOff+nLocal>nUsable ) goto statPageIsCorrupt; + pCell->nLastOvfl = (nPayload-nLocal) - (nOvfl-1) * (nUsable-4); + pCell->nOvfl = nOvfl; + pCell->aOvfl = sqlite3_malloc64(sizeof(u32)*nOvfl); +@@ -175642,6 +192138,11 @@ + } + + return SQLITE_OK; ++ ++statPageIsCorrupt: ++ p->flags = 0; ++ statClearCells(p); ++ return SQLITE_OK; + } + + /* +@@ -175664,7 +192165,7 @@ + */ + fd = sqlite3PagerFile(pPager); + x[0] = pCsr->iPageno; +- if( fd->pMethods!=0 && sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){ ++ if( sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){ + pCsr->iOffset = x[0]; + pCsr->szPage = (int)x[1]; + } +@@ -175937,6 +192438,7 @@ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ ++ 0 /* xShadowName */ + }; + return sqlite3_create_module(db, "dbstat", &dbstat_module, 0); + } +@@ -175945,6 +192447,424 @@ + #endif /* SQLITE_ENABLE_DBSTAT_VTAB */ + + /************** End of dbstat.c **********************************************/ ++/************** Begin file dbpage.c ******************************************/ ++/* ++** 2017-10-11 ++** ++** The author disclaims copyright to this source code. In place of ++** a legal notice, here is a blessing: ++** ++** May you do good and not evil. ++** May you find forgiveness for yourself and forgive others. ++** May you share freely, never taking more than you give. ++** ++****************************************************************************** ++** ++** This file contains an implementation of the "sqlite_dbpage" virtual table. ++** ++** The sqlite_dbpage virtual table is used to read or write whole raw ++** pages of the database file. The pager interface is used so that ++** uncommitted changes and changes recorded in the WAL file are correctly ++** retrieved. ++** ++** Usage example: ++** ++** SELECT data FROM sqlite_dbpage('aux1') WHERE pgno=123; ++** ++** This is an eponymous virtual table so it does not need to be created before ++** use. The optional argument to the sqlite_dbpage() table name is the ++** schema for the database file that is to be read. The default schema is ++** "main". ++** ++** The data field of sqlite_dbpage table can be updated. The new ++** value must be a BLOB which is the correct page size, otherwise the ++** update fails. Rows may not be deleted or inserted. ++*/ ++ ++/* #include "sqliteInt.h" ** Requires access to internal data structures ** */ ++#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \ ++ && !defined(SQLITE_OMIT_VIRTUALTABLE) ++ ++typedef struct DbpageTable DbpageTable; ++typedef struct DbpageCursor DbpageCursor; ++ ++struct DbpageCursor { ++ sqlite3_vtab_cursor base; /* Base class. Must be first */ ++ int pgno; /* Current page number */ ++ int mxPgno; /* Last page to visit on this scan */ ++ Pager *pPager; /* Pager being read/written */ ++ DbPage *pPage1; /* Page 1 of the database */ ++ int iDb; /* Index of database to analyze */ ++ int szPage; /* Size of each page in bytes */ ++}; ++ ++struct DbpageTable { ++ sqlite3_vtab base; /* Base class. Must be first */ ++ sqlite3 *db; /* The database */ ++}; ++ ++/* Columns */ ++#define DBPAGE_COLUMN_PGNO 0 ++#define DBPAGE_COLUMN_DATA 1 ++#define DBPAGE_COLUMN_SCHEMA 2 ++ ++ ++ ++/* ++** Connect to or create a dbpagevfs virtual table. ++*/ ++static int dbpageConnect( ++ sqlite3 *db, ++ void *pAux, ++ int argc, const char *const*argv, ++ sqlite3_vtab **ppVtab, ++ char **pzErr ++){ ++ DbpageTable *pTab = 0; ++ int rc = SQLITE_OK; ++ ++ 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; ++ } ++ ++ assert( rc==SQLITE_OK || pTab==0 ); ++ if( rc==SQLITE_OK ){ ++ memset(pTab, 0, sizeof(DbpageTable)); ++ pTab->db = db; ++ } ++ ++ *ppVtab = (sqlite3_vtab*)pTab; ++ return rc; ++} ++ ++/* ++** Disconnect from or destroy a dbpagevfs virtual table. ++*/ ++static int dbpageDisconnect(sqlite3_vtab *pVtab){ ++ sqlite3_free(pVtab); ++ return SQLITE_OK; ++} ++ ++/* ++** idxNum: ++** ++** 0 schema=main, full table scan ++** 1 schema=main, pgno=?1 ++** 2 schema=?1, full table scan ++** 3 schema=?1, pgno=?2 ++*/ ++static int dbpageBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ ++ int i; ++ int iPlan = 0; ++ ++ /* If there is a schema= constraint, it must be honored. Report a ++ ** ridiculously large estimated cost if the schema= constraint is ++ ** unavailable ++ */ ++ for(i=0; i<pIdxInfo->nConstraint; i++){ ++ struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i]; ++ if( p->iColumn!=DBPAGE_COLUMN_SCHEMA ) continue; ++ if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; ++ if( !p->usable ){ ++ /* No solution. */ ++ return SQLITE_CONSTRAINT; ++ } ++ iPlan = 2; ++ pIdxInfo->aConstraintUsage[i].argvIndex = 1; ++ pIdxInfo->aConstraintUsage[i].omit = 1; ++ break; ++ } ++ ++ /* If we reach this point, it means that either there is no schema= ++ ** constraint (in which case we use the "main" schema) or else the ++ ** schema constraint was accepted. Lower the estimated cost accordingly ++ */ ++ pIdxInfo->estimatedCost = 1.0e6; ++ ++ /* Check for constraints against pgno */ ++ for(i=0; i<pIdxInfo->nConstraint; i++){ ++ struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i]; ++ if( p->usable && p->iColumn<=0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ ++ pIdxInfo->estimatedRows = 1; ++ pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE; ++ pIdxInfo->estimatedCost = 1.0; ++ pIdxInfo->aConstraintUsage[i].argvIndex = iPlan ? 2 : 1; ++ pIdxInfo->aConstraintUsage[i].omit = 1; ++ iPlan |= 1; ++ break; ++ } ++ } ++ pIdxInfo->idxNum = iPlan; ++ ++ 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){ ++ DbpageCursor *pCsr; ++ ++ pCsr = (DbpageCursor *)sqlite3_malloc64(sizeof(DbpageCursor)); ++ if( pCsr==0 ){ ++ return SQLITE_NOMEM_BKPT; ++ }else{ ++ memset(pCsr, 0, sizeof(DbpageCursor)); ++ pCsr->base.pVtab = pVTab; ++ pCsr->pgno = -1; ++ } ++ ++ *ppCursor = (sqlite3_vtab_cursor *)pCsr; ++ return SQLITE_OK; ++} ++ ++/* ++** Close a dbpagevfs cursor. ++*/ ++static int dbpageClose(sqlite3_vtab_cursor *pCursor){ ++ DbpageCursor *pCsr = (DbpageCursor *)pCursor; ++ if( pCsr->pPage1 ) sqlite3PagerUnrefPageOne(pCsr->pPage1); ++ sqlite3_free(pCsr); ++ return SQLITE_OK; ++} ++ ++/* ++** Move a dbpagevfs cursor to the next entry in the file. ++*/ ++static int dbpageNext(sqlite3_vtab_cursor *pCursor){ ++ int rc = SQLITE_OK; ++ DbpageCursor *pCsr = (DbpageCursor *)pCursor; ++ pCsr->pgno++; ++ return rc; ++} ++ ++static int dbpageEof(sqlite3_vtab_cursor *pCursor){ ++ DbpageCursor *pCsr = (DbpageCursor *)pCursor; ++ return pCsr->pgno > pCsr->mxPgno; ++} ++ ++/* ++** idxNum: ++** ++** 0 schema=main, full table scan ++** 1 schema=main, pgno=?1 ++** 2 schema=?1, full table scan ++** 3 schema=?1, pgno=?2 ++** ++** idxStr is not used ++*/ ++static int dbpageFilter( ++ sqlite3_vtab_cursor *pCursor, ++ int idxNum, const char *idxStr, ++ int argc, sqlite3_value **argv ++){ ++ DbpageCursor *pCsr = (DbpageCursor *)pCursor; ++ DbpageTable *pTab = (DbpageTable *)pCursor->pVtab; ++ int rc; ++ sqlite3 *db = pTab->db; ++ Btree *pBt; ++ ++ /* Default setting is no rows of result */ ++ pCsr->pgno = 1; ++ pCsr->mxPgno = 0; ++ ++ if( idxNum & 2 ){ ++ const char *zSchema; ++ assert( argc>=1 ); ++ zSchema = (const char*)sqlite3_value_text(argv[0]); ++ pCsr->iDb = sqlite3FindDbName(db, zSchema); ++ if( pCsr->iDb<0 ) return SQLITE_OK; ++ }else{ ++ pCsr->iDb = 0; ++ } ++ pBt = db->aDb[pCsr->iDb].pBt; ++ if( pBt==0 ) return SQLITE_OK; ++ pCsr->pPager = sqlite3BtreePager(pBt); ++ pCsr->szPage = sqlite3BtreeGetPageSize(pBt); ++ pCsr->mxPgno = sqlite3BtreeLastPage(pBt); ++ if( idxNum & 1 ){ ++ assert( argc>(idxNum>>1) ); ++ pCsr->pgno = sqlite3_value_int(argv[idxNum>>1]); ++ if( pCsr->pgno<1 || pCsr->pgno>pCsr->mxPgno ){ ++ pCsr->pgno = 1; ++ pCsr->mxPgno = 0; ++ }else{ ++ pCsr->mxPgno = pCsr->pgno; ++ } ++ }else{ ++ assert( pCsr->pgno==1 ); ++ } ++ if( pCsr->pPage1 ) sqlite3PagerUnrefPageOne(pCsr->pPage1); ++ rc = sqlite3PagerGet(pCsr->pPager, 1, &pCsr->pPage1, 0); ++ return rc; ++} ++ ++static int dbpageColumn( ++ sqlite3_vtab_cursor *pCursor, ++ sqlite3_context *ctx, ++ int i ++){ ++ DbpageCursor *pCsr = (DbpageCursor *)pCursor; ++ int rc = SQLITE_OK; ++ switch( i ){ ++ case 0: { /* pgno */ ++ sqlite3_result_int(ctx, pCsr->pgno); ++ break; ++ } ++ case 1: { /* data */ ++ DbPage *pDbPage = 0; ++ rc = sqlite3PagerGet(pCsr->pPager, pCsr->pgno, (DbPage**)&pDbPage, 0); ++ if( rc==SQLITE_OK ){ ++ sqlite3_result_blob(ctx, sqlite3PagerGetData(pDbPage), pCsr->szPage, ++ SQLITE_TRANSIENT); ++ } ++ sqlite3PagerUnref(pDbPage); ++ break; ++ } ++ default: { /* schema */ ++ sqlite3 *db = sqlite3_context_db_handle(ctx); ++ sqlite3_result_text(ctx, db->aDb[pCsr->iDb].zDbSName, -1, SQLITE_STATIC); ++ break; ++ } ++ } ++ return SQLITE_OK; ++} ++ ++static int dbpageRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ ++ DbpageCursor *pCsr = (DbpageCursor *)pCursor; ++ *pRowid = pCsr->pgno; ++ return SQLITE_OK; ++} ++ ++static int dbpageUpdate( ++ sqlite3_vtab *pVtab, ++ int argc, ++ sqlite3_value **argv, ++ sqlite_int64 *pRowid ++){ ++ DbpageTable *pTab = (DbpageTable *)pVtab; ++ Pgno pgno; ++ DbPage *pDbPage = 0; ++ int rc = SQLITE_OK; ++ char *zErr = 0; ++ const char *zSchema; ++ int iDb; ++ Btree *pBt; ++ Pager *pPager; ++ int szPage; ++ ++ if( pTab->db->flags & SQLITE_Defensive ){ ++ zErr = "read-only"; ++ goto update_fail; ++ } ++ if( argc==1 ){ ++ zErr = "cannot delete"; ++ goto update_fail; ++ } ++ pgno = sqlite3_value_int(argv[0]); ++ if( (Pgno)sqlite3_value_int(argv[1])!=pgno ){ ++ zErr = "cannot insert"; ++ goto update_fail; ++ } ++ zSchema = (const char*)sqlite3_value_text(argv[4]); ++ iDb = zSchema ? sqlite3FindDbName(pTab->db, zSchema) : -1; ++ if( iDb<0 ){ ++ zErr = "no such schema"; ++ goto update_fail; ++ } ++ pBt = pTab->db->aDb[iDb].pBt; ++ if( pgno<1 || pBt==0 || pgno>(int)sqlite3BtreeLastPage(pBt) ){ ++ zErr = "bad page number"; ++ goto update_fail; ++ } ++ szPage = sqlite3BtreeGetPageSize(pBt); ++ if( sqlite3_value_type(argv[3])!=SQLITE_BLOB ++ || sqlite3_value_bytes(argv[3])!=szPage ++ ){ ++ zErr = "bad page value"; ++ goto update_fail; ++ } ++ pPager = sqlite3BtreePager(pBt); ++ rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pDbPage, 0); ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3PagerWrite(pDbPage); ++ if( rc==SQLITE_OK ){ ++ memcpy(sqlite3PagerGetData(pDbPage), ++ sqlite3_value_blob(argv[3]), ++ szPage); ++ } ++ } ++ sqlite3PagerUnref(pDbPage); ++ return rc; ++ ++update_fail: ++ sqlite3_free(pVtab->zErrMsg); ++ pVtab->zErrMsg = sqlite3_mprintf("%s", zErr); ++ return SQLITE_ERROR; ++} ++ ++/* Since we do not know in advance which database files will be ++** written by the sqlite_dbpage virtual table, start a write transaction ++** on them all. ++*/ ++static int dbpageBegin(sqlite3_vtab *pVtab){ ++ DbpageTable *pTab = (DbpageTable *)pVtab; ++ sqlite3 *db = pTab->db; ++ int i; ++ for(i=0; i<db->nDb; i++){ ++ Btree *pBt = db->aDb[i].pBt; ++ if( pBt ) sqlite3BtreeBeginTrans(pBt, 1, 0); ++ } ++ return SQLITE_OK; ++} ++ ++ ++/* ++** Invoke this routine to register the "dbpage" virtual table module ++*/ ++SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3 *db){ ++ static sqlite3_module dbpage_module = { ++ 0, /* iVersion */ ++ dbpageConnect, /* xCreate */ ++ dbpageConnect, /* xConnect */ ++ dbpageBestIndex, /* xBestIndex */ ++ dbpageDisconnect, /* xDisconnect */ ++ dbpageDisconnect, /* xDestroy */ ++ dbpageOpen, /* xOpen - open a cursor */ ++ dbpageClose, /* xClose - close a cursor */ ++ dbpageFilter, /* xFilter - configure scan constraints */ ++ dbpageNext, /* xNext - advance a cursor */ ++ dbpageEof, /* xEof - check for end of scan */ ++ dbpageColumn, /* xColumn - read data */ ++ dbpageRowid, /* xRowid - read data */ ++ dbpageUpdate, /* xUpdate */ ++ dbpageBegin, /* xBegin */ ++ 0, /* xSync */ ++ 0, /* xCommit */ ++ 0, /* xRollback */ ++ 0, /* xFindMethod */ ++ 0, /* xRename */ ++ 0, /* xSavepoint */ ++ 0, /* xRelease */ ++ 0, /* xRollbackTo */ ++ 0 /* xShadowName */ ++ }; ++ return sqlite3_create_module(db, "sqlite_dbpage", &dbpage_module, 0); ++} ++#elif defined(SQLITE_ENABLE_DBPAGE_VTAB) ++SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3 *db){ return SQLITE_OK; } ++#endif /* SQLITE_ENABLE_DBSTAT_VTAB */ ++ ++/************** End of dbpage.c **********************************************/ + /************** Begin file sqlite3session.c **********************************/ + + #if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK) +@@ -175973,6 +192893,8 @@ + # endif + #endif + ++static int sessions_strm_chunk_size = SESSIONS_STRM_CHUNK_SIZE; ++ + typedef struct SessionHook SessionHook; + struct SessionHook { + void *pCtx; +@@ -175994,6 +192916,7 @@ + int rc; /* Non-zero if an error has occurred */ + void *pFilterCtx; /* First argument to pass to xTableFilter */ + int (*xTableFilter)(void *pCtx, const char *zTab); ++ sqlite3_value *pZeroBlob; /* Value containing X'' */ + sqlite3_session *pNext; /* Next session object on same db. */ + SessionTable *pTable; /* List of attached tables */ + SessionHook hook; /* APIs to grab new and old data with */ +@@ -176015,7 +192938,7 @@ + ** sqlite3changeset_start_strm()). + */ + struct SessionInput { +- int bNoDiscard; /* If true, discard no data */ ++ int bNoDiscard; /* If true, do not discard in InputBuffer() */ + int iCurrent; /* Offset in aData[] of current change */ + int iNext; /* Offset in aData[] of next change */ + u8 *aData; /* Pointer to buffer containing changeset */ +@@ -176034,6 +192957,7 @@ + SessionInput in; /* Input buffer or stream */ + SessionBuffer tblhdr; /* Buffer to hold apValue/zTab/abPK/ */ + int bPatchset; /* True if this is a patchset */ ++ int bInvert; /* True to invert changeset */ + int rc; /* Iterator error code */ + sqlite3_stmt *pConflict; /* Points to conflicting row, if any */ + char *zTab; /* Current table */ +@@ -176061,6 +192985,7 @@ + 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 */ +@@ -176178,8 +193103,8 @@ + ** statement. + ** + ** For a DELETE change, all fields within the record except those associated +-** with PRIMARY KEY columns are set to "undefined". The PRIMARY KEY fields +-** contain the values identifying the row to delete. ++** with PRIMARY KEY columns are omitted. The PRIMARY KEY fields contain the ++** values identifying the row to delete. + ** + ** For an UPDATE change, all fields except those associated with PRIMARY KEY + ** columns and columns that are modified by the UPDATE are set to "undefined". +@@ -176189,6 +193114,42 @@ + ** The records associated with INSERT changes are in the same format as for + ** changesets. It is not possible for a record associated with an INSERT + ** change to contain a field set to "undefined". ++** ++** REBASE BLOB FORMAT: ++** ++** A rebase blob may be output by sqlite3changeset_apply_v2() and its ++** streaming equivalent for use with the sqlite3_rebaser APIs to rebase ++** existing changesets. A rebase blob contains one entry for each conflict ++** resolved using either the OMIT or REPLACE strategies within the apply_v2() ++** call. ++** ++** The format used for a rebase blob is very similar to that used for ++** changesets. All entries related to a single table are grouped together. ++** ++** Each group of entries begins with a table header in changeset format: ++** ++** 1 byte: Constant 0x54 (capital 'T') ++** Varint: Number of columns in the table. ++** nCol bytes: 0x01 for PK columns, 0x00 otherwise. ++** N bytes: Unqualified table name (encoded using UTF-8). Nul-terminated. ++** ++** Followed by one or more entries associated with the table. ++** ++** 1 byte: Either SQLITE_INSERT (0x12), DELETE (0x09). ++** 1 byte: Flag. 0x01 for REPLACE, 0x00 for OMIT. ++** record: (in the record format defined above). ++** ++** In a rebase blob, the first field is set to SQLITE_INSERT if the change ++** that caused the conflict was an INSERT or UPDATE, or to SQLITE_DELETE if ++** it was a DELETE. The second field is set to 0x01 if the conflict ++** resolution strategy was REPLACE, or 0x00 if it was OMIT. ++** ++** If the change that caused the conflict was a DELETE, then the single ++** record is a copy of the old.* record from the original changeset. If it ++** was an INSERT, then the single record is a copy of the new.* record. If ++** the conflicting change was an UPDATE, then the single record is a copy ++** of the new.* record with the PK fields filled in based on the original ++** old.* record. + */ + + /* +@@ -176444,6 +193405,7 @@ + h = sessionHashAppendBlob(h, n, z); + }else{ + assert( eType==SQLITE_NULL ); ++ assert( pTab->bStat1==0 || i!=1 ); + *pbNullPK = 1; + } + } +@@ -176461,7 +193423,7 @@ + static int sessionSerialLen(u8 *a){ + int e = *a; + int n; +- if( e==0 ) return 1; ++ if( e==0 || e==0xFF ) return 1; + if( e==SQLITE_NULL ) return 1; + if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9; + return sessionVarintGet(&a[1], &n) + 1 + n; +@@ -176541,7 +193503,7 @@ + int n1 = sessionSerialLen(a1); + int n2 = sessionSerialLen(a2); + +- if( pTab->abPK[iCol] && (n1!=n2 || memcmp(a1, a2, n1)) ){ ++ if( n1!=n2 || memcmp(a1, a2, n1) ){ + return 0; + } + a1 += n1; +@@ -176784,9 +193746,8 @@ + }else{ + z = sqlite3_value_blob(pVal); + } +- if( memcmp(a, z, n) ) return 0; ++ if( n>0 && memcmp(a, z, n) ) return 0; + a += n; +- break; + } + } + } +@@ -176842,9 +193803,7 @@ + + /* + ** This function queries the database for the names of the columns of table +-** zThis, in schema zDb. It is expected that the table has nCol columns. If +-** not, SQLITE_SCHEMA is returned and none of the output variables are +-** populated. ++** zThis, in schema zDb. + ** + ** Otherwise, if they are not NULL, variable *pnCol is set to the number + ** of columns in the database table and variable *pzTab is set to point to a +@@ -176865,9 +193824,7 @@ + ** *pabPK = {1, 0, 0, 1} + ** + ** All returned buffers are part of the same single allocation, which must +-** be freed using sqlite3_free() by the caller. If pazCol was not NULL, then +-** pointer *pazCol should be freed to release all memory. Otherwise, pointer +-** *pabPK. It is illegal for both pazCol and pabPK to be NULL. ++** be freed using sqlite3_free() by the caller + */ + static int sessionTableInfo( + sqlite3 *db, /* Database connection */ +@@ -176892,7 +193849,23 @@ + assert( pazCol && pabPK ); + + nThis = sqlite3Strlen30(zThis); +- zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, 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 ){ ++ /* For sqlite_stat1, pretend that (tbl,idx) is the PRIMARY KEY. */ ++ zPragma = sqlite3_mprintf( ++ "SELECT 0, 'tbl', '', 0, '', 1 UNION ALL " ++ "SELECT 1, 'idx', '', 0, '', 2 UNION ALL " ++ "SELECT 2, 'stat', '', 0, '', 0" ++ ); ++ }else if( rc==SQLITE_ERROR ){ ++ zPragma = sqlite3_mprintf(""); ++ }else{ ++ return rc; ++ } ++ }else{ ++ zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis); ++ } + if( !zPragma ) return SQLITE_NOMEM; + + rc = sqlite3_prepare_v2(db, zPragma, -1, &pStmt, 0); +@@ -176984,6 +193957,9 @@ + break; + } + } ++ if( 0==sqlite3_stricmp("sqlite_stat1", pTab->zName) ){ ++ pTab->bStat1 = 1; ++ } + } + } + return (pSession->rc || pTab->abPK==0); +@@ -176990,6 +193966,47 @@ + } + + /* ++** Versions of the four methods in object SessionHook for use with the ++** sqlite_stat1 table. The purpose of this is to substitute a zero-length ++** blob each time a NULL value is read from the "idx" column of the ++** sqlite_stat1 table. ++*/ ++typedef struct SessionStat1Ctx SessionStat1Ctx; ++struct SessionStat1Ctx { ++ SessionHook hook; ++ sqlite3_session *pSession; ++}; ++static int sessionStat1Old(void *pCtx, int iCol, sqlite3_value **ppVal){ ++ SessionStat1Ctx *p = (SessionStat1Ctx*)pCtx; ++ sqlite3_value *pVal = 0; ++ int rc = p->hook.xOld(p->hook.pCtx, iCol, &pVal); ++ if( rc==SQLITE_OK && iCol==1 && sqlite3_value_type(pVal)==SQLITE_NULL ){ ++ pVal = p->pSession->pZeroBlob; ++ } ++ *ppVal = pVal; ++ return rc; ++} ++static int sessionStat1New(void *pCtx, int iCol, sqlite3_value **ppVal){ ++ SessionStat1Ctx *p = (SessionStat1Ctx*)pCtx; ++ sqlite3_value *pVal = 0; ++ int rc = p->hook.xNew(p->hook.pCtx, iCol, &pVal); ++ if( rc==SQLITE_OK && iCol==1 && sqlite3_value_type(pVal)==SQLITE_NULL ){ ++ pVal = p->pSession->pZeroBlob; ++ } ++ *ppVal = pVal; ++ return rc; ++} ++static int sessionStat1Count(void *pCtx){ ++ SessionStat1Ctx *p = (SessionStat1Ctx*)pCtx; ++ return p->hook.xCount(p->hook.pCtx); ++} ++static int sessionStat1Depth(void *pCtx){ ++ SessionStat1Ctx *p = (SessionStat1Ctx*)pCtx; ++ return p->hook.xDepth(p->hook.pCtx); ++} ++ ++ ++/* + ** This function is only called from with a pre-update-hook reporting a + ** change on table pTab (attached to session pSession). The type of change + ** (UPDATE, INSERT, DELETE) is specified by the first argument. +@@ -177005,6 +194022,7 @@ + int iHash; + int bNull = 0; + int rc = SQLITE_OK; ++ SessionStat1Ctx stat1 = {0}; + + if( pSession->rc ) return; + +@@ -177024,6 +194042,25 @@ + return; + } + ++ if( pTab->bStat1 ){ ++ stat1.hook = pSession->hook; ++ stat1.pSession = pSession; ++ pSession->hook.pCtx = (void*)&stat1; ++ pSession->hook.xNew = sessionStat1New; ++ pSession->hook.xOld = sessionStat1Old; ++ pSession->hook.xCount = sessionStat1Count; ++ pSession->hook.xDepth = sessionStat1Depth; ++ if( pSession->pZeroBlob==0 ){ ++ sqlite3_value *p = sqlite3ValueNew(0); ++ if( p==0 ){ ++ rc = SQLITE_NOMEM; ++ goto error_out; ++ } ++ sqlite3ValueSetStr(p, 0, "", 0, SQLITE_STATIC); ++ 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. */ +@@ -177113,6 +194150,9 @@ + + /* If an error has occurred, mark the session object as failed. */ + error_out: ++ if( pTab->bStat1 ){ ++ pSession->hook = stat1.hook; ++ } + if( rc!=SQLITE_OK ){ + pSession->rc = rc; + } +@@ -177449,7 +194489,6 @@ + if( abPK[i] ) bHasPk = 1; + } + } +- + } + sqlite3_free((char*)azCol); + if( bMismatch ){ +@@ -177575,6 +194614,7 @@ + } + } + sqlite3_mutex_leave(sqlite3_db_mutex(db)); ++ sqlite3ValueFree(pSession->pZeroBlob); + + /* Delete all attached table objects. And the contents of their + ** associated hash-tables. */ +@@ -177660,12 +194700,12 @@ + static int sessionBufferGrow(SessionBuffer *p, int nByte, int *pRc){ + if( *pRc==SQLITE_OK && p->nAlloc-p->nBuf<nByte ){ + u8 *aNew; +- int nNew = p->nAlloc ? p->nAlloc : 128; ++ i64 nNew = p->nAlloc ? p->nAlloc : 128; + do { + nNew = nNew*2; +- }while( nNew<(p->nBuf+nByte) ); ++ }while( (nNew-p->nBuf)<nByte ); + +- aNew = (u8 *)sqlite3_realloc(p->aBuf, nNew); ++ aNew = (u8 *)sqlite3_realloc64(p->aBuf, nNew); + if( 0==aNew ){ + *pRc = SQLITE_NOMEM; + }else{ +@@ -178042,28 +195082,42 @@ + sqlite3_stmt **ppStmt /* OUT: Prepared SELECT statement */ + ){ + int rc = SQLITE_OK; +- int i; +- const char *zSep = ""; +- SessionBuffer buf = {0, 0, 0}; ++ char *zSql = 0; ++ int nSql = -1; + +- 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, " = ?", &rc); +- sessionAppendInteger(&buf, i+1, &rc); +- zSep = " AND "; ++ 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, (char *)buf.aBuf, buf.nBuf, ppStmt, 0); ++ rc = sqlite3_prepare_v2(db, zSql, nSql, ppStmt, 0); + } +- sqlite3_free(buf.aBuf); ++ sqlite3_free(zSql); + return rc; + } + +@@ -178249,12 +195303,12 @@ + rc = sqlite3_reset(pSel); + } + +- /* If the buffer is now larger than SESSIONS_STRM_CHUNK_SIZE, pass ++ /* If the buffer is now larger than sessions_strm_chunk_size, pass + ** its contents to the xOutput() callback. */ + if( xOutput + && rc==SQLITE_OK + && buf.nBuf>nNoop +- && buf.nBuf>SESSIONS_STRM_CHUNK_SIZE ++ && buf.nBuf>sessions_strm_chunk_size + ){ + rc = xOutput(pOut, (void*)buf.aBuf, buf.nBuf); + nNoop = -1; +@@ -178393,7 +195447,8 @@ + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int nChangeset, /* Size of buffer pChangeset in bytes */ +- void *pChangeset /* Pointer to buffer containing changeset */ ++ void *pChangeset, /* Pointer to buffer containing changeset */ ++ int bInvert /* True to invert changeset */ + ){ + sqlite3_changeset_iter *pRet; /* Iterator to return */ + int nByte; /* Number of bytes to allocate for iterator */ +@@ -178413,6 +195468,7 @@ + pRet->in.xInput = xInput; + pRet->in.pIn = pIn; + pRet->in.bEof = (xInput ? 0 : 1); ++ pRet->bInvert = bInvert; + + /* Populate the output variable and return success. */ + *pp = pRet; +@@ -178427,8 +195483,17 @@ + int nChangeset, /* Size of buffer pChangeset in bytes */ + void *pChangeset /* Pointer to buffer containing changeset */ + ){ +- return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset); ++ return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, 0); + } ++SQLITE_API int sqlite3changeset_start_v2( ++ sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ ++ int nChangeset, /* Size of buffer pChangeset in bytes */ ++ void *pChangeset, /* Pointer to buffer containing changeset */ ++ int flags ++){ ++ int bInvert = !!(flags & SQLITE_CHANGESETSTART_INVERT); ++ return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, bInvert); ++} + + /* + ** Streaming version of sqlite3changeset_start(). +@@ -178438,8 +195503,17 @@ + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn + ){ +- return sessionChangesetStart(pp, xInput, pIn, 0, 0); ++ return sessionChangesetStart(pp, xInput, pIn, 0, 0, 0); + } ++SQLITE_API int sqlite3changeset_start_v2_strm( ++ sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ ++ int (*xInput)(void *pIn, void *pData, int *pnData), ++ void *pIn, ++ int flags ++){ ++ int bInvert = !!(flags & SQLITE_CHANGESETSTART_INVERT); ++ return sessionChangesetStart(pp, xInput, pIn, 0, 0, bInvert); ++} + + /* + ** If the SessionInput object passed as the only argument is a streaming +@@ -178446,7 +195520,7 @@ + ** object and the buffer is full, discard some data to free up space. + */ + static void sessionDiscardData(SessionInput *pIn){ +- if( pIn->bEof && pIn->xInput && pIn->iNext>=SESSIONS_STRM_CHUNK_SIZE ){ ++ if( pIn->xInput && pIn->iNext>=sessions_strm_chunk_size ){ + int nMove = pIn->buf.nBuf - pIn->iNext; + assert( nMove>=0 ); + if( nMove>0 ){ +@@ -178469,7 +195543,7 @@ + int rc = SQLITE_OK; + if( pIn->xInput ){ + while( !pIn->bEof && (pIn->iNext+nByte)>=pIn->nData && rc==SQLITE_OK ){ +- int nNew = SESSIONS_STRM_CHUNK_SIZE; ++ int nNew = sessions_strm_chunk_size; + + if( pIn->bNoDiscard==0 ) sessionDiscardData(pIn); + if( SQLITE_OK==sessionBufferGrow(&pIn->buf, nNew, &rc) ){ +@@ -178574,15 +195648,18 @@ + if( abPK && abPK[i]==0 ) continue; + rc = sessionInputBuffer(pIn, 9); + if( rc==SQLITE_OK ){ +- eType = pIn->aData[pIn->iNext++]; ++ if( pIn->iNext>=pIn->nData ){ ++ rc = SQLITE_CORRUPT_BKPT; ++ }else{ ++ eType = pIn->aData[pIn->iNext++]; ++ assert( apOut[i]==0 ); ++ if( eType ){ ++ apOut[i] = sqlite3ValueNew(0); ++ if( !apOut[i] ) rc = SQLITE_NOMEM; ++ } ++ } + } + +- assert( apOut[i]==0 ); +- if( eType ){ +- apOut[i] = sqlite3ValueNew(0); +- if( !apOut[i] ) rc = SQLITE_NOMEM; +- } +- + if( rc==SQLITE_OK ){ + u8 *aVal = &pIn->aData[pIn->iNext]; + if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ +@@ -178590,10 +195667,14 @@ + pIn->iNext += sessionVarintGet(aVal, &nByte); + rc = sessionInputBuffer(pIn, nByte); + if( rc==SQLITE_OK ){ +- u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0); +- rc = sessionValueSetStr(apOut[i],&pIn->aData[pIn->iNext],nByte,enc); ++ if( nByte<0 || nByte>pIn->nData-pIn->iNext ){ ++ rc = SQLITE_CORRUPT_BKPT; ++ }else{ ++ u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0); ++ rc = sessionValueSetStr(apOut[i],&pIn->aData[pIn->iNext],nByte,enc); ++ pIn->iNext += nByte; ++ } + } +- pIn->iNext += nByte; + } + if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ + sqlite3_int64 v = sessionGetI64(aVal); +@@ -178633,8 +195714,19 @@ + rc = sessionInputBuffer(pIn, 9); + if( rc==SQLITE_OK ){ + nRead += sessionVarintGet(&pIn->aData[pIn->iNext + nRead], &nCol); +- rc = sessionInputBuffer(pIn, nRead+nCol+100); +- nRead += nCol; ++ /* The hard upper limit for the number of columns in an SQLite ++ ** database table is, according to sqliteLimit.h, 32676. So ++ ** consider any table-header that purports to have more than 65536 ++ ** columns to be corrupt. This is convenient because otherwise, ++ ** if the (nCol>65536) condition below were omitted, a sufficiently ++ ** large value for nCol may cause nRead to wrap around and become ++ ** negative. Leading to a crash. */ ++ if( nCol<0 || nCol>65536 ){ ++ rc = SQLITE_CORRUPT_BKPT; ++ }else{ ++ rc = sessionInputBuffer(pIn, nRead+nCol+100); ++ nRead += nCol; ++ } + } + + while( rc==SQLITE_OK ){ +@@ -178711,11 +195803,15 @@ + int nByte; + int nVarint; + nVarint = sessionVarintGet(&p->in.aData[p->in.iNext], &p->nCol); +- nCopy -= nVarint; +- p->in.iNext += nVarint; +- nByte = p->nCol * sizeof(sqlite3_value*) * 2 + nCopy; +- p->tblhdr.nBuf = 0; +- sessionBufferGrow(&p->tblhdr, nByte, &rc); ++ if( p->nCol>0 ){ ++ nCopy -= nVarint; ++ p->in.iNext += nVarint; ++ nByte = p->nCol * sizeof(sqlite3_value*) * 2 + nCopy; ++ p->tblhdr.nBuf = 0; ++ sessionBufferGrow(&p->tblhdr, nByte, &rc); ++ }else{ ++ rc = SQLITE_CORRUPT_BKPT; ++ } + } + + if( rc==SQLITE_OK ){ +@@ -178750,7 +195846,8 @@ + static int sessionChangesetNext( + sqlite3_changeset_iter *p, /* Changeset iterator */ + u8 **paRec, /* If non-NULL, store record pointer here */ +- int *pnRec /* If non-NULL, store size of record here */ ++ int *pnRec, /* If non-NULL, store size of record here */ ++ int *pbNew /* If non-NULL, true if new table */ + ){ + int i; + u8 op; +@@ -178785,6 +195882,7 @@ + + op = p->in.aData[p->in.iNext++]; + while( op=='T' || op=='P' ){ ++ if( pbNew ) *pbNew = 1; + p->bPatchset = (op=='P'); + if( sessionChangesetReadTblhdr(p) ) return p->rc; + if( (p->rc = sessionInputBuffer(&p->in, 2)) ) return p->rc; +@@ -178793,6 +195891,13 @@ + op = p->in.aData[p->in.iNext++]; + } + ++ if( p->zTab==0 || (p->bPatchset && p->bInvert) ){ ++ /* The first record in the changeset is not a table header. Must be a ++ ** corrupt changeset. */ ++ assert( p->in.iNext==1 || p->zTab ); ++ return (p->rc = SQLITE_CORRUPT_BKPT); ++ } ++ + p->op = op; + p->bIndirect = p->in.aData[p->in.iNext++]; + if( p->op!=SQLITE_UPDATE && p->op!=SQLITE_DELETE && p->op!=SQLITE_INSERT ){ +@@ -178814,33 +195919,39 @@ + *paRec = &p->in.aData[p->in.iNext]; + p->in.iNext += *pnRec; + }else{ ++ sqlite3_value **apOld = (p->bInvert ? &p->apValue[p->nCol] : p->apValue); ++ sqlite3_value **apNew = (p->bInvert ? p->apValue : &p->apValue[p->nCol]); + + /* If this is an UPDATE or DELETE, read the old.* record. */ + if( p->op!=SQLITE_INSERT && (p->bPatchset==0 || p->op==SQLITE_DELETE) ){ + u8 *abPK = p->bPatchset ? p->abPK : 0; +- p->rc = sessionReadRecord(&p->in, p->nCol, abPK, p->apValue); ++ p->rc = sessionReadRecord(&p->in, p->nCol, abPK, apOld); + if( p->rc!=SQLITE_OK ) return p->rc; + } + + /* If this is an INSERT or UPDATE, read the new.* record. */ + if( p->op!=SQLITE_DELETE ){ +- p->rc = sessionReadRecord(&p->in, p->nCol, 0, &p->apValue[p->nCol]); ++ p->rc = sessionReadRecord(&p->in, p->nCol, 0, apNew); + if( p->rc!=SQLITE_OK ) return p->rc; + } + +- if( p->bPatchset && p->op==SQLITE_UPDATE ){ ++ if( (p->bPatchset || p->bInvert) && p->op==SQLITE_UPDATE ){ + /* If this is an UPDATE that is part of a patchset, then all PK and + ** modified fields are present in the new.* record. The old.* record + ** is currently completely empty. This block shifts the PK fields from + ** new.* to old.*, to accommodate the code that reads these arrays. */ + for(i=0; i<p->nCol; i++){ +- assert( p->apValue[i]==0 ); +- assert( p->abPK[i]==0 || p->apValue[i+p->nCol] ); ++ assert( p->bPatchset==0 || p->apValue[i]==0 ); + if( p->abPK[i] ){ ++ assert( p->apValue[i]==0 ); + p->apValue[i] = p->apValue[i+p->nCol]; ++ if( p->apValue[i]==0 ) return (p->rc = SQLITE_CORRUPT_BKPT); + p->apValue[i+p->nCol] = 0; + } + } ++ }else if( p->bInvert ){ ++ if( p->op==SQLITE_INSERT ) p->op = SQLITE_DELETE; ++ else if( p->op==SQLITE_DELETE ) p->op = SQLITE_INSERT; + } + } + +@@ -178856,7 +195967,7 @@ + ** callback by changeset_apply(). + */ + SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *p){ +- return sessionChangesetNext(p, 0, 0); ++ return sessionChangesetNext(p, 0, 0, 0); + } + + /* +@@ -179157,7 +196268,7 @@ + } + + assert( rc==SQLITE_OK ); +- if( xOutput && sOut.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){ ++ if( xOutput && sOut.nBuf>=sessions_strm_chunk_size ){ + rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); + sOut.nBuf = 0; + if( rc!=SQLITE_OK ) goto finished_invert; +@@ -179232,9 +196343,12 @@ + int nCol; /* Size of azCol[] and abPK[] arrays */ + const char **azCol; /* Array of column names */ + u8 *abPK; /* Boolean array - true if column is in PK */ +- ++ int bStat1; /* True if table is sqlite_stat1 */ + int bDeferConstraints; /* True to defer constraints */ + 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 */ + }; + + /* +@@ -179402,6 +196516,7 @@ + return rc; + } + ++ + /* + ** Formulate and prepare an SQL statement to query table zTab by primary + ** key. Assuming the following table structure: +@@ -179463,7 +196578,47 @@ + return rc; + } + ++static int sessionPrepare(sqlite3 *db, sqlite3_stmt **pp, const char *zSql){ ++ return sqlite3_prepare_v2(db, zSql, -1, pp, 0); ++} ++ + /* ++** Prepare statements for applying changes to the sqlite_stat1 table. ++** These are similar to those created by sessionSelectRow(), ++** sessionInsertRow(), sessionUpdateRow() and sessionDeleteRow() for ++** other tables. ++*/ ++static int sessionStat1Sql(sqlite3 *db, SessionApplyCtx *p){ ++ int rc = sessionSelectRow(db, "sqlite_stat1", p); ++ if( rc==SQLITE_OK ){ ++ rc = sessionPrepare(db, &p->pInsert, ++ "INSERT INTO main.sqlite_stat1 VALUES(?1, " ++ "CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END, " ++ "?3)" ++ ); ++ } ++ if( rc==SQLITE_OK ){ ++ rc = sessionPrepare(db, &p->pUpdate, ++ "UPDATE main.sqlite_stat1 SET " ++ "tbl = CASE WHEN ?2 THEN ?3 ELSE tbl END, " ++ "idx = CASE WHEN ?5 THEN ?6 ELSE idx END, " ++ "stat = CASE WHEN ?8 THEN ?9 ELSE stat END " ++ "WHERE tbl=?1 AND idx IS " ++ "CASE WHEN length(?4)=0 AND typeof(?4)='blob' THEN NULL ELSE ?4 END " ++ "AND (?10 OR ?8=0 OR stat IS ?7)" ++ ); ++ } ++ if( rc==SQLITE_OK ){ ++ rc = sessionPrepare(db, &p->pDelete, ++ "DELETE FROM main.sqlite_stat1 WHERE tbl=?1 AND idx IS " ++ "CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END " ++ "AND (?4 OR stat IS ?3)" ++ ); ++ } ++ return rc; ++} ++ ++/* + ** A wrapper around sqlite3_bind_value() that detects an extra problem. + ** See comments in the body of this function for details. + */ +@@ -179520,7 +196675,13 @@ + if( !abPK || abPK[i] ){ + sqlite3_value *pVal; + (void)xValue(pIter, i, &pVal); +- rc = sessionBindValue(pStmt, i+1, pVal); ++ if( pVal==0 ){ ++ /* The value in the changeset was "undefined". This indicates a ++ ** corrupt changeset blob. */ ++ rc = SQLITE_CORRUPT_BKPT; ++ }else{ ++ rc = sessionBindValue(pStmt, i+1, pVal); ++ } + } + } + return rc; +@@ -179569,6 +196730,55 @@ + } + + /* ++** This function is called from within sqlite3changset_apply_v2() when ++** a conflict is encountered and resolved using conflict resolution ++** mode eType (either SQLITE_CHANGESET_OMIT or SQLITE_CHANGESET_REPLACE).. ++** It adds a conflict resolution record to the buffer in ++** SessionApplyCtx.rebase, which will eventually be returned to the caller ++** of apply_v2() as the "rebase" buffer. ++** ++** Return SQLITE_OK if successful, or an SQLite error code otherwise. ++*/ ++static int sessionRebaseAdd( ++ SessionApplyCtx *p, /* Apply context */ ++ int eType, /* Conflict resolution (OMIT or REPLACE) */ ++ sqlite3_changeset_iter *pIter /* Iterator pointing at current change */ ++){ ++ int rc = SQLITE_OK; ++ if( p->bRebase ){ ++ int i; ++ int eOp = pIter->op; ++ if( p->bRebaseStarted==0 ){ ++ /* Append a table-header to the rebase buffer */ ++ const char *zTab = pIter->zTab; ++ sessionAppendByte(&p->rebase, 'T', &rc); ++ sessionAppendVarint(&p->rebase, p->nCol, &rc); ++ sessionAppendBlob(&p->rebase, p->abPK, p->nCol, &rc); ++ sessionAppendBlob(&p->rebase, (u8*)zTab, (int)strlen(zTab)+1, &rc); ++ p->bRebaseStarted = 1; ++ } ++ ++ assert( eType==SQLITE_CHANGESET_REPLACE||eType==SQLITE_CHANGESET_OMIT ); ++ assert( eOp==SQLITE_DELETE || eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE ); ++ ++ sessionAppendByte(&p->rebase, ++ (eOp==SQLITE_DELETE ? SQLITE_DELETE : SQLITE_INSERT), &rc ++ ); ++ sessionAppendByte(&p->rebase, (eType==SQLITE_CHANGESET_REPLACE), &rc); ++ for(i=0; i<p->nCol; i++){ ++ sqlite3_value *pVal = 0; ++ if( eOp==SQLITE_DELETE || (eOp==SQLITE_UPDATE && p->abPK[i]) ){ ++ sqlite3changeset_old(pIter, i, &pVal); ++ }else{ ++ sqlite3changeset_new(pIter, i, &pVal); ++ } ++ sessionAppendValue(&p->rebase, pVal, &rc); ++ } ++ } ++ return rc; ++} ++ ++/* + ** Invoke the conflict handler for the change that the changeset iterator + ** currently points to. + ** +@@ -179643,7 +196853,7 @@ + u8 *aBlob = &pIter->in.aData[pIter->in.iCurrent]; + int nBlob = pIter->in.iNext - pIter->in.iCurrent; + sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc); +- res = SQLITE_CHANGESET_OMIT; ++ return SQLITE_OK; + }else{ + /* No other row with the new.* primary key. */ + res = xConflict(pCtx, eType+1, pIter); +@@ -179669,6 +196879,9 @@ + rc = SQLITE_MISUSE; + break; + } ++ if( rc==SQLITE_OK ){ ++ rc = sessionRebaseAdd(p, res, pIter); ++ } + } + + return rc; +@@ -179793,11 +197006,25 @@ + + }else{ + assert( op==SQLITE_INSERT ); +- rc = sessionBindRow(pIter, sqlite3changeset_new, nCol, 0, p->pInsert); +- if( rc!=SQLITE_OK ) return rc; ++ 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(p->db, pIter, p->abPK, p->pSelect); ++ if( rc==SQLITE_ROW ){ ++ rc = SQLITE_CONSTRAINT; ++ sqlite3_reset(p->pSelect); ++ } ++ } + +- sqlite3_step(p->pInsert); +- rc = sqlite3_reset(p->pInsert); ++ if( rc==SQLITE_OK ){ ++ rc = sessionBindRow(pIter, sqlite3changeset_new, nCol, 0, p->pInsert); ++ if( rc!=SQLITE_OK ) return rc; ++ ++ sqlite3_step(p->pInsert); ++ rc = sqlite3_reset(p->pInsert); ++ } ++ + if( (rc&0xff)==SQLITE_CONSTRAINT ){ + rc = sessionConflictHandler( + SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, pbReplace +@@ -179830,42 +197057,42 @@ + int rc; + + rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, &bReplace, &bRetry); +- assert( rc==SQLITE_OK || (bRetry==0 && bReplace==0) ); +- +- /* If the bRetry flag is set, the change has not been applied due to an +- ** SQLITE_CHANGESET_DATA problem (i.e. this is an UPDATE or DELETE and +- ** a row with the correct PK is present in the db, but one or more other +- ** fields do not contain the expected values) and the conflict handler +- ** returned SQLITE_CHANGESET_REPLACE. In this case retry the operation, +- ** but pass NULL as the final argument so that sessionApplyOneOp() ignores +- ** the SQLITE_CHANGESET_DATA problem. */ +- if( bRetry ){ +- assert( pIter->op==SQLITE_UPDATE || pIter->op==SQLITE_DELETE ); +- rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0); +- } +- +- /* If the bReplace flag is set, the change is an INSERT that has not +- ** been performed because the database already contains a row with the +- ** specified primary key and the conflict handler returned +- ** SQLITE_CHANGESET_REPLACE. In this case remove the conflicting row +- ** before reattempting the INSERT. */ +- else if( bReplace ){ +- assert( pIter->op==SQLITE_INSERT ); +- rc = sqlite3_exec(db, "SAVEPOINT replace_op", 0, 0, 0); +- if( rc==SQLITE_OK ){ +- rc = sessionBindRow(pIter, +- sqlite3changeset_new, pApply->nCol, pApply->abPK, pApply->pDelete); +- sqlite3_bind_int(pApply->pDelete, pApply->nCol+1, 1); +- } +- if( rc==SQLITE_OK ){ +- sqlite3_step(pApply->pDelete); +- rc = sqlite3_reset(pApply->pDelete); +- } +- if( rc==SQLITE_OK ){ ++ if( rc==SQLITE_OK ){ ++ /* If the bRetry flag is set, the change has not been applied due to an ++ ** SQLITE_CHANGESET_DATA problem (i.e. this is an UPDATE or DELETE and ++ ** a row with the correct PK is present in the db, but one or more other ++ ** fields do not contain the expected values) and the conflict handler ++ ** returned SQLITE_CHANGESET_REPLACE. In this case retry the operation, ++ ** but pass NULL as the final argument so that sessionApplyOneOp() ignores ++ ** the SQLITE_CHANGESET_DATA problem. */ ++ if( bRetry ){ ++ assert( pIter->op==SQLITE_UPDATE || pIter->op==SQLITE_DELETE ); + rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0); + } +- if( rc==SQLITE_OK ){ +- rc = sqlite3_exec(db, "RELEASE replace_op", 0, 0, 0); ++ ++ /* If the bReplace flag is set, the change is an INSERT that has not ++ ** been performed because the database already contains a row with the ++ ** specified primary key and the conflict handler returned ++ ** SQLITE_CHANGESET_REPLACE. In this case remove the conflicting row ++ ** before reattempting the INSERT. */ ++ else if( bReplace ){ ++ assert( pIter->op==SQLITE_INSERT ); ++ rc = sqlite3_exec(db, "SAVEPOINT replace_op", 0, 0, 0); ++ if( rc==SQLITE_OK ){ ++ rc = sessionBindRow(pIter, ++ sqlite3changeset_new, pApply->nCol, pApply->abPK, pApply->pDelete); ++ sqlite3_bind_int(pApply->pDelete, pApply->nCol+1, 1); ++ } ++ if( rc==SQLITE_OK ){ ++ sqlite3_step(pApply->pDelete); ++ rc = sqlite3_reset(pApply->pDelete); ++ } ++ if( rc==SQLITE_OK ){ ++ rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0); ++ } ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3_exec(db, "RELEASE replace_op", 0, 0, 0); ++ } + } + } + +@@ -179890,7 +197117,7 @@ + SessionBuffer cons = pApply->constraints; + memset(&pApply->constraints, 0, sizeof(SessionBuffer)); + +- rc = sessionChangesetStart(&pIter2, 0, 0, cons.nBuf, cons.aBuf); ++ rc = sessionChangesetStart(&pIter2, 0, 0, cons.nBuf, cons.aBuf, 0); + if( rc==SQLITE_OK ){ + int nByte = 2*pApply->nCol*sizeof(sqlite3_value*); + int rc2; +@@ -179941,10 +197168,12 @@ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), +- void *pCtx /* First argument passed to xConflict */ ++ void *pCtx, /* First argument passed to xConflict */ ++ void **ppRebase, int *pnRebase, /* OUT: Rebase information */ ++ int flags /* SESSION_APPLY_XXX flags */ + ){ + int schemaMismatch = 0; +- int rc; /* Return code */ ++ int rc = SQLITE_OK; /* Return code */ + const char *zTab = 0; /* Name of current table */ + int nTab = 0; /* Result of sqlite3Strlen30(zTab) */ + SessionApplyCtx sApply; /* changeset_apply() context object */ +@@ -179954,8 +197183,11 @@ + + pIter->in.bNoDiscard = 1; + memset(&sApply, 0, sizeof(sApply)); ++ sApply.bRebase = (ppRebase && pnRebase); + sqlite3_mutex_enter(sqlite3_db_mutex(db)); +- rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0); ++ 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); + } +@@ -179979,9 +197211,18 @@ + sqlite3_finalize(sApply.pUpdate); + sqlite3_finalize(sApply.pInsert); + sqlite3_finalize(sApply.pSelect); +- memset(&sApply, 0, sizeof(sApply)); + sApply.db = db; ++ sApply.pDelete = 0; ++ sApply.pUpdate = 0; ++ sApply.pInsert = 0; ++ 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 +@@ -180030,12 +197271,20 @@ + } + else{ + sApply.nCol = nCol; +- if((rc = sessionSelectRow(db, zTab, &sApply)) +- || (rc = sessionUpdateRow(db, zTab, &sApply)) +- || (rc = sessionDeleteRow(db, zTab, &sApply)) +- || (rc = sessionInsertRow(db, zTab, &sApply)) +- ){ +- break; ++ if( 0==sqlite3_stricmp(zTab, "sqlite_stat1") ){ ++ if( (rc = sessionStat1Sql(db, &sApply) ) ){ ++ break; ++ } ++ sApply.bStat1 = 1; ++ }else{ ++ if((rc = sessionSelectRow(db, zTab, &sApply)) ++ || (rc = sessionUpdateRow(db, zTab, &sApply)) ++ || (rc = sessionDeleteRow(db, zTab, &sApply)) ++ || (rc = sessionInsertRow(db, zTab, &sApply)) ++ ){ ++ break; ++ } ++ sApply.bStat1 = 0; + } + } + nTab = sqlite3Strlen30(zTab); +@@ -180076,13 +197325,21 @@ + } + sqlite3_exec(db, "PRAGMA defer_foreign_keys = 0", 0, 0, 0); + +- if( rc==SQLITE_OK ){ +- rc = sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0); +- }else{ +- sqlite3_exec(db, "ROLLBACK TO changeset_apply", 0, 0, 0); +- sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0); ++ if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){ ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0); ++ }else{ ++ sqlite3_exec(db, "ROLLBACK TO changeset_apply", 0, 0, 0); ++ sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0); ++ } + } + ++ assert( sApply.bRebase || sApply.rebase.nBuf==0 ); ++ if( rc==SQLITE_OK && bPatchset==0 && sApply.bRebase ){ ++ *ppRebase = (void*)sApply.rebase.aBuf; ++ *pnRebase = sApply.rebase.nBuf; ++ sApply.rebase.aBuf = 0; ++ } + sqlite3_finalize(sApply.pInsert); + sqlite3_finalize(sApply.pDelete); + sqlite3_finalize(sApply.pUpdate); +@@ -180089,11 +197346,44 @@ + sqlite3_finalize(sApply.pSelect); + sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */ + sqlite3_free((char*)sApply.constraints.aBuf); ++ sqlite3_free((char*)sApply.rebase.aBuf); + sqlite3_mutex_leave(sqlite3_db_mutex(db)); + return rc; + } + + /* ++** Apply the changeset passed via pChangeset/nChangeset to the main ++** database attached to handle "db". ++*/ ++SQLITE_API int sqlite3changeset_apply_v2( ++ sqlite3 *db, /* Apply change to "main" db of this handle */ ++ int nChangeset, /* Size of changeset in bytes */ ++ void *pChangeset, /* Changeset blob */ ++ int(*xFilter)( ++ void *pCtx, /* Copy of sixth arg to _apply() */ ++ const char *zTab /* Table name */ ++ ), ++ int(*xConflict)( ++ void *pCtx, /* Copy of sixth arg to _apply() */ ++ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ ++ sqlite3_changeset_iter *p /* Handle describing change and conflict */ ++ ), ++ void *pCtx, /* First argument passed to xConflict */ ++ void **ppRebase, int *pnRebase, ++ int flags ++){ ++ sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ ++ int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT); ++ int rc = sessionChangesetStart(&pIter, 0, 0, nChangeset, pChangeset,bInverse); ++ if( rc==SQLITE_OK ){ ++ rc = sessionChangesetApply( ++ db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags ++ ); ++ } ++ return rc; ++} ++ ++/* + ** Apply the changeset passed via pChangeset/nChangeset to the main database + ** attached to handle "db". Invoke the supplied conflict handler callback + ** to resolve any conflicts encountered while applying the change. +@@ -180113,12 +197403,9 @@ + ), + void *pCtx /* First argument passed to xConflict */ + ){ +- sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ +- int rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset); +- if( rc==SQLITE_OK ){ +- rc = sessionChangesetApply(db, pIter, xFilter, xConflict, pCtx); +- } +- return rc; ++ return sqlite3changeset_apply_v2( ++ db, nChangeset, pChangeset, xFilter, xConflict, pCtx, 0, 0, 0 ++ ); + } + + /* +@@ -180126,7 +197413,7 @@ + ** attached to handle "db". Invoke the supplied conflict handler callback + ** to resolve any conflicts encountered while applying the change. + */ +-SQLITE_API int sqlite3changeset_apply_strm( ++SQLITE_API int sqlite3changeset_apply_v2_strm( + sqlite3 *db, /* Apply change to "main" db of this handle */ + int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ + void *pIn, /* First arg for xInput */ +@@ -180139,15 +197426,39 @@ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), +- void *pCtx /* First argument passed to xConflict */ ++ void *pCtx, /* First argument passed to xConflict */ ++ void **ppRebase, int *pnRebase, ++ int flags + ){ + sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ +- int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); ++ int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT); ++ int rc = sessionChangesetStart(&pIter, xInput, pIn, 0, 0, bInverse); + if( rc==SQLITE_OK ){ +- rc = sessionChangesetApply(db, pIter, xFilter, xConflict, pCtx); ++ rc = sessionChangesetApply( ++ db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags ++ ); + } + return rc; + } ++SQLITE_API int sqlite3changeset_apply_strm( ++ sqlite3 *db, /* Apply change to "main" db of this handle */ ++ int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ ++ void *pIn, /* First arg for xInput */ ++ int(*xFilter)( ++ void *pCtx, /* Copy of sixth arg to _apply() */ ++ const char *zTab /* Table name */ ++ ), ++ int(*xConflict)( ++ void *pCtx, /* Copy of sixth arg to _apply() */ ++ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ ++ sqlite3_changeset_iter *p /* Handle describing change and conflict */ ++ ), ++ void *pCtx /* First argument passed to xConflict */ ++){ ++ return sqlite3changeset_apply_v2_strm( ++ db, xInput, pIn, xFilter, xConflict, pCtx, 0, 0, 0 ++ ); ++} + + /* + ** sqlite3_changegroup handle. +@@ -180165,6 +197476,7 @@ + */ + static int sessionChangeMerge( + SessionTable *pTab, /* Table structure */ ++ int bRebase, /* True for a rebase hash-table */ + int bPatchset, /* True for patchsets */ + SessionChange *pExist, /* Existing change */ + int op2, /* Second change operation */ +@@ -180174,6 +197486,7 @@ + SessionChange **ppNew /* OUT: Merged change */ + ){ + SessionChange *pNew = 0; ++ int rc = SQLITE_OK; + + if( !pExist ){ + pNew = (SessionChange *)sqlite3_malloc(sizeof(SessionChange) + nRec); +@@ -180183,9 +197496,66 @@ + memset(pNew, 0, sizeof(SessionChange)); + pNew->op = op2; + pNew->bIndirect = bIndirect; +- pNew->nRecord = nRec; + pNew->aRecord = (u8*)&pNew[1]; +- memcpy(pNew->aRecord, aRec, nRec); ++ if( bIndirect==0 || bRebase==0 ){ ++ pNew->nRecord = nRec; ++ memcpy(pNew->aRecord, aRec, nRec); ++ }else{ ++ int i; ++ u8 *pIn = aRec; ++ u8 *pOut = pNew->aRecord; ++ for(i=0; i<pTab->nCol; i++){ ++ int nIn = sessionSerialLen(pIn); ++ if( *pIn==0 ){ ++ *pOut++ = 0; ++ }else if( pTab->abPK[i]==0 ){ ++ *pOut++ = 0xFF; ++ }else{ ++ memcpy(pOut, pIn, nIn); ++ pOut += nIn; ++ } ++ pIn += nIn; ++ } ++ pNew->nRecord = pOut - pNew->aRecord; ++ } ++ }else if( bRebase ){ ++ if( pExist->op==SQLITE_DELETE && pExist->bIndirect ){ ++ *ppNew = pExist; ++ }else{ ++ int nByte = nRec + pExist->nRecord + sizeof(SessionChange); ++ pNew = (SessionChange*)sqlite3_malloc(nByte); ++ if( pNew==0 ){ ++ rc = SQLITE_NOMEM; ++ }else{ ++ int i; ++ u8 *a1 = pExist->aRecord; ++ u8 *a2 = aRec; ++ u8 *pOut; ++ ++ memset(pNew, 0, nByte); ++ pNew->bIndirect = bIndirect || pExist->bIndirect; ++ pNew->op = op2; ++ pOut = pNew->aRecord = (u8*)&pNew[1]; ++ ++ for(i=0; i<pTab->nCol; i++){ ++ int n1 = sessionSerialLen(a1); ++ int n2 = sessionSerialLen(a2); ++ if( *a1==0xFF || (pTab->abPK[i]==0 && bIndirect) ){ ++ *pOut++ = 0xFF; ++ }else if( *a2==0 ){ ++ memcpy(pOut, a1, n1); ++ pOut += n1; ++ }else{ ++ memcpy(pOut, a2, n2); ++ pOut += n2; ++ } ++ a1 += n1; ++ a2 += n2; ++ } ++ pNew->nRecord = pOut - pNew->aRecord; ++ } ++ sqlite3_free(pExist); ++ } + }else{ + int op1 = pExist->op; + +@@ -180279,7 +197649,7 @@ + } + + *ppNew = pNew; +- return SQLITE_OK; ++ return rc; + } + + /* +@@ -180288,7 +197658,8 @@ + */ + static int sessionChangesetToHash( + sqlite3_changeset_iter *pIter, /* Iterator to read from */ +- sqlite3_changegroup *pGrp /* Changegroup object to add changeset to */ ++ sqlite3_changegroup *pGrp, /* Changegroup object to add changeset to */ ++ int bRebase /* True if hash table is for rebasing */ + ){ + u8 *aRec; + int nRec; +@@ -180295,8 +197666,7 @@ + int rc = SQLITE_OK; + SessionTable *pTab = 0; + +- +- while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec) ){ ++ while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec, 0) ){ + const char *zNew; + int nCol; + int op; +@@ -180376,7 +197746,7 @@ + } + } + +- rc = sessionChangeMerge(pTab, ++ rc = sessionChangeMerge(pTab, bRebase, + pIter->bPatchset, pExist, op, bIndirect, aRec, nRec, &pChange + ); + if( rc ) break; +@@ -180435,13 +197805,12 @@ + sessionAppendByte(&buf, p->op, &rc); + sessionAppendByte(&buf, p->bIndirect, &rc); + sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); ++ if( rc==SQLITE_OK && xOutput && buf.nBuf>=sessions_strm_chunk_size ){ ++ rc = xOutput(pOut, buf.aBuf, buf.nBuf); ++ buf.nBuf = 0; ++ } + } + } +- +- if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){ +- rc = xOutput(pOut, buf.aBuf, buf.nBuf); +- buf.nBuf = 0; +- } + } + + if( rc==SQLITE_OK ){ +@@ -180484,7 +197853,7 @@ + + rc = sqlite3changeset_start(&pIter, nData, pData); + if( rc==SQLITE_OK ){ +- rc = sessionChangesetToHash(pIter, pGrp); ++ rc = sessionChangesetToHash(pIter, pGrp, 0); + } + sqlite3changeset_finalize(pIter); + return rc; +@@ -180515,7 +197884,7 @@ + + rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); + if( rc==SQLITE_OK ){ +- rc = sessionChangesetToHash(pIter, pGrp); ++ rc = sessionChangesetToHash(pIter, pGrp, 0); + } + sqlite3changeset_finalize(pIter); + return rc; +@@ -180600,2439 +197969,373 @@ + return rc; + } + +-#endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */ +- +-/************** End of sqlite3session.c **************************************/ +-/************** Begin file json1.c *******************************************/ + /* +-** 2015-08-12 +-** +-** 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 JSON functions. The interface is +-** modeled after MySQL JSON functions: +-** +-** https://dev.mysql.com/doc/refman/5.7/en/json.html +-** +-** For the time being, all JSON is stored as pure text. (We might add +-** a JSONB type in the future which stores a binary encoding of JSON in +-** a BLOB, but there is no support for JSONB in the current implementation. +-** This implementation parses JSON text at 250 MB/s, so it is hard to see +-** how JSONB might improve on that.) ++** Changeset rebaser handle. + */ +-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1) +-#if !defined(SQLITEINT_H) +-/* #include "sqlite3ext.h" */ +-#endif +-SQLITE_EXTENSION_INIT1 +-/* #include <assert.h> */ +-/* #include <string.h> */ +-/* #include <stdlib.h> */ +-/* #include <stdarg.h> */ +- +-/* Mark a function parameter as unused, to suppress nuisance compiler +-** warnings. */ +-#ifndef UNUSED_PARAM +-# define UNUSED_PARAM(X) (void)(X) +-#endif +- +-#ifndef LARGEST_INT64 +-# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32)) +-# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64) +-#endif +- +-/* +-** Versions of isspace(), isalnum() and isdigit() to which it is safe +-** to pass signed char values. +-*/ +-#ifdef sqlite3Isdigit +- /* Use the SQLite core versions if this routine is part of the +- ** SQLite amalgamation */ +-# define safe_isdigit(x) sqlite3Isdigit(x) +-# define safe_isalnum(x) sqlite3Isalnum(x) +-# define safe_isxdigit(x) sqlite3Isxdigit(x) +-#else +- /* Use the standard library for separate compilation */ +-#include <ctype.h> /* amalgamator: keep */ +-# define safe_isdigit(x) isdigit((unsigned char)(x)) +-# define safe_isalnum(x) isalnum((unsigned char)(x)) +-# define safe_isxdigit(x) isxdigit((unsigned char)(x)) +-#endif +- +-/* +-** Growing our own isspace() routine this way is twice as fast as +-** the library isspace() function, resulting in a 7% overall performance +-** increase for the parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os). +-*/ +-static const char jsonIsSpace[] = { +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++struct sqlite3_rebaser { ++ sqlite3_changegroup grp; /* Hash table */ + }; +-#define safe_isspace(x) (jsonIsSpace[(unsigned char)x]) + +-#ifndef SQLITE_AMALGAMATION +- /* Unsigned integer types. These are already defined in the sqliteInt.h, +- ** but the definitions need to be repeated for separate compilation. */ +- typedef sqlite3_uint64 u64; +- typedef unsigned int u32; +- typedef unsigned short int u16; +- typedef unsigned char u8; +-#endif +- +-/* Objects */ +-typedef struct JsonString JsonString; +-typedef struct JsonNode JsonNode; +-typedef struct JsonParse JsonParse; +- +-/* An instance of this object represents a JSON string +-** under construction. Really, this is a generic string accumulator +-** that can be and is used to create strings other than JSON. +-*/ +-struct JsonString { +- sqlite3_context *pCtx; /* Function context - put error messages here */ +- char *zBuf; /* Append JSON content here */ +- u64 nAlloc; /* Bytes of storage available in zBuf[] */ +- u64 nUsed; /* Bytes of zBuf[] currently used */ +- u8 bStatic; /* True if zBuf is static space */ +- u8 bErr; /* True if an error has been encountered */ +- char zSpace[100]; /* Initial static space */ +-}; +- +-/* JSON type values +-*/ +-#define JSON_NULL 0 +-#define JSON_TRUE 1 +-#define JSON_FALSE 2 +-#define JSON_INT 3 +-#define JSON_REAL 4 +-#define JSON_STRING 5 +-#define JSON_ARRAY 6 +-#define JSON_OBJECT 7 +- +-/* The "subtype" set for JSON values */ +-#define JSON_SUBTYPE 74 /* Ascii for "J" */ +- + /* +-** Names of the various JSON types: ++** Buffers a1 and a2 must both contain a sessions module record nCol ++** fields in size. This function appends an nCol sessions module ++** record to buffer pBuf that is a copy of a1, except that for ++** each field that is undefined in a1[], swap in the field from a2[]. + */ +-static const char * const jsonType[] = { +- "null", "true", "false", "integer", "real", "text", "array", "object" +-}; +- +-/* Bit values for the JsonNode.jnFlag field +-*/ +-#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 */ +- u32 n; /* Bytes of content, or number of sub-nodes */ +- union { +- const char *zJContent; /* Content for INT, REAL, and STRING */ +- u32 iAppend; /* More terms for ARRAY and OBJECT */ +- u32 iKey; /* Key for ARRAY objects in json_tree() */ +- u32 iReplace; /* Replacement content for JNODE_REPLACE */ +- JsonNode *pPatch; /* Node chain of patch for JNODE_PATCH */ +- } u; +-}; +- +-/* A completely parsed JSON string +-*/ +-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 */ +-}; +- +-/* +-** Maximum nesting depth of JSON for this implementation. +-** +-** This limit is needed to avoid a stack overflow in the recursive +-** descent parser. A depth of 2000 is far deeper than any sane JSON +-** should go. +-*/ +-#define JSON_MAX_DEPTH 2000 +- +-/************************************************************************** +-** Utility routines for dealing with JsonString objects +-**************************************************************************/ +- +-/* Set the JsonString object to an empty string +-*/ +-static void jsonZero(JsonString *p){ +- p->zBuf = p->zSpace; +- p->nAlloc = sizeof(p->zSpace); +- p->nUsed = 0; +- p->bStatic = 1; +-} +- +-/* Initialize the JsonString object +-*/ +-static void jsonInit(JsonString *p, sqlite3_context *pCtx){ +- p->pCtx = pCtx; +- p->bErr = 0; +- jsonZero(p); +-} +- +- +-/* Free all allocated memory and reset the JsonString object back to its +-** initial state. +-*/ +-static void jsonReset(JsonString *p){ +- if( !p->bStatic ) sqlite3_free(p->zBuf); +- jsonZero(p); +-} +- +- +-/* Report an out-of-memory (OOM) condition +-*/ +-static void jsonOom(JsonString *p){ +- p->bErr = 1; +- sqlite3_result_error_nomem(p->pCtx); +- jsonReset(p); +-} +- +-/* Enlarge pJson->zBuf so that it can hold at least N more bytes. +-** Return zero on success. Return non-zero on an OOM error +-*/ +-static int jsonGrow(JsonString *p, u32 N){ +- u64 nTotal = N<p->nAlloc ? p->nAlloc*2 : p->nAlloc+N+10; +- char *zNew; +- if( p->bStatic ){ +- if( p->bErr ) return 1; +- zNew = sqlite3_malloc64(nTotal); +- if( zNew==0 ){ +- jsonOom(p); +- return SQLITE_NOMEM; +- } +- memcpy(zNew, p->zBuf, (size_t)p->nUsed); +- p->zBuf = zNew; +- p->bStatic = 0; +- }else{ +- zNew = sqlite3_realloc64(p->zBuf, nTotal); +- if( zNew==0 ){ +- jsonOom(p); +- return SQLITE_NOMEM; +- } +- p->zBuf = zNew; +- } +- p->nAlloc = nTotal; +- return SQLITE_OK; +-} +- +-/* Append N bytes from zIn onto the end of the JsonString string. +-*/ +-static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){ +- if( (N+p->nUsed >= p->nAlloc) && jsonGrow(p,N)!=0 ) return; +- memcpy(p->zBuf+p->nUsed, zIn, N); +- p->nUsed += N; +-} +- +-/* Append formatted text (not to exceed N bytes) to the JsonString. +-*/ +-static void jsonPrintf(int N, JsonString *p, const char *zFormat, ...){ +- va_list ap; +- if( (p->nUsed + N >= p->nAlloc) && jsonGrow(p, N) ) return; +- va_start(ap, zFormat); +- sqlite3_vsnprintf(N, p->zBuf+p->nUsed, zFormat, ap); +- va_end(ap); +- p->nUsed += (int)strlen(p->zBuf+p->nUsed); +-} +- +-/* Append a single character +-*/ +-static void jsonAppendChar(JsonString *p, char c){ +- if( p->nUsed>=p->nAlloc && jsonGrow(p,1)!=0 ) return; +- p->zBuf[p->nUsed++] = c; +-} +- +-/* Append a comma separator to the output buffer, if the previous +-** character is not '[' or '{'. +-*/ +-static void jsonAppendSeparator(JsonString *p){ +- char c; +- if( p->nUsed==0 ) return; +- c = p->zBuf[p->nUsed-1]; +- if( c!='[' && c!='{' ) jsonAppendChar(p, ','); +-} +- +-/* Append the N-byte string in zIn to the end of the JsonString string +-** under construction. Enclose the string in "..." and escape +-** any double-quotes or backslash characters contained within the +-** string. +-*/ +-static void jsonAppendString(JsonString *p, const char *zIn, u32 N){ +- u32 i; +- if( (N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0 ) return; +- p->zBuf[p->nUsed++] = '"'; +- for(i=0; i<N; i++){ +- unsigned char c = ((unsigned const char*)zIn)[i]; +- if( c=='"' || c=='\\' ){ +- json_simple_escape: +- if( (p->nUsed+N+3-i > p->nAlloc) && jsonGrow(p,N+3-i)!=0 ) return; +- p->zBuf[p->nUsed++] = '\\'; +- }else if( c<=0x1f ){ +- static const char aSpecial[] = { +- 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +- }; +- assert( sizeof(aSpecial)==32 ); +- assert( aSpecial['\b']=='b' ); +- assert( aSpecial['\f']=='f' ); +- assert( aSpecial['\n']=='n' ); +- assert( aSpecial['\r']=='r' ); +- assert( aSpecial['\t']=='t' ); +- if( aSpecial[c] ){ +- c = aSpecial[c]; +- goto json_simple_escape; +- } +- if( (p->nUsed+N+7+i > p->nAlloc) && jsonGrow(p,N+7-i)!=0 ) return; +- p->zBuf[p->nUsed++] = '\\'; +- p->zBuf[p->nUsed++] = 'u'; +- p->zBuf[p->nUsed++] = '0'; +- p->zBuf[p->nUsed++] = '0'; +- p->zBuf[p->nUsed++] = '0' + (c>>4); +- 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 */ ++static void sessionAppendRecordMerge( ++ SessionBuffer *pBuf, /* Buffer to append to */ ++ int nCol, /* Number of columns in each record */ ++ u8 *a1, int n1, /* Record 1 */ ++ u8 *a2, int n2, /* Record 2 */ ++ int *pRc /* IN/OUT: error code */ + ){ +- 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); +- u32 n = (u32)sqlite3_value_bytes(pValue); +- if( sqlite3_value_subtype(pValue)==JSON_SUBTYPE ){ +- jsonAppendRaw(p, z, n); ++ sessionBufferGrow(pBuf, n1+n2, pRc); ++ if( *pRc==SQLITE_OK ){ ++ int i; ++ u8 *pOut = &pBuf->aBuf[pBuf->nBuf]; ++ for(i=0; i<nCol; i++){ ++ int nn1 = sessionSerialLen(a1); ++ int nn2 = sessionSerialLen(a2); ++ if( *a1==0 || *a1==0xFF ){ ++ memcpy(pOut, a2, nn2); ++ pOut += nn2; + }else{ +- jsonAppendString(p, z, n); ++ memcpy(pOut, a1, nn1); ++ pOut += nn1; + } +- break; ++ a1 += nn1; ++ a2 += nn2; + } +- default: { +- if( p->bErr==0 ){ +- sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1); +- p->bErr = 2; +- jsonReset(p); +- } +- break; +- } +- } +-} + +- +-/* Make the JSON in p the result of the SQL function. +-*/ +-static void jsonResult(JsonString *p){ +- if( p->bErr==0 ){ +- sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed, +- p->bStatic ? SQLITE_TRANSIENT : sqlite3_free, +- SQLITE_UTF8); +- jsonZero(p); ++ pBuf->nBuf = pOut-pBuf->aBuf; ++ assert( pBuf->nBuf<=pBuf->nAlloc ); + } +- assert( p->bStatic ); + } + +-/************************************************************************** +-** Utility routines for dealing with JsonNode and JsonParse objects +-**************************************************************************/ +- + /* +-** Return the number of consecutive JsonNode slots need to represent +-** the parsed JSON at pNode. The minimum answer is 1. For ARRAY and +-** OBJECT types, the number might be larger. ++** This function is called when rebasing a local UPDATE change against one ++** or more remote UPDATE changes. The aRec/nRec buffer contains the current ++** old.* and new.* records for the change. The rebase buffer (a single ++** record) is in aChange/nChange. The rebased change is appended to buffer ++** pBuf. + ** +-** Appended elements are not counted. The value returned is the number +-** by which the JsonNode counter should increment in order to go to the +-** next peer value. ++** Rebasing the UPDATE involves: ++** ++** * Removing any changes to fields for which the corresponding field ++** in the rebase buffer is set to "replaced" (type 0xFF). If this ++** means the UPDATE change updates no fields, nothing is appended ++** to the output buffer. ++** ++** * For each field modified by the local change for which the ++** corresponding field in the rebase buffer is not "undefined" (0x00) ++** or "replaced" (0xFF), the old.* value is replaced by the value ++** in the rebase buffer. + */ +-static u32 jsonNodeSize(JsonNode *pNode){ +- return pNode->eType>=JSON_ARRAY ? pNode->n+1 : 1; +-} +- +-/* +-** Reclaim all memory allocated by a JsonParse object. But do not +-** delete the JsonParse object itself. +-*/ +-static void jsonParseReset(JsonParse *pParse){ +- sqlite3_free(pParse->aNode); +- pParse->aNode = 0; +- pParse->nNode = 0; +- pParse->nAlloc = 0; +- sqlite3_free(pParse->aUp); +- pParse->aUp = 0; +-} +- +-/* +-** Free a JsonParse object that was obtained from sqlite3_malloc(). +-*/ +-static void jsonParseFree(JsonParse *pParse){ +- jsonParseReset(pParse); +- sqlite3_free(pParse); +-} +- +-/* +-** Convert the JsonNode pNode into a pure JSON string and +-** append to pOut. Subsubstructure is also included. Return +-** the number of JsonNode objects that are encoded. +-*/ +-static void jsonRenderNode( +- JsonNode *pNode, /* The node to render */ +- JsonString *pOut, /* Write JSON here */ +- sqlite3_value **aReplace /* Replacement values */ ++static void sessionAppendPartialUpdate( ++ SessionBuffer *pBuf, /* Append record here */ ++ sqlite3_changeset_iter *pIter, /* Iterator pointed at local change */ ++ u8 *aRec, int nRec, /* Local change */ ++ u8 *aChange, int nChange, /* Record to rebase against */ ++ int *pRc /* IN/OUT: Return Code */ + ){ +- if( pNode->jnFlags & (JNODE_REPLACE|JNODE_PATCH) ){ +- if( pNode->jnFlags & JNODE_REPLACE ){ +- jsonAppendValue(pOut, aReplace[pNode->u.iReplace]); +- return; +- } +- pNode = pNode->u.pPatch; +- } +- switch( pNode->eType ){ +- default: { +- assert( pNode->eType==JSON_NULL ); +- jsonAppendRaw(pOut, "null", 4); +- break; +- } +- case JSON_TRUE: { +- jsonAppendRaw(pOut, "true", 4); +- break; +- } +- case JSON_FALSE: { +- jsonAppendRaw(pOut, "false", 5); +- break; +- } +- case JSON_STRING: { +- if( pNode->jnFlags & JNODE_RAW ){ +- jsonAppendString(pOut, pNode->u.zJContent, pNode->n); +- break; +- } +- /* Fall through into the next case */ +- } +- case JSON_REAL: +- case JSON_INT: { +- jsonAppendRaw(pOut, pNode->u.zJContent, pNode->n); +- break; +- } +- case JSON_ARRAY: { +- u32 j = 1; +- jsonAppendChar(pOut, '['); +- for(;;){ +- while( j<=pNode->n ){ +- if( (pNode[j].jnFlags & JNODE_REMOVE)==0 ){ +- jsonAppendSeparator(pOut); +- jsonRenderNode(&pNode[j], pOut, aReplace); +- } +- j += jsonNodeSize(&pNode[j]); +- } +- if( (pNode->jnFlags & JNODE_APPEND)==0 ) break; +- pNode = &pNode[pNode->u.iAppend]; +- j = 1; +- } +- jsonAppendChar(pOut, ']'); +- break; +- } +- case JSON_OBJECT: { +- u32 j = 1; +- jsonAppendChar(pOut, '{'); +- for(;;){ +- while( j<=pNode->n ){ +- if( (pNode[j+1].jnFlags & JNODE_REMOVE)==0 ){ +- jsonAppendSeparator(pOut); +- jsonRenderNode(&pNode[j], pOut, aReplace); +- jsonAppendChar(pOut, ':'); +- jsonRenderNode(&pNode[j+1], pOut, aReplace); +- } +- j += 1 + jsonNodeSize(&pNode[j+1]); +- } +- if( (pNode->jnFlags & JNODE_APPEND)==0 ) break; +- pNode = &pNode[pNode->u.iAppend]; +- j = 1; +- } +- jsonAppendChar(pOut, '}'); +- break; +- } +- } +-} ++ sessionBufferGrow(pBuf, 2+nRec+nChange, pRc); ++ if( *pRc==SQLITE_OK ){ ++ int bData = 0; ++ u8 *pOut = &pBuf->aBuf[pBuf->nBuf]; ++ int i; ++ u8 *a1 = aRec; ++ u8 *a2 = aChange; + +-/* +-** Return a JsonNode and all its descendents as a JSON string. +-*/ +-static void jsonReturnJson( +- JsonNode *pNode, /* Node to return */ +- sqlite3_context *pCtx, /* Return value for this function */ +- sqlite3_value **aReplace /* Array of replacement values */ +-){ +- JsonString s; +- jsonInit(&s, pCtx); +- jsonRenderNode(pNode, &s, aReplace); +- jsonResult(&s); +- sqlite3_result_subtype(pCtx, JSON_SUBTYPE); +-} +- +-/* +-** Make the JsonNode the return value of the function. +-*/ +-static void jsonReturn( +- JsonNode *pNode, /* Node to return */ +- sqlite3_context *pCtx, /* Return value for this function */ +- sqlite3_value **aReplace /* Array of replacement values */ +-){ +- switch( pNode->eType ){ +- default: { +- assert( pNode->eType==JSON_NULL ); +- sqlite3_result_null(pCtx); +- break; +- } +- case JSON_TRUE: { +- sqlite3_result_int(pCtx, 1); +- break; +- } +- case JSON_FALSE: { +- sqlite3_result_int(pCtx, 0); +- break; +- } +- case JSON_INT: { +- sqlite3_int64 i = 0; +- const char *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; ++ *pOut++ = SQLITE_UPDATE; ++ *pOut++ = pIter->bIndirect; ++ for(i=0; i<pIter->nCol; i++){ ++ int n1 = sessionSerialLen(a1); ++ int n2 = sessionSerialLen(a2); ++ if( pIter->abPK[i] || a2[0]==0 ){ ++ if( !pIter->abPK[i] ) bData = 1; ++ memcpy(pOut, a1, n1); ++ pOut += n1; ++ }else if( a2[0]!=0xFF ){ ++ bData = 1; ++ memcpy(pOut, a2, n2); ++ pOut += n2; ++ }else{ ++ *pOut++ = '\0'; + } +- if( pNode->u.zJContent[0]=='-' ){ i = -i; } +- sqlite3_result_int64(pCtx, i); +- int_done: +- break; +- int_as_real: /* fall through to real */; ++ a1 += n1; ++ a2 += n2; + } +- case JSON_REAL: { +- double r; +-#ifdef SQLITE_AMALGAMATION +- const char *z = pNode->u.zJContent; +- sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8); +-#else +- 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 ){ +- 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 */ +- 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 = pNode->u.zJContent; +- char *zOut; +- u32 j; +- zOut = sqlite3_malloc( n+1 ); +- if( zOut==0 ){ +- sqlite3_result_error_nomem(pCtx); +- break; ++ if( bData ){ ++ a2 = aChange; ++ for(i=0; i<pIter->nCol; i++){ ++ int n1 = sessionSerialLen(a1); ++ int n2 = sessionSerialLen(a2); ++ if( pIter->abPK[i] || a2[0]!=0xFF ){ ++ memcpy(pOut, a1, n1); ++ pOut += n1; ++ }else{ ++ *pOut++ = '\0'; + } +- 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 = 0, k; +- for(k=0; k<4; i++, k++){ +- assert( i<n-2 ); +- c = z[i+1]; +- assert( safe_isxdigit(c) ); +- if( c<='9' ) v = v*16 + c - '0'; +- else if( c<='F' ) v = v*16 + c - 'A' + 10; +- else v = v*16 + c - 'a' + 10; +- } +- if( v==0 ) break; +- if( v<=0x7f ){ +- zOut[j++] = (char)v; +- }else if( v<=0x7ff ){ +- zOut[j++] = (char)(0xc0 | (v>>6)); +- zOut[j++] = 0x80 | (v&0x3f); +- }else{ +- zOut[j++] = (char)(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); ++ a1 += n1; ++ a2 += n2; + } +- break; ++ pBuf->nBuf = (pOut - pBuf->aBuf); + } +- case JSON_ARRAY: +- case JSON_OBJECT: { +- jsonReturnJson(pNode, pCtx, aReplace); +- break; +- } + } + } + +-/* Forward reference */ +-static int jsonParseAddNode(JsonParse*,u32,u32,const char*); +- + /* +-** A macro to hint to the compiler that a function should not be +-** inlined. ++** pIter is configured to iterate through a changeset. This function rebases ++** that changeset according to the current configuration of the rebaser ++** object passed as the first argument. If no error occurs and argument xOutput ++** is not NULL, then the changeset is returned to the caller by invoking ++** xOutput zero or more times and SQLITE_OK returned. Or, if xOutput is NULL, ++** then (*ppOut) is set to point to a buffer containing the rebased changeset ++** before this function returns. In this case (*pnOut) is set to the size of ++** the buffer in bytes. It is the responsibility of the caller to eventually ++** free the (*ppOut) buffer using sqlite3_free(). ++** ++** If an error occurs, an SQLite error code is returned. If ppOut and ++** pnOut are not NULL, then the two output parameters are set to 0 before ++** returning. + */ +-#if defined(__GNUC__) +-# define JSON_NOINLINE __attribute__((noinline)) +-#elif defined(_MSC_VER) && _MSC_VER>=1310 +-# define JSON_NOINLINE __declspec(noinline) +-#else +-# define JSON_NOINLINE +-#endif +- +- +-static JSON_NOINLINE int jsonParseAddNodeExpand( +- JsonParse *pParse, /* Append the node to this object */ +- u32 eType, /* Node type */ +- u32 n, /* Content size or sub-node count */ +- const char *zContent /* Content */ ++static int sessionRebase( ++ sqlite3_rebaser *p, /* Rebaser hash table */ ++ sqlite3_changeset_iter *pIter, /* Input data */ ++ int (*xOutput)(void *pOut, const void *pData, int nData), ++ void *pOut, /* Context for xOutput callback */ ++ int *pnOut, /* OUT: Number of bytes in output changeset */ ++ void **ppOut /* OUT: Inverse of pChangeset */ + ){ +- u32 nNew; +- JsonNode *pNew; +- assert( pParse->nNode>=pParse->nAlloc ); +- if( pParse->oom ) return -1; +- nNew = pParse->nAlloc*2 + 10; +- pNew = sqlite3_realloc(pParse->aNode, sizeof(JsonNode)*nNew); +- if( pNew==0 ){ +- pParse->oom = 1; +- return -1; +- } +- pParse->nAlloc = nNew; +- pParse->aNode = pNew; +- assert( pParse->nNode<pParse->nAlloc ); +- return jsonParseAddNode(pParse, eType, n, zContent); +-} ++ int rc = SQLITE_OK; ++ u8 *aRec = 0; ++ int nRec = 0; ++ int bNew = 0; ++ SessionTable *pTab = 0; ++ SessionBuffer sOut = {0,0,0}; + +-/* +-** Create a new JsonNode instance based on the arguments and append that +-** instance to the JsonParse. Return the index in pParse->aNode[] of the +-** new node, or -1 if a memory allocation fails. +-*/ +-static int jsonParseAddNode( +- JsonParse *pParse, /* Append the node to this object */ +- u32 eType, /* Node type */ +- u32 n, /* Content size or sub-node count */ +- const char *zContent /* Content */ +-){ +- JsonNode *p; +- if( pParse->nNode>=pParse->nAlloc ){ +- return jsonParseAddNodeExpand(pParse, eType, n, zContent); +- } +- p = &pParse->aNode[pParse->nNode]; +- p->eType = (u8)eType; +- p->jnFlags = 0; +- p->n = n; +- p->u.zJContent = zContent; +- return pParse->nNode++; +-} ++ while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec, &bNew) ){ ++ SessionChange *pChange = 0; ++ int bDone = 0; + +-/* +-** 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( !safe_isxdigit(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( safe_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( safe_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( bNew ){ ++ const char *zTab = pIter->zTab; ++ for(pTab=p->grp.pList; pTab; pTab=pTab->pNext){ ++ if( 0==sqlite3_stricmp(pTab->zName, zTab) ) break; + } +- 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( safe_isspace(z[j]) ){ j++; } +- if( z[j]!=':' ) return -1; +- j++; +- x = jsonParseValue(pParse, j); +- pParse->iDepth--; +- if( x<0 ) return -1; +- j = x; +- while( safe_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; +- for(j=i+1;;j++){ +- while( safe_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( safe_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 +- && !safe_isalnum(z[i+4]) ){ +- jsonParseAddNode(pParse, JSON_NULL, 0, 0); +- return i+4; +- }else if( c=='t' +- && strncmp(z+i,"true",4)==0 +- && !safe_isalnum(z[i+4]) ){ +- jsonParseAddNode(pParse, JSON_TRUE, 0, 0); +- return i+4; +- }else if( c=='f' +- && strncmp(z+i,"false",5)==0 +- && !safe_isalnum(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 */ +- } +-} ++ bNew = 0; + +-/* +-** 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. +-** +-** pParse is uninitialized when this routine is called. +-*/ +-static int jsonParse( +- JsonParse *pParse, /* Initialize and fill this JsonParse object */ +- sqlite3_context *pCtx, /* Report errors here */ +- const char *zJson /* Input JSON text to be parsed */ +-){ +- int i; +- memset(pParse, 0, sizeof(*pParse)); +- 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( safe_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); ++ /* A patchset may not be rebased */ ++ if( pIter->bPatchset ){ ++ rc = SQLITE_ERROR; + } +- } +- jsonParseReset(pParse); +- return 1; +- } +- return 0; +-} + +-/* Mark node i of pParse as being a child of iParent. Call recursively +-** to fill in all the descendants of node i. +-*/ +-static void jsonParseFillInParentage(JsonParse *pParse, u32 i, u32 iParent){ +- JsonNode *pNode = &pParse->aNode[i]; +- u32 j; +- pParse->aUp[i] = iParent; +- switch( pNode->eType ){ +- case JSON_ARRAY: { +- for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j)){ +- jsonParseFillInParentage(pParse, i+j, i); +- } +- break; ++ /* Append a table header to the output for this new table */ ++ sessionAppendByte(&sOut, pIter->bPatchset ? 'P' : 'T', &rc); ++ sessionAppendVarint(&sOut, pIter->nCol, &rc); ++ sessionAppendBlob(&sOut, pIter->abPK, pIter->nCol, &rc); ++ sessionAppendBlob(&sOut,(u8*)pIter->zTab,(int)strlen(pIter->zTab)+1,&rc); + } +- case JSON_OBJECT: { +- for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j+1)+1){ +- pParse->aUp[i+j] = i; +- jsonParseFillInParentage(pParse, i+j+1, i); +- } +- break; +- } +- default: { +- break; +- } +- } +-} + +-/* +-** Compute the parentage of all nodes in a completed parse. +-*/ +-static int jsonParseFindParents(JsonParse *pParse){ +- u32 *aUp; +- assert( pParse->aUp==0 ); +- aUp = pParse->aUp = sqlite3_malloc( sizeof(u32)*pParse->nNode ); +- if( aUp==0 ){ +- pParse->oom = 1; +- return SQLITE_NOMEM; +- } +- jsonParseFillInParentage(pParse, 0, 0); +- return SQLITE_OK; +-} ++ if( pTab && rc==SQLITE_OK ){ ++ int iHash = sessionChangeHash(pTab, 0, aRec, pTab->nChange); + +-/* +-** Magic number used for the JSON parse cache in sqlite3_get_auxdata() +-*/ +-#define JSON_CACHE_ID (-429938) +- +-/* +-** 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 +-){ +- const char *zJson = (const char*)sqlite3_value_text(argv[0]); +- int nJson = sqlite3_value_bytes(argv[0]); +- JsonParse *p; +- if( zJson==0 ) return 0; +- p = (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID); +- if( p && p->nJson==nJson && memcmp(p->zJson,zJson,nJson)==0 ){ +- p->nErr = 0; +- return p; /* The cached entry matches, so return it */ +- } +- p = sqlite3_malloc( sizeof(*p) + nJson + 1 ); +- if( p==0 ){ +- 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, pCtx, p->zJson) ){ +- sqlite3_free(p); +- return 0; +- } +- p->nJson = nJson; +- sqlite3_set_auxdata(pCtx, JSON_CACHE_ID, p, (void(*)(void*))jsonParseFree); +- return (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID); +-} +- +-/* +-** Compare the OBJECT label at pNode against zKey,nKey. Return true on +-** a match. +-*/ +-static int jsonLabelCompare(JsonNode *pNode, const char *zKey, u32 nKey){ +- 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 +-** node. +-** +-** If pApnd!=0, then try to append new nodes to complete zPath if it is +-** possible to do so and if no existing node corresponds to zPath. If +-** new nodes are appended *pApnd is set to 1. +-*/ +-static JsonNode *jsonLookupStep( +- JsonParse *pParse, /* The JSON to search */ +- u32 iRoot, /* Begin the search at this node */ +- const char *zPath, /* The path to search */ +- int *pApnd, /* Append nodes to complete path if not NULL */ +- const char **pzErr /* Make *pzErr point to any syntax error in zPath */ +-){ +- u32 i, j, nKey; +- const char *zKey; +- JsonNode *pRoot = &pParse->aNode[iRoot]; +- if( zPath[0]==0 ) return pRoot; +- if( zPath[0]=='.' ){ +- if( pRoot->eType!=JSON_OBJECT ) return 0; +- zPath++; +- if( zPath[0]=='"' ){ +- zKey = zPath + 1; +- for(i=1; zPath[i] && zPath[i]!='"'; i++){} +- nKey = i-1; +- if( zPath[i] ){ +- i++; +- }else{ +- *pzErr = zPath; +- return 0; +- } +- }else{ +- zKey = zPath; +- for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){} +- nKey = i; +- } +- if( nKey==0 ){ +- *pzErr = zPath; +- return 0; +- } +- j = 1; +- for(;;){ +- while( j<=pRoot->n ){ +- if( jsonLabelCompare(pRoot+j, zKey, nKey) ){ +- return jsonLookupStep(pParse, iRoot+j+1, &zPath[i], pApnd, pzErr); ++ for(pChange=pTab->apChange[iHash]; pChange; pChange=pChange->pNext){ ++ if( sessionChangeEqual(pTab, 0, aRec, 0, pChange->aRecord) ){ ++ break; + } +- j++; +- j += jsonNodeSize(&pRoot[j]); + } +- if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break; +- iRoot += pRoot->u.iAppend; +- pRoot = &pParse->aNode[iRoot]; +- j = 1; + } +- if( pApnd ){ +- u32 iStart, iLabel; +- JsonNode *pNode; +- iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0); +- iLabel = jsonParseAddNode(pParse, JSON_STRING, i, zPath); +- zPath += i; +- pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr); +- if( pParse->oom ) return 0; +- if( pNode ){ +- pRoot = &pParse->aNode[iRoot]; +- pRoot->u.iAppend = iStart - iRoot; +- pRoot->jnFlags |= JNODE_APPEND; +- pParse->aNode[iLabel].jnFlags |= JNODE_RAW; +- } +- return pNode; +- } +- }else if( zPath[0]=='[' && safe_isdigit(zPath[1]) ){ +- if( pRoot->eType!=JSON_ARRAY ) return 0; +- i = 0; +- j = 1; +- while( safe_isdigit(zPath[j]) ){ +- i = i*10 + zPath[j] - '0'; +- j++; +- } +- if( zPath[j]!=']' ){ +- *pzErr = zPath; +- return 0; +- } +- zPath += j + 1; +- j = 1; +- for(;;){ +- while( j<=pRoot->n && (i>0 || (pRoot[j].jnFlags & JNODE_REMOVE)!=0) ){ +- if( (pRoot[j].jnFlags & JNODE_REMOVE)==0 ) i--; +- j += jsonNodeSize(&pRoot[j]); +- } +- if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break; +- iRoot += pRoot->u.iAppend; +- pRoot = &pParse->aNode[iRoot]; +- j = 1; +- } +- if( j<=pRoot->n ){ +- return jsonLookupStep(pParse, iRoot+j, zPath, pApnd, pzErr); +- } +- if( i==0 && pApnd ){ +- u32 iStart; +- JsonNode *pNode; +- iStart = jsonParseAddNode(pParse, JSON_ARRAY, 1, 0); +- pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr); +- if( pParse->oom ) return 0; +- if( pNode ){ +- pRoot = &pParse->aNode[iRoot]; +- pRoot->u.iAppend = iStart - iRoot; +- pRoot->jnFlags |= JNODE_APPEND; +- } +- return pNode; +- } +- }else{ +- *pzErr = zPath; +- } +- return 0; +-} + +-/* +-** Append content to pParse that will complete zPath. Return a pointer +-** to the inserted node, or return NULL if the append fails. +-*/ +-static JsonNode *jsonLookupAppend( +- JsonParse *pParse, /* Append content to the JSON parse */ +- const char *zPath, /* Description of content to append */ +- int *pApnd, /* Set this flag to 1 */ +- const char **pzErr /* Make this point to any syntax error */ +-){ +- *pApnd = 1; +- if( zPath[0]==0 ){ +- jsonParseAddNode(pParse, JSON_NULL, 0, 0); +- return pParse->oom ? 0 : &pParse->aNode[pParse->nNode-1]; +- } +- if( zPath[0]=='.' ){ +- jsonParseAddNode(pParse, JSON_OBJECT, 0, 0); +- }else if( strncmp(zPath,"[0]",3)==0 ){ +- jsonParseAddNode(pParse, JSON_ARRAY, 0, 0); +- }else{ +- return 0; +- } +- if( pParse->oom ) return 0; +- return jsonLookupStep(pParse, pParse->nNode-1, zPath, pApnd, pzErr); +-} ++ if( pChange ){ ++ assert( pChange->op==SQLITE_DELETE || pChange->op==SQLITE_INSERT ); ++ switch( pIter->op ){ ++ case SQLITE_INSERT: ++ if( pChange->op==SQLITE_INSERT ){ ++ bDone = 1; ++ if( pChange->bIndirect==0 ){ ++ sessionAppendByte(&sOut, SQLITE_UPDATE, &rc); ++ sessionAppendByte(&sOut, pIter->bIndirect, &rc); ++ sessionAppendBlob(&sOut, pChange->aRecord, pChange->nRecord, &rc); ++ sessionAppendBlob(&sOut, aRec, nRec, &rc); ++ } ++ } ++ break; + +-/* +-** Return the text of a syntax error message on a JSON path. Space is +-** obtained from sqlite3_malloc(). +-*/ +-static char *jsonPathSyntaxError(const char *zErr){ +- return sqlite3_mprintf("JSON path error near '%q'", zErr); +-} ++ case SQLITE_UPDATE: ++ bDone = 1; ++ if( pChange->op==SQLITE_DELETE ){ ++ if( pChange->bIndirect==0 ){ ++ u8 *pCsr = aRec; ++ sessionSkipRecord(&pCsr, pIter->nCol); ++ sessionAppendByte(&sOut, SQLITE_INSERT, &rc); ++ sessionAppendByte(&sOut, pIter->bIndirect, &rc); ++ sessionAppendRecordMerge(&sOut, pIter->nCol, ++ pCsr, nRec-(pCsr-aRec), ++ pChange->aRecord, pChange->nRecord, &rc ++ ); ++ } ++ }else{ ++ sessionAppendPartialUpdate(&sOut, pIter, ++ aRec, nRec, pChange->aRecord, pChange->nRecord, &rc ++ ); ++ } ++ break; + +-/* +-** Do a node lookup using zPath. Return a pointer to the node on success. +-** Return NULL if not found or if there is an error. +-** +-** On an error, write an error message into pCtx and increment the +-** pParse->nErr counter. +-** +-** If pApnd!=NULL then try to append missing nodes and set *pApnd = 1 if +-** nodes are appended. +-*/ +-static JsonNode *jsonLookup( +- JsonParse *pParse, /* The JSON to search */ +- const char *zPath, /* The path to search */ +- int *pApnd, /* Append nodes to complete path if not NULL */ +- sqlite3_context *pCtx /* Report errors here, if not NULL */ +-){ +- const char *zErr = 0; +- JsonNode *pNode = 0; +- char *zMsg; +- +- if( zPath==0 ) return 0; +- if( zPath[0]!='$' ){ +- zErr = zPath; +- goto lookup_err; +- } +- zPath++; +- pNode = jsonLookupStep(pParse, 0, zPath, pApnd, &zErr); +- if( zErr==0 ) return pNode; +- +-lookup_err: +- pParse->nErr++; +- assert( zErr!=0 && pCtx!=0 ); +- zMsg = jsonPathSyntaxError(zErr); +- if( zMsg ){ +- sqlite3_result_error(pCtx, zMsg, -1); +- sqlite3_free(zMsg); +- }else{ +- sqlite3_result_error_nomem(pCtx); +- } +- return 0; +-} +- +- +-/* +-** Report the wrong number of arguments for json_insert(), json_replace() +-** or json_set(). +-*/ +-static void jsonWrongNumArgs( +- sqlite3_context *pCtx, +- const char *zFuncName +-){ +- char *zMsg = sqlite3_mprintf("json_%s() needs an odd number of arguments", +- zFuncName); +- sqlite3_result_error(pCtx, zMsg, -1); +- sqlite3_free(zMsg); +-} +- +-/* +-** Mark all NULL entries in the Object passed in as JNODE_REMOVE. +-*/ +-static void jsonRemoveAllNulls(JsonNode *pNode){ +- int i, n; +- assert( pNode->eType==JSON_OBJECT ); +- n = pNode->n; +- for(i=2; i<=n; i += jsonNodeSize(&pNode[i])+1){ +- switch( pNode[i].eType ){ +- case JSON_NULL: +- pNode[i].jnFlags |= JNODE_REMOVE; +- break; +- case JSON_OBJECT: +- jsonRemoveAllNulls(&pNode[i]); +- break; ++ default: ++ assert( pIter->op==SQLITE_DELETE ); ++ bDone = 1; ++ if( pChange->op==SQLITE_INSERT ){ ++ sessionAppendByte(&sOut, SQLITE_DELETE, &rc); ++ sessionAppendByte(&sOut, pIter->bIndirect, &rc); ++ sessionAppendRecordMerge(&sOut, pIter->nCol, ++ pChange->aRecord, pChange->nRecord, aRec, nRec, &rc ++ ); ++ } ++ break; ++ } + } +- } +-} + +- +-/**************************************************************************** +-** SQL functions used for testing and debugging +-****************************************************************************/ +- +-#ifdef SQLITE_DEBUG +-/* +-** The json_parse(JSON) function returns a string which describes +-** a parse of the JSON provided. Or it returns NULL if JSON is not +-** well-formed. +-*/ +-static void jsonParseFunc( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- JsonString s; /* Output string - not real JSON */ +- JsonParse x; /* The parse */ +- u32 i; +- +- assert( argc==1 ); +- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; +- jsonParseFindParents(&x); +- jsonInit(&s, ctx); +- for(i=0; i<x.nNode; i++){ +- const char *zType; +- if( x.aNode[i].jnFlags & JNODE_LABEL ){ +- assert( x.aNode[i].eType==JSON_STRING ); +- zType = "label"; +- }else{ +- zType = jsonType[x.aNode[i].eType]; ++ if( bDone==0 ){ ++ sessionAppendByte(&sOut, pIter->op, &rc); ++ sessionAppendByte(&sOut, pIter->bIndirect, &rc); ++ sessionAppendBlob(&sOut, aRec, nRec, &rc); + } +- jsonPrintf(100, &s,"node %3u: %7s n=%-4d up=%-4d", +- i, zType, x.aNode[i].n, x.aUp[i]); +- if( x.aNode[i].u.zJContent!=0 ){ +- jsonAppendRaw(&s, " ", 1); +- jsonAppendRaw(&s, x.aNode[i].u.zJContent, x.aNode[i].n); ++ if( rc==SQLITE_OK && xOutput && sOut.nBuf>sessions_strm_chunk_size ){ ++ rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); ++ sOut.nBuf = 0; + } +- jsonAppendRaw(&s, "\n", 1); ++ if( rc ) break; + } +- jsonParseReset(&x); +- jsonResult(&s); +-} + +-/* +-** The json_test1(JSON) function return true (1) if the input is JSON +-** text generated by another json function. It returns (0) if the input +-** is not known to be JSON. +-*/ +-static void jsonTest1Func( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- UNUSED_PARAM(argc); +- sqlite3_result_int(ctx, sqlite3_value_subtype(argv[0])==JSON_SUBTYPE); +-} +-#endif /* SQLITE_DEBUG */ +- +-/**************************************************************************** +-** Scalar SQL function implementations +-****************************************************************************/ +- +-/* +-** Implementation of the json_QUOTE(VALUE) function. Return a JSON value +-** corresponding to the SQL value input. Mostly this means putting +-** double-quotes around strings and returning the unquoted string "null" +-** when given a NULL input. +-*/ +-static void jsonQuoteFunc( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- JsonString jx; +- UNUSED_PARAM(argc); +- +- jsonInit(&jx, ctx); +- jsonAppendValue(&jx, argv[0]); +- jsonResult(&jx); +- sqlite3_result_subtype(ctx, JSON_SUBTYPE); +-} +- +-/* +-** Implementation of the json_array(VALUE,...) function. Return a JSON +-** array that contains all values given in arguments. Or if any argument +-** is a BLOB, throw an error. +-*/ +-static void jsonArrayFunc( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- int i; +- JsonString jx; +- +- jsonInit(&jx, ctx); +- jsonAppendChar(&jx, '['); +- for(i=0; i<argc; i++){ +- jsonAppendSeparator(&jx); +- jsonAppendValue(&jx, argv[i]); ++ if( rc!=SQLITE_OK ){ ++ sqlite3_free(sOut.aBuf); ++ memset(&sOut, 0, sizeof(sOut)); + } +- jsonAppendChar(&jx, ']'); +- jsonResult(&jx); +- sqlite3_result_subtype(ctx, JSON_SUBTYPE); +-} + +- +-/* +-** json_array_length(JSON) +-** json_array_length(JSON, PATH) +-** +-** Return the number of elements in the top-level JSON array. +-** Return 0 if the input is not a well-formed JSON array. +-*/ +-static void jsonArrayLengthFunc( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- JsonParse *p; /* The parse */ +- sqlite3_int64 n = 0; +- u32 i; +- JsonNode *pNode; +- +- p = jsonParseCached(ctx, argv); +- if( p==0 ) return; +- assert( p->nNode ); +- if( argc==2 ){ +- const char *zPath = (const char*)sqlite3_value_text(argv[1]); +- pNode = jsonLookup(p, zPath, 0, ctx); +- }else{ +- pNode = p->aNode; +- } +- if( pNode==0 ){ +- return; +- } +- if( pNode->eType==JSON_ARRAY ){ +- assert( (pNode->jnFlags & JNODE_APPEND)==0 ); +- for(i=1; i<=pNode->n; n++){ +- i += jsonNodeSize(&pNode[i]); +- } +- } +- sqlite3_result_int64(ctx, n); +-} +- +-/* +-** json_extract(JSON, PATH, ...) +-** +-** Return the element described by PATH. Return NULL if there is no +-** PATH element. If there are multiple PATHs, then return a JSON array +-** with the result from each path. Throw an error if the JSON or any PATH +-** is malformed. +-*/ +-static void jsonExtractFunc( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- JsonParse *p; /* The parse */ +- JsonNode *pNode; +- const char *zPath; +- JsonString jx; +- int i; +- +- if( argc<2 ) return; +- p = jsonParseCached(ctx, argv); +- if( p==0 ) return; +- jsonInit(&jx, ctx); +- jsonAppendChar(&jx, '['); +- for(i=1; i<argc; i++){ +- zPath = (const char*)sqlite3_value_text(argv[i]); +- pNode = jsonLookup(p, zPath, 0, ctx); +- if( p->nErr ) break; +- if( argc>2 ){ +- jsonAppendSeparator(&jx); +- if( pNode ){ +- jsonRenderNode(pNode, &jx, 0); +- }else{ +- jsonAppendRaw(&jx, "null", 4); ++ if( rc==SQLITE_OK ){ ++ if( xOutput ){ ++ if( sOut.nBuf>0 ){ ++ rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); + } +- }else if( pNode ){ +- jsonReturn(pNode, ctx, 0); ++ }else{ ++ *ppOut = (void*)sOut.aBuf; ++ *pnOut = sOut.nBuf; ++ sOut.aBuf = 0; + } + } +- if( argc>2 && i==argc ){ +- jsonAppendChar(&jx, ']'); +- jsonResult(&jx); +- sqlite3_result_subtype(ctx, JSON_SUBTYPE); +- } +- jsonReset(&jx); ++ sqlite3_free(sOut.aBuf); ++ return rc; + } + +-/* This is the RFC 7396 MergePatch algorithm. ++/* ++** Create a new rebaser object. + */ +-static JsonNode *jsonMergePatch( +- JsonParse *pParse, /* The JSON parser that contains the TARGET */ +- u32 iTarget, /* Node of the TARGET in pParse */ +- JsonNode *pPatch /* The PATCH */ +-){ +- u32 i, j; +- u32 iRoot; +- JsonNode *pTarget; +- if( pPatch->eType!=JSON_OBJECT ){ +- return pPatch; +- } +- assert( iTarget>=0 && iTarget<pParse->nNode ); +- pTarget = &pParse->aNode[iTarget]; +- assert( (pPatch->jnFlags & JNODE_APPEND)==0 ); +- if( pTarget->eType!=JSON_OBJECT ){ +- jsonRemoveAllNulls(pPatch); +- return pPatch; +- } +- iRoot = iTarget; +- for(i=1; i<pPatch->n; i += jsonNodeSize(&pPatch[i+1])+1){ +- u32 nKey; +- const char *zKey; +- assert( pPatch[i].eType==JSON_STRING ); +- assert( pPatch[i].jnFlags & JNODE_LABEL ); +- 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]; +- if( pNew!=&pTarget[j+1] ){ +- pTarget[j+1].u.pPatch = pNew; +- pTarget[j+1].jnFlags |= JNODE_PATCH; +- } +- } +- break; +- } +- } +- if( j>=pTarget->n && pPatch[i+1].eType!=JSON_NULL ){ +- int iStart, iPatch; +- iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0); +- jsonParseAddNode(pParse, JSON_STRING, nKey, zKey); +- iPatch = jsonParseAddNode(pParse, JSON_TRUE, 0, 0); +- if( pParse->oom ) return 0; +- jsonRemoveAllNulls(pPatch); +- pTarget = &pParse->aNode[iTarget]; +- pParse->aNode[iRoot].jnFlags |= JNODE_APPEND; +- pParse->aNode[iRoot].u.iAppend = iStart - iRoot; +- iRoot = iStart; +- pParse->aNode[iPatch].jnFlags |= JNODE_PATCH; +- pParse->aNode[iPatch].u.pPatch = &pPatch[i+1]; +- } +- } +- return pTarget; +-} ++SQLITE_API int sqlite3rebaser_create(sqlite3_rebaser **ppNew){ ++ int rc = SQLITE_OK; ++ sqlite3_rebaser *pNew; + +-/* +-** Implementation of the json_mergepatch(JSON1,JSON2) function. Return a JSON +-** object that is the result of running the RFC 7396 MergePatch() algorithm +-** on the two arguments. +-*/ +-static void jsonPatchFunc( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- JsonParse x; /* The JSON that is being patched */ +- JsonParse y; /* The patch */ +- JsonNode *pResult; /* The result of the merge */ +- +- UNUSED_PARAM(argc); +- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; +- if( jsonParse(&y, ctx, (const char*)sqlite3_value_text(argv[1])) ){ +- jsonParseReset(&x); +- return; +- } +- pResult = jsonMergePatch(&x, 0, y.aNode); +- assert( pResult!=0 || x.oom ); +- if( pResult ){ +- jsonReturnJson(pResult, ctx, 0); ++ pNew = sqlite3_malloc(sizeof(sqlite3_rebaser)); ++ if( pNew==0 ){ ++ rc = SQLITE_NOMEM; + }else{ +- sqlite3_result_error_nomem(ctx); ++ memset(pNew, 0, sizeof(sqlite3_rebaser)); + } +- jsonParseReset(&x); +- jsonParseReset(&y); ++ *ppNew = pNew; ++ return rc; + } + +- +-/* +-** Implementation of the json_object(NAME,VALUE,...) function. Return a JSON +-** object that contains all name/value given in arguments. Or if any name +-** is not a string or if any value is a BLOB, throw an error. ++/* ++** Call this one or more times to configure a rebaser. + */ +-static void jsonObjectFunc( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv ++SQLITE_API int sqlite3rebaser_configure( ++ sqlite3_rebaser *p, ++ int nRebase, const void *pRebase + ){ +- int i; +- JsonString jx; +- const char *z; +- u32 n; +- +- if( argc&1 ){ +- sqlite3_result_error(ctx, "json_object() requires an even number " +- "of arguments", -1); +- return; ++ sqlite3_changeset_iter *pIter = 0; /* Iterator opened on pData/nData */ ++ int rc; /* Return code */ ++ rc = sqlite3changeset_start(&pIter, nRebase, (void*)pRebase); ++ if( rc==SQLITE_OK ){ ++ rc = sessionChangesetToHash(pIter, &p->grp, 1); + } +- jsonInit(&jx, ctx); +- jsonAppendChar(&jx, '{'); +- for(i=0; i<argc; i+=2){ +- if( sqlite3_value_type(argv[i])!=SQLITE_TEXT ){ +- sqlite3_result_error(ctx, "json_object() labels must be TEXT", -1); +- jsonReset(&jx); +- return; +- } +- jsonAppendSeparator(&jx); +- z = (const char*)sqlite3_value_text(argv[i]); +- n = (u32)sqlite3_value_bytes(argv[i]); +- jsonAppendString(&jx, z, n); +- jsonAppendChar(&jx, ':'); +- jsonAppendValue(&jx, argv[i+1]); +- } +- jsonAppendChar(&jx, '}'); +- jsonResult(&jx); +- sqlite3_result_subtype(ctx, JSON_SUBTYPE); ++ sqlite3changeset_finalize(pIter); ++ return rc; + } + +- +-/* +-** json_remove(JSON, PATH, ...) +-** +-** Remove the named elements from JSON and return the result. malformed +-** JSON or PATH arguments result in an error. ++/* ++** Rebase a changeset according to current rebaser configuration + */ +-static void jsonRemoveFunc( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv ++SQLITE_API int sqlite3rebaser_rebase( ++ sqlite3_rebaser *p, ++ int nIn, const void *pIn, ++ int *pnOut, void **ppOut + ){ +- JsonParse x; /* The parse */ +- JsonNode *pNode; +- const char *zPath; +- u32 i; ++ sqlite3_changeset_iter *pIter = 0; /* Iterator to skip through input */ ++ int rc = sqlite3changeset_start(&pIter, nIn, (void*)pIn); + +- if( argc<1 ) return; +- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; +- assert( x.nNode ); +- for(i=1; i<(u32)argc; i++){ +- zPath = (const char*)sqlite3_value_text(argv[i]); +- if( zPath==0 ) goto remove_done; +- pNode = jsonLookup(&x, zPath, 0, ctx); +- if( x.nErr ) goto remove_done; +- if( pNode ) pNode->jnFlags |= JNODE_REMOVE; ++ if( rc==SQLITE_OK ){ ++ rc = sessionRebase(p, pIter, 0, 0, pnOut, ppOut); ++ sqlite3changeset_finalize(pIter); + } +- if( (x.aNode[0].jnFlags & JNODE_REMOVE)==0 ){ +- jsonReturnJson(x.aNode, ctx, 0); +- } +-remove_done: +- jsonParseReset(&x); +-} + +-/* +-** json_replace(JSON, PATH, VALUE, ...) +-** +-** Replace the value at PATH with VALUE. If PATH does not already exist, +-** this routine is a no-op. If JSON or PATH is malformed, throw an error. +-*/ +-static void jsonReplaceFunc( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- JsonParse x; /* The parse */ +- JsonNode *pNode; +- const char *zPath; +- u32 i; +- +- if( argc<1 ) return; +- if( (argc&1)==0 ) { +- jsonWrongNumArgs(ctx, "replace"); +- return; +- } +- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; +- assert( x.nNode ); +- for(i=1; i<(u32)argc; i+=2){ +- zPath = (const char*)sqlite3_value_text(argv[i]); +- pNode = jsonLookup(&x, zPath, 0, ctx); +- if( x.nErr ) goto replace_err; +- if( pNode ){ +- pNode->jnFlags |= (u8)JNODE_REPLACE; +- pNode->u.iReplace = i + 1; +- } +- } +- if( x.aNode[0].jnFlags & JNODE_REPLACE ){ +- sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]); +- }else{ +- jsonReturnJson(x.aNode, ctx, argv); +- } +-replace_err: +- jsonParseReset(&x); ++ return rc; + } + +-/* +-** json_set(JSON, PATH, VALUE, ...) +-** +-** Set the value at PATH to VALUE. Create the PATH if it does not already +-** exist. Overwrite existing values that do exist. +-** If JSON or PATH is malformed, throw an error. +-** +-** json_insert(JSON, PATH, VALUE, ...) +-** +-** Create PATH and initialize it to VALUE. If PATH already exists, this +-** routine is a no-op. If JSON or PATH is malformed, throw an error. ++/* ++** Rebase a changeset according to current rebaser configuration + */ +-static void jsonSetFunc( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv ++SQLITE_API int sqlite3rebaser_rebase_strm( ++ sqlite3_rebaser *p, ++ int (*xInput)(void *pIn, void *pData, int *pnData), ++ void *pIn, ++ int (*xOutput)(void *pOut, const void *pData, int nData), ++ void *pOut + ){ +- JsonParse x; /* The parse */ +- JsonNode *pNode; +- const char *zPath; +- u32 i; +- int bApnd; +- int bIsSet = *(int*)sqlite3_user_data(ctx); ++ sqlite3_changeset_iter *pIter = 0; /* Iterator to skip through input */ ++ int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); + +- if( argc<1 ) return; +- if( (argc&1)==0 ) { +- jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert"); +- return; +- } +- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; +- assert( x.nNode ); +- for(i=1; i<(u32)argc; i+=2){ +- zPath = (const char*)sqlite3_value_text(argv[i]); +- bApnd = 0; +- pNode = jsonLookup(&x, zPath, &bApnd, ctx); +- if( x.oom ){ +- sqlite3_result_error_nomem(ctx); +- goto jsonSetDone; +- }else if( x.nErr ){ +- goto jsonSetDone; +- }else if( pNode && (bApnd || bIsSet) ){ +- pNode->jnFlags |= (u8)JNODE_REPLACE; +- pNode->u.iReplace = i + 1; +- } +- } +- if( x.aNode[0].jnFlags & JNODE_REPLACE ){ +- sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]); +- }else{ +- jsonReturnJson(x.aNode, ctx, argv); +- } +-jsonSetDone: +- jsonParseReset(&x); +-} +- +-/* +-** json_type(JSON) +-** json_type(JSON, PATH) +-** +-** Return the top-level "type" of a JSON string. Throw an error if +-** either the JSON or PATH inputs are not well-formed. +-*/ +-static void jsonTypeFunc( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- JsonParse x; /* The parse */ +- const char *zPath; +- JsonNode *pNode; +- +- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; +- assert( x.nNode ); +- if( argc==2 ){ +- zPath = (const char*)sqlite3_value_text(argv[1]); +- pNode = jsonLookup(&x, zPath, 0, ctx); +- }else{ +- pNode = x.aNode; +- } +- if( pNode ){ +- sqlite3_result_text(ctx, jsonType[pNode->eType], -1, SQLITE_STATIC); +- } +- jsonParseReset(&x); +-} +- +-/* +-** 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 x; /* The parse */ +- int rc = 0; +- +- UNUSED_PARAM(argc); +- if( jsonParse(&x, 0, (const char*)sqlite3_value_text(argv[0]))==0 ){ +- rc = 1; +- } +- jsonParseReset(&x); +- sqlite3_result_int(ctx, rc); +-} +- +- +-/**************************************************************************** +-** Aggregate SQL function implementations +-****************************************************************************/ +-/* +-** json_group_array(VALUE) +-** +-** Return a JSON array composed of all values in the aggregate. +-*/ +-static void jsonArrayStep( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- JsonString *pStr; +- UNUSED_PARAM(argc); +- pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); +- if( pStr ){ +- if( pStr->zBuf==0 ){ +- jsonInit(pStr, ctx); +- jsonAppendChar(pStr, '['); +- }else{ +- jsonAppendChar(pStr, ','); +- pStr->pCtx = ctx; +- } +- jsonAppendValue(pStr, argv[0]); +- } +-} +-static void jsonArrayFinal(sqlite3_context *ctx){ +- JsonString *pStr; +- pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); +- if( pStr ){ +- pStr->pCtx = ctx; +- jsonAppendChar(pStr, ']'); +- if( pStr->bErr ){ +- if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); +- assert( pStr->bStatic ); +- }else{ +- sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed, +- pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); +- pStr->bStatic = 1; +- } +- }else{ +- sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC); +- } +- sqlite3_result_subtype(ctx, JSON_SUBTYPE); +-} +- +-/* +-** json_group_obj(NAME,VALUE) +-** +-** Return a JSON object composed of all names and values in the aggregate. +-*/ +-static void jsonObjectStep( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- JsonString *pStr; +- const char *z; +- u32 n; +- UNUSED_PARAM(argc); +- pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); +- if( pStr ){ +- if( pStr->zBuf==0 ){ +- jsonInit(pStr, ctx); +- jsonAppendChar(pStr, '{'); +- }else{ +- jsonAppendChar(pStr, ','); +- pStr->pCtx = ctx; +- } +- z = (const char*)sqlite3_value_text(argv[0]); +- n = (u32)sqlite3_value_bytes(argv[0]); +- jsonAppendString(pStr, z, n); +- jsonAppendChar(pStr, ':'); +- jsonAppendValue(pStr, argv[1]); +- } +-} +-static void jsonObjectFinal(sqlite3_context *ctx){ +- JsonString *pStr; +- pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); +- if( pStr ){ +- jsonAppendChar(pStr, '}'); +- if( pStr->bErr ){ +- if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); +- assert( pStr->bStatic ); +- }else{ +- sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed, +- pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); +- pStr->bStatic = 1; +- } +- }else{ +- sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC); +- } +- sqlite3_result_subtype(ctx, JSON_SUBTYPE); +-} +- +- +-#ifndef SQLITE_OMIT_VIRTUALTABLE +-/**************************************************************************** +-** The json_each virtual table +-****************************************************************************/ +-typedef struct JsonEachCursor JsonEachCursor; +-struct JsonEachCursor { +- sqlite3_vtab_cursor base; /* Base class - must be first */ +- u32 iRowid; /* The rowid */ +- u32 iBegin; /* The first node of the scan */ +- u32 i; /* Index in sParse.aNode[] of current row */ +- u32 iEnd; /* EOF when i equals or exceeds this value */ +- u8 eType; /* Type of top-level element */ +- u8 bRecursive; /* True for json_tree(). False for json_each() */ +- char *zJson; /* Input JSON */ +- char *zRoot; /* Path by which to filter zJson */ +- JsonParse sParse; /* Parse of the input JSON */ +-}; +- +-/* Constructor for the json_each virtual table */ +-static int jsonEachConnect( +- sqlite3 *db, +- void *pAux, +- int argc, const char *const*argv, +- sqlite3_vtab **ppVtab, +- char **pzErr +-){ +- sqlite3_vtab *pNew; +- int rc; +- +-/* Column numbers */ +-#define JEACH_KEY 0 +-#define JEACH_VALUE 1 +-#define JEACH_TYPE 2 +-#define JEACH_ATOM 3 +-#define JEACH_ID 4 +-#define JEACH_PARENT 5 +-#define JEACH_FULLKEY 6 +-#define JEACH_PATH 7 +-#define JEACH_JSON 8 +-#define JEACH_ROOT 9 +- +- UNUSED_PARAM(pzErr); +- UNUSED_PARAM(argv); +- UNUSED_PARAM(argc); +- UNUSED_PARAM(pAux); +- rc = sqlite3_declare_vtab(db, +- "CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path," +- "json HIDDEN,root HIDDEN)"); + if( rc==SQLITE_OK ){ +- pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) ); +- if( pNew==0 ) return SQLITE_NOMEM; +- memset(pNew, 0, sizeof(*pNew)); ++ rc = sessionRebase(p, pIter, xOutput, pOut, 0, 0); ++ sqlite3changeset_finalize(pIter); + } +- return rc; +-} + +-/* destructor for json_each virtual table */ +-static int jsonEachDisconnect(sqlite3_vtab *pVtab){ +- sqlite3_free(pVtab); +- return SQLITE_OK; +-} +- +-/* constructor for a JsonEachCursor object for json_each(). */ +-static int jsonEachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ +- JsonEachCursor *pCur; +- +- UNUSED_PARAM(p); +- pCur = sqlite3_malloc( sizeof(*pCur) ); +- if( pCur==0 ) return SQLITE_NOMEM; +- memset(pCur, 0, sizeof(*pCur)); +- *ppCursor = &pCur->base; +- return SQLITE_OK; +-} +- +-/* constructor for a JsonEachCursor object for json_tree(). */ +-static int jsonEachOpenTree(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ +- int rc = jsonEachOpenEach(p, ppCursor); +- if( rc==SQLITE_OK ){ +- JsonEachCursor *pCur = (JsonEachCursor*)*ppCursor; +- pCur->bRecursive = 1; +- } + return rc; + } + +-/* Reset a JsonEachCursor back to its original state. Free any memory +-** held. */ +-static void jsonEachCursorReset(JsonEachCursor *p){ +- sqlite3_free(p->zJson); +- sqlite3_free(p->zRoot); +- jsonParseReset(&p->sParse); +- p->iRowid = 0; +- p->i = 0; +- p->iEnd = 0; +- p->eType = 0; +- p->zJson = 0; +- p->zRoot = 0; +-} +- +-/* Destructor for a jsonEachCursor object */ +-static int jsonEachClose(sqlite3_vtab_cursor *cur){ +- JsonEachCursor *p = (JsonEachCursor*)cur; +- jsonEachCursorReset(p); +- sqlite3_free(cur); +- return SQLITE_OK; +-} +- +-/* Return TRUE if the jsonEachCursor object has been advanced off the end +-** of the JSON object */ +-static int jsonEachEof(sqlite3_vtab_cursor *cur){ +- JsonEachCursor *p = (JsonEachCursor*)cur; +- return p->i >= p->iEnd; +-} +- +-/* Advance the cursor to the next element for json_tree() */ +-static int jsonEachNext(sqlite3_vtab_cursor *cur){ +- JsonEachCursor *p = (JsonEachCursor*)cur; +- if( p->bRecursive ){ +- if( p->sParse.aNode[p->i].jnFlags & JNODE_LABEL ) p->i++; +- p->i++; +- p->iRowid++; +- if( p->i<p->iEnd ){ +- u32 iUp = p->sParse.aUp[p->i]; +- JsonNode *pUp = &p->sParse.aNode[iUp]; +- p->eType = pUp->eType; +- if( pUp->eType==JSON_ARRAY ){ +- if( iUp==p->i-1 ){ +- pUp->u.iKey = 0; +- }else{ +- pUp->u.iKey++; +- } +- } +- } +- }else{ +- switch( p->eType ){ +- case JSON_ARRAY: { +- p->i += jsonNodeSize(&p->sParse.aNode[p->i]); +- p->iRowid++; +- break; +- } +- case JSON_OBJECT: { +- p->i += 1 + jsonNodeSize(&p->sParse.aNode[p->i+1]); +- p->iRowid++; +- break; +- } +- default: { +- p->i = p->iEnd; +- break; +- } +- } ++/* ++** Destroy a rebaser object ++*/ ++SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p){ ++ if( p ){ ++ sessionDeleteTable(p->grp.pList); ++ sqlite3_free(p); + } +- return SQLITE_OK; + } + +-/* Append the name of the path for element i to pStr ++/* ++** Global configuration + */ +-static void jsonEachComputePath( +- JsonEachCursor *p, /* The cursor */ +- JsonString *pStr, /* Write the path here */ +- u32 i /* Path to this element */ +-){ +- JsonNode *pNode, *pUp; +- u32 iUp; +- if( i==0 ){ +- jsonAppendChar(pStr, '$'); +- return; +- } +- iUp = p->sParse.aUp[i]; +- jsonEachComputePath(p, pStr, iUp); +- pNode = &p->sParse.aNode[i]; +- pUp = &p->sParse.aNode[iUp]; +- if( pUp->eType==JSON_ARRAY ){ +- jsonPrintf(30, pStr, "[%d]", pUp->u.iKey); +- }else{ +- assert( pUp->eType==JSON_OBJECT ); +- if( (pNode->jnFlags & JNODE_LABEL)==0 ) pNode--; +- assert( pNode->eType==JSON_STRING ); +- assert( pNode->jnFlags & JNODE_LABEL ); +- jsonPrintf(pNode->n+1, pStr, ".%.*s", pNode->n-2, pNode->u.zJContent+1); +- } +-} +- +-/* Return the value of a column */ +-static int jsonEachColumn( +- sqlite3_vtab_cursor *cur, /* The cursor */ +- sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ +- int i /* Which column to return */ +-){ +- JsonEachCursor *p = (JsonEachCursor*)cur; +- JsonNode *pThis = &p->sParse.aNode[p->i]; +- switch( i ){ +- case JEACH_KEY: { +- if( p->i==0 ) break; +- if( p->eType==JSON_OBJECT ){ +- jsonReturn(pThis, ctx, 0); +- }else if( p->eType==JSON_ARRAY ){ +- u32 iKey; +- if( p->bRecursive ){ +- if( p->iRowid==0 ) break; +- iKey = p->sParse.aNode[p->sParse.aUp[p->i]].u.iKey; +- }else{ +- iKey = p->iRowid; +- } +- sqlite3_result_int64(ctx, (sqlite3_int64)iKey); ++SQLITE_API int sqlite3session_config(int op, void *pArg){ ++ int rc = SQLITE_OK; ++ switch( op ){ ++ case SQLITE_SESSION_CONFIG_STRMSIZE: { ++ int *pInt = (int*)pArg; ++ if( *pInt>0 ){ ++ sessions_strm_chunk_size = *pInt; + } ++ *pInt = sessions_strm_chunk_size; + break; + } +- case JEACH_VALUE: { +- if( pThis->jnFlags & JNODE_LABEL ) pThis++; +- jsonReturn(pThis, ctx, 0); ++ default: ++ rc = SQLITE_MISUSE; + break; +- } +- case JEACH_TYPE: { +- if( pThis->jnFlags & JNODE_LABEL ) pThis++; +- sqlite3_result_text(ctx, jsonType[pThis->eType], -1, SQLITE_STATIC); +- break; +- } +- case JEACH_ATOM: { +- if( pThis->jnFlags & JNODE_LABEL ) pThis++; +- if( pThis->eType>=JSON_ARRAY ) break; +- jsonReturn(pThis, ctx, 0); +- break; +- } +- case JEACH_ID: { +- sqlite3_result_int64(ctx, +- (sqlite3_int64)p->i + ((pThis->jnFlags & JNODE_LABEL)!=0)); +- break; +- } +- case JEACH_PARENT: { +- if( p->i>p->iBegin && p->bRecursive ){ +- sqlite3_result_int64(ctx, (sqlite3_int64)p->sParse.aUp[p->i]); +- } +- break; +- } +- case JEACH_FULLKEY: { +- JsonString x; +- jsonInit(&x, ctx); +- if( p->bRecursive ){ +- jsonEachComputePath(p, &x, p->i); +- }else{ +- if( p->zRoot ){ +- jsonAppendRaw(&x, p->zRoot, (int)strlen(p->zRoot)); +- }else{ +- jsonAppendChar(&x, '$'); +- } +- if( p->eType==JSON_ARRAY ){ +- jsonPrintf(30, &x, "[%d]", p->iRowid); +- }else{ +- jsonPrintf(pThis->n, &x, ".%.*s", pThis->n-2, pThis->u.zJContent+1); +- } +- } +- jsonResult(&x); +- break; +- } +- case JEACH_PATH: { +- if( p->bRecursive ){ +- JsonString x; +- jsonInit(&x, ctx); +- jsonEachComputePath(p, &x, p->sParse.aUp[p->i]); +- jsonResult(&x); +- break; +- } +- /* For json_each() path and root are the same so fall through +- ** into the root case */ +- } +- default: { +- const char *zRoot = p->zRoot; +- if( zRoot==0 ) zRoot = "$"; +- sqlite3_result_text(ctx, zRoot, -1, SQLITE_STATIC); +- break; +- } +- case JEACH_JSON: { +- assert( i==JEACH_JSON ); +- sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_STATIC); +- break; +- } + } +- return SQLITE_OK; +-} +- +-/* Return the current rowid value */ +-static int jsonEachRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ +- JsonEachCursor *p = (JsonEachCursor*)cur; +- *pRowid = p->iRowid; +- return SQLITE_OK; +-} +- +-/* The query strategy is to look for an equality constraint on the json +-** column. Without such a constraint, the table cannot operate. idxNum is +-** 1 if the constraint is found, 3 if the constraint and zRoot are found, +-** and 0 otherwise. +-*/ +-static int jsonEachBestIndex( +- sqlite3_vtab *tab, +- sqlite3_index_info *pIdxInfo +-){ +- int i; +- int jsonIdx = -1; +- int rootIdx = -1; +- const struct sqlite3_index_constraint *pConstraint; +- +- UNUSED_PARAM(tab); +- pConstraint = pIdxInfo->aConstraint; +- for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ +- if( pConstraint->usable==0 ) continue; +- if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; +- switch( pConstraint->iColumn ){ +- case JEACH_JSON: jsonIdx = i; break; +- case JEACH_ROOT: rootIdx = i; break; +- default: /* no-op */ break; +- } +- } +- if( jsonIdx<0 ){ +- pIdxInfo->idxNum = 0; +- pIdxInfo->estimatedCost = 1e99; +- }else{ +- pIdxInfo->estimatedCost = 1.0; +- pIdxInfo->aConstraintUsage[jsonIdx].argvIndex = 1; +- pIdxInfo->aConstraintUsage[jsonIdx].omit = 1; +- if( rootIdx<0 ){ +- pIdxInfo->idxNum = 1; +- }else{ +- pIdxInfo->aConstraintUsage[rootIdx].argvIndex = 2; +- pIdxInfo->aConstraintUsage[rootIdx].omit = 1; +- pIdxInfo->idxNum = 3; +- } +- } +- return SQLITE_OK; +-} +- +-/* Start a search on a new JSON string */ +-static int jsonEachFilter( +- sqlite3_vtab_cursor *cur, +- int idxNum, const char *idxStr, +- int argc, sqlite3_value **argv +-){ +- JsonEachCursor *p = (JsonEachCursor*)cur; +- const char *z; +- const char *zRoot = 0; +- sqlite3_int64 n; +- +- UNUSED_PARAM(idxStr); +- UNUSED_PARAM(argc); +- jsonEachCursorReset(p); +- if( idxNum==0 ) return SQLITE_OK; +- z = (const char*)sqlite3_value_text(argv[0]); +- if( z==0 ) return SQLITE_OK; +- n = sqlite3_value_bytes(argv[0]); +- p->zJson = sqlite3_malloc64( n+1 ); +- if( p->zJson==0 ) return SQLITE_NOMEM; +- memcpy(p->zJson, z, (size_t)n+1); +- if( jsonParse(&p->sParse, 0, p->zJson) ){ +- int rc = SQLITE_NOMEM; +- if( p->sParse.oom==0 ){ +- sqlite3_free(cur->pVtab->zErrMsg); +- cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON"); +- if( cur->pVtab->zErrMsg ) rc = SQLITE_ERROR; +- } +- jsonEachCursorReset(p); +- return rc; +- }else if( p->bRecursive && jsonParseFindParents(&p->sParse) ){ +- jsonEachCursorReset(p); +- return SQLITE_NOMEM; +- }else{ +- JsonNode *pNode = 0; +- if( idxNum==3 ){ +- const char *zErr = 0; +- zRoot = (const char*)sqlite3_value_text(argv[1]); +- if( zRoot==0 ) return SQLITE_OK; +- n = sqlite3_value_bytes(argv[1]); +- p->zRoot = sqlite3_malloc64( n+1 ); +- if( p->zRoot==0 ) return SQLITE_NOMEM; +- memcpy(p->zRoot, zRoot, (size_t)n+1); +- if( zRoot[0]!='$' ){ +- zErr = zRoot; +- }else{ +- pNode = jsonLookupStep(&p->sParse, 0, p->zRoot+1, 0, &zErr); +- } +- if( zErr ){ +- sqlite3_free(cur->pVtab->zErrMsg); +- cur->pVtab->zErrMsg = jsonPathSyntaxError(zErr); +- jsonEachCursorReset(p); +- return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; +- }else if( pNode==0 ){ +- return SQLITE_OK; +- } +- }else{ +- pNode = p->sParse.aNode; +- } +- p->iBegin = p->i = (int)(pNode - p->sParse.aNode); +- p->eType = pNode->eType; +- if( p->eType>=JSON_ARRAY ){ +- pNode->u.iKey = 0; +- p->iEnd = p->i + pNode->n + 1; +- if( p->bRecursive ){ +- p->eType = p->sParse.aNode[p->sParse.aUp[p->i]].eType; +- if( p->i>0 && (p->sParse.aNode[p->i-1].jnFlags & JNODE_LABEL)!=0 ){ +- p->i--; +- } +- }else{ +- p->i++; +- } +- }else{ +- p->iEnd = p->i+1; +- } +- } +- return SQLITE_OK; +-} +- +-/* The methods of the json_each virtual table */ +-static sqlite3_module jsonEachModule = { +- 0, /* iVersion */ +- 0, /* xCreate */ +- jsonEachConnect, /* xConnect */ +- jsonEachBestIndex, /* xBestIndex */ +- jsonEachDisconnect, /* xDisconnect */ +- 0, /* xDestroy */ +- jsonEachOpenEach, /* xOpen - open a cursor */ +- jsonEachClose, /* xClose - close a cursor */ +- jsonEachFilter, /* xFilter - configure scan constraints */ +- jsonEachNext, /* xNext - advance a cursor */ +- jsonEachEof, /* xEof - check for end of scan */ +- jsonEachColumn, /* xColumn - read data */ +- jsonEachRowid, /* xRowid - read data */ +- 0, /* xUpdate */ +- 0, /* xBegin */ +- 0, /* xSync */ +- 0, /* xCommit */ +- 0, /* xRollback */ +- 0, /* xFindMethod */ +- 0, /* xRename */ +- 0, /* xSavepoint */ +- 0, /* xRelease */ +- 0 /* xRollbackTo */ +-}; +- +-/* The methods of the json_tree virtual table. */ +-static sqlite3_module jsonTreeModule = { +- 0, /* iVersion */ +- 0, /* xCreate */ +- jsonEachConnect, /* xConnect */ +- jsonEachBestIndex, /* xBestIndex */ +- jsonEachDisconnect, /* xDisconnect */ +- 0, /* xDestroy */ +- jsonEachOpenTree, /* xOpen - open a cursor */ +- jsonEachClose, /* xClose - close a cursor */ +- jsonEachFilter, /* xFilter - configure scan constraints */ +- jsonEachNext, /* xNext - advance a cursor */ +- jsonEachEof, /* xEof - check for end of scan */ +- jsonEachColumn, /* xColumn - read data */ +- jsonEachRowid, /* xRowid - read data */ +- 0, /* xUpdate */ +- 0, /* xBegin */ +- 0, /* xSync */ +- 0, /* xCommit */ +- 0, /* xRollback */ +- 0, /* xFindMethod */ +- 0, /* xRename */ +- 0, /* xSavepoint */ +- 0, /* xRelease */ +- 0 /* xRollbackTo */ +-}; +-#endif /* SQLITE_OMIT_VIRTUALTABLE */ +- +-/**************************************************************************** +-** The following routines are the only publically visible identifiers in this +-** file. Call the following routines in order to register the various SQL +-** functions and the virtual table implemented by this file. +-****************************************************************************/ +- +-SQLITE_PRIVATE int sqlite3Json1Init(sqlite3 *db){ +- int rc = SQLITE_OK; +- unsigned int i; +- static const struct { +- const char *zName; +- int nArg; +- int flag; +- void (*xFunc)(sqlite3_context*,int,sqlite3_value**); +- } aFunc[] = { +- { "json", 1, 0, jsonRemoveFunc }, +- { "json_array", -1, 0, jsonArrayFunc }, +- { "json_array_length", 1, 0, jsonArrayLengthFunc }, +- { "json_array_length", 2, 0, jsonArrayLengthFunc }, +- { "json_extract", -1, 0, jsonExtractFunc }, +- { "json_insert", -1, 0, jsonSetFunc }, +- { "json_object", -1, 0, jsonObjectFunc }, +- { "json_patch", 2, 0, jsonPatchFunc }, +- { "json_quote", 1, 0, jsonQuoteFunc }, +- { "json_remove", -1, 0, jsonRemoveFunc }, +- { "json_replace", -1, 0, jsonReplaceFunc }, +- { "json_set", -1, 1, jsonSetFunc }, +- { "json_type", 1, 0, jsonTypeFunc }, +- { "json_type", 2, 0, jsonTypeFunc }, +- { "json_valid", 1, 0, jsonValidFunc }, +- +-#if SQLITE_DEBUG +- /* DEBUG and TESTING functions */ +- { "json_parse", 1, 0, jsonParseFunc }, +- { "json_test1", 1, 0, jsonTest1Func }, +-#endif +- }; +- static const struct { +- const char *zName; +- int nArg; +- void (*xStep)(sqlite3_context*,int,sqlite3_value**); +- void (*xFinal)(sqlite3_context*); +- } aAgg[] = { +- { "json_group_array", 1, jsonArrayStep, jsonArrayFinal }, +- { "json_group_object", 2, jsonObjectStep, jsonObjectFinal }, +- }; +-#ifndef SQLITE_OMIT_VIRTUALTABLE +- static const struct { +- const char *zName; +- sqlite3_module *pModule; +- } aMod[] = { +- { "json_each", &jsonEachModule }, +- { "json_tree", &jsonTreeModule }, +- }; +-#endif +- for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){ +- rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg, +- SQLITE_UTF8 | SQLITE_DETERMINISTIC, +- (void*)&aFunc[i].flag, +- aFunc[i].xFunc, 0, 0); +- } +- for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){ +- rc = sqlite3_create_function(db, aAgg[i].zName, aAgg[i].nArg, +- SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0, +- 0, aAgg[i].xStep, aAgg[i].xFinal); +- } +-#ifndef SQLITE_OMIT_VIRTUALTABLE +- for(i=0; i<sizeof(aMod)/sizeof(aMod[0]) && rc==SQLITE_OK; i++){ +- rc = sqlite3_create_module(db, aMod[i].zName, aMod[i].pModule, 0); +- } +-#endif + return rc; + } + ++#endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */ + +-#ifndef SQLITE_CORE +-#ifdef _WIN32 +-__declspec(dllexport) +-#endif +-SQLITE_API int sqlite3_json_init( +- sqlite3 *db, +- char **pzErrMsg, +- const sqlite3_api_routines *pApi +-){ +- SQLITE_EXTENSION_INIT2(pApi); +- (void)pzErrMsg; /* Unused parameter */ +- return sqlite3Json1Init(db); +-} +-#endif +-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1) */ +- +-/************** End of json1.c ***********************************************/ ++/************** End of sqlite3session.c **************************************/ + /************** Begin file fts5.c ********************************************/ + + +@@ -183491,7 +198794,7 @@ + ** This way, even if the tokenizer does not provide synonyms + ** when tokenizing query text (it should not - to do would be + ** inefficient), it doesn't matter if the user queries for +-** 'first + place' or '1st + place', as there are entires in the ++** 'first + place' or '1st + place', as there are entries in the + ** FTS index corresponding to both forms of the first token. + ** </ol> + ** +@@ -183519,7 +198822,7 @@ + ** extra data to the FTS index or require FTS5 to query for multiple terms, + ** so it is efficient in terms of disk space and query speed. However, it + ** does not support prefix queries very well. If, as suggested above, the +-** token "first" is subsituted for "1st" by the tokenizer, then the query: ++** token "first" is substituted for "1st" by the tokenizer, then the query: + ** + ** <codeblock> + ** ... MATCH '1s*'</codeblock> +@@ -184349,6 +199652,8 @@ + int bPrefix + ); + ++static void sqlite3Fts5ParseSetCaret(Fts5ExprPhrase*); ++ + static Fts5ExprNearset *sqlite3Fts5ParseNearset( + Fts5Parse*, + Fts5ExprNearset*, +@@ -184409,9 +199714,12 @@ + /************************************************************************** + ** Interface to automatically generated code in fts5_unicode2.c. + */ +-static int sqlite3Fts5UnicodeIsalnum(int c); + static int sqlite3Fts5UnicodeIsdiacritic(int c); + static int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic); ++ ++static int sqlite3Fts5UnicodeCatParse(const char*, u8*); ++static int sqlite3Fts5UnicodeCategory(int iCode); ++static void sqlite3Fts5UnicodeAscii(u8*, u8*); + /* + ** End of interface to code in fts5_unicode2.c. + **************************************************************************/ +@@ -184429,9 +199737,10 @@ + #define FTS5_STRING 9 + #define FTS5_LP 10 + #define FTS5_RP 11 +-#define FTS5_COMMA 12 +-#define FTS5_PLUS 13 +-#define FTS5_STAR 14 ++#define FTS5_CARET 12 ++#define FTS5_COMMA 13 ++#define FTS5_PLUS 14 ++#define FTS5_STAR 15 + + /* + ** 2000-05-29 +@@ -184458,6 +199767,7 @@ + ** input grammar file: + */ + /* #include <stdio.h> */ ++/* #include <assert.h> */ + /************ Begin %include sections from the grammar ************************/ + + /* #include "fts5Int.h" */ +@@ -184526,19 +199836,23 @@ + ** zero the stack is dynamically sized using realloc() + ** sqlite3Fts5ParserARG_SDECL A static variable declaration for the %extra_argument + ** sqlite3Fts5ParserARG_PDECL A parameter declaration for the %extra_argument ++** sqlite3Fts5ParserARG_PARAM Code to pass %extra_argument as a subroutine parameter + ** sqlite3Fts5ParserARG_STORE Code to store %extra_argument into fts5yypParser + ** sqlite3Fts5ParserARG_FETCH Code to extract %extra_argument from fts5yypParser ++** sqlite3Fts5ParserCTX_* As sqlite3Fts5ParserARG_ except for %extra_context + ** fts5YYERRORSYMBOL is the code number of the error symbol. If not + ** defined, then do no error processing. + ** fts5YYNSTATE the combined number of states. + ** fts5YYNRULE the number of rules in the grammar ++** fts5YYNFTS5TOKEN Number of terminal symbols + ** fts5YY_MAX_SHIFT Maximum value for shift actions + ** fts5YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions + ** fts5YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions +-** fts5YY_MIN_REDUCE Maximum value for reduce actions + ** fts5YY_ERROR_ACTION The fts5yy_action[] code for syntax error + ** fts5YY_ACCEPT_ACTION The fts5yy_action[] code for accept + ** fts5YY_NO_ACTION The fts5yy_action[] code for no-op ++** fts5YY_MIN_REDUCE Minimum value for reduce actions ++** fts5YY_MAX_REDUCE Maximum value for reduce actions + */ + #ifndef INTERFACE + # define INTERFACE 1 +@@ -184545,7 +199859,7 @@ + #endif + /************* Begin control #defines *****************************************/ + #define fts5YYCODETYPE unsigned char +-#define fts5YYNOCODE 28 ++#define fts5YYNOCODE 27 + #define fts5YYACTIONTYPE unsigned char + #define sqlite3Fts5ParserFTS5TOKENTYPE Fts5Token + typedef union { +@@ -184562,19 +199876,27 @@ + #endif + #define sqlite3Fts5ParserARG_SDECL Fts5Parse *pParse; + #define sqlite3Fts5ParserARG_PDECL ,Fts5Parse *pParse +-#define sqlite3Fts5ParserARG_FETCH Fts5Parse *pParse = fts5yypParser->pParse +-#define sqlite3Fts5ParserARG_STORE fts5yypParser->pParse = pParse +-#define fts5YYNSTATE 33 +-#define fts5YYNRULE 27 +-#define fts5YY_MAX_SHIFT 32 +-#define fts5YY_MIN_SHIFTREDUCE 50 +-#define fts5YY_MAX_SHIFTREDUCE 76 +-#define fts5YY_MIN_REDUCE 77 +-#define fts5YY_MAX_REDUCE 103 +-#define fts5YY_ERROR_ACTION 104 +-#define fts5YY_ACCEPT_ACTION 105 +-#define fts5YY_NO_ACTION 106 ++#define sqlite3Fts5ParserARG_PARAM ,pParse ++#define sqlite3Fts5ParserARG_FETCH Fts5Parse *pParse=fts5yypParser->pParse; ++#define sqlite3Fts5ParserARG_STORE fts5yypParser->pParse=pParse; ++#define sqlite3Fts5ParserCTX_SDECL ++#define sqlite3Fts5ParserCTX_PDECL ++#define sqlite3Fts5ParserCTX_PARAM ++#define sqlite3Fts5ParserCTX_FETCH ++#define sqlite3Fts5ParserCTX_STORE ++#define fts5YYNSTATE 35 ++#define fts5YYNRULE 28 ++#define fts5YYNFTS5TOKEN 16 ++#define fts5YY_MAX_SHIFT 34 ++#define fts5YY_MIN_SHIFTREDUCE 52 ++#define fts5YY_MAX_SHIFTREDUCE 79 ++#define fts5YY_ERROR_ACTION 80 ++#define fts5YY_ACCEPT_ACTION 81 ++#define fts5YY_NO_ACTION 82 ++#define fts5YY_MIN_REDUCE 83 ++#define fts5YY_MAX_REDUCE 110 + /************* End control #defines *******************************************/ ++#define fts5YY_NLOOKAHEAD ((int)(sizeof(fts5yy_lookahead)/sizeof(fts5yy_lookahead[0]))) + + /* Define the fts5yytestcase() macro to be a no-op if is not already defined + ** otherwise. +@@ -184603,9 +199925,6 @@ + ** N between fts5YY_MIN_SHIFTREDUCE Shift to an arbitrary state then + ** and fts5YY_MAX_SHIFTREDUCE reduce by rule N-fts5YY_MIN_SHIFTREDUCE. + ** +-** N between fts5YY_MIN_REDUCE Reduce by rule N-fts5YY_MIN_REDUCE +-** and fts5YY_MAX_REDUCE +-** + ** N == fts5YY_ERROR_ACTION A syntax error has occurred. + ** + ** N == fts5YY_ACCEPT_ACTION The parser accepts its input. +@@ -184613,6 +199932,9 @@ + ** N == fts5YY_NO_ACTION No such action. Denotes unused + ** slots in the fts5yy_action[] table. + ** ++** N between fts5YY_MIN_REDUCE Reduce by rule N-fts5YY_MIN_REDUCE ++** and fts5YY_MAX_REDUCE ++** + ** The action table is constructed as a single large table named fts5yy_action[]. + ** Given state S and lookahead X, the action is computed as either: + ** +@@ -184619,19 +199941,13 @@ + ** (A) N = fts5yy_action[ fts5yy_shift_ofst[S] + X ] + ** (B) N = fts5yy_default[S] + ** +-** The (A) formula is preferred. The B formula is used instead if: +-** (1) The fts5yy_shift_ofst[S]+X value is out of range, or +-** (2) fts5yy_lookahead[fts5yy_shift_ofst[S]+X] is not equal to X, or +-** (3) fts5yy_shift_ofst[S] equal fts5YY_SHIFT_USE_DFLT. +-** (Implementation note: fts5YY_SHIFT_USE_DFLT is chosen so that +-** fts5YY_SHIFT_USE_DFLT+X will be out of range for all possible lookaheads X. +-** Hence only tests (1) and (2) need to be evaluated.) ++** The (A) formula is preferred. The B formula is used instead if ++** fts5yy_lookahead[fts5yy_shift_ofst[S]+X] is not equal to X. + ** + ** The formulas above are for computing the action when the lookahead is + ** a terminal symbol. If the lookahead is a non-terminal (as occurs after + ** a reduce action) then the fts5yy_reduce_ofst[] array is used in place of +-** the fts5yy_shift_ofst[] array and fts5YY_REDUCE_USE_DFLT is used in place of +-** fts5YY_SHIFT_USE_DFLT. ++** the fts5yy_shift_ofst[] array. + ** + ** The following are the tables generated in this section: + ** +@@ -184645,54 +199961,56 @@ + ** fts5yy_default[] Default action for each state. + ** + *********** Begin parsing tables **********************************************/ +-#define fts5YY_ACTTAB_COUNT (98) ++#define fts5YY_ACTTAB_COUNT (105) + static const fts5YYACTIONTYPE fts5yy_action[] = { +- /* 0 */ 105, 19, 90, 6, 26, 93, 92, 24, 24, 17, +- /* 10 */ 90, 6, 26, 16, 92, 54, 24, 18, 90, 6, +- /* 20 */ 26, 10, 92, 12, 24, 75, 86, 90, 6, 26, +- /* 30 */ 13, 92, 75, 24, 20, 90, 6, 26, 101, 92, +- /* 40 */ 56, 24, 27, 90, 6, 26, 100, 92, 21, 24, +- /* 50 */ 23, 15, 30, 11, 1, 91, 22, 25, 9, 92, +- /* 60 */ 7, 24, 3, 4, 5, 3, 4, 5, 3, 77, +- /* 70 */ 4, 5, 3, 61, 23, 15, 60, 11, 80, 12, +- /* 80 */ 2, 13, 68, 10, 29, 52, 55, 75, 31, 32, +- /* 90 */ 8, 28, 5, 3, 51, 55, 72, 14, ++ /* 0 */ 81, 20, 96, 6, 28, 99, 98, 26, 26, 18, ++ /* 10 */ 96, 6, 28, 17, 98, 56, 26, 19, 96, 6, ++ /* 20 */ 28, 14, 98, 14, 26, 31, 92, 96, 6, 28, ++ /* 30 */ 108, 98, 25, 26, 21, 96, 6, 28, 78, 98, ++ /* 40 */ 58, 26, 29, 96, 6, 28, 107, 98, 22, 26, ++ /* 50 */ 24, 16, 12, 11, 1, 13, 13, 24, 16, 23, ++ /* 60 */ 11, 33, 34, 13, 97, 8, 27, 32, 98, 7, ++ /* 70 */ 26, 3, 4, 5, 3, 4, 5, 3, 83, 4, ++ /* 80 */ 5, 3, 63, 5, 3, 62, 12, 2, 86, 13, ++ /* 90 */ 9, 30, 10, 10, 54, 57, 75, 78, 78, 53, ++ /* 100 */ 57, 15, 82, 82, 71, + }; + static const fts5YYCODETYPE fts5yy_lookahead[] = { + /* 0 */ 16, 17, 18, 19, 20, 22, 22, 24, 24, 17, + /* 10 */ 18, 19, 20, 7, 22, 9, 24, 17, 18, 19, +- /* 20 */ 20, 10, 22, 9, 24, 14, 17, 18, 19, 20, +- /* 30 */ 9, 22, 14, 24, 17, 18, 19, 20, 26, 22, ++ /* 20 */ 20, 9, 22, 9, 24, 13, 17, 18, 19, 20, ++ /* 30 */ 26, 22, 24, 24, 17, 18, 19, 20, 15, 22, + /* 40 */ 9, 24, 17, 18, 19, 20, 26, 22, 21, 24, +- /* 50 */ 6, 7, 13, 9, 10, 18, 21, 20, 5, 22, +- /* 60 */ 5, 24, 3, 1, 2, 3, 1, 2, 3, 0, +- /* 70 */ 1, 2, 3, 11, 6, 7, 11, 9, 5, 9, +- /* 80 */ 10, 9, 11, 10, 12, 8, 9, 14, 24, 25, +- /* 90 */ 23, 24, 2, 3, 8, 9, 9, 9, ++ /* 50 */ 6, 7, 9, 9, 10, 12, 12, 6, 7, 21, ++ /* 60 */ 9, 24, 25, 12, 18, 5, 20, 14, 22, 5, ++ /* 70 */ 24, 3, 1, 2, 3, 1, 2, 3, 0, 1, ++ /* 80 */ 2, 3, 11, 2, 3, 11, 9, 10, 5, 12, ++ /* 90 */ 23, 24, 10, 10, 8, 9, 9, 15, 15, 8, ++ /* 100 */ 9, 9, 27, 27, 11, 27, 27, 27, 27, 27, ++ /* 110 */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, ++ /* 120 */ 27, + }; +-#define fts5YY_SHIFT_USE_DFLT (98) +-#define fts5YY_SHIFT_COUNT (32) ++#define fts5YY_SHIFT_COUNT (34) + #define fts5YY_SHIFT_MIN (0) +-#define fts5YY_SHIFT_MAX (90) ++#define fts5YY_SHIFT_MAX (93) + static const unsigned char fts5yy_shift_ofst[] = { +- /* 0 */ 44, 44, 44, 44, 44, 44, 68, 70, 72, 14, +- /* 10 */ 21, 73, 11, 18, 18, 31, 31, 62, 65, 69, +- /* 20 */ 90, 77, 86, 6, 39, 53, 55, 59, 39, 87, +- /* 30 */ 88, 39, 71, ++ /* 0 */ 44, 44, 44, 44, 44, 44, 51, 77, 43, 12, ++ /* 10 */ 14, 83, 82, 14, 23, 23, 31, 31, 71, 74, ++ /* 20 */ 78, 81, 86, 91, 6, 53, 53, 60, 64, 68, ++ /* 30 */ 53, 87, 92, 53, 93, + }; +-#define fts5YY_REDUCE_USE_DFLT (-18) +-#define fts5YY_REDUCE_COUNT (16) ++#define fts5YY_REDUCE_COUNT (17) + #define fts5YY_REDUCE_MIN (-17) + #define fts5YY_REDUCE_MAX (67) + static const signed char fts5yy_reduce_ofst[] = { +- /* 0 */ -16, -8, 0, 9, 17, 25, 37, -17, 64, -17, +- /* 10 */ 67, 12, 12, 12, 20, 27, 35, ++ /* 0 */ -16, -8, 0, 9, 17, 25, 46, -17, -17, 37, ++ /* 10 */ 67, 4, 4, 8, 4, 20, 27, 38, + }; + static const fts5YYACTIONTYPE fts5yy_default[] = { +- /* 0 */ 104, 104, 104, 104, 104, 104, 89, 104, 98, 104, +- /* 10 */ 104, 103, 103, 103, 103, 104, 104, 104, 104, 104, +- /* 20 */ 85, 104, 104, 104, 94, 104, 104, 84, 96, 104, +- /* 30 */ 104, 97, 104, ++ /* 0 */ 80, 80, 80, 80, 80, 80, 95, 80, 80, 105, ++ /* 10 */ 80, 110, 110, 80, 110, 110, 80, 80, 80, 80, ++ /* 20 */ 80, 91, 80, 80, 80, 101, 100, 80, 80, 90, ++ /* 30 */ 103, 80, 80, 104, 80, + }; + /********** End of lemon-generated parsing tables *****************************/ + +@@ -184751,6 +200069,7 @@ + int fts5yyerrcnt; /* Shifts left before out of the error */ + #endif + sqlite3Fts5ParserARG_SDECL /* A place to hold %extra_argument */ ++ sqlite3Fts5ParserCTX_SDECL /* A place to hold %extra_context */ + #if fts5YYSTACKDEPTH<=0 + int fts5yystksz; /* Current side of the stack */ + fts5yyStackEntry *fts5yystack; /* The parser's stack */ +@@ -184794,19 +200113,39 @@ + } + #endif /* NDEBUG */ + +-#ifndef NDEBUG ++#if defined(fts5YYCOVERAGE) || !defined(NDEBUG) + /* For tracing shifts, the names of all terminals and nonterminals + ** are required. The following table supplies these names */ + static const char *const fts5yyTokenName[] = { +- "$", "OR", "AND", "NOT", +- "TERM", "COLON", "MINUS", "LCP", +- "RCP", "STRING", "LP", "RP", +- "COMMA", "PLUS", "STAR", "error", +- "input", "expr", "cnearset", "exprlist", +- "colset", "colsetlist", "nearset", "nearphrases", +- "phrase", "neardist_opt", "star_opt", ++ /* 0 */ "$", ++ /* 1 */ "OR", ++ /* 2 */ "AND", ++ /* 3 */ "NOT", ++ /* 4 */ "TERM", ++ /* 5 */ "COLON", ++ /* 6 */ "MINUS", ++ /* 7 */ "LCP", ++ /* 8 */ "RCP", ++ /* 9 */ "STRING", ++ /* 10 */ "LP", ++ /* 11 */ "RP", ++ /* 12 */ "CARET", ++ /* 13 */ "COMMA", ++ /* 14 */ "PLUS", ++ /* 15 */ "STAR", ++ /* 16 */ "input", ++ /* 17 */ "expr", ++ /* 18 */ "cnearset", ++ /* 19 */ "exprlist", ++ /* 20 */ "colset", ++ /* 21 */ "colsetlist", ++ /* 22 */ "nearset", ++ /* 23 */ "nearphrases", ++ /* 24 */ "phrase", ++ /* 25 */ "neardist_opt", ++ /* 26 */ "star_opt", + }; +-#endif /* NDEBUG */ ++#endif /* defined(fts5YYCOVERAGE) || !defined(NDEBUG) */ + + #ifndef NDEBUG + /* For tracing reduce actions, the names of all rules are required. +@@ -184830,15 +200169,16 @@ + /* 15 */ "cnearset ::= nearset", + /* 16 */ "cnearset ::= colset COLON nearset", + /* 17 */ "nearset ::= phrase", +- /* 18 */ "nearset ::= STRING LP nearphrases neardist_opt RP", +- /* 19 */ "nearphrases ::= phrase", +- /* 20 */ "nearphrases ::= nearphrases phrase", +- /* 21 */ "neardist_opt ::=", +- /* 22 */ "neardist_opt ::= COMMA STRING", +- /* 23 */ "phrase ::= phrase PLUS STRING star_opt", +- /* 24 */ "phrase ::= STRING star_opt", +- /* 25 */ "star_opt ::= STAR", +- /* 26 */ "star_opt ::=", ++ /* 18 */ "nearset ::= CARET phrase", ++ /* 19 */ "nearset ::= STRING LP nearphrases neardist_opt RP", ++ /* 20 */ "nearphrases ::= phrase", ++ /* 21 */ "nearphrases ::= nearphrases phrase", ++ /* 22 */ "neardist_opt ::=", ++ /* 23 */ "neardist_opt ::= COMMA STRING", ++ /* 24 */ "phrase ::= phrase PLUS STRING star_opt", ++ /* 25 */ "phrase ::= STRING star_opt", ++ /* 26 */ "star_opt ::= STAR", ++ /* 27 */ "star_opt ::=", + }; + #endif /* NDEBUG */ + +@@ -184887,28 +200227,29 @@ + + /* Initialize a new parser that has already been allocated. + */ +-static void sqlite3Fts5ParserInit(void *fts5yypParser){ +- fts5yyParser *pParser = (fts5yyParser*)fts5yypParser; ++static void sqlite3Fts5ParserInit(void *fts5yypRawParser sqlite3Fts5ParserCTX_PDECL){ ++ fts5yyParser *fts5yypParser = (fts5yyParser*)fts5yypRawParser; ++ sqlite3Fts5ParserCTX_STORE + #ifdef fts5YYTRACKMAXSTACKDEPTH +- pParser->fts5yyhwm = 0; ++ fts5yypParser->fts5yyhwm = 0; + #endif + #if fts5YYSTACKDEPTH<=0 +- pParser->fts5yytos = NULL; +- pParser->fts5yystack = NULL; +- pParser->fts5yystksz = 0; +- if( fts5yyGrowStack(pParser) ){ +- pParser->fts5yystack = &pParser->fts5yystk0; +- pParser->fts5yystksz = 1; ++ fts5yypParser->fts5yytos = NULL; ++ fts5yypParser->fts5yystack = NULL; ++ fts5yypParser->fts5yystksz = 0; ++ if( fts5yyGrowStack(fts5yypParser) ){ ++ fts5yypParser->fts5yystack = &fts5yypParser->fts5yystk0; ++ fts5yypParser->fts5yystksz = 1; + } + #endif + #ifndef fts5YYNOERRORRECOVERY +- pParser->fts5yyerrcnt = -1; ++ fts5yypParser->fts5yyerrcnt = -1; + #endif +- pParser->fts5yytos = pParser->fts5yystack; +- pParser->fts5yystack[0].stateno = 0; +- pParser->fts5yystack[0].major = 0; ++ fts5yypParser->fts5yytos = fts5yypParser->fts5yystack; ++ fts5yypParser->fts5yystack[0].stateno = 0; ++ fts5yypParser->fts5yystack[0].major = 0; + #if fts5YYSTACKDEPTH>0 +- pParser->fts5yystackEnd = &pParser->fts5yystack[fts5YYSTACKDEPTH-1]; ++ fts5yypParser->fts5yystackEnd = &fts5yypParser->fts5yystack[fts5YYSTACKDEPTH-1]; + #endif + } + +@@ -184925,11 +200266,14 @@ + ** A pointer to a parser. This pointer is used in subsequent calls + ** to sqlite3Fts5Parser and sqlite3Fts5ParserFree. + */ +-static void *sqlite3Fts5ParserAlloc(void *(*mallocProc)(fts5YYMALLOCARGTYPE)){ +- fts5yyParser *pParser; +- pParser = (fts5yyParser*)(*mallocProc)( (fts5YYMALLOCARGTYPE)sizeof(fts5yyParser) ); +- if( pParser ) sqlite3Fts5ParserInit(pParser); +- return pParser; ++static void *sqlite3Fts5ParserAlloc(void *(*mallocProc)(fts5YYMALLOCARGTYPE) sqlite3Fts5ParserCTX_PDECL){ ++ fts5yyParser *fts5yypParser; ++ fts5yypParser = (fts5yyParser*)(*mallocProc)( (fts5YYMALLOCARGTYPE)sizeof(fts5yyParser) ); ++ if( fts5yypParser ){ ++ sqlite3Fts5ParserCTX_STORE ++ sqlite3Fts5ParserInit(fts5yypParser sqlite3Fts5ParserCTX_PARAM); ++ } ++ return (void*)fts5yypParser; + } + #endif /* sqlite3Fts5Parser_ENGINEALWAYSONSTACK */ + +@@ -184946,7 +200290,8 @@ + fts5YYCODETYPE fts5yymajor, /* Type code for object to destroy */ + fts5YYMINORTYPE *fts5yypminor /* The object to be destroyed */ + ){ +- sqlite3Fts5ParserARG_FETCH; ++ sqlite3Fts5ParserARG_FETCH ++ sqlite3Fts5ParserCTX_FETCH + switch( fts5yymajor ){ + /* Here is inserted the actions which take place when a + ** terminal or non-terminal is destroyed. This can happen +@@ -185056,24 +200401,66 @@ + } + #endif + ++/* This array of booleans keeps track of the parser statement ++** coverage. The element fts5yycoverage[X][Y] is set when the parser ++** is in state X and has a lookahead token Y. In a well-tested ++** systems, every element of this matrix should end up being set. ++*/ ++#if defined(fts5YYCOVERAGE) ++static unsigned char fts5yycoverage[fts5YYNSTATE][fts5YYNFTS5TOKEN]; ++#endif ++ + /* ++** Write into out a description of every state/lookahead combination that ++** ++** (1) has not been used by the parser, and ++** (2) is not a syntax error. ++** ++** Return the number of missed state/lookahead combinations. ++*/ ++#if defined(fts5YYCOVERAGE) ++static int sqlite3Fts5ParserCoverage(FILE *out){ ++ int stateno, iLookAhead, i; ++ int nMissed = 0; ++ for(stateno=0; stateno<fts5YYNSTATE; stateno++){ ++ i = fts5yy_shift_ofst[stateno]; ++ for(iLookAhead=0; iLookAhead<fts5YYNFTS5TOKEN; iLookAhead++){ ++ if( fts5yy_lookahead[i+iLookAhead]!=iLookAhead ) continue; ++ if( fts5yycoverage[stateno][iLookAhead]==0 ) nMissed++; ++ if( out ){ ++ fprintf(out,"State %d lookahead %s %s\n", stateno, ++ fts5yyTokenName[iLookAhead], ++ fts5yycoverage[stateno][iLookAhead] ? "ok" : "missed"); ++ } ++ } ++ } ++ return nMissed; ++} ++#endif ++ ++/* + ** Find the appropriate action for a parser given the terminal + ** look-ahead token iLookAhead. + */ +-static unsigned int fts5yy_find_shift_action( +- fts5yyParser *pParser, /* The parser */ +- fts5YYCODETYPE iLookAhead /* The look-ahead token */ ++static fts5YYACTIONTYPE fts5yy_find_shift_action( ++ fts5YYCODETYPE iLookAhead, /* The look-ahead token */ ++ fts5YYACTIONTYPE stateno /* Current state number */ + ){ + int i; +- int stateno = pParser->fts5yytos->stateno; +- +- if( stateno>=fts5YY_MIN_REDUCE ) return stateno; ++ ++ if( stateno>fts5YY_MAX_SHIFT ) return stateno; + assert( stateno <= fts5YY_SHIFT_COUNT ); ++#if defined(fts5YYCOVERAGE) ++ fts5yycoverage[stateno][iLookAhead] = 1; ++#endif + do{ + i = fts5yy_shift_ofst[stateno]; ++ assert( i>=0 ); ++ /* assert( i+fts5YYNFTS5TOKEN<=(int)fts5YY_NLOOKAHEAD ); */ + assert( iLookAhead!=fts5YYNOCODE ); ++ assert( iLookAhead < fts5YYNFTS5TOKEN ); + i += iLookAhead; +- if( i<0 || i>=fts5YY_ACTTAB_COUNT || fts5yy_lookahead[i]!=iLookAhead ){ ++ if( i>=fts5YY_NLOOKAHEAD || fts5yy_lookahead[i]!=iLookAhead ){ + #ifdef fts5YYFALLBACK + fts5YYCODETYPE iFallback; /* Fallback token */ + if( iLookAhead<sizeof(fts5yyFallback)/sizeof(fts5yyFallback[0]) +@@ -185099,6 +200486,7 @@ + #if fts5YY_SHIFT_MAX+fts5YYWILDCARD>=fts5YY_ACTTAB_COUNT + j<fts5YY_ACTTAB_COUNT && + #endif ++ j<(int)(sizeof(fts5yy_lookahead)/sizeof(fts5yy_lookahead[0])) && + fts5yy_lookahead[j]==fts5YYWILDCARD && iLookAhead>0 + ){ + #ifndef NDEBUG +@@ -185123,8 +200511,8 @@ + ** Find the appropriate action for a parser given the non-terminal + ** look-ahead token iLookAhead. + */ +-static int fts5yy_find_reduce_action( +- int stateno, /* Current state number */ ++static fts5YYACTIONTYPE fts5yy_find_reduce_action( ++ fts5YYACTIONTYPE stateno, /* Current state number */ + fts5YYCODETYPE iLookAhead /* The look-ahead token */ + ){ + int i; +@@ -185136,7 +200524,6 @@ + assert( stateno<=fts5YY_REDUCE_COUNT ); + #endif + i = fts5yy_reduce_ofst[stateno]; +- assert( i!=fts5YY_REDUCE_USE_DFLT ); + assert( iLookAhead!=fts5YYNOCODE ); + i += iLookAhead; + #ifdef fts5YYERRORSYMBOL +@@ -185154,7 +200541,8 @@ + ** The following routine is called if the stack overflows. + */ + static void fts5yyStackOverflow(fts5yyParser *fts5yypParser){ +- sqlite3Fts5ParserARG_FETCH; ++ sqlite3Fts5ParserARG_FETCH ++ sqlite3Fts5ParserCTX_FETCH + #ifndef NDEBUG + if( fts5yyTraceFILE ){ + fprintf(fts5yyTraceFILE,"%sStack Overflow!\n",fts5yyTracePrompt); +@@ -185167,7 +200555,8 @@ + + sqlite3Fts5ParseError(pParse, "fts5: parser stack overflow"); + /******** End %stack_overflow code ********************************************/ +- sqlite3Fts5ParserARG_STORE; /* Suppress warning about unused %extra_argument var */ ++ sqlite3Fts5ParserARG_STORE /* Suppress warning about unused %extra_argument var */ ++ sqlite3Fts5ParserCTX_STORE + } + + /* +@@ -185174,20 +200563,21 @@ + ** Print tracing information for a SHIFT action + */ + #ifndef NDEBUG +-static void fts5yyTraceShift(fts5yyParser *fts5yypParser, int fts5yyNewState){ ++static void fts5yyTraceShift(fts5yyParser *fts5yypParser, int fts5yyNewState, const char *zTag){ + if( fts5yyTraceFILE ){ + if( fts5yyNewState<fts5YYNSTATE ){ +- fprintf(fts5yyTraceFILE,"%sShift '%s', go to state %d\n", +- fts5yyTracePrompt,fts5yyTokenName[fts5yypParser->fts5yytos->major], ++ fprintf(fts5yyTraceFILE,"%s%s '%s', go to state %d\n", ++ fts5yyTracePrompt, zTag, fts5yyTokenName[fts5yypParser->fts5yytos->major], + fts5yyNewState); + }else{ +- fprintf(fts5yyTraceFILE,"%sShift '%s'\n", +- fts5yyTracePrompt,fts5yyTokenName[fts5yypParser->fts5yytos->major]); ++ fprintf(fts5yyTraceFILE,"%s%s '%s', pending reduce %d\n", ++ fts5yyTracePrompt, zTag, fts5yyTokenName[fts5yypParser->fts5yytos->major], ++ fts5yyNewState - fts5YY_MIN_REDUCE); + } + } + } + #else +-# define fts5yyTraceShift(X,Y) ++# define fts5yyTraceShift(X,Y,Z) + #endif + + /* +@@ -185195,8 +200585,8 @@ + */ + static void fts5yy_shift( + fts5yyParser *fts5yypParser, /* The parser to be shifted */ +- int fts5yyNewState, /* The new state to shift in */ +- int fts5yyMajor, /* The major token to shift in */ ++ fts5YYACTIONTYPE fts5yyNewState, /* The new state to shift in */ ++ fts5YYCODETYPE fts5yyMajor, /* The major token to shift in */ + sqlite3Fts5ParserFTS5TOKENTYPE fts5yyMinor /* The minor token to shift in */ + ){ + fts5yyStackEntry *fts5yytos; +@@ -185226,10 +200616,10 @@ + fts5yyNewState += fts5YY_MIN_REDUCE - fts5YY_MIN_SHIFTREDUCE; + } + fts5yytos = fts5yypParser->fts5yytos; +- fts5yytos->stateno = (fts5YYACTIONTYPE)fts5yyNewState; +- fts5yytos->major = (fts5YYCODETYPE)fts5yyMajor; ++ fts5yytos->stateno = fts5yyNewState; ++ fts5yytos->major = fts5yyMajor; + fts5yytos->minor.fts5yy0 = fts5yyMinor; +- fts5yyTraceShift(fts5yypParser, fts5yyNewState); ++ fts5yyTraceShift(fts5yypParser, fts5yyNewState, "Shift"); + } + + /* The following table contains information about every rule that +@@ -185239,33 +200629,34 @@ + fts5YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ + signed char nrhs; /* Negative of the number of RHS symbols in the rule */ + } fts5yyRuleInfo[] = { +- { 16, -1 }, +- { 20, -4 }, +- { 20, -3 }, +- { 20, -1 }, +- { 20, -2 }, +- { 21, -2 }, +- { 21, -1 }, +- { 17, -3 }, +- { 17, -3 }, +- { 17, -3 }, +- { 17, -5 }, +- { 17, -3 }, +- { 17, -1 }, +- { 19, -1 }, +- { 19, -2 }, +- { 18, -1 }, +- { 18, -3 }, +- { 22, -1 }, +- { 22, -5 }, +- { 23, -1 }, +- { 23, -2 }, +- { 25, 0 }, +- { 25, -2 }, +- { 24, -4 }, +- { 24, -2 }, +- { 26, -1 }, +- { 26, 0 }, ++ { 16, -1 }, /* (0) input ::= expr */ ++ { 20, -4 }, /* (1) colset ::= MINUS LCP colsetlist RCP */ ++ { 20, -3 }, /* (2) colset ::= LCP colsetlist RCP */ ++ { 20, -1 }, /* (3) colset ::= STRING */ ++ { 20, -2 }, /* (4) colset ::= MINUS STRING */ ++ { 21, -2 }, /* (5) colsetlist ::= colsetlist STRING */ ++ { 21, -1 }, /* (6) colsetlist ::= STRING */ ++ { 17, -3 }, /* (7) expr ::= expr AND expr */ ++ { 17, -3 }, /* (8) expr ::= expr OR expr */ ++ { 17, -3 }, /* (9) expr ::= expr NOT expr */ ++ { 17, -5 }, /* (10) expr ::= colset COLON LP expr RP */ ++ { 17, -3 }, /* (11) expr ::= LP expr RP */ ++ { 17, -1 }, /* (12) expr ::= exprlist */ ++ { 19, -1 }, /* (13) exprlist ::= cnearset */ ++ { 19, -2 }, /* (14) exprlist ::= exprlist cnearset */ ++ { 18, -1 }, /* (15) cnearset ::= nearset */ ++ { 18, -3 }, /* (16) cnearset ::= colset COLON nearset */ ++ { 22, -1 }, /* (17) nearset ::= phrase */ ++ { 22, -2 }, /* (18) nearset ::= CARET phrase */ ++ { 22, -5 }, /* (19) nearset ::= STRING LP nearphrases neardist_opt RP */ ++ { 23, -1 }, /* (20) nearphrases ::= phrase */ ++ { 23, -2 }, /* (21) nearphrases ::= nearphrases phrase */ ++ { 25, 0 }, /* (22) neardist_opt ::= */ ++ { 25, -2 }, /* (23) neardist_opt ::= COMMA STRING */ ++ { 24, -4 }, /* (24) phrase ::= phrase PLUS STRING star_opt */ ++ { 24, -2 }, /* (25) phrase ::= STRING star_opt */ ++ { 26, -1 }, /* (26) star_opt ::= STAR */ ++ { 26, 0 }, /* (27) star_opt ::= */ + }; + + static void fts5yy_accept(fts5yyParser*); /* Forward Declaration */ +@@ -185273,22 +200664,39 @@ + /* + ** Perform a reduce action and the shift that must immediately + ** follow the reduce. ++** ++** The fts5yyLookahead and fts5yyLookaheadToken parameters provide reduce actions ++** access to the lookahead token (if any). The fts5yyLookahead will be fts5YYNOCODE ++** if the lookahead token has already been consumed. As this procedure is ++** only called from one place, optimizing compilers will in-line it, which ++** means that the extra parameters have no performance impact. + */ +-static void fts5yy_reduce( ++static fts5YYACTIONTYPE fts5yy_reduce( + fts5yyParser *fts5yypParser, /* The parser */ +- unsigned int fts5yyruleno /* Number of the rule by which to reduce */ ++ unsigned int fts5yyruleno, /* Number of the rule by which to reduce */ ++ int fts5yyLookahead, /* Lookahead token, or fts5YYNOCODE if none */ ++ sqlite3Fts5ParserFTS5TOKENTYPE fts5yyLookaheadToken /* Value of the lookahead token */ ++ sqlite3Fts5ParserCTX_PDECL /* %extra_context */ + ){ + int fts5yygoto; /* The next state */ +- int fts5yyact; /* The next action */ ++ fts5YYACTIONTYPE fts5yyact; /* The next action */ + fts5yyStackEntry *fts5yymsp; /* The top of the parser's stack */ + int fts5yysize; /* Amount to pop the stack */ +- sqlite3Fts5ParserARG_FETCH; ++ sqlite3Fts5ParserARG_FETCH ++ (void)fts5yyLookahead; ++ (void)fts5yyLookaheadToken; + fts5yymsp = fts5yypParser->fts5yytos; + #ifndef NDEBUG + if( fts5yyTraceFILE && fts5yyruleno<(int)(sizeof(fts5yyRuleName)/sizeof(fts5yyRuleName[0])) ){ + fts5yysize = fts5yyRuleInfo[fts5yyruleno].nrhs; +- fprintf(fts5yyTraceFILE, "%sReduce [%s], go to state %d.\n", fts5yyTracePrompt, +- fts5yyRuleName[fts5yyruleno], fts5yymsp[fts5yysize].stateno); ++ if( fts5yysize ){ ++ fprintf(fts5yyTraceFILE, "%sReduce %d [%s], go to state %d.\n", ++ fts5yyTracePrompt, ++ fts5yyruleno, fts5yyRuleName[fts5yyruleno], fts5yymsp[fts5yysize].stateno); ++ }else{ ++ fprintf(fts5yyTraceFILE, "%sReduce %d [%s].\n", ++ fts5yyTracePrompt, fts5yyruleno, fts5yyRuleName[fts5yyruleno]); ++ } + } + #endif /* NDEBUG */ + +@@ -185305,13 +200713,19 @@ + #if fts5YYSTACKDEPTH>0 + if( fts5yypParser->fts5yytos>=fts5yypParser->fts5yystackEnd ){ + fts5yyStackOverflow(fts5yypParser); +- return; ++ /* The call to fts5yyStackOverflow() above pops the stack until it is ++ ** empty, causing the main parser loop to exit. So the return value ++ ** is never used and does not matter. */ ++ return 0; + } + #else + if( fts5yypParser->fts5yytos>=&fts5yypParser->fts5yystack[fts5yypParser->fts5yystksz-1] ){ + if( fts5yyGrowStack(fts5yypParser) ){ + fts5yyStackOverflow(fts5yypParser); +- return; ++ /* The call to fts5yyStackOverflow() above pops the stack until it is ++ ** empty, causing the main parser loop to exit. So the return value ++ ** is never used and does not matter. */ ++ return 0; + } + fts5yymsp = fts5yypParser->fts5yytos; + } +@@ -185419,7 +200833,13 @@ + { fts5yylhsminor.fts5yy46 = sqlite3Fts5ParseNearset(pParse, 0, fts5yymsp[0].minor.fts5yy53); } + fts5yymsp[0].minor.fts5yy46 = fts5yylhsminor.fts5yy46; + break; +- case 18: /* nearset ::= STRING LP nearphrases neardist_opt RP */ ++ case 18: /* nearset ::= CARET phrase */ ++{ ++ sqlite3Fts5ParseSetCaret(fts5yymsp[0].minor.fts5yy53); ++ fts5yymsp[-1].minor.fts5yy46 = sqlite3Fts5ParseNearset(pParse, 0, fts5yymsp[0].minor.fts5yy53); ++} ++ break; ++ case 19: /* nearset ::= STRING LP nearphrases neardist_opt RP */ + { + sqlite3Fts5ParseNear(pParse, &fts5yymsp[-4].minor.fts5yy0); + sqlite3Fts5ParseSetDistance(pParse, fts5yymsp[-2].minor.fts5yy46, &fts5yymsp[-1].minor.fts5yy0); +@@ -185427,40 +200847,40 @@ + } + fts5yymsp[-4].minor.fts5yy46 = fts5yylhsminor.fts5yy46; + break; +- case 19: /* nearphrases ::= phrase */ ++ case 20: /* nearphrases ::= phrase */ + { + fts5yylhsminor.fts5yy46 = sqlite3Fts5ParseNearset(pParse, 0, fts5yymsp[0].minor.fts5yy53); + } + fts5yymsp[0].minor.fts5yy46 = fts5yylhsminor.fts5yy46; + break; +- case 20: /* nearphrases ::= nearphrases phrase */ ++ case 21: /* nearphrases ::= nearphrases phrase */ + { + fts5yylhsminor.fts5yy46 = sqlite3Fts5ParseNearset(pParse, fts5yymsp[-1].minor.fts5yy46, fts5yymsp[0].minor.fts5yy53); + } + fts5yymsp[-1].minor.fts5yy46 = fts5yylhsminor.fts5yy46; + break; +- case 21: /* neardist_opt ::= */ ++ case 22: /* neardist_opt ::= */ + { fts5yymsp[1].minor.fts5yy0.p = 0; fts5yymsp[1].minor.fts5yy0.n = 0; } + break; +- case 22: /* neardist_opt ::= COMMA STRING */ ++ case 23: /* neardist_opt ::= COMMA STRING */ + { fts5yymsp[-1].minor.fts5yy0 = fts5yymsp[0].minor.fts5yy0; } + break; +- case 23: /* phrase ::= phrase PLUS STRING star_opt */ ++ case 24: /* phrase ::= phrase PLUS STRING star_opt */ + { + fts5yylhsminor.fts5yy53 = sqlite3Fts5ParseTerm(pParse, fts5yymsp[-3].minor.fts5yy53, &fts5yymsp[-1].minor.fts5yy0, fts5yymsp[0].minor.fts5yy4); + } + fts5yymsp[-3].minor.fts5yy53 = fts5yylhsminor.fts5yy53; + break; +- case 24: /* phrase ::= STRING star_opt */ ++ case 25: /* phrase ::= STRING star_opt */ + { + fts5yylhsminor.fts5yy53 = sqlite3Fts5ParseTerm(pParse, 0, &fts5yymsp[-1].minor.fts5yy0, fts5yymsp[0].minor.fts5yy4); + } + fts5yymsp[-1].minor.fts5yy53 = fts5yylhsminor.fts5yy53; + break; +- case 25: /* star_opt ::= STAR */ ++ case 26: /* star_opt ::= STAR */ + { fts5yymsp[0].minor.fts5yy4 = 1; } + break; +- case 26: /* star_opt ::= */ ++ case 27: /* star_opt ::= */ + { fts5yymsp[1].minor.fts5yy4 = 0; } + break; + default: +@@ -185479,16 +200899,12 @@ + /* It is not possible for a REDUCE to be followed by an error */ + assert( fts5yyact!=fts5YY_ERROR_ACTION ); + +- if( fts5yyact==fts5YY_ACCEPT_ACTION ){ +- fts5yypParser->fts5yytos += fts5yysize; +- fts5yy_accept(fts5yypParser); +- }else{ +- fts5yymsp += fts5yysize+1; +- fts5yypParser->fts5yytos = fts5yymsp; +- fts5yymsp->stateno = (fts5YYACTIONTYPE)fts5yyact; +- fts5yymsp->major = (fts5YYCODETYPE)fts5yygoto; +- fts5yyTraceShift(fts5yypParser, fts5yyact); +- } ++ fts5yymsp += fts5yysize+1; ++ fts5yypParser->fts5yytos = fts5yymsp; ++ fts5yymsp->stateno = (fts5YYACTIONTYPE)fts5yyact; ++ fts5yymsp->major = (fts5YYCODETYPE)fts5yygoto; ++ fts5yyTraceShift(fts5yypParser, fts5yyact, "... then shift"); ++ return fts5yyact; + } + + /* +@@ -185498,7 +200914,8 @@ + static void fts5yy_parse_failed( + fts5yyParser *fts5yypParser /* The parser */ + ){ +- sqlite3Fts5ParserARG_FETCH; ++ sqlite3Fts5ParserARG_FETCH ++ sqlite3Fts5ParserCTX_FETCH + #ifndef NDEBUG + if( fts5yyTraceFILE ){ + fprintf(fts5yyTraceFILE,"%sFail!\n",fts5yyTracePrompt); +@@ -185509,7 +200926,8 @@ + ** parser fails */ + /************ Begin %parse_failure code ***************************************/ + /************ End %parse_failure code *****************************************/ +- sqlite3Fts5ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ ++ sqlite3Fts5ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ ++ sqlite3Fts5ParserCTX_STORE + } + #endif /* fts5YYNOERRORRECOVERY */ + +@@ -185521,7 +200939,8 @@ + int fts5yymajor, /* The major type of the error token */ + sqlite3Fts5ParserFTS5TOKENTYPE fts5yyminor /* The minor type of the error token */ + ){ +- sqlite3Fts5ParserARG_FETCH; ++ sqlite3Fts5ParserARG_FETCH ++ sqlite3Fts5ParserCTX_FETCH + #define FTS5TOKEN fts5yyminor + /************ Begin %syntax_error code ****************************************/ + +@@ -185530,7 +200949,8 @@ + pParse, "fts5: syntax error near \"%.*s\"",FTS5TOKEN.n,FTS5TOKEN.p + ); + /************ End %syntax_error code ******************************************/ +- sqlite3Fts5ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ ++ sqlite3Fts5ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ ++ sqlite3Fts5ParserCTX_STORE + } + + /* +@@ -185539,7 +200959,8 @@ + static void fts5yy_accept( + fts5yyParser *fts5yypParser /* The parser */ + ){ +- sqlite3Fts5ParserARG_FETCH; ++ sqlite3Fts5ParserARG_FETCH ++ sqlite3Fts5ParserCTX_FETCH + #ifndef NDEBUG + if( fts5yyTraceFILE ){ + fprintf(fts5yyTraceFILE,"%sAccept!\n",fts5yyTracePrompt); +@@ -185553,7 +200974,8 @@ + ** parser accepts */ + /*********** Begin %parse_accept code *****************************************/ + /*********** End %parse_accept code *******************************************/ +- sqlite3Fts5ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ ++ sqlite3Fts5ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ ++ sqlite3Fts5ParserCTX_STORE + } + + /* The main parser program. +@@ -185582,7 +201004,7 @@ + sqlite3Fts5ParserARG_PDECL /* Optional %extra_argument parameter */ + ){ + fts5YYMINORTYPE fts5yyminorunion; +- unsigned int fts5yyact; /* The parser action. */ ++ fts5YYACTIONTYPE fts5yyact; /* The parser action. */ + #if !defined(fts5YYERRORSYMBOL) && !defined(fts5YYNOERRORRECOVERY) + int fts5yyendofinput; /* True if we are at the end of input */ + #endif +@@ -185589,31 +201011,44 @@ + #ifdef fts5YYERRORSYMBOL + int fts5yyerrorhit = 0; /* True if fts5yymajor has invoked an error */ + #endif +- fts5yyParser *fts5yypParser; /* The parser */ ++ fts5yyParser *fts5yypParser = (fts5yyParser*)fts5yyp; /* The parser */ ++ sqlite3Fts5ParserCTX_FETCH ++ sqlite3Fts5ParserARG_STORE + +- fts5yypParser = (fts5yyParser*)fts5yyp; + assert( fts5yypParser->fts5yytos!=0 ); + #if !defined(fts5YYERRORSYMBOL) && !defined(fts5YYNOERRORRECOVERY) + fts5yyendofinput = (fts5yymajor==0); + #endif +- sqlite3Fts5ParserARG_STORE; + ++ fts5yyact = fts5yypParser->fts5yytos->stateno; + #ifndef NDEBUG + if( fts5yyTraceFILE ){ +- fprintf(fts5yyTraceFILE,"%sInput '%s'\n",fts5yyTracePrompt,fts5yyTokenName[fts5yymajor]); ++ if( fts5yyact < fts5YY_MIN_REDUCE ){ ++ fprintf(fts5yyTraceFILE,"%sInput '%s' in state %d\n", ++ fts5yyTracePrompt,fts5yyTokenName[fts5yymajor],fts5yyact); ++ }else{ ++ fprintf(fts5yyTraceFILE,"%sInput '%s' with pending reduce %d\n", ++ fts5yyTracePrompt,fts5yyTokenName[fts5yymajor],fts5yyact-fts5YY_MIN_REDUCE); ++ } + } + #endif + + do{ +- fts5yyact = fts5yy_find_shift_action(fts5yypParser,(fts5YYCODETYPE)fts5yymajor); +- if( fts5yyact <= fts5YY_MAX_SHIFTREDUCE ){ +- fts5yy_shift(fts5yypParser,fts5yyact,fts5yymajor,fts5yyminor); ++ assert( fts5yyact==fts5yypParser->fts5yytos->stateno ); ++ fts5yyact = fts5yy_find_shift_action((fts5YYCODETYPE)fts5yymajor,fts5yyact); ++ if( fts5yyact >= fts5YY_MIN_REDUCE ){ ++ fts5yyact = fts5yy_reduce(fts5yypParser,fts5yyact-fts5YY_MIN_REDUCE,fts5yymajor, ++ fts5yyminor sqlite3Fts5ParserCTX_PARAM); ++ }else if( fts5yyact <= fts5YY_MAX_SHIFTREDUCE ){ ++ fts5yy_shift(fts5yypParser,fts5yyact,(fts5YYCODETYPE)fts5yymajor,fts5yyminor); + #ifndef fts5YYNOERRORRECOVERY + fts5yypParser->fts5yyerrcnt--; + #endif +- fts5yymajor = fts5YYNOCODE; +- }else if( fts5yyact <= fts5YY_MAX_REDUCE ){ +- fts5yy_reduce(fts5yypParser,fts5yyact-fts5YY_MIN_REDUCE); ++ break; ++ }else if( fts5yyact==fts5YY_ACCEPT_ACTION ){ ++ fts5yypParser->fts5yytos--; ++ fts5yy_accept(fts5yypParser); ++ return; + }else{ + assert( fts5yyact == fts5YY_ERROR_ACTION ); + fts5yyminorunion.fts5yy0 = fts5yyminor; +@@ -185660,10 +201095,9 @@ + fts5yymajor = fts5YYNOCODE; + }else{ + while( fts5yypParser->fts5yytos >= fts5yypParser->fts5yystack +- && fts5yymx != fts5YYERRORSYMBOL + && (fts5yyact = fts5yy_find_reduce_action( + fts5yypParser->fts5yytos->stateno, +- fts5YYERRORSYMBOL)) >= fts5YY_MIN_REDUCE ++ fts5YYERRORSYMBOL)) > fts5YY_MAX_SHIFTREDUCE + ){ + fts5yy_pop_parser_stack(fts5yypParser); + } +@@ -185680,6 +201114,8 @@ + } + fts5yypParser->fts5yyerrcnt = 3; + fts5yyerrorhit = 1; ++ if( fts5yymajor==fts5YYNOCODE ) break; ++ fts5yyact = fts5yypParser->fts5yytos->stateno; + #elif defined(fts5YYNOERRORRECOVERY) + /* If the fts5YYNOERRORRECOVERY macro is defined, then do not attempt to + ** do any kind of error recovery. Instead, simply invoke the syntax +@@ -185690,8 +201126,7 @@ + */ + fts5yy_syntax_error(fts5yypParser,fts5yymajor, fts5yyminor); + fts5yy_destructor(fts5yypParser,(fts5YYCODETYPE)fts5yymajor,&fts5yyminorunion); +- fts5yymajor = fts5YYNOCODE; +- ++ break; + #else /* fts5YYERRORSYMBOL is not defined */ + /* This is what we do if the grammar does not define ERROR: + ** +@@ -185713,10 +201148,10 @@ + fts5yypParser->fts5yyerrcnt = -1; + #endif + } +- fts5yymajor = fts5YYNOCODE; ++ break; + #endif + } +- }while( fts5yymajor!=fts5YYNOCODE && fts5yypParser->fts5yytos>fts5yypParser->fts5yystack ); ++ }while( fts5yypParser->fts5yytos>fts5yypParser->fts5yystack ); + #ifndef NDEBUG + if( fts5yyTraceFILE ){ + fts5yyStackEntry *i; +@@ -185733,6 +201168,21 @@ + } + + /* ++** Return the fallback token corresponding to canonical token iToken, or ++** 0 if iToken has no fallback. ++*/ ++static int sqlite3Fts5ParserFallback(int iToken){ ++#ifdef fts5YYFALLBACK ++ if( iToken<(int)(sizeof(fts5yyFallback)/sizeof(fts5yyFallback[0])) ){ ++ return fts5yyFallback[iToken]; ++ } ++#else ++ (void)iToken; ++#endif ++ return 0; ++} ++ ++/* + ** 2014 May 31 + ** + ** The author disclaims copyright to this source code. In place of +@@ -186093,6 +201543,16 @@ + } + + /* ++** Return the value in pVal interpreted as utf-8 text. Except, if pVal ++** contains a NULL value, return a pointer to a static string zero ++** bytes in length instead of a NULL pointer. ++*/ ++static const char *fts5ValueToText(sqlite3_value *pVal){ ++ const char *zRet = (const char*)sqlite3_value_text(pVal); ++ return zRet ? zRet : ""; ++} ++ ++/* + ** Implementation of snippet() function. + */ + static void fts5SnippetFunction( +@@ -186127,9 +201587,9 @@ + nCol = pApi->xColumnCount(pFts); + memset(&ctx, 0, sizeof(HighlightContext)); + iCol = sqlite3_value_int(apVal[0]); +- ctx.zOpen = (const char*)sqlite3_value_text(apVal[1]); +- ctx.zClose = (const char*)sqlite3_value_text(apVal[2]); +- zEllips = (const char*)sqlite3_value_text(apVal[3]); ++ 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); +@@ -187832,6 +203292,7 @@ + /* #include <stdio.h> */ + static void sqlite3Fts5ParserTrace(FILE*, char*); + #endif ++static int sqlite3Fts5ParserFallback(int); + + + struct Fts5Expr { +@@ -187883,7 +203344,8 @@ + ** or term prefix. + */ + struct Fts5ExprTerm { +- int bPrefix; /* True for a prefix term */ ++ u8 bPrefix; /* True for a prefix term */ ++ u8 bFirst; /* True if token must be first in column */ + char *zTerm; /* nul-terminated term */ + Fts5IndexIter *pIter; /* Iterator for this term */ + Fts5ExprTerm *pSynonym; /* Pointer to first in list of synonyms */ +@@ -187964,6 +203426,7 @@ + case '+': tok = FTS5_PLUS; break; + case '*': tok = FTS5_STAR; break; + case '-': tok = FTS5_MINUS; break; ++ case '^': tok = FTS5_CARET; break; + case '\0': tok = FTS5_EOF; break; + + case '"': { +@@ -188223,6 +203686,7 @@ + Fts5PoslistReader *aIter = aStatic; + int i; + int rc = SQLITE_OK; ++ int bFirst = pPhrase->aTerm[0].bFirst; + + fts5BufferZero(&pPhrase->poslist); + +@@ -188277,8 +203741,10 @@ + }while( bMatch==0 ); + + /* Append position iPos to the output */ +- rc = sqlite3Fts5PoslistWriterAppend(&pPhrase->poslist, &writer, iPos); +- if( rc!=SQLITE_OK ) goto ismatch_out; ++ if( bFirst==0 || FTS5_POS2OFFSET(iPos)==0 ){ ++ rc = sqlite3Fts5PoslistWriterAppend(&pPhrase->poslist, &writer, iPos); ++ if( rc!=SQLITE_OK ) goto ismatch_out; ++ } + + for(i=0; i<pPhrase->nTerm; i++){ + if( sqlite3Fts5PoslistReaderNext(&aIter[i]) ) goto ismatch_out; +@@ -188532,7 +203998,9 @@ + ** phrase is not a match, break out of the loop early. */ + for(i=0; rc==SQLITE_OK && i<pNear->nPhrase; i++){ + Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; +- if( pPhrase->nTerm>1 || pPhrase->aTerm[0].pSynonym || pNear->pColset ){ ++ if( pPhrase->nTerm>1 || pPhrase->aTerm[0].pSynonym ++ || pNear->pColset || pPhrase->aTerm[0].bFirst ++ ){ + int bMatch = 0; + rc = fts5ExprPhraseIsMatch(pNode, pPhrase, &bMatch); + if( bMatch==0 ) break; +@@ -188713,6 +204181,7 @@ + assert( pNear->nPhrase>1 + || pNear->apPhrase[0]->nTerm>1 + || pNear->apPhrase[0]->aTerm[0].pSynonym ++ || pNear->apPhrase[0]->aTerm[0].bFirst + ); + + /* Initialize iLast, the "lastest" rowid any iterator points to. If the +@@ -189238,6 +204707,16 @@ + } + + /* ++** Set the "bFirst" flag on the first token of the phrase passed as the ++** only argument. ++*/ ++static void sqlite3Fts5ParseSetCaret(Fts5ExprPhrase *pPhrase){ ++ if( pPhrase && pPhrase->nTerm ){ ++ pPhrase->aTerm[0].bFirst = 1; ++ } ++} ++ ++/* + ** If argument pNear is NULL, then a new Fts5ExprNearset object is allocated + ** and populated with pPhrase. Or, if pNear is not NULL, phrase pPhrase is + ** appended to it and the results returned. +@@ -189454,7 +204933,7 @@ + ** no token characters at all. (e.g ... MATCH '""'). */ + sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, sizeof(Fts5ExprPhrase)); + }else if( sCtx.pPhrase->nTerm ){ +- sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = bPrefix; ++ sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = (u8)bPrefix; + } + pParse->apPhrase[pParse->nPhrase-1] = sCtx.pPhrase; + } +@@ -189515,6 +204994,7 @@ + } + if( rc==SQLITE_OK ){ + sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix; ++ sCtx.pPhrase->aTerm[i].bFirst = pOrig->aTerm[i].bFirst; + } + } + }else{ +@@ -189533,7 +205013,10 @@ + pNew->pRoot->pNear->nPhrase = 1; + sCtx.pPhrase->pNode = pNew->pRoot; + +- if( pOrig->nTerm==1 && pOrig->aTerm[0].pSynonym==0 ){ ++ if( pOrig->nTerm==1 ++ && pOrig->aTerm[0].pSynonym==0 ++ && pOrig->aTerm[0].bFirst==0 ++ ){ + pNew->pRoot->eType = FTS5_TERM; + pNew->pRoot->xNext = fts5ExprNodeNext_TERM; + }else{ +@@ -189807,6 +205290,7 @@ + Fts5ExprNearset *pNear = pNode->pNear; + if( pNear->nPhrase==1 && pNear->apPhrase[0]->nTerm==1 + && pNear->apPhrase[0]->aTerm[0].pSynonym==0 ++ && pNear->apPhrase[0]->aTerm[0].bFirst==0 + ){ + pNode->eType = FTS5_TERM; + pNode->xNext = fts5ExprNodeNext_TERM; +@@ -189893,20 +205377,23 @@ + } + } + +- if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL +- && (pNear->nPhrase!=1 || pNear->apPhrase[0]->nTerm>1) +- ){ +- assert( pParse->rc==SQLITE_OK ); +- pParse->rc = SQLITE_ERROR; +- assert( pParse->zErr==0 ); +- pParse->zErr = sqlite3_mprintf( +- "fts5: %s queries are not supported (detail!=full)", +- pNear->nPhrase==1 ? "phrase": "NEAR" +- ); +- sqlite3_free(pRet); +- pRet = 0; ++ if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){ ++ Fts5ExprPhrase *pPhrase = pNear->apPhrase[0]; ++ if( pNear->nPhrase!=1 ++ || pPhrase->nTerm>1 ++ || (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst) ++ ){ ++ assert( pParse->rc==SQLITE_OK ); ++ pParse->rc = SQLITE_ERROR; ++ assert( pParse->zErr==0 ); ++ pParse->zErr = sqlite3_mprintf( ++ "fts5: %s queries are not supported (detail!=full)", ++ pNear->nPhrase==1 ? "phrase": "NEAR" ++ ); ++ sqlite3_free(pRet); ++ pRet = 0; ++ } + } +- + }else{ + fts5ExprAddChildren(pRet, pLeft); + fts5ExprAddChildren(pRet, pRight); +@@ -190310,6 +205797,7 @@ + sqlite3_value **apVal /* Function arguments */ + ){ + int iCode; ++ u8 aArr[32]; + if( nArg!=1 ){ + sqlite3_result_error(pCtx, + "wrong number of arguments to function fts5_isalnum", -1 +@@ -190316,8 +205804,12 @@ + ); + return; + } ++ memset(aArr, 0, sizeof(aArr)); ++ sqlite3Fts5UnicodeCatParse("L*", aArr); ++ sqlite3Fts5UnicodeCatParse("N*", aArr); ++ sqlite3Fts5UnicodeCatParse("Co", aArr); + iCode = sqlite3_value_int(apVal[0]); +- sqlite3_result_int(pCtx, sqlite3Fts5UnicodeIsalnum(iCode)); ++ sqlite3_result_int(pCtx, aArr[sqlite3Fts5UnicodeCategory(iCode)]); + } + + static void fts5ExprFold( +@@ -190361,10 +205853,12 @@ + rc = sqlite3_create_function(db, p->z, -1, SQLITE_UTF8, pCtx, p->x, 0, 0); + } + +- /* Avoid a warning indicating that sqlite3Fts5ParserTrace() is unused */ ++ /* Avoid warnings indicating that sqlite3Fts5ParserTrace() and ++ ** sqlite3Fts5ParserFallback() are unused */ + #ifndef NDEBUG + (void)sqlite3Fts5ParserTrace; + #endif ++ (void)sqlite3Fts5ParserFallback; + + return rc; + } +@@ -191909,6 +207403,7 @@ + sqlite3_bind_blob(p->pWriter, 2, pData, nData, SQLITE_STATIC); + sqlite3_step(p->pWriter); + p->rc = sqlite3_reset(p->pWriter); ++ sqlite3_bind_null(p->pWriter, 2); + } + + /* +@@ -193537,6 +209032,7 @@ + bDlidx = (val & 0x0001); + } + p->rc = sqlite3_reset(pIdxSelect); ++ sqlite3_bind_null(pIdxSelect, 2); + + if( iPg<pSeg->pgnoFirst ){ + iPg = pSeg->pgnoFirst; +@@ -194749,6 +210245,7 @@ + sqlite3_bind_blob(pIdxSelect, 2, aBlob, 2, SQLITE_STATIC); + assert( sqlite3_step(pIdxSelect)!=SQLITE_ROW ); + p->rc = sqlite3_reset(pIdxSelect); ++ sqlite3_bind_null(pIdxSelect, 2); + } + } + #endif +@@ -194875,6 +210372,7 @@ + sqlite3_bind_int64(p->pIdxWriter, 3, bFlag + ((i64)pWriter->iBtPage<<1)); + sqlite3_step(p->pIdxWriter); + p->rc = sqlite3_reset(p->pIdxWriter); ++ sqlite3_bind_null(p->pIdxWriter, 2); + } + pWriter->iBtPage = 0; + } +@@ -196060,7 +211558,13 @@ + Fts5Buffer out = {0, 0, 0}; + Fts5Buffer tmp = {0, 0, 0}; + +- if( sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n) ) return; ++ /* The maximum size of the output is equal to the sum of the two ++ ** input sizes + 1 varint (9 bytes). The extra varint is because if the ++ ** first rowid in one input is a large negative number, and the first in ++ ** the other a non-negative number, the delta for the non-negative ++ ** number will be larger on disk than the literal integer value ++ ** was. */ ++ if( sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n + 9) ) return; + fts5DoclistIterInit(p1, &i1); + fts5DoclistIterInit(p2, &i2); + +@@ -196154,6 +211658,7 @@ + fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid); + fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.aEof - i2.aPoslist); + } ++ assert( out.n<=(p1->n+p2->n+9) ); + + fts5BufferSet(&p->rc, p1, out.n, out.p); + fts5BufferFree(&tmp); +@@ -196401,7 +211906,10 @@ + for(i=0; i<nChar; i++){ + if( n>=nByte ) return 0; /* Input contains fewer than nChar chars */ + if( (unsigned char)p[n++]>=0xc0 ){ +- while( (p[n] & 0xc0)==0x80 ) n++; ++ while( (p[n] & 0xc0)==0x80 ){ ++ n++; ++ if( n>=nByte ) break; ++ } + } + } + return n; +@@ -196539,7 +212047,7 @@ + fts5CloseReader(p); + } + +- *ppIter = &pRet->base; ++ *ppIter = (Fts5IndexIter*)pRet; + sqlite3Fts5BufferFree(&buf); + } + return fts5IndexReturn(p); +@@ -197926,7 +213434,7 @@ + case FTS5_SAVEPOINT: + assert( p->ts.eState==1 ); + assert( iSavepoint>=0 ); +- assert( iSavepoint>p->ts.iSavepoint ); ++ assert( iSavepoint>=p->ts.iSavepoint ); + p->ts.iSavepoint = iSavepoint; + break; + +@@ -198181,6 +213689,12 @@ + aColMap[1] = nCol; + aColMap[2] = nCol+1; + ++ assert( SQLITE_INDEX_CONSTRAINT_EQ<SQLITE_INDEX_CONSTRAINT_MATCH ); ++ assert( SQLITE_INDEX_CONSTRAINT_GT<SQLITE_INDEX_CONSTRAINT_MATCH ); ++ assert( SQLITE_INDEX_CONSTRAINT_LE<SQLITE_INDEX_CONSTRAINT_MATCH ); ++ assert( SQLITE_INDEX_CONSTRAINT_GE<SQLITE_INDEX_CONSTRAINT_MATCH ); ++ assert( SQLITE_INDEX_CONSTRAINT_LE<SQLITE_INDEX_CONSTRAINT_MATCH ); ++ + /* Set idxFlags flags for all WHERE clause terms that will be used. */ + for(i=0; i<pInfo->nConstraint; i++){ + struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; +@@ -198199,11 +213713,11 @@ + pInfo->estimatedCost = 1e50; + return SQLITE_OK; + } +- }else{ ++ }else if( p->op<=SQLITE_INDEX_CONSTRAINT_MATCH ){ + int j; + for(j=1; j<ArraySize(aConstraint); j++){ + struct Constraint *pC = &aConstraint[j]; +- if( iCol==aColMap[pC->iCol] && p->op & pC->op && p->usable ){ ++ if( iCol==aColMap[pC->iCol] && (p->op & pC->op) && p->usable ){ + pC->iConsIndex = i; + idxFlags |= pC->fts5op; + } +@@ -198845,6 +214359,13 @@ + assert( nVal==0 && pMatch==0 && bOrderByRank==0 && bDesc==0 ); + assert( pCsr->iLastRowid==LARGEST_INT64 ); + assert( pCsr->iFirstRowid==SMALLEST_INT64 ); ++ if( pTab->pSortCsr->bDesc ){ ++ pCsr->iLastRowid = pTab->pSortCsr->iFirstRowid; ++ pCsr->iFirstRowid = pTab->pSortCsr->iLastRowid; ++ }else{ ++ pCsr->iLastRowid = pTab->pSortCsr->iLastRowid; ++ pCsr->iFirstRowid = pTab->pSortCsr->iFirstRowid; ++ } + pCsr->ePlan = FTS5_PLAN_SOURCE; + pCsr->pExpr = pTab->pSortCsr->pExpr; + rc = fts5CursorFirst(pTab, pCsr, bDesc); +@@ -200275,12 +215796,27 @@ + ){ + assert( nArg==0 ); + UNUSED_PARAM2(nArg, apUnused); +- sqlite3_result_text(pCtx, "fts5: 2017-08-01 13:24:15 9501e22dfeebdcefa783575e47c60b514d7c2e0cad73b2a496c0bc4b680900a8", -1, SQLITE_TRANSIENT); ++ sqlite3_result_text(pCtx, "fts5: 2018-12-01 12:34:55 bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238b4f9", -1, SQLITE_TRANSIENT); + } + ++/* ++** Return true if zName is the extension on one of the shadow tables used ++** by this module. ++*/ ++static int fts5ShadowName(const char *zName){ ++ static const char *azName[] = { ++ "config", "content", "data", "docsize", "idx" ++ }; ++ unsigned int i; ++ for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){ ++ if( sqlite3_stricmp(zName, azName[i])==0 ) return 1; ++ } ++ return 0; ++} ++ + static int fts5Init(sqlite3 *db){ + static const sqlite3_module fts5Mod = { +- /* iVersion */ 2, ++ /* iVersion */ 3, + /* xCreate */ fts5CreateMethod, + /* xConnect */ fts5ConnectMethod, + /* xBestIndex */ fts5BestIndexMethod, +@@ -200303,6 +215839,7 @@ + /* xSavepoint */ fts5SavepointMethod, + /* xRelease */ fts5ReleaseMethod, + /* xRollbackTo */ fts5RollbackToMethod, ++ /* xShadowName */ fts5ShadowName + }; + + int rc; +@@ -200851,6 +216388,7 @@ + sqlite3_bind_blob(pReplace, 2, pBuf->p, pBuf->n, SQLITE_STATIC); + sqlite3_step(pReplace); + rc = sqlite3_reset(pReplace); ++ sqlite3_bind_null(pReplace, 2); + } + } + return rc; +@@ -201511,6 +217049,7 @@ + } + sqlite3_step(pReplace); + rc = sqlite3_reset(pReplace); ++ sqlite3_bind_null(pReplace, 1); + } + if( rc==SQLITE_OK && pVal ){ + int iNew = p->pConfig->iCookie + 1; +@@ -201761,6 +217300,8 @@ + int bRemoveDiacritic; /* True if remove_diacritics=1 is set */ + int nException; + int *aiException; ++ ++ unsigned char aCategory[32]; /* True for token char categories */ + }; + + static int fts5UnicodeAddExceptions( +@@ -201785,7 +217326,7 @@ + if( iCode<128 ){ + p->aTokenChar[iCode] = (unsigned char)bTokenChars; + }else{ +- bToken = sqlite3Fts5UnicodeIsalnum(iCode); ++ bToken = p->aCategory[sqlite3Fts5UnicodeCategory(iCode)]; + assert( (bToken==0 || bToken==1) ); + assert( (bTokenChars==0 || bTokenChars==1) ); + if( bToken!=bTokenChars && sqlite3Fts5UnicodeIsdiacritic(iCode)==0 ){ +@@ -201846,6 +217387,21 @@ + return; + } + ++static int unicodeSetCategories(Unicode61Tokenizer *p, const char *zCat){ ++ const char *z = zCat; ++ ++ while( *z ){ ++ while( *z==' ' || *z=='\t' ) z++; ++ if( *z && sqlite3Fts5UnicodeCatParse(z, p->aCategory) ){ ++ return SQLITE_ERROR; ++ } ++ while( *z!=' ' && *z!='\t' && *z!='\0' ) z++; ++ } ++ ++ sqlite3Fts5UnicodeAscii(p->aCategory, p->aTokenChar); ++ return SQLITE_OK; ++} ++ + /* + ** Create a "unicode61" tokenizer. + */ +@@ -201864,9 +217420,10 @@ + }else{ + p = (Unicode61Tokenizer*)sqlite3_malloc(sizeof(Unicode61Tokenizer)); + if( p ){ ++ const char *zCat = "L* N* Co"; + int i; + memset(p, 0, sizeof(Unicode61Tokenizer)); +- memcpy(p->aTokenChar, aAsciiTokenChar, sizeof(aAsciiTokenChar)); ++ + p->bRemoveDiacritic = 1; + p->nFold = 64; + p->aFold = sqlite3_malloc(p->nFold * sizeof(char)); +@@ -201873,7 +217430,19 @@ + if( p->aFold==0 ){ + rc = SQLITE_NOMEM; + } ++ ++ /* Search for a "categories" argument */ + for(i=0; rc==SQLITE_OK && i<nArg; i+=2){ ++ if( 0==sqlite3_stricmp(azArg[i], "categories") ){ ++ zCat = azArg[i+1]; ++ } ++ } ++ ++ if( rc==SQLITE_OK ){ ++ rc = unicodeSetCategories(p, zCat); ++ } ++ ++ for(i=0; rc==SQLITE_OK && i<nArg; i+=2){ + const char *zArg = azArg[i+1]; + if( 0==sqlite3_stricmp(azArg[i], "remove_diacritics") ){ + if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){ +@@ -201886,10 +217455,14 @@ + }else + if( 0==sqlite3_stricmp(azArg[i], "separators") ){ + rc = fts5UnicodeAddExceptions(p, zArg, 0); ++ }else ++ if( 0==sqlite3_stricmp(azArg[i], "categories") ){ ++ /* no-op */ + }else{ + rc = SQLITE_ERROR; + } + } ++ + }else{ + rc = SQLITE_NOMEM; + } +@@ -201908,8 +217481,10 @@ + ** character (not a separator). + */ + static int fts5UnicodeIsAlnum(Unicode61Tokenizer *p, int iCode){ +- assert( (sqlite3Fts5UnicodeIsalnum(iCode) & 0xFFFFFFFE)==0 ); +- return sqlite3Fts5UnicodeIsalnum(iCode) ^ fts5UnicodeIsException(p, iCode); ++ return ( ++ p->aCategory[sqlite3Fts5UnicodeCategory(iCode)] ++ ^ fts5UnicodeIsException(p, iCode) ++ ); + } + + static int fts5UnicodeTokenize( +@@ -202785,137 +218360,8 @@ + + /* #include <assert.h> */ + +-/* +-** Return true if the argument corresponds to a unicode codepoint +-** classified as either a letter or a number. Otherwise false. +-** +-** The results are undefined if the value passed to this function +-** is less than zero. +-*/ +-static int sqlite3Fts5UnicodeIsalnum(int c){ +- /* Each unsigned integer in the following array corresponds to a contiguous +- ** range of unicode codepoints that are not either letters or numbers (i.e. +- ** codepoints for which this function should return 0). +- ** +- ** The most significant 22 bits in each 32-bit value contain the first +- ** codepoint in the range. The least significant 10 bits are used to store +- ** the size of the range (always at least 1). In other words, the value +- ** ((C<<22) + N) represents a range of N codepoints starting with codepoint +- ** C. It is not possible to represent a range larger than 1023 codepoints +- ** using this format. +- */ +- static const unsigned int aEntry[] = { +- 0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07, +- 0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01, +- 0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401, +- 0x000BBC81, 0x000DD401, 0x000DF801, 0x000E1002, 0x000E1C01, +- 0x000FD801, 0x00120808, 0x00156806, 0x00162402, 0x00163C01, +- 0x00164437, 0x0017CC02, 0x00180005, 0x00181816, 0x00187802, +- 0x00192C15, 0x0019A804, 0x0019C001, 0x001B5001, 0x001B580F, +- 0x001B9C07, 0x001BF402, 0x001C000E, 0x001C3C01, 0x001C4401, +- 0x001CC01B, 0x001E980B, 0x001FAC09, 0x001FD804, 0x00205804, +- 0x00206C09, 0x00209403, 0x0020A405, 0x0020C00F, 0x00216403, +- 0x00217801, 0x0023901B, 0x00240004, 0x0024E803, 0x0024F812, +- 0x00254407, 0x00258804, 0x0025C001, 0x00260403, 0x0026F001, +- 0x0026F807, 0x00271C02, 0x00272C03, 0x00275C01, 0x00278802, +- 0x0027C802, 0x0027E802, 0x00280403, 0x0028F001, 0x0028F805, +- 0x00291C02, 0x00292C03, 0x00294401, 0x0029C002, 0x0029D401, +- 0x002A0403, 0x002AF001, 0x002AF808, 0x002B1C03, 0x002B2C03, +- 0x002B8802, 0x002BC002, 0x002C0403, 0x002CF001, 0x002CF807, +- 0x002D1C02, 0x002D2C03, 0x002D5802, 0x002D8802, 0x002DC001, +- 0x002E0801, 0x002EF805, 0x002F1803, 0x002F2804, 0x002F5C01, +- 0x002FCC08, 0x00300403, 0x0030F807, 0x00311803, 0x00312804, +- 0x00315402, 0x00318802, 0x0031FC01, 0x00320802, 0x0032F001, +- 0x0032F807, 0x00331803, 0x00332804, 0x00335402, 0x00338802, +- 0x00340802, 0x0034F807, 0x00351803, 0x00352804, 0x00355C01, +- 0x00358802, 0x0035E401, 0x00360802, 0x00372801, 0x00373C06, +- 0x00375801, 0x00376008, 0x0037C803, 0x0038C401, 0x0038D007, +- 0x0038FC01, 0x00391C09, 0x00396802, 0x003AC401, 0x003AD006, +- 0x003AEC02, 0x003B2006, 0x003C041F, 0x003CD00C, 0x003DC417, +- 0x003E340B, 0x003E6424, 0x003EF80F, 0x003F380D, 0x0040AC14, +- 0x00412806, 0x00415804, 0x00417803, 0x00418803, 0x00419C07, +- 0x0041C404, 0x0042080C, 0x00423C01, 0x00426806, 0x0043EC01, +- 0x004D740C, 0x004E400A, 0x00500001, 0x0059B402, 0x005A0001, +- 0x005A6C02, 0x005BAC03, 0x005C4803, 0x005CC805, 0x005D4802, +- 0x005DC802, 0x005ED023, 0x005F6004, 0x005F7401, 0x0060000F, +- 0x0062A401, 0x0064800C, 0x0064C00C, 0x00650001, 0x00651002, +- 0x0066C011, 0x00672002, 0x00677822, 0x00685C05, 0x00687802, +- 0x0069540A, 0x0069801D, 0x0069FC01, 0x006A8007, 0x006AA006, +- 0x006C0005, 0x006CD011, 0x006D6823, 0x006E0003, 0x006E840D, +- 0x006F980E, 0x006FF004, 0x00709014, 0x0070EC05, 0x0071F802, +- 0x00730008, 0x00734019, 0x0073B401, 0x0073C803, 0x00770027, +- 0x0077F004, 0x007EF401, 0x007EFC03, 0x007F3403, 0x007F7403, +- 0x007FB403, 0x007FF402, 0x00800065, 0x0081A806, 0x0081E805, +- 0x00822805, 0x0082801A, 0x00834021, 0x00840002, 0x00840C04, +- 0x00842002, 0x00845001, 0x00845803, 0x00847806, 0x00849401, +- 0x00849C01, 0x0084A401, 0x0084B801, 0x0084E802, 0x00850005, +- 0x00852804, 0x00853C01, 0x00864264, 0x00900027, 0x0091000B, +- 0x0092704E, 0x00940200, 0x009C0475, 0x009E53B9, 0x00AD400A, +- 0x00B39406, 0x00B3BC03, 0x00B3E404, 0x00B3F802, 0x00B5C001, +- 0x00B5FC01, 0x00B7804F, 0x00B8C00C, 0x00BA001A, 0x00BA6C59, +- 0x00BC00D6, 0x00BFC00C, 0x00C00005, 0x00C02019, 0x00C0A807, +- 0x00C0D802, 0x00C0F403, 0x00C26404, 0x00C28001, 0x00C3EC01, +- 0x00C64002, 0x00C6580A, 0x00C70024, 0x00C8001F, 0x00C8A81E, +- 0x00C94001, 0x00C98020, 0x00CA2827, 0x00CB003F, 0x00CC0100, +- 0x01370040, 0x02924037, 0x0293F802, 0x02983403, 0x0299BC10, +- 0x029A7C01, 0x029BC008, 0x029C0017, 0x029C8002, 0x029E2402, +- 0x02A00801, 0x02A01801, 0x02A02C01, 0x02A08C09, 0x02A0D804, +- 0x02A1D004, 0x02A20002, 0x02A2D011, 0x02A33802, 0x02A38012, +- 0x02A3E003, 0x02A4980A, 0x02A51C0D, 0x02A57C01, 0x02A60004, +- 0x02A6CC1B, 0x02A77802, 0x02A8A40E, 0x02A90C01, 0x02A93002, +- 0x02A97004, 0x02A9DC03, 0x02A9EC01, 0x02AAC001, 0x02AAC803, +- 0x02AADC02, 0x02AAF802, 0x02AB0401, 0x02AB7802, 0x02ABAC07, +- 0x02ABD402, 0x02AF8C0B, 0x03600001, 0x036DFC02, 0x036FFC02, +- 0x037FFC01, 0x03EC7801, 0x03ECA401, 0x03EEC810, 0x03F4F802, +- 0x03F7F002, 0x03F8001A, 0x03F88007, 0x03F8C023, 0x03F95013, +- 0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807, 0x03FCEC06, +- 0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405, 0x04040003, +- 0x0404DC09, 0x0405E411, 0x0406400C, 0x0407402E, 0x040E7C01, +- 0x040F4001, 0x04215C01, 0x04247C01, 0x0424FC01, 0x04280403, +- 0x04281402, 0x04283004, 0x0428E003, 0x0428FC01, 0x04294009, +- 0x0429FC01, 0x042CE407, 0x04400003, 0x0440E016, 0x04420003, +- 0x0442C012, 0x04440003, 0x04449C0E, 0x04450004, 0x04460003, +- 0x0446CC0E, 0x04471404, 0x045AAC0D, 0x0491C004, 0x05BD442E, +- 0x05BE3C04, 0x074000F6, 0x07440027, 0x0744A4B5, 0x07480046, +- 0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01, 0x075C5401, +- 0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401, 0x075EA401, +- 0x075F0C01, 0x07BBC002, 0x07C0002C, 0x07C0C064, 0x07C2800F, +- 0x07C2C40E, 0x07C3040F, 0x07C3440F, 0x07C4401F, 0x07C4C03C, +- 0x07C5C02B, 0x07C7981D, 0x07C8402B, 0x07C90009, 0x07C94002, +- 0x07CC0021, 0x07CCC006, 0x07CCDC46, 0x07CE0014, 0x07CE8025, +- 0x07CF1805, 0x07CF8011, 0x07D0003F, 0x07D10001, 0x07D108B6, +- 0x07D3E404, 0x07D4003E, 0x07D50004, 0x07D54018, 0x07D7EC46, +- 0x07D9140B, 0x07DA0046, 0x07DC0074, 0x38000401, 0x38008060, +- 0x380400F0, +- }; +- static const unsigned int aAscii[4] = { +- 0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001, +- }; + +- if( (unsigned int)c<128 ){ +- return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 ); +- }else if( (unsigned int)c<(1<<22) ){ +- unsigned int key = (((unsigned int)c)<<10) | 0x000003FF; +- int iRes = 0; +- int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; +- int iLo = 0; +- while( iHi>=iLo ){ +- int iTest = (iHi + iLo) / 2; +- if( key >= aEntry[iTest] ){ +- iRes = iTest; +- iLo = iTest+1; +- }else{ +- iHi = iTest-1; +- } +- } +- assert( aEntry[0]<key ); +- assert( key>=aEntry[iRes] ); +- return (((unsigned int)c) >= ((aEntry[iRes]>>10) + (aEntry[iRes]&0x3FF))); +- } +- return 1; +-} + +- + /* + ** If the argument is a codepoint corresponding to a lowercase letter + ** in the ASCII range with a diacritic added, return the codepoint +@@ -203126,6 +218572,539 @@ + return ret; + } + ++ ++#if 0 ++static int sqlite3Fts5UnicodeNCat(void) { ++ return 32; ++} ++#endif ++ ++static int sqlite3Fts5UnicodeCatParse(const char *zCat, u8 *aArray){ ++ aArray[0] = 1; ++ switch( zCat[0] ){ ++ case 'C': ++ switch( zCat[1] ){ ++ case 'c': aArray[1] = 1; break; ++ case 'f': aArray[2] = 1; break; ++ case 'n': aArray[3] = 1; break; ++ case 's': aArray[4] = 1; break; ++ case 'o': aArray[31] = 1; break; ++ case '*': ++ aArray[1] = 1; ++ aArray[2] = 1; ++ aArray[3] = 1; ++ aArray[4] = 1; ++ aArray[31] = 1; ++ break; ++ default: return 1; } ++ break; ++ ++ case 'L': ++ switch( zCat[1] ){ ++ case 'l': aArray[5] = 1; break; ++ case 'm': aArray[6] = 1; break; ++ case 'o': aArray[7] = 1; break; ++ case 't': aArray[8] = 1; break; ++ case 'u': aArray[9] = 1; break; ++ case 'C': aArray[30] = 1; break; ++ case '*': ++ aArray[5] = 1; ++ aArray[6] = 1; ++ aArray[7] = 1; ++ aArray[8] = 1; ++ aArray[9] = 1; ++ aArray[30] = 1; ++ break; ++ default: return 1; } ++ break; ++ ++ case 'M': ++ switch( zCat[1] ){ ++ case 'c': aArray[10] = 1; break; ++ case 'e': aArray[11] = 1; break; ++ case 'n': aArray[12] = 1; break; ++ case '*': ++ aArray[10] = 1; ++ aArray[11] = 1; ++ aArray[12] = 1; ++ break; ++ default: return 1; } ++ break; ++ ++ case 'N': ++ switch( zCat[1] ){ ++ case 'd': aArray[13] = 1; break; ++ case 'l': aArray[14] = 1; break; ++ case 'o': aArray[15] = 1; break; ++ case '*': ++ aArray[13] = 1; ++ aArray[14] = 1; ++ aArray[15] = 1; ++ break; ++ default: return 1; } ++ break; ++ ++ case 'P': ++ switch( zCat[1] ){ ++ case 'c': aArray[16] = 1; break; ++ case 'd': aArray[17] = 1; break; ++ case 'e': aArray[18] = 1; break; ++ case 'f': aArray[19] = 1; break; ++ case 'i': aArray[20] = 1; break; ++ case 'o': aArray[21] = 1; break; ++ case 's': aArray[22] = 1; break; ++ case '*': ++ aArray[16] = 1; ++ aArray[17] = 1; ++ aArray[18] = 1; ++ aArray[19] = 1; ++ aArray[20] = 1; ++ aArray[21] = 1; ++ aArray[22] = 1; ++ break; ++ default: return 1; } ++ break; ++ ++ case 'S': ++ switch( zCat[1] ){ ++ case 'c': aArray[23] = 1; break; ++ case 'k': aArray[24] = 1; break; ++ case 'm': aArray[25] = 1; break; ++ case 'o': aArray[26] = 1; break; ++ case '*': ++ aArray[23] = 1; ++ aArray[24] = 1; ++ aArray[25] = 1; ++ aArray[26] = 1; ++ break; ++ default: return 1; } ++ break; ++ ++ case 'Z': ++ switch( zCat[1] ){ ++ case 'l': aArray[27] = 1; break; ++ case 'p': aArray[28] = 1; break; ++ case 's': aArray[29] = 1; break; ++ case '*': ++ aArray[27] = 1; ++ aArray[28] = 1; ++ aArray[29] = 1; ++ break; ++ default: return 1; } ++ break; ++ ++ } ++ return 0; ++} ++ ++static u16 aFts5UnicodeBlock[] = { ++ 0, 1471, 1753, 1760, 1760, 1760, 1760, 1760, 1760, 1760, ++ 1760, 1760, 1760, 1760, 1760, 1763, 1765, ++ }; ++static u16 aFts5UnicodeMap[] = { ++ 0, 32, 33, 36, 37, 40, 41, 42, 43, 44, ++ 45, 46, 48, 58, 60, 63, 65, 91, 92, 93, ++ 94, 95, 96, 97, 123, 124, 125, 126, 127, 160, ++ 161, 162, 166, 167, 168, 169, 170, 171, 172, 173, ++ 174, 175, 176, 177, 178, 180, 181, 182, 184, 185, ++ 186, 187, 188, 191, 192, 215, 216, 223, 247, 248, ++ 256, 312, 313, 329, 330, 377, 383, 385, 387, 388, ++ 391, 394, 396, 398, 402, 403, 405, 406, 409, 412, ++ 414, 415, 417, 418, 423, 427, 428, 431, 434, 436, ++ 437, 440, 442, 443, 444, 446, 448, 452, 453, 454, ++ 455, 456, 457, 458, 459, 460, 461, 477, 478, 496, ++ 497, 498, 499, 500, 503, 505, 506, 564, 570, 572, ++ 573, 575, 577, 580, 583, 584, 592, 660, 661, 688, ++ 706, 710, 722, 736, 741, 748, 749, 750, 751, 768, ++ 880, 884, 885, 886, 890, 891, 894, 900, 902, 903, ++ 904, 908, 910, 912, 913, 931, 940, 975, 977, 978, ++ 981, 984, 1008, 1012, 1014, 1015, 1018, 1020, 1021, 1072, ++ 1120, 1154, 1155, 1160, 1162, 1217, 1231, 1232, 1329, 1369, ++ 1370, 1377, 1417, 1418, 1423, 1425, 1470, 1471, 1472, 1473, ++ 1475, 1476, 1478, 1479, 1488, 1520, 1523, 1536, 1542, 1545, ++ 1547, 1548, 1550, 1552, 1563, 1566, 1568, 1600, 1601, 1611, ++ 1632, 1642, 1646, 1648, 1649, 1748, 1749, 1750, 1757, 1758, ++ 1759, 1765, 1767, 1769, 1770, 1774, 1776, 1786, 1789, 1791, ++ 1792, 1807, 1808, 1809, 1810, 1840, 1869, 1958, 1969, 1984, ++ 1994, 2027, 2036, 2038, 2039, 2042, 2048, 2070, 2074, 2075, ++ 2084, 2085, 2088, 2089, 2096, 2112, 2137, 2142, 2208, 2210, ++ 2276, 2304, 2307, 2308, 2362, 2363, 2364, 2365, 2366, 2369, ++ 2377, 2381, 2382, 2384, 2385, 2392, 2402, 2404, 2406, 2416, ++ 2417, 2418, 2425, 2433, 2434, 2437, 2447, 2451, 2474, 2482, ++ 2486, 2492, 2493, 2494, 2497, 2503, 2507, 2509, 2510, 2519, ++ 2524, 2527, 2530, 2534, 2544, 2546, 2548, 2554, 2555, 2561, ++ 2563, 2565, 2575, 2579, 2602, 2610, 2613, 2616, 2620, 2622, ++ 2625, 2631, 2635, 2641, 2649, 2654, 2662, 2672, 2674, 2677, ++ 2689, 2691, 2693, 2703, 2707, 2730, 2738, 2741, 2748, 2749, ++ 2750, 2753, 2759, 2761, 2763, 2765, 2768, 2784, 2786, 2790, ++ 2800, 2801, 2817, 2818, 2821, 2831, 2835, 2858, 2866, 2869, ++ 2876, 2877, 2878, 2879, 2880, 2881, 2887, 2891, 2893, 2902, ++ 2903, 2908, 2911, 2914, 2918, 2928, 2929, 2930, 2946, 2947, ++ 2949, 2958, 2962, 2969, 2972, 2974, 2979, 2984, 2990, 3006, ++ 3008, 3009, 3014, 3018, 3021, 3024, 3031, 3046, 3056, 3059, ++ 3065, 3066, 3073, 3077, 3086, 3090, 3114, 3125, 3133, 3134, ++ 3137, 3142, 3146, 3157, 3160, 3168, 3170, 3174, 3192, 3199, ++ 3202, 3205, 3214, 3218, 3242, 3253, 3260, 3261, 3262, 3263, ++ 3264, 3270, 3271, 3274, 3276, 3285, 3294, 3296, 3298, 3302, ++ 3313, 3330, 3333, 3342, 3346, 3389, 3390, 3393, 3398, 3402, ++ 3405, 3406, 3415, 3424, 3426, 3430, 3440, 3449, 3450, 3458, ++ 3461, 3482, 3507, 3517, 3520, 3530, 3535, 3538, 3542, 3544, ++ 3570, 3572, 3585, 3633, 3634, 3636, 3647, 3648, 3654, 3655, ++ 3663, 3664, 3674, 3713, 3716, 3719, 3722, 3725, 3732, 3737, ++ 3745, 3749, 3751, 3754, 3757, 3761, 3762, 3764, 3771, 3773, ++ 3776, 3782, 3784, 3792, 3804, 3840, 3841, 3844, 3859, 3860, ++ 3861, 3864, 3866, 3872, 3882, 3892, 3893, 3894, 3895, 3896, ++ 3897, 3898, 3899, 3900, 3901, 3902, 3904, 3913, 3953, 3967, ++ 3968, 3973, 3974, 3976, 3981, 3993, 4030, 4038, 4039, 4046, ++ 4048, 4053, 4057, 4096, 4139, 4141, 4145, 4146, 4152, 4153, ++ 4155, 4157, 4159, 4160, 4170, 4176, 4182, 4184, 4186, 4190, ++ 4193, 4194, 4197, 4199, 4206, 4209, 4213, 4226, 4227, 4229, ++ 4231, 4237, 4238, 4239, 4240, 4250, 4253, 4254, 4256, 4295, ++ 4301, 4304, 4347, 4348, 4349, 4682, 4688, 4696, 4698, 4704, ++ 4746, 4752, 4786, 4792, 4800, 4802, 4808, 4824, 4882, 4888, ++ 4957, 4960, 4969, 4992, 5008, 5024, 5120, 5121, 5741, 5743, ++ 5760, 5761, 5787, 5788, 5792, 5867, 5870, 5888, 5902, 5906, ++ 5920, 5938, 5941, 5952, 5970, 5984, 5998, 6002, 6016, 6068, ++ 6070, 6071, 6078, 6086, 6087, 6089, 6100, 6103, 6104, 6107, ++ 6108, 6109, 6112, 6128, 6144, 6150, 6151, 6155, 6158, 6160, ++ 6176, 6211, 6212, 6272, 6313, 6314, 6320, 6400, 6432, 6435, ++ 6439, 6441, 6448, 6450, 6451, 6457, 6464, 6468, 6470, 6480, ++ 6512, 6528, 6576, 6593, 6600, 6608, 6618, 6622, 6656, 6679, ++ 6681, 6686, 6688, 6741, 6742, 6743, 6744, 6752, 6753, 6754, ++ 6755, 6757, 6765, 6771, 6783, 6784, 6800, 6816, 6823, 6824, ++ 6912, 6916, 6917, 6964, 6965, 6966, 6971, 6972, 6973, 6978, ++ 6979, 6981, 6992, 7002, 7009, 7019, 7028, 7040, 7042, 7043, ++ 7073, 7074, 7078, 7080, 7082, 7083, 7084, 7086, 7088, 7098, ++ 7142, 7143, 7144, 7146, 7149, 7150, 7151, 7154, 7164, 7168, ++ 7204, 7212, 7220, 7222, 7227, 7232, 7245, 7248, 7258, 7288, ++ 7294, 7360, 7376, 7379, 7380, 7393, 7394, 7401, 7405, 7406, ++ 7410, 7412, 7413, 7424, 7468, 7531, 7544, 7545, 7579, 7616, ++ 7676, 7680, 7830, 7838, 7936, 7944, 7952, 7960, 7968, 7976, ++ 7984, 7992, 8000, 8008, 8016, 8025, 8027, 8029, 8031, 8033, ++ 8040, 8048, 8064, 8072, 8080, 8088, 8096, 8104, 8112, 8118, ++ 8120, 8124, 8125, 8126, 8127, 8130, 8134, 8136, 8140, 8141, ++ 8144, 8150, 8152, 8157, 8160, 8168, 8173, 8178, 8182, 8184, ++ 8188, 8189, 8192, 8203, 8208, 8214, 8216, 8217, 8218, 8219, ++ 8221, 8222, 8223, 8224, 8232, 8233, 8234, 8239, 8240, 8249, ++ 8250, 8251, 8255, 8257, 8260, 8261, 8262, 8263, 8274, 8275, ++ 8276, 8277, 8287, 8288, 8298, 8304, 8305, 8308, 8314, 8317, ++ 8318, 8319, 8320, 8330, 8333, 8334, 8336, 8352, 8400, 8413, ++ 8417, 8418, 8421, 8448, 8450, 8451, 8455, 8456, 8458, 8459, ++ 8462, 8464, 8467, 8468, 8469, 8470, 8472, 8473, 8478, 8484, ++ 8485, 8486, 8487, 8488, 8489, 8490, 8494, 8495, 8496, 8500, ++ 8501, 8505, 8506, 8508, 8510, 8512, 8517, 8519, 8522, 8523, ++ 8524, 8526, 8527, 8528, 8544, 8579, 8581, 8585, 8592, 8597, ++ 8602, 8604, 8608, 8609, 8611, 8612, 8614, 8615, 8622, 8623, ++ 8654, 8656, 8658, 8659, 8660, 8661, 8692, 8960, 8968, 8972, ++ 8992, 8994, 9001, 9002, 9003, 9084, 9085, 9115, 9140, 9180, ++ 9186, 9216, 9280, 9312, 9372, 9450, 9472, 9655, 9656, 9665, ++ 9666, 9720, 9728, 9839, 9840, 9985, 10088, 10089, 10090, 10091, ++ 10092, 10093, 10094, 10095, 10096, 10097, 10098, 10099, 10100, 10101, ++ 10102, 10132, 10176, 10181, 10182, 10183, 10214, 10215, 10216, 10217, ++ 10218, 10219, 10220, 10221, 10222, 10223, 10224, 10240, 10496, 10627, ++ 10628, 10629, 10630, 10631, 10632, 10633, 10634, 10635, 10636, 10637, ++ 10638, 10639, 10640, 10641, 10642, 10643, 10644, 10645, 10646, 10647, ++ 10648, 10649, 10712, 10713, 10714, 10715, 10716, 10748, 10749, 10750, ++ 11008, 11056, 11077, 11079, 11088, 11264, 11312, 11360, 11363, 11365, ++ 11367, 11374, 11377, 11378, 11380, 11381, 11383, 11388, 11390, 11393, ++ 11394, 11492, 11493, 11499, 11503, 11506, 11513, 11517, 11518, 11520, ++ 11559, 11565, 11568, 11631, 11632, 11647, 11648, 11680, 11688, 11696, ++ 11704, 11712, 11720, 11728, 11736, 11744, 11776, 11778, 11779, 11780, ++ 11781, 11782, 11785, 11786, 11787, 11788, 11789, 11790, 11799, 11800, ++ 11802, 11803, 11804, 11805, 11806, 11808, 11809, 11810, 11811, 11812, ++ 11813, 11814, 11815, 11816, 11817, 11818, 11823, 11824, 11834, 11904, ++ 11931, 12032, 12272, 12288, 12289, 12292, 12293, 12294, 12295, 12296, ++ 12297, 12298, 12299, 12300, 12301, 12302, 12303, 12304, 12305, 12306, ++ 12308, 12309, 12310, 12311, 12312, 12313, 12314, 12315, 12316, 12317, ++ 12318, 12320, 12321, 12330, 12334, 12336, 12337, 12342, 12344, 12347, ++ 12348, 12349, 12350, 12353, 12441, 12443, 12445, 12447, 12448, 12449, ++ 12539, 12540, 12543, 12549, 12593, 12688, 12690, 12694, 12704, 12736, ++ 12784, 12800, 12832, 12842, 12872, 12880, 12881, 12896, 12928, 12938, ++ 12977, 12992, 13056, 13312, 19893, 19904, 19968, 40908, 40960, 40981, ++ 40982, 42128, 42192, 42232, 42238, 42240, 42508, 42509, 42512, 42528, ++ 42538, 42560, 42606, 42607, 42608, 42611, 42612, 42622, 42623, 42624, ++ 42655, 42656, 42726, 42736, 42738, 42752, 42775, 42784, 42786, 42800, ++ 42802, 42864, 42865, 42873, 42878, 42888, 42889, 42891, 42896, 42912, ++ 43000, 43002, 43003, 43010, 43011, 43014, 43015, 43019, 43020, 43043, ++ 43045, 43047, 43048, 43056, 43062, 43064, 43065, 43072, 43124, 43136, ++ 43138, 43188, 43204, 43214, 43216, 43232, 43250, 43256, 43259, 43264, ++ 43274, 43302, 43310, 43312, 43335, 43346, 43359, 43360, 43392, 43395, ++ 43396, 43443, 43444, 43446, 43450, 43452, 43453, 43457, 43471, 43472, ++ 43486, 43520, 43561, 43567, 43569, 43571, 43573, 43584, 43587, 43588, ++ 43596, 43597, 43600, 43612, 43616, 43632, 43633, 43639, 43642, 43643, ++ 43648, 43696, 43697, 43698, 43701, 43703, 43705, 43710, 43712, 43713, ++ 43714, 43739, 43741, 43742, 43744, 43755, 43756, 43758, 43760, 43762, ++ 43763, 43765, 43766, 43777, 43785, 43793, 43808, 43816, 43968, 44003, ++ 44005, 44006, 44008, 44009, 44011, 44012, 44013, 44016, 44032, 55203, ++ 55216, 55243, 55296, 56191, 56319, 57343, 57344, 63743, 63744, 64112, ++ 64256, 64275, 64285, 64286, 64287, 64297, 64298, 64312, 64318, 64320, ++ 64323, 64326, 64434, 64467, 64830, 64831, 64848, 64914, 65008, 65020, ++ 65021, 65024, 65040, 65047, 65048, 65049, 65056, 65072, 65073, 65075, ++ 65077, 65078, 65079, 65080, 65081, 65082, 65083, 65084, 65085, 65086, ++ 65087, 65088, 65089, 65090, 65091, 65092, 65093, 65095, 65096, 65097, ++ 65101, 65104, 65108, 65112, 65113, 65114, 65115, 65116, 65117, 65118, ++ 65119, 65122, 65123, 65124, 65128, 65129, 65130, 65136, 65142, 65279, ++ 65281, 65284, 65285, 65288, 65289, 65290, 65291, 65292, 65293, 65294, ++ 65296, 65306, 65308, 65311, 65313, 65339, 65340, 65341, 65342, 65343, ++ 65344, 65345, 65371, 65372, 65373, 65374, 65375, 65376, 65377, 65378, ++ 65379, 65380, 65382, 65392, 65393, 65438, 65440, 65474, 65482, 65490, ++ 65498, 65504, 65506, 65507, 65508, 65509, 65512, 65513, 65517, 65529, ++ 65532, 0, 13, 40, 60, 63, 80, 128, 256, 263, ++ 311, 320, 373, 377, 394, 400, 464, 509, 640, 672, ++ 768, 800, 816, 833, 834, 842, 896, 927, 928, 968, ++ 976, 977, 1024, 1064, 1104, 1184, 2048, 2056, 2058, 2103, ++ 2108, 2111, 2135, 2136, 2304, 2326, 2335, 2336, 2367, 2432, ++ 2494, 2560, 2561, 2565, 2572, 2576, 2581, 2585, 2616, 2623, ++ 2624, 2640, 2656, 2685, 2687, 2816, 2873, 2880, 2904, 2912, ++ 2936, 3072, 3680, 4096, 4097, 4098, 4099, 4152, 4167, 4178, ++ 4198, 4224, 4226, 4227, 4272, 4275, 4279, 4281, 4283, 4285, ++ 4286, 4304, 4336, 4352, 4355, 4391, 4396, 4397, 4406, 4416, ++ 4480, 4482, 4483, 4531, 4534, 4543, 4545, 4549, 4560, 5760, ++ 5803, 5804, 5805, 5806, 5808, 5814, 5815, 5824, 8192, 9216, ++ 9328, 12288, 26624, 28416, 28496, 28497, 28559, 28563, 45056, 53248, ++ 53504, 53545, 53605, 53607, 53610, 53613, 53619, 53627, 53635, 53637, ++ 53644, 53674, 53678, 53760, 53826, 53829, 54016, 54112, 54272, 54298, ++ 54324, 54350, 54358, 54376, 54402, 54428, 54430, 54434, 54437, 54441, ++ 54446, 54454, 54459, 54461, 54469, 54480, 54506, 54532, 54535, 54541, ++ 54550, 54558, 54584, 54587, 54592, 54598, 54602, 54610, 54636, 54662, ++ 54688, 54714, 54740, 54766, 54792, 54818, 54844, 54870, 54896, 54922, ++ 54952, 54977, 54978, 55003, 55004, 55010, 55035, 55036, 55061, 55062, ++ 55068, 55093, 55094, 55119, 55120, 55126, 55151, 55152, 55177, 55178, ++ 55184, 55209, 55210, 55235, 55236, 55242, 55246, 60928, 60933, 60961, ++ 60964, 60967, 60969, 60980, 60985, 60987, 60994, 60999, 61001, 61003, ++ 61005, 61009, 61012, 61015, 61017, 61019, 61021, 61023, 61025, 61028, ++ 61031, 61036, 61044, 61049, 61054, 61056, 61067, 61089, 61093, 61099, ++ 61168, 61440, 61488, 61600, 61617, 61633, 61649, 61696, 61712, 61744, ++ 61808, 61926, 61968, 62016, 62032, 62208, 62256, 62263, 62336, 62368, ++ 62406, 62432, 62464, 62528, 62530, 62713, 62720, 62784, 62800, 62971, ++ 63045, 63104, 63232, 0, 42710, 42752, 46900, 46912, 47133, 63488, ++ 1, 32, 256, 0, 65533, ++ }; ++static u16 aFts5UnicodeData[] = { ++ 1025, 61, 117, 55, 117, 54, 50, 53, 57, 53, ++ 49, 85, 333, 85, 121, 85, 841, 54, 53, 50, ++ 56, 48, 56, 837, 54, 57, 50, 57, 1057, 61, ++ 53, 151, 58, 53, 56, 58, 39, 52, 57, 34, ++ 58, 56, 58, 57, 79, 56, 37, 85, 56, 47, ++ 39, 51, 111, 53, 745, 57, 233, 773, 57, 261, ++ 1822, 37, 542, 37, 1534, 222, 69, 73, 37, 126, ++ 126, 73, 69, 137, 37, 73, 37, 105, 101, 73, ++ 37, 73, 37, 190, 158, 37, 126, 126, 73, 37, ++ 126, 94, 37, 39, 94, 69, 135, 41, 40, 37, ++ 41, 40, 37, 41, 40, 37, 542, 37, 606, 37, ++ 41, 40, 37, 126, 73, 37, 1886, 197, 73, 37, ++ 73, 69, 126, 105, 37, 286, 2181, 39, 869, 582, ++ 152, 390, 472, 166, 248, 38, 56, 38, 568, 3596, ++ 158, 38, 56, 94, 38, 101, 53, 88, 41, 53, ++ 105, 41, 73, 37, 553, 297, 1125, 94, 37, 105, ++ 101, 798, 133, 94, 57, 126, 94, 37, 1641, 1541, ++ 1118, 58, 172, 75, 1790, 478, 37, 2846, 1225, 38, ++ 213, 1253, 53, 49, 55, 1452, 49, 44, 53, 76, ++ 53, 76, 53, 44, 871, 103, 85, 162, 121, 85, ++ 55, 85, 90, 364, 53, 85, 1031, 38, 327, 684, ++ 333, 149, 71, 44, 3175, 53, 39, 236, 34, 58, ++ 204, 70, 76, 58, 140, 71, 333, 103, 90, 39, ++ 469, 34, 39, 44, 967, 876, 2855, 364, 39, 333, ++ 1063, 300, 70, 58, 117, 38, 711, 140, 38, 300, ++ 38, 108, 38, 172, 501, 807, 108, 53, 39, 359, ++ 876, 108, 42, 1735, 44, 42, 44, 39, 106, 268, ++ 138, 44, 74, 39, 236, 327, 76, 85, 333, 53, ++ 38, 199, 231, 44, 74, 263, 71, 711, 231, 39, ++ 135, 44, 39, 106, 140, 74, 74, 44, 39, 42, ++ 71, 103, 76, 333, 71, 87, 207, 58, 55, 76, ++ 42, 199, 71, 711, 231, 71, 71, 71, 44, 106, ++ 76, 76, 108, 44, 135, 39, 333, 76, 103, 44, ++ 76, 42, 295, 103, 711, 231, 71, 167, 44, 39, ++ 106, 172, 76, 42, 74, 44, 39, 71, 76, 333, ++ 53, 55, 44, 74, 263, 71, 711, 231, 71, 167, ++ 44, 39, 42, 44, 42, 140, 74, 74, 44, 44, ++ 42, 71, 103, 76, 333, 58, 39, 207, 44, 39, ++ 199, 103, 135, 71, 39, 71, 71, 103, 391, 74, ++ 44, 74, 106, 106, 44, 39, 42, 333, 111, 218, ++ 55, 58, 106, 263, 103, 743, 327, 167, 39, 108, ++ 138, 108, 140, 76, 71, 71, 76, 333, 239, 58, ++ 74, 263, 103, 743, 327, 167, 44, 39, 42, 44, ++ 170, 44, 74, 74, 76, 74, 39, 71, 76, 333, ++ 71, 74, 263, 103, 1319, 39, 106, 140, 106, 106, ++ 44, 39, 42, 71, 76, 333, 207, 58, 199, 74, ++ 583, 775, 295, 39, 231, 44, 106, 108, 44, 266, ++ 74, 53, 1543, 44, 71, 236, 55, 199, 38, 268, ++ 53, 333, 85, 71, 39, 71, 39, 39, 135, 231, ++ 103, 39, 39, 71, 135, 44, 71, 204, 76, 39, ++ 167, 38, 204, 333, 135, 39, 122, 501, 58, 53, ++ 122, 76, 218, 333, 335, 58, 44, 58, 44, 58, ++ 44, 54, 50, 54, 50, 74, 263, 1159, 460, 42, ++ 172, 53, 76, 167, 364, 1164, 282, 44, 218, 90, ++ 181, 154, 85, 1383, 74, 140, 42, 204, 42, 76, ++ 74, 76, 39, 333, 213, 199, 74, 76, 135, 108, ++ 39, 106, 71, 234, 103, 140, 423, 44, 74, 76, ++ 202, 44, 39, 42, 333, 106, 44, 90, 1225, 41, ++ 41, 1383, 53, 38, 10631, 135, 231, 39, 135, 1319, ++ 135, 1063, 135, 231, 39, 135, 487, 1831, 135, 2151, ++ 108, 309, 655, 519, 346, 2727, 49, 19847, 85, 551, ++ 61, 839, 54, 50, 2407, 117, 110, 423, 135, 108, ++ 583, 108, 85, 583, 76, 423, 103, 76, 1671, 76, ++ 42, 236, 266, 44, 74, 364, 117, 38, 117, 55, ++ 39, 44, 333, 335, 213, 49, 149, 108, 61, 333, ++ 1127, 38, 1671, 1319, 44, 39, 2247, 935, 108, 138, ++ 76, 106, 74, 44, 202, 108, 58, 85, 333, 967, ++ 167, 1415, 554, 231, 74, 333, 47, 1114, 743, 76, ++ 106, 85, 1703, 42, 44, 42, 236, 44, 42, 44, ++ 74, 268, 202, 332, 44, 333, 333, 245, 38, 213, ++ 140, 42, 1511, 44, 42, 172, 42, 44, 170, 44, ++ 74, 231, 333, 245, 346, 300, 314, 76, 42, 967, ++ 42, 140, 74, 76, 42, 44, 74, 71, 333, 1415, ++ 44, 42, 76, 106, 44, 42, 108, 74, 149, 1159, ++ 266, 268, 74, 76, 181, 333, 103, 333, 967, 198, ++ 85, 277, 108, 53, 428, 42, 236, 135, 44, 135, ++ 74, 44, 71, 1413, 2022, 421, 38, 1093, 1190, 1260, ++ 140, 4830, 261, 3166, 261, 265, 197, 201, 261, 265, ++ 261, 265, 197, 201, 261, 41, 41, 41, 94, 229, ++ 265, 453, 261, 264, 261, 264, 261, 264, 165, 69, ++ 137, 40, 56, 37, 120, 101, 69, 137, 40, 120, ++ 133, 69, 137, 120, 261, 169, 120, 101, 69, 137, ++ 40, 88, 381, 162, 209, 85, 52, 51, 54, 84, ++ 51, 54, 52, 277, 59, 60, 162, 61, 309, 52, ++ 51, 149, 80, 117, 57, 54, 50, 373, 57, 53, ++ 48, 341, 61, 162, 194, 47, 38, 207, 121, 54, ++ 50, 38, 335, 121, 54, 50, 422, 855, 428, 139, ++ 44, 107, 396, 90, 41, 154, 41, 90, 37, 105, ++ 69, 105, 37, 58, 41, 90, 57, 169, 218, 41, ++ 58, 41, 58, 41, 58, 137, 58, 37, 137, 37, ++ 135, 37, 90, 69, 73, 185, 94, 101, 58, 57, ++ 90, 37, 58, 527, 1134, 94, 142, 47, 185, 186, ++ 89, 154, 57, 90, 57, 90, 57, 250, 57, 1018, ++ 89, 90, 57, 58, 57, 1018, 8601, 282, 153, 666, ++ 89, 250, 54, 50, 2618, 57, 986, 825, 1306, 217, ++ 602, 1274, 378, 1935, 2522, 719, 5882, 57, 314, 57, ++ 1754, 281, 3578, 57, 4634, 3322, 54, 50, 54, 50, ++ 54, 50, 54, 50, 54, 50, 54, 50, 54, 50, ++ 975, 1434, 185, 54, 50, 1017, 54, 50, 54, 50, ++ 54, 50, 54, 50, 54, 50, 537, 8218, 4217, 54, ++ 50, 54, 50, 54, 50, 54, 50, 54, 50, 54, ++ 50, 54, 50, 54, 50, 54, 50, 54, 50, 54, ++ 50, 2041, 54, 50, 54, 50, 1049, 54, 50, 8281, ++ 1562, 697, 90, 217, 346, 1513, 1509, 126, 73, 69, ++ 254, 105, 37, 94, 37, 94, 165, 70, 105, 37, ++ 3166, 37, 218, 158, 108, 94, 149, 47, 85, 1221, ++ 37, 37, 1799, 38, 53, 44, 743, 231, 231, 231, ++ 231, 231, 231, 231, 231, 1036, 85, 52, 51, 52, ++ 51, 117, 52, 51, 53, 52, 51, 309, 49, 85, ++ 49, 53, 52, 51, 85, 52, 51, 54, 50, 54, ++ 50, 54, 50, 54, 50, 181, 38, 341, 81, 858, ++ 2874, 6874, 410, 61, 117, 58, 38, 39, 46, 54, ++ 50, 54, 50, 54, 50, 54, 50, 54, 50, 90, ++ 54, 50, 54, 50, 54, 50, 54, 50, 49, 54, ++ 82, 58, 302, 140, 74, 49, 166, 90, 110, 38, ++ 39, 53, 90, 2759, 76, 88, 70, 39, 49, 2887, ++ 53, 102, 39, 1319, 3015, 90, 143, 346, 871, 1178, ++ 519, 1018, 335, 986, 271, 58, 495, 1050, 335, 1274, ++ 495, 2042, 8218, 39, 39, 2074, 39, 39, 679, 38, ++ 36583, 1786, 1287, 198, 85, 8583, 38, 117, 519, 333, ++ 71, 1502, 39, 44, 107, 53, 332, 53, 38, 798, ++ 44, 2247, 334, 76, 213, 760, 294, 88, 478, 69, ++ 2014, 38, 261, 190, 350, 38, 88, 158, 158, 382, ++ 70, 37, 231, 44, 103, 44, 135, 44, 743, 74, ++ 76, 42, 154, 207, 90, 55, 58, 1671, 149, 74, ++ 1607, 522, 44, 85, 333, 588, 199, 117, 39, 333, ++ 903, 268, 85, 743, 364, 74, 53, 935, 108, 42, ++ 1511, 44, 74, 140, 74, 44, 138, 437, 38, 333, ++ 85, 1319, 204, 74, 76, 74, 76, 103, 44, 263, ++ 44, 42, 333, 149, 519, 38, 199, 122, 39, 42, ++ 1543, 44, 39, 108, 71, 76, 167, 76, 39, 44, ++ 39, 71, 38, 85, 359, 42, 76, 74, 85, 39, ++ 70, 42, 44, 199, 199, 199, 231, 231, 1127, 74, ++ 44, 74, 44, 74, 53, 42, 44, 333, 39, 39, ++ 743, 1575, 36, 68, 68, 36, 63, 63, 11719, 3399, ++ 229, 165, 39, 44, 327, 57, 423, 167, 39, 71, ++ 71, 3463, 536, 11623, 54, 50, 2055, 1735, 391, 55, ++ 58, 524, 245, 54, 50, 53, 236, 53, 81, 80, ++ 54, 50, 54, 50, 54, 50, 54, 50, 54, 50, ++ 54, 50, 54, 50, 54, 50, 85, 54, 50, 149, ++ 112, 117, 149, 49, 54, 50, 54, 50, 54, 50, ++ 117, 57, 49, 121, 53, 55, 85, 167, 4327, 34, ++ 117, 55, 117, 54, 50, 53, 57, 53, 49, 85, ++ 333, 85, 121, 85, 841, 54, 53, 50, 56, 48, ++ 56, 837, 54, 57, 50, 57, 54, 50, 53, 54, ++ 50, 85, 327, 38, 1447, 70, 999, 199, 199, 199, ++ 103, 87, 57, 56, 58, 87, 58, 153, 90, 98, ++ 90, 391, 839, 615, 71, 487, 455, 3943, 117, 1455, ++ 314, 1710, 143, 570, 47, 410, 1466, 44, 935, 1575, ++ 999, 143, 551, 46, 263, 46, 967, 53, 1159, 263, ++ 53, 174, 1289, 1285, 2503, 333, 199, 39, 1415, 71, ++ 39, 743, 53, 271, 711, 207, 53, 839, 53, 1799, ++ 71, 39, 108, 76, 140, 135, 103, 871, 108, 44, ++ 271, 309, 935, 79, 53, 1735, 245, 711, 271, 615, ++ 271, 2343, 1007, 42, 44, 42, 1703, 492, 245, 655, ++ 333, 76, 42, 1447, 106, 140, 74, 76, 85, 34, ++ 149, 807, 333, 108, 1159, 172, 42, 268, 333, 149, ++ 76, 42, 1543, 106, 300, 74, 135, 149, 333, 1383, ++ 44, 42, 44, 74, 204, 42, 44, 333, 28135, 3182, ++ 149, 34279, 18215, 2215, 39, 1482, 140, 422, 71, 7898, ++ 1274, 1946, 74, 108, 122, 202, 258, 268, 90, 236, ++ 986, 140, 1562, 2138, 108, 58, 2810, 591, 841, 837, ++ 841, 229, 581, 841, 837, 41, 73, 41, 73, 137, ++ 265, 133, 37, 229, 357, 841, 837, 73, 137, 265, ++ 233, 837, 73, 137, 169, 41, 233, 837, 841, 837, ++ 841, 837, 841, 837, 841, 837, 841, 837, 841, 901, ++ 809, 57, 805, 57, 197, 809, 57, 805, 57, 197, ++ 809, 57, 805, 57, 197, 809, 57, 805, 57, 197, ++ 809, 57, 805, 57, 197, 94, 1613, 135, 871, 71, ++ 39, 39, 327, 135, 39, 39, 39, 39, 39, 39, ++ 103, 71, 39, 39, 39, 39, 39, 39, 71, 39, ++ 135, 231, 135, 135, 39, 327, 551, 103, 167, 551, ++ 89, 1434, 3226, 506, 474, 506, 506, 367, 1018, 1946, ++ 1402, 954, 1402, 314, 90, 1082, 218, 2266, 666, 1210, ++ 186, 570, 2042, 58, 5850, 154, 2010, 154, 794, 2266, ++ 378, 2266, 3738, 39, 39, 39, 39, 39, 39, 17351, ++ 34, 3074, 7692, 63, 63, ++ }; ++ ++static int sqlite3Fts5UnicodeCategory(int iCode) { ++ int iRes = -1; ++ int iHi; ++ int iLo; ++ int ret; ++ u16 iKey; ++ ++ if( iCode>=(1<<20) ){ ++ return 0; ++ } ++ iLo = aFts5UnicodeBlock[(iCode>>16)]; ++ iHi = aFts5UnicodeBlock[1+(iCode>>16)]; ++ iKey = (iCode & 0xFFFF); ++ while( iHi>iLo ){ ++ int iTest = (iHi + iLo) / 2; ++ assert( iTest>=iLo && iTest<iHi ); ++ if( iKey>=aFts5UnicodeMap[iTest] ){ ++ iRes = iTest; ++ iLo = iTest+1; ++ }else{ ++ iHi = iTest; ++ } ++ } ++ ++ if( iRes<0 ) return 0; ++ if( iKey>=(aFts5UnicodeMap[iRes]+(aFts5UnicodeData[iRes]>>5)) ) return 0; ++ ret = aFts5UnicodeData[iRes] & 0x1F; ++ if( ret!=30 ) return ret; ++ return ((iKey - aFts5UnicodeMap[iRes]) & 0x01) ? 5 : 9; ++} ++ ++static void sqlite3Fts5UnicodeAscii(u8 *aArray, u8 *aAscii){ ++ int i = 0; ++ int iTbl = 0; ++ while( i<128 ){ ++ int bToken = aArray[ aFts5UnicodeData[iTbl] & 0x1F ]; ++ int n = (aFts5UnicodeData[iTbl] >> 5) + i; ++ for(; i<128 && i<n; i++){ ++ aAscii[i] = (u8)bToken; ++ } ++ iTbl++; ++ } ++} ++ ++ + /* + ** 2015 May 30 + ** +@@ -203503,6 +219482,11 @@ + ** the number of fts5 rows that contain at least one instance of term + ** $term. Field $cnt is set to the total number of instances of term + ** $term in the database. ++** ++** instance: ++** CREATE TABLE vocab(term, doc, col, offset, PRIMARY KEY(<all-fields>)); ++** ++** One row for each term instance in the database. + */ + + +@@ -203518,7 +219502,7 @@ + char *zFts5Db; /* Db containing fts5 table */ + sqlite3 *db; /* Database handle */ + Fts5Global *pGlobal; /* FTS5 global object for this database */ +- int eType; /* FTS5_VOCAB_COL or ROW */ ++ int eType; /* FTS5_VOCAB_COL, ROW or INSTANCE */ + }; + + struct Fts5VocabCursor { +@@ -203538,16 +219522,22 @@ + i64 *aCnt; + i64 *aDoc; + +- /* Output values used by 'row' and 'col' tables */ ++ /* Output values used by all tables. */ + i64 rowid; /* This table's current rowid value */ + Fts5Buffer term; /* Current value of 'term' column */ ++ ++ /* Output values Used by 'instance' tables only */ ++ i64 iInstPos; ++ int iInstOff; + }; + +-#define FTS5_VOCAB_COL 0 +-#define FTS5_VOCAB_ROW 1 ++#define FTS5_VOCAB_COL 0 ++#define FTS5_VOCAB_ROW 1 ++#define FTS5_VOCAB_INSTANCE 2 + + #define FTS5_VOCAB_COL_SCHEMA "term, col, doc, cnt" + #define FTS5_VOCAB_ROW_SCHEMA "term, doc, cnt" ++#define FTS5_VOCAB_INST_SCHEMA "term, doc, col, offset" + + /* + ** Bits for the mask used as the idxNum value by xBestIndex/xFilter. +@@ -203575,6 +219565,9 @@ + if( sqlite3_stricmp(zCopy, "row")==0 ){ + *peType = FTS5_VOCAB_ROW; + }else ++ if( sqlite3_stricmp(zCopy, "instance")==0 ){ ++ *peType = FTS5_VOCAB_INSTANCE; ++ }else + { + *pzErr = sqlite3_mprintf("fts5vocab: unknown table type: %Q", zCopy); + rc = SQLITE_ERROR; +@@ -203635,7 +219628,8 @@ + ){ + const char *azSchema[] = { + "CREATE TABlE vocab(" FTS5_VOCAB_COL_SCHEMA ")", +- "CREATE TABlE vocab(" FTS5_VOCAB_ROW_SCHEMA ")" ++ "CREATE TABlE vocab(" FTS5_VOCAB_ROW_SCHEMA ")", ++ "CREATE TABlE vocab(" FTS5_VOCAB_INST_SCHEMA ")" + }; + + Fts5VocabTable *pRet = 0; +@@ -203709,6 +219703,15 @@ + + /* + ** Implementation of the xBestIndex method. ++** ++** Only constraints of the form: ++** ++** term <= ? ++** term == ? ++** term >= ? ++** ++** are interpreted. Less-than and less-than-or-equal are treated ++** identically, as are greater-than and greater-than-or-equal. + */ + static int fts5VocabBestIndexMethod( + sqlite3_vtab *pUnused, +@@ -203852,7 +219855,57 @@ + return SQLITE_OK; + } + ++static int fts5VocabInstanceNewTerm(Fts5VocabCursor *pCsr){ ++ int rc = SQLITE_OK; ++ ++ if( sqlite3Fts5IterEof(pCsr->pIter) ){ ++ pCsr->bEof = 1; ++ }else{ ++ const char *zTerm; ++ int nTerm; ++ zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm); ++ if( pCsr->nLeTerm>=0 ){ ++ int nCmp = MIN(nTerm, pCsr->nLeTerm); ++ int bCmp = memcmp(pCsr->zLeTerm, zTerm, nCmp); ++ if( bCmp<0 || (bCmp==0 && pCsr->nLeTerm<nTerm) ){ ++ pCsr->bEof = 1; ++ } ++ } + ++ sqlite3Fts5BufferSet(&rc, &pCsr->term, nTerm, (const u8*)zTerm); ++ } ++ return rc; ++} ++ ++static int fts5VocabInstanceNext(Fts5VocabCursor *pCsr){ ++ int eDetail = pCsr->pConfig->eDetail; ++ int rc = SQLITE_OK; ++ Fts5IndexIter *pIter = pCsr->pIter; ++ i64 *pp = &pCsr->iInstPos; ++ int *po = &pCsr->iInstOff; ++ ++ assert( sqlite3Fts5IterEof(pIter)==0 ); ++ assert( pCsr->bEof==0 ); ++ while( eDetail==FTS5_DETAIL_NONE ++ || sqlite3Fts5PoslistNext64(pIter->pData, pIter->nData, po, pp) ++ ){ ++ pCsr->iInstPos = 0; ++ pCsr->iInstOff = 0; ++ ++ rc = sqlite3Fts5IterNextScan(pCsr->pIter); ++ if( rc==SQLITE_OK ){ ++ rc = fts5VocabInstanceNewTerm(pCsr); ++ if( pCsr->bEof || eDetail==FTS5_DETAIL_NONE ) break; ++ } ++ if( rc ){ ++ pCsr->bEof = 1; ++ break; ++ } ++ } ++ ++ return rc; ++} ++ + /* + ** Advance the cursor to the next row in the table. + */ +@@ -203864,6 +219917,10 @@ + + pCsr->rowid++; + ++ if( pTab->eType==FTS5_VOCAB_INSTANCE ){ ++ return fts5VocabInstanceNext(pCsr); ++ } ++ + if( pTab->eType==FTS5_VOCAB_COL ){ + for(pCsr->iCol++; pCsr->iCol<nCol; pCsr->iCol++){ + if( pCsr->aDoc[pCsr->iCol] ) break; +@@ -203870,7 +219927,7 @@ + } + } + +- if( pTab->eType==FTS5_VOCAB_ROW || pCsr->iCol>=nCol ){ ++ if( pTab->eType!=FTS5_VOCAB_COL || pCsr->iCol>=nCol ){ + if( sqlite3Fts5IterEof(pCsr->pIter) ){ + pCsr->bEof = 1; + }else{ +@@ -203894,6 +219951,7 @@ + + assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW ); + while( rc==SQLITE_OK ){ ++ int eDetail = pCsr->pConfig->eDetail; + const u8 *pPos; int nPos; /* Position list */ + i64 iPos = 0; /* 64-bit position read from poslist */ + int iOff = 0; /* Current offset within position list */ +@@ -203900,16 +219958,19 @@ + + pPos = pCsr->pIter->pData; + nPos = pCsr->pIter->nData; +- switch( pCsr->pConfig->eDetail ){ +- case FTS5_DETAIL_FULL: +- pPos = pCsr->pIter->pData; +- nPos = pCsr->pIter->nData; +- if( pTab->eType==FTS5_VOCAB_ROW ){ ++ ++ switch( pTab->eType ){ ++ case FTS5_VOCAB_ROW: ++ if( eDetail==FTS5_DETAIL_FULL ){ + while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ + pCsr->aCnt[0]++; + } +- pCsr->aDoc[0]++; +- }else{ ++ } ++ pCsr->aDoc[0]++; ++ break; ++ ++ case FTS5_VOCAB_COL: ++ if( eDetail==FTS5_DETAIL_FULL ){ + int iCol = -1; + while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ + int ii = FTS5_POS2COLUMN(iPos); +@@ -203923,13 +219984,7 @@ + iCol = ii; + } + } +- } +- break; +- +- case FTS5_DETAIL_COLUMNS: +- if( pTab->eType==FTS5_VOCAB_ROW ){ +- pCsr->aDoc[0]++; +- }else{ ++ }else if( eDetail==FTS5_DETAIL_COLUMNS ){ + while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff,&iPos) ){ + assert_nc( iPos>=0 && iPos<nCol ); + if( iPos>=nCol ){ +@@ -203938,12 +219993,14 @@ + } + pCsr->aDoc[iPos]++; + } ++ }else{ ++ assert( eDetail==FTS5_DETAIL_NONE ); ++ pCsr->aDoc[0]++; + } + break; + +- default: +- assert( pCsr->pConfig->eDetail==FTS5_DETAIL_NONE ); +- pCsr->aDoc[0]++; ++ default: ++ assert( pTab->eType==FTS5_VOCAB_INSTANCE ); + break; + } + +@@ -203950,6 +220007,7 @@ + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5IterNextScan(pCsr->pIter); + } ++ if( pTab->eType==FTS5_VOCAB_INSTANCE ) break; + + if( rc==SQLITE_OK ){ + zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm); +@@ -203979,7 +220037,9 @@ + int nUnused, /* Number of elements in apVal */ + sqlite3_value **apVal /* Arguments for the indexing scheme */ + ){ ++ Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab; + Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; ++ int eType = pTab->eType; + int rc = SQLITE_OK; + + int iVal = 0; +@@ -204019,11 +220079,16 @@ + } + } + +- + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5IndexQuery(pCsr->pIndex, zTerm, nTerm, f, 0, &pCsr->pIter); + } +- if( rc==SQLITE_OK ){ ++ if( rc==SQLITE_OK && eType==FTS5_VOCAB_INSTANCE ){ ++ rc = fts5VocabInstanceNewTerm(pCsr); ++ } ++ if( rc==SQLITE_OK ++ && !pCsr->bEof ++ && (eType!=FTS5_VOCAB_INSTANCE || pCsr->pConfig->eDetail!=FTS5_DETAIL_NONE) ++ ){ + rc = fts5VocabNextMethod(pCursor); + } + +@@ -204065,7 +220130,7 @@ + }else{ + iVal = pCsr->aCnt[pCsr->iCol]; + } +- }else{ ++ }else if( eType==FTS5_VOCAB_ROW ){ + assert( iCol==1 || iCol==2 ); + if( iCol==1 ){ + iVal = pCsr->aDoc[0]; +@@ -204072,6 +220137,34 @@ + }else{ + iVal = pCsr->aCnt[0]; + } ++ }else{ ++ assert( eType==FTS5_VOCAB_INSTANCE ); ++ switch( iCol ){ ++ case 1: ++ sqlite3_result_int64(pCtx, pCsr->pIter->iRowid); ++ break; ++ case 2: { ++ int ii = -1; ++ if( eDetail==FTS5_DETAIL_FULL ){ ++ ii = FTS5_POS2COLUMN(pCsr->iInstPos); ++ }else if( eDetail==FTS5_DETAIL_COLUMNS ){ ++ ii = (int)pCsr->iInstPos; ++ } ++ if( ii>=0 && ii<pCsr->pConfig->nCol ){ ++ const char *z = pCsr->pConfig->azCol[ii]; ++ sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC); ++ } ++ break; ++ } ++ default: { ++ assert( iCol==3 ); ++ if( eDetail==FTS5_DETAIL_FULL ){ ++ int ii = FTS5_POS2OFFSET(pCsr->iInstPos); ++ sqlite3_result_int(pCtx, ii); ++ } ++ break; ++ } ++ } + } + + if( iVal>0 ) sqlite3_result_int64(pCtx, iVal); +@@ -204117,6 +220210,7 @@ + /* xSavepoint */ 0, + /* xRelease */ 0, + /* xRollbackTo */ 0, ++ /* xShadowName */ 0 + }; + void *p = (void*)pGlobal; + +@@ -204124,8 +220218,6 @@ + } + + +- +- + + #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5) */ + +@@ -204399,6 +220491,7 @@ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ ++ 0, /* xShadowName */ + }; + + #endif /* SQLITE_OMIT_VIRTUALTABLE */ +@@ -204431,3 +220524,10 @@ + #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ + + /************** End of stmt.c ************************************************/ ++#if __LINE__!=220527 ++#undef SQLITE_SOURCE_ID ++#define SQLITE_SOURCE_ID "2018-12-01 12:34:55 bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238alt2" ++#endif ++/* Return the source-id for this library */ ++SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } ++/************************** End of sqlite3.c ******************************/ +--- contrib/sqlite3/sqlite3.h.orig ++++ contrib/sqlite3/sqlite3.h +@@ -115,15 +115,17 @@ + ** a string which identifies a particular check-in of SQLite + ** within its configuration management system. ^The SQLITE_SOURCE_ID + ** string contains the date and time of the check-in (UTC) and a SHA1 +-** or SHA3-256 hash of the entire source tree. ++** or SHA3-256 hash of the entire source tree. If the source code has ++** been edited in any way since it was last checked in, then the last ++** four hexadecimal digits of the hash may be modified. + ** + ** See also: [sqlite3_libversion()], + ** [sqlite3_libversion_number()], [sqlite3_sourceid()], + ** [sqlite_version()] and [sqlite_source_id()]. + */ +-#define SQLITE_VERSION "3.20.0" +-#define SQLITE_VERSION_NUMBER 3020000 +-#define SQLITE_SOURCE_ID "2017-08-01 13:24:15 9501e22dfeebdcefa783575e47c60b514d7c2e0cad73b2a496c0bc4b680900a8" ++#define SQLITE_VERSION "3.26.0" ++#define SQLITE_VERSION_NUMBER 3026000 ++#define SQLITE_SOURCE_ID "2018-12-01 12:34:55 bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238b4f9" + + /* + ** CAPI3REF: Run-Time Library Version Numbers +@@ -139,7 +141,7 @@ + ** + ** <blockquote><pre> + ** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER ); +-** assert( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)==0 ); ++** assert( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,80)==0 ); + ** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 ); + ** </pre></blockquote>)^ + ** +@@ -149,9 +151,11 @@ + ** function is provided for use in DLLs since DLL users usually do not have + ** direct access to string constants within the DLL. ^The + ** sqlite3_libversion_number() function returns an integer equal to +-** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns ++** [SQLITE_VERSION_NUMBER]. ^(The sqlite3_sourceid() function returns + ** a pointer to a string constant whose value is the same as the +-** [SQLITE_SOURCE_ID] C preprocessor macro. ++** [SQLITE_SOURCE_ID] C preprocessor macro. Except if SQLite is built ++** using an edited copy of [the amalgamation], then the last four characters ++** of the hash might be different from [SQLITE_SOURCE_ID].)^ + ** + ** See also: [sqlite_version()] and [sqlite_source_id()]. + */ +@@ -432,7 +436,7 @@ + #define SQLITE_FULL 13 /* Insertion failed because database is full */ + #define SQLITE_CANTOPEN 14 /* Unable to open the database file */ + #define SQLITE_PROTOCOL 15 /* Database lock protocol error */ +-#define SQLITE_EMPTY 16 /* Not used */ ++#define SQLITE_EMPTY 16 /* Internal use only */ + #define SQLITE_SCHEMA 17 /* The database schema changed */ + #define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ + #define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ +@@ -466,6 +470,9 @@ + ** the most recent error can be obtained using + ** [sqlite3_extended_errcode()]. + */ ++#define SQLITE_ERROR_MISSING_COLLSEQ (SQLITE_ERROR | (1<<8)) ++#define SQLITE_ERROR_RETRY (SQLITE_ERROR | (2<<8)) ++#define SQLITE_ERROR_SNAPSHOT (SQLITE_ERROR | (3<<8)) + #define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) + #define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) + #define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) +@@ -494,7 +501,11 @@ + #define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8)) + #define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8)) + #define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28<<8)) ++#define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8)) ++#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8)) ++#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8)) + #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) ++#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) + #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) + #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) + #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) +@@ -501,11 +512,15 @@ + #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) + #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) + #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) ++#define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */ + #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) ++#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8)) + #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) + #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) + #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) + #define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8)) ++#define SQLITE_READONLY_CANTINIT (SQLITE_READONLY | (5<<8)) ++#define SQLITE_READONLY_DIRECTORY (SQLITE_READONLY | (6<<8)) + #define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) + #define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8)) + #define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8)) +@@ -580,6 +595,11 @@ + ** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on + ** read-only media and cannot be changed even by processes with + ** elevated privileges. ++** ++** The SQLITE_IOCAP_BATCH_ATOMIC property means that the underlying ++** filesystem supports doing multiple write operations atomically when those ++** write operations are bracketed by [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] and ++** [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]. + */ + #define SQLITE_IOCAP_ATOMIC 0x00000001 + #define SQLITE_IOCAP_ATOMIC512 0x00000002 +@@ -595,6 +615,7 @@ + #define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800 + #define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000 + #define SQLITE_IOCAP_IMMUTABLE 0x00002000 ++#define SQLITE_IOCAP_BATCH_ATOMIC 0x00004000 + + /* + ** CAPI3REF: File Locking Levels +@@ -729,6 +750,7 @@ + ** <li> [SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN] + ** <li> [SQLITE_IOCAP_POWERSAFE_OVERWRITE] + ** <li> [SQLITE_IOCAP_IMMUTABLE] ++** <li> [SQLITE_IOCAP_BATCH_ATOMIC] + ** </ul> + ** + ** The SQLITE_IOCAP_ATOMIC property means that all writes of +@@ -866,7 +888,8 @@ + ** <li>[[SQLITE_FCNTL_PERSIST_WAL]] + ** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the + ** persistent [WAL | Write Ahead Log] setting. By default, the auxiliary +-** write ahead log and shared memory files used for transaction control ++** write ahead log ([WAL file]) and shared memory ++** files used for transaction control + ** are automatically deleted when the latest connection to the database + ** closes. Setting persistent WAL mode causes those files to persist after + ** close. Persisting the files is useful when other processes that do not +@@ -1012,6 +1035,66 @@ + ** The [SQLITE_FCNTL_RBU] opcode is implemented by the special VFS used by + ** the RBU extension only. All other VFS should return SQLITE_NOTFOUND for + ** this opcode. ++** ++** <li>[[SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]] ++** If the [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] opcode returns SQLITE_OK, then ++** the file descriptor is placed in "batch write mode", which ++** means all subsequent write operations will be deferred and done ++** atomically at the next [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]. Systems ++** that do not support batch atomic writes will return SQLITE_NOTFOUND. ++** ^Following a successful SQLITE_FCNTL_BEGIN_ATOMIC_WRITE and prior to ++** the closing [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] or ++** [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE], SQLite will make ++** no VFS interface calls on the same [sqlite3_file] file descriptor ++** except for calls to the xWrite method and the xFileControl method ++** with [SQLITE_FCNTL_SIZE_HINT]. ++** ++** <li>[[SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]] ++** The [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] opcode causes all write ++** operations since the previous successful call to ++** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be performed atomically. ++** This file control returns [SQLITE_OK] if and only if the writes were ++** all performed successfully and have been committed to persistent storage. ++** ^Regardless of whether or not it is successful, this file control takes ++** the file descriptor out of batch write mode so that all subsequent ++** write operations are independent. ++** ^SQLite will never invoke SQLITE_FCNTL_COMMIT_ATOMIC_WRITE without ++** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]. ++** ++** <li>[[SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE]] ++** The [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE] opcode causes all write ++** operations since the previous successful call to ++** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be rolled back. ++** ^This file control takes the file descriptor out of batch write mode ++** so that all subsequent write operations are independent. ++** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without ++** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]. ++** ++** <li>[[SQLITE_FCNTL_LOCK_TIMEOUT]] ++** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode causes attempts to obtain ++** a file lock using the xLock or xShmLock methods of the VFS to wait ++** for up to M milliseconds before failing, where M is the single ++** unsigned integer parameter. ++** ++** <li>[[SQLITE_FCNTL_DATA_VERSION]] ++** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to ++** a database file. The argument is a pointer to a 32-bit unsigned integer. ++** The "data version" for the pager is written into the pointer. The ++** "data version" changes whenever any change occurs to the corresponding ++** database file, either through SQL statements on the same database ++** connection or through transactions committed by separate database ++** connections possibly in other processes. The [sqlite3_total_changes()] ++** interface can be used to find if any database on the connection has changed, ++** but that interface responds to changes on TEMP as well as MAIN and does ++** not provide a mechanism to detect changes to MAIN only. Also, the ++** [sqlite3_total_changes()] interface responds to internal changes only and ++** omits changes made by other database connections. The ++** [PRAGMA data_version] command provide a mechanism to detect changes to ++** a single attached database that occur due to other database connections, ++** but omits changes implemented by the database connection on which it is ++** called. This file control is the only mechanism to detect changes that ++** happen either internally or externally and that are associated with ++** a particular attached database. + ** </ul> + */ + #define SQLITE_FCNTL_LOCKSTATE 1 +@@ -1043,6 +1126,11 @@ + #define SQLITE_FCNTL_JOURNAL_POINTER 28 + #define SQLITE_FCNTL_WIN32_GET_HANDLE 29 + #define SQLITE_FCNTL_PDB 30 ++#define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE 31 ++#define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32 ++#define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33 ++#define SQLITE_FCNTL_LOCK_TIMEOUT 34 ++#define SQLITE_FCNTL_DATA_VERSION 35 + + /* deprecated names */ + #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE +@@ -1080,12 +1168,18 @@ + ** in the name of the object stands for "virtual file system". See + ** the [VFS | VFS documentation] for further information. + ** +-** The value of the iVersion field is initially 1 but may be larger in +-** future versions of SQLite. Additional fields may be appended to this +-** object when the iVersion value is increased. Note that the structure +-** of the sqlite3_vfs object changes in the transaction between +-** SQLite version 3.5.9 and 3.6.0 and yet the iVersion field was not +-** modified. ++** The VFS interface is sometimes extended by adding new methods onto ++** the end. Each time such an extension occurs, the iVersion field ++** is incremented. The iVersion value started out as 1 in ++** SQLite [version 3.5.0] on [dateof:3.5.0], then increased to 2 ++** with SQLite [version 3.7.0] on [dateof:3.7.0], and then increased ++** to 3 with SQLite [version 3.7.6] on [dateof:3.7.6]. Additional fields ++** may be appended to the sqlite3_vfs object and the iVersion value ++** may increase again in future versions of SQLite. ++** Note that the structure ++** of the sqlite3_vfs object changes in the transition from ++** SQLite [version 3.5.9] to [version 3.6.0] on [dateof:3.6.0] ++** and yet the iVersion field was not modified. + ** + ** The szOsFile field is the size of the subclassed [sqlite3_file] + ** structure used by this VFS. mxPathname is the maximum length of +@@ -1613,6 +1707,16 @@ + ** routines with a wrapper that simulations memory allocation failure or + ** tracks memory usage, for example. </dd> + ** ++** [[SQLITE_CONFIG_SMALL_MALLOC]] <dt>SQLITE_CONFIG_SMALL_MALLOC</dt> ++** <dd> ^The SQLITE_CONFIG_SMALL_MALLOC option takes single argument of ++** type int, interpreted as a boolean, which if true provides a hint to ++** SQLite that it should avoid large memory allocations if possible. ++** SQLite will run faster if it is free to make large memory allocations, ++** but some application might prefer to run slower in exchange for ++** guarantees about memory fragmentation that are possible if large ++** allocations are avoided. This hint is normally off. ++** </dd> ++** + ** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt> + ** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int, + ** interpreted as a boolean, which enables or disables the collection of +@@ -1630,25 +1734,7 @@ + ** </dd> + ** + ** [[SQLITE_CONFIG_SCRATCH]] <dt>SQLITE_CONFIG_SCRATCH</dt> +-** <dd> ^The SQLITE_CONFIG_SCRATCH option specifies a static memory buffer +-** that SQLite can use for scratch memory. ^(There are three arguments +-** to SQLITE_CONFIG_SCRATCH: A pointer an 8-byte +-** aligned memory buffer from which the scratch allocations will be +-** drawn, the size of each scratch allocation (sz), +-** and the maximum number of scratch allocations (N).)^ +-** The first argument must be a pointer to an 8-byte aligned buffer +-** of at least sz*N bytes of memory. +-** ^SQLite will not use more than one scratch buffers per thread. +-** ^SQLite will never request a scratch buffer that is more than 6 +-** times the database page size. +-** ^If SQLite needs needs additional +-** scratch memory beyond what is provided by this configuration option, then +-** [sqlite3_malloc()] will be used to obtain the memory needed.<p> +-** ^When the application provides any amount of scratch memory using +-** SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary large +-** [sqlite3_malloc|heap allocations]. +-** This can help [Robson proof|prevent memory allocation failures] due to heap +-** fragmentation in low-memory embedded systems. ++** <dd> The SQLITE_CONFIG_SCRATCH option is no longer used. + ** </dd> + ** + ** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt> +@@ -1684,8 +1770,7 @@ + ** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt> + ** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer + ** that SQLite will use for all of its dynamic memory allocation needs +-** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and +-** [SQLITE_CONFIG_PAGECACHE]. ++** beyond those provided for by [SQLITE_CONFIG_PAGECACHE]. + ** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled + ** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns + ** [SQLITE_ERROR] if invoked otherwise. +@@ -1871,6 +1956,22 @@ + ** I/O required to support statement rollback. + ** The default value for this setting is controlled by the + ** [SQLITE_STMTJRNL_SPILL] compile-time option. ++** ++** [[SQLITE_CONFIG_SORTERREF_SIZE]] ++** <dt>SQLITE_CONFIG_SORTERREF_SIZE ++** <dd>The SQLITE_CONFIG_SORTERREF_SIZE option accepts a single parameter ++** of type (int) - the new value of the sorter-reference size threshold. ++** Usually, when SQLite uses an external sort to order records according ++** to an ORDER BY clause, all fields required by the caller are present in the ++** sorted records. However, if SQLite determines based on the declared type ++** of a table column that its values are likely to be very large - larger ++** than the configured sorter-reference size threshold - then a reference ++** is stored in each sorted record and the required column values loaded ++** from the database as records are returned in sorted order. The default ++** value for this option is to never use this optimization. Specifying a ++** negative value for this option restores the default behaviour. ++** This option is only available if SQLite is compiled with the ++** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option. + ** </dl> + */ + #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ +@@ -1878,7 +1979,7 @@ + #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ + #define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ + #define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */ +-#define SQLITE_CONFIG_SCRATCH 6 /* void*, int sz, int N */ ++#define SQLITE_CONFIG_SCRATCH 6 /* No longer used */ + #define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */ + #define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */ + #define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */ +@@ -1899,6 +2000,8 @@ + #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */ + #define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */ + #define SQLITE_CONFIG_STMTJRNL_SPILL 26 /* int nByte */ ++#define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */ ++#define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */ + + /* + ** CAPI3REF: Database Connection Configuration Options +@@ -1914,6 +2017,7 @@ + ** is invoked. + ** + ** <dl> ++** [[SQLITE_DBCONFIG_LOOKASIDE]] + ** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt> + ** <dd> ^This option takes three additional arguments that determine the + ** [lookaside memory allocator] configuration for the [database connection]. +@@ -1936,6 +2040,7 @@ + ** memory is in use leaves the configuration unchanged and returns + ** [SQLITE_BUSY].)^</dd> + ** ++** [[SQLITE_DBCONFIG_ENABLE_FKEY]] + ** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt> + ** <dd> ^This option is used to enable or disable the enforcement of + ** [foreign key constraints]. There should be two additional arguments. +@@ -1946,6 +2051,7 @@ + ** following this call. The second parameter may be a NULL pointer, in + ** which case the FK enforcement setting is not reported back. </dd> + ** ++** [[SQLITE_DBCONFIG_ENABLE_TRIGGER]] + ** <dt>SQLITE_DBCONFIG_ENABLE_TRIGGER</dt> + ** <dd> ^This option is used to enable or disable [CREATE TRIGGER | triggers]. + ** There should be two additional arguments. +@@ -1956,6 +2062,7 @@ + ** following this call. The second parameter may be a NULL pointer, in + ** which case the trigger setting is not reported back. </dd> + ** ++** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]] + ** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt> + ** <dd> ^This option is used to enable or disable the two-argument + ** version of the [fts3_tokenizer()] function which is part of the +@@ -1969,6 +2076,7 @@ + ** following this call. The second parameter may be a NULL pointer, in + ** which case the new setting is not reported back. </dd> + ** ++** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]] + ** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt> + ** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()] + ** interface independently of the [load_extension()] SQL function. +@@ -1986,7 +2094,7 @@ + ** be a NULL pointer, in which case the new setting is not reported back. + ** </dd> + ** +-** <dt>SQLITE_DBCONFIG_MAINDBNAME</dt> ++** [[SQLITE_DBCONFIG_MAINDBNAME]] <dt>SQLITE_DBCONFIG_MAINDBNAME</dt> + ** <dd> ^This option is used to change the name of the "main" database + ** schema. ^The sole argument is a pointer to a constant UTF8 string + ** which will become the new schema name in place of "main". ^SQLite +@@ -1995,6 +2103,7 @@ + ** until after the database connection closes. + ** </dd> + ** ++** [[SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE]] + ** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt> + ** <dd> Usually, when a database in wal mode is closed or detached from a + ** database handle, SQLite checks if this will mean that there are now no +@@ -2001,13 +2110,14 @@ + ** connections at all to the database. If so, it performs a checkpoint + ** operation before closing the connection. This option may be used to + ** override this behaviour. The first parameter passed to this operation +-** is an integer - non-zero to disable checkpoints-on-close, or zero (the +-** default) to enable them. The second parameter is a pointer to an integer ++** is an integer - positive to disable checkpoints-on-close, or zero (the ++** default) to enable them, and negative to leave the setting unchanged. ++** The second parameter is a pointer to an integer + ** into which is written 0 or 1 to indicate whether checkpoints-on-close + ** have been disabled - 0 if they are not disabled, 1 if they are. + ** </dd> + ** +-** <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt> ++** [[SQLITE_DBCONFIG_ENABLE_QPSG]] <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt> + ** <dd>^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates + ** the [query planner stability guarantee] (QPSG). When the QPSG is active, + ** a single SQL query statement will always use the same algorithm regardless +@@ -2016,8 +2126,57 @@ + ** slower. But the QPSG has the advantage of more predictable behavior. With + ** the QPSG active, SQLite will always use the same query plan in the field as + ** was used during testing in the lab. ++** The first argument to this setting is an integer which is 0 to disable ++** the QPSG, positive to enable QPSG, or negative to leave the setting ++** unchanged. The second parameter is a pointer to an integer into which ++** is written 0 or 1 to indicate whether the QPSG is disabled or enabled ++** following this call. + ** </dd> + ** ++** [[SQLITE_DBCONFIG_TRIGGER_EQP]] <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt> ++** <dd> By default, the output of EXPLAIN QUERY PLAN commands does not ++** include output for any operations performed by trigger programs. This ++** option is used to set or clear (the default) a flag that governs this ++** behavior. The first parameter passed to this operation is an integer - ++** positive to enable output for trigger programs, or zero to disable it, ++** or negative to leave the setting unchanged. ++** The second parameter is a pointer to an integer into which is written ++** 0 or 1 to indicate whether output-for-triggers has been disabled - 0 if ++** it is not disabled, 1 if it is. ++** </dd> ++** ++** [[SQLITE_DBCONFIG_RESET_DATABASE]] <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt> ++** <dd> Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run ++** [VACUUM] in order to reset a database back to an empty database ++** with no schema and no content. The following process works even for ++** a badly corrupted database file: ++** <ol> ++** <li> If the database connection is newly opened, make sure it has read the ++** database schema by preparing then discarding some query against the ++** database, or calling sqlite3_table_column_metadata(), ignoring any ++** errors. This step is only necessary if the application desires to keep ++** the database in WAL mode after the reset if it was in WAL mode before ++** the reset. ++** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0); ++** <li> [sqlite3_exec](db, "[VACUUM]", 0, 0, 0); ++** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0); ++** </ol> ++** Because resetting a database is destructive and irreversible, the ++** process requires the use of this obscure API and multiple steps to help ++** ensure that it does not happen by accident. ++** ++** [[SQLITE_DBCONFIG_DEFENSIVE]] <dt>SQLITE_DBCONFIG_DEFENSIVE</dt> ++** <dd>The SQLITE_DBCONFIG_DEFENSIVE option activates or deactivates the ++** "defensive" flag for a database connection. When the defensive ++** flag is enabled, language features that allow ordinary SQL to ++** deliberately corrupt the database file are disabled. The disabled ++** features include but are not limited to the following: ++** <ul> ++** <li> The [PRAGMA writable_schema=ON] statement. ++** <li> Writes to the [sqlite_dbpage] virtual table. ++** <li> Direct writes to [shadow tables]. ++** </ul> ++** </dd> + ** </dl> + */ + #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ +@@ -2028,8 +2187,11 @@ + #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_MAX 1010 /* Largest DBCONFIG */ + +- + /* + ** CAPI3REF: Enable Or Disable Extended Result Codes + ** METHOD: sqlite3 +@@ -2156,12 +2318,17 @@ + ** program, the value returned reflects the number of rows modified by the + ** previous INSERT, UPDATE or DELETE statement within the same trigger. + ** +-** See also the [sqlite3_total_changes()] interface, the +-** [count_changes pragma], and the [changes() SQL function]. +-** + ** If a separate thread makes changes on the same database connection + ** while [sqlite3_changes()] is running then the value returned + ** is unpredictable and not meaningful. ++** ++** See also: ++** <ul> ++** <li> the [sqlite3_total_changes()] interface ++** <li> the [count_changes pragma] ++** <li> the [changes() SQL function] ++** <li> the [data_version pragma] ++** </ul> + */ + SQLITE_API int sqlite3_changes(sqlite3*); + +@@ -2179,13 +2346,26 @@ + ** count, but those made as part of REPLACE constraint resolution are + ** not. ^Changes to a view that are intercepted by INSTEAD OF triggers + ** are not counted. ++** ++** This the [sqlite3_total_changes(D)] interface only reports the number ++** of rows that changed due to SQL statement run against database ++** connection D. Any changes by other database connections are ignored. ++** To detect changes against a database file from other database ++** connections use the [PRAGMA data_version] command or the ++** [SQLITE_FCNTL_DATA_VERSION] [file control]. + ** +-** See also the [sqlite3_changes()] interface, the +-** [count_changes pragma], and the [total_changes() SQL function]. +-** + ** If a separate thread makes changes on the same database connection + ** while [sqlite3_total_changes()] is running then the value + ** returned is unpredictable and not meaningful. ++** ++** See also: ++** <ul> ++** <li> the [sqlite3_changes()] interface ++** <li> the [count_changes pragma] ++** <li> the [changes() SQL function] ++** <li> the [data_version pragma] ++** <li> the [SQLITE_FCNTL_DATA_VERSION] [file control] ++** </ul> + */ + SQLITE_API int sqlite3_total_changes(sqlite3*); + +@@ -2434,16 +2614,16 @@ + ** + ** These routines are work-alikes of the "printf()" family of functions + ** from the standard C library. +-** These routines understand most of the common K&R formatting options, +-** plus some additional non-standard formats, detailed below. +-** Note that some of the more obscure formatting options from recent +-** C-library standards are omitted from this implementation. ++** These routines understand most of the common formatting options from ++** the standard library printf() ++** plus some additional non-standard formats ([%q], [%Q], [%w], and [%z]). ++** See the [built-in printf()] documentation for details. + ** + ** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their +-** results into memory obtained from [sqlite3_malloc()]. ++** results into memory obtained from [sqlite3_malloc64()]. + ** The strings returned by these two routines should be + ** released by [sqlite3_free()]. ^Both routines return a +-** NULL pointer if [sqlite3_malloc()] is unable to allocate enough ++** NULL pointer if [sqlite3_malloc64()] is unable to allocate enough + ** memory to hold the resulting string. + ** + ** ^(The sqlite3_snprintf() routine is similar to "snprintf()" from +@@ -2467,71 +2647,7 @@ + ** + ** ^The sqlite3_vsnprintf() routine is a varargs version of sqlite3_snprintf(). + ** +-** These routines all implement some additional formatting +-** options that are useful for constructing SQL statements. +-** All of the usual printf() formatting options apply. In addition, there +-** is are "%q", "%Q", "%w" and "%z" options. +-** +-** ^(The %q option works like %s in that it substitutes a nul-terminated +-** string from the argument list. But %q also doubles every '\'' character. +-** %q is designed for use inside a string literal.)^ By doubling each '\'' +-** character it escapes that character and allows it to be inserted into +-** the string. +-** +-** For example, assume the string variable zText contains text as follows: +-** +-** <blockquote><pre> +-** char *zText = "It's a happy day!"; +-** </pre></blockquote> +-** +-** One can use this text in an SQL statement as follows: +-** +-** <blockquote><pre> +-** char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText); +-** sqlite3_exec(db, zSQL, 0, 0, 0); +-** sqlite3_free(zSQL); +-** </pre></blockquote> +-** +-** Because the %q format string is used, the '\'' character in zText +-** is escaped and the SQL generated is as follows: +-** +-** <blockquote><pre> +-** INSERT INTO table1 VALUES('It''s a happy day!') +-** </pre></blockquote> +-** +-** This is correct. Had we used %s instead of %q, the generated SQL +-** would have looked like this: +-** +-** <blockquote><pre> +-** INSERT INTO table1 VALUES('It's a happy day!'); +-** </pre></blockquote> +-** +-** This second example is an SQL syntax error. As a general rule you should +-** always use %q instead of %s when inserting text into a string literal. +-** +-** ^(The %Q option works like %q except it also adds single quotes around +-** the outside of the total string. Additionally, if the parameter in the +-** argument list is a NULL pointer, %Q substitutes the text "NULL" (without +-** single quotes).)^ So, for example, one could say: +-** +-** <blockquote><pre> +-** char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText); +-** sqlite3_exec(db, zSQL, 0, 0, 0); +-** sqlite3_free(zSQL); +-** </pre></blockquote> +-** +-** The code above will render a correct SQL statement in the zSQL +-** variable even if the zText variable is a NULL pointer. +-** +-** ^(The "%w" formatting option is like "%q" except that it expects to +-** be contained within double-quotes instead of single quotes, and it +-** escapes the double-quote character instead of the single-quote +-** character.)^ The "%w" formatting option is intended for safely inserting +-** table and column names into a constructed SQL statement. +-** +-** ^(The "%z" formatting option works like "%s" but with the +-** addition that after the string has been read and copied into +-** the result, [sqlite3_free()] is called on the input string.)^ ++** See also: [built-in printf()], [printf() SQL function] + */ + SQLITE_API char *sqlite3_mprintf(const char*,...); + SQLITE_API char *sqlite3_vmprintf(const char*, va_list); +@@ -2889,8 +3005,8 @@ + ** KEYWORDS: SQLITE_TRACE + ** + ** These constants identify classes of events that can be monitored +-** using the [sqlite3_trace_v2()] tracing logic. The third argument +-** to [sqlite3_trace_v2()] is an OR-ed combination of one or more of ++** using the [sqlite3_trace_v2()] tracing logic. The M argument ++** to [sqlite3_trace_v2(D,M,X,P)] is an OR-ed combination of one or more of + ** the following constants. ^The first argument to the trace callback + ** is one of the following constants. + ** +@@ -3099,10 +3215,10 @@ + ** ^If [URI filename] interpretation is enabled, and the filename argument + ** begins with "file:", then the filename is interpreted as a URI. ^URI + ** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is +-** set in the fourth argument to sqlite3_open_v2(), or if it has ++** set in the third argument to sqlite3_open_v2(), or if it has + ** been enabled globally using the [SQLITE_CONFIG_URI] option with the + ** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option. +-** As of SQLite version 3.7.7, URI filename interpretation is turned off ++** URI filename interpretation is turned off + ** by default, but future releases of SQLite might enable URI filename + ** interpretation by default. See "[URI filenames]" for additional + ** information. +@@ -3305,13 +3421,24 @@ + ** [database connection] D failed, then the sqlite3_errcode(D) interface + ** returns the numeric [result code] or [extended result code] for that + ** API call. +-** If the most recent API call was successful, +-** then the return value from sqlite3_errcode() is undefined. + ** ^The sqlite3_extended_errcode() + ** interface is the same except that it always returns the + ** [extended result code] even when extended result codes are + ** disabled. + ** ++** The values returned by sqlite3_errcode() and/or ++** sqlite3_extended_errcode() might change with each API call. ++** Except, there are some interfaces that are guaranteed to never ++** change the value of the error code. The error-code preserving ++** interfaces are: ++** ++** <ul> ++** <li> sqlite3_errcode() ++** <li> sqlite3_extended_errcode() ++** <li> sqlite3_errmsg() ++** <li> sqlite3_errmsg16() ++** </ul> ++** + ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language + ** text that describes the error, as either UTF-8 or UTF-16 respectively. + ** ^(Memory to hold the error message string is managed internally. +@@ -3501,9 +3628,19 @@ + ** on this hint by avoiding the use of [lookaside memory] so as not to + ** deplete the limited store of lookaside memory. Future versions of + ** SQLite may act on this hint differently. ++** ++** [[SQLITE_PREPARE_NORMALIZE]] ^(<dt>SQLITE_PREPARE_NORMALIZE</dt> ++** <dd>The SQLITE_PREPARE_NORMALIZE flag indicates that a normalized ++** representation of the SQL statement should be calculated and then ++** associated with the prepared statement, which can be obtained via ++** the [sqlite3_normalized_sql()] interface.)^ The semantics used to ++** normalize a SQL statement are unspecified and subject to change. ++** At a minimum, literal values will be replaced with suitable ++** placeholders. + ** </dl> + */ + #define SQLITE_PREPARE_PERSISTENT 0x01 ++#define SQLITE_PREPARE_NORMALIZE 0x02 + + /* + ** CAPI3REF: Compiling An SQL Statement +@@ -3597,6 +3734,7 @@ + ** or [GLOB] operator or if the parameter is compared to an indexed column + ** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled. + ** </li> ++** </ol> + ** + ** <p>^sqlite3_prepare_v3() differs from sqlite3_prepare_v2() only in having + ** the extra prepFlags parameter, which is a bit array consisting of zero or +@@ -3603,7 +3741,6 @@ + ** more of the [SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_*] flags. ^The + ** sqlite3_prepare_v2() interface works exactly the same as + ** sqlite3_prepare_v3() with a zero prepFlags parameter. +-** </ol> + */ + SQLITE_API int sqlite3_prepare( + sqlite3 *db, /* Database handle */ +@@ -3661,6 +3798,11 @@ + ** ^The sqlite3_expanded_sql(P) interface returns a pointer to a UTF-8 + ** string containing the SQL text of prepared statement P with + ** [bound parameters] expanded. ++** ^The sqlite3_normalized_sql(P) interface returns a pointer to a UTF-8 ++** string containing the normalized SQL text of prepared statement P. The ++** semantics used to normalize a SQL statement are unspecified and subject ++** to change. At a minimum, literal values will be replaced with suitable ++** placeholders. + ** + ** ^(For example, if a prepared statement is created using the SQL + ** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345 +@@ -3676,8 +3818,9 @@ + ** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time + ** option causes sqlite3_expanded_sql() to always return NULL. + ** +-** ^The string returned by sqlite3_sql(P) is managed by SQLite and is +-** automatically freed when the prepared statement is finalized. ++** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P) ++** are managed by SQLite and are automatically freed when the prepared ++** statement is finalized. + ** ^The string returned by sqlite3_expanded_sql(P), on the other hand, + ** is obtained from [sqlite3_malloc()] and must be free by the application + ** by passing it to [sqlite3_free()]. +@@ -3684,6 +3827,7 @@ + */ + SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); + SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt); ++SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt); + + /* + ** CAPI3REF: Determine If An SQL Statement Writes The Database +@@ -3776,8 +3920,9 @@ + ** implementation of [application-defined SQL functions] are protected. + ** ^The sqlite3_value object returned by + ** [sqlite3_column_value()] is unprotected. +-** Unprotected sqlite3_value objects may only be used with +-** [sqlite3_result_value()] and [sqlite3_bind_value()]. ++** Unprotected sqlite3_value objects may only be used as arguments ++** to [sqlite3_result_value()], [sqlite3_bind_value()], and ++** [sqlite3_value_dup()]. + ** The [sqlite3_value_blob | sqlite3_value_type()] family of + ** interfaces require protected sqlite3_value objects. + */ +@@ -4199,7 +4344,7 @@ + ** other than [SQLITE_ROW] before any subsequent invocation of + ** sqlite3_step(). Failure to reset the prepared statement using + ** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from +-** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1]), ++** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1], + ** sqlite3_step() began + ** calling [sqlite3_reset()] automatically in this circumstance rather + ** than returning [SQLITE_MISUSE]. This is not considered a compatibility +@@ -4464,11 +4609,25 @@ + ** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into + ** [sqlite3_free()]. + ** +-** ^(If a memory allocation error occurs during the evaluation of any +-** of these routines, a default value is returned. The default value +-** is either the integer 0, the floating point number 0.0, or a NULL +-** pointer. Subsequent calls to [sqlite3_errcode()] will return +-** [SQLITE_NOMEM].)^ ++** As long as the input parameters are correct, these routines will only ++** fail if an out-of-memory error occurs during a format conversion. ++** Only the following subset of interfaces are subject to out-of-memory ++** errors: ++** ++** <ul> ++** <li> sqlite3_column_blob() ++** <li> sqlite3_column_text() ++** <li> sqlite3_column_text16() ++** <li> sqlite3_column_bytes() ++** <li> sqlite3_column_bytes16() ++** </ul> ++** ++** If an out-of-memory error occurs, then the return value from these ++** routines is the same as if the column had contained an SQL NULL value. ++** Valid SQL NULL returns can be distinguished from out-of-memory errors ++** by invoking the [sqlite3_errcode()] immediately after the suspect ++** return value is obtained and before any ++** other SQLite interface is called on the same [database connection]. + */ + SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); + SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol); +@@ -4545,11 +4704,13 @@ + ** + ** ^These functions (collectively known as "function creation routines") + ** are used to add SQL functions or aggregates or to redefine the behavior +-** of existing SQL functions or aggregates. The only differences between +-** these routines are the text encoding expected for +-** the second parameter (the name of the function being created) +-** and the presence or absence of a destructor callback for +-** the application data pointer. ++** of existing SQL functions or aggregates. The only differences between ++** the three "sqlite3_create_function*" routines are the text encoding ++** expected for the second parameter (the name of the function being ++** created) and the presence or absence of a destructor callback for ++** the application data pointer. Function sqlite3_create_window_function() ++** is similar, but allows the user to supply the extra callback functions ++** needed by [aggregate window functions]. + ** + ** ^The first parameter is the [database connection] to which the SQL + ** function is to be added. ^If an application uses more than one database +@@ -4595,7 +4756,8 @@ + ** ^(The fifth parameter is an arbitrary pointer. The implementation of the + ** function can gain access to this pointer using [sqlite3_user_data()].)^ + ** +-** ^The sixth, seventh and eighth parameters, xFunc, xStep and xFinal, are ++** ^The sixth, seventh and eighth parameters passed to the three ++** "sqlite3_create_function*" functions, xFunc, xStep and xFinal, are + ** pointers to C-language functions that implement the SQL function or + ** aggregate. ^A scalar SQL function requires an implementation of the xFunc + ** callback only; NULL pointers must be passed as the xStep and xFinal +@@ -4604,16 +4766,25 @@ + ** SQL function or aggregate, pass NULL pointers for all three function + ** callbacks. + ** +-** ^(If the ninth parameter to sqlite3_create_function_v2() is not NULL, +-** then it is destructor for the application data pointer. +-** The destructor is invoked when the function is deleted, either by being +-** overloaded or when the database connection closes.)^ +-** ^The destructor is also invoked if the call to +-** sqlite3_create_function_v2() fails. +-** ^When the destructor callback of the tenth parameter is invoked, it +-** is passed a single argument which is a copy of the application data +-** pointer which was the fifth parameter to sqlite3_create_function_v2(). ++** ^The sixth, seventh, eighth and ninth parameters (xStep, xFinal, xValue ++** and xInverse) passed to sqlite3_create_window_function are pointers to ++** C-language callbacks that implement the new function. xStep and xFinal ++** must both be non-NULL. xValue and xInverse may either both be NULL, in ++** which case a regular aggregate function is created, or must both be ++** non-NULL, in which case the new function may be used as either an aggregate ++** or aggregate window function. More details regarding the implementation ++** of aggregate window functions are ++** [user-defined window functions|available here]. + ** ++** ^(If the final parameter to sqlite3_create_function_v2() or ++** sqlite3_create_window_function() is not NULL, then it is destructor for ++** the application data pointer. The destructor is invoked when the function ++** is deleted, either by being overloaded or when the database connection ++** closes.)^ ^The destructor is also invoked if the call to ++** sqlite3_create_function_v2() fails. ^When the destructor callback is ++** invoked, it is passed a single argument which is a copy of the application ++** data pointer which was the fifth parameter to sqlite3_create_function_v2(). ++** + ** ^It is permitted to register multiple implementations of the same + ** functions with the same name but with either differing numbers of + ** arguments or differing preferred text encodings. ^SQLite will use +@@ -4665,6 +4836,18 @@ + void (*xFinal)(sqlite3_context*), + void(*xDestroy)(void*) + ); ++SQLITE_API int sqlite3_create_window_function( ++ sqlite3 *db, ++ const char *zFunctionName, ++ int nArg, ++ int eTextRep, ++ void *pApp, ++ void (*xStep)(sqlite3_context*,int,sqlite3_value**), ++ void (*xFinal)(sqlite3_context*), ++ void (*xValue)(sqlite3_context*), ++ void (*xInverse)(sqlite3_context*,int,sqlite3_value**), ++ void(*xDestroy)(void*) ++); + + /* + ** CAPI3REF: Text Encodings +@@ -4735,6 +4918,9 @@ + ** datatype of the value + ** <tr><td><b>sqlite3_value_numeric_type </b> + ** <td>→ <td>Best numeric datatype of the value ++** <tr><td><b>sqlite3_value_nochange </b> ++** <td>→ <td>True if the column is unchanged in an UPDATE ++** against a virtual table. + ** </table></blockquote> + ** + ** <b>Details:</b> +@@ -4783,6 +4969,19 @@ + ** then the conversion is performed. Otherwise no conversion occurs. + ** The [SQLITE_INTEGER | datatype] after conversion is returned.)^ + ** ++** ^Within the [xUpdate] method of a [virtual table], the ++** sqlite3_value_nochange(X) interface returns true if and only if ++** the column corresponding to X is unchanged by the UPDATE operation ++** that the xUpdate method call was invoked to implement and if ++** and the prior [xColumn] method call that was invoked to extracted ++** the value for that column returned without setting a result (probably ++** because it queried [sqlite3_vtab_nochange()] and found that the column ++** was unchanging). ^Within an [xUpdate] method, any value for which ++** sqlite3_value_nochange(X) is true will in all other respects appear ++** to be a NULL value. If sqlite3_value_nochange(X) is invoked anywhere other ++** than within an [xUpdate] method call for an UPDATE statement, then ++** the return value is arbitrary and meaningless. ++** + ** Please pay particular attention to the fact that the pointer returned + ** from [sqlite3_value_blob()], [sqlite3_value_text()], or + ** [sqlite3_value_text16()] can be invalidated by a subsequent call to +@@ -4791,6 +4990,28 @@ + ** + ** These routines must be called from the same thread as + ** the SQL function that supplied the [sqlite3_value*] parameters. ++** ++** As long as the input parameter is correct, these routines can only ++** fail if an out-of-memory error occurs during a format conversion. ++** Only the following subset of interfaces are subject to out-of-memory ++** errors: ++** ++** <ul> ++** <li> sqlite3_value_blob() ++** <li> sqlite3_value_text() ++** <li> sqlite3_value_text16() ++** <li> sqlite3_value_text16le() ++** <li> sqlite3_value_text16be() ++** <li> sqlite3_value_bytes() ++** <li> sqlite3_value_bytes16() ++** </ul> ++** ++** If an out-of-memory error occurs, then the return value from these ++** routines is the same as if the column had contained an SQL NULL value. ++** Valid SQL NULL returns can be distinguished from out-of-memory errors ++** by invoking the [sqlite3_errcode()] immediately after the suspect ++** return value is obtained and before any ++** other SQLite interface is called on the same [database connection]. + */ + SQLITE_API const void *sqlite3_value_blob(sqlite3_value*); + SQLITE_API double sqlite3_value_double(sqlite3_value*); +@@ -4805,6 +5026,7 @@ + SQLITE_API int sqlite3_value_bytes16(sqlite3_value*); + SQLITE_API int sqlite3_value_type(sqlite3_value*); + SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); ++SQLITE_API int sqlite3_value_nochange(sqlite3_value*); + + /* + ** CAPI3REF: Finding The Subtype Of SQL Values +@@ -5461,6 +5683,41 @@ + SQLITE_API SQLITE_EXTERN char *sqlite3_data_directory; + + /* ++** CAPI3REF: Win32 Specific Interface ++** ++** These interfaces are available only on Windows. The ++** [sqlite3_win32_set_directory] interface is used to set the value associated ++** with the [sqlite3_temp_directory] or [sqlite3_data_directory] variable, to ++** zValue, depending on the value of the type parameter. The zValue parameter ++** should be NULL to cause the previous value to be freed via [sqlite3_free]; ++** a non-NULL value will be copied into memory obtained from [sqlite3_malloc] ++** prior to being used. The [sqlite3_win32_set_directory] interface returns ++** [SQLITE_OK] to indicate success, [SQLITE_ERROR] if the type is unsupported, ++** or [SQLITE_NOMEM] if memory could not be allocated. The value of the ++** [sqlite3_data_directory] variable is intended to act as a replacement for ++** the current directory on the sub-platforms of Win32 where that concept is ++** not present, e.g. WinRT and UWP. The [sqlite3_win32_set_directory8] and ++** [sqlite3_win32_set_directory16] interfaces behave exactly the same as the ++** sqlite3_win32_set_directory interface except the string parameter must be ++** UTF-8 or UTF-16, respectively. ++*/ ++SQLITE_API int sqlite3_win32_set_directory( ++ unsigned long type, /* Identifier for directory being set or reset */ ++ void *zValue /* New value for directory being set or reset */ ++); ++SQLITE_API int sqlite3_win32_set_directory8(unsigned long type, const char *zValue); ++SQLITE_API int sqlite3_win32_set_directory16(unsigned long type, const void *zValue); ++ ++/* ++** CAPI3REF: Win32 Directory Types ++** ++** These macros are only available on Windows. They define the allowed values ++** for the type argument to the [sqlite3_win32_set_directory] interface. ++*/ ++#define SQLITE_WIN32_DATA_DIRECTORY_TYPE 1 ++#define SQLITE_WIN32_TEMP_DIRECTORY_TYPE 2 ++ ++/* + ** CAPI3REF: Test For Auto-Commit Mode + ** KEYWORDS: {autocommit mode} + ** METHOD: sqlite3 +@@ -6060,6 +6317,9 @@ + int (*xSavepoint)(sqlite3_vtab *pVTab, int); + int (*xRelease)(sqlite3_vtab *pVTab, int); + int (*xRollbackTo)(sqlite3_vtab *pVTab, int); ++ /* The methods above are in versions 1 and 2 of the sqlite_module object. ++ ** Those below are for version 3 and greater. */ ++ int (*xShadowName)(const char*); + }; + + /* +@@ -6192,6 +6452,10 @@ + + /* + ** CAPI3REF: Virtual Table Scan Flags ++** ++** Virtual table implementations are allowed to set the ++** [sqlite3_index_info].idxFlags field to some combination of ++** these bits. + */ + #define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */ + +@@ -6203,15 +6467,21 @@ + ** an operator that is part of a constraint term in the wHERE clause of + ** a query that uses a [virtual table]. + */ +-#define SQLITE_INDEX_CONSTRAINT_EQ 2 +-#define SQLITE_INDEX_CONSTRAINT_GT 4 +-#define SQLITE_INDEX_CONSTRAINT_LE 8 +-#define SQLITE_INDEX_CONSTRAINT_LT 16 +-#define SQLITE_INDEX_CONSTRAINT_GE 32 +-#define SQLITE_INDEX_CONSTRAINT_MATCH 64 +-#define SQLITE_INDEX_CONSTRAINT_LIKE 65 +-#define SQLITE_INDEX_CONSTRAINT_GLOB 66 +-#define SQLITE_INDEX_CONSTRAINT_REGEXP 67 ++#define SQLITE_INDEX_CONSTRAINT_EQ 2 ++#define SQLITE_INDEX_CONSTRAINT_GT 4 ++#define SQLITE_INDEX_CONSTRAINT_LE 8 ++#define SQLITE_INDEX_CONSTRAINT_LT 16 ++#define SQLITE_INDEX_CONSTRAINT_GE 32 ++#define SQLITE_INDEX_CONSTRAINT_MATCH 64 ++#define SQLITE_INDEX_CONSTRAINT_LIKE 65 ++#define SQLITE_INDEX_CONSTRAINT_GLOB 66 ++#define SQLITE_INDEX_CONSTRAINT_REGEXP 67 ++#define SQLITE_INDEX_CONSTRAINT_NE 68 ++#define SQLITE_INDEX_CONSTRAINT_ISNOT 69 ++#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70 ++#define SQLITE_INDEX_CONSTRAINT_ISNULL 71 ++#define SQLITE_INDEX_CONSTRAINT_IS 72 ++#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150 + + /* + ** CAPI3REF: Register A Virtual Table Implementation +@@ -6888,6 +7158,7 @@ + /* + ** CAPI3REF: Low-Level Control Of Database Files + ** METHOD: sqlite3 ++** KEYWORDS: {file control} + ** + ** ^The [sqlite3_file_control()] interface makes a direct call to the + ** xFileControl method for the [sqlite3_io_methods] object associated +@@ -6902,11 +7173,18 @@ + ** the xFileControl method. ^The return value of the xFileControl + ** method becomes the return value of this routine. + ** +-** ^The SQLITE_FCNTL_FILE_POINTER value for the op parameter causes ++** A few opcodes for [sqlite3_file_control()] are handled directly ++** by the SQLite core and never invoke the ++** sqlite3_io_methods.xFileControl method. ++** ^The [SQLITE_FCNTL_FILE_POINTER] value for the op parameter causes + ** a pointer to the underlying [sqlite3_file] object to be written into +-** the space pointed to by the 4th parameter. ^The SQLITE_FCNTL_FILE_POINTER +-** case is a short-circuit path which does not actually invoke the +-** underlying sqlite3_io_methods.xFileControl method. ++** the space pointed to by the 4th parameter. The ++** [SQLITE_FCNTL_JOURNAL_POINTER] works similarly except that it returns ++** the [sqlite3_file] object associated with the journal file instead of ++** the main database. The [SQLITE_FCNTL_VFS_POINTER] opcode returns ++** a pointer to the underlying [sqlite3_vfs] object for the file. ++** The [SQLITE_FCNTL_DATA_VERSION] returns the data version counter ++** from the pager. + ** + ** ^If the second parameter (zDbName) does not match the name of any + ** open database file, then SQLITE_ERROR is returned. ^This error +@@ -6916,7 +7194,7 @@ + ** an incorrect zDbName and an SQLITE_ERROR return from the underlying + ** xFileControl method. + ** +-** See also: [SQLITE_FCNTL_LOCKSTATE] ++** See also: [file control opcodes] + */ + SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); + +@@ -6962,8 +7240,9 @@ + #define SQLITE_TESTCTRL_ALWAYS 13 + #define SQLITE_TESTCTRL_RESERVE 14 + #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 +-#define SQLITE_TESTCTRL_ISKEYWORD 16 +-#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 ++#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ ++#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ ++#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17 + #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 + #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ + #define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19 +@@ -6973,9 +7252,193 @@ + #define SQLITE_TESTCTRL_ISINIT 23 + #define SQLITE_TESTCTRL_SORTER_MMAP 24 + #define SQLITE_TESTCTRL_IMPOSTER 25 +-#define SQLITE_TESTCTRL_LAST 25 ++#define SQLITE_TESTCTRL_PARSER_COVERAGE 26 ++#define SQLITE_TESTCTRL_LAST 26 /* Largest TESTCTRL */ + + /* ++** CAPI3REF: SQL Keyword Checking ++** ++** These routines provide access to the set of SQL language keywords ++** recognized by SQLite. Applications can uses these routines to determine ++** whether or not a specific identifier needs to be escaped (for example, ++** by enclosing in double-quotes) so as not to confuse the parser. ++** ++** The sqlite3_keyword_count() interface returns the number of distinct ++** keywords understood by SQLite. ++** ++** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and ++** makes *Z point to that keyword expressed as UTF8 and writes the number ++** of bytes in the keyword into *L. The string that *Z points to is not ++** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns ++** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z ++** or L are NULL or invalid pointers then calls to ++** sqlite3_keyword_name(N,Z,L) result in undefined behavior. ++** ++** The sqlite3_keyword_check(Z,L) interface checks to see whether or not ++** the L-byte UTF8 identifier that Z points to is a keyword, returning non-zero ++** if it is and zero if not. ++** ++** The parser used by SQLite is forgiving. It is often possible to use ++** a keyword as an identifier as long as such use does not result in a ++** parsing ambiguity. For example, the statement ++** "CREATE TABLE BEGIN(REPLACE,PRAGMA,END);" is accepted by SQLite, and ++** creates a new table named "BEGIN" with three columns named ++** "REPLACE", "PRAGMA", and "END". Nevertheless, best practice is to avoid ++** using keywords as identifiers. Common techniques used to avoid keyword ++** name collisions include: ++** <ul> ++** <li> Put all identifier names inside double-quotes. This is the official ++** SQL way to escape identifier names. ++** <li> Put identifier names inside [...]. This is not standard SQL, ++** but it is what SQL Server does and so lots of programmers use this ++** technique. ++** <li> Begin every identifier with the letter "Z" as no SQL keywords start ++** with "Z". ++** <li> Include a digit somewhere in every identifier name. ++** </ul> ++** ++** Note that the number of keywords understood by SQLite can depend on ++** compile-time options. For example, "VACUUM" is not a keyword if ++** SQLite is compiled with the [-DSQLITE_OMIT_VACUUM] option. Also, ++** new keywords may be added to future releases of SQLite. ++*/ ++SQLITE_API int sqlite3_keyword_count(void); ++SQLITE_API int sqlite3_keyword_name(int,const char**,int*); ++SQLITE_API int sqlite3_keyword_check(const char*,int); ++ ++/* ++** CAPI3REF: Dynamic String Object ++** KEYWORDS: {dynamic string} ++** ++** An instance of the sqlite3_str object contains a dynamically-sized ++** string under construction. ++** ++** The lifecycle of an sqlite3_str object is as follows: ++** <ol> ++** <li> ^The sqlite3_str object is created using [sqlite3_str_new()]. ++** <li> ^Text is appended to the sqlite3_str object using various ++** methods, such as [sqlite3_str_appendf()]. ++** <li> ^The sqlite3_str object is destroyed and the string it created ++** is returned using the [sqlite3_str_finish()] interface. ++** </ol> ++*/ ++typedef struct sqlite3_str sqlite3_str; ++ ++/* ++** CAPI3REF: Create A New Dynamic String Object ++** CONSTRUCTOR: sqlite3_str ++** ++** ^The [sqlite3_str_new(D)] interface allocates and initializes ++** a new [sqlite3_str] object. To avoid memory leaks, the object returned by ++** [sqlite3_str_new()] must be freed by a subsequent call to ++** [sqlite3_str_finish(X)]. ++** ++** ^The [sqlite3_str_new(D)] interface always returns a pointer to a ++** valid [sqlite3_str] object, though in the event of an out-of-memory ++** error the returned object might be a special singleton that will ++** silently reject new text, always return SQLITE_NOMEM from ++** [sqlite3_str_errcode()], always return 0 for ++** [sqlite3_str_length()], and always return NULL from ++** [sqlite3_str_finish(X)]. It is always safe to use the value ++** returned by [sqlite3_str_new(D)] as the sqlite3_str parameter ++** to any of the other [sqlite3_str] methods. ++** ++** The D parameter to [sqlite3_str_new(D)] may be NULL. If the ++** D parameter in [sqlite3_str_new(D)] is not NULL, then the maximum ++** length of the string contained in the [sqlite3_str] object will be ++** the value set for [sqlite3_limit](D,[SQLITE_LIMIT_LENGTH]) instead ++** of [SQLITE_MAX_LENGTH]. ++*/ ++SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3*); ++ ++/* ++** CAPI3REF: Finalize A Dynamic String ++** DESTRUCTOR: sqlite3_str ++** ++** ^The [sqlite3_str_finish(X)] interface destroys the sqlite3_str object X ++** and returns a pointer to a memory buffer obtained from [sqlite3_malloc64()] ++** that contains the constructed string. The calling application should ++** pass the returned value to [sqlite3_free()] to avoid a memory leak. ++** ^The [sqlite3_str_finish(X)] interface may return a NULL pointer if any ++** errors were encountered during construction of the string. ^The ++** [sqlite3_str_finish(X)] interface will also return a NULL pointer if the ++** string in [sqlite3_str] object X is zero bytes long. ++*/ ++SQLITE_API char *sqlite3_str_finish(sqlite3_str*); ++ ++/* ++** CAPI3REF: Add Content To A Dynamic String ++** METHOD: sqlite3_str ++** ++** These interfaces add content to an sqlite3_str object previously obtained ++** from [sqlite3_str_new()]. ++** ++** ^The [sqlite3_str_appendf(X,F,...)] and ++** [sqlite3_str_vappendf(X,F,V)] interfaces uses the [built-in printf] ++** functionality of SQLite to append formatted text onto the end of ++** [sqlite3_str] object X. ++** ++** ^The [sqlite3_str_append(X,S,N)] method appends exactly N bytes from string S ++** onto the end of the [sqlite3_str] object X. N must be non-negative. ++** S must contain at least N non-zero bytes of content. To append a ++** zero-terminated string in its entirety, use the [sqlite3_str_appendall()] ++** method instead. ++** ++** ^The [sqlite3_str_appendall(X,S)] method appends the complete content of ++** zero-terminated string S onto the end of [sqlite3_str] object X. ++** ++** ^The [sqlite3_str_appendchar(X,N,C)] method appends N copies of the ++** single-byte character C onto the end of [sqlite3_str] object X. ++** ^This method can be used, for example, to add whitespace indentation. ++** ++** ^The [sqlite3_str_reset(X)] method resets the string under construction ++** inside [sqlite3_str] object X back to zero bytes in length. ++** ++** These methods do not return a result code. ^If an error occurs, that fact ++** is recorded in the [sqlite3_str] object and can be recovered by a ++** subsequent call to [sqlite3_str_errcode(X)]. ++*/ ++SQLITE_API void sqlite3_str_appendf(sqlite3_str*, const char *zFormat, ...); ++SQLITE_API void sqlite3_str_vappendf(sqlite3_str*, const char *zFormat, va_list); ++SQLITE_API void sqlite3_str_append(sqlite3_str*, const char *zIn, int N); ++SQLITE_API void sqlite3_str_appendall(sqlite3_str*, const char *zIn); ++SQLITE_API void sqlite3_str_appendchar(sqlite3_str*, int N, char C); ++SQLITE_API void sqlite3_str_reset(sqlite3_str*); ++ ++/* ++** CAPI3REF: Status Of A Dynamic String ++** METHOD: sqlite3_str ++** ++** These interfaces return the current status of an [sqlite3_str] object. ++** ++** ^If any prior errors have occurred while constructing the dynamic string ++** in sqlite3_str X, then the [sqlite3_str_errcode(X)] method will return ++** an appropriate error code. ^The [sqlite3_str_errcode(X)] method returns ++** [SQLITE_NOMEM] following any out-of-memory error, or ++** [SQLITE_TOOBIG] if the size of the dynamic string exceeds ++** [SQLITE_MAX_LENGTH], or [SQLITE_OK] if there have been no errors. ++** ++** ^The [sqlite3_str_length(X)] method returns the current length, in bytes, ++** of the dynamic string under construction in [sqlite3_str] object X. ++** ^The length returned by [sqlite3_str_length(X)] does not include the ++** zero-termination byte. ++** ++** ^The [sqlite3_str_value(X)] method returns a pointer to the current ++** content of the dynamic string under construction in X. The value ++** returned by [sqlite3_str_value(X)] is managed by the sqlite3_str object X ++** and might be freed or altered by any subsequent method on the same ++** [sqlite3_str] object. Applications must not used the pointer returned ++** [sqlite3_str_value(X)] after any subsequent method call on the same ++** object. ^Applications may change the content of the string returned ++** by [sqlite3_str_value(X)] as long as they do not write into any bytes ++** outside the range of 0 to [sqlite3_str_length(X)] and do not read or ++** write any byte after any subsequent sqlite3_str method call. ++*/ ++SQLITE_API int sqlite3_str_errcode(sqlite3_str*); ++SQLITE_API int sqlite3_str_length(sqlite3_str*); ++SQLITE_API char *sqlite3_str_value(sqlite3_str*); ++ ++/* + ** CAPI3REF: SQLite Runtime Status + ** + ** ^These interfaces are used to retrieve runtime status information +@@ -7022,8 +7485,7 @@ + ** <dd>This parameter is the current amount of memory checked out + ** using [sqlite3_malloc()], either directly or indirectly. The + ** figure includes calls made to [sqlite3_malloc()] by the application +-** and internal memory usage by the SQLite library. Scratch memory +-** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache ++** and internal memory usage by the SQLite library. Auxiliary page-cache + ** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in + ** this parameter. The amount returned is the sum of the allocation + ** sizes as reported by the xSize method in [sqlite3_mem_methods].</dd>)^ +@@ -7061,29 +7523,14 @@ + ** *pHighwater parameter to [sqlite3_status()] is of interest. + ** The value written into the *pCurrent parameter is undefined.</dd>)^ + ** +-** [[SQLITE_STATUS_SCRATCH_USED]] ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt> +-** <dd>This parameter returns the number of allocations used out of the +-** [scratch memory allocator] configured using +-** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not +-** in bytes. Since a single thread may only have one scratch allocation +-** outstanding at time, this parameter also reports the number of threads +-** using scratch memory at the same time.</dd>)^ ++** [[SQLITE_STATUS_SCRATCH_USED]] <dt>SQLITE_STATUS_SCRATCH_USED</dt> ++** <dd>No longer used.</dd> + ** + ** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt> +-** <dd>This parameter returns the number of bytes of scratch memory +-** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH] +-** buffer and where forced to overflow to [sqlite3_malloc()]. The values +-** returned include overflows because the requested allocation was too +-** larger (that is, because the requested allocation was larger than the +-** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer +-** slots were available. +-** </dd>)^ ++** <dd>No longer used.</dd> + ** +-** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt> +-** <dd>This parameter records the largest memory allocation request +-** handed to [scratch memory allocator]. Only the value returned in the +-** *pHighwater parameter to [sqlite3_status()] is of interest. +-** The value written into the *pCurrent parameter is undefined.</dd>)^ ++** [[SQLITE_STATUS_SCRATCH_SIZE]] <dt>SQLITE_STATUS_SCRATCH_SIZE</dt> ++** <dd>No longer used.</dd> + ** + ** [[SQLITE_STATUS_PARSER_STACK]] ^(<dt>SQLITE_STATUS_PARSER_STACK</dt> + ** <dd>The *pHighwater parameter records the deepest parser stack. +@@ -7096,12 +7543,12 @@ + #define SQLITE_STATUS_MEMORY_USED 0 + #define SQLITE_STATUS_PAGECACHE_USED 1 + #define SQLITE_STATUS_PAGECACHE_OVERFLOW 2 +-#define SQLITE_STATUS_SCRATCH_USED 3 +-#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 ++#define SQLITE_STATUS_SCRATCH_USED 3 /* NOT USED */ ++#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 /* NOT USED */ + #define SQLITE_STATUS_MALLOC_SIZE 5 + #define SQLITE_STATUS_PARSER_STACK 6 + #define SQLITE_STATUS_PAGECACHE_SIZE 7 +-#define SQLITE_STATUS_SCRATCH_SIZE 8 ++#define SQLITE_STATUS_SCRATCH_SIZE 8 /* NOT USED */ + #define SQLITE_STATUS_MALLOC_COUNT 9 + + /* +@@ -7224,6 +7671,15 @@ + ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. + ** </dd> + ** ++** [[SQLITE_DBSTATUS_CACHE_SPILL]] ^(<dt>SQLITE_DBSTATUS_CACHE_SPILL</dt> ++** <dd>This parameter returns the number of dirty cache entries that have ++** been written to disk in the middle of a transaction due to the page ++** cache overflowing. Transactions are more efficient if they are written ++** to disk all at once. When pages spill mid-transaction, that introduces ++** additional overhead. This parameter can be used help identify ++** inefficiencies that can be resolve by increasing the cache size. ++** </dd> ++** + ** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt> + ** <dd>This parameter returns zero for the current value if and only if + ** all foreign key constraints (deferred or immediate) have been +@@ -7243,7 +7699,8 @@ + #define SQLITE_DBSTATUS_CACHE_WRITE 9 + #define SQLITE_DBSTATUS_DEFERRED_FKS 10 + #define SQLITE_DBSTATUS_CACHE_USED_SHARED 11 +-#define SQLITE_DBSTATUS_MAX 11 /* Largest defined DBSTATUS */ ++#define SQLITE_DBSTATUS_CACHE_SPILL 12 ++#define SQLITE_DBSTATUS_MAX 12 /* Largest defined DBSTATUS */ + + + /* +@@ -8198,6 +8655,7 @@ + ** can use to customize and optimize their behavior. + ** + ** <dl> ++** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]] + ** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT + ** <dd>Calls of the form + ** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported, +@@ -8244,6 +8702,40 @@ + SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *); + + /* ++** CAPI3REF: Determine If Virtual Table Column Access Is For UPDATE ++** ++** If the sqlite3_vtab_nochange(X) routine is called within the [xColumn] ++** method of a [virtual table], then it returns true if and only if the ++** column is being fetched as part of an UPDATE operation during which the ++** column value will not change. Applications might use this to substitute ++** a return value that is less expensive to compute and that the corresponding ++** [xUpdate] method understands as a "no-change" value. ++** ++** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that ++** the column is not changed by the UPDATE statement, then the xColumn ++** method can optionally return without setting a result, without calling ++** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces]. ++** In that case, [sqlite3_value_nochange(X)] will return true for the ++** same column in the [xUpdate] method. ++*/ ++SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*); ++ ++/* ++** CAPI3REF: Determine The Collation For a Virtual Table Constraint ++** ++** This function may only be called from within a call to the [xBestIndex] ++** method of a [virtual table]. ++** ++** The first argument must be the sqlite3_index_info object that is the ++** first parameter to the xBestIndex() method. The second argument must be ++** an index into the aConstraint[] array belonging to the sqlite3_index_info ++** structure passed to xBestIndex. This function returns a pointer to a buffer ++** containing the name of the collation sequence for the corresponding ++** constraint. ++*/ ++SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_info*,int); ++ ++/* + ** CAPI3REF: Conflict resolution modes + ** KEYWORDS: {conflict resolution mode} + ** +@@ -8513,7 +9005,6 @@ + /* + ** CAPI3REF: Database Snapshot + ** KEYWORDS: {snapshot} {sqlite3_snapshot} +-** EXPERIMENTAL + ** + ** An instance of the snapshot object records the state of a [WAL mode] + ** database for some specific point in history. +@@ -8530,11 +9021,6 @@ + ** version of the database file so that it is possible to later open a new read + ** transaction that sees that historical version of the database rather than + ** the most recent version. +-** +-** The constructor for this object is [sqlite3_snapshot_get()]. The +-** [sqlite3_snapshot_open()] method causes a fresh read transaction to refer +-** to an historical snapshot (if possible). The destructor for +-** sqlite3_snapshot objects is [sqlite3_snapshot_free()]. + */ + typedef struct sqlite3_snapshot { + unsigned char hidden[48]; +@@ -8542,7 +9028,7 @@ + + /* + ** CAPI3REF: Record A Database Snapshot +-** EXPERIMENTAL ++** CONSTRUCTOR: sqlite3_snapshot + ** + ** ^The [sqlite3_snapshot_get(D,S,P)] interface attempts to make a + ** new [sqlite3_snapshot] object that records the current state of +@@ -8558,7 +9044,7 @@ + ** in this case. + ** + ** <ul> +-** <li> The database handle must be in [autocommit mode]. ++** <li> The database handle must not be in [autocommit mode]. + ** + ** <li> Schema S of [database connection] D must be a [WAL mode] database. + ** +@@ -8581,7 +9067,7 @@ + ** to avoid a memory leak. + ** + ** The [sqlite3_snapshot_get()] interface is only available when the +-** SQLITE_ENABLE_SNAPSHOT compile-time option is used. ++** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. + */ + SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get( + sqlite3 *db, +@@ -8591,24 +9077,35 @@ + + /* + ** CAPI3REF: Start a read transaction on an historical snapshot +-** EXPERIMENTAL ++** METHOD: sqlite3_snapshot + ** +-** ^The [sqlite3_snapshot_open(D,S,P)] interface starts a +-** read transaction for schema S of +-** [database connection] D such that the read transaction +-** refers to historical [snapshot] P, rather than the most +-** recent change to the database. +-** ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK on success +-** or an appropriate [error code] if it fails. ++** ^The [sqlite3_snapshot_open(D,S,P)] interface either starts a new read ++** transaction or upgrades an existing one for schema S of ++** [database connection] D such that the read transaction refers to ++** historical [snapshot] P, rather than the most recent change to the ++** database. ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK ++** on success or an appropriate [error code] if it fails. + ** +-** ^In order to succeed, a call to [sqlite3_snapshot_open(D,S,P)] must be +-** the first operation following the [BEGIN] that takes the schema S +-** out of [autocommit mode]. +-** ^In other words, schema S must not currently be in +-** a transaction for [sqlite3_snapshot_open(D,S,P)] to work, but the +-** database connection D must be out of [autocommit mode]. +-** ^A [snapshot] will fail to open if it has been overwritten by a +-** [checkpoint]. ++** ^In order to succeed, the database connection must not be in ++** [autocommit mode] when [sqlite3_snapshot_open(D,S,P)] is called. If there ++** is already a read transaction open on schema S, then the database handle ++** must have no active statements (SELECT statements that have been passed ++** to sqlite3_step() but not sqlite3_reset() or sqlite3_finalize()). ++** SQLITE_ERROR is returned if either of these conditions is violated, or ++** if schema S does not exist, or if the snapshot object is invalid. ++** ++** ^A call to sqlite3_snapshot_open() will fail to open if the specified ++** snapshot has been overwritten by a [checkpoint]. In this case ++** SQLITE_ERROR_SNAPSHOT is returned. ++** ++** If there is already a read transaction open when this function is ++** invoked, then the same read transaction remains open (on the same ++** database snapshot) if SQLITE_ERROR, SQLITE_BUSY or SQLITE_ERROR_SNAPSHOT ++** is returned. If another error code - for example SQLITE_PROTOCOL or an ++** SQLITE_IOERR error code - is returned, then the final state of the ++** read transaction is undefined. If SQLITE_OK is returned, then the ++** read transaction is now open on database snapshot P. ++** + ** ^(A call to [sqlite3_snapshot_open(D,S,P)] will fail if the + ** database connection D does not know that the database file for + ** schema S is in [WAL mode]. A database connection might not know +@@ -8619,7 +9116,7 @@ + ** database connection in order to make it ready to use snapshots.) + ** + ** The [sqlite3_snapshot_open()] interface is only available when the +-** SQLITE_ENABLE_SNAPSHOT compile-time option is used. ++** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. + */ + SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open( + sqlite3 *db, +@@ -8629,7 +9126,7 @@ + + /* + ** CAPI3REF: Destroy a snapshot +-** EXPERIMENTAL ++** DESTRUCTOR: sqlite3_snapshot + ** + ** ^The [sqlite3_snapshot_free(P)] interface destroys [sqlite3_snapshot] P. + ** The application must eventually free every [sqlite3_snapshot] object +@@ -8636,13 +9133,13 @@ + ** using this routine to avoid a memory leak. + ** + ** The [sqlite3_snapshot_free()] interface is only available when the +-** SQLITE_ENABLE_SNAPSHOT compile-time option is used. ++** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. + */ + SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*); + + /* + ** CAPI3REF: Compare the ages of two snapshot handles. +-** EXPERIMENTAL ++** METHOD: sqlite3_snapshot + ** + ** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages + ** of two valid snapshot handles. +@@ -8661,6 +9158,9 @@ + ** Otherwise, this API returns a negative value if P1 refers to an older + ** snapshot than P2, zero if the two handles refer to the same database + ** snapshot, and a positive value if P1 is a newer snapshot than P2. ++** ++** This interface is only available if SQLite is compiled with the ++** [SQLITE_ENABLE_SNAPSHOT] option. + */ + SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( + sqlite3_snapshot *p1, +@@ -8669,27 +9169,152 @@ + + /* + ** CAPI3REF: Recover snapshots from a wal file +-** EXPERIMENTAL ++** METHOD: sqlite3_snapshot + ** +-** If all connections disconnect from a database file but do not perform +-** a checkpoint, the existing wal file is opened along with the database +-** file the next time the database is opened. At this point it is only +-** possible to successfully call sqlite3_snapshot_open() to open the most +-** recent snapshot of the database (the one at the head of the wal file), +-** even though the wal file may contain other valid snapshots for which +-** clients have sqlite3_snapshot handles. ++** If a [WAL file] remains on disk after all database connections close ++** (either through the use of the [SQLITE_FCNTL_PERSIST_WAL] [file control] ++** or because the last process to have the database opened exited without ++** calling [sqlite3_close()]) and a new connection is subsequently opened ++** on that database and [WAL file], the [sqlite3_snapshot_open()] interface ++** will only be able to open the last transaction added to the WAL file ++** even though the WAL file contains other valid transactions. + ** +-** This function attempts to scan the wal file associated with database zDb ++** This function attempts to scan the WAL file associated with database zDb + ** of database handle db and make all valid snapshots available to + ** sqlite3_snapshot_open(). It is an error if there is already a read +-** transaction open on the database, or if the database is not a wal mode ++** transaction open on the database, or if the database is not a WAL mode + ** database. + ** + ** SQLITE_OK is returned if successful, or an SQLite error code otherwise. ++** ++** This interface is only available if SQLite is compiled with the ++** [SQLITE_ENABLE_SNAPSHOT] option. + */ + SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); + + /* ++** CAPI3REF: Serialize a database ++** ++** The sqlite3_serialize(D,S,P,F) interface returns a pointer to memory ++** that is a serialization of the S database on [database connection] D. ++** If P is not a NULL pointer, then the size of the database in bytes ++** is written into *P. ++** ++** For an ordinary on-disk database file, the serialization is just a ++** copy of the disk file. For an in-memory database or a "TEMP" database, ++** the serialization is the same sequence of bytes which would be written ++** to disk if that database where backed up to disk. ++** ++** The usual case is that sqlite3_serialize() copies the serialization of ++** the database into memory obtained from [sqlite3_malloc64()] and returns ++** a pointer to that memory. The caller is responsible for freeing the ++** returned value to avoid a memory leak. However, if the F argument ++** contains the SQLITE_SERIALIZE_NOCOPY bit, then no memory allocations ++** are made, and the sqlite3_serialize() function will return a pointer ++** to the contiguous memory representation of the database that SQLite ++** is currently using for that database, or NULL if the no such contiguous ++** memory representation of the database exists. A contiguous memory ++** representation of the database will usually only exist if there has ++** been a prior call to [sqlite3_deserialize(D,S,...)] with the same ++** values of D and S. ++** The size of the database is written into *P even if the ++** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy ++** of the database exists. ++** ++** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the ++** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory ++** allocation error occurs. ++** ++** This interface is only available if SQLite is compiled with the ++** [SQLITE_ENABLE_DESERIALIZE] option. ++*/ ++SQLITE_API unsigned char *sqlite3_serialize( ++ sqlite3 *db, /* The database connection */ ++ const char *zSchema, /* Which DB to serialize. ex: "main", "temp", ... */ ++ sqlite3_int64 *piSize, /* Write size of the DB here, if not NULL */ ++ unsigned int mFlags /* Zero or more SQLITE_SERIALIZE_* flags */ ++); ++ ++/* ++** CAPI3REF: Flags for sqlite3_serialize ++** ++** Zero or more of the following constants can be OR-ed together for ++** the F argument to [sqlite3_serialize(D,S,P,F)]. ++** ++** SQLITE_SERIALIZE_NOCOPY means that [sqlite3_serialize()] will return ++** a pointer to contiguous in-memory database that it is currently using, ++** without making a copy of the database. If SQLite is not currently using ++** a contiguous in-memory database, then this option causes ++** [sqlite3_serialize()] to return a NULL pointer. SQLite will only be ++** using a contiguous in-memory database if it has been initialized by a ++** prior call to [sqlite3_deserialize()]. ++*/ ++#define SQLITE_SERIALIZE_NOCOPY 0x001 /* Do no memory allocations */ ++ ++/* ++** CAPI3REF: Deserialize a database ++** ++** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the ++** [database connection] D to disconnect from database S and then ++** reopen S as an in-memory database based on the serialization contained ++** in P. The serialized database P is N bytes in size. M is the size of ++** the buffer P, which might be larger than N. If M is larger than N, and ++** the SQLITE_DESERIALIZE_READONLY bit is not set in F, then SQLite is ++** permitted to add content to the in-memory database as long as the total ++** size does not exceed M bytes. ++** ++** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will ++** invoke sqlite3_free() on the serialization buffer when the database ++** connection closes. If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then ++** SQLite will try to increase the buffer size using sqlite3_realloc64() ++** if writes on the database cause it to grow larger than M bytes. ++** ++** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the ++** database is currently in a read transaction or is involved in a backup ++** operation. ++** ++** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the ++** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then ++** [sqlite3_free()] is invoked on argument P prior to returning. ++** ++** This interface is only available if SQLite is compiled with the ++** [SQLITE_ENABLE_DESERIALIZE] option. ++*/ ++SQLITE_API int sqlite3_deserialize( ++ sqlite3 *db, /* The database connection */ ++ const char *zSchema, /* Which DB to reopen with the deserialization */ ++ unsigned char *pData, /* The serialized database content */ ++ sqlite3_int64 szDb, /* Number bytes in the deserialization */ ++ sqlite3_int64 szBuf, /* Total size of buffer pData[] */ ++ unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */ ++); ++ ++/* ++** CAPI3REF: Flags for sqlite3_deserialize() ++** ++** The following are allowed values for 6th argument (the F argument) to ++** the [sqlite3_deserialize(D,S,P,N,M,F)] interface. ++** ++** The SQLITE_DESERIALIZE_FREEONCLOSE means that the database serialization ++** in the P argument is held in memory obtained from [sqlite3_malloc64()] ++** and that SQLite should take ownership of this memory and automatically ++** free it when it has finished using it. Without this flag, the caller ++** is responsible for freeing any dynamically allocated memory. ++** ++** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to ++** grow the size of the database using calls to [sqlite3_realloc64()]. This ++** flag should only be used if SQLITE_DESERIALIZE_FREEONCLOSE is also used. ++** Without this flag, the deserialized database cannot increase in size beyond ++** the number of bytes specified by the M parameter. ++** ++** The SQLITE_DESERIALIZE_READONLY flag means that the deserialized database ++** should be treated as read-only. ++*/ ++#define SQLITE_DESERIALIZE_FREEONCLOSE 1 /* Call sqlite3_free() on close */ ++#define SQLITE_DESERIALIZE_RESIZEABLE 2 /* Resize using sqlite3_realloc64() */ ++#define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */ ++ ++/* + ** Undo the hack that converts floating point types to integer for + ** builds on processors without floating point support. + */ +@@ -8800,7 +9425,7 @@ + sqlite3_int64 iRowid; /* Rowid for current entry */ + sqlite3_rtree_dbl rParentScore; /* Score of parent node */ + int eParentWithin; /* Visibility of parent node */ +- int eWithin; /* OUT: Visiblity */ ++ int eWithin; /* OUT: Visibility */ + sqlite3_rtree_dbl rScore; /* OUT: Write the score here */ + /* The following fields are only available in 3.8.11 and later */ + sqlite3_value **apSqlParam; /* Original SQL values of parameters */ +@@ -8836,16 +9461,23 @@ + + /* + ** CAPI3REF: Session Object Handle ++** ++** An instance of this object is a [session] that can be used to ++** record changes to a database. + */ + typedef struct sqlite3_session sqlite3_session; + + /* + ** CAPI3REF: Changeset Iterator Handle ++** ++** An instance of this object acts as a cursor for iterating ++** over the elements of a [changeset] or [patchset]. + */ + typedef struct sqlite3_changeset_iter sqlite3_changeset_iter; + + /* + ** CAPI3REF: Create A New Session Object ++** CONSTRUCTOR: sqlite3_session + ** + ** Create a new session object attached to database handle db. If successful, + ** a pointer to the new object is written to *ppSession and SQLITE_OK is +@@ -8882,6 +9514,7 @@ + + /* + ** CAPI3REF: Delete A Session Object ++** DESTRUCTOR: sqlite3_session + ** + ** Delete a session object previously allocated using + ** [sqlite3session_create()]. Once a session object has been deleted, the +@@ -8897,6 +9530,7 @@ + + /* + ** 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 +@@ -8916,6 +9550,7 @@ + + /* + ** CAPI3REF: Set Or Clear the Indirect Change Flag ++** METHOD: sqlite3_session + ** + ** Each change recorded by a session object is marked as either direct or + ** indirect. A change is marked as indirect if either: +@@ -8945,6 +9580,7 @@ + + /* + ** CAPI3REF: Attach A Table To A Session Object ++** METHOD: sqlite3_session + ** + ** If argument zTab is not NULL, then it is the name of a table to attach + ** to the session object passed as the first argument. All subsequent changes +@@ -8970,6 +9606,35 @@ + ** + ** SQLITE_OK is returned if the call completes without error. Or, if an error + ** occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned. ++** ++** <h3>Special sqlite_stat1 Handling</h3> ++** ++** As of SQLite version 3.22.0, the "sqlite_stat1" table is an exception to ++** some of the rules above. In SQLite, the schema of sqlite_stat1 is: ++** <pre> ++** CREATE TABLE sqlite_stat1(tbl,idx,stat) ++** </pre> ++** ++** Even though sqlite_stat1 does not have a PRIMARY KEY, changes are ++** recorded for it as if the PRIMARY KEY is (tbl,idx). Additionally, changes ++** are recorded for rows for which (idx IS NULL) is true. However, for such ++** rows a zero-length blob (SQL value X'') is stored in the changeset or ++** patchset instead of a NULL value. This allows such changesets to be ++** manipulated by legacy implementations of sqlite3changeset_invert(), ++** concat() and similar. ++** ++** The sqlite3changeset_apply() function automatically converts the ++** zero-length blob back to a NULL value when updating the sqlite_stat1 ++** table. However, if the application calls sqlite3changeset_new(), ++** sqlite3changeset_old() or sqlite3changeset_conflict on a changeset ++** iterator directly (including on a changeset iterator passed to a ++** conflict-handler callback) then the X'' value is returned. The application ++** must translate X'' to NULL itself if required. ++** ++** Legacy (older than 3.22.0) versions of the sessions module cannot capture ++** changes made to the sqlite_stat1 table. Legacy versions of the ++** sqlite3changeset_apply() function silently ignore any modifications to the ++** sqlite_stat1 table that are part of a changeset or patchset. + */ + SQLITE_API int sqlite3session_attach( + sqlite3_session *pSession, /* Session object */ +@@ -8978,6 +9643,7 @@ + + /* + ** CAPI3REF: Set a table filter on a Session Object. ++** METHOD: sqlite3_session + ** + ** The second argument (xFilter) is the "filter callback". For changes to rows + ** in tables that are not attached to the Session object, the filter is called +@@ -8996,6 +9662,7 @@ + + /* + ** CAPI3REF: Generate A Changeset From A Session Object ++** METHOD: sqlite3_session + ** + ** Obtain a changeset containing changes to the tables attached to the + ** session object passed as the first argument. If successful, +@@ -9105,7 +9772,8 @@ + ); + + /* +-** CAPI3REF: Load The Difference Between Tables Into A Session ++** CAPI3REF: Load The Difference Between Tables Into A Session ++** METHOD: sqlite3_session + ** + ** If it is not already attached to the session object passed as the first + ** argument, this function attaches table zTbl in the same manner as the +@@ -9170,6 +9838,7 @@ + + /* + ** CAPI3REF: Generate A Patchset From A Session Object ++** METHOD: sqlite3_session + ** + ** The differences between a patchset and a changeset are that: + ** +@@ -9198,8 +9867,8 @@ + */ + SQLITE_API int sqlite3session_patchset( + sqlite3_session *pSession, /* Session object */ +- int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */ +- void **ppPatchset /* OUT: Buffer containing changeset */ ++ int *pnPatchset, /* OUT: Size of buffer at *ppPatchset */ ++ void **ppPatchset /* OUT: Buffer containing patchset */ + ); + + /* +@@ -9221,6 +9890,7 @@ + + /* + ** CAPI3REF: Create An Iterator To Traverse A Changeset ++** CONSTRUCTOR: sqlite3_changeset_iter + ** + ** Create an iterator used to iterate through the contents of a changeset. + ** If successful, *pp is set to point to the iterator handle and SQLITE_OK +@@ -9251,6 +9921,13 @@ + ** consecutively. There is no chance that the iterator will visit a change + ** the applies to table X, then one for table Y, and then later on visit + ** another change for table X. ++** ++** The behavior of sqlite3changeset_start_v2() and its streaming equivalent ++** may be modified by passing a combination of ++** [SQLITE_CHANGESETSTART_INVERT | supported flags] as the 4th parameter. ++** ++** Note that the sqlite3changeset_start_v2() API is still <b>experimental</b> ++** and therefore subject to change. + */ + SQLITE_API int sqlite3changeset_start( + sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ +@@ -9257,10 +9934,30 @@ + int nChangeset, /* Size of changeset blob in bytes */ + void *pChangeset /* Pointer to blob containing changeset */ + ); ++SQLITE_API int sqlite3changeset_start_v2( ++ sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ ++ int nChangeset, /* Size of changeset blob in bytes */ ++ void *pChangeset, /* Pointer to blob containing changeset */ ++ int flags /* SESSION_CHANGESETSTART_* flags */ ++); + ++/* ++** CAPI3REF: Flags for sqlite3changeset_start_v2 ++** ++** The following flags may passed via the 4th parameter to ++** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]: ++** ++** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd> ++** Invert the changeset while iterating through 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_CHANGESETSTART_INVERT 0x0002 + ++ + /* + ** CAPI3REF: Advance A Changeset Iterator ++** METHOD: sqlite3_changeset_iter + ** + ** This function may only be used with iterators created by function + ** [sqlite3changeset_start()]. If it is called on an iterator passed to +@@ -9285,6 +9982,7 @@ + + /* + ** CAPI3REF: Obtain The Current Operation From A Changeset Iterator ++** METHOD: sqlite3_changeset_iter + ** + ** The pIter argument passed to this function may either be an iterator + ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator +@@ -9319,6 +10017,7 @@ + + /* + ** CAPI3REF: Obtain The Primary Key Definition Of A Table ++** METHOD: sqlite3_changeset_iter + ** + ** For each modified table, a changeset includes the following: + ** +@@ -9350,6 +10049,7 @@ + + /* + ** CAPI3REF: Obtain old.* Values From A Changeset Iterator ++** METHOD: sqlite3_changeset_iter + ** + ** The pIter argument passed to this function may either be an iterator + ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator +@@ -9380,6 +10080,7 @@ + + /* + ** CAPI3REF: Obtain new.* Values From A Changeset Iterator ++** METHOD: sqlite3_changeset_iter + ** + ** The pIter argument passed to this function may either be an iterator + ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator +@@ -9413,6 +10114,7 @@ + + /* + ** CAPI3REF: Obtain Conflicting Row Values From A Changeset Iterator ++** METHOD: sqlite3_changeset_iter + ** + ** This function should only be used with iterator objects passed to a + ** conflict-handler callback by [sqlite3changeset_apply()] with either +@@ -9440,6 +10142,7 @@ + + /* + ** CAPI3REF: Determine The Number Of Foreign Key Constraint Violations ++** METHOD: sqlite3_changeset_iter + ** + ** This function may only be called with an iterator passed to an + ** SQLITE_CHANGESET_FOREIGN_KEY conflict handler callback. In this case +@@ -9456,6 +10159,7 @@ + + /* + ** CAPI3REF: Finalize A Changeset Iterator ++** METHOD: sqlite3_changeset_iter + ** + ** This function is used to finalize an iterator allocated with + ** [sqlite3changeset_start()]. +@@ -9472,6 +10176,7 @@ + ** to that error is returned by this function. Otherwise, SQLITE_OK is + ** returned. This is to allow the following pattern (pseudo-code): + ** ++** <pre> + ** sqlite3changeset_start(); + ** while( SQLITE_ROW==sqlite3changeset_next() ){ + ** // Do something with change. +@@ -9480,6 +10185,7 @@ + ** if( rc!=SQLITE_OK ){ + ** // An error has occurred + ** } ++** </pre> + */ + SQLITE_API int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); + +@@ -9527,6 +10233,7 @@ + ** sqlite3_changegroup object. Calling it produces similar results as the + ** following code fragment: + ** ++** <pre> + ** sqlite3_changegroup *pGrp; + ** rc = sqlite3_changegroup_new(&pGrp); + ** if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nA, pA); +@@ -9537,6 +10244,7 @@ + ** *ppOut = 0; + ** *pnOut = 0; + ** } ++** </pre> + ** + ** Refer to the sqlite3_changegroup documentation below for details. + */ +@@ -9552,11 +10260,15 @@ + + /* + ** CAPI3REF: Changegroup Handle ++** ++** A changegroup is an object used to combine two or more ++** [changesets] or [patchsets] + */ + typedef struct sqlite3_changegroup sqlite3_changegroup; + + /* + ** CAPI3REF: Create A New Changegroup Object ++** CONSTRUCTOR: sqlite3_changegroup + ** + ** An sqlite3_changegroup object is used to combine two or more changesets + ** (or patchsets) into a single changeset (or patchset). A single changegroup +@@ -9594,6 +10306,7 @@ + + /* + ** CAPI3REF: Add A Changeset To A Changegroup ++** METHOD: sqlite3_changegroup + ** + ** Add all changes within the changeset (or patchset) in buffer pData (size + ** nData bytes) to the changegroup. +@@ -9671,6 +10384,7 @@ + + /* + ** CAPI3REF: Obtain A Composite Changeset From A Changegroup ++** METHOD: sqlite3_changegroup + ** + ** Obtain a buffer containing a changeset (or patchset) representing the + ** current contents of the changegroup. If the inputs to the changegroup +@@ -9701,6 +10415,7 @@ + + /* + ** CAPI3REF: Delete A Changegroup Object ++** DESTRUCTOR: sqlite3_changegroup + */ + SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); + +@@ -9707,19 +10422,18 @@ + /* + ** CAPI3REF: Apply A Changeset To A Database + ** +-** Apply a changeset to a database. This function attempts to update the +-** "main" database attached to handle db with the changes found in the +-** changeset passed via the second and third arguments. ++** Apply a changeset or patchset to a database. These functions attempt to ++** update the "main" database attached to handle db with the changes found in ++** the changeset passed via the second and third arguments. + ** +-** The fourth argument (xFilter) passed to this function is the "filter ++** The fourth argument (xFilter) passed to these functions is the "filter + ** callback". If it is not NULL, then for each table affected by at least one + ** change in the changeset, the filter callback is invoked with + ** the table name as the second argument, and a copy of the context pointer +-** passed as the sixth argument to this function as the first. If the "filter +-** callback" returns zero, then no attempt is made to apply any changes to +-** the table. Otherwise, if the return value is non-zero or the xFilter +-** argument to this function is NULL, all changes related to the table are +-** attempted. ++** passed as the sixth argument as the first. If the "filter callback" ++** returns zero, then no attempt is made to apply any changes to the table. ++** Otherwise, if the return value is non-zero or the xFilter argument to ++** is NULL, all changes related to the table are attempted. + ** + ** For each table that is not excluded by the filter callback, this function + ** tests that the target database contains a compatible table. A table is +@@ -9764,7 +10478,7 @@ + ** + ** <dl> + ** <dt>DELETE Changes<dd> +-** For each DELETE change, this function checks if the target database ++** For each DELETE change, the function checks if the target database + ** contains a row with the same primary key value (or values) as the + ** original row values stored in the changeset. If it does, and the values + ** stored in all non-primary key columns also match the values stored in +@@ -9809,7 +10523,7 @@ + ** [SQLITE_CHANGESET_REPLACE]. + ** + ** <dt>UPDATE Changes<dd> +-** For each UPDATE change, this function checks if the target database ++** For each UPDATE change, the function checks if the target database + ** contains a row with the same primary key value (or values) as the + ** original row values stored in the changeset. If it does, and the values + ** stored in all modified non-primary key columns also match the values +@@ -9840,11 +10554,28 @@ + ** This can be used to further customize the applications conflict + ** resolution strategy. + ** +-** All changes made by this function are enclosed in a savepoint transaction. ++** All changes made by these functions are enclosed in a savepoint transaction. + ** If any other error (aside from a constraint failure when attempting to + ** write to the target database) occurs, then the savepoint transaction is + ** rolled back, restoring the target database to its original state, and an + ** SQLite error code returned. ++** ++** If the output parameters (ppRebase) and (pnRebase) are non-NULL and ++** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2() ++** may set (*ppRebase) to point to a "rebase" that may be used with the ++** sqlite3_rebaser APIs buffer before returning. In this case (*pnRebase) ++** is set to the size of the buffer in bytes. It is the responsibility of the ++** caller to eventually free any such buffer using sqlite3_free(). The buffer ++** is only allocated and populated if one or more conflicts were encountered ++** while applying the patchset. See comments surrounding the sqlite3_rebaser ++** APIs for further details. ++** ++** The behavior of sqlite3changeset_apply_v2() and its streaming equivalent ++** may be modified by passing a combination of ++** [SQLITE_CHANGESETAPPLY_NOSAVEPOINT | supported flags] as the 9th parameter. ++** ++** Note that the sqlite3changeset_apply_v2() API is still <b>experimental</b> ++** and therefore subject to change. + */ + SQLITE_API int sqlite3changeset_apply( + sqlite3 *db, /* Apply change to "main" db of this handle */ +@@ -9861,7 +10592,48 @@ + ), + void *pCtx /* First argument passed to xConflict */ + ); ++SQLITE_API int sqlite3changeset_apply_v2( ++ sqlite3 *db, /* Apply change to "main" db of this handle */ ++ int nChangeset, /* Size of changeset in bytes */ ++ void *pChangeset, /* Changeset blob */ ++ int(*xFilter)( ++ void *pCtx, /* Copy of sixth arg to _apply() */ ++ const char *zTab /* Table name */ ++ ), ++ int(*xConflict)( ++ void *pCtx, /* Copy of sixth arg to _apply() */ ++ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ ++ sqlite3_changeset_iter *p /* Handle describing change and conflict */ ++ ), ++ void *pCtx, /* First argument passed to xConflict */ ++ void **ppRebase, int *pnRebase, /* OUT: Rebase data */ ++ int flags /* SESSION_CHANGESETAPPLY_* flags */ ++); + ++/* ++** CAPI3REF: Flags for sqlite3changeset_apply_v2 ++** ++** The following flags may passed via the 9th parameter to ++** [sqlite3changeset_apply_v2] and [sqlite3changeset_apply_v2_strm]: ++** ++** <dl> ++** <dt>SQLITE_CHANGESETAPPLY_NOSAVEPOINT <dd> ++** Usually, the sessions module encloses all operations performed by ++** a single call to apply_v2() or apply_v2_strm() in a [SAVEPOINT]. The ++** SAVEPOINT is committed if the changeset or patchset is successfully ++** applied, or rolled back if an error occurs. Specifying this flag ++** causes the sessions module to omit this savepoint. In this case, if the ++** 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 + ** +@@ -9958,7 +10730,162 @@ + #define SQLITE_CHANGESET_REPLACE 1 + #define SQLITE_CHANGESET_ABORT 2 + ++/* ++** CAPI3REF: Rebasing changesets ++** EXPERIMENTAL ++** ++** Suppose there is a site hosting a database in state S0. And that ++** modifications are made that move that database to state S1 and a ++** changeset recorded (the "local" changeset). Then, a changeset based ++** on S0 is received from another site (the "remote" changeset) and ++** applied to the database. The database is then in state ++** (S1+"remote"), where the exact state depends on any conflict ++** resolution decisions (OMIT or REPLACE) made while applying "remote". ++** Rebasing a changeset is to update it to take those conflict ++** resolution decisions into account, so that the same conflicts ++** do not have to be resolved elsewhere in the network. ++** ++** For example, if both the local and remote changesets contain an ++** INSERT of the same key on "CREATE TABLE t1(a PRIMARY KEY, b)": ++** ++** local: INSERT INTO t1 VALUES(1, 'v1'); ++** remote: INSERT INTO t1 VALUES(1, 'v2'); ++** ++** and the conflict resolution is REPLACE, then the INSERT change is ++** removed from the local changeset (it was overridden). Or, if the ++** conflict resolution was "OMIT", then the local changeset is modified ++** to instead contain: ++** ++** UPDATE t1 SET b = 'v2' WHERE a=1; ++** ++** Changes within the local changeset are rebased as follows: ++** ++** <dl> ++** <dt>Local INSERT<dd> ++** This may only conflict with a remote INSERT. If the conflict ++** resolution was OMIT, then add an UPDATE change to the rebased ++** changeset. Or, if the conflict resolution was REPLACE, add ++** nothing to the rebased changeset. ++** ++** <dt>Local DELETE<dd> ++** This may conflict with a remote UPDATE or DELETE. In both cases the ++** only possible resolution is OMIT. If the remote operation was a ++** DELETE, then add no change to the rebased changeset. If the remote ++** operation was an UPDATE, then the old.* fields of change are updated ++** to reflect the new.* values in the UPDATE. ++** ++** <dt>Local UPDATE<dd> ++** This may conflict with a remote UPDATE or DELETE. If it conflicts ++** with a DELETE, and the conflict resolution was OMIT, then the update ++** is changed into an INSERT. Any undefined values in the new.* record ++** from the update change are filled in using the old.* values from ++** the conflicting DELETE. Or, if the conflict resolution was REPLACE, ++** the UPDATE change is simply omitted from the rebased changeset. ++** ++** If conflict is with a remote UPDATE and the resolution is OMIT, then ++** the old.* values are rebased using the new.* values in the remote ++** change. Or, if the resolution is REPLACE, then the change is copied ++** into the rebased changeset with updates to columns also updated by ++** the conflicting remote UPDATE removed. If this means no columns would ++** be updated, the change is omitted. ++** </dl> ++** ++** A local change may be rebased against multiple remote changes ++** simultaneously. If a single key is modified by multiple remote ++** changesets, they are combined as follows before the local changeset ++** is rebased: ++** ++** <ul> ++** <li> If there has been one or more REPLACE resolutions on a ++** key, it is rebased according to a REPLACE. ++** ++** <li> If there have been no REPLACE resolutions on a key, then ++** the local changeset is rebased according to the most recent ++** of the OMIT resolutions. ++** </ul> ++** ++** Note that conflict resolutions from multiple remote changesets are ++** combined on a per-field basis, not per-row. This means that in the ++** case of multiple remote UPDATE operations, some fields of a single ++** local change may be rebased for REPLACE while others are rebased for ++** OMIT. ++** ++** In order to rebase a local changeset, the remote changeset must first ++** be applied to the local database using sqlite3changeset_apply_v2() and ++** the buffer of rebase information captured. Then: ++** ++** <ol> ++** <li> An sqlite3_rebaser object is created by calling ++** sqlite3rebaser_create(). ++** <li> The new object is configured with the rebase buffer obtained from ++** sqlite3changeset_apply_v2() by calling sqlite3rebaser_configure(). ++** If the local changeset is to be rebased against multiple remote ++** changesets, then sqlite3rebaser_configure() should be called ++** multiple times, in the same order that the multiple ++** sqlite3changeset_apply_v2() calls were made. ++** <li> Each local changeset is rebased by calling sqlite3rebaser_rebase(). ++** <li> The sqlite3_rebaser object is deleted by calling ++** sqlite3rebaser_delete(). ++** </ol> ++*/ ++typedef struct sqlite3_rebaser sqlite3_rebaser; ++ + /* ++** CAPI3REF: Create a changeset rebaser object. ++** EXPERIMENTAL ++** ++** Allocate a new changeset rebaser object. If successful, set (*ppNew) to ++** point to the new object and return SQLITE_OK. Otherwise, if an error ++** occurs, return an SQLite error code (e.g. SQLITE_NOMEM) and set (*ppNew) ++** to NULL. ++*/ ++SQLITE_API int sqlite3rebaser_create(sqlite3_rebaser **ppNew); ++ ++/* ++** CAPI3REF: Configure a changeset rebaser object. ++** EXPERIMENTAL ++** ++** Configure the changeset rebaser object to rebase changesets according ++** to the conflict resolutions described by buffer pRebase (size nRebase ++** bytes), which must have been obtained from a previous call to ++** sqlite3changeset_apply_v2(). ++*/ ++SQLITE_API int sqlite3rebaser_configure( ++ sqlite3_rebaser*, ++ int nRebase, const void *pRebase ++); ++ ++/* ++** CAPI3REF: Rebase a changeset ++** EXPERIMENTAL ++** ++** Argument pIn must point to a buffer containing a changeset nIn bytes ++** in size. This function allocates and populates a buffer with a copy ++** of the changeset rebased rebased according to the configuration of the ++** rebaser object passed as the first argument. If successful, (*ppOut) ++** is set to point to the new buffer containing the rebased changset and ++** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the ++** responsibility of the caller to eventually free the new buffer using ++** sqlite3_free(). Otherwise, if an error occurs, (*ppOut) and (*pnOut) ++** are set to zero and an SQLite error code returned. ++*/ ++SQLITE_API int sqlite3rebaser_rebase( ++ sqlite3_rebaser*, ++ int nIn, const void *pIn, ++ int *pnOut, void **ppOut ++); ++ ++/* ++** CAPI3REF: Delete a changeset rebaser object. ++** EXPERIMENTAL ++** ++** Delete the changeset rebaser object and all associated resources. There ++** should be one call to this function for each successful invocation ++** of sqlite3rebaser_create(). ++*/ ++SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p); ++ ++/* + ** CAPI3REF: Streaming Versions of API functions. + ** + ** The six streaming API xxx_strm() functions serve similar purposes to the +@@ -9966,12 +10893,13 @@ + ** + ** <table border=1 style="margin-left:8ex;margin-right:8ex"> + ** <tr><th>Streaming function<th>Non-streaming equivalent</th> +-** <tr><td>sqlite3changeset_apply_str<td>[sqlite3changeset_apply] +-** <tr><td>sqlite3changeset_concat_str<td>[sqlite3changeset_concat] +-** <tr><td>sqlite3changeset_invert_str<td>[sqlite3changeset_invert] +-** <tr><td>sqlite3changeset_start_str<td>[sqlite3changeset_start] +-** <tr><td>sqlite3session_changeset_str<td>[sqlite3session_changeset] +-** <tr><td>sqlite3session_patchset_str<td>[sqlite3session_patchset] ++** <tr><td>sqlite3changeset_apply_strm<td>[sqlite3changeset_apply] ++** <tr><td>sqlite3changeset_apply_strm_v2<td>[sqlite3changeset_apply_v2] ++** <tr><td>sqlite3changeset_concat_strm<td>[sqlite3changeset_concat] ++** <tr><td>sqlite3changeset_invert_strm<td>[sqlite3changeset_invert] ++** <tr><td>sqlite3changeset_start_strm<td>[sqlite3changeset_start] ++** <tr><td>sqlite3session_changeset_strm<td>[sqlite3session_changeset] ++** <tr><td>sqlite3session_patchset_strm<td>[sqlite3session_patchset] + ** </table> + ** + ** Non-streaming functions that accept changesets (or patchsets) as input +@@ -10062,6 +10990,23 @@ + ), + void *pCtx /* First argument passed to xConflict */ + ); ++SQLITE_API int sqlite3changeset_apply_v2_strm( ++ sqlite3 *db, /* Apply change to "main" db of this handle */ ++ int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ ++ void *pIn, /* First arg for xInput */ ++ int(*xFilter)( ++ void *pCtx, /* Copy of sixth arg to _apply() */ ++ const char *zTab /* Table name */ ++ ), ++ int(*xConflict)( ++ void *pCtx, /* Copy of sixth arg to _apply() */ ++ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ ++ sqlite3_changeset_iter *p /* Handle describing change and conflict */ ++ ), ++ void *pCtx, /* First argument passed to xConflict */ ++ void **ppRebase, int *pnRebase, ++ int flags ++); + SQLITE_API int sqlite3changeset_concat_strm( + int (*xInputA)(void *pIn, void *pData, int *pnData), + void *pInA, +@@ -10081,6 +11026,12 @@ + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn + ); ++SQLITE_API int sqlite3changeset_start_v2_strm( ++ sqlite3_changeset_iter **pp, ++ int (*xInput)(void *pIn, void *pData, int *pnData), ++ void *pIn, ++ int flags ++); + SQLITE_API int sqlite3session_changeset_strm( + sqlite3_session *pSession, + int (*xOutput)(void *pOut, const void *pData, int nData), +@@ -10099,9 +11050,55 @@ + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut + ); ++SQLITE_API int sqlite3rebaser_rebase_strm( ++ sqlite3_rebaser *pRebaser, ++ int (*xInput)(void *pIn, void *pData, int *pnData), ++ void *pIn, ++ int (*xOutput)(void *pOut, const void *pData, int nData), ++ void *pOut ++); + ++/* ++** CAPI3REF: Configure global parameters ++** ++** The sqlite3session_config() interface is used to make global configuration ++** changes to the sessions module in order to tune it to the specific needs ++** of the application. ++** ++** The sqlite3session_config() interface is not threadsafe. If it is invoked ++** while any other thread is inside any other sessions method then the ++** results are undefined. Furthermore, if it is invoked after any sessions ++** related objects have been created, the results are also undefined. ++** ++** The first argument to the sqlite3session_config() function must be one ++** of the SQLITE_SESSION_CONFIG_XXX constants defined below. The ++** interpretation of the (void*) value passed as the second parameter and ++** the effect of calling this function depends on the value of the first ++** parameter. ++** ++** <dl> ++** <dt>SQLITE_SESSION_CONFIG_STRMSIZE<dd> ++** By default, the sessions module streaming interfaces attempt to input ++** and output data in approximately 1 KiB chunks. This operand may be used ++** to set and query the value of this configuration setting. The pointer ++** passed as the second argument must point to a value of type (int). ++** If this value is greater than 0, it is used as the new streaming data ++** chunk size for both input and output. Before returning, the (int) value ++** pointed to by pArg is set to the final value of the streaming interface ++** chunk size. ++** </dl> ++** ++** This function returns SQLITE_OK if successful, or an SQLite error code ++** otherwise. ++*/ ++SQLITE_API int sqlite3session_config(int op, void *pArg); + + /* ++** CAPI3REF: Values for sqlite3session_config(). ++*/ ++#define SQLITE_SESSION_CONFIG_STRMSIZE 1 ++ ++/* + ** Make sure we can call this stuff from C++. + */ + #ifdef __cplusplus +@@ -10557,7 +11554,7 @@ + ** This way, even if the tokenizer does not provide synonyms + ** when tokenizing query text (it should not - to do would be + ** inefficient), it doesn't matter if the user queries for +-** 'first + place' or '1st + place', as there are entires in the ++** 'first + place' or '1st + place', as there are entries in the + ** FTS index corresponding to both forms of the first token. + ** </ol> + ** +@@ -10585,7 +11582,7 @@ + ** extra data to the FTS index or require FTS5 to query for multiple terms, + ** so it is efficient in terms of disk space and query speed. However, it + ** does not support prefix queries very well. If, as suggested above, the +-** token "first" is subsituted for "1st" by the tokenizer, then the query: ++** token "first" is substituted for "1st" by the tokenizer, then the query: + ** + ** <codeblock> + ** ... MATCH '1s*'</codeblock> +--- contrib/sqlite3/sqlite3ext.h.orig ++++ contrib/sqlite3/sqlite3ext.h +@@ -134,7 +134,7 @@ + int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*, + const char*,const char*),void*); + void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*)); +- char * (*snprintf)(int,char*,const char*,...); ++ char * (*xsnprintf)(int,char*,const char*,...); + int (*step)(sqlite3_stmt*); + int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*, + char const**,char const**,int*,int*,int*); +@@ -246,7 +246,7 @@ + int (*uri_boolean)(const char*,const char*,int); + sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64); + const char *(*uri_parameter)(const char*,const char*); +- char *(*vsnprintf)(int,char*,const char*,va_list); ++ char *(*xvsnprintf)(int,char*,const char*,va_list); + int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*); + /* Version 3.8.7 and later */ + int (*auto_extension)(void(*)(void)); +@@ -292,6 +292,33 @@ + int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*)); + void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*)); + void *(*value_pointer)(sqlite3_value*,const char*); ++ int (*vtab_nochange)(sqlite3_context*); ++ int (*value_nochange)(sqlite3_value*); ++ const char *(*vtab_collation)(sqlite3_index_info*,int); ++ /* Version 3.24.0 and later */ ++ int (*keyword_count)(void); ++ int (*keyword_name)(int,const char**,int*); ++ int (*keyword_check)(const char*,int); ++ sqlite3_str *(*str_new)(sqlite3*); ++ char *(*str_finish)(sqlite3_str*); ++ void (*str_appendf)(sqlite3_str*, const char *zFormat, ...); ++ void (*str_vappendf)(sqlite3_str*, const char *zFormat, va_list); ++ void (*str_append)(sqlite3_str*, const char *zIn, int N); ++ void (*str_appendall)(sqlite3_str*, const char *zIn); ++ void (*str_appendchar)(sqlite3_str*, int N, char C); ++ void (*str_reset)(sqlite3_str*); ++ int (*str_errcode)(sqlite3_str*); ++ int (*str_length)(sqlite3_str*); ++ char *(*str_value)(sqlite3_str*); ++ /* Version 3.25.0 and later */ ++ int (*create_window_function)(sqlite3*,const char*,int,int,void*, ++ void (*xStep)(sqlite3_context*,int,sqlite3_value**), ++ void (*xFinal)(sqlite3_context*), ++ void (*xValue)(sqlite3_context*), ++ void (*xInv)(sqlite3_context*,int,sqlite3_value**), ++ void(*xDestroy)(void*)); ++ /* Version 3.26.0 and later */ ++ const char *(*normalized_sql)(sqlite3_stmt*); + }; + + /* +@@ -418,7 +445,7 @@ + #define sqlite3_rollback_hook sqlite3_api->rollback_hook + #define sqlite3_set_authorizer sqlite3_api->set_authorizer + #define sqlite3_set_auxdata sqlite3_api->set_auxdata +-#define sqlite3_snprintf sqlite3_api->snprintf ++#define sqlite3_snprintf sqlite3_api->xsnprintf + #define sqlite3_step sqlite3_api->step + #define sqlite3_table_column_metadata sqlite3_api->table_column_metadata + #define sqlite3_thread_cleanup sqlite3_api->thread_cleanup +@@ -442,7 +469,7 @@ + #define sqlite3_value_text16le sqlite3_api->value_text16le + #define sqlite3_value_type sqlite3_api->value_type + #define sqlite3_vmprintf sqlite3_api->vmprintf +-#define sqlite3_vsnprintf sqlite3_api->vsnprintf ++#define sqlite3_vsnprintf sqlite3_api->xvsnprintf + #define sqlite3_overload_function sqlite3_api->overload_function + #define sqlite3_prepare_v2 sqlite3_api->prepare_v2 + #define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 +@@ -518,7 +545,7 @@ + #define sqlite3_uri_boolean sqlite3_api->uri_boolean + #define sqlite3_uri_int64 sqlite3_api->uri_int64 + #define sqlite3_uri_parameter sqlite3_api->uri_parameter +-#define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf ++#define sqlite3_uri_vsnprintf sqlite3_api->xvsnprintf + #define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2 + /* Version 3.8.7 and later */ + #define sqlite3_auto_extension sqlite3_api->auto_extension +@@ -558,6 +585,29 @@ + #define sqlite3_bind_pointer sqlite3_api->bind_pointer + #define sqlite3_result_pointer sqlite3_api->result_pointer + #define sqlite3_value_pointer sqlite3_api->value_pointer ++/* Version 3.22.0 and later */ ++#define sqlite3_vtab_nochange sqlite3_api->vtab_nochange ++#define sqlite3_value_nochange sqlite3_api->value_nochange ++#define sqlite3_vtab_collation sqlite3_api->vtab_collation ++/* Version 3.24.0 and later */ ++#define sqlite3_keyword_count sqlite3_api->keyword_count ++#define sqlite3_keyword_name sqlite3_api->keyword_name ++#define sqlite3_keyword_check sqlite3_api->keyword_check ++#define sqlite3_str_new sqlite3_api->str_new ++#define sqlite3_str_finish sqlite3_api->str_finish ++#define sqlite3_str_appendf sqlite3_api->str_appendf ++#define sqlite3_str_vappendf sqlite3_api->str_vappendf ++#define sqlite3_str_append sqlite3_api->str_append ++#define sqlite3_str_appendall sqlite3_api->str_appendall ++#define sqlite3_str_appendchar sqlite3_api->str_appendchar ++#define sqlite3_str_reset sqlite3_api->str_reset ++#define sqlite3_str_errcode sqlite3_api->str_errcode ++#define sqlite3_str_length sqlite3_api->str_length ++#define sqlite3_str_value sqlite3_api->str_value ++/* Version 3.25.0 and later */ ++#define sqlite3_create_window_function sqlite3_api->create_window_function ++/* Version 3.26.0 and later */ ++#define sqlite3_normalized_sql sqlite3_api->normalized_sql + #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ + + #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) +--- contrib/sqlite3/tea/configure.orig ++++ contrib/sqlite3/tea/configure +@@ -1,6 +1,6 @@ + #! /bin/sh + # Guess values for system-dependent variables and create Makefiles. +-# Generated by GNU Autoconf 2.69 for sqlite 3.20.0. ++# Generated by GNU Autoconf 2.69 for sqlite 3.26.0. + # + # + # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +@@ -577,8 +577,8 @@ + # Identity of this package. + PACKAGE_NAME='sqlite' + PACKAGE_TARNAME='sqlite' +-PACKAGE_VERSION='3.20.0' +-PACKAGE_STRING='sqlite 3.20.0' ++PACKAGE_VERSION='3.26.0' ++PACKAGE_STRING='sqlite 3.26.0' + PACKAGE_BUGREPORT='' + PACKAGE_URL='' + +@@ -1292,7 +1292,7 @@ + # 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.20.0 to adapt to many kinds of systems. ++\`configure' configures sqlite 3.26.0 to adapt to many kinds of systems. + + Usage: $0 [OPTION]... [VAR=VALUE]... + +@@ -1353,7 +1353,7 @@ + + if test -n "$ac_init_help"; then + case $ac_init_help in +- short | recursive ) echo "Configuration of sqlite 3.20.0:";; ++ short | recursive ) echo "Configuration of sqlite 3.26.0:";; + esac + cat <<\_ACEOF + +@@ -1455,7 +1455,7 @@ + test -n "$ac_init_help" && exit $ac_status + if $ac_init_version; then + cat <<\_ACEOF +-sqlite configure 3.20.0 ++sqlite configure 3.26.0 + generated by GNU Autoconf 2.69 + + Copyright (C) 2012 Free Software Foundation, Inc. +@@ -1866,7 +1866,7 @@ + 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.20.0, which was ++It was created by sqlite $as_me 3.26.0, which was + generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ +@@ -9361,7 +9361,7 @@ + # 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.20.0, which was ++This file was extended by sqlite $as_me 3.26.0, which was + generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES +@@ -9414,7 +9414,7 @@ + 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.20.0 ++sqlite config.status 3.26.0 + configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +--- contrib/sqlite3/tea/configure.ac.orig ++++ contrib/sqlite3/tea/configure.ac +@@ -19,7 +19,7 @@ + # so you can encode the package version directly into the source files. + #----------------------------------------------------------------------- + +-AC_INIT([sqlite], [3.20.0]) ++AC_INIT([sqlite], [3.26.0]) + + #-------------------------------------------------------------------- + # Call TEA_INIT as the first TEA_ macro to set up initial vars. +--- contrib/sqlite3/tea/generic/tclsqlite3.c.orig ++++ contrib/sqlite3/tea/generic/tclsqlite3.c +@@ -19,17 +19,19 @@ + ** + ** Compile-time options: + ** +-** -DTCLSH=1 Add a "main()" routine that works as a tclsh. ++** -DTCLSH Add a "main()" routine that works as a tclsh. + ** +-** -DSQLITE_TCLMD5 When used in conjuction with -DTCLSH=1, add +-** four new commands to the TCL interpreter for +-** generating MD5 checksums: md5, md5file, +-** md5-10x8, and md5file-10x8. ++** -DTCLSH_INIT_PROC=name + ** +-** -DSQLITE_TEST When used in conjuction with -DTCLSH=1, add +-** hundreds of new commands used for testing +-** SQLite. This option implies -DSQLITE_TCLMD5. ++** Invoke name(interp) to initialize the Tcl interpreter. ++** If name(interp) returns a non-NULL string, then run ++** that string as a Tcl script to launch the application. ++** If name(interp) returns NULL, then run the regular ++** tclsh-emulator code. + */ ++#ifdef TCLSH_INIT_PROC ++# define TCLSH 1 ++#endif + + /* + ** If requested, include the SQLite compiler options file for MSVC. +@@ -63,13 +65,18 @@ + + /* Used to get the current process ID */ + #if !defined(_WIN32) ++# include <signal.h> + # include <unistd.h> + # define GETPID getpid + #elif !defined(_WIN32_WCE) + # ifndef SQLITE_AMALGAMATION +-# define WIN32_LEAN_AND_MEAN ++# ifndef WIN32_LEAN_AND_MEAN ++# define WIN32_LEAN_AND_MEAN ++# endif + # include <windows.h> + # endif ++# include <io.h> ++# define isatty(h) _isatty(h) + # define GETPID (int)GetCurrentProcessId + #endif + +@@ -649,7 +656,7 @@ + } + case SQLITE_TRACE_PROFILE: { + sqlite3_stmt *pStmt = (sqlite3_stmt *)pd; +- sqlite3_int64 ns = (sqlite3_int64)xd; ++ sqlite3_int64 ns = *(sqlite3_int64*)xd; + + pCmd = Tcl_NewStringObj(pDb->zTraceV2, -1); + Tcl_IncrRefCount(pCmd); +@@ -1849,35 +1856,35 @@ + int choice; + int rc = TCL_OK; + static const char *DB_strs[] = { +- "authorizer", "backup", "busy", +- "cache", "changes", "close", +- "collate", "collation_needed", "commit_hook", +- "complete", "copy", "enable_load_extension", +- "errorcode", "eval", "exists", +- "function", "incrblob", "interrupt", +- "last_insert_rowid", "nullvalue", "onecolumn", +- "preupdate", "profile", "progress", +- "rekey", "restore", "rollback_hook", +- "status", "timeout", "total_changes", +- "trace", "trace_v2", "transaction", +- "unlock_notify", "update_hook", "version", +- "wal_hook", +- 0 ++ "authorizer", "backup", "busy", ++ "cache", "changes", "close", ++ "collate", "collation_needed", "commit_hook", ++ "complete", "copy", "deserialize", ++ "enable_load_extension", "errorcode", "eval", ++ "exists", "function", "incrblob", ++ "interrupt", "last_insert_rowid", "nullvalue", ++ "onecolumn", "preupdate", "profile", ++ "progress", "rekey", "restore", ++ "rollback_hook", "serialize", "status", ++ "timeout", "total_changes", "trace", ++ "trace_v2", "transaction", "unlock_notify", ++ "update_hook", "version", "wal_hook", ++ 0 + }; + enum DB_enum { +- DB_AUTHORIZER, DB_BACKUP, DB_BUSY, +- DB_CACHE, DB_CHANGES, DB_CLOSE, +- DB_COLLATE, DB_COLLATION_NEEDED, DB_COMMIT_HOOK, +- DB_COMPLETE, DB_COPY, DB_ENABLE_LOAD_EXTENSION, +- DB_ERRORCODE, DB_EVAL, DB_EXISTS, +- DB_FUNCTION, DB_INCRBLOB, DB_INTERRUPT, +- DB_LAST_INSERT_ROWID, DB_NULLVALUE, DB_ONECOLUMN, +- DB_PREUPDATE, DB_PROFILE, DB_PROGRESS, +- DB_REKEY, DB_RESTORE, DB_ROLLBACK_HOOK, +- DB_STATUS, DB_TIMEOUT, DB_TOTAL_CHANGES, +- DB_TRACE, DB_TRACE_V2, DB_TRANSACTION, +- DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK, DB_VERSION, +- DB_WAL_HOOK, ++ DB_AUTHORIZER, DB_BACKUP, DB_BUSY, ++ DB_CACHE, DB_CHANGES, DB_CLOSE, ++ DB_COLLATE, DB_COLLATION_NEEDED, DB_COMMIT_HOOK, ++ DB_COMPLETE, DB_COPY, DB_DESERIALIZE, ++ DB_ENABLE_LOAD_EXTENSION, DB_ERRORCODE, DB_EVAL, ++ DB_EXISTS, DB_FUNCTION, DB_INCRBLOB, ++ DB_INTERRUPT, DB_LAST_INSERT_ROWID, DB_NULLVALUE, ++ DB_ONECOLUMN, DB_PREUPDATE, DB_PROFILE, ++ DB_PROGRESS, DB_REKEY, DB_RESTORE, ++ DB_ROLLBACK_HOOK, DB_SERIALIZE, DB_STATUS, ++ DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE, ++ DB_TRACE_V2, DB_TRANSACTION, DB_UNLOCK_NOTIFY, ++ DB_UPDATE_HOOK, DB_VERSION, DB_WAL_HOOK + }; + /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */ + +@@ -2416,6 +2423,53 @@ + } + + /* ++ ** $db deserialize ?DATABASE? VALUE ++ ** ++ ** Reopen DATABASE (default "main") using the content in $VALUE ++ */ ++ case DB_DESERIALIZE: { ++#ifndef SQLITE_ENABLE_DESERIALIZE ++ Tcl_AppendResult(interp, "MEMDB not available in this build", ++ (char*)0); ++ rc = TCL_ERROR; ++#else ++ const char *zSchema; ++ Tcl_Obj *pValue; ++ unsigned char *pBA; ++ unsigned char *pData; ++ int len, xrc; ++ ++ if( objc==3 ){ ++ zSchema = 0; ++ pValue = objv[2]; ++ }else if( objc==4 ){ ++ zSchema = Tcl_GetString(objv[2]); ++ pValue = objv[3]; ++ }else{ ++ Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? VALUE"); ++ rc = TCL_ERROR; ++ break; ++ } ++ pBA = Tcl_GetByteArrayFromObj(pValue, &len); ++ pData = sqlite3_malloc64( len ); ++ if( pData==0 && len>0 ){ ++ Tcl_AppendResult(interp, "out of memory", (char*)0); ++ rc = TCL_ERROR; ++ }else{ ++ if( len>0 ) memcpy(pData, pBA, len); ++ xrc = sqlite3_deserialize(pDb->db, zSchema, pData, len, len, ++ SQLITE_DESERIALIZE_FREEONCLOSE | ++ SQLITE_DESERIALIZE_RESIZEABLE); ++ if( xrc ){ ++ Tcl_AppendResult(interp, "unable to set MEMDB content", (char*)0); ++ rc = TCL_ERROR; ++ } ++ } ++#endif ++ break; ++ } ++ ++ /* + ** $db enable_load_extension BOOLEAN + ** + ** Turn the extension loading feature on or off. It if off by +@@ -2891,6 +2945,39 @@ + } + + /* ++ ** $db serialize ?DATABASE? ++ ** ++ ** Return a serialization of a database. ++ */ ++ case DB_SERIALIZE: { ++#ifndef SQLITE_ENABLE_DESERIALIZE ++ Tcl_AppendResult(interp, "MEMDB not available in this build", ++ (char*)0); ++ rc = TCL_ERROR; ++#else ++ const char *zSchema = objc>=3 ? Tcl_GetString(objv[2]) : "main"; ++ sqlite3_int64 sz = 0; ++ unsigned char *pData; ++ if( objc!=2 && objc!=3 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE?"); ++ rc = TCL_ERROR; ++ }else{ ++ int needFree; ++ pData = sqlite3_serialize(pDb->db, zSchema, &sz, SQLITE_SERIALIZE_NOCOPY); ++ if( pData ){ ++ needFree = 0; ++ }else{ ++ pData = sqlite3_serialize(pDb->db, zSchema, &sz, 0); ++ needFree = 1; ++ } ++ Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pData,sz)); ++ if( needFree ) sqlite3_free(pData); ++ } ++#endif ++ break; ++ } ++ ++ /* + ** $db status (step|sort|autoindex|vmstep) + ** + ** Display SQLITE_STMTSTATUS_FULLSCAN_STEP or +@@ -3291,7 +3378,42 @@ + ** Return the version string for this database. + */ + case DB_VERSION: { +- Tcl_SetResult(interp, (char *)sqlite3_libversion(), TCL_STATIC); ++ int i; ++ for(i=2; i<objc; i++){ ++ const char *zArg = Tcl_GetString(objv[i]); ++ /* Optional arguments to $db version are used for testing purpose */ ++#ifdef SQLITE_TEST ++ /* $db version -use-legacy-prepare BOOLEAN ++ ** ++ ** Turn the use of legacy sqlite3_prepare() on or off. ++ */ ++ if( strcmp(zArg, "-use-legacy-prepare")==0 && i+1<objc ){ ++ i++; ++ if( Tcl_GetBooleanFromObj(interp, objv[i], &pDb->bLegacyPrepare) ){ ++ return TCL_ERROR; ++ } ++ }else ++ ++ /* $db version -last-stmt-ptr ++ ** ++ ** Return a string which is a hex encoding of the pointer to the ++ ** most recent sqlite3_stmt in the statement cache. ++ */ ++ if( strcmp(zArg, "-last-stmt-ptr")==0 ){ ++ char zBuf[100]; ++ sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", ++ pDb->stmtList ? pDb->stmtList->pStmt: 0); ++ Tcl_SetResult(interp, zBuf, TCL_VOLATILE); ++ }else ++#endif /* SQLITE_TEST */ ++ { ++ Tcl_AppendResult(interp, "unknown argument: ", zArg, (char*)0); ++ return TCL_ERROR; ++ } ++ } ++ if( i==2 ){ ++ Tcl_SetResult(interp, (char *)sqlite3_libversion(), TCL_STATIC); ++ } + break; + } + +@@ -3316,6 +3438,24 @@ + #endif /* SQLITE_TCL_NRE */ + + /* ++** Issue the usage message when the "sqlite3" command arguments are ++** incorrect. ++*/ ++static int sqliteCmdUsage( ++ Tcl_Interp *interp, ++ Tcl_Obj *const*objv ++){ ++ Tcl_WrongNumArgs(interp, 1, objv, ++ "HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?" ++ " ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?" ++#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL) ++ " ?-key CODECKEY?" ++#endif ++ ); ++ return TCL_ERROR; ++} ++ ++/* + ** sqlite3 DBNAME FILENAME ?-vfs VFSNAME? ?-key KEY? ?-readonly BOOLEAN? + ** ?-create BOOLEAN? ?-nomutex BOOLEAN? + ** +@@ -3340,7 +3480,7 @@ + const char *zArg; + char *zErrMsg; + int i; +- const char *zFile; ++ const char *zFile = 0; + const char *zVfs = 0; + int flags; + Tcl_DString translatedFilename; +@@ -3351,7 +3491,7 @@ + int rc; + + /* In normal use, each TCL interpreter runs in a single thread. So +- ** by default, we can turn of mutexing on SQLite database connections. ++ ** by default, we can turn off mutexing on SQLite database connections. + ** However, for testing purposes it is useful to have mutexes turned + ** on. So, by default, mutexes default off. But if compiled with + ** SQLITE_TCL_DEFAULT_FULLMUTEX then mutexes default on. +@@ -3362,6 +3502,7 @@ + flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX; + #endif + ++ if( objc==1 ) return sqliteCmdUsage(interp, objv); + if( objc==2 ){ + zArg = Tcl_GetStringFromObj(objv[1], 0); + if( strcmp(zArg,"-version")==0 ){ +@@ -3380,18 +3521,26 @@ + #endif + return TCL_OK; + } ++ if( zArg[0]=='-' ) return sqliteCmdUsage(interp, objv); + } +- for(i=3; i+1<objc; i+=2){ ++ for(i=2; i<objc; i++){ + zArg = Tcl_GetString(objv[i]); ++ if( zArg[0]!='-' ){ ++ if( zFile!=0 ) return sqliteCmdUsage(interp, objv); ++ zFile = zArg; ++ continue; ++ } ++ if( i==objc-1 ) return sqliteCmdUsage(interp, objv); ++ i++; + if( strcmp(zArg,"-key")==0 ){ + #if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL) +- pKey = Tcl_GetByteArrayFromObj(objv[i+1], &nKey); ++ pKey = Tcl_GetByteArrayFromObj(objv[i], &nKey); + #endif + }else if( strcmp(zArg, "-vfs")==0 ){ +- zVfs = Tcl_GetString(objv[i+1]); ++ zVfs = Tcl_GetString(objv[i]); + }else if( strcmp(zArg, "-readonly")==0 ){ + int b; +- if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR; ++ if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR; + if( b ){ + flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); + flags |= SQLITE_OPEN_READONLY; +@@ -3401,7 +3550,7 @@ + } + }else if( strcmp(zArg, "-create")==0 ){ + int b; +- if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR; ++ if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR; + if( b && (flags & SQLITE_OPEN_READONLY)==0 ){ + flags |= SQLITE_OPEN_CREATE; + }else{ +@@ -3409,7 +3558,7 @@ + } + }else if( strcmp(zArg, "-nomutex")==0 ){ + int b; +- if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR; ++ if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR; + if( b ){ + flags |= SQLITE_OPEN_NOMUTEX; + flags &= ~SQLITE_OPEN_FULLMUTEX; +@@ -3418,7 +3567,7 @@ + } + }else if( strcmp(zArg, "-fullmutex")==0 ){ + int b; +- if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR; ++ if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR; + if( b ){ + flags |= SQLITE_OPEN_FULLMUTEX; + flags &= ~SQLITE_OPEN_NOMUTEX; +@@ -3427,7 +3576,7 @@ + } + }else if( strcmp(zArg, "-uri")==0 ){ + int b; +- if( Tcl_GetBooleanFromObj(interp, objv[i+1], &b) ) return TCL_ERROR; ++ if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR; + if( b ){ + flags |= SQLITE_OPEN_URI; + }else{ +@@ -3438,20 +3587,10 @@ + return TCL_ERROR; + } + } +- if( objc<3 || (objc&1)!=1 ){ +- Tcl_WrongNumArgs(interp, 1, objv, +- "HANDLE FILENAME ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?" +- " ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?" +-#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL) +- " ?-key CODECKEY?" +-#endif +- ); +- return TCL_ERROR; +- } + zErrMsg = 0; + p = (SqliteDb*)Tcl_Alloc( sizeof(*p) ); + memset(p, 0, sizeof(*p)); +- zFile = Tcl_GetStringFromObj(objv[2], 0); ++ if( zFile==0 ) zFile = ""; + zFile = Tcl_TranslateFileName(interp, zFile, &translatedFilename); + rc = sqlite3_open_v2(zFile, &p->db, flags, zVfs); + Tcl_DStringFree(&translatedFilename); +@@ -3551,731 +3690,74 @@ + int Tclsqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; } + #endif + +-#ifdef TCLSH +-/***************************************************************************** +-** All of the code that follows is used to build standalone TCL interpreters +-** that are statically linked with SQLite. Enable these by compiling +-** with -DTCLSH=n where n can be 1 or 2. An n of 1 generates a standard +-** tclsh but with SQLite built in. An n of 2 generates the SQLite space +-** analysis program. +-*/ +- +-#if defined(SQLITE_TEST) || defined(SQLITE_TCLMD5) + /* +- * This code implements the MD5 message-digest algorithm. +- * The algorithm is due to Ron Rivest. This code was +- * written by Colin Plumb in 1993, no copyright is claimed. +- * This code is in the public domain; do with it what you wish. +- * +- * Equivalent code is available from RSA Data Security, Inc. +- * This code has been tested against that, and is equivalent, +- * except that you don't need to include two pages of legalese +- * with every copy. +- * +- * To compute the message digest of a chunk of bytes, declare an +- * MD5Context structure, pass it to MD5Init, call MD5Update as +- * needed on buffers full of bytes, and then call MD5Final, which +- * will fill a supplied 16-byte array with the digest. +- */ +- +-/* +- * If compiled on a machine that doesn't have a 32-bit integer, +- * you just set "uint32" to the appropriate datatype for an +- * unsigned 32-bit integer. For example: +- * +- * cc -Duint32='unsigned long' md5.c +- * +- */ +-#ifndef uint32 +-# define uint32 unsigned int +-#endif +- +-struct MD5Context { +- int isInit; +- uint32 buf[4]; +- uint32 bits[2]; +- unsigned char in[64]; +-}; +-typedef struct MD5Context MD5Context; +- +-/* +- * Note: this code is harmless on little-endian machines. +- */ +-static void byteReverse (unsigned char *buf, unsigned longs){ +- uint32 t; +- do { +- t = (uint32)((unsigned)buf[3]<<8 | buf[2]) << 16 | +- ((unsigned)buf[1]<<8 | buf[0]); +- *(uint32 *)buf = t; +- buf += 4; +- } while (--longs); +-} +-/* The four core functions - F1 is optimized somewhat */ +- +-/* #define F1(x, y, z) (x & y | ~x & z) */ +-#define F1(x, y, z) (z ^ (x & (y ^ z))) +-#define F2(x, y, z) F1(z, x, y) +-#define F3(x, y, z) (x ^ y ^ z) +-#define F4(x, y, z) (y ^ (x | ~z)) +- +-/* This is the central step in the MD5 algorithm. */ +-#define MD5STEP(f, w, x, y, z, data, s) \ +- ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) +- +-/* +- * The core of the MD5 algorithm, this alters an existing MD5 hash to +- * reflect the addition of 16 longwords of new data. MD5Update blocks +- * the data and converts bytes into longwords for this routine. +- */ +-static void MD5Transform(uint32 buf[4], const uint32 in[16]){ +- register uint32 a, b, c, d; +- +- a = buf[0]; +- b = buf[1]; +- c = buf[2]; +- d = buf[3]; +- +- MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7); +- MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12); +- MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17); +- MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22); +- MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7); +- MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12); +- MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17); +- MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22); +- MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7); +- MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12); +- MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17); +- MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22); +- MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7); +- MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12); +- MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17); +- MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22); +- +- MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5); +- MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9); +- MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14); +- MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20); +- MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5); +- MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9); +- MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14); +- MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20); +- MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5); +- MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9); +- MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14); +- MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20); +- MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5); +- MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9); +- MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14); +- MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20); +- +- MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4); +- MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11); +- MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16); +- MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23); +- MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4); +- MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11); +- MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16); +- MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23); +- MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4); +- MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11); +- MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16); +- MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23); +- MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4); +- MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11); +- MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16); +- MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23); +- +- MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6); +- MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10); +- MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15); +- MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21); +- MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6); +- MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10); +- MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15); +- MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21); +- MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6); +- MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10); +- MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15); +- MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21); +- MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6); +- MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10); +- MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15); +- MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21); +- +- buf[0] += a; +- buf[1] += b; +- buf[2] += c; +- buf[3] += d; +-} +- +-/* +- * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious +- * initialization constants. +- */ +-static void MD5Init(MD5Context *ctx){ +- ctx->isInit = 1; +- ctx->buf[0] = 0x67452301; +- ctx->buf[1] = 0xefcdab89; +- ctx->buf[2] = 0x98badcfe; +- ctx->buf[3] = 0x10325476; +- ctx->bits[0] = 0; +- ctx->bits[1] = 0; +-} +- +-/* +- * Update context to reflect the concatenation of another buffer full +- * of bytes. +- */ +-static +-void MD5Update(MD5Context *ctx, const unsigned char *buf, unsigned int len){ +- uint32 t; +- +- /* Update bitcount */ +- +- t = ctx->bits[0]; +- if ((ctx->bits[0] = t + ((uint32)len << 3)) < t) +- ctx->bits[1]++; /* Carry from low to high */ +- ctx->bits[1] += len >> 29; +- +- t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ +- +- /* Handle any leading odd-sized chunks */ +- +- if ( t ) { +- unsigned char *p = (unsigned char *)ctx->in + t; +- +- t = 64-t; +- if (len < t) { +- memcpy(p, buf, len); +- return; +- } +- memcpy(p, buf, t); +- byteReverse(ctx->in, 16); +- MD5Transform(ctx->buf, (uint32 *)ctx->in); +- buf += t; +- len -= t; +- } +- +- /* Process data in 64-byte chunks */ +- +- while (len >= 64) { +- memcpy(ctx->in, buf, 64); +- byteReverse(ctx->in, 16); +- MD5Transform(ctx->buf, (uint32 *)ctx->in); +- buf += 64; +- len -= 64; +- } +- +- /* Handle any remaining bytes of data. */ +- +- memcpy(ctx->in, buf, len); +-} +- +-/* +- * Final wrapup - pad to 64-byte boundary with the bit pattern +- * 1 0* (64-bit count of bits processed, MSB-first) +- */ +-static void MD5Final(unsigned char digest[16], MD5Context *ctx){ +- unsigned count; +- unsigned char *p; +- +- /* Compute number of bytes mod 64 */ +- count = (ctx->bits[0] >> 3) & 0x3F; +- +- /* Set the first char of padding to 0x80. This is safe since there is +- always at least one byte free */ +- p = ctx->in + count; +- *p++ = 0x80; +- +- /* Bytes of padding needed to make 64 bytes */ +- count = 64 - 1 - count; +- +- /* Pad out to 56 mod 64 */ +- if (count < 8) { +- /* Two lots of padding: Pad the first block to 64 bytes */ +- memset(p, 0, count); +- byteReverse(ctx->in, 16); +- MD5Transform(ctx->buf, (uint32 *)ctx->in); +- +- /* Now fill the next block with 56 bytes */ +- memset(ctx->in, 0, 56); +- } else { +- /* Pad block to 56 bytes */ +- memset(p, 0, count-8); +- } +- byteReverse(ctx->in, 14); +- +- /* Append length in bits and transform */ +- memcpy(ctx->in + 14*4, ctx->bits, 8); +- +- MD5Transform(ctx->buf, (uint32 *)ctx->in); +- byteReverse((unsigned char *)ctx->buf, 4); +- memcpy(digest, ctx->buf, 16); +-} +- +-/* +-** Convert a 128-bit MD5 digest into a 32-digit base-16 number. ++** If the TCLSH macro is defined, add code to make a stand-alone program. + */ +-static void MD5DigestToBase16(unsigned char *digest, char *zBuf){ +- static char const zEncode[] = "0123456789abcdef"; +- int i, j; ++#if defined(TCLSH) + +- for(j=i=0; i<16; i++){ +- int a = digest[i]; +- zBuf[j++] = zEncode[(a>>4)&0xf]; +- zBuf[j++] = zEncode[a & 0xf]; +- } +- zBuf[j] = 0; +-} +- +- +-/* +-** Convert a 128-bit MD5 digest into sequency of eight 5-digit integers +-** each representing 16 bits of the digest and separated from each +-** other by a "-" character. ++/* This is the main routine for an ordinary TCL shell. If there are ++** are arguments, run the first argument as a script. Otherwise, ++** read TCL commands from standard input + */ +-static void MD5DigestToBase10x8(unsigned char digest[16], char zDigest[50]){ +- int i, j; +- unsigned int x; +- for(i=j=0; i<16; i+=2){ +- x = digest[i]*256 + digest[i+1]; +- if( i>0 ) zDigest[j++] = '-'; +- sqlite3_snprintf(50-j, &zDigest[j], "%05u", x); +- j += 5; +- } +- zDigest[j] = 0; +-} +- +-/* +-** A TCL command for md5. The argument is the text to be hashed. The +-** Result is the hash in base64. +-*/ +-static int SQLITE_TCLAPI md5_cmd( +- void*cd, +- Tcl_Interp *interp, +- int argc, +- const char **argv +-){ +- MD5Context ctx; +- unsigned char digest[16]; +- char zBuf[50]; +- void (*converter)(unsigned char*, char*); +- +- if( argc!=2 ){ +- Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0], +- " TEXT\"", (char*)0); +- return TCL_ERROR; +- } +- MD5Init(&ctx); +- MD5Update(&ctx, (unsigned char*)argv[1], (unsigned)strlen(argv[1])); +- MD5Final(digest, &ctx); +- converter = (void(*)(unsigned char*,char*))cd; +- converter(digest, zBuf); +- Tcl_AppendResult(interp, zBuf, (char*)0); +- return TCL_OK; +-} +- +-/* +-** A TCL command to take the md5 hash of a file. The argument is the +-** name of the file. +-*/ +-static int SQLITE_TCLAPI md5file_cmd( +- void*cd, +- Tcl_Interp *interp, +- int argc, +- const char **argv +-){ +- FILE *in; +- MD5Context ctx; +- void (*converter)(unsigned char*, char*); +- unsigned char digest[16]; +- char zBuf[10240]; +- +- if( argc!=2 ){ +- Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0], +- " FILENAME\"", (char*)0); +- return TCL_ERROR; +- } +- in = fopen(argv[1],"rb"); +- if( in==0 ){ +- Tcl_AppendResult(interp,"unable to open file \"", argv[1], +- "\" for reading", (char*)0); +- return TCL_ERROR; +- } +- MD5Init(&ctx); +- for(;;){ +- int n; +- n = (int)fread(zBuf, 1, sizeof(zBuf), in); +- if( n<=0 ) break; +- MD5Update(&ctx, (unsigned char*)zBuf, (unsigned)n); +- } +- fclose(in); +- MD5Final(digest, &ctx); +- converter = (void(*)(unsigned char*,char*))cd; +- converter(digest, zBuf); +- Tcl_AppendResult(interp, zBuf, (char*)0); +- return TCL_OK; +-} +- +-/* +-** Register the four new TCL commands for generating MD5 checksums +-** with the TCL interpreter. +-*/ +-int Md5_Init(Tcl_Interp *interp){ +- Tcl_CreateCommand(interp, "md5", (Tcl_CmdProc*)md5_cmd, +- MD5DigestToBase16, 0); +- Tcl_CreateCommand(interp, "md5-10x8", (Tcl_CmdProc*)md5_cmd, +- MD5DigestToBase10x8, 0); +- Tcl_CreateCommand(interp, "md5file", (Tcl_CmdProc*)md5file_cmd, +- MD5DigestToBase16, 0); +- Tcl_CreateCommand(interp, "md5file-10x8", (Tcl_CmdProc*)md5file_cmd, +- MD5DigestToBase10x8, 0); +- return TCL_OK; +-} +-#endif /* defined(SQLITE_TEST) || defined(SQLITE_TCLMD5) */ +- +-#if defined(SQLITE_TEST) +-/* +-** During testing, the special md5sum() aggregate function is available. +-** inside SQLite. The following routines implement that function. +-*/ +-static void md5step(sqlite3_context *context, int argc, sqlite3_value **argv){ +- MD5Context *p; +- int i; +- if( argc<1 ) return; +- p = sqlite3_aggregate_context(context, sizeof(*p)); +- if( p==0 ) return; +- if( !p->isInit ){ +- MD5Init(p); +- } +- for(i=0; i<argc; i++){ +- const char *zData = (char*)sqlite3_value_text(argv[i]); +- if( zData ){ +- MD5Update(p, (unsigned char*)zData, (int)strlen(zData)); +- } +- } +-} +-static void md5finalize(sqlite3_context *context){ +- MD5Context *p; +- unsigned char digest[16]; +- char zBuf[33]; +- p = sqlite3_aggregate_context(context, sizeof(*p)); +- MD5Final(digest,p); +- MD5DigestToBase16(digest, zBuf); +- sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); +-} +-int Md5_Register( +- sqlite3 *db, +- char **pzErrMsg, +- const sqlite3_api_routines *pThunk +-){ +- int rc = sqlite3_create_function(db, "md5sum", -1, SQLITE_UTF8, 0, 0, +- md5step, md5finalize); +- sqlite3_overload_function(db, "md5sum", -1); /* To exercise this API */ +- return rc; +-} +-#endif /* defined(SQLITE_TEST) */ +- +- +-/* +-** If the macro TCLSH is one, then put in code this for the +-** "main" routine that will initialize Tcl and take input from +-** standard input, or if a file is named on the command line +-** the TCL interpreter reads and evaluates that file. +-*/ +-#if TCLSH==1 + static const char *tclsh_main_loop(void){ + static const char zMainloop[] = +- "set line {}\n" +- "while {![eof stdin]} {\n" +- "if {$line!=\"\"} {\n" +- "puts -nonewline \"> \"\n" +- "} else {\n" +- "puts -nonewline \"% \"\n" +- "}\n" +- "flush stdout\n" +- "append line [gets stdin]\n" +- "if {[info complete $line]} {\n" +- "if {[catch {uplevel #0 $line} result]} {\n" +- "puts stderr \"Error: $result\"\n" +- "} elseif {$result!=\"\"} {\n" +- "puts $result\n" ++ "if {[llength $argv]>=1} {\n" ++ "set argv0 [lindex $argv 0]\n" ++ "set argv [lrange $argv 1 end]\n" ++ "source $argv0\n" ++ "} else {\n" ++ "set line {}\n" ++ "while {![eof stdin]} {\n" ++ "if {$line!=\"\"} {\n" ++ "puts -nonewline \"> \"\n" ++ "} else {\n" ++ "puts -nonewline \"% \"\n" + "}\n" +- "set line {}\n" +- "} else {\n" +- "append line \\n\n" ++ "flush stdout\n" ++ "append line [gets stdin]\n" ++ "if {[info complete $line]} {\n" ++ "if {[catch {uplevel #0 $line} result]} {\n" ++ "puts stderr \"Error: $result\"\n" ++ "} elseif {$result!=\"\"} {\n" ++ "puts $result\n" ++ "}\n" ++ "set line {}\n" ++ "} else {\n" ++ "append line \\n\n" ++ "}\n" + "}\n" + "}\n" + ; + return zMainloop; + } +-#endif +-#if TCLSH==2 +-static const char *tclsh_main_loop(void); +-#endif + +-#ifdef SQLITE_TEST +-static void init_all(Tcl_Interp *); +-static int SQLITE_TCLAPI init_all_cmd( +- ClientData cd, +- Tcl_Interp *interp, +- int objc, +- Tcl_Obj *CONST objv[] +-){ +- +- Tcl_Interp *slave; +- if( objc!=2 ){ +- Tcl_WrongNumArgs(interp, 1, objv, "SLAVE"); +- return TCL_ERROR; +- } +- +- slave = Tcl_GetSlave(interp, Tcl_GetString(objv[1])); +- if( !slave ){ +- return TCL_ERROR; +- } +- +- init_all(slave); +- return TCL_OK; +-} +- +-/* +-** Tclcmd: db_use_legacy_prepare DB BOOLEAN +-** +-** The first argument to this command must be a database command created by +-** [sqlite3]. If the second argument is true, then the handle is configured +-** to use the sqlite3_prepare_v2() function to prepare statements. If it +-** is false, sqlite3_prepare(). +-*/ +-static int SQLITE_TCLAPI db_use_legacy_prepare_cmd( +- ClientData cd, +- Tcl_Interp *interp, +- int objc, +- Tcl_Obj *CONST objv[] +-){ +- Tcl_CmdInfo cmdInfo; +- SqliteDb *pDb; +- int bPrepare; +- +- if( objc!=3 ){ +- Tcl_WrongNumArgs(interp, 1, objv, "DB BOOLEAN"); +- return TCL_ERROR; +- } +- +- if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){ +- Tcl_AppendResult(interp, "no such db: ", Tcl_GetString(objv[1]), (char*)0); +- return TCL_ERROR; +- } +- pDb = (SqliteDb*)cmdInfo.objClientData; +- if( Tcl_GetBooleanFromObj(interp, objv[2], &bPrepare) ){ +- return TCL_ERROR; +- } +- +- pDb->bLegacyPrepare = bPrepare; +- +- Tcl_ResetResult(interp); +- return TCL_OK; +-} +- +-/* +-** Tclcmd: db_last_stmt_ptr DB +-** +-** If the statement cache associated with database DB is not empty, +-** return the text representation of the most recently used statement +-** handle. +-*/ +-static int SQLITE_TCLAPI db_last_stmt_ptr( +- ClientData cd, +- Tcl_Interp *interp, +- int objc, +- Tcl_Obj *CONST objv[] +-){ +- extern int sqlite3TestMakePointerStr(Tcl_Interp*, char*, void*); +- Tcl_CmdInfo cmdInfo; +- SqliteDb *pDb; +- sqlite3_stmt *pStmt = 0; +- char zBuf[100]; +- +- if( objc!=2 ){ +- Tcl_WrongNumArgs(interp, 1, objv, "DB"); +- return TCL_ERROR; +- } +- +- if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){ +- Tcl_AppendResult(interp, "no such db: ", Tcl_GetString(objv[1]), (char*)0); +- return TCL_ERROR; +- } +- pDb = (SqliteDb*)cmdInfo.objClientData; +- +- if( pDb->stmtList ) pStmt = pDb->stmtList->pStmt; +- if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ){ +- return TCL_ERROR; +- } +- Tcl_SetResult(interp, zBuf, TCL_VOLATILE); +- +- return TCL_OK; +-} +-#endif /* SQLITE_TEST */ +- +-/* +-** Configure the interpreter passed as the first argument to have access +-** to the commands and linked variables that make up: +-** +-** * the [sqlite3] extension itself, +-** +-** * If SQLITE_TCLMD5 or SQLITE_TEST is defined, the Md5 commands, and +-** +-** * If SQLITE_TEST is set, the various test interfaces used by the Tcl +-** test suite. +-*/ +-static void init_all(Tcl_Interp *interp){ +- Sqlite3_Init(interp); +- +-#if defined(SQLITE_TEST) || defined(SQLITE_TCLMD5) +- Md5_Init(interp); +-#endif +- +-#ifdef SQLITE_TEST +- { +- extern int Sqliteconfig_Init(Tcl_Interp*); +- extern int Sqlitetest1_Init(Tcl_Interp*); +- extern int Sqlitetest2_Init(Tcl_Interp*); +- extern int Sqlitetest3_Init(Tcl_Interp*); +- extern int Sqlitetest4_Init(Tcl_Interp*); +- extern int Sqlitetest5_Init(Tcl_Interp*); +- extern int Sqlitetest6_Init(Tcl_Interp*); +- extern int Sqlitetest7_Init(Tcl_Interp*); +- extern int Sqlitetest8_Init(Tcl_Interp*); +- extern int Sqlitetest9_Init(Tcl_Interp*); +- extern int Sqlitetestasync_Init(Tcl_Interp*); +- extern int Sqlitetest_autoext_Init(Tcl_Interp*); +- extern int Sqlitetest_blob_Init(Tcl_Interp*); +- extern int Sqlitetest_demovfs_Init(Tcl_Interp *); +- extern int Sqlitetest_func_Init(Tcl_Interp*); +- extern int Sqlitetest_hexio_Init(Tcl_Interp*); +- extern int Sqlitetest_init_Init(Tcl_Interp*); +- extern int Sqlitetest_malloc_Init(Tcl_Interp*); +- extern int Sqlitetest_mutex_Init(Tcl_Interp*); +- extern int Sqlitetestschema_Init(Tcl_Interp*); +- extern int Sqlitetestsse_Init(Tcl_Interp*); +- extern int Sqlitetesttclvar_Init(Tcl_Interp*); +- extern int Sqlitetestfs_Init(Tcl_Interp*); +- extern int SqlitetestThread_Init(Tcl_Interp*); +- extern int SqlitetestOnefile_Init(); +- extern int SqlitetestOsinst_Init(Tcl_Interp*); +- extern int Sqlitetestbackup_Init(Tcl_Interp*); +- extern int Sqlitetestintarray_Init(Tcl_Interp*); +- extern int Sqlitetestvfs_Init(Tcl_Interp *); +- extern int Sqlitetestrtree_Init(Tcl_Interp*); +- extern int Sqlitequota_Init(Tcl_Interp*); +- extern int Sqlitemultiplex_Init(Tcl_Interp*); +- extern int SqliteSuperlock_Init(Tcl_Interp*); +- extern int SqlitetestSyscall_Init(Tcl_Interp*); +-#if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK) +- extern int TestSession_Init(Tcl_Interp*); +-#endif +- extern int Fts5tcl_Init(Tcl_Interp *); +- extern int SqliteRbu_Init(Tcl_Interp*); +- extern int Sqlitetesttcl_Init(Tcl_Interp*); +-#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) +- extern int Sqlitetestfts3_Init(Tcl_Interp *interp); +-#endif +- +-#ifdef SQLITE_ENABLE_ZIPVFS +- extern int Zipvfs_Init(Tcl_Interp*); +- Zipvfs_Init(interp); +-#endif +- +- Sqliteconfig_Init(interp); +- Sqlitetest1_Init(interp); +- Sqlitetest2_Init(interp); +- Sqlitetest3_Init(interp); +- Sqlitetest4_Init(interp); +- Sqlitetest5_Init(interp); +- Sqlitetest6_Init(interp); +- Sqlitetest7_Init(interp); +- Sqlitetest8_Init(interp); +- Sqlitetest9_Init(interp); +- Sqlitetestasync_Init(interp); +- Sqlitetest_autoext_Init(interp); +- Sqlitetest_blob_Init(interp); +- Sqlitetest_demovfs_Init(interp); +- Sqlitetest_func_Init(interp); +- Sqlitetest_hexio_Init(interp); +- Sqlitetest_init_Init(interp); +- Sqlitetest_malloc_Init(interp); +- Sqlitetest_mutex_Init(interp); +- Sqlitetestschema_Init(interp); +- Sqlitetesttclvar_Init(interp); +- Sqlitetestfs_Init(interp); +- SqlitetestThread_Init(interp); +- SqlitetestOnefile_Init(); +- SqlitetestOsinst_Init(interp); +- Sqlitetestbackup_Init(interp); +- Sqlitetestintarray_Init(interp); +- Sqlitetestvfs_Init(interp); +- Sqlitetestrtree_Init(interp); +- Sqlitequota_Init(interp); +- Sqlitemultiplex_Init(interp); +- SqliteSuperlock_Init(interp); +- SqlitetestSyscall_Init(interp); +-#if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK) +- TestSession_Init(interp); +-#endif +- Fts5tcl_Init(interp); +- SqliteRbu_Init(interp); +- Sqlitetesttcl_Init(interp); +- +-#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) +- Sqlitetestfts3_Init(interp); +-#endif +- +- Tcl_CreateObjCommand( +- interp, "load_testfixture_extensions", init_all_cmd, 0, 0 +- ); +- Tcl_CreateObjCommand( +- interp, "db_use_legacy_prepare", db_use_legacy_prepare_cmd, 0, 0 +- ); +- Tcl_CreateObjCommand( +- interp, "db_last_stmt_ptr", db_last_stmt_ptr, 0, 0 +- ); +- +-#ifdef SQLITE_SSE +- Sqlitetestsse_Init(interp); +-#endif +- } +-#endif +-} +- +-/* Needed for the setrlimit() system call on unix */ +-#if defined(unix) +-#include <sys/resource.h> +-#endif +- + #define TCLSH_MAIN main /* Needed to fake out mktclapp */ + int SQLITE_CDECL TCLSH_MAIN(int argc, char **argv){ + Tcl_Interp *interp; ++ int i; ++ const char *zScript = 0; ++ char zArgc[32]; ++#if defined(TCLSH_INIT_PROC) ++ extern const char *TCLSH_INIT_PROC(Tcl_Interp*); ++#endif + + #if !defined(_WIN32_WCE) +- if( getenv("BREAK") ){ +- fprintf(stderr, +- "attach debugger to process %d and press any key to continue.\n", +- GETPID()); +- fgetc(stdin); ++ 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) ++ DebugBreak(); ++#elif defined(SIGTRAP) ++ raise(SIGTRAP); ++#endif ++ } + } + #endif + +- /* Since the primary use case for this binary is testing of SQLite, +- ** be sure to generate core files if we crash */ +-#if defined(SQLITE_TEST) && defined(unix) +- { struct rlimit x; +- getrlimit(RLIMIT_CORE, &x); +- x.rlim_cur = x.rlim_max; +- setrlimit(RLIMIT_CORE, &x); +- } +-#endif /* SQLITE_TEST && unix */ +- +- + /* Call sqlite3_shutdown() once before doing anything else. This is to + ** test that sqlite3_shutdown() can be safely called by a process before + ** sqlite3_initialize() is. */ +@@ -4284,32 +3766,27 @@ + Tcl_FindExecutable(argv[0]); + Tcl_SetSystemEncoding(NULL, "utf-8"); + interp = Tcl_CreateInterp(); ++ Sqlite3_Init(interp); + +-#if TCLSH==2 +- sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); ++ sqlite3_snprintf(sizeof(zArgc), zArgc, "%d", argc-1); ++ Tcl_SetVar(interp,"argc", zArgc, TCL_GLOBAL_ONLY); ++ Tcl_SetVar(interp,"argv0",argv[0],TCL_GLOBAL_ONLY); ++ Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY); ++ for(i=1; i<argc; i++){ ++ Tcl_SetVar(interp, "argv", argv[i], ++ TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE); ++ } ++#if defined(TCLSH_INIT_PROC) ++ zScript = TCLSH_INIT_PROC(interp); + #endif +- +- init_all(interp); +- if( argc>=2 ){ +- int i; +- char zArgc[32]; +- sqlite3_snprintf(sizeof(zArgc), zArgc, "%d", argc-(3-TCLSH)); +- Tcl_SetVar(interp,"argc", zArgc, TCL_GLOBAL_ONLY); +- Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY); +- Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY); +- for(i=3-TCLSH; i<argc; i++){ +- Tcl_SetVar(interp, "argv", argv[i], +- TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE); +- } +- if( TCLSH==1 && Tcl_EvalFile(interp, argv[1])!=TCL_OK ){ +- const char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY); +- if( zInfo==0 ) zInfo = Tcl_GetStringResult(interp); +- fprintf(stderr,"%s: %s\n", *argv, zInfo); +- return 1; +- } ++ if( zScript==0 ){ ++ zScript = tclsh_main_loop(); + } +- if( TCLSH==2 || argc<=1 ){ +- Tcl_GlobalEval(interp, tclsh_main_loop()); ++ if( Tcl_GlobalEval(interp, zScript)!=TCL_OK ){ ++ const char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY); ++ if( zInfo==0 ) zInfo = Tcl_GetStringResult(interp); ++ fprintf(stderr,"%s: %s\n", *argv, zInfo); ++ return 1; + } + return 0; + } diff --git a/share/security/patches/EN-19:03/sqlite-11.patch.asc b/share/security/patches/EN-19:03/sqlite-11.patch.asc new file mode 100644 index 0000000000..53594fbae7 --- /dev/null +++ b/share/security/patches/EN-19:03/sqlite-11.patch.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- + +iQKTBAABCgB9FiEE/A6HiuWv54gCjWNV05eS9J6n5cIFAlw2RiJfFIAAAAAALgAo +aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldEZD +MEU4NzhBRTVBRkU3ODgwMjhENjM1NUQzOTc5MkY0OUVBN0U1QzIACgkQ05eS9J6n +5cJUcA//Sbp6kYL6InxUHPlQYO+MSTT+vc8bnzo7pW2sGs9VP+mnseZUQLO8pp29 +cCYNOC+4W2aIRP236IgeyPWSWUFSQ2MY+TSBxwa2kbIQW6Dts3ZvJNGT2MrMFqfx +4mXMf8bgrsgGHymJ7qTgudeQzgsl0OPSzXSVzp/KVT+VQb9gIok3Dx7gGzTj/u2O +5NIok6oBxUUcuoFfMV5z1fVS3Ny/gK80BVQy0f8ZlutkVZ2H09zu1pnHSLUCnUYT +psE5QlJZ/baCkPBioComDJsy8YqEf9E4W4rm/Ds/tzV+IA5s7RzH/HvfHp3j7t8l +ODNBr13lAlV6hQ71CwAPJEH5R8tmzRTKBQInAIS3xKiNBWqhshWf//ZSobHCPqJT +BDEnE/9XF1GHaa4vb5RTZRIEhTU0zJ+o1CQOR6McdJ4IxOc1P23hOvRwkylQB84S +E/3Yy42bde5RLnDYdQuxCW/c6S3PRo1jSMYjS7DnQ2PS8k+wAeAzHgj575UpcpDl +5pSuzejvobSd0qyqwmBjKVWqAhkrRcUw/Yy/wt62RyHepEtpLat6U9deq481eart +IC3eDJAaPW06mnmT9nfAqSh2CKvFUxTQ1XwZh0R+ZltdtjWFVWsU1XMc5fsfiQKU +aD3o/huTvc2MhYTexvqYQcWZYndMgnXgWQt2LqLoe0YZAgMX5ZU= +=I2kE +-----END PGP SIGNATURE----- diff --git a/share/security/patches/EN-19:03/sqlite-12.patch b/share/security/patches/EN-19:03/sqlite-12.patch new file mode 100644 index 0000000000..d6dc834a44 --- /dev/null +++ b/share/security/patches/EN-19:03/sqlite-12.patch @@ -0,0 +1,65012 @@ +--- contrib/sqlite3/Makefile.am.orig ++++ contrib/sqlite3/Makefile.am +@@ -1,6 +1,5 @@ + +-AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ @FTS5_FLAGS@ @JSON1_FLAGS@ @ZLIB_FLAGS@ @SESSION_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE +- ++AM_CFLAGS = @BUILD_CFLAGS@ + lib_LTLIBRARIES = libsqlite3.la + libsqlite3_la_SOURCES = sqlite3.c + libsqlite3_la_LDFLAGS = -no-undefined -version-info 8:6:8 +@@ -14,7 +13,7 @@ + + include_HEADERS = sqlite3.h sqlite3ext.h + +-EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt Replace.cs ++EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt Replace.cs Makefile.fallback + pkgconfigdir = ${libdir}/pkgconfig + pkgconfig_DATA = sqlite3.pc + +--- contrib/sqlite3/Makefile.fallback.orig ++++ contrib/sqlite3/Makefile.fallback +@@ -0,0 +1,19 @@ ++#!/usr/bin/make ++# ++# If the configure script does not work, then this Makefile is available ++# as a backup. Manually configure the variables below. ++# ++# Note: This makefile works out-of-the-box on MacOS 10.2 (Jaguar) ++# ++CC = gcc ++CFLAGS = -O0 -I. ++LIBS = -lz ++COPTS += -D_BSD_SOURCE ++COPTS += -DSQLITE_ENABLE_LOCKING_STYLE=0 ++COPTS += -DSQLITE_THREADSAFE=0 ++COPTS += -DSQLITE_OMIT_LOAD_EXTENSION ++COPTS += -DSQLITE_WITHOUT_ZONEMALLOC ++COPTS += -DSQLITE_ENABLE_RTREE ++ ++sqlite3: shell.c sqlite3.c ++ $(CC) $(CFLAGS) $(COPTS) -o sqlite3 shell.c sqlite3.c $(LIBS) +--- contrib/sqlite3/Makefile.in.orig ++++ contrib/sqlite3/Makefile.in +@@ -260,7 +260,6 @@ + DLLTOOL = @DLLTOOL@ + DSYMUTIL = @DSYMUTIL@ + DUMPBIN = @DUMPBIN@ +-DYNAMIC_EXTENSION_FLAGS = @DYNAMIC_EXTENSION_FLAGS@ + ECHO_C = @ECHO_C@ + ECHO_N = @ECHO_N@ + ECHO_T = @ECHO_T@ +@@ -268,7 +267,6 @@ + EXEEXT = @EXEEXT@ + EXTRA_SHELL_OBJ = @EXTRA_SHELL_OBJ@ + FGREP = @FGREP@ +-FTS5_FLAGS = @FTS5_FLAGS@ + GREP = @GREP@ + INSTALL = @INSTALL@ + INSTALL_DATA = @INSTALL_DATA@ +@@ -275,7 +273,6 @@ + INSTALL_PROGRAM = @INSTALL_PROGRAM@ + INSTALL_SCRIPT = @INSTALL_SCRIPT@ + INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +-JSON1_FLAGS = @JSON1_FLAGS@ + LD = @LD@ + LDFLAGS = @LDFLAGS@ + LIBOBJS = @LIBOBJS@ +@@ -305,14 +302,11 @@ + RANLIB = @RANLIB@ + READLINE_LIBS = @READLINE_LIBS@ + SED = @SED@ +-SESSION_FLAGS = @SESSION_FLAGS@ + SET_MAKE = @SET_MAKE@ + SHELL = @SHELL@ + SHELL_CFLAGS = @SHELL_CFLAGS@ + STRIP = @STRIP@ +-THREADSAFE_FLAGS = @THREADSAFE_FLAGS@ + VERSION = @VERSION@ +-ZLIB_FLAGS = @ZLIB_FLAGS@ + abs_builddir = @abs_builddir@ + abs_srcdir = @abs_srcdir@ + abs_top_builddir = @abs_top_builddir@ +@@ -365,7 +359,7 @@ + top_build_prefix = @top_build_prefix@ + top_builddir = @top_builddir@ + top_srcdir = @top_srcdir@ +-AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ @FTS5_FLAGS@ @JSON1_FLAGS@ @ZLIB_FLAGS@ @SESSION_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE ++AM_CFLAGS = @BUILD_CFLAGS@ + lib_LTLIBRARIES = libsqlite3.la + libsqlite3_la_SOURCES = sqlite3.c + libsqlite3_la_LDFLAGS = -no-undefined -version-info 8:6:8 +@@ -375,7 +369,7 @@ + sqlite3_DEPENDENCIES = @EXTRA_SHELL_OBJ@ + sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_STMTVTAB -DSQLITE_ENABLE_DBSTAT_VTAB $(SHELL_CFLAGS) + include_HEADERS = sqlite3.h sqlite3ext.h +-EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt Replace.cs ++EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt Replace.cs Makefile.fallback + pkgconfigdir = ${libdir}/pkgconfig + pkgconfig_DATA = sqlite3.pc + man_MANS = sqlite3.1 +--- contrib/sqlite3/Makefile.msc.orig ++++ contrib/sqlite3/Makefile.msc +@@ -277,6 +277,12 @@ + !IF $(MINIMAL_AMALGAMATION)==0 + OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1 + OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1 ++OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_GEOPOLY=1 ++OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_JSON1=1 ++OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1 ++OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1 ++OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1 ++OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_INTROSPECTION_PRAGMAS=1 + !ENDIF + OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1 + !ENDIF +@@ -928,10 +934,9 @@ + # when the shell is not being dynamically linked. + # + !IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0 +-SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_STMTVTAB +-SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_DBSTAT_VTAB +-SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC -DSQLITE_INTROSPECTION_PRAGMAS +-SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_RTREE ++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 + + +@@ -966,7 +971,7 @@ + sqlite3.def: Replace.exe $(LIBOBJ) + echo EXPORTS > sqlite3.def + dumpbin /all $(LIBOBJ) \ +- | .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \ ++ | .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup|rebaser)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \ + | sort >> sqlite3.def + + $(SQLITE3EXE): shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H) +--- contrib/sqlite3/configure.orig ++++ contrib/sqlite3/configure +@@ -1,6 +1,6 @@ + #! /bin/sh + # Guess values for system-dependent variables and create Makefiles. +-# Generated by GNU Autoconf 2.69 for sqlite 3.23.1. ++# Generated by GNU Autoconf 2.69 for sqlite 3.26.0. + # + # Report bugs to <http://www.sqlite.org>. + # +@@ -590,8 +590,8 @@ + # Identity of this package. + PACKAGE_NAME='sqlite' + PACKAGE_TARNAME='sqlite' +-PACKAGE_VERSION='3.23.1' +-PACKAGE_STRING='sqlite 3.23.1' ++PACKAGE_VERSION='3.26.0' ++PACKAGE_STRING='sqlite 3.26.0' + PACKAGE_BUGREPORT='http://www.sqlite.org' + PACKAGE_URL='' + +@@ -637,13 +637,7 @@ + LTLIBOBJS + LIBOBJS + SHELL_CFLAGS +-ZLIB_FLAGS + EXTRA_SHELL_OBJ +-SESSION_FLAGS +-JSON1_FLAGS +-FTS5_FLAGS +-DYNAMIC_EXTENSION_FLAGS +-THREADSAFE_FLAGS + READLINE_LIBS + BUILD_CFLAGS + CPP +@@ -777,9 +771,13 @@ + enable_readline + enable_threadsafe + enable_dynamic_extensions ++enable_fts4 ++enable_fts3 + enable_fts5 + enable_json1 ++enable_rtree + enable_session ++enable_debug + enable_static_shell + ' + ac_precious_vars='build_alias +@@ -1332,7 +1330,7 @@ + # 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.23.1 to adapt to many kinds of systems. ++\`configure' configures sqlite 3.26.0 to adapt to many kinds of systems. + + Usage: $0 [OPTION]... [VAR=VALUE]... + +@@ -1402,7 +1400,7 @@ + + if test -n "$ac_init_help"; then + case $ac_init_help in +- short | recursive ) echo "Configuration of sqlite 3.23.1:";; ++ short | recursive ) echo "Configuration of sqlite 3.26.0:";; + esac + cat <<\_ACEOF + +@@ -1427,9 +1425,13 @@ + --enable-threadsafe build a thread-safe library [default=yes] + --enable-dynamic-extensions + support loadable extensions [default=yes] +- --enable-fts5 include fts5 support [default=no] +- --enable-json1 include json1 support [default=no] ++ --enable-fts4 include fts4 support [default=yes] ++ --enable-fts3 include fts3 support [default=no] ++ --enable-fts5 include fts5 support [default=yes] ++ --enable-json1 include json1 support [default=yes] ++ --enable-rtree include rtree support [default=yes] + --enable-session enable the session extension [default=no] ++ --enable-debug build with debugging features enabled [default=no] + --enable-static-shell statically link libsqlite3 into shell tool + [default=yes] + +@@ -1523,7 +1525,7 @@ + test -n "$ac_init_help" && exit $ac_status + if $ac_init_version; then + cat <<\_ACEOF +-sqlite configure 3.23.1 ++sqlite configure 3.26.0 + generated by GNU Autoconf 2.69 + + Copyright (C) 2012 Free Software Foundation, Inc. +@@ -1938,7 +1940,7 @@ + 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.23.1, which was ++It was created by sqlite $as_me 3.26.0, which was + generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ +@@ -2804,7 +2806,7 @@ + + # Define the identity of the package. + PACKAGE='sqlite' +- VERSION='3.23.1' ++ VERSION='3.26.0' + + + cat >>confdefs.h <<_ACEOF +@@ -13040,6 +13042,7 @@ + + ac_config_files="$ac_config_files Makefile sqlite3.pc" + ++BUILD_CFLAGS= + + + #------------------------------------------------------------------------- +@@ -13304,9 +13307,8 @@ + enable_threadsafe=yes + fi + +-THREADSAFE_FLAGS=-DSQLITE_THREADSAFE=0 + if test x"$enable_threadsafe" != "xno"; then +- THREADSAFE_FLAGS="-D_REENTRANT=1 -DSQLITE_THREADSAFE=1" ++ BUILD_CFLAGS="$BUILD_CFLAGS -D_REENTRANT=1 -DSQLITE_THREADSAFE=1" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_create" >&5 + $as_echo_n "checking for library containing pthread_create... " >&6; } + if ${ac_cv_search_pthread_create+:} false; then : +@@ -13420,7 +13422,6 @@ + fi + + fi +- + #----------------------------------------------------------------------- + + #----------------------------------------------------------------------- +@@ -13491,16 +13492,43 @@ + fi + + else +- DYNAMIC_EXTENSION_FLAGS=-DSQLITE_OMIT_LOAD_EXTENSION=1 ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_OMIT_LOAD_EXTENSION=1" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for whether to support dynamic extensions" >&5 + $as_echo_n "checking for whether to support dynamic extensions... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_dynamic_extensions" >&5 + $as_echo "$enable_dynamic_extensions" >&6; } ++#----------------------------------------------------------------------- + + #----------------------------------------------------------------------- ++# --enable-fts4 ++# ++# Check whether --enable-fts4 was given. ++if test "${enable_fts4+set}" = set; then : ++ enableval=$enable_fts4; ++else ++ enable_fts4=yes ++fi + ++if test x"$enable_fts4" = "xyes"; then ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS4" ++fi + #----------------------------------------------------------------------- ++ ++#----------------------------------------------------------------------- ++# --enable-fts3 ++# ++# Check whether --enable-fts3 was given. ++if test "${enable_fts3+set}" = set; then : ++ enableval=$enable_fts3; ++fi ++ ++if test x"$enable_fts3" = "xyes" -a x"$enable_fts4" = "xno"; then ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS3" ++fi ++#----------------------------------------------------------------------- ++ ++#----------------------------------------------------------------------- + # --enable-fts5 + # + # Check whether --enable-fts5 was given. +@@ -13507,7 +13535,7 @@ + if test "${enable_fts5+set}" = set; then : + enableval=$enable_fts5; + else +- enable_fts5=no ++ enable_fts5=yes + fi + + if test x"$enable_fts5" = "xyes"; then +@@ -13567,9 +13595,8 @@ + + fi + +- FTS5_FLAGS=-DSQLITE_ENABLE_FTS5 ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS5" + fi +- + #----------------------------------------------------------------------- + + #----------------------------------------------------------------------- +@@ -13579,32 +13606,57 @@ + if test "${enable_json1+set}" = set; then : + enableval=$enable_json1; + else +- enable_json1=no ++ enable_json1=yes + fi + + if test x"$enable_json1" = "xyes"; then +- JSON1_FLAGS=-DSQLITE_ENABLE_JSON1 ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_JSON1" + fi ++#----------------------------------------------------------------------- + + #----------------------------------------------------------------------- ++# --enable-rtree ++# ++# Check whether --enable-rtree was given. ++if test "${enable_rtree+set}" = set; then : ++ enableval=$enable_rtree; ++else ++ enable_rtree=yes ++fi + ++if test x"$enable_rtree" = "xyes"; then ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_RTREE" ++fi + #----------------------------------------------------------------------- ++ ++#----------------------------------------------------------------------- + # --enable-session + # + # Check whether --enable-session was given. + if test "${enable_session+set}" = set; then : + enableval=$enable_session; +-else +- enable_session=no + fi + + if test x"$enable_session" = "xyes"; then +- SESSION_FLAGS="-DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK" ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK" + fi ++#----------------------------------------------------------------------- + + #----------------------------------------------------------------------- ++# --enable-debug ++# ++# Check whether --enable-debug was given. ++if test "${enable_debug+set}" = set; then : ++ enableval=$enable_debug; ++fi + ++if test x"$enable_debug" = "xyes"; then ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_DEBUG -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE" ++ CFLAGS="-g -O0" ++fi + #----------------------------------------------------------------------- ++ ++#----------------------------------------------------------------------- + # --enable-static-shell + # + # Check whether --enable-static-shell was given. +@@ -13694,7 +13746,7 @@ + ac_res=$ac_cv_search_deflate + if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" +- ZLIB_FLAGS="-DSQLITE_HAVE_ZLIB" ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_HAVE_ZLIB" + fi + + +@@ -13703,7 +13755,6 @@ + done + + +- + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing system" >&5 + $as_echo_n "checking for library containing system... " >&6; } + if ${ac_cv_search_system+:} false; then : +@@ -14359,7 +14410,7 @@ + # 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.23.1, which was ++This file was extended by sqlite $as_me 3.26.0, which was + generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES +@@ -14416,7 +14467,7 @@ + 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.23.1 ++sqlite config.status 3.26.0 + configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +--- contrib/sqlite3/configure.ac.orig ++++ contrib/sqlite3/configure.ac +@@ -10,7 +10,7 @@ + # + + AC_PREREQ(2.61) +-AC_INIT(sqlite, 3.23.1, http://www.sqlite.org) ++AC_INIT(sqlite, 3.26.0, http://www.sqlite.org) + AC_CONFIG_SRCDIR([sqlite3.c]) + AC_CONFIG_AUX_DIR([.]) + +@@ -29,6 +29,7 @@ + AC_FUNC_STRERROR_R + + AC_CONFIG_FILES([Makefile sqlite3.pc]) ++BUILD_CFLAGS= + AC_SUBST(BUILD_CFLAGS) + + #------------------------------------------------------------------------- +@@ -86,13 +87,11 @@ + AC_ARG_ENABLE(threadsafe, [AS_HELP_STRING( + [--enable-threadsafe], [build a thread-safe library [default=yes]])], + [], [enable_threadsafe=yes]) +-THREADSAFE_FLAGS=-DSQLITE_THREADSAFE=0 + if test x"$enable_threadsafe" != "xno"; then +- THREADSAFE_FLAGS="-D_REENTRANT=1 -DSQLITE_THREADSAFE=1" ++ BUILD_CFLAGS="$BUILD_CFLAGS -D_REENTRANT=1 -DSQLITE_THREADSAFE=1" + AC_SEARCH_LIBS(pthread_create, pthread) + AC_SEARCH_LIBS(pthread_mutexattr_init, pthread) + fi +-AC_SUBST(THREADSAFE_FLAGS) + #----------------------------------------------------------------------- + + #----------------------------------------------------------------------- +@@ -104,24 +103,44 @@ + if test x"$enable_dynamic_extensions" != "xno"; then + AC_SEARCH_LIBS(dlopen, dl) + else +- DYNAMIC_EXTENSION_FLAGS=-DSQLITE_OMIT_LOAD_EXTENSION=1 ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_OMIT_LOAD_EXTENSION=1" + fi + AC_MSG_CHECKING([for whether to support dynamic extensions]) + AC_MSG_RESULT($enable_dynamic_extensions) +-AC_SUBST(DYNAMIC_EXTENSION_FLAGS) + #----------------------------------------------------------------------- + + #----------------------------------------------------------------------- ++# --enable-fts4 ++# ++AC_ARG_ENABLE(fts4, [AS_HELP_STRING( ++ [--enable-fts4], [include fts4 support [default=yes]])], ++ [], [enable_fts4=yes]) ++if test x"$enable_fts4" = "xyes"; then ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS4" ++fi ++#----------------------------------------------------------------------- ++ ++#----------------------------------------------------------------------- ++# --enable-fts3 ++# ++AC_ARG_ENABLE(fts3, [AS_HELP_STRING( ++ [--enable-fts3], [include fts3 support [default=no]])], ++ [], []) ++if test x"$enable_fts3" = "xyes" -a x"$enable_fts4" = "xno"; then ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS3" ++fi ++#----------------------------------------------------------------------- ++ ++#----------------------------------------------------------------------- + # --enable-fts5 + # + AC_ARG_ENABLE(fts5, [AS_HELP_STRING( +- [--enable-fts5], [include fts5 support [default=no]])], +- [], [enable_fts5=no]) ++ [--enable-fts5], [include fts5 support [default=yes]])], ++ [], [enable_fts5=yes]) + if test x"$enable_fts5" = "xyes"; then + AC_SEARCH_LIBS(log, m) +- FTS5_FLAGS=-DSQLITE_ENABLE_FTS5 ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_FTS5" + fi +-AC_SUBST(FTS5_FLAGS) + #----------------------------------------------------------------------- + + #----------------------------------------------------------------------- +@@ -128,27 +147,48 @@ + # --enable-json1 + # + AC_ARG_ENABLE(json1, [AS_HELP_STRING( +- [--enable-json1], [include json1 support [default=no]])], +- [], [enable_json1=no]) ++ [--enable-json1], [include json1 support [default=yes]])], ++ [],[enable_json1=yes]) + if test x"$enable_json1" = "xyes"; then +- JSON1_FLAGS=-DSQLITE_ENABLE_JSON1 ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_JSON1" + fi +-AC_SUBST(JSON1_FLAGS) + #----------------------------------------------------------------------- + + #----------------------------------------------------------------------- ++# --enable-rtree ++# ++AC_ARG_ENABLE(rtree, [AS_HELP_STRING( ++ [--enable-rtree], [include rtree support [default=yes]])], ++ [], [enable_rtree=yes]) ++if test x"$enable_rtree" = "xyes"; then ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_RTREE" ++fi ++#----------------------------------------------------------------------- ++ ++#----------------------------------------------------------------------- + # --enable-session + # + AC_ARG_ENABLE(session, [AS_HELP_STRING( + [--enable-session], [enable the session extension [default=no]])], +- [], [enable_session=no]) ++ [], []) + if test x"$enable_session" = "xyes"; then +- SESSION_FLAGS="-DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK" ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK" + fi +-AC_SUBST(SESSION_FLAGS) + #----------------------------------------------------------------------- + + #----------------------------------------------------------------------- ++# --enable-debug ++# ++AC_ARG_ENABLE(debug, [AS_HELP_STRING( ++ [--enable-debug], [build with debugging features enabled [default=no]])], ++ [], []) ++if test x"$enable_debug" = "xyes"; then ++ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_DEBUG -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE" ++ CFLAGS="-g -O0" ++fi ++#----------------------------------------------------------------------- ++ ++#----------------------------------------------------------------------- + # --enable-static-shell + # + AC_ARG_ENABLE(static-shell, [AS_HELP_STRING( +@@ -165,9 +205,8 @@ + + AC_CHECK_FUNCS(posix_fallocate) + AC_CHECK_HEADERS(zlib.h,[ +- AC_SEARCH_LIBS(deflate,z,[ZLIB_FLAGS="-DSQLITE_HAVE_ZLIB"]) ++ AC_SEARCH_LIBS(deflate,z,[BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_HAVE_ZLIB"]) + ]) +-AC_SUBST(ZLIB_FLAGS) + + AC_SEARCH_LIBS(system,,,[SHELL_CFLAGS="-DSQLITE_NOHAVE_SYSTEM"]) + AC_SUBST(SHELL_CFLAGS) +--- contrib/sqlite3/shell.c.orig ++++ contrib/sqlite3/shell.c +@@ -97,6 +97,7 @@ + #if (!defined(_WIN32) && !defined(WIN32)) || defined(__MINGW32__) + # include <unistd.h> + # include <dirent.h> ++# define GETPID getpid + # if defined(__MINGW32__) + # define DIRENT dirent + # ifndef S_ISLNK +@@ -103,6 +104,8 @@ + # define S_ISLNK(mode) (0) + # endif + # endif ++#else ++# define GETPID (int)GetCurrentProcessId + #endif + #include <sys/types.h> + #include <sys/stat.h> +@@ -454,6 +457,12 @@ + # define raw_printf fprintf + #endif + ++/* Indicate out-of-memory and exit. */ ++static void shell_out_of_memory(void){ ++ raw_printf(stderr,"Error: out of memory\n"); ++ exit(1); ++} ++ + /* + ** Write I/O traces to the following stream. + */ +@@ -577,7 +586,7 @@ + if( n+100>nLine ){ + nLine = nLine*2 + 100; + zLine = realloc(zLine, nLine); +- if( zLine==0 ) return 0; ++ if( zLine==0 ) shell_out_of_memory(); + } + if( fgets(&zLine[n], nLine - n, in)==0 ){ + if( n==0 ){ +@@ -604,10 +613,7 @@ + int nTrans = strlen30(zTrans)+1; + if( nTrans>nLine ){ + zLine = realloc(zLine, nTrans); +- if( zLine==0 ){ +- sqlite3_free(zTrans); +- return 0; +- } ++ if( zLine==0 ) shell_out_of_memory(); + } + memcpy(zLine, zTrans, nTrans); + sqlite3_free(zTrans); +@@ -754,10 +760,7 @@ + if( p->n+len>=p->nAlloc ){ + p->nAlloc = p->nAlloc*2 + len + 20; + p->z = realloc(p->z, p->nAlloc); +- if( p->z==0 ){ +- memset(p, 0, sizeof(*p)); +- return; +- } ++ if( p->z==0 ) shell_out_of_memory(); + } + + if( quote ){ +@@ -786,45 +789,12 @@ + ** Return '"' if quoting is required. Return 0 if no quoting is required. + */ + static char quoteChar(const char *zName){ +- /* All SQLite keywords, in alphabetical order */ +- static const char *azKeywords[] = { +- "ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS", +- "ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY", +- "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT", +- "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE", +- "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE", +- "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH", +- "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN", +- "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF", +- "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER", +- "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY", +- "LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL", +- "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA", +- "PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP", +- "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT", +- "ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP", +- "TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE", +- "UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE", +- "WITH", "WITHOUT", +- }; +- int i, lwr, upr, mid, c; ++ 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 '"'; + } +- lwr = 0; +- upr = sizeof(azKeywords)/sizeof(azKeywords[0]) - 1; +- while( lwr<=upr ){ +- mid = (lwr+upr)/2; +- c = sqlite3_stricmp(azKeywords[mid], zName); +- if( c==0 ) return '"'; +- if( c<0 ){ +- lwr = mid+1; +- }else{ +- upr = mid-1; +- } +- } +- return 0; ++ return sqlite3_keyword_check(zName, i) ? '"' : 0; + } + + /* +@@ -1347,7 +1317,7 @@ + ** + ****************************************************************************** + ** +-** This SQLite extension implements a functions that compute SHA1 hashes. ++** This SQLite extension implements functions that compute SHA3 hashes. + ** Two SQL functions are implemented: + ** + ** sha3(X,SIZE) +@@ -2158,8 +2128,19 @@ + #include <errno.h> + + ++/* ++** Structure of the fsdir() table-valued function ++*/ ++ /* 0 1 2 3 4 5 */ + #define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)" ++#define FSDIR_COLUMN_NAME 0 /* Name of the file */ ++#define FSDIR_COLUMN_MODE 1 /* Access mode */ ++#define FSDIR_COLUMN_MTIME 2 /* Last modification time */ ++#define FSDIR_COLUMN_DATA 3 /* File content */ ++#define FSDIR_COLUMN_PATH 4 /* Path to top of search */ ++#define FSDIR_COLUMN_DIR 5 /* Path is relative to this directory */ + ++ + /* + ** Set the result stored by context ctx to a blob containing the + ** contents of file zName. +@@ -2256,7 +2237,7 @@ + extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*); + zUnicodeName = sqlite3_win32_utf8_to_unicode(zPath); + if( zUnicodeName ){ +- memset(&fd, 0, sizeof(WIN32_FIND_DATA)); ++ memset(&fd, 0, sizeof(WIN32_FIND_DATAW)); + hFindFile = FindFirstFileW(zUnicodeName, &fd); + if( hFindFile!=NULL ){ + pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime); +@@ -2747,20 +2728,20 @@ + ){ + fsdir_cursor *pCur = (fsdir_cursor*)cur; + switch( i ){ +- case 0: { /* name */ ++ case FSDIR_COLUMN_NAME: { + sqlite3_result_text(ctx, &pCur->zPath[pCur->nBase], -1, SQLITE_TRANSIENT); + break; + } + +- case 1: /* mode */ ++ case FSDIR_COLUMN_MODE: + sqlite3_result_int64(ctx, pCur->sStat.st_mode); + break; + +- case 2: /* mtime */ ++ case FSDIR_COLUMN_MTIME: + sqlite3_result_int64(ctx, pCur->sStat.st_mtime); + break; + +- case 3: { /* data */ ++ case FSDIR_COLUMN_DATA: { + mode_t m = pCur->sStat.st_mode; + if( S_ISDIR(m) ){ + sqlite3_result_null(ctx); +@@ -2790,6 +2771,12 @@ + readFileContents(ctx, pCur->zPath); + } + } ++ case FSDIR_COLUMN_PATH: ++ default: { ++ /* The FSDIR_COLUMN_PATH and FSDIR_COLUMN_DIR are input parameters. ++ ** always return their values as NULL */ ++ break; ++ } + } + return SQLITE_OK; + } +@@ -2816,6 +2803,9 @@ + + /* + ** xFilter callback. ++** ++** idxNum==1 PATH parameter only ++** idxNum==2 Both PATH and DIR supplied + */ + static int fsdirFilter( + sqlite3_vtab_cursor *cur, +@@ -2868,12 +2858,10 @@ + ** In this implementation idxNum is used to represent the + ** query plan. idxStr is unused. + ** +-** The query plan is represented by bits in idxNum: ++** The query plan is represented by values of idxNum: + ** +-** (1) start = $value -- constraint exists +-** (2) stop = $value -- constraint exists +-** (4) step = $value -- constraint exists +-** (8) output in descending order ++** (1) The path value is supplied by argv[0] ++** (2) Path is in argv[0] and dir is in argv[1] + */ + static int fsdirBestIndex( + sqlite3_vtab *tab, +@@ -2880,28 +2868,53 @@ + sqlite3_index_info *pIdxInfo + ){ + int i; /* Loop over constraints */ +- int idx4 = -1; +- int idx5 = -1; ++ int idxPath = -1; /* Index in pIdxInfo->aConstraint of PATH= */ ++ int idxDir = -1; /* Index in pIdxInfo->aConstraint of DIR= */ ++ int seenPath = 0; /* True if an unusable PATH= constraint is seen */ ++ int seenDir = 0; /* True if an unusable DIR= constraint is seen */ + const struct sqlite3_index_constraint *pConstraint; + + (void)tab; + pConstraint = pIdxInfo->aConstraint; + for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ +- if( pConstraint->usable==0 ) continue; + if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; +- if( pConstraint->iColumn==4 ) idx4 = i; +- if( pConstraint->iColumn==5 ) idx5 = i; ++ switch( pConstraint->iColumn ){ ++ case FSDIR_COLUMN_PATH: { ++ if( pConstraint->usable ){ ++ idxPath = i; ++ seenPath = 0; ++ }else if( idxPath<0 ){ ++ seenPath = 1; ++ } ++ break; ++ } ++ case FSDIR_COLUMN_DIR: { ++ if( pConstraint->usable ){ ++ idxDir = i; ++ seenDir = 0; ++ }else if( idxDir<0 ){ ++ seenDir = 1; ++ } ++ break; ++ } ++ } + } ++ if( seenPath || seenDir ){ ++ /* If input parameters are unusable, disallow this plan */ ++ return SQLITE_CONSTRAINT; ++ } + +- if( idx4<0 ){ ++ if( idxPath<0 ){ + pIdxInfo->idxNum = 0; +- pIdxInfo->estimatedCost = (double)(((sqlite3_int64)1) << 50); ++ /* The pIdxInfo->estimatedCost should have been initialized to a huge ++ ** number. Leave it unchanged. */ ++ pIdxInfo->estimatedRows = 0x7fffffff; + }else{ +- pIdxInfo->aConstraintUsage[idx4].omit = 1; +- pIdxInfo->aConstraintUsage[idx4].argvIndex = 1; +- if( idx5>=0 ){ +- pIdxInfo->aConstraintUsage[idx5].omit = 1; +- pIdxInfo->aConstraintUsage[idx5].argvIndex = 2; ++ pIdxInfo->aConstraintUsage[idxPath].omit = 1; ++ pIdxInfo->aConstraintUsage[idxPath].argvIndex = 1; ++ if( idxDir>=0 ){ ++ pIdxInfo->aConstraintUsage[idxDir].omit = 1; ++ pIdxInfo->aConstraintUsage[idxDir].argvIndex = 2; + pIdxInfo->idxNum = 2; + pIdxInfo->estimatedCost = 10.0; + }else{ +@@ -2940,7 +2953,8 @@ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ +- 0 /* xRollbackTo */ ++ 0, /* xRollbackTo */ ++ 0, /* xShadowName */ + }; + + int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0); +@@ -3042,6 +3056,7 @@ + char *zPrefix; /* The prefix for the word we want to complete */ + char *zLine; /* The whole that we want to complete */ + const char *zCurrentRow; /* Current output row */ ++ int szRow; /* Length of the zCurrentRow string */ + sqlite3_stmt *pStmt; /* Current statement */ + sqlite3_int64 iRowid; /* The rowid */ + int ePhase; /* Current phase */ +@@ -3155,32 +3170,6 @@ + } + + /* +-** All SQL keywords understood by SQLite +-*/ +-static const char *completionKwrds[] = { +- "ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS", +- "ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY", +- "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT", +- "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE", +- "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE", +- "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH", +- "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN", +- "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF", +- "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER", +- "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY", +- "LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL", +- "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA", +- "PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP", +- "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT", +- "ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP", +- "TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE", +- "UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE", +- "WITH", "WITHOUT", +-}; +-#define completionKwCount \ +- (int)(sizeof(completionKwrds)/sizeof(completionKwrds[0])) +- +-/* + ** Advance a completion_cursor to its next row of output. + ** + ** The ->ePhase, ->j, and ->pStmt fields of the completion_cursor object +@@ -3202,11 +3191,11 @@ + while( pCur->ePhase!=COMPLETION_EOF ){ + switch( pCur->ePhase ){ + case COMPLETION_KEYWORDS: { +- if( pCur->j >= completionKwCount ){ ++ if( pCur->j >= sqlite3_keyword_count() ){ + pCur->zCurrentRow = 0; + pCur->ePhase = COMPLETION_DATABASES; + }else{ +- pCur->zCurrentRow = completionKwrds[pCur->j++]; ++ sqlite3_keyword_name(pCur->j++, &pCur->zCurrentRow, &pCur->szRow); + } + iCol = -1; + break; +@@ -3278,6 +3267,7 @@ + if( sqlite3_step(pCur->pStmt)==SQLITE_ROW ){ + /* Extract the next row of content */ + pCur->zCurrentRow = (const char*)sqlite3_column_text(pCur->pStmt, iCol); ++ pCur->szRow = sqlite3_column_bytes(pCur->pStmt, iCol); + }else{ + /* When all rows are finished, advance to the next phase */ + sqlite3_finalize(pCur->pStmt); +@@ -3287,7 +3277,9 @@ + } + } + if( pCur->nPrefix==0 ) break; +- if( sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0 ){ ++ if( pCur->nPrefix<=pCur->szRow ++ && sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0 ++ ){ + break; + } + } +@@ -3307,7 +3299,7 @@ + completion_cursor *pCur = (completion_cursor*)cur; + switch( i ){ + case COMPLETION_COLUMN_CANDIDATE: { +- sqlite3_result_text(ctx, pCur->zCurrentRow, -1, SQLITE_TRANSIENT); ++ sqlite3_result_text(ctx, pCur->zCurrentRow, pCur->szRow,SQLITE_TRANSIENT); + break; + } + case COMPLETION_COLUMN_PREFIX: { +@@ -3367,7 +3359,7 @@ + pCur->zPrefix = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg])); + if( pCur->zPrefix==0 ) return SQLITE_NOMEM; + } +- iArg++; ++ iArg = 1; + } + if( idxNum & 2 ){ + pCur->nLine = sqlite3_value_bytes(argv[iArg]); +@@ -3375,7 +3367,6 @@ + pCur->zLine = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg])); + if( pCur->zLine==0 ) return SQLITE_NOMEM; + } +- iArg++; + } + if( pCur->zLine!=0 && pCur->zPrefix==0 ){ + int i = pCur->nLine; +@@ -3471,7 +3462,8 @@ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ +- 0 /* xRollbackTo */ ++ 0, /* xRollbackTo */ ++ 0 /* xShadowName */ + }; + + #endif /* SQLITE_OMIT_VIRTUALTABLE */ +@@ -5368,25 +5360,26 @@ + sqlite3_index_info *pIdxInfo + ){ + int i; ++ int idx = -1; ++ int unusable = 0; + + for(i=0; i<pIdxInfo->nConstraint; i++){ + const struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i]; +- if( pCons->usable==0 ) continue; +- if( pCons->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; + if( pCons->iColumn!=ZIPFILE_F_COLUMN_IDX ) continue; +- break; ++ if( pCons->usable==0 ){ ++ unusable = 1; ++ }else if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){ ++ idx = i; ++ } + } +- +- if( i<pIdxInfo->nConstraint ){ +- pIdxInfo->aConstraintUsage[i].argvIndex = 1; +- pIdxInfo->aConstraintUsage[i].omit = 1; ++ if( idx>=0 ){ ++ pIdxInfo->aConstraintUsage[idx].argvIndex = 1; ++ pIdxInfo->aConstraintUsage[idx].omit = 1; + pIdxInfo->estimatedCost = 1000.0; + pIdxInfo->idxNum = 1; +- }else{ +- pIdxInfo->estimatedCost = (double)(((sqlite3_int64)1) << 50); +- pIdxInfo->idxNum = 0; ++ }else if( unusable ){ ++ return SQLITE_CONSTRAINT; + } +- + return SQLITE_OK; + } + +@@ -7189,6 +7182,7 @@ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ ++ 0, /* xShadowName */ + }; + + return sqlite3_create_module(p->dbv, "expert", &expertModule, (void*)p); +@@ -7668,9 +7662,9 @@ + "EXPLAIN QUERY PLAN %s", pStmt->zSql + ); + while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){ +- int iSelectid = sqlite3_column_int(pExplain, 0); +- int iOrder = sqlite3_column_int(pExplain, 1); +- int iFrom = sqlite3_column_int(pExplain, 2); ++ /* int iId = sqlite3_column_int(pExplain, 0); */ ++ /* int iParent = sqlite3_column_int(pExplain, 1); */ ++ /* int iNotUsed = sqlite3_column_int(pExplain, 2); */ + const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3); + int nDetail = STRLEN(zDetail); + int i; +@@ -7697,9 +7691,9 @@ + } + } + +- pStmt->zEQP = idxAppendText(&rc, pStmt->zEQP, "%d|%d|%d|%s\n", +- iSelectid, iOrder, iFrom, zDetail +- ); ++ if( zDetail[0]!='-' ){ ++ pStmt->zEQP = idxAppendText(&rc, pStmt->zEQP, "%s\n", zDetail); ++ } + } + + for(pEntry=hIdx.pFirst; pEntry; pEntry=pEntry->pNext){ +@@ -8529,6 +8523,23 @@ + int bVerbose; + }; + ++/* A single line in the EQP output */ ++typedef struct EQPGraphRow EQPGraphRow; ++struct EQPGraphRow { ++ int iEqpId; /* ID for this row */ ++ int iParentId; /* ID of the parent row */ ++ EQPGraphRow *pNext; /* Next row in sequence */ ++ char zText[1]; /* Text to display for this row */ ++}; ++ ++/* All EQP output is collected into an instance of the following */ ++typedef struct EQPGraph EQPGraph; ++struct EQPGraph { ++ EQPGraphRow *pRow; /* Linked list of all rows of the EQP output */ ++ EQPGraphRow *pLast; /* Last element of the pRow list */ ++ char zPrefix[100]; /* Graph prefix */ ++}; ++ + /* + ** State information about the database connection is contained in an + ** instance of the following structure. +@@ -8538,10 +8549,13 @@ + sqlite3 *db; /* The database */ + u8 autoExplain; /* Automatically turn on .explain mode */ + u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ ++ u8 autoEQPtest; /* autoEQP is in test mode */ + u8 statsOn; /* True to display memory stats before each finalize */ + u8 scanstatsOn; /* True to display scan stats before each finalize */ + u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */ + u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */ ++ u8 nEqpLevel; /* Depth of the EQP output graph */ ++ unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */ + int outCount; /* Revert to stdout when reaching zero */ + int cnt; /* Number of records displayed so far */ + FILE *out; /* Write results here */ +@@ -8575,6 +8589,7 @@ + int *aiIndent; /* Array of indents used in MODE_Explain */ + int nIndent; /* Size of array aiIndent[] */ + int iIndent; /* Index of current op in aiIndent[] */ ++ EQPGraph sGraph; /* Information for the graphical EXPLAIN QUERY PLAN */ + #if defined(SQLITE_ENABLE_SESSION) + int nSession; /* Number of active sessions */ + OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */ +@@ -8585,18 +8600,19 @@ + + /* Allowed values for ShellState.autoEQP + */ +-#define AUTOEQP_off 0 +-#define AUTOEQP_on 1 +-#define AUTOEQP_trigger 2 +-#define AUTOEQP_full 3 ++#define AUTOEQP_off 0 /* Automatic EXPLAIN QUERY PLAN is off */ ++#define AUTOEQP_on 1 /* Automatic EQP is on */ ++#define AUTOEQP_trigger 2 /* On and also show plans for triggers */ ++#define AUTOEQP_full 3 /* Show full EXPLAIN */ + + /* Allowed values for ShellState.openMode + */ +-#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */ +-#define SHELL_OPEN_NORMAL 1 /* Normal database file */ +-#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */ +-#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */ +-#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */ ++#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */ ++#define SHELL_OPEN_NORMAL 1 /* Normal database file */ ++#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */ ++#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */ ++#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */ ++#define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */ + + /* + ** These are the allowed shellFlgs values +@@ -8631,6 +8647,7 @@ + #define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */ + #define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */ + #define MODE_Pretty 11 /* Pretty-print schemas */ ++#define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */ + + static const char *modeDescr[] = { + "line", +@@ -8645,6 +8662,7 @@ + "explain", + "ascii", + "prettyprint", ++ "eqp" + }; + + /* +@@ -8715,6 +8733,7 @@ + char *zCmd = 0; + int bBin; + int rc; ++ int hasCRNL = 0; + FILE *f = 0; + sqlite3_int64 sz; + sqlite3_int64 x; +@@ -8746,6 +8765,8 @@ + } + } + bBin = sqlite3_value_type(argv[0])==SQLITE_BLOB; ++ /* When writing the file to be edited, do \n to \r\n conversions on systems ++ ** that want \r\n line endings */ + f = fopen(zTempFile, bBin ? "wb" : "w"); + if( f==0 ){ + sqlite3_result_error(context, "edit() cannot open temp file", -1); +@@ -8755,6 +8776,9 @@ + if( bBin ){ + x = fwrite(sqlite3_value_blob(argv[0]), 1, sz, f); + }else{ ++ const char *z = (const char*)sqlite3_value_text(argv[0]); ++ /* Remember whether or not the value originally contained \r\n */ ++ if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1; + x = fwrite(sqlite3_value_text(argv[0]), 1, sz, f); + } + fclose(f); +@@ -8774,7 +8798,7 @@ + sqlite3_result_error(context, "EDITOR returned non-zero", -1); + goto edit_func_end; + } +- f = fopen(zTempFile, bBin ? "rb" : "r"); ++ f = fopen(zTempFile, "rb"); + if( f==0 ){ + sqlite3_result_error(context, + "edit() cannot reopen temp file after edit", -1); +@@ -8788,12 +8812,7 @@ + sqlite3_result_error_nomem(context); + goto edit_func_end; + } +- if( bBin ){ +- x = fread(p, 1, sz, f); +- }else{ +- x = fread(p, 1, sz, f); +- p[sz] = 0; +- } ++ x = fread(p, 1, sz, f); + fclose(f); + f = 0; + if( x!=sz ){ +@@ -8803,6 +8822,20 @@ + if( bBin ){ + sqlite3_result_blob64(context, p, sz, sqlite3_free); + }else{ ++ sqlite3_int64 i, j; ++ if( hasCRNL ){ ++ /* If the original contains \r\n then do no conversions back to \n */ ++ j = sz; ++ }else{ ++ /* If the file did not originally contain \r\n then convert any new ++ ** \r\n back into \n */ ++ for(i=j=0; i<sz; i++){ ++ if( p[i]=='\r' && p[i+1]=='\n' ) i++; ++ p[j++] = p[i]; ++ } ++ sz = j; ++ p[sz] = 0; ++ } + sqlite3_result_text64(context, (const char*)p, sz, + sqlite3_free, SQLITE_UTF8); + } +@@ -9193,9 +9226,95 @@ + } + return 1; + } +- + + /* ++** Add a new entry to the EXPLAIN QUERY PLAN data ++*/ ++static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){ ++ EQPGraphRow *pNew; ++ int nText = strlen30(zText); ++ if( p->autoEQPtest ){ ++ utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText); ++ } ++ pNew = sqlite3_malloc64( sizeof(*pNew) + nText ); ++ if( pNew==0 ) shell_out_of_memory(); ++ pNew->iEqpId = iEqpId; ++ pNew->iParentId = p2; ++ memcpy(pNew->zText, zText, nText+1); ++ pNew->pNext = 0; ++ if( p->sGraph.pLast ){ ++ p->sGraph.pLast->pNext = pNew; ++ }else{ ++ p->sGraph.pRow = pNew; ++ } ++ p->sGraph.pLast = pNew; ++} ++ ++/* ++** Free and reset the EXPLAIN QUERY PLAN data that has been collected ++** in p->sGraph. ++*/ ++static void eqp_reset(ShellState *p){ ++ EQPGraphRow *pRow, *pNext; ++ for(pRow = p->sGraph.pRow; pRow; pRow = pNext){ ++ pNext = pRow->pNext; ++ sqlite3_free(pRow); ++ } ++ memset(&p->sGraph, 0, sizeof(p->sGraph)); ++} ++ ++/* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after ++** pOld, or return the first such line if pOld is NULL ++*/ ++static EQPGraphRow *eqp_next_row(ShellState *p, int iEqpId, EQPGraphRow *pOld){ ++ EQPGraphRow *pRow = pOld ? pOld->pNext : p->sGraph.pRow; ++ while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext; ++ return pRow; ++} ++ ++/* Render a single level of the graph that has iEqpId as its parent. Called ++** recursively to render sublevels. ++*/ ++static void eqp_render_level(ShellState *p, int iEqpId){ ++ EQPGraphRow *pRow, *pNext; ++ int n = strlen30(p->sGraph.zPrefix); ++ char *z; ++ for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){ ++ pNext = eqp_next_row(p, iEqpId, pRow); ++ z = pRow->zText; ++ utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix, pNext ? "|--" : "`--", z); ++ if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){ ++ memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4); ++ eqp_render_level(p, pRow->iEqpId); ++ p->sGraph.zPrefix[n] = 0; ++ } ++ } ++} ++ ++/* ++** Display and reset the EXPLAIN QUERY PLAN data ++*/ ++static void eqp_render(ShellState *p){ ++ EQPGraphRow *pRow = p->sGraph.pRow; ++ if( pRow ){ ++ if( pRow->zText[0]=='-' ){ ++ if( pRow->pNext==0 ){ ++ eqp_reset(p); ++ return; ++ } ++ utf8_printf(p->out, "%s\n", pRow->zText+3); ++ p->sGraph.pRow = pRow->pNext; ++ sqlite3_free(pRow); ++ }else{ ++ utf8_printf(p->out, "QUERY PLAN\n"); ++ } ++ p->sGraph.zPrefix[0] = 0; ++ eqp_render_level(p, 0); ++ eqp_reset(p); ++ } ++} ++ ++/* + ** This is the callback routine that the shell + ** invokes for each row of a query result. + */ +@@ -9475,8 +9594,16 @@ + }else if( aiType && aiType[i]==SQLITE_FLOAT ){ + char z[50]; + double r = sqlite3_column_double(p->pStmt, i); +- sqlite3_snprintf(50,z,"%!.20g", r); +- raw_printf(p->out, "%s", z); ++ 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); +@@ -9544,6 +9671,10 @@ + utf8_printf(p->out, "%s", p->rowSeparator); + break; + } ++ case MODE_EQP: { ++ eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]); ++ break; ++ } + } + return 0; + } +@@ -9642,10 +9773,7 @@ + n = strlen30(zName); + if( cQuote ) n += n+2; + z = p->zDestTable = malloc( n+1 ); +- if( z==0 ){ +- raw_printf(stderr,"Error: out of memory\n"); +- exit(1); +- } ++ if( z==0 ) shell_out_of_memory(); + n = 0; + if( cQuote ) z[n++] = cQuote; + for(i=0; zName[i]; i++){ +@@ -10008,8 +10136,7 @@ + int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */ + int iOp; /* Index of operation in p->aiIndent[] */ + +- const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", +- "NextIfOpen", "PrevIfOpen", 0 }; ++ const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 }; + const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead", + "Rewind", 0 }; + const char *azGoto[] = { "Goto", 0 }; +@@ -10059,7 +10186,9 @@ + } + nAlloc += 100; + p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int)); ++ if( p->aiIndent==0 ) shell_out_of_memory(); + abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int)); ++ if( abYield==0 ) shell_out_of_memory(); + } + abYield[iOp] = str_in_array(zOp, azYield); + p->aiIndent[iOp] = 0; +@@ -10385,11 +10514,13 @@ + rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0); + if( rc==SQLITE_OK ){ + while( sqlite3_step(pExplain)==SQLITE_ROW ){ +- raw_printf(pArg->out,"--EQP-- %d,",sqlite3_column_int(pExplain, 0)); +- raw_printf(pArg->out,"%d,", sqlite3_column_int(pExplain, 1)); +- raw_printf(pArg->out,"%d,", sqlite3_column_int(pExplain, 2)); +- utf8_printf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3)); ++ const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3); ++ int iEqpId = sqlite3_column_int(pExplain, 0); ++ int iParentId = sqlite3_column_int(pExplain, 1); ++ if( zEQPLine[0]=='-' ) eqp_render(pArg); ++ eqp_append(pArg, iEqpId, iParentId, zEQPLine); + } ++ eqp_render(pArg); + } + sqlite3_finalize(pExplain); + sqlite3_free(zEQP); +@@ -10411,6 +10542,7 @@ + /* Reprepare pStmt before reactiving trace modes */ + sqlite3_finalize(pStmt); + sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); ++ if( pArg ) pArg->pStmt = pStmt; + } + restore_debug_trace_modes(); + } +@@ -10417,11 +10549,16 @@ + + if( pArg ){ + pArg->cMode = pArg->mode; +- if( pArg->autoExplain +- && sqlite3_column_count(pStmt)==8 +- && sqlite3_strlike("EXPLAIN%", zStmtSql,0)==0 +- ){ +- pArg->cMode = MODE_Explain; ++ if( pArg->autoExplain ){ ++ if( sqlite3_column_count(pStmt)==8 ++ && sqlite3_strlike("EXPLAIN%", zStmtSql,0)==0 ++ ){ ++ pArg->cMode = MODE_Explain; ++ } ++ if( sqlite3_column_count(pStmt)==4 ++ && sqlite3_strlike("EXPLAIN QUERY PLAN%", zStmtSql,0)==0 ){ ++ pArg->cMode = MODE_EQP; ++ } + } + + /* If the shell is currently in ".explain" mode, gather the extra +@@ -10433,6 +10570,7 @@ + + exec_prepared_stmt(pArg, pStmt); + explain_data_delete(pArg); ++ eqp_render(pArg); + + /* print usage stats if stats on */ + if( pArg && pArg->statsOn ){ +@@ -10510,10 +10648,7 @@ + if( nCol>=nAlloc-2 ){ + nAlloc = nAlloc*2 + nCol + 10; + azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0])); +- if( azCol==0 ){ +- raw_printf(stderr, "Error: out of memory\n"); +- exit(1); +- } ++ if( azCol==0 ) shell_out_of_memory(); + } + azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1)); + if( sqlite3_column_int(pStmt, 5) ){ +@@ -10749,136 +10884,239 @@ + } + + /* +-** Text of a help message ++** Text of help messages. ++** ++** The help text for each individual command begins with a line that starts ++** with ".". Subsequent lines are supplimental information. ++** ++** There must be two or more spaces between the end of the command and the ++** start of the description of what that command does. + */ +-static char zHelp[] = ++static const char *(azHelp[]) = { + #if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE) +- ".archive ... Manage SQL archives: \".archive --help\" for details\n" ++ ".archive ... Manage SQL archives", ++ " Each command must have exactly one of the following options:", ++ " -c, --create Create a new archive", ++ " -u, --update Update or add files to an existing archive", ++ " -t, --list List contents of archive", ++ " -x, --extract Extract files from archive", ++ " Optional arguments:", ++ " -v, --verbose Print each filename as it is processed", ++ " -f FILE, --file FILE Operate on archive FILE (default is current db)", ++ " -a FILE, --append FILE Operate on FILE opened using the apndvfs VFS", ++ " -C DIR, --directory DIR Change to directory DIR to read/extract files", ++ " -n, --dryrun Show the SQL that would have occurred", ++ " Examples:", ++ " .ar -cf archive.sar foo bar # Create archive.sar from files foo and bar", ++ " .ar -tf archive.sar # List members of archive.sar", ++ " .ar -xvf archive.sar # Verbosely extract files from archive.sar", ++ " See also:", ++ " http://sqlite.org/cli.html#sqlar_archive_support", + #endif + #ifndef SQLITE_OMIT_AUTHORIZATION +- ".auth ON|OFF Show authorizer callbacks\n" ++ ".auth ON|OFF Show authorizer callbacks", + #endif +- ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n" +- ".bail on|off Stop after hitting an error. Default OFF\n" +- ".binary on|off Turn binary output on or off. Default OFF\n" +- ".cd DIRECTORY Change the working directory to DIRECTORY\n" +- ".changes on|off Show number of rows changed by SQL\n" +- ".check GLOB Fail if output since .testcase does not match\n" +- ".clone NEWDB Clone data into NEWDB from the existing database\n" +- ".databases List names and files of attached databases\n" +- ".dbinfo ?DB? Show status information about the database\n" +- ".dump ?TABLE? ... Dump the database in an SQL text format\n" +- " If TABLE specified, only dump tables matching\n" +- " LIKE pattern TABLE.\n" +- ".echo on|off Turn command echo on or off\n" +- ".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN\n" +- ".excel Display the output of next command in a spreadsheet\n" +- ".exit Exit this program\n" +- ".expert EXPERIMENTAL. Suggest indexes for specified queries\n" ++ ".backup ?DB? FILE Backup DB (default \"main\") to FILE", ++ " --append Use the appendvfs", ++ ".bail on|off Stop after hitting an error. Default OFF", ++ ".binary on|off Turn binary output on or off. Default OFF", ++ ".cd DIRECTORY Change the working directory to DIRECTORY", ++ ".changes on|off Show number of rows changed by SQL", ++ ".check GLOB Fail if output since .testcase does not match", ++ ".clone NEWDB Clone data into NEWDB from the existing database", ++ ".databases List names and files of attached databases", ++ ".dbconfig ?op? ?val? List or change sqlite3_db_config() options", ++ ".dbinfo ?DB? Show status information about the database", ++ ".dump ?TABLE? ... Render all database content as SQL", ++ " Options:", ++ " --preserve-rowids Include ROWID values in the output", ++ " --newlines Allow unescaped newline characters in output", ++ " TABLE is LIKE pattern for the tables to dump", ++ ".echo on|off Turn command echo on or off", ++ ".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN", ++ ".excel Display the output of next command in a spreadsheet", ++ ".exit ?CODE? Exit this program with return-code CODE", ++ ".expert EXPERIMENTAL. Suggest indexes for specified queries", + /* Because explain mode comes on automatically now, the ".explain" mode + ** is removed from the help screen. It is still supported for legacy, however */ +-/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic\n"*/ +- ".fullschema ?--indent? Show schema and the content of sqlite_stat tables\n" +- ".headers on|off Turn display of headers on or off\n" +- ".help Show this message\n" +- ".import FILE TABLE Import data from FILE into TABLE\n" ++/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic",*/ ++ ".fullschema ?--indent? Show schema and the content of sqlite_stat tables", ++ ".headers on|off Turn display of headers on or off", ++ ".help ?-all? ?PATTERN? Show help text for PATTERN", ++ ".import FILE TABLE Import data from FILE into TABLE", + #ifndef SQLITE_OMIT_TEST_CONTROL +- ".imposter INDEX TABLE Create imposter table TABLE on index INDEX\n" ++ ".imposter INDEX TABLE Create imposter table TABLE on index INDEX", + #endif +- ".indexes ?TABLE? Show names of all indexes\n" +- " If TABLE specified, only show indexes for tables\n" +- " matching LIKE pattern TABLE.\n" ++ ".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\n" ++ ".iotrace FILE Enable I/O diagnostic logging to FILE", + #endif +- ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT\n" +- ".lint OPTIONS Report potential schema issues. Options:\n" +- " fkey-indexes Find missing foreign key indexes\n" ++ ".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", + #ifndef SQLITE_OMIT_LOAD_EXTENSION +- ".load FILE ?ENTRY? Load an extension library\n" ++ ".load FILE ?ENTRY? Load an extension library", + #endif +- ".log FILE|off Turn logging on or off. FILE can be stderr/stdout\n" +- ".mode MODE ?TABLE? Set output mode where MODE is one of:\n" +- " ascii Columns/rows delimited by 0x1F and 0x1E\n" +- " csv Comma-separated values\n" +- " column Left-aligned columns. (See .width)\n" +- " html HTML <table> code\n" +- " insert SQL insert statements for TABLE\n" +- " line One value per line\n" +- " list Values delimited by \"|\"\n" +- " quote Escape answers as for SQL\n" +- " tabs Tab-separated values\n" +- " tcl TCL list elements\n" +- ".nullvalue STRING Use STRING in place of NULL values\n" +- ".once (-e|-x|FILE) Output for the next SQL command only to FILE\n" +- " or invoke system text editor (-e) or spreadsheet (-x)\n" +- " on the output.\n" +- ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE\n" +- " The --new option starts with an empty file\n" +- " Other options: --readonly --append --zip\n" +- ".output ?FILE? Send output to FILE or stdout\n" +- ".print STRING... Print literal STRING\n" +- ".prompt MAIN CONTINUE Replace the standard prompts\n" +- ".quit Exit this program\n" +- ".read FILENAME Execute SQL in FILENAME\n" +- ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n" +- ".save FILE Write in-memory database into FILE\n" +- ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off\n" +- ".schema ?PATTERN? Show the CREATE statements matching PATTERN\n" +- " Add --indent for pretty-printing\n" +- ".selftest ?--init? Run tests defined in the SELFTEST table\n" +- ".separator COL ?ROW? Change the column separator and optionally the row\n" +- " separator for both the output mode and .import\n" ++ ".log FILE|off Turn logging on or off. FILE can be stderr/stdout", ++ ".mode MODE ?TABLE? Set output mode", ++ " MODE is one of:", ++ " ascii Columns/rows delimited by 0x1F and 0x1E", ++ " csv Comma-separated values", ++ " column Left-aligned columns. (See .width)", ++ " html HTML <table> code", ++ " insert SQL insert statements for TABLE", ++ " line One value per line", ++ " list Values delimited by \"|\"", ++ " quote Escape answers as for SQL", ++ " tabs Tab-separated values", ++ " tcl TCL list elements", ++ ".nullvalue STRING Use STRING in place of NULL values", ++ ".once (-e|-x|FILE) Output for the next SQL command only to FILE", ++ " If FILE begins with '|' then open as a pipe", ++ " Other options:", ++ " -e Invoke system text editor", ++ " -x Open in a spreadsheet", ++ ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE", ++ " Options:", ++ " --append Use appendvfs to append database to the end of FILE", ++#ifdef SQLITE_ENABLE_DESERIALIZE ++ " --deserialize Load into memory useing sqlite3_deserialize()", ++#endif ++ " --new Initialize FILE to an empty database", ++ " --readonly Open FILE readonly", ++ " --zip FILE is a ZIP archive", ++ ".output ?FILE? Send output to FILE or stdout if FILE is omitted", ++ " If FILE begins with '|' then open it as a pipe.", ++ ".print STRING... Print literal STRING", ++ ".prompt MAIN CONTINUE Replace the standard prompts", ++ ".quit Exit this program", ++ ".read FILE Read input from FILE", ++ ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE", ++ ".save FILE Write in-memory database into FILE", ++ ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off", ++ ".schema ?PATTERN? Show the CREATE statements matching PATTERN", ++ " Options:", ++ " --indent Try to pretty-print the schema", ++ ".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 CMD ... Create or control sessions\n" ++ ".session ?NAME? CMD ... Create or control sessions", ++ " Subcommands:", ++ " attach TABLE Attach TABLE", ++ " changeset FILE Write a changeset into FILE", ++ " close Close one session", ++ " enable ?BOOLEAN? Set or query the enable bit", ++ " filter GLOB... Reject tables matching GLOBs", ++ " indirect ?BOOLEAN? Mark or query the indirect status", ++ " isempty Query whether the session is empty", ++ " list List currently open session names", ++ " open DB NAME Open a new session on DB", ++ " patchset FILE Write a patchset into FILE", ++ " If ?NAME? is omitted, the first defined session is used.", + #endif +- ".sha3sum ?OPTIONS...? Compute a SHA3 hash of database content\n" ++ ".sha3sum ... Compute a SHA3 hash of database content", ++ " Options:", ++ " --schema Also hash the sqlite_master table", ++ " --sha3-224 Use the sha3-224 algorithm", ++ " --sha3-256 Use the sha3-256 algorithm. This is the default.", ++ " --sha3-384 Use the sha3-384 algorithm", ++ " --sha3-512 Use the sha3-512 algorithm", ++ " Any other argument is a LIKE pattern for tables to hash", + #ifndef SQLITE_NOHAVE_SYSTEM +- ".shell CMD ARGS... Run CMD ARGS... in a system shell\n" ++ ".shell CMD ARGS... Run CMD ARGS... in a system shell", + #endif +- ".show Show the current values for various settings\n" +- ".stats ?on|off? Show stats or turn stats on or off\n" ++ ".show Show the current values for various settings", ++ ".stats ?on|off? Show stats or turn stats on or off", + #ifndef SQLITE_NOHAVE_SYSTEM +- ".system CMD ARGS... Run CMD ARGS... in a system shell\n" ++ ".system CMD ARGS... Run CMD ARGS... in a system shell", + #endif +- ".tables ?TABLE? List names of tables\n" +- " If TABLE specified, only list tables matching\n" +- " LIKE pattern TABLE.\n" +- ".testcase NAME Begin redirecting output to 'testcase-out.txt'\n" +- ".timeout MS Try opening locked tables for MS milliseconds\n" +- ".timer on|off Turn SQL timer on or off\n" +- ".trace FILE|off Output each SQL statement as it is run\n" +- ".vfsinfo ?AUX? Information about the top-level VFS\n" +- ".vfslist List all available VFSes\n" +- ".vfsname ?AUX? Print the name of the VFS stack\n" +- ".width NUM1 NUM2 ... Set column widths for \"column\" mode\n" +- " Negative values right-justify\n" +-; ++ ".tables ?TABLE? List names of tables matching LIKE pattern TABLE", ++ ".testcase NAME Begin redirecting output to 'testcase-out.txt'", ++ ".timeout MS Try opening locked tables for MS milliseconds", ++ ".timer on|off Turn SQL timer on or off", ++ ".trace FILE|off Output each SQL statement as it is run", ++ ".vfsinfo ?AUX? Information about the top-level VFS", ++ ".vfslist List all available VFSes", ++ ".vfsname ?AUX? Print the name of the VFS stack", ++ ".width NUM1 NUM2 ... Set column widths for \"column\" mode", ++ " Negative values right-justify", ++}; + +-#if defined(SQLITE_ENABLE_SESSION) + /* +-** Print help information for the ".sessions" command ++** Output help text. ++** ++** zPattern describes the set of commands for which help text is provided. ++** If zPattern is NULL, then show all commands, but only give a one-line ++** description of each. ++** ++** Return the number of matches. + */ +-void session_help(ShellState *p){ +- raw_printf(p->out, +- ".session ?NAME? SUBCOMMAND ?ARGS...?\n" +- "If ?NAME? is omitted, the first defined session is used.\n" +- "Subcommands:\n" +- " attach TABLE Attach TABLE\n" +- " changeset FILE Write a changeset into FILE\n" +- " close Close one session\n" +- " enable ?BOOLEAN? Set or query the enable bit\n" +- " filter GLOB... Reject tables matching GLOBs\n" +- " indirect ?BOOLEAN? Mark or query the indirect status\n" +- " isempty Query whether the session is empty\n" +- " list List currently open session names\n" +- " open DB NAME Open a new session on DB\n" +- " patchset FILE Write a patchset into FILE\n" +- ); ++static int showHelp(FILE *out, const char *zPattern){ ++ int i = 0; ++ int j = 0; ++ int n = 0; ++ char *zPat; ++ if( zPattern==0 ++ || zPattern[0]=='0' ++ || strcmp(zPattern,"-a")==0 ++ || 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); ++ 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); ++ 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++; ++ } ++ } ++ sqlite3_free(zPat); ++ } ++ return n; + } +-#endif + +- + /* Forward reference */ + static int process_input(ShellState *p, FILE *in); + +@@ -10907,7 +11145,7 @@ + nIn = ftell(in); + rewind(in); + pBuf = sqlite3_malloc64( nIn+1 ); +- if( pBuf==0 ) return 0; ++ if( pBuf==0 ){ fclose(in); return 0; } + nRead = fread(pBuf, nIn, 1, in); + fclose(in); + if( nRead!=1 ){ +@@ -10975,13 +11213,21 @@ + ** Otherwise, assume an ordinary database regardless of the filename if + ** the type cannot be determined from content. + */ +-static int deduceDatabaseType(const char *zName, int dfltZip){ ++int deduceDatabaseType(const char *zName, int dfltZip){ + FILE *f = fopen(zName, "rb"); + size_t n; + int rc = SHELL_OPEN_UNSPEC; + char zBuf[100]; + if( f==0 ){ +- if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ) return SHELL_OPEN_ZIPFILE; ++ if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){ ++ return SHELL_OPEN_ZIPFILE; ++ }else{ ++ return SHELL_OPEN_NORMAL; ++ } ++ } ++ n = fread(zBuf, 16, 1, f); ++ if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){ ++ fclose(f); + return SHELL_OPEN_NORMAL; + } + fseek(f, -25, SEEK_END); +@@ -10995,7 +11241,7 @@ + && zBuf[3]==0x06 ){ + rc = SHELL_OPEN_ZIPFILE; + }else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){ +- return SHELL_OPEN_ZIPFILE; ++ rc = SHELL_OPEN_ZIPFILE; + } + } + fclose(f); +@@ -11002,15 +11248,32 @@ + return rc; + } + ++/* 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. ++** ++** The OPEN_DB_ZIPFILE flag causes open_db() to prefer to open files as a ++** ZIP archive if the file does not exist or is empty and its name matches ++** the *.zip pattern. ++*/ ++#define OPEN_DB_KEEPALIVE 0x001 /* Return after error if true */ ++#define OPEN_DB_ZIPFILE 0x002 /* Open as ZIP if name matches *.zip */ ++ + /* + ** Make sure the database is open. If it is not, then open it. If + ** the database fails to open, print an error message and exit. + */ +-static void open_db(ShellState *p, int keepAlive){ ++static void open_db(ShellState *p, int openFlags){ + if( p->db==0 ){ +- sqlite3_initialize(); +- if( p->openMode==SHELL_OPEN_UNSPEC && access(p->zDbFilename,0)==0 ){ +- p->openMode = (u8)deduceDatabaseType(p->zDbFilename, 0); ++ if( p->openMode==SHELL_OPEN_UNSPEC ){ ++ if( p->zDbFilename==0 || p->zDbFilename[0]==0 ){ ++ p->openMode = SHELL_OPEN_NORMAL; ++ }else{ ++ p->openMode = (u8)deduceDatabaseType(p->zDbFilename, ++ (openFlags & OPEN_DB_ZIPFILE)!=0); ++ } + } + switch( p->openMode ){ + case SHELL_OPEN_APPENDVFS: { +@@ -11018,6 +11281,10 @@ + SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, "apndvfs"); + break; + } ++ case SHELL_OPEN_DESERIALIZE: { ++ sqlite3_open(0, &p->db); ++ break; ++ } + case SHELL_OPEN_ZIPFILE: { + sqlite3_open(":memory:", &p->db); + break; +@@ -11036,7 +11303,7 @@ + if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){ + utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n", + p->zDbFilename, sqlite3_errmsg(p->db)); +- if( keepAlive ) return; ++ if( openFlags & OPEN_DB_KEEPALIVE ) return; + exit(1); + } + #ifndef SQLITE_OMIT_LOAD_EXTENSION +@@ -11067,9 +11334,32 @@ + sqlite3_exec(p->db, zSql, 0, 0, 0); + sqlite3_free(zSql); + } ++#ifdef SQLITE_ENABLE_DESERIALIZE ++ else if( p->openMode==SHELL_OPEN_DESERIALIZE ){ ++ int nData = 0; ++ unsigned char *aData = (unsigned char*)readFile(p->zDbFilename, &nData); ++ int 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); ++ } ++ } ++#endif + } + } + ++/* ++** Attempt to close the databaes connection. Report errors. ++*/ ++void close_db(sqlite3 *db){ ++ int rc = sqlite3_close(db); ++ if( rc ){ ++ utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n", ++ rc, sqlite3_errmsg(db)); ++ } ++} ++ + #if HAVE_READLINE || HAVE_EDITLINE + /* + ** Readline completion callbacks +@@ -11111,7 +11401,7 @@ + char zBuf[1000]; + + if( nLine>sizeof(zBuf)-30 ) return; +- if( zLine[0]=='.' ) 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; +@@ -11311,10 +11601,7 @@ + if( p->n+1>=p->nAlloc ){ + p->nAlloc += p->nAlloc + 100; + p->z = sqlite3_realloc64(p->z, p->nAlloc); +- if( p->z==0 ){ +- raw_printf(stderr, "out of memory\n"); +- exit(1); +- } ++ if( p->z==0 ) shell_out_of_memory(); + } + p->z[p->n++] = (char)c; + } +@@ -11475,10 +11762,7 @@ + } + n = sqlite3_column_count(pQuery); + zInsert = sqlite3_malloc64(200 + nTable + n*3); +- if( zInsert==0 ){ +- raw_printf(stderr, "out of memory\n"); +- goto end_data_xfer; +- } ++ if( zInsert==0 ) shell_out_of_memory(); + sqlite3_snprintf(200+nTable,zInsert, + "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable); + i = strlen30(zInsert); +@@ -11656,7 +11940,7 @@ + sqlite3_exec(newDb, "COMMIT;", 0, 0, 0); + sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0); + } +- sqlite3_close(newDb); ++ close_db(newDb); + } + + /* +@@ -11755,6 +12039,7 @@ + "SELECT total(length(sql)) FROM %s" }, + }; + int i; ++ unsigned iDataVersion; + char *zSchemaTab; + char *zDb = nArg>=2 ? azArg[1] : "main"; + sqlite3_stmt *pStmt = 0; +@@ -11807,6 +12092,8 @@ + utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val); + } + sqlite3_free(zSchemaTab); ++ sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion); ++ utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion); + return 0; + } + +@@ -11820,14 +12107,6 @@ + } + + /* +-** Print an out-of-memory message to stderr and return 1. +-*/ +-static int shellNomemError(void){ +- raw_printf(stderr, "Error: out of memory\n"); +- return 1; +-} +- +-/* + ** Compare the pattern in zGlob[] against the text in z[]. Return TRUE + ** if they match and FALSE (0) if they do not match. + ** +@@ -12271,6 +12550,7 @@ + char *z; + va_start(ap, zFmt); + z = sqlite3_vmprintf(zFmt, ap); ++ va_end(ap); + if( z==0 ){ + *pRc = SQLITE_NOMEM; + }else{ +@@ -12319,6 +12599,7 @@ + u8 bZip; /* True if the archive is a ZIP */ + u8 bDryRun; /* True if --dry-run */ + u8 bAppend; /* True if --append */ ++ u8 fromCmdLine; /* Run from -A instead of .archive */ + int nArg; /* Number of command arguments */ + char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */ + const char *zFile; /* --file argument, or NULL */ +@@ -12332,32 +12613,7 @@ + ** Print a usage message for the .ar command to stderr and return SQLITE_ERROR. + */ + static int arUsage(FILE *f){ +- raw_printf(f, +-"\n" +-"Usage: .ar [OPTION...] [FILE...]\n" +-"The .ar command manages sqlar archives.\n" +-"\n" +-"Examples:\n" +-" .ar -cf archive.sar foo bar # Create archive.sar from files foo and bar\n" +-" .ar -tf archive.sar # List members of archive.sar\n" +-" .ar -xvf archive.sar # Verbosely extract files from archive.sar\n" +-"\n" +-"Each command line must feature exactly one command option:\n" +-" -c, --create Create a new archive\n" +-" -u, --update Update or add files to an existing archive\n" +-" -t, --list List contents of archive\n" +-" -x, --extract Extract files from archive\n" +-"\n" +-"And zero or more optional options:\n" +-" -v, --verbose Print each filename as it is processed\n" +-" -f FILE, --file FILE Operate on archive FILE (default is current db)\n" +-" -a FILE, --append FILE Operate on FILE opened using the apndvfs VFS\n" +-" -C DIR, --directory DIR Change to directory DIR to read/extract files\n" +-" -n, --dryrun Show the SQL that would have occurred\n" +-"\n" +-"See also: http://sqlite.org/cli.html#sqlar_archive_support\n" +-"\n" +-); ++ showHelp(f,"archive"); + return SQLITE_ERROR; + } + +@@ -12365,13 +12621,18 @@ + ** Print an error message for the .ar command to stderr and return + ** SQLITE_ERROR. + */ +-static int arErrorMsg(const char *zFmt, ...){ ++static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){ + va_list ap; + char *z; + va_start(ap, zFmt); + z = sqlite3_vmprintf(zFmt, ap); + va_end(ap); +- raw_printf(stderr, "Error: %s (try \".ar --help\")\n", z); ++ utf8_printf(stderr, "Error: %s\n", z); ++ if( pAr->fromCmdLine ){ ++ utf8_printf(stderr, "Use \"-A\" for more help\n"); ++ }else{ ++ utf8_printf(stderr, "Use \".archive --help\" for more help\n"); ++ } + sqlite3_free(z); + return SQLITE_ERROR; + } +@@ -12402,7 +12663,7 @@ + case AR_CMD_UPDATE: + case AR_CMD_HELP: + if( pAr->eCmd ){ +- return arErrorMsg("multiple command options"); ++ return arErrorMsg(pAr, "multiple command options"); + } + pAr->eCmd = eSwitch; + break; +@@ -12459,11 +12720,10 @@ + struct ArSwitch *pEnd = &aSwitch[nSwitch]; + + if( nArg<=1 ){ ++ utf8_printf(stderr, "Wrong number of arguments. Usage:\n"); + return arUsage(stderr); + }else{ + char *z = azArg[1]; +- memset(pAr, 0, sizeof(ArCommand)); +- + if( z[0]!='-' ){ + /* Traditional style [tar] invocation */ + int i; +@@ -12475,11 +12735,11 @@ + if( z[i]==pOpt->cShort ) break; + } + if( pOpt==pEnd ){ +- return arErrorMsg("unrecognized option: %c", z[i]); ++ return arErrorMsg(pAr, "unrecognized option: %c", z[i]); + } + if( pOpt->bArg ){ + if( iArg>=nArg ){ +- return arErrorMsg("option requires an argument: %c",z[i]); ++ return arErrorMsg(pAr, "option requires an argument: %c",z[i]); + } + zArg = azArg[iArg++]; + } +@@ -12513,7 +12773,7 @@ + if( z[i]==pOpt->cShort ) break; + } + if( pOpt==pEnd ){ +- return arErrorMsg("unrecognized option: %c\n", z[i]); ++ return arErrorMsg(pAr, "unrecognized option: %c", z[i]); + } + if( pOpt->bArg ){ + if( i<(n-1) ){ +@@ -12521,7 +12781,7 @@ + i = n; + }else{ + if( iArg>=(nArg-1) ){ +- return arErrorMsg("option requires an argument: %c\n",z[i]); ++ return arErrorMsg(pAr, "option requires an argument: %c",z[i]); + } + zArg = azArg[++iArg]; + } +@@ -12543,7 +12803,7 @@ + const char *zLong = pOpt->zLong; + if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){ + if( pMatch ){ +- return arErrorMsg("ambiguous option: %s",z); ++ return arErrorMsg(pAr, "ambiguous option: %s",z); + }else{ + pMatch = pOpt; + } +@@ -12551,11 +12811,11 @@ + } + + if( pMatch==0 ){ +- return arErrorMsg("unrecognized option: %s", z); ++ return arErrorMsg(pAr, "unrecognized option: %s", z); + } + if( pMatch->bArg ){ + if( iArg>=(nArg-1) ){ +- return arErrorMsg("option requires an argument: %s", z); ++ return arErrorMsg(pAr, "option requires an argument: %s", z); + } + zArg = azArg[++iArg]; + } +@@ -12684,6 +12944,7 @@ + } + } + shellFinalize(&rc, pSql); ++ sqlite3_free(zWhere); + return rc; + } + +@@ -12696,7 +12957,8 @@ + "SELECT " + " ($dir || name)," + " writefile(($dir || name), %s, mode, mtime) " +- "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)"; ++ "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)" ++ " AND name NOT GLOB '*..[/\\]*'"; + + const char *azExtraArg[] = { + "sqlar_uncompress(data, sz)", +@@ -12886,6 +13148,7 @@ + */ + static int arDotCommand( + ShellState *pState, /* Current shell tool state */ ++ int fromCmdLine, /* True if -A command-line option, not .ar cmd */ + char **azArg, /* Array of arguments passed to dot command */ + int nArg /* Number of entries in azArg[] */ + ){ +@@ -12892,6 +13155,7 @@ + ArCommand cmd; + int rc; + memset(&cmd, 0, sizeof(cmd)); ++ cmd.fromCmdLine = fromCmdLine; + rc = arParseCommand(azArg, nArg, &cmd); + if( rc==SQLITE_OK ){ + int eDbType = SHELL_OPEN_UNSPEC; +@@ -12938,7 +13202,7 @@ + shellPutsFunc, 0, 0); + + } +- if( cmd.zSrcTable==0 && cmd.bZip==0 ){ ++ if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){ + if( cmd.eCmd!=AR_CMD_CREATE + && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0) + ){ +@@ -12974,7 +13238,7 @@ + } + end_ar_command: + if( cmd.db!=pState->db ){ +- sqlite3_close(cmd.db); ++ close_db(cmd.db); + } + sqlite3_free(cmd.zSrcTable); + +@@ -13054,7 +13318,7 @@ + #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) + if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){ + open_db(p, 0); +- rc = arDotCommand(p, azArg, nArg); ++ rc = arDotCommand(p, 0, azArg, nArg); + }else + #endif + +@@ -13066,11 +13330,14 @@ + sqlite3 *pDest; + sqlite3_backup *pBackup; + int j; ++ const char *zVfs = 0; + for(j=1; j<nArg; j++){ + const char *z = azArg[j]; + if( z[0]=='-' ){ +- while( z[0]=='-' ) z++; +- /* No options to process at this time */ ++ if( z[1]=='-' ) z++; ++ if( strcmp(z, "-append")==0 ){ ++ zVfs = "apndvfs"; ++ }else + { + utf8_printf(stderr, "unknown option: %s\n", azArg[j]); + return 1; +@@ -13081,7 +13348,7 @@ + zDb = zDestFile; + zDestFile = azArg[j]; + }else{ +- raw_printf(stderr, "too many arguments to .backup\n"); ++ raw_printf(stderr, "Usage: .backup ?DB? ?--append? FILENAME\n"); + return 1; + } + } +@@ -13090,10 +13357,11 @@ + return 1; + } + if( zDb==0 ) zDb = "main"; +- rc = sqlite3_open(zDestFile, &pDest); ++ rc = sqlite3_open_v2(zDestFile, &pDest, ++ SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs); + if( rc!=SQLITE_OK ){ + utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile); +- sqlite3_close(pDest); ++ close_db(pDest); + return 1; + } + open_db(p, 0); +@@ -13100,7 +13368,7 @@ + pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb); + if( pBackup==0 ){ + utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); +- sqlite3_close(pDest); ++ close_db(pDest); + return 1; + } + while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){} +@@ -13111,7 +13379,7 @@ + utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); + rc = 1; + } +- sqlite3_close(pDest); ++ close_db(pDest); + }else + + if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){ +@@ -13223,7 +13491,39 @@ + } + }else + +- if( c=='d' && strncmp(azArg[0], "dbinfo", n)==0 ){ ++ if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){ ++ static const struct DbConfigChoices { ++ const char *zName; ++ int op; ++ } aDbConfig[] = { ++ { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY }, ++ { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER }, ++ { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER }, ++ { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION }, ++ { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE }, ++ { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG }, ++ { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP }, ++ { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE }, ++ { "defensive", SQLITE_DBCONFIG_DEFENSIVE }, ++ }; ++ int ii, v; ++ open_db(p, 0); ++ for(ii=0; ii<ArraySize(aDbConfig); ii++){ ++ if( nArg>1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue; ++ if( nArg>=3 ){ ++ sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0); ++ } ++ sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v); ++ utf8_printf(p->out, "%18s %s\n", aDbConfig[ii].zName, v ? "on" : "off"); ++ if( nArg>1 ) break; ++ } ++ if( nArg>1 && ii==ArraySize(aDbConfig) ){ ++ utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]); ++ utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n"); ++ } ++ }else ++ ++ if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){ + rc = shell_dbinfo_command(p, nArg, azArg); + }else + +@@ -13231,7 +13531,8 @@ + const char *zLike = 0; + int i; + int savedShowHeader = p->showHeader; +- ShellClearFlag(p, SHFLG_PreserveRowid|SHFLG_Newlines); ++ int savedShellFlags = p->shellFlgs; ++ ShellClearFlag(p, SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo); + for(i=1; i<nArg; i++){ + if( azArg[i][0]=='-' ){ + const char *z = azArg[i]+1; +@@ -13313,6 +13614,7 @@ + sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0); + raw_printf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n"); + p->showHeader = savedShowHeader; ++ p->shellFlgs = savedShellFlags; + }else + + if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){ +@@ -13326,10 +13628,14 @@ + + if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){ + if( nArg==2 ){ ++ p->autoEQPtest = 0; + if( strcmp(azArg[1],"full")==0 ){ + p->autoEQP = AUTOEQP_full; + }else if( strcmp(azArg[1],"trigger")==0 ){ + p->autoEQP = AUTOEQP_trigger; ++ }else if( strcmp(azArg[1],"test")==0 ){ ++ p->autoEQP = AUTOEQP_on; ++ p->autoEQPtest = 1; + }else{ + p->autoEQP = (u8)booleanValue(azArg[1]); + } +@@ -13418,11 +13724,11 @@ + callback, &data, &zErrMsg); + data.cMode = data.mode = MODE_Insert; + data.zDestTable = "sqlite_stat1"; +- shell_exec(p, "SELECT * FROM sqlite_stat1", &zErrMsg); ++ shell_exec(&data, "SELECT * FROM sqlite_stat1", &zErrMsg); + data.zDestTable = "sqlite_stat3"; +- shell_exec(p, "SELECT * FROM sqlite_stat3", &zErrMsg); ++ shell_exec(&data, "SELECT * FROM sqlite_stat3", &zErrMsg); + data.zDestTable = "sqlite_stat4"; +- shell_exec(p, "SELECT * FROM sqlite_stat4", &zErrMsg); ++ shell_exec(&data, "SELECT * FROM sqlite_stat4", &zErrMsg); + raw_printf(p->out, "ANALYZE sqlite_master;\n"); + } + }else +@@ -13437,7 +13743,14 @@ + }else + + if( c=='h' && strncmp(azArg[0], "help", n)==0 ){ +- utf8_printf(p->out, "%s", zHelp); ++ if( nArg>=2 ){ ++ n = showHelp(p->out, azArg[1]); ++ if( n==0 ){ ++ utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]); ++ } ++ }else{ ++ showHelp(p->out, 0); ++ } + }else + + if( c=='i' && strncmp(azArg[0], "import", n)==0 ){ +@@ -13520,9 +13833,8 @@ + sCtx.cRowSep = p->rowSeparator[0]; + zSql = sqlite3_mprintf("SELECT * FROM %s", zTable); + if( zSql==0 ){ +- raw_printf(stderr, "Error: out of memory\n"); + xCloser(sCtx.in); +- return 1; ++ shell_out_of_memory(); + } + nByte = strlen30(zSql); + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); +@@ -13567,9 +13879,8 @@ + if( nCol==0 ) return 0; /* no columns, no error */ + zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 ); + if( zSql==0 ){ +- raw_printf(stderr, "Error: out of memory\n"); + xCloser(sCtx.in); +- return 1; ++ shell_out_of_memory(); + } + sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable); + j = strlen30(zSql); +@@ -13645,12 +13956,17 @@ + sqlite3_stmt *pStmt; + int tnum = 0; + int i; +- if( nArg!=3 ){ +- utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"); ++ if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){ ++ utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n" ++ " .imposter off\n"); + rc = 1; + goto meta_command_exit; + } + open_db(p, 0); ++ if( nArg==2 ){ ++ sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1); ++ goto meta_command_exit; ++ } + zSql = sqlite3_mprintf("SELECT rootpage FROM sqlite_master" + " WHERE name='%q' AND type='index'", azArg[1]); + sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); +@@ -13892,7 +14208,7 @@ + int newFlag = 0; /* True to delete file before opening */ + /* Close the existing database */ + session_close_all(p); +- sqlite3_close(p->db); ++ close_db(p->db); + p->db = 0; + p->zDbFilename = 0; + sqlite3_free(p->zFreeOnClose); +@@ -13911,6 +14227,10 @@ + p->openMode = SHELL_OPEN_APPENDVFS; + }else if( optionMatch(z, "readonly") ){ + p->openMode = SHELL_OPEN_READONLY; ++#ifdef SQLITE_ENABLE_DESERIALIZE ++ }else if( optionMatch(z, "deserialize") ){ ++ p->openMode = SHELL_OPEN_DESERIALIZE; ++#endif + }else if( z[0]=='-' ){ + utf8_printf(stderr, "unknown option: %s\n", z); + rc = 1; +@@ -13922,7 +14242,7 @@ + if( zNewFilename ){ + if( newFlag ) shellDeleteFile(zNewFilename); + p->zDbFilename = zNewFilename; +- open_db(p, 1); ++ open_db(p, OPEN_DB_KEEPALIVE); + if( p->db==0 ){ + utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename); + sqlite3_free(zNewFilename); +@@ -14072,7 +14392,7 @@ + rc = sqlite3_open(zSrcFile, &pSrc); + if( rc!=SQLITE_OK ){ + utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile); +- sqlite3_close(pSrc); ++ close_db(pSrc); + return 1; + } + open_db(p, 0); +@@ -14079,7 +14399,7 @@ + pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main"); + if( pBackup==0 ){ + utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); +- sqlite3_close(pSrc); ++ close_db(pSrc); + return 1; + } + while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK +@@ -14099,7 +14419,7 @@ + utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); + rc = 1; + } +- sqlite3_close(pSrc); ++ close_db(pSrc); + }else + + if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){ +@@ -14438,7 +14758,7 @@ + }else + /* If no command name matches, show a syntax error */ + session_syntax_error: +- session_help(p); ++ showHelp(p->out, "session"); + }else + #endif + +@@ -14619,7 +14939,7 @@ + utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n", + azArg[i], azArg[0]); + raw_printf(stderr, "Should be one of: --schema" +- " --sha3-224 --sha3-255 --sha3-384 --sha3-512\n"); ++ " --sha3-224 --sha3-256 --sha3-384 --sha3-512\n"); + rc = 1; + goto meta_command_exit; + } +@@ -14783,7 +15103,10 @@ + initText(&s); + open_db(p, 0); + rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); +- if( rc ) return shellDatabaseError(p->db); ++ if( rc ){ ++ sqlite3_finalize(pStmt); ++ return shellDatabaseError(p->db); ++ } + + if( nArg>2 && c=='i' ){ + /* It is an historical accident that the .indexes command shows an error +@@ -14791,6 +15114,7 @@ + ** command does not. */ + raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n"); + rc = 1; ++ sqlite3_finalize(pStmt); + goto meta_command_exit; + } + for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){ +@@ -14835,18 +15159,12 @@ + char **azNew; + int n2 = nAlloc*2 + 10; + azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2); +- if( azNew==0 ){ +- rc = shellNomemError(); +- break; +- } ++ if( azNew==0 ) shell_out_of_memory(); + nAlloc = n2; + azResult = azNew; + } + azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0)); +- if( 0==azResult[nRow] ){ +- rc = shellNomemError(); +- break; +- } ++ if( 0==azResult[nRow] ) shell_out_of_memory(); + nRow++; + } + if( sqlite3_finalize(pStmt)!=SQLITE_OK ){ +@@ -14907,9 +15225,7 @@ + { "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" }, + /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" }, */ + { "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"}, +-#ifdef SQLITE_N_KEYWORD +- { "iskeyword", SQLITE_TESTCTRL_ISKEYWORD, "IDENTIFIER" }, +-#endif ++ { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "BOOLEAN" }, + { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" }, + { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" }, + { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" }, +@@ -15004,6 +15320,7 @@ + /* sqlite3_test_control(int, int) */ + case SQLITE_TESTCTRL_ASSERT: + case SQLITE_TESTCTRL_ALWAYS: ++ case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: + if( nArg==3 ){ + int opt = booleanValue(azArg[2]); + rc2 = sqlite3_test_control(testctrl, opt); +@@ -15021,17 +15338,6 @@ + } + break; + +- /* sqlite3_test_control(int, char *) */ +-#ifdef SQLITE_N_KEYWORD +- case SQLITE_TESTCTRL_ISKEYWORD: +- if( nArg==3 ){ +- const char *opt = azArg[2]; +- rc2 = sqlite3_test_control(testctrl, opt); +- isOk = 1; +- } +- break; +-#endif +- + case SQLITE_TESTCTRL_IMPOSTER: + if( nArg==5 ){ + rc2 = sqlite3_test_control(testctrl, p->db, +@@ -15309,7 +15615,7 @@ + ** user-friendly, but it does seem to work. + */ + #ifdef SQLITE_OMIT_COMPLETE +-int sqlite3_complete(const char *zSql){ return 1; } ++#define sqlite3_complete(x) 1 + #endif + + /* +@@ -15327,7 +15633,7 @@ + } + + /* +-** Run a single line of SQL ++** Run a single line of SQL. Return the number of errors. + */ + static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){ + int rc; +@@ -15400,13 +15706,15 @@ + if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine); + continue; + } +- if( zLine && zLine[0]=='.' && nSql==0 ){ ++ if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){ + if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine); +- rc = do_meta_command(zLine, p); +- if( rc==2 ){ /* exit requested */ +- break; +- }else if( rc ){ +- errCnt++; ++ if( zLine[0]=='.' ){ ++ rc = do_meta_command(zLine, p); ++ if( rc==2 ){ /* exit requested */ ++ break; ++ }else if( rc ){ ++ errCnt++; ++ } + } + continue; + } +@@ -15417,10 +15725,7 @@ + if( nSql+nLine+2>=nAlloc ){ + nAlloc = nSql+nLine+100; + zSql = realloc(zSql, nAlloc); +- if( zSql==0 ){ +- raw_printf(stderr, "Error: out of memory\n"); +- exit(1); +- } ++ if( zSql==0 ) shell_out_of_memory(); + } + nSqlPrior = nSql; + if( nSql==0 ){ +@@ -15451,7 +15756,7 @@ + } + } + if( nSql && !_all_whitespace(zSql) ){ +- runOneSqlLine(p, zSql, in, startline); ++ errCnt += runOneSqlLine(p, zSql, in, startline); + } + free(zSql); + free(zLine); +@@ -15549,7 +15854,6 @@ + " cannot read ~/.sqliterc\n"); + return; + } +- sqlite3_initialize(); + zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir); + sqliterc = zBuf; + } +@@ -15600,6 +15904,9 @@ + " -quote set output mode to 'quote'\n" + " -readonly open the database read-only\n" + " -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" + " -version show SQLite version\n" + " -vfs NAME use NAME as the default VFS\n" +@@ -15624,6 +15931,17 @@ + } + + /* ++** Internal check: Verify that the SQLite is uninitialized. Print a ++** error message if it is initialized. ++*/ ++static void verify_uninitialized(void){ ++ if( sqlite3_config(-1)==SQLITE_MISUSE ){ ++ utf8_printf(stdout, "WARNING: attempt to configure SQLite after" ++ " initialization.\n"); ++ } ++} ++ ++/* + ** Initialize the state information in data + */ + static void main_init(ShellState *data) { +@@ -15634,6 +15952,7 @@ + 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); +@@ -15697,6 +16016,11 @@ + 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 */ +@@ -15703,6 +16027,23 @@ + stdin_is_interactive = isatty(0); + stdout_is_console = isatty(1); + ++#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) ++ DebugBreak(); ++#elif defined(SIGTRAP) ++ raise(SIGTRAP); ++#endif ++ } ++ } ++#endif ++ + #if USE_SYSTEM_SQLITE+0!=1 + if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){ + utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n", +@@ -15720,25 +16061,19 @@ + */ + #if !SQLITE_SHELL_IS_UTF8 + sqlite3_initialize(); +- argv = malloc(sizeof(argv[0])*argc); +- if( argv==0 ){ +- raw_printf(stderr, "out of memory\n"); +- exit(1); +- } ++ argvToFree = malloc(sizeof(argv[0])*argc*2); ++ argcToFree = argc; ++ argv = argvToFree + argc; ++ if( argv==0 ) shell_out_of_memory(); + for(i=0; i<argc; i++){ + char *z = sqlite3_win32_unicode_to_utf8(wargv[i]); + int n; +- if( z==0 ){ +- raw_printf(stderr, "out of memory\n"); +- exit(1); +- } ++ if( z==0 ) shell_out_of_memory(); + n = (int)strlen(z); + argv[i] = malloc( n+1 ); +- if( argv[i]==0 ){ +- raw_printf(stderr, "out of memory\n"); +- exit(1); +- } ++ if( argv[i]==0 ) shell_out_of_memory(); + memcpy(argv[i], z, n+1); ++ argvToFree[i] = argv[i]; + sqlite3_free(z); + } + sqlite3_shutdown(); +@@ -15773,6 +16108,7 @@ + ** 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]; +@@ -15785,10 +16121,7 @@ + readStdin = 0; + nCmd++; + azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd); +- if( azCmd==0 ){ +- raw_printf(stderr, "out of memory\n"); +- exit(1); +- } ++ if( azCmd==0 ) shell_out_of_memory(); + azCmd[nCmd-1] = z; + } + } +@@ -15855,14 +16188,13 @@ + }else if( 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( 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( strcmp(z,"-vfs")==0 ){ +- sqlite3_vfs *pVfs = sqlite3_vfs_find(cmdline_option_value(argc,argv,++i)); +- if( pVfs ){ +- sqlite3_vfs_register(pVfs, 1); +- }else{ +- utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]); +- exit(1); +- } ++ zVfs = cmdline_option_value(argc, argv, ++i); + #ifdef SQLITE_HAVE_ZLIB + }else if( strcmp(z,"-zip")==0 ){ + data.openMode = SHELL_OPEN_ZIPFILE; +@@ -15869,6 +16201,10 @@ + #endif + }else if( strcmp(z,"-append")==0 ){ + data.openMode = SHELL_OPEN_APPENDVFS; ++#ifdef SQLITE_ENABLE_DESERIALIZE ++ }else if( strcmp(z,"-deserialize")==0 ){ ++ data.openMode = SHELL_OPEN_DESERIALIZE; ++#endif + }else if( strcmp(z,"-readonly")==0 ){ + data.openMode = SHELL_OPEN_READONLY; + #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) +@@ -15879,6 +16215,34 @@ + #endif + } + } ++ 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 ++ ** option to embed this shell program in larger applications. */ ++ extern void SQLITE_SHELL_INIT_PROC(void); ++ SQLITE_SHELL_INIT_PROC(); ++ } ++#else ++ /* All the sqlite3_config() calls have now been made. So it is safe ++ ** to call sqlite3_initialize() and process any command line -vfs option. */ ++ sqlite3_initialize(); ++#endif ++ ++ if( zVfs ){ ++ sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs); ++ if( pVfs ){ ++ sqlite3_vfs_register(pVfs, 1); ++ }else{ ++ utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]); ++ exit(1); ++ } ++ } ++ + if( data.zDbFilename==0 ){ + #ifndef SQLITE_OMIT_MEMORYDB + data.zDbFilename = ":memory:"; +@@ -15936,6 +16300,10 @@ + #endif + }else if( strcmp(z,"-append")==0 ){ + data.openMode = SHELL_OPEN_APPENDVFS; ++#ifdef SQLITE_ENABLE_DESERIALIZE ++ }else if( strcmp(z,"-deserialize")==0 ){ ++ data.openMode = SHELL_OPEN_DESERIALIZE; ++#endif + }else if( strcmp(z,"-readonly")==0 ){ + data.openMode = SHELL_OPEN_READONLY; + }else if( strcmp(z,"-ascii")==0 ){ +@@ -15991,6 +16359,10 @@ + i+=2; + }else if( strcmp(z,"-mmap")==0 ){ + i++; ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ }else if( strcmp(z,"-sorterref")==0 ){ ++ i++; ++#endif + }else if( strcmp(z,"-vfs")==0 ){ + i++; + #ifdef SQLITE_ENABLE_VFSTRACE +@@ -16031,12 +16403,12 @@ + " with \"%s\"\n", z); + return 1; + } +- open_db(&data, 0); ++ open_db(&data, OPEN_DB_ZIPFILE); + if( z[2] ){ + argv[i] = &z[2]; +- arDotCommand(&data, argv+(i-1), argc-(i-1)); ++ arDotCommand(&data, 1, argv+(i-1), argc-(i-1)); + }else{ +- arDotCommand(&data, argv+i, argc-i); ++ arDotCommand(&data, 1, argv+i, argc-i); + } + readStdin = 0; + break; +@@ -16076,7 +16448,7 @@ + */ + if( stdin_is_interactive ){ + char *zHome; +- char *zHistory = 0; ++ char *zHistory; + int nHistory; + printf( + "SQLite version %s %.19s\n" /*extra-version-info*/ +@@ -16089,8 +16461,10 @@ + printf(".\nUse \".open FILENAME\" to reopen on a " + "persistent database.\n"); + } +- zHome = find_home_dir(0); +- if( zHome ){ ++ zHistory = getenv("SQLITE_HISTORY"); ++ if( zHistory ){ ++ zHistory = strdup(zHistory); ++ }else if( (zHome = find_home_dir(0))!=0 ){ + nHistory = strlen30(zHome) + 20; + if( (zHistory = malloc(nHistory))!=0 ){ + sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome); +@@ -16115,7 +16489,7 @@ + set_table_name(&data, 0); + if( data.db ){ + session_close_all(&data); +- sqlite3_close(data.db); ++ close_db(data.db); + } + sqlite3_free(data.zFreeOnClose); + find_home_dir(1); +@@ -16123,8 +16497,11 @@ + data.doXdgOpen = 0; + clearTempFile(&data); + #if !SQLITE_SHELL_IS_UTF8 +- for(i=0; i<argc; i++) free(argv[i]); +- free(argv); ++ for(i=0; i<argcToFree; i++) free(argvToFree[i]); ++ free(argvToFree); + #endif ++ /* Clear the global data structure so that valgrind will detect memory ++ ** leaks */ ++ memset(&data, 0, sizeof(data)); + return rc; + } +--- contrib/sqlite3/sqlite3.c.orig ++++ contrib/sqlite3/sqlite3.c +@@ -1,6 +1,6 @@ + /****************************************************************************** + ** This file is an amalgamation of many separate C source files from SQLite +-** version 3.23.1. By combining all the individual C code files into this ++** version 3.26.0. By combining all the individual C code files into this + ** single large file, the entire code can be compiled as a single translation + ** unit. This allows many compilers to do optimizations that would not be + ** possible if the files were compiled separately. Performance improvements +@@ -55,6 +55,12 @@ + #define CTIMEOPT_VAL_(opt) #opt + #define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt) + ++/* Like CTIMEOPT_VAL, but especially for SQLITE_DEFAULT_LOOKASIDE. This ++** option requires a separate macro because legal values contain a single ++** comma. e.g. (-DSQLITE_DEFAULT_LOOKASIDE="100,100") */ ++#define CTIMEOPT_VAL2_(opt1,opt2) #opt1 "," #opt2 ++#define CTIMEOPT_VAL2(opt) CTIMEOPT_VAL2_(opt) ++ + /* + ** An array of names of all compile-time options. This array should + ** be sorted A-Z. +@@ -138,7 +144,7 @@ + "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), + #endif + #ifdef SQLITE_DEFAULT_LOOKASIDE +- "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOOKASIDE), ++ "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL2(SQLITE_DEFAULT_LOOKASIDE), + #endif + #if SQLITE_DEFAULT_MEMSTATUS + "DEFAULT_MEMSTATUS", +@@ -254,6 +260,9 @@ + #if SQLITE_ENABLE_FTS5 + "ENABLE_FTS5", + #endif ++#if SQLITE_ENABLE_GEOPOLY ++ "ENABLE_GEOPOLY", ++#endif + #if SQLITE_ENABLE_HIDDEN_COLUMNS + "ENABLE_HIDDEN_COLUMNS", + #endif +@@ -284,6 +293,9 @@ + #if SQLITE_ENABLE_MULTIPLEX + "ENABLE_MULTIPLEX", + #endif ++#if SQLITE_ENABLE_NORMALIZE ++ "ENABLE_NORMALIZE", ++#endif + #if SQLITE_ENABLE_NULL_TRIM + "ENABLE_NULL_TRIM", + #endif +@@ -311,6 +323,9 @@ + #if SQLITE_ENABLE_SNAPSHOT + "ENABLE_SNAPSHOT", + #endif ++#if SQLITE_ENABLE_SORTER_REFERENCES ++ "ENABLE_SORTER_REFERENCES", ++#endif + #if SQLITE_ENABLE_SQLLOG + "ENABLE_SQLLOG", + #endif +@@ -1147,9 +1162,9 @@ + ** [sqlite3_libversion_number()], [sqlite3_sourceid()], + ** [sqlite_version()] and [sqlite_source_id()]. + */ +-#define SQLITE_VERSION "3.23.1" +-#define SQLITE_VERSION_NUMBER 3023001 +-#define SQLITE_SOURCE_ID "2018-04-10 17:39:29 4bb2294022060e61de7da5c227a69ccd846ba330e31626ebcd59a94efd148b3b" ++#define SQLITE_VERSION "3.26.0" ++#define SQLITE_VERSION_NUMBER 3026000 ++#define SQLITE_SOURCE_ID "2018-12-01 12:34:55 bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238b4f9" + + /* + ** CAPI3REF: Run-Time Library Version Numbers +@@ -1496,6 +1511,7 @@ + */ + #define SQLITE_ERROR_MISSING_COLLSEQ (SQLITE_ERROR | (1<<8)) + #define SQLITE_ERROR_RETRY (SQLITE_ERROR | (2<<8)) ++#define SQLITE_ERROR_SNAPSHOT (SQLITE_ERROR | (3<<8)) + #define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) + #define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) + #define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) +@@ -1528,6 +1544,7 @@ + #define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8)) + #define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8)) + #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) ++#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) + #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) + #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) + #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) +@@ -1534,7 +1551,9 @@ + #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) + #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) + #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) ++#define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */ + #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) ++#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8)) + #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) + #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) + #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) +@@ -1908,7 +1927,8 @@ + ** <li>[[SQLITE_FCNTL_PERSIST_WAL]] + ** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the + ** persistent [WAL | Write Ahead Log] setting. By default, the auxiliary +-** write ahead log and shared memory files used for transaction control ++** write ahead log ([WAL file]) and shared memory ++** files used for transaction control + ** are automatically deleted when the latest connection to the database + ** closes. Setting persistent WAL mode causes those files to persist after + ** close. Persisting the files is useful when other processes that do not +@@ -2094,6 +2114,26 @@ + ** a file lock using the xLock or xShmLock methods of the VFS to wait + ** for up to M milliseconds before failing, where M is the single + ** unsigned integer parameter. ++** ++** <li>[[SQLITE_FCNTL_DATA_VERSION]] ++** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to ++** a database file. The argument is a pointer to a 32-bit unsigned integer. ++** The "data version" for the pager is written into the pointer. The ++** "data version" changes whenever any change occurs to the corresponding ++** database file, either through SQL statements on the same database ++** connection or through transactions committed by separate database ++** connections possibly in other processes. The [sqlite3_total_changes()] ++** interface can be used to find if any database on the connection has changed, ++** but that interface responds to changes on TEMP as well as MAIN and does ++** not provide a mechanism to detect changes to MAIN only. Also, the ++** [sqlite3_total_changes()] interface responds to internal changes only and ++** omits changes made by other database connections. The ++** [PRAGMA data_version] command provide a mechanism to detect changes to ++** a single attached database that occur due to other database connections, ++** but omits changes implemented by the database connection on which it is ++** called. This file control is the only mechanism to detect changes that ++** happen either internally or externally and that are associated with ++** a particular attached database. + ** </ul> + */ + #define SQLITE_FCNTL_LOCKSTATE 1 +@@ -2129,6 +2169,7 @@ + #define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32 + #define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33 + #define SQLITE_FCNTL_LOCK_TIMEOUT 34 ++#define SQLITE_FCNTL_DATA_VERSION 35 + + /* deprecated names */ + #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE +@@ -2954,6 +2995,22 @@ + ** I/O required to support statement rollback. + ** The default value for this setting is controlled by the + ** [SQLITE_STMTJRNL_SPILL] compile-time option. ++** ++** [[SQLITE_CONFIG_SORTERREF_SIZE]] ++** <dt>SQLITE_CONFIG_SORTERREF_SIZE ++** <dd>The SQLITE_CONFIG_SORTERREF_SIZE option accepts a single parameter ++** of type (int) - the new value of the sorter-reference size threshold. ++** Usually, when SQLite uses an external sort to order records according ++** to an ORDER BY clause, all fields required by the caller are present in the ++** sorted records. However, if SQLite determines based on the declared type ++** of a table column that its values are likely to be very large - larger ++** than the configured sorter-reference size threshold - then a reference ++** is stored in each sorted record and the required column values loaded ++** from the database as records are returned in sorted order. The default ++** value for this option is to never use this optimization. Specifying a ++** negative value for this option restores the default behaviour. ++** This option is only available if SQLite is compiled with the ++** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option. + ** </dl> + */ + #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ +@@ -2983,6 +3040,7 @@ + #define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */ + #define SQLITE_CONFIG_STMTJRNL_SPILL 26 /* int nByte */ + #define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */ ++#define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */ + + /* + ** CAPI3REF: Database Connection Configuration Options +@@ -2998,6 +3056,7 @@ + ** is invoked. + ** + ** <dl> ++** [[SQLITE_DBCONFIG_LOOKASIDE]] + ** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt> + ** <dd> ^This option takes three additional arguments that determine the + ** [lookaside memory allocator] configuration for the [database connection]. +@@ -3020,6 +3079,7 @@ + ** memory is in use leaves the configuration unchanged and returns + ** [SQLITE_BUSY].)^</dd> + ** ++** [[SQLITE_DBCONFIG_ENABLE_FKEY]] + ** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt> + ** <dd> ^This option is used to enable or disable the enforcement of + ** [foreign key constraints]. There should be two additional arguments. +@@ -3030,6 +3090,7 @@ + ** following this call. The second parameter may be a NULL pointer, in + ** which case the FK enforcement setting is not reported back. </dd> + ** ++** [[SQLITE_DBCONFIG_ENABLE_TRIGGER]] + ** <dt>SQLITE_DBCONFIG_ENABLE_TRIGGER</dt> + ** <dd> ^This option is used to enable or disable [CREATE TRIGGER | triggers]. + ** There should be two additional arguments. +@@ -3040,6 +3101,7 @@ + ** following this call. The second parameter may be a NULL pointer, in + ** which case the trigger setting is not reported back. </dd> + ** ++** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]] + ** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt> + ** <dd> ^This option is used to enable or disable the two-argument + ** version of the [fts3_tokenizer()] function which is part of the +@@ -3053,6 +3115,7 @@ + ** following this call. The second parameter may be a NULL pointer, in + ** which case the new setting is not reported back. </dd> + ** ++** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]] + ** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt> + ** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()] + ** interface independently of the [load_extension()] SQL function. +@@ -3070,7 +3133,7 @@ + ** be a NULL pointer, in which case the new setting is not reported back. + ** </dd> + ** +-** <dt>SQLITE_DBCONFIG_MAINDBNAME</dt> ++** [[SQLITE_DBCONFIG_MAINDBNAME]] <dt>SQLITE_DBCONFIG_MAINDBNAME</dt> + ** <dd> ^This option is used to change the name of the "main" database + ** schema. ^The sole argument is a pointer to a constant UTF8 string + ** which will become the new schema name in place of "main". ^SQLite +@@ -3079,6 +3142,7 @@ + ** until after the database connection closes. + ** </dd> + ** ++** [[SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE]] + ** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt> + ** <dd> Usually, when a database in wal mode is closed or detached from a + ** database handle, SQLite checks if this will mean that there are now no +@@ -3092,7 +3156,7 @@ + ** have been disabled - 0 if they are not disabled, 1 if they are. + ** </dd> + ** +-** <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt> ++** [[SQLITE_DBCONFIG_ENABLE_QPSG]] <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt> + ** <dd>^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates + ** the [query planner stability guarantee] (QPSG). When the QPSG is active, + ** a single SQL query statement will always use the same algorithm regardless +@@ -3108,7 +3172,7 @@ + ** following this call. + ** </dd> + ** +-** <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt> ++** [[SQLITE_DBCONFIG_TRIGGER_EQP]] <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt> + ** <dd> By default, the output of EXPLAIN QUERY PLAN commands does not + ** include output for any operations performed by trigger programs. This + ** option is used to set or clear (the default) a flag that governs this +@@ -3119,6 +3183,39 @@ + ** 0 or 1 to indicate whether output-for-triggers has been disabled - 0 if + ** it is not disabled, 1 if it is. + ** </dd> ++** ++** [[SQLITE_DBCONFIG_RESET_DATABASE]] <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt> ++** <dd> Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run ++** [VACUUM] in order to reset a database back to an empty database ++** with no schema and no content. The following process works even for ++** a badly corrupted database file: ++** <ol> ++** <li> If the database connection is newly opened, make sure it has read the ++** database schema by preparing then discarding some query against the ++** database, or calling sqlite3_table_column_metadata(), ignoring any ++** errors. This step is only necessary if the application desires to keep ++** the database in WAL mode after the reset if it was in WAL mode before ++** the reset. ++** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0); ++** <li> [sqlite3_exec](db, "[VACUUM]", 0, 0, 0); ++** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0); ++** </ol> ++** Because resetting a database is destructive and irreversible, the ++** process requires the use of this obscure API and multiple steps to help ++** ensure that it does not happen by accident. ++** ++** [[SQLITE_DBCONFIG_DEFENSIVE]] <dt>SQLITE_DBCONFIG_DEFENSIVE</dt> ++** <dd>The SQLITE_DBCONFIG_DEFENSIVE option activates or deactivates the ++** "defensive" flag for a database connection. When the defensive ++** flag is enabled, language features that allow ordinary SQL to ++** deliberately corrupt the database file are disabled. The disabled ++** features include but are not limited to the following: ++** <ul> ++** <li> The [PRAGMA writable_schema=ON] statement. ++** <li> Writes to the [sqlite_dbpage] virtual table. ++** <li> Direct writes to [shadow tables]. ++** </ul> ++** </dd> + ** </dl> + */ + #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ +@@ -3130,7 +3227,9 @@ + #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_MAX 1008 /* Largest DBCONFIG */ ++#define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */ ++#define SQLITE_DBCONFIG_DEFENSIVE 1010 /* int int* */ ++#define SQLITE_DBCONFIG_MAX 1010 /* Largest DBCONFIG */ + + /* + ** CAPI3REF: Enable Or Disable Extended Result Codes +@@ -3258,12 +3357,17 @@ + ** program, the value returned reflects the number of rows modified by the + ** previous INSERT, UPDATE or DELETE statement within the same trigger. + ** +-** See also the [sqlite3_total_changes()] interface, the +-** [count_changes pragma], and the [changes() SQL function]. +-** + ** If a separate thread makes changes on the same database connection + ** while [sqlite3_changes()] is running then the value returned + ** is unpredictable and not meaningful. ++** ++** See also: ++** <ul> ++** <li> the [sqlite3_total_changes()] interface ++** <li> the [count_changes pragma] ++** <li> the [changes() SQL function] ++** <li> the [data_version pragma] ++** </ul> + */ + SQLITE_API int sqlite3_changes(sqlite3*); + +@@ -3281,13 +3385,26 @@ + ** count, but those made as part of REPLACE constraint resolution are + ** not. ^Changes to a view that are intercepted by INSTEAD OF triggers + ** are not counted. ++** ++** This the [sqlite3_total_changes(D)] interface only reports the number ++** of rows that changed due to SQL statement run against database ++** connection D. Any changes by other database connections are ignored. ++** To detect changes against a database file from other database ++** connections use the [PRAGMA data_version] command or the ++** [SQLITE_FCNTL_DATA_VERSION] [file control]. + ** +-** See also the [sqlite3_changes()] interface, the +-** [count_changes pragma], and the [total_changes() SQL function]. +-** + ** If a separate thread makes changes on the same database connection + ** while [sqlite3_total_changes()] is running then the value + ** returned is unpredictable and not meaningful. ++** ++** See also: ++** <ul> ++** <li> the [sqlite3_changes()] interface ++** <li> the [count_changes pragma] ++** <li> the [changes() SQL function] ++** <li> the [data_version pragma] ++** <li> the [SQLITE_FCNTL_DATA_VERSION] [file control] ++** </ul> + */ + SQLITE_API int sqlite3_total_changes(sqlite3*); + +@@ -4343,13 +4460,24 @@ + ** [database connection] D failed, then the sqlite3_errcode(D) interface + ** returns the numeric [result code] or [extended result code] for that + ** API call. +-** If the most recent API call was successful, +-** then the return value from sqlite3_errcode() is undefined. + ** ^The sqlite3_extended_errcode() + ** interface is the same except that it always returns the + ** [extended result code] even when extended result codes are + ** disabled. + ** ++** The values returned by sqlite3_errcode() and/or ++** sqlite3_extended_errcode() might change with each API call. ++** Except, there are some interfaces that are guaranteed to never ++** change the value of the error code. The error-code preserving ++** interfaces are: ++** ++** <ul> ++** <li> sqlite3_errcode() ++** <li> sqlite3_extended_errcode() ++** <li> sqlite3_errmsg() ++** <li> sqlite3_errmsg16() ++** </ul> ++** + ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language + ** text that describes the error, as either UTF-8 or UTF-16 respectively. + ** ^(Memory to hold the error message string is managed internally. +@@ -4539,9 +4667,19 @@ + ** on this hint by avoiding the use of [lookaside memory] so as not to + ** deplete the limited store of lookaside memory. Future versions of + ** SQLite may act on this hint differently. ++** ++** [[SQLITE_PREPARE_NORMALIZE]] ^(<dt>SQLITE_PREPARE_NORMALIZE</dt> ++** <dd>The SQLITE_PREPARE_NORMALIZE flag indicates that a normalized ++** representation of the SQL statement should be calculated and then ++** associated with the prepared statement, which can be obtained via ++** the [sqlite3_normalized_sql()] interface.)^ The semantics used to ++** normalize a SQL statement are unspecified and subject to change. ++** At a minimum, literal values will be replaced with suitable ++** placeholders. + ** </dl> + */ + #define SQLITE_PREPARE_PERSISTENT 0x01 ++#define SQLITE_PREPARE_NORMALIZE 0x02 + + /* + ** CAPI3REF: Compiling An SQL Statement +@@ -4699,6 +4837,11 @@ + ** ^The sqlite3_expanded_sql(P) interface returns a pointer to a UTF-8 + ** string containing the SQL text of prepared statement P with + ** [bound parameters] expanded. ++** ^The sqlite3_normalized_sql(P) interface returns a pointer to a UTF-8 ++** string containing the normalized SQL text of prepared statement P. The ++** semantics used to normalize a SQL statement are unspecified and subject ++** to change. At a minimum, literal values will be replaced with suitable ++** placeholders. + ** + ** ^(For example, if a prepared statement is created using the SQL + ** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345 +@@ -4714,8 +4857,9 @@ + ** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time + ** option causes sqlite3_expanded_sql() to always return NULL. + ** +-** ^The string returned by sqlite3_sql(P) is managed by SQLite and is +-** automatically freed when the prepared statement is finalized. ++** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P) ++** are managed by SQLite and are automatically freed when the prepared ++** statement is finalized. + ** ^The string returned by sqlite3_expanded_sql(P), on the other hand, + ** is obtained from [sqlite3_malloc()] and must be free by the application + ** by passing it to [sqlite3_free()]. +@@ -4722,6 +4866,7 @@ + */ + SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); + SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt); ++SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt); + + /* + ** CAPI3REF: Determine If An SQL Statement Writes The Database +@@ -5503,11 +5648,25 @@ + ** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into + ** [sqlite3_free()]. + ** +-** ^(If a memory allocation error occurs during the evaluation of any +-** of these routines, a default value is returned. The default value +-** is either the integer 0, the floating point number 0.0, or a NULL +-** pointer. Subsequent calls to [sqlite3_errcode()] will return +-** [SQLITE_NOMEM].)^ ++** As long as the input parameters are correct, these routines will only ++** fail if an out-of-memory error occurs during a format conversion. ++** Only the following subset of interfaces are subject to out-of-memory ++** errors: ++** ++** <ul> ++** <li> sqlite3_column_blob() ++** <li> sqlite3_column_text() ++** <li> sqlite3_column_text16() ++** <li> sqlite3_column_bytes() ++** <li> sqlite3_column_bytes16() ++** </ul> ++** ++** If an out-of-memory error occurs, then the return value from these ++** routines is the same as if the column had contained an SQL NULL value. ++** Valid SQL NULL returns can be distinguished from out-of-memory errors ++** by invoking the [sqlite3_errcode()] immediately after the suspect ++** return value is obtained and before any ++** other SQLite interface is called on the same [database connection]. + */ + SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); + SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol); +@@ -5584,11 +5743,13 @@ + ** + ** ^These functions (collectively known as "function creation routines") + ** are used to add SQL functions or aggregates or to redefine the behavior +-** of existing SQL functions or aggregates. The only differences between +-** these routines are the text encoding expected for +-** the second parameter (the name of the function being created) +-** and the presence or absence of a destructor callback for +-** the application data pointer. ++** of existing SQL functions or aggregates. The only differences between ++** the three "sqlite3_create_function*" routines are the text encoding ++** expected for the second parameter (the name of the function being ++** created) and the presence or absence of a destructor callback for ++** the application data pointer. Function sqlite3_create_window_function() ++** is similar, but allows the user to supply the extra callback functions ++** needed by [aggregate window functions]. + ** + ** ^The first parameter is the [database connection] to which the SQL + ** function is to be added. ^If an application uses more than one database +@@ -5634,7 +5795,8 @@ + ** ^(The fifth parameter is an arbitrary pointer. The implementation of the + ** function can gain access to this pointer using [sqlite3_user_data()].)^ + ** +-** ^The sixth, seventh and eighth parameters, xFunc, xStep and xFinal, are ++** ^The sixth, seventh and eighth parameters passed to the three ++** "sqlite3_create_function*" functions, xFunc, xStep and xFinal, are + ** pointers to C-language functions that implement the SQL function or + ** aggregate. ^A scalar SQL function requires an implementation of the xFunc + ** callback only; NULL pointers must be passed as the xStep and xFinal +@@ -5643,16 +5805,25 @@ + ** SQL function or aggregate, pass NULL pointers for all three function + ** callbacks. + ** +-** ^(If the ninth parameter to sqlite3_create_function_v2() is not NULL, +-** then it is destructor for the application data pointer. +-** The destructor is invoked when the function is deleted, either by being +-** overloaded or when the database connection closes.)^ +-** ^The destructor is also invoked if the call to +-** sqlite3_create_function_v2() fails. +-** ^When the destructor callback of the tenth parameter is invoked, it +-** is passed a single argument which is a copy of the application data +-** pointer which was the fifth parameter to sqlite3_create_function_v2(). ++** ^The sixth, seventh, eighth and ninth parameters (xStep, xFinal, xValue ++** and xInverse) passed to sqlite3_create_window_function are pointers to ++** C-language callbacks that implement the new function. xStep and xFinal ++** must both be non-NULL. xValue and xInverse may either both be NULL, in ++** which case a regular aggregate function is created, or must both be ++** non-NULL, in which case the new function may be used as either an aggregate ++** or aggregate window function. More details regarding the implementation ++** of aggregate window functions are ++** [user-defined window functions|available here]. + ** ++** ^(If the final parameter to sqlite3_create_function_v2() or ++** sqlite3_create_window_function() is not NULL, then it is destructor for ++** the application data pointer. The destructor is invoked when the function ++** is deleted, either by being overloaded or when the database connection ++** closes.)^ ^The destructor is also invoked if the call to ++** sqlite3_create_function_v2() fails. ^When the destructor callback is ++** invoked, it is passed a single argument which is a copy of the application ++** data pointer which was the fifth parameter to sqlite3_create_function_v2(). ++** + ** ^It is permitted to register multiple implementations of the same + ** functions with the same name but with either differing numbers of + ** arguments or differing preferred text encodings. ^SQLite will use +@@ -5704,6 +5875,18 @@ + void (*xFinal)(sqlite3_context*), + void(*xDestroy)(void*) + ); ++SQLITE_API int sqlite3_create_window_function( ++ sqlite3 *db, ++ const char *zFunctionName, ++ int nArg, ++ int eTextRep, ++ void *pApp, ++ void (*xStep)(sqlite3_context*,int,sqlite3_value**), ++ void (*xFinal)(sqlite3_context*), ++ void (*xValue)(sqlite3_context*), ++ void (*xInverse)(sqlite3_context*,int,sqlite3_value**), ++ void(*xDestroy)(void*) ++); + + /* + ** CAPI3REF: Text Encodings +@@ -5846,6 +6029,28 @@ + ** + ** These routines must be called from the same thread as + ** the SQL function that supplied the [sqlite3_value*] parameters. ++** ++** As long as the input parameter is correct, these routines can only ++** fail if an out-of-memory error occurs during a format conversion. ++** Only the following subset of interfaces are subject to out-of-memory ++** errors: ++** ++** <ul> ++** <li> sqlite3_value_blob() ++** <li> sqlite3_value_text() ++** <li> sqlite3_value_text16() ++** <li> sqlite3_value_text16le() ++** <li> sqlite3_value_text16be() ++** <li> sqlite3_value_bytes() ++** <li> sqlite3_value_bytes16() ++** </ul> ++** ++** If an out-of-memory error occurs, then the return value from these ++** routines is the same as if the column had contained an SQL NULL value. ++** Valid SQL NULL returns can be distinguished from out-of-memory errors ++** by invoking the [sqlite3_errcode()] immediately after the suspect ++** return value is obtained and before any ++** other SQLite interface is called on the same [database connection]. + */ + SQLITE_API const void *sqlite3_value_blob(sqlite3_value*); + SQLITE_API double sqlite3_value_double(sqlite3_value*); +@@ -6517,6 +6722,41 @@ + SQLITE_API char *sqlite3_data_directory; + + /* ++** CAPI3REF: Win32 Specific Interface ++** ++** These interfaces are available only on Windows. The ++** [sqlite3_win32_set_directory] interface is used to set the value associated ++** with the [sqlite3_temp_directory] or [sqlite3_data_directory] variable, to ++** zValue, depending on the value of the type parameter. The zValue parameter ++** should be NULL to cause the previous value to be freed via [sqlite3_free]; ++** a non-NULL value will be copied into memory obtained from [sqlite3_malloc] ++** prior to being used. The [sqlite3_win32_set_directory] interface returns ++** [SQLITE_OK] to indicate success, [SQLITE_ERROR] if the type is unsupported, ++** or [SQLITE_NOMEM] if memory could not be allocated. The value of the ++** [sqlite3_data_directory] variable is intended to act as a replacement for ++** the current directory on the sub-platforms of Win32 where that concept is ++** not present, e.g. WinRT and UWP. The [sqlite3_win32_set_directory8] and ++** [sqlite3_win32_set_directory16] interfaces behave exactly the same as the ++** sqlite3_win32_set_directory interface except the string parameter must be ++** UTF-8 or UTF-16, respectively. ++*/ ++SQLITE_API int sqlite3_win32_set_directory( ++ unsigned long type, /* Identifier for directory being set or reset */ ++ void *zValue /* New value for directory being set or reset */ ++); ++SQLITE_API int sqlite3_win32_set_directory8(unsigned long type, const char *zValue); ++SQLITE_API int sqlite3_win32_set_directory16(unsigned long type, const void *zValue); ++ ++/* ++** CAPI3REF: Win32 Directory Types ++** ++** These macros are only available on Windows. They define the allowed values ++** for the type argument to the [sqlite3_win32_set_directory] interface. ++*/ ++#define SQLITE_WIN32_DATA_DIRECTORY_TYPE 1 ++#define SQLITE_WIN32_TEMP_DIRECTORY_TYPE 2 ++ ++/* + ** CAPI3REF: Test For Auto-Commit Mode + ** KEYWORDS: {autocommit mode} + ** METHOD: sqlite3 +@@ -7116,6 +7356,9 @@ + int (*xSavepoint)(sqlite3_vtab *pVTab, int); + int (*xRelease)(sqlite3_vtab *pVTab, int); + int (*xRollbackTo)(sqlite3_vtab *pVTab, int); ++ /* The methods above are in versions 1 and 2 of the sqlite_module object. ++ ** Those below are for version 3 and greater. */ ++ int (*xShadowName)(const char*); + }; + + /* +@@ -7248,6 +7491,10 @@ + + /* + ** CAPI3REF: Virtual Table Scan Flags ++** ++** Virtual table implementations are allowed to set the ++** [sqlite3_index_info].idxFlags field to some combination of ++** these bits. + */ + #define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */ + +@@ -7273,6 +7520,7 @@ + #define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70 + #define SQLITE_INDEX_CONSTRAINT_ISNULL 71 + #define SQLITE_INDEX_CONSTRAINT_IS 72 ++#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150 + + /* + ** CAPI3REF: Register A Virtual Table Implementation +@@ -7949,6 +8197,7 @@ + /* + ** CAPI3REF: Low-Level Control Of Database Files + ** METHOD: sqlite3 ++** KEYWORDS: {file control} + ** + ** ^The [sqlite3_file_control()] interface makes a direct call to the + ** xFileControl method for the [sqlite3_io_methods] object associated +@@ -7963,11 +8212,18 @@ + ** the xFileControl method. ^The return value of the xFileControl + ** method becomes the return value of this routine. + ** ++** A few opcodes for [sqlite3_file_control()] are handled directly ++** by the SQLite core and never invoke the ++** sqlite3_io_methods.xFileControl method. + ** ^The [SQLITE_FCNTL_FILE_POINTER] value for the op parameter causes + ** a pointer to the underlying [sqlite3_file] object to be written into +-** the space pointed to by the 4th parameter. ^The [SQLITE_FCNTL_FILE_POINTER] +-** case is a short-circuit path which does not actually invoke the +-** underlying sqlite3_io_methods.xFileControl method. ++** the space pointed to by the 4th parameter. The ++** [SQLITE_FCNTL_JOURNAL_POINTER] works similarly except that it returns ++** the [sqlite3_file] object associated with the journal file instead of ++** the main database. The [SQLITE_FCNTL_VFS_POINTER] opcode returns ++** a pointer to the underlying [sqlite3_vfs] object for the file. ++** The [SQLITE_FCNTL_DATA_VERSION] returns the data version counter ++** from the pager. + ** + ** ^If the second parameter (zDbName) does not match the name of any + ** open database file, then SQLITE_ERROR is returned. ^This error +@@ -8023,8 +8279,9 @@ + #define SQLITE_TESTCTRL_ALWAYS 13 + #define SQLITE_TESTCTRL_RESERVE 14 + #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 +-#define SQLITE_TESTCTRL_ISKEYWORD 16 ++#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ + #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ ++#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17 + #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 + #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ + #define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19 +@@ -8038,6 +8295,189 @@ + #define SQLITE_TESTCTRL_LAST 26 /* Largest TESTCTRL */ + + /* ++** CAPI3REF: SQL Keyword Checking ++** ++** These routines provide access to the set of SQL language keywords ++** recognized by SQLite. Applications can uses these routines to determine ++** whether or not a specific identifier needs to be escaped (for example, ++** by enclosing in double-quotes) so as not to confuse the parser. ++** ++** The sqlite3_keyword_count() interface returns the number of distinct ++** keywords understood by SQLite. ++** ++** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and ++** makes *Z point to that keyword expressed as UTF8 and writes the number ++** of bytes in the keyword into *L. The string that *Z points to is not ++** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns ++** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z ++** or L are NULL or invalid pointers then calls to ++** sqlite3_keyword_name(N,Z,L) result in undefined behavior. ++** ++** The sqlite3_keyword_check(Z,L) interface checks to see whether or not ++** the L-byte UTF8 identifier that Z points to is a keyword, returning non-zero ++** if it is and zero if not. ++** ++** The parser used by SQLite is forgiving. It is often possible to use ++** a keyword as an identifier as long as such use does not result in a ++** parsing ambiguity. For example, the statement ++** "CREATE TABLE BEGIN(REPLACE,PRAGMA,END);" is accepted by SQLite, and ++** creates a new table named "BEGIN" with three columns named ++** "REPLACE", "PRAGMA", and "END". Nevertheless, best practice is to avoid ++** using keywords as identifiers. Common techniques used to avoid keyword ++** name collisions include: ++** <ul> ++** <li> Put all identifier names inside double-quotes. This is the official ++** SQL way to escape identifier names. ++** <li> Put identifier names inside [...]. This is not standard SQL, ++** but it is what SQL Server does and so lots of programmers use this ++** technique. ++** <li> Begin every identifier with the letter "Z" as no SQL keywords start ++** with "Z". ++** <li> Include a digit somewhere in every identifier name. ++** </ul> ++** ++** Note that the number of keywords understood by SQLite can depend on ++** compile-time options. For example, "VACUUM" is not a keyword if ++** SQLite is compiled with the [-DSQLITE_OMIT_VACUUM] option. Also, ++** new keywords may be added to future releases of SQLite. ++*/ ++SQLITE_API int sqlite3_keyword_count(void); ++SQLITE_API int sqlite3_keyword_name(int,const char**,int*); ++SQLITE_API int sqlite3_keyword_check(const char*,int); ++ ++/* ++** CAPI3REF: Dynamic String Object ++** KEYWORDS: {dynamic string} ++** ++** An instance of the sqlite3_str object contains a dynamically-sized ++** string under construction. ++** ++** The lifecycle of an sqlite3_str object is as follows: ++** <ol> ++** <li> ^The sqlite3_str object is created using [sqlite3_str_new()]. ++** <li> ^Text is appended to the sqlite3_str object using various ++** methods, such as [sqlite3_str_appendf()]. ++** <li> ^The sqlite3_str object is destroyed and the string it created ++** is returned using the [sqlite3_str_finish()] interface. ++** </ol> ++*/ ++typedef struct sqlite3_str sqlite3_str; ++ ++/* ++** CAPI3REF: Create A New Dynamic String Object ++** CONSTRUCTOR: sqlite3_str ++** ++** ^The [sqlite3_str_new(D)] interface allocates and initializes ++** a new [sqlite3_str] object. To avoid memory leaks, the object returned by ++** [sqlite3_str_new()] must be freed by a subsequent call to ++** [sqlite3_str_finish(X)]. ++** ++** ^The [sqlite3_str_new(D)] interface always returns a pointer to a ++** valid [sqlite3_str] object, though in the event of an out-of-memory ++** error the returned object might be a special singleton that will ++** silently reject new text, always return SQLITE_NOMEM from ++** [sqlite3_str_errcode()], always return 0 for ++** [sqlite3_str_length()], and always return NULL from ++** [sqlite3_str_finish(X)]. It is always safe to use the value ++** returned by [sqlite3_str_new(D)] as the sqlite3_str parameter ++** to any of the other [sqlite3_str] methods. ++** ++** The D parameter to [sqlite3_str_new(D)] may be NULL. If the ++** D parameter in [sqlite3_str_new(D)] is not NULL, then the maximum ++** length of the string contained in the [sqlite3_str] object will be ++** the value set for [sqlite3_limit](D,[SQLITE_LIMIT_LENGTH]) instead ++** of [SQLITE_MAX_LENGTH]. ++*/ ++SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3*); ++ ++/* ++** CAPI3REF: Finalize A Dynamic String ++** DESTRUCTOR: sqlite3_str ++** ++** ^The [sqlite3_str_finish(X)] interface destroys the sqlite3_str object X ++** and returns a pointer to a memory buffer obtained from [sqlite3_malloc64()] ++** that contains the constructed string. The calling application should ++** pass the returned value to [sqlite3_free()] to avoid a memory leak. ++** ^The [sqlite3_str_finish(X)] interface may return a NULL pointer if any ++** errors were encountered during construction of the string. ^The ++** [sqlite3_str_finish(X)] interface will also return a NULL pointer if the ++** string in [sqlite3_str] object X is zero bytes long. ++*/ ++SQLITE_API char *sqlite3_str_finish(sqlite3_str*); ++ ++/* ++** CAPI3REF: Add Content To A Dynamic String ++** METHOD: sqlite3_str ++** ++** These interfaces add content to an sqlite3_str object previously obtained ++** from [sqlite3_str_new()]. ++** ++** ^The [sqlite3_str_appendf(X,F,...)] and ++** [sqlite3_str_vappendf(X,F,V)] interfaces uses the [built-in printf] ++** functionality of SQLite to append formatted text onto the end of ++** [sqlite3_str] object X. ++** ++** ^The [sqlite3_str_append(X,S,N)] method appends exactly N bytes from string S ++** onto the end of the [sqlite3_str] object X. N must be non-negative. ++** S must contain at least N non-zero bytes of content. To append a ++** zero-terminated string in its entirety, use the [sqlite3_str_appendall()] ++** method instead. ++** ++** ^The [sqlite3_str_appendall(X,S)] method appends the complete content of ++** zero-terminated string S onto the end of [sqlite3_str] object X. ++** ++** ^The [sqlite3_str_appendchar(X,N,C)] method appends N copies of the ++** single-byte character C onto the end of [sqlite3_str] object X. ++** ^This method can be used, for example, to add whitespace indentation. ++** ++** ^The [sqlite3_str_reset(X)] method resets the string under construction ++** inside [sqlite3_str] object X back to zero bytes in length. ++** ++** These methods do not return a result code. ^If an error occurs, that fact ++** is recorded in the [sqlite3_str] object and can be recovered by a ++** subsequent call to [sqlite3_str_errcode(X)]. ++*/ ++SQLITE_API void sqlite3_str_appendf(sqlite3_str*, const char *zFormat, ...); ++SQLITE_API void sqlite3_str_vappendf(sqlite3_str*, const char *zFormat, va_list); ++SQLITE_API void sqlite3_str_append(sqlite3_str*, const char *zIn, int N); ++SQLITE_API void sqlite3_str_appendall(sqlite3_str*, const char *zIn); ++SQLITE_API void sqlite3_str_appendchar(sqlite3_str*, int N, char C); ++SQLITE_API void sqlite3_str_reset(sqlite3_str*); ++ ++/* ++** CAPI3REF: Status Of A Dynamic String ++** METHOD: sqlite3_str ++** ++** These interfaces return the current status of an [sqlite3_str] object. ++** ++** ^If any prior errors have occurred while constructing the dynamic string ++** in sqlite3_str X, then the [sqlite3_str_errcode(X)] method will return ++** an appropriate error code. ^The [sqlite3_str_errcode(X)] method returns ++** [SQLITE_NOMEM] following any out-of-memory error, or ++** [SQLITE_TOOBIG] if the size of the dynamic string exceeds ++** [SQLITE_MAX_LENGTH], or [SQLITE_OK] if there have been no errors. ++** ++** ^The [sqlite3_str_length(X)] method returns the current length, in bytes, ++** of the dynamic string under construction in [sqlite3_str] object X. ++** ^The length returned by [sqlite3_str_length(X)] does not include the ++** zero-termination byte. ++** ++** ^The [sqlite3_str_value(X)] method returns a pointer to the current ++** content of the dynamic string under construction in X. The value ++** returned by [sqlite3_str_value(X)] is managed by the sqlite3_str object X ++** and might be freed or altered by any subsequent method on the same ++** [sqlite3_str] object. Applications must not used the pointer returned ++** [sqlite3_str_value(X)] after any subsequent method call on the same ++** object. ^Applications may change the content of the string returned ++** by [sqlite3_str_value(X)] as long as they do not write into any bytes ++** outside the range of 0 to [sqlite3_str_length(X)] and do not read or ++** write any byte after any subsequent sqlite3_str method call. ++*/ ++SQLITE_API int sqlite3_str_errcode(sqlite3_str*); ++SQLITE_API int sqlite3_str_length(sqlite3_str*); ++SQLITE_API char *sqlite3_str_value(sqlite3_str*); ++ ++/* + ** CAPI3REF: SQLite Runtime Status + ** + ** ^These interfaces are used to retrieve runtime status information +@@ -9254,6 +9694,7 @@ + ** can use to customize and optimize their behavior. + ** + ** <dl> ++** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]] + ** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT + ** <dd>Calls of the form + ** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported, +@@ -9306,11 +9747,11 @@ + ** method of a [virtual table], then it returns true if and only if the + ** column is being fetched as part of an UPDATE operation during which the + ** column value will not change. Applications might use this to substitute +-** a lighter-weight value to return that the corresponding [xUpdate] method +-** understands as a "no-change" value. ++** a return value that is less expensive to compute and that the corresponding ++** [xUpdate] method understands as a "no-change" value. + ** + ** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that +-** the column is not changed by the UPDATE statement, they the xColumn ++** the column is not changed by the UPDATE statement, then the xColumn + ** method can optionally return without setting a result, without calling + ** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces]. + ** In that case, [sqlite3_value_nochange(X)] will return true for the +@@ -9603,7 +10044,6 @@ + /* + ** CAPI3REF: Database Snapshot + ** KEYWORDS: {snapshot} {sqlite3_snapshot} +-** EXPERIMENTAL + ** + ** An instance of the snapshot object records the state of a [WAL mode] + ** database for some specific point in history. +@@ -9620,11 +10060,6 @@ + ** version of the database file so that it is possible to later open a new read + ** transaction that sees that historical version of the database rather than + ** the most recent version. +-** +-** The constructor for this object is [sqlite3_snapshot_get()]. The +-** [sqlite3_snapshot_open()] method causes a fresh read transaction to refer +-** to an historical snapshot (if possible). The destructor for +-** sqlite3_snapshot objects is [sqlite3_snapshot_free()]. + */ + typedef struct sqlite3_snapshot { + unsigned char hidden[48]; +@@ -9632,7 +10067,7 @@ + + /* + ** CAPI3REF: Record A Database Snapshot +-** EXPERIMENTAL ++** CONSTRUCTOR: sqlite3_snapshot + ** + ** ^The [sqlite3_snapshot_get(D,S,P)] interface attempts to make a + ** new [sqlite3_snapshot] object that records the current state of +@@ -9648,7 +10083,7 @@ + ** in this case. + ** + ** <ul> +-** <li> The database handle must be in [autocommit mode]. ++** <li> The database handle must not be in [autocommit mode]. + ** + ** <li> Schema S of [database connection] D must be a [WAL mode] database. + ** +@@ -9671,7 +10106,7 @@ + ** to avoid a memory leak. + ** + ** The [sqlite3_snapshot_get()] interface is only available when the +-** SQLITE_ENABLE_SNAPSHOT compile-time option is used. ++** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. + */ + SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get( + sqlite3 *db, +@@ -9681,24 +10116,35 @@ + + /* + ** CAPI3REF: Start a read transaction on an historical snapshot +-** EXPERIMENTAL ++** METHOD: sqlite3_snapshot + ** +-** ^The [sqlite3_snapshot_open(D,S,P)] interface starts a +-** read transaction for schema S of +-** [database connection] D such that the read transaction +-** refers to historical [snapshot] P, rather than the most +-** recent change to the database. +-** ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK on success +-** or an appropriate [error code] if it fails. ++** ^The [sqlite3_snapshot_open(D,S,P)] interface either starts a new read ++** transaction or upgrades an existing one for schema S of ++** [database connection] D such that the read transaction refers to ++** historical [snapshot] P, rather than the most recent change to the ++** database. ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK ++** on success or an appropriate [error code] if it fails. + ** +-** ^In order to succeed, a call to [sqlite3_snapshot_open(D,S,P)] must be +-** the first operation following the [BEGIN] that takes the schema S +-** out of [autocommit mode]. +-** ^In other words, schema S must not currently be in +-** a transaction for [sqlite3_snapshot_open(D,S,P)] to work, but the +-** database connection D must be out of [autocommit mode]. +-** ^A [snapshot] will fail to open if it has been overwritten by a +-** [checkpoint]. ++** ^In order to succeed, the database connection must not be in ++** [autocommit mode] when [sqlite3_snapshot_open(D,S,P)] is called. If there ++** is already a read transaction open on schema S, then the database handle ++** must have no active statements (SELECT statements that have been passed ++** to sqlite3_step() but not sqlite3_reset() or sqlite3_finalize()). ++** SQLITE_ERROR is returned if either of these conditions is violated, or ++** if schema S does not exist, or if the snapshot object is invalid. ++** ++** ^A call to sqlite3_snapshot_open() will fail to open if the specified ++** snapshot has been overwritten by a [checkpoint]. In this case ++** SQLITE_ERROR_SNAPSHOT is returned. ++** ++** If there is already a read transaction open when this function is ++** invoked, then the same read transaction remains open (on the same ++** database snapshot) if SQLITE_ERROR, SQLITE_BUSY or SQLITE_ERROR_SNAPSHOT ++** is returned. If another error code - for example SQLITE_PROTOCOL or an ++** SQLITE_IOERR error code - is returned, then the final state of the ++** read transaction is undefined. If SQLITE_OK is returned, then the ++** read transaction is now open on database snapshot P. ++** + ** ^(A call to [sqlite3_snapshot_open(D,S,P)] will fail if the + ** database connection D does not know that the database file for + ** schema S is in [WAL mode]. A database connection might not know +@@ -9709,7 +10155,7 @@ + ** database connection in order to make it ready to use snapshots.) + ** + ** The [sqlite3_snapshot_open()] interface is only available when the +-** SQLITE_ENABLE_SNAPSHOT compile-time option is used. ++** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. + */ + SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open( + sqlite3 *db, +@@ -9719,7 +10165,7 @@ + + /* + ** CAPI3REF: Destroy a snapshot +-** EXPERIMENTAL ++** DESTRUCTOR: sqlite3_snapshot + ** + ** ^The [sqlite3_snapshot_free(P)] interface destroys [sqlite3_snapshot] P. + ** The application must eventually free every [sqlite3_snapshot] object +@@ -9726,13 +10172,13 @@ + ** using this routine to avoid a memory leak. + ** + ** The [sqlite3_snapshot_free()] interface is only available when the +-** SQLITE_ENABLE_SNAPSHOT compile-time option is used. ++** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. + */ + SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*); + + /* + ** CAPI3REF: Compare the ages of two snapshot handles. +-** EXPERIMENTAL ++** METHOD: sqlite3_snapshot + ** + ** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages + ** of two valid snapshot handles. +@@ -9751,6 +10197,9 @@ + ** Otherwise, this API returns a negative value if P1 refers to an older + ** snapshot than P2, zero if the two handles refer to the same database + ** snapshot, and a positive value if P1 is a newer snapshot than P2. ++** ++** This interface is only available if SQLite is compiled with the ++** [SQLITE_ENABLE_SNAPSHOT] option. + */ + SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( + sqlite3_snapshot *p1, +@@ -9759,23 +10208,26 @@ + + /* + ** CAPI3REF: Recover snapshots from a wal file +-** EXPERIMENTAL ++** METHOD: sqlite3_snapshot + ** +-** If all connections disconnect from a database file but do not perform +-** a checkpoint, the existing wal file is opened along with the database +-** file the next time the database is opened. At this point it is only +-** possible to successfully call sqlite3_snapshot_open() to open the most +-** recent snapshot of the database (the one at the head of the wal file), +-** even though the wal file may contain other valid snapshots for which +-** clients have sqlite3_snapshot handles. ++** If a [WAL file] remains on disk after all database connections close ++** (either through the use of the [SQLITE_FCNTL_PERSIST_WAL] [file control] ++** or because the last process to have the database opened exited without ++** calling [sqlite3_close()]) and a new connection is subsequently opened ++** on that database and [WAL file], the [sqlite3_snapshot_open()] interface ++** will only be able to open the last transaction added to the WAL file ++** even though the WAL file contains other valid transactions. + ** +-** This function attempts to scan the wal file associated with database zDb ++** This function attempts to scan the WAL file associated with database zDb + ** of database handle db and make all valid snapshots available to + ** sqlite3_snapshot_open(). It is an error if there is already a read +-** transaction open on the database, or if the database is not a wal mode ++** transaction open on the database, or if the database is not a WAL mode + ** database. + ** + ** SQLITE_OK is returned if successful, or an SQLite error code otherwise. ++** ++** This interface is only available if SQLite is compiled with the ++** [SQLITE_ENABLE_SNAPSHOT] option. + */ + SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); + +@@ -9805,7 +10257,7 @@ + ** been a prior call to [sqlite3_deserialize(D,S,...)] with the same + ** values of D and S. + ** The size of the database is written into *P even if the +-** SQLITE_SERIALIZE_NOCOPY bit is set but no contigious copy ++** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy + ** of the database exists. + ** + ** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the +@@ -9886,7 +10338,7 @@ + ** in the P argument is held in memory obtained from [sqlite3_malloc64()] + ** and that SQLite should take ownership of this memory and automatically + ** free it when it has finished using it. Without this flag, the caller +-** is resposible for freeing any dynamically allocated memory. ++** is responsible for freeing any dynamically allocated memory. + ** + ** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to + ** grow the size of the database using calls to [sqlite3_realloc64()]. This +@@ -10012,7 +10464,7 @@ + sqlite3_int64 iRowid; /* Rowid for current entry */ + sqlite3_rtree_dbl rParentScore; /* Score of parent node */ + int eParentWithin; /* Visibility of parent node */ +- int eWithin; /* OUT: Visiblity */ ++ int eWithin; /* OUT: Visibility */ + sqlite3_rtree_dbl rScore; /* OUT: Write the score here */ + /* The following fields are only available in 3.8.11 and later */ + sqlite3_value **apSqlParam; /* Original SQL values of parameters */ +@@ -10508,6 +10960,13 @@ + ** consecutively. There is no chance that the iterator will visit a change + ** the applies to table X, then one for table Y, and then later on visit + ** another change for table X. ++** ++** The behavior of sqlite3changeset_start_v2() and its streaming equivalent ++** may be modified by passing a combination of ++** [SQLITE_CHANGESETSTART_INVERT | supported flags] as the 4th parameter. ++** ++** Note that the sqlite3changeset_start_v2() API is still <b>experimental</b> ++** and therefore subject to change. + */ + SQLITE_API int sqlite3changeset_start( + sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ +@@ -10514,8 +10973,27 @@ + int nChangeset, /* Size of changeset blob in bytes */ + void *pChangeset /* Pointer to blob containing changeset */ + ); ++SQLITE_API int sqlite3changeset_start_v2( ++ sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ ++ int nChangeset, /* Size of changeset blob in bytes */ ++ void *pChangeset, /* Pointer to blob containing changeset */ ++ int flags /* SESSION_CHANGESETSTART_* flags */ ++); + ++/* ++** CAPI3REF: Flags for sqlite3changeset_start_v2 ++** ++** The following flags may passed via the 4th parameter to ++** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]: ++** ++** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd> ++** Invert the changeset while iterating through 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_CHANGESETSTART_INVERT 0x0002 + ++ + /* + ** CAPI3REF: Advance A Changeset Iterator + ** METHOD: sqlite3_changeset_iter +@@ -11168,7 +11646,7 @@ + ), + void *pCtx, /* First argument passed to xConflict */ + void **ppRebase, int *pnRebase, /* OUT: Rebase data */ +- int flags /* Combination of SESSION_APPLY_* flags */ ++ int flags /* SESSION_CHANGESETAPPLY_* flags */ + ); + + /* +@@ -11186,8 +11664,14 @@ + ** causes the sessions module to omit this savepoint. In this case, if the + ** 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 +@@ -11581,6 +12065,12 @@ + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn + ); ++SQLITE_API int sqlite3changeset_start_v2_strm( ++ sqlite3_changeset_iter **pp, ++ int (*xInput)(void *pIn, void *pData, int *pnData), ++ void *pIn, ++ int flags ++); + SQLITE_API int sqlite3session_changeset_strm( + sqlite3_session *pSession, + int (*xOutput)(void *pOut, const void *pData, int nData), +@@ -11607,8 +12097,47 @@ + void *pOut + ); + ++/* ++** CAPI3REF: Configure global parameters ++** ++** The sqlite3session_config() interface is used to make global configuration ++** changes to the sessions module in order to tune it to the specific needs ++** of the application. ++** ++** The sqlite3session_config() interface is not threadsafe. If it is invoked ++** while any other thread is inside any other sessions method then the ++** results are undefined. Furthermore, if it is invoked after any sessions ++** related objects have been created, the results are also undefined. ++** ++** The first argument to the sqlite3session_config() function must be one ++** of the SQLITE_SESSION_CONFIG_XXX constants defined below. The ++** interpretation of the (void*) value passed as the second parameter and ++** the effect of calling this function depends on the value of the first ++** parameter. ++** ++** <dl> ++** <dt>SQLITE_SESSION_CONFIG_STRMSIZE<dd> ++** By default, the sessions module streaming interfaces attempt to input ++** and output data in approximately 1 KiB chunks. This operand may be used ++** to set and query the value of this configuration setting. The pointer ++** passed as the second argument must point to a value of type (int). ++** If this value is greater than 0, it is used as the new streaming data ++** chunk size for both input and output. Before returning, the (int) value ++** pointed to by pArg is set to the final value of the streaming interface ++** chunk size. ++** </dl> ++** ++** This function returns SQLITE_OK if successful, or an SQLite error code ++** otherwise. ++*/ ++SQLITE_API int sqlite3session_config(int op, void *pArg); + + /* ++** CAPI3REF: Values for sqlite3session_config(). ++*/ ++#define SQLITE_SESSION_CONFIG_STRMSIZE 1 ++ ++/* + ** Make sure we can call this stuff from C++. + */ + #if 0 +@@ -12064,7 +12593,7 @@ + ** This way, even if the tokenizer does not provide synonyms + ** when tokenizing query text (it should not - to do would be + ** inefficient), it doesn't matter if the user queries for +-** 'first + place' or '1st + place', as there are entires in the ++** 'first + place' or '1st + place', as there are entries in the + ** FTS index corresponding to both forms of the first token. + ** </ol> + ** +@@ -12092,7 +12621,7 @@ + ** extra data to the FTS index or require FTS5 to query for multiple terms, + ** so it is efficient in terms of disk space and query speed. However, it + ** does not support prefix queries very well. If, as suggested above, the +-** token "first" is subsituted for "1st" by the tokenizer, then the query: ++** token "first" is substituted for "1st" by the tokenizer, then the query: + ** + ** <codeblock> + ** ... MATCH '1s*'</codeblock> +@@ -12941,107 +13470,119 @@ + #define TK_ESCAPE 58 + #define TK_ID 59 + #define TK_COLUMNKW 60 +-#define TK_FOR 61 +-#define TK_IGNORE 62 +-#define TK_INITIALLY 63 +-#define TK_INSTEAD 64 +-#define TK_NO 65 +-#define TK_KEY 66 +-#define TK_OF 67 +-#define TK_OFFSET 68 +-#define TK_PRAGMA 69 +-#define TK_RAISE 70 +-#define TK_RECURSIVE 71 +-#define TK_REPLACE 72 +-#define TK_RESTRICT 73 +-#define TK_ROW 74 +-#define TK_TRIGGER 75 +-#define TK_VACUUM 76 +-#define TK_VIEW 77 +-#define TK_VIRTUAL 78 +-#define TK_WITH 79 +-#define TK_REINDEX 80 +-#define TK_RENAME 81 +-#define TK_CTIME_KW 82 +-#define TK_ANY 83 +-#define TK_BITAND 84 +-#define TK_BITOR 85 +-#define TK_LSHIFT 86 +-#define TK_RSHIFT 87 +-#define TK_PLUS 88 +-#define TK_MINUS 89 +-#define TK_STAR 90 +-#define TK_SLASH 91 +-#define TK_REM 92 +-#define TK_CONCAT 93 +-#define TK_COLLATE 94 +-#define TK_BITNOT 95 +-#define TK_INDEXED 96 +-#define TK_STRING 97 +-#define TK_JOIN_KW 98 +-#define TK_CONSTRAINT 99 +-#define TK_DEFAULT 100 +-#define TK_NULL 101 +-#define TK_PRIMARY 102 +-#define TK_UNIQUE 103 +-#define TK_CHECK 104 +-#define TK_REFERENCES 105 +-#define TK_AUTOINCR 106 +-#define TK_ON 107 +-#define TK_INSERT 108 +-#define TK_DELETE 109 +-#define TK_UPDATE 110 +-#define TK_SET 111 +-#define TK_DEFERRABLE 112 +-#define TK_FOREIGN 113 +-#define TK_DROP 114 +-#define TK_UNION 115 +-#define TK_ALL 116 +-#define TK_EXCEPT 117 +-#define TK_INTERSECT 118 +-#define TK_SELECT 119 +-#define TK_VALUES 120 +-#define TK_DISTINCT 121 +-#define TK_DOT 122 +-#define TK_FROM 123 +-#define TK_JOIN 124 +-#define TK_USING 125 +-#define TK_ORDER 126 +-#define TK_GROUP 127 +-#define TK_HAVING 128 +-#define TK_LIMIT 129 +-#define TK_WHERE 130 +-#define TK_INTO 131 +-#define TK_FLOAT 132 +-#define TK_BLOB 133 +-#define TK_INTEGER 134 +-#define TK_VARIABLE 135 +-#define TK_CASE 136 +-#define TK_WHEN 137 +-#define TK_THEN 138 +-#define TK_ELSE 139 +-#define TK_INDEX 140 +-#define TK_ALTER 141 +-#define TK_ADD 142 +-#define TK_TRUEFALSE 143 +-#define TK_ISNOT 144 +-#define TK_FUNCTION 145 +-#define TK_COLUMN 146 +-#define TK_AGG_FUNCTION 147 +-#define TK_AGG_COLUMN 148 +-#define TK_UMINUS 149 +-#define TK_UPLUS 150 +-#define TK_TRUTH 151 +-#define TK_REGISTER 152 +-#define TK_VECTOR 153 +-#define TK_SELECT_COLUMN 154 +-#define TK_IF_NULL_ROW 155 +-#define TK_ASTERISK 156 +-#define TK_SPAN 157 +-#define TK_END_OF_FILE 158 +-#define TK_UNCLOSED_STRING 159 +-#define TK_SPACE 160 +-#define TK_ILLEGAL 161 ++#define TK_DO 61 ++#define TK_FOR 62 ++#define TK_IGNORE 63 ++#define TK_INITIALLY 64 ++#define TK_INSTEAD 65 ++#define TK_NO 66 ++#define TK_KEY 67 ++#define TK_OF 68 ++#define TK_OFFSET 69 ++#define TK_PRAGMA 70 ++#define TK_RAISE 71 ++#define TK_RECURSIVE 72 ++#define TK_REPLACE 73 ++#define TK_RESTRICT 74 ++#define TK_ROW 75 ++#define TK_ROWS 76 ++#define TK_TRIGGER 77 ++#define TK_VACUUM 78 ++#define TK_VIEW 79 ++#define TK_VIRTUAL 80 ++#define TK_WITH 81 ++#define TK_CURRENT 82 ++#define TK_FOLLOWING 83 ++#define TK_PARTITION 84 ++#define TK_PRECEDING 85 ++#define TK_RANGE 86 ++#define TK_UNBOUNDED 87 ++#define TK_REINDEX 88 ++#define TK_RENAME 89 ++#define TK_CTIME_KW 90 ++#define TK_ANY 91 ++#define TK_BITAND 92 ++#define TK_BITOR 93 ++#define TK_LSHIFT 94 ++#define TK_RSHIFT 95 ++#define TK_PLUS 96 ++#define TK_MINUS 97 ++#define TK_STAR 98 ++#define TK_SLASH 99 ++#define TK_REM 100 ++#define TK_CONCAT 101 ++#define TK_COLLATE 102 ++#define TK_BITNOT 103 ++#define TK_ON 104 ++#define TK_INDEXED 105 ++#define TK_STRING 106 ++#define TK_JOIN_KW 107 ++#define TK_CONSTRAINT 108 ++#define TK_DEFAULT 109 ++#define TK_NULL 110 ++#define TK_PRIMARY 111 ++#define TK_UNIQUE 112 ++#define TK_CHECK 113 ++#define TK_REFERENCES 114 ++#define TK_AUTOINCR 115 ++#define TK_INSERT 116 ++#define TK_DELETE 117 ++#define TK_UPDATE 118 ++#define TK_SET 119 ++#define TK_DEFERRABLE 120 ++#define TK_FOREIGN 121 ++#define TK_DROP 122 ++#define TK_UNION 123 ++#define TK_ALL 124 ++#define TK_EXCEPT 125 ++#define TK_INTERSECT 126 ++#define TK_SELECT 127 ++#define TK_VALUES 128 ++#define TK_DISTINCT 129 ++#define TK_DOT 130 ++#define TK_FROM 131 ++#define TK_JOIN 132 ++#define TK_USING 133 ++#define TK_ORDER 134 ++#define TK_GROUP 135 ++#define TK_HAVING 136 ++#define TK_LIMIT 137 ++#define TK_WHERE 138 ++#define TK_INTO 139 ++#define TK_NOTHING 140 ++#define TK_FLOAT 141 ++#define TK_BLOB 142 ++#define TK_INTEGER 143 ++#define TK_VARIABLE 144 ++#define TK_CASE 145 ++#define TK_WHEN 146 ++#define TK_THEN 147 ++#define TK_ELSE 148 ++#define TK_INDEX 149 ++#define TK_ALTER 150 ++#define TK_ADD 151 ++#define TK_WINDOW 152 ++#define TK_OVER 153 ++#define TK_FILTER 154 ++#define TK_TRUEFALSE 155 ++#define TK_ISNOT 156 ++#define TK_FUNCTION 157 ++#define TK_COLUMN 158 ++#define TK_AGG_FUNCTION 159 ++#define TK_AGG_COLUMN 160 ++#define TK_UMINUS 161 ++#define TK_UPLUS 162 ++#define TK_TRUTH 163 ++#define TK_REGISTER 164 ++#define TK_VECTOR 165 ++#define TK_SELECT_COLUMN 166 ++#define TK_IF_NULL_ROW 167 ++#define TK_ASTERISK 168 ++#define TK_SPAN 169 ++#define TK_END_OF_FILE 170 ++#define TK_UNCLOSED_STRING 171 ++#define TK_SPACE 172 ++#define TK_ILLEGAL 173 + + /* The token codes above must all fit in 8 bits */ + #define TKFLG_MASK 0xff +@@ -13162,6 +13703,13 @@ + #endif + + /* ++** Default value for the SQLITE_CONFIG_SORTERREF_SIZE option. ++*/ ++#ifndef SQLITE_DEFAULT_SORTERREF_SIZE ++# define SQLITE_DEFAULT_SORTERREF_SIZE 0x7fffffff ++#endif ++ ++/* + ** The compile-time options SQLITE_MMAP_READWRITE and + ** SQLITE_ENABLE_BATCH_ATOMIC_WRITE are not compatible with one another. + ** You must choose one or the other (or neither) but not both. +@@ -13308,7 +13856,8 @@ + # if defined(__SIZEOF_POINTER__) + # define SQLITE_PTRSIZE __SIZEOF_POINTER__ + # elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \ +- defined(_M_ARM) || defined(__arm__) || defined(__x86) ++ defined(_M_ARM) || defined(__arm__) || defined(__x86) || \ ++ (defined(__TOS_AIX__) && !defined(__64BIT__)) + # define SQLITE_PTRSIZE 4 + # else + # define SQLITE_PTRSIZE 8 +@@ -13349,7 +13898,7 @@ + # 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__) ++ defined(__arm__) || defined(_M_ARM64) + # define SQLITE_BYTEORDER 1234 + # elif defined(sparc) || defined(__ppc__) + # define SQLITE_BYTEORDER 4321 +@@ -13604,6 +14153,7 @@ + typedef struct Parse Parse; + typedef struct PreUpdate PreUpdate; + typedef struct PrintfArguments PrintfArguments; ++typedef struct RenameToken RenameToken; + typedef struct RowSet RowSet; + typedef struct Savepoint Savepoint; + typedef struct Select Select; +@@ -13610,7 +14160,7 @@ + typedef struct SQLiteThread SQLiteThread; + typedef struct SelectDest SelectDest; + typedef struct SrcList SrcList; +-typedef struct StrAccum StrAccum; ++typedef struct sqlite3_str StrAccum; /* Internal alias for sqlite3_str */ + typedef struct Table Table; + typedef struct TableLock TableLock; + typedef struct Token Token; +@@ -13619,12 +14169,40 @@ + typedef struct TriggerPrg TriggerPrg; + typedef struct TriggerStep TriggerStep; + typedef struct UnpackedRecord UnpackedRecord; ++typedef struct Upsert Upsert; + typedef struct VTable VTable; + typedef struct VtabCtx VtabCtx; + typedef struct Walker Walker; + typedef struct WhereInfo WhereInfo; ++typedef struct Window Window; + typedef struct With With; + ++ ++/* ++** The bitmask datatype defined below is used for various optimizations. ++** ++** Changing this from a 64-bit to a 32-bit type limits the number of ++** tables in a join to 32 instead of 64. But it also reduces the size ++** of the library by 738 bytes on ix86. ++*/ ++#ifdef SQLITE_BITMASK_TYPE ++ typedef SQLITE_BITMASK_TYPE Bitmask; ++#else ++ typedef u64 Bitmask; ++#endif ++ ++/* ++** The number of bits in a Bitmask. "BMS" means "BitMask Size". ++*/ ++#define BMS ((int)(sizeof(Bitmask)*8)) ++ ++/* ++** A bit in a Bitmask ++*/ ++#define MASKBIT(n) (((Bitmask)1)<<(n)) ++#define MASKBIT32(n) (((unsigned int)1)<<(n)) ++#define ALLBITS ((Bitmask)-1) ++ + /* A VList object records a mapping between parameters/variables/wildcards + ** in the SQL statement (such as $abc, @pqr, or :xyz) and the integer + ** variable number associated with that parameter. See the format description +@@ -13720,7 +14298,7 @@ + SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p); + SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int); + SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *); +-SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int); ++SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int,int*); + SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); + SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*, int); + SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*); +@@ -13901,14 +14479,29 @@ + ** entry in either an index or table btree. + ** + ** Index btrees (used for indexes and also WITHOUT ROWID tables) contain +-** an arbitrary key and no data. These btrees have pKey,nKey set to their +-** key and pData,nData,nZero set to zero. ++** an arbitrary key and no data. These btrees have pKey,nKey set to the ++** key and the pData,nData,nZero fields are uninitialized. The aMem,nMem ++** fields give an array of Mem objects that are a decomposition of the key. ++** The nMem field might be zero, indicating that no decomposition is available. + ** + ** Table btrees (used for rowid tables) contain an integer rowid used as + ** the key and passed in the nKey field. The pKey field is zero. + ** pData,nData hold the content of the new entry. nZero extra zero bytes + ** are appended to the end of the content when constructing the entry. ++** The aMem,nMem fields are uninitialized for table btrees. + ** ++** Field usage summary: ++** ++** Table BTrees Index Btrees ++** ++** pKey always NULL encoded key ++** nKey the ROWID length of pKey ++** pData data not used ++** aMem not used decomposed key value ++** nMem not used entries in aMem ++** nData length of pData not used ++** nZero extra zeros after pData not used ++** + ** This object is used to pass information into sqlite3BtreeInsert(). The + ** same information used to be passed as five separate parameters. But placing + ** the information into this object helps to keep the interface more +@@ -13918,7 +14511,7 @@ + struct BtreePayload { + const void *pKey; /* Key content for indexes. NULL for tables */ + sqlite3_int64 nKey; /* Size of pKey for indexes. PRIMARY KEY for tabs */ +- const void *pData; /* Data for tables. NULL for indexes */ ++ const void *pData; /* Data for tables. */ + sqlite3_value *aMem; /* First of nMem value in the unpacked pKey */ + u16 nMem; /* Number of aMem[] value. Might be zero */ + int nData; /* Size of pData. 0 if none. */ +@@ -13928,6 +14521,9 @@ + SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload, + int flags, int seekResult); + SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++SQLITE_PRIVATE void sqlite3BtreeSkipNext(BtCursor*); ++#endif + SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes); + SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int flags); + SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*); +@@ -14095,7 +14691,8 @@ + u64 cycles; /* Total time spent executing this instruction */ + #endif + #ifdef SQLITE_VDBE_COVERAGE +- int iSrcLine; /* Source-code line that generated this opcode */ ++ u32 iSrcLine; /* Source-code line that generated this opcode ++ ** with flags in the upper 8 bits */ + #endif + }; + typedef struct VdbeOp VdbeOp; +@@ -14196,52 +14793,52 @@ + #define OP_AutoCommit 1 + #define OP_Transaction 2 + #define OP_SorterNext 3 /* jump */ +-#define OP_PrevIfOpen 4 /* jump */ +-#define OP_NextIfOpen 5 /* jump */ +-#define OP_Prev 6 /* jump */ +-#define OP_Next 7 /* jump */ +-#define OP_Checkpoint 8 +-#define OP_JournalMode 9 +-#define OP_Vacuum 10 +-#define OP_VFilter 11 /* jump, synopsis: iplan=r[P3] zplan='P4' */ +-#define OP_VUpdate 12 /* synopsis: data=r[P3@P2] */ +-#define OP_Goto 13 /* jump */ +-#define OP_Gosub 14 /* jump */ +-#define OP_InitCoroutine 15 /* jump */ +-#define OP_Yield 16 /* jump */ +-#define OP_MustBeInt 17 /* jump */ +-#define OP_Jump 18 /* jump */ ++#define OP_Prev 4 /* jump */ ++#define OP_Next 5 /* jump */ ++#define OP_Checkpoint 6 ++#define OP_JournalMode 7 ++#define OP_Vacuum 8 ++#define OP_VFilter 9 /* jump, synopsis: iplan=r[P3] zplan='P4' */ ++#define OP_VUpdate 10 /* synopsis: data=r[P3@P2] */ ++#define OP_Goto 11 /* jump */ ++#define OP_Gosub 12 /* jump */ ++#define OP_InitCoroutine 13 /* jump */ ++#define OP_Yield 14 /* jump */ ++#define OP_MustBeInt 15 /* jump */ ++#define OP_Jump 16 /* jump */ ++#define OP_Once 17 /* jump */ ++#define OP_If 18 /* jump */ + #define OP_Not 19 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */ +-#define OP_Once 20 /* jump */ +-#define OP_If 21 /* jump */ +-#define OP_IfNot 22 /* jump */ +-#define OP_IfNullRow 23 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */ +-#define OP_SeekLT 24 /* jump, synopsis: key=r[P3@P4] */ +-#define OP_SeekLE 25 /* jump, synopsis: key=r[P3@P4] */ +-#define OP_SeekGE 26 /* jump, synopsis: key=r[P3@P4] */ +-#define OP_SeekGT 27 /* jump, synopsis: key=r[P3@P4] */ +-#define OP_NoConflict 28 /* jump, synopsis: key=r[P3@P4] */ +-#define OP_NotFound 29 /* jump, synopsis: key=r[P3@P4] */ +-#define OP_Found 30 /* jump, synopsis: key=r[P3@P4] */ +-#define OP_SeekRowid 31 /* jump, synopsis: intkey=r[P3] */ +-#define OP_NotExists 32 /* jump, synopsis: intkey=r[P3] */ +-#define OP_Last 33 /* jump */ +-#define OP_IfSmaller 34 /* jump */ +-#define OP_SorterSort 35 /* jump */ +-#define OP_Sort 36 /* jump */ +-#define OP_Rewind 37 /* jump */ +-#define OP_IdxLE 38 /* jump, synopsis: key=r[P3@P4] */ +-#define OP_IdxGT 39 /* jump, synopsis: key=r[P3@P4] */ +-#define OP_IdxLT 40 /* jump, synopsis: key=r[P3@P4] */ +-#define OP_IdxGE 41 /* jump, synopsis: key=r[P3@P4] */ +-#define OP_RowSetRead 42 /* jump, synopsis: r[P3]=rowset(P1) */ ++#define OP_IfNot 20 /* jump */ ++#define OP_IfNullRow 21 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */ ++#define OP_SeekLT 22 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_SeekLE 23 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_SeekGE 24 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_SeekGT 25 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_IfNoHope 26 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_NoConflict 27 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_NotFound 28 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_Found 29 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_SeekRowid 30 /* jump, synopsis: intkey=r[P3] */ ++#define OP_NotExists 31 /* jump, synopsis: intkey=r[P3] */ ++#define OP_Last 32 /* jump */ ++#define OP_IfSmaller 33 /* jump */ ++#define OP_SorterSort 34 /* jump */ ++#define OP_Sort 35 /* jump */ ++#define OP_Rewind 36 /* jump */ ++#define OP_IdxLE 37 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_IdxGT 38 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_IdxLT 39 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_IdxGE 40 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_RowSetRead 41 /* jump, synopsis: r[P3]=rowset(P1) */ ++#define OP_RowSetTest 42 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */ + #define OP_Or 43 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */ + #define OP_And 44 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */ +-#define OP_RowSetTest 45 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */ +-#define OP_Program 46 /* jump */ +-#define OP_FkIfZero 47 /* jump, synopsis: if fkctr[P1]==0 goto P2 */ +-#define OP_IfPos 48 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ +-#define OP_IfNotZero 49 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */ ++#define OP_Program 45 /* jump */ ++#define OP_FkIfZero 46 /* jump, synopsis: if fkctr[P1]==0 goto P2 */ ++#define OP_IfPos 47 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ ++#define OP_IfNotZero 48 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */ ++#define OP_DecrJumpZero 49 /* jump, synopsis: if (--r[P1])==0 goto P2 */ + #define OP_IsNull 50 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */ + #define OP_NotNull 51 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */ + #define OP_Ne 52 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */ +@@ -14251,118 +14848,121 @@ + #define OP_Lt 56 /* jump, same as TK_LT, synopsis: IF r[P3]<r[P1] */ + #define OP_Ge 57 /* jump, same as TK_GE, synopsis: IF r[P3]>=r[P1] */ + #define OP_ElseNotEq 58 /* jump, same as TK_ESCAPE */ +-#define OP_DecrJumpZero 59 /* jump, synopsis: if (--r[P1])==0 goto P2 */ +-#define OP_IncrVacuum 60 /* jump */ +-#define OP_VNext 61 /* jump */ +-#define OP_Init 62 /* jump, synopsis: Start at P2 */ +-#define OP_Return 63 +-#define OP_EndCoroutine 64 +-#define OP_HaltIfNull 65 /* synopsis: if r[P3]=null halt */ +-#define OP_Halt 66 +-#define OP_Integer 67 /* synopsis: r[P2]=P1 */ +-#define OP_Int64 68 /* synopsis: r[P2]=P4 */ +-#define OP_String 69 /* synopsis: r[P2]='P4' (len=P1) */ +-#define OP_Null 70 /* synopsis: r[P2..P3]=NULL */ +-#define OP_SoftNull 71 /* synopsis: r[P1]=NULL */ +-#define OP_Blob 72 /* synopsis: r[P2]=P4 (len=P1) */ +-#define OP_Variable 73 /* synopsis: r[P2]=parameter(P1,P4) */ +-#define OP_Move 74 /* synopsis: r[P2@P3]=r[P1@P3] */ +-#define OP_Copy 75 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ +-#define OP_SCopy 76 /* synopsis: r[P2]=r[P1] */ +-#define OP_IntCopy 77 /* synopsis: r[P2]=r[P1] */ +-#define OP_ResultRow 78 /* synopsis: output=r[P1@P2] */ +-#define OP_CollSeq 79 +-#define OP_AddImm 80 /* synopsis: r[P1]=r[P1]+P2 */ +-#define OP_RealAffinity 81 +-#define OP_Cast 82 /* synopsis: affinity(r[P1]) */ +-#define OP_Permutation 83 +-#define OP_BitAnd 84 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */ +-#define OP_BitOr 85 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */ +-#define OP_ShiftLeft 86 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */ +-#define OP_ShiftRight 87 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */ +-#define OP_Add 88 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */ +-#define OP_Subtract 89 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */ +-#define OP_Multiply 90 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */ +-#define OP_Divide 91 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ +-#define OP_Remainder 92 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ +-#define OP_Concat 93 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ +-#define OP_Compare 94 /* synopsis: r[P1@P3] <-> r[P2@P3] */ +-#define OP_BitNot 95 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */ +-#define OP_IsTrue 96 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */ +-#define OP_String8 97 /* same as TK_STRING, synopsis: r[P2]='P4' */ +-#define OP_Offset 98 /* synopsis: r[P3] = sqlite_offset(P1) */ +-#define OP_Column 99 /* synopsis: r[P3]=PX */ +-#define OP_Affinity 100 /* synopsis: affinity(r[P1@P2]) */ +-#define OP_MakeRecord 101 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ +-#define OP_Count 102 /* synopsis: r[P2]=count() */ +-#define OP_ReadCookie 103 +-#define OP_SetCookie 104 +-#define OP_ReopenIdx 105 /* synopsis: root=P2 iDb=P3 */ +-#define OP_OpenRead 106 /* synopsis: root=P2 iDb=P3 */ +-#define OP_OpenWrite 107 /* synopsis: root=P2 iDb=P3 */ +-#define OP_OpenDup 108 +-#define OP_OpenAutoindex 109 /* synopsis: nColumn=P2 */ +-#define OP_OpenEphemeral 110 /* synopsis: nColumn=P2 */ +-#define OP_SorterOpen 111 +-#define OP_SequenceTest 112 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ +-#define OP_OpenPseudo 113 /* synopsis: P3 columns in r[P2] */ +-#define OP_Close 114 +-#define OP_ColumnsUsed 115 +-#define OP_Sequence 116 /* synopsis: r[P2]=cursor[P1].ctr++ */ +-#define OP_NewRowid 117 /* synopsis: r[P2]=rowid */ +-#define OP_Insert 118 /* synopsis: intkey=r[P3] data=r[P2] */ +-#define OP_InsertInt 119 /* synopsis: intkey=P3 data=r[P2] */ +-#define OP_Delete 120 +-#define OP_ResetCount 121 +-#define OP_SorterCompare 122 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ +-#define OP_SorterData 123 /* synopsis: r[P2]=data */ +-#define OP_RowData 124 /* synopsis: r[P2]=data */ +-#define OP_Rowid 125 /* synopsis: r[P2]=rowid */ +-#define OP_NullRow 126 +-#define OP_SeekEnd 127 +-#define OP_SorterInsert 128 /* synopsis: key=r[P2] */ +-#define OP_IdxInsert 129 /* synopsis: key=r[P2] */ +-#define OP_IdxDelete 130 /* synopsis: key=r[P2@P3] */ +-#define OP_DeferredSeek 131 /* synopsis: Move P3 to P1.rowid if needed */ +-#define OP_Real 132 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ +-#define OP_IdxRowid 133 /* synopsis: r[P2]=rowid */ +-#define OP_Destroy 134 +-#define OP_Clear 135 +-#define OP_ResetSorter 136 +-#define OP_CreateBtree 137 /* synopsis: r[P2]=root iDb=P1 flags=P3 */ +-#define OP_SqlExec 138 +-#define OP_ParseSchema 139 +-#define OP_LoadAnalysis 140 +-#define OP_DropTable 141 +-#define OP_DropIndex 142 +-#define OP_DropTrigger 143 +-#define OP_IntegrityCk 144 +-#define OP_RowSetAdd 145 /* synopsis: rowset(P1)=r[P2] */ +-#define OP_Param 146 +-#define OP_FkCounter 147 /* synopsis: fkctr[P1]+=P2 */ +-#define OP_MemMax 148 /* synopsis: r[P1]=max(r[P1],r[P2]) */ +-#define OP_OffsetLimit 149 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ +-#define OP_AggStep0 150 /* synopsis: accum=r[P3] step(r[P2@P5]) */ +-#define OP_AggStep 151 /* synopsis: accum=r[P3] step(r[P2@P5]) */ +-#define OP_AggFinal 152 /* synopsis: accum=r[P1] N=P2 */ +-#define OP_Expire 153 +-#define OP_TableLock 154 /* synopsis: iDb=P1 root=P2 write=P3 */ +-#define OP_VBegin 155 +-#define OP_VCreate 156 +-#define OP_VDestroy 157 +-#define OP_VOpen 158 +-#define OP_VColumn 159 /* synopsis: r[P3]=vcolumn(P2) */ +-#define OP_VRename 160 +-#define OP_Pagecount 161 +-#define OP_MaxPgcnt 162 +-#define OP_PureFunc0 163 +-#define OP_Function0 164 /* synopsis: r[P3]=func(r[P2@P5]) */ +-#define OP_PureFunc 165 +-#define OP_Function 166 /* synopsis: r[P3]=func(r[P2@P5]) */ +-#define OP_Trace 167 +-#define OP_CursorHint 168 +-#define OP_Noop 169 +-#define OP_Explain 170 ++#define OP_IncrVacuum 59 /* jump */ ++#define OP_VNext 60 /* jump */ ++#define OP_Init 61 /* jump, synopsis: Start at P2 */ ++#define OP_PureFunc0 62 ++#define OP_Function0 63 /* synopsis: r[P3]=func(r[P2@P5]) */ ++#define OP_PureFunc 64 ++#define OP_Function 65 /* synopsis: r[P3]=func(r[P2@P5]) */ ++#define OP_Return 66 ++#define OP_EndCoroutine 67 ++#define OP_HaltIfNull 68 /* synopsis: if r[P3]=null halt */ ++#define OP_Halt 69 ++#define OP_Integer 70 /* synopsis: r[P2]=P1 */ ++#define OP_Int64 71 /* synopsis: r[P2]=P4 */ ++#define OP_String 72 /* synopsis: r[P2]='P4' (len=P1) */ ++#define OP_Null 73 /* synopsis: r[P2..P3]=NULL */ ++#define OP_SoftNull 74 /* synopsis: r[P1]=NULL */ ++#define OP_Blob 75 /* synopsis: r[P2]=P4 (len=P1) */ ++#define OP_Variable 76 /* synopsis: r[P2]=parameter(P1,P4) */ ++#define OP_Move 77 /* synopsis: r[P2@P3]=r[P1@P3] */ ++#define OP_Copy 78 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ ++#define OP_SCopy 79 /* synopsis: r[P2]=r[P1] */ ++#define OP_IntCopy 80 /* synopsis: r[P2]=r[P1] */ ++#define OP_ResultRow 81 /* synopsis: output=r[P1@P2] */ ++#define OP_CollSeq 82 ++#define OP_AddImm 83 /* synopsis: r[P1]=r[P1]+P2 */ ++#define OP_RealAffinity 84 ++#define OP_Cast 85 /* synopsis: affinity(r[P1]) */ ++#define OP_Permutation 86 ++#define OP_Compare 87 /* synopsis: r[P1@P3] <-> r[P2@P3] */ ++#define OP_IsTrue 88 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */ ++#define OP_Offset 89 /* synopsis: r[P3] = sqlite_offset(P1) */ ++#define OP_Column 90 /* synopsis: r[P3]=PX */ ++#define OP_Affinity 91 /* synopsis: affinity(r[P1@P2]) */ ++#define OP_BitAnd 92 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */ ++#define OP_BitOr 93 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */ ++#define OP_ShiftLeft 94 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */ ++#define OP_ShiftRight 95 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */ ++#define OP_Add 96 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */ ++#define OP_Subtract 97 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */ ++#define OP_Multiply 98 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */ ++#define OP_Divide 99 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ ++#define OP_Remainder 100 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ ++#define OP_Concat 101 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ ++#define OP_MakeRecord 102 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ ++#define OP_BitNot 103 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */ ++#define OP_Count 104 /* synopsis: r[P2]=count() */ ++#define OP_ReadCookie 105 ++#define OP_String8 106 /* same as TK_STRING, synopsis: r[P2]='P4' */ ++#define OP_SetCookie 107 ++#define OP_ReopenIdx 108 /* synopsis: root=P2 iDb=P3 */ ++#define OP_OpenRead 109 /* synopsis: root=P2 iDb=P3 */ ++#define OP_OpenWrite 110 /* synopsis: root=P2 iDb=P3 */ ++#define OP_OpenDup 111 ++#define OP_OpenAutoindex 112 /* synopsis: nColumn=P2 */ ++#define OP_OpenEphemeral 113 /* synopsis: nColumn=P2 */ ++#define OP_SorterOpen 114 ++#define OP_SequenceTest 115 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ ++#define OP_OpenPseudo 116 /* synopsis: P3 columns in r[P2] */ ++#define OP_Close 117 ++#define OP_ColumnsUsed 118 ++#define OP_SeekHit 119 /* synopsis: seekHit=P2 */ ++#define OP_Sequence 120 /* synopsis: r[P2]=cursor[P1].ctr++ */ ++#define OP_NewRowid 121 /* synopsis: r[P2]=rowid */ ++#define OP_Insert 122 /* synopsis: intkey=r[P3] data=r[P2] */ ++#define OP_InsertInt 123 /* synopsis: intkey=P3 data=r[P2] */ ++#define OP_Delete 124 ++#define OP_ResetCount 125 ++#define OP_SorterCompare 126 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ ++#define OP_SorterData 127 /* synopsis: r[P2]=data */ ++#define OP_RowData 128 /* synopsis: r[P2]=data */ ++#define OP_Rowid 129 /* synopsis: r[P2]=rowid */ ++#define OP_NullRow 130 ++#define OP_SeekEnd 131 ++#define OP_SorterInsert 132 /* synopsis: key=r[P2] */ ++#define OP_IdxInsert 133 /* synopsis: key=r[P2] */ ++#define OP_IdxDelete 134 /* synopsis: key=r[P2@P3] */ ++#define OP_DeferredSeek 135 /* synopsis: Move P3 to P1.rowid if needed */ ++#define OP_IdxRowid 136 /* synopsis: r[P2]=rowid */ ++#define OP_Destroy 137 ++#define OP_Clear 138 ++#define OP_ResetSorter 139 ++#define OP_CreateBtree 140 /* synopsis: r[P2]=root iDb=P1 flags=P3 */ ++#define OP_Real 141 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ ++#define OP_SqlExec 142 ++#define OP_ParseSchema 143 ++#define OP_LoadAnalysis 144 ++#define OP_DropTable 145 ++#define OP_DropIndex 146 ++#define OP_DropTrigger 147 ++#define OP_IntegrityCk 148 ++#define OP_RowSetAdd 149 /* synopsis: rowset(P1)=r[P2] */ ++#define OP_Param 150 ++#define OP_FkCounter 151 /* synopsis: fkctr[P1]+=P2 */ ++#define OP_MemMax 152 /* synopsis: r[P1]=max(r[P1],r[P2]) */ ++#define OP_OffsetLimit 153 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ ++#define OP_AggInverse 154 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */ ++#define OP_AggStep 155 /* synopsis: accum=r[P3] step(r[P2@P5]) */ ++#define OP_AggStep1 156 /* synopsis: accum=r[P3] step(r[P2@P5]) */ ++#define OP_AggValue 157 /* synopsis: r[P3]=value N=P2 */ ++#define OP_AggFinal 158 /* synopsis: accum=r[P1] N=P2 */ ++#define OP_Expire 159 ++#define OP_TableLock 160 /* synopsis: iDb=P1 root=P2 write=P3 */ ++#define OP_VBegin 161 ++#define OP_VCreate 162 ++#define OP_VDestroy 163 ++#define OP_VOpen 164 ++#define OP_VColumn 165 /* synopsis: r[P3]=vcolumn(P2) */ ++#define OP_VRename 166 ++#define OP_Pagecount 167 ++#define OP_MaxPgcnt 168 ++#define OP_Trace 169 ++#define OP_CursorHint 170 ++#define OP_Noop 171 ++#define OP_Explain 172 ++#define OP_Abortable 173 + + /* Properties such as "out2" or "jump" that are specified in + ** comments following the "case" for each opcode in the vdbe.c +@@ -14375,28 +14975,28 @@ + #define OPFLG_OUT2 0x10 /* out2: P2 is an output */ + #define OPFLG_OUT3 0x20 /* out3: P3 is an output */ + #define OPFLG_INITIALIZER {\ +-/* 0 */ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,\ +-/* 8 */ 0x00, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01,\ +-/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0x03, 0x03, 0x01,\ ++/* 0 */ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x10,\ ++/* 8 */ 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x03, 0x03,\ ++/* 16 */ 0x01, 0x01, 0x03, 0x12, 0x03, 0x01, 0x09, 0x09,\ + /* 24 */ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,\ +-/* 32 */ 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\ +-/* 40 */ 0x01, 0x01, 0x23, 0x26, 0x26, 0x0b, 0x01, 0x01,\ ++/* 32 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\ ++/* 40 */ 0x01, 0x23, 0x0b, 0x26, 0x26, 0x01, 0x01, 0x03,\ + /* 48 */ 0x03, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\ +-/* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x01, 0x01, 0x01, 0x02,\ +-/* 64 */ 0x02, 0x08, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00,\ +-/* 72 */ 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ +-/* 80 */ 0x02, 0x02, 0x02, 0x00, 0x26, 0x26, 0x26, 0x26,\ +-/* 88 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00, 0x12,\ +-/* 96 */ 0x12, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10, 0x10,\ +-/* 104 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +-/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ +-/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,\ +-/* 128 */ 0x04, 0x04, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00,\ +-/* 136 */ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +-/* 144 */ 0x00, 0x06, 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00,\ +-/* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +-/* 160 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\ +-/* 168 */ 0x00, 0x00, 0x00,} ++/* 56 */ 0x0b, 0x0b, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,\ ++/* 64 */ 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10, 0x10,\ ++/* 72 */ 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,\ ++/* 80 */ 0x10, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,\ ++/* 88 */ 0x12, 0x20, 0x00, 0x00, 0x26, 0x26, 0x26, 0x26,\ ++/* 96 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00, 0x12,\ ++/* 104 */ 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\ ++/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ ++/* 120 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ ++/* 128 */ 0x00, 0x10, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00,\ ++/* 136 */ 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ ++/* 144 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00,\ ++/* 152 */ 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ ++/* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\ ++/* 168 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,} + + /* The sqlite3P2Values() routine is able to run faster if it knows + ** the value of the largest JUMP opcode. The smaller the maximum +@@ -14404,7 +15004,7 @@ + ** generated this include file strives to group all JUMP opcodes + ** together near the beginning of the list. + */ +-#define SQLITE_MX_JUMP_OPCODE 62 /* Maximum JUMP opcode */ ++#define SQLITE_MX_JUMP_OPCODE 61 /* Maximum JUMP opcode */ + + /************** End of opcodes.h *********************************************/ + /************** Continuing where we left off in vdbe.h ***********************/ +@@ -14438,7 +15038,24 @@ + # define sqlite3VdbeVerifyNoMallocRequired(A,B) + # define sqlite3VdbeVerifyNoResultRow(A) + #endif +-SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno); ++#if defined(SQLITE_DEBUG) ++SQLITE_PRIVATE void sqlite3VdbeVerifyAbortable(Vdbe *p, int); ++#else ++# define sqlite3VdbeVerifyAbortable(A,B) ++#endif ++SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno); ++#ifndef SQLITE_OMIT_EXPLAIN ++SQLITE_PRIVATE void sqlite3VdbeExplain(Parse*,u8,const char*,...); ++SQLITE_PRIVATE void sqlite3VdbeExplainPop(Parse*); ++SQLITE_PRIVATE int sqlite3VdbeExplainParent(Parse*); ++# define ExplainQueryPlan(P) sqlite3VdbeExplain P ++# define ExplainQueryPlanPop(P) sqlite3VdbeExplainPop(P) ++# define ExplainQueryPlanParent(P) sqlite3VdbeExplainParent(P) ++#else ++# define ExplainQueryPlan(P) ++# define ExplainQueryPlanPop(P) ++# define ExplainQueryPlanParent(P) 0 ++#endif + SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*); + SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8); + SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1); +@@ -14482,6 +15099,7 @@ + SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*); + #endif + SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); ++SQLITE_PRIVATE int sqlite3BlobCompare(const Mem*, const Mem*); + + SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); + SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); +@@ -14537,17 +15155,43 @@ + ** + ** VdbeCoverageNeverTaken(v) // Previous branch is never taken + ** ++** VdbeCoverageNeverNull(v) // Previous three-way branch is only ++** // taken on the first two ways. The ++** // NULL option is not possible ++** ++** VdbeCoverageEqNe(v) // Previous OP_Jump is only interested ++** // in distingishing equal and not-equal. ++** + ** Every VDBE branch operation must be tagged with one of the macros above. + ** If not, then when "make test" is run with -DSQLITE_VDBE_COVERAGE and + ** -DSQLITE_DEBUG then an ALWAYS() will fail in the vdbeTakeBranch() + ** routine in vdbe.c, alerting the developer to the missed tag. ++** ++** During testing, the test application will invoke ++** sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE,...) to set a callback ++** routine that is invoked as each bytecode branch is taken. The callback ++** contains the sqlite3.c source line number ov the VdbeCoverage macro and ++** flags to indicate whether or not the branch was taken. The test application ++** is responsible for keeping track of this and reporting byte-code branches ++** that are never taken. ++** ++** See the VdbeBranchTaken() macro and vdbeTakeBranch() function in the ++** vdbe.c source file for additional information. + */ + #ifdef SQLITE_VDBE_COVERAGE + SQLITE_PRIVATE void sqlite3VdbeSetLineNumber(Vdbe*,int); + # define VdbeCoverage(v) sqlite3VdbeSetLineNumber(v,__LINE__) + # define VdbeCoverageIf(v,x) if(x)sqlite3VdbeSetLineNumber(v,__LINE__) +-# define VdbeCoverageAlwaysTaken(v) sqlite3VdbeSetLineNumber(v,2); +-# define VdbeCoverageNeverTaken(v) sqlite3VdbeSetLineNumber(v,1); ++# define VdbeCoverageAlwaysTaken(v) \ ++ sqlite3VdbeSetLineNumber(v,__LINE__|0x5000000); ++# define VdbeCoverageNeverTaken(v) \ ++ sqlite3VdbeSetLineNumber(v,__LINE__|0x6000000); ++# define VdbeCoverageNeverNull(v) \ ++ sqlite3VdbeSetLineNumber(v,__LINE__|0x4000000); ++# define VdbeCoverageNeverNullIf(v,x) \ ++ if(x)sqlite3VdbeSetLineNumber(v,__LINE__|0x4000000); ++# define VdbeCoverageEqNe(v) \ ++ sqlite3VdbeSetLineNumber(v,__LINE__|0x8000000); + # define VDBE_OFFSET_LINENO(x) (__LINE__+x) + #else + # define VdbeCoverage(v) +@@ -14554,6 +15198,9 @@ + # define VdbeCoverageIf(v,x) + # define VdbeCoverageAlwaysTaken(v) + # define VdbeCoverageNeverTaken(v) ++# define VdbeCoverageNeverNull(v) ++# define VdbeCoverageNeverNullIf(v,x) ++# define VdbeCoverageEqNe(v) + # define VDBE_OFFSET_LINENO(x) 0 + #endif + +@@ -14563,6 +15210,10 @@ + # define sqlite3VdbeScanStatus(a,b,c,d,e) + #endif + ++#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) ++SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, VdbeOp*); ++#endif ++ + #endif /* SQLITE_VDBE_H */ + + /************** End of vdbe.h ************************************************/ +@@ -14750,18 +15401,19 @@ + SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); + SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); + SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3*); +-# ifdef SQLITE_DIRECT_OVERFLOW_READ +-SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager, Pgno); +-# endif + # ifdef SQLITE_ENABLE_SNAPSHOT + SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot); + SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot); + SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager); ++SQLITE_PRIVATE int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot); ++SQLITE_PRIVATE void sqlite3PagerSnapshotUnlock(Pager *pPager); + # endif +-#else +-# define sqlite3PagerUseWal(x,y) 0 + #endif + ++#ifdef SQLITE_DIRECT_OVERFLOW_READ ++SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno); ++#endif ++ + #ifdef SQLITE_ENABLE_ZIPVFS + SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); + #endif +@@ -15004,6 +15656,10 @@ + /* Number of dirty pages as a percentage of the configured cache size */ + SQLITE_PRIVATE int sqlite3PCachePercentDirty(PCache*); + ++#ifdef SQLITE_DIRECT_OVERFLOW_READ ++SQLITE_PRIVATE int sqlite3PCacheIsDirty(PCache *pCache); ++#endif ++ + #endif /* _PCACHE_H_ */ + + /************** End of pcache.h **********************************************/ +@@ -15509,12 +16165,14 @@ + ** functions use a regular table table from hash.h.) + ** + ** Hash each FuncDef structure into one of the FuncDefHash.a[] slots. +-** Collisions are on the FuncDef.u.pHash chain. ++** Collisions are on the FuncDef.u.pHash chain. Use the SQLITE_FUNC_HASH() ++** macro to compute a hash on the function name. + */ + #define SQLITE_FUNC_HASH_SZ 23 + struct FuncDefHash { + FuncDef *a[SQLITE_FUNC_HASH_SZ]; /* Hash table for functions */ + }; ++#define SQLITE_FUNC_HASH(C,L) (((C)+(L))%SQLITE_FUNC_HASH_SZ) + + #ifdef SQLITE_USER_AUTHENTICATION + /* +@@ -15575,7 +16233,7 @@ + Db *aDb; /* All backends */ + int nDb; /* Number of backends currently in use */ + u32 mDbFlags; /* flags recording internal state */ +- u32 flags; /* flags settable by pragmas. See below */ ++ u64 flags; /* flags settable by pragmas. See below */ + i64 lastRowid; /* ROWID of most recent insert (see above) */ + i64 szMmap; /* Default mmap_size setting */ + u32 nSchemaLock; /* Do not reset the schema when non-zero */ +@@ -15595,7 +16253,7 @@ + u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */ + u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ + u8 mTrace; /* zero or more SQLITE_TRACE flags */ +- u8 skipBtreeMutex; /* True if no shared-cache backends */ ++ u8 noSharedCache; /* True if no shared-cache backends */ + u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */ + int nextPagesize; /* Pagesize after VACUUM if >0 */ + u32 magic; /* Magic number for detect library misuse */ +@@ -15739,14 +16397,19 @@ + #define SQLITE_Fts3Tokenizer 0x00400000 /* Enable fts3_tokenizer(2) */ + #define SQLITE_EnableQPSG 0x00800000 /* Query Planner Stability Guarantee*/ + #define SQLITE_TriggerEQP 0x01000000 /* Show trigger EXPLAIN QUERY PLAN */ ++#define SQLITE_ResetDatabase 0x02000000 /* Reset the database */ ++#define SQLITE_LegacyAlter 0x04000000 /* Legacy ALTER TABLE behaviour */ ++#define SQLITE_NoSchemaError 0x08000000 /* Do not report schema parse errors*/ ++#define SQLITE_Defensive 0x10000000 /* Input SQL is likely hostile */ + + /* Flags used only if debugging */ ++#define HI(X) ((u64)(X)<<32) + #ifdef SQLITE_DEBUG +-#define SQLITE_SqlTrace 0x08000000 /* Debug print SQL as it executes */ +-#define SQLITE_VdbeListing 0x10000000 /* Debug listings of VDBE programs */ +-#define SQLITE_VdbeTrace 0x20000000 /* True to trace VDBE execution */ +-#define SQLITE_VdbeAddopTrace 0x40000000 /* Trace sqlite3VdbeAddOp() calls */ +-#define SQLITE_VdbeEQP 0x80000000 /* Debug EXPLAIN QUERY PLAN */ ++#define SQLITE_SqlTrace HI(0x0001) /* Debug print SQL as it executes */ ++#define SQLITE_VdbeListing HI(0x0002) /* Debug listings of VDBE progs */ ++#define SQLITE_VdbeTrace HI(0x0004) /* True to trace VDBE execution */ ++#define SQLITE_VdbeAddopTrace HI(0x0008) /* Trace sqlite3VdbeAddOp() calls */ ++#define SQLITE_VdbeEQP HI(0x0010) /* Debug EXPLAIN QUERY PLAN */ + #endif + + /* +@@ -15755,6 +16418,7 @@ + #define DBFLAG_SchemaChange 0x0001 /* Uncommitted Hash table changes */ + #define DBFLAG_PreferBuiltin 0x0002 /* Preference to built-in funcs */ + #define DBFLAG_Vacuum 0x0004 /* Currently in a VACUUM */ ++#define DBFLAG_SchemaKnownOk 0x0008 /* Schema is known to be valid */ + + /* + ** Bits of the sqlite3.dbOptFlags field that are used by the +@@ -15762,7 +16426,7 @@ + ** selectively disable various optimizations. + */ + #define SQLITE_QueryFlattener 0x0001 /* Query flattening */ +-#define SQLITE_ColumnCache 0x0002 /* Column cache */ ++ /* 0x0002 available for reuse */ + #define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */ + #define SQLITE_FactorOutConst 0x0008 /* Constant factoring */ + #define SQLITE_DistinctOpt 0x0010 /* DISTINCT using indexes */ +@@ -15776,6 +16440,8 @@ + /* TH3 expects the Stat34 ^^^^^^ value to be 0x0800. Don't change it */ + #define SQLITE_PushDown 0x1000 /* The push-down optimization */ + #define SQLITE_SimplifyJoin 0x2000 /* Convert LEFT JOIN to JOIN */ ++#define SQLITE_SkipScan 0x4000 /* Skip-scans */ ++#define SQLITE_PropagateConst 0x8000 /* The constant propagation opt */ + #define SQLITE_AllOpts 0xffff /* All optimizations */ + + /* +@@ -15814,11 +16480,13 @@ + */ + struct FuncDef { + i8 nArg; /* Number of arguments. -1 means unlimited */ +- u16 funcFlags; /* Some combination of SQLITE_FUNC_* */ ++ u32 funcFlags; /* Some combination of SQLITE_FUNC_* */ + void *pUserData; /* User data parameter */ + FuncDef *pNext; /* Next function with same name */ + void (*xSFunc)(sqlite3_context*,int,sqlite3_value**); /* func or agg-step */ + void (*xFinalize)(sqlite3_context*); /* Agg finalizer */ ++ void (*xValue)(sqlite3_context*); /* Current agg value */ ++ void (*xInverse)(sqlite3_context*,int,sqlite3_value**); /* inverse agg-step */ + const char *zName; /* SQL name of the function. */ + union { + FuncDef *pHash; /* Next with a different name but the same hash */ +@@ -15875,6 +16543,9 @@ + ** single query - might change over time */ + #define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */ + #define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */ ++#define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */ ++#define SQLITE_FUNC_WINDOW_SIZE 0x20000 /* Requires partition size as arg. */ ++#define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */ + + /* + ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are +@@ -15909,6 +16580,12 @@ + ** are interpreted in the same way as the first 4 parameters to + ** FUNCTION(). + ** ++** WFUNCTION(zName, nArg, iArg, xStep, xFinal, xValue, xInverse) ++** Used to create an aggregate function definition implemented by ++** the C functions xStep and xFinal. The first four parameters ++** are interpreted in the same way as the first 4 parameters to ++** FUNCTION(). ++** + ** LIKEFUNC(zName, nArg, pArg, flags) + ** Used to create a scalar function definition of a function zName + ** that accepts nArg arguments and is implemented by a call to C +@@ -15919,32 +16596,39 @@ + */ + #define FUNCTION(zName, nArg, iArg, bNC, xFunc) \ + {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ +- SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} } ++ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} } + #define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \ + {nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ +- SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} } ++ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} } + #define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \ + {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8, \ +- 0, 0, xFunc, 0, #zName, {0} } ++ 0, 0, xFunc, 0, 0, 0, #zName, {0} } + #define PURE_DATE(zName, nArg, iArg, bNC, xFunc) \ + {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \ +- (void*)&sqlite3Config, 0, xFunc, 0, #zName, {0} } ++ (void*)&sqlite3Config, 0, xFunc, 0, 0, 0, #zName, {0} } + #define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \ + {nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\ +- SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} } ++ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} } + #define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \ + {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ +- pArg, 0, xFunc, 0, #zName, } ++ pArg, 0, xFunc, 0, 0, 0, #zName, } + #define LIKEFUNC(zName, nArg, arg, flags) \ + {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \ +- (void *)arg, 0, likeFunc, 0, #zName, {0} } +-#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \ ++ (void *)arg, 0, likeFunc, 0, 0, 0, #zName, {0} } ++#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue) \ + {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \ +- SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,#zName, {0}} ++ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,0,#zName, {0}} + #define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \ + {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \ +- SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,#zName, {0}} ++ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xFinal,0,#zName, {0}} ++#define WAGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue, xInverse, f) \ ++ {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|f, \ ++ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,xInverse,#zName, {0}} ++#define INTERNAL_FUNCTION(zName, nArg, xFunc) \ ++ {nArg, SQLITE_FUNC_INTERNAL|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \ ++ 0, 0, xFunc, 0, 0, 0, #zName, {0} } + ++ + /* + ** All current savepoints are stored in a linked list starting at + ** sqlite3.pSavepoint. The first element in the list is the most recently +@@ -16000,6 +16684,7 @@ + #define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */ + #define COLFLAG_HASTYPE 0x0004 /* Type name follows column name */ + #define COLFLAG_UNIQUE 0x0008 /* Column def contains "UNIQUE" or "PK" */ ++#define COLFLAG_SORTERREF 0x0010 /* Use sorter-refs with this column */ + + /* + ** A "Collating Sequence" is defined by an instance of the following +@@ -16127,6 +16812,9 @@ + struct Table { + char *zName; /* Name of the table or view */ + Column *aCol; /* Information about each column */ ++#ifdef SQLITE_ENABLE_NORMALIZE ++ Hash *pColHash; /* All columns indexed by name */ ++#endif + Index *pIndex; /* List of SQL indexes on this table. */ + Select *pSelect; /* NULL for tables. Points to definition if a view. */ + FKey *pFKey; /* Linked list of all foreign keys in this table */ +@@ -16177,6 +16865,7 @@ + #define TF_StatsUsed 0x0100 /* Query planner decisions affected by + ** Index.aiRowLogEst[] values */ + #define TF_HasNotNull 0x0200 /* Contains NOT NULL constraints */ ++#define TF_Shadow 0x0400 /* True for a shadow table */ + + /* + ** Test to see whether or not a table is a virtual table. This is +@@ -16287,15 +16976,14 @@ + #define OE_Fail 3 /* Stop the operation but leave all prior changes */ + #define OE_Ignore 4 /* Ignore the error. Do not do the INSERT or UPDATE */ + #define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */ ++#define OE_Update 6 /* Process as a DO UPDATE in an upsert */ ++#define OE_Restrict 7 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */ ++#define OE_SetNull 8 /* Set the foreign key value to NULL */ ++#define OE_SetDflt 9 /* Set the foreign key value to its default */ ++#define OE_Cascade 10 /* Cascade the changes */ ++#define OE_Default 11 /* Do whatever the default action is */ + +-#define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */ +-#define OE_SetNull 7 /* Set the foreign key value to NULL */ +-#define OE_SetDflt 8 /* Set the foreign key value to its default */ +-#define OE_Cascade 9 /* Cascade the changes */ + +-#define OE_Default 10 /* Do whatever the default action is */ +- +- + /* + ** An instance of the following structure is passed as the first + ** argument to sqlite3VdbeKeyCompare and is used to control the +@@ -16429,6 +17117,7 @@ + tRowcnt *aiRowEst; /* Non-logarithmic stat1 data for this index */ + tRowcnt nRowEst0; /* Non-logarithmic number of rows in the index */ + #endif ++ Bitmask colNotIdxed; /* 0 for unindexed columns in pTab */ + }; + + /* +@@ -16464,12 +17153,20 @@ + }; + + /* ++** Possible values to use within the flags argument to sqlite3GetToken(). ++*/ ++#define SQLITE_TOKEN_QUOTED 0x1 /* Token is a quoted identifier. */ ++#define SQLITE_TOKEN_KEYWORD 0x2 /* Token is a keyword. */ ++ ++/* + ** Each token coming out of the lexer is an instance of + ** this structure. Tokens are also used as part of an expression. + ** +-** Note if Token.z==0 then Token.dyn and Token.n are undefined and +-** may contain random values. Do not make any assumptions about Token.dyn +-** and Token.n when Token.z==0. ++** The memory that "z" points to is owned by other objects. Take care ++** that the owner of the "z" string does not deallocate the string before ++** the Token goes out of scope! Very often, the "z" points to some place ++** in the middle of the Parse.zSql text. But it might also point to a ++** static string. + */ + struct Token { + const char *z; /* Text of the token. Not NULL-terminated! */ +@@ -16642,8 +17339,11 @@ + ** TK_COLUMN: the value of p5 for OP_Column + ** TK_AGG_FUNCTION: nesting depth */ + AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ +- Table *pTab; /* Table for TK_COLUMN expressions. Can be NULL +- ** for a column of an index on an expression */ ++ union { ++ Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL ++ ** for a column of an index on an expression */ ++ Window *pWin; /* TK_FUNCTION: Window definition for the func */ ++ } y; + }; + + /* +@@ -16652,7 +17352,7 @@ + #define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */ + #define EP_Agg 0x000002 /* Contains one or more aggregate functions */ + #define EP_HasFunc 0x000004 /* Contains one or more functions of any kind */ +- /* 0x000008 // available for use */ ++#define EP_FixedCol 0x000008 /* TK_Column with a known fixed value */ + #define EP_Distinct 0x000010 /* Aggregate function with DISTINCT keyword */ + #define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */ + #define EP_DblQuoted 0x000040 /* token.z was originally in "..." */ +@@ -16673,6 +17373,7 @@ + #define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */ + #define EP_Alias 0x400000 /* Is an alias for a result set column */ + #define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */ ++#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */ + + /* + ** The EP_Propagate mask is a set of properties that automatically propagate +@@ -16740,6 +17441,7 @@ + unsigned done :1; /* A flag to indicate when processing is finished */ + unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */ + unsigned reusable :1; /* Constant expression is reusable */ ++ unsigned bSorterRef :1; /* Defer evaluation until after sorting */ + union { + struct { + u16 iOrderByCol; /* For ORDER BY, column number in result set */ +@@ -16774,31 +17476,6 @@ + }; + + /* +-** The bitmask datatype defined below is used for various optimizations. +-** +-** Changing this from a 64-bit to a 32-bit type limits the number of +-** tables in a join to 32 instead of 64. But it also reduces the size +-** of the library by 738 bytes on ix86. +-*/ +-#ifdef SQLITE_BITMASK_TYPE +- typedef SQLITE_BITMASK_TYPE Bitmask; +-#else +- typedef u64 Bitmask; +-#endif +- +-/* +-** The number of bits in a Bitmask. "BMS" means "BitMask Size". +-*/ +-#define BMS ((int)(sizeof(Bitmask)*8)) +- +-/* +-** A bit in a Bitmask +-*/ +-#define MASKBIT(n) (((Bitmask)1)<<(n)) +-#define MASKBIT32(n) (((unsigned int)1)<<(n)) +-#define ALLBITS ((Bitmask)-1) +- +-/* + ** The following structure describes the FROM clause of a SELECT statement. + ** Each table or subquery in the FROM clause is a separate element of + ** the SrcList.a[] array. +@@ -16839,9 +17516,6 @@ + unsigned viaCoroutine :1; /* Implemented as a co-routine */ + unsigned isRecursive :1; /* True for recursive reference in WITH */ + } fg; +-#ifndef SQLITE_OMIT_EXPLAIN +- u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */ +-#endif + int iCursor; /* The VDBE cursor number used to access this table */ + Expr *pOn; /* The ON clause of a join */ + IdList *pUsing; /* The USING clause of a join */ +@@ -16923,12 +17597,16 @@ + struct NameContext { + Parse *pParse; /* The parser */ + SrcList *pSrcList; /* One or more tables used to resolve names */ +- ExprList *pEList; /* Optional list of result-set columns */ +- AggInfo *pAggInfo; /* Information about aggregates at this level */ ++ union { ++ ExprList *pEList; /* Optional list of result-set columns */ ++ AggInfo *pAggInfo; /* Information about aggregates at this level */ ++ Upsert *pUpsert; /* ON CONFLICT clause information from an upsert */ ++ } uNC; + NameContext *pNext; /* Next outer name context. NULL for outermost */ + int nRef; /* Number of names resolved by this context */ + int nErr; /* Number of errors encountered while resolving names */ + u16 ncFlags; /* Zero or more NC_* flags defined below */ ++ Select *pWinSelect; /* SELECT statement for any window functions */ + }; + + /* +@@ -16946,18 +17624,49 @@ + #define NC_HasAgg 0x0010 /* One or more aggregate functions seen */ + #define NC_IdxExpr 0x0020 /* True if resolving columns of CREATE INDEX */ + #define NC_VarSelect 0x0040 /* A correlated subquery has been seen */ ++#define NC_UEList 0x0080 /* True if uNC.pEList is used */ ++#define NC_UAggInfo 0x0100 /* True if uNC.pAggInfo is used */ ++#define NC_UUpsert 0x0200 /* True if uNC.pUpsert is used */ + #define NC_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */ + #define NC_Complex 0x2000 /* True if a function or subquery seen */ ++#define NC_AllowWin 0x4000 /* Window functions are allowed here */ + + /* ++** An instance of the following object describes a single ON CONFLICT ++** clause in an upsert. ++** ++** The pUpsertTarget field is only set if the ON CONFLICT clause includes ++** conflict-target clause. (In "ON CONFLICT(a,b)" the "(a,b)" is the ++** conflict-target clause.) The pUpsertTargetWhere is the optional ++** WHERE clause used to identify partial unique indexes. ++** ++** pUpsertSet is the list of column=expr terms of the UPDATE statement. ++** The pUpsertSet field is NULL for a ON CONFLICT DO NOTHING. The ++** pUpsertWhere is the WHERE clause for the UPDATE and is NULL if the ++** WHERE clause is omitted. ++*/ ++struct Upsert { ++ ExprList *pUpsertTarget; /* Optional description of conflicting index */ ++ Expr *pUpsertTargetWhere; /* WHERE clause for partial index targets */ ++ ExprList *pUpsertSet; /* The SET clause from an ON CONFLICT UPDATE */ ++ Expr *pUpsertWhere; /* WHERE clause for the ON CONFLICT UPDATE */ ++ /* The fields above comprise the parse tree for the upsert clause. ++ ** The fields below are used to transfer information from the INSERT ++ ** processing down into the UPDATE processing while generating code. ++ ** Upsert owns the memory allocated above, but not the memory below. */ ++ Index *pUpsertIdx; /* Constraint that pUpsertTarget identifies */ ++ SrcList *pUpsertSrc; /* Table to be updated */ ++ int regData; /* First register holding array of VALUES */ ++ int iDataCur; /* Index of the data cursor */ ++ int iIdxCur; /* Index of the first index cursor */ ++}; ++ ++/* + ** An instance of the following structure contains all information + ** needed to generate code for a single SELECT statement. + ** +-** nLimit is set to -1 if there is no LIMIT clause. nOffset is set to 0. +-** If there is a LIMIT clause, the parser sets nLimit to the value of the +-** limit and nOffset to the value of the offset (or 0 if there is not +-** offset). But later on, nLimit and nOffset become the memory locations +-** in the VDBE that record the limit and offset counters. ++** See the header comment on the computeLimitRegisters() routine for a ++** detailed description of the meaning of the iLimit and iOffset fields. + ** + ** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes. + ** These addresses must be stored so that we can go back and fill in +@@ -16975,9 +17684,7 @@ + LogEst nSelectRow; /* Estimated number of result rows */ + u32 selFlags; /* Various SF_* values */ + int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */ +-#if SELECTTRACE_ENABLED +- char zSelName[12]; /* Symbolic name of this SELECT use for debugging */ +-#endif ++ u32 selId; /* Unique identifier number for this SELECT */ + int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */ + SrcList *pSrc; /* The FROM clause */ + Expr *pWhere; /* The WHERE clause */ +@@ -16988,6 +17695,10 @@ + Select *pNext; /* Next select to the left in a compound */ + Expr *pLimit; /* LIMIT expression. NULL means not used. */ + With *pWith; /* WITH clause attached to this select. Or NULL. */ ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ Window *pWin; /* List of window functions */ ++ Window *pWinDefn; /* List of named window definitions */ ++#endif + }; + + /* +@@ -17017,9 +17728,8 @@ + #define SF_MaybeConvert 0x08000 /* Need convertCompoundSelectToSubquery() */ + #define SF_Converted 0x10000 /* By convertCompoundSelectToSubquery() */ + #define SF_IncludeHidden 0x20000 /* Include hidden columns in output */ +-#define SF_ComplexResult 0x40000 /* Result set contains subquery or function */ ++#define SF_ComplexResult 0x40000 /* Result contains subquery or function */ + +- + /* + ** The results of a SELECT can be distributed in several ways, as defined + ** by one of the following macros. The "SRT" prefix means "SELECT Result +@@ -17133,13 +17843,6 @@ + }; + + /* +-** Size of the column cache +-*/ +-#ifndef SQLITE_N_COLCACHE +-# define SQLITE_N_COLCACHE 10 +-#endif +- +-/* + ** At least one instance of the following structure is created for each + ** trigger that may be fired while parsing an INSERT, UPDATE or DELETE + ** statement. All such objects are stored in the linked list headed at +@@ -17214,7 +17917,6 @@ + u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ + u8 okConstFactor; /* OK to factor out constants */ + u8 disableLookaside; /* Number of times lookaside has been disabled */ +- u8 nColCache; /* Number of entries in aColCache[] */ + int nRangeReg; /* Size of the temporary register block */ + int iRangeReg; /* First register in temporary register block */ + int nErr; /* Number of errors seen */ +@@ -17224,8 +17926,6 @@ + int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */ + int iSelfTab; /* Table associated with an index on expr, or negative + ** of the base register during check-constraint eval */ +- int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */ +- int iCacheCnt; /* Counter used to generate aColCache[].lru values */ + int nLabel; /* Number of labels used */ + int *aLabel; /* Space to hold the labels */ + ExprList *pConstExpr;/* Constant expressions */ +@@ -17235,9 +17935,7 @@ + int regRowid; /* Register holding rowid of CREATE TABLE entry */ + int regRoot; /* Register holding root page number for new objects */ + int nMaxArg; /* Max args passed to user function by sub-program */ +-#if SELECTTRACE_ENABLED +- int nSelect; /* Number of SELECT statements seen */ +-#endif ++ int nSelect; /* Number of SELECT stmts. Counter for Select.selId */ + #ifndef SQLITE_OMIT_SHARED_CACHE + int nTableLock; /* Number of locks in aTableLock */ + TableLock *aTableLock; /* Required table locks for shared-cache mode */ +@@ -17257,17 +17955,9 @@ + ** Fields above must be initialized to zero. The fields that follow, + ** down to the beginning of the recursive section, do not need to be + ** initialized as they will be set before being used. The boundary is +- ** determined by offsetof(Parse,aColCache). ++ ** determined by offsetof(Parse,aTempReg). + **************************************************************************/ + +- struct yColCache { +- int iTable; /* Table cursor number */ +- i16 iColumn; /* Table column number */ +- u8 tempReg; /* iReg is a temp register that needs to be freed */ +- int iLevel; /* Nesting level */ +- int iReg; /* Reg with value of this column. 0 means none. */ +- int lru; /* Least recently used entry has the smallest value */ +- } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */ + int aTempReg[8]; /* Holding area for temporary registers */ + Token sNameToken; /* Token with unqualified schema object name */ + +@@ -17282,19 +17972,21 @@ + ynVar nVar; /* Number of '?' variables seen in the SQL so far */ + u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */ + u8 explain; /* True if the EXPLAIN flag is found on the query */ ++#if !(defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_OMIT_ALTERTABLE)) ++ u8 eParseMode; /* PARSE_MODE_XXX constant */ ++#endif + #ifndef SQLITE_OMIT_VIRTUALTABLE +- u8 declareVtab; /* True if inside sqlite3_declare_vtab() */ + int nVtabLock; /* Number of virtual tables to lock */ + #endif + int nHeight; /* Expression tree height of current sub-select */ + #ifndef SQLITE_OMIT_EXPLAIN +- int iSelectId; /* ID of current select for EXPLAIN output */ +- int iNextSelectId; /* Next available select ID for EXPLAIN output */ ++ int addrExplain; /* Address of current OP_Explain opcode */ + #endif + VList *pVList; /* Mapping between variable names and numbers */ + Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */ + const char *zTail; /* All SQL text past the last semicolon parsed */ + Table *pNewTable; /* A table being constructed by CREATE TABLE */ ++ Index *pNewIndex; /* An index being constructed by CREATE INDEX */ + Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */ + const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ + #ifndef SQLITE_OMIT_VIRTUALTABLE +@@ -17305,12 +17997,20 @@ + TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ + With *pWith; /* Current WITH clause, or NULL */ + With *pWithToFree; /* Free this WITH object at the end of the parse */ ++#ifndef SQLITE_OMIT_ALTERTABLE ++ RenameToken *pRename; /* Tokens subject to renaming by ALTER TABLE */ ++#endif + }; + ++#define PARSE_MODE_NORMAL 0 ++#define PARSE_MODE_DECLARE_VTAB 1 ++#define PARSE_MODE_RENAME_COLUMN 2 ++#define PARSE_MODE_RENAME_TABLE 3 ++ + /* + ** Sizes and pointers of various parts of the Parse object. + */ +-#define PARSE_HDR_SZ offsetof(Parse,aColCache) /* Recursive part w/o aColCache*/ ++#define PARSE_HDR_SZ offsetof(Parse,aTempReg) /* Recursive part w/o aColCache*/ + #define PARSE_RECURSE_SZ offsetof(Parse,sLastToken) /* Recursive part */ + #define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */ + #define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */ +@@ -17321,9 +18021,21 @@ + #ifdef SQLITE_OMIT_VIRTUALTABLE + #define IN_DECLARE_VTAB 0 + #else +- #define IN_DECLARE_VTAB (pParse->declareVtab) ++ #define IN_DECLARE_VTAB (pParse->eParseMode==PARSE_MODE_DECLARE_VTAB) + #endif + ++#if defined(SQLITE_OMIT_ALTERTABLE) ++ #define IN_RENAME_OBJECT 0 ++#else ++ #define IN_RENAME_OBJECT (pParse->eParseMode>=PARSE_MODE_RENAME_COLUMN) ++#endif ++ ++#if defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_OMIT_ALTERTABLE) ++ #define IN_SPECIAL_PARSE 0 ++#else ++ #define IN_SPECIAL_PARSE (pParse->eParseMode!=PARSE_MODE_NORMAL) ++#endif ++ + /* + ** An instance of the following structure can be declared on a stack and used + ** to save the Parse.zAuthContext value so that it can be restored later. +@@ -17347,6 +18059,7 @@ + */ + #define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */ + /* Also used in P2 (not P5) of OP_Delete */ ++#define OPFLAG_NOCHNG 0x01 /* OP_VColumn nochange for UPDATE */ + #define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */ + #define OPFLAG_LASTROWID 0x20 /* Set to update db->lastRowid */ + #define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */ +@@ -17448,8 +18161,9 @@ + Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */ + char *zTarget; /* Target table for DELETE, UPDATE, INSERT */ + Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */ +- ExprList *pExprList; /* SET clause for UPDATE. */ ++ ExprList *pExprList; /* SET clause for UPDATE */ + IdList *pIdList; /* Column names for INSERT */ ++ Upsert *pUpsert; /* Upsert clauses on an INSERT */ + char *zSpan; /* Original SQL text of this command */ + TriggerStep *pNext; /* Next in the link-list */ + TriggerStep *pLast; /* Last element in link-list. Valid for 1st elem only */ +@@ -17474,17 +18188,15 @@ + ** An objected used to accumulate the text of a string where we + ** do not necessarily know how big the string will be in the end. + */ +-struct StrAccum { ++struct sqlite3_str { + sqlite3 *db; /* Optional database for lookaside. Can be NULL */ + char *zText; /* The string collected so far */ + u32 nAlloc; /* Amount of space allocated in zText */ + u32 mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */ + u32 nChar; /* Length of the string so far */ +- u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */ ++ u8 accError; /* SQLITE_NOMEM or SQLITE_TOOBIG */ + u8 printfFlags; /* SQLITE_PRINTF flags below */ + }; +-#define STRACCUM_NOMEM 1 +-#define STRACCUM_TOOBIG 2 + #define SQLITE_PRINTF_INTERNAL 0x01 /* Internal-use-only converters allowed */ + #define SQLITE_PRINTF_SQLFUNC 0x02 /* SQL function arguments to VXPrintf */ + #define SQLITE_PRINTF_MALLOCED 0x04 /* True if xText is allocated space */ +@@ -17501,9 +18213,15 @@ + char **pzErrMsg; /* Error message stored here */ + int iDb; /* 0 for main database. 1 for TEMP, 2.. for ATTACHed */ + int rc; /* Result code stored here */ ++ u32 mInitFlags; /* Flags controlling error messages */ + } InitData; + + /* ++** Allowed values for mInitFlags ++*/ ++#define INITFLAG_AlterTable 0x0001 /* This is a reparse after ALTER TABLE */ ++ ++/* + ** Structure containing global configuration data for the SQLite library. + ** + ** This structure also contains some state information. +@@ -17553,7 +18271,7 @@ + /* The following callback (if not NULL) is invoked on every VDBE branch + ** operation. Set the callback using SQLITE_TESTCTRL_VDBE_COVERAGE. + */ +- void (*xVdbeBranch)(void*,int iSrcLine,u8 eThis,u8 eMx); /* Callback */ ++ void (*xVdbeBranch)(void*,unsigned iSrcLine,u8 eThis,u8 eMx); /* Callback */ + void *pVdbeBranchArg; /* 1st argument */ + #endif + #ifndef SQLITE_UNTESTABLE +@@ -17560,7 +18278,9 @@ + int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */ + #endif + int bLocaltimeFault; /* True to fail localtime() calls */ ++ int bInternalFunctions; /* Internal SQL functions are visible */ + int iOnceResetThreshold; /* When to reset OP_Once counters */ ++ u32 szSorterRef; /* Min size in bytes to use sorter-refs */ + }; + + /* +@@ -17603,6 +18323,9 @@ + struct IdxExprTrans *pIdxTrans; /* Convert idxed expr to column */ + ExprList *pGroupBy; /* GROUP BY clause */ + Select *pSelect; /* HAVING to WHERE clause ctx */ ++ struct WindowRewrite *pRewrite; /* Window rewrite context */ ++ struct WhereConst *pConst; /* WHERE clause constants */ ++ struct RenameCtx *pRename; /* RENAME COLUMN context */ + } u; + }; + +@@ -17654,6 +18377,68 @@ + #endif /* SQLITE_DEBUG */ + + /* ++** This object is used in varioius ways, all related to window functions ++** ++** (1) A single instance of this structure is attached to the ++** the Expr.pWin field for each window function in an expression tree. ++** This object holds the information contained in the OVER clause, ++** plus additional fields used during code generation. ++** ++** (2) All window functions in a single SELECT form a linked-list ++** attached to Select.pWin. The Window.pFunc and Window.pExpr ++** fields point back to the expression that is the window function. ++** ++** (3) The terms of the WINDOW clause of a SELECT are instances of this ++** object on a linked list attached to Select.pWinDefn. ++** ++** The uses (1) and (2) are really the same Window object that just happens ++** to be accessible in two different ways. Use (3) is are separate objects. ++*/ ++struct Window { ++ char *zName; /* Name of window (may be NULL) */ ++ ExprList *pPartition; /* PARTITION BY clause */ ++ ExprList *pOrderBy; /* ORDER BY clause */ ++ u8 eType; /* TK_RANGE or TK_ROWS */ ++ u8 eStart; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */ ++ u8 eEnd; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */ ++ Expr *pStart; /* Expression for "<expr> PRECEDING" */ ++ Expr *pEnd; /* Expression for "<expr> FOLLOWING" */ ++ Window *pNextWin; /* Next window function belonging to this SELECT */ ++ Expr *pFilter; /* The FILTER expression */ ++ FuncDef *pFunc; /* The function */ ++ int iEphCsr; /* Partition buffer or Peer buffer */ ++ int regAccum; ++ int regResult; ++ int csrApp; /* Function cursor (used by min/max) */ ++ int regApp; /* Function register (also used by min/max) */ ++ int regPart; /* First in a set of registers holding PARTITION BY ++ ** and ORDER BY values for the window */ ++ Expr *pOwner; /* Expression object this window is attached to */ ++ int nBufferCol; /* Number of columns in buffer table */ ++ int iArgCol; /* Offset of first argument for this function */ ++}; ++ ++#ifndef SQLITE_OMIT_WINDOWFUNC ++SQLITE_PRIVATE void sqlite3WindowDelete(sqlite3*, Window*); ++SQLITE_PRIVATE void sqlite3WindowListDelete(sqlite3 *db, Window *p); ++SQLITE_PRIVATE Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*); ++SQLITE_PRIVATE void sqlite3WindowAttach(Parse*, Expr*, Window*); ++SQLITE_PRIVATE int sqlite3WindowCompare(Parse*, Window*, Window*); ++SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse*, Window*); ++SQLITE_PRIVATE void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int); ++SQLITE_PRIVATE int sqlite3WindowRewrite(Parse*, Select*); ++SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse*, struct SrcList_item*); ++SQLITE_PRIVATE void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*); ++SQLITE_PRIVATE Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p); ++SQLITE_PRIVATE Window *sqlite3WindowListDup(sqlite3 *db, Window *p); ++SQLITE_PRIVATE void sqlite3WindowFunctions(void); ++#else ++# define sqlite3WindowDelete(a,b) ++# define sqlite3WindowFunctions() ++# define sqlite3WindowAttach(a,b,c) ++#endif ++ ++/* + ** Assuming zIn points to the first byte of a UTF-8 character, + ** advance zIn to point to the first byte of the next UTF-8 character. + */ +@@ -17740,9 +18525,7 @@ + # define sqlite3Tolower(x) tolower((unsigned char)(x)) + # define sqlite3Isquote(x) ((x)=='"'||(x)=='\''||(x)=='['||(x)=='`') + #endif +-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS + SQLITE_PRIVATE int sqlite3IsIdChar(u8); +-#endif + + /* + ** Internal function prototypes +@@ -17749,6 +18532,7 @@ + */ + SQLITE_PRIVATE int sqlite3StrICmp(const char*,const char*); + SQLITE_PRIVATE int sqlite3Strlen30(const char*); ++#define sqlite3Strlen30NN(C) (strlen(C)&0x3fffffff) + SQLITE_PRIVATE char *sqlite3ColumnType(Column*,char*); + #define sqlite3StrNICmp sqlite3_strnicmp + +@@ -17852,8 +18636,6 @@ + sqlite3_value **apArg; /* The argument values */ + }; + +-SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, const char*, va_list); +-SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, const char*, ...); + SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...); + SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list); + #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) +@@ -17867,9 +18649,14 @@ + SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView*, const Expr*, u8); + SQLITE_PRIVATE void sqlite3TreeViewBareExprList(TreeView*, const ExprList*, const char*); + SQLITE_PRIVATE void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*); ++SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView*, const SrcList*); + SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView*, const Select*, u8); + SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView*, const With*, u8); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView*, const Window*, u8); ++SQLITE_PRIVATE void sqlite3TreeViewWinFunc(TreeView*, const Window*, u8); + #endif ++#endif + + + SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*); +@@ -17893,7 +18680,7 @@ + SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*); + SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*); + SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*); +-SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*); ++SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int); + SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32); + SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*); + SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); +@@ -17905,6 +18692,7 @@ + SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*); + SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**); + SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**); ++SQLITE_PRIVATE int sqlite3InitOne(sqlite3*, int, char**, u32); + SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); + #ifndef SQLITE_OMIT_VIRTUALTABLE + SQLITE_PRIVATE Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName); +@@ -17954,8 +18742,9 @@ + SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int,int*); + #endif + +-SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int); +-SQLITE_PRIVATE void sqlite3RowSetClear(RowSet*); ++SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3*); ++SQLITE_PRIVATE void sqlite3RowSetDelete(void*); ++SQLITE_PRIVATE void sqlite3RowSetClear(void*); + SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet*, i64); + SQLITE_PRIVATE int sqlite3RowSetTest(RowSet*, int iBatch, i64); + SQLITE_PRIVATE int sqlite3RowSetNext(RowSet*, i64*); +@@ -17974,6 +18763,7 @@ + SQLITE_PRIVATE void sqlite3DropTable(Parse*, SrcList*, int, int); + SQLITE_PRIVATE void sqlite3CodeDropTable(Parse*, Table*, int, int); + SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3*, Table*); ++SQLITE_PRIVATE void sqlite3FreeIndex(sqlite3*, Index*); + #ifndef SQLITE_OMIT_AUTOINCREMENT + SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse); + SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse); +@@ -17981,9 +18771,9 @@ + # define sqlite3AutoincrementBegin(X) + # define sqlite3AutoincrementEnd(X) + #endif +-SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int); ++SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int, Upsert*); + SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*); +-SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*); ++SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse*, IdList*, Token*); + SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*); + SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(sqlite3*, SrcList*, int, int); + SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*); +@@ -18011,13 +18801,14 @@ + SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*); + #endif + SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*); +-SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*); ++SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*, ++ Upsert*); + SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int); + SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*); + SQLITE_PRIVATE LogEst sqlite3WhereOutputRowCount(WhereInfo*); + SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo*); + SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo*); +-SQLITE_PRIVATE int sqlite3WhereOrderedInnerLoop(WhereInfo*); ++SQLITE_PRIVATE int sqlite3WhereOrderByLimitOptLabel(WhereInfo*); + SQLITE_PRIVATE int sqlite3WhereIsSorted(WhereInfo*); + SQLITE_PRIVATE int sqlite3WhereContinueLabel(WhereInfo*); + SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo*); +@@ -18027,15 +18818,8 @@ + #define ONEPASS_MULTI 2 /* ONEPASS is valid for multiple rows */ + SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int); + SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8); +-SQLITE_PRIVATE void sqlite3ExprCodeGetColumnToReg(Parse*, Table*, int, int, int); + SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int); + SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int); +-SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse*, int, int, int); +-SQLITE_PRIVATE void sqlite3ExprCachePush(Parse*); +-SQLITE_PRIVATE void sqlite3ExprCachePop(Parse*); +-SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse*, int, int); +-SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse*); +-SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse*, int, int); + SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int); + SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, Expr*, int); + SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int); +@@ -18098,13 +18882,17 @@ + SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*); + SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); + SQLITE_PRIVATE int sqlite3IsRowid(const char*); ++#ifdef SQLITE_ENABLE_NORMALIZE ++SQLITE_PRIVATE int sqlite3IsRowidN(const char*, int); ++#endif + SQLITE_PRIVATE void sqlite3GenerateRowDelete( + Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int); + SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int); + SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int); + SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse*,int); ++SQLITE_PRIVATE int sqlite3ExprReferencesUpdatedColumn(Expr*,int*,int); + SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int, +- u8,u8,int,int*,int*); ++ u8,u8,int,int*,int*,Upsert*); + #ifdef SQLITE_ENABLE_NULL_TRIM + SQLITE_PRIVATE void sqlite3SetMakeRecordP5(Vdbe*,Table*); + #else +@@ -18123,10 +18911,8 @@ + SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int); + SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*); + SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*,int); +-#if SELECTTRACE_ENABLED +-SQLITE_PRIVATE void sqlite3SelectSetName(Select*,const char*); +-#else +-# define sqlite3SelectSetName(A,B) ++#ifdef SQLITE_ENABLE_NORMALIZE ++SQLITE_PRIVATE FuncDef *sqlite3FunctionSearchN(int,const char*,int); + #endif + SQLITE_PRIVATE void sqlite3InsertBuiltinFuncs(FuncDef*,int); + SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8); +@@ -18156,12 +18942,13 @@ + SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*); + SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*, + const char*,const char*); +-SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*, +- Select*,u8,const char*,const char*); +-SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8, ++SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(Parse*,Token*, IdList*, ++ Select*,u8,Upsert*, + const char*,const char*); +-SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*, ++SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(Parse*,Token*,ExprList*, Expr*, u8, + const char*,const char*); ++SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(Parse*,Token*, Expr*, ++ const char*,const char*); + SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*); + SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); + SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int); +@@ -18275,6 +19062,7 @@ + SQLITE_PRIVATE const char *sqlite3ErrStr(int); + SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse); + SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); ++SQLITE_PRIVATE int sqlite3IsBinary(const CollSeq*); + SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); + SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); + SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr); +@@ -18283,6 +19071,7 @@ + SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*); + SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*); + SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *); ++SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3*); + SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *); + SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int); + SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64); +@@ -18327,9 +19116,13 @@ + SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*); + SQLITE_PRIVATE void sqlite3AlterFunctions(void); + SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); ++SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*); + SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *); ++#ifdef SQLITE_ENABLE_NORMALIZE ++SQLITE_PRIVATE int sqlite3GetTokenNormalized(const unsigned char *, int *, int *); ++#endif + SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); +-SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*); ++SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, int); + SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr *, int, int); + SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); + SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p); +@@ -18342,8 +19135,12 @@ + SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int); + SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *); + SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *); ++SQLITE_PRIVATE void *sqlite3RenameTokenMap(Parse*, void*, Token*); ++SQLITE_PRIVATE void sqlite3RenameTokenRemap(Parse*, void *pTo, void *pFrom); ++SQLITE_PRIVATE void sqlite3RenameExprUnmap(Parse*, Expr*); ++SQLITE_PRIVATE void sqlite3RenameExprlistUnmap(Parse*, ExprList*); + SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*); +-SQLITE_PRIVATE char sqlite3AffinityType(const char*, u8*); ++SQLITE_PRIVATE char sqlite3AffinityType(const char*, Column*); + SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*); + SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*, sqlite3_file*); + SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*); +@@ -18360,14 +19157,20 @@ + SQLITE_PRIVATE void sqlite3KeyInfoUnref(KeyInfo*); + SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoRef(KeyInfo*); + SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*); ++SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoFromExprList(Parse*, ExprList*, int, int); ++ + #ifdef SQLITE_DEBUG + SQLITE_PRIVATE int sqlite3KeyInfoIsWriteable(KeyInfo*); + #endif + SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, + void (*)(sqlite3_context*,int,sqlite3_value **), +- void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*), ++ void (*)(sqlite3_context*,int,sqlite3_value **), ++ void (*)(sqlite3_context*), ++ void (*)(sqlite3_context*), ++ void (*)(sqlite3_context*,int,sqlite3_value **), + FuncDestructor *pDestructor + ); ++SQLITE_PRIVATE void sqlite3NoopDestructor(void*); + SQLITE_PRIVATE void sqlite3OomFault(sqlite3*); + SQLITE_PRIVATE void sqlite3OomClear(sqlite3*); + SQLITE_PRIVATE int sqlite3ApiExit(sqlite3 *db, int); +@@ -18374,11 +19177,7 @@ + SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *); + + SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int); +-SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum*,const char*,int); +-SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum*,const char*); +-SQLITE_PRIVATE void sqlite3AppendChar(StrAccum*,int,char); + SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum*); +-SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum*); + SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest*,int,int); + SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int); + +@@ -18405,10 +19204,11 @@ + ** The interface to the LEMON-generated parser + */ + #ifndef SQLITE_AMALGAMATION +-SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(u64)); ++SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(u64), Parse*); + SQLITE_PRIVATE void sqlite3ParserFree(void*, void(*)(void*)); + #endif +-SQLITE_PRIVATE void sqlite3Parser(void*, int, Token, Parse*); ++SQLITE_PRIVATE void sqlite3Parser(void*, int, Token); ++SQLITE_PRIVATE int sqlite3ParserFallback(int); + #ifdef YYTRACKMAXSTACKDEPTH + SQLITE_PRIVATE int sqlite3ParserStackPeak(void*); + #endif +@@ -18474,11 +19274,13 @@ + SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *); + SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, VTable *); + SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); +-SQLITE_PRIVATE void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**); + SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*); + SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); + SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); + SQLITE_PRIVATE void sqlite3ParserReset(Parse*); ++#ifdef SQLITE_ENABLE_NORMALIZE ++SQLITE_PRIVATE void sqlite3Normalize(Vdbe*, const char*, int, u8); ++#endif + SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*); + SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*); + SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *); +@@ -18496,7 +19298,19 @@ + #define sqlite3WithPush(x,y,z) + #define sqlite3WithDelete(x,y) + #endif ++#ifndef SQLITE_OMIT_UPSERT ++SQLITE_PRIVATE Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*); ++SQLITE_PRIVATE void sqlite3UpsertDelete(sqlite3*,Upsert*); ++SQLITE_PRIVATE Upsert *sqlite3UpsertDup(sqlite3*,Upsert*); ++SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*); ++SQLITE_PRIVATE void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int); ++#else ++#define sqlite3UpsertNew(v,w,x,y,z) ((Upsert*)0) ++#define sqlite3UpsertDelete(x,y) ++#define sqlite3UpsertDup(x,y) ((Upsert*)0) ++#endif + ++ + /* Declarations for functions in fkey.c. All of these are replaced by + ** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign + ** key functionality is available. If OMIT_TRIGGER is defined but +@@ -18928,7 +19742,9 @@ + 0, /* xTestCallback */ + #endif + 0, /* bLocaltimeFault */ +- 0x7ffffffe /* iOnceResetThreshold */ ++ 0, /* bInternalFunctions */ ++ 0x7ffffffe, /* iOnceResetThreshold */ ++ SQLITE_DEFAULT_SORTERREF_SIZE /* szSorterRef */ + }; + + /* +@@ -19097,6 +19913,7 @@ + Bool isEphemeral:1; /* True for an ephemeral table */ + Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */ + Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */ ++ Bool seekHit:1; /* See the OP_SeekHit and OP_IfNoHope opcodes */ + Btree *pBtx; /* Separate file holding temporary table */ + i64 seqCount; /* Sequence counter */ + int *aAltMap; /* Mapping from table to index column numbers */ +@@ -19180,6 +19997,9 @@ + void *token; /* Copy of SubProgram.token */ + i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ + AuxData *pAuxData; /* Linked list of auxdata allocations */ ++#if SQLITE_DEBUG ++ u32 iFrameMagic; /* magic number for sanity checking */ ++#endif + int nCursor; /* Number of entries in apCsr */ + int pc; /* Program Counter in parent (calling) frame */ + int nOp; /* Size of aOp array */ +@@ -19190,6 +20010,13 @@ + int nDbChange; /* Value of db->nChange */ + }; + ++/* Magic number for sanity checking on VdbeFrame objects */ ++#define SQLITE_FRAME_MAGIC 0x879fb71e ++ ++/* ++** Return a pointer to the array of registers allocated for use ++** by a VdbeFrame. ++*/ + #define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))]) + + /* +@@ -19204,8 +20031,6 @@ + int nZero; /* Extra zero bytes when MEM_Zero and MEM_Blob set */ + const char *zPType; /* Pointer type when MEM_Term|MEM_Subtype|MEM_Null */ + FuncDef *pDef; /* Used only when flags==MEM_Agg */ +- RowSet *pRowSet; /* Used only when flags==MEM_RowSet */ +- VdbeFrame *pFrame; /* Used when flags==MEM_Frame */ + } u; + u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ + u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */ +@@ -19220,7 +20045,7 @@ + void (*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */ + #ifdef SQLITE_DEBUG + Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */ +- void *pFiller; /* So that sizeof(Mem) is a multiple of 8 */ ++ u16 mScopyFlags; /* flags value immediately after the shallow copy */ + #endif + }; + +@@ -19249,8 +20074,8 @@ + #define MEM_Real 0x0008 /* Value is a real number */ + #define MEM_Blob 0x0010 /* Value is a BLOB */ + #define MEM_AffMask 0x001f /* Mask of affinity bits */ +-#define MEM_RowSet 0x0020 /* Value is a RowSet object */ +-#define MEM_Frame 0x0040 /* Value is a VdbeFrame object */ ++/* Available 0x0020 */ ++/* Available 0x0040 */ + #define MEM_Undefined 0x0080 /* Value is undefined */ + #define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */ + #define MEM_TypeMask 0xc1ff /* Mask of type bits */ +@@ -19277,7 +20102,7 @@ + ** that needs to be deallocated to avoid a leak. + */ + #define VdbeMemDynamic(X) \ +- (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0) ++ (((X)->flags&(MEM_Agg|MEM_Dyn))!=0) + + /* + ** Clear any existing type flags from a Mem and replace them with f +@@ -19391,14 +20216,15 @@ + int nOp; /* Number of instructions in the program */ + #ifdef SQLITE_DEBUG + int rcApp; /* errcode set by sqlite3_result_error_code() */ ++ u32 nWrite; /* Number of write operations that have occurred */ + #endif + u16 nResColumn; /* Number of columns in one row of the result set */ + u8 errorAction; /* Recovery action to do in case of an error */ + u8 minWriteFileFormat; /* Minimum file format for writable database files */ + u8 prepFlags; /* SQLITE_PREPARE_* flags */ +- bft expired:1; /* True if the VM needs to be recompiled */ ++ bft expired:2; /* 1: recompile VM immediately 2: when convenient */ ++ bft explain:2; /* True if EXPLAIN present on SQL command */ + bft doingRerun:1; /* True if rerunning after an auto-reprepare */ +- bft explain:2; /* True if EXPLAIN present on SQL command */ + bft changeCntOn:1; /* True to update the change-counter */ + bft runOnlyOnce:1; /* Automatically expire on reset */ + bft usesStmtJournal:1; /* True if uses a statement journal */ +@@ -19408,6 +20234,9 @@ + yDbMask lockMask; /* Subset of btreeMask that requires a lock */ + u32 aCounter[7]; /* Counters used by sqlite3_stmt_status() */ + char *zSql; /* Text of the SQL statement that generated this */ ++#ifdef SQLITE_ENABLE_NORMALIZE ++ char *zNormSql; /* Normalization of the associated SQL statement */ ++#endif + void *pFree; /* Free this when deleting the vdbe */ + VdbeFrame *pFrame; /* Parent frame */ + VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */ +@@ -19459,9 +20288,6 @@ + void sqliteVdbePopStack(Vdbe*,int); + SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor**, int*); + SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor*); +-#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) +-SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, Op*); +-#endif + SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32); + SQLITE_PRIVATE u8 sqlite3VdbeOneByteSerialTypeLen(u8); + SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int, u32*); +@@ -19473,7 +20299,9 @@ + SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*); + SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*); + SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*); ++#ifndef SQLITE_OMIT_EXPLAIN + SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*); ++#endif + SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*); + SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *, int); + SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem*); +@@ -19492,7 +20320,10 @@ + SQLITE_PRIVATE void sqlite3VdbeMemInit(Mem*,sqlite3*,u16); + SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*); + SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int); +-SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem*); ++#ifdef SQLITE_DEBUG ++SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem*); ++#endif ++SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem*); + SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*); + SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8); + SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*); +@@ -19506,11 +20337,20 @@ + SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*); + SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p); + SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*); ++#endif ++#ifndef SQLITE_OMIT_EXPLAIN + SQLITE_PRIVATE const char *sqlite3OpcodeName(int); ++#endif + SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); + SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int n); + SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int); +-SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*); ++#ifdef SQLITE_DEBUG ++SQLITE_PRIVATE int sqlite3VdbeFrameIsValid(VdbeFrame*); ++#endif ++SQLITE_PRIVATE void sqlite3VdbeFrameMemDel(void*); /* Destructor on Mem */ ++SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*); /* Actually deletes the Frame */ + SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *); + #ifdef SQLITE_ENABLE_PREUPDATE_HOOK + SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int); +@@ -19526,6 +20366,14 @@ + SQLITE_PRIVATE int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *); + SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *); + ++#ifdef SQLITE_DEBUG ++SQLITE_PRIVATE void sqlite3VdbeIncrWriteCounter(Vdbe*, VdbeCursor*); ++SQLITE_PRIVATE void sqlite3VdbeAssertAbortable(Vdbe*); ++#else ++# define sqlite3VdbeIncrWriteCounter(V,C) ++# define sqlite3VdbeAssertAbortable(V) ++#endif ++ + #if !defined(SQLITE_OMIT_SHARED_CACHE) + SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe*); + #else +@@ -21600,9 +22448,12 @@ + ** Unregister a VFS so that it is no longer accessible. + */ + SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ +-#if SQLITE_THREADSAFE +- sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); ++ MUTEX_LOGIC(sqlite3_mutex *mutex;) ++#ifndef SQLITE_OMIT_AUTOINIT ++ int rc = sqlite3_initialize(); ++ if( rc ) return rc; + #endif ++ MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); ) + sqlite3_mutex_enter(mutex); + vfsUnlink(pVfs); + sqlite3_mutex_leave(mutex); +@@ -24218,7 +25069,6 @@ + + #endif /* !defined(SQLITE_MUTEX_OMIT) */ + +- + /************** End of mutex.c ***********************************************/ + /************** Begin file mutex_noop.c **************************************/ + /* +@@ -26382,7 +27232,7 @@ + ** Set the StrAccum object to an error mode. + */ + static void setStrAccumError(StrAccum *p, u8 eError){ +- assert( eError==STRACCUM_NOMEM || eError==STRACCUM_TOOBIG ); ++ assert( eError==SQLITE_NOMEM || eError==SQLITE_TOOBIG ); + p->accError = eError; + p->nAlloc = 0; + } +@@ -26416,8 +27266,8 @@ + /* + ** Render a string given by "fmt" into the StrAccum object. + */ +-SQLITE_PRIVATE void sqlite3VXPrintf( +- StrAccum *pAccum, /* Accumulate results here */ ++SQLITE_API void sqlite3_str_vappendf( ++ sqlite3_str *pAccum, /* Accumulate results here */ + const char *fmt, /* Format string */ + va_list ap /* arguments */ + ){ +@@ -26474,11 +27324,11 @@ + #else + do{ fmt++; }while( *fmt && *fmt != '%' ); + #endif +- sqlite3StrAccumAppend(pAccum, bufpt, (int)(fmt - bufpt)); ++ sqlite3_str_append(pAccum, bufpt, (int)(fmt - bufpt)); + if( *fmt==0 ) break; + } + if( (c=(*++fmt))==0 ){ +- sqlite3StrAccumAppend(pAccum, "%", 1); ++ sqlite3_str_append(pAccum, "%", 1); + break; + } + /* Find out what flags are present */ +@@ -26656,7 +27506,7 @@ + u64 n = (u64)precision + 10 + precision/3; + zOut = zExtra = sqlite3Malloc( n ); + if( zOut==0 ){ +- setStrAccumError(pAccum, STRACCUM_NOMEM); ++ setStrAccumError(pAccum, SQLITE_NOMEM); + return; + } + nOut = (int)n; +@@ -26781,7 +27631,7 @@ + bufpt = zExtra + = sqlite3Malloc( MAX(e2,0)+(i64)precision+(i64)width+15 ); + if( bufpt==0 ){ +- setStrAccumError(pAccum, STRACCUM_NOMEM); ++ setStrAccumError(pAccum, SQLITE_NOMEM); + return; + } + } +@@ -26913,11 +27763,11 @@ + if( precision>1 ){ + width -= precision-1; + if( width>1 && !flag_leftjustify ){ +- sqlite3AppendChar(pAccum, width-1, ' '); ++ sqlite3_str_appendchar(pAccum, width-1, ' '); + width = 0; + } + while( precision-- > 1 ){ +- sqlite3StrAccumAppend(pAccum, buf, length); ++ sqlite3_str_append(pAccum, buf, length); + } + } + bufpt = buf; +@@ -26934,7 +27784,12 @@ + if( bufpt==0 ){ + bufpt = ""; + }else if( xtype==etDYNSTRING ){ +- if( pAccum->nChar==0 && pAccum->mxAlloc && width==0 && precision<0 ){ ++ if( pAccum->nChar==0 ++ && pAccum->mxAlloc ++ && width==0 ++ && precision<0 ++ && pAccum->accError==0 ++ ){ + /* Special optimization for sqlite3_mprintf("%z..."): + ** Extend an existing memory allocation rather than creating + ** a new one. */ +@@ -27003,7 +27858,7 @@ + if( n>etBUFSIZE ){ + bufpt = zExtra = sqlite3Malloc( n ); + if( bufpt==0 ){ +- setStrAccumError(pAccum, STRACCUM_NOMEM); ++ setStrAccumError(pAccum, SQLITE_NOMEM); + return; + } + }else{ +@@ -27027,7 +27882,7 @@ + pToken = va_arg(ap, Token*); + assert( bArgList==0 ); + if( pToken && pToken->n ){ +- sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n); ++ sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n); + } + length = width = 0; + break; +@@ -27043,10 +27898,10 @@ + assert( bArgList==0 ); + assert( k>=0 && k<pSrc->nSrc ); + if( pItem->zDatabase ){ +- sqlite3StrAccumAppendAll(pAccum, pItem->zDatabase); +- sqlite3StrAccumAppend(pAccum, ".", 1); ++ sqlite3_str_appendall(pAccum, pItem->zDatabase); ++ sqlite3_str_append(pAccum, ".", 1); + } +- sqlite3StrAccumAppendAll(pAccum, pItem->zName); ++ sqlite3_str_appendall(pAccum, pItem->zName); + length = width = 0; + break; + } +@@ -27065,11 +27920,11 @@ + */ + width -= length; + if( width>0 ){ +- if( !flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); +- sqlite3StrAccumAppend(pAccum, bufpt, length); +- if( flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); ++ if( !flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' '); ++ sqlite3_str_append(pAccum, bufpt, length); ++ if( flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' '); + }else{ +- sqlite3StrAccumAppend(pAccum, bufpt, length); ++ sqlite3_str_append(pAccum, bufpt, length); + } + + if( zExtra ){ +@@ -27090,13 +27945,13 @@ + char *zNew; + assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */ + if( p->accError ){ +- testcase(p->accError==STRACCUM_TOOBIG); +- testcase(p->accError==STRACCUM_NOMEM); ++ testcase(p->accError==SQLITE_TOOBIG); ++ testcase(p->accError==SQLITE_NOMEM); + return 0; + } + if( p->mxAlloc==0 ){ + N = p->nAlloc - p->nChar - 1; +- setStrAccumError(p, STRACCUM_TOOBIG); ++ setStrAccumError(p, SQLITE_TOOBIG); + return N; + }else{ + char *zOld = isMalloced(p) ? p->zText : 0; +@@ -27108,8 +27963,8 @@ + szNew += p->nChar; + } + if( szNew > p->mxAlloc ){ +- sqlite3StrAccumReset(p); +- setStrAccumError(p, STRACCUM_TOOBIG); ++ sqlite3_str_reset(p); ++ setStrAccumError(p, SQLITE_TOOBIG); + return 0; + }else{ + p->nAlloc = (int)szNew; +@@ -27126,8 +27981,8 @@ + p->nAlloc = sqlite3DbMallocSize(p->db, zNew); + p->printfFlags |= SQLITE_PRINTF_MALLOCED; + }else{ +- sqlite3StrAccumReset(p); +- setStrAccumError(p, STRACCUM_NOMEM); ++ sqlite3_str_reset(p); ++ setStrAccumError(p, SQLITE_NOMEM); + return 0; + } + } +@@ -27137,7 +27992,7 @@ + /* + ** Append N copies of character c to the given string buffer. + */ +-SQLITE_PRIVATE void sqlite3AppendChar(StrAccum *p, int N, char c){ ++SQLITE_API void sqlite3_str_appendchar(sqlite3_str *p, int N, char c){ + testcase( p->nChar + (i64)N > 0x7fffffff ); + if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){ + return; +@@ -27149,9 +28004,9 @@ + ** The StrAccum "p" is not large enough to accept N new bytes of z[]. + ** So enlarge if first, then do the append. + ** +-** This is a helper routine to sqlite3StrAccumAppend() that does special-case ++** This is a helper routine to sqlite3_str_append() that does special-case + ** work (enlarging the buffer) using tail recursion, so that the +-** sqlite3StrAccumAppend() routine can use fast calling semantics. ++** sqlite3_str_append() routine can use fast calling semantics. + */ + static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){ + N = sqlite3StrAccumEnlarge(p, N); +@@ -27165,7 +28020,7 @@ + ** Append N bytes of text from z to the StrAccum object. Increase the + ** size of the memory allocation for StrAccum if necessary. + */ +-SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ ++SQLITE_API void sqlite3_str_append(sqlite3_str *p, const char *z, int N){ + assert( z!=0 || N==0 ); + assert( p->zText!=0 || p->nChar==0 || p->accError ); + assert( N>=0 ); +@@ -27182,8 +28037,8 @@ + /* + ** Append the complete text of zero-terminated string z[] to the p string. + */ +-SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){ +- sqlite3StrAccumAppend(p, z, sqlite3Strlen30(z)); ++SQLITE_API void sqlite3_str_appendall(sqlite3_str *p, const char *z){ ++ sqlite3_str_append(p, z, sqlite3Strlen30(z)); + } + + +@@ -27200,7 +28055,7 @@ + memcpy(zText, p->zText, p->nChar+1); + p->printfFlags |= SQLITE_PRINTF_MALLOCED; + }else{ +- setStrAccumError(p, STRACCUM_NOMEM); ++ setStrAccumError(p, SQLITE_NOMEM); + } + p->zText = zText; + return zText; +@@ -27216,13 +28071,55 @@ + } + + /* ++** This singleton is an sqlite3_str object that is returned if ++** sqlite3_malloc() fails to provide space for a real one. This ++** sqlite3_str object accepts no new text and always returns ++** an SQLITE_NOMEM error. ++*/ ++static sqlite3_str sqlite3OomStr = { ++ 0, 0, 0, 0, 0, SQLITE_NOMEM, 0 ++}; ++ ++/* Finalize a string created using sqlite3_str_new(). ++*/ ++SQLITE_API char *sqlite3_str_finish(sqlite3_str *p){ ++ char *z; ++ if( p!=0 && p!=&sqlite3OomStr ){ ++ z = sqlite3StrAccumFinish(p); ++ sqlite3_free(p); ++ }else{ ++ z = 0; ++ } ++ return z; ++} ++ ++/* Return any error code associated with p */ ++SQLITE_API int sqlite3_str_errcode(sqlite3_str *p){ ++ return p ? p->accError : SQLITE_NOMEM; ++} ++ ++/* Return the current length of p in bytes */ ++SQLITE_API int sqlite3_str_length(sqlite3_str *p){ ++ return p ? p->nChar : 0; ++} ++ ++/* Return the current value for p */ ++SQLITE_API char *sqlite3_str_value(sqlite3_str *p){ ++ if( p==0 || p->nChar==0 ) return 0; ++ p->zText[p->nChar] = 0; ++ return p->zText; ++} ++ ++/* + ** Reset an StrAccum string. Reclaim all malloced memory. + */ +-SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum *p){ ++SQLITE_API void sqlite3_str_reset(StrAccum *p){ + if( isMalloced(p) ){ + sqlite3DbFree(p->db, p->zText); + p->printfFlags &= ~SQLITE_PRINTF_MALLOCED; + } ++ p->nAlloc = 0; ++ p->nChar = 0; + p->zText = 0; + } + +@@ -27250,6 +28147,18 @@ + p->printfFlags = 0; + } + ++/* Allocate and initialize a new dynamic string object */ ++SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3 *db){ ++ sqlite3_str *p = sqlite3_malloc64(sizeof(*p)); ++ if( p ){ ++ sqlite3StrAccumInit(p, 0, 0, 0, ++ db ? db->aLimit[SQLITE_LIMIT_LENGTH] : SQLITE_MAX_LENGTH); ++ }else{ ++ p = &sqlite3OomStr; ++ } ++ return p; ++} ++ + /* + ** Print into memory obtained from sqliteMalloc(). Use the internal + ** %-conversion extensions. +@@ -27262,9 +28171,9 @@ + sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase), + db->aLimit[SQLITE_LIMIT_LENGTH]); + acc.printfFlags = SQLITE_PRINTF_INTERNAL; +- sqlite3VXPrintf(&acc, zFormat, ap); ++ sqlite3_str_vappendf(&acc, zFormat, ap); + z = sqlite3StrAccumFinish(&acc); +- if( acc.accError==STRACCUM_NOMEM ){ ++ if( acc.accError==SQLITE_NOMEM ){ + sqlite3OomFault(db); + } + return z; +@@ -27302,7 +28211,7 @@ + if( sqlite3_initialize() ) return 0; + #endif + sqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); +- sqlite3VXPrintf(&acc, zFormat, ap); ++ sqlite3_str_vappendf(&acc, zFormat, ap); + z = sqlite3StrAccumFinish(&acc); + return z; + } +@@ -27347,7 +28256,7 @@ + } + #endif + sqlite3StrAccumInit(&acc, 0, zBuf, n, 0); +- sqlite3VXPrintf(&acc, zFormat, ap); ++ sqlite3_str_vappendf(&acc, zFormat, ap); + zBuf[acc.nChar] = 0; + return zBuf; + } +@@ -27369,7 +28278,7 @@ + ** allocate memory because it might be called while the memory allocator + ** mutex is held. + ** +-** sqlite3VXPrintf() might ask for *temporary* memory allocations for ++** sqlite3_str_vappendf() might ask for *temporary* memory allocations for + ** certain format characters (%q) or for very large precisions or widths. + ** Care must be taken that any sqlite3_log() calls that occur while the + ** memory mutex is held do not use these mechanisms. +@@ -27379,7 +28288,7 @@ + char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */ + + sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0); +- sqlite3VXPrintf(&acc, zFormat, ap); ++ sqlite3_str_vappendf(&acc, zFormat, ap); + sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode, + sqlite3StrAccumFinish(&acc)); + } +@@ -27408,7 +28317,7 @@ + char zBuf[500]; + sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); + va_start(ap,zFormat); +- sqlite3VXPrintf(&acc, zFormat, ap); ++ sqlite3_str_vappendf(&acc, zFormat, ap); + va_end(ap); + sqlite3StrAccumFinish(&acc); + #ifdef SQLITE_OS_TRACE_PROC +@@ -27425,13 +28334,13 @@ + + + /* +-** variable-argument wrapper around sqlite3VXPrintf(). The bFlags argument ++** variable-argument wrapper around sqlite3_str_vappendf(). The bFlags argument + ** can contain the bit SQLITE_PRINTF_INTERNAL enable internal formats. + */ +-SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){ ++SQLITE_API void sqlite3_str_appendf(StrAccum *p, const char *zFormat, ...){ + va_list ap; + va_start(ap,zFormat); +- sqlite3VXPrintf(p, zFormat, ap); ++ sqlite3_str_vappendf(p, zFormat, ap); + va_end(ap); + } + +@@ -27497,15 +28406,17 @@ + sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); + if( p ){ + for(i=0; i<p->iLevel && i<sizeof(p->bLine)-1; i++){ +- sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4); ++ sqlite3_str_append(&acc, p->bLine[i] ? "| " : " ", 4); + } +- sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4); ++ sqlite3_str_append(&acc, p->bLine[i] ? "|-- " : "'-- ", 4); + } +- va_start(ap, zFormat); +- sqlite3VXPrintf(&acc, zFormat, ap); +- va_end(ap); +- assert( acc.nChar>0 ); +- if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1); ++ if( zFormat!=0 ){ ++ va_start(ap, zFormat); ++ sqlite3_str_vappendf(&acc, zFormat, ap); ++ va_end(ap); ++ assert( acc.nChar>0 ); ++ sqlite3_str_append(&acc, "\n", 1); ++ } + sqlite3StrAccumFinish(&acc); + fprintf(stdout,"%s", zBuf); + fflush(stdout); +@@ -27538,17 +28449,17 @@ + char zLine[1000]; + const struct Cte *pCte = &pWith->a[i]; + sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); +- sqlite3XPrintf(&x, "%s", pCte->zName); ++ sqlite3_str_appendf(&x, "%s", pCte->zName); + if( pCte->pCols && pCte->pCols->nExpr>0 ){ + char cSep = '('; + int j; + for(j=0; j<pCte->pCols->nExpr; j++){ +- sqlite3XPrintf(&x, "%c%s", cSep, pCte->pCols->a[j].zName); ++ sqlite3_str_appendf(&x, "%c%s", cSep, pCte->pCols->a[j].zName); + cSep = ','; + } +- sqlite3XPrintf(&x, ")"); ++ sqlite3_str_appendf(&x, ")"); + } +- sqlite3XPrintf(&x, " AS"); ++ sqlite3_str_appendf(&x, " AS"); + sqlite3StrAccumFinish(&x); + sqlite3TreeViewItem(pView, zLine, i<pWith->nCte-1); + sqlite3TreeViewSelect(pView, pCte->pSelect, 0); +@@ -27558,6 +28469,42 @@ + } + } + ++/* ++** Generate a human-readable description of a SrcList object. ++*/ ++SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){ ++ int i; ++ for(i=0; i<pSrc->nSrc; i++){ ++ const struct SrcList_item *pItem = &pSrc->a[i]; ++ StrAccum x; ++ char zLine[100]; ++ sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); ++ sqlite3_str_appendf(&x, "{%d,*}", pItem->iCursor); ++ if( pItem->zDatabase ){ ++ sqlite3_str_appendf(&x, " %s.%s", pItem->zDatabase, pItem->zName); ++ }else if( pItem->zName ){ ++ sqlite3_str_appendf(&x, " %s", pItem->zName); ++ } ++ if( pItem->pTab ){ ++ sqlite3_str_appendf(&x, " tabname=%Q", pItem->pTab->zName); ++ } ++ if( pItem->zAlias ){ ++ sqlite3_str_appendf(&x, " (AS %s)", pItem->zAlias); ++ } ++ if( pItem->fg.jointype & JT_LEFT ){ ++ sqlite3_str_appendf(&x, " LEFT-JOIN"); ++ } ++ sqlite3StrAccumFinish(&x); ++ sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1); ++ if( pItem->pSelect ){ ++ sqlite3TreeViewSelect(pView, pItem->pSelect, 0); ++ } ++ if( pItem->fg.isTabFunc ){ ++ sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:"); ++ } ++ sqlite3TreeViewPop(pView); ++ } ++} + + /* + ** Generate a human-readable description of a Select object. +@@ -27576,21 +28523,13 @@ + sqlite3TreeViewPush(pView, 1); + } + do{ +-#if SELECTTRACE_ENABLED + sqlite3TreeViewLine(pView, +- "SELECT%s%s (%s/%p) selFlags=0x%x nSelectRow=%d", ++ "SELECT%s%s (%u/%p) selFlags=0x%x nSelectRow=%d", + ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""), + ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), +- p->zSelName, p, p->selFlags, ++ p->selId, p, p->selFlags, + (int)p->nSelectRow + ); +-#else +- sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x nSelectRow=%d", +- ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""), +- ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p, p->selFlags, +- (int)p->nSelectRow +- ); +-#endif + if( cnt++ ) sqlite3TreeViewPop(pView); + if( p->pPrior ){ + n = 1000; +@@ -27602,42 +28541,27 @@ + if( p->pHaving ) n++; + if( p->pOrderBy ) n++; + if( p->pLimit ) n++; ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( p->pWin ) n++; ++ if( p->pWinDefn ) n++; ++#endif + } + sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set"); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( p->pWin ){ ++ Window *pX; ++ pView = sqlite3TreeViewPush(pView, (n--)>0); ++ sqlite3TreeViewLine(pView, "window-functions"); ++ for(pX=p->pWin; pX; pX=pX->pNextWin){ ++ sqlite3TreeViewWinFunc(pView, pX, pX->pNextWin!=0); ++ } ++ sqlite3TreeViewPop(pView); ++ } ++#endif + if( p->pSrc && p->pSrc->nSrc ){ +- int i; + pView = sqlite3TreeViewPush(pView, (n--)>0); + sqlite3TreeViewLine(pView, "FROM"); +- for(i=0; i<p->pSrc->nSrc; i++){ +- struct SrcList_item *pItem = &p->pSrc->a[i]; +- StrAccum x; +- char zLine[100]; +- sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); +- sqlite3XPrintf(&x, "{%d,*}", pItem->iCursor); +- if( pItem->zDatabase ){ +- sqlite3XPrintf(&x, " %s.%s", pItem->zDatabase, pItem->zName); +- }else if( pItem->zName ){ +- sqlite3XPrintf(&x, " %s", pItem->zName); +- } +- if( pItem->pTab ){ +- sqlite3XPrintf(&x, " tabname=%Q", pItem->pTab->zName); +- } +- if( pItem->zAlias ){ +- sqlite3XPrintf(&x, " (AS %s)", pItem->zAlias); +- } +- if( pItem->fg.jointype & JT_LEFT ){ +- sqlite3XPrintf(&x, " LEFT-JOIN"); +- } +- sqlite3StrAccumFinish(&x); +- sqlite3TreeViewItem(pView, zLine, i<p->pSrc->nSrc-1); +- if( pItem->pSelect ){ +- sqlite3TreeViewSelect(pView, pItem->pSelect, 0); +- } +- if( pItem->fg.isTabFunc ){ +- sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:"); +- } +- sqlite3TreeViewPop(pView); +- } ++ sqlite3TreeViewSrcList(pView, p->pSrc); + sqlite3TreeViewPop(pView); + } + if( p->pWhere ){ +@@ -27653,6 +28577,16 @@ + sqlite3TreeViewExpr(pView, p->pHaving, 0); + sqlite3TreeViewPop(pView); + } ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( p->pWinDefn ){ ++ Window *pX; ++ sqlite3TreeViewItem(pView, "WINDOW", (n--)>0); ++ for(pX=p->pWinDefn; pX; pX=pX->pNextWin){ ++ sqlite3TreeViewWindow(pView, pX, pX->pNextWin!=0); ++ } ++ sqlite3TreeViewPop(pView); ++ } ++#endif + if( p->pOrderBy ){ + sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY"); + } +@@ -27680,7 +28614,84 @@ + sqlite3TreeViewPop(pView); + } + ++#ifndef SQLITE_OMIT_WINDOWFUNC + /* ++** Generate a description of starting or stopping bounds ++*/ ++SQLITE_PRIVATE void sqlite3TreeViewBound( ++ TreeView *pView, /* View context */ ++ u8 eBound, /* UNBOUNDED, CURRENT, PRECEDING, FOLLOWING */ ++ Expr *pExpr, /* Value for PRECEDING or FOLLOWING */ ++ u8 moreToFollow /* True if more to follow */ ++){ ++ switch( eBound ){ ++ case TK_UNBOUNDED: { ++ sqlite3TreeViewItem(pView, "UNBOUNDED", moreToFollow); ++ sqlite3TreeViewPop(pView); ++ break; ++ } ++ case TK_CURRENT: { ++ sqlite3TreeViewItem(pView, "CURRENT", moreToFollow); ++ sqlite3TreeViewPop(pView); ++ break; ++ } ++ case TK_PRECEDING: { ++ sqlite3TreeViewItem(pView, "PRECEDING", moreToFollow); ++ sqlite3TreeViewExpr(pView, pExpr, 0); ++ sqlite3TreeViewPop(pView); ++ break; ++ } ++ case TK_FOLLOWING: { ++ sqlite3TreeViewItem(pView, "FOLLOWING", moreToFollow); ++ sqlite3TreeViewExpr(pView, pExpr, 0); ++ sqlite3TreeViewPop(pView); ++ break; ++ } ++ } ++} ++#endif /* SQLITE_OMIT_WINDOWFUNC */ ++ ++#ifndef SQLITE_OMIT_WINDOWFUNC ++/* ++** Generate a human-readable explanation for a Window object ++*/ ++SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u8 more){ ++ pView = sqlite3TreeViewPush(pView, more); ++ if( pWin->zName ){ ++ sqlite3TreeViewLine(pView, "OVER %s", pWin->zName); ++ }else{ ++ sqlite3TreeViewLine(pView, "OVER"); ++ } ++ if( pWin->pPartition ){ ++ sqlite3TreeViewExprList(pView, pWin->pPartition, 1, "PARTITION-BY"); ++ } ++ if( pWin->pOrderBy ){ ++ sqlite3TreeViewExprList(pView, pWin->pOrderBy, 1, "ORDER-BY"); ++ } ++ if( pWin->eType ){ ++ sqlite3TreeViewItem(pView, pWin->eType==TK_RANGE ? "RANGE" : "ROWS", 0); ++ sqlite3TreeViewBound(pView, pWin->eStart, pWin->pStart, 1); ++ sqlite3TreeViewBound(pView, pWin->eEnd, pWin->pEnd, 0); ++ sqlite3TreeViewPop(pView); ++ } ++ sqlite3TreeViewPop(pView); ++} ++#endif /* SQLITE_OMIT_WINDOWFUNC */ ++ ++#ifndef SQLITE_OMIT_WINDOWFUNC ++/* ++** Generate a human-readable explanation for a Window Function object ++*/ ++SQLITE_PRIVATE void sqlite3TreeViewWinFunc(TreeView *pView, const Window *pWin, u8 more){ ++ pView = sqlite3TreeViewPush(pView, more); ++ sqlite3TreeViewLine(pView, "WINFUNC %s(%d)", ++ pWin->pFunc->zName, pWin->pFunc->nArg); ++ sqlite3TreeViewWindow(pView, pWin, 0); ++ sqlite3TreeViewPop(pView); ++} ++#endif /* SQLITE_OMIT_WINDOWFUNC */ ++ ++/* + ** Generate a human-readable explanation of an expression tree. + */ + SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ +@@ -27717,6 +28728,9 @@ + sqlite3TreeViewLine(pView, "{%d:%d}%s", + pExpr->iTable, pExpr->iColumn, zFlgs); + } ++ if( ExprHasProperty(pExpr, EP_FixedCol) ){ ++ sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); ++ } + break; + } + case TK_INTEGER: { +@@ -27830,10 +28844,17 @@ + case TK_AGG_FUNCTION: + case TK_FUNCTION: { + ExprList *pFarg; /* List of function arguments */ ++ Window *pWin; + if( ExprHasProperty(pExpr, EP_TokenOnly) ){ + pFarg = 0; ++ pWin = 0; + }else{ + pFarg = pExpr->x.pList; ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ pWin = pExpr->y.pWin; ++#else ++ pWin = 0; ++#endif + } + if( pExpr->op==TK_AGG_FUNCTION ){ + sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q", +@@ -27842,8 +28863,13 @@ + sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken); + } + if( pFarg ){ +- sqlite3TreeViewExprList(pView, pFarg, 0, 0); ++ sqlite3TreeViewExprList(pView, pFarg, pWin!=0, 0); + } ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( pWin ){ ++ sqlite3TreeViewWindow(pView, pWin, 0); ++ } ++#endif + break; + } + #ifndef SQLITE_OMIT_SUBQUERY +@@ -27975,16 +29001,21 @@ + for(i=0; i<pList->nExpr; i++){ + int j = pList->a[i].u.x.iOrderByCol; + char *zName = pList->a[i].zName; ++ int moreToFollow = i<pList->nExpr - 1; + if( j || zName ){ +- sqlite3TreeViewPush(pView, 0); ++ sqlite3TreeViewPush(pView, moreToFollow); ++ moreToFollow = 0; ++ sqlite3TreeViewLine(pView, 0); ++ if( zName ){ ++ fprintf(stdout, "AS %s ", zName); ++ } ++ if( j ){ ++ fprintf(stdout, "iOrderByCol=%d", j); ++ } ++ fprintf(stdout, "\n"); ++ fflush(stdout); + } +- if( zName ){ +- sqlite3TreeViewLine(pView, "AS %s", zName); +- } +- if( j ){ +- sqlite3TreeViewLine(pView, "iOrderByCol=%d", j); +- } +- sqlite3TreeViewExpr(pView, pList->a[i].pExpr, i<pList->nExpr-1); ++ sqlite3TreeViewExpr(pView, pList->a[i].pExpr, moreToFollow); + if( j || zName ){ + sqlite3TreeViewPop(pView); + } +@@ -30648,6 +31679,20 @@ + } + return h; + } ++#ifdef SQLITE_ENABLE_NORMALIZE ++static unsigned int strHashN(const char *z, int n){ ++ unsigned int h = 0; ++ int i; ++ for(i=0; i<n; i++){ ++ /* Knuth multiplicative hashing. (Sorting & Searching, p. 510). ++ ** 0x9e3779b1 is 2654435761 which is the closest prime number to ++ ** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2. */ ++ h += sqlite3UpperToLower[z[i]]; ++ h *= 0x9e3779b1; ++ } ++ return h; ++} ++#endif /* SQLITE_ENABLE_NORMALIZE */ + + + /* Link pNew element into the hash table pH. If pEntry!=0 then also +@@ -30759,7 +31804,41 @@ + } + return &nullElement; + } ++#ifdef SQLITE_ENABLE_NORMALIZE ++static HashElem *findElementWithHashN( ++ const Hash *pH, /* The pH to be searched */ ++ const char *pKey, /* The key we are searching for */ ++ int nKey, /* Number of key bytes to use */ ++ unsigned int *pHash /* Write the hash value here */ ++){ ++ HashElem *elem; /* Used to loop thru the element list */ ++ int count; /* Number of elements left to test */ ++ unsigned int h; /* The computed hash */ ++ static HashElem nullElement = { 0, 0, 0, 0 }; + ++ if( pH->ht ){ /*OPTIMIZATION-IF-TRUE*/ ++ struct _ht *pEntry; ++ h = strHashN(pKey, nKey) % pH->htsize; ++ pEntry = &pH->ht[h]; ++ elem = pEntry->chain; ++ count = pEntry->count; ++ }else{ ++ h = 0; ++ elem = pH->first; ++ count = pH->count; ++ } ++ if( pHash ) *pHash = h; ++ while( count-- ){ ++ assert( elem!=0 ); ++ if( sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){ ++ return elem; ++ } ++ elem = elem->next; ++ } ++ return &nullElement; ++} ++#endif /* SQLITE_ENABLE_NORMALIZE */ ++ + /* Remove a single entry from the hash table given a pointer to that + ** element and a hash on the element's key. + */ +@@ -30803,6 +31882,14 @@ + assert( pKey!=0 ); + return findElementWithHash(pH, pKey, 0)->data; + } ++#ifdef SQLITE_ENABLE_NORMALIZE ++SQLITE_PRIVATE void *sqlite3HashFindN(const Hash *pH, const char *pKey, int nKey){ ++ assert( pH!=0 ); ++ assert( pKey!=0 ); ++ assert( nKey>=0 ); ++ return findElementWithHashN(pH, pKey, nKey, 0)->data; ++} ++#endif /* SQLITE_ENABLE_NORMALIZE */ + + /* Insert an element into the hash table pH. The key is pKey + ** and the data is "data". +@@ -30870,52 +31957,52 @@ + /* 1 */ "AutoCommit" OpHelp(""), + /* 2 */ "Transaction" OpHelp(""), + /* 3 */ "SorterNext" OpHelp(""), +- /* 4 */ "PrevIfOpen" OpHelp(""), +- /* 5 */ "NextIfOpen" OpHelp(""), +- /* 6 */ "Prev" OpHelp(""), +- /* 7 */ "Next" OpHelp(""), +- /* 8 */ "Checkpoint" OpHelp(""), +- /* 9 */ "JournalMode" OpHelp(""), +- /* 10 */ "Vacuum" OpHelp(""), +- /* 11 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"), +- /* 12 */ "VUpdate" OpHelp("data=r[P3@P2]"), +- /* 13 */ "Goto" OpHelp(""), +- /* 14 */ "Gosub" OpHelp(""), +- /* 15 */ "InitCoroutine" OpHelp(""), +- /* 16 */ "Yield" OpHelp(""), +- /* 17 */ "MustBeInt" OpHelp(""), +- /* 18 */ "Jump" OpHelp(""), ++ /* 4 */ "Prev" OpHelp(""), ++ /* 5 */ "Next" OpHelp(""), ++ /* 6 */ "Checkpoint" OpHelp(""), ++ /* 7 */ "JournalMode" OpHelp(""), ++ /* 8 */ "Vacuum" OpHelp(""), ++ /* 9 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"), ++ /* 10 */ "VUpdate" OpHelp("data=r[P3@P2]"), ++ /* 11 */ "Goto" OpHelp(""), ++ /* 12 */ "Gosub" OpHelp(""), ++ /* 13 */ "InitCoroutine" OpHelp(""), ++ /* 14 */ "Yield" OpHelp(""), ++ /* 15 */ "MustBeInt" OpHelp(""), ++ /* 16 */ "Jump" OpHelp(""), ++ /* 17 */ "Once" OpHelp(""), ++ /* 18 */ "If" OpHelp(""), + /* 19 */ "Not" OpHelp("r[P2]= !r[P1]"), +- /* 20 */ "Once" OpHelp(""), +- /* 21 */ "If" OpHelp(""), +- /* 22 */ "IfNot" OpHelp(""), +- /* 23 */ "IfNullRow" OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"), +- /* 24 */ "SeekLT" OpHelp("key=r[P3@P4]"), +- /* 25 */ "SeekLE" OpHelp("key=r[P3@P4]"), +- /* 26 */ "SeekGE" OpHelp("key=r[P3@P4]"), +- /* 27 */ "SeekGT" OpHelp("key=r[P3@P4]"), +- /* 28 */ "NoConflict" OpHelp("key=r[P3@P4]"), +- /* 29 */ "NotFound" OpHelp("key=r[P3@P4]"), +- /* 30 */ "Found" OpHelp("key=r[P3@P4]"), +- /* 31 */ "SeekRowid" OpHelp("intkey=r[P3]"), +- /* 32 */ "NotExists" OpHelp("intkey=r[P3]"), +- /* 33 */ "Last" OpHelp(""), +- /* 34 */ "IfSmaller" OpHelp(""), +- /* 35 */ "SorterSort" OpHelp(""), +- /* 36 */ "Sort" OpHelp(""), +- /* 37 */ "Rewind" OpHelp(""), +- /* 38 */ "IdxLE" OpHelp("key=r[P3@P4]"), +- /* 39 */ "IdxGT" OpHelp("key=r[P3@P4]"), +- /* 40 */ "IdxLT" OpHelp("key=r[P3@P4]"), +- /* 41 */ "IdxGE" OpHelp("key=r[P3@P4]"), +- /* 42 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), ++ /* 20 */ "IfNot" OpHelp(""), ++ /* 21 */ "IfNullRow" OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"), ++ /* 22 */ "SeekLT" OpHelp("key=r[P3@P4]"), ++ /* 23 */ "SeekLE" OpHelp("key=r[P3@P4]"), ++ /* 24 */ "SeekGE" OpHelp("key=r[P3@P4]"), ++ /* 25 */ "SeekGT" OpHelp("key=r[P3@P4]"), ++ /* 26 */ "IfNoHope" OpHelp("key=r[P3@P4]"), ++ /* 27 */ "NoConflict" OpHelp("key=r[P3@P4]"), ++ /* 28 */ "NotFound" OpHelp("key=r[P3@P4]"), ++ /* 29 */ "Found" OpHelp("key=r[P3@P4]"), ++ /* 30 */ "SeekRowid" OpHelp("intkey=r[P3]"), ++ /* 31 */ "NotExists" OpHelp("intkey=r[P3]"), ++ /* 32 */ "Last" OpHelp(""), ++ /* 33 */ "IfSmaller" OpHelp(""), ++ /* 34 */ "SorterSort" OpHelp(""), ++ /* 35 */ "Sort" OpHelp(""), ++ /* 36 */ "Rewind" OpHelp(""), ++ /* 37 */ "IdxLE" OpHelp("key=r[P3@P4]"), ++ /* 38 */ "IdxGT" OpHelp("key=r[P3@P4]"), ++ /* 39 */ "IdxLT" OpHelp("key=r[P3@P4]"), ++ /* 40 */ "IdxGE" OpHelp("key=r[P3@P4]"), ++ /* 41 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), ++ /* 42 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), + /* 43 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"), + /* 44 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"), +- /* 45 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), +- /* 46 */ "Program" OpHelp(""), +- /* 47 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), +- /* 48 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), +- /* 49 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"), ++ /* 45 */ "Program" OpHelp(""), ++ /* 46 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), ++ /* 47 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), ++ /* 48 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"), ++ /* 49 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), + /* 50 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"), + /* 51 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"), + /* 52 */ "Ne" OpHelp("IF r[P3]!=r[P1]"), +@@ -30925,118 +32012,121 @@ + /* 56 */ "Lt" OpHelp("IF r[P3]<r[P1]"), + /* 57 */ "Ge" OpHelp("IF r[P3]>=r[P1]"), + /* 58 */ "ElseNotEq" OpHelp(""), +- /* 59 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), +- /* 60 */ "IncrVacuum" OpHelp(""), +- /* 61 */ "VNext" OpHelp(""), +- /* 62 */ "Init" OpHelp("Start at P2"), +- /* 63 */ "Return" OpHelp(""), +- /* 64 */ "EndCoroutine" OpHelp(""), +- /* 65 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), +- /* 66 */ "Halt" OpHelp(""), +- /* 67 */ "Integer" OpHelp("r[P2]=P1"), +- /* 68 */ "Int64" OpHelp("r[P2]=P4"), +- /* 69 */ "String" OpHelp("r[P2]='P4' (len=P1)"), +- /* 70 */ "Null" OpHelp("r[P2..P3]=NULL"), +- /* 71 */ "SoftNull" OpHelp("r[P1]=NULL"), +- /* 72 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), +- /* 73 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), +- /* 74 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), +- /* 75 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), +- /* 76 */ "SCopy" OpHelp("r[P2]=r[P1]"), +- /* 77 */ "IntCopy" OpHelp("r[P2]=r[P1]"), +- /* 78 */ "ResultRow" OpHelp("output=r[P1@P2]"), +- /* 79 */ "CollSeq" OpHelp(""), +- /* 80 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), +- /* 81 */ "RealAffinity" OpHelp(""), +- /* 82 */ "Cast" OpHelp("affinity(r[P1])"), +- /* 83 */ "Permutation" OpHelp(""), +- /* 84 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), +- /* 85 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), +- /* 86 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"), +- /* 87 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"), +- /* 88 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"), +- /* 89 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"), +- /* 90 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"), +- /* 91 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), +- /* 92 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), +- /* 93 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), +- /* 94 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), +- /* 95 */ "BitNot" OpHelp("r[P1]= ~r[P1]"), +- /* 96 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"), +- /* 97 */ "String8" OpHelp("r[P2]='P4'"), +- /* 98 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"), +- /* 99 */ "Column" OpHelp("r[P3]=PX"), +- /* 100 */ "Affinity" OpHelp("affinity(r[P1@P2])"), +- /* 101 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), +- /* 102 */ "Count" OpHelp("r[P2]=count()"), +- /* 103 */ "ReadCookie" OpHelp(""), +- /* 104 */ "SetCookie" OpHelp(""), +- /* 105 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), +- /* 106 */ "OpenRead" OpHelp("root=P2 iDb=P3"), +- /* 107 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), +- /* 108 */ "OpenDup" OpHelp(""), +- /* 109 */ "OpenAutoindex" OpHelp("nColumn=P2"), +- /* 110 */ "OpenEphemeral" OpHelp("nColumn=P2"), +- /* 111 */ "SorterOpen" OpHelp(""), +- /* 112 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), +- /* 113 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), +- /* 114 */ "Close" OpHelp(""), +- /* 115 */ "ColumnsUsed" OpHelp(""), +- /* 116 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), +- /* 117 */ "NewRowid" OpHelp("r[P2]=rowid"), +- /* 118 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), +- /* 119 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), +- /* 120 */ "Delete" OpHelp(""), +- /* 121 */ "ResetCount" OpHelp(""), +- /* 122 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), +- /* 123 */ "SorterData" OpHelp("r[P2]=data"), +- /* 124 */ "RowData" OpHelp("r[P2]=data"), +- /* 125 */ "Rowid" OpHelp("r[P2]=rowid"), +- /* 126 */ "NullRow" OpHelp(""), +- /* 127 */ "SeekEnd" OpHelp(""), +- /* 128 */ "SorterInsert" OpHelp("key=r[P2]"), +- /* 129 */ "IdxInsert" OpHelp("key=r[P2]"), +- /* 130 */ "IdxDelete" OpHelp("key=r[P2@P3]"), +- /* 131 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"), +- /* 132 */ "Real" OpHelp("r[P2]=P4"), +- /* 133 */ "IdxRowid" OpHelp("r[P2]=rowid"), +- /* 134 */ "Destroy" OpHelp(""), +- /* 135 */ "Clear" OpHelp(""), +- /* 136 */ "ResetSorter" OpHelp(""), +- /* 137 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"), +- /* 138 */ "SqlExec" OpHelp(""), +- /* 139 */ "ParseSchema" OpHelp(""), +- /* 140 */ "LoadAnalysis" OpHelp(""), +- /* 141 */ "DropTable" OpHelp(""), +- /* 142 */ "DropIndex" OpHelp(""), +- /* 143 */ "DropTrigger" OpHelp(""), +- /* 144 */ "IntegrityCk" OpHelp(""), +- /* 145 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), +- /* 146 */ "Param" OpHelp(""), +- /* 147 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), +- /* 148 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), +- /* 149 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), +- /* 150 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"), +- /* 151 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), +- /* 152 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), +- /* 153 */ "Expire" OpHelp(""), +- /* 154 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), +- /* 155 */ "VBegin" OpHelp(""), +- /* 156 */ "VCreate" OpHelp(""), +- /* 157 */ "VDestroy" OpHelp(""), +- /* 158 */ "VOpen" OpHelp(""), +- /* 159 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), +- /* 160 */ "VRename" OpHelp(""), +- /* 161 */ "Pagecount" OpHelp(""), +- /* 162 */ "MaxPgcnt" OpHelp(""), +- /* 163 */ "PureFunc0" OpHelp(""), +- /* 164 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), +- /* 165 */ "PureFunc" OpHelp(""), +- /* 166 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), +- /* 167 */ "Trace" OpHelp(""), +- /* 168 */ "CursorHint" OpHelp(""), +- /* 169 */ "Noop" OpHelp(""), +- /* 170 */ "Explain" OpHelp(""), ++ /* 59 */ "IncrVacuum" OpHelp(""), ++ /* 60 */ "VNext" OpHelp(""), ++ /* 61 */ "Init" OpHelp("Start at P2"), ++ /* 62 */ "PureFunc0" OpHelp(""), ++ /* 63 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), ++ /* 64 */ "PureFunc" OpHelp(""), ++ /* 65 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), ++ /* 66 */ "Return" OpHelp(""), ++ /* 67 */ "EndCoroutine" OpHelp(""), ++ /* 68 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), ++ /* 69 */ "Halt" OpHelp(""), ++ /* 70 */ "Integer" OpHelp("r[P2]=P1"), ++ /* 71 */ "Int64" OpHelp("r[P2]=P4"), ++ /* 72 */ "String" OpHelp("r[P2]='P4' (len=P1)"), ++ /* 73 */ "Null" OpHelp("r[P2..P3]=NULL"), ++ /* 74 */ "SoftNull" OpHelp("r[P1]=NULL"), ++ /* 75 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), ++ /* 76 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), ++ /* 77 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), ++ /* 78 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), ++ /* 79 */ "SCopy" OpHelp("r[P2]=r[P1]"), ++ /* 80 */ "IntCopy" OpHelp("r[P2]=r[P1]"), ++ /* 81 */ "ResultRow" OpHelp("output=r[P1@P2]"), ++ /* 82 */ "CollSeq" OpHelp(""), ++ /* 83 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), ++ /* 84 */ "RealAffinity" OpHelp(""), ++ /* 85 */ "Cast" OpHelp("affinity(r[P1])"), ++ /* 86 */ "Permutation" OpHelp(""), ++ /* 87 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), ++ /* 88 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"), ++ /* 89 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"), ++ /* 90 */ "Column" OpHelp("r[P3]=PX"), ++ /* 91 */ "Affinity" OpHelp("affinity(r[P1@P2])"), ++ /* 92 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), ++ /* 93 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), ++ /* 94 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"), ++ /* 95 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"), ++ /* 96 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"), ++ /* 97 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"), ++ /* 98 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"), ++ /* 99 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), ++ /* 100 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), ++ /* 101 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), ++ /* 102 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), ++ /* 103 */ "BitNot" OpHelp("r[P2]= ~r[P1]"), ++ /* 104 */ "Count" OpHelp("r[P2]=count()"), ++ /* 105 */ "ReadCookie" OpHelp(""), ++ /* 106 */ "String8" OpHelp("r[P2]='P4'"), ++ /* 107 */ "SetCookie" OpHelp(""), ++ /* 108 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), ++ /* 109 */ "OpenRead" OpHelp("root=P2 iDb=P3"), ++ /* 110 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), ++ /* 111 */ "OpenDup" OpHelp(""), ++ /* 112 */ "OpenAutoindex" OpHelp("nColumn=P2"), ++ /* 113 */ "OpenEphemeral" OpHelp("nColumn=P2"), ++ /* 114 */ "SorterOpen" OpHelp(""), ++ /* 115 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), ++ /* 116 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), ++ /* 117 */ "Close" OpHelp(""), ++ /* 118 */ "ColumnsUsed" OpHelp(""), ++ /* 119 */ "SeekHit" OpHelp("seekHit=P2"), ++ /* 120 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), ++ /* 121 */ "NewRowid" OpHelp("r[P2]=rowid"), ++ /* 122 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), ++ /* 123 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), ++ /* 124 */ "Delete" OpHelp(""), ++ /* 125 */ "ResetCount" OpHelp(""), ++ /* 126 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), ++ /* 127 */ "SorterData" OpHelp("r[P2]=data"), ++ /* 128 */ "RowData" OpHelp("r[P2]=data"), ++ /* 129 */ "Rowid" OpHelp("r[P2]=rowid"), ++ /* 130 */ "NullRow" OpHelp(""), ++ /* 131 */ "SeekEnd" OpHelp(""), ++ /* 132 */ "SorterInsert" OpHelp("key=r[P2]"), ++ /* 133 */ "IdxInsert" OpHelp("key=r[P2]"), ++ /* 134 */ "IdxDelete" OpHelp("key=r[P2@P3]"), ++ /* 135 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"), ++ /* 136 */ "IdxRowid" OpHelp("r[P2]=rowid"), ++ /* 137 */ "Destroy" OpHelp(""), ++ /* 138 */ "Clear" OpHelp(""), ++ /* 139 */ "ResetSorter" OpHelp(""), ++ /* 140 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"), ++ /* 141 */ "Real" OpHelp("r[P2]=P4"), ++ /* 142 */ "SqlExec" OpHelp(""), ++ /* 143 */ "ParseSchema" OpHelp(""), ++ /* 144 */ "LoadAnalysis" OpHelp(""), ++ /* 145 */ "DropTable" OpHelp(""), ++ /* 146 */ "DropIndex" OpHelp(""), ++ /* 147 */ "DropTrigger" OpHelp(""), ++ /* 148 */ "IntegrityCk" OpHelp(""), ++ /* 149 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), ++ /* 150 */ "Param" OpHelp(""), ++ /* 151 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), ++ /* 152 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), ++ /* 153 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), ++ /* 154 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"), ++ /* 155 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), ++ /* 156 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"), ++ /* 157 */ "AggValue" OpHelp("r[P3]=value N=P2"), ++ /* 158 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), ++ /* 159 */ "Expire" OpHelp(""), ++ /* 160 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), ++ /* 161 */ "VBegin" OpHelp(""), ++ /* 162 */ "VCreate" OpHelp(""), ++ /* 163 */ "VDestroy" OpHelp(""), ++ /* 164 */ "VOpen" OpHelp(""), ++ /* 165 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), ++ /* 166 */ "VRename" OpHelp(""), ++ /* 167 */ "Pagecount" OpHelp(""), ++ /* 168 */ "MaxPgcnt" OpHelp(""), ++ /* 169 */ "Trace" OpHelp(""), ++ /* 170 */ "CursorHint" OpHelp(""), ++ /* 171 */ "Noop" OpHelp(""), ++ /* 172 */ "Explain" OpHelp(""), ++ /* 173 */ "Abortable" OpHelp(""), + }; + return azName[i]; + } +@@ -31182,12 +32272,10 @@ + #define SQLITE_FSFLAGS_IS_MSDOS 0x1 + + /* +-** If we are to be thread-safe, include the pthreads header and define +-** the SQLITE_UNIX_THREADS macro. ++** If we are to be thread-safe, include the pthreads header. + */ + #if SQLITE_THREADSAFE + /* # include <pthread.h> */ +-# define SQLITE_UNIX_THREADS 1 + #endif + + /* +@@ -31765,7 +32853,11 @@ + #define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent) + + #if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) ++# ifdef __ANDROID__ ++ { "ioctl", (sqlite3_syscall_ptr)(int(*)(int, int, ...))ioctl, 0 }, ++# else + { "ioctl", (sqlite3_syscall_ptr)ioctl, 0 }, ++# endif + #else + { "ioctl", (sqlite3_syscall_ptr)0, 0 }, + #endif +@@ -31946,12 +33038,25 @@ + ** unixEnterMutex() + ** assert( unixMutexHeld() ); + ** unixEnterLeave() ++** ++** To prevent deadlock, the global unixBigLock must must be acquired ++** before the unixInodeInfo.pLockMutex mutex, if both are held. It is ++** OK to get the pLockMutex without holding unixBigLock first, but if ++** that happens, the unixBigLock mutex must not be acquired until after ++** pLockMutex is released. ++** ++** OK: enter(unixBigLock), enter(pLockInfo) ++** OK: enter(unixBigLock) ++** OK: enter(pLockInfo) ++** ERROR: enter(pLockInfo), enter(unixBigLock) + */ + static sqlite3_mutex *unixBigLock = 0; + static void unixEnterMutex(void){ ++ assert( sqlite3_mutex_notheld(unixBigLock) ); /* Not a recursive mutex */ + sqlite3_mutex_enter(unixBigLock); + } + static void unixLeaveMutex(void){ ++ assert( sqlite3_mutex_held(unixBigLock) ); + sqlite3_mutex_leave(unixBigLock); + } + #ifdef SQLITE_DEBUG +@@ -32346,22 +33451,39 @@ + + /* + ** An instance of the following structure is allocated for each open +-** inode. Or, on LinuxThreads, there is one of these structures for +-** each inode opened by each thread. ++** inode. + ** + ** A single inode can have multiple file descriptors, so each unixFile + ** structure contains a pointer to an instance of this object and this + ** object keeps a count of the number of unixFile pointing to it. ++** ++** Mutex rules: ++** ++** (1) Only the pLockMutex mutex must be held in order to read or write ++** any of the locking fields: ++** nShared, nLock, eFileLock, bProcessLock, pUnused ++** ++** (2) When nRef>0, then the following fields are unchanging and can ++** be read (but not written) without holding any mutex: ++** fileId, pLockMutex ++** ++** (3) With the exceptions above, all the fields may only be read ++** or written while holding the global unixBigLock mutex. ++** ++** Deadlock prevention: The global unixBigLock mutex may not ++** be acquired while holding the pLockMutex mutex. If both unixBigLock ++** and pLockMutex are needed, then unixBigLock must be acquired first. + */ + struct unixInodeInfo { + struct unixFileId fileId; /* The lookup key */ +- int nShared; /* Number of SHARED locks held */ +- unsigned char eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ +- unsigned char bProcessLock; /* An exclusive process lock is held */ ++ sqlite3_mutex *pLockMutex; /* Hold this mutex for... */ ++ int nShared; /* Number of SHARED locks held */ ++ int nLock; /* Number of outstanding file locks */ ++ unsigned char eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ ++ unsigned char bProcessLock; /* An exclusive process lock is held */ ++ UnixUnusedFd *pUnused; /* Unused file descriptors to close */ + int nRef; /* Number of pointers to this structure */ + unixShmNode *pShmNode; /* Shared memory associated with this inode */ +- int nLock; /* Number of outstanding file locks */ +- UnixUnusedFd *pUnused; /* Unused file descriptors to close */ + unixInodeInfo *pNext; /* List of all unixInodeInfo objects */ + unixInodeInfo *pPrev; /* .... doubly linked */ + #if SQLITE_ENABLE_LOCKING_STYLE +@@ -32375,11 +33497,28 @@ + + /* + ** A lists of all unixInodeInfo objects. ++** ++** Must hold unixBigLock in order to read or write this variable. + */ + static unixInodeInfo *inodeList = 0; /* All unixInodeInfo objects */ +-static unsigned int nUnusedFd = 0; /* Total unused file descriptors */ + ++#ifdef SQLITE_DEBUG + /* ++** True if the inode mutex (on the unixFile.pFileMutex field) is held, or not. ++** This routine is used only within assert() to help verify correct mutex ++** usage. ++*/ ++int unixFileMutexHeld(unixFile *pFile){ ++ assert( pFile->pInode ); ++ return sqlite3_mutex_held(pFile->pInode->pLockMutex); ++} ++int unixFileMutexNotheld(unixFile *pFile){ ++ assert( pFile->pInode ); ++ return sqlite3_mutex_notheld(pFile->pInode->pLockMutex); ++} ++#endif ++ ++/* + ** + ** This function - unixLogErrorAtLine(), is only ever called via the macro + ** unixLogError(). +@@ -32483,11 +33622,11 @@ + unixInodeInfo *pInode = pFile->pInode; + UnixUnusedFd *p; + UnixUnusedFd *pNext; ++ assert( unixFileMutexHeld(pFile) ); + for(p=pInode->pUnused; p; p=pNext){ + pNext = p->pNext; + robust_close(pFile, p->fd, __LINE__); + sqlite3_free(p); +- nUnusedFd--; + } + pInode->pUnused = 0; + } +@@ -32495,17 +33634,20 @@ + /* + ** Release a unixInodeInfo structure previously allocated by findInodeInfo(). + ** +-** The mutex entered using the unixEnterMutex() function must be held +-** when this function is called. ++** The global mutex must be held when this routine is called, but the mutex ++** on the inode being deleted must NOT be held. + */ + static void releaseInodeInfo(unixFile *pFile){ + unixInodeInfo *pInode = pFile->pInode; + assert( unixMutexHeld() ); ++ assert( unixFileMutexNotheld(pFile) ); + if( ALWAYS(pInode) ){ + pInode->nRef--; + if( pInode->nRef==0 ){ + assert( pInode->pShmNode==0 ); ++ sqlite3_mutex_enter(pInode->pLockMutex); + closePendingFds(pFile); ++ sqlite3_mutex_leave(pInode->pLockMutex); + if( pInode->pPrev ){ + assert( pInode->pPrev->pNext==pInode ); + pInode->pPrev->pNext = pInode->pNext; +@@ -32517,10 +33659,10 @@ + assert( pInode->pNext->pPrev==pInode ); + pInode->pNext->pPrev = pInode->pPrev; + } ++ sqlite3_mutex_free(pInode->pLockMutex); + sqlite3_free(pInode); + } + } +- assert( inodeList!=0 || nUnusedFd==0 ); + } + + /* +@@ -32528,8 +33670,7 @@ + ** describes that file descriptor. Create a new one if necessary. The + ** return value might be uninitialized if an error occurs. + ** +-** The mutex entered using the unixEnterMutex() function must be held +-** when this function is called. ++** The global mutex must held when calling this routine. + ** + ** Return an appropriate error code. + */ +@@ -32590,7 +33731,7 @@ + #else + fileId.ino = (u64)statbuf.st_ino; + #endif +- assert( inodeList!=0 || nUnusedFd==0 ); ++ assert( unixMutexHeld() ); + pInode = inodeList; + while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){ + pInode = pInode->pNext; +@@ -32602,7 +33743,15 @@ + } + memset(pInode, 0, sizeof(*pInode)); + memcpy(&pInode->fileId, &fileId, sizeof(fileId)); ++ if( sqlite3GlobalConfig.bCoreMutex ){ ++ pInode->pLockMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); ++ if( pInode->pLockMutex==0 ){ ++ sqlite3_free(pInode); ++ return SQLITE_NOMEM_BKPT; ++ } ++ } + pInode->nRef = 1; ++ assert( unixMutexHeld() ); + pInode->pNext = inodeList; + pInode->pPrev = 0; + if( inodeList ) inodeList->pPrev = pInode; +@@ -32680,7 +33829,7 @@ + + assert( pFile ); + assert( pFile->eFileLock<=SHARED_LOCK ); +- unixEnterMutex(); /* Because pFile->pInode is shared across threads */ ++ sqlite3_mutex_enter(pFile->pInode->pLockMutex); + + /* Check if a thread in this process holds such a lock */ + if( pFile->pInode->eFileLock>SHARED_LOCK ){ +@@ -32705,7 +33854,7 @@ + } + #endif + +- unixLeaveMutex(); ++ sqlite3_mutex_leave(pFile->pInode->pLockMutex); + OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved)); + + *pResOut = reserved; +@@ -32771,8 +33920,8 @@ + static int unixFileLock(unixFile *pFile, struct flock *pLock){ + int rc; + unixInodeInfo *pInode = pFile->pInode; +- assert( unixMutexHeld() ); + assert( pInode!=0 ); ++ assert( sqlite3_mutex_held(pInode->pLockMutex) ); + if( (pFile->ctrlFlags & (UNIXFILE_EXCL|UNIXFILE_RDONLY))==UNIXFILE_EXCL ){ + if( pInode->bProcessLock==0 ){ + struct flock lock; +@@ -32891,8 +34040,8 @@ + + /* This mutex is needed because pFile->pInode is shared across threads + */ +- unixEnterMutex(); + pInode = pFile->pInode; ++ sqlite3_mutex_enter(pInode->pLockMutex); + + /* If some thread using this PID has a lock via a different unixFile* + ** handle that precludes the requested lock, return BUSY. +@@ -33035,7 +34184,7 @@ + } + + end_lock: +- unixLeaveMutex(); ++ sqlite3_mutex_leave(pInode->pLockMutex); + OSTRACE(("LOCK %d %s %s (unix)\n", pFile->h, azFileLock(eFileLock), + rc==SQLITE_OK ? "ok" : "failed")); + return rc; +@@ -33048,11 +34197,11 @@ + static void setPendingFd(unixFile *pFile){ + unixInodeInfo *pInode = pFile->pInode; + UnixUnusedFd *p = pFile->pPreallocatedUnused; ++ assert( unixFileMutexHeld(pFile) ); + p->pNext = pInode->pUnused; + pInode->pUnused = p; + pFile->h = -1; + pFile->pPreallocatedUnused = 0; +- nUnusedFd++; + } + + /* +@@ -33083,8 +34232,8 @@ + if( pFile->eFileLock<=eFileLock ){ + return SQLITE_OK; + } +- unixEnterMutex(); + pInode = pFile->pInode; ++ sqlite3_mutex_enter(pInode->pLockMutex); + assert( pInode->nShared!=0 ); + if( pFile->eFileLock>SHARED_LOCK ){ + assert( pInode->eFileLock==pFile->eFileLock ); +@@ -33210,14 +34359,14 @@ + */ + pInode->nLock--; + assert( pInode->nLock>=0 ); +- if( pInode->nLock==0 ){ +- closePendingFds(pFile); +- } ++ if( pInode->nLock==0 ) closePendingFds(pFile); + } + + end_unlock: +- unixLeaveMutex(); +- if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock; ++ sqlite3_mutex_leave(pInode->pLockMutex); ++ if( rc==SQLITE_OK ){ ++ pFile->eFileLock = eFileLock; ++ } + return rc; + } + +@@ -33288,8 +34437,12 @@ + static int unixClose(sqlite3_file *id){ + int rc = SQLITE_OK; + unixFile *pFile = (unixFile *)id; ++ unixInodeInfo *pInode = pFile->pInode; ++ ++ assert( pInode!=0 ); + verifyDbFile(pFile); + unixUnlock(id, NO_LOCK); ++ assert( unixFileMutexNotheld(pFile) ); + unixEnterMutex(); + + /* unixFile.pInode is always valid here. Otherwise, a different close +@@ -33296,7 +34449,8 @@ + ** routine (e.g. nolockClose()) would be called instead. + */ + assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 ); +- if( ALWAYS(pFile->pInode) && pFile->pInode->nLock ){ ++ sqlite3_mutex_enter(pInode->pLockMutex); ++ if( pInode->nLock ){ + /* If there are outstanding locks, do not actually close the file just + ** yet because that would clear those locks. Instead, add the file + ** descriptor to pInode->pUnused list. It will be automatically closed +@@ -33304,6 +34458,7 @@ + */ + setPendingFd(pFile); + } ++ sqlite3_mutex_leave(pInode->pLockMutex); + releaseInodeInfo(pFile); + rc = closeUnixFile(id); + unixLeaveMutex(); +@@ -33901,6 +35056,7 @@ + unixFile *pFile = (unixFile*)id; + semXUnlock(id, NO_LOCK); + assert( pFile ); ++ assert( unixFileMutexNotheld(pFile) ); + unixEnterMutex(); + releaseInodeInfo(pFile); + unixLeaveMutex(); +@@ -34015,8 +35171,7 @@ + *pResOut = 1; + return SQLITE_OK; + } +- unixEnterMutex(); /* Because pFile->pInode is shared across threads */ +- ++ sqlite3_mutex_enter(pFile->pInode->pLockMutex); + /* Check if a thread in this process holds such a lock */ + if( pFile->pInode->eFileLock>SHARED_LOCK ){ + reserved = 1; +@@ -34040,7 +35195,7 @@ + } + } + +- unixLeaveMutex(); ++ sqlite3_mutex_leave(pFile->pInode->pLockMutex); + OSTRACE(("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved)); + + *pResOut = reserved; +@@ -34103,8 +35258,8 @@ + + /* This mutex is needed because pFile->pInode is shared across threads + */ +- unixEnterMutex(); + pInode = pFile->pInode; ++ sqlite3_mutex_enter(pInode->pLockMutex); + + /* If some thread using this PID has a lock via a different unixFile* + ** handle that precludes the requested lock, return BUSY. +@@ -34240,7 +35395,7 @@ + } + + afp_end_lock: +- unixLeaveMutex(); ++ sqlite3_mutex_leave(pInode->pLockMutex); + OSTRACE(("LOCK %d %s %s (afp)\n", pFile->h, azFileLock(eFileLock), + rc==SQLITE_OK ? "ok" : "failed")); + return rc; +@@ -34272,8 +35427,8 @@ + if( pFile->eFileLock<=eFileLock ){ + return SQLITE_OK; + } +- unixEnterMutex(); + pInode = pFile->pInode; ++ sqlite3_mutex_enter(pInode->pLockMutex); + assert( pInode->nShared!=0 ); + if( pFile->eFileLock>SHARED_LOCK ){ + assert( pInode->eFileLock==pFile->eFileLock ); +@@ -34342,14 +35497,14 @@ + if( rc==SQLITE_OK ){ + pInode->nLock--; + assert( pInode->nLock>=0 ); +- if( pInode->nLock==0 ){ +- closePendingFds(pFile); +- } ++ if( pInode->nLock==0 ) closePendingFds(pFile); + } + } + +- unixLeaveMutex(); +- if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock; ++ sqlite3_mutex_leave(pInode->pLockMutex); ++ if( rc==SQLITE_OK ){ ++ pFile->eFileLock = eFileLock; ++ } + return rc; + } + +@@ -34361,14 +35516,20 @@ + unixFile *pFile = (unixFile*)id; + assert( id!=0 ); + afpUnlock(id, NO_LOCK); ++ assert( unixFileMutexNotheld(pFile) ); + unixEnterMutex(); +- if( pFile->pInode && pFile->pInode->nLock ){ +- /* If there are outstanding locks, do not actually close the file just +- ** yet because that would clear those locks. Instead, add the file +- ** descriptor to pInode->aPending. It will be automatically closed when +- ** the last lock is cleared. +- */ +- setPendingFd(pFile); ++ if( pFile->pInode ){ ++ unixInodeInfo *pInode = pFile->pInode; ++ sqlite3_mutex_enter(pInode->pLockMutex); ++ if( pInode->nLock ){ ++ /* If there are outstanding locks, do not actually close the file just ++ ** yet because that would clear those locks. Instead, add the file ++ ** descriptor to pInode->aPending. It will be automatically closed when ++ ** the last lock is cleared. ++ */ ++ setPendingFd(pFile); ++ } ++ sqlite3_mutex_leave(pInode->pLockMutex); + } + releaseInodeInfo(pFile); + sqlite3_free(pFile->lockingContext); +@@ -35023,7 +36184,7 @@ + do{ + err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size); + }while( err==EINTR ); +- if( err ) return SQLITE_IOERR_WRITE; ++ if( err && err!=EINVAL ) return SQLITE_IOERR_WRITE; + #else + /* If the OS does not have posix_fallocate(), fake it. Write a + ** single byte to the last byte in each block that falls entirely +@@ -35388,18 +36549,18 @@ + ** + ** The following fields are read-only after the object is created: + ** +-** fid ++** hShm + ** zFilename + ** +-** Either unixShmNode.mutex must be held or unixShmNode.nRef==0 and ++** Either unixShmNode.pShmMutex must be held or unixShmNode.nRef==0 and + ** unixMutexHeld() is true when reading or writing any other field + ** in this structure. + */ + struct unixShmNode { + unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */ +- sqlite3_mutex *mutex; /* Mutex to access this object */ ++ sqlite3_mutex *pShmMutex; /* Mutex to access this object */ + char *zFilename; /* Name of the mmapped file */ +- int h; /* Open file descriptor */ ++ int hShm; /* Open file descriptor */ + int szRegion; /* Size of shared-memory regions */ + u16 nRegion; /* Size of array apRegion */ + u8 isReadonly; /* True if read-only */ +@@ -35421,16 +36582,16 @@ + ** The following fields are initialized when this object is created and + ** are read-only thereafter: + ** +-** unixShm.pFile ++** unixShm.pShmNode + ** unixShm.id + ** +-** All other fields are read/write. The unixShm.pFile->mutex must be held +-** while accessing any read/write fields. ++** All other fields are read/write. The unixShm.pShmNode->pShmMutex must ++** be held while accessing any read/write fields. + */ + struct unixShm { + unixShmNode *pShmNode; /* The underlying unixShmNode object */ + unixShm *pNext; /* Next unixShm with the same unixShmNode */ +- u8 hasMutex; /* True if holding the unixShmNode mutex */ ++ u8 hasMutex; /* True if holding the unixShmNode->pShmMutex */ + u8 id; /* Id of this connection within its unixShmNode */ + u16 sharedMask; /* Mask of shared locks held */ + u16 exclMask; /* Mask of exclusive locks held */ +@@ -35460,7 +36621,8 @@ + + /* Access to the unixShmNode object is serialized by the caller */ + pShmNode = pFile->pInode->pShmNode; +- assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->mutex) ); ++ assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->pShmMutex) ); ++ assert( pShmNode->nRef>0 || unixMutexHeld() ); + + /* Shared locks never span more than one byte */ + assert( n==1 || lockType!=F_RDLCK ); +@@ -35468,13 +36630,13 @@ + /* Locks are within range */ + assert( n>=1 && n<=SQLITE_SHM_NLOCK ); + +- if( pShmNode->h>=0 ){ ++ if( pShmNode->hShm>=0 ){ + /* Initialize the locking parameters */ + f.l_type = lockType; + f.l_whence = SEEK_SET; + f.l_start = ofst; + f.l_len = n; +- rc = osSetPosixAdvisoryLock(pShmNode->h, &f, pFile); ++ rc = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile); + rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY; + } + +@@ -35546,9 +36708,9 @@ + int nShmPerMap = unixShmRegionPerMap(); + int i; + assert( p->pInode==pFd->pInode ); +- sqlite3_mutex_free(p->mutex); ++ sqlite3_mutex_free(p->pShmMutex); + for(i=0; i<p->nRegion; i+=nShmPerMap){ +- if( p->h>=0 ){ ++ if( p->hShm>=0 ){ + osMunmap(p->apRegion[i], p->szRegion); + }else{ + sqlite3_free(p->apRegion[i]); +@@ -35555,9 +36717,9 @@ + } + } + sqlite3_free(p->apRegion); +- if( p->h>=0 ){ +- robust_close(pFd, p->h, __LINE__); +- p->h = -1; ++ if( p->hShm>=0 ){ ++ robust_close(pFd, p->hShm, __LINE__); ++ p->hShm = -1; + } + p->pInode->pShmNode = 0; + sqlite3_free(p); +@@ -35599,7 +36761,7 @@ + lock.l_start = UNIX_SHM_DMS; + lock.l_len = 1; + lock.l_type = F_WRLCK; +- if( osFcntl(pShmNode->h, F_GETLK, &lock)!=0 ) { ++ if( osFcntl(pShmNode->hShm, F_GETLK, &lock)!=0 ) { + rc = SQLITE_IOERR_LOCK; + }else if( lock.l_type==F_UNLCK ){ + if( pShmNode->isReadonly ){ +@@ -35607,7 +36769,12 @@ + rc = SQLITE_READONLY_CANTINIT; + }else{ + rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1); +- if( rc==SQLITE_OK && robust_ftruncate(pShmNode->h, 0) ){ ++ /* The first connection to attach must truncate the -shm file. We ++ ** truncate to 3 bytes (an arbitrary small number, less than the ++ ** -shm header size) rather than 0 as a system debugging aid, to ++ ** help detect if a -shm file truncation is legitimate or is the work ++ ** or a rogue process. */ ++ if( rc==SQLITE_OK && robust_ftruncate(pShmNode->hShm, 3) ){ + rc = unixLogError(SQLITE_IOERR_SHMOPEN,"ftruncate",pShmNode->zFilename); + } + } +@@ -35674,6 +36841,7 @@ + /* Check to see if a unixShmNode object already exists. Reuse an existing + ** one if present. Create a new one if necessary. + */ ++ assert( unixFileMutexNotheld(pDbFd) ); + unixEnterMutex(); + pInode = pDbFd->pInode; + pShmNode = pInode->pShmNode; +@@ -35712,12 +36880,12 @@ + sqlite3_snprintf(nShmFilename, zShm, "%s-shm", zBasePath); + sqlite3FileSuffix3(pDbFd->zPath, zShm); + #endif +- pShmNode->h = -1; ++ pShmNode->hShm = -1; + pDbFd->pInode->pShmNode = pShmNode; + pShmNode->pInode = pDbFd->pInode; + if( sqlite3GlobalConfig.bCoreMutex ){ +- pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); +- if( pShmNode->mutex==0 ){ ++ pShmNode->pShmMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); ++ if( pShmNode->pShmMutex==0 ){ + rc = SQLITE_NOMEM_BKPT; + goto shm_open_err; + } +@@ -35725,11 +36893,11 @@ + + if( pInode->bProcessLock==0 ){ + if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){ +- pShmNode->h = robust_open(zShm, O_RDWR|O_CREAT, (sStat.st_mode&0777)); ++ pShmNode->hShm = robust_open(zShm, O_RDWR|O_CREAT,(sStat.st_mode&0777)); + } +- if( pShmNode->h<0 ){ +- pShmNode->h = robust_open(zShm, O_RDONLY, (sStat.st_mode&0777)); +- if( pShmNode->h<0 ){ ++ if( pShmNode->hShm<0 ){ ++ pShmNode->hShm = robust_open(zShm, O_RDONLY, (sStat.st_mode&0777)); ++ if( pShmNode->hShm<0 ){ + rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShm); + goto shm_open_err; + } +@@ -35740,7 +36908,7 @@ + ** is owned by the same user that owns the original database. Otherwise, + ** the original owner will not be able to connect. + */ +- robustFchown(pShmNode->h, sStat.st_uid, sStat.st_gid); ++ robustFchown(pShmNode->hShm, sStat.st_uid, sStat.st_gid); + + rc = unixLockSharedMemory(pDbFd, pShmNode); + if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err; +@@ -35760,13 +36928,13 @@ + ** the cover of the unixEnterMutex() mutex and the pointer from the + ** new (struct unixShm) object to the pShmNode has been set. All that is + ** left to do is to link the new object into the linked list starting +- ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex +- ** mutex. ++ ** at pShmNode->pFirst. This must be done while holding the ++ ** pShmNode->pShmMutex. + */ +- sqlite3_mutex_enter(pShmNode->mutex); ++ sqlite3_mutex_enter(pShmNode->pShmMutex); + p->pNext = pShmNode->pFirst; + pShmNode->pFirst = p; +- sqlite3_mutex_leave(pShmNode->mutex); ++ sqlite3_mutex_leave(pShmNode->pShmMutex); + return rc; + + /* Jump here on any error */ +@@ -35818,7 +36986,7 @@ + + p = pDbFd->pShm; + pShmNode = p->pShmNode; +- sqlite3_mutex_enter(pShmNode->mutex); ++ sqlite3_mutex_enter(pShmNode->pShmMutex); + if( pShmNode->isUnlocked ){ + rc = unixLockSharedMemory(pDbFd, pShmNode); + if( rc!=SQLITE_OK ) goto shmpage_out; +@@ -35826,8 +36994,8 @@ + } + assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 ); + assert( pShmNode->pInode==pDbFd->pInode ); +- assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 ); +- assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 ); ++ assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 ); ++ assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 ); + + /* Minimum number of regions required to be mapped. */ + nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap; +@@ -35839,12 +37007,12 @@ + + pShmNode->szRegion = szRegion; + +- if( pShmNode->h>=0 ){ ++ if( pShmNode->hShm>=0 ){ + /* The requested region is not mapped into this processes address space. + ** Check to see if it has been allocated (i.e. if the wal-index file is + ** large enough to contain the requested region). + */ +- if( osFstat(pShmNode->h, &sStat) ){ ++ if( osFstat(pShmNode->hShm, &sStat) ){ + rc = SQLITE_IOERR_SHMSIZE; + goto shmpage_out; + } +@@ -35872,7 +37040,7 @@ + assert( (nByte % pgsz)==0 ); + for(iPg=(sStat.st_size/pgsz); iPg<(nByte/pgsz); iPg++){ + int x = 0; +- if( seekAndWriteFd(pShmNode->h, iPg*pgsz + pgsz-1, "", 1, &x)!=1 ){ ++ if( seekAndWriteFd(pShmNode->hShm, iPg*pgsz + pgsz-1,"",1,&x)!=1 ){ + const char *zFile = pShmNode->zFilename; + rc = unixLogError(SQLITE_IOERR_SHMSIZE, "write", zFile); + goto shmpage_out; +@@ -35895,10 +37063,10 @@ + int nMap = szRegion*nShmPerMap; + int i; + void *pMem; +- if( pShmNode->h>=0 ){ ++ if( pShmNode->hShm>=0 ){ + pMem = osMmap(0, nMap, + pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, +- MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion ++ MAP_SHARED, pShmNode->hShm, szRegion*(i64)pShmNode->nRegion + ); + if( pMem==MAP_FAILED ){ + rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename); +@@ -35905,12 +37073,12 @@ + goto shmpage_out; + } + }else{ +- pMem = sqlite3_malloc64(szRegion); ++ pMem = sqlite3_malloc64(nMap); + if( pMem==0 ){ + rc = SQLITE_NOMEM_BKPT; + goto shmpage_out; + } +- memset(pMem, 0, szRegion); ++ memset(pMem, 0, nMap); + } + + for(i=0; i<nShmPerMap; i++){ +@@ -35927,7 +37095,7 @@ + *pp = 0; + } + if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY; +- sqlite3_mutex_leave(pShmNode->mutex); ++ sqlite3_mutex_leave(pShmNode->pShmMutex); + return rc; + } + +@@ -35961,12 +37129,12 @@ + || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED) + || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) ); + assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 ); +- assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 ); +- assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 ); ++ assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 ); ++ assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 ); + + mask = (1<<(ofst+n)) - (1<<ofst); + assert( n>1 || mask==(1<<ofst) ); +- sqlite3_mutex_enter(pShmNode->mutex); ++ sqlite3_mutex_enter(pShmNode->pShmMutex); + if( flags & SQLITE_SHM_UNLOCK ){ + u16 allMask = 0; /* Mask of locks held by siblings */ + +@@ -36039,7 +37207,7 @@ + } + } + } +- sqlite3_mutex_leave(pShmNode->mutex); ++ sqlite3_mutex_leave(pShmNode->pShmMutex); + OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n", + p->id, osGetpid(0), p->sharedMask, p->exclMask)); + return rc; +@@ -36056,6 +37224,9 @@ + ){ + UNUSED_PARAMETER(fd); + sqlite3MemoryBarrier(); /* compiler-defined memory barrier */ ++ assert( fd->pMethods->xLock==nolockLock ++ || unixFileMutexNotheld((unixFile*)fd) ++ ); + unixEnterMutex(); /* Also mutex, for redundancy */ + unixLeaveMutex(); + } +@@ -36086,7 +37257,7 @@ + + /* Remove connection p from the set of connections associated + ** with pShmNode */ +- sqlite3_mutex_enter(pShmNode->mutex); ++ sqlite3_mutex_enter(pShmNode->pShmMutex); + for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){} + *pp = p->pNext; + +@@ -36093,15 +37264,16 @@ + /* Free the connection p */ + sqlite3_free(p); + pDbFd->pShm = 0; +- sqlite3_mutex_leave(pShmNode->mutex); ++ sqlite3_mutex_leave(pShmNode->pShmMutex); + + /* If pShmNode->nRef has reached 0, then close the underlying + ** shared-memory file, too */ ++ assert( unixFileMutexNotheld(pDbFd) ); + unixEnterMutex(); + assert( pShmNode->nRef>0 ); + pShmNode->nRef--; + if( pShmNode->nRef==0 ){ +- if( deleteFlag && pShmNode->h>=0 ){ ++ if( deleteFlag && pShmNode->hShm>=0 ){ + osUnlink(pShmNode->zFilename); + } + unixShmPurge(pDbFd); +@@ -36423,7 +37595,7 @@ + IOMETHODS( + nolockIoFinder, /* Finder function name */ + nolockIoMethods, /* sqlite3_io_methods object name */ +- 3, /* shared memory is disabled */ ++ 3, /* shared memory and mmap are enabled */ + nolockClose, /* xClose method */ + nolockLock, /* xLock method */ + nolockUnlock, /* xUnlock method */ +@@ -36919,7 +38091,7 @@ + ** + ** Even if a subsequent open() call does succeed, the consequences of + ** not searching for a reusable file descriptor are not dire. */ +- if( nUnusedFd>0 && 0==osStat(zPath, &sStat) ){ ++ if( inodeList!=0 && 0==osStat(zPath, &sStat) ){ + unixInodeInfo *pInode; + + pInode = inodeList; +@@ -36929,12 +38101,14 @@ + } + if( pInode ){ + UnixUnusedFd **pp; ++ assert( sqlite3_mutex_notheld(pInode->pLockMutex) ); ++ sqlite3_mutex_enter(pInode->pLockMutex); + for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext)); + pUnused = *pp; + if( pUnused ){ +- nUnusedFd--; + *pp = pUnused->pNext; + } ++ sqlite3_mutex_leave(pInode->pLockMutex); + } + } + unixLeaveMutex(); +@@ -39517,8 +40691,7 @@ + int nFetchOut; /* Number of outstanding xFetch references */ + HANDLE hMap; /* Handle for accessing memory mapping */ + void *pMapRegion; /* Area memory mapped */ +- sqlite3_int64 mmapSize; /* Usable size of mapped region */ +- sqlite3_int64 mmapSizeActual; /* Actual size of mapped region */ ++ sqlite3_int64 mmapSize; /* Size of mapped region */ + sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */ + #endif + }; +@@ -39549,22 +40722,6 @@ + #endif + + /* +- * The value used with sqlite3_win32_set_directory() to specify that +- * the data directory should be changed. +- */ +-#ifndef SQLITE_WIN32_DATA_DIRECTORY_TYPE +-# define SQLITE_WIN32_DATA_DIRECTORY_TYPE (1) +-#endif +- +-/* +- * The value used with sqlite3_win32_set_directory() to specify that +- * the temporary directory should be changed. +- */ +-#ifndef SQLITE_WIN32_TEMP_DIRECTORY_TYPE +-# define SQLITE_WIN32_TEMP_DIRECTORY_TYPE (2) +-#endif +- +-/* + * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the + * various Win32 API heap functions instead of our own. + */ +@@ -41160,13 +42317,13 @@ + } + + /* +-** This function sets the data directory or the temporary directory based on +-** the provided arguments. The type argument must be 1 in order to set the +-** data directory or 2 in order to set the temporary directory. The zValue +-** argument is the name of the directory to use. The return value will be +-** SQLITE_OK if successful. ++** This function is the same as sqlite3_win32_set_directory (below); however, ++** it accepts a UTF-8 string. + */ +-SQLITE_API int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){ ++SQLITE_API int sqlite3_win32_set_directory8( ++ unsigned long type, /* Identifier for directory being set or reset */ ++ const char *zValue /* New value for directory being set or reset */ ++){ + char **ppDirectory = 0; + #ifndef SQLITE_OMIT_AUTOINIT + int rc = sqlite3_initialize(); +@@ -41182,15 +42339,15 @@ + ); + assert( !ppDirectory || sqlite3MemdebugHasType(*ppDirectory, MEMTYPE_HEAP) ); + if( ppDirectory ){ +- char *zValueUtf8 = 0; ++ char *zCopy = 0; + if( zValue && zValue[0] ){ +- zValueUtf8 = winUnicodeToUtf8(zValue); +- if ( zValueUtf8==0 ){ ++ zCopy = sqlite3_mprintf("%s", zValue); ++ if ( zCopy==0 ){ + return SQLITE_NOMEM_BKPT; + } + } + sqlite3_free(*ppDirectory); +- *ppDirectory = zValueUtf8; ++ *ppDirectory = zCopy; + return SQLITE_OK; + } + return SQLITE_ERROR; +@@ -41197,6 +42354,39 @@ + } + + /* ++** This function is the same as sqlite3_win32_set_directory (below); however, ++** it accepts a UTF-16 string. ++*/ ++SQLITE_API int sqlite3_win32_set_directory16( ++ unsigned long type, /* Identifier for directory being set or reset */ ++ const void *zValue /* New value for directory being set or reset */ ++){ ++ int rc; ++ char *zUtf8 = 0; ++ if( zValue ){ ++ zUtf8 = sqlite3_win32_unicode_to_utf8(zValue); ++ if( zUtf8==0 ) return SQLITE_NOMEM_BKPT; ++ } ++ rc = sqlite3_win32_set_directory8(type, zUtf8); ++ if( zUtf8 ) sqlite3_free(zUtf8); ++ return rc; ++} ++ ++/* ++** This function sets the data directory or the temporary directory based on ++** the provided arguments. The type argument must be 1 in order to set the ++** data directory or 2 in order to set the temporary directory. The zValue ++** argument is the name of the directory to use. The return value will be ++** SQLITE_OK if successful. ++*/ ++SQLITE_API int sqlite3_win32_set_directory( ++ unsigned long type, /* Identifier for directory being set or reset */ ++ void *zValue /* New value for directory being set or reset */ ++){ ++ return sqlite3_win32_set_directory16(type, zValue); ++} ++ ++/* + ** The return value of winGetLastErrorMsg + ** is zero if the error message fits in the buffer, or non-zero + ** otherwise (if the message was truncated). +@@ -42120,6 +43310,29 @@ + winFile *pFile = (winFile*)id; /* File handle object */ + int rc = SQLITE_OK; /* Return code for this function */ + DWORD lastErrno; ++#if SQLITE_MAX_MMAP_SIZE>0 ++ sqlite3_int64 oldMmapSize; ++ if( pFile->nFetchOut>0 ){ ++ /* File truncation is a no-op if there are outstanding memory mapped ++ ** pages. This is because truncating the file means temporarily unmapping ++ ** the file, and that might delete memory out from under existing cursors. ++ ** ++ ** This can result in incremental vacuum not truncating the file, ++ ** if there is an active read cursor when the incremental vacuum occurs. ++ ** No real harm comes of this - the database file is not corrupted, ++ ** though some folks might complain that the file is bigger than it ++ ** needs to be. ++ ** ++ ** The only feasible work-around is to defer the truncation until after ++ ** all references to memory-mapped content are closed. That is doable, ++ ** but involves adding a few branches in the common write code path which ++ ** could slow down normal operations slightly. Hence, we have decided for ++ ** now to simply make trancations a no-op if there are pending reads. We ++ ** can maybe revisit this decision in the future. ++ */ ++ return SQLITE_OK; ++ } ++#endif + + assert( pFile ); + SimulateIOError(return SQLITE_IOERR_TRUNCATE); +@@ -42135,6 +43348,15 @@ + nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk; + } + ++#if SQLITE_MAX_MMAP_SIZE>0 ++ if( pFile->pMapRegion ){ ++ oldMmapSize = pFile->mmapSize; ++ }else{ ++ oldMmapSize = 0; ++ } ++ winUnmapfile(pFile); ++#endif ++ + /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */ + if( winSeekFile(pFile, nByte) ){ + rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno, +@@ -42147,12 +43369,12 @@ + } + + #if SQLITE_MAX_MMAP_SIZE>0 +- /* If the file was truncated to a size smaller than the currently +- ** mapped region, reduce the effective mapping size as well. SQLite will +- ** use read() and write() to access data beyond this point from now on. +- */ +- if( pFile->pMapRegion && nByte<pFile->mmapSize ){ +- pFile->mmapSize = nByte; ++ if( rc==SQLITE_OK && oldMmapSize>0 ){ ++ if( oldMmapSize>nByte ){ ++ winMapfile(pFile, -1); ++ }else{ ++ winMapfile(pFile, oldMmapSize); ++ } + } + #endif + +@@ -43538,9 +44760,9 @@ + static int winUnmapfile(winFile *pFile){ + assert( pFile!=0 ); + OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, pMapRegion=%p, " +- "mmapSize=%lld, mmapSizeActual=%lld, mmapSizeMax=%lld\n", ++ "mmapSize=%lld, mmapSizeMax=%lld\n", + osGetCurrentProcessId(), pFile, pFile->hMap, pFile->pMapRegion, +- pFile->mmapSize, pFile->mmapSizeActual, pFile->mmapSizeMax)); ++ pFile->mmapSize, pFile->mmapSizeMax)); + if( pFile->pMapRegion ){ + if( !osUnmapViewOfFile(pFile->pMapRegion) ){ + pFile->lastErrno = osGetLastError(); +@@ -43552,7 +44774,6 @@ + } + pFile->pMapRegion = 0; + pFile->mmapSize = 0; +- pFile->mmapSizeActual = 0; + } + if( pFile->hMap!=NULL ){ + if( !osCloseHandle(pFile->hMap) ){ +@@ -43663,7 +44884,6 @@ + } + pFd->pMapRegion = pNew; + pFd->mmapSize = nMap; +- pFd->mmapSizeActual = nMap; + } + + OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n", +@@ -44465,7 +45685,6 @@ + pFile->hMap = NULL; + pFile->pMapRegion = 0; + pFile->mmapSize = 0; +- pFile->mmapSizeActual = 0; + pFile->mmapSizeMax = sqlite3GlobalConfig.szMmap; + #endif + +@@ -45340,8 +46559,8 @@ + ** This file also implements interface sqlite3_serialize() and + ** sqlite3_deserialize(). + */ ++/* #include "sqliteInt.h" */ + #ifdef SQLITE_ENABLE_DESERIALIZE +-/* #include "sqliteInt.h" */ + + /* + ** Forward declaration of objects used by this utility +@@ -46362,7 +47581,7 @@ + ** The PCache.pSynced variable is used to optimize searching for a dirty + ** page to eject from the cache mid-transaction. It is better to eject + ** a page that does not require a journal sync than one that does. +-** Therefore, pSynced is maintained to that it *almost* always points ++** Therefore, pSynced is maintained so that it *almost* always points + ** to either the oldest page in the pDirty/pDirtyTail list that has a + ** 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 +@@ -47186,6 +48405,15 @@ + return nCache ? (int)(((i64)nDirty * 100) / nCache) : 0; + } + ++#ifdef SQLITE_DIRECT_OVERFLOW_READ ++/* ++** Return true if there are one or more dirty pages in the cache. Else false. ++*/ ++SQLITE_PRIVATE int sqlite3PCacheIsDirty(PCache *pCache){ ++ return (pCache->pDirty!=0); ++} ++#endif ++ + #if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) + /* + ** For all dirty pages currently in the cache, invoke the specified +@@ -47309,7 +48537,8 @@ + }; + + /* +-** A page is pinned if it is no on the LRU list ++** A page is pinned if it is not on the LRU list. To be "pinned" means ++** that the page is in active use and must not be deallocated. + */ + #define PAGE_IS_PINNED(p) ((p)->pLruNext==0) + #define PAGE_IS_UNPINNED(p) ((p)->pLruNext!=0) +@@ -48589,30 +49818,23 @@ + #define ROWSET_NEXT 0x02 /* True if sqlite3RowSetNext() has been called */ + + /* +-** Turn bulk memory into a RowSet object. N bytes of memory +-** are available at pSpace. The db pointer is used as a memory context +-** for any subsequent allocations that need to occur. +-** Return a pointer to the new RowSet object. +-** +-** It must be the case that N is sufficient to make a Rowset. If not +-** an assertion fault occurs. +-** +-** If N is larger than the minimum, use the surplus as an initial +-** allocation of entries available to be filled. ++** Allocate a RowSet object. Return NULL if a memory allocation ++** error occurs. + */ +-SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3 *db, void *pSpace, unsigned int N){ +- RowSet *p; +- assert( N >= ROUND8(sizeof(*p)) ); +- p = pSpace; +- p->pChunk = 0; +- p->db = db; +- p->pEntry = 0; +- p->pLast = 0; +- p->pForest = 0; +- p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p); +- p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry)); +- p->rsFlags = ROWSET_SORTED; +- p->iBatch = 0; ++SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3 *db){ ++ RowSet *p = sqlite3DbMallocRawNN(db, sizeof(*p)); ++ if( p ){ ++ int N = sqlite3DbMallocSize(db, p); ++ p->pChunk = 0; ++ p->db = db; ++ p->pEntry = 0; ++ p->pLast = 0; ++ p->pForest = 0; ++ p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p); ++ p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry)); ++ p->rsFlags = ROWSET_SORTED; ++ p->iBatch = 0; ++ } + return p; + } + +@@ -48621,7 +49843,8 @@ + ** the RowSet has allocated over its lifetime. This routine is + ** the destructor for the RowSet. + */ +-SQLITE_PRIVATE void sqlite3RowSetClear(RowSet *p){ ++SQLITE_PRIVATE void sqlite3RowSetClear(void *pArg){ ++ RowSet *p = (RowSet*)pArg; + struct RowSetChunk *pChunk, *pNextChunk; + for(pChunk=p->pChunk; pChunk; pChunk = pNextChunk){ + pNextChunk = pChunk->pNextChunk; +@@ -48636,6 +49859,16 @@ + } + + /* ++** Deallocate all chunks from a RowSet. This frees all memory that ++** the RowSet has allocated over its lifetime. This routine is ++** the destructor for the RowSet. ++*/ ++SQLITE_PRIVATE void sqlite3RowSetDelete(void *pArg){ ++ sqlite3RowSetClear(pArg); ++ sqlite3DbFree(((RowSet*)pArg)->db, pArg); ++} ++ ++/* + ** Allocate a new RowSetEntry object that is associated with the + ** given RowSet. Return a pointer to the new and completely uninitialized + ** objected. +@@ -49122,6 +50355,8 @@ + SQLITE_PRIVATE int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot); + SQLITE_PRIVATE void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot); + SQLITE_PRIVATE int sqlite3WalSnapshotRecover(Wal *pWal); ++SQLITE_PRIVATE int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot); ++SQLITE_PRIVATE void sqlite3WalSnapshotUnlock(Wal *pWal); + #endif + + #ifdef SQLITE_ENABLE_ZIPVFS +@@ -49943,19 +51178,30 @@ + */ + #define isOpen(pFd) ((pFd)->pMethods!=0) + ++#ifdef SQLITE_DIRECT_OVERFLOW_READ + /* +-** Return true if this pager uses a write-ahead log to read page pgno. +-** Return false if the pager reads pgno directly from the database. ++** Return true if page pgno can be read directly from the database file ++** by the b-tree layer. This is the case if: ++** ++** * the database file is open, ++** * there are no dirty pages in the cache, and ++** * the desired page is not currently in the wal file. + */ +-#if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_DIRECT_OVERFLOW_READ) +-SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager, Pgno pgno){ +- u32 iRead = 0; +- int rc; +- if( pPager->pWal==0 ) return 0; +- rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead); +- return rc || iRead; ++SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){ ++ if( pPager->fd->pMethods==0 ) return 0; ++ if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0; ++#ifndef SQLITE_OMIT_WAL ++ if( pPager->pWal ){ ++ u32 iRead = 0; ++ int rc; ++ rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead); ++ return (rc==SQLITE_OK && iRead==0); ++ } ++#endif ++ return 1; + } + #endif ++ + #ifndef SQLITE_OMIT_WAL + # define pagerUseWal(x) ((x)->pWal!=0) + #else +@@ -50115,8 +51361,12 @@ + ** to "print *pPager" in gdb: + ** + ** (gdb) printf "%s", print_pager_state(pPager) ++** ++** This routine has external linkage in order to suppress compiler warnings ++** about an unused function. It is enclosed within SQLITE_DEBUG and so does ++** not appear in normal builds. + */ +-static char *print_pager_state(Pager *p){ ++char *print_pager_state(Pager *p){ + static char zRet[1024]; + + sqlite3_snprintf(1024, zRet, +@@ -50882,7 +52132,6 @@ + ** Return the pPager->iDataVersion value + */ + SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager *pPager){ +- assert( pPager->eState>PAGER_OPEN ); + return pPager->iDataVersion; + } + +@@ -55500,9 +56749,10 @@ + ** backup in progress needs to be restarted. */ + sqlite3BackupRestart(pPager->pBackup); + }else{ ++ PgHdr *pList; + if( pagerUseWal(pPager) ){ +- PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache); + PgHdr *pPageOne = 0; ++ pList = sqlite3PcacheDirtyList(pPager->pPCache); + if( pList==0 ){ + /* Must have at least one page for the WAL commit flag. + ** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */ +@@ -55523,14 +56773,14 @@ + ** should be used. No rollback journal is created if batch-atomic-write + ** is enabled. + */ ++#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE + sqlite3_file *fd = pPager->fd; +-#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE +- const int bBatch = zMaster==0 /* An SQLITE_IOCAP_BATCH_ATOMIC commit */ ++ int bBatch = zMaster==0 /* An SQLITE_IOCAP_BATCH_ATOMIC commit */ + && (sqlite3OsDeviceCharacteristics(fd) & SQLITE_IOCAP_BATCH_ATOMIC) + && !pPager->noSync + && sqlite3JournalIsInMemory(pPager->jfd); + #else +-# define bBatch 0 ++# define bBatch 0 + #endif + + #ifdef SQLITE_ENABLE_ATOMIC_WRITE +@@ -55582,15 +56832,16 @@ + } + } + } +-#else ++#else /* SQLITE_ENABLE_ATOMIC_WRITE */ + #ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE + if( zMaster ){ + rc = sqlite3JournalCreate(pPager->jfd); + if( rc!=SQLITE_OK ) goto commit_phase_one_exit; ++ assert( bBatch==0 ); + } + #endif + rc = pager_incr_changecounter(pPager, 0); +-#endif ++#endif /* !SQLITE_ENABLE_ATOMIC_WRITE */ + if( rc!=SQLITE_OK ) goto commit_phase_one_exit; + + /* Write the master journal name into the journal file. If a master +@@ -55614,24 +56865,36 @@ + rc = syncJournal(pPager, 0); + if( rc!=SQLITE_OK ) goto commit_phase_one_exit; + ++ pList = sqlite3PcacheDirtyList(pPager->pPCache); ++#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE + if( bBatch ){ +- /* The pager is now in DBMOD state. But regardless of what happens +- ** next, attempting to play the journal back into the database would +- ** be unsafe. Close it now to make sure that does not happen. */ +- sqlite3OsClose(pPager->jfd); + rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_BEGIN_ATOMIC_WRITE, 0); +- if( rc!=SQLITE_OK ) goto commit_phase_one_exit; +- } +- rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache)); +- if( bBatch ){ + if( rc==SQLITE_OK ){ +- rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_COMMIT_ATOMIC_WRITE, 0); ++ rc = pager_write_pagelist(pPager, pList); ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_COMMIT_ATOMIC_WRITE, 0); ++ } ++ if( rc!=SQLITE_OK ){ ++ sqlite3OsFileControlHint(fd, SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE, 0); ++ } + } +- if( rc!=SQLITE_OK ){ +- sqlite3OsFileControlHint(fd, SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE, 0); ++ ++ if( (rc&0xFF)==SQLITE_IOERR && rc!=SQLITE_IOERR_NOMEM ){ ++ rc = sqlite3JournalCreate(pPager->jfd); ++ if( rc!=SQLITE_OK ){ ++ sqlite3OsClose(pPager->jfd); ++ goto commit_phase_one_exit; ++ } ++ bBatch = 0; ++ }else{ ++ sqlite3OsClose(pPager->jfd); + } + } ++#endif /* SQLITE_ENABLE_BATCH_ATOMIC_WRITE */ + ++ if( bBatch==0 ){ ++ rc = pager_write_pagelist(pPager, pList); ++ } + if( rc!=SQLITE_OK ){ + assert( rc!=SQLITE_IOERR_BLOCKED ); + goto commit_phase_one_exit; +@@ -56122,7 +57385,11 @@ + void (*xCodecFree)(void*), + void *pCodec + ){ +- if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec); ++ if( pPager->xCodecFree ){ ++ pPager->xCodecFree(pPager->pCodec); ++ }else{ ++ pager_reset(pPager); ++ } + pPager->xCodec = pPager->memDb ? 0 : xCodec; + pPager->xCodecSizeChng = xCodecSizeChng; + pPager->xCodecFree = xCodecFree; +@@ -56383,13 +57650,6 @@ + SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){ + u8 eOld = pPager->journalMode; /* Prior journalmode */ + +-#ifdef SQLITE_DEBUG +- /* The print_pager_state() routine is intended to be used by the debugger +- ** only. We invoke it once here to suppress a compiler warning. */ +- print_pager_state(pPager); +-#endif +- +- + /* The eMode parameter is always valid */ + assert( eMode==PAGER_JOURNALMODE_DELETE + || eMode==PAGER_JOURNALMODE_TRUNCATE +@@ -56758,6 +58018,38 @@ + } + return rc; + } ++ ++/* ++** The caller currently has a read transaction open on the database. ++** If this is not a WAL database, SQLITE_ERROR is returned. Otherwise, ++** this function takes a SHARED lock on the CHECKPOINTER slot and then ++** checks if the snapshot passed as the second argument is still ++** available. If so, SQLITE_OK is returned. ++** ++** If the snapshot is not available, SQLITE_ERROR is returned. Or, if ++** the CHECKPOINTER lock cannot be obtained, SQLITE_BUSY. If any error ++** occurs (any value other than SQLITE_OK is returned), the CHECKPOINTER ++** lock is released before returning. ++*/ ++SQLITE_PRIVATE int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot){ ++ int rc; ++ if( pPager->pWal ){ ++ rc = sqlite3WalSnapshotCheck(pPager->pWal, pSnapshot); ++ }else{ ++ rc = SQLITE_ERROR; ++ } ++ return rc; ++} ++ ++/* ++** Release a lock obtained by an earlier successful call to ++** sqlite3PagerSnapshotCheck(). ++*/ ++SQLITE_PRIVATE void sqlite3PagerSnapshotUnlock(Pager *pPager){ ++ assert( pPager->pWal ); ++ return sqlite3WalSnapshotUnlock(pPager->pWal); ++} ++ + #endif /* SQLITE_ENABLE_SNAPSHOT */ + #endif /* !SQLITE_OMIT_WAL */ + +@@ -57040,6 +58332,18 @@ + #endif + + /* ++** WAL mode depends on atomic aligned 32-bit loads and stores in a few ++** places. The following macros try to make this explicit. ++*/ ++#if GCC_VESRION>=5004000 ++# define AtomicLoad(PTR) __atomic_load_n((PTR),__ATOMIC_RELAXED) ++# define AtomicStore(PTR,VAL) __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED) ++#else ++# define AtomicLoad(PTR) (*(PTR)) ++# define AtomicStore(PTR,VAL) (*(PTR) = (VAL)) ++#endif ++ ++/* + ** The maximum (and only) versions of the wal and wal-index formats + ** that may be interpreted by this version of SQLite. + ** +@@ -57661,48 +58965,51 @@ + return (iPriorHash+1)&(HASHTABLE_NSLOT-1); + } + ++/* ++** An instance of the WalHashLoc object is used to describe the location ++** of a page hash table in the wal-index. This becomes the return value ++** from walHashGet(). ++*/ ++typedef struct WalHashLoc WalHashLoc; ++struct WalHashLoc { ++ volatile ht_slot *aHash; /* Start of the wal-index hash table */ ++ volatile u32 *aPgno; /* aPgno[1] is the page of first frame indexed */ ++ u32 iZero; /* One less than the frame number of first indexed*/ ++}; ++ + /* + ** Return pointers to the hash table and page number array stored on + ** page iHash of the wal-index. The wal-index is broken into 32KB pages + ** numbered starting from 0. + ** +-** Set output variable *paHash to point to the start of the hash table +-** in the wal-index file. Set *piZero to one less than the frame ++** Set output variable pLoc->aHash to point to the start of the hash table ++** in the wal-index file. Set pLoc->iZero to one less than the frame + ** number of the first frame indexed by this hash table. If a + ** slot in the hash table is set to N, it refers to frame number +-** (*piZero+N) in the log. ++** (pLoc->iZero+N) in the log. + ** +-** Finally, set *paPgno so that *paPgno[1] is the page number of the +-** first frame indexed by the hash table, frame (*piZero+1). ++** Finally, set pLoc->aPgno so that pLoc->aPgno[1] is the page number of the ++** first frame indexed by the hash table, frame (pLoc->iZero+1). + */ + static int walHashGet( + Wal *pWal, /* WAL handle */ + int iHash, /* Find the iHash'th table */ +- volatile ht_slot **paHash, /* OUT: Pointer to hash index */ +- volatile u32 **paPgno, /* OUT: Pointer to page number array */ +- u32 *piZero /* OUT: Frame associated with *paPgno[0] */ ++ WalHashLoc *pLoc /* OUT: Hash table location */ + ){ + int rc; /* Return code */ +- volatile u32 *aPgno; + +- rc = walIndexPage(pWal, iHash, &aPgno); ++ rc = walIndexPage(pWal, iHash, &pLoc->aPgno); + assert( rc==SQLITE_OK || iHash>0 ); + + if( rc==SQLITE_OK ){ +- u32 iZero; +- volatile ht_slot *aHash; +- +- aHash = (volatile ht_slot *)&aPgno[HASHTABLE_NPAGE]; ++ pLoc->aHash = (volatile ht_slot *)&pLoc->aPgno[HASHTABLE_NPAGE]; + if( iHash==0 ){ +- aPgno = &aPgno[WALINDEX_HDR_SIZE/sizeof(u32)]; +- iZero = 0; ++ pLoc->aPgno = &pLoc->aPgno[WALINDEX_HDR_SIZE/sizeof(u32)]; ++ pLoc->iZero = 0; + }else{ +- iZero = HASHTABLE_NPAGE_ONE + (iHash-1)*HASHTABLE_NPAGE; ++ pLoc->iZero = HASHTABLE_NPAGE_ONE + (iHash-1)*HASHTABLE_NPAGE; + } +- +- *paPgno = &aPgno[-1]; +- *paHash = aHash; +- *piZero = iZero; ++ pLoc->aPgno = &pLoc->aPgno[-1]; + } + return rc; + } +@@ -57748,9 +59055,7 @@ + ** actually needed. + */ + static void walCleanupHash(Wal *pWal){ +- volatile ht_slot *aHash = 0; /* Pointer to hash table to clear */ +- volatile u32 *aPgno = 0; /* Page number array for hash table */ +- u32 iZero = 0; /* frame == (aHash[x]+iZero) */ ++ WalHashLoc sLoc; /* Hash table location */ + int iLimit = 0; /* Zero values greater than this */ + int nByte; /* Number of bytes to zero in aPgno[] */ + int i; /* Used to iterate through aHash[] */ +@@ -57768,16 +59073,16 @@ + */ + assert( pWal->nWiData>walFramePage(pWal->hdr.mxFrame) ); + assert( pWal->apWiData[walFramePage(pWal->hdr.mxFrame)] ); +- walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &aHash, &aPgno, &iZero); ++ walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &sLoc); + + /* Zero all hash-table entries that correspond to frame numbers greater + ** than pWal->hdr.mxFrame. + */ +- iLimit = pWal->hdr.mxFrame - iZero; ++ iLimit = pWal->hdr.mxFrame - sLoc.iZero; + assert( iLimit>0 ); + for(i=0; i<HASHTABLE_NSLOT; i++){ +- if( aHash[i]>iLimit ){ +- aHash[i] = 0; ++ if( sLoc.aHash[i]>iLimit ){ ++ sLoc.aHash[i] = 0; + } + } + +@@ -57784,8 +59089,8 @@ + /* Zero the entries in the aPgno array that correspond to frames with + ** frame numbers greater than pWal->hdr.mxFrame. + */ +- nByte = (int)((char *)aHash - (char *)&aPgno[iLimit+1]); +- memset((void *)&aPgno[iLimit+1], 0, nByte); ++ nByte = (int)((char *)sLoc.aHash - (char *)&sLoc.aPgno[iLimit+1]); ++ memset((void *)&sLoc.aPgno[iLimit+1], 0, nByte); + + #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT + /* Verify that the every entry in the mapping region is still reachable +@@ -57795,10 +59100,10 @@ + int j; /* Loop counter */ + int iKey; /* Hash key */ + for(j=1; j<=iLimit; j++){ +- for(iKey=walHash(aPgno[j]); aHash[iKey]; iKey=walNextHash(iKey)){ +- if( aHash[iKey]==j ) break; ++ for(iKey=walHash(sLoc.aPgno[j]);sLoc.aHash[iKey];iKey=walNextHash(iKey)){ ++ if( sLoc.aHash[iKey]==j ) break; + } +- assert( aHash[iKey]==j ); ++ assert( sLoc.aHash[iKey]==j ); + } + } + #endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */ +@@ -57811,11 +59116,9 @@ + */ + static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){ + int rc; /* Return code */ +- u32 iZero = 0; /* One less than frame number of aPgno[1] */ +- volatile u32 *aPgno = 0; /* Page number array */ +- volatile ht_slot *aHash = 0; /* Hash table */ ++ WalHashLoc sLoc; /* Wal-index hash table location */ + +- rc = walHashGet(pWal, walFramePage(iFrame), &aHash, &aPgno, &iZero); ++ rc = walHashGet(pWal, walFramePage(iFrame), &sLoc); + + /* Assuming the wal-index file was successfully mapped, populate the + ** page number array and hash table entry. +@@ -57825,7 +59128,7 @@ + int idx; /* Value to write to hash-table slot */ + int nCollide; /* Number of hash collisions */ + +- idx = iFrame - iZero; ++ idx = iFrame - sLoc.iZero; + assert( idx <= HASHTABLE_NSLOT/2 + 1 ); + + /* If this is the first entry to be added to this hash-table, zero the +@@ -57832,8 +59135,9 @@ + ** entire hash table and aPgno[] array before proceeding. + */ + if( idx==1 ){ +- int nByte = (int)((u8 *)&aHash[HASHTABLE_NSLOT] - (u8 *)&aPgno[1]); +- memset((void*)&aPgno[1], 0, nByte); ++ int nByte = (int)((u8 *)&sLoc.aHash[HASHTABLE_NSLOT] ++ - (u8 *)&sLoc.aPgno[1]); ++ memset((void*)&sLoc.aPgno[1], 0, nByte); + } + + /* If the entry in aPgno[] is already set, then the previous writer +@@ -57842,18 +59146,18 @@ + ** Remove the remnants of that writers uncommitted transaction from + ** the hash-table before writing any new entries. + */ +- if( aPgno[idx] ){ ++ if( sLoc.aPgno[idx] ){ + walCleanupHash(pWal); +- assert( !aPgno[idx] ); ++ assert( !sLoc.aPgno[idx] ); + } + + /* Write the aPgno[] array entry and the hash-table slot. */ + nCollide = idx; +- for(iKey=walHash(iPage); aHash[iKey]; iKey=walNextHash(iKey)){ ++ for(iKey=walHash(iPage); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){ + if( (nCollide--)==0 ) return SQLITE_CORRUPT_BKPT; + } +- aPgno[idx] = iPage; +- aHash[iKey] = (ht_slot)idx; ++ sLoc.aPgno[idx] = iPage; ++ sLoc.aHash[iKey] = (ht_slot)idx; + + #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT + /* Verify that the number of entries in the hash table exactly equals +@@ -57862,7 +59166,7 @@ + { + int i; /* Loop counter */ + int nEntry = 0; /* Number of entries in the hash table */ +- for(i=0; i<HASHTABLE_NSLOT; i++){ if( aHash[i] ) nEntry++; } ++ for(i=0; i<HASHTABLE_NSLOT; i++){ if( sLoc.aHash[i] ) nEntry++; } + assert( nEntry==idx ); + } + +@@ -57874,10 +59178,12 @@ + if( (idx&0x3ff)==0 ){ + int i; /* Loop counter */ + for(i=1; i<=idx; i++){ +- for(iKey=walHash(aPgno[i]); aHash[iKey]; iKey=walNextHash(iKey)){ +- if( aHash[iKey]==i ) break; ++ for(iKey=walHash(sLoc.aPgno[i]); ++ sLoc.aHash[iKey]; ++ iKey=walNextHash(iKey)){ ++ if( sLoc.aHash[iKey]==i ) break; + } +- assert( aHash[iKey]==i ); ++ assert( sLoc.aHash[iKey]==i ); + } + } + #endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */ +@@ -58415,33 +59721,31 @@ + } + + for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && i<nSegment; i++){ +- volatile ht_slot *aHash; +- u32 iZero; +- volatile u32 *aPgno; ++ WalHashLoc sLoc; + +- rc = walHashGet(pWal, i, &aHash, &aPgno, &iZero); ++ rc = walHashGet(pWal, i, &sLoc); + if( rc==SQLITE_OK ){ + int j; /* Counter variable */ + int nEntry; /* Number of entries in this segment */ + ht_slot *aIndex; /* Sorted index for this segment */ + +- aPgno++; ++ sLoc.aPgno++; + if( (i+1)==nSegment ){ +- nEntry = (int)(iLast - iZero); ++ nEntry = (int)(iLast - sLoc.iZero); + }else{ +- nEntry = (int)((u32*)aHash - (u32*)aPgno); ++ nEntry = (int)((u32*)sLoc.aHash - (u32*)sLoc.aPgno); + } +- aIndex = &((ht_slot *)&p->aSegment[p->nSegment])[iZero]; +- iZero++; ++ aIndex = &((ht_slot *)&p->aSegment[p->nSegment])[sLoc.iZero]; ++ sLoc.iZero++; + + for(j=0; j<nEntry; j++){ + aIndex[j] = (ht_slot)j; + } +- walMergesort((u32 *)aPgno, aTmp, aIndex, &nEntry); +- p->aSegment[i].iZero = iZero; ++ walMergesort((u32 *)sLoc.aPgno, aTmp, aIndex, &nEntry); ++ p->aSegment[i].iZero = sLoc.iZero; + p->aSegment[i].nEntry = nEntry; + p->aSegment[i].aIndex = aIndex; +- p->aSegment[i].aPgno = (u32 *)aPgno; ++ p->aSegment[i].aPgno = (u32 *)sLoc.aPgno; + } + } + sqlite3_free(aTmp); +@@ -58616,7 +59920,6 @@ + if( pIter + && (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0),1))==SQLITE_OK + ){ +- i64 nSize; /* Current size of database file */ + u32 nBackfill = pInfo->nBackfill; + + pInfo->nBackfillAttempted = mxSafeFrame; +@@ -58629,6 +59932,7 @@ + */ + if( rc==SQLITE_OK ){ + i64 nReq = ((i64)mxPage * szPage); ++ i64 nSize; /* Current size of database file */ + rc = sqlite3OsFileSize(pWal->pDbFd, &nSize); + if( rc==SQLITE_OK && nSize<nReq ){ + sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq); +@@ -59336,7 +60640,7 @@ + } + #endif + for(i=1; i<WAL_NREADER; i++){ +- u32 thisMark = pInfo->aReadMark[i]; ++ u32 thisMark = AtomicLoad(pInfo->aReadMark+i); + if( mxReadMark<=thisMark && thisMark<=mxFrame ){ + assert( thisMark!=READMARK_NOT_USED ); + mxReadMark = thisMark; +@@ -59349,7 +60653,7 @@ + for(i=1; i<WAL_NREADER; i++){ + rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1); + if( rc==SQLITE_OK ){ +- mxReadMark = pInfo->aReadMark[i] = mxFrame; ++ mxReadMark = AtomicStore(pInfo->aReadMark+i,mxFrame); + mxI = i; + walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); + break; +@@ -59401,9 +60705,9 @@ + ** we can guarantee that the checkpointer that set nBackfill could not + ** see any pages past pWal->hdr.mxFrame, this problem does not come up. + */ +- pWal->minFrame = pInfo->nBackfill+1; ++ pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1; + walShmBarrier(pWal); +- if( pInfo->aReadMark[mxI]!=mxReadMark ++ if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark + || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) + ){ + walUnlockShared(pWal, WAL_READ_LOCK(mxI)); +@@ -59454,16 +60758,14 @@ + }else{ + u32 i = pInfo->nBackfillAttempted; + for(i=pInfo->nBackfillAttempted; i>pInfo->nBackfill; i--){ +- volatile ht_slot *dummy; +- volatile u32 *aPgno; /* Array of page numbers */ +- u32 iZero; /* Frame corresponding to aPgno[0] */ ++ WalHashLoc sLoc; /* Hash table location */ + u32 pgno; /* Page number in db file */ + i64 iDbOff; /* Offset of db file entry */ + i64 iWalOff; /* Offset of wal file entry */ + +- rc = walHashGet(pWal, walFramePage(i), &dummy, &aPgno, &iZero); ++ rc = walHashGet(pWal, walFramePage(i), &sLoc); + if( rc!=SQLITE_OK ) break; +- pgno = aPgno[i-iZero]; ++ pgno = sLoc.aPgno[i-sLoc.iZero]; + iDbOff = (i64)(pgno-1) * szPage; + + if( iDbOff+szPage<=szDb ){ +@@ -59504,7 +60806,7 @@ + ** + ** If the database contents have changes since the previous read + ** transaction, then *pChanged is set to 1 before returning. The +-** Pager layer will use this to know that is cache is stale and ++** Pager layer will use this to know that its cache is stale and + ** needs to be flushed. + */ + SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ +@@ -59566,7 +60868,7 @@ + /* Check that the wal file has not been wrapped. Assuming that it has + ** not, also check that no checkpointer has attempted to checkpoint any + ** frames beyond pSnapshot->mxFrame. If either of these conditions are +- ** true, return SQLITE_BUSY_SNAPSHOT. Otherwise, overwrite pWal->hdr ++ ** true, return SQLITE_ERROR_SNAPSHOT. Otherwise, overwrite pWal->hdr + ** with *pSnapshot and set *pChanged as appropriate for opening the + ** snapshot. */ + if( !memcmp(pSnapshot->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)) +@@ -59576,11 +60878,12 @@ + memcpy(&pWal->hdr, pSnapshot, sizeof(WalIndexHdr)); + *pChanged = bChanged; + }else{ +- rc = SQLITE_BUSY_SNAPSHOT; ++ rc = SQLITE_ERROR_SNAPSHOT; + } + + /* Release the shared CKPT lock obtained above. */ + walUnlockShared(pWal, WAL_CKPT_LOCK); ++ pWal->minFrame = 1; + } + + +@@ -59664,21 +60967,20 @@ + */ + iMinHash = walFramePage(pWal->minFrame); + for(iHash=walFramePage(iLast); iHash>=iMinHash; iHash--){ +- volatile ht_slot *aHash; /* Pointer to hash table */ +- volatile u32 *aPgno; /* Pointer to array of page numbers */ +- u32 iZero; /* Frame number corresponding to aPgno[0] */ ++ WalHashLoc sLoc; /* Hash table location */ + int iKey; /* Hash slot index */ + int nCollide; /* Number of hash collisions remaining */ + int rc; /* Error code */ + +- rc = walHashGet(pWal, iHash, &aHash, &aPgno, &iZero); ++ rc = walHashGet(pWal, iHash, &sLoc); + if( rc!=SQLITE_OK ){ + return rc; + } + nCollide = HASHTABLE_NSLOT; +- for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){ +- u32 iFrame = aHash[iKey] + iZero; +- if( iFrame<=iLast && iFrame>=pWal->minFrame && aPgno[aHash[iKey]]==pgno ){ ++ for(iKey=walHash(pgno); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){ ++ u32 iFrame = sLoc.aHash[iKey] + sLoc.iZero; ++ if( iFrame<=iLast && iFrame>=pWal->minFrame ++ && sLoc.aPgno[sLoc.aHash[iKey]]==pgno ){ + assert( iFrame>iRead || CORRUPT_DB ); + iRead = iFrame; + } +@@ -60553,6 +61855,43 @@ + if( pHdr1->mxFrame>pHdr2->mxFrame ) return +1; + return 0; + } ++ ++/* ++** The caller currently has a read transaction open on the database. ++** This function takes a SHARED lock on the CHECKPOINTER slot and then ++** checks if the snapshot passed as the second argument is still ++** available. If so, SQLITE_OK is returned. ++** ++** If the snapshot is not available, SQLITE_ERROR is returned. Or, if ++** the CHECKPOINTER lock cannot be obtained, SQLITE_BUSY. If any error ++** occurs (any value other than SQLITE_OK is returned), the CHECKPOINTER ++** lock is released before returning. ++*/ ++SQLITE_PRIVATE int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot){ ++ int rc; ++ rc = walLockShared(pWal, WAL_CKPT_LOCK); ++ if( rc==SQLITE_OK ){ ++ WalIndexHdr *pNew = (WalIndexHdr*)pSnapshot; ++ if( memcmp(pNew->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)) ++ || pNew->mxFrame<walCkptInfo(pWal)->nBackfillAttempted ++ ){ ++ rc = SQLITE_ERROR_SNAPSHOT; ++ walUnlockShared(pWal, WAL_CKPT_LOCK); ++ } ++ } ++ return rc; ++} ++ ++/* ++** Release a lock obtained by an earlier successful call to ++** sqlite3WalSnapshotCheck(). ++*/ ++SQLITE_PRIVATE void sqlite3WalSnapshotUnlock(Wal *pWal){ ++ assert( pWal ); ++ walUnlockShared(pWal, WAL_CKPT_LOCK); ++} ++ ++ + #endif /* SQLITE_ENABLE_SNAPSHOT */ + + #ifdef SQLITE_ENABLE_ZIPVFS +@@ -61482,10 +62821,10 @@ + skipOk = 0; + } + } +- db->skipBtreeMutex = skipOk; ++ db->noSharedCache = skipOk; + } + SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3 *db){ +- if( db->skipBtreeMutex==0 ) btreeEnterAll(db); ++ if( db->noSharedCache==0 ) btreeEnterAll(db); + } + static void SQLITE_NOINLINE btreeLeaveAll(sqlite3 *db){ + int i; +@@ -61497,7 +62836,7 @@ + } + } + SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3 *db){ +- if( db->skipBtreeMutex==0 ) btreeLeaveAll(db); ++ if( db->noSharedCache==0 ) btreeLeaveAll(db); + } + + #ifndef NDEBUG +@@ -62462,7 +63801,11 @@ + ** back to where it ought to be if this routine returns true. + */ + SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor *pCur){ +- return pCur->eState!=CURSOR_VALID; ++ assert( EIGHT_BYTE_ALIGNMENT(pCur) ++ || pCur==sqlite3BtreeFakeValidCursor() ); ++ assert( offsetof(BtCursor, eState)==0 ); ++ assert( sizeof(pCur->eState)==1 ); ++ return CURSOR_VALID != *(u8*)pCur; + } + + /* +@@ -64570,6 +65913,10 @@ + # define setDefaultSyncFlag(pBt,safety_level) + #endif + ++/* Forward declaration */ ++static int newDatabase(BtShared*); ++ ++ + /* + ** Get a reference to pPage1 of the database file. This will + ** also acquire a readlock on that file. +@@ -64601,6 +65948,9 @@ + if( nPage==0 || memcmp(24+(u8*)pPage1->aData, 92+(u8*)pPage1->aData,4)!=0 ){ + nPage = nPageFile; + } ++ if( (pBt->db->flags & SQLITE_ResetDatabase)!=0 ){ ++ nPage = 0; ++ } + if( nPage>0 ){ + u32 pageSize; + u32 usableSize; +@@ -64699,7 +66049,7 @@ + pageSize-usableSize); + return rc; + } +- if( (pBt->db->flags & SQLITE_WriteSchema)==0 && nPage>nPageFile ){ ++ if( sqlite3WritableSchema(pBt->db)==0 && nPage>nPageFile ){ + rc = SQLITE_CORRUPT_BKPT; + goto page1_init_failed; + } +@@ -64887,7 +66237,7 @@ + ** when A already has a read lock, we encourage A to give up and let B + ** proceed. + */ +-SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){ ++SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){ + BtShared *pBt = p->pBt; + int rc = SQLITE_OK; + +@@ -64903,6 +66253,12 @@ + } + assert( pBt->inTransaction==TRANS_WRITE || IfNotOmitAV(pBt->bDoTruncate)==0 ); + ++ if( (p->db->flags & SQLITE_ResetDatabase) ++ && sqlite3PagerIsreadonly(pBt->pPager)==0 ++ ){ ++ pBt->btsFlags &= ~BTS_READ_ONLY; ++ } ++ + /* Write transactions are not possible on a read-only database */ + if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){ + rc = SQLITE_READONLY; +@@ -64962,6 +66318,11 @@ + rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db)); + if( rc==SQLITE_OK ){ + rc = newDatabase(pBt); ++ }else if( rc==SQLITE_BUSY_SNAPSHOT && pBt->inTransaction==TRANS_NONE ){ ++ /* if there was no transaction opened when this function was ++ ** called and SQLITE_BUSY_SNAPSHOT is returned, change the error ++ ** code to SQLITE_BUSY. */ ++ rc = SQLITE_BUSY; + } + } + } +@@ -65013,14 +66374,18 @@ + } + } + +- + trans_begun: +- if( rc==SQLITE_OK && wrflag ){ +- /* This call makes sure that the pager has the correct number of +- ** open savepoints. If the second parameter is greater than 0 and +- ** the sub-journal is not already open, then it will be opened here. +- */ +- rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint); ++ if( rc==SQLITE_OK ){ ++ if( pSchemaVersion ){ ++ *pSchemaVersion = get4byte(&pBt->pPage1->aData[40]); ++ } ++ if( wrflag ){ ++ /* This call makes sure that the pager has the correct number of ++ ** open savepoints. If the second parameter is greater than 0 and ++ ** the sub-journal is not already open, then it will be opened here. ++ */ ++ rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint); ++ } + } + + btreeIntegrity(p); +@@ -65158,6 +66523,7 @@ + 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", +@@ -66329,9 +67695,6 @@ + /* Need to read this page properly. It contains some of the + ** range of data that is being read (eOp==0) or written (eOp!=0). + */ +-#ifdef SQLITE_DIRECT_OVERFLOW_READ +- sqlite3_file *fd; /* File from which to do direct overflow read */ +-#endif + int a = amt; + if( a + offset > ovflSize ){ + a = ovflSize - offset; +@@ -66342,7 +67705,7 @@ + ** + ** 1) this is a read operation, and + ** 2) data is required from the start of this overflow page, and +- ** 3) there is no open write-transaction, and ++ ** 3) there are no dirty pages in the page-cache + ** 4) the database is file-backed, and + ** 5) the page is not in the WAL file + ** 6) at least 4 bytes have already been read into the output buffer +@@ -66353,11 +67716,10 @@ + */ + if( eOp==0 /* (1) */ + && offset==0 /* (2) */ +- && pBt->inTransaction==TRANS_READ /* (3) */ +- && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (4) */ +- && 0==sqlite3PagerUseWal(pBt->pPager, nextPage) /* (5) */ ++ && sqlite3PagerDirectReadOk(pBt->pPager, nextPage) /* (3,4,5) */ + && &pBuf[-4]>=pBufStart /* (6) */ + ){ ++ sqlite3_file *fd = sqlite3PagerFile(pBt->pPager); + u8 aSave[4]; + u8 *aWrite = &pBuf[-4]; + assert( aWrite>=pBufStart ); /* due to (6) */ +@@ -66767,6 +68129,23 @@ + return rc; + } + ++/* ++** This function is a no-op if cursor pCur does not point to a valid row. ++** Otherwise, if pCur is valid, configure it so that the next call to ++** sqlite3BtreeNext() is a no-op. ++*/ ++#ifndef SQLITE_OMIT_WINDOWFUNC ++SQLITE_PRIVATE void sqlite3BtreeSkipNext(BtCursor *pCur){ ++ /* We believe that the cursor must always be in the valid state when ++ ** this routine is called, but the proof is difficult, so we add an ++ ** ALWaYS() test just in case we are wrong. */ ++ if( ALWAYS(pCur->eState==CURSOR_VALID) ){ ++ pCur->eState = CURSOR_SKIPNEXT; ++ pCur->skipNext = 1; ++ } ++} ++#endif /* SQLITE_OMIT_WINDOWFUNC */ ++ + /* Move the cursor to the last entry in the table. Return SQLITE_OK + ** on success. Set *pRes to 0 if the cursor actually points to something + ** or set *pRes to 1 if the table is empty. +@@ -67171,7 +68550,16 @@ + + pPage = pCur->pPage; + idx = ++pCur->ix; +- assert( pPage->isInit ); ++ if( !pPage->isInit ){ ++ /* The only known way for this to happen is for there to be a ++ ** recursive SQL function that does a DELETE operation as part of a ++ ** SELECT which deletes content out from under an active cursor ++ ** in a corrupt database file where the table being DELETE-ed from ++ ** has pages in common with the table being queried. See TH3 ++ ** module cov1/btree78.test testcase 220 (2018-06-08) for an ++ ** example. */ ++ return SQLITE_CORRUPT_BKPT; ++ } + + /* If the database file is corrupt, it is possible for the value of idx + ** to be invalid here. This can only occur if a second cursor modifies +@@ -67817,7 +69205,9 @@ + if( pInfo->nLocal==pInfo->nPayload ){ + return SQLITE_OK; /* No overflow pages. Return without doing anything */ + } +- if( pCell+pInfo->nSize-1 > pPage->aData+pPage->maskPage ){ ++ testcase( pCell + pInfo->nSize == pPage->aDataEnd ); ++ testcase( pCell + (pInfo->nSize-1) == pPage->aDataEnd ); ++ if( pCell + pInfo->nSize > pPage->aDataEnd ){ + /* Cell extends past end of page */ + return SQLITE_CORRUPT_PAGE(pPage); + } +@@ -69743,8 +71133,96 @@ + return rc; + } + ++/* Overwrite content from pX into pDest. Only do the write if the ++** content is different from what is already there. ++*/ ++static int btreeOverwriteContent( ++ MemPage *pPage, /* MemPage on which writing will occur */ ++ u8 *pDest, /* Pointer to the place to start writing */ ++ const BtreePayload *pX, /* Source of data to write */ ++ int iOffset, /* Offset of first byte to write */ ++ int iAmt /* Number of bytes to be written */ ++){ ++ int nData = pX->nData - iOffset; ++ if( nData<=0 ){ ++ /* Overwritting with zeros */ ++ int i; ++ for(i=0; i<iAmt && pDest[i]==0; i++){} ++ if( i<iAmt ){ ++ int rc = sqlite3PagerWrite(pPage->pDbPage); ++ if( rc ) return rc; ++ memset(pDest + i, 0, iAmt - i); ++ } ++ }else{ ++ if( nData<iAmt ){ ++ /* Mixed read data and zeros at the end. Make a recursive call ++ ** to write the zeros then fall through to write the real data */ ++ int rc = btreeOverwriteContent(pPage, pDest+nData, pX, iOffset+nData, ++ iAmt-nData); ++ if( rc ) return rc; ++ iAmt = nData; ++ } ++ if( memcmp(pDest, ((u8*)pX->pData) + iOffset, iAmt)!=0 ){ ++ int rc = sqlite3PagerWrite(pPage->pDbPage); ++ if( rc ) return rc; ++ memcpy(pDest, ((u8*)pX->pData) + iOffset, iAmt); ++ } ++ } ++ return SQLITE_OK; ++} + + /* ++** Overwrite the cell that cursor pCur is pointing to with fresh content ++** contained in pX. ++*/ ++static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){ ++ int iOffset; /* Next byte of pX->pData to write */ ++ int nTotal = pX->nData + pX->nZero; /* Total bytes of to write */ ++ int rc; /* Return code */ ++ MemPage *pPage = pCur->pPage; /* Page being written */ ++ BtShared *pBt; /* Btree */ ++ Pgno ovflPgno; /* Next overflow page to write */ ++ u32 ovflPageSize; /* Size to write on overflow page */ ++ ++ if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd ){ ++ return SQLITE_CORRUPT_BKPT; ++ } ++ /* Overwrite the local portion first */ ++ rc = btreeOverwriteContent(pPage, pCur->info.pPayload, pX, ++ 0, pCur->info.nLocal); ++ if( rc ) return rc; ++ if( pCur->info.nLocal==nTotal ) return SQLITE_OK; ++ ++ /* Now overwrite the overflow pages */ ++ iOffset = pCur->info.nLocal; ++ assert( nTotal>=0 ); ++ assert( iOffset>=0 ); ++ ovflPgno = get4byte(pCur->info.pPayload + iOffset); ++ pBt = pPage->pBt; ++ ovflPageSize = pBt->usableSize - 4; ++ do{ ++ rc = btreeGetPage(pBt, ovflPgno, &pPage, 0); ++ if( rc ) return rc; ++ if( sqlite3PagerPageRefcount(pPage->pDbPage)!=1 ){ ++ rc = SQLITE_CORRUPT_BKPT; ++ }else{ ++ if( iOffset+ovflPageSize<(u32)nTotal ){ ++ ovflPgno = get4byte(pPage->aData); ++ }else{ ++ ovflPageSize = nTotal - iOffset; ++ } ++ rc = btreeOverwriteContent(pPage, pPage->aData+4, pX, ++ iOffset, ovflPageSize); ++ } ++ sqlite3PagerUnref(pPage->pDbPage); ++ if( rc ) return rc; ++ iOffset += ovflPageSize; ++ }while( iOffset<nTotal ); ++ return SQLITE_OK; ++} ++ ++ ++/* + ** Insert a new record into the BTree. The content of the new record + ** is described by the pX object. The pCur cursor is used only to + ** define what table the record should be inserted into, and is left +@@ -69833,35 +71311,86 @@ + invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0); + + /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing +- ** to a row with the same key as the new entry being inserted. */ +- assert( (flags & BTREE_SAVEPOSITION)==0 || +- ((pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey) ); ++ ** to a row with the same key as the new entry being inserted. ++ */ ++#ifdef SQLITE_DEBUG ++ if( flags & BTREE_SAVEPOSITION ){ ++ assert( pCur->curFlags & BTCF_ValidNKey ); ++ assert( pX->nKey==pCur->info.nKey ); ++ assert( pCur->info.nSize!=0 ); ++ assert( loc==0 ); ++ } ++#endif + +- /* If the cursor is currently on the last row and we are appending a +- ** new row onto the end, set the "loc" to avoid an unnecessary +- ** btreeMoveto() call */ ++ /* On the other hand, BTREE_SAVEPOSITION==0 does not imply ++ ** that the cursor is not pointing to a row to be overwritten. ++ ** So do a complete check. ++ */ + if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey ){ +- loc = 0; ++ /* The cursor is pointing to the entry that is to be ++ ** overwritten */ ++ assert( pX->nData>=0 && pX->nZero>=0 ); ++ if( pCur->info.nSize!=0 ++ && pCur->info.nPayload==(u32)pX->nData+pX->nZero ++ ){ ++ /* New entry is the same size as the old. Do an overwrite */ ++ return btreeOverwriteCell(pCur, pX); ++ } ++ assert( loc==0 ); + }else if( loc==0 ){ ++ /* The cursor is *not* pointing to the cell to be overwritten, nor ++ ** to an adjacent cell. Move the cursor so that it is pointing either ++ ** to the cell to be overwritten or an adjacent cell. ++ */ + rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, flags!=0, &loc); + if( rc ) return rc; + } +- }else if( loc==0 && (flags & BTREE_SAVEPOSITION)==0 ){ +- if( pX->nMem ){ +- UnpackedRecord r; +- r.pKeyInfo = pCur->pKeyInfo; +- r.aMem = pX->aMem; +- r.nField = pX->nMem; +- r.default_rc = 0; +- r.errCode = 0; +- r.r1 = 0; +- r.r2 = 0; +- r.eqSeen = 0; +- rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, flags!=0, &loc); +- }else{ +- rc = btreeMoveto(pCur, pX->pKey, pX->nKey, flags!=0, &loc); ++ }else{ ++ /* This is an index or a WITHOUT ROWID table */ ++ ++ /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing ++ ** to a row with the same key as the new entry being inserted. ++ */ ++ assert( (flags & BTREE_SAVEPOSITION)==0 || loc==0 ); ++ ++ /* If the cursor is not already pointing either to the cell to be ++ ** overwritten, or if a new cell is being inserted, if the cursor is ++ ** not pointing to an immediately adjacent cell, then move the cursor ++ ** so that it does. ++ */ ++ if( loc==0 && (flags & BTREE_SAVEPOSITION)==0 ){ ++ if( pX->nMem ){ ++ UnpackedRecord r; ++ r.pKeyInfo = pCur->pKeyInfo; ++ r.aMem = pX->aMem; ++ r.nField = pX->nMem; ++ r.default_rc = 0; ++ r.errCode = 0; ++ r.r1 = 0; ++ r.r2 = 0; ++ r.eqSeen = 0; ++ rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, flags!=0, &loc); ++ }else{ ++ rc = btreeMoveto(pCur, pX->pKey, pX->nKey, flags!=0, &loc); ++ } ++ if( rc ) return rc; + } +- if( rc ) return rc; ++ ++ /* If the cursor is currently pointing to an entry to be overwritten ++ ** and the new content is the same as as the old, then use the ++ ** overwrite optimization. ++ */ ++ if( loc==0 ){ ++ getCellInfo(pCur); ++ if( pCur->info.nKey==pX->nKey ){ ++ BtreePayload x2; ++ x2.pData = pX->pKey; ++ x2.nData = pX->nKey; ++ x2.nZero = 0; ++ return btreeOverwriteCell(pCur, &x2); ++ } ++ } ++ + } + assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) ); + +@@ -70700,14 +72229,14 @@ + pCheck->nErr++; + va_start(ap, zFormat); + if( pCheck->errMsg.nChar ){ +- sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1); ++ sqlite3_str_append(&pCheck->errMsg, "\n", 1); + } + if( pCheck->zPfx ){ +- sqlite3XPrintf(&pCheck->errMsg, pCheck->zPfx, pCheck->v1, pCheck->v2); ++ sqlite3_str_appendf(&pCheck->errMsg, pCheck->zPfx, pCheck->v1, pCheck->v2); + } +- sqlite3VXPrintf(&pCheck->errMsg, zFormat, ap); ++ sqlite3_str_vappendf(&pCheck->errMsg, zFormat, ap); + va_end(ap); +- if( pCheck->errMsg.accError==STRACCUM_NOMEM ){ ++ if( pCheck->errMsg.accError==SQLITE_NOMEM ){ + pCheck->mallocFailed = 1; + } + } +@@ -70742,8 +72271,7 @@ + ** Also check that the page number is in bounds. + */ + static int checkRef(IntegrityCk *pCheck, Pgno iPage){ +- if( iPage==0 ) return 1; +- if( iPage>pCheck->nPage ){ ++ if( iPage>pCheck->nPage || iPage==0 ){ + checkAppendMsg(pCheck, "invalid page number %d", iPage); + return 1; + } +@@ -70798,17 +72326,12 @@ + ){ + int i; + int expected = N; +- int iFirst = iPage; +- while( N-- > 0 && pCheck->mxErr ){ ++ int nErrAtStart = pCheck->nErr; ++ while( iPage!=0 && pCheck->mxErr ){ + DbPage *pOvflPage; + unsigned char *pOvflData; +- if( iPage<1 ){ +- checkAppendMsg(pCheck, +- "%d of %d pages missing from overflow list starting at %d", +- N+1, expected, iFirst); +- break; +- } + if( checkRef(pCheck, iPage) ) break; ++ N--; + if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage, 0) ){ + checkAppendMsg(pCheck, "failed to get page %d", iPage); + break; +@@ -70852,11 +72375,13 @@ + #endif + iPage = get4byte(pOvflData); + sqlite3PagerUnref(pOvflPage); +- +- if( isFreeList && N<(iPage!=0) ){ +- checkAppendMsg(pCheck, "free-page count in header is too small"); +- } + } ++ 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 */ + +@@ -71249,6 +72774,24 @@ + + /* Check all the tables. + */ ++#ifndef SQLITE_OMIT_AUTOVACUUM ++ if( pBt->autoVacuum ){ ++ int mx = 0; ++ int 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" ++ ); ++ } ++#endif + testcase( pBt->db->flags & SQLITE_CellSizeCk ); + pBt->db->flags &= ~SQLITE_CellSizeCk; + for(i=0; (int)i<nRoot && sCheck.mxErr; i++){ +@@ -71291,11 +72834,11 @@ + sqlite3PageFree(sCheck.heap); + sqlite3_free(sCheck.aPgRef); + if( sCheck.mallocFailed ){ +- sqlite3StrAccumReset(&sCheck.errMsg); ++ sqlite3_str_reset(&sCheck.errMsg); + sCheck.nErr++; + } + *pnErr = sCheck.nErr; +- if( sCheck.nErr==0 ) sqlite3StrAccumReset(&sCheck.errMsg); ++ if( sCheck.nErr==0 ) sqlite3_str_reset(&sCheck.errMsg); + /* Make sure this analysis did not leave any unref() pages. */ + assert( nRef==sqlite3PagerRefcount(pBt->pPager) ); + sqlite3BtreeLeave(p); +@@ -71530,11 +73073,11 @@ + pBt->btsFlags &= ~BTS_NO_WAL; + if( iVersion==1 ) pBt->btsFlags |= BTS_NO_WAL; + +- rc = sqlite3BtreeBeginTrans(pBtree, 0); ++ rc = sqlite3BtreeBeginTrans(pBtree, 0, 0); + if( rc==SQLITE_OK ){ + u8 *aData = pBt->pPage1->aData; + if( aData[18]!=(u8)iVersion || aData[19]!=(u8)iVersion ){ +- rc = sqlite3BtreeBeginTrans(pBtree, 2); ++ rc = sqlite3BtreeBeginTrans(pBtree, 2, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); + if( rc==SQLITE_OK ){ +@@ -71974,7 +73517,7 @@ + ** before this function exits. + */ + if( rc==SQLITE_OK && 0==sqlite3BtreeIsInReadTrans(p->pSrc) ){ +- rc = sqlite3BtreeBeginTrans(p->pSrc, 0); ++ rc = sqlite3BtreeBeginTrans(p->pSrc, 0, 0); + bCloseTrans = 1; + } + +@@ -71990,10 +73533,10 @@ + + /* Lock the destination database, if it is not locked already. */ + if( SQLITE_OK==rc && p->bDestLocked==0 +- && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2)) ++ && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2, ++ (int*)&p->iDestSchema)) + ){ + p->bDestLocked = 1; +- sqlite3BtreeGetMeta(p->pDest, BTREE_SCHEMA_VERSION, &p->iDestSchema); + } + + /* Do not allow backup if the destination database is in WAL mode +@@ -72437,8 +73980,7 @@ + + if( p->flags & MEM_Null ){ + /* Cannot be both MEM_Null and some other type */ +- assert( (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob +- |MEM_RowSet|MEM_Frame|MEM_Agg))==0 ); ++ assert( (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob|MEM_Agg))==0 ); + + /* If MEM_Null is set, then either the value is a pure NULL (the usual + ** case) or it is a pointer set using sqlite3_bind_pointer() or +@@ -72551,7 +74093,7 @@ + #ifndef SQLITE_OMIT_UTF16 + int rc; + #endif +- assert( (pMem->flags&MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pMem) ); + assert( desiredEnc==SQLITE_UTF8 || desiredEnc==SQLITE_UTF16LE + || desiredEnc==SQLITE_UTF16BE ); + if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){ +@@ -72584,7 +74126,7 @@ + */ + SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ + assert( sqlite3VdbeCheckMemInvariants(pMem) ); +- assert( (pMem->flags&MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pMem) ); + testcase( pMem->db==0 ); + + /* If the bPreserve flag is set to true, then the memory cell must already +@@ -72672,7 +74214,7 @@ + */ + SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){ + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); +- assert( (pMem->flags&MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pMem) ); + if( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ){ + if( ExpandBlob(pMem) ) return SQLITE_NOMEM; + if( pMem->szMalloc==0 || pMem->z!=pMem->zMalloc ){ +@@ -72697,7 +74239,7 @@ + int nByte; + assert( pMem->flags & MEM_Zero ); + assert( pMem->flags&MEM_Blob ); +- assert( (pMem->flags&MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pMem) ); + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + + /* Set nByte to the number of bytes required to store the expanded blob. */ +@@ -72752,7 +74294,7 @@ + assert( !(fg&MEM_Zero) ); + assert( !(fg&(MEM_Str|MEM_Blob)) ); + assert( fg&(MEM_Int|MEM_Real) ); +- assert( (pMem->flags&MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pMem) ); + assert( EIGHT_BYTE_ALIGNMENT(pMem) ); + + +@@ -72773,7 +74315,8 @@ + assert( fg & MEM_Real ); + sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->u.r); + } +- pMem->n = sqlite3Strlen30(pMem->z); ++ assert( pMem->z!=0 ); ++ pMem->n = sqlite3Strlen30NN(pMem->z); + pMem->enc = SQLITE_UTF8; + pMem->flags |= MEM_Str|MEM_Term; + if( bForce ) pMem->flags &= ~(MEM_Int|MEM_Real); +@@ -72811,6 +74354,35 @@ + } + + /* ++** Memory cell pAccum contains the context of an aggregate function. ++** This routine calls the xValue method for that function and stores ++** the results in memory cell pMem. ++** ++** SQLITE_ERROR is returned if xValue() reports an error. SQLITE_OK ++** otherwise. ++*/ ++#ifndef SQLITE_OMIT_WINDOWFUNC ++SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem *pAccum, Mem *pOut, FuncDef *pFunc){ ++ sqlite3_context ctx; ++ Mem t; ++ assert( pFunc!=0 ); ++ assert( pFunc->xValue!=0 ); ++ assert( (pAccum->flags & MEM_Null)!=0 || pFunc==pAccum->u.pDef ); ++ assert( pAccum->db==0 || sqlite3_mutex_held(pAccum->db->mutex) ); ++ memset(&ctx, 0, sizeof(ctx)); ++ memset(&t, 0, sizeof(t)); ++ t.flags = MEM_Null; ++ t.db = pAccum->db; ++ sqlite3VdbeMemSetNull(pOut); ++ ctx.pOut = pOut; ++ ctx.pMem = pAccum; ++ ctx.pFunc = pFunc; ++ pFunc->xValue(&ctx); ++ return ctx.isError; ++} ++#endif /* SQLITE_OMIT_WINDOWFUNC */ ++ ++/* + ** If the memory cell contains a value that must be freed by + ** invoking the external callback in Mem.xDel, then this routine + ** will free that value. It also sets Mem.flags to MEM_Null. +@@ -72828,15 +74400,8 @@ + testcase( p->flags & MEM_Dyn ); + } + if( p->flags&MEM_Dyn ){ +- assert( (p->flags&MEM_RowSet)==0 ); + assert( p->xDel!=SQLITE_DYNAMIC && p->xDel!=0 ); + p->xDel((void *)p->z); +- }else if( p->flags&MEM_RowSet ){ +- sqlite3RowSetClear(p->u.pRowSet); +- }else if( p->flags&MEM_Frame ){ +- VdbeFrame *pFrame = p->u.pFrame; +- pFrame->pParent = pFrame->v->pDelFrame; +- pFrame->v->pDelFrame = pFrame; + } + p->flags = MEM_Null; + } +@@ -72984,7 +74549,7 @@ + SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem *pMem){ + i64 ix; + assert( pMem->flags & MEM_Real ); +- assert( (pMem->flags & MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pMem) ); + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + assert( EIGHT_BYTE_ALIGNMENT(pMem) ); + +@@ -73011,7 +74576,7 @@ + */ + SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem *pMem){ + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); +- assert( (pMem->flags & MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pMem) ); + assert( EIGHT_BYTE_ALIGNMENT(pMem) ); + + pMem->u.i = sqlite3VdbeIntValue(pMem); +@@ -73195,7 +74760,7 @@ + } + + /* A no-op destructor */ +-static void sqlite3NoopDestructor(void *p){ UNUSED_PARAMETER(p); } ++SQLITE_PRIVATE void sqlite3NoopDestructor(void *p){ UNUSED_PARAMETER(p); } + + /* + ** Set the value stored in *pMem should already be a NULL. +@@ -73229,26 +74794,36 @@ + } + #endif + ++#ifdef SQLITE_DEBUG + /* ++** Return true if the Mem holds a RowSet object. This routine is intended ++** for use inside of assert() statements. ++*/ ++SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem *pMem){ ++ return (pMem->flags&(MEM_Blob|MEM_Dyn))==(MEM_Blob|MEM_Dyn) ++ && pMem->xDel==sqlite3RowSetDelete; ++} ++#endif ++ ++/* + ** Delete any previous value and set the value of pMem to be an + ** empty boolean index. ++** ++** Return SQLITE_OK on success and SQLITE_NOMEM if a memory allocation ++** error occurs. + */ +-SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem *pMem){ ++SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem *pMem){ + sqlite3 *db = pMem->db; ++ RowSet *p; + assert( db!=0 ); +- assert( (pMem->flags & MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pMem) ); + sqlite3VdbeMemRelease(pMem); +- pMem->zMalloc = sqlite3DbMallocRawNN(db, 64); +- if( db->mallocFailed ){ +- pMem->flags = MEM_Null; +- pMem->szMalloc = 0; +- }else{ +- assert( pMem->zMalloc ); +- pMem->szMalloc = sqlite3DbMallocSize(db, pMem->zMalloc); +- pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc, pMem->szMalloc); +- assert( pMem->u.pRowSet!=0 ); +- pMem->flags = MEM_RowSet; +- } ++ p = sqlite3RowSetInit(db); ++ if( p==0 ) return SQLITE_NOMEM; ++ pMem->z = (char*)p; ++ pMem->flags = MEM_Blob|MEM_Dyn; ++ pMem->xDel = sqlite3RowSetDelete; ++ return SQLITE_OK; + } + + /* +@@ -73281,7 +74856,21 @@ + Mem *pX; + for(i=0, pX=pVdbe->aMem; i<pVdbe->nMem; i++, pX++){ + if( pX->pScopyFrom==pMem ){ +- pX->flags |= MEM_Undefined; ++ /* If pX is marked as a shallow copy of pMem, then verify that ++ ** no significant changes have been made to pX since the OP_SCopy. ++ ** A significant change would indicated a missed call to this ++ ** function for pX. Minor changes, such as adding or removing a ++ ** dual type, are allowed, as long as the underlying value is the ++ ** same. */ ++ u16 mFlags = pMem->flags & pX->flags & pX->mScopyFlags; ++ assert( (mFlags&MEM_Int)==0 || pMem->u.i==pX->u.i ); ++ assert( (mFlags&MEM_Real)==0 || pMem->u.r==pX->u.r ); ++ assert( (mFlags&MEM_Str)==0 || (pMem->n==pX->n && pMem->z==pX->z) ); ++ assert( (mFlags&MEM_Blob)==0 || sqlite3BlobCompare(pMem,pX)==0 ); ++ ++ /* pMem is the register that is changing. But also mark pX as ++ ** undefined so that we can quickly detect the shallow-copy error */ ++ pX->flags = MEM_Undefined; + pX->pScopyFrom = 0; + } + } +@@ -73302,7 +74891,7 @@ + sqlite3VdbeMemShallowCopy(pTo, pFrom, eType); + } + SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){ +- assert( (pFrom->flags & MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pFrom) ); + assert( pTo->db==pFrom->db ); + if( VdbeMemDynamic(pTo) ){ vdbeClrCopy(pTo,pFrom,srcType); return; } + memcpy(pTo, pFrom, MEMCELLSIZE); +@@ -73320,7 +74909,7 @@ + SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){ + int rc = SQLITE_OK; + +- assert( (pFrom->flags & MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pFrom) ); + if( VdbeMemDynamic(pTo) ) vdbeMemClearExternAndSetNull(pTo); + memcpy(pTo, pFrom, MEMCELLSIZE); + pTo->flags &= ~MEM_Dyn; +@@ -73378,7 +74967,7 @@ + u16 flags = 0; /* New value for pMem->flags */ + + assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); +- assert( (pMem->flags & MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pMem) ); + + /* If z is a NULL pointer, set pMem to contain an SQL NULL. */ + if( !z ){ +@@ -73500,7 +75089,7 @@ + + /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert() + ** that both the BtShared and database handle mutexes are held. */ +- assert( (pMem->flags & MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pMem) ); + zData = (char *)sqlite3BtreePayloadFetch(pCur, &available); + assert( zData!=0 ); + +@@ -73524,7 +75113,7 @@ + assert( pVal!=0 ); + assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) ); + assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) ); +- assert( (pVal->flags & MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pVal) ); + assert( (pVal->flags & (MEM_Null))==0 ); + if( pVal->flags & (MEM_Blob|MEM_Str) ){ + if( ExpandBlob(pVal) ) return 0; +@@ -73567,7 +75156,7 @@ + if( !pVal ) return 0; + assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) ); + assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) ); +- assert( (pVal->flags & MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pVal) ); + if( (pVal->flags&(MEM_Str|MEM_Term))==(MEM_Str|MEM_Term) && pVal->enc==enc ){ + assert( sqlite3VdbeMemConsistentDualRep(pVal) ); + return pVal->z; +@@ -73873,12 +75462,16 @@ + 0, SQLITE_DYNAMIC); + } + #endif +- + #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + else if( op==TK_FUNCTION && pCtx!=0 ){ + rc = valueFromFunction(db, pExpr, enc, affinity, &pVal, pCtx); + } + #endif ++ else if( op==TK_TRUEFALSE ){ ++ pVal = valueNew(db, pCtx); ++ pVal->flags = MEM_Int; ++ pVal->u.i = pExpr->u.zToken[4]==0; ++ } + + *ppVal = pVal; + return rc; +@@ -74130,11 +75723,11 @@ + int iCol, /* Column to extract */ + sqlite3_value **ppVal /* OUT: Extracted value */ + ){ +- u32 t; /* a column type code */ ++ u32 t = 0; /* a column type code */ + int nHdr; /* Size of the header in the record */ + int iHdr; /* Next unread header byte */ + int iField; /* Next unread data byte */ +- int szField; /* Size of the current data field */ ++ int szField = 0; /* Size of the current data field */ + int i; /* Column index */ + u8 *a = (u8*)pRec; /* Typecast byte array */ + Mem *pMem = *ppVal; /* Write result into this Mem object */ +@@ -74298,6 +75891,13 @@ + } + assert( p->zSql==0 ); + p->zSql = sqlite3DbStrNDup(p->db, z, n); ++#ifdef SQLITE_ENABLE_NORMALIZE ++ assert( p->zNormSql==0 ); ++ if( p->zSql && (prepFlags & SQLITE_PREPARE_NORMALIZE)!=0 ){ ++ sqlite3Normalize(p, p->zSql, n, prepFlags); ++ assert( p->zNormSql!=0 || p->db->mallocFailed ); ++ } ++#endif + } + + /* +@@ -74319,6 +75919,11 @@ + zTmp = pA->zSql; + pA->zSql = pB->zSql; + pB->zSql = zTmp; ++#ifdef SQLITE_ENABLE_NORMALIZE ++ zTmp = pA->zNormSql; ++ pA->zNormSql = pB->zNormSql; ++ pB->zNormSql = zTmp; ++#endif + pB->expmask = pA->expmask; + pB->prepFlags = pA->prepFlags; + memcpy(pB->aCounter, pA->aCounter, sizeof(pB->aCounter)); +@@ -74427,14 +76032,6 @@ + #endif + #ifdef SQLITE_DEBUG + if( p->db->flags & SQLITE_VdbeAddopTrace ){ +- int jj, kk; +- Parse *pParse = p->pParse; +- for(jj=kk=0; jj<pParse->nColCache; jj++){ +- struct yColCache *x = pParse->aColCache + jj; +- printf(" r[%d]={%d:%d}", x->iReg, x->iTable, x->iColumn); +- kk++; +- } +- if( kk ) printf("\n"); + sqlite3VdbePrintOp(0, i, &p->aOp[i]); + test_addop_breakpoint(); + } +@@ -74537,7 +76134,50 @@ + return sqlite3VdbeAddOp4(p, op, p1, p2, p3, p4copy, p4type); + } + ++#ifndef SQLITE_OMIT_EXPLAIN + /* ++** Return the address of the current EXPLAIN QUERY PLAN baseline. ++** 0 means "none". ++*/ ++SQLITE_PRIVATE int sqlite3VdbeExplainParent(Parse *pParse){ ++ VdbeOp *pOp; ++ if( pParse->addrExplain==0 ) return 0; ++ pOp = sqlite3VdbeGetOp(pParse->pVdbe, pParse->addrExplain); ++ return pOp->p2; ++} ++ ++/* ++** 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. ++*/ ++SQLITE_PRIVATE void sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){ ++ if( pParse->explain==2 ){ ++ char *zMsg; ++ Vdbe *v; ++ va_list ap; ++ int iThis; ++ va_start(ap, zFmt); ++ zMsg = sqlite3VMPrintf(pParse->db, zFmt, ap); ++ va_end(ap); ++ v = pParse->pVdbe; ++ iThis = v->nOp; ++ sqlite3VdbeAddOp4(v, OP_Explain, iThis, pParse->addrExplain, 0, ++ zMsg, P4_DYNAMIC); ++ if( bPush) pParse->addrExplain = iThis; ++ } ++} ++ ++/* ++** Pop the EXPLAIN QUERY PLAN stack one level. ++*/ ++SQLITE_PRIVATE void sqlite3VdbeExplainPop(Parse *pParse){ ++ pParse->addrExplain = sqlite3VdbeExplainParent(pParse); ++} ++#endif /* SQLITE_OMIT_EXPLAIN */ ++ ++/* + ** Add an OP_ParseSchema opcode. This routine is broken out from + ** sqlite3VdbeAddOp4() since it needs to also needs to mark all btrees + ** as having been used. +@@ -74626,6 +76266,12 @@ + assert( j<p->nLabel ); + assert( j>=0 ); + if( p->aLabel ){ ++#ifdef SQLITE_DEBUG ++ if( p->db->flags & SQLITE_VdbeAddopTrace ){ ++ printf("RESOLVE LABEL %d to %d\n", x, v->nOp); ++ } ++#endif ++ assert( p->aLabel[j]==(-1) ); /* Labels may only be resolved once */ + p->aLabel[j] = v->nOp; + } + } +@@ -74775,7 +76421,33 @@ + } + #endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */ + ++#ifdef SQLITE_DEBUG + /* ++** Increment the nWrite counter in the VDBE if the cursor is not an ++** ephemeral cursor, or if the cursor argument is NULL. ++*/ ++SQLITE_PRIVATE void sqlite3VdbeIncrWriteCounter(Vdbe *p, VdbeCursor *pC){ ++ if( pC==0 ++ || (pC->eCurType!=CURTYPE_SORTER ++ && pC->eCurType!=CURTYPE_PSEUDO ++ && !pC->isEphemeral) ++ ){ ++ p->nWrite++; ++ } ++} ++#endif ++ ++#ifdef SQLITE_DEBUG ++/* ++** Assert if an Abort at this point in time might result in a corrupt ++** database. ++*/ ++SQLITE_PRIVATE void sqlite3VdbeAssertAbortable(Vdbe *p){ ++ assert( p->nWrite==0 || p->usesStmtJournal ); ++} ++#endif ++ ++/* + ** This routine is called after all opcodes have been inserted. It loops + ** through all the opcodes and fixes up some details. + ** +@@ -74835,7 +76507,6 @@ + break; + } + case OP_Next: +- case OP_NextIfOpen: + case OP_SorterNext: { + pOp->p4.xAdvance = sqlite3BtreeNext; + pOp->p4type = P4_ADVANCE; +@@ -74845,8 +76516,7 @@ + assert( pOp->p2>=0 ); + break; + } +- case OP_Prev: +- case OP_PrevIfOpen: { ++ case OP_Prev: { + pOp->p4.xAdvance = sqlite3BtreePrevious; + pOp->p4type = P4_ADVANCE; + /* The code generator never codes any of these opcodes as a jump +@@ -74935,6 +76605,17 @@ + #endif + + /* ++** Generate code (a single OP_Abortable opcode) that will ++** verify that the VDBE program can safely call Abort in the current ++** context. ++*/ ++#if defined(SQLITE_DEBUG) ++SQLITE_PRIVATE void sqlite3VdbeVerifyAbortable(Vdbe *p, int onError){ ++ if( onError==OE_Abort ) sqlite3VdbeAddOp0(p, OP_Abortable); ++} ++#endif ++ ++/* + ** This function returns a pointer to the array of opcodes associated with + ** the Vdbe passed as the first argument. It is the callers responsibility + ** to arrange for the returned array to be eventually freed using the +@@ -75478,23 +77159,23 @@ + const char *zOp = 0; + switch( pExpr->op ){ + case TK_STRING: +- sqlite3XPrintf(p, "%Q", pExpr->u.zToken); ++ sqlite3_str_appendf(p, "%Q", pExpr->u.zToken); + break; + case TK_INTEGER: +- sqlite3XPrintf(p, "%d", pExpr->u.iValue); ++ sqlite3_str_appendf(p, "%d", pExpr->u.iValue); + break; + case TK_NULL: +- sqlite3XPrintf(p, "NULL"); ++ sqlite3_str_appendf(p, "NULL"); + break; + case TK_REGISTER: { +- sqlite3XPrintf(p, "r[%d]", pExpr->iTable); ++ sqlite3_str_appendf(p, "r[%d]", pExpr->iTable); + break; + } + case TK_COLUMN: { + if( pExpr->iColumn<0 ){ +- sqlite3XPrintf(p, "rowid"); ++ sqlite3_str_appendf(p, "rowid"); + }else{ +- sqlite3XPrintf(p, "c%d", (int)pExpr->iColumn); ++ sqlite3_str_appendf(p, "c%d", (int)pExpr->iColumn); + } + break; + } +@@ -75526,18 +77207,18 @@ + case TK_NOTNULL: zOp = "NOTNULL"; break; + + default: +- sqlite3XPrintf(p, "%s", "expr"); ++ sqlite3_str_appendf(p, "%s", "expr"); + break; + } + + if( zOp ){ +- sqlite3XPrintf(p, "%s(", zOp); ++ sqlite3_str_appendf(p, "%s(", zOp); + displayP4Expr(p, pExpr->pLeft); + if( pExpr->pRight ){ +- sqlite3StrAccumAppend(p, ",", 1); ++ sqlite3_str_append(p, ",", 1); + displayP4Expr(p, pExpr->pRight); + } +- sqlite3StrAccumAppend(p, ")", 1); ++ sqlite3_str_append(p, ")", 1); + } + } + #endif /* VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) */ +@@ -75558,14 +77239,15 @@ + int j; + KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; + assert( pKeyInfo->aSortOrder!=0 ); +- sqlite3XPrintf(&x, "k(%d", pKeyInfo->nKeyField); ++ sqlite3_str_appendf(&x, "k(%d", pKeyInfo->nKeyField); + for(j=0; j<pKeyInfo->nKeyField; j++){ + CollSeq *pColl = pKeyInfo->aColl[j]; + const char *zColl = pColl ? pColl->zName : ""; + if( strcmp(zColl, "BINARY")==0 ) zColl = "B"; +- sqlite3XPrintf(&x, ",%s%s", pKeyInfo->aSortOrder[j] ? "-" : "", zColl); ++ sqlite3_str_appendf(&x, ",%s%s", ++ pKeyInfo->aSortOrder[j] ? "-" : "", zColl); + } +- sqlite3StrAccumAppend(&x, ")", 1); ++ sqlite3_str_append(&x, ")", 1); + break; + } + #ifdef SQLITE_ENABLE_CURSOR_HINTS +@@ -75576,31 +77258,31 @@ + #endif + case P4_COLLSEQ: { + CollSeq *pColl = pOp->p4.pColl; +- sqlite3XPrintf(&x, "(%.20s)", pColl->zName); ++ sqlite3_str_appendf(&x, "(%.20s)", pColl->zName); + break; + } + case P4_FUNCDEF: { + FuncDef *pDef = pOp->p4.pFunc; +- sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg); ++ sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg); + break; + } + #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) + case P4_FUNCCTX: { + FuncDef *pDef = pOp->p4.pCtx->pFunc; +- sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg); ++ sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg); + break; + } + #endif + case P4_INT64: { +- sqlite3XPrintf(&x, "%lld", *pOp->p4.pI64); ++ sqlite3_str_appendf(&x, "%lld", *pOp->p4.pI64); + break; + } + case P4_INT32: { +- sqlite3XPrintf(&x, "%d", pOp->p4.i); ++ sqlite3_str_appendf(&x, "%d", pOp->p4.i); + break; + } + case P4_REAL: { +- sqlite3XPrintf(&x, "%.16g", *pOp->p4.pReal); ++ sqlite3_str_appendf(&x, "%.16g", *pOp->p4.pReal); + break; + } + case P4_MEM: { +@@ -75608,9 +77290,9 @@ + if( pMem->flags & MEM_Str ){ + zP4 = pMem->z; + }else if( pMem->flags & MEM_Int ){ +- sqlite3XPrintf(&x, "%lld", pMem->u.i); ++ sqlite3_str_appendf(&x, "%lld", pMem->u.i); + }else if( pMem->flags & MEM_Real ){ +- sqlite3XPrintf(&x, "%.16g", pMem->u.r); ++ sqlite3_str_appendf(&x, "%.16g", pMem->u.r); + }else if( pMem->flags & MEM_Null ){ + zP4 = "NULL"; + }else{ +@@ -75622,7 +77304,7 @@ + #ifndef SQLITE_OMIT_VIRTUALTABLE + case P4_VTAB: { + sqlite3_vtab *pVtab = pOp->p4.pVtab->pVtab; +- sqlite3XPrintf(&x, "vtab:%p", pVtab); ++ sqlite3_str_appendf(&x, "vtab:%p", pVtab); + break; + } + #endif +@@ -75632,14 +77314,14 @@ + int n = ai[0]; /* The first element of an INTARRAY is always the + ** count of the number of elements to follow */ + for(i=1; i<=n; i++){ +- sqlite3XPrintf(&x, ",%d", ai[i]); ++ sqlite3_str_appendf(&x, ",%d", ai[i]); + } + zTemp[0] = '['; +- sqlite3StrAccumAppend(&x, "]", 1); ++ sqlite3_str_append(&x, "]", 1); + break; + } + case P4_SUBPROGRAM: { +- sqlite3XPrintf(&x, "program"); ++ sqlite3_str_appendf(&x, "program"); + break; + } + case P4_DYNBLOB: +@@ -75648,7 +77330,7 @@ + break; + } + case P4_TABLE: { +- sqlite3XPrintf(&x, "%s", pOp->p4.pTab->zName); ++ sqlite3_str_appendf(&x, "%s", pOp->p4.pTab->zName); + break; + } + default: { +@@ -75749,7 +77431,7 @@ + /* + ** Print a single opcode. This routine is used for debugging only. + */ +-SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){ ++SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, VdbeOp *pOp){ + char *zP4; + char zPtr[50]; + char zCom[100]; +@@ -75818,9 +77500,8 @@ + */ + testcase( p->flags & MEM_Agg ); + testcase( p->flags & MEM_Dyn ); +- testcase( p->flags & MEM_Frame ); +- testcase( p->flags & MEM_RowSet ); +- if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){ ++ testcase( p->xDel==sqlite3VdbeFrameMemDel ); ++ if( p->flags&(MEM_Agg|MEM_Dyn) ){ + sqlite3VdbeMemRelease(p); + }else if( p->szMalloc ){ + sqlite3DbFreeNN(db, p->zMalloc); +@@ -75832,7 +77513,36 @@ + } + } + ++#ifdef SQLITE_DEBUG + /* ++** Verify that pFrame is a valid VdbeFrame pointer. Return true if it is ++** and false if something is wrong. ++** ++** This routine is intended for use inside of assert() statements only. ++*/ ++SQLITE_PRIVATE int sqlite3VdbeFrameIsValid(VdbeFrame *pFrame){ ++ if( pFrame->iFrameMagic!=SQLITE_FRAME_MAGIC ) return 0; ++ return 1; ++} ++#endif ++ ++ ++/* ++** This is a destructor on a Mem object (which is really an sqlite3_value) ++** that deletes the Frame object that is attached to it as a blob. ++** ++** This routine does not delete the Frame right away. It merely adds the ++** frame to a list of frames to be deleted when the Vdbe halts. ++*/ ++SQLITE_PRIVATE void sqlite3VdbeFrameMemDel(void *pArg){ ++ VdbeFrame *pFrame = (VdbeFrame*)pArg; ++ assert( sqlite3VdbeFrameIsValid(pFrame) ); ++ pFrame->pParent = pFrame->v->pDelFrame; ++ pFrame->v->pDelFrame = pFrame; ++} ++ ++ ++/* + ** Delete a VdbeFrame object and its contents. VdbeFrame objects are + ** allocated by the OP_Program opcode in sqlite3VdbeExec(). + */ +@@ -75840,6 +77550,7 @@ + int i; + Mem *aMem = VdbeFrameMem(p); + VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem]; ++ assert( sqlite3VdbeFrameIsValid(p) ); + for(i=0; i<p->nChildCsr; i++){ + sqlite3VdbeFreeCursor(p->v, apCsr[i]); + } +@@ -75860,6 +77571,9 @@ + ** p->explain==2, only OP_Explain instructions are listed and these + ** are shown in a different format. p->explain==2 is used to implement + ** EXPLAIN QUERY PLAN. ++** 2018-04-24: In p->explain==2 mode, the OP_Init opcodes of triggers ++** are also shown, so that the boundaries between the main program and ++** each trigger are clear. + ** + ** When p->explain==1, first the main program is listed, then each of + ** the trigger subprograms are listed one by one. +@@ -75922,7 +77636,7 @@ + } + } + +- do{ ++ while(1){ /* Loop exits via break */ + i = p->pc++; + if( i>=nRow ){ + p->rc = SQLITE_OK; +@@ -75968,7 +77682,10 @@ + nRow += pOp->p4.pProgram->nOp; + } + } +- }while( p->explain==2 && pOp->opcode!=OP_Explain ); ++ if( p->explain<2 ) break; ++ if( pOp->opcode==OP_Explain ) break; ++ if( pOp->opcode==OP_Init && p->pc>1 ) break; ++ } + + if( rc==SQLITE_OK ){ + if( db->u1.isInterrupted ){ +@@ -77130,7 +78847,7 @@ + */ + sqlite3VdbeHalt(p); + +- /* If the VDBE has be run even partially, then transfer the error code ++ /* If the VDBE has been run even partially, then transfer the error code + ** and error message from the VDBE into the main database structure. But + ** if the VDBE has just been set to run but has not actually executed any + ** instructions yet, leave the main database error information unchanged. +@@ -77160,6 +78877,9 @@ + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = 0; + p->pResultSet = 0; ++#ifdef SQLITE_DEBUG ++ p->nWrite = 0; ++#endif + + /* Save profiling information from this VDBE run. + */ +@@ -77275,6 +78995,9 @@ + vdbeFreeOpArray(db, p->aOp, p->nOp); + sqlite3DbFree(db, p->aColName); + sqlite3DbFree(db, p->zSql); ++#ifdef SQLITE_ENABLE_NORMALIZE ++ sqlite3DbFree(db, p->zNormSql); ++#endif + #ifdef SQLITE_ENABLE_STMT_SCANSTATUS + { + int i; +@@ -78039,7 +79762,7 @@ + ** is less than, equal to, or greater than the second, respectively. + ** If one blob is a prefix of the other, then the shorter is the lessor. + */ +-static SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem *pB2){ ++SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem *pB2){ + int c; + int n1 = pB1->n; + int n2 = pB2->n; +@@ -78082,13 +79805,10 @@ + i64 y; + double s; + if( r<-9223372036854775808.0 ) return +1; +- if( r>9223372036854775807.0 ) return -1; ++ if( r>=9223372036854775808.0 ) return -1; + y = (i64)r; + if( i<y ) return -1; +- if( i>y ){ +- if( y==SMALLEST_INT64 && r>0.0 ) return -1; +- return +1; +- } ++ if( i>y ) return +1; + s = (double)i; + if( s<r ) return -1; + if( s>r ) return +1; +@@ -78112,7 +79832,7 @@ + f1 = pMem1->flags; + f2 = pMem2->flags; + combined_flags = f1|f2; +- assert( (combined_flags & MEM_RowSet)==0 ); ++ assert( !sqlite3VdbeMemIsRowSet(pMem1) && !sqlite3VdbeMemIsRowSet(pMem2) ); + + /* If one value is NULL, it is less than the other. If both values + ** are NULL, return 0. +@@ -78257,7 +79977,7 @@ + u32 idx1; /* Offset of first type in header */ + int rc = 0; /* Return value */ + Mem *pRhs = pPKey2->aMem; /* Next field of pPKey2 to compare */ +- KeyInfo *pKeyInfo = pPKey2->pKeyInfo; ++ KeyInfo *pKeyInfo; + const unsigned char *aKey1 = (const unsigned char *)pKey1; + Mem mem1; + +@@ -78352,7 +80072,7 @@ + if( (d1+mem1.n) > (unsigned)nKey1 ){ + pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT; + return 0; /* Corruption */ +- }else if( pKeyInfo->aColl[i] ){ ++ }else if( (pKeyInfo = pPKey2->pKeyInfo)->aColl[i] ){ + mem1.enc = pKeyInfo->enc; + mem1.db = pKeyInfo->db; + mem1.flags = MEM_Str; +@@ -78403,7 +80123,7 @@ + } + + if( rc!=0 ){ +- if( pKeyInfo->aSortOrder[i] ){ ++ if( pPKey2->pKeyInfo->aSortOrder[i] ){ + rc = -rc; + } + assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, rc) ); +@@ -78412,10 +80132,11 @@ + } + + i++; ++ if( i==pPKey2->nField ) break; + pRhs++; + d1 += sqlite3VdbeSerialTypeLen(serial_type); + idx1 += sqlite3VarintLen(serial_type); +- }while( idx1<(unsigned)szHdr1 && i<pPKey2->nField && d1<=(unsigned)nKey1 ); ++ }while( idx1<(unsigned)szHdr1 && d1<=(unsigned)nKey1 ); + + /* No memory allocation is ever used on mem1. Prove this using + ** the following assert(). If the assert() fails, it indicates a +@@ -78427,7 +80148,7 @@ + ** value. */ + assert( CORRUPT_DB + || vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, pPKey2->default_rc) +- || pKeyInfo->db->mallocFailed ++ || pPKey2->pKeyInfo->db->mallocFailed + ); + pPKey2->eqSeen = 1; + return pPKey2->default_rc; +@@ -78678,7 +80399,9 @@ + (void)getVarint32((u8*)m.z, szHdr); + testcase( szHdr==3 ); + testcase( szHdr==m.n ); +- if( unlikely(szHdr<3 || (int)szHdr>m.n) ){ ++ testcase( szHdr>0x7fffffff ); ++ assert( m.n>=0 ); ++ if( unlikely(szHdr<3 || szHdr>(unsigned)m.n) ){ + goto idx_rowid_corruption; + } + +@@ -78753,7 +80476,7 @@ + if( rc ){ + return rc; + } +- *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked); ++ *res = sqlite3VdbeRecordCompareWithSkip(m.n, m.z, pUnpacked, 0); + sqlite3VdbeMemRelease(&m); + return SQLITE_OK; + } +@@ -78785,11 +80508,19 @@ + ** programs obsolete. Removing user-defined functions or collating + ** sequences, or changing an authorization function are the types of + ** things that make prepared statements obsolete. ++** ++** If iCode is 1, then expiration is advisory. The statement should ++** be reprepared before being restarted, but if it is already running ++** it is allowed to run to completion. ++** ++** Internally, this function just sets the Vdbe.expired flag on all ++** prepared statements. The flag is set to 1 for an immediate expiration ++** and set to 2 for an advisory expiration. + */ +-SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3 *db){ ++SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3 *db, int iCode){ + Vdbe *p; + for(p = db->pVdbe; p; p=p->pNext){ +- p->expired = 1; ++ p->expired = iCode+1; + } + } + +@@ -79767,28 +81498,6 @@ + } + + /* +-** The following is the implementation of an SQL function that always +-** fails with an error message stating that the function is used in the +-** wrong context. The sqlite3_overload_function() API might construct +-** SQL function that use this routine so that the functions will exist +-** for name resolution but are actually overloaded by the xFindFunction +-** method of virtual tables. +-*/ +-SQLITE_PRIVATE void sqlite3InvalidFunction( +- sqlite3_context *context, /* The function calling context */ +- int NotUsed, /* Number of arguments to the function */ +- sqlite3_value **NotUsed2 /* Value of each argument */ +-){ +- const char *zName = context->pFunc->zName; +- char *zErr; +- UNUSED_PARAMETER2(NotUsed, NotUsed2); +- zErr = sqlite3_mprintf( +- "unable to use function %s in the requested context", zName); +- sqlite3_result_error(context, zErr, -1); +- sqlite3_free(zErr); +-} +- +-/* + ** Create a new aggregate context for p and return a pointer to + ** its pMem->z element. + */ +@@ -79971,7 +81680,7 @@ + /* .xDel = */ (void(*)(void*))0, + #ifdef SQLITE_DEBUG + /* .pScopyFrom = */ (Mem*)0, +- /* .pFiller = */ (void*)0, ++ /* .mScopyFlags= */ 0, + #endif + }; + return &nullMem; +@@ -80703,6 +82412,16 @@ + #endif + } + ++#ifdef SQLITE_ENABLE_NORMALIZE ++/* ++** Return the normalized SQL associated with a prepared statement. ++*/ ++SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt){ ++ Vdbe *p = (Vdbe *)pStmt; ++ return p ? p->zNormSql : 0; ++} ++#endif /* SQLITE_ENABLE_NORMALIZE */ ++ + #ifdef SQLITE_ENABLE_PREUPDATE_HOOK + /* + ** Allocate and populate an UnpackedRecord structure based on the serialized +@@ -81055,17 +82774,17 @@ + while( *zRawSql ){ + const char *zStart = zRawSql; + while( *(zRawSql++)!='\n' && *zRawSql ); +- sqlite3StrAccumAppend(&out, "-- ", 3); ++ sqlite3_str_append(&out, "-- ", 3); + assert( (zRawSql - zStart) > 0 ); +- sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart)); ++ sqlite3_str_append(&out, zStart, (int)(zRawSql-zStart)); + } + }else if( p->nVar==0 ){ +- sqlite3StrAccumAppend(&out, zRawSql, sqlite3Strlen30(zRawSql)); ++ sqlite3_str_append(&out, zRawSql, sqlite3Strlen30(zRawSql)); + }else{ + while( zRawSql[0] ){ + n = findNextHostParameter(zRawSql, &nToken); + assert( n>0 ); +- sqlite3StrAccumAppend(&out, zRawSql, n); ++ sqlite3_str_append(&out, zRawSql, n); + zRawSql += n; + assert( zRawSql[0] || nToken==0 ); + if( nToken==0 ) break; +@@ -81091,11 +82810,11 @@ + assert( idx>0 && idx<=p->nVar ); + pVar = &p->aVar[idx-1]; + if( pVar->flags & MEM_Null ){ +- sqlite3StrAccumAppend(&out, "NULL", 4); ++ sqlite3_str_append(&out, "NULL", 4); + }else if( pVar->flags & MEM_Int ){ +- sqlite3XPrintf(&out, "%lld", pVar->u.i); ++ sqlite3_str_appendf(&out, "%lld", pVar->u.i); + }else if( pVar->flags & MEM_Real ){ +- sqlite3XPrintf(&out, "%!.15g", pVar->u.r); ++ sqlite3_str_appendf(&out, "%!.15g", pVar->u.r); + }else if( pVar->flags & MEM_Str ){ + int nOut; /* Number of bytes of the string text to include in output */ + #ifndef SQLITE_OMIT_UTF16 +@@ -81105,7 +82824,7 @@ + utf8.db = db; + sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC); + if( SQLITE_NOMEM==sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8) ){ +- out.accError = STRACCUM_NOMEM; ++ out.accError = SQLITE_NOMEM; + out.nAlloc = 0; + } + pVar = &utf8; +@@ -81118,10 +82837,10 @@ + while( nOut<pVar->n && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; } + } + #endif +- sqlite3XPrintf(&out, "'%.*q'", nOut, pVar->z); ++ sqlite3_str_appendf(&out, "'%.*q'", nOut, pVar->z); + #ifdef SQLITE_TRACE_SIZE_LIMIT + if( nOut<pVar->n ){ +- sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut); ++ sqlite3_str_appendf(&out, "/*+%d bytes*/", pVar->n-nOut); + } + #endif + #ifndef SQLITE_OMIT_UTF16 +@@ -81128,28 +82847,28 @@ + if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8); + #endif + }else if( pVar->flags & MEM_Zero ){ +- sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero); ++ sqlite3_str_appendf(&out, "zeroblob(%d)", pVar->u.nZero); + }else{ + int nOut; /* Number of bytes of the blob to include in output */ + assert( pVar->flags & MEM_Blob ); +- sqlite3StrAccumAppend(&out, "x'", 2); ++ sqlite3_str_append(&out, "x'", 2); + nOut = pVar->n; + #ifdef SQLITE_TRACE_SIZE_LIMIT + if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT; + #endif + for(i=0; i<nOut; i++){ +- sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff); ++ sqlite3_str_appendf(&out, "%02x", pVar->z[i]&0xff); + } +- sqlite3StrAccumAppend(&out, "'", 1); ++ sqlite3_str_append(&out, "'", 1); + #ifdef SQLITE_TRACE_SIZE_LIMIT + if( nOut<pVar->n ){ +- sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut); ++ sqlite3_str_appendf(&out, "/*+%d bytes*/", pVar->n-nOut); + } + #endif + } + } + } +- if( out.accError ) sqlite3StrAccumReset(&out); ++ if( out.accError ) sqlite3_str_reset(&out); + return sqlite3StrAccumFinish(&out); + } + +@@ -81281,32 +83000,56 @@ + ** feature is used for test suite validation only and does not appear an + ** production builds. + ** +-** M is an integer, 2 or 3, that indices how many different ways the +-** branch can go. It is usually 2. "I" is the direction the branch +-** goes. 0 means falls through. 1 means branch is taken. 2 means the +-** second alternative branch is taken. ++** M is an integer between 2 and 4. 2 indicates a ordinary two-way ++** branch (I=0 means fall through and I=1 means taken). 3 indicates ++** a 3-way branch where the third way is when one of the operands is ++** NULL. 4 indicates the OP_Jump instruction which has three destinations ++** depending on whether the first operand is less than, equal to, or greater ++** than the second. + ** + ** iSrcLine is the source code line (from the __LINE__ macro) that +-** generated the VDBE instruction. This instrumentation assumes that all +-** source code is in a single file (the amalgamation). Special values 1 +-** and 2 for the iSrcLine parameter mean that this particular branch is +-** always taken or never taken, respectively. ++** generated the VDBE instruction combined with flag bits. The source ++** code line number is in the lower 24 bits of iSrcLine and the upper ++** 8 bytes are flags. The lower three bits of the flags indicate ++** values for I that should never occur. For example, if the branch is ++** always taken, the flags should be 0x05 since the fall-through and ++** alternate branch are never taken. If a branch is never taken then ++** flags should be 0x06 since only the fall-through approach is allowed. ++** ++** Bit 0x04 of the flags indicates an OP_Jump opcode that is only ++** interested in equal or not-equal. In other words, I==0 and I==2 ++** should be treated the same. ++** ++** Since only a line number is retained, not the filename, this macro ++** only works for amalgamation builds. But that is ok, since these macros ++** should be no-ops except for special builds used to measure test coverage. + */ + #if !defined(SQLITE_VDBE_COVERAGE) + # define VdbeBranchTaken(I,M) + #else + # define VdbeBranchTaken(I,M) vdbeTakeBranch(pOp->iSrcLine,I,M) +- static void vdbeTakeBranch(int iSrcLine, u8 I, u8 M){ +- if( iSrcLine<=2 && ALWAYS(iSrcLine>0) ){ +- M = iSrcLine; +- /* Assert the truth of VdbeCoverageAlwaysTaken() and +- ** VdbeCoverageNeverTaken() */ +- assert( (M & I)==I ); +- }else{ +- if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/ +- sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg, +- iSrcLine,I,M); ++ static void vdbeTakeBranch(u32 iSrcLine, u8 I, u8 M){ ++ u8 mNever; ++ assert( I<=2 ); /* 0: fall through, 1: taken, 2: alternate taken */ ++ assert( M<=4 ); /* 2: two-way branch, 3: three-way branch, 4: OP_Jump */ ++ assert( I<M ); /* I can only be 2 if M is 3 or 4 */ ++ /* Transform I from a integer [0,1,2] into a bitmask of [1,2,4] */ ++ I = 1<<I; ++ /* The upper 8 bits of iSrcLine are flags. The lower three bits of ++ ** the flags indicate directions that the branch can never go. If ++ ** a branch really does go in one of those directions, assert right ++ ** away. */ ++ mNever = iSrcLine >> 24; ++ assert( (I & mNever)==0 ); ++ if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/ ++ I |= mNever; ++ if( M==2 ) I |= 0x04; ++ if( M==4 ){ ++ I |= 0x08; ++ if( (mNever&0x08)!=0 && (I&0x05)!=0) I |= 0x05; /*NO_TEST*/ + } ++ sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg, ++ iSrcLine&0xffffff, I, M); + } + #endif + +@@ -81637,7 +83380,7 @@ + }else if( p->flags & MEM_Real ){ + printf(" r:%g", p->u.r); + #endif +- }else if( p->flags & MEM_RowSet ){ ++ }else if( sqlite3VdbeMemIsRowSet(p) ){ + printf(" (rowset)"); + }else{ + char zBuf[200]; +@@ -82163,6 +83906,9 @@ + */ + case OP_HaltIfNull: { /* in3 */ + pIn3 = &aMem[pOp->p3]; ++#ifdef SQLITE_DEBUG ++ if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); } ++#endif + if( (pIn3->flags & MEM_Null)==0 ) break; + /* Fall through into OP_Halt */ + } +@@ -82202,6 +83948,9 @@ + int pcx; + + pcx = (int)(pOp - aOp); ++#ifdef SQLITE_DEBUG ++ if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); } ++#endif + if( pOp->p1==SQLITE_OK && p->pFrame ){ + /* Halt the sub-program. Return control to the parent frame. */ + pFrame = p->pFrame; +@@ -82385,6 +84134,9 @@ + assert( pOp->p3<=(p->nMem+1 - p->nCursor) ); + pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null; + pOut->n = 0; ++#ifdef SQLITE_DEBUG ++ pOut->uTemp = 0; ++#endif + while( cnt>0 ){ + pOut++; + memAboutToChange(p, pOut); +@@ -82506,6 +84258,7 @@ + pOut = &aMem[pOp->p2]; + assert( pOut!=pIn1 ); + while( 1 ){ ++ memAboutToChange(p, pOut); + sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); + Deephemeralize(pOut); + #ifdef SQLITE_DEBUG +@@ -82538,7 +84291,8 @@ + assert( pOut!=pIn1 ); + sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); + #ifdef SQLITE_DEBUG +- if( pOut->pScopyFrom==0 ) pOut->pScopyFrom = pIn1; ++ pOut->pScopyFrom = pIn1; ++ pOut->mScopyFlags = pIn1->flags; + #endif + break; + } +@@ -83172,7 +84926,12 @@ + if( (flags1 | flags3)&MEM_Str ){ + if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ + applyNumericAffinity(pIn1,0); +- testcase( flags3!=pIn3->flags ); /* Possible if pIn1==pIn3 */ ++ assert( flags3==pIn3->flags ); ++ /* testcase( flags3!=pIn3->flags ); ++ ** this used to be possible with pIn1==pIn3, but not since ++ ** the column cache was removed. The following assignment ++ ** is essentially a no-op. But, it provides defense-in-depth ++ ** in case our analysis is incorrect, so it is left in. */ + flags3 = pIn3->flags; + } + if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){ +@@ -83386,11 +85145,11 @@ + */ + case OP_Jump: { /* jump */ + if( iCompare<0 ){ +- VdbeBranchTaken(0,3); pOp = &aOp[pOp->p1 - 1]; ++ VdbeBranchTaken(0,4); pOp = &aOp[pOp->p1 - 1]; + }else if( iCompare==0 ){ +- VdbeBranchTaken(1,3); pOp = &aOp[pOp->p2 - 1]; ++ VdbeBranchTaken(1,4); pOp = &aOp[pOp->p2 - 1]; + }else{ +- VdbeBranchTaken(2,3); pOp = &aOp[pOp->p3 - 1]; ++ VdbeBranchTaken(2,4); pOp = &aOp[pOp->p3 - 1]; + } + break; + } +@@ -83487,7 +85246,7 @@ + } + + /* Opcode: BitNot P1 P2 * * * +-** Synopsis: r[P1]= ~r[P1] ++** Synopsis: r[P2]= ~r[P1] + ** + ** Interpret the content of register P1 as an integer. Store the + ** ones-complement of the P1 value into register P2. If P1 holds +@@ -84102,9 +85861,6 @@ + if( nVarint<sqlite3VarintLen(nHdr) ) nHdr++; + } + nByte = nHdr+nData; +- if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){ +- goto too_big; +- } + + /* Make sure the output register has a buffer large enough to store + ** the new record. The output register (pOp->p3) is not allowed to +@@ -84111,8 +85867,19 @@ + ** be one of the input registers (because the following call to + ** sqlite3VdbeMemClearAndResize() could clobber the value before it is used). + */ +- if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){ +- goto no_mem; ++ if( nByte+nZero<=pOut->szMalloc ){ ++ /* The output register is already large enough to hold the record. ++ ** No error checks or buffer enlargement is required */ ++ pOut->z = pOut->zMalloc; ++ }else{ ++ /* Need to make sure that the output is not too big and then enlarge ++ ** the output register to hold the full result */ ++ if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){ ++ goto too_big; ++ } ++ if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){ ++ goto no_mem; ++ } + } + zNewRecord = (u8 *)pOut->z; + +@@ -84302,7 +86069,7 @@ + } + } + if( isSchemaChange ){ +- sqlite3ExpirePreparedStatements(db); ++ sqlite3ExpirePreparedStatements(db, 0); + sqlite3ResetAllSchemasOfConnection(db); + db->mDbFlags |= DBFLAG_SchemaChange; + } +@@ -84444,8 +86211,7 @@ + */ + case OP_Transaction: { + Btree *pBt; +- int iMeta; +- int iGen; ++ int iMeta = 0; + + assert( p->bIsReader ); + assert( p->readOnly==0 || pOp->p2==0 ); +@@ -84458,7 +86224,7 @@ + pBt = db->aDb[pOp->p1].pBt; + + if( pBt ){ +- rc = sqlite3BtreeBeginTrans(pBt, pOp->p2); ++ rc = sqlite3BtreeBeginTrans(pBt, pOp->p2, &iMeta); + testcase( rc==SQLITE_BUSY_SNAPSHOT ); + testcase( rc==SQLITE_BUSY_RECOVERY ); + if( rc!=SQLITE_OK ){ +@@ -84491,19 +86257,17 @@ + p->nStmtDefCons = db->nDeferredCons; + p->nStmtDefImmCons = db->nDeferredImmCons; + } +- +- /* Gather the schema version number for checking: ++ } ++ assert( pOp->p5==0 || pOp->p4type==P4_INT32 ); ++ if( pOp->p5 ++ && (iMeta!=pOp->p3 ++ || db->aDb[pOp->p1].pSchema->iGeneration!=pOp->p4.i) ++ ){ ++ /* + ** IMPLEMENTATION-OF: R-03189-51135 As each SQL statement runs, the schema + ** version is checked to ensure that the schema has not changed since the + ** SQL statement was prepared. + */ +- sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta); +- iGen = db->aDb[pOp->p1].pSchema->iGeneration; +- }else{ +- iGen = iMeta = 0; +- } +- assert( pOp->p5==0 || pOp->p4type==P4_INT32 ); +- if( pOp->p5 && (iMeta!=pOp->p3 || iGen!=pOp->p4.i) ){ + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed"); + /* If the schema-cookie from the database file matches the cookie +@@ -84572,6 +86336,8 @@ + */ + case OP_SetCookie: { + Db *pDb; ++ ++ sqlite3VdbeIncrWriteCounter(p, 0); + assert( pOp->p2<SQLITE_N_BTREE_META ); + assert( pOp->p1>=0 && pOp->p1<db->nDb ); + assert( DbMaskTest(p->btreeMask, pOp->p1) ); +@@ -84592,7 +86358,7 @@ + if( pOp->p1==1 ){ + /* Invalidate all prepared statements whenever the TEMP database + ** schema is changed. Ticket #1644 */ +- sqlite3ExpirePreparedStatements(db); ++ sqlite3ExpirePreparedStatements(db, 0); + p->expired = 0; + } + if( rc ) goto abort_due_to_error; +@@ -84610,23 +86376,20 @@ + ** values need not be contiguous but all P1 values should be small integers. + ** It is an error for P1 to be negative. + ** +-** If P5!=0 then use the content of register P2 as the root page, not +-** the value of P2 itself. ++** Allowed P5 bits: ++** <ul> ++** <li> <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for ++** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT ++** of OP_SeekLE/OP_IdxGT) ++** </ul> + ** +-** There will be a read lock on the database whenever there is an +-** open cursor. If the database was unlocked prior to this instruction +-** then a read lock is acquired as part of this instruction. A read +-** lock allows other processes to read the database but prohibits +-** any other process from modifying the database. The read lock is +-** released when all cursors are closed. If this instruction attempts +-** to get a read lock but fails, the script terminates with an +-** SQLITE_BUSY error code. +-** + ** The P4 value may be either an integer (P4_INT32) or a pointer to + ** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo +-** structure, then said structure defines the content and collating +-** sequence of the index being opened. Otherwise, if P4 is an integer +-** value, it is set to the number of columns in the table. ++** object, then table being opened must be an [index b-tree] where the ++** KeyInfo object defines the content and collating ++** sequence of that index b-tree. Otherwise, if P4 is an integer ++** value, then the table being opened must be a [table b-tree] with a ++** number of columns no less than the value of P4. + ** + ** See also: OpenWrite, ReopenIdx + */ +@@ -84633,36 +86396,58 @@ + /* Opcode: ReopenIdx P1 P2 P3 P4 P5 + ** Synopsis: root=P2 iDb=P3 + ** +-** The ReopenIdx opcode works exactly like ReadOpen except that it first +-** checks to see if the cursor on P1 is already open with a root page +-** number of P2 and if it is this opcode becomes a no-op. In other words, ++** The ReopenIdx opcode works like OP_OpenRead except that it first ++** checks to see if the cursor on P1 is already open on the same ++** b-tree and if it is this opcode becomes a no-op. In other words, + ** if the cursor is already open, do not reopen it. + ** +-** The ReopenIdx opcode may only be used with P5==0 and with P4 being +-** a P4_KEYINFO object. Furthermore, the P3 value must be the same as +-** every other ReopenIdx or OpenRead for the same cursor number. ++** The ReopenIdx opcode may only be used with P5==0 or P5==OPFLAG_SEEKEQ ++** and with P4 being a P4_KEYINFO object. Furthermore, the P3 value must ++** be the same as every other ReopenIdx or OpenRead for the same cursor ++** number. + ** +-** See the OpenRead opcode documentation for additional information. ++** Allowed P5 bits: ++** <ul> ++** <li> <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for ++** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT ++** of OP_SeekLE/OP_IdxGT) ++** </ul> ++** ++** See also: OP_OpenRead, OP_OpenWrite + */ + /* Opcode: OpenWrite P1 P2 P3 P4 P5 + ** Synopsis: root=P2 iDb=P3 + ** + ** Open a read/write cursor named P1 on the table or index whose root +-** page is P2. Or if P5!=0 use the content of register P2 to find the +-** root page. ++** page is P2 (or whose root page is held in register P2 if the ++** OPFLAG_P2ISREG bit is set in P5 - see below). + ** + ** The P4 value may be either an integer (P4_INT32) or a pointer to + ** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo +-** structure, then said structure defines the content and collating +-** sequence of the index being opened. Otherwise, if P4 is an integer +-** value, it is set to the number of columns in the table, or to the +-** largest index of any column of the table that is actually used. ++** object, then table being opened must be an [index b-tree] where the ++** KeyInfo object defines the content and collating ++** sequence of that index b-tree. Otherwise, if P4 is an integer ++** value, then the table being opened must be a [table b-tree] with a ++** number of columns no less than the value of P4. + ** +-** This instruction works just like OpenRead except that it opens the cursor +-** in read/write mode. For a given table, there can be one or more read-only +-** cursors or a single read/write cursor but not both. ++** Allowed P5 bits: ++** <ul> ++** <li> <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for ++** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT ++** of OP_SeekLE/OP_IdxGT) ++** <li> <b>0x08 OPFLAG_FORDELETE</b>: This cursor is used only to seek ++** and subsequently delete entries in an index btree. This is a ++** hint to the storage engine that the storage engine is allowed to ++** ignore. The hint is not used by the official SQLite b*tree storage ++** engine, but is used by COMDB2. ++** <li> <b>0x10 OPFLAG_P2ISREG</b>: Use the content of register P2 ++** as the root page, not the value of P2 itself. ++** </ul> + ** +-** See also OpenRead. ++** This instruction works like OpenRead except that it opens the cursor ++** in read/write mode. ++** ++** See also: OP_OpenRead, OP_ReopenIdx + */ + case OP_ReopenIdx: { + int nField; +@@ -84691,7 +86476,7 @@ + assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx + || p->readOnly==0 ); + +- if( p->expired ){ ++ if( p->expired==1 ){ + rc = SQLITE_ABORT_ROLLBACK; + goto abort_due_to_error; + } +@@ -84718,6 +86503,7 @@ + if( pOp->p5 & OPFLAG_P2ISREG ){ + assert( p2>0 ); + assert( p2<=(p->nMem+1 - p->nCursor) ); ++ assert( pOp->opcode==OP_OpenWrite ); + pIn2 = &aMem[p2]; + assert( memIsValid(pIn2) ); + assert( (pIn2->flags & MEM_Int)!=0 ); +@@ -84846,7 +86632,7 @@ + rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBtx, + BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags); + if( rc==SQLITE_OK ){ +- rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1); ++ rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1, 0); + } + if( rc==SQLITE_OK ){ + /* If a transient index is required, create it by calling +@@ -85073,10 +86859,10 @@ + ** + ** See also: Found, NotFound, SeekGt, SeekGe, SeekLt + */ +-case OP_SeekLT: /* jump, in3 */ +-case OP_SeekLE: /* jump, in3 */ +-case OP_SeekGE: /* jump, in3 */ +-case OP_SeekGT: { /* jump, in3 */ ++case OP_SeekLT: /* jump, in3, group */ ++case OP_SeekLE: /* jump, in3, group */ ++case OP_SeekGE: /* jump, in3, group */ ++case OP_SeekGT: { /* jump, in3, group */ + int res; /* Comparison result */ + int oc; /* Opcode */ + VdbeCursor *pC; /* The cursor to seek */ +@@ -85254,6 +87040,25 @@ + break; + } + ++/* Opcode: SeekHit P1 P2 * * * ++** Synopsis: seekHit=P2 ++** ++** Set the seekHit flag on cursor P1 to the value in P2. ++** The seekHit flag is used by the IfNoHope opcode. ++** ++** P1 must be a valid b-tree cursor. P2 must be a boolean value, ++** either 0 or 1. ++*/ ++case OP_SeekHit: { ++ VdbeCursor *pC; ++ assert( pOp->p1>=0 && pOp->p1<p->nCursor ); ++ pC = p->apCsr[pOp->p1]; ++ assert( pC!=0 ); ++ assert( pOp->p2==0 || pOp->p2==1 ); ++ pC->seekHit = pOp->p2 & 1; ++ break; ++} ++ + /* Opcode: Found P1 P2 P3 P4 * + ** Synopsis: key=r[P3@P4] + ** +@@ -85288,8 +87093,35 @@ + ** advanced in either direction. In other words, the Next and Prev + ** opcodes do not work after this operation. + ** +-** See also: Found, NotExists, NoConflict ++** See also: Found, NotExists, NoConflict, IfNoHope + */ ++/* Opcode: IfNoHope P1 P2 P3 P4 * ++** Synopsis: key=r[P3@P4] ++** ++** Register P3 is the first of P4 registers that form an unpacked ++** record. ++** ++** Cursor P1 is on an index btree. If the seekHit flag is set on P1, then ++** this opcode is a no-op. But if the seekHit flag of P1 is clear, then ++** check to see if there is any entry in P1 that matches the ++** prefix identified by P3 and P4. If no entry matches the prefix, ++** jump to P2. Otherwise fall through. ++** ++** This opcode behaves like OP_NotFound if the seekHit ++** flag is clear and it behaves like OP_Noop if the seekHit flag is set. ++** ++** This opcode is used in IN clause processing for a multi-column key. ++** If an IN clause is attached to an element of the key other than the ++** left-most element, and if there are no matches on the most recent ++** seek over the whole key, then it might be that one of the key element ++** to the left is prohibiting a match, and hence there is "no hope" of ++** any match regardless of how many IN clause elements are checked. ++** In such a case, we abandon the IN clause search early, using this ++** opcode. The opcode name comes from the fact that the ++** jump is taken if there is "no hope" of achieving a match. ++** ++** See also: NotFound, SeekHit ++*/ + /* Opcode: NoConflict P1 P2 P3 P4 * + ** Synopsis: key=r[P3@P4] + ** +@@ -85313,6 +87145,14 @@ + ** + ** See also: NotFound, Found, NotExists + */ ++case OP_IfNoHope: { /* jump, in3 */ ++ VdbeCursor *pC; ++ assert( pOp->p1>=0 && pOp->p1<p->nCursor ); ++ pC = p->apCsr[pOp->p1]; ++ assert( pC!=0 ); ++ if( pC->seekHit ) break; ++ /* Fall through into OP_NotFound */ ++} + case OP_NoConflict: /* jump, in3 */ + case OP_NotFound: /* jump, in3 */ + case OP_Found: { /* jump, in3 */ +@@ -85450,18 +87290,26 @@ + + pIn3 = &aMem[pOp->p3]; + if( (pIn3->flags & MEM_Int)==0 ){ ++ /* Make sure pIn3->u.i contains a valid integer representation of ++ ** the key value, but do not change the datatype of the register, as ++ ** other parts of the perpared statement might be depending on the ++ ** current datatype. */ ++ u16 origFlags = pIn3->flags; ++ int isNotInt; + applyAffinity(pIn3, SQLITE_AFF_NUMERIC, encoding); +- if( (pIn3->flags & MEM_Int)==0 ) goto jump_to_p2; ++ isNotInt = (pIn3->flags & MEM_Int)==0; ++ pIn3->flags = origFlags; ++ if( isNotInt ) goto jump_to_p2; + } + /* Fall through into OP_NotExists */ + case OP_NotExists: /* jump, in3 */ + pIn3 = &aMem[pOp->p3]; +- assert( pIn3->flags & MEM_Int ); ++ assert( (pIn3->flags & MEM_Int)!=0 || pOp->opcode==OP_SeekRowid ); + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + #ifdef SQLITE_DEBUG +- pC->seekOp = 0; ++ pC->seekOp = OP_SeekRowid; + #endif + assert( pC->isTable ); + assert( pC->eCurType==CURTYPE_BTREE ); +@@ -85535,11 +87383,8 @@ + pOut = out2Prerelease(p, pOp); + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + pC = p->apCsr[pOp->p1]; +- if( !pC->isTable ){ +- rc = SQLITE_CORRUPT_BKPT; +- goto abort_due_to_error; +- } + assert( pC!=0 ); ++ assert( pC->isTable ); + assert( pC->eCurType==CURTYPE_BTREE ); + assert( pC->uc.pCursor!=0 ); + { +@@ -85708,6 +87553,7 @@ + assert( (pOp->p5 & OPFLAG_ISNOOP) || pC->isTable ); + assert( pOp->p4type==P4_TABLE || pOp->p4type>=P4_STATIC ); + REGISTER_TRACE(pOp->p2, pData); ++ sqlite3VdbeIncrWriteCounter(p, pC); + + if( pOp->opcode==OP_Insert ){ + pKey = &aMem[pOp->p3]; +@@ -85822,6 +87668,7 @@ + assert( pC->eCurType==CURTYPE_BTREE ); + assert( pC->uc.pCursor!=0 ); + assert( pC->deferredMoveto==0 ); ++ sqlite3VdbeIncrWriteCounter(p, pC); + + #ifdef SQLITE_DEBUG + if( pOp->p4type==P4_TABLE && HasRowid(pOp->p4.pTab) && pOp->p5==0 ){ +@@ -85990,10 +87837,10 @@ + ** If the P1 cursor must be pointing to a valid row (not a NULL row) + ** of a real table, not a pseudo-table. + ** +-** If P3!=0 then this opcode is allowed to make an ephermeral pointer ++** If P3!=0 then this opcode is allowed to make an ephemeral pointer + ** into the database page. That means that the content of the output + ** register will be invalidated as soon as the cursor moves - including +-** moves caused by other cursors that "save" the the current cursors ++** moves caused by other cursors that "save" the current cursors + ** position in order that they can write to the same table. If P3==0 + ** then a copy of the data is made into memory. P3!=0 is faster, but + ** P3==0 is safer. +@@ -86116,6 +87963,9 @@ + assert( pC->uc.pCursor!=0 ); + sqlite3BtreeClearCursor(pC->uc.pCursor); + } ++#ifdef SQLITE_DEBUG ++ if( pC->seekOp==0 ) pC->seekOp = OP_NullRow; ++#endif + break; + } + +@@ -86234,7 +88084,7 @@ + p->aCounter[SQLITE_STMTSTATUS_SORT]++; + /* Fall through into OP_Rewind */ + } +-/* Opcode: Rewind P1 P2 * * * ++/* Opcode: Rewind P1 P2 * * P5 + ** + ** The next use of the Rowid or Column or Next instruction for P1 + ** will refer to the first entry in the database table or index. +@@ -86242,6 +88092,10 @@ + ** If the table or index is not empty, fall through to the following + ** instruction. + ** ++** If P5 is non-zero and the table is not empty, then the "skip-next" ++** flag is set on the cursor so that the next OP_Next instruction ++** executed on it is a no-op. ++** + ** This opcode leaves the cursor configured to move in forward order, + ** from the beginning toward the end. In other words, the cursor is + ** configured to use Next, not Prev. +@@ -86266,6 +88120,9 @@ + pCrsr = pC->uc.pCursor; + assert( pCrsr ); + rc = sqlite3BtreeFirst(pCrsr, &res); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( pOp->p5 ) sqlite3BtreeSkipNext(pCrsr); ++#endif + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; + } +@@ -86302,13 +88159,8 @@ + ** If P5 is positive and the jump is taken, then event counter + ** number P5-1 in the prepared statement is incremented. + ** +-** See also: Prev, NextIfOpen ++** See also: Prev + */ +-/* Opcode: NextIfOpen P1 P2 P3 P4 P5 +-** +-** This opcode works just like Next except that if cursor P1 is not +-** open it behaves a no-op. +-*/ + /* Opcode: Prev P1 P2 P3 P4 P5 + ** + ** Back up cursor P1 so that it points to the previous key/data pair in its +@@ -86335,11 +88187,6 @@ + ** If P5 is positive and the jump is taken, then event counter + ** number P5-1 in the prepared statement is incremented. + */ +-/* Opcode: PrevIfOpen P1 P2 P3 P4 P5 +-** +-** This opcode works just like Prev except that if cursor P1 is not +-** open it behaves a no-op. +-*/ + /* Opcode: SorterNext P1 P2 * * P5 + ** + ** This opcode works just like OP_Next except that P1 must be a +@@ -86354,10 +88201,6 @@ + assert( isSorter(pC) ); + rc = sqlite3VdbeSorterNext(db, pC); + goto next_tail; +-case OP_PrevIfOpen: /* jump */ +-case OP_NextIfOpen: /* jump */ +- if( p->apCsr[pOp->p1]==0 ) break; +- /* Fall through */ + case OP_Prev: /* jump */ + case OP_Next: /* jump */ + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); +@@ -86368,17 +88211,17 @@ + assert( pC->eCurType==CURTYPE_BTREE ); + assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext ); + assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious ); +- assert( pOp->opcode!=OP_NextIfOpen || pOp->p4.xAdvance==sqlite3BtreeNext ); +- assert( pOp->opcode!=OP_PrevIfOpen || pOp->p4.xAdvance==sqlite3BtreePrevious); + +- /* The Next opcode is only used after SeekGT, SeekGE, and Rewind. ++ /* The Next opcode is only used after SeekGT, SeekGE, Rewind, and Found. + ** The Prev opcode is only used after SeekLT, SeekLE, and Last. */ +- assert( pOp->opcode!=OP_Next || pOp->opcode!=OP_NextIfOpen ++ assert( pOp->opcode!=OP_Next + || pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE +- || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found); +- assert( pOp->opcode!=OP_Prev || pOp->opcode!=OP_PrevIfOpen ++ || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found ++ || pC->seekOp==OP_NullRow); ++ assert( pOp->opcode!=OP_Prev + || pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE +- || pC->seekOp==OP_Last ); ++ || pC->seekOp==OP_Last ++ || pC->seekOp==OP_NullRow); + + rc = pOp->p4.xAdvance(pC->uc.pCursor, pOp->p3); + next_tail: +@@ -86440,6 +88283,7 @@ + + assert( pOp->p1>=0 && pOp->p1<p->nCursor ); + pC = p->apCsr[pOp->p1]; ++ sqlite3VdbeIncrWriteCounter(p, pC); + assert( pC!=0 ); + assert( isSorter(pC)==(pOp->opcode==OP_SorterInsert) ); + pIn2 = &aMem[pOp->p2]; +@@ -86486,6 +88330,7 @@ + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( pC->eCurType==CURTYPE_BTREE ); ++ sqlite3VdbeIncrWriteCounter(p, pC); + pCrsr = pC->uc.pCursor; + assert( pCrsr!=0 ); + assert( pOp->p5==0 ); +@@ -86659,7 +88504,13 @@ + } + r.aMem = &aMem[pOp->p3]; + #ifdef SQLITE_DEBUG +- { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); } ++ { ++ int i; ++ for(i=0; i<r.nField; i++){ ++ assert( memIsValid(&r.aMem[i]) ); ++ REGISTER_TRACE(pOp->p3+i, &aMem[pOp->p3+i]); ++ } ++ } + #endif + res = 0; /* Not needed. Only used to silence a warning. */ + rc = sqlite3VdbeIdxKeyCompare(db, pC, &r, &res); +@@ -86708,6 +88559,7 @@ + int iMoved; + int iDb; + ++ sqlite3VdbeIncrWriteCounter(p, 0); + assert( p->readOnly==0 ); + assert( pOp->p1>1 ); + pOut = out2Prerelease(p, pOp); +@@ -86757,6 +88609,7 @@ + case OP_Clear: { + int nChange; + ++ sqlite3VdbeIncrWriteCounter(p, 0); + nChange = 0; + assert( p->readOnly==0 ); + assert( DbMaskTest(p->btreeMask, pOp->p2) ); +@@ -86806,7 +88659,7 @@ + ** Allocate a new b-tree in the main database file if P1==0 or in the + ** TEMP database file if P1==1 or in an attached database if + ** P1>1. The P3 argument must be 1 (BTREE_INTKEY) for a rowid table +-** it must be 2 (BTREE_BLOBKEY) for a index or WITHOUT ROWID table. ++** it must be 2 (BTREE_BLOBKEY) for an index or WITHOUT ROWID table. + ** The root page number of the new b-tree is stored in register P2. + */ + case OP_CreateBtree: { /* out2 */ +@@ -86813,6 +88666,7 @@ + int pgno; + Db *pDb; + ++ sqlite3VdbeIncrWriteCounter(p, 0); + pOut = out2Prerelease(p, pOp); + pgno = 0; + assert( pOp->p3==BTREE_INTKEY || pOp->p3==BTREE_BLOBKEY ); +@@ -86832,6 +88686,7 @@ + ** Run the SQL statement or statements specified in the P4 string. + */ + case OP_SqlExec: { ++ sqlite3VdbeIncrWriteCounter(p, 0); + db->nSqlExec++; + rc = sqlite3_exec(db, pOp->p4.z, 0, 0, 0); + db->nSqlExec--; +@@ -86842,7 +88697,8 @@ + /* Opcode: ParseSchema P1 * * P4 * + ** + ** Read and parse all entries from the SQLITE_MASTER table of database P1 +-** that match the WHERE clause P4. ++** that match the WHERE clause P4. If P4 is a NULL pointer, then the ++** entire schema for P1 is reparsed. + ** + ** This opcode invokes the parser to create a new virtual machine, + ** then runs the new virtual machine. It is thus a re-entrant opcode. +@@ -86866,11 +88722,22 @@ + iDb = pOp->p1; + assert( iDb>=0 && iDb<db->nDb ); + assert( DbHasProperty(db, iDb, DB_SchemaLoaded) ); +- /* Used to be a conditional */ { ++ ++#ifndef SQLITE_OMIT_ALTERTABLE ++ if( pOp->p4.z==0 ){ ++ sqlite3SchemaClear(db->aDb[iDb].pSchema); ++ db->mDbFlags &= ~DBFLAG_SchemaKnownOk; ++ rc = sqlite3InitOne(db, iDb, &p->zErrMsg, INITFLAG_AlterTable); ++ db->mDbFlags |= DBFLAG_SchemaChange; ++ p->expired = 0; ++ }else ++#endif ++ { + zMaster = MASTER_NAME; + initData.db = db; +- initData.iDb = pOp->p1; ++ initData.iDb = iDb; + initData.pzErrMsg = &p->zErrMsg; ++ initData.mInitFlags = 0; + zSql = sqlite3MPrintf(db, + "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid", + db->aDb[iDb].zDbSName, zMaster, pOp->p4.z); +@@ -86921,6 +88788,7 @@ + ** schema consistent with what is on disk. + */ + case OP_DropTable: { ++ sqlite3VdbeIncrWriteCounter(p, 0); + sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p4.z); + break; + } +@@ -86934,6 +88802,7 @@ + ** schema consistent with what is on disk. + */ + case OP_DropIndex: { ++ sqlite3VdbeIncrWriteCounter(p, 0); + sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p4.z); + break; + } +@@ -86947,6 +88816,7 @@ + ** schema consistent with what is on disk. + */ + case OP_DropTrigger: { ++ sqlite3VdbeIncrWriteCounter(p, 0); + sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p4.z); + break; + } +@@ -87020,11 +88890,11 @@ + pIn1 = &aMem[pOp->p1]; + pIn2 = &aMem[pOp->p2]; + assert( (pIn2->flags & MEM_Int)!=0 ); +- if( (pIn1->flags & MEM_RowSet)==0 ){ +- sqlite3VdbeMemSetRowSet(pIn1); +- if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem; ++ if( (pIn1->flags & MEM_Blob)==0 ){ ++ if( sqlite3VdbeMemSetRowSet(pIn1) ) goto no_mem; + } +- sqlite3RowSetInsert(pIn1->u.pRowSet, pIn2->u.i); ++ assert( sqlite3VdbeMemIsRowSet(pIn1) ); ++ sqlite3RowSetInsert((RowSet*)pIn1->z, pIn2->u.i); + break; + } + +@@ -87040,8 +88910,9 @@ + i64 val; + + pIn1 = &aMem[pOp->p1]; +- if( (pIn1->flags & MEM_RowSet)==0 +- || sqlite3RowSetNext(pIn1->u.pRowSet, &val)==0 ++ assert( (pIn1->flags & MEM_Blob)==0 || sqlite3VdbeMemIsRowSet(pIn1) ); ++ if( (pIn1->flags & MEM_Blob)==0 ++ || sqlite3RowSetNext((RowSet*)pIn1->z, &val)==0 + ){ + /* The boolean index is empty */ + sqlite3VdbeMemSetNull(pIn1); +@@ -87090,20 +88961,19 @@ + /* If there is anything other than a rowset object in memory cell P1, + ** delete it now and initialize P1 with an empty rowset + */ +- if( (pIn1->flags & MEM_RowSet)==0 ){ +- sqlite3VdbeMemSetRowSet(pIn1); +- if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem; ++ if( (pIn1->flags & MEM_Blob)==0 ){ ++ if( sqlite3VdbeMemSetRowSet(pIn1) ) goto no_mem; + } +- ++ assert( sqlite3VdbeMemIsRowSet(pIn1) ); + assert( pOp->p4type==P4_INT32 ); + assert( iSet==-1 || iSet>=0 ); + if( iSet ){ +- exists = sqlite3RowSetTest(pIn1->u.pRowSet, iSet, pIn3->u.i); ++ exists = sqlite3RowSetTest((RowSet*)pIn1->z, iSet, pIn3->u.i); + VdbeBranchTaken(exists!=0,2); + if( exists ) goto jump_to_p2; + } + if( iSet>=0 ){ +- sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i); ++ sqlite3RowSetInsert((RowSet*)pIn1->z, pIn3->u.i); + } + break; + } +@@ -87167,7 +89037,7 @@ + ** of the current program, and the memory required at runtime to execute + ** the trigger program. If this trigger has been fired before, then pRt + ** is already allocated. Otherwise, it must be initialized. */ +- if( (pRt->flags&MEM_Frame)==0 ){ ++ if( (pRt->flags&MEM_Blob)==0 ){ + /* SubProgram.nMem is set to the number of memory cells used by the + ** program stored in SubProgram.aOp. As well as these, one memory + ** cell is required for each cursor used by the program. Set local +@@ -87185,8 +89055,10 @@ + goto no_mem; + } + sqlite3VdbeMemRelease(pRt); +- pRt->flags = MEM_Frame; +- pRt->u.pFrame = pFrame; ++ pRt->flags = MEM_Blob|MEM_Dyn; ++ pRt->z = (char*)pFrame; ++ pRt->n = nByte; ++ pRt->xDel = sqlite3VdbeFrameMemDel; + + pFrame->v = p; + pFrame->nChildMem = nMem; +@@ -87202,6 +89074,9 @@ + #ifdef SQLITE_ENABLE_STMT_SCANSTATUS + pFrame->anExec = p->anExec; + #endif ++#ifdef SQLITE_DEBUG ++ pFrame->iFrameMagic = SQLITE_FRAME_MAGIC; ++#endif + + pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem]; + for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){ +@@ -87209,7 +89084,8 @@ + pMem->db = db; + } + }else{ +- pFrame = pRt->u.pFrame; ++ pFrame = (VdbeFrame*)pRt->z; ++ assert( pRt->xDel==sqlite3VdbeFrameMemDel ); + assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem + || (pProgram->nCsr==0 && pProgram->nMem+1==pFrame->nChildMem) ); + assert( pProgram->nCsr==pFrame->nChildCsr ); +@@ -87438,24 +89314,35 @@ + } + + +-/* Opcode: AggStep0 * P2 P3 P4 P5 ++/* Opcode: AggStep * P2 P3 P4 P5 + ** Synopsis: accum=r[P3] step(r[P2@P5]) + ** +-** Execute the step function for an aggregate. The +-** function has P5 arguments. P4 is a pointer to the FuncDef +-** structure that specifies the function. Register P3 is the ++** Execute the xStep function for an aggregate. ++** The function has P5 arguments. P4 is a pointer to the ++** FuncDef structure that specifies the function. Register P3 is the + ** accumulator. + ** + ** The P5 arguments are taken from register P2 and its + ** successors. + */ +-/* Opcode: AggStep * P2 P3 P4 P5 ++/* Opcode: AggInverse * P2 P3 P4 P5 ++** Synopsis: accum=r[P3] inverse(r[P2@P5]) ++** ++** Execute the xInverse function for an aggregate. ++** The function has P5 arguments. P4 is a pointer to the ++** FuncDef structure that specifies the function. Register P3 is the ++** accumulator. ++** ++** The P5 arguments are taken from register P2 and its ++** successors. ++*/ ++/* Opcode: AggStep1 P1 P2 P3 P4 P5 + ** Synopsis: accum=r[P3] step(r[P2@P5]) + ** +-** Execute the step function for an aggregate. The +-** function has P5 arguments. P4 is a pointer to an sqlite3_context +-** object that is used to run the function. Register P3 is +-** as the accumulator. ++** Execute the xStep (if P1==0) or xInverse (if P1!=0) function for an ++** aggregate. The function has P5 arguments. P4 is a pointer to the ++** FuncDef structure that specifies the function. Register P3 is the ++** accumulator. + ** + ** The P5 arguments are taken from register P2 and its + ** successors. +@@ -87466,7 +89353,8 @@ + ** sqlite3_context only happens once, instead of on each call to the + ** step function. + */ +-case OP_AggStep0: { ++case OP_AggInverse: ++case OP_AggStep: { + int n; + sqlite3_context *pCtx; + +@@ -87489,10 +89377,14 @@ + pCtx->argc = n; + pOp->p4type = P4_FUNCCTX; + pOp->p4.pCtx = pCtx; +- pOp->opcode = OP_AggStep; ++ ++ /* OP_AggInverse must have P1==1 and OP_AggStep must have P1==0 */ ++ assert( pOp->p1==(pOp->opcode==OP_AggInverse) ); ++ ++ pOp->opcode = OP_AggStep1; + /* Fall through into OP_AggStep */ + } +-case OP_AggStep: { ++case OP_AggStep1: { + int i; + sqlite3_context *pCtx; + Mem *pMem; +@@ -87501,6 +89393,17 @@ + pCtx = pOp->p4.pCtx; + pMem = &aMem[pOp->p3]; + ++#ifdef SQLITE_DEBUG ++ if( pOp->p1 ){ ++ /* This is an OP_AggInverse call. Verify that xStep has always ++ ** been called at least once prior to any xInverse call. */ ++ assert( pMem->uTemp==0x1122e0e3 ); ++ }else{ ++ /* This is an OP_AggStep call. Mark it as such. */ ++ pMem->uTemp = 0x1122e0e3; ++ } ++#endif ++ + /* If this function is inside of a trigger, the register array in aMem[] + ** might change from one evaluation to the next. The next block of code + ** checks to see if the register array has changed, and if so it +@@ -87521,7 +89424,13 @@ + assert( pCtx->pOut->flags==MEM_Null ); + assert( pCtx->isError==0 ); + assert( pCtx->skipFlag==0 ); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( pOp->p1 ){ ++ (pCtx->pFunc->xInverse)(pCtx,pCtx->argc,pCtx->argv); ++ }else ++#endif + (pCtx->pFunc->xSFunc)(pCtx,pCtx->argc,pCtx->argv); /* IMP: R-24505-23230 */ ++ + if( pCtx->isError ){ + if( pCtx->isError>0 ){ + sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut)); +@@ -87546,22 +89455,46 @@ + /* Opcode: AggFinal P1 P2 * P4 * + ** Synopsis: accum=r[P1] N=P2 + ** +-** Execute the finalizer function for an aggregate. P1 is +-** the memory location that is the accumulator for the aggregate. ++** P1 is the memory location that is the accumulator for an aggregate ++** or window function. Execute the finalizer function ++** for an aggregate and store the result in P1. + ** + ** P2 is the number of arguments that the step function takes and + ** P4 is a pointer to the FuncDef for this function. The P2 + ** argument is not used by this opcode. It is only there to disambiguate + ** functions that can take varying numbers of arguments. The +-** P4 argument is only needed for the degenerate case where ++** P4 argument is only needed for the case where + ** the step function was not previously called. + */ ++/* Opcode: AggValue * P2 P3 P4 * ++** Synopsis: r[P3]=value N=P2 ++** ++** Invoke the xValue() function and store the result in register P3. ++** ++** P2 is the number of arguments that the step function takes and ++** P4 is a pointer to the FuncDef for this function. The P2 ++** argument is not used by this opcode. It is only there to disambiguate ++** functions that can take varying numbers of arguments. The ++** P4 argument is only needed for the case where ++** the step function was not previously called. ++*/ ++case OP_AggValue: + case OP_AggFinal: { + Mem *pMem; + assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); ++ assert( pOp->p3==0 || pOp->opcode==OP_AggValue ); + pMem = &aMem[pOp->p1]; + assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 ); +- rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( pOp->p3 ){ ++ rc = sqlite3VdbeMemAggValue(pMem, &aMem[pOp->p3], pOp->p4.pFunc); ++ pMem = &aMem[pOp->p3]; ++ }else ++#endif ++ { ++ rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc); ++ } ++ + if( rc ){ + sqlite3VdbeError(p, "%s", sqlite3_value_text(pMem)); + goto abort_due_to_error; +@@ -87756,7 +89689,7 @@ + } + #endif + +-/* Opcode: Expire P1 * * * * ++/* Opcode: Expire P1 P2 * * * + ** + ** Cause precompiled statements to expire. When an expired statement + ** is executed using sqlite3_step() it will either automatically +@@ -87765,12 +89698,19 @@ + ** + ** If P1 is 0, then all SQL statements become expired. If P1 is non-zero, + ** then only the currently executing statement is expired. ++** ++** If P2 is 0, then SQL statements are expired immediately. If P2 is 1, ++** then running SQL statements are allowed to continue to run to completion. ++** The P2==1 case occurs when a CREATE INDEX or similar schema change happens ++** that might help the statement run faster but which does not affect the ++** correctness of operation. + */ + case OP_Expire: { ++ assert( pOp->p2==0 || pOp->p2==1 ); + if( !pOp->p1 ){ +- sqlite3ExpirePreparedStatements(db); ++ sqlite3ExpirePreparedStatements(db, pOp->p2); + }else{ +- p->expired = 1; ++ p->expired = pOp->p2+1; + } + break; + } +@@ -87992,10 +89932,11 @@ + ** + ** If the VColumn opcode is being used to fetch the value of + ** an unchanging column during an UPDATE operation, then the P5 +-** value is 1. Otherwise, P5 is 0. The P5 value is returned +-** by sqlite3_vtab_nochange() routine can can be used +-** by virtual table implementations to return special "no-change" +-** marks which can be more efficient, depending on the virtual table. ++** value is OPFLAG_NOCHNG. This will cause the sqlite3_vtab_nochange() ++** function to return true inside the xColumn method of the virtual ++** table implementation. The P5 column might also contain other ++** bits (OPFLAG_LENGTHARG or OPFLAG_TYPEOFARG) but those bits are ++** unused by OP_VColumn. + */ + case OP_VColumn: { + sqlite3_vtab *pVtab; +@@ -88017,7 +89958,8 @@ + assert( pModule->xColumn ); + memset(&sContext, 0, sizeof(sContext)); + sContext.pOut = pDest; +- if( pOp->p5 ){ ++ testcase( (pOp->p5 & OPFLAG_NOCHNG)==0 && pOp->p5!=0 ); ++ if( pOp->p5 & OPFLAG_NOCHNG ){ + sqlite3VdbeMemSetNull(pDest); + pDest->flags = MEM_Null|MEM_Zero; + pDest->u.nZero = 0; +@@ -88094,7 +90036,10 @@ + case OP_VRename: { + sqlite3_vtab *pVtab; + Mem *pName; +- ++ int isLegacy; ++ ++ isLegacy = (db->flags & SQLITE_LegacyAlter); ++ db->flags |= SQLITE_LegacyAlter; + pVtab = pOp->p4.pVtab->pVtab; + pName = &aMem[pOp->p1]; + assert( pVtab->pModule->xRename ); +@@ -88108,6 +90053,7 @@ + rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8); + if( rc ) goto abort_due_to_error; + rc = pVtab->pModule->xRename(pVtab, pName->z); ++ if( isLegacy==0 ) db->flags &= ~SQLITE_LegacyAlter; + sqlite3VtabImportErrmsg(p, pVtab); + p->expired = 0; + if( rc ) goto abort_due_to_error; +@@ -88156,6 +90102,8 @@ + || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace + ); + assert( p->readOnly==0 ); ++ if( db->mallocFailed ) goto no_mem; ++ sqlite3VdbeIncrWriteCounter(p, 0); + pVtab = pOp->p4.pVtab->pVtab; + if( pVtab==0 || NEVER(pVtab->pModule==0) ){ + rc = SQLITE_LOCKED; +@@ -88276,8 +90224,8 @@ + ** + ** See also: Function0, AggStep, AggFinal + */ +-case OP_PureFunc0: +-case OP_Function0: { ++case OP_PureFunc0: /* group */ ++case OP_Function0: { /* group */ + int n; + sqlite3_context *pCtx; + +@@ -88301,8 +90249,8 @@ + pOp->opcode += 2; + /* Fall through into OP_Function */ + } +-case OP_PureFunc: +-case OP_Function: { ++case OP_PureFunc: /* group */ ++case OP_Function: { /* group */ + int i; + sqlite3_context *pCtx; + +@@ -88473,6 +90421,22 @@ + } + #endif /* SQLITE_ENABLE_CURSOR_HINTS */ + ++#ifdef SQLITE_DEBUG ++/* Opcode: Abortable * * * * * ++** ++** Verify that an Abort can happen. Assert if an Abort at this point ++** might cause database corruption. This opcode only appears in debugging ++** builds. ++** ++** An Abort is safe if either there have been no writes, or if there is ++** an active statement journal. ++*/ ++case OP_Abortable: { ++ sqlite3VdbeAssertAbortable(p); ++ break; ++} ++#endif ++ + /* Opcode: Noop * * * * * + ** + ** Do nothing. This instruction is often useful as a jump +@@ -88484,8 +90448,9 @@ + ** This opcode records information from the optimizer. It is the + ** the same as a no-op. This opcodesnever appears in a real VM program. + */ +-default: { /* This is really OP_Noop and OP_Explain */ ++default: { /* This is really OP_Noop, OP_Explain */ + assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain ); ++ + break; + } + +@@ -91210,8 +93175,12 @@ + ){ + int rc = SQLITE_OK; /* Return code */ + int i; /* For looping over PmaReader objects */ +- int nTree = pMerger->nTree; ++ int nTree; /* Number of subtrees to merge */ + ++ /* Failure to allocate the merge would have been detected prior to ++ ** invoking this routine */ ++ assert( pMerger!=0 ); ++ + /* eMode is always INCRINIT_NORMAL in single-threaded mode */ + assert( SQLITE_MAX_WORKER_THREADS>0 || eMode==INCRINIT_NORMAL ); + +@@ -91219,6 +93188,7 @@ + assert( pMerger->pTask==0 ); + pMerger->pTask = pTask; + ++ nTree = pMerger->nTree; + for(i=0; i<nTree; i++){ + if( SQLITE_MAX_WORKER_THREADS>0 && eMode==INCRINIT_ROOT ){ + /* PmaReaders should be normally initialized in order, as if they are +@@ -92347,6 +94317,14 @@ + }else if( pExpr->x.pList ){ + if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort; + } ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( ExprHasProperty(pExpr, EP_WinFunc) ){ ++ Window *pWin = pExpr->y.pWin; ++ if( sqlite3WalkExprList(pWalker, pWin->pPartition) ) return WRC_Abort; ++ if( sqlite3WalkExprList(pWalker, pWin->pOrderBy) ) return WRC_Abort; ++ if( sqlite3WalkExpr(pWalker, pWin->pFilter) ) return WRC_Abort; ++ } ++#endif + } + break; + } +@@ -92530,29 +94508,31 @@ + assert( pOrig!=0 ); + db = pParse->db; + pDup = sqlite3ExprDup(db, pOrig, 0); +- if( pDup==0 ) return; +- if( zType[0]!='G' ) incrAggFunctionDepth(pDup, nSubquery); +- if( pExpr->op==TK_COLLATE ){ +- pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken); +- } +- ExprSetProperty(pDup, EP_Alias); ++ if( pDup!=0 ){ ++ if( zType[0]!='G' ) incrAggFunctionDepth(pDup, nSubquery); ++ if( pExpr->op==TK_COLLATE ){ ++ pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken); ++ } ++ ExprSetProperty(pDup, EP_Alias); + +- /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This +- ** prevents ExprDelete() from deleting the Expr structure itself, +- ** allowing it to be repopulated by the memcpy() on the following line. +- ** The pExpr->u.zToken might point into memory that will be freed by the +- ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to +- ** make a copy of the token before doing the sqlite3DbFree(). +- */ +- ExprSetProperty(pExpr, EP_Static); +- sqlite3ExprDelete(db, pExpr); +- memcpy(pExpr, pDup, sizeof(*pExpr)); +- if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){ +- assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 ); +- pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken); +- pExpr->flags |= EP_MemToken; ++ /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This ++ ** prevents ExprDelete() from deleting the Expr structure itself, ++ ** allowing it to be repopulated by the memcpy() on the following line. ++ ** The pExpr->u.zToken might point into memory that will be freed by the ++ ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to ++ ** make a copy of the token before doing the sqlite3DbFree(). ++ */ ++ ExprSetProperty(pExpr, EP_Static); ++ sqlite3ExprDelete(db, pExpr); ++ memcpy(pExpr, pDup, sizeof(*pExpr)); ++ if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){ ++ assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 ); ++ pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken); ++ pExpr->flags |= EP_MemToken; ++ } ++ sqlite3DbFree(db, pDup); + } +- sqlite3DbFree(db, pDup); ++ ExprSetProperty(pExpr, EP_Alias); + } + + +@@ -92612,7 +94592,7 @@ + ** (even if X is implied). + ** pExpr->iTable Set to the cursor number for the table obtained + ** from pSrcList. +-** pExpr->pTab Points to the Table structure of X.Y (even if ++** pExpr->y.pTab Points to the Table structure of X.Y (even if + ** X and/or Y are implied.) + ** pExpr->iColumn Set to the column number within the table. + ** pExpr->op Set to TK_COLUMN. +@@ -92646,7 +94626,7 @@ + struct SrcList_item *pMatch = 0; /* The matching pSrcList item */ + NameContext *pTopNC = pNC; /* First namecontext in the list */ + Schema *pSchema = 0; /* Schema of the expression */ +- int isTrigger = 0; /* True if resolved to a trigger column */ ++ int eNewExprOp = TK_COLUMN; /* New value for pExpr->op on success */ + Table *pTab = 0; /* Table hold the row */ + Column *pCol; /* A column of pTab */ + +@@ -92656,7 +94636,6 @@ + + /* Initialize the node to no-match */ + pExpr->iTable = -1; +- pExpr->pTab = 0; + ExprSetVVAProperty(pExpr, EP_NoReduce); + + /* Translate the schema name in zDb into a pointer to the corresponding +@@ -92717,6 +94696,9 @@ + if( sqlite3StrICmp(zTabName, zTab)!=0 ){ + continue; + } ++ if( IN_RENAME_OBJECT && pItem->zAlias ){ ++ sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab); ++ } + } + if( 0==(cntTab++) ){ + pMatch = pItem; +@@ -92741,32 +94723,45 @@ + } + if( pMatch ){ + pExpr->iTable = pMatch->iCursor; +- pExpr->pTab = pMatch->pTab; ++ pExpr->y.pTab = pMatch->pTab; + /* RIGHT JOIN not (yet) supported */ + assert( (pMatch->fg.jointype & JT_RIGHT)==0 ); + if( (pMatch->fg.jointype & JT_LEFT)!=0 ){ + ExprSetProperty(pExpr, EP_CanBeNull); + } +- pSchema = pExpr->pTab->pSchema; ++ pSchema = pExpr->y.pTab->pSchema; + } + } /* if( pSrcList ) */ + +-#ifndef SQLITE_OMIT_TRIGGER ++#if !defined(SQLITE_OMIT_TRIGGER) || !defined(SQLITE_OMIT_UPSERT) + /* If we have not already resolved the name, then maybe +- ** it is a new.* or old.* trigger argument reference ++ ** it is a new.* or old.* trigger argument reference. Or ++ ** maybe it is an excluded.* from an upsert. + */ +- if( zDb==0 && zTab!=0 && cntTab==0 && pParse->pTriggerTab!=0 ){ +- int op = pParse->eTriggerOp; +- assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT ); +- if( op!=TK_DELETE && sqlite3StrICmp("new",zTab) == 0 ){ +- pExpr->iTable = 1; +- pTab = pParse->pTriggerTab; +- }else if( op!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){ +- pExpr->iTable = 0; +- pTab = pParse->pTriggerTab; +- }else{ +- pTab = 0; ++ if( zDb==0 && zTab!=0 && cntTab==0 ){ ++ 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( op!=TK_DELETE && sqlite3StrICmp("new",zTab) == 0 ){ ++ pExpr->iTable = 1; ++ pTab = pParse->pTriggerTab; ++ }else if( op!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){ ++ pExpr->iTable = 0; ++ pTab = pParse->pTriggerTab; ++ } + } ++#endif /* SQLITE_OMIT_TRIGGER */ ++#ifndef SQLITE_OMIT_UPSERT ++ if( (pNC->ncFlags & NC_UUpsert)!=0 ){ ++ Upsert *pUpsert = pNC->uNC.pUpsert; ++ if( pUpsert && sqlite3StrICmp("excluded",zTab)==0 ){ ++ pTab = pUpsert->pUpsertSrc->a[0].pTab; ++ pExpr->iTable = 2; ++ } ++ } ++#endif /* SQLITE_OMIT_UPSERT */ + + if( pTab ){ + int iCol; +@@ -92786,24 +94781,42 @@ + } + if( iCol<pTab->nCol ){ + cnt++; +- if( iCol<0 ){ +- pExpr->affinity = SQLITE_AFF_INTEGER; +- }else if( pExpr->iTable==0 ){ +- testcase( iCol==31 ); +- testcase( iCol==32 ); +- pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol)); +- }else{ +- testcase( iCol==31 ); +- testcase( iCol==32 ); +- pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol)); ++#ifndef SQLITE_OMIT_UPSERT ++ if( pExpr->iTable==2 ){ ++ testcase( iCol==(-1) ); ++ if( IN_RENAME_OBJECT ){ ++ pExpr->iColumn = iCol; ++ pExpr->y.pTab = pTab; ++ eNewExprOp = TK_COLUMN; ++ }else{ ++ pExpr->iTable = pNC->uNC.pUpsert->regData + iCol; ++ eNewExprOp = TK_REGISTER; ++ ExprSetProperty(pExpr, EP_Alias); ++ } ++ }else ++#endif /* SQLITE_OMIT_UPSERT */ ++ { ++#ifndef SQLITE_OMIT_TRIGGER ++ if( iCol<0 ){ ++ pExpr->affinity = SQLITE_AFF_INTEGER; ++ }else if( pExpr->iTable==0 ){ ++ testcase( iCol==31 ); ++ testcase( iCol==32 ); ++ pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol)); ++ }else{ ++ testcase( iCol==31 ); ++ testcase( iCol==32 ); ++ pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol)); ++ } ++ pExpr->y.pTab = pTab; ++ pExpr->iColumn = (i16)iCol; ++ eNewExprOp = TK_TRIGGER; ++#endif /* SQLITE_OMIT_TRIGGER */ + } +- pExpr->iColumn = (i16)iCol; +- pExpr->pTab = pTab; +- isTrigger = 1; + } + } + } +-#endif /* !defined(SQLITE_OMIT_TRIGGER) */ ++#endif /* !defined(SQLITE_OMIT_TRIGGER) || !defined(SQLITE_OMIT_UPSERT) */ + + /* + ** Perhaps the name is a reference to the ROWID +@@ -92838,10 +94851,12 @@ + ** is supported for backwards compatibility only. Hence, we issue a warning + ** on sqlite3_log() whenever the capability is used. + */ +- if( (pEList = pNC->pEList)!=0 ++ if( (pNC->ncFlags & NC_UEList)!=0 ++ && cnt==0 + && zTab==0 +- && cnt==0 + ){ ++ pEList = pNC->uNC.pEList; ++ assert( pEList!=0 ); + for(j=0; j<pEList->nExpr; j++){ + char *zAs = pEList->a[j].zName; + if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ +@@ -92862,6 +94877,9 @@ + cnt = 1; + pMatch = 0; + assert( zTab==0 && zDb==0 ); ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameTokenRemap(pParse, 0, (void*)pExpr); ++ } + goto lookupname_end; + } + } +@@ -92890,7 +94908,7 @@ + assert( pExpr->op==TK_ID ); + if( ExprHasProperty(pExpr,EP_DblQuoted) ){ + pExpr->op = TK_STRING; +- pExpr->pTab = 0; ++ pExpr->y.pTab = 0; + return WRC_Prune; + } + if( sqlite3ExprIdToTrueFalse(pExpr) ){ +@@ -92938,7 +94956,7 @@ + pExpr->pLeft = 0; + sqlite3ExprDelete(db, pExpr->pRight); + pExpr->pRight = 0; +- pExpr->op = (isTrigger ? TK_TRIGGER : TK_COLUMN); ++ pExpr->op = eNewExprOp; + ExprSetProperty(pExpr, EP_Leaf); + lookupname_end: + if( cnt==1 ){ +@@ -92968,9 +94986,9 @@ + Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0); + if( p ){ + struct SrcList_item *pItem = &pSrc->a[iSrc]; +- p->pTab = pItem->pTab; ++ p->y.pTab = pItem->pTab; + p->iTable = pItem->iCursor; +- if( p->pTab->iPKey==iCol ){ ++ if( p->y.pTab->iPKey==iCol ){ + p->iColumn = -1; + }else{ + p->iColumn = (ynVar)iCol; +@@ -93060,7 +95078,7 @@ + pItem = pSrcList->a; + assert( HasRowid(pItem->pTab) && pItem->pTab->pSelect==0 ); + pExpr->op = TK_COLUMN; +- pExpr->pTab = pItem->pTab; ++ pExpr->y.pTab = pItem->pTab; + pExpr->iTable = pItem->iCursor; + pExpr->iColumn = -1; + pExpr->affinity = SQLITE_AFF_INTEGER; +@@ -93089,18 +95107,23 @@ + zTable = 0; + zColumn = pExpr->u.zToken; + }else{ ++ Expr *pLeft = pExpr->pLeft; + notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr); + pRight = pExpr->pRight; + if( pRight->op==TK_ID ){ + zDb = 0; +- zTable = pExpr->pLeft->u.zToken; +- zColumn = pRight->u.zToken; + }else{ + assert( pRight->op==TK_DOT ); +- zDb = pExpr->pLeft->u.zToken; +- zTable = pRight->pLeft->u.zToken; +- zColumn = pRight->pRight->u.zToken; ++ zDb = pLeft->u.zToken; ++ pLeft = pRight->pLeft; ++ pRight = pRight->pRight; + } ++ zTable = pLeft->u.zToken; ++ zColumn = pRight->u.zToken; ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameTokenRemap(pParse, (void*)pExpr, (void*)pRight); ++ sqlite3RenameTokenRemap(pParse, (void*)&pExpr->y.pTab, (void*)pLeft); ++ } + } + return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr); + } +@@ -93181,41 +95204,105 @@ + notValid(pParse, pNC, "non-deterministic functions", + NC_IdxExpr|NC_PartIdx); + } ++ if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0 ++ && pParse->nested==0 ++ && sqlite3Config.bInternalFunctions==0 ++ ){ ++ /* Internal-use-only functions are disallowed unless the ++ ** SQL is being compiled using sqlite3NestedParse() */ ++ no_such_func = 1; ++ pDef = 0; ++ } + } +- if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ +- sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); +- pNC->nErr++; +- is_agg = 0; +- }else if( no_such_func && pParse->db->init.busy==0 ++ ++ if( 0==IN_RENAME_OBJECT ){ ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ assert( is_agg==0 || (pDef->funcFlags & SQLITE_FUNC_MINMAX) ++ || (pDef->xValue==0 && pDef->xInverse==0) ++ || (pDef->xValue && pDef->xInverse && pDef->xSFunc && pDef->xFinalize) ++ ); ++ if( pDef && pDef->xValue==0 && ExprHasProperty(pExpr, EP_WinFunc) ){ ++ sqlite3ErrorMsg(pParse, ++ "%.*s() may not be used as a window function", nId, zId ++ ); ++ pNC->nErr++; ++ }else if( ++ (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) ++ || (is_agg && (pDef->funcFlags&SQLITE_FUNC_WINDOW) && !pExpr->y.pWin) ++ || (is_agg && pExpr->y.pWin && (pNC->ncFlags & NC_AllowWin)==0) ++ ){ ++ const char *zType; ++ if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->y.pWin ){ ++ zType = "window"; ++ }else{ ++ zType = "aggregate"; ++ } ++ sqlite3ErrorMsg(pParse, "misuse of %s function %.*s()",zType,nId,zId); ++ pNC->nErr++; ++ is_agg = 0; ++ } ++#else ++ if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) ){ ++ sqlite3ErrorMsg(pParse,"misuse of aggregate function %.*s()",nId,zId); ++ pNC->nErr++; ++ is_agg = 0; ++ } ++#endif ++ else if( no_such_func && pParse->db->init.busy==0 + #ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION +- && pParse->explain==0 ++ && pParse->explain==0 + #endif +- ){ +- sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId); +- pNC->nErr++; +- }else if( wrong_num_args ){ +- sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()", +- nId, zId); +- pNC->nErr++; ++ ){ ++ sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId); ++ pNC->nErr++; ++ }else if( wrong_num_args ){ ++ sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()", ++ nId, zId); ++ pNC->nErr++; ++ } ++ if( is_agg ){ ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ pNC->ncFlags &= ~(pExpr->y.pWin ? NC_AllowWin : NC_AllowAgg); ++#else ++ pNC->ncFlags &= ~NC_AllowAgg; ++#endif ++ } + } +- if( is_agg ) pNC->ncFlags &= ~NC_AllowAgg; + sqlite3WalkExprList(pWalker, pList); + if( is_agg ){ +- NameContext *pNC2 = pNC; +- pExpr->op = TK_AGG_FUNCTION; +- pExpr->op2 = 0; +- while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){ +- pExpr->op2++; +- pNC2 = pNC2->pNext; +- } +- assert( pDef!=0 ); +- if( pNC2 ){ +- assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg ); +- testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 ); +- pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( pExpr->y.pWin ){ ++ Select *pSel = pNC->pWinSelect; ++ sqlite3WalkExprList(pWalker, pExpr->y.pWin->pPartition); ++ sqlite3WalkExprList(pWalker, pExpr->y.pWin->pOrderBy); ++ sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter); ++ sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->y.pWin, pDef); ++ if( 0==pSel->pWin ++ || 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->y.pWin) ++ ){ ++ pExpr->y.pWin->pNextWin = pSel->pWin; ++ pSel->pWin = pExpr->y.pWin; ++ } ++ pNC->ncFlags |= NC_AllowWin; ++ }else ++#endif /* SQLITE_OMIT_WINDOWFUNC */ ++ { ++ NameContext *pNC2 = pNC; ++ pExpr->op = TK_AGG_FUNCTION; ++ pExpr->op2 = 0; ++ while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){ ++ pExpr->op2++; ++ pNC2 = pNC2->pNext; ++ } ++ assert( pDef!=0 ); ++ if( pNC2 ){ ++ assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg ); ++ testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 ); ++ pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX); + ++ } ++ pNC->ncFlags |= NC_AllowAgg; + } +- pNC->ncFlags |= NC_AllowAgg; + } + /* FIX ME: Compute pExpr->affinity based on the expected return + ** type of the function +@@ -93370,8 +95457,8 @@ + memset(&nc, 0, sizeof(nc)); + nc.pParse = pParse; + nc.pSrcList = pSelect->pSrc; +- nc.pEList = pEList; +- nc.ncFlags = NC_AllowAgg; ++ nc.uNC.pEList = pEList; ++ nc.ncFlags = NC_AllowAgg|NC_UEList; + nc.nErr = 0; + db = pParse->db; + savedSuppErr = db->suppressErr; +@@ -93616,6 +95703,19 @@ + } + for(j=0; j<pSelect->pEList->nExpr; j++){ + if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){ ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( ExprHasProperty(pE, EP_WinFunc) ){ ++ /* Since this window function is being changed into a reference ++ ** to the same window function the result set, remove the instance ++ ** of this window function from the Select.pWin list. */ ++ Window **pp; ++ for(pp=&pSelect->pWin; *pp; pp=&(*pp)->pNextWin){ ++ if( *pp==pE->y.pWin ){ ++ *pp = (*pp)->pNextWin; ++ } ++ } ++ } ++#endif + pItem->u.x.iOrderByCol = j+1; + } + } +@@ -93672,6 +95772,7 @@ + */ + memset(&sNC, 0, sizeof(sNC)); + sNC.pParse = pParse; ++ sNC.pWinSelect = p; + if( sqlite3ResolveExprNames(&sNC, p->pLimit) ){ + return WRC_Abort; + } +@@ -93720,12 +95821,13 @@ + /* Set up the local name-context to pass to sqlite3ResolveExprNames() to + ** resolve the result-set expression list. + */ +- sNC.ncFlags = NC_AllowAgg; ++ sNC.ncFlags = NC_AllowAgg|NC_AllowWin; + sNC.pSrcList = p->pSrc; + sNC.pNext = pOuterNC; + + /* Resolve names in the result set. */ + if( sqlite3ResolveExprListNames(&sNC, p->pEList) ) return WRC_Abort; ++ sNC.ncFlags &= ~NC_AllowWin; + + /* If there are no aggregate functions in the result-set, and no GROUP BY + ** expression, do not allow aggregates in any of the other expressions. +@@ -93754,7 +95856,9 @@ + ** Minor point: If this is the case, then the expression will be + ** re-evaluated for each reference to it. + */ +- sNC.pEList = p->pEList; ++ assert( (sNC.ncFlags & (NC_UAggInfo|NC_UUpsert))==0 ); ++ sNC.uNC.pEList = p->pEList; ++ sNC.ncFlags |= NC_UEList; + if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort; + if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort; + +@@ -93772,7 +95876,7 @@ + ** outer queries + */ + sNC.pNext = 0; +- sNC.ncFlags |= NC_AllowAgg; ++ sNC.ncFlags |= NC_AllowAgg|NC_AllowWin; + + /* If this is a converted compound query, move the ORDER BY clause from + ** the sub-query back to the parent query. At this point each term +@@ -93803,6 +95907,7 @@ + if( db->mallocFailed ){ + return WRC_Abort; + } ++ sNC.ncFlags &= ~NC_AllowWin; + + /* Resolve the GROUP BY clause. At the same time, make sure + ** the GROUP BY clause does not contain aggregate functions. +@@ -93987,7 +96092,7 @@ + Table *pTab, /* The table being referenced */ + int type, /* NC_IsCheck or NC_PartIdx or NC_IdxExpr */ + Expr *pExpr, /* Expression to resolve. May be NULL. */ +- ExprList *pList /* Expression list to resolve. May be NUL. */ ++ ExprList *pList /* Expression list to resolve. May be NULL. */ + ){ + SrcList sSrc; /* Fake SrcList for pParse->pNewTable */ + NameContext sNC; /* Name context for pParse->pNewTable */ +@@ -94068,8 +96173,8 @@ + return sqlite3AffinityType(pExpr->u.zToken, 0); + } + #endif +- if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->pTab ){ +- return sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn); ++ if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->y.pTab ){ ++ return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn); + } + if( op==TK_SELECT_COLUMN ){ + assert( pExpr->pLeft->flags&EP_xIsSelect ); +@@ -94151,27 +96256,27 @@ + while( p ){ + int op = p->op; + if( p->flags & EP_Generic ) break; +- if( op==TK_CAST || op==TK_UPLUS ){ +- p = p->pLeft; +- continue; +- } +- if( op==TK_COLLATE || (op==TK_REGISTER && p->op2==TK_COLLATE) ){ +- pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken); +- break; +- } + if( (op==TK_AGG_COLUMN || op==TK_COLUMN + || op==TK_REGISTER || op==TK_TRIGGER) +- && p->pTab!=0 ++ && p->y.pTab!=0 + ){ +- /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally ++ /* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally + ** a TK_COLUMN but was previously evaluated and cached in a register */ + int j = p->iColumn; + if( j>=0 ){ +- const char *zColl = p->pTab->aCol[j].zColl; ++ const char *zColl = p->y.pTab->aCol[j].zColl; + pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); + } + break; + } ++ if( op==TK_CAST || op==TK_UPLUS ){ ++ p = p->pLeft; ++ continue; ++ } ++ if( op==TK_COLLATE || (op==TK_REGISTER && p->op2==TK_COLLATE) ){ ++ pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken); ++ break; ++ } + if( p->flags & EP_Collate ){ + if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){ + p = p->pLeft; +@@ -94591,7 +96696,6 @@ + Expr *pL, *pR; + int r1, r2; + assert( i>=0 && i<nLeft ); +- if( i>0 ) sqlite3ExprCachePush(pParse); + r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, ®Free1); + r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, ®Free2); + codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5); +@@ -94603,7 +96707,6 @@ + testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); + sqlite3ReleaseTempReg(pParse, regFree1); + sqlite3ReleaseTempReg(pParse, regFree2); +- if( i>0 ) sqlite3ExprCachePop(pParse); + if( i==nLeft-1 ){ + break; + } +@@ -94951,7 +97054,12 @@ + ** Construct a new expression node for a function with multiple + ** arguments. + */ +-SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){ ++SQLITE_PRIVATE Expr *sqlite3ExprFunction( ++ Parse *pParse, /* Parsing context */ ++ ExprList *pList, /* Argument list */ ++ Token *pToken, /* Name of the function */ ++ int eDistinct /* SF_Distinct or SF_ALL or 0 */ ++){ + Expr *pNew; + sqlite3 *db = pParse->db; + assert( pToken ); +@@ -94960,10 +97068,14 @@ + sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */ + return 0; + } ++ if( pList && pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ ++ sqlite3ErrorMsg(pParse, "too many arguments on function %T", pToken); ++ } + pNew->x.pList = pList; + ExprSetProperty(pNew, EP_HasFunc); + assert( !ExprHasProperty(pNew, EP_xIsSelect) ); + sqlite3ExprSetHeightAndFlags(pParse, pNew); ++ if( eDistinct==SF_Distinct ) ExprSetProperty(pNew, EP_Distinct); + return pNew; + } + +@@ -95055,6 +97167,10 @@ + assert( p!=0 ); + /* Sanity check: Assert that the IntValue is non-negative if it exists */ + assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 ); ++ ++ assert( !ExprHasProperty(p, EP_WinFunc) || p->y.pWin!=0 || db->mallocFailed ); ++ assert( p->op!=TK_FUNCTION || ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ++ || p->y.pWin==0 || ExprHasProperty(p, EP_WinFunc) ); + #ifdef SQLITE_DEBUG + if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){ + assert( p->pLeft==0 ); +@@ -95073,6 +97189,10 @@ + }else{ + sqlite3ExprListDelete(db, p->x.pList); + } ++ if( ExprHasProperty(p, EP_WinFunc) ){ ++ assert( p->op==TK_FUNCTION ); ++ sqlite3WindowDelete(db, p->y.pWin); ++ } + } + if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken); + if( !ExprHasProperty(p, EP_Static) ){ +@@ -95121,7 +97241,7 @@ + ** Note that with flags==EXPRDUP_REDUCE, this routines works on full-size + ** (unreduced) Expr objects as they or originally constructed by the parser. + ** During expression analysis, extra information is computed and moved into +-** later parts of teh Expr object and that extra information might get chopped ++** later parts of the Expr object and that extra information might get chopped + ** off if the expression is reduced. Note also that it does not work to + ** make an EXPRDUP_REDUCE copy of a reduced expression. It is only legal + ** to reduce a pristine expression tree from the parser. The implementation +@@ -95133,7 +97253,11 @@ + assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */ + assert( EXPR_FULLSIZE<=0xfff ); + assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 ); +- if( 0==flags || p->op==TK_SELECT_COLUMN ){ ++ if( 0==flags || p->op==TK_SELECT_COLUMN ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ || ExprHasProperty(p, EP_WinFunc) ++#endif ++ ){ + nSize = EXPR_FULLSIZE; + }else{ + assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); +@@ -95158,7 +97282,7 @@ + static int dupedExprNodeSize(Expr *p, int flags){ + int nByte = dupedExprStructSize(p, flags) & 0xfff; + if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ +- nByte += sqlite3Strlen30(p->u.zToken)+1; ++ nByte += sqlite3Strlen30NN(p->u.zToken)+1; + } + return ROUND8(nByte); + } +@@ -95261,7 +97385,7 @@ + } + + /* Fill in pNew->pLeft and pNew->pRight. */ +- if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){ ++ if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly|EP_WinFunc) ){ + zAlloc += dupedExprNodeSize(p, dupFlags); + if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){ + pNew->pLeft = p->pLeft ? +@@ -95269,6 +97393,12 @@ + pNew->pRight = p->pRight ? + exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0; + } ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( ExprHasProperty(p, EP_WinFunc) ){ ++ pNew->y.pWin = sqlite3WindowDup(db, pNew, p->y.pWin); ++ assert( ExprHasProperty(pNew, EP_WinFunc) ); ++ } ++#endif /* SQLITE_OMIT_WINDOWFUNC */ + if( pzBuffer ){ + *pzBuffer = zAlloc; + } +@@ -95373,6 +97503,7 @@ + pItem->sortOrder = pOldItem->sortOrder; + pItem->done = 0; + pItem->bSpanIsTab = pOldItem->bSpanIsTab; ++ pItem->bSorterRef = pOldItem->bSorterRef; + pItem->u = pOldItem->u; + } + return pNew; +@@ -95478,7 +97609,11 @@ + pNew->addrOpenEphm[1] = -1; + pNew->nSelectRow = p->nSelectRow; + pNew->pWith = withDup(db, p->pWith); +- sqlite3SelectSetName(pNew, p->zSelName); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ pNew->pWin = 0; ++ pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn); ++#endif ++ pNew->selId = p->selId; + *pp = pNew; + pp = &pNew->pPrior; + pNext = pNew; +@@ -95650,6 +97785,9 @@ + assert( pItem->zName==0 ); + pItem->zName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n); + if( dequote ) sqlite3Dequote(pItem->zName); ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameTokenMap(pParse, (void*)pItem->zName, pName); ++ } + } + } + +@@ -95830,11 +97968,16 @@ + testcase( pExpr->op==TK_COLUMN ); + testcase( pExpr->op==TK_AGG_FUNCTION ); + testcase( pExpr->op==TK_AGG_COLUMN ); ++ if( ExprHasProperty(pExpr, EP_FixedCol) && pWalker->eCode!=2 ){ ++ return WRC_Continue; ++ } + if( pWalker->eCode==3 && pExpr->iTable==pWalker->u.iCur ){ + return WRC_Continue; + } + /* Fall through */ + case TK_IF_NULL_ROW: ++ case TK_REGISTER: ++ testcase( pExpr->op==TK_REGISTER ); + testcase( pExpr->op==TK_IF_NULL_ROW ); + pWalker->eCode = 0; + return WRC_Abort; +@@ -95852,8 +97995,8 @@ + } + /* Fall through */ + default: +- testcase( pExpr->op==TK_SELECT ); /* sqlite3SelectWalkFail will disallow */ +- testcase( pExpr->op==TK_EXISTS ); /* sqlite3SelectWalkFail will disallow */ ++ testcase( pExpr->op==TK_SELECT ); /* sqlite3SelectWalkFail() disallows */ ++ testcase( pExpr->op==TK_EXISTS ); /* sqlite3SelectWalkFail() disallows */ + return WRC_Continue; + } + } +@@ -95883,10 +98026,17 @@ + } + + /* +-** Walk an expression tree. Return non-zero if the expression is constant +-** that does no originate from the ON or USING clauses of a join. +-** Return 0 if it involves variables or function calls or terms from +-** an ON or USING clause. ++** Walk an expression tree. Return non-zero if ++** ++** (1) the expression is constant, and ++** (2) the expression does originate in the ON or USING clause ++** of a LEFT JOIN, and ++** (3) the expression does not contain any EP_FixedCol TK_COLUMN ++** operands created by the constant propagation optimization. ++** ++** When this routine returns true, it indicates that the expression ++** can be added to the pParse->pConstExpr list and evaluated once when ++** the prepared statement starts up. See sqlite3ExprCodeAtInit(). + */ + SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr *p){ + return exprIsConst(p, 2, 0); +@@ -95916,7 +98066,7 @@ + Expr *p = pGroupBy->a[i].pExpr; + if( sqlite3ExprCompare(0, pExpr, p, -1)<2 ){ + CollSeq *pColl = sqlite3ExprNNCollSeq(pWalker->pParse, p); +- if( sqlite3_stricmp("BINARY", pColl->zName)==0 ){ ++ if( sqlite3IsBinary(pColl) ){ + return WRC_Prune; + } + } +@@ -96058,8 +98208,8 @@ + return 0; + case TK_COLUMN: + return ExprHasProperty(p, EP_CanBeNull) || +- p->pTab==0 || /* Reference to column of index on expression */ +- (p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0); ++ p->y.pTab==0 || /* Reference to column of index on expression */ ++ (p->iColumn>=0 && p->y.pTab->aCol[p->iColumn].notNull==0); + default: + return 1; + } +@@ -96114,6 +98264,14 @@ + if( sqlite3StrICmp(z, "OID")==0 ) return 1; + return 0; + } ++#ifdef SQLITE_ENABLE_NORMALIZE ++SQLITE_PRIVATE int sqlite3IsRowidN(const char *z, int n){ ++ if( sqlite3StrNICmp(z, "_ROWID_", n)==0 ) return 1; ++ if( sqlite3StrNICmp(z, "ROWID", n)==0 ) return 1; ++ if( sqlite3StrNICmp(z, "OID", n)==0 ) return 1; ++ return 0; ++} ++#endif + + /* + ** pX is the RHS of an IN operator. If pX is a SELECT statement +@@ -96338,7 +98496,8 @@ + + sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); + eType = IN_INDEX_ROWID; +- ++ ExplainQueryPlan((pParse, 0, ++ "USING ROWID SEARCH ON TABLE %s FOR IN-OPERATOR",pTab->zName)); + sqlite3VdbeJumpHere(v, iAddr); + }else{ + Index *pIdx; /* Iterator variable */ +@@ -96417,11 +98576,8 @@ + if( colUsed==(MASKBIT(nExpr)-1) ){ + /* If we reach this point, that means the index pIdx is usable */ + int iAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); +-#ifndef SQLITE_OMIT_EXPLAIN +- sqlite3VdbeAddOp4(v, OP_Explain, 0, 0, 0, +- sqlite3MPrintf(db, "USING INDEX %s FOR IN-OPERATOR",pIdx->zName), +- P4_DYNAMIC); +-#endif ++ ExplainQueryPlan((pParse, 0, ++ "USING INDEX %s FOR IN-OPERATOR",pIdx->zName)); + sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb); + sqlite3VdbeSetP4KeyInfo(pParse, pIdx); + VdbeComment((v, "%s", pIdx->zName)); +@@ -96600,7 +98756,6 @@ + int rReg = 0; /* Register storing resulting */ + Vdbe *v = sqlite3GetVdbe(pParse); + if( NEVER(v==0) ) return 0; +- sqlite3ExprCachePush(pParse); + + /* The evaluation of the IN/EXISTS/SELECT must be repeated every time it + ** is encountered if any of the following is true: +@@ -96616,17 +98771,6 @@ + jmpIfDynamic = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); + } + +-#ifndef SQLITE_OMIT_EXPLAIN +- if( pParse->explain==2 ){ +- char *zMsg = sqlite3MPrintf(pParse->db, "EXECUTE %s%s SUBQUERY %d", +- jmpIfDynamic>=0?"":"CORRELATED ", +- pExpr->op==TK_IN?"LIST":"SCALAR", +- pParse->iNextSelectId +- ); +- sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); +- } +-#endif +- + switch( pExpr->op ){ + case TK_IN: { + int addr; /* Address of OP_OpenEphemeral instruction */ +@@ -96664,6 +98808,9 @@ + Select *pSelect = pExpr->x.pSelect; + ExprList *pEList = pSelect->pEList; + ++ ExplainQueryPlan((pParse, 1, "%sLIST SUBQUERY", ++ jmpIfDynamic>=0?"":"CORRELATED " ++ )); + assert( !isRowid ); + /* If the LHS and RHS of the IN operator do not match, that + ** error will have been caught long before we reach this point. */ +@@ -96705,7 +98852,6 @@ + ExprList *pList = pExpr->x.pList; + struct ExprList_item *pItem; + int r1, r2, r3; +- + affinity = sqlite3ExprAffinity(pLeft); + if( !affinity ){ + affinity = SQLITE_AFF_BLOB; +@@ -96745,7 +98891,6 @@ + sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3); + }else{ + sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); +- sqlite3ExprCacheAffinityChange(pParse, r3, 1); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pExpr->iTable, r2, r3, 1); + } + } +@@ -96786,6 +98931,8 @@ + assert( ExprHasProperty(pExpr, EP_xIsSelect) ); + + pSel = pExpr->x.pSelect; ++ ExplainQueryPlan((pParse, 1, "%sSCALAR SUBQUERY", ++ jmpIfDynamic>=0?"":"CORRELATED ")); + nReg = pExpr->op==TK_SELECT ? pSel->pEList->nExpr : 1; + sqlite3SelectDestInit(&dest, 0, pParse->nMem+1); + pParse->nMem += nReg; +@@ -96824,7 +98971,6 @@ + if( jmpIfDynamic>=0 ){ + sqlite3VdbeJumpHere(v, jmpIfDynamic); + } +- sqlite3ExprCachePop(pParse); + + return rReg; + } +@@ -96943,7 +99089,6 @@ + ** aiMap[] array contains a mapping from the original LHS field order to + ** the field order that matches the RHS index. + */ +- sqlite3ExprCachePush(pParse); + rLhsOrig = exprCodeVector(pParse, pLeft, &iDummy); + for(i=0; i<nVector && aiMap[i]==i; i++){} /* Are LHS fields reordered? */ + if( i==nVector ){ +@@ -97102,7 +99247,6 @@ + + sqlite3ExprCodeIN_finished: + if( rLhs!=rLhsOrig ) sqlite3ReleaseTempReg(pParse, rLhs); +- sqlite3ExprCachePop(pParse); + VdbeComment((v, "end IN expr")); + sqlite3ExprCodeIN_oom_error: + sqlite3DbFree(pParse->db, aiMap); +@@ -97170,146 +99314,7 @@ + } + } + +-/* +-** Erase column-cache entry number i +-*/ +-static void cacheEntryClear(Parse *pParse, int i){ +- if( pParse->aColCache[i].tempReg ){ +- if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){ +- pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg; +- } +- } +- pParse->nColCache--; +- if( i<pParse->nColCache ){ +- pParse->aColCache[i] = pParse->aColCache[pParse->nColCache]; +- } +-} + +- +-/* +-** Record in the column cache that a particular column from a +-** particular table is stored in a particular register. +-*/ +-SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){ +- int i; +- int minLru; +- int idxLru; +- struct yColCache *p; +- +- /* Unless an error has occurred, register numbers are always positive. */ +- assert( iReg>0 || pParse->nErr || pParse->db->mallocFailed ); +- assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */ +- +- /* The SQLITE_ColumnCache flag disables the column cache. This is used +- ** for testing only - to verify that SQLite always gets the same answer +- ** with and without the column cache. +- */ +- if( OptimizationDisabled(pParse->db, SQLITE_ColumnCache) ) return; +- +- /* First replace any existing entry. +- ** +- ** Actually, the way the column cache is currently used, we are guaranteed +- ** that the object will never already be in cache. Verify this guarantee. +- */ +-#ifndef NDEBUG +- for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){ +- assert( p->iTable!=iTab || p->iColumn!=iCol ); +- } +-#endif +- +- /* If the cache is already full, delete the least recently used entry */ +- if( pParse->nColCache>=SQLITE_N_COLCACHE ){ +- minLru = 0x7fffffff; +- idxLru = -1; +- for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ +- if( p->lru<minLru ){ +- idxLru = i; +- minLru = p->lru; +- } +- } +- p = &pParse->aColCache[idxLru]; +- }else{ +- p = &pParse->aColCache[pParse->nColCache++]; +- } +- +- /* Add the new entry to the end of the cache */ +- p->iLevel = pParse->iCacheLevel; +- p->iTable = iTab; +- p->iColumn = iCol; +- p->iReg = iReg; +- p->tempReg = 0; +- p->lru = pParse->iCacheCnt++; +-} +- +-/* +-** Indicate that registers between iReg..iReg+nReg-1 are being overwritten. +-** Purge the range of registers from the column cache. +-*/ +-SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){ +- int i = 0; +- while( i<pParse->nColCache ){ +- struct yColCache *p = &pParse->aColCache[i]; +- if( p->iReg >= iReg && p->iReg < iReg+nReg ){ +- cacheEntryClear(pParse, i); +- }else{ +- i++; +- } +- } +-} +- +-/* +-** Remember the current column cache context. Any new entries added +-** added to the column cache after this call are removed when the +-** corresponding pop occurs. +-*/ +-SQLITE_PRIVATE void sqlite3ExprCachePush(Parse *pParse){ +- pParse->iCacheLevel++; +-#ifdef SQLITE_DEBUG +- if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ +- printf("PUSH to %d\n", pParse->iCacheLevel); +- } +-#endif +-} +- +-/* +-** Remove from the column cache any entries that were added since the +-** the previous sqlite3ExprCachePush operation. In other words, restore +-** the cache to the state it was in prior the most recent Push. +-*/ +-SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse){ +- int i = 0; +- assert( pParse->iCacheLevel>=1 ); +- pParse->iCacheLevel--; +-#ifdef SQLITE_DEBUG +- if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ +- printf("POP to %d\n", pParse->iCacheLevel); +- } +-#endif +- while( i<pParse->nColCache ){ +- if( pParse->aColCache[i].iLevel>pParse->iCacheLevel ){ +- cacheEntryClear(pParse, i); +- }else{ +- i++; +- } +- } +-} +- +-/* +-** When a cached column is reused, make sure that its register is +-** no longer available as a temp register. ticket #3879: that same +-** register might be in the cache in multiple places, so be sure to +-** get them all. +-*/ +-static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){ +- int i; +- struct yColCache *p; +- for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){ +- if( p->iReg==iReg ){ +- p->tempReg = 0; +- } +- } +-} +- + /* Generate code that will load into register regOut a value that is + ** appropriate for the iIdxCol-th column of index pIdx. + */ +@@ -97364,13 +99369,8 @@ + + /* + ** Generate code that will extract the iColumn-th column from +-** table pTab and store the column value in a register. ++** table pTab and store the column value in register iReg. + ** +-** An effort is made to store the column value in register iReg. This +-** is not garanteeed for GetColumn() - the result can be stored in +-** any register. But the result is guaranteed to land in register iReg +-** for GetColumnToReg(). +-** + ** There must be an open cursor to pTab in iTable when this routine + ** is called. If iColumn<0 then code is generated that extracts the rowid. + */ +@@ -97383,97 +99383,24 @@ + u8 p5 /* P5 value for OP_Column + FLAGS */ + ){ + Vdbe *v = pParse->pVdbe; +- int i; +- struct yColCache *p; +- +- for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){ +- if( p->iTable==iTable && p->iColumn==iColumn ){ +- p->lru = pParse->iCacheCnt++; +- sqlite3ExprCachePinRegister(pParse, p->iReg); +- return p->iReg; +- } +- } + assert( v!=0 ); + sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg); + if( p5 ){ + sqlite3VdbeChangeP5(v, p5); +- }else{ +- sqlite3ExprCacheStore(pParse, iTable, iColumn, iReg); + } + return iReg; + } +-SQLITE_PRIVATE void sqlite3ExprCodeGetColumnToReg( +- Parse *pParse, /* Parsing and code generating context */ +- Table *pTab, /* Description of the table we are reading from */ +- int iColumn, /* Index of the table column */ +- int iTable, /* The cursor pointing to the table */ +- int iReg /* Store results here */ +-){ +- int r1 = sqlite3ExprCodeGetColumn(pParse, pTab, iColumn, iTable, iReg, 0); +- if( r1!=iReg ) sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, r1, iReg); +-} + +- + /* +-** Clear all column cache entries. +-*/ +-SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){ +- int i; +- +-#ifdef SQLITE_DEBUG +- if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ +- printf("CLEAR\n"); +- } +-#endif +- for(i=0; i<pParse->nColCache; i++){ +- if( pParse->aColCache[i].tempReg +- && pParse->nTempReg<ArraySize(pParse->aTempReg) +- ){ +- pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg; +- } +- } +- pParse->nColCache = 0; +-} +- +-/* +-** Record the fact that an affinity change has occurred on iCount +-** registers starting with iStart. +-*/ +-SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){ +- sqlite3ExprCacheRemove(pParse, iStart, iCount); +-} +- +-/* + ** Generate code to move content from registers iFrom...iFrom+nReg-1 +-** over to iTo..iTo+nReg-1. Keep the column cache up-to-date. ++** over to iTo..iTo+nReg-1. + */ + SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){ + assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo ); + sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg); +- sqlite3ExprCacheRemove(pParse, iFrom, nReg); + } + +-#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) + /* +-** Return true if any register in the range iFrom..iTo (inclusive) +-** is used as part of the column cache. +-** +-** This routine is used within assert() and testcase() macros only +-** and does not appear in a normal build. +-*/ +-static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){ +- int i; +- struct yColCache *p; +- for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){ +- int r = p->iReg; +- if( r>=iFrom && r<=iTo ) return 1; /*NO_TEST*/ +- } +- return 0; +-} +-#endif /* SQLITE_DEBUG || SQLITE_COVERAGE_TEST */ +- +- +-/* + ** Convert a scalar expression node to a TK_REGISTER referencing + ** register iReg. The caller must ensure that iReg already contains + ** the correct value for the expression. +@@ -97548,6 +99475,7 @@ + return 0; + } + ++expr_code_doover: + if( pExpr==0 ){ + op = TK_NULL; + }else{ +@@ -97569,6 +99497,28 @@ + } + case TK_COLUMN: { + int iTab = pExpr->iTable; ++ if( ExprHasProperty(pExpr, EP_FixedCol) ){ ++ /* This COLUMN expression is really a constant due to WHERE clause ++ ** constraints, and that constant is coded by the pExpr->pLeft ++ ** expresssion. However, make sure the constant has the correct ++ ** datatype by applying the Affinity of the table column to the ++ ** constant. ++ */ ++ int iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target); ++ int aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn); ++ if( aff!=SQLITE_AFF_BLOB ){ ++ static const char zAff[] = "B\000C\000D\000E"; ++ assert( SQLITE_AFF_BLOB=='A' ); ++ assert( SQLITE_AFF_TEXT=='B' ); ++ if( iReg!=target ){ ++ sqlite3VdbeAddOp2(v, OP_SCopy, iReg, target); ++ iReg = target; ++ } ++ sqlite3VdbeAddOp4(v, OP_Affinity, iReg, 1, 0, ++ &zAff[(aff-'B')*2], P4_STATIC); ++ } ++ return iReg; ++ } + if( iTab<0 ){ + if( pParse->iSelfTab<0 ){ + /* Generating CHECK constraints or inserting into partial index */ +@@ -97579,7 +99529,7 @@ + iTab = pParse->iSelfTab - 1; + } + } +- return sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, ++ return sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab, + pExpr->iColumn, iTab, target, + pExpr->op2); + } +@@ -97649,8 +99599,6 @@ + } + sqlite3VdbeAddOp2(v, OP_Cast, target, + sqlite3AffinityType(pExpr->u.zToken, 0)); +- testcase( usedAsColumnCache(pParse, inReg, inReg) ); +- sqlite3ExprCacheAffinityChange(pParse, inReg, 1); + return inReg; + } + #endif /* SQLITE_OMIT_CAST */ +@@ -97794,6 +99742,12 @@ + u8 enc = ENC(db); /* The text encoding used by this database */ + CollSeq *pColl = 0; /* A collating sequence */ + ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( ExprHasProperty(pExpr, EP_WinFunc) ){ ++ return pExpr->y.pWin->regResult; ++ } ++#endif ++ + if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){ + /* SQL functions can be expensive. So try to move constant functions + ** out of the inner loop, even if that means an extra OP_Copy. */ +@@ -97830,10 +99784,7 @@ + for(i=1; i<nFarg; i++){ + sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce); + VdbeCoverage(v); +- sqlite3ExprCacheRemove(pParse, target, 1); +- sqlite3ExprCachePush(pParse); + sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target); +- sqlite3ExprCachePop(pParse); + } + sqlite3VdbeResolveLabel(v, endCoalesce); + break; +@@ -97899,10 +99850,8 @@ + } + } + +- sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */ + sqlite3ExprCodeExprList(pParse, pFarg, r1, 0, + SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR); +- sqlite3ExprCachePop(pParse); /* Ticket 2ea2425d34be */ + }else{ + r1 = 0; + } +@@ -97919,7 +99868,7 @@ + ** "glob(B,A). We want to use the A in "A glob B" to test + ** for function overloading. But we use the B term in "glob(B,A)". + */ +- if( nFarg>=2 && (pExpr->flags & EP_InfixFunc) ){ ++ if( nFarg>=2 && ExprHasProperty(pExpr, EP_InfixFunc) ){ + pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[1].pExpr); + }else if( nFarg>0 ){ + pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr); +@@ -98008,7 +99957,8 @@ + case TK_SPAN: + case TK_COLLATE: + case TK_UPLUS: { +- return sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); ++ pExpr = pExpr->pLeft; ++ goto expr_code_doover; /* 2018-04-28: Prevent deep recursion. OSSFuzz. */ + } + + case TK_TRIGGER: { +@@ -98037,7 +99987,7 @@ + ** p1==1 -> old.a p1==4 -> new.a + ** p1==2 -> old.b p1==5 -> new.b + */ +- Table *pTab = pExpr->pTab; ++ Table *pTab = pExpr->y.pTab; + int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn; + + assert( pExpr->iTable==0 || pExpr->iTable==1 ); +@@ -98046,10 +99996,9 @@ + assert( p1>=0 && p1<(pTab->nCol*2+2) ); + + sqlite3VdbeAddOp2(v, OP_Param, p1, target); +- VdbeComment((v, "%s.%s -> $%d", ++ VdbeComment((v, "r[%d]=%s.%s", target, + (pExpr->iTable ? "new" : "old"), +- (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName), +- target ++ (pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[pExpr->iColumn].zName) + )); + + #ifndef SQLITE_OMIT_FLOATING_POINT +@@ -98075,9 +100024,7 @@ + case TK_IF_NULL_ROW: { + int addrINR; + addrINR = sqlite3VdbeAddOp1(v, OP_IfNullRow, pExpr->iTable); +- sqlite3ExprCachePush(pParse); + inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); +- sqlite3ExprCachePop(pParse); + sqlite3VdbeJumpHere(v, addrINR); + sqlite3VdbeChangeP3(v, addrINR, inReg); + break; +@@ -98114,7 +100061,6 @@ + Expr opCompare; /* The X==Ei expression */ + Expr *pX; /* The X expression */ + Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */ +- VVA_ONLY( int iCacheLevel = pParse->iCacheLevel; ) + + assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList ); + assert(pExpr->x.pList->nExpr > 0); +@@ -98138,7 +100084,6 @@ + regFree1 = 0; + } + for(i=0; i<nExpr-1; i=i+2){ +- sqlite3ExprCachePush(pParse); + if( pX ){ + assert( pTest!=0 ); + opCompare.pRight = aListelem[i].pExpr; +@@ -98151,18 +100096,13 @@ + testcase( aListelem[i+1].pExpr->op==TK_COLUMN ); + sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target); + sqlite3VdbeGoto(v, endLabel); +- sqlite3ExprCachePop(pParse); + sqlite3VdbeResolveLabel(v, nextCase); + } + if( (nExpr&1)!=0 ){ +- sqlite3ExprCachePush(pParse); + sqlite3ExprCode(pParse, pEList->a[nExpr-1].pExpr, target); +- sqlite3ExprCachePop(pParse); + }else{ + sqlite3VdbeAddOp2(v, OP_Null, 0, target); + } +- assert( pParse->db->mallocFailed || pParse->nErr>0 +- || pParse->iCacheLevel==iCacheLevel ); + sqlite3VdbeResolveLabel(v, endLabel); + break; + } +@@ -98312,7 +100252,7 @@ + ** might choose to code the expression at initialization time. + */ + SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){ +- if( pParse->okConstFactor && sqlite3ExprIsConstant(pExpr) ){ ++ if( pParse->okConstFactor && sqlite3ExprIsConstantNotJoin(pExpr) ){ + sqlite3ExprCodeAtInit(pParse, pExpr, target); + }else{ + sqlite3ExprCode(pParse, pExpr, target); +@@ -98381,6 +100321,12 @@ + if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR; + for(pItem=pList->a, i=0; i<n; i++, pItem++){ + Expr *pExpr = pItem->pExpr; ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ if( pItem->bSorterRef ){ ++ i--; ++ n--; ++ }else ++#endif + if( (flags & SQLITE_ECEL_REF)!=0 && (j = pItem->u.x.iOrderByCol)>0 ){ + if( flags & SQLITE_ECEL_OMITREF ){ + i--; +@@ -98388,7 +100334,9 @@ + }else{ + sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i); + } +- }else if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){ ++ }else if( (flags & SQLITE_ECEL_FACTOR)!=0 ++ && sqlite3ExprIsConstantNotJoin(pExpr) ++ ){ + sqlite3ExprCodeAtInit(pParse, pExpr, target+i); + }else{ + int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i); +@@ -98514,18 +100462,14 @@ + int d2 = sqlite3VdbeMakeLabel(v); + testcase( jumpIfNull==0 ); + sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL); +- sqlite3ExprCachePush(pParse); + sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); + sqlite3VdbeResolveLabel(v, d2); +- sqlite3ExprCachePop(pParse); + break; + } + case TK_OR: { + testcase( jumpIfNull==0 ); + sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); +- sqlite3ExprCachePush(pParse); + sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); +- sqlite3ExprCachePop(pParse); + break; + } + case TK_NOT: { +@@ -98684,9 +100628,7 @@ + case TK_AND: { + testcase( jumpIfNull==0 ); + sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); +- sqlite3ExprCachePush(pParse); + sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); +- sqlite3ExprCachePop(pParse); + break; + } + case TK_OR: { +@@ -98693,10 +100635,8 @@ + int d2 = sqlite3VdbeMakeLabel(v); + testcase( jumpIfNull==0 ); + sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL); +- sqlite3ExprCachePush(pParse); + sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); + sqlite3VdbeResolveLabel(v, d2); +- sqlite3ExprCachePop(pParse); + break; + } + case TK_NOT: { +@@ -98909,17 +100849,35 @@ + if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){ + if( pA->op==TK_FUNCTION ){ + if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2; ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ /* Justification for the assert(): ++ ** window functions have p->op==TK_FUNCTION but aggregate functions ++ ** have p->op==TK_AGG_FUNCTION. So any comparison between an aggregate ++ ** function and a window function should have failed before reaching ++ ** this point. And, it is not possible to have a window function and ++ ** a scalar function with the same name and number of arguments. So ++ ** if we reach this point, either A and B both window functions or ++ ** neither are a window functions. */ ++ assert( ExprHasProperty(pA,EP_WinFunc)==ExprHasProperty(pB,EP_WinFunc) ); ++ if( ExprHasProperty(pA,EP_WinFunc) ){ ++ if( sqlite3WindowCompare(pParse,pA->y.pWin,pB->y.pWin)!=0 ) return 2; ++ } ++#endif ++ }else if( pA->op==TK_COLLATE ){ ++ if( sqlite3_stricmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2; + }else if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ +- return pA->op==TK_COLLATE ? 1 : 2; ++ return 2; + } + } + if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; + if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){ + if( combinedFlags & EP_xIsSelect ) return 2; +- if( sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2; ++ if( (combinedFlags & EP_FixedCol)==0 ++ && sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2; + if( sqlite3ExprCompare(pParse, pA->pRight, pB->pRight, iTab) ) return 2; + if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2; +- if( ALWAYS((combinedFlags & EP_Reduced)==0) && pA->op!=TK_STRING ){ ++ assert( (combinedFlags & EP_Reduced)==0 ); ++ if( pA->op!=TK_STRING && pA->op!=TK_TRUEFALSE ){ + if( pA->iColumn!=pB->iColumn ) return 2; + if( pA->iTable!=pB->iTable + && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2; +@@ -99014,18 +100972,15 @@ + /* + ** This is the Expr node callback for sqlite3ExprImpliesNotNullRow(). + ** If the expression node requires that the table at pWalker->iCur +-** have a non-NULL column, then set pWalker->eCode to 1 and abort. ++** have one or more non-NULL column, then set pWalker->eCode to 1 and abort. ++** ++** This routine controls an optimization. False positives (setting ++** pWalker->eCode to 1 when it should not be) are deadly, but false-negatives ++** (never setting pWalker->eCode) is a harmless missed optimization. + */ + static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ +- /* This routine is only called for WHERE clause expressions and so it +- ** cannot have any TK_AGG_COLUMN entries because those are only found +- ** in HAVING clauses. We can get a TK_AGG_FUNCTION in a WHERE clause, +- ** but that is an illegal construct and the query will be rejected at +- ** a later stage of processing, so the TK_AGG_FUNCTION case does not +- ** need to be considered here. */ +- assert( pExpr->op!=TK_AGG_COLUMN ); ++ testcase( pExpr->op==TK_AGG_COLUMN ); + testcase( pExpr->op==TK_AGG_FUNCTION ); +- + if( ExprHasProperty(pExpr, EP_FromJoin) ) return WRC_Prune; + switch( pExpr->op ){ + case TK_ISNOT: +@@ -99067,8 +101022,8 @@ + testcase( pExpr->op==TK_LE ); + testcase( pExpr->op==TK_GT ); + testcase( pExpr->op==TK_GE ); +- if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->pTab)) +- || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->pTab)) ++ if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->y.pTab)) ++ || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->y.pTab)) + ){ + return WRC_Prune; + } +@@ -99265,8 +101220,9 @@ + NameContext *pNC = pWalker->u.pNC; + Parse *pParse = pNC->pParse; + SrcList *pSrcList = pNC->pSrcList; +- AggInfo *pAggInfo = pNC->pAggInfo; ++ AggInfo *pAggInfo = pNC->uNC.pAggInfo; + ++ assert( pNC->ncFlags & NC_UAggInfo ); + switch( pExpr->op ){ + case TK_AGG_COLUMN: + case TK_COLUMN: { +@@ -99298,7 +101254,7 @@ + && (k = addAggInfoColumn(pParse->db, pAggInfo))>=0 + ){ + pCol = &pAggInfo->aCol[k]; +- pCol->pTab = pExpr->pTab; ++ pCol->pTab = pExpr->y.pTab; + pCol->iTable = pExpr->iTable; + pCol->iColumn = pExpr->iColumn; + pCol->iMem = ++pParse->nMem; +@@ -99444,21 +101400,9 @@ + /* + ** Deallocate a register, making available for reuse for some other + ** purpose. +-** +-** If a register is currently being used by the column cache, then +-** the deallocation is deferred until the column cache line that uses +-** the register becomes stale. + */ + SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ + if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){ +- int i; +- struct yColCache *p; +- for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){ +- if( p->iReg==iReg ){ +- p->tempReg = 1; +- return; +- } +- } + pParse->aTempReg[pParse->nTempReg++] = iReg; + } + } +@@ -99472,7 +101416,6 @@ + i = pParse->iRangeReg; + n = pParse->nRangeReg; + if( nReg<=n ){ +- assert( !usedAsColumnCache(pParse, i, i+n-1) ); + pParse->iRangeReg += nReg; + pParse->nRangeReg -= nReg; + }else{ +@@ -99486,7 +101429,6 @@ + sqlite3ReleaseTempReg(pParse, iReg); + return; + } +- sqlite3ExprCacheRemove(pParse, iReg, nReg); + if( nReg>pParse->nRangeReg ){ + pParse->nRangeReg = nReg; + pParse->iRangeReg = iReg; +@@ -99548,369 +101490,66 @@ + */ + #ifndef SQLITE_OMIT_ALTERTABLE + +- + /* +-** This function is used by SQL generated to implement the +-** ALTER TABLE command. The first argument is the text of a CREATE TABLE or +-** CREATE INDEX command. The second is a table name. The table name in +-** the CREATE TABLE or CREATE INDEX statement is replaced with the third +-** argument and the result returned. Examples: ++** Parameter zName is the name of a table that is about to be altered ++** (either with ALTER TABLE ... RENAME TO or ALTER TABLE ... ADD COLUMN). ++** If the table is a system table, this function leaves an error message ++** in pParse->zErr (system tables may not be altered) and returns non-zero. + ** +-** sqlite_rename_table('CREATE TABLE abc(a, b, c)', 'def') +-** -> 'CREATE TABLE def(a, b, c)' +-** +-** sqlite_rename_table('CREATE INDEX i ON abc(a)', 'def') +-** -> 'CREATE INDEX i ON def(a, b, c)' ++** Or, if zName is not a system table, zero is returned. + */ +-static void renameTableFunc( +- sqlite3_context *context, +- int NotUsed, +- sqlite3_value **argv +-){ +- unsigned char const *zSql = sqlite3_value_text(argv[0]); +- unsigned char const *zTableName = sqlite3_value_text(argv[1]); +- +- int token; +- Token tname; +- unsigned char const *zCsr = zSql; +- int len = 0; +- char *zRet; +- +- sqlite3 *db = sqlite3_context_db_handle(context); +- +- UNUSED_PARAMETER(NotUsed); +- +- /* The principle used to locate the table name in the CREATE TABLE +- ** statement is that the table name is the first non-space token that +- ** is immediately followed by a TK_LP or TK_USING token. +- */ +- if( zSql ){ +- do { +- if( !*zCsr ){ +- /* Ran out of input before finding an opening bracket. Return NULL. */ +- return; +- } +- +- /* Store the token that zCsr points to in tname. */ +- tname.z = (char*)zCsr; +- tname.n = len; +- +- /* Advance zCsr to the next token. Store that token type in 'token', +- ** and its length in 'len' (to be used next iteration of this loop). +- */ +- do { +- zCsr += len; +- len = sqlite3GetToken(zCsr, &token); +- } while( token==TK_SPACE ); +- assert( len>0 ); +- } while( token!=TK_LP && token!=TK_USING ); +- +- zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql), +- zSql, zTableName, tname.z+tname.n); +- sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); ++static int isSystemTable(Parse *pParse, const char *zName){ ++ if( 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ ++ sqlite3ErrorMsg(pParse, "table %s may not be altered", zName); ++ return 1; + } ++ return 0; + } + + /* +-** This C function implements an SQL user function that is used by SQL code +-** generated by the ALTER TABLE ... RENAME command to modify the definition +-** of any foreign key constraints that use the table being renamed as the +-** parent table. It is passed three arguments: +-** +-** 1) The complete text of the CREATE TABLE statement being modified, +-** 2) The old name of the table being renamed, and +-** 3) The new name of the table being renamed. +-** +-** It returns the new CREATE TABLE statement. For example: +-** +-** sqlite_rename_parent('CREATE TABLE t1(a REFERENCES t2)', 't2', 't3') +-** -> 'CREATE TABLE t1(a REFERENCES t3)' ++** Generate code to verify that the schemas of database zDb and, if ++** bTemp is not true, database "temp", can still be parsed. This is ++** called at the end of the generation of an ALTER TABLE ... RENAME ... ++** statement to ensure that the operation has not rendered any schema ++** objects unusable. + */ +-#ifndef SQLITE_OMIT_FOREIGN_KEY +-static void renameParentFunc( +- sqlite3_context *context, +- int NotUsed, +- sqlite3_value **argv +-){ +- sqlite3 *db = sqlite3_context_db_handle(context); +- char *zOutput = 0; +- char *zResult; +- unsigned char const *zInput = sqlite3_value_text(argv[0]); +- unsigned char const *zOld = sqlite3_value_text(argv[1]); +- unsigned char const *zNew = sqlite3_value_text(argv[2]); ++static void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){ ++ sqlite3NestedParse(pParse, ++ "SELECT 1 " ++ "FROM \"%w\".%s " ++ "WHERE name NOT LIKE 'sqlite_%%'" ++ " AND sql NOT LIKE 'create virtual%%'" ++ " AND sqlite_rename_test(%Q, sql, type, name, %d)=NULL ", ++ zDb, MASTER_NAME, ++ zDb, bTemp ++ ); + +- unsigned const char *z; /* Pointer to token */ +- int n; /* Length of token z */ +- int token; /* Type of token */ +- +- UNUSED_PARAMETER(NotUsed); +- if( zInput==0 || zOld==0 ) return; +- for(z=zInput; *z; z=z+n){ +- n = sqlite3GetToken(z, &token); +- if( token==TK_REFERENCES ){ +- char *zParent; +- do { +- z += n; +- n = sqlite3GetToken(z, &token); +- }while( token==TK_SPACE ); +- +- if( token==TK_ILLEGAL ) break; +- zParent = sqlite3DbStrNDup(db, (const char *)z, n); +- if( zParent==0 ) break; +- sqlite3Dequote(zParent); +- if( 0==sqlite3StrICmp((const char *)zOld, zParent) ){ +- char *zOut = sqlite3MPrintf(db, "%s%.*s\"%w\"", +- (zOutput?zOutput:""), (int)(z-zInput), zInput, (const char *)zNew +- ); +- sqlite3DbFree(db, zOutput); +- zOutput = zOut; +- zInput = &z[n]; +- } +- sqlite3DbFree(db, zParent); +- } ++ if( bTemp==0 ){ ++ sqlite3NestedParse(pParse, ++ "SELECT 1 " ++ "FROM temp.%s " ++ "WHERE name NOT LIKE 'sqlite_%%'" ++ " AND sql NOT LIKE 'create virtual%%'" ++ " AND sqlite_rename_test(%Q, sql, type, name, 1)=NULL ", ++ MASTER_NAME, zDb ++ ); + } +- +- zResult = sqlite3MPrintf(db, "%s%s", (zOutput?zOutput:""), zInput), +- sqlite3_result_text(context, zResult, -1, SQLITE_DYNAMIC); +- sqlite3DbFree(db, zOutput); + } +-#endif + +-#ifndef SQLITE_OMIT_TRIGGER +-/* This function is used by SQL generated to implement the +-** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER +-** statement. The second is a table name. The table name in the CREATE +-** TRIGGER statement is replaced with the third argument and the result +-** returned. This is analagous to renameTableFunc() above, except for CREATE +-** TRIGGER, not CREATE INDEX and CREATE TABLE. +-*/ +-static void renameTriggerFunc( +- sqlite3_context *context, +- int NotUsed, +- sqlite3_value **argv +-){ +- unsigned char const *zSql = sqlite3_value_text(argv[0]); +- unsigned char const *zTableName = sqlite3_value_text(argv[1]); +- +- int token; +- Token tname; +- int dist = 3; +- unsigned char const *zCsr = zSql; +- int len = 0; +- char *zRet; +- sqlite3 *db = sqlite3_context_db_handle(context); +- +- UNUSED_PARAMETER(NotUsed); +- +- /* The principle used to locate the table name in the CREATE TRIGGER +- ** statement is that the table name is the first token that is immediately +- ** preceded by either TK_ON or TK_DOT and immediately followed by one +- ** of TK_WHEN, TK_BEGIN or TK_FOR. +- */ +- if( zSql ){ +- do { +- +- if( !*zCsr ){ +- /* Ran out of input before finding the table name. Return NULL. */ +- return; +- } +- +- /* Store the token that zCsr points to in tname. */ +- tname.z = (char*)zCsr; +- tname.n = len; +- +- /* Advance zCsr to the next token. Store that token type in 'token', +- ** and its length in 'len' (to be used next iteration of this loop). +- */ +- do { +- zCsr += len; +- len = sqlite3GetToken(zCsr, &token); +- }while( token==TK_SPACE ); +- assert( len>0 ); +- +- /* Variable 'dist' stores the number of tokens read since the most +- ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN +- ** token is read and 'dist' equals 2, the condition stated above +- ** to be met. +- ** +- ** Note that ON cannot be a database, table or column name, so +- ** there is no need to worry about syntax like +- ** "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc. +- */ +- dist++; +- if( token==TK_DOT || token==TK_ON ){ +- dist = 0; +- } +- } while( dist!=2 || (token!=TK_WHEN && token!=TK_FOR && token!=TK_BEGIN) ); +- +- /* Variable tname now contains the token that is the old table-name +- ** in the CREATE TRIGGER statement. +- */ +- zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql), +- zSql, zTableName, tname.z+tname.n); +- sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); +- } +-} +-#endif /* !SQLITE_OMIT_TRIGGER */ +- + /* +-** Register built-in functions used to help implement ALTER TABLE ++** Generate code to reload the schema for database iDb. And, if iDb!=1, for ++** the temp database as well. + */ +-SQLITE_PRIVATE void sqlite3AlterFunctions(void){ +- static FuncDef aAlterTableFuncs[] = { +- FUNCTION(sqlite_rename_table, 2, 0, 0, renameTableFunc), +-#ifndef SQLITE_OMIT_TRIGGER +- FUNCTION(sqlite_rename_trigger, 2, 0, 0, renameTriggerFunc), +-#endif +-#ifndef SQLITE_OMIT_FOREIGN_KEY +- FUNCTION(sqlite_rename_parent, 3, 0, 0, renameParentFunc), +-#endif +- }; +- sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs)); +-} +- +-/* +-** This function is used to create the text of expressions of the form: +-** +-** name=<constant1> OR name=<constant2> OR ... +-** +-** If argument zWhere is NULL, then a pointer string containing the text +-** "name=<constant>" is returned, where <constant> is the quoted version +-** of the string passed as argument zConstant. The returned buffer is +-** allocated using sqlite3DbMalloc(). It is the responsibility of the +-** caller to ensure that it is eventually freed. +-** +-** If argument zWhere is not NULL, then the string returned is +-** "<where> OR name=<constant>", where <where> is the contents of zWhere. +-** In this case zWhere is passed to sqlite3DbFree() before returning. +-** +-*/ +-static char *whereOrName(sqlite3 *db, char *zWhere, char *zConstant){ +- char *zNew; +- if( !zWhere ){ +- zNew = sqlite3MPrintf(db, "name=%Q", zConstant); +- }else{ +- zNew = sqlite3MPrintf(db, "%s OR name=%Q", zWhere, zConstant); +- sqlite3DbFree(db, zWhere); ++static void renameReloadSchema(Parse *pParse, int iDb){ ++ Vdbe *v = pParse->pVdbe; ++ if( v ){ ++ sqlite3ChangeCookie(pParse, iDb); ++ sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iDb, 0); ++ if( iDb!=1 ) sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, 1, 0); + } +- return zNew; + } + +-#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) + /* +-** Generate the text of a WHERE expression which can be used to select all +-** tables that have foreign key constraints that refer to table pTab (i.e. +-** constraints for which pTab is the parent table) from the sqlite_master +-** table. +-*/ +-static char *whereForeignKeys(Parse *pParse, Table *pTab){ +- FKey *p; +- char *zWhere = 0; +- for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ +- zWhere = whereOrName(pParse->db, zWhere, p->pFrom->zName); +- } +- return zWhere; +-} +-#endif +- +-/* +-** Generate the text of a WHERE expression which can be used to select all +-** temporary triggers on table pTab from the sqlite_temp_master table. If +-** table pTab has no temporary triggers, or is itself stored in the +-** temporary database, NULL is returned. +-*/ +-static char *whereTempTriggers(Parse *pParse, Table *pTab){ +- Trigger *pTrig; +- char *zWhere = 0; +- const Schema *pTempSchema = pParse->db->aDb[1].pSchema; /* Temp db schema */ +- +- /* If the table is not located in the temp-db (in which case NULL is +- ** returned, loop through the tables list of triggers. For each trigger +- ** that is not part of the temp-db schema, add a clause to the WHERE +- ** expression being built up in zWhere. +- */ +- if( pTab->pSchema!=pTempSchema ){ +- sqlite3 *db = pParse->db; +- for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){ +- if( pTrig->pSchema==pTempSchema ){ +- zWhere = whereOrName(db, zWhere, pTrig->zName); +- } +- } +- } +- if( zWhere ){ +- char *zNew = sqlite3MPrintf(pParse->db, "type='trigger' AND (%s)", zWhere); +- sqlite3DbFree(pParse->db, zWhere); +- zWhere = zNew; +- } +- return zWhere; +-} +- +-/* +-** Generate code to drop and reload the internal representation of table +-** pTab from the database, including triggers and temporary triggers. +-** Argument zName is the name of the table in the database schema at +-** the time the generated code is executed. This can be different from +-** pTab->zName if this function is being called to code part of an +-** "ALTER TABLE RENAME TO" statement. +-*/ +-static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){ +- Vdbe *v; +- char *zWhere; +- int iDb; /* Index of database containing pTab */ +-#ifndef SQLITE_OMIT_TRIGGER +- Trigger *pTrig; +-#endif +- +- v = sqlite3GetVdbe(pParse); +- if( NEVER(v==0) ) return; +- assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); +- iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); +- assert( iDb>=0 ); +- +-#ifndef SQLITE_OMIT_TRIGGER +- /* Drop any table triggers from the internal schema. */ +- for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){ +- int iTrigDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); +- assert( iTrigDb==iDb || iTrigDb==1 ); +- sqlite3VdbeAddOp4(v, OP_DropTrigger, iTrigDb, 0, 0, pTrig->zName, 0); +- } +-#endif +- +- /* Drop the table and index from the internal schema. */ +- sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0); +- +- /* Reload the table, index and permanent trigger schemas. */ +- zWhere = sqlite3MPrintf(pParse->db, "tbl_name=%Q", zName); +- if( !zWhere ) return; +- sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere); +- +-#ifndef SQLITE_OMIT_TRIGGER +- /* Now, if the table is not stored in the temp database, reload any temp +- ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined. +- */ +- if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){ +- sqlite3VdbeAddParseSchemaOp(v, 1, zWhere); +- } +-#endif +-} +- +-/* +-** Parameter zName is the name of a table that is about to be altered +-** (either with ALTER TABLE ... RENAME TO or ALTER TABLE ... ADD COLUMN). +-** If the table is a system table, this function leaves an error message +-** in pParse->zErr (system tables may not be altered) and returns non-zero. +-** +-** Or, if zName is not a system table, zero is returned. +-*/ +-static int isSystemTable(Parse *pParse, const char *zName){ +- if( 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ +- sqlite3ErrorMsg(pParse, "table %s may not be altered", zName); +- return 1; +- } +- return 0; +-} +- +-/* + ** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy" + ** command. + */ +@@ -99927,9 +101566,6 @@ + int nTabName; /* Number of UTF-8 characters in zTabName */ + const char *zTabName; /* Original name of the table */ + Vdbe *v; +-#ifndef SQLITE_OMIT_TRIGGER +- char *zWhere = 0; /* Where clause to locate temp triggers */ +-#endif + VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */ + u32 savedDbFlags; /* Saved value of db->mDbFlags */ + +@@ -100002,52 +101638,25 @@ + if( v==0 ){ + goto exit_rename_table; + } +- sqlite3BeginWriteOperation(pParse, pVTab!=0, iDb); +- sqlite3ChangeCookie(pParse, iDb); + +- /* If this is a virtual table, invoke the xRename() function if +- ** one is defined. The xRename() callback will modify the names +- ** of any resources used by the v-table implementation (including other +- ** SQLite tables) that are identified by the name of the virtual table. +- */ +-#ifndef SQLITE_OMIT_VIRTUALTABLE +- if( pVTab ){ +- int i = ++pParse->nMem; +- sqlite3VdbeLoadString(v, i, zName); +- sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB); +- sqlite3MayAbort(pParse); +- } +-#endif +- + /* figure out how many UTF-8 characters are in zName */ + zTabName = pTab->zName; + nTabName = sqlite3Utf8CharLen(zTabName, -1); + +-#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) +- if( db->flags&SQLITE_ForeignKeys ){ +- /* If foreign-key support is enabled, rewrite the CREATE TABLE +- ** statements corresponding to all child tables of foreign key constraints +- ** for which the renamed table is the parent table. */ +- if( (zWhere=whereForeignKeys(pParse, pTab))!=0 ){ +- sqlite3NestedParse(pParse, +- "UPDATE \"%w\".%s SET " +- "sql = sqlite_rename_parent(sql, %Q, %Q) " +- "WHERE %s;", zDb, MASTER_NAME, zTabName, zName, zWhere); +- sqlite3DbFree(db, zWhere); +- } +- } +-#endif ++ /* Rewrite all CREATE TABLE, INDEX, TRIGGER or VIEW statements in ++ ** the schema to use the new table name. */ ++ sqlite3NestedParse(pParse, ++ "UPDATE \"%w\".%s SET " ++ "sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, %d) " ++ "WHERE (type!='index' OR tbl_name=%Q COLLATE nocase)" ++ "AND name NOT LIKE 'sqlite_%%'" ++ , zDb, MASTER_NAME, zDb, zTabName, zName, (iDb==1), zTabName ++ ); + +- /* Modify the sqlite_master table to use the new table name. */ ++ /* Update the tbl_name and name columns of the sqlite_master table ++ ** as required. */ + sqlite3NestedParse(pParse, + "UPDATE %Q.%s SET " +-#ifdef SQLITE_OMIT_TRIGGER +- "sql = sqlite_rename_table(sql, %Q), " +-#else +- "sql = CASE " +- "WHEN type = 'trigger' THEN sqlite_rename_trigger(sql, %Q)" +- "ELSE sqlite_rename_table(sql, %Q) END, " +-#endif + "tbl_name = %Q, " + "name = CASE " + "WHEN type='table' THEN %Q " +@@ -100056,11 +101665,9 @@ + "ELSE name END " + "WHERE tbl_name=%Q COLLATE nocase AND " + "(type='table' OR type='index' OR type='trigger');", +- zDb, MASTER_NAME, zName, zName, zName, +-#ifndef SQLITE_OMIT_TRIGGER +- zName, +-#endif +- zName, nTabName, zTabName ++ zDb, MASTER_NAME, ++ zName, zName, zName, ++ nTabName, zTabName + ); + + #ifndef SQLITE_OMIT_AUTOINCREMENT +@@ -100074,35 +101681,37 @@ + } + #endif + +-#ifndef SQLITE_OMIT_TRIGGER +- /* If there are TEMP triggers on this table, modify the sqlite_temp_master +- ** table. Don't do this if the table being ALTERed is itself located in +- ** the temp database. +- */ +- if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){ ++ /* If the table being renamed is not itself part of the temp database, ++ ** edit view and trigger definitions within the temp database ++ ** as required. */ ++ if( iDb!=1 ){ + sqlite3NestedParse(pParse, + "UPDATE sqlite_temp_master SET " +- "sql = sqlite_rename_trigger(sql, %Q), " +- "tbl_name = %Q " +- "WHERE %s;", zName, zName, zWhere); +- sqlite3DbFree(db, zWhere); ++ "sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, 1), " ++ "tbl_name = " ++ "CASE WHEN tbl_name=%Q COLLATE nocase AND " ++ " sqlite_rename_test(%Q, sql, type, name, 1) " ++ "THEN %Q ELSE tbl_name END " ++ "WHERE type IN ('view', 'trigger')" ++ , zDb, zTabName, zName, zTabName, zDb, zName); + } +-#endif + +-#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) +- if( db->flags&SQLITE_ForeignKeys ){ +- FKey *p; +- for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ +- Table *pFrom = p->pFrom; +- if( pFrom!=pTab ){ +- reloadTableSchema(pParse, p->pFrom, pFrom->zName); +- } +- } ++ /* If this is a virtual table, invoke the xRename() function if ++ ** one is defined. The xRename() callback will modify the names ++ ** of any resources used by the v-table implementation (including other ++ ** SQLite tables) that are identified by the name of the virtual table. ++ */ ++#ifndef SQLITE_OMIT_VIRTUALTABLE ++ if( pVTab ){ ++ int i = ++pParse->nMem; ++ sqlite3VdbeLoadString(v, i, zName); ++ sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB); ++ sqlite3MayAbort(pParse); + } + #endif + +- /* Drop and reload the internal table schema. */ +- reloadTableSchema(pParse, pTab, zName); ++ renameReloadSchema(pParse, iDb); ++ renameTestSchema(pParse, zDb, iDb==1); + + exit_rename_table: + sqlite3SrcListDelete(db, pSrc); +@@ -100128,12 +101737,11 @@ + Column *pCol; /* The new column */ + Expr *pDflt; /* Default value for the new column */ + sqlite3 *db; /* The database connection; */ +- Vdbe *v = pParse->pVdbe; /* The prepared statement under construction */ ++ Vdbe *v; /* The prepared statement under construction */ + int r1; /* Temporary registers */ + + db = pParse->db; + if( pParse->nErr || db->mallocFailed ) return; +- assert( v!=0 ); + pNew = pParse->pNewTable; + assert( pNew ); + +@@ -100228,17 +101836,20 @@ + ** from less than 3 to 4, as that will corrupt any preexisting DESC + ** index. + */ +- r1 = sqlite3GetTempReg(pParse); +- sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); +- sqlite3VdbeUsesBtree(v, iDb); +- sqlite3VdbeAddOp2(v, OP_AddImm, r1, -2); +- sqlite3VdbeAddOp2(v, OP_IfPos, r1, sqlite3VdbeCurrentAddr(v)+2); +- VdbeCoverage(v); +- sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, 3); +- sqlite3ReleaseTempReg(pParse, r1); ++ v = sqlite3GetVdbe(pParse); ++ if( v ){ ++ r1 = sqlite3GetTempReg(pParse); ++ sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); ++ sqlite3VdbeUsesBtree(v, iDb); ++ sqlite3VdbeAddOp2(v, OP_AddImm, r1, -2); ++ sqlite3VdbeAddOp2(v, OP_IfPos, r1, sqlite3VdbeCurrentAddr(v)+2); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, 3); ++ sqlite3ReleaseTempReg(pParse, r1); ++ } + +- /* Reload the schema of the modified table. */ +- reloadTableSchema(pParse, pTab, pTab->zName); ++ /* Reload the table definition */ ++ renameReloadSchema(pParse, iDb); + } + + /* +@@ -100259,7 +101870,6 @@ + SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ + Table *pNew; + Table *pTab; +- Vdbe *v; + int iDb; + int i; + int nAlloc; +@@ -100323,16 +101933,1146 @@ + pNew->addColOffset = pTab->addColOffset; + pNew->nTabRef = 1; + +- /* Begin a transaction and increment the schema cookie. */ +- sqlite3BeginWriteOperation(pParse, 0, iDb); +- v = sqlite3GetVdbe(pParse); +- if( !v ) goto exit_begin_add_column; +- sqlite3ChangeCookie(pParse, iDb); +- + exit_begin_add_column: + sqlite3SrcListDelete(db, pSrc); + return; + } ++ ++/* ++** Parameter pTab is the subject of an ALTER TABLE ... RENAME COLUMN ++** command. This function checks if the table is a view or virtual ++** table (columns of views or virtual tables may not be renamed). If so, ++** it loads an error message into pParse and returns non-zero. ++** ++** Or, if pTab is not a view or virtual table, zero is returned. ++*/ ++#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) ++static int isRealTable(Parse *pParse, Table *pTab){ ++ const char *zType = 0; ++#ifndef SQLITE_OMIT_VIEW ++ if( pTab->pSelect ){ ++ zType = "view"; ++ } ++#endif ++#ifndef SQLITE_OMIT_VIRTUALTABLE ++ if( IsVirtual(pTab) ){ ++ zType = "virtual table"; ++ } ++#endif ++ if( zType ){ ++ sqlite3ErrorMsg( ++ pParse, "cannot rename columns of %s \"%s\"", zType, pTab->zName ++ ); ++ return 1; ++ } ++ return 0; ++} ++#else /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */ ++# define isRealTable(x,y) (0) ++#endif ++ ++/* ++** Handles the following parser reduction: ++** ++** cmd ::= ALTER TABLE pSrc RENAME COLUMN pOld TO pNew ++*/ ++SQLITE_PRIVATE void sqlite3AlterRenameColumn( ++ Parse *pParse, /* Parsing context */ ++ SrcList *pSrc, /* Table being altered. pSrc->nSrc==1 */ ++ Token *pOld, /* Name of column being changed */ ++ Token *pNew /* New column name */ ++){ ++ sqlite3 *db = pParse->db; /* Database connection */ ++ Table *pTab; /* Table being updated */ ++ int iCol; /* Index of column being renamed */ ++ char *zOld = 0; /* Old column name */ ++ char *zNew = 0; /* New column name */ ++ const char *zDb; /* Name of schema containing the table */ ++ int iSchema; /* Index of the schema */ ++ int bQuote; /* True to quote the new name */ ++ ++ /* Locate the table to be altered */ ++ pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); ++ if( !pTab ) goto exit_rename_column; ++ ++ /* Cannot alter a system table */ ++ if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ) goto exit_rename_column; ++ if( SQLITE_OK!=isRealTable(pParse, pTab) ) goto exit_rename_column; ++ ++ /* Which schema holds the table to be altered */ ++ iSchema = sqlite3SchemaToIndex(db, pTab->pSchema); ++ assert( iSchema>=0 ); ++ zDb = db->aDb[iSchema].zDbSName; ++ ++#ifndef SQLITE_OMIT_AUTHORIZATION ++ /* Invoke the authorization callback. */ ++ if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ ++ goto exit_rename_column; ++ } ++#endif ++ ++ /* Make sure the old name really is a column name in the table to be ++ ** altered. Set iCol to be the index of the column being renamed */ ++ zOld = sqlite3NameFromToken(db, pOld); ++ if( !zOld ) goto exit_rename_column; ++ for(iCol=0; iCol<pTab->nCol; iCol++){ ++ if( 0==sqlite3StrICmp(pTab->aCol[iCol].zName, zOld) ) break; ++ } ++ if( iCol==pTab->nCol ){ ++ sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zOld); ++ goto exit_rename_column; ++ } ++ ++ /* Do the rename operation using a recursive UPDATE statement that ++ ** uses the sqlite_rename_column() SQL function to compute the new ++ ** CREATE statement text for the sqlite_master table. ++ */ ++ zNew = sqlite3NameFromToken(db, pNew); ++ if( !zNew ) goto exit_rename_column; ++ assert( pNew->n>0 ); ++ bQuote = sqlite3Isquote(pNew->z[0]); ++ sqlite3NestedParse(pParse, ++ "UPDATE \"%w\".%s SET " ++ "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, %d) " ++ "WHERE name NOT LIKE 'sqlite_%%' AND (type != 'index' OR tbl_name = %Q)" ++ " AND sql NOT LIKE 'create virtual%%'", ++ zDb, MASTER_NAME, ++ zDb, pTab->zName, iCol, zNew, bQuote, iSchema==1, ++ pTab->zName ++ ); ++ ++ sqlite3NestedParse(pParse, ++ "UPDATE temp.%s SET " ++ "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, 1) " ++ "WHERE type IN ('trigger', 'view')", ++ MASTER_NAME, ++ zDb, pTab->zName, iCol, zNew, bQuote ++ ); ++ ++ /* Drop and reload the database schema. */ ++ renameReloadSchema(pParse, iSchema); ++ renameTestSchema(pParse, zDb, iSchema==1); ++ ++ exit_rename_column: ++ sqlite3SrcListDelete(db, pSrc); ++ sqlite3DbFree(db, zOld); ++ sqlite3DbFree(db, zNew); ++ return; ++} ++ ++/* ++** Each RenameToken object maps an element of the parse tree into ++** the token that generated that element. The parse tree element ++** might be one of: ++** ++** * A pointer to an Expr that represents an ID ++** * The name of a table column in Column.zName ++** ++** A list of RenameToken objects can be constructed during parsing. ++** Each new object is created by sqlite3RenameTokenMap(). ++** As the parse tree is transformed, the sqlite3RenameTokenRemap() ++** routine is used to keep the mapping current. ++** ++** After the parse finishes, renameTokenFind() routine can be used ++** to look up the actual token value that created some element in ++** the parse tree. ++*/ ++struct RenameToken { ++ void *p; /* Parse tree element created by token t */ ++ Token t; /* The token that created parse tree element p */ ++ RenameToken *pNext; /* Next is a list of all RenameToken objects */ ++}; ++ ++/* ++** The context of an ALTER TABLE RENAME COLUMN operation that gets passed ++** down into the Walker. ++*/ ++typedef struct RenameCtx RenameCtx; ++struct RenameCtx { ++ RenameToken *pList; /* List of tokens to overwrite */ ++ int nList; /* Number of tokens in pList */ ++ int iCol; /* Index of column being renamed */ ++ Table *pTab; /* Table being ALTERed */ ++ const char *zOld; /* Old column name */ ++}; ++ ++#ifdef SQLITE_DEBUG ++/* ++** This function is only for debugging. It performs two tasks: ++** ++** 1. Checks that pointer pPtr does not already appear in the ++** rename-token list. ++** ++** 2. Dereferences each pointer in the rename-token list. ++** ++** The second is most effective when debugging under valgrind or ++** address-sanitizer or similar. If any of these pointers no longer ++** point to valid objects, an exception is raised by the memory-checking ++** tool. ++** ++** The point of this is to prevent comparisons of invalid pointer values. ++** Even though this always seems to work, it is undefined according to the ++** C standard. Example of undefined comparison: ++** ++** sqlite3_free(x); ++** if( x==y ) ... ++** ++** Technically, as x no longer points into a valid object or to the byte ++** following a valid object, it may not be used in comparison operations. ++*/ ++static void renameTokenCheckAll(Parse *pParse, void *pPtr){ ++ if( pParse->nErr==0 && pParse->db->mallocFailed==0 ){ ++ RenameToken *p; ++ u8 i = 0; ++ for(p=pParse->pRename; p; p=p->pNext){ ++ if( p->p ){ ++ assert( p->p!=pPtr ); ++ i += *(u8*)(p->p); ++ } ++ } ++ } ++} ++#else ++# define renameTokenCheckAll(x,y) ++#endif ++ ++/* ++** Remember that the parser tree element pPtr was created using ++** the token pToken. ++** ++** In other words, construct a new RenameToken object and add it ++** to the list of RenameToken objects currently being built up ++** in pParse->pRename. ++** ++** The pPtr argument is returned so that this routine can be used ++** with tail recursion in tokenExpr() routine, for a small performance ++** improvement. ++*/ ++SQLITE_PRIVATE void *sqlite3RenameTokenMap(Parse *pParse, void *pPtr, Token *pToken){ ++ RenameToken *pNew; ++ assert( pPtr || pParse->db->mallocFailed ); ++ renameTokenCheckAll(pParse, pPtr); ++ pNew = sqlite3DbMallocZero(pParse->db, sizeof(RenameToken)); ++ if( pNew ){ ++ pNew->p = pPtr; ++ pNew->t = *pToken; ++ pNew->pNext = pParse->pRename; ++ pParse->pRename = pNew; ++ } ++ ++ return pPtr; ++} ++ ++/* ++** It is assumed that there is already a RenameToken object associated ++** with parse tree element pFrom. This function remaps the associated token ++** to parse tree element pTo. ++*/ ++SQLITE_PRIVATE void sqlite3RenameTokenRemap(Parse *pParse, void *pTo, void *pFrom){ ++ RenameToken *p; ++ renameTokenCheckAll(pParse, pTo); ++ for(p=pParse->pRename; p; p=p->pNext){ ++ if( p->p==pFrom ){ ++ p->p = pTo; ++ break; ++ } ++ } ++} ++ ++/* ++** Walker callback used by sqlite3RenameExprUnmap(). ++*/ ++static int renameUnmapExprCb(Walker *pWalker, Expr *pExpr){ ++ Parse *pParse = pWalker->pParse; ++ sqlite3RenameTokenRemap(pParse, 0, (void*)pExpr); ++ return WRC_Continue; ++} ++ ++/* ++** Remove all nodes that are part of expression pExpr from the rename list. ++*/ ++SQLITE_PRIVATE void sqlite3RenameExprUnmap(Parse *pParse, Expr *pExpr){ ++ Walker sWalker; ++ memset(&sWalker, 0, sizeof(Walker)); ++ sWalker.pParse = pParse; ++ sWalker.xExprCallback = renameUnmapExprCb; ++ sqlite3WalkExpr(&sWalker, pExpr); ++} ++ ++/* ++** Remove all nodes that are part of expression-list pEList from the ++** rename list. ++*/ ++SQLITE_PRIVATE void sqlite3RenameExprlistUnmap(Parse *pParse, ExprList *pEList){ ++ if( pEList ){ ++ int i; ++ Walker sWalker; ++ memset(&sWalker, 0, sizeof(Walker)); ++ sWalker.pParse = pParse; ++ sWalker.xExprCallback = renameUnmapExprCb; ++ sqlite3WalkExprList(&sWalker, pEList); ++ for(i=0; i<pEList->nExpr; i++){ ++ sqlite3RenameTokenRemap(pParse, 0, (void*)pEList->a[i].zName); ++ } ++ } ++} ++ ++/* ++** Free the list of RenameToken objects given in the second argument ++*/ ++static void renameTokenFree(sqlite3 *db, RenameToken *pToken){ ++ RenameToken *pNext; ++ RenameToken *p; ++ for(p=pToken; p; p=pNext){ ++ pNext = p->pNext; ++ sqlite3DbFree(db, p); ++ } ++} ++ ++/* ++** Search the Parse object passed as the first argument for a RenameToken ++** object associated with parse tree element pPtr. If found, remove it ++** from the Parse object and add it to the list maintained by the ++** RenameCtx object passed as the second argument. ++*/ ++static void renameTokenFind(Parse *pParse, struct RenameCtx *pCtx, void *pPtr){ ++ RenameToken **pp; ++ assert( pPtr!=0 ); ++ for(pp=&pParse->pRename; (*pp); pp=&(*pp)->pNext){ ++ if( (*pp)->p==pPtr ){ ++ RenameToken *pToken = *pp; ++ *pp = pToken->pNext; ++ pToken->pNext = pCtx->pList; ++ pCtx->pList = pToken; ++ pCtx->nList++; ++ break; ++ } ++ } ++} ++ ++/* ++** This is a Walker select callback. It does nothing. It is only required ++** because without a dummy callback, sqlite3WalkExpr() and similar do not ++** descend into sub-select statements. ++*/ ++static int renameColumnSelectCb(Walker *pWalker, Select *p){ ++ UNUSED_PARAMETER(pWalker); ++ UNUSED_PARAMETER(p); ++ return WRC_Continue; ++} ++ ++/* ++** This is a Walker expression callback. ++** ++** For every TK_COLUMN node in the expression tree, search to see ++** if the column being references is the column being renamed by an ++** ALTER TABLE statement. If it is, then attach its associated ++** RenameToken object to the list of RenameToken objects being ++** constructed in RenameCtx object at pWalker->u.pRename. ++*/ ++static int renameColumnExprCb(Walker *pWalker, Expr *pExpr){ ++ RenameCtx *p = pWalker->u.pRename; ++ if( pExpr->op==TK_TRIGGER ++ && pExpr->iColumn==p->iCol ++ && pWalker->pParse->pTriggerTab==p->pTab ++ ){ ++ renameTokenFind(pWalker->pParse, p, (void*)pExpr); ++ }else if( pExpr->op==TK_COLUMN ++ && pExpr->iColumn==p->iCol ++ && p->pTab==pExpr->y.pTab ++ ){ ++ renameTokenFind(pWalker->pParse, p, (void*)pExpr); ++ } ++ return WRC_Continue; ++} ++ ++/* ++** The RenameCtx contains a list of tokens that reference a column that ++** is being renamed by an ALTER TABLE statement. Return the "last" ++** RenameToken in the RenameCtx and remove that RenameToken from the ++** RenameContext. "Last" means the last RenameToken encountered when ++** the input SQL is parsed from left to right. Repeated calls to this routine ++** return all column name tokens in the order that they are encountered ++** in the SQL statement. ++*/ ++static RenameToken *renameColumnTokenNext(RenameCtx *pCtx){ ++ RenameToken *pBest = pCtx->pList; ++ RenameToken *pToken; ++ RenameToken **pp; ++ ++ for(pToken=pBest->pNext; pToken; pToken=pToken->pNext){ ++ if( pToken->t.z>pBest->t.z ) pBest = pToken; ++ } ++ for(pp=&pCtx->pList; *pp!=pBest; pp=&(*pp)->pNext); ++ *pp = pBest->pNext; ++ ++ return pBest; ++} ++ ++/* ++** An error occured while parsing or otherwise processing a database ++** object (either pParse->pNewTable, pNewIndex or pNewTrigger) as part of an ++** ALTER TABLE RENAME COLUMN program. The error message emitted by the ++** sub-routine is currently stored in pParse->zErrMsg. This function ++** adds context to the error message and then stores it in pCtx. ++*/ ++static void renameColumnParseError( ++ sqlite3_context *pCtx, ++ int bPost, ++ sqlite3_value *pType, ++ sqlite3_value *pObject, ++ Parse *pParse ++){ ++ const char *zT = (const char*)sqlite3_value_text(pType); ++ const char *zN = (const char*)sqlite3_value_text(pObject); ++ char *zErr; ++ ++ zErr = sqlite3_mprintf("error in %s %s%s: %s", ++ zT, zN, (bPost ? " after rename" : ""), ++ pParse->zErrMsg ++ ); ++ sqlite3_result_error(pCtx, zErr, -1); ++ sqlite3_free(zErr); ++} ++ ++/* ++** For each name in the the expression-list pEList (i.e. each ++** pEList->a[i].zName) that matches the string in zOld, extract the ++** corresponding rename-token from Parse object pParse and add it ++** to the RenameCtx pCtx. ++*/ ++static void renameColumnElistNames( ++ Parse *pParse, ++ RenameCtx *pCtx, ++ ExprList *pEList, ++ const char *zOld ++){ ++ if( pEList ){ ++ int i; ++ for(i=0; i<pEList->nExpr; i++){ ++ char *zName = pEList->a[i].zName; ++ if( 0==sqlite3_stricmp(zName, zOld) ){ ++ renameTokenFind(pParse, pCtx, (void*)zName); ++ } ++ } ++ } ++} ++ ++/* ++** For each name in the the id-list pIdList (i.e. each pIdList->a[i].zName) ++** that matches the string in zOld, extract the corresponding rename-token ++** from Parse object pParse and add it to the RenameCtx pCtx. ++*/ ++static void renameColumnIdlistNames( ++ Parse *pParse, ++ RenameCtx *pCtx, ++ IdList *pIdList, ++ const char *zOld ++){ ++ if( pIdList ){ ++ int i; ++ for(i=0; i<pIdList->nId; i++){ ++ char *zName = pIdList->a[i].zName; ++ if( 0==sqlite3_stricmp(zName, zOld) ){ ++ renameTokenFind(pParse, pCtx, (void*)zName); ++ } ++ } ++ } ++} ++ ++/* ++** Parse the SQL statement zSql using Parse object (*p). The Parse object ++** is initialized by this function before it is used. ++*/ ++static int renameParseSql( ++ Parse *p, /* Memory to use for Parse object */ ++ const char *zDb, /* Name of schema SQL belongs to */ ++ int bTable, /* 1 -> RENAME TABLE, 0 -> RENAME COLUMN */ ++ sqlite3 *db, /* Database handle */ ++ const char *zSql, /* SQL to parse */ ++ int bTemp /* True if SQL is from temp schema */ ++){ ++ int rc; ++ char *zErr = 0; ++ ++ db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb); ++ ++ /* Parse the SQL statement passed as the first argument. If no error ++ ** occurs and the parse does not result in a new table, index or ++ ** trigger object, the database must be corrupt. */ ++ memset(p, 0, sizeof(Parse)); ++ p->eParseMode = (bTable ? PARSE_MODE_RENAME_TABLE : PARSE_MODE_RENAME_COLUMN); ++ p->db = db; ++ p->nQueryLoop = 1; ++ rc = sqlite3RunParser(p, zSql, &zErr); ++ assert( p->zErrMsg==0 ); ++ assert( rc!=SQLITE_OK || zErr==0 ); ++ assert( (0!=p->pNewTable) + (0!=p->pNewIndex) + (0!=p->pNewTrigger)<2 ); ++ p->zErrMsg = zErr; ++ if( db->mallocFailed ) rc = SQLITE_NOMEM; ++ if( rc==SQLITE_OK ++ && p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0 ++ ){ ++ rc = SQLITE_CORRUPT_BKPT; ++ } ++ ++#ifdef SQLITE_DEBUG ++ /* Ensure that all mappings in the Parse.pRename list really do map to ++ ** a part of the input string. */ ++ if( rc==SQLITE_OK ){ ++ int nSql = sqlite3Strlen30(zSql); ++ RenameToken *pToken; ++ for(pToken=p->pRename; pToken; pToken=pToken->pNext){ ++ assert( pToken->t.z>=zSql && &pToken->t.z[pToken->t.n]<=&zSql[nSql] ); ++ } ++ } ++#endif ++ ++ db->init.iDb = 0; ++ return rc; ++} ++ ++/* ++** This function edits SQL statement zSql, replacing each token identified ++** by the linked list pRename with the text of zNew. If argument bQuote is ++** true, then zNew is always quoted first. If no error occurs, the result ++** is loaded into context object pCtx as the result. ++** ++** Or, if an error occurs (i.e. an OOM condition), an error is left in ++** pCtx and an SQLite error code returned. ++*/ ++static int renameEditSql( ++ sqlite3_context *pCtx, /* Return result here */ ++ RenameCtx *pRename, /* Rename context */ ++ const char *zSql, /* SQL statement to edit */ ++ const char *zNew, /* New token text */ ++ int bQuote /* True to always quote token */ ++){ ++ int nNew = sqlite3Strlen30(zNew); ++ int nSql = sqlite3Strlen30(zSql); ++ sqlite3 *db = sqlite3_context_db_handle(pCtx); ++ int rc = SQLITE_OK; ++ char *zQuot; ++ char *zOut; ++ int nQuot; ++ ++ /* Set zQuot to point to a buffer containing a quoted copy of the ++ ** identifier zNew. If the corresponding identifier in the original ++ ** ALTER TABLE statement was quoted (bQuote==1), then set zNew to ++ ** point to zQuot so that all substitutions are made using the ++ ** quoted version of the new column name. */ ++ zQuot = sqlite3MPrintf(db, "\"%w\"", zNew); ++ if( zQuot==0 ){ ++ return SQLITE_NOMEM; ++ }else{ ++ nQuot = sqlite3Strlen30(zQuot); ++ } ++ if( bQuote ){ ++ zNew = zQuot; ++ nNew = nQuot; ++ } ++ ++ /* At this point pRename->pList contains a list of RenameToken objects ++ ** corresponding to all tokens in the input SQL that must be replaced ++ ** with the new column name. All that remains is to construct and ++ ** return the edited SQL string. */ ++ assert( nQuot>=nNew ); ++ zOut = sqlite3DbMallocZero(db, nSql + pRename->nList*nQuot + 1); ++ if( zOut ){ ++ int nOut = nSql; ++ memcpy(zOut, zSql, nSql); ++ while( pRename->pList ){ ++ int iOff; /* Offset of token to replace in zOut */ ++ RenameToken *pBest = renameColumnTokenNext(pRename); ++ ++ u32 nReplace; ++ const char *zReplace; ++ if( sqlite3IsIdChar(*pBest->t.z) ){ ++ nReplace = nNew; ++ zReplace = zNew; ++ }else{ ++ nReplace = nQuot; ++ zReplace = zQuot; ++ } ++ ++ iOff = pBest->t.z - zSql; ++ if( pBest->t.n!=nReplace ){ ++ memmove(&zOut[iOff + nReplace], &zOut[iOff + pBest->t.n], ++ nOut - (iOff + pBest->t.n) ++ ); ++ nOut += nReplace - pBest->t.n; ++ zOut[nOut] = '\0'; ++ } ++ memcpy(&zOut[iOff], zReplace, nReplace); ++ sqlite3DbFree(db, pBest); ++ } ++ ++ sqlite3_result_text(pCtx, zOut, -1, SQLITE_TRANSIENT); ++ sqlite3DbFree(db, zOut); ++ }else{ ++ 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, const char *zDb){ ++ sqlite3 *db = pParse->db; ++ Trigger *pNew = pParse->pNewTrigger; ++ TriggerStep *pStep; ++ NameContext sNC; ++ int rc = SQLITE_OK; ++ ++ memset(&sNC, 0, sizeof(sNC)); ++ sNC.pParse = pParse; ++ assert( pNew->pTabSchema ); ++ pParse->pTriggerTab = sqlite3FindTable(db, pNew->table, ++ db->aDb[sqlite3SchemaToIndex(db, pNew->pTabSchema)].zDbSName ++ ); ++ pParse->eTriggerOp = pNew->op; ++ /* ALWAYS() because if the table of the trigger does not exist, the ++ ** error would have been hit before this point */ ++ if( ALWAYS(pParse->pTriggerTab) ){ ++ rc = sqlite3ViewGetColumnNames(pParse, pParse->pTriggerTab); ++ } ++ ++ /* Resolve symbols in WHEN clause */ ++ if( rc==SQLITE_OK && pNew->pWhen ){ ++ rc = sqlite3ResolveExprNames(&sNC, pNew->pWhen); ++ } ++ ++ for(pStep=pNew->step_list; rc==SQLITE_OK && pStep; pStep=pStep->pNext){ ++ if( pStep->pSelect ){ ++ sqlite3SelectPrep(pParse, pStep->pSelect, &sNC); ++ if( pParse->nErr ) rc = pParse->rc; ++ } ++ if( rc==SQLITE_OK && pStep->zTarget ){ ++ Table *pTarget = sqlite3LocateTable(pParse, 0, pStep->zTarget, zDb); ++ if( pTarget==0 ){ ++ rc = SQLITE_ERROR; ++ }else if( SQLITE_OK==(rc = sqlite3ViewGetColumnNames(pParse, pTarget)) ){ ++ SrcList sSrc; ++ memset(&sSrc, 0, sizeof(sSrc)); ++ sSrc.nSrc = 1; ++ sSrc.a[0].zName = pStep->zTarget; ++ sSrc.a[0].pTab = pTarget; ++ sNC.pSrcList = &sSrc; ++ if( pStep->pWhere ){ ++ rc = sqlite3ResolveExprNames(&sNC, pStep->pWhere); ++ } ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3ResolveExprListNames(&sNC, pStep->pExprList); ++ } ++ assert( !pStep->pUpsert || (!pStep->pWhere && !pStep->pExprList) ); ++ if( pStep->pUpsert ){ ++ Upsert *pUpsert = pStep->pUpsert; ++ assert( rc==SQLITE_OK ); ++ pUpsert->pUpsertSrc = &sSrc; ++ sNC.uNC.pUpsert = pUpsert; ++ sNC.ncFlags = NC_UUpsert; ++ rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget); ++ if( rc==SQLITE_OK ){ ++ ExprList *pUpsertSet = pUpsert->pUpsertSet; ++ rc = sqlite3ResolveExprListNames(&sNC, pUpsertSet); ++ } ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertWhere); ++ } ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere); ++ } ++ sNC.ncFlags = 0; ++ } ++ } ++ } ++ } ++ return rc; ++} ++ ++/* ++** Invoke sqlite3WalkExpr() or sqlite3WalkSelect() on all Select or Expr ++** objects that are part of the trigger passed as the second argument. ++*/ ++static void renameWalkTrigger(Walker *pWalker, Trigger *pTrigger){ ++ TriggerStep *pStep; ++ ++ /* Find tokens to edit in WHEN clause */ ++ sqlite3WalkExpr(pWalker, pTrigger->pWhen); ++ ++ /* Find tokens to edit in trigger steps */ ++ for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){ ++ sqlite3WalkSelect(pWalker, pStep->pSelect); ++ sqlite3WalkExpr(pWalker, pStep->pWhere); ++ sqlite3WalkExprList(pWalker, pStep->pExprList); ++ if( pStep->pUpsert ){ ++ Upsert *pUpsert = pStep->pUpsert; ++ sqlite3WalkExprList(pWalker, pUpsert->pUpsertTarget); ++ sqlite3WalkExprList(pWalker, pUpsert->pUpsertSet); ++ sqlite3WalkExpr(pWalker, pUpsert->pUpsertWhere); ++ sqlite3WalkExpr(pWalker, pUpsert->pUpsertTargetWhere); ++ } ++ } ++} ++ ++/* ++** Free the contents of Parse object (*pParse). Do not free the memory ++** occupied by the Parse object itself. ++*/ ++static void renameParseCleanup(Parse *pParse){ ++ sqlite3 *db = pParse->db; ++ if( pParse->pVdbe ){ ++ sqlite3VdbeFinalize(pParse->pVdbe); ++ } ++ sqlite3DeleteTable(db, pParse->pNewTable); ++ if( pParse->pNewIndex ) sqlite3FreeIndex(db, pParse->pNewIndex); ++ sqlite3DeleteTrigger(db, pParse->pNewTrigger); ++ sqlite3DbFree(db, pParse->zErrMsg); ++ renameTokenFree(db, pParse->pRename); ++ sqlite3ParserReset(pParse); ++} ++ ++/* ++** SQL function: ++** ++** sqlite_rename_column(zSql, iCol, bQuote, zNew, zTable, zOld) ++** ++** 0. zSql: SQL statement to rewrite ++** 1. type: Type of object ("table", "view" etc.) ++** 2. object: Name of object ++** 3. Database: Database name (e.g. "main") ++** 4. Table: Table name ++** 5. iCol: Index of column to rename ++** 6. zNew: New column name ++** 7. bQuote: Non-zero if the new column name should be quoted. ++** 8. bTemp: True if zSql comes from temp schema ++** ++** Do a column rename operation on the CREATE statement given in zSql. ++** The iCol-th column (left-most is 0) of table zTable is renamed from zCol ++** into zNew. The name should be quoted if bQuote is true. ++** ++** This function is used internally by the ALTER TABLE RENAME COLUMN command. ++** It is only accessible to SQL created using sqlite3NestedParse(). It is ++** not reachable from ordinary SQL passed into sqlite3_prepare(). ++*/ ++static void renameColumnFunc( ++ sqlite3_context *context, ++ int NotUsed, ++ sqlite3_value **argv ++){ ++ sqlite3 *db = sqlite3_context_db_handle(context); ++ RenameCtx sCtx; ++ const char *zSql = (const char*)sqlite3_value_text(argv[0]); ++ const char *zDb = (const char*)sqlite3_value_text(argv[3]); ++ const char *zTable = (const char*)sqlite3_value_text(argv[4]); ++ int iCol = sqlite3_value_int(argv[5]); ++ const char *zNew = (const char*)sqlite3_value_text(argv[6]); ++ int bQuote = sqlite3_value_int(argv[7]); ++ int bTemp = sqlite3_value_int(argv[8]); ++ const char *zOld; ++ int rc; ++ Parse sParse; ++ Walker sWalker; ++ Index *pIdx; ++ int i; ++ Table *pTab; ++#ifndef SQLITE_OMIT_AUTHORIZATION ++ sqlite3_xauth xAuth = db->xAuth; ++#endif ++ ++ UNUSED_PARAMETER(NotUsed); ++ if( zSql==0 ) return; ++ if( zTable==0 ) return; ++ if( zNew==0 ) return; ++ if( iCol<0 ) return; ++ sqlite3BtreeEnterAll(db); ++ pTab = sqlite3FindTable(db, zTable, zDb); ++ if( pTab==0 || iCol>=pTab->nCol ){ ++ sqlite3BtreeLeaveAll(db); ++ return; ++ } ++ zOld = pTab->aCol[iCol].zName; ++ memset(&sCtx, 0, sizeof(sCtx)); ++ sCtx.iCol = ((iCol==pTab->iPKey) ? -1 : iCol); ++ ++#ifndef SQLITE_OMIT_AUTHORIZATION ++ db->xAuth = 0; ++#endif ++ rc = renameParseSql(&sParse, zDb, 0, db, zSql, bTemp); ++ ++ /* Find tokens that need to be replaced. */ ++ memset(&sWalker, 0, sizeof(Walker)); ++ sWalker.pParse = &sParse; ++ sWalker.xExprCallback = renameColumnExprCb; ++ sWalker.xSelectCallback = renameColumnSelectCb; ++ sWalker.u.pRename = &sCtx; ++ ++ sCtx.pTab = pTab; ++ if( rc!=SQLITE_OK ) goto renameColumnFunc_done; ++ if( sParse.pNewTable ){ ++ Select *pSelect = sParse.pNewTable->pSelect; ++ if( pSelect ){ ++ sParse.rc = SQLITE_OK; ++ sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, 0); ++ rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc); ++ if( rc==SQLITE_OK ){ ++ sqlite3WalkSelect(&sWalker, pSelect); ++ } ++ if( rc!=SQLITE_OK ) goto renameColumnFunc_done; ++ }else{ ++ /* A regular table */ ++ int bFKOnly = sqlite3_stricmp(zTable, sParse.pNewTable->zName); ++ FKey *pFKey; ++ assert( sParse.pNewTable->pSelect==0 ); ++ sCtx.pTab = sParse.pNewTable; ++ if( bFKOnly==0 ){ ++ renameTokenFind( ++ &sParse, &sCtx, (void*)sParse.pNewTable->aCol[iCol].zName ++ ); ++ if( sCtx.iCol<0 ){ ++ renameTokenFind(&sParse, &sCtx, (void*)&sParse.pNewTable->iPKey); ++ } ++ sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck); ++ for(pIdx=sParse.pNewTable->pIndex; pIdx; pIdx=pIdx->pNext){ ++ sqlite3WalkExprList(&sWalker, pIdx->aColExpr); ++ } ++ } ++ ++ for(pFKey=sParse.pNewTable->pFKey; pFKey; pFKey=pFKey->pNextFrom){ ++ for(i=0; i<pFKey->nCol; i++){ ++ if( bFKOnly==0 && pFKey->aCol[i].iFrom==iCol ){ ++ renameTokenFind(&sParse, &sCtx, (void*)&pFKey->aCol[i]); ++ } ++ if( 0==sqlite3_stricmp(pFKey->zTo, zTable) ++ && 0==sqlite3_stricmp(pFKey->aCol[i].zCol, zOld) ++ ){ ++ renameTokenFind(&sParse, &sCtx, (void*)pFKey->aCol[i].zCol); ++ } ++ } ++ } ++ } ++ }else if( sParse.pNewIndex ){ ++ sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr); ++ sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere); ++ }else{ ++ /* A trigger */ ++ TriggerStep *pStep; ++ rc = renameResolveTrigger(&sParse, (bTemp ? 0 : zDb)); ++ if( rc!=SQLITE_OK ) goto renameColumnFunc_done; ++ ++ for(pStep=sParse.pNewTrigger->step_list; pStep; pStep=pStep->pNext){ ++ if( pStep->zTarget ){ ++ Table *pTarget = sqlite3LocateTable(&sParse, 0, pStep->zTarget, zDb); ++ if( pTarget==pTab ){ ++ if( pStep->pUpsert ){ ++ ExprList *pUpsertSet = pStep->pUpsert->pUpsertSet; ++ renameColumnElistNames(&sParse, &sCtx, pUpsertSet, zOld); ++ } ++ renameColumnIdlistNames(&sParse, &sCtx, pStep->pIdList, zOld); ++ renameColumnElistNames(&sParse, &sCtx, pStep->pExprList, zOld); ++ } ++ } ++ } ++ ++ ++ /* Find tokens to edit in UPDATE OF clause */ ++ if( sParse.pTriggerTab==pTab ){ ++ renameColumnIdlistNames(&sParse, &sCtx,sParse.pNewTrigger->pColumns,zOld); ++ } ++ ++ /* Find tokens to edit in various expressions and selects */ ++ renameWalkTrigger(&sWalker, sParse.pNewTrigger); ++ } ++ ++ assert( rc==SQLITE_OK ); ++ rc = renameEditSql(context, &sCtx, zSql, zNew, bQuote); ++ ++renameColumnFunc_done: ++ if( rc!=SQLITE_OK ){ ++ if( sParse.zErrMsg ){ ++ renameColumnParseError(context, 0, argv[1], argv[2], &sParse); ++ }else{ ++ sqlite3_result_error_code(context, rc); ++ } ++ } ++ ++ renameParseCleanup(&sParse); ++ renameTokenFree(db, sCtx.pList); ++#ifndef SQLITE_OMIT_AUTHORIZATION ++ db->xAuth = xAuth; ++#endif ++ sqlite3BtreeLeaveAll(db); ++} ++ ++/* ++** Walker expression callback used by "RENAME TABLE". ++*/ ++static int renameTableExprCb(Walker *pWalker, Expr *pExpr){ ++ RenameCtx *p = pWalker->u.pRename; ++ if( pExpr->op==TK_COLUMN && p->pTab==pExpr->y.pTab ){ ++ renameTokenFind(pWalker->pParse, p, (void*)&pExpr->y.pTab); ++ } ++ return WRC_Continue; ++} ++ ++/* ++** Walker select callback used by "RENAME TABLE". ++*/ ++static int renameTableSelectCb(Walker *pWalker, Select *pSelect){ ++ int i; ++ RenameCtx *p = pWalker->u.pRename; ++ SrcList *pSrc = pSelect->pSrc; ++ for(i=0; i<pSrc->nSrc; i++){ ++ struct SrcList_item *pItem = &pSrc->a[i]; ++ if( pItem->pTab==p->pTab ){ ++ renameTokenFind(pWalker->pParse, p, pItem->zName); ++ } ++ } ++ ++ return WRC_Continue; ++} ++ ++ ++/* ++** This C function implements an SQL user function that is used by SQL code ++** generated by the ALTER TABLE ... RENAME command to modify the definition ++** of any foreign key constraints that use the table being renamed as the ++** parent table. It is passed three arguments: ++** ++** 0: The database containing the table being renamed. ++** 1. type: Type of object ("table", "view" etc.) ++** 2. object: Name of object ++** 3: The complete text of the schema statement being modified, ++** 4: The old name of the table being renamed, and ++** 5: The new name of the table being renamed. ++** 6: True if the schema statement comes from the temp db. ++** ++** It returns the new schema statement. For example: ++** ++** sqlite_rename_table('main', 'CREATE TABLE t1(a REFERENCES t2)','t2','t3',0) ++** -> 'CREATE TABLE t1(a REFERENCES t3)' ++*/ ++static void renameTableFunc( ++ sqlite3_context *context, ++ int NotUsed, ++ sqlite3_value **argv ++){ ++ sqlite3 *db = sqlite3_context_db_handle(context); ++ const char *zDb = (const char*)sqlite3_value_text(argv[0]); ++ const char *zInput = (const char*)sqlite3_value_text(argv[3]); ++ const char *zOld = (const char*)sqlite3_value_text(argv[4]); ++ const char *zNew = (const char*)sqlite3_value_text(argv[5]); ++ int bTemp = sqlite3_value_int(argv[6]); ++ UNUSED_PARAMETER(NotUsed); ++ ++ if( zInput && zOld && zNew ){ ++ Parse sParse; ++ int rc; ++ int bQuote = 1; ++ RenameCtx sCtx; ++ Walker sWalker; ++ ++#ifndef SQLITE_OMIT_AUTHORIZATION ++ sqlite3_xauth xAuth = db->xAuth; ++ db->xAuth = 0; ++#endif ++ ++ sqlite3BtreeEnterAll(db); ++ ++ memset(&sCtx, 0, sizeof(RenameCtx)); ++ sCtx.pTab = sqlite3FindTable(db, zOld, zDb); ++ memset(&sWalker, 0, sizeof(Walker)); ++ sWalker.pParse = &sParse; ++ sWalker.xExprCallback = renameTableExprCb; ++ sWalker.xSelectCallback = renameTableSelectCb; ++ sWalker.u.pRename = &sCtx; ++ ++ rc = renameParseSql(&sParse, zDb, 1, db, zInput, bTemp); ++ ++ if( rc==SQLITE_OK ){ ++ int isLegacy = (db->flags & SQLITE_LegacyAlter); ++ if( sParse.pNewTable ){ ++ Table *pTab = sParse.pNewTable; ++ ++ if( pTab->pSelect ){ ++ if( isLegacy==0 ){ ++ NameContext sNC; ++ memset(&sNC, 0, sizeof(sNC)); ++ sNC.pParse = &sParse; ++ ++ sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC); ++ if( sParse.nErr ) rc = sParse.rc; ++ sqlite3WalkSelect(&sWalker, pTab->pSelect); ++ } ++ }else{ ++ /* Modify any FK definitions to point to the new table. */ ++#ifndef SQLITE_OMIT_FOREIGN_KEY ++ if( isLegacy==0 || (db->flags & SQLITE_ForeignKeys) ){ ++ FKey *pFKey; ++ for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){ ++ if( sqlite3_stricmp(pFKey->zTo, zOld)==0 ){ ++ renameTokenFind(&sParse, &sCtx, (void*)pFKey->zTo); ++ } ++ } ++ } ++#endif ++ ++ /* If this is the table being altered, fix any table refs in CHECK ++ ** expressions. Also update the name that appears right after the ++ ** "CREATE [VIRTUAL] TABLE" bit. */ ++ if( sqlite3_stricmp(zOld, pTab->zName)==0 ){ ++ sCtx.pTab = pTab; ++ if( isLegacy==0 ){ ++ sqlite3WalkExprList(&sWalker, pTab->pCheck); ++ } ++ renameTokenFind(&sParse, &sCtx, pTab->zName); ++ } ++ } ++ } ++ ++ else if( sParse.pNewIndex ){ ++ renameTokenFind(&sParse, &sCtx, sParse.pNewIndex->zName); ++ if( isLegacy==0 ){ ++ sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere); ++ } ++ } ++ ++#ifndef SQLITE_OMIT_TRIGGER ++ else{ ++ Trigger *pTrigger = sParse.pNewTrigger; ++ TriggerStep *pStep; ++ if( 0==sqlite3_stricmp(sParse.pNewTrigger->table, zOld) ++ && sCtx.pTab->pSchema==pTrigger->pTabSchema ++ ){ ++ renameTokenFind(&sParse, &sCtx, sParse.pNewTrigger->table); ++ } ++ ++ if( isLegacy==0 ){ ++ rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb); ++ if( rc==SQLITE_OK ){ ++ renameWalkTrigger(&sWalker, pTrigger); ++ for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){ ++ if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){ ++ renameTokenFind(&sParse, &sCtx, pStep->zTarget); ++ } ++ } ++ } ++ } ++ } ++#endif ++ } ++ ++ if( rc==SQLITE_OK ){ ++ rc = renameEditSql(context, &sCtx, zInput, zNew, bQuote); ++ } ++ if( rc!=SQLITE_OK ){ ++ if( sParse.zErrMsg ){ ++ renameColumnParseError(context, 0, argv[1], argv[2], &sParse); ++ }else{ ++ sqlite3_result_error_code(context, rc); ++ } ++ } ++ ++ renameParseCleanup(&sParse); ++ renameTokenFree(db, sCtx.pList); ++ sqlite3BtreeLeaveAll(db); ++#ifndef SQLITE_OMIT_AUTHORIZATION ++ db->xAuth = xAuth; ++#endif ++ } ++ ++ return; ++} ++ ++/* ++** An SQL user function that checks that there are no parse or symbol ++** resolution problems in a CREATE TRIGGER|TABLE|VIEW|INDEX statement. ++** After an ALTER TABLE .. RENAME operation is performed and the schema ++** reloaded, this function is called on each SQL statement in the schema ++** to ensure that it is still usable. ++** ++** 0: Database name ("main", "temp" etc.). ++** 1: SQL statement. ++** 2: Object type ("view", "table", "trigger" or "index"). ++** 3: Object name. ++** 4: True if object is from temp schema. ++** ++** Unless it finds an error, this function normally returns NULL. However, it ++** returns integer value 1 if: ++** ++** * the SQL argument creates a trigger, and ++** * the table that the trigger is attached to is in database zDb. ++*/ ++static void renameTableTest( ++ sqlite3_context *context, ++ int NotUsed, ++ sqlite3_value **argv ++){ ++ sqlite3 *db = sqlite3_context_db_handle(context); ++ char const *zDb = (const char*)sqlite3_value_text(argv[0]); ++ char const *zInput = (const char*)sqlite3_value_text(argv[1]); ++ int bTemp = sqlite3_value_int(argv[4]); ++ int isLegacy = (db->flags & SQLITE_LegacyAlter); ++ ++#ifndef SQLITE_OMIT_AUTHORIZATION ++ sqlite3_xauth xAuth = db->xAuth; ++ db->xAuth = 0; ++#endif ++ ++ UNUSED_PARAMETER(NotUsed); ++ if( zDb && zInput ){ ++ int rc; ++ Parse sParse; ++ rc = renameParseSql(&sParse, zDb, 1, db, zInput, bTemp); ++ if( rc==SQLITE_OK ){ ++ if( isLegacy==0 && sParse.pNewTable && sParse.pNewTable->pSelect ){ ++ NameContext sNC; ++ memset(&sNC, 0, sizeof(sNC)); ++ sNC.pParse = &sParse; ++ sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, &sNC); ++ if( sParse.nErr ) rc = sParse.rc; ++ } ++ ++ else if( sParse.pNewTrigger ){ ++ if( isLegacy==0 ){ ++ rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb); ++ } ++ if( rc==SQLITE_OK ){ ++ int i1 = sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema); ++ int i2 = sqlite3FindDbName(db, zDb); ++ if( i1==i2 ) sqlite3_result_int(context, 1); ++ } ++ } ++ } ++ ++ if( rc!=SQLITE_OK ){ ++ renameColumnParseError(context, 1, argv[2], argv[3], &sParse); ++ } ++ renameParseCleanup(&sParse); ++ } ++ ++#ifndef SQLITE_OMIT_AUTHORIZATION ++ db->xAuth = xAuth; ++#endif ++} ++ ++/* ++** Register built-in functions used to help implement ALTER TABLE ++*/ ++SQLITE_PRIVATE void sqlite3AlterFunctions(void){ ++ static FuncDef aAlterTableFuncs[] = { ++ INTERNAL_FUNCTION(sqlite_rename_column, 9, renameColumnFunc), ++ INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc), ++ INTERNAL_FUNCTION(sqlite_rename_test, 5, renameTableTest), ++ }; ++ sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs)); ++} + #endif /* SQLITE_ALTER_TABLE */ + + /************** End of alter.c ***********************************************/ +@@ -100824,6 +103564,7 @@ + 0, /* pNext */ + statInit, /* xSFunc */ + 0, /* xFinalize */ ++ 0, 0, /* xValue, xInverse */ + "stat_init", /* zName */ + {0} + }; +@@ -101140,6 +103881,7 @@ + 0, /* pNext */ + statPush, /* xSFunc */ + 0, /* xFinalize */ ++ 0, 0, /* xValue, xInverse */ + "stat_push", /* zName */ + {0} + }; +@@ -101291,6 +104033,7 @@ + 0, /* pNext */ + statGet, /* xSFunc */ + 0, /* xFinalize */ ++ 0, 0, /* xValue, xInverse */ + "stat_get", /* zName */ + {0} + }; +@@ -101610,10 +104353,7 @@ + callStatGet(v, regStat4, STAT_GET_NLT, regLt); + callStatGet(v, regStat4, STAT_GET_NDLT, regDLt); + sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0); +- /* We know that the regSampleRowid row exists because it was read by +- ** the previous loop. Thus the not-found jump of seekOp will never +- ** be taken */ +- VdbeCoverageNeverTaken(v); ++ VdbeCoverage(v); + #ifdef SQLITE_ENABLE_STAT3 + sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iTabCur, 0, regSample); + #else +@@ -102253,7 +104993,7 @@ + + /* Load the statistics from the sqlite_stat4 table. */ + #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +- if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){ ++ if( rc==SQLITE_OK ){ + db->lookaside.bDisable++; + rc = loadStat4(db, sInfo.zDatabase); + db->lookaside.bDisable--; +@@ -102378,7 +105118,7 @@ + if( pNew->pBt ) sqlite3BtreeClose(pNew->pBt); + pNew->pBt = 0; + pNew->pSchema = 0; +- rc = sqlite3BtreeOpen(pVfs, "x", db, &pNew->pBt, 0, SQLITE_OPEN_MAIN_DB); ++ rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNew->pBt, 0, SQLITE_OPEN_MAIN_DB); + }else{ + /* This is a real ATTACH + ** +@@ -102436,7 +105176,7 @@ + sqlite3_free( zPath ); + db->nDb++; + } +- db->skipBtreeMutex = 0; ++ db->noSharedCache = 0; + if( rc==SQLITE_CONSTRAINT ){ + rc = SQLITE_ERROR; + zErrDyn = sqlite3MPrintf(db, "database is already attached"); +@@ -102508,6 +105248,7 @@ + if( rc==SQLITE_OK ){ + sqlite3BtreeEnterAll(db); + db->init.iDb = 0; ++ db->mDbFlags &= ~(DBFLAG_SchemaKnownOk); + rc = sqlite3Init(db, &zErrDyn); + sqlite3BtreeLeaveAll(db); + assert( zErrDyn==0 || rc!=SQLITE_OK ); +@@ -102691,6 +105432,7 @@ + 0, /* pNext */ + detachFunc, /* xSFunc */ + 0, /* xFinalize */ ++ 0, 0, /* xValue, xInverse */ + "sqlite_detach", /* zName */ + {0} + }; +@@ -102710,6 +105452,7 @@ + 0, /* pNext */ + attachFunc, /* xSFunc */ + 0, /* xFinalize */ ++ 0, 0, /* xValue, xInverse */ + "sqlite_attach", /* zName */ + {0} + }; +@@ -102780,6 +105523,9 @@ + if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1; + if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1; + #endif ++ if( pItem->fg.isTabFunc && sqlite3FixExprList(pFix, pItem->u1.pFuncArg) ){ ++ return 1; ++ } + } + return 0; + } +@@ -102879,6 +105625,18 @@ + if( sqlite3FixExprList(pFix, pStep->pExprList) ){ + return 1; + } ++#ifndef SQLITE_OMIT_UPSERT ++ if( pStep->pUpsert ){ ++ Upsert *pUp = pStep->pUpsert; ++ if( sqlite3FixExprList(pFix, pUp->pUpsertTarget) ++ || sqlite3FixExpr(pFix, pUp->pUpsertTargetWhere) ++ || sqlite3FixExprList(pFix, pUp->pUpsertSet) ++ || sqlite3FixExpr(pFix, pUp->pUpsertWhere) ++ ){ ++ return 1; ++ } ++ } ++#endif + pStep = pStep->pNext; + } + return 0; +@@ -102967,7 +105725,7 @@ + sqlite3_mutex_enter(db->mutex); + db->xAuth = (sqlite3_xauth)xAuth; + db->pAuthArg = pArg; +- sqlite3ExpirePreparedStatements(db); ++ sqlite3ExpirePreparedStatements(db, 0); + sqlite3_mutex_leave(db->mutex); + return SQLITE_OK; + } +@@ -103039,6 +105797,8 @@ + int iDb; /* The index of the database the expression refers to */ + int iCol; /* Index of column in table */ + ++ assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER ); ++ assert( !IN_RENAME_OBJECT || db->xAuth==0 ); + if( db->xAuth==0 ) return; + iDb = sqlite3SchemaToIndex(pParse->db, pSchema); + if( iDb<0 ){ +@@ -103047,7 +105807,6 @@ + return; + } + +- assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER ); + if( pExpr->op==TK_TRIGGER ){ + pTab = pParse->pTriggerTab; + }else{ +@@ -103096,7 +105855,8 @@ + /* Don't do any authorization checks if the database is initialising + ** or if the parser is being invoked from within sqlite3_declare_vtab. + */ +- if( db->init.busy || IN_DECLARE_VTAB ){ ++ assert( !IN_RENAME_OBJECT || db->xAuth==0 ); ++ if( db->init.busy || IN_SPECIAL_PARSE ){ + return SQLITE_OK; + } + +@@ -103388,7 +106148,6 @@ + /* Get the VDBE program ready for execution + */ + if( v && pParse->nErr==0 && !db->mallocFailed ){ +- assert( pParse->iCacheLevel==0 ); /* Disables and re-enables match */ + /* A minimum of one cursor is required if autoincrement is used + * See ticket [a696379c1f08866] */ + if( pParse->pAinc!=0 && pParse->nTab==0 ) pParse->nTab = 1; +@@ -103506,29 +106265,30 @@ + const char *zDbase /* Name of the database. Might be NULL */ + ){ + Table *p; ++ sqlite3 *db = pParse->db; + + /* Read the database schema. If an error occurs, leave an error message + ** and code in pParse and return NULL. */ +- if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ ++ if( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 ++ && SQLITE_OK!=sqlite3ReadSchema(pParse) ++ ){ + return 0; + } + +- p = sqlite3FindTable(pParse->db, zName, zDbase); ++ p = sqlite3FindTable(db, zName, zDbase); + if( p==0 ){ + const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table"; + #ifndef SQLITE_OMIT_VIRTUALTABLE +- if( sqlite3FindDbName(pParse->db, zDbase)<1 ){ +- /* If zName is the not the name of a table in the schema created using +- ** CREATE, then check to see if it is the name of an virtual table that +- ** can be an eponymous virtual table. */ +- Module *pMod = (Module*)sqlite3HashFind(&pParse->db->aModule, zName); +- if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){ +- pMod = sqlite3PragmaVtabRegister(pParse->db, zName); +- } +- if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){ +- return pMod->pEpoTab; +- } ++ /* If zName is the not the name of a table in the schema created using ++ ** CREATE, then check to see if it is the name of an virtual table that ++ ** can be an eponymous virtual table. */ ++ Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName); ++ if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){ ++ pMod = sqlite3PragmaVtabRegister(db, zName); + } ++ if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){ ++ return pMod->pEpoTab; ++ } + #endif + if( (flags & LOCATE_NOERR)==0 ){ + if( zDbase ){ +@@ -103600,7 +106360,7 @@ + /* + ** Reclaim the memory used by an index + */ +-static void freeIndex(sqlite3 *db, Index *p){ ++SQLITE_PRIVATE void sqlite3FreeIndex(sqlite3 *db, Index *p){ + #ifndef SQLITE_OMIT_ANALYZE + sqlite3DeleteIndexSamples(db, p); + #endif +@@ -103640,7 +106400,7 @@ + p->pNext = pIndex->pNext; + } + } +- freeIndex(db, pIndex); ++ sqlite3FreeIndex(db, pIndex); + } + db->mDbFlags |= DBFLAG_SchemaChange; + } +@@ -103688,6 +106448,7 @@ + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); + DbSetProperty(db, iDb, DB_ResetWanted); + DbSetProperty(db, 1, DB_ResetWanted); ++ db->mDbFlags &= ~DBFLAG_SchemaKnownOk; + } + + if( db->nSchemaLock==0 ){ +@@ -103706,17 +106467,22 @@ + SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){ + int i; + sqlite3BtreeEnterAll(db); +- assert( db->nSchemaLock==0 ); + for(i=0; i<db->nDb; i++){ + Db *pDb = &db->aDb[i]; + if( pDb->pSchema ){ +- sqlite3SchemaClear(pDb->pSchema); ++ if( db->nSchemaLock==0 ){ ++ sqlite3SchemaClear(pDb->pSchema); ++ }else{ ++ DbSetProperty(db, i, DB_ResetWanted); ++ } + } + } +- db->mDbFlags &= ~DBFLAG_SchemaChange; ++ db->mDbFlags &= ~(DBFLAG_SchemaChange|DBFLAG_SchemaKnownOk); + sqlite3VtabUnlockList(db); + sqlite3BtreeLeaveAll(db); +- sqlite3CollapseDatabaseArray(db); ++ if( db->nSchemaLock==0 ){ ++ sqlite3CollapseDatabaseArray(db); ++ } + } + + /* +@@ -103785,7 +106551,7 @@ + assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); + assert( pOld==pIndex || pOld==0 ); + } +- freeIndex(db, pIndex); ++ sqlite3FreeIndex(db, pIndex); + } + + /* Delete any foreign keys attached to this table. */ +@@ -103793,6 +106559,12 @@ + + /* Delete the Table structure itself. + */ ++#ifdef SQLITE_ENABLE_NORMALIZE ++ if( pTable->pColHash ){ ++ sqlite3HashClear(pTable->pColHash); ++ sqlite3_free(pTable->pColHash); ++ } ++#endif + sqlite3DeleteColumnNames(db, pTable); + sqlite3DbFree(db, pTable->zName); + sqlite3DbFree(db, pTable->zColAff); +@@ -103943,7 +106715,7 @@ + return -1; + } + }else{ +- assert( db->init.iDb==0 || db->init.busy ++ assert( db->init.iDb==0 || db->init.busy || IN_RENAME_OBJECT + || (db->mDbFlags & DBFLAG_Vacuum)!=0); + iDb = db->init.iDb; + *pUnqual = pName1; +@@ -103952,6 +106724,20 @@ + } + + /* ++** True if PRAGMA writable_schema is ON ++*/ ++SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3 *db){ ++ testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==0 ); ++ testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))== ++ SQLITE_WriteSchema ); ++ testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))== ++ SQLITE_Defensive ); ++ testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))== ++ (SQLITE_WriteSchema|SQLITE_Defensive) ); ++ return (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==SQLITE_WriteSchema; ++} ++ ++/* + ** This routine is used to check if the UTF-8 string zName is a legal + ** unqualified name for a new schema object (table, index, view or + ** trigger). All names are legal except those that begin with the string +@@ -103960,7 +106746,7 @@ + */ + SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *pParse, const char *zName){ + if( !pParse->db->init.busy && pParse->nested==0 +- && (pParse->db->flags & SQLITE_WriteSchema)==0 ++ && sqlite3WritableSchema(pParse->db)==0 + && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ + sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName); + return SQLITE_ERROR; +@@ -104038,6 +106824,9 @@ + } + if( !OMIT_TEMPDB && isTemp ) iDb = 1; + zName = sqlite3NameFromToken(db, pName); ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameTokenMap(pParse, (void*)zName, pName); ++ } + } + pParse->sNameToken = *pName; + if( zName==0 ) return; +@@ -104073,7 +106862,7 @@ + ** and types will be used, so there is no need to test for namespace + ** collisions. + */ +- if( !IN_DECLARE_VTAB ){ ++ if( !IN_SPECIAL_PARSE ){ + char *zDb = db->aDb[iDb].zDbSName; + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ + goto begin_table_error; +@@ -104232,6 +107021,7 @@ + } + z = sqlite3DbMallocRaw(db, pName->n + pType->n + 2); + if( z==0 ) return; ++ if( IN_RENAME_OBJECT ) sqlite3RenameTokenMap(pParse, (void*)z, pName); + memcpy(z, pName->z, pName->n); + z[pName->n] = 0; + sqlite3Dequote(z); +@@ -104258,15 +107048,20 @@ + + if( pType->n==0 ){ + /* If there is no type specified, columns have the default affinity +- ** 'BLOB'. */ ++ ** 'BLOB' with a default size of 4 bytes. */ + pCol->affinity = SQLITE_AFF_BLOB; + pCol->szEst = 1; ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ if( 4>=sqlite3GlobalConfig.szSorterRef ){ ++ pCol->colFlags |= COLFLAG_SORTERREF; ++ } ++#endif + }else{ + zType = z + sqlite3Strlen30(z) + 1; + memcpy(zType, pType->z, pType->n); + zType[pType->n] = 0; + sqlite3Dequote(zType); +- pCol->affinity = sqlite3AffinityType(zType, &pCol->szEst); ++ pCol->affinity = sqlite3AffinityType(zType, pCol); + pCol->colFlags |= COLFLAG_HASTYPE; + } + p->nCol++; +@@ -104326,7 +107121,7 @@ + ** If none of the substrings in the above table are found, + ** SQLITE_AFF_NUMERIC is returned. + */ +-SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn, u8 *pszEst){ ++SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn, Column *pCol){ + u32 h = 0; + char aff = SQLITE_AFF_NUMERIC; + const char *zChar = 0; +@@ -104363,27 +107158,32 @@ + } + } + +- /* If pszEst is not NULL, store an estimate of the field size. The ++ /* If pCol is not NULL, store an estimate of the field size. The + ** estimate is scaled so that the size of an integer is 1. */ +- if( pszEst ){ +- *pszEst = 1; /* default size is approx 4 bytes */ ++ if( pCol ){ ++ int v = 0; /* default size is approx 4 bytes */ + if( aff<SQLITE_AFF_NUMERIC ){ + if( zChar ){ + while( zChar[0] ){ + if( sqlite3Isdigit(zChar[0]) ){ +- int v = 0; ++ /* BLOB(k), VARCHAR(k), CHAR(k) -> r=(k/4+1) */ + sqlite3GetInt32(zChar, &v); +- v = v/4 + 1; +- if( v>255 ) v = 255; +- *pszEst = v; /* BLOB(k), VARCHAR(k), CHAR(k) -> r=(k/4+1) */ + break; + } + zChar++; + } + }else{ +- *pszEst = 5; /* BLOB, TEXT, CLOB -> r=5 (approx 20 bytes)*/ ++ v = 16; /* BLOB, TEXT, CLOB -> r=5 (approx 20 bytes)*/ + } + } ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ if( v>=sqlite3GlobalConfig.szSorterRef ){ ++ pCol->colFlags |= COLFLAG_SORTERREF; ++ } ++#endif ++ v = v/4 + 1; ++ if( v>255 ) v = 255; ++ pCol->szEst = v; + } + return aff; + } +@@ -104428,6 +107228,9 @@ + sqlite3DbFree(db, x.u.zToken); + } + } ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameExprUnmap(pParse, pExpr); ++ } + sqlite3ExprDelete(db, pExpr); + } + +@@ -104519,6 +107322,9 @@ + && sqlite3StrICmp(sqlite3ColumnType(pCol,""), "INTEGER")==0 + && sortOrder!=SQLITE_SO_DESC + ){ ++ if( IN_RENAME_OBJECT && pList ){ ++ sqlite3RenameTokenRemap(pParse, &pTab->iPKey, pList->a[0].pExpr); ++ } + pTab->iPKey = iCol; + pTab->keyConf = (u8)onError; + assert( autoInc==0 || autoInc==1 ); +@@ -104844,6 +107650,31 @@ + return 0; + } + ++/* Recompute the colNotIdxed field of the Index. ++** ++** colNotIdxed is a bitmask that has a 0 bit representing each indexed ++** columns that are within the first 63 columns of the table. The ++** high-order bit of colNotIdxed is always 1. All unindexed columns ++** of the table have a 1. ++** ++** The colNotIdxed mask is AND-ed with the SrcList.a[].colUsed mask ++** to determine if the index is covering index. ++*/ ++static void recomputeColumnsNotIndexed(Index *pIdx){ ++ Bitmask m = 0; ++ int j; ++ for(j=pIdx->nColumn-1; j>=0; j--){ ++ int x = pIdx->aiColumn[j]; ++ if( x>=0 ){ ++ testcase( x==BMS-1 ); ++ testcase( x==BMS-2 ); ++ if( x<BMS-1 ) m |= MASKBIT(x); ++ } ++ } ++ pIdx->colNotIdxed = ~m; ++ assert( (pIdx->colNotIdxed>>63)==1 ); ++} ++ + /* + ** This routine runs at the end of parsing a CREATE TABLE statement that + ** has a WITHOUT ROWID clause. The job of this routine is to convert both +@@ -104886,10 +107717,6 @@ + } + } + +- /* The remaining transformations only apply to b-tree tables, not to +- ** virtual tables */ +- if( IN_DECLARE_VTAB ) return; +- + /* Convert the P3 operand of the OP_CreateBtree opcode from BTREE_INTKEY + ** into BTREE_BLOBKEY. + */ +@@ -104912,7 +107739,7 @@ + assert( pParse->pNewTable==pTab ); + sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0, + SQLITE_IDXTYPE_PRIMARYKEY); +- if( db->mallocFailed ) return; ++ if( db->mallocFailed || pParse->nErr ) return; + pPk = sqlite3PrimaryKeyIndex(pTab); + pTab->iPKey = -1; + }else{ +@@ -104992,9 +107819,40 @@ + }else{ + pPk->nColumn = pTab->nCol; + } ++ recomputeColumnsNotIndexed(pPk); + } + ++#ifndef SQLITE_OMIT_VIRTUALTABLE + /* ++** Return true if zName is a shadow table name in the current database ++** connection. ++** ++** zName is temporarily modified while this routine is running, but is ++** restored to its original value prior to this routine returning. ++*/ ++static int isShadowTableName(sqlite3 *db, char *zName){ ++ char *zTail; /* Pointer to the last "_" in zName */ ++ Table *pTab; /* Table that zName is a shadow of */ ++ Module *pMod; /* Module for the virtual table */ ++ ++ zTail = strrchr(zName, '_'); ++ if( zTail==0 ) return 0; ++ *zTail = 0; ++ pTab = sqlite3FindTable(db, zName, 0); ++ *zTail = '_'; ++ if( pTab==0 ) return 0; ++ if( !IsVirtual(pTab) ) return 0; ++ pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]); ++ if( pMod==0 ) return 0; ++ if( pMod->pModule->iVersion<3 ) return 0; ++ if( pMod->pModule->xShadowName==0 ) return 0; ++ return pMod->pModule->xShadowName(zTail+1); ++} ++#else ++# define isShadowTableName(x,y) 0 ++#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ ++ ++/* + ** This routine is called to report the final ")" that terminates + ** a CREATE TABLE statement. + ** +@@ -105033,6 +107891,10 @@ + p = pParse->pNewTable; + if( p==0 ) return; + ++ if( pSelect==0 && isShadowTableName(db, p->zName) ){ ++ p->tabFlags |= TF_Shadow; ++ } ++ + /* If the db->init.busy is 1 it means we are reading the SQL off the + ** "sqlite_master" or "sqlite_temp_master" table on the disk. + ** So do not write to the disk again. Extract the root page number +@@ -105295,7 +108157,12 @@ + ** allocated rather than point to the input string - which means that + ** they will persist after the current sqlite3_exec() call returns. + */ +- p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); ++ if( IN_RENAME_OBJECT ){ ++ p->pSelect = pSelect; ++ pSelect = 0; ++ }else{ ++ p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); ++ } + p->pCheck = sqlite3ExprListDup(db, pCNames, EXPRDUP_REDUCE); + if( db->mallocFailed ) goto create_view_fail; + +@@ -105320,6 +108187,9 @@ + + create_view_fail: + sqlite3SelectDelete(db, pSelect); ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameExprlistUnmap(pParse, pCNames); ++ } + sqlite3ExprListDelete(db, pCNames); + return; + } +@@ -105393,6 +108263,10 @@ + assert( pTable->pSelect ); + pSel = sqlite3SelectDup(db, pTable->pSelect, 0); + if( pSel ){ ++#ifndef SQLITE_OMIT_ALTERTABLE ++ u8 eParseMode = pParse->eParseMode; ++ pParse->eParseMode = PARSE_MODE_NORMAL; ++#endif + n = pParse->nTab; + sqlite3SrcListAssignCursors(pParse, pSel->pSrc); + pTable->nCol = -1; +@@ -105438,10 +108312,18 @@ + sqlite3DeleteTable(db, pSelTab); + sqlite3SelectDelete(db, pSel); + db->lookaside.bDisable--; ++#ifndef SQLITE_OMIT_ALTERTABLE ++ pParse->eParseMode = eParseMode; ++#endif + } else { + nErr++; + } + pTable->pSchema->schemaFlags |= DB_UnresetViews; ++ if( db->mallocFailed ){ ++ sqlite3DeleteColumnNames(db, pTable); ++ pTable->aCol = 0; ++ pTable->nCol = 0; ++ } + #endif /* SQLITE_OMIT_VIEW */ + return nErr; + } +@@ -105520,7 +108402,7 @@ + static void destroyRootPage(Parse *pParse, int iTable, int iDb){ + Vdbe *v = sqlite3GetVdbe(pParse); + int r1 = sqlite3GetTempReg(pParse); +- assert( iTable>1 ); ++ if( iTable<2 ) sqlite3ErrorMsg(pParse, "corrupt schema"); + sqlite3VdbeAddOp3(v, OP_Destroy, iTable, r1, iDb); + sqlite3MayAbort(pParse); + #ifndef SQLITE_OMIT_AUTOVACUUM +@@ -105780,8 +108662,10 @@ + v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3BeginWriteOperation(pParse, 1, iDb); +- sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName); +- sqlite3FkDropTable(pParse, pName, pTab); ++ if( !isView ){ ++ sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName); ++ sqlite3FkDropTable(pParse, pName, pTab); ++ } + sqlite3CodeDropTable(pParse, pTab, iDb, isView); + } + +@@ -105856,6 +108740,9 @@ + pFKey->pNextFrom = p->pFKey; + z = (char*)&pFKey->aCol[nCol]; + pFKey->zTo = z; ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameTokenMap(pParse, (void*)z, pTo); ++ } + memcpy(z, pTo->z, pTo->n); + z[pTo->n] = 0; + sqlite3Dequote(z); +@@ -105878,6 +108765,9 @@ + pFromCol->a[i].zName); + goto fk_end; + } ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameTokenRemap(pParse, &pFKey->aCol[i], pFromCol->a[i].zName); ++ } + } + } + if( pToCol ){ +@@ -105884,6 +108774,9 @@ + for(i=0; i<nCol; i++){ + int n = sqlite3Strlen30(pToCol->a[i].zName); + pFKey->aCol[i].zCol = z; ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameTokenRemap(pParse, z, pToCol->a[i].zName); ++ } + memcpy(z, pToCol->a[i].zName, n); + z[n] = 0; + z += n+1; +@@ -105992,6 +108885,7 @@ + sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); + addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); VdbeCoverage(v); + regRecord = sqlite3GetTempReg(pParse); ++ sqlite3MultiWrite(pParse); + + sqlite3GenerateIndexKey(pParse,pIndex,iTab,regRecord,0,&iPartIdxLabel,0,0); + sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord); +@@ -106005,12 +108899,13 @@ + + addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v); + if( IsUniqueIndex(pIndex) ){ +- int j2 = sqlite3VdbeCurrentAddr(v) + 3; +- sqlite3VdbeGoto(v, j2); ++ int j2 = sqlite3VdbeGoto(v, 1); + addr2 = sqlite3VdbeCurrentAddr(v); ++ sqlite3VdbeVerifyAbortable(v, OE_Abort); + sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord, + pIndex->nKeyCol); VdbeCoverage(v); + sqlite3UniqueConstraint(pParse, OE_Abort, pIndex); ++ sqlite3VdbeJumpHere(v, j2); + }else{ + addr2 = sqlite3VdbeCurrentAddr(v); + } +@@ -106173,7 +109068,11 @@ + #if SQLITE_USER_AUTHENTICATION + && sqlite3UserAuthTable(pTab->zName)==0 + #endif +- && sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0 ){ ++#ifdef SQLITE_ALLOW_SQLITE_MASTER_INDEX ++ && sqlite3StrICmp(&pTab->zName[7],"master")!=0 ++#endif ++ && sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0 ++ ){ + sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName); + goto exit_create_index; + } +@@ -106210,21 +109109,23 @@ + if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ + goto exit_create_index; + } +- if( !db->init.busy ){ +- if( sqlite3FindTable(db, zName, 0)!=0 ){ +- sqlite3ErrorMsg(pParse, "there is already a table named %s", zName); ++ if( !IN_RENAME_OBJECT ){ ++ if( !db->init.busy ){ ++ if( sqlite3FindTable(db, zName, 0)!=0 ){ ++ sqlite3ErrorMsg(pParse, "there is already a table named %s", zName); ++ goto exit_create_index; ++ } ++ } ++ if( sqlite3FindIndex(db, zName, pDb->zDbSName)!=0 ){ ++ if( !ifNotExist ){ ++ sqlite3ErrorMsg(pParse, "index %s already exists", zName); ++ }else{ ++ assert( !db->init.busy ); ++ sqlite3CodeVerifySchema(pParse, iDb); ++ } + goto exit_create_index; + } + } +- if( sqlite3FindIndex(db, zName, pDb->zDbSName)!=0 ){ +- if( !ifNotExist ){ +- sqlite3ErrorMsg(pParse, "index %s already exists", zName); +- }else{ +- assert( !db->init.busy ); +- sqlite3CodeVerifySchema(pParse, iDb); +- } +- goto exit_create_index; +- } + }else{ + int n; + Index *pLoop; +@@ -106239,13 +109140,13 @@ + ** The following statement converts "sqlite3_autoindex..." into + ** "sqlite3_butoindex..." in order to make the names distinct. + ** The "vtab_err.test" test demonstrates the need of this statement. */ +- if( IN_DECLARE_VTAB ) zName[7]++; ++ if( IN_SPECIAL_PARSE ) zName[7]++; + } + + /* Check for authorization to create an index. + */ + #ifndef SQLITE_OMIT_AUTHORIZATION +- { ++ if( !IN_RENAME_OBJECT ){ + const char *zDb = pDb->zDbSName; + if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iDb), 0, zDb) ){ + goto exit_create_index; +@@ -106332,7 +109233,12 @@ + ** TODO: Issue a warning if the table primary key is used as part of the + ** index key. + */ +- for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){ ++ pListItem = pList->a; ++ if( IN_RENAME_OBJECT ){ ++ pIndex->aColExpr = pList; ++ pList = 0; ++ } ++ for(i=0; i<pIndex->nKeyCol; i++, pListItem++){ + Expr *pCExpr; /* The i-th index expression */ + int requestedSortOrder; /* ASC or DESC on the i-th expression */ + const char *zColl; /* Collation sequence name */ +@@ -106348,12 +109254,8 @@ + goto exit_create_index; + } + if( pIndex->aColExpr==0 ){ +- ExprList *pCopy = sqlite3ExprListDup(db, pList, 0); +- pIndex->aColExpr = pCopy; +- if( !db->mallocFailed ){ +- assert( pCopy!=0 ); +- pListItem = &pCopy->a[i]; +- } ++ pIndex->aColExpr = pList; ++ pList = 0; + } + j = XN_EXPR; + pIndex->aiColumn[i] = XN_EXPR; +@@ -106419,6 +109321,7 @@ + ** it as a covering index */ + assert( HasRowid(pTab) + || pTab->iPKey<0 || sqlite3ColumnOfIndex(pIndex, pTab->iPKey)>=0 ); ++ recomputeColumnsNotIndexed(pIndex); + if( pTblName!=0 && pIndex->nColumn>=pTab->nCol ){ + pIndex->isCovering = 1; + for(j=0; j<pTab->nCol; j++){ +@@ -106491,98 +109394,101 @@ + } + } + +- /* Link the new Index structure to its table and to the other +- ** in-memory database structures. +- */ +- assert( pParse->nErr==0 ); +- if( db->init.busy ){ +- Index *p; +- assert( !IN_DECLARE_VTAB ); +- assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); +- p = sqlite3HashInsert(&pIndex->pSchema->idxHash, +- pIndex->zName, pIndex); +- if( p ){ +- assert( p==pIndex ); /* Malloc must have failed */ +- sqlite3OomFault(db); +- goto exit_create_index; ++ if( !IN_RENAME_OBJECT ){ ++ ++ /* Link the new Index structure to its table and to the other ++ ** in-memory database structures. ++ */ ++ assert( pParse->nErr==0 ); ++ if( db->init.busy ){ ++ Index *p; ++ assert( !IN_SPECIAL_PARSE ); ++ assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); ++ p = sqlite3HashInsert(&pIndex->pSchema->idxHash, ++ pIndex->zName, pIndex); ++ if( p ){ ++ assert( p==pIndex ); /* Malloc must have failed */ ++ sqlite3OomFault(db); ++ goto exit_create_index; ++ } ++ db->mDbFlags |= DBFLAG_SchemaChange; ++ if( pTblName!=0 ){ ++ pIndex->tnum = db->init.newTnum; ++ } + } +- db->mDbFlags |= DBFLAG_SchemaChange; +- if( pTblName!=0 ){ +- pIndex->tnum = db->init.newTnum; +- } +- } + +- /* If this is the initial CREATE INDEX statement (or CREATE TABLE if the +- ** index is an implied index for a UNIQUE or PRIMARY KEY constraint) then +- ** emit code to allocate the index rootpage on disk and make an entry for +- ** the index in the sqlite_master table and populate the index with +- ** content. But, do not do this if we are simply reading the sqlite_master +- ** table to parse the schema, or if this index is the PRIMARY KEY index +- ** of a WITHOUT ROWID table. +- ** +- ** If pTblName==0 it means this index is generated as an implied PRIMARY KEY +- ** or UNIQUE index in a CREATE TABLE statement. Since the table +- ** has just been created, it contains no data and the index initialization +- ** step can be skipped. +- */ +- else if( HasRowid(pTab) || pTblName!=0 ){ +- Vdbe *v; +- char *zStmt; +- int iMem = ++pParse->nMem; ++ /* If this is the initial CREATE INDEX statement (or CREATE TABLE if the ++ ** index is an implied index for a UNIQUE or PRIMARY KEY constraint) then ++ ** emit code to allocate the index rootpage on disk and make an entry for ++ ** the index in the sqlite_master table and populate the index with ++ ** content. But, do not do this if we are simply reading the sqlite_master ++ ** table to parse the schema, or if this index is the PRIMARY KEY index ++ ** of a WITHOUT ROWID table. ++ ** ++ ** If pTblName==0 it means this index is generated as an implied PRIMARY KEY ++ ** or UNIQUE index in a CREATE TABLE statement. Since the table ++ ** has just been created, it contains no data and the index initialization ++ ** step can be skipped. ++ */ ++ else if( HasRowid(pTab) || pTblName!=0 ){ ++ Vdbe *v; ++ char *zStmt; ++ int iMem = ++pParse->nMem; + +- v = sqlite3GetVdbe(pParse); +- if( v==0 ) goto exit_create_index; ++ v = sqlite3GetVdbe(pParse); ++ if( v==0 ) goto exit_create_index; + +- sqlite3BeginWriteOperation(pParse, 1, iDb); ++ sqlite3BeginWriteOperation(pParse, 1, iDb); + +- /* Create the rootpage for the index using CreateIndex. But before +- ** doing so, code a Noop instruction and store its address in +- ** Index.tnum. This is required in case this index is actually a +- ** PRIMARY KEY and the table is actually a WITHOUT ROWID table. In +- ** that case the convertToWithoutRowidTable() routine will replace +- ** the Noop with a Goto to jump over the VDBE code generated below. */ +- pIndex->tnum = sqlite3VdbeAddOp0(v, OP_Noop); +- sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, iMem, BTREE_BLOBKEY); ++ /* Create the rootpage for the index using CreateIndex. But before ++ ** doing so, code a Noop instruction and store its address in ++ ** Index.tnum. This is required in case this index is actually a ++ ** PRIMARY KEY and the table is actually a WITHOUT ROWID table. In ++ ** that case the convertToWithoutRowidTable() routine will replace ++ ** the Noop with a Goto to jump over the VDBE code generated below. */ ++ pIndex->tnum = sqlite3VdbeAddOp0(v, OP_Noop); ++ sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, iMem, BTREE_BLOBKEY); + +- /* Gather the complete text of the CREATE INDEX statement into +- ** the zStmt variable +- */ +- if( pStart ){ +- int n = (int)(pParse->sLastToken.z - pName->z) + pParse->sLastToken.n; +- if( pName->z[n-1]==';' ) n--; +- /* A named index with an explicit CREATE INDEX statement */ +- zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s", +- onError==OE_None ? "" : " UNIQUE", n, pName->z); +- }else{ +- /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */ +- /* zStmt = sqlite3MPrintf(""); */ +- zStmt = 0; +- } ++ /* Gather the complete text of the CREATE INDEX statement into ++ ** the zStmt variable ++ */ ++ if( pStart ){ ++ int n = (int)(pParse->sLastToken.z - pName->z) + pParse->sLastToken.n; ++ if( pName->z[n-1]==';' ) n--; ++ /* A named index with an explicit CREATE INDEX statement */ ++ zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s", ++ onError==OE_None ? "" : " UNIQUE", n, pName->z); ++ }else{ ++ /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */ ++ /* zStmt = sqlite3MPrintf(""); */ ++ zStmt = 0; ++ } + +- /* Add an entry in sqlite_master for this index +- */ +- sqlite3NestedParse(pParse, +- "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);", +- db->aDb[iDb].zDbSName, MASTER_NAME, +- pIndex->zName, +- pTab->zName, +- iMem, +- zStmt +- ); +- sqlite3DbFree(db, zStmt); ++ /* Add an entry in sqlite_master for this index ++ */ ++ sqlite3NestedParse(pParse, ++ "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);", ++ db->aDb[iDb].zDbSName, MASTER_NAME, ++ pIndex->zName, ++ pTab->zName, ++ iMem, ++ zStmt ++ ); ++ sqlite3DbFree(db, zStmt); + +- /* Fill the index with data and reparse the schema. Code an OP_Expire +- ** to invalidate all pre-compiled statements. +- */ +- if( pTblName ){ +- sqlite3RefillIndex(pParse, pIndex, iMem); +- sqlite3ChangeCookie(pParse, iDb); +- sqlite3VdbeAddParseSchemaOp(v, iDb, +- sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName)); +- sqlite3VdbeAddOp0(v, OP_Expire); ++ /* Fill the index with data and reparse the schema. Code an OP_Expire ++ ** to invalidate all pre-compiled statements. ++ */ ++ if( pTblName ){ ++ sqlite3RefillIndex(pParse, pIndex, iMem); ++ sqlite3ChangeCookie(pParse, iDb); ++ sqlite3VdbeAddParseSchemaOp(v, iDb, ++ sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName)); ++ sqlite3VdbeAddOp2(v, OP_Expire, 0, 1); ++ } ++ ++ sqlite3VdbeJumpHere(v, pIndex->tnum); + } +- +- sqlite3VdbeJumpHere(v, pIndex->tnum); + } + + /* When adding an index to the list of indices for a table, make +@@ -106606,10 +109512,15 @@ + } + pIndex = 0; + } ++ else if( IN_RENAME_OBJECT ){ ++ assert( pParse->pNewIndex==0 ); ++ pParse->pNewIndex = pIndex; ++ pIndex = 0; ++ } + + /* Clean up before exiting */ + exit_create_index: +- if( pIndex ) freeIndex(db, pIndex); ++ if( pIndex ) sqlite3FreeIndex(db, pIndex); + sqlite3ExprDelete(db, pPIWhere); + sqlite3ExprListDelete(db, pList); + sqlite3SrcListDelete(db, pTblName); +@@ -106778,7 +109689,8 @@ + ** + ** A new IdList is returned, or NULL if malloc() fails. + */ +-SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3 *db, IdList *pList, Token *pToken){ ++SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token *pToken){ ++ sqlite3 *db = pParse->db; + int i; + if( pList==0 ){ + pList = sqlite3DbMallocZero(db, sizeof(IdList) ); +@@ -106796,6 +109708,9 @@ + return 0; + } + pList->a[i].zName = sqlite3NameFromToken(db, pToken); ++ if( IN_RENAME_OBJECT && pList->a[i].zName ){ ++ sqlite3RenameTokenMap(pParse, (void*)pList->a[i].zName, pToken); ++ } + return pList; + } + +@@ -107042,6 +109957,12 @@ + } + assert( p->nSrc>0 ); + pItem = &p->a[p->nSrc-1]; ++ assert( (pTable==0)==(pDatabase==0) ); ++ assert( pItem->zName==0 || pDatabase!=0 ); ++ if( IN_RENAME_OBJECT && pItem->zName ){ ++ Token *pToken = (ALWAYS(pDatabase) && pDatabase->z) ? pDatabase : pTable; ++ sqlite3RenameTokenMap(pParse, pItem->zName, pToken); ++ } + assert( pAlias!=0 ); + if( pAlias->n ){ + pItem->zAlias = sqlite3NameFromToken(db, pAlias); +@@ -107352,16 +110273,16 @@ + + sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, 200); + if( pIdx->aColExpr ){ +- sqlite3XPrintf(&errMsg, "index '%q'", pIdx->zName); ++ sqlite3_str_appendf(&errMsg, "index '%q'", pIdx->zName); + }else{ + for(j=0; j<pIdx->nKeyCol; j++){ + char *zCol; + assert( pIdx->aiColumn[j]>=0 ); + zCol = pTab->aCol[pIdx->aiColumn[j]].zName; +- if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2); +- sqlite3StrAccumAppendAll(&errMsg, pTab->zName); +- sqlite3StrAccumAppend(&errMsg, ".", 1); +- sqlite3StrAccumAppendAll(&errMsg, zCol); ++ if( j ) sqlite3_str_append(&errMsg, ", ", 2); ++ sqlite3_str_appendall(&errMsg, pTab->zName); ++ sqlite3_str_append(&errMsg, ".", 1); ++ sqlite3_str_appendall(&errMsg, zCol); + } + } + zErr = sqlite3StrAccumFinish(&errMsg); +@@ -107936,6 +110857,21 @@ + } + return 0; + } ++#ifdef SQLITE_ENABLE_NORMALIZE ++SQLITE_PRIVATE FuncDef *sqlite3FunctionSearchN( ++ int h, /* Hash of the name */ ++ const char *zFunc, /* Name of function */ ++ int nFunc /* Length of the name */ ++){ ++ FuncDef *p; ++ for(p=sqlite3BuiltinFunctions.a[h]; p; p=p->u.pHash){ ++ if( sqlite3StrNICmp(p->zName, zFunc, nFunc)==0 ){ ++ return p; ++ } ++ } ++ return 0; ++} ++#endif /* SQLITE_ENABLE_NORMALIZE */ + + /* + ** Insert a new FuncDef into a FuncDefHash hash table. +@@ -107949,7 +110885,7 @@ + FuncDef *pOther; + const char *zName = aDef[i].zName; + int nName = sqlite3Strlen30(zName); +- int h = (zName[0] + nName) % SQLITE_FUNC_HASH_SZ; ++ int h = SQLITE_FUNC_HASH(zName[0], nName); + assert( zName[0]>='a' && zName[0]<='z' ); + pOther = functionSearch(h, zName); + if( pOther ){ +@@ -108028,7 +110964,7 @@ + */ + if( !createFlag && (pBest==0 || (db->mDbFlags & DBFLAG_PreferBuiltin)!=0) ){ + bestScore = 0; +- h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % SQLITE_FUNC_HASH_SZ; ++ h = SQLITE_FUNC_HASH(sqlite3UpperToLower[(u8)zName[0]], nName); + p = functionSearch(h, zName); + while( p ){ + int score = matchQuality(p, nArg, enc); +@@ -108047,10 +110983,12 @@ + if( createFlag && bestScore<FUNC_PERFECT_MATCH && + (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){ + FuncDef *pOther; ++ u8 *z; + pBest->zName = (const char*)&pBest[1]; + pBest->nArg = (u16)nArg; + pBest->funcFlags = enc; + memcpy((char*)&pBest[1], zName, nName+1); ++ for(z=(u8*)pBest->zName; *z; z++) *z = sqlite3UpperToLower[*z]; + pOther = (FuncDef*)sqlite3HashInsert(&db->aFunc, pBest->zName, pBest); + if( pOther==pBest ){ + sqlite3DbFree(db, pBest); +@@ -108174,6 +111112,39 @@ + return pTab; + } + ++/* Return true if table pTab is read-only. ++** ++** A table is read-only if any of the following are true: ++** ++** 1) It is a virtual table and no implementation of the xUpdate method ++** has been provided ++** ++** 2) It is a system table (i.e. sqlite_master), this call is not ++** part of a nested parse and writable_schema pragma has not ++** been specified ++** ++** 3) The table is a shadow table, the database connection is in ++** defensive mode, and the current sqlite3_prepare() ++** is for a top-level SQL statement. ++*/ ++static int tabIsReadOnly(Parse *pParse, Table *pTab){ ++ sqlite3 *db; ++ if( IsVirtual(pTab) ){ ++ return sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0; ++ } ++ if( (pTab->tabFlags & (TF_Readonly|TF_Shadow))==0 ) return 0; ++ db = pParse->db; ++ if( (pTab->tabFlags & TF_Readonly)!=0 ){ ++ return sqlite3WritableSchema(db)==0 && pParse->nested==0; ++ } ++ assert( pTab->tabFlags & TF_Shadow ); ++ return (db->flags & SQLITE_Defensive)!=0 ++#ifndef SQLITE_OMIT_VIRTUALTABLE ++ && db->pVtabCtx==0 ++#endif ++ && db->nVdbeExec==0; ++} ++ + /* + ** Check to make sure the given table is writable. If it is not + ** writable, generate an error message and return 1. If it is +@@ -108180,26 +111151,10 @@ + ** writable return 0; + */ + SQLITE_PRIVATE int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){ +- /* A table is not writable under the following circumstances: +- ** +- ** 1) It is a virtual table and no implementation of the xUpdate method +- ** has been provided, or +- ** 2) It is a system table (i.e. sqlite_master), this call is not +- ** part of a nested parse and writable_schema pragma has not +- ** been specified. +- ** +- ** In either case leave an error message in pParse and return non-zero. +- */ +- if( ( IsVirtual(pTab) +- && sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 ) +- || ( (pTab->tabFlags & TF_Readonly)!=0 +- && (pParse->db->flags & SQLITE_WriteSchema)==0 +- && pParse->nested==0 ) +- ){ ++ if( tabIsReadOnly(pParse, pTab) ){ + sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName); + return 1; + } +- + #ifndef SQLITE_OMIT_VIEW + if( !viewOk && pTab->pSelect ){ + sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName); +@@ -108368,7 +111323,7 @@ + AuthContext sContext; /* Authorization context */ + NameContext sNC; /* Name context to resolve expressions in */ + int iDb; /* Database number */ +- int memCnt = -1; /* Memory cell used for change counting */ ++ int memCnt = 0; /* Memory cell used for change counting */ + int rcauth; /* Value returned by authorization callback */ + int eOnePass; /* ONEPASS_OFF or _SINGLE or _MULTI */ + int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */ +@@ -108473,7 +111428,7 @@ + goto delete_from_cleanup; + } + if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); +- sqlite3BeginWriteOperation(pParse, 1, iDb); ++ sqlite3BeginWriteOperation(pParse, bComplex, iDb); + + /* If we are trying to delete from a view, realize that view into + ** an ephemeral table. +@@ -108501,7 +111456,10 @@ + /* Initialize the counter of the number of rows deleted, if + ** we are counting rows. + */ +- if( db->flags & SQLITE_CountRows ){ ++ if( (db->flags & SQLITE_CountRows)!=0 ++ && !pParse->nested ++ && !pParse->pTriggerTab ++ ){ + memCnt = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt); + } +@@ -108529,7 +111487,7 @@ + assert( !isView ); + sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName); + if( HasRowid(pTab) ){ +- sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt, ++ sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt ? memCnt : -1, + pTab->zName, P4_STATIC); + } + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ +@@ -108574,9 +111532,10 @@ + eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); + assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI ); + assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF ); ++ if( eOnePass!=ONEPASS_SINGLE ) sqlite3MultiWrite(pParse); + + /* Keep track of the number of rows to be deleted */ +- if( db->flags & SQLITE_CountRows ){ ++ if( memCnt ){ + sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1); + } + +@@ -108589,9 +111548,8 @@ + } + iKey = iPk; + }else{ +- iKey = pParse->nMem + 1; +- iKey = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iTabCur, iKey, 0); +- if( iKey>pParse->nMem ) pParse->nMem = iKey; ++ iKey = ++pParse->nMem; ++ sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, -1, iKey); + } + + if( eOnePass!=ONEPASS_OFF ){ +@@ -108679,13 +111637,16 @@ + if( IsVirtual(pTab) ){ + const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); + sqlite3VtabMakeWritable(pParse, pTab); +- sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB); +- sqlite3VdbeChangeP5(v, OE_Abort); + assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE ); + sqlite3MayAbort(pParse); +- if( eOnePass==ONEPASS_SINGLE && sqlite3IsToplevel(pParse) ){ +- pParse->isMultiWrite = 0; ++ if( eOnePass==ONEPASS_SINGLE ){ ++ sqlite3VdbeAddOp1(v, OP_Close, iTabCur); ++ if( sqlite3IsToplevel(pParse) ){ ++ pParse->isMultiWrite = 0; ++ } + } ++ sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB); ++ sqlite3VdbeChangeP5(v, OE_Abort); + }else + #endif + { +@@ -108719,7 +111680,7 @@ + ** generating code because of a call to sqlite3NestedParse(), do not + ** invoke the callback function. + */ +- if( (db->flags&SQLITE_CountRows) && !pParse->nested && !pParse->pTriggerTab ){ ++ if( memCnt ){ + sqlite3VdbeAddOp2(v, OP_ResultRow, memCnt, 1); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC); +@@ -109021,7 +111982,6 @@ + if( pIdx->pPartIdxWhere ){ + *piPartIdxLabel = sqlite3VdbeMakeLabel(v); + pParse->iSelfTab = iDataCur + 1; +- sqlite3ExprCachePush(pParse); + sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel, + SQLITE_JUMPIFNULL); + pParse->iSelfTab = 0; +@@ -109068,7 +112028,6 @@ + SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse *pParse, int iLabel){ + if( iLabel ){ + sqlite3VdbeResolveLabel(pParse->pVdbe, iLabel); +- sqlite3ExprCachePop(pParse); + } + } + +@@ -109327,7 +112286,7 @@ + x.apArg = argv+1; + sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); + str.printfFlags = SQLITE_PRINTF_SQLFUNC; +- sqlite3XPrintf(&str, zFormat, &x); ++ sqlite3_str_appendf(&str, zFormat, &x); + n = str.nChar; + sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n, + SQLITE_DYNAMIC); +@@ -110581,7 +113540,7 @@ + i64 v = sqlite3_value_int64(argv[0]); + p->rSum += v; + if( (p->approx|p->overflow)==0 && sqlite3AddInt64(&p->iSum, v) ){ +- p->overflow = 1; ++ p->approx = p->overflow = 1; + } + }else{ + p->rSum += sqlite3_value_double(argv[0]); +@@ -110589,6 +113548,32 @@ + } + } + } ++#ifndef SQLITE_OMIT_WINDOWFUNC ++static void sumInverse(sqlite3_context *context, int argc, sqlite3_value**argv){ ++ SumCtx *p; ++ int type; ++ assert( argc==1 ); ++ UNUSED_PARAMETER(argc); ++ p = sqlite3_aggregate_context(context, sizeof(*p)); ++ type = sqlite3_value_numeric_type(argv[0]); ++ /* p is always non-NULL because sumStep() will have been called first ++ ** to initialize it */ ++ if( ALWAYS(p) && type!=SQLITE_NULL ){ ++ assert( p->cnt>0 ); ++ p->cnt--; ++ assert( type==SQLITE_INTEGER || p->approx ); ++ if( type==SQLITE_INTEGER && p->approx==0 ){ ++ i64 v = sqlite3_value_int64(argv[0]); ++ p->rSum -= v; ++ p->iSum -= v; ++ }else{ ++ p->rSum -= sqlite3_value_double(argv[0]); ++ } ++ } ++} ++#else ++# define sumInverse 0 ++#endif /* SQLITE_OMIT_WINDOWFUNC */ + static void sumFinalize(sqlite3_context *context){ + SumCtx *p; + p = sqlite3_aggregate_context(context, 0); +@@ -110623,6 +113608,9 @@ + typedef struct CountCtx CountCtx; + struct CountCtx { + i64 n; ++#ifdef SQLITE_DEBUG ++ int bInverse; /* True if xInverse() ever called */ ++#endif + }; + + /* +@@ -110640,7 +113628,7 @@ + ** sure it still operates correctly, verify that its count agrees with our + ** internal count when using count(*) and when the total count can be + ** expressed as a 32-bit integer. */ +- assert( argc==1 || p==0 || p->n>0x7fffffff ++ assert( argc==1 || p==0 || p->n>0x7fffffff || p->bInverse + || p->n==sqlite3_aggregate_count(context) ); + #endif + } +@@ -110649,6 +113637,21 @@ + p = sqlite3_aggregate_context(context, 0); + sqlite3_result_int64(context, p ? p->n : 0); + } ++#ifndef SQLITE_OMIT_WINDOWFUNC ++static void countInverse(sqlite3_context *ctx, int argc, sqlite3_value **argv){ ++ CountCtx *p; ++ p = sqlite3_aggregate_context(ctx, sizeof(*p)); ++ /* p is always non-NULL since countStep() will have been called first */ ++ if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0])) && ALWAYS(p) ){ ++ p->n--; ++#ifdef SQLITE_DEBUG ++ p->bInverse = 1; ++#endif ++ } ++} ++#else ++# define countInverse 0 ++#endif /* SQLITE_OMIT_WINDOWFUNC */ + + /* + ** Routines to implement min() and max() aggregate functions. +@@ -110665,7 +113668,7 @@ + pBest = (Mem *)sqlite3_aggregate_context(context, sizeof(*pBest)); + if( !pBest ) return; + +- if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ ++ if( sqlite3_value_type(pArg)==SQLITE_NULL ){ + if( pBest->flags ) sqlite3SkipAccumulatorLoad(context); + }else if( pBest->flags ){ + int max; +@@ -110691,7 +113694,7 @@ + sqlite3VdbeMemCopy(pBest, pArg); + } + } +-static void minMaxFinalize(sqlite3_context *context){ ++static void minMaxValueFinalize(sqlite3_context *context, int bValue){ + sqlite3_value *pRes; + pRes = (sqlite3_value *)sqlite3_aggregate_context(context, 0); + if( pRes ){ +@@ -110698,9 +113701,19 @@ + if( pRes->flags ){ + sqlite3_result_value(context, pRes); + } +- sqlite3VdbeMemRelease(pRes); ++ if( bValue==0 ) sqlite3VdbeMemRelease(pRes); + } + } ++#ifndef SQLITE_OMIT_WINDOWFUNC ++static void minMaxValue(sqlite3_context *context){ ++ minMaxValueFinalize(context, 1); ++} ++#else ++# define minMaxValue 0 ++#endif /* SQLITE_OMIT_WINDOWFUNC */ ++static void minMaxFinalize(sqlite3_context *context){ ++ minMaxValueFinalize(context, 0); ++} + + /* + ** group_concat(EXPR, ?SEPARATOR?) +@@ -110730,20 +113743,52 @@ + zSep = ","; + nSep = 1; + } +- if( zSep ) sqlite3StrAccumAppend(pAccum, zSep, nSep); ++ if( zSep ) sqlite3_str_append(pAccum, zSep, nSep); + } + zVal = (char*)sqlite3_value_text(argv[0]); + nVal = sqlite3_value_bytes(argv[0]); +- if( zVal ) sqlite3StrAccumAppend(pAccum, zVal, nVal); ++ if( zVal ) sqlite3_str_append(pAccum, zVal, nVal); + } + } ++#ifndef SQLITE_OMIT_WINDOWFUNC ++static void groupConcatInverse( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ int n; ++ StrAccum *pAccum; ++ assert( argc==1 || argc==2 ); ++ if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; ++ pAccum = (StrAccum*)sqlite3_aggregate_context(context, sizeof(*pAccum)); ++ /* pAccum is always non-NULL since groupConcatStep() will have always ++ ** run frist to initialize it */ ++ if( ALWAYS(pAccum) ){ ++ n = sqlite3_value_bytes(argv[0]); ++ if( argc==2 ){ ++ n += sqlite3_value_bytes(argv[1]); ++ }else{ ++ n++; ++ } ++ if( n>=(int)pAccum->nChar ){ ++ pAccum->nChar = 0; ++ }else{ ++ pAccum->nChar -= n; ++ memmove(pAccum->zText, &pAccum->zText[n], pAccum->nChar); ++ } ++ if( pAccum->nChar==0 ) pAccum->mxAlloc = 0; ++ } ++} ++#else ++# define groupConcatInverse 0 ++#endif /* SQLITE_OMIT_WINDOWFUNC */ + static void groupConcatFinalize(sqlite3_context *context){ + StrAccum *pAccum; + pAccum = sqlite3_aggregate_context(context, 0); + if( pAccum ){ +- if( pAccum->accError==STRACCUM_TOOBIG ){ ++ if( pAccum->accError==SQLITE_TOOBIG ){ + sqlite3_result_error_toobig(context); +- }else if( pAccum->accError==STRACCUM_NOMEM ){ ++ }else if( pAccum->accError==SQLITE_NOMEM ){ + sqlite3_result_error_nomem(context); + }else{ + sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1, +@@ -110751,6 +113796,24 @@ + } + } + } ++#ifndef SQLITE_OMIT_WINDOWFUNC ++static void groupConcatValue(sqlite3_context *context){ ++ sqlite3_str *pAccum; ++ pAccum = (sqlite3_str*)sqlite3_aggregate_context(context, 0); ++ if( pAccum ){ ++ if( pAccum->accError==SQLITE_TOOBIG ){ ++ sqlite3_result_error_toobig(context); ++ }else if( pAccum->accError==SQLITE_NOMEM ){ ++ sqlite3_result_error_nomem(context); ++ }else{ ++ const char *zText = sqlite3_str_value(pAccum); ++ sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT); ++ } ++ } ++} ++#else ++# define groupConcatValue 0 ++#endif /* SQLITE_OMIT_WINDOWFUNC */ + + /* + ** This routine does per-connection function registration. Most +@@ -110788,10 +113851,10 @@ + }else{ + pInfo = (struct compareInfo*)&likeInfoNorm; + } +- sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0); +- sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0); ++ sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0, 0, 0); ++ sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0, 0, 0); + sqlite3CreateFunc(db, "glob", 2, SQLITE_UTF8, +- (struct compareInfo*)&globInfo, likeFunc, 0, 0, 0); ++ (struct compareInfo*)&globInfo, likeFunc, 0, 0, 0, 0, 0); + setLikeOptFlag(db, "glob", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE); + setLikeOptFlag(db, "like", + caseSensitive ? (SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE) : SQLITE_FUNC_LIKE); +@@ -110900,11 +113963,11 @@ + FUNCTION(trim, 2, 3, 0, trimFunc ), + FUNCTION(min, -1, 0, 1, minmaxFunc ), + FUNCTION(min, 0, 0, 1, 0 ), +- AGGREGATE2(min, 1, 0, 1, minmaxStep, minMaxFinalize, ++ WAGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize, minMaxValue, 0, + SQLITE_FUNC_MINMAX ), + FUNCTION(max, -1, 1, 1, minmaxFunc ), + FUNCTION(max, 0, 1, 1, 0 ), +- AGGREGATE2(max, 1, 1, 1, minmaxStep, minMaxFinalize, ++ WAGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize, minMaxValue, 0, + SQLITE_FUNC_MINMAX ), + FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF), + FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH), +@@ -110935,14 +113998,17 @@ + FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ), + FUNCTION(substr, 2, 0, 0, substrFunc ), + FUNCTION(substr, 3, 0, 0, substrFunc ), +- AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ), +- AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ), +- AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ), +- AGGREGATE2(count, 0, 0, 0, countStep, countFinalize, +- SQLITE_FUNC_COUNT ), +- AGGREGATE(count, 1, 0, 0, countStep, countFinalize ), +- AGGREGATE(group_concat, 1, 0, 0, groupConcatStep, groupConcatFinalize), +- AGGREGATE(group_concat, 2, 0, 0, groupConcatStep, groupConcatFinalize), ++ WAGGREGATE(sum, 1,0,0, sumStep, sumFinalize, sumFinalize, sumInverse, 0), ++ WAGGREGATE(total, 1,0,0, sumStep,totalFinalize,totalFinalize,sumInverse, 0), ++ WAGGREGATE(avg, 1,0,0, sumStep, avgFinalize, avgFinalize, sumInverse, 0), ++ WAGGREGATE(count, 0,0,0, countStep, ++ countFinalize, countFinalize, countInverse, SQLITE_FUNC_COUNT ), ++ WAGGREGATE(count, 1,0,0, countStep, ++ countFinalize, countFinalize, countInverse, 0 ), ++ WAGGREGATE(group_concat, 1, 0, 0, groupConcatStep, ++ groupConcatFinalize, groupConcatValue, groupConcatInverse, 0), ++ WAGGREGATE(group_concat, 2, 0, 0, groupConcatStep, ++ groupConcatFinalize, groupConcatValue, groupConcatInverse, 0), + + LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), + #ifdef SQLITE_CASE_SENSITIVE_LIKE +@@ -110962,6 +114028,7 @@ + #ifndef SQLITE_OMIT_ALTERTABLE + sqlite3AlterFunctions(); + #endif ++ sqlite3WindowFunctions(); + #if defined(SQLITE_ENABLE_STAT3) || defined(SQLITE_ENABLE_STAT4) + sqlite3AnalyzeFunctions(); + #endif +@@ -111320,6 +114387,12 @@ + int iCur = pParse->nTab - 1; /* Cursor number to use */ + int iOk = sqlite3VdbeMakeLabel(v); /* jump here if parent key found */ + ++ sqlite3VdbeVerifyAbortable(v, ++ (!pFKey->isDeferred ++ && !(pParse->db->flags & SQLITE_DeferFKs) ++ && !pParse->pToplevel ++ && !pParse->isMultiWrite) ? OE_Abort : OE_Ignore); ++ + /* If nIncr is less than zero, then check at runtime if there are any + ** outstanding constraints to resolve. If there are not, there is no need + ** to check if deleting this row resolves any outstanding violations. +@@ -111485,7 +114558,7 @@ + ){ + Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0); + if( pExpr ){ +- pExpr->pTab = pTab; ++ pExpr->y.pTab = pTab; + pExpr->iTable = iCursor; + pExpr->iColumn = iCol; + } +@@ -111693,11 +114766,12 @@ + */ + SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){ + sqlite3 *db = pParse->db; +- if( (db->flags&SQLITE_ForeignKeys) && !IsVirtual(pTab) && !pTab->pSelect ){ ++ if( (db->flags&SQLITE_ForeignKeys) && !IsVirtual(pTab) ){ + int iSkip = 0; + Vdbe *v = sqlite3GetVdbe(pParse); + + assert( v ); /* VDBE has already been allocated */ ++ assert( pTab->pSelect==0 ); /* Not a view */ + if( sqlite3FkReferences(pTab)==0 ){ + /* Search for a deferred foreign key constraint for which this table + ** is the child table. If one cannot be found, return without +@@ -111727,6 +114801,7 @@ + ** constraints are violated. + */ + if( (db->flags & SQLITE_DeferFKs)==0 ){ ++ sqlite3VdbeVerifyAbortable(v, OE_Abort); + sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2); + VdbeCoverage(v); + sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, +@@ -112559,7 +115634,8 @@ + }while( i>=0 && zColAff[i]==SQLITE_AFF_BLOB ); + pTab->zColAff = zColAff; + } +- i = sqlite3Strlen30(zColAff); ++ assert( zColAff!=0 ); ++ i = sqlite3Strlen30NN(zColAff); + if( i ){ + if( iReg ){ + sqlite3VdbeAddOp4(v, OP_Affinity, iReg, i, 0, zColAff, i); +@@ -112639,12 +115715,27 @@ + Table *pTab /* The table we are writing to */ + ){ + int memId = 0; /* Register holding maximum rowid */ ++ assert( pParse->db->aDb[iDb].pSchema!=0 ); + if( (pTab->tabFlags & TF_Autoincrement)!=0 + && (pParse->db->mDbFlags & DBFLAG_Vacuum)==0 + ){ + Parse *pToplevel = sqlite3ParseToplevel(pParse); + AutoincInfo *pInfo; ++ Table *pSeqTab = pParse->db->aDb[iDb].pSchema->pSeqTab; + ++ /* Verify that the sqlite_sequence table exists and is an ordinary ++ ** rowid table with exactly two columns. ++ ** Ticket d8dc2b3a58cd5dc2918a1d4acb 2018-05-23 */ ++ if( pSeqTab==0 ++ || !HasRowid(pSeqTab) ++ || IsVirtual(pSeqTab) ++ || pSeqTab->nCol!=2 ++ ){ ++ pParse->nErr++; ++ pParse->rc = SQLITE_CORRUPT_SEQUENCE; ++ return 0; ++ } ++ + pInfo = pToplevel->pAinc; + while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; } + if( pInfo==0 ){ +@@ -112901,7 +115992,8 @@ + SrcList *pTabList, /* Name of table into which we are inserting */ + Select *pSelect, /* A SELECT statement to use as the data source */ + IdList *pColumn, /* Column names corresponding to IDLIST. */ +- int onError /* How to handle constraint errors */ ++ int onError, /* How to handle constraint errors */ ++ Upsert *pUpsert /* ON CONFLICT clauses for upsert, or NULL */ + ){ + sqlite3 *db; /* The main database structure */ + Table *pTab; /* The table to insert into. aka TABLE */ +@@ -113196,7 +116288,10 @@ + + /* Initialize the count of rows to be inserted + */ +- if( db->flags & SQLITE_CountRows ){ ++ if( (db->flags & SQLITE_CountRows)!=0 ++ && !pParse->nested ++ && !pParse->pTriggerTab ++ ){ + regRowCount = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); + } +@@ -113216,7 +116311,20 @@ + pParse->nMem += pIdx->nColumn; + } + } ++#ifndef SQLITE_OMIT_UPSERT ++ if( pUpsert ){ ++ pTabList->a[0].iCursor = iDataCur; ++ pUpsert->pUpsertSrc = pTabList; ++ pUpsert->regData = regData; ++ pUpsert->iDataCur = iDataCur; ++ pUpsert->iIdxCur = iIdxCur; ++ if( pUpsert->pUpsertTarget ){ ++ sqlite3UpsertAnalyzeTarget(pParse, pTabList, pUpsert); ++ } ++ } ++#endif + ++ + /* This is the top of the main insertion loop */ + if( useTempTable ){ + /* This block codes the top of loop only. The complete loop is the +@@ -113418,7 +116526,7 @@ + int isReplace; /* Set to true if constraints may cause a replace */ + int bUseSeek; /* True to use OPFLAG_SEEKRESULT */ + sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, +- regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0 ++ regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0, pUpsert + ); + sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0); + +@@ -113441,7 +116549,7 @@ + + /* Update the count of rows that are inserted + */ +- if( (db->flags & SQLITE_CountRows)!=0 ){ ++ if( regRowCount ){ + sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); + } + +@@ -113478,7 +116586,7 @@ + ** generating code because of a call to sqlite3NestedParse(), do not + ** invoke the callback function. + */ +- if( (db->flags&SQLITE_CountRows) && !pParse->nested && !pParse->pTriggerTab ){ ++ if( regRowCount ){ + sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC); +@@ -113487,6 +116595,7 @@ + insert_cleanup: + sqlite3SrcListDelete(db, pTabList); + sqlite3ExprListDelete(db, pList); ++ sqlite3UpsertDelete(db, pUpsert); + sqlite3SelectDelete(db, pSelect); + sqlite3IdListDelete(db, pColumn); + sqlite3DbFree(db, aRegIdx); +@@ -113506,14 +116615,15 @@ + #endif + + /* +-** Meanings of bits in of pWalker->eCode for checkConstraintUnchanged() ++** Meanings of bits in of pWalker->eCode for ++** sqlite3ExprReferencesUpdatedColumn() + */ + #define CKCNSTRNT_COLUMN 0x01 /* CHECK constraint uses a changing column */ + #define CKCNSTRNT_ROWID 0x02 /* CHECK constraint references the ROWID */ + +-/* This is the Walker callback from checkConstraintUnchanged(). Set +-** bit 0x01 of pWalker->eCode if +-** pWalker->eCode to 0 if this expression node references any of the ++/* This is the Walker callback from sqlite3ExprReferencesUpdatedColumn(). ++* Set bit 0x01 of pWalker->eCode if pWalker->eCode to 0 and if this ++** expression node references any of the + ** columns that are being modifed by an UPDATE statement. + */ + static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){ +@@ -113535,12 +116645,21 @@ + ** only columns that are modified by the UPDATE are those for which + ** aiChng[i]>=0, and also the ROWID is modified if chngRowid is true. + ** +-** Return true if CHECK constraint pExpr does not use any of the ++** Return true if CHECK constraint pExpr uses any of the + ** changing columns (or the rowid if it is changing). In other words, +-** return true if this CHECK constraint can be skipped when validating ++** return true if this CHECK constraint must be validated for + ** the new row in the UPDATE statement. ++** ++** 2018-09-15: pExpr might also be an expression for an index-on-expressions. ++** The operation of this routine is the same - return true if an only if ++** the expression uses one or more of columns identified by the second and ++** third arguments. + */ +-static int checkConstraintUnchanged(Expr *pExpr, int *aiChng, int chngRowid){ ++SQLITE_PRIVATE int sqlite3ExprReferencesUpdatedColumn( ++ Expr *pExpr, /* The expression to be checked */ ++ int *aiChng, /* aiChng[x]>=0 if column x changed by the UPDATE */ ++ int chngRowid /* True if UPDATE changes the rowid */ ++){ + Walker w; + memset(&w, 0, sizeof(w)); + w.eCode = 0; +@@ -113555,7 +116674,7 @@ + testcase( w.eCode==CKCNSTRNT_COLUMN ); + testcase( w.eCode==CKCNSTRNT_ROWID ); + testcase( w.eCode==(CKCNSTRNT_ROWID|CKCNSTRNT_COLUMN) ); +- return !w.eCode; ++ return w.eCode!=0; + } + + /* +@@ -113653,7 +116772,8 @@ + u8 overrideError, /* Override onError to this if not OE_Default */ + int ignoreDest, /* Jump to this label on an OE_Ignore resolution */ + int *pbMayReplace, /* OUT: Set to true if constraint may cause a replace */ +- int *aiChng /* column i is unchanged if aiChng[i]<0 */ ++ int *aiChng, /* column i is unchanged if aiChng[i]<0 */ ++ Upsert *pUpsert /* ON CONFLICT clauses, if any. NULL otherwise */ + ){ + Vdbe *v; /* VDBE under constrution */ + Index *pIdx; /* Pointer to one of the indices */ +@@ -113666,10 +116786,13 @@ + int addr1; /* Address of jump instruction */ + int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */ + int nPkField; /* Number of fields in PRIMARY KEY. 1 for ROWID tables */ +- int ipkTop = 0; /* Top of the rowid change constraint check */ +- int ipkBottom = 0; /* Bottom of the rowid change constraint check */ ++ Index *pUpIdx = 0; /* Index to which to apply the upsert */ + u8 isUpdate; /* True if this is an UPDATE operation */ + u8 bAffinityDone = 0; /* True if the OP_Affinity operation has been run */ ++ int upsertBypass = 0; /* Address of Goto to bypass upsert subroutine */ ++ int upsertJump = 0; /* Address of Goto that jumps into upsert subroutine */ ++ int ipkTop = 0; /* Top of the IPK uniqueness check */ ++ int ipkBottom = 0; /* OP_Goto at the end of the IPK uniqueness check */ + + isUpdate = regOldData!=0; + db = pParse->db; +@@ -113757,8 +116880,15 @@ + for(i=0; i<pCheck->nExpr; i++){ + int allOk; + Expr *pExpr = pCheck->a[i].pExpr; +- if( aiChng && checkConstraintUnchanged(pExpr, aiChng, pkChng) ) continue; ++ if( aiChng ++ && !sqlite3ExprReferencesUpdatedColumn(pExpr, aiChng, pkChng) ++ ){ ++ /* The check constraints do not reference any of the columns being ++ ** updated so there is no point it verifying the check constraint */ ++ continue; ++ } + allOk = sqlite3VdbeMakeLabel(v); ++ sqlite3VdbeVerifyAbortable(v, onError); + sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL); + if( onError==OE_Ignore ){ + sqlite3VdbeGoto(v, ignoreDest); +@@ -113776,6 +116906,50 @@ + } + #endif /* !defined(SQLITE_OMIT_CHECK) */ + ++ /* UNIQUE and PRIMARY KEY constraints should be handled in the following ++ ** order: ++ ** ++ ** (1) OE_Update ++ ** (2) OE_Abort, OE_Fail, OE_Rollback, OE_Ignore ++ ** (3) OE_Replace ++ ** ++ ** OE_Fail and OE_Ignore must happen before any changes are made. ++ ** OE_Update guarantees that only a single row will change, so it ++ ** must happen before OE_Replace. Technically, OE_Abort and OE_Rollback ++ ** could happen in any order, but they are grouped up front for ++ ** convenience. ++ ** ++ ** 2018-08-14: Ticket https://www.sqlite.org/src/info/908f001483982c43 ++ ** The order of constraints used to have OE_Update as (2) and OE_Abort ++ ** and so forth as (1). But apparently PostgreSQL checks the OE_Update ++ ** constraint before any others, so it had to be moved. ++ ** ++ ** Constraint checking code is generated in this order: ++ ** (A) The rowid constraint ++ ** (B) Unique index constraints that do not have OE_Replace as their ++ ** default conflict resolution strategy ++ ** (C) Unique index that do use OE_Replace by default. ++ ** ++ ** The ordering of (2) and (3) is accomplished by making sure the linked ++ ** list of indexes attached to a table puts all OE_Replace indexes last ++ ** in the list. See sqlite3CreateIndex() for where that happens. ++ */ ++ ++ if( pUpsert ){ ++ if( pUpsert->pUpsertTarget==0 ){ ++ /* An ON CONFLICT DO NOTHING clause, without a constraint-target. ++ ** Make all unique constraint resolution be OE_Ignore */ ++ assert( pUpsert->pUpsertSet==0 ); ++ overrideError = OE_Ignore; ++ pUpsert = 0; ++ }else if( (pUpIdx = pUpsert->pUpsertIdx)!=0 ){ ++ /* If the constraint-target uniqueness check must be run first. ++ ** Jump to that uniqueness check now */ ++ upsertJump = sqlite3VdbeAddOp0(v, OP_Goto); ++ VdbeComment((v, "UPSERT constraint goes first")); ++ } ++ } ++ + /* If rowid is changing, make sure the new rowid does not previously + ** exist in the table. + */ +@@ -113790,6 +116964,28 @@ + onError = OE_Abort; + } + ++ /* figure out whether or not upsert applies in this case */ ++ if( pUpsert && pUpsert->pUpsertIdx==0 ){ ++ if( pUpsert->pUpsertSet==0 ){ ++ onError = OE_Ignore; /* DO NOTHING is the same as INSERT OR IGNORE */ ++ }else{ ++ onError = OE_Update; /* DO UPDATE */ ++ } ++ } ++ ++ /* If the response to a rowid conflict is REPLACE but the response ++ ** to some other UNIQUE constraint is FAIL or IGNORE, then we need ++ ** to defer the running of the rowid conflict checking until after ++ ** the UNIQUE constraints have run. ++ */ ++ if( onError==OE_Replace /* IPK rule is REPLACE */ ++ && onError!=overrideError /* Rules for other contraints are different */ ++ && pTab->pIndex /* There exist other constraints */ ++ ){ ++ ipkTop = sqlite3VdbeAddOp0(v, OP_Goto)+1; ++ VdbeComment((v, "defer IPK REPLACE until last")); ++ } ++ + if( isUpdate ){ + /* pkChng!=0 does not mean that the rowid has changed, only that + ** it might have changed. Skip the conflict logic below if the rowid +@@ -113799,26 +116995,13 @@ + VdbeCoverage(v); + } + +- /* If the response to a rowid conflict is REPLACE but the response +- ** to some other UNIQUE constraint is FAIL or IGNORE, then we need +- ** to defer the running of the rowid conflict checking until after +- ** the UNIQUE constraints have run. +- */ +- if( onError==OE_Replace && overrideError!=OE_Replace ){ +- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ +- if( pIdx->onError==OE_Ignore || pIdx->onError==OE_Fail ){ +- ipkTop = sqlite3VdbeAddOp0(v, OP_Goto); +- break; +- } +- } +- } +- + /* Check to see if the new rowid already exists in the table. Skip + ** the following conflict logic if it does not. */ ++ VdbeNoopComment((v, "uniqueness check for ROWID")); ++ sqlite3VdbeVerifyAbortable(v, onError); + sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData); + VdbeCoverage(v); + +- /* Generate code that deals with a rowid collision */ + switch( onError ){ + default: { + onError = OE_Abort; +@@ -113827,6 +117010,9 @@ + case OE_Rollback: + case OE_Abort: + case OE_Fail: { ++ testcase( onError==OE_Rollback ); ++ testcase( onError==OE_Abort ); ++ testcase( onError==OE_Fail ); + sqlite3RowidConstraint(pParse, onError, pTab); + break; + } +@@ -113863,14 +117049,13 @@ + regNewData, 1, 0, OE_Replace, 1, -1); + }else{ + #ifdef SQLITE_ENABLE_PREUPDATE_HOOK +- if( HasRowid(pTab) ){ +- /* This OP_Delete opcode fires the pre-update-hook only. It does +- ** not modify the b-tree. It is more efficient to let the coming +- ** OP_Insert replace the existing entry than it is to delete the +- ** existing entry and then insert a new one. */ +- sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, OPFLAG_ISNOOP); +- sqlite3VdbeAppendP4(v, pTab, P4_TABLE); +- } ++ assert( HasRowid(pTab) ); ++ /* This OP_Delete opcode fires the pre-update-hook only. It does ++ ** not modify the b-tree. It is more efficient to let the coming ++ ** OP_Insert replace the existing entry than it is to delete the ++ ** existing entry and then insert a new one. */ ++ sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, OPFLAG_ISNOOP); ++ sqlite3VdbeAppendP4(v, pTab, P4_TABLE); + #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ + if( pTab->pIndex ){ + sqlite3MultiWrite(pParse); +@@ -113880,8 +117065,14 @@ + seenReplace = 1; + break; + } ++#ifndef SQLITE_OMIT_UPSERT ++ case OE_Update: { ++ sqlite3UpsertDoUpdate(pParse, pUpsert, pTab, 0, iDataCur); ++ /* Fall through */ ++ } ++#endif + case OE_Ignore: { +- /*assert( seenReplace==0 );*/ ++ testcase( onError==OE_Ignore ); + sqlite3VdbeGoto(v, ignoreDest); + break; + } +@@ -113889,7 +117080,7 @@ + sqlite3VdbeResolveLabel(v, addrRowidOk); + if( ipkTop ){ + ipkBottom = sqlite3VdbeAddOp0(v, OP_Goto); +- sqlite3VdbeJumpHere(v, ipkTop); ++ sqlite3VdbeJumpHere(v, ipkTop-1); + } + } + +@@ -113907,13 +117098,22 @@ + int addrUniqueOk; /* Jump here if the UNIQUE constraint is satisfied */ + + if( aRegIdx[ix]==0 ) continue; /* Skip indices that do not change */ +- if( bAffinityDone==0 ){ ++ if( pUpIdx==pIdx ){ ++ addrUniqueOk = upsertJump+1; ++ upsertBypass = sqlite3VdbeGoto(v, 0); ++ VdbeComment((v, "Skip upsert subroutine")); ++ sqlite3VdbeJumpHere(v, upsertJump); ++ }else{ ++ addrUniqueOk = sqlite3VdbeMakeLabel(v); ++ } ++ if( bAffinityDone==0 && (pUpIdx==0 || pUpIdx==pIdx) ){ + sqlite3TableAffinity(v, pTab, regNewData+1); + bAffinityDone = 1; + } ++ VdbeNoopComment((v, "uniqueness check for %s", pIdx->zName)); + iThisCur = iIdxCur+ix; +- addrUniqueOk = sqlite3VdbeMakeLabel(v); + ++ + /* Skip partial indices for which the WHERE clause is not true */ + if( pIdx->pPartIdxWhere ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[ix]); +@@ -113972,6 +117172,15 @@ + onError = OE_Abort; + } + ++ /* Figure out if the upsert clause applies to this index */ ++ if( pUpIdx==pIdx ){ ++ if( pUpsert->pUpsertSet==0 ){ ++ onError = OE_Ignore; /* DO NOTHING is the same as INSERT OR IGNORE */ ++ }else{ ++ onError = OE_Update; /* DO UPDATE */ ++ } ++ } ++ + /* Collision detection may be omitted if all of the following are true: + ** (1) The conflict resolution algorithm is REPLACE + ** (2) The table is a WITHOUT ROWID table +@@ -113992,7 +117201,7 @@ + } + + /* Check to see if the new index entry will be unique */ +- sqlite3ExprCachePush(pParse); ++ sqlite3VdbeVerifyAbortable(v, onError); + sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk, + regIdx, pIdx->nKeyCol); VdbeCoverage(v); + +@@ -114054,15 +117263,25 @@ + + /* Generate code that executes if the new index entry is not unique */ + assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail +- || onError==OE_Ignore || onError==OE_Replace ); ++ || onError==OE_Ignore || onError==OE_Replace || onError==OE_Update ); + switch( onError ){ + case OE_Rollback: + case OE_Abort: + case OE_Fail: { ++ testcase( onError==OE_Rollback ); ++ testcase( onError==OE_Abort ); ++ testcase( onError==OE_Fail ); + sqlite3UniqueConstraint(pParse, onError, pIdx); + break; + } ++#ifndef SQLITE_OMIT_UPSERT ++ case OE_Update: { ++ sqlite3UpsertDoUpdate(pParse, pUpsert, pTab, pIdx, iIdxCur+ix); ++ /* Fall through */ ++ } ++#endif + case OE_Ignore: { ++ testcase( onError==OE_Ignore ); + sqlite3VdbeGoto(v, ignoreDest); + break; + } +@@ -114069,10 +117288,12 @@ + default: { + Trigger *pTrigger = 0; + assert( onError==OE_Replace ); +- sqlite3MultiWrite(pParse); + if( db->flags&SQLITE_RecTriggers ){ + pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); + } ++ if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){ ++ sqlite3MultiWrite(pParse); ++ } + sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, + regR, nPkField, 0, OE_Replace, + (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur); +@@ -114080,15 +117301,22 @@ + break; + } + } +- sqlite3VdbeResolveLabel(v, addrUniqueOk); +- sqlite3ExprCachePop(pParse); ++ if( pUpIdx==pIdx ){ ++ sqlite3VdbeGoto(v, upsertJump+1); ++ sqlite3VdbeJumpHere(v, upsertBypass); ++ }else{ ++ sqlite3VdbeResolveLabel(v, addrUniqueOk); ++ } + if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField); + } ++ ++ /* If the IPK constraint is a REPLACE, run it last */ + if( ipkTop ){ + sqlite3VdbeGoto(v, ipkTop+1); ++ VdbeComment((v, "Do IPK REPLACE")); + sqlite3VdbeJumpHere(v, ipkBottom); + } +- ++ + *pbMayReplace = seenReplace; + VdbeModuleComment((v, "END: GenCnstCks(%d)", seenReplace)); + } +@@ -114184,7 +117412,6 @@ + sqlite3SetMakeRecordP5(v, pTab); + if( !bAffinityDone ){ + sqlite3TableAffinity(v, pTab, 0); +- sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol); + } + if( pParse->nested ){ + pik_flags = 0; +@@ -114587,6 +117814,7 @@ + emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); + if( pDest->iPKey>=0 ){ + addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); ++ sqlite3VdbeVerifyAbortable(v, onError); + addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid); + VdbeCoverage(v); + sqlite3RowidConstraint(pParse, onError, pDest); +@@ -115144,6 +118372,30 @@ + int (*vtab_nochange)(sqlite3_context*); + int (*value_nochange)(sqlite3_value*); + const char *(*vtab_collation)(sqlite3_index_info*,int); ++ /* Version 3.24.0 and later */ ++ int (*keyword_count)(void); ++ int (*keyword_name)(int,const char**,int*); ++ int (*keyword_check)(const char*,int); ++ sqlite3_str *(*str_new)(sqlite3*); ++ char *(*str_finish)(sqlite3_str*); ++ void (*str_appendf)(sqlite3_str*, const char *zFormat, ...); ++ void (*str_vappendf)(sqlite3_str*, const char *zFormat, va_list); ++ void (*str_append)(sqlite3_str*, const char *zIn, int N); ++ void (*str_appendall)(sqlite3_str*, const char *zIn); ++ void (*str_appendchar)(sqlite3_str*, int N, char C); ++ void (*str_reset)(sqlite3_str*); ++ int (*str_errcode)(sqlite3_str*); ++ int (*str_length)(sqlite3_str*); ++ char *(*str_value)(sqlite3_str*); ++ /* Version 3.25.0 and later */ ++ int (*create_window_function)(sqlite3*,const char*,int,int,void*, ++ void (*xStep)(sqlite3_context*,int,sqlite3_value**), ++ void (*xFinal)(sqlite3_context*), ++ void (*xValue)(sqlite3_context*), ++ void (*xInv)(sqlite3_context*,int,sqlite3_value**), ++ void(*xDestroy)(void*)); ++ /* Version 3.26.0 and later */ ++ const char *(*normalized_sql)(sqlite3_stmt*); + }; + + /* +@@ -115414,6 +118666,25 @@ + #define sqlite3_vtab_nochange sqlite3_api->vtab_nochange + #define sqlite3_value_nochange sqlite3_api->value_nochange + #define sqlite3_vtab_collation sqlite3_api->vtab_collation ++/* Version 3.24.0 and later */ ++#define sqlite3_keyword_count sqlite3_api->keyword_count ++#define sqlite3_keyword_name sqlite3_api->keyword_name ++#define sqlite3_keyword_check sqlite3_api->keyword_check ++#define sqlite3_str_new sqlite3_api->str_new ++#define sqlite3_str_finish sqlite3_api->str_finish ++#define sqlite3_str_appendf sqlite3_api->str_appendf ++#define sqlite3_str_vappendf sqlite3_api->str_vappendf ++#define sqlite3_str_append sqlite3_api->str_append ++#define sqlite3_str_appendall sqlite3_api->str_appendall ++#define sqlite3_str_appendchar sqlite3_api->str_appendchar ++#define sqlite3_str_reset sqlite3_api->str_reset ++#define sqlite3_str_errcode sqlite3_api->str_errcode ++#define sqlite3_str_length sqlite3_api->str_length ++#define sqlite3_str_value sqlite3_api->str_value ++/* Version 3.25.0 and later */ ++#define sqlite3_create_window_function sqlite3_api->create_window_function ++/* Version 3.26.0 and later */ ++#define sqlite3_normalized_sql sqlite3_api->normalized_sql + #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ + + #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) +@@ -115502,6 +118773,7 @@ + # define sqlite3_declare_vtab 0 + # define sqlite3_vtab_config 0 + # define sqlite3_vtab_on_conflict 0 ++# define sqlite3_vtab_collation 0 + #endif + + #ifdef SQLITE_OMIT_SHARED_CACHE +@@ -115852,7 +119124,30 @@ + /* Version 3.22.0 and later */ + sqlite3_vtab_nochange, + sqlite3_value_nochange, +- sqlite3_vtab_collation ++ sqlite3_vtab_collation, ++ /* Version 3.24.0 and later */ ++ sqlite3_keyword_count, ++ sqlite3_keyword_name, ++ sqlite3_keyword_check, ++ sqlite3_str_new, ++ sqlite3_str_finish, ++ sqlite3_str_appendf, ++ sqlite3_str_vappendf, ++ sqlite3_str_append, ++ sqlite3_str_appendall, ++ sqlite3_str_appendchar, ++ sqlite3_str_reset, ++ sqlite3_str_errcode, ++ sqlite3_str_length, ++ sqlite3_str_value, ++ /* Version 3.25.0 and later */ ++ sqlite3_create_window_function, ++ /* Version 3.26.0 and later */ ++#ifdef SQLITE_ENABLE_NORMALIZE ++ sqlite3_normalized_sql ++#else ++ 0 ++#endif + }; + + /* +@@ -115918,10 +119213,8 @@ + #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]); +- int bExists = 0; + if( zAltFile==0 ) return SQLITE_NOMEM_BKPT; +- sqlite3OsAccess(pVfs, zAltFile, SQLITE_ACCESS_EXISTS, &bExists); +- if( bExists ) handle = sqlite3OsDlOpen(pVfs, zAltFile); ++ handle = sqlite3OsDlOpen(pVfs, zAltFile); + sqlite3_free(zAltFile); + } + #endif +@@ -116304,10 +119597,9 @@ + #define PragTyp_ACTIVATE_EXTENSIONS 40 + #define PragTyp_HEXKEY 41 + #define PragTyp_KEY 42 +-#define PragTyp_REKEY 43 +-#define PragTyp_LOCK_STATUS 44 +-#define PragTyp_PARSER_TRACE 45 +-#define PragTyp_STATS 46 ++#define PragTyp_LOCK_STATUS 43 ++#define PragTyp_PARSER_TRACE 44 ++#define PragTyp_STATS 45 + + /* Property flags associated with various pragma. */ + #define PragFlg_NeedSchema 0x01 /* Force schema load before running */ +@@ -116324,21 +119616,22 @@ + ** result column is different from the name of the pragma + */ + static const char *const pragCName[] = { +- /* 0 */ "cache_size", /* Used by: default_cache_size */ +- /* 1 */ "cid", /* Used by: table_info */ +- /* 2 */ "name", +- /* 3 */ "type", +- /* 4 */ "notnull", +- /* 5 */ "dflt_value", +- /* 6 */ "pk", +- /* 7 */ "tbl", /* Used by: stats */ +- /* 8 */ "idx", +- /* 9 */ "wdth", +- /* 10 */ "hght", +- /* 11 */ "flgs", +- /* 12 */ "seqno", /* Used by: index_info */ +- /* 13 */ "cid", +- /* 14 */ "name", ++ /* 0 */ "id", /* Used by: foreign_key_list */ ++ /* 1 */ "seq", ++ /* 2 */ "table", ++ /* 3 */ "from", ++ /* 4 */ "to", ++ /* 5 */ "on_update", ++ /* 6 */ "on_delete", ++ /* 7 */ "match", ++ /* 8 */ "cid", /* Used by: table_xinfo */ ++ /* 9 */ "name", ++ /* 10 */ "type", ++ /* 11 */ "notnull", ++ /* 12 */ "dflt_value", ++ /* 13 */ "pk", ++ /* 14 */ "hidden", ++ /* table_info reuses 8 */ + /* 15 */ "seqno", /* Used by: index_xinfo */ + /* 16 */ "cid", + /* 17 */ "name", +@@ -116345,37 +119638,35 @@ + /* 18 */ "desc", + /* 19 */ "coll", + /* 20 */ "key", +- /* 21 */ "seq", /* Used by: index_list */ +- /* 22 */ "name", +- /* 23 */ "unique", +- /* 24 */ "origin", +- /* 25 */ "partial", +- /* 26 */ "seq", /* Used by: database_list */ ++ /* 21 */ "tbl", /* Used by: stats */ ++ /* 22 */ "idx", ++ /* 23 */ "wdth", ++ /* 24 */ "hght", ++ /* 25 */ "flgs", ++ /* 26 */ "seq", /* Used by: index_list */ + /* 27 */ "name", +- /* 28 */ "file", +- /* 29 */ "name", /* Used by: function_list */ +- /* 30 */ "builtin", +- /* 31 */ "name", /* Used by: module_list pragma_list */ +- /* 32 */ "seq", /* Used by: collation_list */ +- /* 33 */ "name", +- /* 34 */ "id", /* Used by: foreign_key_list */ +- /* 35 */ "seq", +- /* 36 */ "table", +- /* 37 */ "from", +- /* 38 */ "to", +- /* 39 */ "on_update", +- /* 40 */ "on_delete", +- /* 41 */ "match", +- /* 42 */ "table", /* Used by: foreign_key_check */ +- /* 43 */ "rowid", +- /* 44 */ "parent", +- /* 45 */ "fkid", +- /* 46 */ "busy", /* Used by: wal_checkpoint */ +- /* 47 */ "log", +- /* 48 */ "checkpointed", +- /* 49 */ "timeout", /* Used by: busy_timeout */ +- /* 50 */ "database", /* Used by: lock_status */ +- /* 51 */ "status", ++ /* 28 */ "unique", ++ /* 29 */ "origin", ++ /* 30 */ "partial", ++ /* 31 */ "table", /* Used by: foreign_key_check */ ++ /* 32 */ "rowid", ++ /* 33 */ "parent", ++ /* 34 */ "fkid", ++ /* index_info reuses 15 */ ++ /* 35 */ "seq", /* Used by: database_list */ ++ /* 36 */ "name", ++ /* 37 */ "file", ++ /* 38 */ "busy", /* Used by: wal_checkpoint */ ++ /* 39 */ "log", ++ /* 40 */ "checkpointed", ++ /* 41 */ "name", /* Used by: function_list */ ++ /* 42 */ "builtin", ++ /* collation_list reuses 26 */ ++ /* 43 */ "database", /* Used by: lock_status */ ++ /* 44 */ "status", ++ /* 45 */ "cache_size", /* Used by: default_cache_size */ ++ /* module_list pragma_list reuses 9 */ ++ /* 46 */ "timeout", /* Used by: busy_timeout */ + }; + + /* Definitions of all built-in pragmas */ +@@ -116385,7 +119676,7 @@ + u8 mPragFlg; /* Zero or more PragFlg_XXX values */ + u8 iPragCName; /* Start of column names in pragCName[] */ + u8 nPragCName; /* Num of col names. 0 means use pragma name */ +- u32 iArg; /* Extra argument */ ++ u64 iArg; /* Extra argument */ + } PragmaName; + static const PragmaName aPragmaName[] = { + #if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) +@@ -116421,7 +119712,7 @@ + {/* zName: */ "busy_timeout", + /* ePragTyp: */ PragTyp_BUSY_TIMEOUT, + /* ePragFlg: */ PragFlg_Result0, +- /* ColNames: */ 49, 1, ++ /* ColNames: */ 46, 1, + /* iArg: */ 0 }, + #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) + {/* zName: */ "cache_size", +@@ -116458,7 +119749,7 @@ + {/* zName: */ "collation_list", + /* ePragTyp: */ PragTyp_COLLATION_LIST, + /* ePragFlg: */ PragFlg_Result0, +- /* ColNames: */ 32, 2, ++ /* ColNames: */ 26, 2, + /* iArg: */ 0 }, + #endif + #if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS) +@@ -116493,7 +119784,7 @@ + {/* zName: */ "database_list", + /* ePragTyp: */ PragTyp_DATABASE_LIST, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0, +- /* ColNames: */ 26, 3, ++ /* ColNames: */ 35, 3, + /* iArg: */ 0 }, + #endif + #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) +@@ -116500,7 +119791,7 @@ + {/* zName: */ "default_cache_size", + /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, +- /* ColNames: */ 0, 1, ++ /* ColNames: */ 45, 1, + /* iArg: */ 0 }, + #endif + #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) +@@ -116530,7 +119821,7 @@ + {/* zName: */ "foreign_key_check", + /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0, +- /* ColNames: */ 42, 4, ++ /* ColNames: */ 31, 4, + /* iArg: */ 0 }, + #endif + #if !defined(SQLITE_OMIT_FOREIGN_KEY) +@@ -116537,7 +119828,7 @@ + {/* zName: */ "foreign_key_list", + /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, +- /* ColNames: */ 34, 8, ++ /* ColNames: */ 0, 8, + /* iArg: */ 0 }, + #endif + #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) +@@ -116573,7 +119864,7 @@ + {/* zName: */ "function_list", + /* ePragTyp: */ PragTyp_FUNCTION_LIST, + /* ePragFlg: */ PragFlg_Result0, +- /* ColNames: */ 29, 2, ++ /* ColNames: */ 41, 2, + /* iArg: */ 0 }, + #endif + #endif +@@ -116582,12 +119873,12 @@ + /* ePragTyp: */ PragTyp_HEXKEY, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, +- /* iArg: */ 0 }, ++ /* iArg: */ 2 }, + {/* zName: */ "hexrekey", + /* ePragTyp: */ PragTyp_HEXKEY, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, +- /* iArg: */ 0 }, ++ /* iArg: */ 3 }, + #endif + #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + #if !defined(SQLITE_OMIT_CHECK) +@@ -116609,12 +119900,12 @@ + {/* zName: */ "index_info", + /* ePragTyp: */ PragTyp_INDEX_INFO, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, +- /* ColNames: */ 12, 3, ++ /* ColNames: */ 15, 3, + /* iArg: */ 0 }, + {/* zName: */ "index_list", + /* ePragTyp: */ PragTyp_INDEX_LIST, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, +- /* ColNames: */ 21, 5, ++ /* ColNames: */ 26, 5, + /* iArg: */ 0 }, + {/* zName: */ "index_xinfo", + /* ePragTyp: */ PragTyp_INDEX_INFO, +@@ -116649,6 +119940,11 @@ + /* iArg: */ 0 }, + #endif + #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) ++ {/* zName: */ "legacy_alter_table", ++ /* ePragTyp: */ PragTyp_FLAG, ++ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, ++ /* ColNames: */ 0, 0, ++ /* iArg: */ SQLITE_LegacyAlter }, + {/* zName: */ "legacy_file_format", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, +@@ -116666,7 +119962,7 @@ + {/* zName: */ "lock_status", + /* ePragTyp: */ PragTyp_LOCK_STATUS, + /* ePragFlg: */ PragFlg_Result0, +- /* ColNames: */ 50, 2, ++ /* ColNames: */ 43, 2, + /* iArg: */ 0 }, + #endif + #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) +@@ -116692,7 +119988,7 @@ + {/* zName: */ "module_list", + /* ePragTyp: */ PragTyp_MODULE_LIST, + /* ePragFlg: */ PragFlg_Result0, +- /* ColNames: */ 31, 1, ++ /* ColNames: */ 9, 1, + /* iArg: */ 0 }, + #endif + #endif +@@ -116725,7 +120021,7 @@ + {/* zName: */ "pragma_list", + /* ePragTyp: */ PragTyp_PRAGMA_LIST, + /* ePragFlg: */ PragFlg_Result0, +- /* ColNames: */ 31, 1, ++ /* ColNames: */ 9, 1, + /* iArg: */ 0 }, + #endif + #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) +@@ -116756,10 +120052,10 @@ + #endif + #if defined(SQLITE_HAS_CODEC) + {/* zName: */ "rekey", +- /* ePragTyp: */ PragTyp_REKEY, ++ /* ePragTyp: */ PragTyp_KEY, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, +- /* iArg: */ 0 }, ++ /* iArg: */ 1 }, + #endif + #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + {/* zName: */ "reverse_unordered_selects", +@@ -116812,7 +120108,7 @@ + {/* zName: */ "stats", + /* ePragTyp: */ PragTyp_STATS, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, +- /* ColNames: */ 7, 5, ++ /* ColNames: */ 21, 5, + /* iArg: */ 0 }, + #endif + #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) +@@ -116826,8 +120122,13 @@ + {/* zName: */ "table_info", + /* ePragTyp: */ PragTyp_TABLE_INFO, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, +- /* ColNames: */ 1, 6, ++ /* ColNames: */ 8, 6, + /* iArg: */ 0 }, ++ {/* zName: */ "table_xinfo", ++ /* ePragTyp: */ PragTyp_TABLE_INFO, ++ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, ++ /* ColNames: */ 8, 7, ++ /* iArg: */ 1 }, + #endif + #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) + {/* zName: */ "temp_store", +@@ -116841,6 +120142,18 @@ + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, + #endif ++#if defined(SQLITE_HAS_CODEC) ++ {/* zName: */ "textkey", ++ /* ePragTyp: */ PragTyp_KEY, ++ /* ePragFlg: */ 0, ++ /* ColNames: */ 0, 0, ++ /* iArg: */ 4 }, ++ {/* zName: */ "textrekey", ++ /* ePragTyp: */ PragTyp_KEY, ++ /* ePragFlg: */ 0, ++ /* ColNames: */ 0, 0, ++ /* iArg: */ 5 }, ++#endif + {/* zName: */ "threads", + /* ePragTyp: */ PragTyp_THREADS, + /* ePragFlg: */ PragFlg_Result0, +@@ -116891,7 +120204,7 @@ + {/* zName: */ "wal_checkpoint", + /* ePragTyp: */ PragTyp_WAL_CHECKPOINT, + /* ePragFlg: */ PragFlg_NeedSchema, +- /* ColNames: */ 46, 3, ++ /* ColNames: */ 38, 3, + /* iArg: */ 0 }, + #endif + #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) +@@ -116899,10 +120212,10 @@ + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, + /* ColNames: */ 0, 0, +- /* iArg: */ SQLITE_WriteSchema }, ++ /* iArg: */ SQLITE_WriteSchema|SQLITE_NoSchemaError }, + #endif + }; +-/* Number of pragmas: 60 on by default, 77 total. */ ++/* Number of pragmas: 62 on by default, 81 total. */ + + /************** End of pragma.h **********************************************/ + /************** Continuing where we left off in pragma.c *********************/ +@@ -117914,7 +121227,7 @@ + setPragmaResultColumnNames(v, pPragma); + returnSingleInt(v, (db->flags & pPragma->iArg)!=0 ); + }else{ +- int mask = pPragma->iArg; /* Mask of bits to set or clear. */ ++ u64 mask = pPragma->iArg; /* Mask of bits to set or clear. */ + if( db->autoCommit==0 ){ + /* Foreign key support may not be enabled or disabled while not + ** in auto-commit mode. */ +@@ -117963,15 +121276,17 @@ + Table *pTab; + pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb); + if( pTab ){ ++ int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); + int i, k; + int nHidden = 0; + Column *pCol; + Index *pPk = sqlite3PrimaryKeyIndex(pTab); +- pParse->nMem = 6; +- sqlite3CodeVerifySchema(pParse, iDb); ++ pParse->nMem = 7; ++ sqlite3CodeVerifySchema(pParse, iTabDb); + sqlite3ViewGetColumnNames(pParse, pTab); + for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){ +- if( IsHiddenColumn(pCol) ){ ++ int isHidden = IsHiddenColumn(pCol); ++ if( isHidden && pPragma->iArg==0 ){ + nHidden++; + continue; + } +@@ -117983,13 +121298,14 @@ + for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){} + } + assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN ); +- sqlite3VdbeMultiLoad(v, 1, "issisi", ++ sqlite3VdbeMultiLoad(v, 1, pPragma->iArg ? "issisii" : "issisi", + i-nHidden, + pCol->zName, + sqlite3ColumnType(pCol,""), + pCol->notNull ? 1 : 0, + pCol->pDflt ? pCol->pDflt->u.zToken : 0, +- k); ++ k, ++ isHidden); + } + } + } +@@ -118027,6 +121343,7 @@ + Table *pTab; + pIdx = sqlite3FindIndex(db, zRight, zDb); + if( pIdx ){ ++ int iIdxDb = sqlite3SchemaToIndex(db, pIdx->pSchema); + int i; + int mx; + if( pPragma->iArg ){ +@@ -118039,7 +121356,7 @@ + pParse->nMem = 3; + } + pTab = pIdx->pTable; +- sqlite3CodeVerifySchema(pParse, iDb); ++ sqlite3CodeVerifySchema(pParse, iIdxDb); + assert( pParse->nMem<=pPragma->nPragCName ); + for(i=0; i<mx; i++){ + i16 cnum = pIdx->aiColumn[i]; +@@ -118063,8 +121380,9 @@ + int i; + pTab = sqlite3FindTable(db, zRight, zDb); + if( pTab ){ ++ int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); + pParse->nMem = 5; +- sqlite3CodeVerifySchema(pParse, iDb); ++ sqlite3CodeVerifySchema(pParse, iTabDb); + for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){ + const char *azOrigin[] = { "c", "u", "pk" }; + sqlite3VdbeMultiLoad(v, 1, "isisi", +@@ -118111,6 +121429,7 @@ + pParse->nMem = 2; + for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){ + for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash ){ ++ if( p->funcFlags & SQLITE_FUNC_INTERNAL ) continue; + sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 1); + } + } +@@ -118152,9 +121471,10 @@ + if( pTab ){ + pFK = pTab->pFKey; + if( pFK ){ ++ int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); + int i = 0; + pParse->nMem = 8; +- sqlite3CodeVerifySchema(pParse, iDb); ++ sqlite3CodeVerifySchema(pParse, iTabDb); + while(pFK){ + int j; + for(j=0; j<pFK->nCol; j++){ +@@ -118199,9 +121519,9 @@ + pParse->nMem += 4; + regKey = ++pParse->nMem; + regRow = ++pParse->nMem; +- sqlite3CodeVerifySchema(pParse, iDb); + k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash); + while( k ){ ++ int iTabDb; + if( zRight ){ + pTab = sqlite3LocateTable(pParse, 0, zRight, zDb); + k = 0; +@@ -118210,21 +121530,23 @@ + k = sqliteHashNext(k); + } + if( pTab==0 || pTab->pFKey==0 ) continue; +- sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); ++ iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); ++ sqlite3CodeVerifySchema(pParse, iTabDb); ++ sqlite3TableLock(pParse, iTabDb, pTab->tnum, 0, pTab->zName); + if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow; +- sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead); ++ sqlite3OpenTable(pParse, 0, iTabDb, pTab, OP_OpenRead); + sqlite3VdbeLoadString(v, regResult, pTab->zName); + for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ + pParent = sqlite3FindTable(db, pFK->zTo, zDb); + if( pParent==0 ) continue; + pIdx = 0; +- sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName); ++ sqlite3TableLock(pParse, iTabDb, pParent->tnum, 0, pParent->zName); + x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0); + if( x==0 ){ + if( pIdx==0 ){ +- sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead); ++ sqlite3OpenTable(pParse, i, iTabDb, pParent, OP_OpenRead); + }else{ +- sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb); ++ sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iTabDb); + sqlite3VdbeSetP4KeyInfo(pParse, pIdx); + } + }else{ +@@ -118427,7 +121749,6 @@ + + if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */ + pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); +- sqlite3ExprCacheClear(pParse); + sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0, + 1, 0, &iDataCur, &iIdxCur); + /* reg[7] counts the number of entries in the table. +@@ -118441,6 +121762,11 @@ + assert( sqlite3NoTempsInRange(pParse,1,7+j) ); + sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v); + loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1); ++ if( !isQuick ){ ++ /* Sanity check on record header decoding */ ++ sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nCol-1, 3); ++ sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG); ++ } + /* Verify that all NOT NULL columns really are NOT NULL */ + for(j=0; j<pTab->nCol; j++){ + char *zErr; +@@ -118465,7 +121791,6 @@ + char *zErr; + int k; + pParse->iSelfTab = iDataCur + 1; +- sqlite3ExprCachePush(pParse); + for(k=pCheck->nExpr-1; k>0; k--){ + sqlite3ExprIfFalse(pParse, pCheck->a[k].pExpr, addrCkFault, 0); + } +@@ -118478,14 +121803,10 @@ + sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); + integrityCheckResultRow(v); + sqlite3VdbeResolveLabel(v, addrCkOk); +- sqlite3ExprCachePop(pParse); + } + sqlite3ExprListDelete(db, pCheck); + } + if( !isQuick ){ /* Omit the remaining tests for quick_check */ +- /* Sanity check on record header decoding */ +- sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nCol-1, 3); +- sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG); + /* Validate index entries for the current row */ + for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ + int jmp2, jmp3, jmp4, jmp5; +@@ -118994,14 +122315,26 @@ + #endif + + #ifdef SQLITE_HAS_CODEC ++ /* Pragma iArg ++ ** ---------- ------ ++ ** key 0 ++ ** rekey 1 ++ ** hexkey 2 ++ ** hexrekey 3 ++ ** textkey 4 ++ ** textrekey 5 ++ */ + case PragTyp_KEY: { +- if( zRight ) sqlite3_key_v2(db, zDb, zRight, sqlite3Strlen30(zRight)); ++ if( zRight ){ ++ int n = pPragma->iArg<4 ? sqlite3Strlen30(zRight) : -1; ++ if( (pPragma->iArg & 1)==0 ){ ++ sqlite3_key_v2(db, zDb, zRight, n); ++ }else{ ++ sqlite3_rekey_v2(db, zDb, zRight, n); ++ } ++ } + break; + } +- case PragTyp_REKEY: { +- if( zRight ) sqlite3_rekey_v2(db, zDb, zRight, sqlite3Strlen30(zRight)); +- break; +- } + case PragTyp_HEXKEY: { + if( zRight ){ + u8 iByte; +@@ -119011,7 +122344,7 @@ + iByte = (iByte<<4) + sqlite3HexToInt(zRight[i]); + if( (i&1)!=0 ) zKey[i/2] = iByte; + } +- if( (zLeft[3] & 0xf)==0xb ){ ++ if( (pPragma->iArg & 1)==0 ){ + sqlite3_key_v2(db, zDb, zKey, i/2); + }else{ + sqlite3_rekey_v2(db, zDb, zKey, i/2); +@@ -119093,26 +122426,25 @@ + UNUSED_PARAMETER(argc); + UNUSED_PARAMETER(argv); + sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); +- sqlite3StrAccumAppendAll(&acc, "CREATE TABLE x"); ++ sqlite3_str_appendall(&acc, "CREATE TABLE x"); + for(i=0, j=pPragma->iPragCName; i<pPragma->nPragCName; i++, j++){ +- sqlite3XPrintf(&acc, "%c\"%s\"", cSep, pragCName[j]); ++ sqlite3_str_appendf(&acc, "%c\"%s\"", cSep, pragCName[j]); + cSep = ','; + } + if( i==0 ){ +- sqlite3XPrintf(&acc, "(\"%s\"", pPragma->zName); +- cSep = ','; ++ sqlite3_str_appendf(&acc, "(\"%s\"", pPragma->zName); + i++; + } + j = 0; + if( pPragma->mPragFlg & PragFlg_Result1 ){ +- sqlite3StrAccumAppendAll(&acc, ",arg HIDDEN"); ++ sqlite3_str_appendall(&acc, ",arg HIDDEN"); + j++; + } + if( pPragma->mPragFlg & (PragFlg_SchemaOpt|PragFlg_SchemaReq) ){ +- sqlite3StrAccumAppendAll(&acc, ",schema HIDDEN"); ++ sqlite3_str_appendall(&acc, ",schema HIDDEN"); + j++; + } +- sqlite3StrAccumAppend(&acc, ")", 1); ++ sqlite3_str_append(&acc, ")", 1); + sqlite3StrAccumFinish(&acc); + assert( strlen(zBuf) < sizeof(zBuf)-1 ); + rc = sqlite3_declare_vtab(db, zBuf); +@@ -119264,13 +122596,13 @@ + } + } + sqlite3StrAccumInit(&acc, 0, 0, 0, pTab->db->aLimit[SQLITE_LIMIT_SQL_LENGTH]); +- sqlite3StrAccumAppendAll(&acc, "PRAGMA "); ++ sqlite3_str_appendall(&acc, "PRAGMA "); + if( pCsr->azArg[1] ){ +- sqlite3XPrintf(&acc, "%Q.", pCsr->azArg[1]); ++ sqlite3_str_appendf(&acc, "%Q.", pCsr->azArg[1]); + } +- sqlite3StrAccumAppendAll(&acc, pTab->pName->zName); ++ sqlite3_str_appendall(&acc, pTab->pName->zName); + if( pCsr->azArg[0] ){ +- sqlite3XPrintf(&acc, "=%Q", pCsr->azArg[0]); ++ sqlite3_str_appendf(&acc, "=%Q", pCsr->azArg[0]); + } + zSql = sqlite3StrAccumFinish(&acc); + if( zSql==0 ) return SQLITE_NOMEM; +@@ -119342,7 +122674,8 @@ + 0, /* xRename - rename the table */ + 0, /* xSavepoint */ + 0, /* xRelease */ +- 0 /* xRollbackTo */ ++ 0, /* xRollbackTo */ ++ 0 /* xShadowName */ + }; + + /* +@@ -119393,15 +122726,23 @@ + const char *zExtra /* Error information */ + ){ + sqlite3 *db = pData->db; +- if( !db->mallocFailed && (db->flags & SQLITE_WriteSchema)==0 ){ ++ if( db->mallocFailed ){ ++ pData->rc = SQLITE_NOMEM_BKPT; ++ }else if( pData->pzErrMsg[0]!=0 ){ ++ /* A error message has already been generated. Do not overwrite it */ ++ }else if( pData->mInitFlags & INITFLAG_AlterTable ){ ++ *pData->pzErrMsg = sqlite3DbStrDup(db, zExtra); ++ pData->rc = SQLITE_ERROR; ++ }else if( db->flags & SQLITE_WriteSchema ){ ++ pData->rc = SQLITE_CORRUPT_BKPT; ++ }else{ + char *z; + if( zObj==0 ) zObj = "?"; + z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj); + if( zExtra && zExtra[0] ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra); +- sqlite3DbFree(db, *pData->pzErrMsg); + *pData->pzErrMsg = z; ++ pData->rc = SQLITE_CORRUPT_BKPT; + } +- pData->rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_CORRUPT_BKPT; + } + + /* +@@ -119453,7 +122794,7 @@ + rc = db->errCode; + assert( (rc&0xFF)==(rcp&0xFF) ); + db->init.iDb = saved_iDb; +- assert( saved_iDb==0 || (db->mDbFlags & DBFLAG_Vacuum)!=0 ); ++ /* assert( saved_iDb==0 || (db->mDbFlags & DBFLAG_Vacuum)!=0 ); */ + if( SQLITE_OK!=rc ){ + if( db->init.orphanTrigger ){ + assert( iDb==1 ); +@@ -119500,7 +122841,7 @@ + ** auxiliary databases. Return one of the SQLITE_ error codes to + ** indicate success or failure. + */ +-static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ ++SQLITE_PRIVATE int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){ + int rc; + int i; + #ifndef SQLITE_OMIT_DEPRECATED +@@ -119513,6 +122854,7 @@ + const char *zMasterName; + int openedTransaction = 0; + ++ assert( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 ); + assert( iDb>=0 && iDb<db->nDb ); + assert( db->aDb[iDb].pSchema ); + assert( sqlite3_mutex_held(db->mutex) ); +@@ -119534,6 +122876,7 @@ + initData.iDb = iDb; + initData.rc = SQLITE_OK; + initData.pzErrMsg = pzErrMsg; ++ initData.mInitFlags = mFlags; + sqlite3InitCallback(&initData, 3, (char **)azArg, 0); + if( initData.rc ){ + rc = initData.rc; +@@ -119555,7 +122898,7 @@ + ** will be closed before this function returns. */ + sqlite3BtreeEnter(pDb->pBt); + if( !sqlite3BtreeIsInReadTrans(pDb->pBt) ){ +- rc = sqlite3BtreeBeginTrans(pDb->pBt, 0); ++ rc = sqlite3BtreeBeginTrans(pDb->pBt, 0, 0); + if( rc!=SQLITE_OK ){ + sqlite3SetString(pzErrMsg, db, sqlite3ErrStr(rc)); + goto initone_error_out; +@@ -119583,6 +122926,9 @@ + for(i=0; i<ArraySize(meta); i++){ + sqlite3BtreeGetMeta(pDb->pBt, i+1, (u32 *)&meta[i]); + } ++ if( (db->flags & SQLITE_ResetDatabase)!=0 ){ ++ memset(meta, 0, sizeof(meta)); ++ } + pDb->pSchema->schema_cookie = meta[BTREE_SCHEMA_VERSION-1]; + + /* If opening a non-empty database, check the text encoding. For the +@@ -119682,8 +123028,8 @@ + rc = SQLITE_NOMEM_BKPT; + sqlite3ResetAllSchemasOfConnection(db); + } +- if( rc==SQLITE_OK || (db->flags&SQLITE_WriteSchema)){ +- /* Black magic: If the SQLITE_WriteSchema flag is set, then consider ++ if( rc==SQLITE_OK || (db->flags&SQLITE_NoSchemaError)){ ++ /* Black magic: If the SQLITE_NoSchemaError flag is set, then consider + ** the schema loaded, even if errors occurred. In this situation the + ** current sqlite3_prepare() operation will fail, but the following one + ** will attempt to compile the supplied statement against whatever subset +@@ -119737,13 +123083,14 @@ + assert( db->nDb>0 ); + /* Do the main schema first */ + if( !DbHasProperty(db, 0, DB_SchemaLoaded) ){ +- rc = sqlite3InitOne(db, 0, pzErrMsg); ++ rc = sqlite3InitOne(db, 0, pzErrMsg, 0); + if( rc ) return rc; + } + /* All other schemas after the main schema. The "temp" schema must be last */ + for(i=db->nDb-1; i>0; i--){ ++ assert( i==1 || sqlite3BtreeHoldsMutex(db->aDb[i].pBt) ); + if( !DbHasProperty(db, i, DB_SchemaLoaded) ){ +- rc = sqlite3InitOne(db, i, pzErrMsg); ++ rc = sqlite3InitOne(db, i, pzErrMsg, 0); + if( rc ) return rc; + } + } +@@ -119763,11 +123110,13 @@ + assert( sqlite3_mutex_held(db->mutex) ); + if( !db->init.busy ){ + rc = sqlite3Init(db, &pParse->zErrMsg); ++ if( rc!=SQLITE_OK ){ ++ pParse->rc = rc; ++ pParse->nErr++; ++ }else if( db->noSharedCache ){ ++ db->mDbFlags |= DBFLAG_SchemaKnownOk; ++ } + } +- if( rc!=SQLITE_OK ){ +- pParse->rc = rc; +- pParse->nErr++; +- } + return rc; + } + +@@ -119794,7 +123143,7 @@ + ** on the b-tree database, open one now. If a transaction is opened, it + ** will be closed immediately after reading the meta-value. */ + if( !sqlite3BtreeIsInReadTrans(pBt) ){ +- rc = sqlite3BtreeBeginTrans(pBt, 0); ++ rc = sqlite3BtreeBeginTrans(pBt, 0, 0); + if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ + sqlite3OomFault(db); + } +@@ -119977,7 +123326,7 @@ + if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){ + static const char * const azColName[] = { + "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment", +- "selectid", "order", "from", "detail" ++ "id", "parent", "notused", "detail" + }; + int iFirst, mx; + if( sParse.explain==2 ){ +@@ -120061,7 +123410,295 @@ + return rc; + } + ++#ifdef SQLITE_ENABLE_NORMALIZE + /* ++** Checks if the specified token is a table, column, or function name, ++** based on the databases associated with the statement being prepared. ++** If the function fails, zero is returned and pRc is filled with the ++** error code. ++*/ ++static int shouldTreatAsIdentifier( ++ sqlite3 *db, /* Database handle. */ ++ const char *zToken, /* Pointer to start of token to be checked */ ++ int nToken, /* Length of token to be checked */ ++ int *pRc /* Pointer to error code upon failure */ ++){ ++ int bFound = 0; /* Non-zero if token is an identifier name. */ ++ int i, j; /* Database and column loop indexes. */ ++ Schema *pSchema; /* Schema for current database. */ ++ Hash *pHash; /* Hash table of tables for current database. */ ++ HashElem *e; /* Hash element for hash table iteration. */ ++ Table *pTab; /* Database table for columns being checked. */ ++ ++ if( sqlite3IsRowidN(zToken, nToken) ){ ++ return 1; ++ } ++ if( nToken>0 ){ ++ int hash = SQLITE_FUNC_HASH(sqlite3UpperToLower[(u8)zToken[0]], nToken); ++ if( sqlite3FunctionSearchN(hash, zToken, nToken) ) return 1; ++ } ++ assert( db!=0 ); ++ sqlite3_mutex_enter(db->mutex); ++ sqlite3BtreeEnterAll(db); ++ for(i=0; i<db->nDb; i++){ ++ pHash = &db->aFunc; ++ if( sqlite3HashFindN(pHash, zToken, nToken) ){ ++ bFound = 1; ++ break; ++ } ++ pSchema = db->aDb[i].pSchema; ++ if( pSchema==0 ) continue; ++ pHash = &pSchema->tblHash; ++ if( sqlite3HashFindN(pHash, zToken, nToken) ){ ++ bFound = 1; ++ break; ++ } ++ for(e=sqliteHashFirst(pHash); e; e=sqliteHashNext(e)){ ++ pTab = sqliteHashData(e); ++ if( pTab==0 ) continue; ++ pHash = pTab->pColHash; ++ if( pHash==0 ){ ++ pTab->pColHash = pHash = sqlite3_malloc(sizeof(Hash)); ++ if( pHash ){ ++ sqlite3HashInit(pHash); ++ for(j=0; j<pTab->nCol; j++){ ++ Column *pCol = &pTab->aCol[j]; ++ sqlite3HashInsert(pHash, pCol->zName, pCol); ++ } ++ }else{ ++ *pRc = SQLITE_NOMEM_BKPT; ++ bFound = 0; ++ goto done; ++ } ++ } ++ if( pHash && sqlite3HashFindN(pHash, zToken, nToken) ){ ++ bFound = 1; ++ goto done; ++ } ++ } ++ } ++done: ++ sqlite3BtreeLeaveAll(db); ++ sqlite3_mutex_leave(db->mutex); ++ return bFound; ++} ++ ++/* ++** Attempt to estimate the final output buffer size needed for the fully ++** normalized version of the specified SQL string. This should take into ++** account any potential expansion that could occur (e.g. via IN clauses ++** being expanded, etc). This size returned is the total number of bytes ++** including the NUL terminator. ++*/ ++static int estimateNormalizedSize( ++ const char *zSql, /* The original SQL string */ ++ int nSql, /* Length of original SQL string */ ++ u8 prepFlags /* The flags passed to sqlite3_prepare_v3() */ ++){ ++ int nOut = nSql + 4; ++ const char *z = zSql; ++ while( nOut<nSql*5 ){ ++ while( z[0]!=0 && z[0]!='I' && z[0]!='i' ){ z++; } ++ if( z[0]==0 ) break; ++ z++; ++ if( z[0]!='N' && z[0]!='n' ) break; ++ z++; ++ while( sqlite3Isspace(z[0]) ){ z++; } ++ if( z[0]!='(' ) break; ++ z++; ++ nOut += 5; /* ?,?,? */ ++ } ++ return nOut; ++} ++ ++/* ++** Copy the current token into the output buffer while dealing with quoted ++** identifiers. By default, all letters will be converted into lowercase. ++** If the bUpper flag is set, uppercase will be used. The piOut argument ++** will be used to update the target index into the output string. ++*/ ++static void copyNormalizedToken( ++ const char *zSql, /* The original SQL string */ ++ int iIn, /* Current index into the original SQL string */ ++ int nToken, /* Number of bytes in the current token */ ++ int tokenFlags, /* Flags returned by the tokenizer */ ++ char *zOut, /* The output string */ ++ int *piOut /* Pointer to target index into the output string */ ++){ ++ int bQuoted = tokenFlags & SQLITE_TOKEN_QUOTED; ++ int bKeyword = tokenFlags & SQLITE_TOKEN_KEYWORD; ++ int j = *piOut, k = 0; ++ for(; k<nToken; k++){ ++ if( bQuoted ){ ++ if( k==0 && iIn>0 ){ ++ zOut[j++] = '"'; ++ continue; ++ }else if( k==nToken-1 ){ ++ zOut[j++] = '"'; ++ continue; ++ } ++ } ++ if( bKeyword ){ ++ zOut[j++] = sqlite3Toupper(zSql[iIn+k]); ++ }else{ ++ zOut[j++] = sqlite3Tolower(zSql[iIn+k]); ++ } ++ } ++ *piOut = j; ++} ++ ++/* ++** Perform normalization of the SQL contained in the prepared statement and ++** store the result in the zNormSql field. The schema for the associated ++** databases are consulted while performing the normalization in order to ++** determine if a token appears to be an identifier. All identifiers are ++** left intact in the normalized SQL and all literals are replaced with a ++** single '?'. ++*/ ++SQLITE_PRIVATE void sqlite3Normalize( ++ Vdbe *pVdbe, /* VM being reprepared */ ++ const char *zSql, /* The original SQL string */ ++ int nSql, /* Size of the input string in bytes */ ++ u8 prepFlags /* The flags passed to sqlite3_prepare_v3() */ ++){ ++ sqlite3 *db; /* Database handle. */ ++ char *z; /* The output string */ ++ int nZ; /* Size of the output string in bytes */ ++ int i; /* Next character to read from zSql[] */ ++ int j; /* Next character to fill in on z[] */ ++ int tokenType = 0; /* Type of the next token */ ++ int prevTokenType = 0; /* Type of the previous token, except spaces */ ++ int n; /* Size of the next token */ ++ int nParen = 0; /* Nesting level of parenthesis */ ++ Hash inHash; /* Table of parenthesis levels to output index. */ ++ ++ db = sqlite3VdbeDb(pVdbe); ++ assert( db!=0 ); ++ assert( pVdbe->zNormSql==0 ); ++ if( zSql==0 ) return; ++ nZ = estimateNormalizedSize(zSql, nSql, prepFlags); ++ z = sqlite3DbMallocRawNN(db, nZ); ++ if( z==0 ) return; ++ sqlite3HashInit(&inHash); ++ for(i=j=0; i<nSql && zSql[i]; i+=n){ ++ int flags = 0; ++ if( tokenType!=TK_SPACE ) prevTokenType = tokenType; ++ n = sqlite3GetTokenNormalized((unsigned char*)zSql+i, &tokenType, &flags); ++ switch( tokenType ){ ++ case TK_SPACE: { ++ break; ++ } ++ case TK_ILLEGAL: { ++ sqlite3DbFree(db, z); ++ sqlite3HashClear(&inHash); ++ return; ++ } ++ case TK_STRING: ++ case TK_INTEGER: ++ case TK_FLOAT: ++ case TK_VARIABLE: ++ case TK_BLOB: { ++ z[j++] = '?'; ++ break; ++ } ++ case TK_LP: ++ case TK_RP: { ++ if( tokenType==TK_LP ){ ++ nParen++; ++ if( prevTokenType==TK_IN ){ ++ assert( nParen<nSql ); ++ sqlite3HashInsert(&inHash, zSql+nParen, SQLITE_INT_TO_PTR(j)); ++ } ++ }else{ ++ int jj; ++ assert( nParen<nSql ); ++ jj = SQLITE_PTR_TO_INT(sqlite3HashFind(&inHash, zSql+nParen)); ++ if( jj>0 ){ ++ sqlite3HashInsert(&inHash, zSql+nParen, 0); ++ assert( jj+6<nZ ); ++ memcpy(z+jj+1, "?,?,?", 5); ++ j = jj+6; ++ assert( nZ-1-j>=0 ); ++ assert( nZ-1-j<nZ ); ++ memset(z+j, 0, nZ-1-j); ++ } ++ nParen--; ++ } ++ assert( nParen>=0 ); ++ /* Fall through */ ++ } ++ case TK_MINUS: ++ case TK_SEMI: ++ case TK_PLUS: ++ case TK_STAR: ++ case TK_SLASH: ++ case TK_REM: ++ case TK_EQ: ++ case TK_LE: ++ case TK_NE: ++ case TK_LSHIFT: ++ case TK_LT: ++ case TK_RSHIFT: ++ case TK_GT: ++ case TK_GE: ++ case TK_BITOR: ++ case TK_CONCAT: ++ case TK_COMMA: ++ case TK_BITAND: ++ case TK_BITNOT: ++ case TK_DOT: ++ case TK_IN: ++ case TK_IS: ++ case TK_NOT: ++ case TK_NULL: ++ case TK_ID: { ++ if( tokenType==TK_NULL ){ ++ if( prevTokenType==TK_IS || prevTokenType==TK_NOT ){ ++ /* NULL is a keyword in this case, not a literal value */ ++ }else{ ++ /* Here the NULL is a literal value */ ++ z[j++] = '?'; ++ break; ++ } ++ } ++ if( j>0 && sqlite3IsIdChar(z[j-1]) && sqlite3IsIdChar(zSql[i]) ){ ++ z[j++] = ' '; ++ } ++ if( tokenType==TK_ID ){ ++ int i2 = i, n2 = n, rc = SQLITE_OK; ++ if( nParen>0 ){ ++ assert( nParen<nSql ); ++ sqlite3HashInsert(&inHash, zSql+nParen, 0); ++ } ++ if( flags&SQLITE_TOKEN_QUOTED ){ i2++; n2-=2; } ++ if( shouldTreatAsIdentifier(db, zSql+i2, n2, &rc)==0 ){ ++ if( rc!=SQLITE_OK ){ ++ sqlite3DbFree(db, z); ++ sqlite3HashClear(&inHash); ++ return; ++ } ++ if( sqlite3_keyword_check(zSql+i2, n2)==0 ){ ++ z[j++] = '?'; ++ break; ++ } ++ } ++ } ++ copyNormalizedToken(zSql, i, n, flags, z, &j); ++ break; ++ } ++ } ++ } ++ assert( j<nZ && "one" ); ++ while( j>0 && z[j-1]==' ' ){ j--; } ++ if( j>0 && z[j-1]!=';' ){ z[j++] = ';'; } ++ z[j] = 0; ++ assert( j<nZ && "two" ); ++ pVdbe->zNormSql = z; ++ sqlite3HashClear(&inHash); ++} ++#endif /* SQLITE_ENABLE_NORMALIZE */ ++ ++/* + ** Rerun the compilation of a statement after a schema change. + ** + ** If the statement is successfully recompiled, return SQLITE_OK. Otherwise, +@@ -120291,7 +123928,7 @@ + /***/ int sqlite3SelectTrace = 0; + # define SELECTTRACE(K,P,S,X) \ + if(sqlite3SelectTrace&(K)) \ +- sqlite3DebugPrintf("%s/%p: ",(S)->zSelName,(S)),\ ++ sqlite3DebugPrintf("%u/%d/%p: ",(S)->selId,(P)->addrExplain,(S)),\ + sqlite3DebugPrintf X + #else + # define SELECTTRACE(K,P,S,X) +@@ -120314,6 +123951,20 @@ + /* + ** An instance of the following object is used to record information about + ** the ORDER BY (or GROUP BY) clause of query is being coded. ++** ++** The aDefer[] array is used by the sorter-references optimization. For ++** example, assuming there is no index that can be used for the ORDER BY, ++** for the query: ++** ++** SELECT a, bigblob FROM t1 ORDER BY a LIMIT 10; ++** ++** it may be more efficient to add just the "a" values to the sorter, and ++** retrieve the associated "bigblob" values directly from table t1 as the ++** 10 smallest "a" values are extracted from the sorter. ++** ++** When the sorter-reference optimization is used, there is one entry in the ++** aDefer[] array for each database table that may be read as values are ++** extracted from the sorter. + */ + typedef struct SortCtx SortCtx; + struct SortCtx { +@@ -120324,8 +123975,17 @@ + int labelBkOut; /* Start label for the block-output subroutine */ + int addrSortIndex; /* Address of the OP_SorterOpen or OP_OpenEphemeral */ + int labelDone; /* Jump here when done, ex: LIMIT reached */ ++ int labelOBLopt; /* Jump here when sorter is full */ + u8 sortFlags; /* Zero or more SORTFLAG_* bits */ +- u8 bOrderedInnerLoop; /* ORDER BY correctly sorts the inner loop */ ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ u8 nDefer; /* Number of valid entries in aDefer[] */ ++ struct DeferredCsr { ++ Table *pTab; /* Table definition */ ++ int iCsr; /* Cursor number for table */ ++ int nKey; /* Number of PK columns for table pTab (>=1) */ ++ } aDefer[4]; ++#endif ++ struct RowLoadInfo *pDeferredRowLoad; /* Deferred row loading info or NULL */ + }; + #define SORTFLAG_UseSorter 0x01 /* Use SorterOpen instead of OpenEphemeral */ + +@@ -120343,6 +124003,11 @@ + sqlite3ExprDelete(db, p->pHaving); + sqlite3ExprListDelete(db, p->pOrderBy); + sqlite3ExprDelete(db, p->pLimit); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( OK_IF_ALWAYS_TRUE(p->pWinDefn) ){ ++ sqlite3WindowListDelete(db, p->pWinDefn); ++ } ++#endif + if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith); + if( bFree ) sqlite3DbFreeNN(db, p); + p = pPrior; +@@ -120393,9 +124058,7 @@ + pNew->selFlags = selFlags; + pNew->iLimit = 0; + pNew->iOffset = 0; +-#if SELECTTRACE_ENABLED +- pNew->zSelName[0] = 0; +-#endif ++ pNew->selId = ++pParse->nSelect; + pNew->addrOpenEphm[0] = -1; + pNew->addrOpenEphm[1] = -1; + pNew->nSelectRow = 0; +@@ -120409,6 +124072,10 @@ + pNew->pNext = 0; + pNew->pLimit = pLimit; + pNew->pWith = 0; ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ pNew->pWin = 0; ++ pNew->pWinDefn = 0; ++#endif + if( pParse->db->mallocFailed ) { + clearSelect(pParse->db, pNew, pNew!=&standin); + pNew = 0; +@@ -120419,18 +124086,7 @@ + return pNew; + } + +-#if SELECTTRACE_ENABLED +-/* +-** Set the name of a Select object +-*/ +-SQLITE_PRIVATE void sqlite3SelectSetName(Select *p, const char *zName){ +- if( p && zName ){ +- sqlite3_snprintf(sizeof(p->zSelName), p->zSelName, "%s", zName); +- } +-} +-#endif + +- + /* + ** Delete the given Select structure and all of its substructures. + */ +@@ -120776,15 +124432,63 @@ + return 0; + } + +-/* Forward reference */ +-static KeyInfo *keyInfoFromExprList( +- Parse *pParse, /* Parsing context */ +- ExprList *pList, /* Form the KeyInfo object from this ExprList */ +- int iStart, /* Begin with this column of pList */ +- int nExtra /* Add this many extra columns to the end */ +-); ++/* ++** An instance of this object holds information (beyond pParse and pSelect) ++** needed to load the next result row that is to be added to the sorter. ++*/ ++typedef struct RowLoadInfo RowLoadInfo; ++struct RowLoadInfo { ++ int regResult; /* Store results in array of registers here */ ++ u8 ecelFlags; /* Flag argument to ExprCodeExprList() */ ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ ExprList *pExtra; /* Extra columns needed by sorter refs */ ++ int regExtraResult; /* Where to load the extra columns */ ++#endif ++}; + + /* ++** This routine does the work of loading query data into an array of ++** registers so that it can be added to the sorter. ++*/ ++static void innerLoopLoadRow( ++ Parse *pParse, /* Statement under construction */ ++ Select *pSelect, /* The query being coded */ ++ RowLoadInfo *pInfo /* Info needed to complete the row load */ ++){ ++ sqlite3ExprCodeExprList(pParse, pSelect->pEList, pInfo->regResult, ++ 0, pInfo->ecelFlags); ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ if( pInfo->pExtra ){ ++ sqlite3ExprCodeExprList(pParse, pInfo->pExtra, pInfo->regExtraResult, 0, 0); ++ sqlite3ExprListDelete(pParse->db, pInfo->pExtra); ++ } ++#endif ++} ++ ++/* ++** Code the OP_MakeRecord instruction that generates the entry to be ++** added into the sorter. ++** ++** Return the register in which the result is stored. ++*/ ++static int makeSorterRecord( ++ Parse *pParse, ++ SortCtx *pSort, ++ Select *pSelect, ++ int regBase, ++ int nBase ++){ ++ int nOBSat = pSort->nOBSat; ++ Vdbe *v = pParse->pVdbe; ++ int regOut = ++pParse->nMem; ++ if( pSort->pDeferredRowLoad ){ ++ innerLoopLoadRow(pParse, pSelect, pSort->pDeferredRowLoad); ++ } ++ sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regOut); ++ return regOut; ++} ++ ++/* + ** Generate code that will push the record in registers regData + ** through regData+nData-1 onto the sorter. + */ +@@ -120794,7 +124498,7 @@ + Select *pSelect, /* The whole SELECT statement */ + int regData, /* First register holding data to be sorted */ + int regOrigData, /* First register holding data before packing */ +- int nData, /* Number of elements in the data array */ ++ int nData, /* Number of elements in the regData data array */ + int nPrefixReg /* No. of reg prior to regData available for use */ + ){ + Vdbe *v = pParse->pVdbe; /* Stmt under construction */ +@@ -120802,16 +124506,32 @@ + int nExpr = pSort->pOrderBy->nExpr; /* No. of ORDER BY terms */ + int nBase = nExpr + bSeq + nData; /* Fields in sorter record */ + int regBase; /* Regs for sorter record */ +- int regRecord = ++pParse->nMem; /* Assembled sorter record */ ++ int regRecord = 0; /* Assembled sorter record */ + int nOBSat = pSort->nOBSat; /* ORDER BY terms to skip */ + int op; /* Opcode to add sorter record to sorter */ + int iLimit; /* LIMIT counter */ ++ int iSkip = 0; /* End of the sorter insert loop */ + + assert( bSeq==0 || bSeq==1 ); ++ ++ /* Three cases: ++ ** (1) The data to be sorted has already been packed into a Record ++ ** by a prior OP_MakeRecord. In this case nData==1 and regData ++ ** will be completely unrelated to regOrigData. ++ ** (2) All output columns are included in the sort record. In that ++ ** case regData==regOrigData. ++ ** (3) Some output columns are omitted from the sort record due to ++ ** the SQLITE_ENABLE_SORTER_REFERENCE optimization, or due to the ++ ** SQLITE_ECEL_OMITREF optimization, or due to the ++ ** SortCtx.pDeferredRowLoad optimiation. In any of these cases ++ ** regOrigData is 0 to prevent this routine from trying to copy ++ ** values that might not yet exist. ++ */ + assert( nData==1 || regData==regOrigData || regOrigData==0 ); ++ + if( nPrefixReg ){ + assert( nPrefixReg==nExpr+bSeq ); +- regBase = regData - nExpr - bSeq; ++ regBase = regData - nPrefixReg; + }else{ + regBase = pParse->nMem + 1; + pParse->nMem += nBase; +@@ -120827,7 +124547,6 @@ + if( nPrefixReg==0 && nData>0 ){ + sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData); + } +- sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regRecord); + if( nOBSat>0 ){ + int regPrevKey; /* The first nOBSat columns of the previous row */ + int addrFirst; /* Address of the OP_IfNot opcode */ +@@ -120836,6 +124555,7 @@ + int nKey; /* Number of sorting key columns, including OP_Sequence */ + KeyInfo *pKI; /* Original KeyInfo on the sorter table */ + ++ regRecord = makeSorterRecord(pParse, pSort, pSelect, regBase, nBase); + regPrevKey = pParse->nMem+1; + pParse->nMem += pSort->nOBSat; + nKey = nExpr - pSort->nOBSat + bSeq; +@@ -120853,7 +124573,7 @@ + memset(pKI->aSortOrder, 0, pKI->nKeyField); /* Makes OP_Jump testable */ + sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO); + testcase( pKI->nAllField > pKI->nKeyField+2 ); +- pOp->p4.pKeyInfo = keyInfoFromExprList(pParse, pSort->pOrderBy, nOBSat, ++ pOp->p4.pKeyInfo = sqlite3KeyInfoFromExprList(pParse,pSort->pOrderBy,nOBSat, + pKI->nAllField-pKI->nKeyField-1); + addrJmp = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v); +@@ -120869,6 +124589,34 @@ + sqlite3ExprCodeMove(pParse, regBase, regPrevKey, pSort->nOBSat); + sqlite3VdbeJumpHere(v, addrJmp); + } ++ if( iLimit ){ ++ /* At this point the values for the new sorter entry are stored ++ ** in an array of registers. They need to be composed into a record ++ ** and inserted into the sorter if either (a) there are currently ++ ** less than LIMIT+OFFSET items or (b) the new record is smaller than ++ ** the largest record currently in the sorter. If (b) is true and there ++ ** are already LIMIT+OFFSET items in the sorter, delete the largest ++ ** entry before inserting the new one. This way there are never more ++ ** than LIMIT+OFFSET items in the sorter. ++ ** ++ ** If the new record does not need to be inserted into the sorter, ++ ** jump to the next iteration of the loop. If the pSort->labelOBLopt ++ ** value is not zero, then it is a label of where to jump. Otherwise, ++ ** just bypass the row insert logic. See the header comment on the ++ ** sqlite3WhereOrderByLimitOptLabel() function for additional info. ++ */ ++ int iCsr = pSort->iECursor; ++ sqlite3VdbeAddOp2(v, OP_IfNotZero, iLimit, sqlite3VdbeCurrentAddr(v)+4); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp2(v, OP_Last, iCsr, 0); ++ iSkip = sqlite3VdbeAddOp4Int(v, OP_IdxLE, ++ iCsr, 0, regBase+nOBSat, nExpr-nOBSat); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp1(v, OP_Delete, iCsr); ++ } ++ if( regRecord==0 ){ ++ regRecord = makeSorterRecord(pParse, pSort, pSelect, regBase, nBase); ++ } + if( pSort->sortFlags & SORTFLAG_UseSorter ){ + op = OP_SorterInsert; + }else{ +@@ -120876,33 +124624,9 @@ + } + sqlite3VdbeAddOp4Int(v, op, pSort->iECursor, regRecord, + regBase+nOBSat, nBase-nOBSat); +- if( iLimit ){ +- int addr; +- int r1 = 0; +- /* Fill the sorter until it contains LIMIT+OFFSET entries. (The iLimit +- ** register is initialized with value of LIMIT+OFFSET.) After the sorter +- ** fills up, delete the least entry in the sorter after each insert. +- ** Thus we never hold more than the LIMIT+OFFSET rows in memory at once */ +- addr = sqlite3VdbeAddOp1(v, OP_IfNotZero, iLimit); VdbeCoverage(v); +- sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor); +- if( pSort->bOrderedInnerLoop ){ +- r1 = ++pParse->nMem; +- sqlite3VdbeAddOp3(v, OP_Column, pSort->iECursor, nExpr, r1); +- VdbeComment((v, "seq")); +- } +- sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor); +- if( pSort->bOrderedInnerLoop ){ +- /* If the inner loop is driven by an index such that values from +- ** the same iteration of the inner loop are in sorted order, then +- ** immediately jump to the next iteration of an inner loop if the +- ** entry from the current iteration does not fit into the top +- ** LIMIT+OFFSET entries of the sorter. */ +- int iBrk = sqlite3VdbeCurrentAddr(v) + 2; +- sqlite3VdbeAddOp3(v, OP_Eq, regBase+nExpr, iBrk, r1); +- sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); +- VdbeCoverage(v); +- } +- sqlite3VdbeJumpHere(v, addr); ++ if( iSkip ){ ++ sqlite3VdbeChangeP2(v, iSkip, ++ pSort->labelOBLopt ? pSort->labelOBLopt : sqlite3VdbeCurrentAddr(v)); + } + } + +@@ -120948,7 +124672,88 @@ + sqlite3ReleaseTempReg(pParse, r1); + } + ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES + /* ++** This function is called as part of inner-loop generation for a SELECT ++** statement with an ORDER BY that is not optimized by an index. It ++** determines the expressions, if any, that the sorter-reference ++** optimization should be used for. The sorter-reference optimization ++** is used for SELECT queries like: ++** ++** SELECT a, bigblob FROM t1 ORDER BY a LIMIT 10 ++** ++** If the optimization is used for expression "bigblob", then instead of ++** storing values read from that column in the sorter records, the PK of ++** the row from table t1 is stored instead. Then, as records are extracted from ++** the sorter to return to the user, the required value of bigblob is ++** retrieved directly from table t1. If the values are very large, this ++** can be more efficient than storing them directly in the sorter records. ++** ++** The ExprList_item.bSorterRef flag is set for each expression in pEList ++** for which the sorter-reference optimization should be enabled. ++** Additionally, the pSort->aDefer[] array is populated with entries ++** for all cursors required to evaluate all selected expressions. Finally. ++** output variable (*ppExtra) is set to an expression list containing ++** expressions for all extra PK values that should be stored in the ++** sorter records. ++*/ ++static void selectExprDefer( ++ Parse *pParse, /* Leave any error here */ ++ SortCtx *pSort, /* Sorter context */ ++ ExprList *pEList, /* Expressions destined for sorter */ ++ ExprList **ppExtra /* Expressions to append to sorter record */ ++){ ++ int i; ++ int nDefer = 0; ++ ExprList *pExtra = 0; ++ for(i=0; i<pEList->nExpr; i++){ ++ struct ExprList_item *pItem = &pEList->a[i]; ++ if( pItem->u.x.iOrderByCol==0 ){ ++ Expr *pExpr = pItem->pExpr; ++ Table *pTab = pExpr->y.pTab; ++ if( pExpr->op==TK_COLUMN && pExpr->iColumn>=0 && pTab && !IsVirtual(pTab) ++ && (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF) ++ ){ ++ int j; ++ for(j=0; j<nDefer; j++){ ++ if( pSort->aDefer[j].iCsr==pExpr->iTable ) break; ++ } ++ if( j==nDefer ){ ++ if( nDefer==ArraySize(pSort->aDefer) ){ ++ continue; ++ }else{ ++ int nKey = 1; ++ int k; ++ Index *pPk = 0; ++ if( !HasRowid(pTab) ){ ++ pPk = sqlite3PrimaryKeyIndex(pTab); ++ nKey = pPk->nKeyCol; ++ } ++ for(k=0; k<nKey; k++){ ++ Expr *pNew = sqlite3PExpr(pParse, TK_COLUMN, 0, 0); ++ if( pNew ){ ++ pNew->iTable = pExpr->iTable; ++ pNew->y.pTab = pExpr->y.pTab; ++ pNew->iColumn = pPk ? pPk->aiColumn[k] : -1; ++ pExtra = sqlite3ExprListAppend(pParse, pExtra, pNew); ++ } ++ } ++ pSort->aDefer[nDefer].pTab = pExpr->y.pTab; ++ pSort->aDefer[nDefer].iCsr = pExpr->iTable; ++ pSort->aDefer[nDefer].nKey = nKey; ++ nDefer++; ++ } ++ } ++ pItem->bSorterRef = 1; ++ } ++ } ++ } ++ pSort->nDefer = (u8)nDefer; ++ *ppExtra = pExtra; ++} ++#endif ++ ++/* + ** This routine generates the code for the inside of the inner loop + ** of a SELECT. + ** +@@ -120974,6 +124779,7 @@ + int iParm = pDest->iSDParm; /* First argument to disposal method */ + int nResultCol; /* Number of result columns */ + int nPrefixReg = 0; /* Number of extra registers before regResult */ ++ RowLoadInfo sRowLoadInfo; /* Info for deferred row loading */ + + /* Usually, regResult is the first cell in an array of memory cells + ** containing the current result row. In this case regOrig is set to the +@@ -121020,10 +124826,14 @@ + VdbeComment((v, "%s", p->pEList->a[i].zName)); + } + }else if( eDest!=SRT_Exists ){ ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ ExprList *pExtra = 0; ++#endif + /* If the destination is an EXISTS(...) expression, the actual + ** values returned by the SELECT are not required. + */ +- u8 ecelFlags; ++ u8 ecelFlags; /* "ecel" is an abbreviation of "ExprCodeExprList" */ ++ ExprList *pEList; + if( eDest==SRT_Mem || eDest==SRT_Output || eDest==SRT_Coroutine ){ + ecelFlags = SQLITE_ECEL_DUP; + }else{ +@@ -121037,6 +124847,7 @@ + ** This allows the p->pEList field to be omitted from the sorted record, + ** saving space and CPU cycles. */ + ecelFlags |= (SQLITE_ECEL_OMITREF|SQLITE_ECEL_REF); ++ + for(i=pSort->nOBSat; i<pSort->pOrderBy->nExpr; i++){ + int j; + if( (j = pSort->pOrderBy->a[i].u.x.iOrderByCol)>0 ){ +@@ -121043,12 +124854,61 @@ + p->pEList->a[j-1].u.x.iOrderByCol = i+1-pSort->nOBSat; + } + } +- regOrig = 0; ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ selectExprDefer(pParse, pSort, p->pEList, &pExtra); ++ if( pExtra && pParse->db->mallocFailed==0 ){ ++ /* If there are any extra PK columns to add to the sorter records, ++ ** allocate extra memory cells and adjust the OpenEphemeral ++ ** instruction to account for the larger records. This is only ++ ** required if there are one or more WITHOUT ROWID tables with ++ ** composite primary keys in the SortCtx.aDefer[] array. */ ++ VdbeOp *pOp = sqlite3VdbeGetOp(v, pSort->addrSortIndex); ++ pOp->p2 += (pExtra->nExpr - pSort->nDefer); ++ pOp->p4.pKeyInfo->nAllField += (pExtra->nExpr - pSort->nDefer); ++ pParse->nMem += pExtra->nExpr; ++ } ++#endif ++ ++ /* Adjust nResultCol to account for columns that are omitted ++ ** from the sorter by the optimizations in this branch */ ++ pEList = p->pEList; ++ for(i=0; i<pEList->nExpr; i++){ ++ if( pEList->a[i].u.x.iOrderByCol>0 ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ || pEList->a[i].bSorterRef ++#endif ++ ){ ++ nResultCol--; ++ regOrig = 0; ++ } ++ } ++ ++ testcase( regOrig ); ++ testcase( eDest==SRT_Set ); ++ testcase( eDest==SRT_Mem ); ++ testcase( eDest==SRT_Coroutine ); ++ testcase( eDest==SRT_Output ); + assert( eDest==SRT_Set || eDest==SRT_Mem + || eDest==SRT_Coroutine || eDest==SRT_Output ); + } +- nResultCol = sqlite3ExprCodeExprList(pParse,p->pEList,regResult, +- 0,ecelFlags); ++ sRowLoadInfo.regResult = regResult; ++ sRowLoadInfo.ecelFlags = ecelFlags; ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ sRowLoadInfo.pExtra = pExtra; ++ sRowLoadInfo.regExtraResult = regResult + nResultCol; ++ if( pExtra ) nResultCol += pExtra->nExpr; ++#endif ++ if( p->iLimit ++ && (ecelFlags & SQLITE_ECEL_OMITREF)!=0 ++ && nPrefixReg>0 ++ ){ ++ assert( pSort!=0 ); ++ assert( hasDistinct==0 ); ++ pSort->pDeferredRowLoad = &sRowLoadInfo; ++ regOrig = 0; ++ }else{ ++ innerLoopLoadRow(pParse, p, &sRowLoadInfo); ++ } + } + + /* If the DISTINCT keyword was present on the SELECT statement +@@ -121164,7 +125024,8 @@ + } + #endif + if( pSort ){ +- pushOntoSorter(pParse, pSort, p, r1+nPrefixReg,regResult,1,nPrefixReg); ++ assert( regResult==regOrig ); ++ pushOntoSorter(pParse, pSort, p, r1+nPrefixReg, regOrig, 1, nPrefixReg); + }else{ + int r2 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2); +@@ -121194,7 +125055,6 @@ + assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol ); + sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol, + r1, pDest->zAffSdst, nResultCol); +- sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol); + sqlite3ReleaseTempReg(pParse, r1); + } +@@ -121238,7 +125098,6 @@ + sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); + }else{ + sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nResultCol); +- sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol); + } + break; + } +@@ -121381,7 +125240,7 @@ + ** function is responsible for seeing that this structure is eventually + ** freed. + */ +-static KeyInfo *keyInfoFromExprList( ++SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoFromExprList( + Parse *pParse, /* Parsing context */ + ExprList *pList, /* Form the KeyInfo object from this ExprList */ + int iStart, /* Begin with this column of pList */ +@@ -121431,11 +125290,7 @@ + ** is determined by the zUsage argument. + */ + static void explainTempTable(Parse *pParse, const char *zUsage){ +- if( pParse->explain==2 ){ +- Vdbe *v = pParse->pVdbe; +- char *zMsg = sqlite3MPrintf(pParse->db, "USE TEMP B-TREE FOR %s", zUsage); +- sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); +- } ++ ExplainQueryPlan((pParse, 0, "USE TEMP B-TREE FOR %s", zUsage)); + } + + /* +@@ -121453,42 +125308,6 @@ + # define explainSetInteger(y,z) + #endif + +-#if !defined(SQLITE_OMIT_EXPLAIN) && !defined(SQLITE_OMIT_COMPOUND_SELECT) +-/* +-** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function +-** is a no-op. Otherwise, it adds a single row of output to the EQP result, +-** where the caption is of one of the two forms: +-** +-** "COMPOSITE SUBQUERIES iSub1 and iSub2 (op)" +-** "COMPOSITE SUBQUERIES iSub1 and iSub2 USING TEMP B-TREE (op)" +-** +-** where iSub1 and iSub2 are the integers passed as the corresponding +-** function parameters, and op is the text representation of the parameter +-** of the same name. The parameter "op" must be one of TK_UNION, TK_EXCEPT, +-** TK_INTERSECT or TK_ALL. The first form is used if argument bUseTmp is +-** false, or the second form if it is true. +-*/ +-static void explainComposite( +- Parse *pParse, /* Parse context */ +- int op, /* One of TK_UNION, TK_EXCEPT etc. */ +- int iSub1, /* Subquery id 1 */ +- int iSub2, /* Subquery id 2 */ +- int bUseTmp /* True if a temp table was used */ +-){ +- assert( op==TK_UNION || op==TK_EXCEPT || op==TK_INTERSECT || op==TK_ALL ); +- if( pParse->explain==2 ){ +- Vdbe *v = pParse->pVdbe; +- char *zMsg = sqlite3MPrintf( +- pParse->db, "COMPOUND SUBQUERIES %d AND %d %s(%s)", iSub1, iSub2, +- bUseTmp?"USING TEMP B-TREE ":"", selectOpName(op) +- ); +- sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); +- } +-} +-#else +-/* No-op versions of the explainXXX() functions and macros. */ +-# define explainComposite(v,w,x,y,z) +-#endif + + /* + ** If the inner loop was generated using a non-null pOrderBy argument, +@@ -121506,7 +125325,7 @@ + Vdbe *v = pParse->pVdbe; /* The prepared statement */ + int addrBreak = pSort->labelDone; /* Jump here to exit loop */ + int addrContinue = sqlite3VdbeMakeLabel(v); /* Jump here for next cycle */ +- int addr; ++ int addr; /* Top of output loop. Jump for Next. */ + int addrOnce = 0; + int iTab; + ExprList *pOrderBy = pSort->pOrderBy; +@@ -121515,11 +125334,11 @@ + int regRow; + int regRowid; + int iCol; +- int nKey; ++ int nKey; /* Number of key columns in sorter record */ + int iSortTab; /* Sorter cursor to read from */ +- int nSortData; /* Trailing values to read from sorter */ + int i; + int bSeq; /* True if sorter record includes seq. no. */ ++ int nRefKey = 0; + struct ExprList_item *aOutEx = p->pEList->a; + + assert( addrBreak<0 ); +@@ -121528,15 +125347,24 @@ + sqlite3VdbeGoto(v, addrBreak); + sqlite3VdbeResolveLabel(v, pSort->labelBkOut); + } ++ ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ /* Open any cursors needed for sorter-reference expressions */ ++ for(i=0; i<pSort->nDefer; i++){ ++ Table *pTab = pSort->aDefer[i].pTab; ++ int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); ++ sqlite3OpenTable(pParse, pSort->aDefer[i].iCsr, iDb, pTab, OP_OpenRead); ++ nRefKey = MAX(nRefKey, pSort->aDefer[i].nKey); ++ } ++#endif ++ + iTab = pSort->iECursor; + if( eDest==SRT_Output || eDest==SRT_Coroutine || eDest==SRT_Mem ){ + regRowid = 0; + regRow = pDest->iSdst; +- nSortData = nColumn; + }else{ + regRowid = sqlite3GetTempReg(pParse); + regRow = sqlite3GetTempRange(pParse, nColumn); +- nSortData = nColumn; + } + nKey = pOrderBy->nExpr - pSort->nOBSat; + if( pSort->sortFlags & SORTFLAG_UseSorter ){ +@@ -121545,7 +125373,8 @@ + if( pSort->labelBkOut ){ + addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); + } +- sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut, nKey+1+nSortData); ++ sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut, ++ nKey+1+nColumn+nRefKey); + if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); + addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak); + VdbeCoverage(v); +@@ -121558,19 +125387,60 @@ + iSortTab = iTab; + bSeq = 1; + } +- for(i=0, iCol=nKey+bSeq-1; i<nSortData; i++){ ++ for(i=0, iCol=nKey+bSeq-1; i<nColumn; i++){ ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ if( aOutEx[i].bSorterRef ) continue; ++#endif + if( aOutEx[i].u.x.iOrderByCol==0 ) iCol++; + } +- for(i=nSortData-1; i>=0; i--){ +- int iRead; +- if( aOutEx[i].u.x.iOrderByCol ){ +- iRead = aOutEx[i].u.x.iOrderByCol-1; +- }else{ +- iRead = iCol--; ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ if( pSort->nDefer ){ ++ int iKey = iCol+1; ++ int regKey = sqlite3GetTempRange(pParse, nRefKey); ++ ++ for(i=0; i<pSort->nDefer; i++){ ++ int iCsr = pSort->aDefer[i].iCsr; ++ Table *pTab = pSort->aDefer[i].pTab; ++ int nKey = pSort->aDefer[i].nKey; ++ ++ sqlite3VdbeAddOp1(v, OP_NullRow, iCsr); ++ if( HasRowid(pTab) ){ ++ sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iKey++, regKey); ++ sqlite3VdbeAddOp3(v, OP_SeekRowid, iCsr, ++ sqlite3VdbeCurrentAddr(v)+1, regKey); ++ }else{ ++ int k; ++ int iJmp; ++ assert( sqlite3PrimaryKeyIndex(pTab)->nKeyCol==nKey ); ++ for(k=0; k<nKey; k++){ ++ sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iKey++, regKey+k); ++ } ++ iJmp = sqlite3VdbeCurrentAddr(v); ++ sqlite3VdbeAddOp4Int(v, OP_SeekGE, iCsr, iJmp+2, regKey, nKey); ++ sqlite3VdbeAddOp4Int(v, OP_IdxLE, iCsr, iJmp+3, regKey, nKey); ++ sqlite3VdbeAddOp1(v, OP_NullRow, iCsr); ++ } + } +- sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i); +- VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan)); ++ sqlite3ReleaseTempRange(pParse, regKey, nRefKey); + } ++#endif ++ for(i=nColumn-1; i>=0; i--){ ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ if( aOutEx[i].bSorterRef ){ ++ sqlite3ExprCode(pParse, aOutEx[i].pExpr, regRow+i); ++ }else ++#endif ++ { ++ int iRead; ++ if( aOutEx[i].u.x.iOrderByCol ){ ++ iRead = aOutEx[i].u.x.iOrderByCol-1; ++ }else{ ++ iRead = iCol--; ++ } ++ sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i); ++ VdbeComment((v, "%s", aOutEx[i].zName?aOutEx[i].zName : aOutEx[i].zSpan)); ++ } ++ } + switch( eDest ){ + case SRT_Table: + case SRT_EphemTab: { +@@ -121584,7 +125454,6 @@ + assert( nColumn==sqlite3Strlen30(pDest->zAffSdst) ); + sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, nColumn, regRowid, + pDest->zAffSdst, nColumn); +- sqlite3ExprCacheAffinityChange(pParse, regRow, nColumn); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, regRowid, regRow, nColumn); + break; + } +@@ -121599,7 +125468,6 @@ + testcase( eDest==SRT_Coroutine ); + if( eDest==SRT_Output ){ + sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iSdst, nColumn); +- sqlite3ExprCacheAffinityChange(pParse, pDest->iSdst, nColumn); + }else{ + sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); + } +@@ -121719,7 +125587,7 @@ + break; + } + +- assert( pTab && pExpr->pTab==pTab ); ++ assert( pTab && pExpr->y.pTab==pTab ); + if( pS ){ + /* The "table" is actually a sub-select or a view in the FROM clause + ** of the SELECT statement. Return the declaration type and origin +@@ -121887,7 +125755,7 @@ + } + #endif + +- if( pParse->colNamesSet || db->mallocFailed ) return; ++ if( pParse->colNamesSet ) return; + /* Column names are determined by the left-most term of a compound select */ + while( pSelect->pPrior ) pSelect = pSelect->pPrior; + SELECTTRACE(1,pParse,pSelect,("generating column names\n")); +@@ -121904,7 +125772,7 @@ + + assert( p!=0 ); + assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */ +- assert( p->op!=TK_COLUMN || p->pTab!=0 ); /* Covering idx not yet coded */ ++ assert( p->op!=TK_COLUMN || p->y.pTab!=0 ); /* Covering idx not yet coded */ + if( pEList->a[i].zName ){ + /* An AS clause always takes first priority */ + char *zName = pEList->a[i].zName; +@@ -121912,7 +125780,7 @@ + }else if( srcName && p->op==TK_COLUMN ){ + char *zCol; + int iCol = p->iColumn; +- pTab = p->pTab; ++ pTab = p->y.pTab; + assert( pTab!=0 ); + if( iCol<0 ) iCol = pTab->iPKey; + assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) ); +@@ -122003,7 +125871,7 @@ + if( pColExpr->op==TK_COLUMN ){ + /* For columns use the column name name */ + int iCol = pColExpr->iColumn; +- Table *pTab = pColExpr->pTab; ++ Table *pTab = pColExpr->y.pTab; + assert( pTab!=0 ); + if( iCol<0 ) iCol = pTab->iPKey; + zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid"; +@@ -122200,7 +126068,6 @@ + ** The current implementation interprets "LIMIT 0" to mean + ** no rows. + */ +- sqlite3ExprCacheClear(pParse); + if( pLimit ){ + assert( pLimit->op==TK_LIMIT ); + assert( pLimit->pLeft!=0 ); +@@ -122358,6 +126225,13 @@ + Expr *pLimit; /* Saved LIMIT and OFFSET */ + int regLimit, regOffset; /* Registers used by LIMIT and OFFSET */ + ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( p->pWin ){ ++ sqlite3ErrorMsg(pParse, "cannot use window functions in recursive queries"); ++ return; ++ } ++#endif ++ + /* Obtain authorization to do a recursive query */ + if( sqlite3AuthCheck(pParse, SQLITE_RECURSIVE, 0, 0, 0) ) return; + +@@ -122414,6 +126288,7 @@ + + /* Store the results of the setup-query in Queue. */ + pSetup->pNext = 0; ++ ExplainQueryPlan((pParse, 1, "SETUP")); + rc = sqlite3Select(pParse, pSetup, &destQueue); + pSetup->pNext = p; + if( rc ) goto end_of_recursive_query; +@@ -122448,6 +126323,7 @@ + sqlite3ErrorMsg(pParse, "recursive aggregate queries not supported"); + }else{ + p->pPrior = 0; ++ ExplainQueryPlan((pParse, 1, "RECURSIVE STEP")); + sqlite3Select(pParse, p, &destQueue); + assert( p->pPrior==0 ); + p->pPrior = pSetup; +@@ -122493,10 +126369,9 @@ + Select *p, /* The right-most of SELECTs to be coded */ + SelectDest *pDest /* What to do with query results */ + ){ +- Select *pPrior; +- Select *pRightmost = p; + int nRow = 1; + int rc = 0; ++ int bShowAll = p->pLimit==0; + assert( p->selFlags & SF_MultiValue ); + do{ + assert( p->selFlags & SF_Values ); +@@ -122505,14 +126380,13 @@ + if( p->pPrior==0 ) break; + assert( p->pPrior->pNext==p ); + p = p->pPrior; +- nRow++; ++ nRow += bShowAll; + }while(1); ++ ExplainQueryPlan((pParse, 0, "SCAN %d CONSTANT ROW%s", nRow, ++ nRow==1 ? "" : "S")); + while( p ){ +- pPrior = p->pPrior; +- p->pPrior = 0; +- rc = sqlite3Select(pParse, p, pDest); +- p->pPrior = pPrior; +- if( rc || pRightmost->pLimit ) break; ++ selectInnerLoop(pParse, p, -1, 0, 0, pDest, 1, 1); ++ if( !bShowAll ) break; + p->nSelectRow = nRow; + p = p->pNext; + } +@@ -122561,10 +126435,6 @@ + SelectDest dest; /* Alternative data destination */ + Select *pDelete = 0; /* Chain of simple selects to delete */ + sqlite3 *db; /* Database connection */ +-#ifndef SQLITE_OMIT_EXPLAIN +- int iSub1 = 0; /* EQP id of left-hand query */ +- int iSub2 = 0; /* EQP id of right-hand query */ +-#endif + + /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only + ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT. +@@ -122615,217 +126485,231 @@ + */ + if( p->pOrderBy ){ + return multiSelectOrderBy(pParse, p, pDest); +- }else ++ }else{ + +- /* Generate code for the left and right SELECT statements. +- */ +- switch( p->op ){ +- case TK_ALL: { +- int addr = 0; +- int nLimit; +- assert( !pPrior->pLimit ); +- pPrior->iLimit = p->iLimit; +- pPrior->iOffset = p->iOffset; +- pPrior->pLimit = p->pLimit; +- explainSetInteger(iSub1, pParse->iNextSelectId); +- rc = sqlite3Select(pParse, pPrior, &dest); +- p->pLimit = 0; +- if( rc ){ +- goto multi_select_end; ++#ifndef SQLITE_OMIT_EXPLAIN ++ if( pPrior->pPrior==0 ){ ++ ExplainQueryPlan((pParse, 1, "COMPOUND QUERY")); ++ ExplainQueryPlan((pParse, 1, "LEFT-MOST SUBQUERY")); ++ } ++#endif ++ ++ /* Generate code for the left and right SELECT statements. ++ */ ++ switch( p->op ){ ++ case TK_ALL: { ++ int addr = 0; ++ int nLimit; ++ assert( !pPrior->pLimit ); ++ pPrior->iLimit = p->iLimit; ++ pPrior->iOffset = p->iOffset; ++ pPrior->pLimit = p->pLimit; ++ rc = sqlite3Select(pParse, pPrior, &dest); ++ p->pLimit = 0; ++ if( rc ){ ++ goto multi_select_end; ++ } ++ p->pPrior = 0; ++ p->iLimit = pPrior->iLimit; ++ p->iOffset = pPrior->iOffset; ++ if( p->iLimit ){ ++ addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); ++ VdbeComment((v, "Jump ahead if LIMIT reached")); ++ if( p->iOffset ){ ++ sqlite3VdbeAddOp3(v, OP_OffsetLimit, ++ p->iLimit, p->iOffset+1, p->iOffset); ++ } ++ } ++ ExplainQueryPlan((pParse, 1, "UNION ALL")); ++ rc = sqlite3Select(pParse, p, &dest); ++ testcase( rc!=SQLITE_OK ); ++ pDelete = p->pPrior; ++ p->pPrior = pPrior; ++ p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); ++ if( pPrior->pLimit ++ && sqlite3ExprIsInteger(pPrior->pLimit->pLeft, &nLimit) ++ && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit) ++ ){ ++ p->nSelectRow = sqlite3LogEst((u64)nLimit); ++ } ++ if( addr ){ ++ sqlite3VdbeJumpHere(v, addr); ++ } ++ break; + } +- p->pPrior = 0; +- p->iLimit = pPrior->iLimit; +- p->iOffset = pPrior->iOffset; +- if( p->iLimit ){ +- addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); +- VdbeComment((v, "Jump ahead if LIMIT reached")); +- if( p->iOffset ){ +- sqlite3VdbeAddOp3(v, OP_OffsetLimit, +- p->iLimit, p->iOffset+1, p->iOffset); ++ case TK_EXCEPT: ++ case TK_UNION: { ++ int unionTab; /* Cursor number of the temp table holding result */ ++ u8 op = 0; /* One of the SRT_ operations to apply to self */ ++ int priorOp; /* The SRT_ operation to apply to prior selects */ ++ Expr *pLimit; /* Saved values of p->nLimit */ ++ int addr; ++ SelectDest uniondest; ++ ++ testcase( p->op==TK_EXCEPT ); ++ testcase( p->op==TK_UNION ); ++ priorOp = SRT_Union; ++ if( dest.eDest==priorOp ){ ++ /* We can reuse a temporary table generated by a SELECT to our ++ ** right. ++ */ ++ assert( p->pLimit==0 ); /* Not allowed on leftward elements */ ++ unionTab = dest.iSDParm; ++ }else{ ++ /* We will need to create our own temporary table to hold the ++ ** intermediate results. ++ */ ++ unionTab = pParse->nTab++; ++ assert( p->pOrderBy==0 ); ++ addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0); ++ assert( p->addrOpenEphm[0] == -1 ); ++ p->addrOpenEphm[0] = addr; ++ findRightmost(p)->selFlags |= SF_UsesEphemeral; ++ assert( p->pEList ); + } ++ ++ /* Code the SELECT statements to our left ++ */ ++ assert( !pPrior->pOrderBy ); ++ sqlite3SelectDestInit(&uniondest, priorOp, unionTab); ++ rc = sqlite3Select(pParse, pPrior, &uniondest); ++ if( rc ){ ++ goto multi_select_end; ++ } ++ ++ /* Code the current SELECT statement ++ */ ++ if( p->op==TK_EXCEPT ){ ++ op = SRT_Except; ++ }else{ ++ assert( p->op==TK_UNION ); ++ op = SRT_Union; ++ } ++ p->pPrior = 0; ++ pLimit = p->pLimit; ++ p->pLimit = 0; ++ uniondest.eDest = op; ++ ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", ++ selectOpName(p->op))); ++ rc = sqlite3Select(pParse, p, &uniondest); ++ testcase( rc!=SQLITE_OK ); ++ /* Query flattening in sqlite3Select() might refill p->pOrderBy. ++ ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */ ++ sqlite3ExprListDelete(db, p->pOrderBy); ++ pDelete = p->pPrior; ++ p->pPrior = pPrior; ++ p->pOrderBy = 0; ++ if( p->op==TK_UNION ){ ++ p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); ++ } ++ sqlite3ExprDelete(db, p->pLimit); ++ p->pLimit = pLimit; ++ p->iLimit = 0; ++ p->iOffset = 0; ++ ++ /* Convert the data in the temporary table into whatever form ++ ** it is that we currently need. ++ */ ++ assert( unionTab==dest.iSDParm || dest.eDest!=priorOp ); ++ if( dest.eDest!=priorOp ){ ++ int iCont, iBreak, iStart; ++ assert( p->pEList ); ++ iBreak = sqlite3VdbeMakeLabel(v); ++ iCont = sqlite3VdbeMakeLabel(v); ++ computeLimitRegisters(pParse, p, iBreak); ++ sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v); ++ iStart = sqlite3VdbeCurrentAddr(v); ++ selectInnerLoop(pParse, p, unionTab, ++ 0, 0, &dest, iCont, iBreak); ++ sqlite3VdbeResolveLabel(v, iCont); ++ sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v); ++ sqlite3VdbeResolveLabel(v, iBreak); ++ sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); ++ } ++ break; + } +- explainSetInteger(iSub2, pParse->iNextSelectId); +- rc = sqlite3Select(pParse, p, &dest); +- testcase( rc!=SQLITE_OK ); +- pDelete = p->pPrior; +- p->pPrior = pPrior; +- p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); +- if( pPrior->pLimit +- && sqlite3ExprIsInteger(pPrior->pLimit->pLeft, &nLimit) +- && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit) +- ){ +- p->nSelectRow = sqlite3LogEst((u64)nLimit); +- } +- if( addr ){ +- sqlite3VdbeJumpHere(v, addr); +- } +- break; +- } +- case TK_EXCEPT: +- case TK_UNION: { +- int unionTab; /* Cursor number of the temporary table holding result */ +- u8 op = 0; /* One of the SRT_ operations to apply to self */ +- int priorOp; /* The SRT_ operation to apply to prior selects */ +- Expr *pLimit; /* Saved values of p->nLimit */ +- int addr; +- SelectDest uniondest; +- +- testcase( p->op==TK_EXCEPT ); +- testcase( p->op==TK_UNION ); +- priorOp = SRT_Union; +- if( dest.eDest==priorOp ){ +- /* We can reuse a temporary table generated by a SELECT to our +- ** right. ++ default: assert( p->op==TK_INTERSECT ); { ++ int tab1, tab2; ++ int iCont, iBreak, iStart; ++ Expr *pLimit; ++ int addr; ++ SelectDest intersectdest; ++ int r1; ++ ++ /* INTERSECT is different from the others since it requires ++ ** two temporary tables. Hence it has its own case. Begin ++ ** by allocating the tables we will need. + */ +- assert( p->pLimit==0 ); /* Not allowed on leftward elements */ +- unionTab = dest.iSDParm; +- }else{ +- /* We will need to create our own temporary table to hold the +- ** intermediate results. +- */ +- unionTab = pParse->nTab++; ++ tab1 = pParse->nTab++; ++ tab2 = pParse->nTab++; + assert( p->pOrderBy==0 ); +- addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0); ++ ++ addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0); + assert( p->addrOpenEphm[0] == -1 ); + p->addrOpenEphm[0] = addr; + findRightmost(p)->selFlags |= SF_UsesEphemeral; + assert( p->pEList ); +- } +- +- /* Code the SELECT statements to our left +- */ +- assert( !pPrior->pOrderBy ); +- sqlite3SelectDestInit(&uniondest, priorOp, unionTab); +- explainSetInteger(iSub1, pParse->iNextSelectId); +- rc = sqlite3Select(pParse, pPrior, &uniondest); +- if( rc ){ +- goto multi_select_end; +- } +- +- /* Code the current SELECT statement +- */ +- if( p->op==TK_EXCEPT ){ +- op = SRT_Except; +- }else{ +- assert( p->op==TK_UNION ); +- op = SRT_Union; +- } +- p->pPrior = 0; +- pLimit = p->pLimit; +- p->pLimit = 0; +- uniondest.eDest = op; +- explainSetInteger(iSub2, pParse->iNextSelectId); +- rc = sqlite3Select(pParse, p, &uniondest); +- testcase( rc!=SQLITE_OK ); +- /* Query flattening in sqlite3Select() might refill p->pOrderBy. +- ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */ +- sqlite3ExprListDelete(db, p->pOrderBy); +- pDelete = p->pPrior; +- p->pPrior = pPrior; +- p->pOrderBy = 0; +- if( p->op==TK_UNION ){ +- p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); +- } +- sqlite3ExprDelete(db, p->pLimit); +- p->pLimit = pLimit; +- p->iLimit = 0; +- p->iOffset = 0; +- +- /* Convert the data in the temporary table into whatever form +- ** it is that we currently need. +- */ +- assert( unionTab==dest.iSDParm || dest.eDest!=priorOp ); +- if( dest.eDest!=priorOp ){ +- int iCont, iBreak, iStart; ++ ++ /* Code the SELECTs to our left into temporary table "tab1". ++ */ ++ sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1); ++ rc = sqlite3Select(pParse, pPrior, &intersectdest); ++ if( rc ){ ++ goto multi_select_end; ++ } ++ ++ /* Code the current SELECT into temporary table "tab2" ++ */ ++ addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0); ++ assert( p->addrOpenEphm[1] == -1 ); ++ p->addrOpenEphm[1] = addr; ++ p->pPrior = 0; ++ pLimit = p->pLimit; ++ p->pLimit = 0; ++ intersectdest.iSDParm = tab2; ++ ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", ++ selectOpName(p->op))); ++ rc = sqlite3Select(pParse, p, &intersectdest); ++ testcase( rc!=SQLITE_OK ); ++ pDelete = p->pPrior; ++ p->pPrior = pPrior; ++ if( p->nSelectRow>pPrior->nSelectRow ){ ++ p->nSelectRow = pPrior->nSelectRow; ++ } ++ sqlite3ExprDelete(db, p->pLimit); ++ p->pLimit = pLimit; ++ ++ /* Generate code to take the intersection of the two temporary ++ ** tables. ++ */ + assert( p->pEList ); + iBreak = sqlite3VdbeMakeLabel(v); + iCont = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, iBreak); +- sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v); +- iStart = sqlite3VdbeCurrentAddr(v); +- selectInnerLoop(pParse, p, unionTab, ++ sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v); ++ r1 = sqlite3GetTempReg(pParse); ++ iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1); ++ sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); ++ VdbeCoverage(v); ++ sqlite3ReleaseTempReg(pParse, r1); ++ selectInnerLoop(pParse, p, tab1, + 0, 0, &dest, iCont, iBreak); + sqlite3VdbeResolveLabel(v, iCont); +- sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v); ++ sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v); + sqlite3VdbeResolveLabel(v, iBreak); +- sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); ++ sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); ++ sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); ++ break; + } +- break; + } +- default: assert( p->op==TK_INTERSECT ); { +- int tab1, tab2; +- int iCont, iBreak, iStart; +- Expr *pLimit; +- int addr; +- SelectDest intersectdest; +- int r1; +- +- /* INTERSECT is different from the others since it requires +- ** two temporary tables. Hence it has its own case. Begin +- ** by allocating the tables we will need. +- */ +- tab1 = pParse->nTab++; +- tab2 = pParse->nTab++; +- assert( p->pOrderBy==0 ); +- +- addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0); +- assert( p->addrOpenEphm[0] == -1 ); +- p->addrOpenEphm[0] = addr; +- findRightmost(p)->selFlags |= SF_UsesEphemeral; +- assert( p->pEList ); +- +- /* Code the SELECTs to our left into temporary table "tab1". +- */ +- sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1); +- explainSetInteger(iSub1, pParse->iNextSelectId); +- rc = sqlite3Select(pParse, pPrior, &intersectdest); +- if( rc ){ +- goto multi_select_end; +- } +- +- /* Code the current SELECT into temporary table "tab2" +- */ +- addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0); +- assert( p->addrOpenEphm[1] == -1 ); +- p->addrOpenEphm[1] = addr; +- p->pPrior = 0; +- pLimit = p->pLimit; +- p->pLimit = 0; +- intersectdest.iSDParm = tab2; +- explainSetInteger(iSub2, pParse->iNextSelectId); +- rc = sqlite3Select(pParse, p, &intersectdest); +- testcase( rc!=SQLITE_OK ); +- pDelete = p->pPrior; +- p->pPrior = pPrior; +- if( p->nSelectRow>pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow; +- sqlite3ExprDelete(db, p->pLimit); +- p->pLimit = pLimit; +- +- /* Generate code to take the intersection of the two temporary +- ** tables. +- */ +- assert( p->pEList ); +- iBreak = sqlite3VdbeMakeLabel(v); +- iCont = sqlite3VdbeMakeLabel(v); +- computeLimitRegisters(pParse, p, iBreak); +- sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v); +- r1 = sqlite3GetTempReg(pParse); +- iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1); +- sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); VdbeCoverage(v); +- sqlite3ReleaseTempReg(pParse, r1); +- selectInnerLoop(pParse, p, tab1, +- 0, 0, &dest, iCont, iBreak); +- sqlite3VdbeResolveLabel(v, iCont); +- sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v); +- sqlite3VdbeResolveLabel(v, iBreak); +- sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); +- sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); +- break; ++ ++ #ifndef SQLITE_OMIT_EXPLAIN ++ if( p->pNext==0 ){ ++ ExplainQueryPlanPop(pParse); + } ++ #endif + } +- +- explainComposite(pParse, p->op, iSub1, iSub2, p->op!=TK_ALL); +- ++ + /* Compute collating sequences used by + ** temporary tables needed to implement the compound select. + ** Attach the KeyInfo structure to all temporary tables. +@@ -122976,7 +126860,6 @@ + r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, + r1, pDest->zAffSdst, pIn->nSdst); +- sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1, + pIn->iSdst, pIn->nSdst); + sqlite3ReleaseTempReg(pParse, r1); +@@ -123019,7 +126902,6 @@ + default: { + assert( pDest->eDest==SRT_Output ); + sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iSdst, pIn->nSdst); +- sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst); + break; + } + } +@@ -123163,10 +127045,6 @@ + ExprList *pOrderBy; /* The ORDER BY clause */ + int nOrderBy; /* Number of terms in the ORDER BY clause */ + int *aPermute; /* Mapping from ORDER BY terms to result set columns */ +-#ifndef SQLITE_OMIT_EXPLAIN +- int iSub1; /* EQP id of left-hand query */ +- int iSub2; /* EQP id of right-hand query */ +-#endif + + assert( p->pOrderBy!=0 ); + assert( pKeyDup==0 ); /* "Managed" code needs this. Ticket #3382. */ +@@ -123286,6 +127164,8 @@ + sqlite3SelectDestInit(&destA, SRT_Coroutine, regAddrA); + sqlite3SelectDestInit(&destB, SRT_Coroutine, regAddrB); + ++ ExplainQueryPlan((pParse, 1, "MERGE (%s)", selectOpName(p->op))); ++ + /* Generate a coroutine to evaluate the SELECT statement to the + ** left of the compound operator - the "A" select. + */ +@@ -123293,7 +127173,7 @@ + addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA); + VdbeComment((v, "left SELECT")); + pPrior->iLimit = regLimitA; +- explainSetInteger(iSub1, pParse->iNextSelectId); ++ ExplainQueryPlan((pParse, 1, "LEFT")); + sqlite3Select(pParse, pPrior, &destA); + sqlite3VdbeEndCoroutine(v, regAddrA); + sqlite3VdbeJumpHere(v, addr1); +@@ -123308,7 +127188,7 @@ + savedOffset = p->iOffset; + p->iLimit = regLimitB; + p->iOffset = 0; +- explainSetInteger(iSub2, pParse->iNextSelectId); ++ ExplainQueryPlan((pParse, 1, "RIGHT")); + sqlite3Select(pParse, p, &destB); + p->iLimit = savedLimit; + p->iOffset = savedOffset; +@@ -123420,7 +127300,7 @@ + + /*** TBD: Insert subroutine calls to close cursors on incomplete + **** subqueries ****/ +- explainComposite(pParse, p->op, iSub1, iSub2, 0); ++ ExplainQueryPlanPop(pParse); + return pParse->nErr!=0; + } + #endif +@@ -123476,7 +127356,7 @@ + Expr *pCopy = pSubst->pEList->a[pExpr->iColumn].pExpr; + Expr ifNullRow; + assert( pSubst->pEList!=0 && pExpr->iColumn<pSubst->pEList->nExpr ); +- assert( pExpr->pLeft==0 && pExpr->pRight==0 ); ++ assert( pExpr->pRight==0 ); + if( sqlite3ExprIsVector(pCopy) ){ + sqlite3VectorErrorMsg(pSubst->pParse, pCopy); + }else{ +@@ -123690,7 +127570,11 @@ + ** "SELECT x FROM (SELECT max(y), x FROM t1)" would not necessarily + ** return the value X for which Y was maximal.) + ** ++** (25) If either the subquery or the parent query contains a window ++** function in the select list or ORDER BY clause, flattening ++** is not attempted. + ** ++** + ** In this routine, the "p" parameter is a pointer to the outer query. + ** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query + ** uses aggregates. +@@ -123733,6 +127617,10 @@ + pSub = pSubitem->pSelect; + assert( pSub!=0 ); + ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( p->pWin || pSub->pWin ) return 0; /* Restriction (25) */ ++#endif ++ + pSubSrc = pSub->pSrc; + assert( pSubSrc ); + /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants, +@@ -123843,8 +127731,8 @@ + assert( (p->selFlags & SF_Recursive)==0 || pSub->pPrior==0 ); + + /***** If we reach this point, flattening is permitted. *****/ +- SELECTTRACE(1,pParse,p,("flatten %s.%p from term %d\n", +- pSub->zSelName, pSub, iFrom)); ++ SELECTTRACE(1,pParse,p,("flatten %u.%p from term %d\n", ++ pSub->selId, pSub, iFrom)); + + /* Authorize the subquery */ + pParse->zAuthContext = pSubitem->zName; +@@ -123895,7 +127783,6 @@ + p->pPrior = 0; + p->pLimit = 0; + pNew = sqlite3SelectDup(db, p, 0); +- sqlite3SelectSetName(pNew, pSub->zSelName); + p->pLimit = pLimit; + p->pOrderBy = pOrderBy; + p->pSrc = pSrc; +@@ -123907,9 +127794,8 @@ + if( pPrior ) pPrior->pNext = pNew; + pNew->pNext = p; + p->pPrior = pNew; +- SELECTTRACE(2,pParse,p, +- ("compound-subquery flattener creates %s.%p as peer\n", +- pNew->zSelName, pNew)); ++ SELECTTRACE(2,pParse,p,("compound-subquery flattener" ++ " creates %u as peer\n",pNew->selId)); + } + if( db->mallocFailed ) return 1; + } +@@ -124094,8 +127980,184 @@ + } + #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ + ++/* ++** A structure to keep track of all of the column values that are fixed to ++** a known value due to WHERE clause constraints of the form COLUMN=VALUE. ++*/ ++typedef struct WhereConst WhereConst; ++struct WhereConst { ++ Parse *pParse; /* Parsing context */ ++ int nConst; /* Number for COLUMN=CONSTANT terms */ ++ int nChng; /* Number of times a constant is propagated */ ++ Expr **apExpr; /* [i*2] is COLUMN and [i*2+1] is VALUE */ ++}; + ++/* ++** Add a new entry to the pConst object. Except, do not add duplicate ++** pColumn entires. ++*/ ++static void constInsert( ++ WhereConst *pConst, /* The WhereConst into which we are inserting */ ++ Expr *pColumn, /* The COLUMN part of the constraint */ ++ Expr *pValue /* The VALUE part of the constraint */ ++){ ++ int i; ++ assert( pColumn->op==TK_COLUMN ); + ++ /* 2018-10-25 ticket [cf5ed20f] ++ ** Make sure the same pColumn is not inserted more than once */ ++ for(i=0; i<pConst->nConst; i++){ ++ const Expr *pExpr = pConst->apExpr[i*2]; ++ assert( pExpr->op==TK_COLUMN ); ++ if( pExpr->iTable==pColumn->iTable ++ && pExpr->iColumn==pColumn->iColumn ++ ){ ++ return; /* Already present. Return without doing anything. */ ++ } ++ } ++ ++ pConst->nConst++; ++ pConst->apExpr = sqlite3DbReallocOrFree(pConst->pParse->db, pConst->apExpr, ++ pConst->nConst*2*sizeof(Expr*)); ++ if( pConst->apExpr==0 ){ ++ pConst->nConst = 0; ++ }else{ ++ if( ExprHasProperty(pValue, EP_FixedCol) ) pValue = pValue->pLeft; ++ pConst->apExpr[pConst->nConst*2-2] = pColumn; ++ pConst->apExpr[pConst->nConst*2-1] = pValue; ++ } ++} ++ ++/* ++** Find all terms of COLUMN=VALUE or VALUE=COLUMN in pExpr where VALUE ++** is a constant expression and where the term must be true because it ++** is part of the AND-connected terms of the expression. For each term ++** found, add it to the pConst structure. ++*/ ++static void findConstInWhere(WhereConst *pConst, Expr *pExpr){ ++ Expr *pRight, *pLeft; ++ if( pExpr==0 ) return; ++ if( ExprHasProperty(pExpr, EP_FromJoin) ) return; ++ if( pExpr->op==TK_AND ){ ++ findConstInWhere(pConst, pExpr->pRight); ++ findConstInWhere(pConst, pExpr->pLeft); ++ return; ++ } ++ if( pExpr->op!=TK_EQ ) return; ++ pRight = pExpr->pRight; ++ pLeft = pExpr->pLeft; ++ assert( pRight!=0 ); ++ assert( pLeft!=0 ); ++ if( pRight->op==TK_COLUMN ++ && !ExprHasProperty(pRight, EP_FixedCol) ++ && sqlite3ExprIsConstant(pLeft) ++ && sqlite3IsBinary(sqlite3BinaryCompareCollSeq(pConst->pParse,pLeft,pRight)) ++ ){ ++ constInsert(pConst, pRight, pLeft); ++ }else ++ if( pLeft->op==TK_COLUMN ++ && !ExprHasProperty(pLeft, EP_FixedCol) ++ && sqlite3ExprIsConstant(pRight) ++ && sqlite3IsBinary(sqlite3BinaryCompareCollSeq(pConst->pParse,pLeft,pRight)) ++ ){ ++ constInsert(pConst, pLeft, pRight); ++ } ++} ++ ++/* ++** This is a Walker expression callback. pExpr is a candidate expression ++** to be replaced by a value. If pExpr is equivalent to one of the ++** columns named in pWalker->u.pConst, then overwrite it with its ++** corresponding value. ++*/ ++static int propagateConstantExprRewrite(Walker *pWalker, Expr *pExpr){ ++ int i; ++ WhereConst *pConst; ++ if( pExpr->op!=TK_COLUMN ) return WRC_Continue; ++ if( ExprHasProperty(pExpr, EP_FixedCol) ) return WRC_Continue; ++ pConst = pWalker->u.pConst; ++ for(i=0; i<pConst->nConst; i++){ ++ Expr *pColumn = pConst->apExpr[i*2]; ++ if( pColumn==pExpr ) continue; ++ if( pColumn->iTable!=pExpr->iTable ) continue; ++ if( pColumn->iColumn!=pExpr->iColumn ) continue; ++ /* A match is found. Add the EP_FixedCol property */ ++ pConst->nChng++; ++ ExprClearProperty(pExpr, EP_Leaf); ++ ExprSetProperty(pExpr, EP_FixedCol); ++ assert( pExpr->pLeft==0 ); ++ pExpr->pLeft = sqlite3ExprDup(pConst->pParse->db, pConst->apExpr[i*2+1], 0); ++ break; ++ } ++ return WRC_Prune; ++} ++ ++/* ++** The WHERE-clause constant propagation optimization. ++** ++** If the WHERE clause contains terms of the form COLUMN=CONSTANT or ++** CONSTANT=COLUMN that must be tree (in other words, if the terms top-level ++** AND-connected terms that are not part of a ON clause from a LEFT JOIN) ++** then throughout the query replace all other occurrences of COLUMN ++** with CONSTANT within the WHERE clause. ++** ++** For example, the query: ++** ++** SELECT * FROM t1, t2, t3 WHERE t1.a=39 AND t2.b=t1.a AND t3.c=t2.b ++** ++** Is transformed into ++** ++** SELECT * FROM t1, t2, t3 WHERE t1.a=39 AND t2.b=39 AND t3.c=39 ++** ++** Return true if any transformations where made and false if not. ++** ++** Implementation note: Constant propagation is tricky due to affinity ++** and collating sequence interactions. Consider this example: ++** ++** CREATE TABLE t1(a INT,b TEXT); ++** INSERT INTO t1 VALUES(123,'0123'); ++** SELECT * FROM t1 WHERE a=123 AND b=a; ++** SELECT * FROM t1 WHERE a=123 AND b=123; ++** ++** The two SELECT statements above should return different answers. b=a ++** is alway true because the comparison uses numeric affinity, but b=123 ++** is false because it uses text affinity and '0123' is not the same as '123'. ++** To work around this, the expression tree is not actually changed from ++** "b=a" to "b=123" but rather the "a" in "b=a" is tagged with EP_FixedCol ++** and the "123" value is hung off of the pLeft pointer. Code generator ++** routines know to generate the constant "123" instead of looking up the ++** column value. Also, to avoid collation problems, this optimization is ++** only attempted if the "a=123" term uses the default BINARY collation. ++*/ ++static int propagateConstants( ++ Parse *pParse, /* The parsing context */ ++ Select *p /* The query in which to propagate constants */ ++){ ++ WhereConst x; ++ Walker w; ++ int nChng = 0; ++ x.pParse = pParse; ++ do{ ++ x.nConst = 0; ++ x.nChng = 0; ++ x.apExpr = 0; ++ findConstInWhere(&x, p->pWhere); ++ if( x.nConst ){ ++ memset(&w, 0, sizeof(w)); ++ w.pParse = pParse; ++ w.xExprCallback = propagateConstantExprRewrite; ++ w.xSelectCallback = sqlite3SelectWalkNoop; ++ w.xSelectCallback2 = 0; ++ w.walkerDepth = 0; ++ w.u.pConst = &x; ++ sqlite3WalkExpr(&w, p->pWhere); ++ sqlite3DbFree(x.pParse->db, x.apExpr); ++ nChng += x.nChng; ++ } ++ }while( x.nChng ); ++ return nChng; ++} ++ + #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) + /* + ** Make copies of relevant WHERE clause terms of the outer query into +@@ -124124,7 +128186,7 @@ + ** (2) The inner query is the recursive part of a common table expression. + ** + ** (3) The inner query has a LIMIT clause (since the changes to the WHERE +-** close would change the meaning of the LIMIT). ++** clause would change the meaning of the LIMIT). + ** + ** (4) The inner query is the right operand of a LEFT JOIN and the + ** expression to be pushed down does not come from the ON clause +@@ -124143,6 +128205,10 @@ + ** But if the (b2=2) term were to be pushed down into the bb subquery, + ** then the (1,1,NULL) row would be suppressed. + ** ++** (6) The inner query features one or more window-functions (since ++** changes to the WHERE clause of the inner query could change the ++** window over which window functions are calculated). ++** + ** Return 0 if no changes are made and non-zero if one or more WHERE clause + ** terms are duplicated into the subquery. + */ +@@ -124158,6 +128224,10 @@ + if( pWhere==0 ) return 0; + if( pSubq->selFlags & SF_Recursive ) return 0; /* restriction (2) */ + ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( pSubq->pWin ) return 0; /* restriction (6) */ ++#endif ++ + #ifdef SQLITE_DEBUG + /* Only the first term of a compound can have a WITH clause. But make + ** sure no other terms are marked SF_Recursive in case something changes +@@ -124604,6 +128674,35 @@ + #endif + + /* ++** The SrcList_item structure passed as the second argument represents a ++** sub-query in the FROM clause of a SELECT statement. This function ++** allocates and populates the SrcList_item.pTab object. If successful, ++** SQLITE_OK is returned. Otherwise, if an OOM error is encountered, ++** SQLITE_NOMEM. ++*/ ++SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse *pParse, struct SrcList_item *pFrom){ ++ Select *pSel = pFrom->pSelect; ++ Table *pTab; ++ ++ assert( pSel ); ++ pFrom->pTab = pTab = sqlite3DbMallocZero(pParse->db, sizeof(Table)); ++ if( pTab==0 ) return SQLITE_NOMEM; ++ pTab->nTabRef = 1; ++ if( pFrom->zAlias ){ ++ pTab->zName = sqlite3DbStrDup(pParse->db, pFrom->zAlias); ++ }else{ ++ pTab->zName = sqlite3MPrintf(pParse->db, "subquery_%u", pSel->selId); ++ } ++ while( pSel->pPrior ){ pSel = pSel->pPrior; } ++ sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol); ++ pTab->iPKey = -1; ++ pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); ++ pTab->tabFlags |= TF_Ephemeral; ++ ++ return SQLITE_OK; ++} ++ ++/* + ** This routine is a Walker callback for "expanding" a SELECT statement. + ** "Expanding" means to do the following: + ** +@@ -124675,19 +128774,7 @@ + assert( pSel!=0 ); + assert( pFrom->pTab==0 ); + if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort; +- pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); +- if( pTab==0 ) return WRC_Abort; +- pTab->nTabRef = 1; +- if( pFrom->zAlias ){ +- pTab->zName = sqlite3DbStrDup(db, pFrom->zAlias); +- }else{ +- pTab->zName = sqlite3MPrintf(db, "subquery_%p", (void*)pTab); +- } +- while( pSel->pPrior ){ pSel = pSel->pPrior; } +- sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol); +- pTab->iPKey = -1; +- pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); +- pTab->tabFlags |= TF_Ephemeral; ++ if( sqlite3ExpandSubquery(pParse, pFrom) ) return WRC_Abort; + #endif + }else{ + /* An ordinary table or view name in the FROM clause */ +@@ -124710,7 +128797,6 @@ + if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort; + assert( pFrom->pSelect==0 ); + pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0); +- sqlite3SelectSetName(pFrom->pSelect, pTab->zName); + nCol = pTab->nCol; + pTab->nCol = -1; + sqlite3WalkSelect(pWalker, pFrom->pSelect); +@@ -124988,7 +129074,7 @@ + struct SrcList_item *pFrom; + + assert( p->selFlags & SF_Resolved ); +- assert( (p->selFlags & SF_HasTypeInfo)==0 ); ++ if( p->selFlags & SF_HasTypeInfo ) return; + p->selFlags |= SF_HasTypeInfo; + pParse = pWalker->pParse; + pTabList = p->pSrc; +@@ -125091,7 +129177,7 @@ + "argument"); + pFunc->iDistinct = -1; + }else{ +- KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->x.pList, 0, 0); ++ KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pE->x.pList,0,0); + sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0, + (char*)pKeyInfo, P4_KEYINFO); + } +@@ -125115,11 +129201,17 @@ + } + } + ++ + /* + ** Update the accumulator memory cells for an aggregate based on + ** the current cursor position. ++** ++** If regAcc is non-zero and there are no min() or max() aggregates ++** in pAggInfo, then only populate the pAggInfo->nAccumulator accumulator ++** registers i register regAcc contains 0. The caller will take care ++** of setting and clearing regAcc. + */ +-static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ ++static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){ + Vdbe *v = pParse->pVdbe; + int i; + int regHit = 0; +@@ -125162,36 +129254,24 @@ + if( regHit==0 && pAggInfo->nAccumulator ) regHit = ++pParse->nMem; + sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0, (char *)pColl, P4_COLLSEQ); + } +- sqlite3VdbeAddOp3(v, OP_AggStep0, 0, regAgg, pF->iMem); ++ sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, pF->iMem); + sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); + sqlite3VdbeChangeP5(v, (u8)nArg); +- sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg); + sqlite3ReleaseTempRange(pParse, regAgg, nArg); + if( addrNext ){ + sqlite3VdbeResolveLabel(v, addrNext); +- sqlite3ExprCacheClear(pParse); + } + } +- +- /* Before populating the accumulator registers, clear the column cache. +- ** Otherwise, if any of the required column values are already present +- ** in registers, sqlite3ExprCode() may use OP_SCopy to copy the value +- ** to pC->iMem. But by the time the value is used, the original register +- ** may have been used, invalidating the underlying buffer holding the +- ** text or blob value. See ticket [883034dcb5]. +- ** +- ** Another solution would be to change the OP_SCopy used to copy cached +- ** values to an OP_Copy. +- */ ++ if( regHit==0 && pAggInfo->nAccumulator ){ ++ regHit = regAcc; ++ } + if( regHit ){ + addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); VdbeCoverage(v); + } +- sqlite3ExprCacheClear(pParse); + for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){ + sqlite3ExprCode(pParse, pC->pExpr, pC->iMem); + } + pAggInfo->directMode = 0; +- sqlite3ExprCacheClear(pParse); + if( addrHitTest ){ + sqlite3VdbeJumpHere(v, addrHitTest); + } +@@ -125209,14 +129289,11 @@ + ){ + if( pParse->explain==2 ){ + int bCover = (pIdx!=0 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pIdx))); +- char *zEqp = sqlite3MPrintf(pParse->db, "SCAN TABLE %s%s%s", ++ sqlite3VdbeExplain(pParse, 0, "SCAN TABLE %s%s%s", + pTab->zName, + bCover ? " USING COVERING INDEX " : "", + bCover ? pIdx->zName : "" + ); +- sqlite3VdbeAddOp4( +- pParse->pVdbe, OP_Explain, pParse->iSelectId, 0, 0, zEqp, P4_DYNAMIC +- ); + } + } + #else +@@ -125324,6 +129401,7 @@ + ** The transformation only works if all of the following are true: + ** + ** * The subquery is a UNION ALL of two or more terms ++** * The subquery does not have a LIMIT clause + ** * There is no WHERE or GROUP BY or HAVING clauses on the subqueries + ** * The outer query is a simple count(*) + ** +@@ -125347,6 +129425,7 @@ + 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 ); +@@ -125429,12 +129508,8 @@ + ExprList *pMinMaxOrderBy = 0; /* Added ORDER BY for min/max queries */ + u8 minMaxFlag; /* Flag for min/max queries */ + +-#ifndef SQLITE_OMIT_EXPLAIN +- int iRestoreSelectId = pParse->iSelectId; +- pParse->iSelectId = pParse->iNextSelectId++; +-#endif +- + db = pParse->db; ++ v = sqlite3GetVdbe(pParse); + if( p==0 || db->mallocFailed || pParse->nErr ){ + return 1; + } +@@ -125441,7 +129516,7 @@ + if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; + memset(&sAggInfo, 0, sizeof(sAggInfo)); + #if SELECTTRACE_ENABLED +- SELECTTRACE(1,pParse,p, ("begin processing:\n")); ++ SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->addrExplain)); + if( sqlite3SelectTrace & 0x100 ){ + sqlite3TreeViewSelect(0, p, 0); + } +@@ -125463,29 +129538,37 @@ + p->selFlags &= ~SF_Distinct; + } + sqlite3SelectPrep(pParse, p, 0); +- memset(&sSort, 0, sizeof(sSort)); +- sSort.pOrderBy = p->pOrderBy; +- pTabList = p->pSrc; + if( pParse->nErr || db->mallocFailed ){ + goto select_end; + } + assert( p->pEList!=0 ); +- isAgg = (p->selFlags & SF_Aggregate)!=0; + #if SELECTTRACE_ENABLED +- if( sqlite3SelectTrace & 0x100 ){ +- SELECTTRACE(0x100,pParse,p, ("after name resolution:\n")); ++ if( sqlite3SelectTrace & 0x104 ){ ++ SELECTTRACE(0x104,pParse,p, ("after name resolution:\n")); + sqlite3TreeViewSelect(0, p, 0); + } + #endif + +- /* Get a pointer the VDBE under construction, allocating a new VDBE if one +- ** does not already exist */ +- v = sqlite3GetVdbe(pParse); +- if( v==0 ) goto select_end; + if( pDest->eDest==SRT_Output ){ + generateColumnNames(pParse, p); + } + ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( sqlite3WindowRewrite(pParse, p) ){ ++ goto select_end; ++ } ++#if SELECTTRACE_ENABLED ++ if( sqlite3SelectTrace & 0x108 ){ ++ SELECTTRACE(0x104,pParse,p, ("after window rewrite:\n")); ++ sqlite3TreeViewSelect(0, p, 0); ++ } ++#endif ++#endif /* SQLITE_OMIT_WINDOWFUNC */ ++ pTabList = p->pSrc; ++ isAgg = (p->selFlags & SF_Aggregate)!=0; ++ memset(&sSort, 0, sizeof(sSort)); ++ sSort.pOrderBy = p->pOrderBy; ++ + /* Try to various optimizations (flattening subqueries, and strength + ** reduction of join operators) in the FROM clause up into the main query + */ +@@ -125574,14 +129657,46 @@ + */ + if( p->pPrior ){ + rc = multiSelect(pParse, p, pDest); +- explainSetInteger(pParse->iSelectId, iRestoreSelectId); + #if SELECTTRACE_ENABLED +- SELECTTRACE(1,pParse,p,("end compound-select processing\n")); ++ SELECTTRACE(0x1,pParse,p,("end compound-select processing\n")); ++ if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){ ++ sqlite3TreeViewSelect(0, p, 0); ++ } + #endif ++ if( p->pNext==0 ) ExplainQueryPlanPop(pParse); + return rc; + } + #endif + ++ /* Do the WHERE-clause constant propagation optimization if this is ++ ** a join. No need to speed time on this operation for non-join queries ++ ** as the equivalent optimization will be handled by query planner in ++ ** sqlite3WhereBegin(). ++ */ ++ if( pTabList->nSrc>1 ++ && OptimizationEnabled(db, SQLITE_PropagateConst) ++ && propagateConstants(pParse, p) ++ ){ ++#if SELECTTRACE_ENABLED ++ if( sqlite3SelectTrace & 0x100 ){ ++ SELECTTRACE(0x100,pParse,p,("After constant propagation:\n")); ++ sqlite3TreeViewSelect(0, p, 0); ++ } ++#endif ++ }else{ ++ SELECTTRACE(0x100,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 +@@ -125655,7 +129770,8 @@ + ){ + #if SELECTTRACE_ENABLED + if( sqlite3SelectTrace & 0x100 ){ +- SELECTTRACE(0x100,pParse,p,("After WHERE-clause push-down:\n")); ++ SELECTTRACE(0x100,pParse,p, ++ ("After WHERE-clause push-down into subquery %d:\n", pSub->selId)); + sqlite3TreeViewSelect(0, p, 0); + } + #endif +@@ -125689,7 +129805,7 @@ + VdbeComment((v, "%s", pItem->pTab->zName)); + pItem->addrFillSub = addrTop; + sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn); +- explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); ++ ExplainQueryPlan((pParse, 1, "CO-ROUTINE %u", pSub->selId)); + sqlite3Select(pParse, pSub, &dest); + pItem->pTab->nRowLogEst = pSub->nSelectRow; + pItem->fg.viaCoroutine = 1; +@@ -125724,12 +129840,11 @@ + pPrior = isSelfJoinView(pTabList, pItem); + if( pPrior ){ + sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor); +- explainSetInteger(pItem->iSelectId, pPrior->iSelectId); + assert( pPrior->pSelect!=0 ); + pSub->nSelectRow = pPrior->pSelect->nSelectRow; + }else{ + sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); +- explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); ++ ExplainQueryPlan((pParse, 1, "MATERIALIZE %u", pSub->selId)); + sqlite3Select(pParse, pSub, &dest); + } + pItem->pTab->nRowLogEst = pSub->nSelectRow; +@@ -125760,16 +129875,6 @@ + } + #endif + +-#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 +- + /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and + ** if the select-list is the same as the ORDER BY list, then this query + ** can be rewritten as a GROUP BY. In other words, this: +@@ -125813,7 +129918,8 @@ + */ + if( sSort.pOrderBy ){ + KeyInfo *pKeyInfo; +- pKeyInfo = keyInfoFromExprList(pParse, sSort.pOrderBy, 0, pEList->nExpr); ++ pKeyInfo = sqlite3KeyInfoFromExprList( ++ pParse, sSort.pOrderBy, 0, pEList->nExpr); + sSort.iECursor = pParse->nTab++; + sSort.addrSortIndex = + sqlite3VdbeAddOp4(v, OP_OpenEphemeral, +@@ -125847,9 +129953,9 @@ + if( p->selFlags & SF_Distinct ){ + sDistinct.tabTnct = pParse->nTab++; + sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, +- sDistinct.tabTnct, 0, 0, +- (char*)keyInfoFromExprList(pParse, p->pEList,0,0), +- P4_KEYINFO); ++ sDistinct.tabTnct, 0, 0, ++ (char*)sqlite3KeyInfoFromExprList(pParse, p->pEList,0,0), ++ P4_KEYINFO); + sqlite3VdbeChangeP5(v, BTREE_UNORDERED); + sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED; + }else{ +@@ -125858,10 +129964,17 @@ + + if( !isAgg && pGroupBy==0 ){ + /* No aggregate functions and no GROUP BY clause */ +- u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0); ++ u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0) ++ | (p->selFlags & SF_FixedLimit); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ Window *pWin = p->pWin; /* Master window object (or NULL) */ ++ if( pWin ){ ++ sqlite3WindowCodeInit(pParse, pWin); ++ } ++#endif + assert( WHERE_USE_LIMIT==SF_FixedLimit ); +- wctrlFlags |= p->selFlags & SF_FixedLimit; + ++ + /* Begin the database scan. */ + SELECTTRACE(1,pParse,p,("WhereBegin\n")); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy, +@@ -125875,7 +129988,7 @@ + } + if( sSort.pOrderBy ){ + sSort.nOBSat = sqlite3WhereIsOrdered(pWInfo); +- sSort.bOrderedInnerLoop = sqlite3WhereOrderedInnerLoop(pWInfo); ++ sSort.labelOBLopt = sqlite3WhereOrderByLimitOptLabel(pWInfo); + if( sSort.nOBSat==sSort.pOrderBy->nExpr ){ + sSort.pOrderBy = 0; + } +@@ -125889,15 +130002,37 @@ + sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex); + } + +- /* Use the standard inner loop. */ + assert( p->pEList==pEList ); +- selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, +- sqlite3WhereContinueLabel(pWInfo), +- sqlite3WhereBreakLabel(pWInfo)); ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( pWin ){ ++ int addrGosub = sqlite3VdbeMakeLabel(v); ++ int iCont = sqlite3VdbeMakeLabel(v); ++ int iBreak = sqlite3VdbeMakeLabel(v); ++ int regGosub = ++pParse->nMem; + +- /* End the database scan loop. +- */ +- sqlite3WhereEnd(pWInfo); ++ sqlite3WindowCodeStep(pParse, p, pWInfo, regGosub, addrGosub); ++ ++ sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak); ++ sqlite3VdbeResolveLabel(v, addrGosub); ++ VdbeNoopComment((v, "inner-loop subroutine")); ++ sSort.labelOBLopt = 0; ++ selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, iCont, iBreak); ++ sqlite3VdbeResolveLabel(v, iCont); ++ sqlite3VdbeAddOp1(v, OP_Return, regGosub); ++ VdbeComment((v, "end inner-loop subroutine")); ++ sqlite3VdbeResolveLabel(v, iBreak); ++ }else ++#endif /* SQLITE_OMIT_WINDOWFUNC */ ++ { ++ /* Use the standard inner loop. */ ++ selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, ++ sqlite3WhereContinueLabel(pWInfo), ++ sqlite3WhereBreakLabel(pWInfo)); ++ ++ /* End the database scan loop. ++ */ ++ sqlite3WhereEnd(pWInfo); ++ } + }else{ + /* This case when there exist aggregate functions or a GROUP BY clause + ** or both */ +@@ -125956,7 +130091,8 @@ + memset(&sNC, 0, sizeof(sNC)); + sNC.pParse = pParse; + sNC.pSrcList = pTabList; +- sNC.pAggInfo = &sAggInfo; ++ sNC.uNC.pAggInfo = &sAggInfo; ++ VVA_ONLY( sNC.ncFlags = NC_UAggInfo; ) + sAggInfo.mnReg = pParse->nMem+1; + sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr : 0; + sAggInfo.pGroupBy = pGroupBy; +@@ -126025,7 +130161,7 @@ + ** will be converted into a Noop. + */ + sAggInfo.sortingIdx = pParse->nTab++; +- pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0, sAggInfo.nColumn); ++ pKeyInfo = sqlite3KeyInfoFromExprList(pParse,pGroupBy,0,sAggInfo.nColumn); + addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen, + sAggInfo.sortingIdx, sAggInfo.nSortingColumn, + 0, (char*)pKeyInfo, P4_KEYINFO); +@@ -126044,8 +130180,6 @@ + pParse->nMem += pGroupBy->nExpr; + sqlite3VdbeAddOp2(v, OP_Integer, 0, iAbortFlag); + VdbeComment((v, "clear abort flag")); +- sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag); +- VdbeComment((v, "indicate accumulator empty")); + sqlite3VdbeAddOp3(v, OP_Null, 0, iAMem, iAMem+pGroupBy->nExpr-1); + + /* Begin a loop that will extract all source rows in GROUP BY order. +@@ -126091,7 +130225,6 @@ + } + } + regBase = sqlite3GetTempRange(pParse, nCol); +- sqlite3ExprCacheClear(pParse); + sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0, 0); + j = nGroupBy; + for(i=0; i<sAggInfo.nColumn; i++){ +@@ -126098,8 +130231,8 @@ + struct AggInfo_col *pCol = &sAggInfo.aCol[i]; + if( pCol->iSorterColumn>=j ){ + int r1 = j + regBase; +- sqlite3ExprCodeGetColumnToReg(pParse, +- pCol->pTab, pCol->iColumn, pCol->iTable, r1); ++ sqlite3ExprCodeGetColumnOfTable(v, ++ pCol->pTab, pCol->iTable, pCol->iColumn, r1); + j++; + } + } +@@ -126115,8 +130248,6 @@ + sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd); + VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v); + sAggInfo.useSortingIdx = 1; +- sqlite3ExprCacheClear(pParse); +- + } + + /* If the index or temporary table used by the GROUP BY sort +@@ -126139,7 +130270,6 @@ + ** from the previous row currently stored in a0, a1, a2... + */ + addrTopOfLoop = sqlite3VdbeCurrentAddr(v); +- sqlite3ExprCacheClear(pParse); + if( groupBySort ){ + sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx, + sortOut, sortPTab); +@@ -126178,7 +130308,7 @@ + ** the current row + */ + sqlite3VdbeJumpHere(v, addr1); +- updateAccumulator(pParse, &sAggInfo); ++ updateAccumulator(pParse, iUseFlag, &sAggInfo); + sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag); + VdbeComment((v, "indicate data in accumulator")); + +@@ -126230,6 +130360,8 @@ + */ + sqlite3VdbeResolveLabel(v, addrReset); + resetAccumulator(pParse, &sAggInfo); ++ sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag); ++ VdbeComment((v, "indicate accumulator empty")); + sqlite3VdbeAddOp1(v, OP_Return, regReset); + + } /* endif pGroupBy. Begin aggregate queries without GROUP BY: */ +@@ -126295,6 +130427,23 @@ + }else + #endif /* SQLITE_OMIT_BTREECOUNT */ + { ++ int regAcc = 0; /* "populate accumulators" flag */ ++ ++ /* If there are accumulator registers but no min() or max() functions, ++ ** allocate register regAcc. Register regAcc will contain 0 the first ++ ** time the inner loop runs, and 1 thereafter. The code generated ++ ** by updateAccumulator() only updates the accumulator registers if ++ ** regAcc contains 0. */ ++ if( sAggInfo.nAccumulator ){ ++ for(i=0; i<sAggInfo.nFunc; i++){ ++ if( sAggInfo.aFunc[i].pFunc->funcFlags&SQLITE_FUNC_NEEDCOLL ) break; ++ } ++ if( i==sAggInfo.nFunc ){ ++ regAcc = ++pParse->nMem; ++ sqlite3VdbeAddOp2(v, OP_Integer, 0, regAcc); ++ } ++ } ++ + /* This case runs if the aggregate has no GROUP BY clause. The + ** processing is much simpler since there is only a single row + ** of output. +@@ -126316,7 +130465,8 @@ + if( pWInfo==0 ){ + goto select_end; + } +- updateAccumulator(pParse, &sAggInfo); ++ updateAccumulator(pParse, regAcc, &sAggInfo); ++ if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc); + if( sqlite3WhereIsOrdered(pWInfo)>0 ){ + sqlite3VdbeGoto(v, sqlite3WhereBreakLabel(pWInfo)); + VdbeComment((v, "%s() by index", +@@ -126345,6 +130495,7 @@ + if( sSort.pOrderBy ){ + explainTempTable(pParse, + sSort.nOBSat>0 ? "RIGHT PART OF ORDER BY":"ORDER BY"); ++ assert( p->pEList==pEList ); + generateSortTail(pParse, p, &sSort, pEList->nExpr, pDest); + } + +@@ -126360,13 +130511,16 @@ + ** successful coding of the SELECT. + */ + select_end: +- explainSetInteger(pParse->iSelectId, iRestoreSelectId); + sqlite3ExprListDelete(db, pMinMaxOrderBy); + sqlite3DbFree(db, sAggInfo.aCol); + sqlite3DbFree(db, sAggInfo.aFunc); + #if SELECTTRACE_ENABLED +- SELECTTRACE(1,pParse,p,("end processing\n")); ++ SELECTTRACE(0x1,pParse,p,("end processing\n")); ++ if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){ ++ sqlite3TreeViewSelect(0, p, 0); ++ } + #endif ++ ExplainQueryPlanPop(pParse); + return rc; + } + +@@ -126600,6 +130754,7 @@ + sqlite3ExprListDelete(db, pTmp->pExprList); + sqlite3SelectDelete(db, pTmp->pSelect); + sqlite3IdListDelete(db, pTmp->pIdList); ++ sqlite3UpsertDelete(db, pTmp->pUpsert); + sqlite3DbFree(db, pTmp->zSpan); + + sqlite3DbFree(db, pTmp); +@@ -126755,14 +130910,16 @@ + goto trigger_cleanup; + } + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); +- 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); ++ 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; + } +- goto trigger_cleanup; + } + + /* Do not create a trigger on a system table */ +@@ -126786,7 +130943,7 @@ + } + + #ifndef SQLITE_OMIT_AUTHORIZATION +- { ++ if( !IN_RENAME_OBJECT ){ + int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); + int code = SQLITE_CREATE_TRIGGER; + const char *zDb = db->aDb[iTabDb].zDbSName; +@@ -126820,8 +130977,15 @@ + pTrigger->pTabSchema = pTab->pSchema; + pTrigger->op = (u8)op; + pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER; +- pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); +- pTrigger->pColumns = sqlite3IdListDup(db, pColumns); ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameTokenRemap(pParse, pTrigger->table, pTableName->a[0].zName); ++ pTrigger->pWhen = pWhen; ++ pWhen = 0; ++ }else{ ++ pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); ++ } ++ pTrigger->pColumns = pColumns; ++ pColumns = 0; + assert( pParse->pNewTrigger==0 ); + pParse->pNewTrigger = pTrigger; + +@@ -126870,6 +131034,14 @@ + goto triggerfinish_cleanup; + } + ++#ifndef SQLITE_OMIT_ALTERTABLE ++ if( IN_RENAME_OBJECT ){ ++ assert( !db->init.busy ); ++ pParse->pNewTrigger = pTrig; ++ pTrig = 0; ++ }else ++#endif ++ + /* if we are not initializing, + ** build the sqlite_master entry + */ +@@ -126911,7 +131083,7 @@ + + triggerfinish_cleanup: + sqlite3DeleteTrigger(db, pTrig); +- assert( !pParse->pNewTrigger ); ++ assert( IN_RENAME_OBJECT || !pParse->pNewTrigger ); + sqlite3DeleteTriggerStep(db, pStepList); + } + +@@ -126958,12 +131130,13 @@ + ** If an OOM error occurs, NULL is returned and db->mallocFailed is set. + */ + static TriggerStep *triggerStepAllocate( +- sqlite3 *db, /* Database connection */ ++ Parse *pParse, /* Parser context */ + u8 op, /* Trigger opcode */ + Token *pName, /* The target name */ + const char *zStart, /* Start of SQL text */ + const char *zEnd /* End of SQL text */ + ){ ++ sqlite3 *db = pParse->db; + TriggerStep *pTriggerStep; + + pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n + 1); +@@ -126974,6 +131147,9 @@ + pTriggerStep->zTarget = z; + pTriggerStep->op = op; + pTriggerStep->zSpan = triggerSpanDup(db, zStart, zEnd); ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameTokenMap(pParse, pTriggerStep->zTarget, pName); ++ } + } + return pTriggerStep; + } +@@ -126986,25 +131162,36 @@ + ** body of a trigger. + */ + SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep( +- sqlite3 *db, /* The database connection */ ++ Parse *pParse, /* Parser */ + Token *pTableName, /* Name of the table into which we insert */ + IdList *pColumn, /* List of columns in pTableName to insert into */ + Select *pSelect, /* A SELECT statement that supplies values */ + u8 orconf, /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ ++ Upsert *pUpsert, /* ON CONFLICT clauses for upsert */ + const char *zStart, /* Start of SQL text */ + const char *zEnd /* End of SQL text */ + ){ ++ sqlite3 *db = pParse->db; + TriggerStep *pTriggerStep; + + assert(pSelect != 0 || db->mallocFailed); + +- pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName, zStart, zEnd); ++ pTriggerStep = triggerStepAllocate(pParse, TK_INSERT, pTableName,zStart,zEnd); + if( pTriggerStep ){ +- pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); ++ if( IN_RENAME_OBJECT ){ ++ pTriggerStep->pSelect = pSelect; ++ pSelect = 0; ++ }else{ ++ pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); ++ } + pTriggerStep->pIdList = pColumn; ++ pTriggerStep->pUpsert = pUpsert; + pTriggerStep->orconf = orconf; + }else{ ++ testcase( pColumn ); + sqlite3IdListDelete(db, pColumn); ++ testcase( pUpsert ); ++ sqlite3UpsertDelete(db, pUpsert); + } + sqlite3SelectDelete(db, pSelect); + +@@ -127017,7 +131204,7 @@ + ** sees an UPDATE statement inside the body of a CREATE TRIGGER. + */ + SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep( +- sqlite3 *db, /* The database connection */ ++ Parse *pParse, /* Parser */ + Token *pTableName, /* Name of the table to be updated */ + ExprList *pEList, /* The SET clause: list of column and new values */ + Expr *pWhere, /* The WHERE clause */ +@@ -127025,12 +131212,20 @@ + const char *zStart, /* Start of SQL text */ + const char *zEnd /* End of SQL text */ + ){ ++ sqlite3 *db = pParse->db; + TriggerStep *pTriggerStep; + +- pTriggerStep = triggerStepAllocate(db, TK_UPDATE, pTableName, zStart, zEnd); ++ pTriggerStep = triggerStepAllocate(pParse, TK_UPDATE, pTableName,zStart,zEnd); + if( pTriggerStep ){ +- pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE); +- pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); ++ if( IN_RENAME_OBJECT ){ ++ pTriggerStep->pExprList = pEList; ++ pTriggerStep->pWhere = pWhere; ++ pEList = 0; ++ pWhere = 0; ++ }else{ ++ pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE); ++ pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); ++ } + pTriggerStep->orconf = orconf; + } + sqlite3ExprListDelete(db, pEList); +@@ -127044,17 +131239,23 @@ + ** sees a DELETE statement inside the body of a CREATE TRIGGER. + */ + SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep( +- sqlite3 *db, /* Database connection */ ++ Parse *pParse, /* Parser */ + Token *pTableName, /* The table from which rows are deleted */ + Expr *pWhere, /* The WHERE clause */ + const char *zStart, /* Start of SQL text */ + const char *zEnd /* End of SQL text */ + ){ ++ sqlite3 *db = pParse->db; + TriggerStep *pTriggerStep; + +- pTriggerStep = triggerStepAllocate(db, TK_DELETE, pTableName, zStart, zEnd); ++ pTriggerStep = triggerStepAllocate(pParse, TK_DELETE, pTableName,zStart,zEnd); + if( pTriggerStep ){ +- pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); ++ if( IN_RENAME_OBJECT ){ ++ pTriggerStep->pWhere = pWhere; ++ pWhere = 0; ++ }else{ ++ pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); ++ } + pTriggerStep->orconf = OE_Default; + } + sqlite3ExprDelete(db, pWhere); +@@ -127321,7 +131522,7 @@ + targetSrcList(pParse, pStep), + sqlite3ExprListDup(db, pStep->pExprList, 0), + sqlite3ExprDup(db, pStep->pWhere, 0), +- pParse->eOrconf, 0, 0 ++ pParse->eOrconf, 0, 0, 0 + ); + break; + } +@@ -127330,7 +131531,8 @@ + targetSrcList(pParse, pStep), + sqlite3SelectDup(db, pStep->pSelect, 0), + sqlite3IdListDup(db, pStep->pIdList), +- pParse->eOrconf ++ pParse->eOrconf, ++ sqlite3UpsertDup(db, pStep->pUpsert) + ); + break; + } +@@ -127795,6 +131997,57 @@ + } + + /* ++** Check to see if column iCol of index pIdx references any of the ++** columns defined by aXRef and chngRowid. Return true if it does ++** and false if not. This is an optimization. False-positives are a ++** performance degradation, but false-negatives can result in a corrupt ++** index and incorrect answers. ++** ++** aXRef[j] will be non-negative if column j of the original table is ++** being updated. chngRowid will be true if the rowid of the table is ++** being updated. ++*/ ++static int indexColumnIsBeingUpdated( ++ Index *pIdx, /* The index to check */ ++ int iCol, /* Which column of the index to check */ ++ int *aXRef, /* aXRef[j]>=0 if column j is being updated */ ++ int chngRowid /* true if the rowid is being updated */ ++){ ++ i16 iIdxCol = pIdx->aiColumn[iCol]; ++ assert( iIdxCol!=XN_ROWID ); /* Cannot index rowid */ ++ if( iIdxCol>=0 ){ ++ return aXRef[iIdxCol]>=0; ++ } ++ assert( iIdxCol==XN_EXPR ); ++ assert( pIdx->aColExpr!=0 ); ++ assert( pIdx->aColExpr->a[iCol].pExpr!=0 ); ++ return sqlite3ExprReferencesUpdatedColumn(pIdx->aColExpr->a[iCol].pExpr, ++ aXRef,chngRowid); ++} ++ ++/* ++** Check to see if index pIdx is a partial index whose conditional ++** expression might change values due to an UPDATE. Return true if ++** the index is subject to change and false if the index is guaranteed ++** to be unchanged. This is an optimization. False-positives are a ++** performance degradation, but false-negatives can result in a corrupt ++** index and incorrect answers. ++** ++** aXRef[j] will be non-negative if column j of the original table is ++** being updated. chngRowid will be true if the rowid of the table is ++** being updated. ++*/ ++static int indexWhereClauseMightChange( ++ Index *pIdx, /* The index to check */ ++ int *aXRef, /* aXRef[j]>=0 if column j is being updated */ ++ int chngRowid /* true if the rowid is being updated */ ++){ ++ if( pIdx->pPartIdxWhere==0 ) return 0; ++ return sqlite3ExprReferencesUpdatedColumn(pIdx->pPartIdxWhere, ++ aXRef, chngRowid); ++} ++ ++/* + ** Process an UPDATE statement. + ** + ** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL; +@@ -127808,7 +132061,8 @@ + Expr *pWhere, /* The WHERE clause. May be null */ + int onError, /* How to handle constraint errors */ + ExprList *pOrderBy, /* ORDER BY clause. May be null */ +- Expr *pLimit /* LIMIT clause. May be null */ ++ Expr *pLimit, /* LIMIT clause. May be null */ ++ Upsert *pUpsert /* ON CONFLICT clause, or null */ + ){ + int i, j; /* Loop counters */ + Table *pTab; /* The table to be updated */ +@@ -127915,16 +132169,23 @@ + ** need to occur right after the database cursor. So go ahead and + ** allocate enough space, just in case. + */ +- pTabList->a[0].iCursor = iBaseCur = iDataCur = pParse->nTab++; ++ iBaseCur = iDataCur = pParse->nTab++; + iIdxCur = iDataCur+1; + pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); ++ testcase( pPk!=0 && pPk!=pTab->pIndex ); + for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ +- if( IsPrimaryKeyIndex(pIdx) && pPk!=0 ){ ++ if( pPk==pIdx ){ + iDataCur = pParse->nTab; +- pTabList->a[0].iCursor = iDataCur; + } + pParse->nTab++; + } ++ if( pUpsert ){ ++ /* On an UPSERT, reuse the same cursors already opened by INSERT */ ++ iDataCur = pUpsert->iDataCur; ++ iIdxCur = pUpsert->iIdxCur; ++ pParse->nTab = iBaseCur; ++ } ++ pTabList->a[0].iCursor = iDataCur; + + /* Allocate space for aXRef[], aRegIdx[], and aToOpen[]. + ** Initialize aXRef[] and aToOpen[] to their default values. +@@ -127941,6 +132202,8 @@ + memset(&sNC, 0, sizeof(sNC)); + sNC.pParse = pParse; + sNC.pSrcList = pTabList; ++ sNC.uNC.pUpsert = pUpsert; ++ sNC.ncFlags = NC_UUpsert; + + /* Resolve the column names in all the expressions of the + ** of the UPDATE statement. Also find the column index +@@ -128007,19 +132270,18 @@ + /* There is one entry in the aRegIdx[] array for each index on the table + ** being updated. Fill in aRegIdx[] with a register number that will hold + ** the key for accessing each index. +- ** +- ** FIXME: Be smarter about omitting indexes that use expressions. + */ + for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ + int reg; +- if( chngKey || hasFK>1 || pIdx->pPartIdxWhere || pIdx==pPk ){ ++ if( chngKey || hasFK>1 || pIdx==pPk ++ || indexWhereClauseMightChange(pIdx,aXRef,chngRowid) ++ ){ + reg = ++pParse->nMem; + pParse->nMem += pIdx->nColumn; + }else{ + reg = 0; + for(i=0; i<pIdx->nKeyCol; i++){ +- i16 iIdxCol = pIdx->aiColumn[i]; +- if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){ ++ if( indexColumnIsBeingUpdated(pIdx, i, aXRef, chngRowid) ){ + reg = ++pParse->nMem; + pParse->nMem += pIdx->nColumn; + if( (onError==OE_Replace) +@@ -128044,7 +132306,7 @@ + v = sqlite3GetVdbe(pParse); + if( v==0 ) goto update_cleanup; + if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); +- sqlite3BeginWriteOperation(pParse, 1, iDb); ++ sqlite3BeginWriteOperation(pParse, pTrigger || hasFK, iDb); + + /* Allocate required registers. */ + if( !IsVirtual(pTab) ){ +@@ -128095,8 +132357,16 @@ + } + #endif + +- /* Initialize the count of updated rows */ +- if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab ){ ++ /* Jump to labelBreak to abandon further processing of this UPDATE */ ++ labelContinue = labelBreak = sqlite3VdbeMakeLabel(v); ++ ++ /* Not an UPSERT. Normal processing. Begin by ++ ** initialize the count of updated rows */ ++ if( (db->flags&SQLITE_CountRows)!=0 ++ && !pParse->pTriggerTab ++ && !pParse->nested ++ && pUpsert==0 ++ ){ + regRowCount = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); + } +@@ -128109,46 +132379,61 @@ + iPk = pParse->nMem+1; + pParse->nMem += nPk; + regKey = ++pParse->nMem; +- iEph = pParse->nTab++; +- +- sqlite3VdbeAddOp3(v, OP_Null, 0, iPk, iPk+nPk-1); +- addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk); +- sqlite3VdbeSetP4KeyInfo(pParse, pPk); ++ if( pUpsert==0 ){ ++ iEph = pParse->nTab++; ++ sqlite3VdbeAddOp3(v, OP_Null, 0, iPk, iPk+nPk-1); ++ addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk); ++ sqlite3VdbeSetP4KeyInfo(pParse, pPk); ++ } + } +- +- /* 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|WHERE_SEEK_UNIQ_TABLE; +- if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){ +- flags |= WHERE_ONEPASS_MULTIROW; ++ ++ if( pUpsert ){ ++ /* If this is an UPSERT, then all cursors have already been opened by ++ ** the outer INSERT and the data cursor should be pointing at the row ++ ** that is to be updated. So bypass the code that searches for the ++ ** row(s) to be updated. ++ */ ++ pWInfo = 0; ++ eOnePass = ONEPASS_SINGLE; ++ sqlite3ExprIfFalse(pParse, pWhere, labelBreak, SQLITE_JUMPIFNULL); ++ }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|WHERE_SEEK_UNIQ_TABLE; ++ if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){ ++ flags |= WHERE_ONEPASS_MULTIROW; ++ } ++ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 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 ++ ** updated. Otherwise, if there is an index on "b", statements like ++ ** the following could create an infinite loop: ++ ** ++ ** UPDATE t1 SET b=b+1 WHERE b>? ++ ** ++ ** Fall back to ONEPASS_OFF if where.c has selected a ONEPASS_MULTI ++ ** strategy that uses an index for which one or more columns are being ++ ** updated. */ ++ eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); ++ if( eOnePass!=ONEPASS_SINGLE ){ ++ sqlite3MultiWrite(pParse); ++ if( eOnePass==ONEPASS_MULTI ){ ++ int iCur = aiCurOnePass[1]; ++ if( iCur>=0 && iCur!=iDataCur && aToOpen[iCur-iBaseCur] ){ ++ eOnePass = ONEPASS_OFF; ++ } ++ assert( iCur!=iDataCur || !HasRowid(pTab) ); ++ } ++ } + } +- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 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 +- ** updated. Otherwise, if there is an index on "b", statements like +- ** the following could create an infinite loop: +- ** +- ** UPDATE t1 SET b=b+1 WHERE b>? +- ** +- ** Fall back to ONEPASS_OFF if where.c has selected a ONEPASS_MULTI +- ** strategy that uses an index for which one or more columns are being +- ** updated. */ +- eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); +- if( eOnePass==ONEPASS_MULTI ){ +- int iCur = aiCurOnePass[1]; +- if( iCur>=0 && iCur!=iDataCur && aToOpen[iCur-iBaseCur] ){ +- eOnePass = ONEPASS_OFF; +- } +- assert( iCur!=iDataCur || !HasRowid(pTab) ); +- } +- + if( HasRowid(pTab) ){ + /* Read the rowid of the current row of the WHERE scan. In ONEPASS_OFF + ** mode, write the rowid into the FIFO. In either of the one-pass modes, +@@ -128168,7 +132453,7 @@ + sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur,pPk->aiColumn[i],iPk+i); + } + if( eOnePass ){ +- sqlite3VdbeChangeToNoop(v, addrOpen); ++ if( addrOpen ) sqlite3VdbeChangeToNoop(v, addrOpen); + nKey = nPk; + regKey = iPk; + }else{ +@@ -128178,59 +132463,58 @@ + } + } + +- if( eOnePass!=ONEPASS_MULTI ){ +- sqlite3WhereEnd(pWInfo); +- } +- +- labelBreak = sqlite3VdbeMakeLabel(v); +- if( !isView ){ +- int addrOnce = 0; +- +- /* Open every index that needs updating. */ +- if( eOnePass!=ONEPASS_OFF ){ +- if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0; +- if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0; ++ if( pUpsert==0 ){ ++ if( eOnePass!=ONEPASS_MULTI ){ ++ sqlite3WhereEnd(pWInfo); + } +- +- if( eOnePass==ONEPASS_MULTI && (nIdx-(aiCurOnePass[1]>=0))>0 ){ +- addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); ++ ++ if( !isView ){ ++ int addrOnce = 0; ++ ++ /* Open every index that needs updating. */ ++ if( eOnePass!=ONEPASS_OFF ){ ++ if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0; ++ if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0; ++ } ++ ++ if( eOnePass==ONEPASS_MULTI && (nIdx-(aiCurOnePass[1]>=0))>0 ){ ++ addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); ++ } ++ sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur, ++ aToOpen, 0, 0); ++ if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); + } +- sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur, aToOpen, +- 0, 0); +- if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); +- } +- +- /* Top of the update loop */ +- if( eOnePass!=ONEPASS_OFF ){ +- if( !isView && aiCurOnePass[0]!=iDataCur && aiCurOnePass[1]!=iDataCur ){ +- assert( pPk ); +- sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey); +- VdbeCoverageNeverTaken(v); +- } +- if( eOnePass==ONEPASS_SINGLE ){ +- labelContinue = labelBreak; ++ ++ /* Top of the update loop */ ++ if( eOnePass!=ONEPASS_OFF ){ ++ if( !isView && aiCurOnePass[0]!=iDataCur && aiCurOnePass[1]!=iDataCur ){ ++ assert( pPk ); ++ sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey,nKey); ++ VdbeCoverage(v); ++ } ++ if( eOnePass!=ONEPASS_SINGLE ){ ++ labelContinue = sqlite3VdbeMakeLabel(v); ++ } ++ sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak); ++ VdbeCoverageIf(v, pPk==0); ++ VdbeCoverageIf(v, pPk!=0); ++ }else if( pPk ){ ++ labelContinue = sqlite3VdbeMakeLabel(v); ++ sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v); ++ addrTop = sqlite3VdbeAddOp2(v, OP_RowData, iEph, regKey); ++ sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0); ++ VdbeCoverage(v); + }else{ +- labelContinue = sqlite3VdbeMakeLabel(v); ++ labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet,labelBreak, ++ regOldRowid); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid); ++ VdbeCoverage(v); + } +- sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak); +- VdbeCoverageIf(v, pPk==0); +- VdbeCoverageIf(v, pPk!=0); +- }else if( pPk ){ +- labelContinue = sqlite3VdbeMakeLabel(v); +- sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v); +- addrTop = sqlite3VdbeAddOp2(v, OP_RowData, iEph, regKey); +- sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0); +- VdbeCoverage(v); +- }else{ +- labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, labelBreak, +- regOldRowid); +- VdbeCoverage(v); +- sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid); +- VdbeCoverage(v); + } + +- /* If the record number will change, set register regNewRowid to +- ** contain the new value. If the record number is not being modified, ++ /* If the rowid value will change, set register regNewRowid to ++ ** contain the new value. If the rowid is not being modified, + ** then regNewRowid is the same register as regOldRowid, which is + ** already populated. */ + assert( chngKey || pTrigger || hasFK || regOldRowid==regNewRowid ); +@@ -128293,7 +132577,7 @@ + */ + testcase( i==31 ); + testcase( i==32 ); +- sqlite3ExprCodeGetColumnToReg(pParse, pTab, i, iDataCur, regNew+i); ++ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i); + }else{ + sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i); + } +@@ -128322,10 +132606,14 @@ + VdbeCoverage(v); + } + +- /* If it did not delete it, the row-trigger may still have modified ++ /* After-BEFORE-trigger-reload-loop: ++ ** If it did not delete it, the BEFORE trigger may still have modified + ** some of the columns of the row being updated. Load the values for +- ** all columns not modified by the update statement into their +- ** registers in case this has happened. ++ ** all columns not modified by the update statement into their registers ++ ** in case this has happened. Only unmodified columns are reloaded. ++ ** The values computed for modified columns use the values before the ++ ** BEFORE trigger runs. See test case trigger1-18.0 (added 2018-04-26) ++ ** for an example. + */ + for(i=0; i<pTab->nCol; i++){ + if( aXRef[i]<0 && i!=pTab->iPKey ){ +@@ -128341,7 +132629,7 @@ + assert( regOldRowid>0 ); + sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, + regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace, +- aXRef); ++ aXRef, 0); + + /* Do FK constraint checks. */ + if( hasFK ){ +@@ -128411,7 +132699,7 @@ + + /* Increment the row counter + */ +- if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab){ ++ if( regRowCount ){ + sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); + } + +@@ -128438,16 +132726,15 @@ + ** maximum rowid counter values recorded while inserting into + ** autoincrement tables. + */ +- if( pParse->nested==0 && pParse->pTriggerTab==0 ){ ++ if( pParse->nested==0 && pParse->pTriggerTab==0 && pUpsert==0 ){ + sqlite3AutoincrementEnd(pParse); + } + + /* +- ** Return the number of rows that were changed. If this routine is +- ** generating code because of a call to sqlite3NestedParse(), do not +- ** invoke the callback function. ++ ** Return the number of rows that were changed, if we are tracking ++ ** that information. + */ +- if( (db->flags&SQLITE_CountRows) && !pParse->pTriggerTab && !pParse->nested ){ ++ if( regRowCount ){ + sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", SQLITE_STATIC); +@@ -128519,7 +132806,7 @@ + int regRowid; /* Register for ephem table rowid */ + int iCsr = pSrc->a[0].iCursor; /* Cursor used for virtual table scan */ + int aDummy[2]; /* Unused arg for sqlite3WhereOkOnePass() */ +- int bOnePass; /* True to use onepass strategy */ ++ int eOnePass; /* True to use onepass strategy */ + int addr; /* Address of OP_OpenEphemeral */ + + /* Allocate nArg registers in which to gather the arguments for VUpdate. Then +@@ -128543,7 +132830,7 @@ + sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i); + }else{ + sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i); +- sqlite3VdbeChangeP5(v, 1); /* Enable sqlite3_vtab_nochange() */ ++ sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG);/* Enable sqlite3_vtab_nochange() */ + } + } + if( HasRowid(pTab) ){ +@@ -128564,19 +132851,20 @@ + sqlite3VdbeAddOp2(v, OP_SCopy, regArg+2+iPk, regArg+1); + } + +- bOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy); ++ eOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy); + +- if( bOnePass ){ ++ /* There is no ONEPASS_MULTI on virtual tables */ ++ assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE ); ++ ++ if( eOnePass ){ + /* If using the onepass strategy, no-op out the OP_OpenEphemeral coded +- ** above. Also, if this is a top-level parse (not a trigger), clear the +- ** multi-write flag so that the VM does not open a statement journal */ ++ ** above. */ + sqlite3VdbeChangeToNoop(v, addr); +- if( sqlite3IsToplevel(pParse) ){ +- pParse->isMultiWrite = 0; +- } ++ sqlite3VdbeAddOp1(v, OP_Close, iCsr); + }else{ + /* Create a record from the argument register contents and insert it into + ** the ephemeral table. */ ++ sqlite3MultiWrite(pParse); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regArg, nArg, regRec); + #ifdef SQLITE_DEBUG + /* Signal an assert() within OP_MakeRecord that it is allowed to +@@ -128588,7 +132876,7 @@ + } + + +- if( bOnePass==0 ){ ++ if( eOnePass==ONEPASS_OFF ){ + /* End the virtual table scan */ + sqlite3WhereEnd(pWInfo); + +@@ -128608,7 +132896,7 @@ + + /* End of the ephemeral table scan. Or, if using the onepass strategy, + ** jump to here if the scan visited zero rows. */ +- if( bOnePass==0 ){ ++ if( eOnePass==ONEPASS_OFF ){ + sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v); + sqlite3VdbeJumpHere(v, addr); + sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); +@@ -128619,6 +132907,261 @@ + #endif /* SQLITE_OMIT_VIRTUALTABLE */ + + /************** End of update.c **********************************************/ ++/************** Begin file upsert.c ******************************************/ ++/* ++** 2018-04-12 ++** ++** The author disclaims copyright to this source code. In place of ++** a legal notice, here is a blessing: ++** ++** May you do good and not evil. ++** May you find forgiveness for yourself and forgive others. ++** May you share freely, never taking more than you give. ++** ++************************************************************************* ++** This file contains code to implement various aspects of UPSERT ++** processing and handling of the Upsert object. ++*/ ++/* #include "sqliteInt.h" */ ++ ++#ifndef SQLITE_OMIT_UPSERT ++/* ++** Free a list of Upsert objects ++*/ ++SQLITE_PRIVATE void sqlite3UpsertDelete(sqlite3 *db, Upsert *p){ ++ if( p ){ ++ sqlite3ExprListDelete(db, p->pUpsertTarget); ++ sqlite3ExprDelete(db, p->pUpsertTargetWhere); ++ sqlite3ExprListDelete(db, p->pUpsertSet); ++ sqlite3ExprDelete(db, p->pUpsertWhere); ++ sqlite3DbFree(db, p); ++ } ++} ++ ++/* ++** Duplicate an Upsert object. ++*/ ++SQLITE_PRIVATE Upsert *sqlite3UpsertDup(sqlite3 *db, Upsert *p){ ++ if( p==0 ) return 0; ++ return sqlite3UpsertNew(db, ++ sqlite3ExprListDup(db, p->pUpsertTarget, 0), ++ sqlite3ExprDup(db, p->pUpsertTargetWhere, 0), ++ sqlite3ExprListDup(db, p->pUpsertSet, 0), ++ sqlite3ExprDup(db, p->pUpsertWhere, 0) ++ ); ++} ++ ++/* ++** Create a new Upsert object. ++*/ ++SQLITE_PRIVATE Upsert *sqlite3UpsertNew( ++ sqlite3 *db, /* Determines which memory allocator to use */ ++ ExprList *pTarget, /* Target argument to ON CONFLICT, or NULL */ ++ Expr *pTargetWhere, /* Optional WHERE clause on the target */ ++ ExprList *pSet, /* UPDATE columns, or NULL for a DO NOTHING */ ++ Expr *pWhere /* WHERE clause for the ON CONFLICT UPDATE */ ++){ ++ Upsert *pNew; ++ pNew = sqlite3DbMallocRaw(db, sizeof(Upsert)); ++ if( pNew==0 ){ ++ sqlite3ExprListDelete(db, pTarget); ++ sqlite3ExprDelete(db, pTargetWhere); ++ sqlite3ExprListDelete(db, pSet); ++ sqlite3ExprDelete(db, pWhere); ++ return 0; ++ }else{ ++ pNew->pUpsertTarget = pTarget; ++ pNew->pUpsertTargetWhere = pTargetWhere; ++ pNew->pUpsertSet = pSet; ++ pNew->pUpsertWhere = pWhere; ++ pNew->pUpsertIdx = 0; ++ } ++ return pNew; ++} ++ ++/* ++** Analyze the ON CONFLICT clause described by pUpsert. Resolve all ++** symbols in the conflict-target. ++** ++** Return SQLITE_OK if everything works, or an error code is something ++** is wrong. ++*/ ++SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget( ++ Parse *pParse, /* The parsing context */ ++ SrcList *pTabList, /* Table into which we are inserting */ ++ Upsert *pUpsert /* The ON CONFLICT clauses */ ++){ ++ Table *pTab; /* That table into which we are inserting */ ++ int rc; /* Result code */ ++ int iCursor; /* Cursor used by pTab */ ++ Index *pIdx; /* One of the indexes of pTab */ ++ ExprList *pTarget; /* The conflict-target clause */ ++ Expr *pTerm; /* One term of the conflict-target clause */ ++ NameContext sNC; /* Context for resolving symbolic names */ ++ Expr sCol[2]; /* Index column converted into an Expr */ ++ ++ assert( pTabList->nSrc==1 ); ++ assert( pTabList->a[0].pTab!=0 ); ++ assert( pUpsert!=0 ); ++ assert( pUpsert->pUpsertTarget!=0 ); ++ ++ /* Resolve all symbolic names in the conflict-target clause, which ++ ** includes both the list of columns and the optional partial-index ++ ** WHERE clause. ++ */ ++ memset(&sNC, 0, sizeof(sNC)); ++ sNC.pParse = pParse; ++ sNC.pSrcList = pTabList; ++ rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget); ++ if( rc ) return rc; ++ rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere); ++ if( rc ) return rc; ++ ++ /* Check to see if the conflict target matches the rowid. */ ++ pTab = pTabList->a[0].pTab; ++ pTarget = pUpsert->pUpsertTarget; ++ iCursor = pTabList->a[0].iCursor; ++ if( HasRowid(pTab) ++ && pTarget->nExpr==1 ++ && (pTerm = pTarget->a[0].pExpr)->op==TK_COLUMN ++ && pTerm->iColumn==XN_ROWID ++ ){ ++ /* The conflict-target is the rowid of the primary table */ ++ assert( pUpsert->pUpsertIdx==0 ); ++ return SQLITE_OK; ++ } ++ ++ /* Initialize sCol[0..1] to be an expression parse tree for a ++ ** single column of an index. The sCol[0] node will be the TK_COLLATE ++ ** operator and sCol[1] will be the TK_COLUMN operator. Code below ++ ** will populate the specific collation and column number values ++ ** prior to comparing against the conflict-target expression. ++ */ ++ memset(sCol, 0, sizeof(sCol)); ++ sCol[0].op = TK_COLLATE; ++ sCol[0].pLeft = &sCol[1]; ++ sCol[1].op = TK_COLUMN; ++ sCol[1].iTable = pTabList->a[0].iCursor; ++ ++ /* Check for matches against other indexes */ ++ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ ++ int ii, jj, nn; ++ if( !IsUniqueIndex(pIdx) ) continue; ++ if( pTarget->nExpr!=pIdx->nKeyCol ) continue; ++ if( pIdx->pPartIdxWhere ){ ++ if( pUpsert->pUpsertTargetWhere==0 ) continue; ++ if( sqlite3ExprCompare(pParse, pUpsert->pUpsertTargetWhere, ++ pIdx->pPartIdxWhere, iCursor)!=0 ){ ++ continue; ++ } ++ } ++ nn = pIdx->nKeyCol; ++ for(ii=0; ii<nn; ii++){ ++ Expr *pExpr; ++ sCol[0].u.zToken = (char*)pIdx->azColl[ii]; ++ if( pIdx->aiColumn[ii]==XN_EXPR ){ ++ assert( pIdx->aColExpr!=0 ); ++ assert( pIdx->aColExpr->nExpr>ii ); ++ pExpr = pIdx->aColExpr->a[ii].pExpr; ++ if( pExpr->op!=TK_COLLATE ){ ++ sCol[0].pLeft = pExpr; ++ pExpr = &sCol[0]; ++ } ++ }else{ ++ sCol[0].pLeft = &sCol[1]; ++ sCol[1].iColumn = pIdx->aiColumn[ii]; ++ pExpr = &sCol[0]; ++ } ++ for(jj=0; jj<nn; jj++){ ++ if( sqlite3ExprCompare(pParse, pTarget->a[jj].pExpr, pExpr,iCursor)<2 ){ ++ break; /* Column ii of the index matches column jj of target */ ++ } ++ } ++ if( jj>=nn ){ ++ /* The target contains no match for column jj of the index */ ++ break; ++ } ++ } ++ if( ii<nn ){ ++ /* Column ii of the index did not match any term of the conflict target. ++ ** Continue the search with the next index. */ ++ continue; ++ } ++ pUpsert->pUpsertIdx = pIdx; ++ return SQLITE_OK; ++ } ++ sqlite3ErrorMsg(pParse, "ON CONFLICT clause does not match any " ++ "PRIMARY KEY or UNIQUE constraint"); ++ return SQLITE_ERROR; ++} ++ ++/* ++** Generate bytecode that does an UPDATE as part of an upsert. ++** ++** If pIdx is NULL, then the UNIQUE constraint that failed was the IPK. ++** In this case parameter iCur is a cursor open on the table b-tree that ++** currently points to the conflicting table row. Otherwise, if pIdx ++** is not NULL, then pIdx is the constraint that failed and iCur is a ++** cursor points to the conflicting row. ++*/ ++SQLITE_PRIVATE void sqlite3UpsertDoUpdate( ++ Parse *pParse, /* The parsing and code-generating context */ ++ Upsert *pUpsert, /* The ON CONFLICT clause for the upsert */ ++ Table *pTab, /* The table being updated */ ++ Index *pIdx, /* The UNIQUE constraint that failed */ ++ int iCur /* Cursor for pIdx (or pTab if pIdx==NULL) */ ++){ ++ Vdbe *v = pParse->pVdbe; ++ sqlite3 *db = pParse->db; ++ SrcList *pSrc; /* FROM clause for the UPDATE */ ++ int iDataCur; ++ ++ assert( v!=0 ); ++ assert( pUpsert!=0 ); ++ VdbeNoopComment((v, "Begin DO UPDATE of UPSERT")); ++ iDataCur = pUpsert->iDataCur; ++ if( pIdx && iCur!=iDataCur ){ ++ if( HasRowid(pTab) ){ ++ int regRowid = sqlite3GetTempReg(pParse); ++ sqlite3VdbeAddOp2(v, OP_IdxRowid, iCur, regRowid); ++ sqlite3VdbeAddOp3(v, OP_SeekRowid, iDataCur, 0, regRowid); ++ VdbeCoverage(v); ++ sqlite3ReleaseTempReg(pParse, regRowid); ++ }else{ ++ Index *pPk = sqlite3PrimaryKeyIndex(pTab); ++ int nPk = pPk->nKeyCol; ++ int iPk = pParse->nMem+1; ++ int i; ++ pParse->nMem += nPk; ++ for(i=0; i<nPk; i++){ ++ int k; ++ assert( pPk->aiColumn[i]>=0 ); ++ k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]); ++ sqlite3VdbeAddOp3(v, OP_Column, iCur, k, iPk+i); ++ VdbeComment((v, "%s.%s", pIdx->zName, ++ pTab->aCol[pPk->aiColumn[i]].zName)); ++ } ++ sqlite3VdbeVerifyAbortable(v, OE_Abort); ++ i = sqlite3VdbeAddOp4Int(v, OP_Found, iDataCur, 0, iPk, nPk); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CORRUPT, OE_Abort, 0, ++ "corrupt database", P4_STATIC); ++ sqlite3VdbeJumpHere(v, i); ++ } ++ } ++ /* pUpsert does not own pUpsertSrc - the outer INSERT statement does. So ++ ** we have to make a copy before passing it down into sqlite3Update() */ ++ pSrc = sqlite3SrcListDup(db, pUpsert->pUpsertSrc, 0); ++ sqlite3Update(pParse, pSrc, pUpsert->pUpsertSet, ++ pUpsert->pUpsertWhere, OE_Abort, 0, 0, pUpsert); ++ pUpsert->pUpsertSet = 0; /* Will have been deleted by sqlite3Update() */ ++ pUpsert->pUpsertWhere = 0; /* Will have been deleted by sqlite3Update() */ ++ VdbeNoopComment((v, "End DO UPDATE of UPSERT")); ++} ++ ++#endif /* SQLITE_OMIT_UPSERT */ ++ ++/************** End of upsert.c **********************************************/ + /************** Begin file vacuum.c ******************************************/ + /* + ** 2003 April 6 +@@ -128661,8 +133204,14 @@ + while( SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){ + const char *zSubSql = (const char*)sqlite3_column_text(pStmt,0); + assert( sqlite3_strnicmp(zSql,"SELECT",6)==0 ); +- assert( sqlite3_strnicmp(zSubSql,"SELECT",6)!=0 || CORRUPT_DB ); +- if( zSubSql && zSubSql[0]!='S' ){ ++ /* The secondary SQL must be one of CREATE TABLE, CREATE INDEX, ++ ** or INSERT. Historically there have been attacks that first ++ ** corrupt the sqlite_master.sql field with other kinds of statements ++ ** then run VACUUM to get those statements to execute at inappropriate ++ ** times. */ ++ if( zSubSql ++ && (strncmp(zSubSql,"CRE",3)==0 || strncmp(zSubSql,"INS",3)==0) ++ ){ + rc = execSql(db, pzErrMsg, zSubSql); + if( rc!=SQLITE_OK ) break; + } +@@ -128782,7 +133331,8 @@ + saved_mTrace = db->mTrace; + db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks; + db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum; +- db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder | SQLITE_CountRows); ++ db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder ++ | SQLITE_Defensive | SQLITE_CountRows); + db->mTrace = 0; + + zDbMain = db->aDb[iDb].zDbSName; +@@ -128840,7 +133390,7 @@ + */ + rc = execSql(db, pzErrMsg, "BEGIN"); + if( rc!=SQLITE_OK ) goto end_of_vacuum; +- rc = sqlite3BtreeBeginTrans(pMain, 2); ++ rc = sqlite3BtreeBeginTrans(pMain, 2, 0); + if( rc!=SQLITE_OK ) goto end_of_vacuum; + + /* Do not attempt to change the page size for a WAL database */ +@@ -128875,7 +133425,7 @@ + if( rc!=SQLITE_OK ) goto end_of_vacuum; + rc = execSqlF(db, pzErrMsg, + "SELECT sql FROM \"%w\".sqlite_master" +- " WHERE type='index' AND length(sql)>10", ++ " WHERE type='index'", + zDbMain + ); + if( rc!=SQLITE_OK ) goto end_of_vacuum; +@@ -129258,7 +133808,7 @@ + assert( sqlite3_mutex_held(db->mutex) ); + + if( p ){ +- sqlite3ExpirePreparedStatements(db); ++ sqlite3ExpirePreparedStatements(db, 0); + do { + VTable *pNext = p->pNext; + sqlite3VtabUnlock(p); +@@ -129324,7 +133874,6 @@ + Token *pModuleName, /* Name of the module for the virtual table */ + int ifNotExists /* No error if the table already exists */ + ){ +- int iDb; /* The database the table is being created in */ + Table *pTable; /* The new virtual table */ + sqlite3 *db; /* Database connection */ + +@@ -129334,8 +133883,6 @@ + assert( 0==pTable->pIndex ); + + db = pParse->db; +- iDb = sqlite3SchemaToIndex(db, pTable->pSchema); +- assert( iDb>=0 ); + + assert( pTable->nModuleArg==0 ); + addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName)); +@@ -129355,6 +133902,8 @@ + ** The second call, to obtain permission to create the table, is made now. + */ + if( pTable->azModuleArg ){ ++ int iDb = sqlite3SchemaToIndex(db, pTable->pSchema); ++ assert( iDb>=0 ); /* The database the table is being created in */ + sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName, + pTable->azModuleArg[0], pParse->db->aDb[iDb].zDbSName); + } +@@ -129754,7 +134303,7 @@ + assert( IsVirtual(pTab) ); + + memset(&sParse, 0, sizeof(sParse)); +- sParse.declareVtab = 1; ++ sParse.eParseMode = PARSE_MODE_DECLARE_VTAB; + sParse.db = db; + sParse.nQueryLoop = 1; + if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable, &zErr) +@@ -129795,7 +134344,7 @@ + sqlite3DbFree(db, zErr); + rc = SQLITE_ERROR; + } +- sParse.declareVtab = 0; ++ sParse.eParseMode = PARSE_MODE_NORMAL; + + if( sParse.pVdbe ){ + sqlite3VdbeFinalize(sParse.pVdbe); +@@ -130045,14 +134594,11 @@ + void *pArg = 0; + FuncDef *pNew; + int rc = 0; +- char *zLowerName; +- unsigned char *z; + +- + /* Check to see the left operand is a column in a virtual table */ + if( NEVER(pExpr==0) ) return pDef; + if( pExpr->op!=TK_COLUMN ) return pDef; +- pTab = pExpr->pTab; ++ pTab = pExpr->y.pTab; + if( pTab==0 ) return pDef; + if( !IsVirtual(pTab) ) return pDef; + pVtab = sqlite3GetVTable(db, pTab)->pVtab; +@@ -130062,16 +134608,22 @@ + if( pMod->xFindFunction==0 ) return pDef; + + /* Call the xFindFunction method on the virtual table implementation +- ** to see if the implementation wants to overload this function ++ ** to see if the implementation wants to overload this function. ++ ** ++ ** Though undocumented, we have historically always invoked xFindFunction ++ ** with an all lower-case function name. Continue in this tradition to ++ ** avoid any chance of an incompatibility. + */ +- zLowerName = sqlite3DbStrDup(db, pDef->zName); +- if( zLowerName ){ +- for(z=(unsigned char*)zLowerName; *z; z++){ +- *z = sqlite3UpperToLower[*z]; ++#ifdef SQLITE_DEBUG ++ { ++ int i; ++ for(i=0; pDef->zName[i]; i++){ ++ unsigned char x = (unsigned char)pDef->zName[i]; ++ assert( x==sqlite3UpperToLower[x] ); + } +- rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xSFunc, &pArg); +- sqlite3DbFree(db, zLowerName); + } ++#endif ++ rc = pMod->xFindFunction(pVtab, nArg, pDef->zName, &xSFunc, &pArg); + if( rc==0 ){ + return pDef; + } +@@ -130346,6 +134898,8 @@ + struct InLoop { + int iCur; /* The VDBE cursor used by this IN operator */ + int addrInTop; /* Top of the IN loop */ ++ int iBase; /* Base register of multi-key index record */ ++ int nPrefix; /* Number of prior entires in the key */ + u8 eEndLoopOp; /* IN Loop terminator. OP_Next or OP_Prev */ + } *aInLoop; /* Information about each nested IN operator */ + } in; /* Used when pWLoop->wsFlags&WHERE_IN_ABLE */ +@@ -130584,6 +135138,7 @@ + WhereInfo *pWInfo; /* WHERE clause processing context */ + WhereClause *pOuter; /* Outer conjunction */ + u8 op; /* Split operator. TK_AND or TK_OR */ ++ u8 hasOr; /* True if any a[].eOperator is WO_OR */ + int nTerm; /* Number of terms */ + int nSlot; /* Number of entries in a[] */ + WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */ +@@ -130663,6 +135218,7 @@ + int nRecValid; /* Number of valid fields currently in pRec */ + #endif + unsigned int bldFlags; /* SQLITE_BLDF_* flags */ ++ unsigned int iPlanLimit; /* Search limiter */ + }; + + /* Allowed values for WhereLoopBuider.bldFlags */ +@@ -130669,6 +135225,26 @@ + #define SQLITE_BLDF_INDEXED 0x0001 /* An index is used */ + #define SQLITE_BLDF_UNIQUE 0x0002 /* All keys of a UNIQUE index used */ + ++/* The WhereLoopBuilder.iPlanLimit is used to limit the number of ++** index+constraint combinations the query planner will consider for a ++** particular query. If this parameter is unlimited, then certain ++** pathological queries can spend excess time in the sqlite3WhereBegin() ++** routine. The limit is high enough that is should not impact real-world ++** queries. ++** ++** SQLITE_QUERY_PLANNER_LIMIT is the baseline limit. The limit is ++** increased by SQLITE_QUERY_PLANNER_LIMIT_INCR before each term of the FROM ++** clause is processed, so that every table in a join is guaranteed to be ++** able to propose a some index+constraint combinations even if the initial ++** baseline limit was exhausted by prior tables of the join. ++*/ ++#ifndef SQLITE_QUERY_PLANNER_LIMIT ++# define SQLITE_QUERY_PLANNER_LIMIT 20000 ++#endif ++#ifndef SQLITE_QUERY_PLANNER_LIMIT_INCR ++# define SQLITE_QUERY_PLANNER_LIMIT_INCR 1000 ++#endif ++ + /* + ** The WHERE clause processing routine has two halves. The + ** first part does the start of the WHERE loop and the second +@@ -130731,12 +135307,10 @@ + Parse *pParse, /* Parse context */ + SrcList *pTabList, /* Table list this loop refers to */ + WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ +- int iLevel, /* Value for "level" column of output */ +- int iFrom, /* Value for "from" column of output */ + u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ + ); + #else +-# define sqlite3WhereExplainOneScan(u,v,w,x,y,z) 0 ++# define sqlite3WhereExplainOneScan(u,v,w,x) 0 + #endif /* SQLITE_OMIT_EXPLAIN */ + #ifdef SQLITE_ENABLE_STMT_SCANSTATUS + SQLITE_PRIVATE void sqlite3WhereAddScanStatus( +@@ -130759,6 +135333,7 @@ + SQLITE_PRIVATE void sqlite3WhereClauseClear(WhereClause*); + SQLITE_PRIVATE void sqlite3WhereSplit(WhereClause*,Expr*,u8); + SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet*, Expr*); ++SQLITE_PRIVATE Bitmask sqlite3WhereExprUsageNN(WhereMaskSet*, Expr*); + SQLITE_PRIVATE Bitmask sqlite3WhereExprListUsage(WhereMaskSet*, ExprList*); + SQLITE_PRIVATE void sqlite3WhereExprAnalyze(SrcList*, WhereClause*); + SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*); +@@ -130821,6 +135396,7 @@ + #define WHERE_SKIPSCAN 0x00008000 /* Uses the skip-scan algorithm */ + #define WHERE_UNQ_WANTED 0x00010000 /* WHERE_ONEROW would have been helpful*/ + #define WHERE_PARTIALIDX 0x00020000 /* The automatic index is partial */ ++#define WHERE_IN_EARLYOUT 0x00040000 /* Perhaps quit IN loops early */ + + /************** End of whereInt.h ********************************************/ + /************** Continuing where we left off in wherecode.c ******************/ +@@ -130856,23 +135432,23 @@ + int i; + + assert( nTerm>=1 ); +- if( bAnd ) sqlite3StrAccumAppend(pStr, " AND ", 5); ++ if( bAnd ) sqlite3_str_append(pStr, " AND ", 5); + +- if( nTerm>1 ) sqlite3StrAccumAppend(pStr, "(", 1); ++ if( nTerm>1 ) sqlite3_str_append(pStr, "(", 1); + for(i=0; i<nTerm; i++){ +- if( i ) sqlite3StrAccumAppend(pStr, ",", 1); +- sqlite3StrAccumAppendAll(pStr, explainIndexColumnName(pIdx, iTerm+i)); ++ if( i ) sqlite3_str_append(pStr, ",", 1); ++ sqlite3_str_appendall(pStr, explainIndexColumnName(pIdx, iTerm+i)); + } +- if( nTerm>1 ) sqlite3StrAccumAppend(pStr, ")", 1); ++ if( nTerm>1 ) sqlite3_str_append(pStr, ")", 1); + +- sqlite3StrAccumAppend(pStr, zOp, 1); ++ sqlite3_str_append(pStr, zOp, 1); + +- if( nTerm>1 ) sqlite3StrAccumAppend(pStr, "(", 1); ++ if( nTerm>1 ) sqlite3_str_append(pStr, "(", 1); + for(i=0; i<nTerm; i++){ +- if( i ) sqlite3StrAccumAppend(pStr, ",", 1); +- sqlite3StrAccumAppend(pStr, "?", 1); ++ if( i ) sqlite3_str_append(pStr, ",", 1); ++ sqlite3_str_append(pStr, "?", 1); + } +- if( nTerm>1 ) sqlite3StrAccumAppend(pStr, ")", 1); ++ if( nTerm>1 ) sqlite3_str_append(pStr, ")", 1); + } + + /* +@@ -130896,11 +135472,11 @@ + int i, j; + + if( nEq==0 && (pLoop->wsFlags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ) return; +- sqlite3StrAccumAppend(pStr, " (", 2); ++ sqlite3_str_append(pStr, " (", 2); + for(i=0; i<nEq; i++){ + const char *z = explainIndexColumnName(pIndex, i); +- if( i ) sqlite3StrAccumAppend(pStr, " AND ", 5); +- sqlite3XPrintf(pStr, i>=nSkip ? "%s=?" : "ANY(%s)", z); ++ if( i ) sqlite3_str_append(pStr, " AND ", 5); ++ sqlite3_str_appendf(pStr, i>=nSkip ? "%s=?" : "ANY(%s)", z); + } + + j = i; +@@ -130911,7 +135487,7 @@ + if( pLoop->wsFlags&WHERE_TOP_LIMIT ){ + explainAppendTerm(pStr, pIndex, pLoop->u.btree.nTop, j, i, "<"); + } +- sqlite3StrAccumAppend(pStr, ")", 1); ++ sqlite3_str_append(pStr, ")", 1); + } + + /* +@@ -130927,8 +135503,6 @@ + Parse *pParse, /* Parse context */ + SrcList *pTabList, /* Table list this loop refers to */ + WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ +- int iLevel, /* Value for "level" column of output */ +- int iFrom, /* Value for "from" column of output */ + u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ + ){ + int ret = 0; +@@ -130939,7 +135513,6 @@ + struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom]; + Vdbe *v = pParse->pVdbe; /* VM being constructed */ + sqlite3 *db = pParse->db; /* Database handle */ +- int iId = pParse->iSelectId; /* Select id (left-most output column) */ + int isSearch; /* True for a SEARCH. False for SCAN. */ + WhereLoop *pLoop; /* The controlling WhereLoop object */ + u32 flags; /* Flags that describe this loop */ +@@ -130956,15 +135529,15 @@ + || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX)); + + sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); +- sqlite3StrAccumAppendAll(&str, isSearch ? "SEARCH" : "SCAN"); ++ sqlite3_str_appendall(&str, isSearch ? "SEARCH" : "SCAN"); + if( pItem->pSelect ){ +- sqlite3XPrintf(&str, " SUBQUERY %d", pItem->iSelectId); ++ sqlite3_str_appendf(&str, " SUBQUERY %u", pItem->pSelect->selId); + }else{ +- sqlite3XPrintf(&str, " TABLE %s", pItem->zName); ++ sqlite3_str_appendf(&str, " TABLE %s", pItem->zName); + } + + if( pItem->zAlias ){ +- sqlite3XPrintf(&str, " AS %s", pItem->zAlias); ++ sqlite3_str_appendf(&str, " AS %s", pItem->zAlias); + } + if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){ + const char *zFmt = 0; +@@ -130987,8 +135560,8 @@ + zFmt = "INDEX %s"; + } + if( zFmt ){ +- sqlite3StrAccumAppend(&str, " USING ", 7); +- sqlite3XPrintf(&str, zFmt, pIdx->zName); ++ sqlite3_str_append(&str, " USING ", 7); ++ sqlite3_str_appendf(&str, zFmt, pIdx->zName); + explainIndexRange(&str, pLoop); + } + }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){ +@@ -131003,23 +135576,26 @@ + assert( flags&WHERE_TOP_LIMIT); + zRangeOp = "<"; + } +- sqlite3XPrintf(&str, " USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp); ++ sqlite3_str_appendf(&str, ++ " USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp); + } + #ifndef SQLITE_OMIT_VIRTUALTABLE + else if( (flags & WHERE_VIRTUALTABLE)!=0 ){ +- sqlite3XPrintf(&str, " VIRTUAL TABLE INDEX %d:%s", ++ sqlite3_str_appendf(&str, " VIRTUAL TABLE INDEX %d:%s", + pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr); + } + #endif + #ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS + if( pLoop->nOut>=10 ){ +- sqlite3XPrintf(&str, " (~%llu rows)", sqlite3LogEstToInt(pLoop->nOut)); ++ sqlite3_str_appendf(&str, " (~%llu rows)", ++ sqlite3LogEstToInt(pLoop->nOut)); + }else{ +- sqlite3StrAccumAppend(&str, " (~1 row)", 9); ++ sqlite3_str_append(&str, " (~1 row)", 9); + } + #endif + zMsg = sqlite3StrAccumFinish(&str); +- ret = sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg,P4_DYNAMIC); ++ ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v), ++ pParse->addrExplain, 0, zMsg,P4_DYNAMIC); + } + return ret; + } +@@ -131152,7 +135728,6 @@ + /* Code the OP_Affinity opcode if there is anything left to do. */ + if( n>0 ){ + sqlite3VdbeAddOp4(v, OP_Affinity, base, n, 0, zAff, n); +- sqlite3ExprCacheAffinityChange(pParse, base, n); + } + } + +@@ -131231,7 +135806,7 @@ + for(i=iEq; i<pLoop->nLTerm; i++){ + if( pLoop->aLTerm[i]->pExpr==pX ){ + int iField = pLoop->aLTerm[i]->iField - 1; +- assert( pOrigRhs->a[iField].pExpr!=0 ); ++ 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 ); +@@ -131396,7 +135971,14 @@ + sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v); + if( i==iEq ){ + pIn->iCur = iTab; +- pIn->eEndLoopOp = bRev ? OP_PrevIfOpen : OP_NextIfOpen; ++ pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next; ++ if( iEq>0 && (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ){ ++ pIn->iBase = iReg - i; ++ pIn->nPrefix = i; ++ pLoop->wsFlags |= WHERE_IN_EARLYOUT; ++ }else{ ++ pIn->nPrefix = 0; ++ } + }else{ + pIn->eEndLoopOp = OP_Noop; + } +@@ -131683,11 +136265,8 @@ + struct CCurHint *pHint = pWalker->u.pCCurHint; + if( pExpr->op==TK_COLUMN ){ + if( pExpr->iTable!=pHint->iTabCur ){ +- Vdbe *v = pWalker->pParse->pVdbe; + int reg = ++pWalker->pParse->nMem; /* Register for column value */ +- sqlite3ExprCodeGetColumnOfTable( +- v, pExpr->pTab, pExpr->iTable, pExpr->iColumn, reg +- ); ++ sqlite3ExprCode(pWalker->pParse, pExpr, reg); + pExpr->op = TK_REGISTER; + pExpr->iTable = reg; + }else if( pHint->pIdx!=0 ){ +@@ -131919,7 +136498,7 @@ + pExpr->op = TK_COLUMN; + pExpr->iTable = pX->iIdxCur; + pExpr->iColumn = pX->iIdxCol; +- pExpr->pTab = 0; ++ pExpr->y.pTab = 0; + return WRC_Prune; + }else{ + return WRC_Continue; +@@ -132020,6 +136599,9 @@ + ** initialize a memory cell that records if this table matches any + ** row of the left table of the join. + */ ++ assert( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE) ++ || pLevel->iFrom>0 || (pTabItem[0].fg.jointype & JT_LEFT)==0 ++ ); + if( pLevel->iFrom>0 && (pTabItem[0].fg.jointype & JT_LEFT)!=0 ){ + pLevel->iLeftJoin = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin); +@@ -132037,7 +136619,7 @@ + sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub); + pLevel->p2 = sqlite3VdbeAddOp2(v, OP_Yield, regYield, addrBrk); + VdbeCoverage(v); +- VdbeComment((v, "next row of \"%s\"", pTabItem->pTab->zName)); ++ VdbeComment((v, "next row of %s", pTabItem->pTab->zName)); + pLevel->op = OP_Goto; + }else + +@@ -132051,7 +136633,6 @@ + int nConstraint = pLoop->nLTerm; + int iIn; /* Counter for IN constraints */ + +- sqlite3ExprCachePush(pParse); + iReg = sqlite3GetTempRange(pParse, nConstraint+2); + addrNotFound = pLevel->addrBrk; + for(j=0; j<nConstraint; j++){ +@@ -132124,7 +136705,6 @@ + ** + ** sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2); + */ +- sqlite3ExprCachePop(pParse); + }else + #endif /* SQLITE_OMIT_VIRTUALTABLE */ + +@@ -132148,9 +136728,6 @@ + addrNxt = pLevel->addrNxt; + sqlite3VdbeAddOp3(v, OP_SeekRowid, iCur, addrNxt, iRowidReg); + VdbeCoverage(v); +- sqlite3ExprCacheAffinityChange(pParse, iRowidReg, 1); +- sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); +- VdbeComment((v, "pk")); + pLevel->op = OP_Noop; + }else if( (pLoop->wsFlags & WHERE_IPK)!=0 + && (pLoop->wsFlags & WHERE_COLUMN_RANGE)!=0 +@@ -132220,7 +136797,6 @@ + VdbeCoverageIf(v, pX->op==TK_LE); + VdbeCoverageIf(v, pX->op==TK_LT); + VdbeCoverageIf(v, pX->op==TK_GE); +- sqlite3ExprCacheAffinityChange(pParse, r1, 1); + sqlite3ReleaseTempReg(pParse, rTemp); + }else{ + sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrHalt); +@@ -132255,7 +136831,6 @@ + if( testOp!=OP_Noop ){ + iRowidReg = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg); +- sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); + sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg); + VdbeCoverageIf(v, testOp==OP_Le); + VdbeCoverageIf(v, testOp==OP_Lt); +@@ -132460,6 +137035,9 @@ + ** above has already left the cursor sitting on the correct row, + ** so no further seeking is needed */ + }else{ ++ if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){ ++ sqlite3VdbeAddOp1(v, OP_SeekHit, iIdxCur); ++ } + op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; + assert( op!=0 ); + sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); +@@ -132478,7 +137056,6 @@ + nConstraint = nEq; + if( pRangeEnd ){ + Expr *pRight = pRangeEnd->pExpr->pRight; +- sqlite3ExprCacheRemove(pParse, regBase+nEq, 1); + codeExprOrVector(pParse, pRight, regBase+nEq, nTop); + whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd); + if( (pRangeEnd->wtFlags & TERM_VNULL)==0 +@@ -132503,7 +137080,6 @@ + } + }else if( bStopAtNull ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); +- sqlite3ExprCacheRemove(pParse, regBase+nEq, 1); + endEq = 0; + nConstraint++; + } +@@ -132523,6 +137099,10 @@ + testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE ); + } + ++ if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){ ++ sqlite3VdbeAddOp2(v, OP_SeekHit, iIdxCur, 1); ++ } ++ + /* Seek the table cursor, if required */ + if( omitTable ){ + /* pIdx is a covering index. No need to access the main table. */ +@@ -132533,7 +137113,6 @@ + )){ + iRowidReg = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg); +- sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); + sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg); + VdbeCoverage(v); + }else{ +@@ -132553,10 +137132,17 @@ + /* If pIdx is an index on one or more expressions, then look through + ** all the expressions in pWInfo and try to transform matching expressions + ** into reference to index columns. ++ ** ++ ** Do not do this for the RHS of a LEFT JOIN. This is because the ++ ** expression may be evaluated after OP_NullRow has been executed on ++ ** the cursor. In this case it is important to do the full evaluation, ++ ** as the result of the expression may not be NULL, even if all table ++ ** column values are. https://www.sqlite.org/src/info/7fa8049685b50b5a + */ +- whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo); ++ if( pLevel->iLeftJoin==0 ){ ++ whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo); ++ } + +- + /* Record the instruction used to terminate the loop. */ + if( pLoop->wsFlags & WHERE_ONEROW ){ + pLevel->op = OP_Noop; +@@ -132711,7 +137297,6 @@ + for(iTerm=0; iTerm<pWC->nTerm; iTerm++){ + Expr *pExpr = pWC->a[iTerm].pExpr; + if( &pWC->a[iTerm] == pTerm ) continue; +- if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; + testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL ); + testcase( pWC->a[iTerm].wtFlags & TERM_CODED ); + if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED))!=0 ) continue; +@@ -132730,6 +137315,7 @@ + ** sub-WHERE clause is to to invoke the main loop body as a subroutine. + */ + wctrlFlags = WHERE_OR_SUBCLAUSE | (pWInfo->wctrlFlags & WHERE_SEEK_TABLE); ++ ExplainQueryPlan((pParse, 1, "MULTI-INDEX OR")); + for(ii=0; ii<pOrWc->nTerm; ii++){ + WhereTerm *pOrTerm = &pOrWc->a[ii]; + if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){ +@@ -132736,7 +137322,10 @@ + WhereInfo *pSubWInfo; /* Info for single OR-term scan */ + Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */ + int jmp1 = 0; /* Address of jump operation */ +- if( pAndExpr && !ExprHasProperty(pOrExpr, EP_FromJoin) ){ ++ assert( (pTabItem[0].fg.jointype & JT_LEFT)==0 ++ || ExprHasProperty(pOrExpr, EP_FromJoin) ++ ); ++ if( pAndExpr ){ + pAndExpr->pLeft = pOrExpr; + pOrExpr = pAndExpr; + } +@@ -132748,7 +137337,7 @@ + if( pSubWInfo ){ + WhereLoop *pSubLoop; + int addrExplain = sqlite3WhereExplainOneScan( +- pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0 ++ pParse, pOrTab, &pSubWInfo->a[0], 0 + ); + sqlite3WhereAddScanStatus(v, pOrTab, &pSubWInfo->a[0], addrExplain); + +@@ -132758,23 +137347,23 @@ + ** row will be skipped in subsequent sub-WHERE clauses. + */ + if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ +- int r; + int iSet = ((ii==pOrWc->nTerm-1)?-1:ii); + if( HasRowid(pTab) ){ +- r = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, regRowid, 0); ++ sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, -1, regRowid); + jmp1 = sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, 0, +- r,iSet); ++ regRowid, iSet); + VdbeCoverage(v); + }else{ + Index *pPk = sqlite3PrimaryKeyIndex(pTab); + int nPk = pPk->nKeyCol; + int iPk; ++ int r; + + /* Read the PK into an array of temp registers. */ + r = sqlite3GetTempRange(pParse, nPk); + for(iPk=0; iPk<nPk; iPk++){ + int iCol = pPk->aiColumn[iPk]; +- sqlite3ExprCodeGetColumnToReg(pParse, pTab, iCol, iCur, r+iPk); ++ sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol, r+iPk); + } + + /* Check if the temp table already contains this key. If so, +@@ -132847,6 +137436,7 @@ + } + } + } ++ ExplainQueryPlanPop(pParse); + pLevel->u.pCovidx = pCov; + if( pCov ) pLevel->iIdxCur = iCovCur; + if( pAndExpr ){ +@@ -132919,7 +137509,7 @@ + } + pE = pTerm->pExpr; + assert( pE!=0 ); +- if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){ ++ if( (pTabItem->fg.jointype&JT_LEFT) && !ExprHasProperty(pE,EP_FromJoin) ){ + continue; + } + +@@ -133006,7 +137596,6 @@ + pLevel->addrFirst = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin); + VdbeComment((v, "record LEFT JOIN hit")); +- sqlite3ExprCacheClear(pParse); + for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){ + testcase( pTerm->wtFlags & TERM_VIRTUAL ); + testcase( pTerm->wtFlags & TERM_CODED ); +@@ -133222,18 +137811,18 @@ + int *pisComplete, /* True if the only wildcard is % in the last character */ + int *pnoCase /* True if uppercase is equivalent to lowercase */ + ){ +- const u8 *z = 0; /* String on RHS of LIKE operator */ ++ const u8 *z = 0; /* String on RHS of LIKE operator */ + Expr *pRight, *pLeft; /* Right and left size of LIKE operator */ + ExprList *pList; /* List of operands to the LIKE operator */ +- int c; /* One character in z[] */ ++ u8 c; /* One character in z[] */ + int cnt; /* Number of non-wildcard prefix characters */ +- char wc[4]; /* Wildcard characters */ ++ u8 wc[4]; /* Wildcard characters */ + sqlite3 *db = pParse->db; /* Database connection */ + sqlite3_value *pVal = 0; + int op; /* Opcode of pRight */ + int rc; /* Result code to return */ + +- if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, wc) ){ ++ if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, (char*)wc) ){ + return 0; + } + #ifdef SQLITE_EBCDIC +@@ -133258,23 +137847,6 @@ + } + if( z ){ + +- /* If the RHS begins with a digit or a minus sign, then the LHS must +- ** be an ordinary column (not a virtual table column) with TEXT affinity. +- ** Otherwise the LHS might be numeric and "lhs >= rhs" would be false +- ** even though "lhs LIKE rhs" is true. But if the RHS does not start +- ** with a digit or '-', then "lhs LIKE rhs" will always be false if +- ** the LHS is numeric and so the optimization still works. +- */ +- if( sqlite3Isdigit(z[0]) || z[0]=='-' ){ +- if( pLeft->op!=TK_COLUMN +- || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT +- || IsVirtual(pLeft->pTab) /* Value might be numeric */ +- ){ +- sqlite3ValueFree(pVal); +- return 0; +- } +- } +- + /* Count the number of prefix characters prior to the first wildcard */ + cnt = 0; + while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ +@@ -133284,11 +137856,13 @@ + + /* The optimization is possible only if (1) the pattern does not begin + ** with a wildcard and if (2) the non-wildcard prefix does not end with +- ** an (illegal 0xff) character. The second condition is necessary so ++ ** an (illegal 0xff) character, or (3) the pattern does not consist of ++ ** a single escape character. The second condition is necessary so + ** that we can increment the prefix key to find an upper bound for the +- ** range search. +- */ +- if( cnt!=0 && 255!=(u8)z[cnt-1] ){ ++ ** range search. The third is because the caller assumes that the pattern ++ ** consists of at least one character after all escapes have been ++ ** removed. */ ++ if( cnt!=0 && 255!=(u8)z[cnt-1] && (cnt>1 || z[0]!=wc[3]) ){ + Expr *pPrefix; + + /* A "complete" match if the pattern ends with "*" or "%" */ +@@ -133305,6 +137879,32 @@ + zNew[iTo++] = zNew[iFrom]; + } + zNew[iTo] = 0; ++ ++ /* If the RHS begins with a digit or a minus sign, then the LHS must be ++ ** an ordinary column (not a virtual table column) with TEXT affinity. ++ ** Otherwise the LHS might be numeric and "lhs >= rhs" would be false ++ ** even though "lhs LIKE rhs" is true. But if the RHS does not start ++ ** with a digit or '-', then "lhs LIKE rhs" will always be false if ++ ** the LHS is numeric and so the optimization still works. ++ ** ++ ** 2018-09-10 ticket c94369cae9b561b1f996d0054bfab11389f9d033 ++ ** The RHS pattern must not be '/%' because the termination condition ++ ** will then become "x<'0'" and if the affinity is numeric, will then ++ ** be converted into "x<0", which is incorrect. ++ */ ++ if( sqlite3Isdigit(zNew[0]) ++ || zNew[0]=='-' ++ || (zNew[0]+1=='0' && iTo==1) ++ ){ ++ if( pLeft->op!=TK_COLUMN ++ || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT ++ || IsVirtual(pLeft->y.pTab) /* Value might be numeric */ ++ ){ ++ sqlite3ExprDelete(db, pPrefix); ++ sqlite3ValueFree(pVal); ++ return 0; ++ } ++ } + } + *ppPrefix = pPrefix; + +@@ -133366,6 +137966,7 @@ + ** If the expression matches none of the patterns above, return 0. + */ + static int isAuxiliaryVtabOperator( ++ sqlite3 *db, /* Parsing context */ + Expr *pExpr, /* Test this expression */ + unsigned char *peOp2, /* OUT: 0 for MATCH, or else an op2 value */ + Expr **ppLeft, /* Column expression to left of MATCH/op2 */ +@@ -133389,16 +137990,54 @@ + if( pList==0 || pList->nExpr!=2 ){ + return 0; + } ++ ++ /* Built-in operators MATCH, GLOB, LIKE, and REGEXP attach to a ++ ** virtual table on their second argument, which is the same as ++ ** the left-hand side operand in their in-fix form. ++ ** ++ ** vtab_column MATCH expression ++ ** MATCH(expression,vtab_column) ++ */ + pCol = pList->a[1].pExpr; +- if( pCol->op!=TK_COLUMN || !IsVirtual(pCol->pTab) ){ +- return 0; ++ if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){ ++ for(i=0; i<ArraySize(aOp); i++){ ++ if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){ ++ *peOp2 = aOp[i].eOp2; ++ *ppRight = pList->a[0].pExpr; ++ *ppLeft = pCol; ++ return 1; ++ } ++ } + } +- for(i=0; i<ArraySize(aOp); i++){ +- if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){ +- *peOp2 = aOp[i].eOp2; +- *ppRight = pList->a[0].pExpr; +- *ppLeft = pCol; +- return 1; ++ ++ /* We can also match against the first column of overloaded ++ ** functions where xFindFunction returns a value of at least ++ ** SQLITE_INDEX_CONSTRAINT_FUNCTION. ++ ** ++ ** OVERLOADED(vtab_column,expression) ++ ** ++ ** Historically, xFindFunction expected to see lower-case function ++ ** names. But for this use case, xFindFunction is expected to deal ++ ** with function names in an arbitrary case. ++ */ ++ pCol = pList->a[0].pExpr; ++ if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){ ++ sqlite3_vtab *pVtab; ++ sqlite3_module *pMod; ++ void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**); ++ void *pNotUsed; ++ pVtab = sqlite3GetVTable(db, pCol->y.pTab)->pVtab; ++ assert( pVtab!=0 ); ++ assert( pVtab->pModule!=0 ); ++ pMod = (sqlite3_module *)pVtab->pModule; ++ if( pMod->xFindFunction!=0 ){ ++ i = pMod->xFindFunction(pVtab,2, pExpr->u.zToken, &xNotUsed, &pNotUsed); ++ if( i>=SQLITE_INDEX_CONSTRAINT_FUNCTION ){ ++ *peOp2 = i; ++ *ppRight = pList->a[1].pExpr; ++ *ppLeft = pCol; ++ return 1; ++ } + } + } + }else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){ +@@ -133405,10 +138044,10 @@ + int res = 0; + Expr *pLeft = pExpr->pLeft; + Expr *pRight = pExpr->pRight; +- if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->pTab) ){ ++ if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->y.pTab) ){ + res++; + } +- if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->pTab) ){ ++ if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->y.pTab) ){ + res++; + SWAP(Expr*, pLeft, pRight); + } +@@ -133700,7 +138339,12 @@ + ** empty. + */ + pOrInfo->indexable = indexable; +- pTerm->eOperator = indexable==0 ? 0 : WO_OR; ++ if( indexable ){ ++ pTerm->eOperator = WO_OR; ++ pWC->hasOr = 1; ++ }else{ ++ pTerm->eOperator = WO_OR; ++ } + + /* For a two-way OR, attempt to implementation case 2. + */ +@@ -133841,12 +138485,11 @@ + idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC); + testcase( idxNew==0 ); + exprAnalyze(pSrc, pWC, idxNew); +- pTerm = &pWC->a[idxTerm]; ++ /* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm where used again */ + markTermAsChild(pWC, idxNew, idxTerm); + }else{ + sqlite3ExprListDelete(db, pList); + } +- pTerm->eOperator = WO_NOOP; /* case 1 trumps case 3 */ + } + } + } +@@ -133881,7 +138524,7 @@ + return 0; + } + pColl = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight); +- if( pColl==0 || sqlite3StrICmp(pColl->zName, "BINARY")==0 ) return 1; ++ if( sqlite3IsBinary(pColl) ) return 1; + return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight); + } + +@@ -134040,7 +138683,7 @@ + pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->pRight); + } + pMaskSet->bVarSelect = 0; +- prereqAll = sqlite3WhereExprUsage(pMaskSet, pExpr); ++ prereqAll = sqlite3WhereExprUsageNN(pMaskSet, pExpr); + if( pMaskSet->bVarSelect ) pTerm->wtFlags |= TERM_VARSELECT; + if( ExprHasProperty(pExpr, EP_FromJoin) ){ + Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->iRightJoinTable); +@@ -134222,7 +138865,7 @@ + } + *pC = c + 1; + } +- zCollSeqName = noCase ? "NOCASE" : "BINARY"; ++ zCollSeqName = noCase ? "NOCASE" : sqlite3StrBINARY; + pNewExpr1 = sqlite3ExprDup(db, pLeft, 0); + pNewExpr1 = sqlite3PExpr(pParse, TK_GE, + sqlite3ExprAddCollateString(pParse,pNewExpr1,zCollSeqName), +@@ -134259,7 +138902,7 @@ + */ + if( pWC->op==TK_AND ){ + Expr *pRight = 0, *pLeft = 0; +- int res = isAuxiliaryVtabOperator(pExpr, &eOp2, &pLeft, &pRight); ++ int res = isAuxiliaryVtabOperator(db, pExpr, &eOp2, &pLeft, &pRight); + while( res-- > 0 ){ + int idxNew; + WhereTerm *pNewTerm; +@@ -134356,6 +138999,7 @@ + if( pExpr->op==TK_NOTNULL + && pExpr->pLeft->op==TK_COLUMN + && pExpr->pLeft->iColumn>=0 ++ && !ExprHasProperty(pExpr, EP_FromJoin) + && OptimizationEnabled(db, SQLITE_Stat34) + ){ + Expr *pNewExpr; +@@ -134433,6 +139077,7 @@ + WhereInfo *pWInfo /* The WHERE processing context */ + ){ + pWC->pWInfo = pWInfo; ++ pWC->hasOr = 0; + pWC->pOuter = 0; + pWC->nTerm = 0; + pWC->nSlot = ArraySize(pWC->aStatic); +@@ -134469,17 +139114,18 @@ + ** a bitmask indicating which tables are used in that expression + ** tree. + */ +-SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){ ++SQLITE_PRIVATE Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){ + Bitmask mask; +- if( p==0 ) return 0; +- if( p->op==TK_COLUMN ){ ++ if( p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){ + return sqlite3WhereGetMask(pMaskSet, p->iTable); ++ }else if( ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ ++ assert( p->op!=TK_IF_NULL_ROW ); ++ return 0; + } + mask = (p->op==TK_IF_NULL_ROW) ? sqlite3WhereGetMask(pMaskSet, p->iTable) : 0; +- assert( !ExprHasProperty(p, EP_TokenOnly) ); +- if( p->pLeft ) mask |= sqlite3WhereExprUsage(pMaskSet, p->pLeft); ++ if( p->pLeft ) mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pLeft); + if( p->pRight ){ +- mask |= sqlite3WhereExprUsage(pMaskSet, p->pRight); ++ mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pRight); + assert( p->x.pList==0 ); + }else if( ExprHasProperty(p, EP_xIsSelect) ){ + if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1; +@@ -134489,6 +139135,9 @@ + } + return mask; + } ++SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){ ++ return p ? sqlite3WhereExprUsageNN(pMaskSet,p) : 0; ++} + SQLITE_PRIVATE Bitmask sqlite3WhereExprListUsage(WhereMaskSet *pMaskSet, ExprList *pList){ + int i; + Bitmask mask = 0; +@@ -134542,6 +139191,7 @@ + pArgs = pItem->u1.pFuncArg; + if( pArgs==0 ) return; + for(j=k=0; j<pArgs->nExpr; j++){ ++ Expr *pRhs; + while( k<pTab->nCol && (pTab->aCol[k].colFlags & COLFLAG_HIDDEN)==0 ){k++;} + if( k>=pTab->nCol ){ + sqlite3ErrorMsg(pParse, "too many arguments on %s() - max %d", +@@ -134552,9 +139202,10 @@ + if( pColRef==0 ) return; + pColRef->iTable = pItem->iCursor; + pColRef->iColumn = k++; +- pColRef->pTab = pTab; +- pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, +- sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0)); ++ pColRef->y.pTab = pTab; ++ pRhs = sqlite3PExpr(pParse, TK_UPLUS, ++ sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0); ++ pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs); + whereClauseInsert(pWC, pTerm, TERM_DYNAMIC); + } + } +@@ -134630,15 +139281,38 @@ + } + + /* +-** Return TRUE if the innermost loop of the WHERE clause implementation +-** returns rows in ORDER BY order for complete run of the inner loop. ++** In the ORDER BY LIMIT optimization, if the inner-most loop is known ++** to emit rows in increasing order, and if the last row emitted by the ++** inner-most loop did not fit within the sorter, then we can skip all ++** subsequent rows for the current iteration of the inner loop (because they ++** will not fit in the sorter either) and continue with the second inner ++** loop - the loop immediately outside the inner-most. + ** +-** Across multiple iterations of outer loops, the output rows need not be +-** sorted. As long as rows are sorted for just the innermost loop, this +-** routine can return TRUE. ++** When a row does not fit in the sorter (because the sorter already ++** holds LIMIT+OFFSET rows that are smaller), then a jump is made to the ++** label returned by this function. ++** ++** If the ORDER BY LIMIT optimization applies, the jump destination should ++** be the continuation for the second-inner-most loop. If the ORDER BY ++** LIMIT optimization does not apply, then the jump destination should ++** be the continuation for the inner-most loop. ++** ++** It is always safe for this routine to return the continuation of the ++** inner-most loop, in the sense that a correct answer will result. ++** Returning the continuation the second inner loop is an optimization ++** that might make the code run a little faster, but should not change ++** the final answer. + */ +-SQLITE_PRIVATE int sqlite3WhereOrderedInnerLoop(WhereInfo *pWInfo){ +- return pWInfo->bOrderedInnerLoop; ++SQLITE_PRIVATE int sqlite3WhereOrderByLimitOptLabel(WhereInfo *pWInfo){ ++ WhereLevel *pInner; ++ if( !pWInfo->bOrderedInnerLoop ){ ++ /* The ORDER BY LIMIT optimization does not apply. Jump to the ++ ** continuation of the inner-most loop. */ ++ return pWInfo->iContinue; ++ } ++ pInner = &pWInfo->a[pWInfo->nLevel-1]; ++ assert( pInner->addrNxt!=0 ); ++ return pInner->addrNxt; + } + + /* +@@ -135365,7 +140039,6 @@ + VdbeComment((v, "for %s", pTable->zName)); + + /* Fill the automatic index with content */ +- sqlite3ExprCachePush(pParse); + pTabItem = &pWC->pWInfo->pTabList->a[pLevel->iFrom]; + if( pTabItem->fg.viaCoroutine ){ + int regYield = pTabItem->regReturn; +@@ -135373,7 +140046,7 @@ + sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub); + addrTop = sqlite3VdbeAddOp1(v, OP_Yield, regYield); + VdbeCoverage(v); +- VdbeComment((v, "next row of \"%s\"", pTabItem->pTab->zName)); ++ VdbeComment((v, "next row of %s", pTabItem->pTab->zName)); + }else{ + addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v); + } +@@ -135395,7 +140068,6 @@ + translateColumnToCopy(pParse, addrTop, pLevel->iTabCur, + pTabItem->regResult, 1); + sqlite3VdbeGoto(v, addrTop); +- pTabItem->fg.viaCoroutine = 0; + }else{ + sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v); + } +@@ -135402,7 +140074,6 @@ + sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX); + sqlite3VdbeJumpHere(v, addrTop); + sqlite3ReleaseTempReg(pParse, regRecord); +- sqlite3ExprCachePop(pParse); + + /* Jump here when skipping the initialization */ + sqlite3VdbeJumpHere(v, addrInit); +@@ -135508,6 +140179,20 @@ + testcase( pTerm->eOperator & WO_ALL ); + if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue; + if( pTerm->wtFlags & TERM_VNULL ) continue; ++ if( (pSrc->fg.jointype & JT_LEFT)!=0 ++ && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) ++ && (pTerm->eOperator & (WO_IS|WO_ISNULL)) ++ ){ ++ /* An "IS" term in the WHERE clause where the virtual table is the rhs ++ ** of a LEFT JOIN. Do not pass this term to the virtual table ++ ** implementation, as this can lead to incorrect results from SQL such ++ ** as: ++ ** ++ ** "LEFT JOIN vtab WHERE vtab.col IS NULL" */ ++ testcase( pTerm->eOperator & WO_ISNULL ); ++ testcase( pTerm->eOperator & WO_IS ); ++ continue; ++ } + assert( pTerm->u.leftColumn>=(-1) ); + pIdxCons[j].iColumn = pTerm->u.leftColumn; + pIdxCons[j].iTermOffset = i; +@@ -135560,9 +140245,11 @@ + ** method of the virtual table with the sqlite3_index_info object that + ** comes in as the 3rd argument to this function. + ** +-** If an error occurs, pParse is populated with an error message and a +-** non-zero value is returned. Otherwise, 0 is returned and the output +-** part of the sqlite3_index_info structure is left populated. ++** If an error occurs, pParse is populated with an error message and an ++** appropriate error code is returned. A return of SQLITE_CONSTRAINT from ++** xBestIndex is not considered an error. SQLITE_CONSTRAINT indicates that ++** the current configuration of "unusable" flags in sqlite3_index_info can ++** not result in a valid plan. + ** + ** Whether or not an error is returned, it is the responsibility of the + ** caller to eventually free p->idxStr if p->needToFreeIdxStr indicates +@@ -135576,7 +140263,7 @@ + rc = pVtab->pModule->xBestIndex(pVtab, p); + TRACE_IDX_OUTPUTS(p); + +- if( rc!=SQLITE_OK ){ ++ if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT ){ + if( rc==SQLITE_NOMEM ){ + sqlite3OomFault(pParse->db); + }else if( !pVtab->zErrMsg ){ +@@ -135587,19 +140274,7 @@ + } + sqlite3_free(pVtab->zErrMsg); + pVtab->zErrMsg = 0; +- +-#if 0 +- /* This error is now caught by the caller. +- ** Search for "xBestIndex malfunction" below */ +- for(i=0; i<p->nConstraint; i++){ +- if( !p->aConstraint[i].usable && p->aConstraintUsage[i].argvIndex>0 ){ +- sqlite3ErrorMsg(pParse, +- "table %s: xBestIndex returned an invalid plan", pTab->zName); +- } +- } +-#endif +- +- return pParse->nErr; ++ return rc; + } + #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */ + +@@ -135999,7 +140674,9 @@ + Index *p = pLoop->u.btree.pIndex; + int nEq = pLoop->u.btree.nEq; + +- if( p->nSample>0 && nEq<p->nSampleCol ){ ++ if( p->nSample>0 && nEq<p->nSampleCol ++ && OptimizationEnabled(pParse->db, SQLITE_Stat34) ++ ){ + if( nEq==pBuilder->nRecValid ){ + UnpackedRecord *pRec = pBuilder->pRec; + tRowcnt a[2]; +@@ -136652,6 +141329,14 @@ + sqlite3 *db = pWInfo->pParse->db; + int rc; + ++ /* Stop the search once we hit the query planner search limit */ ++ if( pBuilder->iPlanLimit==0 ){ ++ WHERETRACE(0xffffffff,("=== query planner search limit reached ===\n")); ++ if( pBuilder->pOrSet ) pBuilder->pOrSet->n = 0; ++ return SQLITE_DONE; ++ } ++ pBuilder->iPlanLimit--; ++ + /* If pBuilder->pOrSet is defined, then only keep track of the costs + ** and prereqs. + */ +@@ -136983,15 +141668,12 @@ + ** to mix with a lower range bound from some other source */ + if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue; + +- /* Do not allow IS constraints from the WHERE clause to be used by the ++ /* Do not allow constraints from the WHERE clause to be used by the + ** right table of a LEFT JOIN. Only constraints in the ON clause are + ** allowed */ + if( (pSrc->fg.jointype & JT_LEFT)!=0 + && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) +- && (eOp & (WO_IS|WO_ISNULL))!=0 + ){ +- testcase( eOp & WO_IS ); +- testcase( eOp & WO_ISNULL ); + continue; + } + +@@ -137017,7 +141699,6 @@ + + if( eOp & WO_IN ){ + Expr *pExpr = pTerm->pExpr; +- pNew->wsFlags |= WHERE_COLUMN_IN; + if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + /* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */ + int i; +@@ -137037,6 +141718,42 @@ + assert( nIn>0 ); /* RHS always has 2 or more terms... The parser + ** changes "x IN (?)" into "x=?". */ + } ++ if( pProbe->hasStat1 ){ ++ LogEst M, logK, safetyMargin; ++ /* Let: ++ ** N = the total number of rows in the table ++ ** K = the number of entries on the RHS of the IN operator ++ ** M = the number of rows in the table that match terms to the ++ ** to the left in the same index. If the IN operator is on ++ ** the left-most index column, M==N. ++ ** ++ ** Given the definitions above, it is better to omit the IN operator ++ ** from the index lookup and instead do a scan of the M elements, ++ ** testing each scanned row against the IN operator separately, if: ++ ** ++ ** M*log(K) < K*log(N) ++ ** ++ ** Our estimates for M, K, and N might be inaccurate, so we build in ++ ** a safety margin of 2 (LogEst: 10) that favors using the IN operator ++ ** with the index, as using an index has better worst-case behavior. ++ ** If we do not have real sqlite_stat1 data, always prefer to use ++ ** the index. ++ */ ++ M = pProbe->aiRowLogEst[saved_nEq]; ++ logK = estLog(nIn); ++ safetyMargin = 10; /* TUNING: extra weight for indexed IN */ ++ if( M + logK + safetyMargin < nIn + rLogSize ){ ++ WHERETRACE(0x40, ++ ("Scan preferred over IN operator on column %d of \"%s\" (%d<%d)\n", ++ saved_nEq, pProbe->zName, M+logK+10, nIn+rLogSize)); ++ continue; ++ }else{ ++ WHERETRACE(0x40, ++ ("IN operator preferred on column %d of \"%s\" (%d>=%d)\n", ++ saved_nEq, pProbe->zName, M+logK+10, nIn+rLogSize)); ++ } ++ } ++ pNew->wsFlags |= WHERE_COLUMN_IN; + }else if( eOp & (WO_EQ|WO_IS) ){ + int iCol = pProbe->aiColumn[saved_nEq]; + pNew->wsFlags |= WHERE_COLUMN_EQ; +@@ -137115,6 +141832,7 @@ + && pProbe->nSample + && pNew->u.btree.nEq<=pProbe->nSampleCol + && ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect)) ++ && OptimizationEnabled(db, SQLITE_Stat34) + ){ + Expr *pExpr = pTerm->pExpr; + if( (eOp & (WO_EQ|WO_ISNULL|WO_IS))!=0 ){ +@@ -137203,6 +141921,7 @@ + if( saved_nEq==saved_nSkip + && saved_nEq+1<pProbe->nKeyCol + && pProbe->noSkipScan==0 ++ && OptimizationEnabled(db, SQLITE_SkipScan) + && pProbe->aiRowLogEst[saved_nEq+1]>=42 /* TUNING: Minimum for skip-scan */ + && (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK + ){ +@@ -137266,24 +141985,6 @@ + return 0; + } + +-/* +-** Return a bitmask where 1s indicate that the corresponding column of +-** the table is used by an index. Only the first 63 columns are considered. +-*/ +-static Bitmask columnsInIndex(Index *pIdx){ +- Bitmask m = 0; +- int j; +- for(j=pIdx->nColumn-1; j>=0; j--){ +- int x = pIdx->aiColumn[j]; +- if( x>=0 ){ +- testcase( x==BMS-1 ); +- testcase( x==BMS-2 ); +- if( x<BMS-1 ) m |= MASKBIT(x); +- } +- } +- return m; +-} +- + /* Check to see if a partial index with pPartIndexWhere can be used + ** in the current query. Return true if it can be and false if not. + */ +@@ -137428,14 +142129,16 @@ + /* TUNING: One-time cost for computing the automatic index is + ** estimated to be X*N*log2(N) where N is the number of rows in + ** the table being indexed and where X is 7 (LogEst=28) for normal +- ** tables or 1.375 (LogEst=4) for views and subqueries. The value ++ ** tables or 0.5 (LogEst=-10) for views and subqueries. The value + ** of X is smaller for views and subqueries so that the query planner + ** will be more aggressive about generating automatic indexes for + ** those objects, since there is no opportunity to add schema + ** indexes on subqueries and views. */ +- pNew->rSetup = rLogSize + rSize + 4; ++ pNew->rSetup = rLogSize + rSize; + if( pTab->pSelect==0 && (pTab->tabFlags & TF_Ephemeral)==0 ){ +- pNew->rSetup += 24; ++ pNew->rSetup += 28; ++ }else{ ++ pNew->rSetup -= 10; + } + ApplyCostMultiplier(pNew->rSetup, pTab->costMult); + if( pNew->rSetup<0 ) pNew->rSetup = 0; +@@ -137497,7 +142200,7 @@ + pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED; + m = 0; + }else{ +- m = pSrc->colUsed & ~columnsInIndex(pProbe); ++ m = pSrc->colUsed & pProbe->colNotIdxed; + pNew->wsFlags = (m==0) ? (WHERE_IDX_ONLY|WHERE_INDEXED) : WHERE_INDEXED; + } + +@@ -137644,7 +142347,17 @@ + + /* Invoke the virtual table xBestIndex() method */ + rc = vtabBestIndex(pParse, pSrc->pTab, pIdxInfo); +- if( rc ) return rc; ++ if( rc ){ ++ if( rc==SQLITE_CONSTRAINT ){ ++ /* If the xBestIndex method returns SQLITE_CONSTRAINT, that means ++ ** that the particular combination of parameters provided is unusable. ++ ** Make no entries in the loop table. ++ */ ++ WHERETRACE(0xffff, (" ^^^^--- non-viable plan rejected!\n")); ++ return SQLITE_OK; ++ } ++ return rc; ++ } + + mxTerm = -1; + assert( pNew->nLSlot>=nConstraint ); +@@ -137748,7 +142461,7 @@ + if( pX->pLeft ){ + pC = sqlite3BinaryCompareCollSeq(pHidden->pParse, pX->pLeft, pX->pRight); + } +- zRet = (pC ? pC->zName : "BINARY"); ++ zRet = (pC ? pC->zName : sqlite3StrBINARY); + } + return zRet; + } +@@ -138040,9 +142753,11 @@ + /* Loop over the tables in the join, from left to right */ + pNew = pBuilder->pNew; + whereLoopInit(pNew); ++ pBuilder->iPlanLimit = SQLITE_QUERY_PLANNER_LIMIT; + for(iTab=0, pItem=pTabList->a; pItem<pEnd; iTab++, pItem++){ + Bitmask mUnusable = 0; + pNew->iTab = iTab; ++ pBuilder->iPlanLimit += SQLITE_QUERY_PLANNER_LIMIT_INCR; + pNew->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor); + if( ((pItem->fg.jointype|priorJointype) & (JT_LEFT|JT_CROSS))!=0 ){ + /* This condition is true when pItem is the FROM clause term on the +@@ -138064,11 +142779,19 @@ + { + rc = whereLoopAddBtree(pBuilder, mPrereq); + } +- if( rc==SQLITE_OK ){ ++ if( rc==SQLITE_OK && pBuilder->pWC->hasOr ){ + rc = whereLoopAddOr(pBuilder, mPrereq, mUnusable); + } + mPrior |= pNew->maskSelf; +- if( rc || db->mallocFailed ) break; ++ if( rc || db->mallocFailed ){ ++ if( rc==SQLITE_DONE ){ ++ /* We hit the query planner search limit set by iPlanLimit */ ++ sqlite3_log(SQLITE_WARNING, "abbreviated query algorithm search"); ++ rc = SQLITE_OK; ++ }else{ ++ break; ++ } ++ } + } + + whereLoopClear(db, pNew); +@@ -138571,12 +143294,15 @@ + + if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue; + if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue; +- if( (pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 && pFrom->nRow<10 ){ ++ if( (pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 && pFrom->nRow<3 ){ + /* Do not use an automatic index if the this loop is expected +- ** to run less than 2 times. */ ++ ** to run less than 1.25 times. It is tempting to also exclude ++ ** automatic index usage on an outer loop, but sometimes an automatic ++ ** index is useful in the outer loop of a correlated subquery. */ + assert( 10==sqlite3LogEst(2) ); + continue; + } ++ + /* At this point, pWLoop is a candidate to be the next loop. + ** Compute its cost */ + rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow); +@@ -138596,7 +143322,11 @@ + pWInfo, nRowEst, nOrderBy, isOrdered + ); + } +- rCost = sqlite3LogEstAdd(rUnsorted, aSortCost[isOrdered]); ++ /* TUNING: Add a small extra penalty (5) to sorting as an ++ ** extra encouragment to the query planner to select a plan ++ ** where the rows emerge in the correct order without any sorting ++ ** required. */ ++ rCost = sqlite3LogEstAdd(rUnsorted, aSortCost[isOrdered]) + 5; + + WHERETRACE(0x002, + ("---- sort cost=%-3d (%d/%d) increases cost %3d to %-3d\n", +@@ -138786,6 +143516,7 @@ + pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; + } + } ++ pWInfo->bOrderedInnerLoop = 0; + if( pWInfo->pOrderBy ){ + if( pWInfo->wctrlFlags & WHERE_DISTINCTBY ){ + if( pFrom->isOrdered==pWInfo->pOrderBy->nExpr ){ +@@ -138897,7 +143628,7 @@ + } + if( j!=pIdx->nKeyCol ) continue; + pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_ONEROW|WHERE_INDEXED; +- if( pIdx->isCovering || (pItem->colUsed & ~columnsInIndex(pIdx))==0 ){ ++ if( pIdx->isCovering || (pItem->colUsed & pIdx->colNotIdxed)==0 ){ + pLoop->wsFlags |= WHERE_IDX_ONLY; + } + pLoop->nLTerm = j; +@@ -139158,6 +143889,7 @@ + if( wctrlFlags & WHERE_WANT_DISTINCT ){ + pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; + } ++ ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW")); + }else{ + /* Assign a bit from the bitmask to every term in the FROM clause. + ** +@@ -139553,7 +144285,7 @@ + } + #endif + addrExplain = sqlite3WhereExplainOneScan( +- pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags ++ pParse, pTabList, pLevel, wctrlFlags + ); + pLevel->addrBody = sqlite3VdbeCurrentAddr(v); + notReady = sqlite3WhereCodeOneLoopStart(pWInfo, ii, notReady); +@@ -139577,6 +144309,26 @@ + } + + /* ++** Part of sqlite3WhereEnd() will rewrite opcodes to reference the ++** index rather than the main table. In SQLITE_DEBUG mode, we want ++** to trace those changes if PRAGMA vdbe_addoptrace=on. This routine ++** does that. ++*/ ++#ifndef SQLITE_DEBUG ++# define OpcodeRewriteTrace(D,K,P) /* no-op */ ++#else ++# define OpcodeRewriteTrace(D,K,P) sqlite3WhereOpcodeRewriteTrace(D,K,P) ++ static void sqlite3WhereOpcodeRewriteTrace( ++ sqlite3 *db, ++ int pc, ++ VdbeOp *pOp ++ ){ ++ if( (db->flags & SQLITE_VdbeAddopTrace)==0 ) return; ++ sqlite3VdbePrintOp(0, pc, pOp); ++ } ++#endif ++ ++/* + ** Generate the end of the WHERE loop. See comments on + ** sqlite3WhereBegin() for additional information. + */ +@@ -139592,7 +144344,6 @@ + /* Generate loop termination code. + */ + VdbeModuleComment((v, "End WHERE-core")); +- sqlite3ExprCacheClear(pParse); + for(i=pWInfo->nLevel-1; i>=0; i--){ + int addr; + pLevel = &pWInfo->a[i]; +@@ -139643,10 +144394,17 @@ + for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){ + sqlite3VdbeJumpHere(v, pIn->addrInTop+1); + if( pIn->eEndLoopOp!=OP_Noop ){ ++ if( pIn->nPrefix ){ ++ assert( pLoop->wsFlags & WHERE_IN_EARLYOUT ); ++ sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur, ++ sqlite3VdbeCurrentAddr(v)+2, ++ pIn->iBase, pIn->nPrefix); ++ VdbeCoverage(v); ++ } + sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop); + VdbeCoverage(v); +- VdbeCoverageIf(v, pIn->eEndLoopOp==OP_PrevIfOpen); +- VdbeCoverageIf(v, pIn->eEndLoopOp==OP_NextIfOpen); ++ VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Prev); ++ VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Next); + } + sqlite3VdbeJumpHere(v, pIn->addrInTop-1); + } +@@ -139737,6 +144495,11 @@ + ){ + last = sqlite3VdbeCurrentAddr(v); + k = pLevel->addrBody; ++#ifdef SQLITE_DEBUG ++ if( db->flags & SQLITE_VdbeAddopTrace ){ ++ printf("TRANSLATE opcodes in range %d..%d\n", k, last-1); ++ } ++#endif + pOp = sqlite3VdbeGetOp(v, k); + for(; k<last; k++, pOp++){ + if( pOp->p1!=pLevel->iTabCur ) continue; +@@ -139756,6 +144519,7 @@ + if( x>=0 ){ + pOp->p2 = x; + pOp->p1 = pLevel->iIdxCur; ++ OpcodeRewriteTrace(db, k, pOp); + } + assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || x>=0 + || pWInfo->eOnePass ); +@@ -139762,10 +144526,15 @@ + }else if( pOp->opcode==OP_Rowid ){ + pOp->p1 = pLevel->iIdxCur; + pOp->opcode = OP_IdxRowid; ++ OpcodeRewriteTrace(db, k, pOp); + }else if( pOp->opcode==OP_IfNullRow ){ + pOp->p1 = pLevel->iIdxCur; ++ OpcodeRewriteTrace(db, k, pOp); + } + } ++#ifdef SQLITE_DEBUG ++ if( db->flags & SQLITE_VdbeAddopTrace ) printf("TRANSLATE complete\n"); ++#endif + } + } + +@@ -139777,6 +144546,2263 @@ + } + + /************** End of where.c ***********************************************/ ++/************** Begin file window.c ******************************************/ ++/* ++** 2018 May 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. ++** ++************************************************************************* ++*/ ++/* #include "sqliteInt.h" */ ++ ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ ++/* ++** SELECT REWRITING ++** ++** Any SELECT statement that contains one or more window functions in ++** either the select list or ORDER BY clause (the only two places window ++** functions may be used) is transformed by function sqlite3WindowRewrite() ++** in order to support window function processing. For example, with the ++** schema: ++** ++** CREATE TABLE t1(a, b, c, d, e, f, g); ++** ++** the statement: ++** ++** SELECT a+1, max(b) OVER (PARTITION BY c ORDER BY d) FROM t1 ORDER BY e; ++** ++** is transformed to: ++** ++** SELECT a+1, max(b) OVER (PARTITION BY c ORDER BY d) FROM ( ++** SELECT a, e, c, d, b FROM t1 ORDER BY c, d ++** ) ORDER BY e; ++** ++** The flattening optimization is disabled when processing this transformed ++** SELECT statement. This allows the implementation of the window function ++** (in this case max()) to process rows sorted in order of (c, d), which ++** makes things easier for obvious reasons. More generally: ++** ++** * FROM, WHERE, GROUP BY and HAVING clauses are all moved to ++** the sub-query. ++** ++** * ORDER BY, LIMIT and OFFSET remain part of the parent query. ++** ++** * Terminals from each of the expression trees that make up the ++** select-list and ORDER BY expressions in the parent query are ++** selected by the sub-query. For the purposes of the transformation, ++** terminals are column references and aggregate functions. ++** ++** If there is more than one window function in the SELECT that uses ++** the same window declaration (the OVER bit), then a single scan may ++** be used to process more than one window function. For example: ++** ++** SELECT max(b) OVER (PARTITION BY c ORDER BY d), ++** min(e) OVER (PARTITION BY c ORDER BY d) ++** FROM t1; ++** ++** is transformed in the same way as the example above. However: ++** ++** SELECT max(b) OVER (PARTITION BY c ORDER BY d), ++** min(e) OVER (PARTITION BY a ORDER BY b) ++** FROM t1; ++** ++** Must be transformed to: ++** ++** SELECT max(b) OVER (PARTITION BY c ORDER BY d) FROM ( ++** SELECT e, min(e) OVER (PARTITION BY a ORDER BY b), c, d, b FROM ++** SELECT a, e, c, d, b FROM t1 ORDER BY a, b ++** ) ORDER BY c, d ++** ) ORDER BY e; ++** ++** so that both min() and max() may process rows in the order defined by ++** their respective window declarations. ++** ++** INTERFACE WITH SELECT.C ++** ++** When processing the rewritten SELECT statement, code in select.c calls ++** sqlite3WhereBegin() to begin iterating through the results of the ++** sub-query, which is always implemented as a co-routine. It then calls ++** sqlite3WindowCodeStep() to process rows and finish the scan by calling ++** sqlite3WhereEnd(). ++** ++** sqlite3WindowCodeStep() generates VM code so that, for each row returned ++** by the sub-query a sub-routine (OP_Gosub) coded by select.c is invoked. ++** When the sub-routine is invoked: ++** ++** * The results of all window-functions for the row are stored ++** in the associated Window.regResult registers. ++** ++** * The required terminal values are stored in the current row of ++** temp table Window.iEphCsr. ++** ++** In some cases, depending on the window frame and the specific window ++** functions invoked, sqlite3WindowCodeStep() caches each entire partition ++** in a temp table before returning any rows. In other cases it does not. ++** This detail is encapsulated within this file, the code generated by ++** select.c is the same in either case. ++** ++** BUILT-IN WINDOW FUNCTIONS ++** ++** This implementation features the following built-in window functions: ++** ++** row_number() ++** rank() ++** dense_rank() ++** percent_rank() ++** cume_dist() ++** ntile(N) ++** lead(expr [, offset [, default]]) ++** lag(expr [, offset [, default]]) ++** first_value(expr) ++** last_value(expr) ++** nth_value(expr, N) ++** ++** These are the same built-in window functions supported by Postgres. ++** Although the behaviour of aggregate window functions (functions that ++** can be used as either aggregates or window funtions) allows them to ++** be implemented using an API, built-in window functions are much more ++** esoteric. Additionally, some window functions (e.g. nth_value()) ++** may only be implemented by caching the entire partition in memory. ++** As such, some built-in window functions use the same API as aggregate ++** window functions and some are implemented directly using VDBE ++** instructions. Additionally, for those functions that use the API, the ++** window frame is sometimes modified before the SELECT statement is ++** rewritten. For example, regardless of the specified window frame, the ++** row_number() function always uses: ++** ++** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++** ++** See sqlite3WindowUpdate() for details. ++** ++** As well as some of the built-in window functions, aggregate window ++** functions min() and max() are implemented using VDBE instructions if ++** the start of the window frame is declared as anything other than ++** UNBOUNDED PRECEDING. ++*/ ++ ++/* ++** Implementation of built-in window function row_number(). Assumes that the ++** window frame has been coerced to: ++** ++** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++*/ ++static void row_numberStepFunc( ++ sqlite3_context *pCtx, ++ int nArg, ++ sqlite3_value **apArg ++){ ++ i64 *p = (i64*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p ) (*p)++; ++ UNUSED_PARAMETER(nArg); ++ UNUSED_PARAMETER(apArg); ++} ++static void row_numberValueFunc(sqlite3_context *pCtx){ ++ i64 *p = (i64*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ sqlite3_result_int64(pCtx, (p ? *p : 0)); ++} ++ ++/* ++** Context object type used by rank(), dense_rank(), percent_rank() and ++** cume_dist(). ++*/ ++struct CallCount { ++ i64 nValue; ++ i64 nStep; ++ i64 nTotal; ++}; ++ ++/* ++** Implementation of built-in window function dense_rank(). Assumes that ++** the window frame has been set to: ++** ++** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++*/ ++static void dense_rankStepFunc( ++ sqlite3_context *pCtx, ++ int nArg, ++ sqlite3_value **apArg ++){ ++ struct CallCount *p; ++ p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p ) p->nStep = 1; ++ UNUSED_PARAMETER(nArg); ++ UNUSED_PARAMETER(apArg); ++} ++static void dense_rankValueFunc(sqlite3_context *pCtx){ ++ struct CallCount *p; ++ p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p ){ ++ if( p->nStep ){ ++ p->nValue++; ++ p->nStep = 0; ++ } ++ sqlite3_result_int64(pCtx, p->nValue); ++ } ++} ++ ++/* ++** Implementation of built-in window function rank(). Assumes that ++** the window frame has been set to: ++** ++** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++*/ ++static void rankStepFunc( ++ sqlite3_context *pCtx, ++ int nArg, ++ sqlite3_value **apArg ++){ ++ struct CallCount *p; ++ p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p ){ ++ p->nStep++; ++ if( p->nValue==0 ){ ++ p->nValue = p->nStep; ++ } ++ } ++ UNUSED_PARAMETER(nArg); ++ UNUSED_PARAMETER(apArg); ++} ++static void rankValueFunc(sqlite3_context *pCtx){ ++ struct CallCount *p; ++ p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p ){ ++ sqlite3_result_int64(pCtx, p->nValue); ++ p->nValue = 0; ++ } ++} ++ ++/* ++** Implementation of built-in window function percent_rank(). Assumes that ++** the window frame has been set to: ++** ++** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++*/ ++static void percent_rankStepFunc( ++ sqlite3_context *pCtx, ++ int nArg, ++ sqlite3_value **apArg ++){ ++ struct CallCount *p; ++ UNUSED_PARAMETER(nArg); assert( nArg==1 ); ++ ++ p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p ){ ++ if( p->nTotal==0 ){ ++ p->nTotal = sqlite3_value_int64(apArg[0]); ++ } ++ p->nStep++; ++ if( p->nValue==0 ){ ++ p->nValue = p->nStep; ++ } ++ } ++} ++static void percent_rankValueFunc(sqlite3_context *pCtx){ ++ struct CallCount *p; ++ p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p ){ ++ if( p->nTotal>1 ){ ++ double r = (double)(p->nValue-1) / (double)(p->nTotal-1); ++ sqlite3_result_double(pCtx, r); ++ }else{ ++ sqlite3_result_double(pCtx, 0.0); ++ } ++ p->nValue = 0; ++ } ++} ++ ++/* ++** Implementation of built-in window function cume_dist(). Assumes that ++** the window frame has been set to: ++** ++** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++*/ ++static void cume_distStepFunc( ++ sqlite3_context *pCtx, ++ int nArg, ++ sqlite3_value **apArg ++){ ++ struct CallCount *p; ++ assert( nArg==1 ); UNUSED_PARAMETER(nArg); ++ ++ p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p ){ ++ if( p->nTotal==0 ){ ++ p->nTotal = sqlite3_value_int64(apArg[0]); ++ } ++ p->nStep++; ++ } ++} ++static void cume_distValueFunc(sqlite3_context *pCtx){ ++ struct CallCount *p; ++ p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p && p->nTotal ){ ++ double r = (double)(p->nStep) / (double)(p->nTotal); ++ sqlite3_result_double(pCtx, r); ++ } ++} ++ ++/* ++** Context object for ntile() window function. ++*/ ++struct NtileCtx { ++ i64 nTotal; /* Total rows in partition */ ++ i64 nParam; /* Parameter passed to ntile(N) */ ++ i64 iRow; /* Current row */ ++}; ++ ++/* ++** Implementation of ntile(). This assumes that the window frame has ++** been coerced to: ++** ++** ROWS UNBOUNDED PRECEDING AND CURRENT ROW ++*/ ++static void ntileStepFunc( ++ sqlite3_context *pCtx, ++ int nArg, ++ sqlite3_value **apArg ++){ ++ struct NtileCtx *p; ++ assert( nArg==2 ); UNUSED_PARAMETER(nArg); ++ p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p ){ ++ if( p->nTotal==0 ){ ++ p->nParam = sqlite3_value_int64(apArg[0]); ++ p->nTotal = sqlite3_value_int64(apArg[1]); ++ if( p->nParam<=0 ){ ++ sqlite3_result_error( ++ pCtx, "argument of ntile must be a positive integer", -1 ++ ); ++ } ++ } ++ p->iRow++; ++ } ++} ++static void ntileValueFunc(sqlite3_context *pCtx){ ++ struct NtileCtx *p; ++ p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p && p->nParam>0 ){ ++ int nSize = (p->nTotal / p->nParam); ++ if( nSize==0 ){ ++ sqlite3_result_int64(pCtx, p->iRow); ++ }else{ ++ i64 nLarge = p->nTotal - p->nParam*nSize; ++ i64 iSmall = nLarge*(nSize+1); ++ i64 iRow = p->iRow-1; ++ ++ assert( (nLarge*(nSize+1) + (p->nParam-nLarge)*nSize)==p->nTotal ); ++ ++ if( iRow<iSmall ){ ++ sqlite3_result_int64(pCtx, 1 + iRow/(nSize+1)); ++ }else{ ++ sqlite3_result_int64(pCtx, 1 + nLarge + (iRow-iSmall)/nSize); ++ } ++ } ++ } ++} ++ ++/* ++** Context object for last_value() window function. ++*/ ++struct LastValueCtx { ++ sqlite3_value *pVal; ++ int nVal; ++}; ++ ++/* ++** Implementation of last_value(). ++*/ ++static void last_valueStepFunc( ++ sqlite3_context *pCtx, ++ int nArg, ++ sqlite3_value **apArg ++){ ++ struct LastValueCtx *p; ++ UNUSED_PARAMETER(nArg); ++ p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p ){ ++ sqlite3_value_free(p->pVal); ++ p->pVal = sqlite3_value_dup(apArg[0]); ++ if( p->pVal==0 ){ ++ sqlite3_result_error_nomem(pCtx); ++ }else{ ++ p->nVal++; ++ } ++ } ++} ++static void last_valueInvFunc( ++ sqlite3_context *pCtx, ++ int nArg, ++ sqlite3_value **apArg ++){ ++ struct LastValueCtx *p; ++ UNUSED_PARAMETER(nArg); ++ UNUSED_PARAMETER(apArg); ++ p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( ALWAYS(p) ){ ++ p->nVal--; ++ if( p->nVal==0 ){ ++ sqlite3_value_free(p->pVal); ++ p->pVal = 0; ++ } ++ } ++} ++static void last_valueValueFunc(sqlite3_context *pCtx){ ++ struct LastValueCtx *p; ++ p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p && p->pVal ){ ++ sqlite3_result_value(pCtx, p->pVal); ++ } ++} ++static void last_valueFinalizeFunc(sqlite3_context *pCtx){ ++ struct LastValueCtx *p; ++ p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); ++ if( p && p->pVal ){ ++ sqlite3_result_value(pCtx, p->pVal); ++ sqlite3_value_free(p->pVal); ++ p->pVal = 0; ++ } ++} ++ ++/* ++** Static names for the built-in window function names. These static ++** names are used, rather than string literals, so that FuncDef objects ++** can be associated with a particular window function by direct ++** comparison of the zName pointer. Example: ++** ++** if( pFuncDef->zName==row_valueName ){ ... } ++*/ ++static const char row_numberName[] = "row_number"; ++static const char dense_rankName[] = "dense_rank"; ++static const char rankName[] = "rank"; ++static const char percent_rankName[] = "percent_rank"; ++static const char cume_distName[] = "cume_dist"; ++static const char ntileName[] = "ntile"; ++static const char last_valueName[] = "last_value"; ++static const char nth_valueName[] = "nth_value"; ++static const char first_valueName[] = "first_value"; ++static const char leadName[] = "lead"; ++static const char lagName[] = "lag"; ++ ++/* ++** No-op implementations of xStep() and xFinalize(). Used as place-holders ++** for built-in window functions that never call those interfaces. ++** ++** The noopValueFunc() is called but is expected to do nothing. The ++** noopStepFunc() is never called, and so it is marked with NO_TEST to ++** let the test coverage routine know not to expect this function to be ++** invoked. ++*/ ++static void noopStepFunc( /*NO_TEST*/ ++ sqlite3_context *p, /*NO_TEST*/ ++ int n, /*NO_TEST*/ ++ sqlite3_value **a /*NO_TEST*/ ++){ /*NO_TEST*/ ++ UNUSED_PARAMETER(p); /*NO_TEST*/ ++ UNUSED_PARAMETER(n); /*NO_TEST*/ ++ UNUSED_PARAMETER(a); /*NO_TEST*/ ++ assert(0); /*NO_TEST*/ ++} /*NO_TEST*/ ++static void noopValueFunc(sqlite3_context *p){ UNUSED_PARAMETER(p); /*no-op*/ } ++ ++/* Window functions that use all window interfaces: xStep, xFinal, ++** xValue, and xInverse */ ++#define WINDOWFUNCALL(name,nArg,extra) { \ ++ nArg, (SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \ ++ name ## StepFunc, name ## FinalizeFunc, name ## ValueFunc, \ ++ name ## InvFunc, name ## Name, {0} \ ++} ++ ++/* Window functions that are implemented using bytecode and thus have ++** no-op routines for their methods */ ++#define WINDOWFUNCNOOP(name,nArg,extra) { \ ++ nArg, (SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \ ++ noopStepFunc, noopValueFunc, noopValueFunc, \ ++ noopStepFunc, name ## Name, {0} \ ++} ++ ++/* Window functions that use all window interfaces: xStep, the ++** same routine for xFinalize and xValue and which never call ++** xInverse. */ ++#define WINDOWFUNCX(name,nArg,extra) { \ ++ nArg, (SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \ ++ name ## StepFunc, name ## ValueFunc, name ## ValueFunc, \ ++ noopStepFunc, name ## Name, {0} \ ++} ++ ++ ++/* ++** Register those built-in window functions that are not also aggregates. ++*/ ++SQLITE_PRIVATE void sqlite3WindowFunctions(void){ ++ static FuncDef aWindowFuncs[] = { ++ WINDOWFUNCX(row_number, 0, 0), ++ WINDOWFUNCX(dense_rank, 0, 0), ++ WINDOWFUNCX(rank, 0, 0), ++ WINDOWFUNCX(percent_rank, 0, SQLITE_FUNC_WINDOW_SIZE), ++ WINDOWFUNCX(cume_dist, 0, SQLITE_FUNC_WINDOW_SIZE), ++ WINDOWFUNCX(ntile, 1, SQLITE_FUNC_WINDOW_SIZE), ++ WINDOWFUNCALL(last_value, 1, 0), ++ WINDOWFUNCNOOP(nth_value, 2, 0), ++ WINDOWFUNCNOOP(first_value, 1, 0), ++ WINDOWFUNCNOOP(lead, 1, 0), ++ WINDOWFUNCNOOP(lead, 2, 0), ++ WINDOWFUNCNOOP(lead, 3, 0), ++ WINDOWFUNCNOOP(lag, 1, 0), ++ WINDOWFUNCNOOP(lag, 2, 0), ++ WINDOWFUNCNOOP(lag, 3, 0), ++ }; ++ sqlite3InsertBuiltinFuncs(aWindowFuncs, ArraySize(aWindowFuncs)); ++} ++ ++/* ++** This function is called immediately after resolving the function name ++** for a window function within a SELECT statement. Argument pList is a ++** linked list of WINDOW definitions for the current SELECT statement. ++** Argument pFunc is the function definition just resolved and pWin ++** is the Window object representing the associated OVER clause. This ++** function updates the contents of pWin as follows: ++** ++** * If the OVER clause refered to a named window (as in "max(x) OVER win"), ++** search list pList for a matching WINDOW definition, and update pWin ++** accordingly. If no such WINDOW clause can be found, leave an error ++** in pParse. ++** ++** * If the function is a built-in window function that requires the ++** window to be coerced (see "BUILT-IN WINDOW FUNCTIONS" at the top ++** of this file), pWin is updated here. ++*/ ++SQLITE_PRIVATE void sqlite3WindowUpdate( ++ Parse *pParse, ++ Window *pList, /* List of named windows for this SELECT */ ++ Window *pWin, /* Window frame to update */ ++ FuncDef *pFunc /* Window function definition */ ++){ ++ if( pWin->zName && pWin->eType==0 ){ ++ Window *p; ++ for(p=pList; p; p=p->pNextWin){ ++ if( sqlite3StrICmp(p->zName, pWin->zName)==0 ) break; ++ } ++ if( p==0 ){ ++ sqlite3ErrorMsg(pParse, "no such window: %s", pWin->zName); ++ return; ++ } ++ pWin->pPartition = sqlite3ExprListDup(pParse->db, p->pPartition, 0); ++ pWin->pOrderBy = sqlite3ExprListDup(pParse->db, p->pOrderBy, 0); ++ pWin->pStart = sqlite3ExprDup(pParse->db, p->pStart, 0); ++ pWin->pEnd = sqlite3ExprDup(pParse->db, p->pEnd, 0); ++ pWin->eStart = p->eStart; ++ pWin->eEnd = p->eEnd; ++ pWin->eType = p->eType; ++ } ++ if( pFunc->funcFlags & SQLITE_FUNC_WINDOW ){ ++ sqlite3 *db = pParse->db; ++ if( pWin->pFilter ){ ++ sqlite3ErrorMsg(pParse, ++ "FILTER clause may only be used with aggregate window functions" ++ ); ++ }else ++ if( pFunc->zName==row_numberName || pFunc->zName==ntileName ){ ++ sqlite3ExprDelete(db, pWin->pStart); ++ sqlite3ExprDelete(db, pWin->pEnd); ++ pWin->pStart = pWin->pEnd = 0; ++ pWin->eType = TK_ROWS; ++ pWin->eStart = TK_UNBOUNDED; ++ pWin->eEnd = TK_CURRENT; ++ }else ++ ++ if( pFunc->zName==dense_rankName || pFunc->zName==rankName ++ || pFunc->zName==percent_rankName || pFunc->zName==cume_distName ++ ){ ++ sqlite3ExprDelete(db, pWin->pStart); ++ sqlite3ExprDelete(db, pWin->pEnd); ++ pWin->pStart = pWin->pEnd = 0; ++ pWin->eType = TK_RANGE; ++ pWin->eStart = TK_UNBOUNDED; ++ pWin->eEnd = TK_CURRENT; ++ } ++ } ++ pWin->pFunc = pFunc; ++} ++ ++/* ++** Context object passed through sqlite3WalkExprList() to ++** selectWindowRewriteExprCb() by selectWindowRewriteEList(). ++*/ ++typedef struct WindowRewrite WindowRewrite; ++struct WindowRewrite { ++ Window *pWin; ++ SrcList *pSrc; ++ ExprList *pSub; ++ Select *pSubSelect; /* Current sub-select, if any */ ++}; ++ ++/* ++** Callback function used by selectWindowRewriteEList(). If necessary, ++** this function appends to the output expression-list and updates ++** expression (*ppExpr) in place. ++*/ ++static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){ ++ struct WindowRewrite *p = pWalker->u.pRewrite; ++ Parse *pParse = pWalker->pParse; ++ ++ /* If this function is being called from within a scalar sub-select ++ ** that used by the SELECT statement being processed, only process ++ ** TK_COLUMN expressions that refer to it (the outer SELECT). Do ++ ** not process aggregates or window functions at all, as they belong ++ ** to the scalar sub-select. */ ++ if( p->pSubSelect ){ ++ if( pExpr->op!=TK_COLUMN ){ ++ return WRC_Continue; ++ }else{ ++ int nSrc = p->pSrc->nSrc; ++ int i; ++ for(i=0; i<nSrc; i++){ ++ if( pExpr->iTable==p->pSrc->a[i].iCursor ) break; ++ } ++ if( i==nSrc ) return WRC_Continue; ++ } ++ } ++ ++ switch( pExpr->op ){ ++ ++ case TK_FUNCTION: ++ if( !ExprHasProperty(pExpr, EP_WinFunc) ){ ++ break; ++ }else{ ++ Window *pWin; ++ for(pWin=p->pWin; pWin; pWin=pWin->pNextWin){ ++ if( pExpr->y.pWin==pWin ){ ++ assert( pWin->pOwner==pExpr ); ++ return WRC_Prune; ++ } ++ } ++ } ++ /* Fall through. */ ++ ++ case TK_AGG_FUNCTION: ++ case TK_COLUMN: { ++ Expr *pDup = sqlite3ExprDup(pParse->db, pExpr, 0); ++ p->pSub = sqlite3ExprListAppend(pParse, p->pSub, pDup); ++ if( p->pSub ){ ++ assert( ExprHasProperty(pExpr, EP_Static)==0 ); ++ ExprSetProperty(pExpr, EP_Static); ++ sqlite3ExprDelete(pParse->db, pExpr); ++ ExprClearProperty(pExpr, EP_Static); ++ memset(pExpr, 0, sizeof(Expr)); ++ ++ pExpr->op = TK_COLUMN; ++ pExpr->iColumn = p->pSub->nExpr-1; ++ pExpr->iTable = p->pWin->iEphCsr; ++ } ++ ++ break; ++ } ++ ++ default: /* no-op */ ++ break; ++ } ++ ++ return WRC_Continue; ++} ++static int selectWindowRewriteSelectCb(Walker *pWalker, Select *pSelect){ ++ struct WindowRewrite *p = pWalker->u.pRewrite; ++ Select *pSave = p->pSubSelect; ++ if( pSave==pSelect ){ ++ return WRC_Continue; ++ }else{ ++ p->pSubSelect = pSelect; ++ sqlite3WalkSelect(pWalker, pSelect); ++ p->pSubSelect = pSave; ++ } ++ return WRC_Prune; ++} ++ ++ ++/* ++** Iterate through each expression in expression-list pEList. For each: ++** ++** * TK_COLUMN, ++** * aggregate function, or ++** * window function with a Window object that is not a member of the ++** Window list passed as the second argument (pWin). ++** ++** Append the node to output expression-list (*ppSub). And replace it ++** with a TK_COLUMN that reads the (N-1)th element of table ++** pWin->iEphCsr, where N is the number of elements in (*ppSub) after ++** appending the new one. ++*/ ++static void selectWindowRewriteEList( ++ Parse *pParse, ++ Window *pWin, ++ SrcList *pSrc, ++ ExprList *pEList, /* Rewrite expressions in this list */ ++ ExprList **ppSub /* IN/OUT: Sub-select expression-list */ ++){ ++ Walker sWalker; ++ WindowRewrite sRewrite; ++ ++ memset(&sWalker, 0, sizeof(Walker)); ++ memset(&sRewrite, 0, sizeof(WindowRewrite)); ++ ++ sRewrite.pSub = *ppSub; ++ sRewrite.pWin = pWin; ++ sRewrite.pSrc = pSrc; ++ ++ sWalker.pParse = pParse; ++ sWalker.xExprCallback = selectWindowRewriteExprCb; ++ sWalker.xSelectCallback = selectWindowRewriteSelectCb; ++ sWalker.u.pRewrite = &sRewrite; ++ ++ (void)sqlite3WalkExprList(&sWalker, pEList); ++ ++ *ppSub = sRewrite.pSub; ++} ++ ++/* ++** Append a copy of each expression in expression-list pAppend to ++** expression list pList. Return a pointer to the result list. ++*/ ++static ExprList *exprListAppendList( ++ Parse *pParse, /* Parsing context */ ++ ExprList *pList, /* List to which to append. Might be NULL */ ++ ExprList *pAppend /* List of values to append. Might be NULL */ ++){ ++ if( pAppend ){ ++ int i; ++ int nInit = pList ? pList->nExpr : 0; ++ for(i=0; i<pAppend->nExpr; i++){ ++ Expr *pDup = sqlite3ExprDup(pParse->db, pAppend->a[i].pExpr, 0); ++ pList = sqlite3ExprListAppend(pParse, pList, pDup); ++ if( pList ) pList->a[nInit+i].sortOrder = pAppend->a[i].sortOrder; ++ } ++ } ++ return pList; ++} ++ ++/* ++** If the SELECT statement passed as the second argument does not invoke ++** any SQL window functions, this function is a no-op. Otherwise, it ++** rewrites the SELECT statement so that window function xStep functions ++** are invoked in the correct order as described under "SELECT REWRITING" ++** at the top of this file. ++*/ ++SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){ ++ int rc = SQLITE_OK; ++ if( p->pWin && p->pPrior==0 ){ ++ Vdbe *v = sqlite3GetVdbe(pParse); ++ sqlite3 *db = pParse->db; ++ Select *pSub = 0; /* The subquery */ ++ SrcList *pSrc = p->pSrc; ++ Expr *pWhere = p->pWhere; ++ ExprList *pGroupBy = p->pGroupBy; ++ Expr *pHaving = p->pHaving; ++ ExprList *pSort = 0; ++ ++ ExprList *pSublist = 0; /* Expression list for sub-query */ ++ Window *pMWin = p->pWin; /* Master window object */ ++ Window *pWin; /* Window object iterator */ ++ ++ p->pSrc = 0; ++ p->pWhere = 0; ++ p->pGroupBy = 0; ++ p->pHaving = 0; ++ ++ /* Create the ORDER BY clause for the sub-select. This is the concatenation ++ ** of the window PARTITION and ORDER BY clauses. Then, if this makes it ++ ** redundant, remove the ORDER BY from the parent SELECT. */ ++ pSort = sqlite3ExprListDup(db, pMWin->pPartition, 0); ++ pSort = exprListAppendList(pParse, pSort, pMWin->pOrderBy); ++ if( pSort && p->pOrderBy ){ ++ if( sqlite3ExprListCompare(pSort, p->pOrderBy, -1)==0 ){ ++ sqlite3ExprListDelete(db, p->pOrderBy); ++ p->pOrderBy = 0; ++ } ++ } ++ ++ /* Assign a cursor number for the ephemeral table used to buffer rows. ++ ** The OpenEphemeral instruction is coded later, after it is known how ++ ** many columns the table will have. */ ++ pMWin->iEphCsr = pParse->nTab++; ++ ++ selectWindowRewriteEList(pParse, pMWin, pSrc, p->pEList, &pSublist); ++ selectWindowRewriteEList(pParse, pMWin, pSrc, p->pOrderBy, &pSublist); ++ pMWin->nBufferCol = (pSublist ? pSublist->nExpr : 0); ++ ++ /* Append the PARTITION BY and ORDER BY expressions to the to the ++ ** sub-select expression list. They are required to figure out where ++ ** boundaries for partitions and sets of peer rows lie. */ ++ pSublist = exprListAppendList(pParse, pSublist, pMWin->pPartition); ++ pSublist = exprListAppendList(pParse, pSublist, pMWin->pOrderBy); ++ ++ /* Append the arguments passed to each window function to the ++ ** sub-select expression list. Also allocate two registers for each ++ ** window function - one for the accumulator, another for interim ++ ** results. */ ++ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ ++ pWin->iArgCol = (pSublist ? pSublist->nExpr : 0); ++ pSublist = exprListAppendList(pParse, pSublist, pWin->pOwner->x.pList); ++ if( pWin->pFilter ){ ++ Expr *pFilter = sqlite3ExprDup(db, pWin->pFilter, 0); ++ pSublist = sqlite3ExprListAppend(pParse, pSublist, pFilter); ++ } ++ pWin->regAccum = ++pParse->nMem; ++ pWin->regResult = ++pParse->nMem; ++ sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum); ++ } ++ ++ /* If there is no ORDER BY or PARTITION BY clause, and the window ++ ** function accepts zero arguments, and there are no other columns ++ ** selected (e.g. "SELECT row_number() OVER () FROM t1"), it is possible ++ ** that pSublist is still NULL here. Add a constant expression here to ++ ** keep everything legal in this case. ++ */ ++ if( pSublist==0 ){ ++ pSublist = sqlite3ExprListAppend(pParse, 0, ++ sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0) ++ ); ++ } ++ ++ pSub = sqlite3SelectNew( ++ pParse, pSublist, pSrc, pWhere, pGroupBy, pHaving, pSort, 0, 0 ++ ); ++ p->pSrc = sqlite3SrcListAppend(db, 0, 0, 0); ++ assert( p->pSrc || db->mallocFailed ); ++ if( p->pSrc ){ ++ p->pSrc->a[0].pSelect = pSub; ++ sqlite3SrcListAssignCursors(pParse, p->pSrc); ++ if( sqlite3ExpandSubquery(pParse, &p->pSrc->a[0]) ){ ++ rc = SQLITE_NOMEM; ++ }else{ ++ pSub->selFlags |= SF_Expanded; ++ p->selFlags &= ~SF_Aggregate; ++ sqlite3SelectPrep(pParse, pSub, 0); ++ } ++ ++ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pMWin->iEphCsr, pSublist->nExpr); ++ }else{ ++ sqlite3SelectDelete(db, pSub); ++ } ++ if( db->mallocFailed ) rc = SQLITE_NOMEM; ++ } ++ ++ return rc; ++} ++ ++/* ++** Free the Window object passed as the second argument. ++*/ ++SQLITE_PRIVATE void sqlite3WindowDelete(sqlite3 *db, Window *p){ ++ if( p ){ ++ sqlite3ExprDelete(db, p->pFilter); ++ sqlite3ExprListDelete(db, p->pPartition); ++ sqlite3ExprListDelete(db, p->pOrderBy); ++ sqlite3ExprDelete(db, p->pEnd); ++ sqlite3ExprDelete(db, p->pStart); ++ sqlite3DbFree(db, p->zName); ++ sqlite3DbFree(db, p); ++ } ++} ++ ++/* ++** Free the linked list of Window objects starting at the second argument. ++*/ ++SQLITE_PRIVATE void sqlite3WindowListDelete(sqlite3 *db, Window *p){ ++ while( p ){ ++ Window *pNext = p->pNextWin; ++ sqlite3WindowDelete(db, p); ++ p = pNext; ++ } ++} ++ ++/* ++** The argument expression is an PRECEDING or FOLLOWING offset. The ++** value should be a non-negative integer. If the value is not a ++** constant, change it to NULL. The fact that it is then a non-negative ++** integer will be caught later. But it is important not to leave ++** variable values in the expression tree. ++*/ ++static Expr *sqlite3WindowOffsetExpr(Parse *pParse, Expr *pExpr){ ++ if( 0==sqlite3ExprIsConstant(pExpr) ){ ++ sqlite3ExprDelete(pParse->db, pExpr); ++ pExpr = sqlite3ExprAlloc(pParse->db, TK_NULL, 0, 0); ++ } ++ return pExpr; ++} ++ ++/* ++** Allocate and return a new Window object describing a Window Definition. ++*/ ++SQLITE_PRIVATE Window *sqlite3WindowAlloc( ++ Parse *pParse, /* Parsing context */ ++ int eType, /* Frame type. TK_RANGE or TK_ROWS */ ++ int eStart, /* Start type: CURRENT, PRECEDING, FOLLOWING, UNBOUNDED */ ++ Expr *pStart, /* Start window size if TK_PRECEDING or FOLLOWING */ ++ int eEnd, /* End type: CURRENT, FOLLOWING, TK_UNBOUNDED, PRECEDING */ ++ Expr *pEnd /* End window size if TK_FOLLOWING or PRECEDING */ ++){ ++ Window *pWin = 0; ++ ++ /* Parser assures the following: */ ++ assert( eType==TK_RANGE || eType==TK_ROWS ); ++ assert( eStart==TK_CURRENT || eStart==TK_PRECEDING ++ || eStart==TK_UNBOUNDED || eStart==TK_FOLLOWING ); ++ assert( eEnd==TK_CURRENT || eEnd==TK_FOLLOWING ++ || eEnd==TK_UNBOUNDED || eEnd==TK_PRECEDING ); ++ assert( (eStart==TK_PRECEDING || eStart==TK_FOLLOWING)==(pStart!=0) ); ++ assert( (eEnd==TK_FOLLOWING || eEnd==TK_PRECEDING)==(pEnd!=0) ); ++ ++ ++ /* If a frame is declared "RANGE" (not "ROWS"), then it may not use ++ ** either "<expr> PRECEDING" or "<expr> FOLLOWING". ++ */ ++ if( eType==TK_RANGE && (pStart!=0 || pEnd!=0) ){ ++ sqlite3ErrorMsg(pParse, "RANGE must use only UNBOUNDED or CURRENT ROW"); ++ goto windowAllocErr; ++ } ++ ++ /* Additionally, the ++ ** starting boundary type may not occur earlier in the following list than ++ ** the ending boundary type: ++ ** ++ ** UNBOUNDED PRECEDING ++ ** <expr> PRECEDING ++ ** CURRENT ROW ++ ** <expr> FOLLOWING ++ ** UNBOUNDED FOLLOWING ++ ** ++ ** The parser ensures that "UNBOUNDED PRECEDING" cannot be used as an ending ++ ** boundary, and than "UNBOUNDED FOLLOWING" cannot be used as a starting ++ ** frame boundary. ++ */ ++ if( (eStart==TK_CURRENT && eEnd==TK_PRECEDING) ++ || (eStart==TK_FOLLOWING && (eEnd==TK_PRECEDING || eEnd==TK_CURRENT)) ++ ){ ++ sqlite3ErrorMsg(pParse, "unsupported frame delimiter for ROWS"); ++ goto windowAllocErr; ++ } ++ ++ pWin = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); ++ if( pWin==0 ) goto windowAllocErr; ++ pWin->eType = eType; ++ pWin->eStart = eStart; ++ pWin->eEnd = eEnd; ++ pWin->pEnd = sqlite3WindowOffsetExpr(pParse, pEnd); ++ pWin->pStart = sqlite3WindowOffsetExpr(pParse, pStart); ++ return pWin; ++ ++windowAllocErr: ++ sqlite3ExprDelete(pParse->db, pEnd); ++ sqlite3ExprDelete(pParse->db, pStart); ++ return 0; ++} ++ ++/* ++** Attach window object pWin to expression p. ++*/ ++SQLITE_PRIVATE void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){ ++ if( p ){ ++ assert( p->op==TK_FUNCTION ); ++ /* This routine is only called for the parser. If pWin was not ++ ** allocated due to an OOM, then the parser would fail before ever ++ ** invoking this routine */ ++ if( ALWAYS(pWin) ){ ++ p->y.pWin = pWin; ++ ExprSetProperty(p, EP_WinFunc); ++ pWin->pOwner = p; ++ if( p->flags & EP_Distinct ){ ++ sqlite3ErrorMsg(pParse, ++ "DISTINCT is not supported for window functions"); ++ } ++ } ++ }else{ ++ sqlite3WindowDelete(pParse->db, pWin); ++ } ++} ++ ++/* ++** Return 0 if the two window objects are identical, or non-zero otherwise. ++** Identical window objects can be processed in a single scan. ++*/ ++SQLITE_PRIVATE int sqlite3WindowCompare(Parse *pParse, Window *p1, Window *p2){ ++ if( p1->eType!=p2->eType ) return 1; ++ if( p1->eStart!=p2->eStart ) return 1; ++ if( p1->eEnd!=p2->eEnd ) return 1; ++ if( sqlite3ExprCompare(pParse, p1->pStart, p2->pStart, -1) ) return 1; ++ if( sqlite3ExprCompare(pParse, p1->pEnd, p2->pEnd, -1) ) return 1; ++ if( sqlite3ExprListCompare(p1->pPartition, p2->pPartition, -1) ) return 1; ++ if( sqlite3ExprListCompare(p1->pOrderBy, p2->pOrderBy, -1) ) return 1; ++ return 0; ++} ++ ++ ++/* ++** This is called by code in select.c before it calls sqlite3WhereBegin() ++** to begin iterating through the sub-query results. It is used to allocate ++** and initialize registers and cursors used by sqlite3WindowCodeStep(). ++*/ ++SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse *pParse, Window *pMWin){ ++ Window *pWin; ++ Vdbe *v = sqlite3GetVdbe(pParse); ++ int nPart = (pMWin->pPartition ? pMWin->pPartition->nExpr : 0); ++ nPart += (pMWin->pOrderBy ? pMWin->pOrderBy->nExpr : 0); ++ if( nPart ){ ++ pMWin->regPart = pParse->nMem+1; ++ pParse->nMem += nPart; ++ sqlite3VdbeAddOp3(v, OP_Null, 0, pMWin->regPart, pMWin->regPart+nPart-1); ++ } ++ ++ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ ++ FuncDef *p = pWin->pFunc; ++ if( (p->funcFlags & SQLITE_FUNC_MINMAX) && pWin->eStart!=TK_UNBOUNDED ){ ++ /* The inline versions of min() and max() require a single ephemeral ++ ** table and 3 registers. The registers are used as follows: ++ ** ++ ** regApp+0: slot to copy min()/max() argument to for MakeRecord ++ ** regApp+1: integer value used to ensure keys are unique ++ ** regApp+2: output of MakeRecord ++ */ ++ ExprList *pList = pWin->pOwner->x.pList; ++ KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pList, 0, 0); ++ pWin->csrApp = pParse->nTab++; ++ pWin->regApp = pParse->nMem+1; ++ pParse->nMem += 3; ++ if( pKeyInfo && pWin->pFunc->zName[1]=='i' ){ ++ assert( pKeyInfo->aSortOrder[0]==0 ); ++ pKeyInfo->aSortOrder[0] = 1; ++ } ++ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pWin->csrApp, 2); ++ sqlite3VdbeAppendP4(v, pKeyInfo, P4_KEYINFO); ++ sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1); ++ } ++ else if( p->zName==nth_valueName || p->zName==first_valueName ){ ++ /* Allocate two registers at pWin->regApp. These will be used to ++ ** store the start and end index of the current frame. */ ++ assert( pMWin->iEphCsr ); ++ pWin->regApp = pParse->nMem+1; ++ pWin->csrApp = pParse->nTab++; ++ pParse->nMem += 2; ++ sqlite3VdbeAddOp2(v, OP_OpenDup, pWin->csrApp, pMWin->iEphCsr); ++ } ++ else if( p->zName==leadName || p->zName==lagName ){ ++ assert( pMWin->iEphCsr ); ++ pWin->csrApp = pParse->nTab++; ++ sqlite3VdbeAddOp2(v, OP_OpenDup, pWin->csrApp, pMWin->iEphCsr); ++ } ++ } ++} ++ ++/* ++** A "PRECEDING <expr>" (eCond==0) or "FOLLOWING <expr>" (eCond==1) or the ++** value of the second argument to nth_value() (eCond==2) has just been ++** evaluated and the result left in register reg. This function generates VM ++** code to check that the value is a non-negative integer and throws an ++** exception if it is not. ++*/ ++static void windowCheckIntValue(Parse *pParse, int reg, int eCond){ ++ static const char *azErr[] = { ++ "frame starting offset must be a non-negative integer", ++ "frame ending offset must be a non-negative integer", ++ "second argument to nth_value must be a positive integer" ++ }; ++ static int aOp[] = { OP_Ge, OP_Ge, OP_Gt }; ++ Vdbe *v = sqlite3GetVdbe(pParse); ++ int regZero = sqlite3GetTempReg(pParse); ++ assert( eCond==0 || eCond==1 || eCond==2 ); ++ sqlite3VdbeAddOp2(v, OP_Integer, 0, regZero); ++ sqlite3VdbeAddOp2(v, OP_MustBeInt, reg, sqlite3VdbeCurrentAddr(v)+2); ++ VdbeCoverageIf(v, eCond==0); ++ VdbeCoverageIf(v, eCond==1); ++ VdbeCoverageIf(v, eCond==2); ++ sqlite3VdbeAddOp3(v, aOp[eCond], regZero, sqlite3VdbeCurrentAddr(v)+2, reg); ++ VdbeCoverageNeverNullIf(v, eCond==0); ++ VdbeCoverageNeverNullIf(v, eCond==1); ++ VdbeCoverageNeverNullIf(v, eCond==2); ++ sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_ERROR, OE_Abort); ++ sqlite3VdbeAppendP4(v, (void*)azErr[eCond], P4_STATIC); ++ sqlite3ReleaseTempReg(pParse, regZero); ++} ++ ++/* ++** Return the number of arguments passed to the window-function associated ++** with the object passed as the only argument to this function. ++*/ ++static int windowArgCount(Window *pWin){ ++ ExprList *pList = pWin->pOwner->x.pList; ++ return (pList ? pList->nExpr : 0); ++} ++ ++/* ++** Generate VM code to invoke either xStep() (if bInverse is 0) or ++** xInverse (if bInverse is non-zero) for each window function in the ++** linked list starting at pMWin. Or, for built-in window functions ++** that do not use the standard function API, generate the required ++** inline VM code. ++** ++** If argument csr is greater than or equal to 0, then argument reg is ++** the first register in an array of registers guaranteed to be large ++** enough to hold the array of arguments for each function. In this case ++** the arguments are extracted from the current row of csr into the ++** array of registers before invoking OP_AggStep or OP_AggInverse ++** ++** Or, if csr is less than zero, then the array of registers at reg is ++** already populated with all columns from the current row of the sub-query. ++** ++** If argument regPartSize is non-zero, then it is a register containing the ++** number of rows in the current partition. ++*/ ++static void windowAggStep( ++ Parse *pParse, ++ Window *pMWin, /* Linked list of window functions */ ++ int csr, /* Read arguments from this cursor */ ++ int bInverse, /* True to invoke xInverse instead of xStep */ ++ int reg, /* Array of registers */ ++ int regPartSize /* Register containing size of partition */ ++){ ++ Vdbe *v = sqlite3GetVdbe(pParse); ++ Window *pWin; ++ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ ++ int flags = pWin->pFunc->funcFlags; ++ int regArg; ++ int nArg = windowArgCount(pWin); ++ ++ if( csr>=0 ){ ++ int i; ++ for(i=0; i<nArg; i++){ ++ sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+i, reg+i); ++ } ++ regArg = reg; ++ if( flags & SQLITE_FUNC_WINDOW_SIZE ){ ++ if( nArg==0 ){ ++ regArg = regPartSize; ++ }else{ ++ sqlite3VdbeAddOp2(v, OP_SCopy, regPartSize, reg+nArg); ++ } ++ nArg++; ++ } ++ }else{ ++ assert( !(flags & SQLITE_FUNC_WINDOW_SIZE) ); ++ regArg = reg + pWin->iArgCol; ++ } ++ ++ if( (pWin->pFunc->funcFlags & SQLITE_FUNC_MINMAX) ++ && pWin->eStart!=TK_UNBOUNDED ++ ){ ++ int addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regArg); ++ VdbeCoverage(v); ++ if( bInverse==0 ){ ++ sqlite3VdbeAddOp2(v, OP_AddImm, pWin->regApp+1, 1); ++ sqlite3VdbeAddOp2(v, OP_SCopy, regArg, pWin->regApp); ++ sqlite3VdbeAddOp3(v, OP_MakeRecord, pWin->regApp, 2, pWin->regApp+2); ++ sqlite3VdbeAddOp2(v, OP_IdxInsert, pWin->csrApp, pWin->regApp+2); ++ }else{ ++ sqlite3VdbeAddOp4Int(v, OP_SeekGE, pWin->csrApp, 0, regArg, 1); ++ VdbeCoverageNeverTaken(v); ++ sqlite3VdbeAddOp1(v, OP_Delete, pWin->csrApp); ++ sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); ++ } ++ sqlite3VdbeJumpHere(v, addrIsNull); ++ }else if( pWin->regApp ){ ++ assert( pWin->pFunc->zName==nth_valueName ++ || pWin->pFunc->zName==first_valueName ++ ); ++ assert( bInverse==0 || bInverse==1 ); ++ sqlite3VdbeAddOp2(v, OP_AddImm, pWin->regApp+1-bInverse, 1); ++ }else if( pWin->pFunc->zName==leadName ++ || pWin->pFunc->zName==lagName ++ ){ ++ /* no-op */ ++ }else{ ++ int addrIf = 0; ++ if( pWin->pFilter ){ ++ int regTmp; ++ assert( nArg==0 || nArg==pWin->pOwner->x.pList->nExpr ); ++ assert( nArg || pWin->pOwner->x.pList==0 ); ++ if( csr>0 ){ ++ regTmp = sqlite3GetTempReg(pParse); ++ sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp); ++ }else{ ++ regTmp = regArg + nArg; ++ } ++ addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1); ++ VdbeCoverage(v); ++ if( csr>0 ){ ++ sqlite3ReleaseTempReg(pParse, regTmp); ++ } ++ } ++ if( pWin->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ ++ CollSeq *pColl; ++ assert( nArg>0 ); ++ pColl = sqlite3ExprNNCollSeq(pParse, pWin->pOwner->x.pList->a[0].pExpr); ++ sqlite3VdbeAddOp4(v, OP_CollSeq, 0,0,0, (const char*)pColl, P4_COLLSEQ); ++ } ++ sqlite3VdbeAddOp3(v, bInverse? OP_AggInverse : OP_AggStep, ++ bInverse, regArg, pWin->regAccum); ++ sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF); ++ sqlite3VdbeChangeP5(v, (u8)nArg); ++ if( addrIf ) sqlite3VdbeJumpHere(v, addrIf); ++ } ++ } ++} ++ ++/* ++** Generate VM code to invoke either xValue() (bFinal==0) or xFinalize() ++** (bFinal==1) for each window function in the linked list starting at ++** pMWin. Or, for built-in window-functions that do not use the standard ++** API, generate the equivalent VM code. ++*/ ++static void windowAggFinal(Parse *pParse, Window *pMWin, int bFinal){ ++ Vdbe *v = sqlite3GetVdbe(pParse); ++ Window *pWin; ++ ++ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ ++ if( (pWin->pFunc->funcFlags & SQLITE_FUNC_MINMAX) ++ && pWin->eStart!=TK_UNBOUNDED ++ ){ ++ sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult); ++ sqlite3VdbeAddOp1(v, OP_Last, pWin->csrApp); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp3(v, OP_Column, pWin->csrApp, 0, pWin->regResult); ++ sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); ++ if( bFinal ){ ++ sqlite3VdbeAddOp1(v, OP_ResetSorter, pWin->csrApp); ++ } ++ }else if( pWin->regApp ){ ++ }else{ ++ if( bFinal ){ ++ sqlite3VdbeAddOp2(v, OP_AggFinal, pWin->regAccum, windowArgCount(pWin)); ++ sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF); ++ sqlite3VdbeAddOp2(v, OP_Copy, pWin->regAccum, pWin->regResult); ++ sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum); ++ }else{ ++ sqlite3VdbeAddOp3(v, OP_AggValue, pWin->regAccum, windowArgCount(pWin), ++ pWin->regResult); ++ sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF); ++ } ++ } ++ } ++} ++ ++/* ++** This function generates VM code to invoke the sub-routine at address ++** lblFlushPart once for each partition with the entire partition cached in ++** the Window.iEphCsr temp table. ++*/ ++static void windowPartitionCache( ++ Parse *pParse, ++ Select *p, /* The rewritten SELECT statement */ ++ WhereInfo *pWInfo, /* WhereInfo to call WhereEnd() on */ ++ int regFlushPart, /* Register to use with Gosub lblFlushPart */ ++ int lblFlushPart, /* Subroutine to Gosub to */ ++ int *pRegSize /* OUT: Register containing partition size */ ++){ ++ Window *pMWin = p->pWin; ++ Vdbe *v = sqlite3GetVdbe(pParse); ++ int iSubCsr = p->pSrc->a[0].iCursor; ++ int nSub = p->pSrc->a[0].pTab->nCol; ++ int k; ++ ++ int reg = pParse->nMem+1; ++ int regRecord = reg+nSub; ++ int regRowid = regRecord+1; ++ ++ *pRegSize = regRowid; ++ pParse->nMem += nSub + 2; ++ ++ /* Load the column values for the row returned by the sub-select ++ ** into an array of registers starting at reg. */ ++ for(k=0; k<nSub; k++){ ++ sqlite3VdbeAddOp3(v, OP_Column, iSubCsr, k, reg+k); ++ } ++ sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, nSub, regRecord); ++ ++ /* Check if this is the start of a new partition. If so, call the ++ ** flush_partition sub-routine. */ ++ if( pMWin->pPartition ){ ++ int addr; ++ ExprList *pPart = pMWin->pPartition; ++ int nPart = pPart->nExpr; ++ int regNewPart = reg + pMWin->nBufferCol; ++ KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pPart, 0, 0); ++ ++ addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPart, pMWin->regPart,nPart); ++ sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO); ++ sqlite3VdbeAddOp3(v, OP_Jump, addr+2, addr+4, addr+2); ++ VdbeCoverageEqNe(v); ++ sqlite3VdbeAddOp3(v, OP_Copy, regNewPart, pMWin->regPart, nPart-1); ++ sqlite3VdbeAddOp2(v, OP_Gosub, regFlushPart, lblFlushPart); ++ VdbeComment((v, "call flush_partition")); ++ } ++ ++ /* Buffer the current row in the ephemeral table. */ ++ sqlite3VdbeAddOp2(v, OP_NewRowid, pMWin->iEphCsr, regRowid); ++ sqlite3VdbeAddOp3(v, OP_Insert, pMWin->iEphCsr, regRecord, regRowid); ++ ++ /* End of the input loop */ ++ sqlite3WhereEnd(pWInfo); ++ ++ /* Invoke "flush_partition" to deal with the final (or only) partition */ ++ sqlite3VdbeAddOp2(v, OP_Gosub, regFlushPart, lblFlushPart); ++ VdbeComment((v, "call flush_partition")); ++} ++ ++/* ++** Invoke the sub-routine at regGosub (generated by code in select.c) to ++** return the current row of Window.iEphCsr. If all window functions are ++** aggregate window functions that use the standard API, a single ++** OP_Gosub instruction is all that this routine generates. Extra VM code ++** for per-row processing is only generated for the following built-in window ++** functions: ++** ++** nth_value() ++** first_value() ++** lag() ++** lead() ++*/ ++static void windowReturnOneRow( ++ Parse *pParse, ++ Window *pMWin, ++ int regGosub, ++ int addrGosub ++){ ++ Vdbe *v = sqlite3GetVdbe(pParse); ++ Window *pWin; ++ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ ++ FuncDef *pFunc = pWin->pFunc; ++ if( pFunc->zName==nth_valueName ++ || pFunc->zName==first_valueName ++ ){ ++ int csr = pWin->csrApp; ++ int lbl = sqlite3VdbeMakeLabel(v); ++ int tmpReg = sqlite3GetTempReg(pParse); ++ sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult); ++ ++ if( pFunc->zName==nth_valueName ){ ++ sqlite3VdbeAddOp3(v, OP_Column, pMWin->iEphCsr, pWin->iArgCol+1,tmpReg); ++ windowCheckIntValue(pParse, tmpReg, 2); ++ }else{ ++ sqlite3VdbeAddOp2(v, OP_Integer, 1, tmpReg); ++ } ++ sqlite3VdbeAddOp3(v, OP_Add, tmpReg, pWin->regApp, tmpReg); ++ sqlite3VdbeAddOp3(v, OP_Gt, pWin->regApp+1, lbl, tmpReg); ++ VdbeCoverageNeverNull(v); ++ sqlite3VdbeAddOp3(v, OP_SeekRowid, csr, 0, tmpReg); ++ VdbeCoverageNeverTaken(v); ++ sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol, pWin->regResult); ++ sqlite3VdbeResolveLabel(v, lbl); ++ sqlite3ReleaseTempReg(pParse, tmpReg); ++ } ++ else if( pFunc->zName==leadName || pFunc->zName==lagName ){ ++ int nArg = pWin->pOwner->x.pList->nExpr; ++ int iEph = pMWin->iEphCsr; ++ int csr = pWin->csrApp; ++ int lbl = sqlite3VdbeMakeLabel(v); ++ int tmpReg = sqlite3GetTempReg(pParse); ++ ++ if( nArg<3 ){ ++ sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult); ++ }else{ ++ sqlite3VdbeAddOp3(v, OP_Column, iEph, pWin->iArgCol+2, pWin->regResult); ++ } ++ sqlite3VdbeAddOp2(v, OP_Rowid, iEph, tmpReg); ++ if( nArg<2 ){ ++ int val = (pFunc->zName==leadName ? 1 : -1); ++ sqlite3VdbeAddOp2(v, OP_AddImm, tmpReg, val); ++ }else{ ++ int op = (pFunc->zName==leadName ? OP_Add : OP_Subtract); ++ int tmpReg2 = sqlite3GetTempReg(pParse); ++ sqlite3VdbeAddOp3(v, OP_Column, iEph, pWin->iArgCol+1, tmpReg2); ++ sqlite3VdbeAddOp3(v, op, tmpReg2, tmpReg, tmpReg); ++ sqlite3ReleaseTempReg(pParse, tmpReg2); ++ } ++ ++ sqlite3VdbeAddOp3(v, OP_SeekRowid, csr, lbl, tmpReg); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol, pWin->regResult); ++ sqlite3VdbeResolveLabel(v, lbl); ++ sqlite3ReleaseTempReg(pParse, tmpReg); ++ } ++ } ++ sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub); ++} ++ ++/* ++** Invoke the code generated by windowReturnOneRow() and, optionally, the ++** xInverse() function for each window function, for one or more rows ++** from the Window.iEphCsr temp table. This routine generates VM code ++** similar to: ++** ++** while( regCtr>0 ){ ++** regCtr--; ++** windowReturnOneRow() ++** if( bInverse ){ ++** AggInverse ++** } ++** Next (Window.iEphCsr) ++** } ++*/ ++static void windowReturnRows( ++ Parse *pParse, ++ Window *pMWin, /* List of window functions */ ++ int regCtr, /* Register containing number of rows */ ++ int regGosub, /* Register for Gosub addrGosub */ ++ int addrGosub, /* Address of sub-routine for ReturnOneRow */ ++ int regInvArg, /* Array of registers for xInverse args */ ++ int regInvSize /* Register containing size of partition */ ++){ ++ int addr; ++ Vdbe *v = sqlite3GetVdbe(pParse); ++ windowAggFinal(pParse, pMWin, 0); ++ addr = sqlite3VdbeAddOp3(v, OP_IfPos, regCtr, sqlite3VdbeCurrentAddr(v)+2 ,1); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); ++ windowReturnOneRow(pParse, pMWin, regGosub, addrGosub); ++ if( regInvArg ){ ++ windowAggStep(pParse, pMWin, pMWin->iEphCsr, 1, regInvArg, regInvSize); ++ } ++ sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, addr); ++ VdbeCoverage(v); ++ sqlite3VdbeJumpHere(v, addr+1); /* The OP_Goto */ ++} ++ ++/* ++** Generate code to set the accumulator register for each window function ++** in the linked list passed as the second argument to NULL. And perform ++** any equivalent initialization required by any built-in window functions ++** in the list. ++*/ ++static int windowInitAccum(Parse *pParse, Window *pMWin){ ++ Vdbe *v = sqlite3GetVdbe(pParse); ++ int regArg; ++ int nArg = 0; ++ Window *pWin; ++ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ ++ FuncDef *pFunc = pWin->pFunc; ++ sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum); ++ nArg = MAX(nArg, windowArgCount(pWin)); ++ if( pFunc->zName==nth_valueName ++ || pFunc->zName==first_valueName ++ ){ ++ sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp); ++ sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1); ++ } ++ ++ if( (pFunc->funcFlags & SQLITE_FUNC_MINMAX) && pWin->csrApp ){ ++ assert( pWin->eStart!=TK_UNBOUNDED ); ++ sqlite3VdbeAddOp1(v, OP_ResetSorter, pWin->csrApp); ++ sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1); ++ } ++ } ++ regArg = pParse->nMem+1; ++ pParse->nMem += nArg; ++ return regArg; ++} ++ ++ ++/* ++** This function does the work of sqlite3WindowCodeStep() for all "ROWS" ++** window frame types except for "BETWEEN UNBOUNDED PRECEDING AND CURRENT ++** ROW". Pseudo-code for each follows. ++** ++** ROWS BETWEEN <expr1> PRECEDING AND <expr2> FOLLOWING ++** ++** ... ++** if( new partition ){ ++** Gosub flush_partition ++** } ++** Insert (record in eph-table) ++** sqlite3WhereEnd() ++** Gosub flush_partition ++** ++** flush_partition: ++** Once { ++** OpenDup (iEphCsr -> csrStart) ++** OpenDup (iEphCsr -> csrEnd) ++** } ++** regStart = <expr1> // PRECEDING expression ++** regEnd = <expr2> // FOLLOWING expression ++** if( regStart<0 || regEnd<0 ){ error! } ++** Rewind (csr,csrStart,csrEnd) // if EOF goto flush_partition_done ++** Next(csrEnd) // if EOF skip Aggstep ++** Aggstep (csrEnd) ++** if( (regEnd--)<=0 ){ ++** AggFinal (xValue) ++** Gosub addrGosub ++** Next(csr) // if EOF goto flush_partition_done ++** if( (regStart--)<=0 ){ ++** AggInverse (csrStart) ++** Next(csrStart) ++** } ++** } ++** flush_partition_done: ++** ResetSorter (csr) ++** Return ++** ++** ROWS BETWEEN <expr> PRECEDING AND CURRENT ROW ++** ROWS BETWEEN CURRENT ROW AND <expr> FOLLOWING ++** ROWS BETWEEN UNBOUNDED PRECEDING AND <expr> FOLLOWING ++** ++** These are similar to the above. For "CURRENT ROW", intialize the ++** register to 0. For "UNBOUNDED PRECEDING" to infinity. ++** ++** ROWS BETWEEN <expr> PRECEDING AND UNBOUNDED FOLLOWING ++** ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ++** ++** Rewind (csr,csrStart,csrEnd) // if EOF goto flush_partition_done ++** while( 1 ){ ++** Next(csrEnd) // Exit while(1) at EOF ++** Aggstep (csrEnd) ++** } ++** while( 1 ){ ++** AggFinal (xValue) ++** Gosub addrGosub ++** Next(csr) // if EOF goto flush_partition_done ++** if( (regStart--)<=0 ){ ++** AggInverse (csrStart) ++** Next(csrStart) ++** } ++** } ++** ++** For the "CURRENT ROW AND UNBOUNDED FOLLOWING" case, the final if() ++** condition is always true (as if regStart were initialized to 0). ++** ++** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ++** ++** This is the only RANGE case handled by this routine. It modifies the ++** second while( 1 ) loop in "ROWS BETWEEN CURRENT ... UNBOUNDED..." to ++** be: ++** ++** while( 1 ){ ++** AggFinal (xValue) ++** while( 1 ){ ++** regPeer++ ++** Gosub addrGosub ++** Next(csr) // if EOF goto flush_partition_done ++** if( new peer ) break; ++** } ++** while( (regPeer--)>0 ){ ++** AggInverse (csrStart) ++** Next(csrStart) ++** } ++** } ++** ++** ROWS BETWEEN <expr> FOLLOWING AND <expr> FOLLOWING ++** ++** regEnd = regEnd - regStart ++** Rewind (csr,csrStart,csrEnd) // if EOF goto flush_partition_done ++** Aggstep (csrEnd) ++** Next(csrEnd) // if EOF fall-through ++** if( (regEnd--)<=0 ){ ++** if( (regStart--)<=0 ){ ++** AggFinal (xValue) ++** Gosub addrGosub ++** Next(csr) // if EOF goto flush_partition_done ++** } ++** AggInverse (csrStart) ++** Next (csrStart) ++** } ++** ++** ROWS BETWEEN <expr> PRECEDING AND <expr> PRECEDING ++** ++** Replace the bit after "Rewind" in the above with: ++** ++** if( (regEnd--)<=0 ){ ++** AggStep (csrEnd) ++** Next (csrEnd) ++** } ++** AggFinal (xValue) ++** Gosub addrGosub ++** Next(csr) // if EOF goto flush_partition_done ++** if( (regStart--)<=0 ){ ++** AggInverse (csr2) ++** Next (csr2) ++** } ++** ++*/ ++static void windowCodeRowExprStep( ++ Parse *pParse, ++ Select *p, ++ WhereInfo *pWInfo, ++ int regGosub, ++ int addrGosub ++){ ++ Window *pMWin = p->pWin; ++ Vdbe *v = sqlite3GetVdbe(pParse); ++ int regFlushPart; /* Register for "Gosub flush_partition" */ ++ int lblFlushPart; /* Label for "Gosub flush_partition" */ ++ int lblFlushDone; /* Label for "Gosub flush_partition_done" */ ++ ++ int regArg; ++ int addr; ++ int csrStart = pParse->nTab++; ++ int csrEnd = pParse->nTab++; ++ int regStart; /* Value of <expr> PRECEDING */ ++ int regEnd; /* Value of <expr> FOLLOWING */ ++ int addrGoto; ++ int addrTop; ++ int addrIfPos1 = 0; ++ int addrIfPos2 = 0; ++ int regSize = 0; ++ ++ assert( pMWin->eStart==TK_PRECEDING ++ || pMWin->eStart==TK_CURRENT ++ || pMWin->eStart==TK_FOLLOWING ++ || pMWin->eStart==TK_UNBOUNDED ++ ); ++ assert( pMWin->eEnd==TK_FOLLOWING ++ || pMWin->eEnd==TK_CURRENT ++ || pMWin->eEnd==TK_UNBOUNDED ++ || pMWin->eEnd==TK_PRECEDING ++ ); ++ ++ /* Allocate register and label for the "flush_partition" sub-routine. */ ++ regFlushPart = ++pParse->nMem; ++ lblFlushPart = sqlite3VdbeMakeLabel(v); ++ lblFlushDone = sqlite3VdbeMakeLabel(v); ++ ++ regStart = ++pParse->nMem; ++ regEnd = ++pParse->nMem; ++ ++ windowPartitionCache(pParse, p, pWInfo, regFlushPart, lblFlushPart, ®Size); ++ ++ addrGoto = sqlite3VdbeAddOp0(v, OP_Goto); ++ ++ /* Start of "flush_partition" */ ++ sqlite3VdbeResolveLabel(v, lblFlushPart); ++ sqlite3VdbeAddOp2(v, OP_Once, 0, sqlite3VdbeCurrentAddr(v)+3); ++ VdbeCoverage(v); ++ VdbeComment((v, "Flush_partition subroutine")); ++ sqlite3VdbeAddOp2(v, OP_OpenDup, csrStart, pMWin->iEphCsr); ++ sqlite3VdbeAddOp2(v, OP_OpenDup, csrEnd, pMWin->iEphCsr); ++ ++ /* If either regStart or regEnd are not non-negative integers, throw ++ ** an exception. */ ++ if( pMWin->pStart ){ ++ sqlite3ExprCode(pParse, pMWin->pStart, regStart); ++ windowCheckIntValue(pParse, regStart, 0); ++ } ++ if( pMWin->pEnd ){ ++ sqlite3ExprCode(pParse, pMWin->pEnd, regEnd); ++ windowCheckIntValue(pParse, regEnd, 1); ++ } ++ ++ /* If this is "ROWS <expr1> FOLLOWING AND ROWS <expr2> FOLLOWING", do: ++ ** ++ ** if( regEnd<regStart ){ ++ ** // The frame always consists of 0 rows ++ ** regStart = regSize; ++ ** } ++ ** regEnd = regEnd - regStart; ++ */ ++ if( pMWin->pEnd && pMWin->eStart==TK_FOLLOWING ){ ++ assert( pMWin->pStart!=0 ); ++ assert( pMWin->eEnd==TK_FOLLOWING ); ++ sqlite3VdbeAddOp3(v, OP_Ge, regStart, sqlite3VdbeCurrentAddr(v)+2, regEnd); ++ VdbeCoverageNeverNull(v); ++ sqlite3VdbeAddOp2(v, OP_Copy, regSize, regStart); ++ sqlite3VdbeAddOp3(v, OP_Subtract, regStart, regEnd, regEnd); ++ } ++ ++ if( pMWin->pStart && pMWin->eEnd==TK_PRECEDING ){ ++ assert( pMWin->pEnd!=0 ); ++ assert( pMWin->eStart==TK_PRECEDING ); ++ sqlite3VdbeAddOp3(v, OP_Le, regStart, sqlite3VdbeCurrentAddr(v)+3, regEnd); ++ VdbeCoverageNeverNull(v); ++ sqlite3VdbeAddOp2(v, OP_Copy, regSize, regStart); ++ sqlite3VdbeAddOp2(v, OP_Copy, regSize, regEnd); ++ } ++ ++ /* Initialize the accumulator register for each window function to NULL */ ++ regArg = windowInitAccum(pParse, pMWin); ++ ++ sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr, lblFlushDone); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp2(v, OP_Rewind, csrStart, lblFlushDone); ++ VdbeCoverageNeverTaken(v); ++ sqlite3VdbeChangeP5(v, 1); ++ sqlite3VdbeAddOp2(v, OP_Rewind, csrEnd, lblFlushDone); ++ VdbeCoverageNeverTaken(v); ++ sqlite3VdbeChangeP5(v, 1); ++ ++ /* Invoke AggStep function for each window function using the row that ++ ** csrEnd currently points to. Or, if csrEnd is already at EOF, ++ ** do nothing. */ ++ addrTop = sqlite3VdbeCurrentAddr(v); ++ if( pMWin->eEnd==TK_PRECEDING ){ ++ addrIfPos1 = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0 , 1); ++ VdbeCoverage(v); ++ } ++ sqlite3VdbeAddOp2(v, OP_Next, csrEnd, sqlite3VdbeCurrentAddr(v)+2); ++ VdbeCoverage(v); ++ addr = sqlite3VdbeAddOp0(v, OP_Goto); ++ windowAggStep(pParse, pMWin, csrEnd, 0, regArg, regSize); ++ if( pMWin->eEnd==TK_UNBOUNDED ){ ++ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop); ++ sqlite3VdbeJumpHere(v, addr); ++ addrTop = sqlite3VdbeCurrentAddr(v); ++ }else{ ++ sqlite3VdbeJumpHere(v, addr); ++ if( pMWin->eEnd==TK_PRECEDING ){ ++ sqlite3VdbeJumpHere(v, addrIfPos1); ++ } ++ } ++ ++ if( pMWin->eEnd==TK_FOLLOWING ){ ++ addrIfPos1 = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0 , 1); ++ VdbeCoverage(v); ++ } ++ if( pMWin->eStart==TK_FOLLOWING ){ ++ addrIfPos2 = sqlite3VdbeAddOp3(v, OP_IfPos, regStart, 0 , 1); ++ VdbeCoverage(v); ++ } ++ windowAggFinal(pParse, pMWin, 0); ++ windowReturnOneRow(pParse, pMWin, regGosub, addrGosub); ++ sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)+2); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp2(v, OP_Goto, 0, lblFlushDone); ++ if( pMWin->eStart==TK_FOLLOWING ){ ++ sqlite3VdbeJumpHere(v, addrIfPos2); ++ } ++ ++ if( pMWin->eStart==TK_CURRENT ++ || pMWin->eStart==TK_PRECEDING ++ || pMWin->eStart==TK_FOLLOWING ++ ){ ++ int lblSkipInverse = sqlite3VdbeMakeLabel(v);; ++ if( pMWin->eStart==TK_PRECEDING ){ ++ sqlite3VdbeAddOp3(v, OP_IfPos, regStart, lblSkipInverse, 1); ++ VdbeCoverage(v); ++ } ++ if( pMWin->eStart==TK_FOLLOWING ){ ++ sqlite3VdbeAddOp2(v, OP_Next, csrStart, sqlite3VdbeCurrentAddr(v)+2); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp2(v, OP_Goto, 0, lblSkipInverse); ++ }else{ ++ sqlite3VdbeAddOp2(v, OP_Next, csrStart, sqlite3VdbeCurrentAddr(v)+1); ++ VdbeCoverageAlwaysTaken(v); ++ } ++ windowAggStep(pParse, pMWin, csrStart, 1, regArg, regSize); ++ sqlite3VdbeResolveLabel(v, lblSkipInverse); ++ } ++ if( pMWin->eEnd==TK_FOLLOWING ){ ++ sqlite3VdbeJumpHere(v, addrIfPos1); ++ } ++ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop); ++ ++ /* flush_partition_done: */ ++ sqlite3VdbeResolveLabel(v, lblFlushDone); ++ sqlite3VdbeAddOp1(v, OP_ResetSorter, pMWin->iEphCsr); ++ sqlite3VdbeAddOp1(v, OP_Return, regFlushPart); ++ VdbeComment((v, "end flush_partition subroutine")); ++ ++ /* Jump to here to skip over flush_partition */ ++ sqlite3VdbeJumpHere(v, addrGoto); ++} ++ ++/* ++** This function does the work of sqlite3WindowCodeStep() for cases that ++** would normally be handled by windowCodeDefaultStep() when there are ++** one or more built-in window-functions that require the entire partition ++** to be cached in a temp table before any rows can be returned. Additionally. ++** "RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING" is always handled by ++** this function. ++** ++** Pseudo-code corresponding to the VM code generated by this function ++** for each type of window follows. ++** ++** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++** ++** flush_partition: ++** Once { ++** OpenDup (iEphCsr -> csrLead) ++** } ++** Integer ctr 0 ++** foreach row (csrLead){ ++** if( new peer ){ ++** AggFinal (xValue) ++** for(i=0; i<ctr; i++){ ++** Gosub addrGosub ++** Next iEphCsr ++** } ++** Integer ctr 0 ++** } ++** AggStep (csrLead) ++** Incr ctr ++** } ++** ++** AggFinal (xFinalize) ++** for(i=0; i<ctr; i++){ ++** Gosub addrGosub ++** Next iEphCsr ++** } ++** ++** ResetSorter (csr) ++** Return ++** ++** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++** ++** As above, except that the "if( new peer )" branch is always taken. ++** ++** RANGE BETWEEN CURRENT ROW AND CURRENT ROW ++** ++** As above, except that each of the for() loops becomes: ++** ++** for(i=0; i<ctr; i++){ ++** Gosub addrGosub ++** AggInverse (iEphCsr) ++** Next iEphCsr ++** } ++** ++** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ++** ++** flush_partition: ++** Once { ++** OpenDup (iEphCsr -> csrLead) ++** } ++** foreach row (csrLead) { ++** AggStep (csrLead) ++** } ++** foreach row (iEphCsr) { ++** Gosub addrGosub ++** } ++** ++** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ++** ++** flush_partition: ++** Once { ++** OpenDup (iEphCsr -> csrLead) ++** } ++** foreach row (csrLead){ ++** AggStep (csrLead) ++** } ++** Rewind (csrLead) ++** Integer ctr 0 ++** foreach row (csrLead){ ++** if( new peer ){ ++** AggFinal (xValue) ++** for(i=0; i<ctr; i++){ ++** Gosub addrGosub ++** AggInverse (iEphCsr) ++** Next iEphCsr ++** } ++** Integer ctr 0 ++** } ++** Incr ctr ++** } ++** ++** AggFinal (xFinalize) ++** for(i=0; i<ctr; i++){ ++** Gosub addrGosub ++** Next iEphCsr ++** } ++** ++** ResetSorter (csr) ++** Return ++*/ ++static void windowCodeCacheStep( ++ Parse *pParse, ++ Select *p, ++ WhereInfo *pWInfo, ++ int regGosub, ++ int addrGosub ++){ ++ Window *pMWin = p->pWin; ++ Vdbe *v = sqlite3GetVdbe(pParse); ++ int k; ++ int addr; ++ ExprList *pPart = pMWin->pPartition; ++ ExprList *pOrderBy = pMWin->pOrderBy; ++ int nPeer = pOrderBy ? pOrderBy->nExpr : 0; ++ int regNewPeer; ++ ++ int addrGoto; /* Address of Goto used to jump flush_par.. */ ++ int addrNext; /* Jump here for next iteration of loop */ ++ int regFlushPart; ++ int lblFlushPart; ++ int csrLead; ++ int regCtr; ++ int regArg; /* Register array to martial function args */ ++ int regSize; ++ int lblEmpty; ++ int bReverse = pMWin->pOrderBy && pMWin->eStart==TK_CURRENT ++ && pMWin->eEnd==TK_UNBOUNDED; ++ ++ assert( (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_CURRENT) ++ || (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_UNBOUNDED) ++ || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_CURRENT) ++ || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED) ++ ); ++ ++ lblEmpty = sqlite3VdbeMakeLabel(v); ++ regNewPeer = pParse->nMem+1; ++ pParse->nMem += nPeer; ++ ++ /* Allocate register and label for the "flush_partition" sub-routine. */ ++ regFlushPart = ++pParse->nMem; ++ lblFlushPart = sqlite3VdbeMakeLabel(v); ++ ++ csrLead = pParse->nTab++; ++ regCtr = ++pParse->nMem; ++ ++ windowPartitionCache(pParse, p, pWInfo, regFlushPart, lblFlushPart, ®Size); ++ addrGoto = sqlite3VdbeAddOp0(v, OP_Goto); ++ ++ /* Start of "flush_partition" */ ++ sqlite3VdbeResolveLabel(v, lblFlushPart); ++ sqlite3VdbeAddOp2(v, OP_Once, 0, sqlite3VdbeCurrentAddr(v)+2); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp2(v, OP_OpenDup, csrLead, pMWin->iEphCsr); ++ ++ /* Initialize the accumulator register for each window function to NULL */ ++ regArg = windowInitAccum(pParse, pMWin); ++ ++ sqlite3VdbeAddOp2(v, OP_Integer, 0, regCtr); ++ sqlite3VdbeAddOp2(v, OP_Rewind, csrLead, lblEmpty); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr, lblEmpty); ++ VdbeCoverageNeverTaken(v); ++ ++ if( bReverse ){ ++ int addr2 = sqlite3VdbeCurrentAddr(v); ++ windowAggStep(pParse, pMWin, csrLead, 0, regArg, regSize); ++ sqlite3VdbeAddOp2(v, OP_Next, csrLead, addr2); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp2(v, OP_Rewind, csrLead, lblEmpty); ++ VdbeCoverageNeverTaken(v); ++ } ++ addrNext = sqlite3VdbeCurrentAddr(v); ++ ++ if( pOrderBy && (pMWin->eEnd==TK_CURRENT || pMWin->eStart==TK_CURRENT) ){ ++ int bCurrent = (pMWin->eStart==TK_CURRENT); ++ int addrJump = 0; /* Address of OP_Jump below */ ++ if( pMWin->eType==TK_RANGE ){ ++ int iOff = pMWin->nBufferCol + (pPart ? pPart->nExpr : 0); ++ int regPeer = pMWin->regPart + (pPart ? pPart->nExpr : 0); ++ KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pOrderBy, 0, 0); ++ for(k=0; k<nPeer; k++){ ++ sqlite3VdbeAddOp3(v, OP_Column, csrLead, iOff+k, regNewPeer+k); ++ } ++ addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPeer, regPeer, nPeer); ++ sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO); ++ addrJump = sqlite3VdbeAddOp3(v, OP_Jump, addr+2, 0, addr+2); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp3(v, OP_Copy, regNewPeer, regPeer, nPeer-1); ++ } ++ ++ windowReturnRows(pParse, pMWin, regCtr, regGosub, addrGosub, ++ (bCurrent ? regArg : 0), (bCurrent ? regSize : 0) ++ ); ++ if( addrJump ) sqlite3VdbeJumpHere(v, addrJump); ++ } ++ ++ if( bReverse==0 ){ ++ windowAggStep(pParse, pMWin, csrLead, 0, regArg, regSize); ++ } ++ sqlite3VdbeAddOp2(v, OP_AddImm, regCtr, 1); ++ sqlite3VdbeAddOp2(v, OP_Next, csrLead, addrNext); ++ VdbeCoverage(v); ++ ++ windowReturnRows(pParse, pMWin, regCtr, regGosub, addrGosub, 0, 0); ++ ++ sqlite3VdbeResolveLabel(v, lblEmpty); ++ sqlite3VdbeAddOp1(v, OP_ResetSorter, pMWin->iEphCsr); ++ sqlite3VdbeAddOp1(v, OP_Return, regFlushPart); ++ ++ /* Jump to here to skip over flush_partition */ ++ sqlite3VdbeJumpHere(v, addrGoto); ++} ++ ++ ++/* ++** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++** ++** ... ++** if( new partition ){ ++** AggFinal (xFinalize) ++** Gosub addrGosub ++** ResetSorter eph-table ++** } ++** else if( new peer ){ ++** AggFinal (xValue) ++** Gosub addrGosub ++** ResetSorter eph-table ++** } ++** AggStep ++** Insert (record into eph-table) ++** sqlite3WhereEnd() ++** AggFinal (xFinalize) ++** Gosub addrGosub ++** ++** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ++** ++** As above, except take no action for a "new peer". Invoke ++** the sub-routine once only for each partition. ++** ++** RANGE BETWEEN CURRENT ROW AND CURRENT ROW ++** ++** As above, except that the "new peer" condition is handled in the ++** same way as "new partition" (so there is no "else if" block). ++** ++** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++** ++** As above, except assume every row is a "new peer". ++*/ ++static void windowCodeDefaultStep( ++ Parse *pParse, ++ Select *p, ++ WhereInfo *pWInfo, ++ int regGosub, ++ int addrGosub ++){ ++ Window *pMWin = p->pWin; ++ Vdbe *v = sqlite3GetVdbe(pParse); ++ int k; ++ int iSubCsr = p->pSrc->a[0].iCursor; ++ int nSub = p->pSrc->a[0].pTab->nCol; ++ int reg = pParse->nMem+1; ++ int regRecord = reg+nSub; ++ int regRowid = regRecord+1; ++ int addr; ++ ExprList *pPart = pMWin->pPartition; ++ ExprList *pOrderBy = pMWin->pOrderBy; ++ ++ assert( pMWin->eType==TK_RANGE ++ || (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_CURRENT) ++ ); ++ ++ assert( (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_CURRENT) ++ || (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_UNBOUNDED) ++ || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_CURRENT) ++ || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED && !pOrderBy) ++ ); ++ ++ if( pMWin->eEnd==TK_UNBOUNDED ){ ++ pOrderBy = 0; ++ } ++ ++ pParse->nMem += nSub + 2; ++ ++ /* Load the individual column values of the row returned by ++ ** the sub-select into an array of registers. */ ++ for(k=0; k<nSub; k++){ ++ sqlite3VdbeAddOp3(v, OP_Column, iSubCsr, k, reg+k); ++ } ++ ++ /* Check if this is the start of a new partition or peer group. */ ++ if( pPart || pOrderBy ){ ++ int nPart = (pPart ? pPart->nExpr : 0); ++ int addrGoto = 0; ++ int addrJump = 0; ++ int nPeer = (pOrderBy ? pOrderBy->nExpr : 0); ++ ++ if( pPart ){ ++ int regNewPart = reg + pMWin->nBufferCol; ++ KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pPart, 0, 0); ++ addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPart, pMWin->regPart,nPart); ++ sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO); ++ addrJump = sqlite3VdbeAddOp3(v, OP_Jump, addr+2, 0, addr+2); ++ VdbeCoverageEqNe(v); ++ windowAggFinal(pParse, pMWin, 1); ++ if( pOrderBy ){ ++ addrGoto = sqlite3VdbeAddOp0(v, OP_Goto); ++ } ++ } ++ ++ if( pOrderBy ){ ++ int regNewPeer = reg + pMWin->nBufferCol + nPart; ++ int regPeer = pMWin->regPart + nPart; ++ ++ if( addrJump ) sqlite3VdbeJumpHere(v, addrJump); ++ if( pMWin->eType==TK_RANGE ){ ++ KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pOrderBy, 0, 0); ++ addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPeer, regPeer, nPeer); ++ sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO); ++ addrJump = sqlite3VdbeAddOp3(v, OP_Jump, addr+2, 0, addr+2); ++ VdbeCoverage(v); ++ }else{ ++ addrJump = 0; ++ } ++ windowAggFinal(pParse, pMWin, pMWin->eStart==TK_CURRENT); ++ if( addrGoto ) sqlite3VdbeJumpHere(v, addrGoto); ++ } ++ ++ sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr,sqlite3VdbeCurrentAddr(v)+3); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub); ++ sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)-1); ++ VdbeCoverage(v); ++ ++ sqlite3VdbeAddOp1(v, OP_ResetSorter, pMWin->iEphCsr); ++ sqlite3VdbeAddOp3( ++ v, OP_Copy, reg+pMWin->nBufferCol, pMWin->regPart, nPart+nPeer-1 ++ ); ++ ++ if( addrJump ) sqlite3VdbeJumpHere(v, addrJump); ++ } ++ ++ /* Invoke step function for window functions */ ++ windowAggStep(pParse, pMWin, -1, 0, reg, 0); ++ ++ /* Buffer the current row in the ephemeral table. */ ++ if( pMWin->nBufferCol>0 ){ ++ sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, pMWin->nBufferCol, regRecord); ++ }else{ ++ sqlite3VdbeAddOp2(v, OP_Blob, 0, regRecord); ++ sqlite3VdbeAppendP4(v, (void*)"", 0); ++ } ++ sqlite3VdbeAddOp2(v, OP_NewRowid, pMWin->iEphCsr, regRowid); ++ sqlite3VdbeAddOp3(v, OP_Insert, pMWin->iEphCsr, regRecord, regRowid); ++ ++ /* End the database scan loop. */ ++ sqlite3WhereEnd(pWInfo); ++ ++ windowAggFinal(pParse, pMWin, 1); ++ sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr,sqlite3VdbeCurrentAddr(v)+3); ++ VdbeCoverage(v); ++ sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub); ++ sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)-1); ++ VdbeCoverage(v); ++} ++ ++/* ++** Allocate and return a duplicate of the Window object indicated by the ++** third argument. Set the Window.pOwner field of the new object to ++** pOwner. ++*/ ++SQLITE_PRIVATE Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){ ++ Window *pNew = 0; ++ if( ALWAYS(p) ){ ++ pNew = sqlite3DbMallocZero(db, sizeof(Window)); ++ if( pNew ){ ++ pNew->zName = sqlite3DbStrDup(db, p->zName); ++ pNew->pFilter = sqlite3ExprDup(db, p->pFilter, 0); ++ pNew->pPartition = sqlite3ExprListDup(db, p->pPartition, 0); ++ pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, 0); ++ pNew->eType = p->eType; ++ pNew->eEnd = p->eEnd; ++ pNew->eStart = p->eStart; ++ pNew->pStart = sqlite3ExprDup(db, p->pStart, 0); ++ pNew->pEnd = sqlite3ExprDup(db, p->pEnd, 0); ++ pNew->pOwner = pOwner; ++ } ++ } ++ return pNew; ++} ++ ++/* ++** Return a copy of the linked list of Window objects passed as the ++** second argument. ++*/ ++SQLITE_PRIVATE Window *sqlite3WindowListDup(sqlite3 *db, Window *p){ ++ Window *pWin; ++ Window *pRet = 0; ++ Window **pp = &pRet; ++ ++ for(pWin=p; pWin; pWin=pWin->pNextWin){ ++ *pp = sqlite3WindowDup(db, 0, pWin); ++ if( *pp==0 ) break; ++ pp = &((*pp)->pNextWin); ++ } ++ ++ return pRet; ++} ++ ++/* ++** sqlite3WhereBegin() has already been called for the SELECT statement ++** passed as the second argument when this function is invoked. It generates ++** code to populate the Window.regResult register for each window function and ++** invoke the sub-routine at instruction addrGosub once for each row. ++** This function calls sqlite3WhereEnd() before returning. ++*/ ++SQLITE_PRIVATE void sqlite3WindowCodeStep( ++ Parse *pParse, /* Parse context */ ++ Select *p, /* Rewritten SELECT statement */ ++ WhereInfo *pWInfo, /* Context returned by sqlite3WhereBegin() */ ++ int regGosub, /* Register for OP_Gosub */ ++ int addrGosub /* OP_Gosub here to return each row */ ++){ ++ Window *pMWin = p->pWin; ++ ++ /* There are three different functions that may be used to do the work ++ ** of this one, depending on the window frame and the specific built-in ++ ** window functions used (if any). ++ ** ++ ** windowCodeRowExprStep() handles all "ROWS" window frames, except for: ++ ** ++ ** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++ ** ++ ** The exception is because windowCodeRowExprStep() implements all window ++ ** frame types by caching the entire partition in a temp table, and ++ ** "ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW" is easy enough to ++ ** implement without such a cache. ++ ** ++ ** windowCodeCacheStep() is used for: ++ ** ++ ** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ++ ** ++ ** It is also used for anything not handled by windowCodeRowExprStep() ++ ** that invokes a built-in window function that requires the entire ++ ** partition to be cached in a temp table before any rows are returned ++ ** (e.g. nth_value() or percent_rank()). ++ ** ++ ** Finally, assuming there is no built-in window function that requires ++ ** the partition to be cached, windowCodeDefaultStep() is used for: ++ ** ++ ** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++ ** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ++ ** RANGE BETWEEN CURRENT ROW AND CURRENT ROW ++ ** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ++ ** ++ ** windowCodeDefaultStep() is the only one of the three functions that ++ ** does not cache each partition in a temp table before beginning to ++ ** return rows. ++ */ ++ if( pMWin->eType==TK_ROWS ++ && (pMWin->eStart!=TK_UNBOUNDED||pMWin->eEnd!=TK_CURRENT||!pMWin->pOrderBy) ++ ){ ++ VdbeModuleComment((pParse->pVdbe, "Begin RowExprStep()")); ++ windowCodeRowExprStep(pParse, p, pWInfo, regGosub, addrGosub); ++ }else{ ++ Window *pWin; ++ int bCache = 0; /* True to use CacheStep() */ ++ ++ if( pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED ){ ++ bCache = 1; ++ }else{ ++ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ ++ FuncDef *pFunc = pWin->pFunc; ++ if( (pFunc->funcFlags & SQLITE_FUNC_WINDOW_SIZE) ++ || (pFunc->zName==nth_valueName) ++ || (pFunc->zName==first_valueName) ++ || (pFunc->zName==leadName) ++ || (pFunc->zName==lagName) ++ ){ ++ bCache = 1; ++ break; ++ } ++ } ++ } ++ ++ /* Otherwise, call windowCodeDefaultStep(). */ ++ if( bCache ){ ++ VdbeModuleComment((pParse->pVdbe, "Begin CacheStep()")); ++ windowCodeCacheStep(pParse, p, pWInfo, regGosub, addrGosub); ++ }else{ ++ VdbeModuleComment((pParse->pVdbe, "Begin DefaultStep()")); ++ windowCodeDefaultStep(pParse, p, pWInfo, regGosub, addrGosub); ++ } ++ } ++} ++ ++#endif /* SQLITE_OMIT_WINDOWFUNC */ ++ ++/************** End of window.c **********************************************/ + /************** Begin file parse.c *******************************************/ + /* + ** 2000-05-29 +@@ -139803,6 +146829,7 @@ + ** input grammar file: + */ + /* #include <stdio.h> */ ++/* #include <assert.h> */ + /************ Begin %include sections from the grammar ************************/ + + /* #include "sqliteInt.h" */ +@@ -139854,6 +146881,8 @@ + */ + struct TrigEvent { int a; IdList * b; }; + ++struct FrameBound { int eType; Expr *pExpr; }; ++ + /* + ** Disable lookaside memory allocation for objects that might be + ** shared across database connections. +@@ -139894,10 +146923,18 @@ + static Expr *tokenExpr(Parse *pParse, int op, Token t){ + Expr *p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)+t.n+1); + if( p ){ +- memset(p, 0, sizeof(Expr)); ++ /* memset(p, 0, sizeof(Expr)); */ + p->op = (u8)op; ++ p->affinity = 0; + p->flags = EP_Leaf; + p->iAgg = -1; ++ p->pLeft = p->pRight = 0; ++ p->x.pList = 0; ++ p->pAggInfo = 0; ++ p->y.pTab = 0; ++ p->op2 = 0; ++ p->iTable = 0; ++ p->iColumn = 0; + p->u.zToken = (char*)&p[1]; + memcpy(p->u.zToken, t.z, t.n); + p->u.zToken[t.n] = 0; +@@ -139908,15 +146945,19 @@ + #if SQLITE_MAX_EXPR_DEPTH>0 + p->nHeight = 1; + #endif ++ if( IN_RENAME_OBJECT ){ ++ return (Expr*)sqlite3RenameTokenMap(pParse, (void*)p, &t); ++ } + } + return p; + } + ++ + /* A routine to convert a binary TK_IS or TK_ISNOT expression into a + ** unary TK_ISNULL or TK_NOTNULL expression. */ + static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){ + sqlite3 *db = pParse->db; +- if( pA && pY && pY->op==TK_NULL ){ ++ if( pA && pY && pY->op==TK_NULL && !IN_RENAME_OBJECT ){ + pA->op = (u8)op; + sqlite3ExprDelete(db, pA->pRight); + pA->pRight = 0; +@@ -139985,8 +147026,10 @@ + ** zero the stack is dynamically sized using realloc() + ** sqlite3ParserARG_SDECL A static variable declaration for the %extra_argument + ** sqlite3ParserARG_PDECL A parameter declaration for the %extra_argument ++** sqlite3ParserARG_PARAM Code to pass %extra_argument as a subroutine parameter + ** sqlite3ParserARG_STORE Code to store %extra_argument into yypParser + ** sqlite3ParserARG_FETCH Code to extract %extra_argument from yypParser ++** sqlite3ParserCTX_* As sqlite3ParserARG_ except for %extra_context + ** YYERRORSYMBOL is the code number of the error symbol. If not + ** defined, then do no error processing. + ** YYNSTATE the combined number of states. +@@ -140005,46 +147048,56 @@ + # define INTERFACE 1 + #endif + /************* Begin control #defines *****************************************/ +-#define YYCODETYPE unsigned char +-#define YYNOCODE 253 ++#define YYCODETYPE unsigned short int ++#define YYNOCODE 277 + #define YYACTIONTYPE unsigned short int +-#define YYWILDCARD 83 ++#define YYWILDCARD 91 + #define sqlite3ParserTOKENTYPE Token + typedef union { + int yyinit; + sqlite3ParserTOKENTYPE yy0; +- int yy4; +- struct TrigEvent yy90; +- TriggerStep* yy203; +- struct {int value; int mask;} yy215; +- SrcList* yy259; +- Expr* yy314; +- ExprList* yy322; +- const char* yy336; +- IdList* yy384; +- Select* yy387; +- With* yy451; ++ Expr* yy18; ++ struct TrigEvent yy34; ++ IdList* yy48; ++ int yy70; ++ struct {int value; int mask;} yy111; ++ struct FrameBound yy119; ++ SrcList* yy135; ++ TriggerStep* yy207; ++ Window* yy327; ++ Upsert* yy340; ++ const char* yy392; ++ ExprList* yy420; ++ With* yy449; ++ Select* yy489; + } YYMINORTYPE; + #ifndef YYSTACKDEPTH + #define YYSTACKDEPTH 100 + #endif +-#define sqlite3ParserARG_SDECL Parse *pParse; +-#define sqlite3ParserARG_PDECL ,Parse *pParse +-#define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse +-#define sqlite3ParserARG_STORE yypParser->pParse = pParse ++#define sqlite3ParserARG_SDECL ++#define sqlite3ParserARG_PDECL ++#define sqlite3ParserARG_PARAM ++#define sqlite3ParserARG_FETCH ++#define sqlite3ParserARG_STORE ++#define sqlite3ParserCTX_SDECL Parse *pParse; ++#define sqlite3ParserCTX_PDECL ,Parse *pParse ++#define sqlite3ParserCTX_PARAM ,pParse ++#define sqlite3ParserCTX_FETCH Parse *pParse=yypParser->pParse; ++#define sqlite3ParserCTX_STORE yypParser->pParse=pParse; + #define YYFALLBACK 1 +-#define YYNSTATE 472 +-#define YYNRULE 333 +-#define YYNTOKEN 143 +-#define YY_MAX_SHIFT 471 +-#define YY_MIN_SHIFTREDUCE 681 +-#define YY_MAX_SHIFTREDUCE 1013 +-#define YY_ERROR_ACTION 1014 +-#define YY_ACCEPT_ACTION 1015 +-#define YY_NO_ACTION 1016 +-#define YY_MIN_REDUCE 1017 +-#define YY_MAX_REDUCE 1349 ++#define YYNSTATE 521 ++#define YYNRULE 367 ++#define YYNTOKEN 155 ++#define YY_MAX_SHIFT 520 ++#define YY_MIN_SHIFTREDUCE 756 ++#define YY_MAX_SHIFTREDUCE 1122 ++#define YY_ERROR_ACTION 1123 ++#define YY_ACCEPT_ACTION 1124 ++#define YY_NO_ACTION 1125 ++#define YY_MIN_REDUCE 1126 ++#define YY_MAX_REDUCE 1492 + /************* End control #defines *******************************************/ ++#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) + + /* Define the yytestcase() macro to be a no-op if is not already defined + ** otherwise. +@@ -140109,481 +147162,568 @@ + ** yy_default[] Default action for each state. + ** + *********** Begin parsing tables **********************************************/ +-#define YY_ACTTAB_COUNT (1566) ++#define YY_ACTTAB_COUNT (2009) + static const YYACTIONTYPE yy_action[] = { +- /* 0 */ 1169, 1015, 167, 167, 1, 168, 466, 1313, 466, 1083, +- /* 10 */ 1062, 466, 97, 94, 183, 1057, 466, 329, 1083, 342, +- /* 20 */ 97, 94, 183, 459, 459, 459, 436, 57, 57, 57, +- /* 30 */ 57, 807, 57, 57, 367, 367, 367, 57, 57, 808, +- /* 40 */ 1270, 1088, 1088, 104, 105, 95, 991, 991, 868, 871, +- /* 50 */ 860, 860, 102, 102, 103, 103, 103, 103, 233, 233, +- /* 60 */ 326, 1011, 449, 437, 449, 446, 351, 449, 461, 1142, +- /* 70 */ 463, 342, 449, 426, 1316, 209, 180, 742, 80, 299, +- /* 80 */ 857, 857, 869, 872, 101, 101, 101, 101, 100, 100, +- /* 90 */ 99, 99, 99, 98, 368, 104, 105, 95, 991, 991, +- /* 100 */ 868, 871, 860, 860, 102, 102, 103, 103, 103, 103, +- /* 110 */ 99, 99, 99, 98, 368, 355, 97, 94, 183, 228, +- /* 120 */ 106, 1012, 407, 342, 101, 101, 101, 101, 100, 100, +- /* 130 */ 99, 99, 99, 98, 368, 861, 101, 101, 101, 101, +- /* 140 */ 100, 100, 99, 99, 99, 98, 368, 104, 105, 95, +- /* 150 */ 991, 991, 868, 871, 860, 860, 102, 102, 103, 103, +- /* 160 */ 103, 103, 201, 368, 375, 420, 417, 416, 387, 273, +- /* 170 */ 65, 97, 94, 183, 168, 342, 415, 951, 1343, 396, +- /* 180 */ 66, 1343, 320, 959, 371, 970, 334, 340, 101, 101, +- /* 190 */ 101, 101, 100, 100, 99, 99, 99, 98, 368, 104, +- /* 200 */ 105, 95, 991, 991, 868, 871, 860, 860, 102, 102, +- /* 210 */ 103, 103, 103, 103, 373, 100, 100, 99, 99, 99, +- /* 220 */ 98, 368, 970, 971, 972, 201, 1100, 342, 420, 417, +- /* 230 */ 416, 287, 366, 365, 337, 970, 1162, 463, 949, 415, +- /* 240 */ 101, 101, 101, 101, 100, 100, 99, 99, 99, 98, +- /* 250 */ 368, 104, 105, 95, 991, 991, 868, 871, 860, 860, +- /* 260 */ 102, 102, 103, 103, 103, 103, 777, 241, 233, 233, +- /* 270 */ 9, 847, 970, 971, 972, 390, 998, 1141, 998, 342, +- /* 280 */ 463, 252, 829, 719, 98, 368, 840, 298, 338, 142, +- /* 290 */ 839, 339, 101, 101, 101, 101, 100, 100, 99, 99, +- /* 300 */ 99, 98, 368, 104, 105, 95, 991, 991, 868, 871, +- /* 310 */ 860, 860, 102, 102, 103, 103, 103, 103, 272, 466, +- /* 320 */ 392, 839, 839, 841, 97, 94, 183, 390, 1317, 253, +- /* 330 */ 456, 342, 125, 166, 807, 712, 208, 407, 386, 970, +- /* 340 */ 57, 57, 808, 238, 101, 101, 101, 101, 100, 100, +- /* 350 */ 99, 99, 99, 98, 368, 104, 105, 95, 991, 991, +- /* 360 */ 868, 871, 860, 860, 102, 102, 103, 103, 103, 103, +- /* 370 */ 466, 108, 466, 267, 465, 442, 970, 971, 972, 261, +- /* 380 */ 951, 1344, 909, 342, 1344, 142, 829, 848, 1292, 959, +- /* 390 */ 371, 55, 55, 57, 57, 242, 101, 101, 101, 101, +- /* 400 */ 100, 100, 99, 99, 99, 98, 368, 104, 105, 95, +- /* 410 */ 991, 991, 868, 871, 860, 860, 102, 102, 103, 103, +- /* 420 */ 103, 103, 272, 382, 262, 253, 456, 310, 364, 253, +- /* 430 */ 456, 86, 264, 84, 266, 342, 441, 176, 175, 834, +- /* 440 */ 464, 949, 767, 767, 332, 313, 1094, 396, 101, 101, +- /* 450 */ 101, 101, 100, 100, 99, 99, 99, 98, 368, 104, +- /* 460 */ 105, 95, 991, 991, 868, 871, 860, 860, 102, 102, +- /* 470 */ 103, 103, 103, 103, 227, 227, 233, 233, 233, 233, +- /* 480 */ 387, 273, 234, 234, 326, 950, 463, 342, 463, 298, +- /* 490 */ 463, 914, 914, 404, 463, 1037, 123, 265, 27, 970, +- /* 500 */ 101, 101, 101, 101, 100, 100, 99, 99, 99, 98, +- /* 510 */ 368, 104, 105, 95, 991, 991, 868, 871, 860, 860, +- /* 520 */ 102, 102, 103, 103, 103, 103, 435, 233, 233, 466, +- /* 530 */ 285, 686, 687, 688, 127, 271, 970, 971, 972, 463, +- /* 540 */ 1345, 327, 342, 407, 157, 1012, 988, 13, 13, 181, +- /* 550 */ 41, 41, 101, 101, 101, 101, 100, 100, 99, 99, +- /* 560 */ 99, 98, 368, 715, 794, 378, 104, 105, 95, 991, +- /* 570 */ 991, 868, 871, 860, 860, 102, 102, 103, 103, 103, +- /* 580 */ 103, 970, 378, 377, 346, 239, 847, 1086, 1086, 280, +- /* 590 */ 1169, 283, 204, 203, 202, 177, 298, 342, 407, 298, +- /* 600 */ 715, 840, 169, 299, 407, 839, 82, 101, 101, 101, +- /* 610 */ 101, 100, 100, 99, 99, 99, 98, 368, 970, 971, +- /* 620 */ 972, 104, 105, 95, 991, 991, 868, 871, 860, 860, +- /* 630 */ 102, 102, 103, 103, 103, 103, 839, 839, 841, 362, +- /* 640 */ 240, 124, 1169, 172, 126, 378, 1269, 1169, 1066, 342, +- /* 650 */ 253, 456, 407, 407, 407, 396, 352, 401, 407, 429, +- /* 660 */ 398, 85, 101, 101, 101, 101, 100, 100, 99, 99, +- /* 670 */ 99, 98, 368, 104, 105, 95, 991, 991, 868, 871, +- /* 680 */ 860, 860, 102, 102, 103, 103, 103, 103, 1169, 466, +- /* 690 */ 230, 233, 233, 792, 1235, 1095, 1091, 1293, 1, 77, +- /* 700 */ 278, 342, 205, 463, 974, 911, 1040, 348, 353, 911, +- /* 710 */ 42, 42, 79, 403, 101, 101, 101, 101, 100, 100, +- /* 720 */ 99, 99, 99, 98, 368, 104, 93, 95, 991, 991, +- /* 730 */ 868, 871, 860, 860, 102, 102, 103, 103, 103, 103, +- /* 740 */ 402, 9, 974, 243, 772, 458, 348, 232, 180, 771, +- /* 750 */ 946, 312, 342, 328, 363, 349, 143, 831, 389, 1278, +- /* 760 */ 211, 211, 21, 347, 432, 182, 101, 101, 101, 101, +- /* 770 */ 100, 100, 99, 99, 99, 98, 368, 105, 95, 991, +- /* 780 */ 991, 868, 871, 860, 860, 102, 102, 103, 103, 103, +- /* 790 */ 103, 792, 724, 22, 732, 731, 233, 233, 1239, 256, +- /* 800 */ 391, 274, 342, 211, 79, 360, 257, 413, 463, 397, +- /* 810 */ 207, 288, 260, 450, 79, 1239, 1241, 101, 101, 101, +- /* 820 */ 101, 100, 100, 99, 99, 99, 98, 368, 95, 991, +- /* 830 */ 991, 868, 871, 860, 860, 102, 102, 103, 103, 103, +- /* 840 */ 103, 91, 457, 296, 3, 233, 233, 5, 438, 212, +- /* 850 */ 331, 394, 739, 740, 295, 898, 894, 463, 460, 207, +- /* 860 */ 801, 1237, 722, 211, 698, 843, 1283, 101, 101, 101, +- /* 870 */ 101, 100, 100, 99, 99, 99, 98, 368, 1239, 380, +- /* 880 */ 357, 369, 233, 233, 989, 219, 236, 297, 423, 292, +- /* 890 */ 422, 206, 454, 898, 463, 970, 91, 457, 290, 3, +- /* 900 */ 722, 142, 268, 843, 847, 466, 1258, 149, 388, 425, +- /* 910 */ 88, 89, 769, 460, 930, 87, 447, 90, 369, 468, +- /* 920 */ 467, 385, 989, 839, 1257, 439, 57, 57, 395, 931, +- /* 930 */ 1065, 158, 970, 971, 972, 772, 369, 471, 1019, 399, +- /* 940 */ 771, 253, 456, 254, 932, 119, 891, 454, 233, 233, +- /* 950 */ 4, 970, 1096, 275, 839, 839, 841, 842, 19, 847, +- /* 960 */ 463, 449, 448, 163, 453, 88, 89, 776, 970, 1127, +- /* 970 */ 279, 930, 90, 369, 468, 467, 91, 457, 839, 3, +- /* 980 */ 235, 1064, 466, 1228, 233, 233, 931, 970, 970, 971, +- /* 990 */ 972, 970, 908, 460, 908, 2, 463, 81, 457, 212, +- /* 1000 */ 3, 932, 282, 10, 10, 970, 971, 972, 189, 839, +- /* 1010 */ 839, 841, 842, 19, 460, 284, 369, 354, 907, 286, +- /* 1020 */ 907, 753, 466, 1079, 970, 971, 972, 454, 970, 971, +- /* 1030 */ 972, 754, 970, 1063, 989, 372, 792, 369, 1118, 847, +- /* 1040 */ 291, 452, 466, 10, 10, 88, 89, 142, 454, 168, +- /* 1050 */ 300, 412, 90, 369, 468, 467, 793, 356, 839, 706, +- /* 1060 */ 847, 341, 121, 10, 10, 301, 88, 89, 379, 970, +- /* 1070 */ 971, 972, 989, 90, 369, 468, 467, 244, 205, 839, +- /* 1080 */ 1306, 245, 1135, 245, 250, 1168, 1114, 253, 456, 839, +- /* 1090 */ 839, 841, 842, 19, 1125, 237, 122, 451, 1174, 733, +- /* 1100 */ 324, 324, 323, 222, 321, 466, 1046, 695, 182, 225, +- /* 1110 */ 839, 839, 841, 842, 19, 103, 103, 103, 103, 96, +- /* 1120 */ 185, 466, 259, 1039, 1028, 170, 10, 10, 1027, 421, +- /* 1130 */ 258, 1029, 1300, 708, 792, 466, 408, 734, 8, 347, +- /* 1140 */ 444, 174, 12, 12, 290, 101, 101, 101, 101, 100, +- /* 1150 */ 100, 99, 99, 99, 98, 368, 32, 32, 466, 187, +- /* 1160 */ 466, 1111, 103, 103, 103, 103, 188, 466, 325, 138, +- /* 1170 */ 186, 708, 303, 305, 307, 358, 970, 270, 393, 43, +- /* 1180 */ 43, 44, 44, 1157, 333, 178, 418, 294, 45, 45, +- /* 1190 */ 1232, 318, 101, 101, 101, 101, 100, 100, 99, 99, +- /* 1200 */ 99, 98, 368, 381, 343, 366, 365, 466, 263, 253, +- /* 1210 */ 456, 466, 1062, 970, 971, 972, 1231, 997, 309, 466, +- /* 1220 */ 455, 466, 427, 466, 995, 173, 996, 1303, 46, 46, +- /* 1230 */ 145, 376, 37, 37, 1006, 1277, 466, 214, 1275, 64, +- /* 1240 */ 47, 47, 33, 33, 34, 34, 1003, 67, 466, 998, +- /* 1250 */ 350, 998, 466, 155, 233, 233, 466, 36, 36, 24, +- /* 1260 */ 140, 77, 1154, 466, 383, 466, 463, 428, 466, 48, +- /* 1270 */ 48, 466, 147, 49, 49, 466, 150, 50, 50, 466, +- /* 1280 */ 151, 152, 466, 384, 11, 11, 51, 51, 466, 110, +- /* 1290 */ 110, 153, 52, 52, 411, 466, 38, 38, 466, 191, +- /* 1300 */ 53, 53, 466, 54, 54, 466, 400, 466, 330, 39, +- /* 1310 */ 39, 466, 1164, 466, 25, 466, 56, 56, 466, 131, +- /* 1320 */ 131, 72, 466, 132, 132, 159, 133, 133, 61, 61, +- /* 1330 */ 1226, 195, 40, 40, 111, 111, 58, 58, 406, 112, +- /* 1340 */ 112, 466, 277, 113, 113, 466, 226, 466, 1246, 466, +- /* 1350 */ 197, 466, 164, 466, 409, 466, 198, 466, 199, 466, +- /* 1360 */ 335, 281, 109, 109, 466, 1030, 130, 130, 129, 129, +- /* 1370 */ 117, 117, 116, 116, 114, 114, 115, 115, 60, 60, +- /* 1380 */ 62, 62, 466, 359, 466, 59, 59, 424, 1082, 1081, +- /* 1390 */ 1080, 724, 1073, 1054, 336, 293, 1053, 1052, 1315, 431, +- /* 1400 */ 361, 76, 248, 31, 31, 35, 35, 1072, 249, 440, +- /* 1410 */ 302, 434, 213, 1122, 6, 311, 1212, 107, 83, 251, +- /* 1420 */ 78, 1123, 445, 220, 443, 1036, 304, 23, 1121, 469, +- /* 1430 */ 965, 221, 223, 1104, 314, 224, 344, 317, 315, 316, +- /* 1440 */ 470, 306, 1025, 1120, 308, 1262, 1020, 134, 120, 246, +- /* 1450 */ 682, 370, 171, 255, 1263, 135, 184, 1261, 1260, 374, +- /* 1460 */ 118, 906, 904, 827, 1050, 146, 136, 137, 148, 1049, +- /* 1470 */ 63, 1047, 756, 190, 269, 920, 154, 156, 68, 69, +- /* 1480 */ 70, 71, 139, 923, 192, 193, 144, 919, 345, 128, +- /* 1490 */ 14, 194, 276, 211, 1000, 405, 196, 161, 912, 160, +- /* 1500 */ 26, 697, 410, 295, 200, 289, 414, 162, 419, 73, +- /* 1510 */ 15, 16, 141, 74, 28, 247, 846, 845, 735, 874, +- /* 1520 */ 954, 75, 430, 955, 29, 433, 179, 229, 231, 800, +- /* 1530 */ 165, 795, 87, 210, 889, 79, 875, 17, 873, 877, +- /* 1540 */ 929, 18, 928, 216, 215, 878, 20, 30, 462, 844, +- /* 1550 */ 707, 92, 766, 770, 7, 322, 217, 218, 319, 1308, +- /* 1560 */ 960, 1016, 1016, 1016, 1016, 1307, ++ /* 0 */ 368, 105, 102, 197, 105, 102, 197, 515, 1124, 1, ++ /* 10 */ 1, 520, 2, 1128, 515, 1192, 1171, 1456, 275, 370, ++ /* 20 */ 127, 1389, 1197, 1197, 1192, 1166, 178, 1205, 64, 64, ++ /* 30 */ 477, 887, 322, 428, 348, 37, 37, 808, 362, 888, ++ /* 40 */ 509, 509, 509, 112, 113, 103, 1100, 1100, 953, 956, ++ /* 50 */ 946, 946, 110, 110, 111, 111, 111, 111, 365, 252, ++ /* 60 */ 252, 515, 252, 252, 497, 515, 309, 515, 459, 515, ++ /* 70 */ 1079, 491, 512, 478, 6, 512, 809, 134, 498, 228, ++ /* 80 */ 194, 428, 37, 37, 515, 208, 64, 64, 64, 64, ++ /* 90 */ 13, 13, 109, 109, 109, 109, 108, 108, 107, 107, ++ /* 100 */ 107, 106, 401, 258, 381, 13, 13, 398, 397, 428, ++ /* 110 */ 252, 252, 370, 476, 405, 1104, 1079, 1080, 1081, 386, ++ /* 120 */ 1106, 390, 497, 512, 497, 1423, 1419, 304, 1105, 307, ++ /* 130 */ 1256, 496, 370, 499, 16, 16, 112, 113, 103, 1100, ++ /* 140 */ 1100, 953, 956, 946, 946, 110, 110, 111, 111, 111, ++ /* 150 */ 111, 262, 1107, 495, 1107, 401, 112, 113, 103, 1100, ++ /* 160 */ 1100, 953, 956, 946, 946, 110, 110, 111, 111, 111, ++ /* 170 */ 111, 129, 1425, 343, 1420, 339, 1059, 492, 1057, 263, ++ /* 180 */ 73, 105, 102, 197, 994, 109, 109, 109, 109, 108, ++ /* 190 */ 108, 107, 107, 107, 106, 401, 370, 111, 111, 111, ++ /* 200 */ 111, 104, 492, 89, 1432, 109, 109, 109, 109, 108, ++ /* 210 */ 108, 107, 107, 107, 106, 401, 111, 111, 111, 111, ++ /* 220 */ 112, 113, 103, 1100, 1100, 953, 956, 946, 946, 110, ++ /* 230 */ 110, 111, 111, 111, 111, 109, 109, 109, 109, 108, ++ /* 240 */ 108, 107, 107, 107, 106, 401, 114, 108, 108, 107, ++ /* 250 */ 107, 107, 106, 401, 109, 109, 109, 109, 108, 108, ++ /* 260 */ 107, 107, 107, 106, 401, 152, 399, 399, 399, 109, ++ /* 270 */ 109, 109, 109, 108, 108, 107, 107, 107, 106, 401, ++ /* 280 */ 178, 493, 1412, 434, 1037, 1486, 1079, 515, 1486, 370, ++ /* 290 */ 421, 297, 357, 412, 74, 1079, 109, 109, 109, 109, ++ /* 300 */ 108, 108, 107, 107, 107, 106, 401, 1413, 37, 37, ++ /* 310 */ 1431, 274, 506, 112, 113, 103, 1100, 1100, 953, 956, ++ /* 320 */ 946, 946, 110, 110, 111, 111, 111, 111, 1436, 520, ++ /* 330 */ 2, 1128, 1079, 1080, 1081, 430, 275, 1079, 127, 366, ++ /* 340 */ 933, 1079, 1080, 1081, 220, 1205, 913, 458, 455, 454, ++ /* 350 */ 392, 167, 515, 1035, 152, 445, 924, 453, 152, 874, ++ /* 360 */ 923, 289, 109, 109, 109, 109, 108, 108, 107, 107, ++ /* 370 */ 107, 106, 401, 13, 13, 261, 853, 252, 252, 227, ++ /* 380 */ 106, 401, 370, 1079, 1080, 1081, 311, 388, 1079, 296, ++ /* 390 */ 512, 923, 923, 925, 231, 323, 1255, 1388, 1423, 490, ++ /* 400 */ 274, 506, 12, 208, 274, 506, 112, 113, 103, 1100, ++ /* 410 */ 1100, 953, 956, 946, 946, 110, 110, 111, 111, 111, ++ /* 420 */ 111, 1440, 286, 1128, 288, 1079, 1097, 247, 275, 1098, ++ /* 430 */ 127, 387, 405, 389, 1079, 1080, 1081, 1205, 159, 238, ++ /* 440 */ 255, 321, 461, 316, 460, 225, 790, 105, 102, 197, ++ /* 450 */ 513, 314, 842, 842, 445, 109, 109, 109, 109, 108, ++ /* 460 */ 108, 107, 107, 107, 106, 401, 515, 514, 515, 252, ++ /* 470 */ 252, 1079, 1080, 1081, 435, 370, 1098, 933, 1460, 794, ++ /* 480 */ 274, 506, 512, 105, 102, 197, 336, 63, 63, 64, ++ /* 490 */ 64, 27, 790, 924, 287, 208, 1354, 923, 515, 112, ++ /* 500 */ 113, 103, 1100, 1100, 953, 956, 946, 946, 110, 110, ++ /* 510 */ 111, 111, 111, 111, 107, 107, 107, 106, 401, 49, ++ /* 520 */ 49, 515, 28, 1079, 405, 497, 421, 297, 923, 923, ++ /* 530 */ 925, 186, 468, 1079, 467, 999, 999, 442, 515, 1079, ++ /* 540 */ 334, 515, 45, 45, 1083, 342, 173, 168, 109, 109, ++ /* 550 */ 109, 109, 108, 108, 107, 107, 107, 106, 401, 13, ++ /* 560 */ 13, 205, 13, 13, 252, 252, 1195, 1195, 370, 1079, ++ /* 570 */ 1080, 1081, 787, 265, 5, 359, 494, 512, 469, 1079, ++ /* 580 */ 1080, 1081, 398, 397, 1079, 1079, 1080, 1081, 3, 282, ++ /* 590 */ 1079, 1083, 112, 113, 103, 1100, 1100, 953, 956, 946, ++ /* 600 */ 946, 110, 110, 111, 111, 111, 111, 252, 252, 1015, ++ /* 610 */ 220, 1079, 873, 458, 455, 454, 943, 943, 954, 957, ++ /* 620 */ 512, 252, 252, 453, 1016, 1079, 445, 1107, 1209, 1107, ++ /* 630 */ 1079, 1080, 1081, 515, 512, 426, 1079, 1080, 1081, 1017, ++ /* 640 */ 512, 109, 109, 109, 109, 108, 108, 107, 107, 107, ++ /* 650 */ 106, 401, 1052, 515, 50, 50, 515, 1079, 1080, 1081, ++ /* 660 */ 828, 370, 1051, 379, 411, 1064, 1358, 207, 408, 773, ++ /* 670 */ 829, 1079, 1080, 1081, 64, 64, 322, 64, 64, 1302, ++ /* 680 */ 947, 411, 410, 1358, 1360, 112, 113, 103, 1100, 1100, ++ /* 690 */ 953, 956, 946, 946, 110, 110, 111, 111, 111, 111, ++ /* 700 */ 294, 482, 515, 1037, 1487, 515, 434, 1487, 354, 1120, ++ /* 710 */ 483, 996, 913, 485, 466, 996, 132, 178, 33, 450, ++ /* 720 */ 1203, 136, 406, 64, 64, 479, 64, 64, 419, 369, ++ /* 730 */ 283, 1146, 252, 252, 109, 109, 109, 109, 108, 108, ++ /* 740 */ 107, 107, 107, 106, 401, 512, 224, 440, 411, 266, ++ /* 750 */ 1358, 266, 252, 252, 370, 296, 416, 284, 934, 396, ++ /* 760 */ 976, 470, 400, 252, 252, 512, 9, 473, 231, 500, ++ /* 770 */ 354, 1036, 1035, 1488, 355, 374, 512, 1121, 112, 113, ++ /* 780 */ 103, 1100, 1100, 953, 956, 946, 946, 110, 110, 111, ++ /* 790 */ 111, 111, 111, 252, 252, 1015, 515, 1347, 295, 252, ++ /* 800 */ 252, 252, 252, 1098, 375, 249, 512, 445, 872, 322, ++ /* 810 */ 1016, 480, 512, 195, 512, 434, 273, 15, 15, 515, ++ /* 820 */ 314, 515, 95, 515, 93, 1017, 367, 109, 109, 109, ++ /* 830 */ 109, 108, 108, 107, 107, 107, 106, 401, 515, 1121, ++ /* 840 */ 39, 39, 51, 51, 52, 52, 503, 370, 515, 1204, ++ /* 850 */ 1098, 918, 439, 341, 133, 436, 223, 222, 221, 53, ++ /* 860 */ 53, 322, 1400, 761, 762, 763, 515, 370, 88, 54, ++ /* 870 */ 54, 112, 113, 103, 1100, 1100, 953, 956, 946, 946, ++ /* 880 */ 110, 110, 111, 111, 111, 111, 407, 55, 55, 196, ++ /* 890 */ 515, 112, 113, 103, 1100, 1100, 953, 956, 946, 946, ++ /* 900 */ 110, 110, 111, 111, 111, 111, 135, 264, 1149, 376, ++ /* 910 */ 515, 40, 40, 515, 872, 515, 993, 515, 993, 116, ++ /* 920 */ 109, 109, 109, 109, 108, 108, 107, 107, 107, 106, ++ /* 930 */ 401, 41, 41, 515, 43, 43, 44, 44, 56, 56, ++ /* 940 */ 109, 109, 109, 109, 108, 108, 107, 107, 107, 106, ++ /* 950 */ 401, 515, 379, 515, 57, 57, 515, 799, 515, 379, ++ /* 960 */ 515, 445, 200, 515, 323, 515, 1397, 515, 1459, 515, ++ /* 970 */ 1287, 817, 58, 58, 14, 14, 515, 59, 59, 118, ++ /* 980 */ 118, 60, 60, 515, 46, 46, 61, 61, 62, 62, ++ /* 990 */ 47, 47, 515, 190, 189, 91, 515, 140, 140, 515, ++ /* 1000 */ 394, 515, 277, 1200, 141, 141, 515, 1115, 515, 992, ++ /* 1010 */ 515, 992, 515, 69, 69, 370, 278, 48, 48, 259, ++ /* 1020 */ 65, 65, 119, 119, 246, 246, 260, 66, 66, 120, ++ /* 1030 */ 120, 121, 121, 117, 117, 370, 515, 512, 383, 112, ++ /* 1040 */ 113, 103, 1100, 1100, 953, 956, 946, 946, 110, 110, ++ /* 1050 */ 111, 111, 111, 111, 515, 872, 515, 139, 139, 112, ++ /* 1060 */ 113, 103, 1100, 1100, 953, 956, 946, 946, 110, 110, ++ /* 1070 */ 111, 111, 111, 111, 1287, 138, 138, 125, 125, 515, ++ /* 1080 */ 12, 515, 281, 1287, 515, 445, 131, 1287, 109, 109, ++ /* 1090 */ 109, 109, 108, 108, 107, 107, 107, 106, 401, 515, ++ /* 1100 */ 124, 124, 122, 122, 515, 123, 123, 515, 109, 109, ++ /* 1110 */ 109, 109, 108, 108, 107, 107, 107, 106, 401, 515, ++ /* 1120 */ 68, 68, 463, 783, 515, 70, 70, 302, 67, 67, ++ /* 1130 */ 1032, 253, 253, 356, 1287, 191, 196, 1433, 465, 1301, ++ /* 1140 */ 38, 38, 384, 94, 512, 42, 42, 177, 848, 274, ++ /* 1150 */ 506, 385, 420, 847, 1356, 441, 508, 376, 377, 153, ++ /* 1160 */ 423, 872, 432, 370, 224, 251, 194, 887, 182, 293, ++ /* 1170 */ 783, 848, 88, 254, 466, 888, 847, 915, 807, 806, ++ /* 1180 */ 230, 1241, 910, 370, 17, 413, 797, 112, 113, 103, ++ /* 1190 */ 1100, 1100, 953, 956, 946, 946, 110, 110, 111, 111, ++ /* 1200 */ 111, 111, 395, 814, 815, 1175, 983, 112, 101, 103, ++ /* 1210 */ 1100, 1100, 953, 956, 946, 946, 110, 110, 111, 111, ++ /* 1220 */ 111, 111, 375, 422, 427, 429, 298, 230, 230, 88, ++ /* 1230 */ 1240, 451, 312, 797, 226, 88, 109, 109, 109, 109, ++ /* 1240 */ 108, 108, 107, 107, 107, 106, 401, 86, 433, 979, ++ /* 1250 */ 927, 881, 226, 983, 230, 415, 109, 109, 109, 109, ++ /* 1260 */ 108, 108, 107, 107, 107, 106, 401, 320, 845, 781, ++ /* 1270 */ 846, 100, 130, 100, 1403, 290, 370, 319, 1377, 1376, ++ /* 1280 */ 437, 1449, 299, 1237, 303, 306, 308, 310, 1188, 1174, ++ /* 1290 */ 1173, 1172, 315, 324, 325, 1228, 370, 927, 1249, 271, ++ /* 1300 */ 1286, 113, 103, 1100, 1100, 953, 956, 946, 946, 110, ++ /* 1310 */ 110, 111, 111, 111, 111, 1224, 1235, 502, 501, 1292, ++ /* 1320 */ 1221, 1155, 103, 1100, 1100, 953, 956, 946, 946, 110, ++ /* 1330 */ 110, 111, 111, 111, 111, 1148, 1137, 1136, 1138, 1443, ++ /* 1340 */ 446, 244, 184, 98, 507, 188, 4, 353, 327, 109, ++ /* 1350 */ 109, 109, 109, 108, 108, 107, 107, 107, 106, 401, ++ /* 1360 */ 510, 329, 331, 199, 414, 456, 292, 285, 318, 109, ++ /* 1370 */ 109, 109, 109, 108, 108, 107, 107, 107, 106, 401, ++ /* 1380 */ 11, 1271, 1279, 402, 361, 192, 1171, 1351, 431, 505, ++ /* 1390 */ 346, 1350, 333, 98, 507, 504, 4, 187, 1446, 1115, ++ /* 1400 */ 233, 1396, 155, 1394, 1112, 152, 72, 75, 378, 425, ++ /* 1410 */ 510, 165, 149, 157, 933, 1276, 86, 30, 1268, 417, ++ /* 1420 */ 96, 96, 8, 160, 161, 162, 163, 97, 418, 402, ++ /* 1430 */ 517, 516, 449, 402, 923, 210, 358, 424, 1282, 438, ++ /* 1440 */ 169, 214, 360, 1345, 80, 504, 31, 444, 1365, 301, ++ /* 1450 */ 245, 274, 506, 216, 174, 305, 488, 447, 217, 462, ++ /* 1460 */ 1139, 487, 218, 363, 933, 923, 923, 925, 926, 24, ++ /* 1470 */ 96, 96, 1191, 1190, 1189, 391, 1182, 97, 1163, 402, ++ /* 1480 */ 517, 516, 799, 364, 923, 1162, 317, 1161, 98, 507, ++ /* 1490 */ 1181, 4, 1458, 472, 393, 269, 270, 475, 481, 1232, ++ /* 1500 */ 85, 1233, 326, 328, 232, 510, 495, 1231, 330, 98, ++ /* 1510 */ 507, 1230, 4, 486, 335, 923, 923, 925, 926, 24, ++ /* 1520 */ 1435, 1068, 404, 181, 336, 256, 510, 115, 402, 332, ++ /* 1530 */ 352, 352, 351, 241, 349, 1214, 1414, 770, 338, 10, ++ /* 1540 */ 504, 340, 272, 92, 1331, 1213, 87, 183, 484, 402, ++ /* 1550 */ 201, 488, 280, 239, 344, 345, 489, 1145, 29, 933, ++ /* 1560 */ 279, 504, 1074, 518, 240, 96, 96, 242, 243, 519, ++ /* 1570 */ 1134, 1129, 97, 154, 402, 517, 516, 372, 373, 923, ++ /* 1580 */ 933, 142, 143, 128, 1381, 267, 96, 96, 852, 757, ++ /* 1590 */ 203, 144, 403, 97, 1382, 402, 517, 516, 204, 1380, ++ /* 1600 */ 923, 146, 1379, 1159, 1158, 71, 1156, 276, 202, 185, ++ /* 1610 */ 923, 923, 925, 926, 24, 198, 257, 126, 991, 989, ++ /* 1620 */ 907, 98, 507, 156, 4, 145, 158, 206, 831, 209, ++ /* 1630 */ 291, 923, 923, 925, 926, 24, 1005, 911, 510, 164, ++ /* 1640 */ 147, 380, 371, 382, 166, 76, 77, 274, 506, 148, ++ /* 1650 */ 78, 79, 1008, 211, 212, 1004, 137, 213, 18, 300, ++ /* 1660 */ 230, 402, 997, 1109, 443, 215, 32, 170, 171, 772, ++ /* 1670 */ 409, 448, 319, 504, 219, 172, 452, 81, 19, 457, ++ /* 1680 */ 313, 20, 82, 268, 488, 150, 810, 179, 83, 487, ++ /* 1690 */ 464, 151, 933, 180, 959, 84, 1040, 34, 96, 96, ++ /* 1700 */ 471, 1041, 35, 474, 193, 97, 248, 402, 517, 516, ++ /* 1710 */ 1068, 404, 923, 250, 256, 880, 229, 175, 875, 352, ++ /* 1720 */ 352, 351, 241, 349, 100, 21, 770, 22, 1054, 1056, ++ /* 1730 */ 7, 98, 507, 1045, 4, 337, 1058, 23, 974, 201, ++ /* 1740 */ 176, 280, 88, 923, 923, 925, 926, 24, 510, 279, ++ /* 1750 */ 960, 958, 962, 1014, 963, 1013, 235, 234, 25, 36, ++ /* 1760 */ 99, 90, 507, 928, 4, 511, 350, 782, 26, 841, ++ /* 1770 */ 236, 402, 347, 1069, 237, 1125, 1125, 1451, 510, 203, ++ /* 1780 */ 1450, 1125, 1125, 504, 1125, 1125, 1125, 204, 1125, 1125, ++ /* 1790 */ 146, 1125, 1125, 1125, 1125, 1125, 1125, 202, 1125, 1125, ++ /* 1800 */ 1125, 402, 933, 1125, 1125, 1125, 1125, 1125, 96, 96, ++ /* 1810 */ 1125, 1125, 1125, 504, 1125, 97, 1125, 402, 517, 516, ++ /* 1820 */ 1125, 1125, 923, 1125, 1125, 1125, 1125, 1125, 1125, 1125, ++ /* 1830 */ 1125, 371, 933, 1125, 1125, 1125, 274, 506, 96, 96, ++ /* 1840 */ 1125, 1125, 1125, 1125, 1125, 97, 1125, 402, 517, 516, ++ /* 1850 */ 1125, 1125, 923, 923, 923, 925, 926, 24, 1125, 409, ++ /* 1860 */ 1125, 1125, 1125, 256, 1125, 1125, 1125, 1125, 352, 352, ++ /* 1870 */ 351, 241, 349, 1125, 1125, 770, 1125, 1125, 1125, 1125, ++ /* 1880 */ 1125, 1125, 1125, 923, 923, 925, 926, 24, 201, 1125, ++ /* 1890 */ 280, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 279, 1125, ++ /* 1900 */ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, ++ /* 1910 */ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, ++ /* 1920 */ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 203, 1125, ++ /* 1930 */ 1125, 1125, 1125, 1125, 1125, 1125, 204, 1125, 1125, 146, ++ /* 1940 */ 1125, 1125, 1125, 1125, 1125, 1125, 202, 1125, 1125, 1125, ++ /* 1950 */ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, ++ /* 1960 */ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, ++ /* 1970 */ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, ++ /* 1980 */ 371, 1125, 1125, 1125, 1125, 274, 506, 1125, 1125, 1125, ++ /* 1990 */ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, ++ /* 2000 */ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 409, + }; + static const YYCODETYPE yy_lookahead[] = { +- /* 0 */ 152, 144, 145, 146, 147, 152, 152, 172, 152, 180, +- /* 10 */ 181, 152, 223, 224, 225, 180, 152, 164, 189, 19, +- /* 20 */ 223, 224, 225, 168, 169, 170, 163, 173, 174, 173, +- /* 30 */ 174, 31, 173, 174, 168, 169, 170, 173, 174, 39, +- /* 40 */ 243, 191, 192, 43, 44, 45, 46, 47, 48, 49, +- /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 195, 196, +- /* 60 */ 22, 23, 208, 209, 208, 209, 218, 208, 209, 176, +- /* 70 */ 207, 19, 208, 209, 23, 212, 213, 26, 26, 152, +- /* 80 */ 46, 47, 48, 49, 84, 85, 86, 87, 88, 89, +- /* 90 */ 90, 91, 92, 93, 94, 43, 44, 45, 46, 47, +- /* 100 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, +- /* 110 */ 90, 91, 92, 93, 94, 188, 223, 224, 225, 171, +- /* 120 */ 68, 83, 152, 19, 84, 85, 86, 87, 88, 89, +- /* 130 */ 90, 91, 92, 93, 94, 101, 84, 85, 86, 87, +- /* 140 */ 88, 89, 90, 91, 92, 93, 94, 43, 44, 45, +- /* 150 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, +- /* 160 */ 56, 57, 99, 94, 194, 102, 103, 104, 109, 110, +- /* 170 */ 66, 223, 224, 225, 152, 19, 113, 22, 23, 152, +- /* 180 */ 24, 26, 160, 1, 2, 59, 164, 173, 84, 85, +- /* 190 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 43, +- /* 200 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, +- /* 210 */ 54, 55, 56, 57, 244, 88, 89, 90, 91, 92, +- /* 220 */ 93, 94, 96, 97, 98, 99, 196, 19, 102, 103, +- /* 230 */ 104, 23, 88, 89, 173, 59, 163, 207, 83, 113, +- /* 240 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, +- /* 250 */ 94, 43, 44, 45, 46, 47, 48, 49, 50, 51, +- /* 260 */ 52, 53, 54, 55, 56, 57, 90, 240, 195, 196, +- /* 270 */ 171, 82, 96, 97, 98, 152, 132, 176, 134, 19, +- /* 280 */ 207, 200, 72, 23, 93, 94, 97, 152, 173, 79, +- /* 290 */ 101, 210, 84, 85, 86, 87, 88, 89, 90, 91, +- /* 300 */ 92, 93, 94, 43, 44, 45, 46, 47, 48, 49, +- /* 310 */ 50, 51, 52, 53, 54, 55, 56, 57, 108, 152, +- /* 320 */ 152, 132, 133, 134, 223, 224, 225, 152, 186, 119, +- /* 330 */ 120, 19, 197, 234, 31, 23, 26, 152, 239, 59, +- /* 340 */ 173, 174, 39, 220, 84, 85, 86, 87, 88, 89, +- /* 350 */ 90, 91, 92, 93, 94, 43, 44, 45, 46, 47, +- /* 360 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, +- /* 370 */ 152, 22, 152, 16, 152, 208, 96, 97, 98, 194, +- /* 380 */ 22, 23, 11, 19, 26, 79, 72, 23, 0, 1, +- /* 390 */ 2, 173, 174, 173, 174, 220, 84, 85, 86, 87, +- /* 400 */ 88, 89, 90, 91, 92, 93, 94, 43, 44, 45, +- /* 410 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, +- /* 420 */ 56, 57, 108, 109, 110, 119, 120, 152, 208, 119, +- /* 430 */ 120, 137, 75, 139, 77, 19, 152, 88, 89, 23, +- /* 440 */ 115, 83, 117, 118, 163, 227, 163, 152, 84, 85, +- /* 450 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 43, +- /* 460 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, +- /* 470 */ 54, 55, 56, 57, 195, 196, 195, 196, 195, 196, +- /* 480 */ 109, 110, 195, 196, 22, 23, 207, 19, 207, 152, +- /* 490 */ 207, 108, 109, 110, 207, 163, 22, 140, 24, 59, +- /* 500 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, +- /* 510 */ 94, 43, 44, 45, 46, 47, 48, 49, 50, 51, +- /* 520 */ 52, 53, 54, 55, 56, 57, 152, 195, 196, 152, +- /* 530 */ 16, 7, 8, 9, 197, 240, 96, 97, 98, 207, +- /* 540 */ 249, 250, 19, 152, 22, 83, 26, 173, 174, 152, +- /* 550 */ 173, 174, 84, 85, 86, 87, 88, 89, 90, 91, +- /* 560 */ 92, 93, 94, 59, 124, 152, 43, 44, 45, 46, +- /* 570 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, +- /* 580 */ 57, 59, 169, 170, 157, 194, 82, 191, 192, 75, +- /* 590 */ 152, 77, 108, 109, 110, 26, 152, 19, 152, 152, +- /* 600 */ 96, 97, 24, 152, 152, 101, 138, 84, 85, 86, +- /* 610 */ 87, 88, 89, 90, 91, 92, 93, 94, 96, 97, +- /* 620 */ 98, 43, 44, 45, 46, 47, 48, 49, 50, 51, +- /* 630 */ 52, 53, 54, 55, 56, 57, 132, 133, 134, 188, +- /* 640 */ 194, 197, 152, 123, 197, 232, 194, 152, 182, 19, +- /* 650 */ 119, 120, 152, 152, 152, 152, 218, 230, 152, 163, +- /* 660 */ 233, 138, 84, 85, 86, 87, 88, 89, 90, 91, +- /* 670 */ 92, 93, 94, 43, 44, 45, 46, 47, 48, 49, +- /* 680 */ 50, 51, 52, 53, 54, 55, 56, 57, 152, 152, +- /* 690 */ 23, 195, 196, 26, 194, 194, 194, 146, 147, 130, +- /* 700 */ 194, 19, 46, 207, 59, 29, 166, 167, 218, 33, +- /* 710 */ 173, 174, 26, 218, 84, 85, 86, 87, 88, 89, +- /* 720 */ 90, 91, 92, 93, 94, 43, 44, 45, 46, 47, +- /* 730 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, +- /* 740 */ 64, 171, 97, 240, 116, 166, 167, 212, 213, 121, +- /* 750 */ 23, 152, 19, 26, 218, 247, 248, 23, 23, 152, +- /* 760 */ 26, 26, 22, 107, 163, 98, 84, 85, 86, 87, +- /* 770 */ 88, 89, 90, 91, 92, 93, 94, 44, 45, 46, +- /* 780 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, +- /* 790 */ 57, 124, 106, 53, 100, 101, 195, 196, 152, 152, +- /* 800 */ 23, 23, 19, 26, 26, 19, 152, 23, 207, 239, +- /* 810 */ 26, 23, 152, 163, 26, 169, 170, 84, 85, 86, +- /* 820 */ 87, 88, 89, 90, 91, 92, 93, 94, 45, 46, +- /* 830 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, +- /* 840 */ 57, 19, 20, 101, 22, 195, 196, 22, 19, 24, +- /* 850 */ 163, 19, 7, 8, 112, 59, 23, 207, 36, 26, +- /* 860 */ 23, 152, 59, 26, 21, 59, 152, 84, 85, 86, +- /* 870 */ 87, 88, 89, 90, 91, 92, 93, 94, 232, 221, +- /* 880 */ 94, 59, 195, 196, 59, 99, 100, 101, 102, 103, +- /* 890 */ 104, 105, 70, 97, 207, 59, 19, 20, 112, 22, +- /* 900 */ 97, 79, 152, 97, 82, 152, 152, 71, 221, 90, +- /* 910 */ 88, 89, 23, 36, 12, 26, 163, 95, 96, 97, +- /* 920 */ 98, 78, 97, 101, 152, 96, 173, 174, 96, 27, +- /* 930 */ 182, 22, 96, 97, 98, 116, 59, 148, 149, 152, +- /* 940 */ 121, 119, 120, 154, 42, 156, 103, 70, 195, 196, +- /* 950 */ 22, 59, 163, 152, 132, 133, 134, 135, 136, 82, +- /* 960 */ 207, 208, 209, 71, 62, 88, 89, 90, 59, 152, +- /* 970 */ 152, 12, 95, 96, 97, 98, 19, 20, 101, 22, +- /* 980 */ 22, 182, 152, 140, 195, 196, 27, 59, 96, 97, +- /* 990 */ 98, 59, 132, 36, 134, 22, 207, 19, 20, 24, +- /* 1000 */ 22, 42, 152, 173, 174, 96, 97, 98, 219, 132, +- /* 1010 */ 133, 134, 135, 136, 36, 152, 59, 187, 132, 152, +- /* 1020 */ 134, 62, 152, 152, 96, 97, 98, 70, 96, 97, +- /* 1030 */ 98, 72, 59, 152, 59, 246, 26, 59, 214, 82, +- /* 1040 */ 152, 192, 152, 173, 174, 88, 89, 79, 70, 152, +- /* 1050 */ 152, 19, 95, 96, 97, 98, 124, 187, 101, 23, +- /* 1060 */ 82, 164, 26, 173, 174, 152, 88, 89, 100, 96, +- /* 1070 */ 97, 98, 97, 95, 96, 97, 98, 187, 46, 101, +- /* 1080 */ 122, 184, 152, 186, 211, 152, 152, 119, 120, 132, +- /* 1090 */ 133, 134, 135, 136, 152, 5, 22, 152, 152, 35, +- /* 1100 */ 10, 11, 12, 13, 14, 152, 152, 17, 98, 235, +- /* 1110 */ 132, 133, 134, 135, 136, 54, 55, 56, 57, 58, +- /* 1120 */ 30, 152, 32, 152, 152, 198, 173, 174, 152, 65, +- /* 1130 */ 40, 152, 152, 59, 124, 152, 236, 73, 199, 107, +- /* 1140 */ 187, 171, 173, 174, 112, 84, 85, 86, 87, 88, +- /* 1150 */ 89, 90, 91, 92, 93, 94, 173, 174, 152, 69, +- /* 1160 */ 152, 211, 54, 55, 56, 57, 76, 152, 150, 79, +- /* 1170 */ 80, 97, 211, 211, 211, 111, 59, 241, 241, 173, +- /* 1180 */ 174, 173, 174, 202, 202, 185, 177, 176, 173, 174, +- /* 1190 */ 176, 201, 84, 85, 86, 87, 88, 89, 90, 91, +- /* 1200 */ 92, 93, 94, 215, 114, 88, 89, 152, 215, 119, +- /* 1210 */ 120, 152, 181, 96, 97, 98, 176, 100, 215, 152, +- /* 1220 */ 229, 152, 163, 152, 107, 199, 109, 155, 173, 174, +- /* 1230 */ 245, 141, 173, 174, 60, 159, 152, 122, 159, 242, +- /* 1240 */ 173, 174, 173, 174, 173, 174, 38, 242, 152, 132, +- /* 1250 */ 159, 134, 152, 22, 195, 196, 152, 173, 174, 222, +- /* 1260 */ 43, 130, 202, 152, 18, 152, 207, 208, 152, 173, +- /* 1270 */ 174, 152, 190, 173, 174, 152, 193, 173, 174, 152, +- /* 1280 */ 193, 193, 152, 159, 173, 174, 173, 174, 152, 173, +- /* 1290 */ 174, 193, 173, 174, 18, 152, 173, 174, 152, 158, +- /* 1300 */ 173, 174, 152, 173, 174, 152, 159, 152, 202, 173, +- /* 1310 */ 174, 152, 190, 152, 222, 152, 173, 174, 152, 173, +- /* 1320 */ 174, 137, 152, 173, 174, 190, 173, 174, 173, 174, +- /* 1330 */ 202, 158, 173, 174, 173, 174, 173, 174, 61, 173, +- /* 1340 */ 174, 152, 237, 173, 174, 152, 159, 152, 238, 152, +- /* 1350 */ 158, 152, 22, 152, 178, 152, 158, 152, 158, 152, +- /* 1360 */ 178, 159, 173, 174, 152, 159, 173, 174, 173, 174, +- /* 1370 */ 173, 174, 173, 174, 173, 174, 173, 174, 173, 174, +- /* 1380 */ 173, 174, 152, 63, 152, 173, 174, 107, 175, 175, +- /* 1390 */ 175, 106, 183, 175, 178, 175, 177, 175, 175, 178, +- /* 1400 */ 94, 107, 231, 173, 174, 173, 174, 183, 231, 125, +- /* 1410 */ 216, 178, 159, 217, 22, 159, 226, 129, 137, 228, +- /* 1420 */ 128, 217, 126, 25, 127, 162, 216, 26, 217, 161, +- /* 1430 */ 13, 153, 153, 206, 205, 6, 251, 202, 204, 203, +- /* 1440 */ 151, 216, 151, 217, 216, 171, 151, 165, 179, 179, +- /* 1450 */ 4, 3, 22, 142, 171, 165, 15, 171, 171, 81, +- /* 1460 */ 16, 23, 23, 120, 171, 131, 165, 111, 123, 171, +- /* 1470 */ 171, 171, 20, 125, 16, 1, 123, 131, 53, 53, +- /* 1480 */ 53, 53, 111, 96, 34, 122, 248, 1, 251, 5, +- /* 1490 */ 22, 107, 140, 26, 74, 41, 122, 107, 67, 67, +- /* 1500 */ 24, 20, 19, 112, 105, 23, 66, 22, 66, 22, +- /* 1510 */ 22, 22, 37, 22, 22, 66, 23, 23, 28, 23, +- /* 1520 */ 23, 26, 24, 23, 22, 24, 122, 23, 23, 96, +- /* 1530 */ 22, 124, 26, 34, 23, 26, 23, 34, 23, 23, +- /* 1540 */ 23, 34, 23, 22, 26, 11, 22, 22, 26, 23, +- /* 1550 */ 23, 22, 116, 23, 22, 15, 122, 122, 23, 122, +- /* 1560 */ 1, 252, 252, 252, 252, 122, 252, 252, 252, 252, +- /* 1570 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, +- /* 1580 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, +- /* 1590 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, +- /* 1600 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, +- /* 1610 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, +- /* 1620 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, +- /* 1630 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, +- /* 1640 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, +- /* 1650 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, +- /* 1660 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, +- /* 1670 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, +- /* 1680 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, +- /* 1690 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, +- /* 1700 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, ++ /* 0 */ 184, 238, 239, 240, 238, 239, 240, 163, 155, 156, ++ /* 10 */ 157, 158, 159, 160, 163, 191, 192, 183, 165, 19, ++ /* 20 */ 167, 258, 202, 203, 200, 191, 163, 174, 184, 185, ++ /* 30 */ 174, 31, 163, 163, 171, 184, 185, 35, 175, 39, ++ /* 40 */ 179, 180, 181, 43, 44, 45, 46, 47, 48, 49, ++ /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 184, 206, ++ /* 60 */ 207, 163, 206, 207, 220, 163, 16, 163, 66, 163, ++ /* 70 */ 59, 270, 219, 229, 273, 219, 74, 208, 174, 223, ++ /* 80 */ 224, 163, 184, 185, 163, 232, 184, 185, 184, 185, ++ /* 90 */ 184, 185, 92, 93, 94, 95, 96, 97, 98, 99, ++ /* 100 */ 100, 101, 102, 233, 198, 184, 185, 96, 97, 163, ++ /* 110 */ 206, 207, 19, 163, 261, 104, 105, 106, 107, 198, ++ /* 120 */ 109, 119, 220, 219, 220, 274, 275, 77, 117, 79, ++ /* 130 */ 187, 229, 19, 229, 184, 185, 43, 44, 45, 46, ++ /* 140 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, ++ /* 150 */ 57, 233, 141, 134, 143, 102, 43, 44, 45, 46, ++ /* 160 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, ++ /* 170 */ 57, 152, 274, 216, 276, 218, 83, 163, 85, 233, ++ /* 180 */ 67, 238, 239, 240, 11, 92, 93, 94, 95, 96, ++ /* 190 */ 97, 98, 99, 100, 101, 102, 19, 54, 55, 56, ++ /* 200 */ 57, 58, 163, 26, 163, 92, 93, 94, 95, 96, ++ /* 210 */ 97, 98, 99, 100, 101, 102, 54, 55, 56, 57, ++ /* 220 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, ++ /* 230 */ 53, 54, 55, 56, 57, 92, 93, 94, 95, 96, ++ /* 240 */ 97, 98, 99, 100, 101, 102, 69, 96, 97, 98, ++ /* 250 */ 99, 100, 101, 102, 92, 93, 94, 95, 96, 97, ++ /* 260 */ 98, 99, 100, 101, 102, 81, 179, 180, 181, 92, ++ /* 270 */ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, ++ /* 280 */ 163, 267, 268, 163, 22, 23, 59, 163, 26, 19, ++ /* 290 */ 117, 118, 175, 109, 24, 59, 92, 93, 94, 95, ++ /* 300 */ 96, 97, 98, 99, 100, 101, 102, 268, 184, 185, ++ /* 310 */ 269, 127, 128, 43, 44, 45, 46, 47, 48, 49, ++ /* 320 */ 50, 51, 52, 53, 54, 55, 56, 57, 157, 158, ++ /* 330 */ 159, 160, 105, 106, 107, 163, 165, 59, 167, 184, ++ /* 340 */ 90, 105, 106, 107, 108, 174, 73, 111, 112, 113, ++ /* 350 */ 19, 22, 163, 91, 81, 163, 106, 121, 81, 132, ++ /* 360 */ 110, 16, 92, 93, 94, 95, 96, 97, 98, 99, ++ /* 370 */ 100, 101, 102, 184, 185, 255, 98, 206, 207, 26, ++ /* 380 */ 101, 102, 19, 105, 106, 107, 23, 198, 59, 116, ++ /* 390 */ 219, 141, 142, 143, 24, 163, 187, 205, 274, 275, ++ /* 400 */ 127, 128, 182, 232, 127, 128, 43, 44, 45, 46, ++ /* 410 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, ++ /* 420 */ 57, 158, 77, 160, 79, 59, 26, 182, 165, 59, ++ /* 430 */ 167, 199, 261, 102, 105, 106, 107, 174, 72, 108, ++ /* 440 */ 109, 110, 111, 112, 113, 114, 59, 238, 239, 240, ++ /* 450 */ 123, 120, 125, 126, 163, 92, 93, 94, 95, 96, ++ /* 460 */ 97, 98, 99, 100, 101, 102, 163, 163, 163, 206, ++ /* 470 */ 207, 105, 106, 107, 254, 19, 106, 90, 197, 23, ++ /* 480 */ 127, 128, 219, 238, 239, 240, 22, 184, 185, 184, ++ /* 490 */ 185, 22, 105, 106, 149, 232, 205, 110, 163, 43, ++ /* 500 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, ++ /* 510 */ 54, 55, 56, 57, 98, 99, 100, 101, 102, 184, ++ /* 520 */ 185, 163, 53, 59, 261, 220, 117, 118, 141, 142, ++ /* 530 */ 143, 131, 174, 59, 229, 116, 117, 118, 163, 59, ++ /* 540 */ 163, 163, 184, 185, 59, 242, 72, 22, 92, 93, ++ /* 550 */ 94, 95, 96, 97, 98, 99, 100, 101, 102, 184, ++ /* 560 */ 185, 24, 184, 185, 206, 207, 202, 203, 19, 105, ++ /* 570 */ 106, 107, 23, 198, 22, 174, 198, 219, 220, 105, ++ /* 580 */ 106, 107, 96, 97, 59, 105, 106, 107, 22, 174, ++ /* 590 */ 59, 106, 43, 44, 45, 46, 47, 48, 49, 50, ++ /* 600 */ 51, 52, 53, 54, 55, 56, 57, 206, 207, 12, ++ /* 610 */ 108, 59, 132, 111, 112, 113, 46, 47, 48, 49, ++ /* 620 */ 219, 206, 207, 121, 27, 59, 163, 141, 207, 143, ++ /* 630 */ 105, 106, 107, 163, 219, 234, 105, 106, 107, 42, ++ /* 640 */ 219, 92, 93, 94, 95, 96, 97, 98, 99, 100, ++ /* 650 */ 101, 102, 76, 163, 184, 185, 163, 105, 106, 107, ++ /* 660 */ 63, 19, 86, 163, 163, 23, 163, 130, 205, 21, ++ /* 670 */ 73, 105, 106, 107, 184, 185, 163, 184, 185, 237, ++ /* 680 */ 110, 180, 181, 180, 181, 43, 44, 45, 46, 47, ++ /* 690 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, ++ /* 700 */ 174, 163, 163, 22, 23, 163, 163, 26, 22, 23, ++ /* 710 */ 220, 29, 73, 220, 272, 33, 22, 163, 24, 19, ++ /* 720 */ 174, 208, 259, 184, 185, 19, 184, 185, 80, 175, ++ /* 730 */ 230, 174, 206, 207, 92, 93, 94, 95, 96, 97, ++ /* 740 */ 98, 99, 100, 101, 102, 219, 46, 65, 247, 195, ++ /* 750 */ 247, 197, 206, 207, 19, 116, 117, 118, 23, 220, ++ /* 760 */ 112, 174, 220, 206, 207, 219, 22, 174, 24, 174, ++ /* 770 */ 22, 23, 91, 264, 265, 168, 219, 91, 43, 44, ++ /* 780 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, ++ /* 790 */ 55, 56, 57, 206, 207, 12, 163, 149, 255, 206, ++ /* 800 */ 207, 206, 207, 59, 104, 23, 219, 163, 26, 163, ++ /* 810 */ 27, 105, 219, 163, 219, 163, 211, 184, 185, 163, ++ /* 820 */ 120, 163, 146, 163, 148, 42, 221, 92, 93, 94, ++ /* 830 */ 95, 96, 97, 98, 99, 100, 101, 102, 163, 91, ++ /* 840 */ 184, 185, 184, 185, 184, 185, 63, 19, 163, 205, ++ /* 850 */ 106, 23, 245, 163, 208, 248, 116, 117, 118, 184, ++ /* 860 */ 185, 163, 163, 7, 8, 9, 163, 19, 26, 184, ++ /* 870 */ 185, 43, 44, 45, 46, 47, 48, 49, 50, 51, ++ /* 880 */ 52, 53, 54, 55, 56, 57, 163, 184, 185, 107, ++ /* 890 */ 163, 43, 44, 45, 46, 47, 48, 49, 50, 51, ++ /* 900 */ 52, 53, 54, 55, 56, 57, 208, 255, 177, 178, ++ /* 910 */ 163, 184, 185, 163, 132, 163, 141, 163, 143, 22, ++ /* 920 */ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, ++ /* 930 */ 102, 184, 185, 163, 184, 185, 184, 185, 184, 185, ++ /* 940 */ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, ++ /* 950 */ 102, 163, 163, 163, 184, 185, 163, 115, 163, 163, ++ /* 960 */ 163, 163, 15, 163, 163, 163, 163, 163, 23, 163, ++ /* 970 */ 163, 26, 184, 185, 184, 185, 163, 184, 185, 184, ++ /* 980 */ 185, 184, 185, 163, 184, 185, 184, 185, 184, 185, ++ /* 990 */ 184, 185, 163, 96, 97, 147, 163, 184, 185, 163, ++ /* 1000 */ 199, 163, 163, 205, 184, 185, 163, 60, 163, 141, ++ /* 1010 */ 163, 143, 163, 184, 185, 19, 163, 184, 185, 230, ++ /* 1020 */ 184, 185, 184, 185, 206, 207, 230, 184, 185, 184, ++ /* 1030 */ 185, 184, 185, 184, 185, 19, 163, 219, 231, 43, ++ /* 1040 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, ++ /* 1050 */ 54, 55, 56, 57, 163, 26, 163, 184, 185, 43, ++ /* 1060 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, ++ /* 1070 */ 54, 55, 56, 57, 163, 184, 185, 184, 185, 163, ++ /* 1080 */ 182, 163, 163, 163, 163, 163, 22, 163, 92, 93, ++ /* 1090 */ 94, 95, 96, 97, 98, 99, 100, 101, 102, 163, ++ /* 1100 */ 184, 185, 184, 185, 163, 184, 185, 163, 92, 93, ++ /* 1110 */ 94, 95, 96, 97, 98, 99, 100, 101, 102, 163, ++ /* 1120 */ 184, 185, 98, 59, 163, 184, 185, 205, 184, 185, ++ /* 1130 */ 23, 206, 207, 26, 163, 26, 107, 153, 154, 237, ++ /* 1140 */ 184, 185, 231, 147, 219, 184, 185, 249, 124, 127, ++ /* 1150 */ 128, 231, 254, 129, 163, 231, 177, 178, 262, 263, ++ /* 1160 */ 118, 132, 19, 19, 46, 223, 224, 31, 24, 23, ++ /* 1170 */ 106, 124, 26, 22, 272, 39, 129, 23, 109, 110, ++ /* 1180 */ 26, 163, 140, 19, 22, 234, 59, 43, 44, 45, ++ /* 1190 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, ++ /* 1200 */ 56, 57, 231, 7, 8, 193, 59, 43, 44, 45, ++ /* 1210 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, ++ /* 1220 */ 56, 57, 104, 61, 23, 23, 23, 26, 26, 26, ++ /* 1230 */ 163, 23, 23, 106, 26, 26, 92, 93, 94, 95, ++ /* 1240 */ 96, 97, 98, 99, 100, 101, 102, 138, 105, 23, ++ /* 1250 */ 59, 23, 26, 106, 26, 163, 92, 93, 94, 95, ++ /* 1260 */ 96, 97, 98, 99, 100, 101, 102, 110, 23, 23, ++ /* 1270 */ 23, 26, 26, 26, 163, 163, 19, 120, 163, 163, ++ /* 1280 */ 163, 130, 163, 163, 163, 163, 163, 163, 163, 193, ++ /* 1290 */ 193, 163, 163, 163, 163, 225, 19, 106, 163, 222, ++ /* 1300 */ 163, 44, 45, 46, 47, 48, 49, 50, 51, 52, ++ /* 1310 */ 53, 54, 55, 56, 57, 163, 163, 203, 163, 163, ++ /* 1320 */ 222, 163, 45, 46, 47, 48, 49, 50, 51, 52, ++ /* 1330 */ 53, 54, 55, 56, 57, 163, 163, 163, 163, 163, ++ /* 1340 */ 251, 250, 209, 19, 20, 182, 22, 161, 222, 92, ++ /* 1350 */ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, ++ /* 1360 */ 36, 222, 222, 260, 226, 188, 256, 226, 187, 92, ++ /* 1370 */ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, ++ /* 1380 */ 210, 213, 213, 59, 213, 196, 192, 187, 256, 244, ++ /* 1390 */ 212, 187, 226, 19, 20, 71, 22, 210, 166, 60, ++ /* 1400 */ 130, 170, 260, 170, 38, 81, 257, 257, 170, 104, ++ /* 1410 */ 36, 22, 43, 201, 90, 236, 138, 235, 213, 18, ++ /* 1420 */ 96, 97, 48, 204, 204, 204, 204, 103, 170, 105, ++ /* 1430 */ 106, 107, 18, 59, 110, 169, 213, 213, 201, 170, ++ /* 1440 */ 201, 169, 236, 213, 146, 71, 235, 62, 253, 252, ++ /* 1450 */ 170, 127, 128, 169, 22, 170, 82, 189, 169, 104, ++ /* 1460 */ 170, 87, 169, 189, 90, 141, 142, 143, 144, 145, ++ /* 1470 */ 96, 97, 186, 186, 186, 64, 194, 103, 186, 105, ++ /* 1480 */ 106, 107, 115, 189, 110, 188, 186, 186, 19, 20, ++ /* 1490 */ 194, 22, 186, 189, 102, 246, 246, 189, 133, 228, ++ /* 1500 */ 104, 228, 227, 227, 170, 36, 134, 228, 227, 19, ++ /* 1510 */ 20, 228, 22, 84, 271, 141, 142, 143, 144, 145, ++ /* 1520 */ 0, 1, 2, 216, 22, 5, 36, 137, 59, 227, ++ /* 1530 */ 10, 11, 12, 13, 14, 217, 269, 17, 216, 22, ++ /* 1540 */ 71, 170, 243, 146, 241, 217, 136, 215, 135, 59, ++ /* 1550 */ 30, 82, 32, 25, 214, 213, 87, 173, 26, 90, ++ /* 1560 */ 40, 71, 13, 172, 164, 96, 97, 164, 6, 162, ++ /* 1570 */ 162, 162, 103, 263, 105, 106, 107, 266, 266, 110, ++ /* 1580 */ 90, 176, 176, 190, 182, 190, 96, 97, 98, 4, ++ /* 1590 */ 70, 176, 3, 103, 182, 105, 106, 107, 78, 182, ++ /* 1600 */ 110, 81, 182, 182, 182, 182, 182, 151, 88, 22, ++ /* 1610 */ 141, 142, 143, 144, 145, 15, 89, 16, 23, 23, ++ /* 1620 */ 128, 19, 20, 139, 22, 119, 131, 24, 20, 133, ++ /* 1630 */ 16, 141, 142, 143, 144, 145, 1, 140, 36, 131, ++ /* 1640 */ 119, 61, 122, 37, 139, 53, 53, 127, 128, 119, ++ /* 1650 */ 53, 53, 105, 34, 130, 1, 5, 104, 22, 149, ++ /* 1660 */ 26, 59, 68, 75, 41, 130, 24, 68, 104, 20, ++ /* 1670 */ 150, 19, 120, 71, 114, 22, 67, 22, 22, 67, ++ /* 1680 */ 23, 22, 22, 67, 82, 37, 28, 23, 138, 87, ++ /* 1690 */ 22, 153, 90, 23, 23, 26, 23, 22, 96, 97, ++ /* 1700 */ 24, 23, 22, 24, 130, 103, 23, 105, 106, 107, ++ /* 1710 */ 1, 2, 110, 23, 5, 105, 34, 22, 132, 10, ++ /* 1720 */ 11, 12, 13, 14, 26, 34, 17, 34, 85, 83, ++ /* 1730 */ 44, 19, 20, 23, 22, 24, 75, 34, 23, 30, ++ /* 1740 */ 26, 32, 26, 141, 142, 143, 144, 145, 36, 40, ++ /* 1750 */ 23, 23, 23, 23, 11, 23, 22, 26, 22, 22, ++ /* 1760 */ 22, 19, 20, 23, 22, 26, 15, 23, 22, 124, ++ /* 1770 */ 130, 59, 23, 1, 130, 277, 277, 130, 36, 70, ++ /* 1780 */ 130, 277, 277, 71, 277, 277, 277, 78, 277, 277, ++ /* 1790 */ 81, 277, 277, 277, 277, 277, 277, 88, 277, 277, ++ /* 1800 */ 277, 59, 90, 277, 277, 277, 277, 277, 96, 97, ++ /* 1810 */ 277, 277, 277, 71, 277, 103, 277, 105, 106, 107, ++ /* 1820 */ 277, 277, 110, 277, 277, 277, 277, 277, 277, 277, ++ /* 1830 */ 277, 122, 90, 277, 277, 277, 127, 128, 96, 97, ++ /* 1840 */ 277, 277, 277, 277, 277, 103, 277, 105, 106, 107, ++ /* 1850 */ 277, 277, 110, 141, 142, 143, 144, 145, 277, 150, ++ /* 1860 */ 277, 277, 277, 5, 277, 277, 277, 277, 10, 11, ++ /* 1870 */ 12, 13, 14, 277, 277, 17, 277, 277, 277, 277, ++ /* 1880 */ 277, 277, 277, 141, 142, 143, 144, 145, 30, 277, ++ /* 1890 */ 32, 277, 277, 277, 277, 277, 277, 277, 40, 277, ++ /* 1900 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, ++ /* 1910 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, ++ /* 1920 */ 277, 277, 277, 277, 277, 277, 277, 277, 70, 277, ++ /* 1930 */ 277, 277, 277, 277, 277, 277, 78, 277, 277, 81, ++ /* 1940 */ 277, 277, 277, 277, 277, 277, 88, 277, 277, 277, ++ /* 1950 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, ++ /* 1960 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, ++ /* 1970 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, ++ /* 1980 */ 122, 277, 277, 277, 277, 127, 128, 277, 277, 277, ++ /* 1990 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, ++ /* 2000 */ 277, 277, 277, 277, 277, 277, 277, 277, 150, 277, ++ /* 2010 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, + }; +-#define YY_SHIFT_COUNT (471) ++#define YY_SHIFT_COUNT (520) + #define YY_SHIFT_MIN (0) +-#define YY_SHIFT_MAX (1559) ++#define YY_SHIFT_MAX (1858) + static const unsigned short int yy_shift_ofst[] = { +- /* 0 */ 182, 1090, 822, 822, 306, 957, 957, 957, 957, 210, +- /* 10 */ 0, 0, 104, 630, 957, 957, 957, 957, 957, 957, +- /* 20 */ 957, 1117, 1117, 126, 968, 306, 306, 306, 306, 306, +- /* 30 */ 306, 52, 156, 208, 260, 312, 364, 416, 468, 523, +- /* 40 */ 578, 630, 630, 630, 630, 630, 630, 630, 630, 630, +- /* 50 */ 630, 630, 630, 630, 630, 630, 630, 630, 682, 630, +- /* 60 */ 733, 783, 783, 877, 957, 957, 957, 957, 957, 957, +- /* 70 */ 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, +- /* 80 */ 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, +- /* 90 */ 957, 957, 957, 957, 957, 978, 957, 957, 957, 957, +- /* 100 */ 957, 957, 957, 957, 957, 957, 957, 957, 957, 1061, +- /* 110 */ 1108, 1108, 1108, 1108, 1108, 40, 127, 20, 280, 843, +- /* 120 */ 1032, 144, 144, 280, 310, 310, 310, 310, 59, 191, +- /* 130 */ 69, 1566, 1566, 1566, 786, 786, 786, 522, 836, 522, +- /* 140 */ 959, 959, 892, 155, 358, 280, 280, 280, 280, 280, +- /* 150 */ 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, +- /* 160 */ 280, 280, 280, 280, 280, 280, 371, 388, 645, 645, +- /* 170 */ 531, 1566, 1566, 1566, 504, 189, 189, 909, 63, 176, +- /* 180 */ 928, 440, 932, 973, 280, 280, 280, 280, 280, 314, +- /* 190 */ 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, +- /* 200 */ 280, 280, 1064, 1064, 1064, 280, 280, 280, 280, 667, +- /* 210 */ 280, 280, 280, 825, 280, 280, 902, 280, 280, 280, +- /* 220 */ 280, 280, 280, 280, 280, 383, 676, 325, 975, 975, +- /* 230 */ 975, 975, 1010, 325, 325, 819, 349, 524, 569, 829, +- /* 240 */ 829, 832, 569, 832, 686, 51, 656, 303, 303, 303, +- /* 250 */ 829, 294, 520, 628, 474, 1174, 1115, 1115, 1208, 1208, +- /* 260 */ 1115, 1231, 1217, 1131, 1246, 1246, 1246, 1246, 1115, 1276, +- /* 270 */ 1131, 1231, 1217, 1217, 1131, 1115, 1276, 1184, 1277, 1115, +- /* 280 */ 1276, 1330, 1115, 1276, 1115, 1276, 1330, 1280, 1280, 1280, +- /* 290 */ 1320, 1330, 1280, 1285, 1280, 1320, 1280, 1280, 1330, 1306, +- /* 300 */ 1306, 1330, 1284, 1294, 1284, 1294, 1284, 1294, 1284, 1294, +- /* 310 */ 1115, 1392, 1115, 1281, 1288, 1296, 1292, 1297, 1131, 1398, +- /* 320 */ 1401, 1417, 1417, 1429, 1429, 1429, 1566, 1566, 1566, 1566, +- /* 330 */ 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, +- /* 340 */ 1566, 1566, 34, 357, 38, 462, 514, 484, 1074, 727, +- /* 350 */ 740, 734, 735, 777, 778, 784, 788, 803, 694, 845, +- /* 360 */ 742, 796, 833, 837, 889, 860, 886, 1036, 806, 958, +- /* 370 */ 1446, 1448, 1430, 1311, 1441, 1378, 1444, 1438, 1439, 1343, +- /* 380 */ 1334, 1356, 1345, 1452, 1348, 1458, 1474, 1353, 1346, 1425, +- /* 390 */ 1426, 1427, 1428, 1371, 1387, 1450, 1363, 1486, 1484, 1468, +- /* 400 */ 1384, 1352, 1431, 1467, 1432, 1420, 1454, 1374, 1390, 1476, +- /* 410 */ 1481, 1483, 1391, 1399, 1485, 1440, 1487, 1488, 1482, 1489, +- /* 420 */ 1442, 1490, 1491, 1449, 1475, 1493, 1494, 1496, 1495, 1497, +- /* 430 */ 1492, 1498, 1500, 1502, 1501, 1404, 1504, 1505, 1433, 1499, +- /* 440 */ 1508, 1407, 1506, 1503, 1509, 1507, 1511, 1513, 1515, 1506, +- /* 450 */ 1516, 1517, 1518, 1519, 1521, 1534, 1524, 1525, 1526, 1527, +- /* 460 */ 1529, 1530, 1532, 1522, 1436, 1434, 1435, 1437, 1443, 1535, +- /* 470 */ 1540, 1559, ++ /* 0 */ 1709, 1520, 1858, 1324, 1324, 277, 1374, 1469, 1602, 1712, ++ /* 10 */ 1712, 1712, 273, 0, 0, 113, 1016, 1712, 1712, 1712, ++ /* 20 */ 1712, 1712, 1712, 1712, 1712, 1712, 1712, 11, 11, 236, ++ /* 30 */ 184, 277, 277, 277, 277, 277, 277, 93, 177, 270, ++ /* 40 */ 363, 456, 549, 642, 735, 828, 848, 996, 1144, 1016, ++ /* 50 */ 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, ++ /* 60 */ 1016, 1016, 1016, 1016, 1016, 1016, 1164, 1016, 1257, 1277, ++ /* 70 */ 1277, 1490, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, ++ /* 80 */ 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, ++ /* 90 */ 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, ++ /* 100 */ 1712, 1712, 1712, 1742, 1712, 1712, 1712, 1712, 1712, 1712, ++ /* 110 */ 1712, 1712, 1712, 1712, 1712, 1712, 1712, 143, 162, 162, ++ /* 120 */ 162, 162, 162, 204, 151, 416, 531, 648, 700, 531, ++ /* 130 */ 486, 486, 531, 353, 353, 353, 353, 409, 279, 53, ++ /* 140 */ 2009, 2009, 331, 331, 331, 329, 366, 329, 329, 597, ++ /* 150 */ 597, 464, 474, 262, 681, 531, 531, 531, 531, 531, ++ /* 160 */ 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, ++ /* 170 */ 531, 531, 531, 531, 531, 531, 531, 173, 485, 984, ++ /* 180 */ 984, 576, 485, 19, 1022, 2009, 2009, 2009, 387, 250, ++ /* 190 */ 250, 525, 502, 278, 552, 227, 480, 566, 531, 531, ++ /* 200 */ 531, 531, 531, 531, 531, 531, 531, 531, 639, 531, ++ /* 210 */ 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, ++ /* 220 */ 531, 2, 2, 2, 531, 531, 531, 531, 782, 531, ++ /* 230 */ 531, 531, 744, 531, 531, 783, 531, 531, 531, 531, ++ /* 240 */ 531, 531, 531, 531, 419, 682, 327, 370, 370, 370, ++ /* 250 */ 370, 1029, 327, 327, 1024, 897, 856, 947, 1109, 706, ++ /* 260 */ 706, 1143, 1109, 1109, 1143, 842, 945, 1118, 1136, 1136, ++ /* 270 */ 1136, 706, 676, 400, 1047, 694, 1339, 1270, 1270, 1366, ++ /* 280 */ 1366, 1270, 1305, 1389, 1369, 1278, 1401, 1401, 1401, 1401, ++ /* 290 */ 1270, 1414, 1278, 1278, 1305, 1389, 1369, 1369, 1278, 1270, ++ /* 300 */ 1414, 1298, 1385, 1270, 1414, 1432, 1270, 1414, 1270, 1414, ++ /* 310 */ 1432, 1355, 1355, 1355, 1411, 1432, 1355, 1367, 1355, 1411, ++ /* 320 */ 1355, 1355, 1432, 1392, 1392, 1432, 1365, 1396, 1365, 1396, ++ /* 330 */ 1365, 1396, 1365, 1396, 1270, 1372, 1429, 1502, 1390, 1372, ++ /* 340 */ 1517, 1270, 1397, 1390, 1410, 1413, 1278, 1528, 1532, 1549, ++ /* 350 */ 1549, 1562, 1562, 1562, 2009, 2009, 2009, 2009, 2009, 2009, ++ /* 360 */ 2009, 2009, 2009, 2009, 2009, 2009, 2009, 2009, 2009, 2009, ++ /* 370 */ 570, 345, 686, 748, 50, 740, 1064, 1107, 469, 537, ++ /* 380 */ 1042, 1146, 1162, 1154, 1201, 1202, 1203, 1208, 1209, 1127, ++ /* 390 */ 1069, 1196, 1157, 1147, 1226, 1228, 1245, 775, 868, 1246, ++ /* 400 */ 1247, 1191, 1151, 1585, 1589, 1587, 1456, 1600, 1527, 1601, ++ /* 410 */ 1595, 1596, 1492, 1484, 1506, 1603, 1495, 1608, 1496, 1614, ++ /* 420 */ 1635, 1508, 1497, 1521, 1580, 1606, 1505, 1592, 1593, 1597, ++ /* 430 */ 1598, 1530, 1547, 1619, 1524, 1654, 1651, 1636, 1553, 1510, ++ /* 440 */ 1594, 1634, 1599, 1588, 1623, 1535, 1564, 1642, 1649, 1652, ++ /* 450 */ 1552, 1560, 1653, 1609, 1655, 1656, 1657, 1659, 1612, 1658, ++ /* 460 */ 1660, 1616, 1648, 1664, 1550, 1668, 1538, 1670, 1671, 1669, ++ /* 470 */ 1673, 1675, 1676, 1678, 1680, 1679, 1574, 1683, 1690, 1610, ++ /* 480 */ 1682, 1695, 1586, 1698, 1691, 1698, 1693, 1643, 1661, 1646, ++ /* 490 */ 1686, 1710, 1711, 1714, 1716, 1703, 1715, 1698, 1727, 1728, ++ /* 500 */ 1729, 1730, 1731, 1732, 1734, 1743, 1736, 1737, 1740, 1744, ++ /* 510 */ 1738, 1746, 1739, 1645, 1640, 1644, 1647, 1650, 1749, 1751, ++ /* 520 */ 1772, + }; +-#define YY_REDUCE_COUNT (341) +-#define YY_REDUCE_MIN (-211) +-#define YY_REDUCE_MAX (1301) ++#define YY_REDUCE_COUNT (369) ++#define YY_REDUCE_MIN (-237) ++#define YY_REDUCE_MAX (1424) + static const short yy_reduce_ofst[] = { +- /* 0 */ -143, 789, 753, 1059, -137, -146, -144, -141, -136, 687, +- /* 10 */ -107, 101, -203, -52, 830, 870, 890, 167, 953, 218, +- /* 20 */ 220, 413, 646, 897, 73, 281, 283, 332, 496, 601, +- /* 30 */ 650, -211, -211, -211, -211, -211, -211, -211, -211, -211, +- /* 40 */ -211, -211, -211, -211, -211, -211, -211, -211, -211, -211, +- /* 50 */ -211, -211, -211, -211, -211, -211, -211, -211, -211, -211, +- /* 60 */ -211, -211, -211, 374, 377, 537, 969, 983, 1006, 1008, +- /* 70 */ 1015, 1055, 1067, 1069, 1071, 1084, 1096, 1100, 1104, 1111, +- /* 80 */ 1113, 1116, 1119, 1123, 1127, 1130, 1136, 1143, 1146, 1150, +- /* 90 */ 1153, 1155, 1159, 1161, 1163, 1166, 1170, 1189, 1193, 1195, +- /* 100 */ 1197, 1199, 1201, 1203, 1205, 1207, 1212, 1230, 1232, -211, +- /* 110 */ -211, -211, -211, -211, -211, -211, -211, -211, -30, 427, +- /* 120 */ -171, -145, -134, 22, 279, 287, 279, 287, 99, -211, +- /* 130 */ -211, -211, -211, -211, -165, -165, -165, 123, 135, 175, +- /* 140 */ -150, 396, 337, 291, 291, -147, 185, 391, 446, 444, +- /* 150 */ 452, 500, 501, 502, 27, -152, 295, 438, 490, 503, +- /* 160 */ 495, 506, -73, 447, 451, 536, 570, 551, 540, 579, +- /* 170 */ 30, 508, 535, 81, 14, 61, 115, 168, 142, 222, +- /* 180 */ 275, 284, 397, 599, 607, 647, 654, 660, 709, 658, +- /* 190 */ 714, 750, 754, 772, 787, 801, 817, 818, 850, 863, +- /* 200 */ 867, 871, 466, 748, 799, 881, 888, 898, 913, 824, +- /* 210 */ 930, 933, 934, 873, 942, 945, 849, 946, 222, 954, +- /* 220 */ 971, 972, 976, 979, 980, 900, 874, 927, 950, 961, +- /* 230 */ 962, 963, 824, 927, 927, 939, 970, 1018, 981, 988, +- /* 240 */ 993, 936, 982, 937, 1009, 1000, 1031, 1011, 1014, 1040, +- /* 250 */ 1003, 991, 990, 1026, 1072, 985, 1076, 1079, 997, 1005, +- /* 260 */ 1091, 1037, 1082, 1060, 1083, 1087, 1088, 1098, 1124, 1141, +- /* 270 */ 1106, 1092, 1122, 1135, 1128, 1147, 1173, 1110, 1105, 1187, +- /* 280 */ 1192, 1176, 1202, 1198, 1206, 1200, 1182, 1213, 1214, 1215, +- /* 290 */ 1209, 1216, 1218, 1219, 1220, 1224, 1222, 1223, 1221, 1171, +- /* 300 */ 1177, 1233, 1196, 1194, 1204, 1210, 1211, 1225, 1226, 1228, +- /* 310 */ 1253, 1190, 1256, 1191, 1227, 1229, 1234, 1236, 1235, 1263, +- /* 320 */ 1268, 1278, 1279, 1289, 1291, 1295, 1185, 1237, 1238, 1282, +- /* 330 */ 1274, 1283, 1286, 1287, 1290, 1269, 1270, 1293, 1298, 1299, +- /* 340 */ 1300, 1301, ++ /* 0 */ -147, 171, 263, -96, 358, -144, -149, -102, 124, -156, ++ /* 10 */ -98, 305, 401, -57, 209, -237, 245, -94, -79, 189, ++ /* 20 */ 375, 490, 493, 378, 303, 539, 542, 501, 503, 554, ++ /* 30 */ 415, 526, 546, 557, 587, 593, 595, -234, -234, -234, ++ /* 40 */ -234, -234, -234, -234, -234, -234, -234, -234, -234, -234, ++ /* 50 */ -234, -234, -234, -234, -234, -234, -234, -234, -234, -234, ++ /* 60 */ -234, -234, -234, -234, -234, -234, -234, -234, -234, -234, ++ /* 70 */ -234, -50, 335, 470, 633, 656, 658, 660, 675, 685, ++ /* 80 */ 703, 727, 747, 750, 752, 754, 770, 788, 790, 793, ++ /* 90 */ 795, 797, 800, 802, 804, 806, 813, 820, 829, 833, ++ /* 100 */ 836, 838, 843, 845, 847, 849, 873, 891, 893, 916, ++ /* 110 */ 918, 921, 936, 941, 944, 956, 961, -234, -234, -234, ++ /* 120 */ -234, -234, -234, -234, -234, -234, 463, 607, -176, 14, ++ /* 130 */ -139, 87, -137, 818, 925, 818, 925, 898, -234, -234, ++ /* 140 */ -234, -234, -166, -166, -166, -130, -131, -82, -54, -180, ++ /* 150 */ 364, 41, 513, 509, 509, 117, 500, 789, 796, 646, ++ /* 160 */ 192, 291, 644, 798, 120, 807, 543, 911, 920, 652, ++ /* 170 */ 924, 922, 232, 698, 801, 971, 39, 220, 731, 442, ++ /* 180 */ 902, -199, 979, -43, 421, 896, 942, 605, -184, -126, ++ /* 190 */ 155, 172, 281, 304, 377, 538, 650, 690, 699, 723, ++ /* 200 */ 803, 839, 853, 919, 991, 1018, 1067, 1092, 951, 1111, ++ /* 210 */ 1112, 1115, 1116, 1117, 1119, 1120, 1121, 1122, 1123, 1124, ++ /* 220 */ 1125, 1012, 1096, 1097, 1128, 1129, 1130, 1131, 1070, 1135, ++ /* 230 */ 1137, 1152, 1077, 1153, 1155, 1114, 1156, 304, 1158, 1172, ++ /* 240 */ 1173, 1174, 1175, 1176, 1089, 1091, 1133, 1098, 1126, 1139, ++ /* 250 */ 1140, 1070, 1133, 1133, 1170, 1163, 1186, 1103, 1168, 1138, ++ /* 260 */ 1141, 1110, 1169, 1171, 1132, 1177, 1189, 1194, 1181, 1200, ++ /* 270 */ 1204, 1166, 1145, 1178, 1187, 1232, 1142, 1231, 1233, 1149, ++ /* 280 */ 1150, 1238, 1179, 1182, 1212, 1205, 1219, 1220, 1221, 1222, ++ /* 290 */ 1258, 1266, 1223, 1224, 1206, 1211, 1237, 1239, 1230, 1269, ++ /* 300 */ 1272, 1195, 1197, 1280, 1284, 1268, 1285, 1289, 1290, 1293, ++ /* 310 */ 1274, 1286, 1287, 1288, 1282, 1294, 1292, 1297, 1300, 1296, ++ /* 320 */ 1301, 1306, 1304, 1249, 1250, 1308, 1271, 1275, 1273, 1276, ++ /* 330 */ 1279, 1281, 1283, 1302, 1334, 1307, 1243, 1267, 1318, 1322, ++ /* 340 */ 1303, 1371, 1299, 1328, 1332, 1340, 1342, 1384, 1391, 1400, ++ /* 350 */ 1403, 1407, 1408, 1409, 1311, 1312, 1310, 1405, 1402, 1412, ++ /* 360 */ 1417, 1420, 1406, 1393, 1395, 1421, 1422, 1423, 1424, 1415, + }; + static const YYACTIONTYPE yy_default[] = { +- /* 0 */ 1297, 1349, 1221, 1014, 1119, 1221, 1221, 1221, 1221, 1014, +- /* 10 */ 1145, 1145, 1272, 1045, 1014, 1014, 1014, 1014, 1014, 1220, +- /* 20 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, +- /* 30 */ 1014, 1151, 1014, 1014, 1014, 1014, 1222, 1223, 1014, 1014, +- /* 40 */ 1014, 1271, 1273, 1161, 1160, 1159, 1158, 1254, 1132, 1156, +- /* 50 */ 1149, 1153, 1216, 1217, 1215, 1219, 1222, 1223, 1014, 1152, +- /* 60 */ 1186, 1200, 1185, 1014, 1014, 1014, 1014, 1014, 1014, 1014, +- /* 70 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, +- /* 80 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, +- /* 90 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, +- /* 100 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1194, +- /* 110 */ 1199, 1206, 1198, 1195, 1188, 1187, 1189, 1190, 1014, 1035, +- /* 120 */ 1084, 1014, 1014, 1014, 1289, 1288, 1014, 1014, 1045, 1191, +- /* 130 */ 1192, 1203, 1202, 1201, 1279, 1305, 1304, 1014, 1014, 1014, +- /* 140 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, +- /* 150 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, +- /* 160 */ 1014, 1014, 1014, 1014, 1014, 1014, 1045, 1297, 1041, 1041, +- /* 170 */ 1014, 1284, 1119, 1110, 1014, 1014, 1014, 1014, 1014, 1014, +- /* 180 */ 1014, 1014, 1014, 1014, 1014, 1276, 1274, 1014, 1236, 1014, +- /* 190 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, +- /* 200 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, +- /* 210 */ 1014, 1014, 1014, 1115, 1014, 1014, 1014, 1014, 1014, 1014, +- /* 220 */ 1014, 1014, 1014, 1014, 1299, 1014, 1249, 1098, 1115, 1115, +- /* 230 */ 1115, 1115, 1117, 1099, 1097, 1109, 1045, 1021, 1155, 1134, +- /* 240 */ 1134, 1338, 1155, 1338, 1059, 1319, 1056, 1145, 1145, 1145, +- /* 250 */ 1134, 1218, 1116, 1109, 1014, 1341, 1124, 1124, 1340, 1340, +- /* 260 */ 1124, 1166, 1087, 1155, 1093, 1093, 1093, 1093, 1124, 1032, +- /* 270 */ 1155, 1166, 1087, 1087, 1155, 1124, 1032, 1253, 1335, 1124, +- /* 280 */ 1032, 1229, 1124, 1032, 1124, 1032, 1229, 1085, 1085, 1085, +- /* 290 */ 1074, 1229, 1085, 1059, 1085, 1074, 1085, 1085, 1229, 1233, +- /* 300 */ 1233, 1229, 1138, 1133, 1138, 1133, 1138, 1133, 1138, 1133, +- /* 310 */ 1124, 1224, 1124, 1014, 1150, 1139, 1148, 1146, 1155, 1038, +- /* 320 */ 1077, 1302, 1302, 1298, 1298, 1298, 1346, 1346, 1284, 1314, +- /* 330 */ 1045, 1045, 1045, 1045, 1314, 1061, 1061, 1045, 1045, 1045, +- /* 340 */ 1045, 1314, 1014, 1014, 1014, 1014, 1014, 1014, 1309, 1014, +- /* 350 */ 1238, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, +- /* 360 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1171, +- /* 370 */ 1014, 1017, 1281, 1014, 1014, 1280, 1014, 1014, 1014, 1014, +- /* 380 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, +- /* 390 */ 1014, 1014, 1014, 1014, 1014, 1014, 1337, 1014, 1014, 1014, +- /* 400 */ 1014, 1014, 1014, 1252, 1251, 1014, 1014, 1126, 1014, 1014, +- /* 410 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, +- /* 420 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, +- /* 430 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, +- /* 440 */ 1014, 1014, 1147, 1014, 1140, 1014, 1014, 1014, 1014, 1328, +- /* 450 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, +- /* 460 */ 1014, 1014, 1014, 1323, 1101, 1173, 1014, 1172, 1176, 1014, +- /* 470 */ 1026, 1014, ++ /* 0 */ 1492, 1492, 1492, 1340, 1123, 1229, 1123, 1123, 1123, 1340, ++ /* 10 */ 1340, 1340, 1123, 1259, 1259, 1391, 1154, 1123, 1123, 1123, ++ /* 20 */ 1123, 1123, 1123, 1123, 1339, 1123, 1123, 1123, 1123, 1123, ++ /* 30 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1265, 1123, ++ /* 40 */ 1123, 1123, 1123, 1123, 1341, 1342, 1123, 1123, 1123, 1390, ++ /* 50 */ 1392, 1275, 1274, 1273, 1272, 1373, 1246, 1270, 1263, 1267, ++ /* 60 */ 1335, 1336, 1334, 1338, 1342, 1341, 1123, 1266, 1306, 1320, ++ /* 70 */ 1305, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 80 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 90 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 100 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 110 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1314, 1319, 1325, ++ /* 120 */ 1318, 1315, 1308, 1307, 1309, 1310, 1123, 1144, 1193, 1123, ++ /* 130 */ 1123, 1123, 1123, 1409, 1408, 1123, 1123, 1154, 1311, 1312, ++ /* 140 */ 1322, 1321, 1398, 1448, 1447, 1123, 1123, 1123, 1123, 1123, ++ /* 150 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 160 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 170 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1154, 1150, 1300, ++ /* 180 */ 1299, 1418, 1150, 1253, 1123, 1404, 1229, 1220, 1123, 1123, ++ /* 190 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 200 */ 1123, 1395, 1393, 1123, 1355, 1123, 1123, 1123, 1123, 1123, ++ /* 210 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 220 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 230 */ 1123, 1123, 1225, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 240 */ 1123, 1123, 1123, 1442, 1123, 1368, 1207, 1225, 1225, 1225, ++ /* 250 */ 1225, 1227, 1208, 1206, 1219, 1154, 1130, 1484, 1269, 1248, ++ /* 260 */ 1248, 1481, 1269, 1269, 1481, 1168, 1462, 1165, 1259, 1259, ++ /* 270 */ 1259, 1248, 1337, 1226, 1219, 1123, 1484, 1234, 1234, 1483, ++ /* 280 */ 1483, 1234, 1278, 1284, 1196, 1269, 1202, 1202, 1202, 1202, ++ /* 290 */ 1234, 1141, 1269, 1269, 1278, 1284, 1196, 1196, 1269, 1234, ++ /* 300 */ 1141, 1372, 1478, 1234, 1141, 1348, 1234, 1141, 1234, 1141, ++ /* 310 */ 1348, 1194, 1194, 1194, 1183, 1348, 1194, 1168, 1194, 1183, ++ /* 320 */ 1194, 1194, 1348, 1352, 1352, 1348, 1252, 1247, 1252, 1247, ++ /* 330 */ 1252, 1247, 1252, 1247, 1234, 1253, 1417, 1123, 1264, 1253, ++ /* 340 */ 1343, 1234, 1123, 1264, 1262, 1260, 1269, 1147, 1186, 1445, ++ /* 350 */ 1445, 1441, 1441, 1441, 1489, 1489, 1404, 1457, 1154, 1154, ++ /* 360 */ 1154, 1154, 1457, 1170, 1170, 1154, 1154, 1154, 1154, 1457, ++ /* 370 */ 1123, 1123, 1123, 1123, 1123, 1123, 1452, 1123, 1357, 1238, ++ /* 380 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 390 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 400 */ 1123, 1123, 1289, 1123, 1126, 1401, 1123, 1123, 1399, 1123, ++ /* 410 */ 1123, 1123, 1123, 1123, 1123, 1239, 1123, 1123, 1123, 1123, ++ /* 420 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 430 */ 1123, 1123, 1123, 1123, 1480, 1123, 1123, 1123, 1123, 1123, ++ /* 440 */ 1123, 1371, 1370, 1123, 1123, 1236, 1123, 1123, 1123, 1123, ++ /* 450 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 460 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 470 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 480 */ 1123, 1123, 1123, 1261, 1123, 1416, 1123, 1123, 1123, 1123, ++ /* 490 */ 1123, 1123, 1123, 1430, 1254, 1123, 1123, 1471, 1123, 1123, ++ /* 500 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, ++ /* 510 */ 1123, 1123, 1466, 1210, 1291, 1123, 1290, 1294, 1123, 1135, ++ /* 520 */ 1123, + }; + /********** End of lemon-generated parsing tables *****************************/ + +@@ -140664,6 +147804,7 @@ + 0, /* ESCAPE => nothing */ + 0, /* ID => nothing */ + 59, /* COLUMNKW => ID */ ++ 59, /* DO => ID */ + 59, /* FOR => ID */ + 59, /* IGNORE => ID */ + 59, /* INITIALLY => ID */ +@@ -140678,11 +147819,18 @@ + 59, /* REPLACE => ID */ + 59, /* RESTRICT => ID */ + 59, /* ROW => ID */ ++ 59, /* ROWS => ID */ + 59, /* TRIGGER => ID */ + 59, /* VACUUM => ID */ + 59, /* VIEW => ID */ + 59, /* VIRTUAL => ID */ + 59, /* WITH => ID */ ++ 59, /* CURRENT => ID */ ++ 59, /* FOLLOWING => ID */ ++ 59, /* PARTITION => ID */ ++ 59, /* PRECEDING => ID */ ++ 59, /* RANGE => ID */ ++ 59, /* UNBOUNDED => ID */ + 59, /* REINDEX => ID */ + 59, /* RENAME => ID */ + 59, /* CTIME_KW => ID */ +@@ -140725,6 +147873,7 @@ + int yyerrcnt; /* Shifts left before out of the error */ + #endif + sqlite3ParserARG_SDECL /* A place to hold %extra_argument */ ++ sqlite3ParserCTX_SDECL /* A place to hold %extra_context */ + #if YYSTACKDEPTH<=0 + int yystksz; /* Current side of the stack */ + yyStackEntry *yystack; /* The parser's stack */ +@@ -140833,197 +147982,222 @@ + /* 58 */ "ESCAPE", + /* 59 */ "ID", + /* 60 */ "COLUMNKW", +- /* 61 */ "FOR", +- /* 62 */ "IGNORE", +- /* 63 */ "INITIALLY", +- /* 64 */ "INSTEAD", +- /* 65 */ "NO", +- /* 66 */ "KEY", +- /* 67 */ "OF", +- /* 68 */ "OFFSET", +- /* 69 */ "PRAGMA", +- /* 70 */ "RAISE", +- /* 71 */ "RECURSIVE", +- /* 72 */ "REPLACE", +- /* 73 */ "RESTRICT", +- /* 74 */ "ROW", +- /* 75 */ "TRIGGER", +- /* 76 */ "VACUUM", +- /* 77 */ "VIEW", +- /* 78 */ "VIRTUAL", +- /* 79 */ "WITH", +- /* 80 */ "REINDEX", +- /* 81 */ "RENAME", +- /* 82 */ "CTIME_KW", +- /* 83 */ "ANY", +- /* 84 */ "BITAND", +- /* 85 */ "BITOR", +- /* 86 */ "LSHIFT", +- /* 87 */ "RSHIFT", +- /* 88 */ "PLUS", +- /* 89 */ "MINUS", +- /* 90 */ "STAR", +- /* 91 */ "SLASH", +- /* 92 */ "REM", +- /* 93 */ "CONCAT", +- /* 94 */ "COLLATE", +- /* 95 */ "BITNOT", +- /* 96 */ "INDEXED", +- /* 97 */ "STRING", +- /* 98 */ "JOIN_KW", +- /* 99 */ "CONSTRAINT", +- /* 100 */ "DEFAULT", +- /* 101 */ "NULL", +- /* 102 */ "PRIMARY", +- /* 103 */ "UNIQUE", +- /* 104 */ "CHECK", +- /* 105 */ "REFERENCES", +- /* 106 */ "AUTOINCR", +- /* 107 */ "ON", +- /* 108 */ "INSERT", +- /* 109 */ "DELETE", +- /* 110 */ "UPDATE", +- /* 111 */ "SET", +- /* 112 */ "DEFERRABLE", +- /* 113 */ "FOREIGN", +- /* 114 */ "DROP", +- /* 115 */ "UNION", +- /* 116 */ "ALL", +- /* 117 */ "EXCEPT", +- /* 118 */ "INTERSECT", +- /* 119 */ "SELECT", +- /* 120 */ "VALUES", +- /* 121 */ "DISTINCT", +- /* 122 */ "DOT", +- /* 123 */ "FROM", +- /* 124 */ "JOIN", +- /* 125 */ "USING", +- /* 126 */ "ORDER", +- /* 127 */ "GROUP", +- /* 128 */ "HAVING", +- /* 129 */ "LIMIT", +- /* 130 */ "WHERE", +- /* 131 */ "INTO", +- /* 132 */ "FLOAT", +- /* 133 */ "BLOB", +- /* 134 */ "INTEGER", +- /* 135 */ "VARIABLE", +- /* 136 */ "CASE", +- /* 137 */ "WHEN", +- /* 138 */ "THEN", +- /* 139 */ "ELSE", +- /* 140 */ "INDEX", +- /* 141 */ "ALTER", +- /* 142 */ "ADD", +- /* 143 */ "error", +- /* 144 */ "input", +- /* 145 */ "cmdlist", +- /* 146 */ "ecmd", +- /* 147 */ "explain", +- /* 148 */ "cmdx", +- /* 149 */ "cmd", +- /* 150 */ "transtype", +- /* 151 */ "trans_opt", +- /* 152 */ "nm", +- /* 153 */ "savepoint_opt", +- /* 154 */ "create_table", +- /* 155 */ "create_table_args", +- /* 156 */ "createkw", +- /* 157 */ "temp", +- /* 158 */ "ifnotexists", +- /* 159 */ "dbnm", +- /* 160 */ "columnlist", +- /* 161 */ "conslist_opt", +- /* 162 */ "table_options", +- /* 163 */ "select", +- /* 164 */ "columnname", +- /* 165 */ "carglist", +- /* 166 */ "typetoken", +- /* 167 */ "typename", +- /* 168 */ "signed", +- /* 169 */ "plus_num", +- /* 170 */ "minus_num", +- /* 171 */ "scanpt", +- /* 172 */ "ccons", +- /* 173 */ "term", +- /* 174 */ "expr", +- /* 175 */ "onconf", +- /* 176 */ "sortorder", +- /* 177 */ "autoinc", +- /* 178 */ "eidlist_opt", +- /* 179 */ "refargs", +- /* 180 */ "defer_subclause", +- /* 181 */ "refarg", +- /* 182 */ "refact", +- /* 183 */ "init_deferred_pred_opt", +- /* 184 */ "conslist", +- /* 185 */ "tconscomma", +- /* 186 */ "tcons", +- /* 187 */ "sortlist", +- /* 188 */ "eidlist", +- /* 189 */ "defer_subclause_opt", +- /* 190 */ "orconf", +- /* 191 */ "resolvetype", +- /* 192 */ "raisetype", +- /* 193 */ "ifexists", +- /* 194 */ "fullname", +- /* 195 */ "selectnowith", +- /* 196 */ "oneselect", +- /* 197 */ "wqlist", +- /* 198 */ "multiselect_op", +- /* 199 */ "distinct", +- /* 200 */ "selcollist", +- /* 201 */ "from", +- /* 202 */ "where_opt", +- /* 203 */ "groupby_opt", +- /* 204 */ "having_opt", +- /* 205 */ "orderby_opt", +- /* 206 */ "limit_opt", +- /* 207 */ "values", +- /* 208 */ "nexprlist", +- /* 209 */ "exprlist", +- /* 210 */ "sclp", +- /* 211 */ "as", +- /* 212 */ "seltablist", +- /* 213 */ "stl_prefix", +- /* 214 */ "joinop", +- /* 215 */ "indexed_opt", +- /* 216 */ "on_opt", +- /* 217 */ "using_opt", +- /* 218 */ "idlist", +- /* 219 */ "with", +- /* 220 */ "setlist", +- /* 221 */ "insert_cmd", +- /* 222 */ "idlist_opt", +- /* 223 */ "likeop", +- /* 224 */ "between_op", +- /* 225 */ "in_op", +- /* 226 */ "paren_exprlist", +- /* 227 */ "case_operand", +- /* 228 */ "case_exprlist", +- /* 229 */ "case_else", +- /* 230 */ "uniqueflag", +- /* 231 */ "collate", +- /* 232 */ "nmnum", +- /* 233 */ "trigger_decl", +- /* 234 */ "trigger_cmd_list", +- /* 235 */ "trigger_time", +- /* 236 */ "trigger_event", +- /* 237 */ "foreach_clause", +- /* 238 */ "when_clause", +- /* 239 */ "trigger_cmd", +- /* 240 */ "trnm", +- /* 241 */ "tridxby", +- /* 242 */ "database_kw_opt", +- /* 243 */ "key_opt", +- /* 244 */ "add_column_fullname", +- /* 245 */ "kwcolumn_opt", +- /* 246 */ "create_vtab", +- /* 247 */ "vtabarglist", +- /* 248 */ "vtabarg", +- /* 249 */ "vtabargtoken", +- /* 250 */ "lp", +- /* 251 */ "anylist", ++ /* 61 */ "DO", ++ /* 62 */ "FOR", ++ /* 63 */ "IGNORE", ++ /* 64 */ "INITIALLY", ++ /* 65 */ "INSTEAD", ++ /* 66 */ "NO", ++ /* 67 */ "KEY", ++ /* 68 */ "OF", ++ /* 69 */ "OFFSET", ++ /* 70 */ "PRAGMA", ++ /* 71 */ "RAISE", ++ /* 72 */ "RECURSIVE", ++ /* 73 */ "REPLACE", ++ /* 74 */ "RESTRICT", ++ /* 75 */ "ROW", ++ /* 76 */ "ROWS", ++ /* 77 */ "TRIGGER", ++ /* 78 */ "VACUUM", ++ /* 79 */ "VIEW", ++ /* 80 */ "VIRTUAL", ++ /* 81 */ "WITH", ++ /* 82 */ "CURRENT", ++ /* 83 */ "FOLLOWING", ++ /* 84 */ "PARTITION", ++ /* 85 */ "PRECEDING", ++ /* 86 */ "RANGE", ++ /* 87 */ "UNBOUNDED", ++ /* 88 */ "REINDEX", ++ /* 89 */ "RENAME", ++ /* 90 */ "CTIME_KW", ++ /* 91 */ "ANY", ++ /* 92 */ "BITAND", ++ /* 93 */ "BITOR", ++ /* 94 */ "LSHIFT", ++ /* 95 */ "RSHIFT", ++ /* 96 */ "PLUS", ++ /* 97 */ "MINUS", ++ /* 98 */ "STAR", ++ /* 99 */ "SLASH", ++ /* 100 */ "REM", ++ /* 101 */ "CONCAT", ++ /* 102 */ "COLLATE", ++ /* 103 */ "BITNOT", ++ /* 104 */ "ON", ++ /* 105 */ "INDEXED", ++ /* 106 */ "STRING", ++ /* 107 */ "JOIN_KW", ++ /* 108 */ "CONSTRAINT", ++ /* 109 */ "DEFAULT", ++ /* 110 */ "NULL", ++ /* 111 */ "PRIMARY", ++ /* 112 */ "UNIQUE", ++ /* 113 */ "CHECK", ++ /* 114 */ "REFERENCES", ++ /* 115 */ "AUTOINCR", ++ /* 116 */ "INSERT", ++ /* 117 */ "DELETE", ++ /* 118 */ "UPDATE", ++ /* 119 */ "SET", ++ /* 120 */ "DEFERRABLE", ++ /* 121 */ "FOREIGN", ++ /* 122 */ "DROP", ++ /* 123 */ "UNION", ++ /* 124 */ "ALL", ++ /* 125 */ "EXCEPT", ++ /* 126 */ "INTERSECT", ++ /* 127 */ "SELECT", ++ /* 128 */ "VALUES", ++ /* 129 */ "DISTINCT", ++ /* 130 */ "DOT", ++ /* 131 */ "FROM", ++ /* 132 */ "JOIN", ++ /* 133 */ "USING", ++ /* 134 */ "ORDER", ++ /* 135 */ "GROUP", ++ /* 136 */ "HAVING", ++ /* 137 */ "LIMIT", ++ /* 138 */ "WHERE", ++ /* 139 */ "INTO", ++ /* 140 */ "NOTHING", ++ /* 141 */ "FLOAT", ++ /* 142 */ "BLOB", ++ /* 143 */ "INTEGER", ++ /* 144 */ "VARIABLE", ++ /* 145 */ "CASE", ++ /* 146 */ "WHEN", ++ /* 147 */ "THEN", ++ /* 148 */ "ELSE", ++ /* 149 */ "INDEX", ++ /* 150 */ "ALTER", ++ /* 151 */ "ADD", ++ /* 152 */ "WINDOW", ++ /* 153 */ "OVER", ++ /* 154 */ "FILTER", ++ /* 155 */ "input", ++ /* 156 */ "cmdlist", ++ /* 157 */ "ecmd", ++ /* 158 */ "cmdx", ++ /* 159 */ "explain", ++ /* 160 */ "cmd", ++ /* 161 */ "transtype", ++ /* 162 */ "trans_opt", ++ /* 163 */ "nm", ++ /* 164 */ "savepoint_opt", ++ /* 165 */ "create_table", ++ /* 166 */ "create_table_args", ++ /* 167 */ "createkw", ++ /* 168 */ "temp", ++ /* 169 */ "ifnotexists", ++ /* 170 */ "dbnm", ++ /* 171 */ "columnlist", ++ /* 172 */ "conslist_opt", ++ /* 173 */ "table_options", ++ /* 174 */ "select", ++ /* 175 */ "columnname", ++ /* 176 */ "carglist", ++ /* 177 */ "typetoken", ++ /* 178 */ "typename", ++ /* 179 */ "signed", ++ /* 180 */ "plus_num", ++ /* 181 */ "minus_num", ++ /* 182 */ "scanpt", ++ /* 183 */ "ccons", ++ /* 184 */ "term", ++ /* 185 */ "expr", ++ /* 186 */ "onconf", ++ /* 187 */ "sortorder", ++ /* 188 */ "autoinc", ++ /* 189 */ "eidlist_opt", ++ /* 190 */ "refargs", ++ /* 191 */ "defer_subclause", ++ /* 192 */ "refarg", ++ /* 193 */ "refact", ++ /* 194 */ "init_deferred_pred_opt", ++ /* 195 */ "conslist", ++ /* 196 */ "tconscomma", ++ /* 197 */ "tcons", ++ /* 198 */ "sortlist", ++ /* 199 */ "eidlist", ++ /* 200 */ "defer_subclause_opt", ++ /* 201 */ "orconf", ++ /* 202 */ "resolvetype", ++ /* 203 */ "raisetype", ++ /* 204 */ "ifexists", ++ /* 205 */ "fullname", ++ /* 206 */ "selectnowith", ++ /* 207 */ "oneselect", ++ /* 208 */ "wqlist", ++ /* 209 */ "multiselect_op", ++ /* 210 */ "distinct", ++ /* 211 */ "selcollist", ++ /* 212 */ "from", ++ /* 213 */ "where_opt", ++ /* 214 */ "groupby_opt", ++ /* 215 */ "having_opt", ++ /* 216 */ "orderby_opt", ++ /* 217 */ "limit_opt", ++ /* 218 */ "window_clause", ++ /* 219 */ "values", ++ /* 220 */ "nexprlist", ++ /* 221 */ "sclp", ++ /* 222 */ "as", ++ /* 223 */ "seltablist", ++ /* 224 */ "stl_prefix", ++ /* 225 */ "joinop", ++ /* 226 */ "indexed_opt", ++ /* 227 */ "on_opt", ++ /* 228 */ "using_opt", ++ /* 229 */ "exprlist", ++ /* 230 */ "xfullname", ++ /* 231 */ "idlist", ++ /* 232 */ "with", ++ /* 233 */ "setlist", ++ /* 234 */ "insert_cmd", ++ /* 235 */ "idlist_opt", ++ /* 236 */ "upsert", ++ /* 237 */ "over_clause", ++ /* 238 */ "likeop", ++ /* 239 */ "between_op", ++ /* 240 */ "in_op", ++ /* 241 */ "paren_exprlist", ++ /* 242 */ "case_operand", ++ /* 243 */ "case_exprlist", ++ /* 244 */ "case_else", ++ /* 245 */ "uniqueflag", ++ /* 246 */ "collate", ++ /* 247 */ "nmnum", ++ /* 248 */ "trigger_decl", ++ /* 249 */ "trigger_cmd_list", ++ /* 250 */ "trigger_time", ++ /* 251 */ "trigger_event", ++ /* 252 */ "foreach_clause", ++ /* 253 */ "when_clause", ++ /* 254 */ "trigger_cmd", ++ /* 255 */ "trnm", ++ /* 256 */ "tridxby", ++ /* 257 */ "database_kw_opt", ++ /* 258 */ "key_opt", ++ /* 259 */ "add_column_fullname", ++ /* 260 */ "kwcolumn_opt", ++ /* 261 */ "create_vtab", ++ /* 262 */ "vtabarglist", ++ /* 263 */ "vtabarg", ++ /* 264 */ "vtabargtoken", ++ /* 265 */ "lp", ++ /* 266 */ "anylist", ++ /* 267 */ "windowdefn_list", ++ /* 268 */ "windowdefn", ++ /* 269 */ "window", ++ /* 270 */ "frame_opt", ++ /* 271 */ "part_opt", ++ /* 272 */ "filter_opt", ++ /* 273 */ "range_or_rows", ++ /* 274 */ "frame_bound", ++ /* 275 */ "frame_bound_s", ++ /* 276 */ "frame_bound_e", + }; + #endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */ + +@@ -141119,251 +148293,285 @@ + /* 85 */ "multiselect_op ::= UNION ALL", + /* 86 */ "multiselect_op ::= EXCEPT|INTERSECT", + /* 87 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", +- /* 88 */ "values ::= VALUES LP nexprlist RP", +- /* 89 */ "values ::= values COMMA LP exprlist RP", +- /* 90 */ "distinct ::= DISTINCT", +- /* 91 */ "distinct ::= ALL", +- /* 92 */ "distinct ::=", +- /* 93 */ "sclp ::=", +- /* 94 */ "selcollist ::= sclp scanpt expr scanpt as", +- /* 95 */ "selcollist ::= sclp scanpt STAR", +- /* 96 */ "selcollist ::= sclp scanpt nm DOT STAR", +- /* 97 */ "as ::= AS nm", +- /* 98 */ "as ::=", +- /* 99 */ "from ::=", +- /* 100 */ "from ::= FROM seltablist", +- /* 101 */ "stl_prefix ::= seltablist joinop", +- /* 102 */ "stl_prefix ::=", +- /* 103 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt", +- /* 104 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt", +- /* 105 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt", +- /* 106 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt", +- /* 107 */ "dbnm ::=", +- /* 108 */ "dbnm ::= DOT nm", +- /* 109 */ "fullname ::= nm", +- /* 110 */ "fullname ::= nm DOT nm", +- /* 111 */ "joinop ::= COMMA|JOIN", +- /* 112 */ "joinop ::= JOIN_KW JOIN", +- /* 113 */ "joinop ::= JOIN_KW nm JOIN", +- /* 114 */ "joinop ::= JOIN_KW nm nm JOIN", +- /* 115 */ "on_opt ::= ON expr", +- /* 116 */ "on_opt ::=", +- /* 117 */ "indexed_opt ::=", +- /* 118 */ "indexed_opt ::= INDEXED BY nm", +- /* 119 */ "indexed_opt ::= NOT INDEXED", +- /* 120 */ "using_opt ::= USING LP idlist RP", +- /* 121 */ "using_opt ::=", +- /* 122 */ "orderby_opt ::=", +- /* 123 */ "orderby_opt ::= ORDER BY sortlist", +- /* 124 */ "sortlist ::= sortlist COMMA expr sortorder", +- /* 125 */ "sortlist ::= expr sortorder", +- /* 126 */ "sortorder ::= ASC", +- /* 127 */ "sortorder ::= DESC", +- /* 128 */ "sortorder ::=", +- /* 129 */ "groupby_opt ::=", +- /* 130 */ "groupby_opt ::= GROUP BY nexprlist", +- /* 131 */ "having_opt ::=", +- /* 132 */ "having_opt ::= HAVING expr", +- /* 133 */ "limit_opt ::=", +- /* 134 */ "limit_opt ::= LIMIT expr", +- /* 135 */ "limit_opt ::= LIMIT expr OFFSET expr", +- /* 136 */ "limit_opt ::= LIMIT expr COMMA expr", +- /* 137 */ "cmd ::= with DELETE FROM fullname indexed_opt where_opt", +- /* 138 */ "where_opt ::=", +- /* 139 */ "where_opt ::= WHERE expr", +- /* 140 */ "cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt", +- /* 141 */ "setlist ::= setlist COMMA nm EQ expr", +- /* 142 */ "setlist ::= setlist COMMA LP idlist RP EQ expr", +- /* 143 */ "setlist ::= nm EQ expr", +- /* 144 */ "setlist ::= LP idlist RP EQ expr", +- /* 145 */ "cmd ::= with insert_cmd INTO fullname idlist_opt select", +- /* 146 */ "cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES", +- /* 147 */ "insert_cmd ::= INSERT orconf", +- /* 148 */ "insert_cmd ::= REPLACE", +- /* 149 */ "idlist_opt ::=", +- /* 150 */ "idlist_opt ::= LP idlist RP", +- /* 151 */ "idlist ::= idlist COMMA nm", +- /* 152 */ "idlist ::= nm", +- /* 153 */ "expr ::= LP expr RP", +- /* 154 */ "expr ::= ID|INDEXED", +- /* 155 */ "expr ::= JOIN_KW", +- /* 156 */ "expr ::= nm DOT nm", +- /* 157 */ "expr ::= nm DOT nm DOT nm", +- /* 158 */ "term ::= NULL|FLOAT|BLOB", +- /* 159 */ "term ::= STRING", +- /* 160 */ "term ::= INTEGER", +- /* 161 */ "expr ::= VARIABLE", +- /* 162 */ "expr ::= expr COLLATE ID|STRING", +- /* 163 */ "expr ::= CAST LP expr AS typetoken RP", +- /* 164 */ "expr ::= ID|INDEXED LP distinct exprlist RP", +- /* 165 */ "expr ::= ID|INDEXED LP STAR RP", +- /* 166 */ "term ::= CTIME_KW", +- /* 167 */ "expr ::= LP nexprlist COMMA expr RP", +- /* 168 */ "expr ::= expr AND expr", +- /* 169 */ "expr ::= expr OR expr", +- /* 170 */ "expr ::= expr LT|GT|GE|LE expr", +- /* 171 */ "expr ::= expr EQ|NE expr", +- /* 172 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", +- /* 173 */ "expr ::= expr PLUS|MINUS expr", +- /* 174 */ "expr ::= expr STAR|SLASH|REM expr", +- /* 175 */ "expr ::= expr CONCAT expr", +- /* 176 */ "likeop ::= NOT LIKE_KW|MATCH", +- /* 177 */ "expr ::= expr likeop expr", +- /* 178 */ "expr ::= expr likeop expr ESCAPE expr", +- /* 179 */ "expr ::= expr ISNULL|NOTNULL", +- /* 180 */ "expr ::= expr NOT NULL", +- /* 181 */ "expr ::= expr IS expr", +- /* 182 */ "expr ::= expr IS NOT expr", +- /* 183 */ "expr ::= NOT expr", +- /* 184 */ "expr ::= BITNOT expr", +- /* 185 */ "expr ::= MINUS expr", +- /* 186 */ "expr ::= PLUS expr", +- /* 187 */ "between_op ::= BETWEEN", +- /* 188 */ "between_op ::= NOT BETWEEN", +- /* 189 */ "expr ::= expr between_op expr AND expr", +- /* 190 */ "in_op ::= IN", +- /* 191 */ "in_op ::= NOT IN", +- /* 192 */ "expr ::= expr in_op LP exprlist RP", +- /* 193 */ "expr ::= LP select RP", +- /* 194 */ "expr ::= expr in_op LP select RP", +- /* 195 */ "expr ::= expr in_op nm dbnm paren_exprlist", +- /* 196 */ "expr ::= EXISTS LP select RP", +- /* 197 */ "expr ::= CASE case_operand case_exprlist case_else END", +- /* 198 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", +- /* 199 */ "case_exprlist ::= WHEN expr THEN expr", +- /* 200 */ "case_else ::= ELSE expr", +- /* 201 */ "case_else ::=", +- /* 202 */ "case_operand ::= expr", +- /* 203 */ "case_operand ::=", +- /* 204 */ "exprlist ::=", +- /* 205 */ "nexprlist ::= nexprlist COMMA expr", +- /* 206 */ "nexprlist ::= expr", +- /* 207 */ "paren_exprlist ::=", +- /* 208 */ "paren_exprlist ::= LP exprlist RP", +- /* 209 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", +- /* 210 */ "uniqueflag ::= UNIQUE", +- /* 211 */ "uniqueflag ::=", +- /* 212 */ "eidlist_opt ::=", +- /* 213 */ "eidlist_opt ::= LP eidlist RP", +- /* 214 */ "eidlist ::= eidlist COMMA nm collate sortorder", +- /* 215 */ "eidlist ::= nm collate sortorder", +- /* 216 */ "collate ::=", +- /* 217 */ "collate ::= COLLATE ID|STRING", +- /* 218 */ "cmd ::= DROP INDEX ifexists fullname", +- /* 219 */ "cmd ::= VACUUM", +- /* 220 */ "cmd ::= VACUUM nm", +- /* 221 */ "cmd ::= PRAGMA nm dbnm", +- /* 222 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", +- /* 223 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", +- /* 224 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", +- /* 225 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", +- /* 226 */ "plus_num ::= PLUS INTEGER|FLOAT", +- /* 227 */ "minus_num ::= MINUS INTEGER|FLOAT", +- /* 228 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", +- /* 229 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", +- /* 230 */ "trigger_time ::= BEFORE|AFTER", +- /* 231 */ "trigger_time ::= INSTEAD OF", +- /* 232 */ "trigger_time ::=", +- /* 233 */ "trigger_event ::= DELETE|INSERT", +- /* 234 */ "trigger_event ::= UPDATE", +- /* 235 */ "trigger_event ::= UPDATE OF idlist", +- /* 236 */ "when_clause ::=", +- /* 237 */ "when_clause ::= WHEN expr", +- /* 238 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", +- /* 239 */ "trigger_cmd_list ::= trigger_cmd SEMI", +- /* 240 */ "trnm ::= nm DOT nm", +- /* 241 */ "tridxby ::= INDEXED BY nm", +- /* 242 */ "tridxby ::= NOT INDEXED", +- /* 243 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt", +- /* 244 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select scanpt", +- /* 245 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt", +- /* 246 */ "trigger_cmd ::= scanpt select scanpt", +- /* 247 */ "expr ::= RAISE LP IGNORE RP", +- /* 248 */ "expr ::= RAISE LP raisetype COMMA nm RP", +- /* 249 */ "raisetype ::= ROLLBACK", +- /* 250 */ "raisetype ::= ABORT", +- /* 251 */ "raisetype ::= FAIL", +- /* 252 */ "cmd ::= DROP TRIGGER ifexists fullname", +- /* 253 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", +- /* 254 */ "cmd ::= DETACH database_kw_opt expr", +- /* 255 */ "key_opt ::=", +- /* 256 */ "key_opt ::= KEY expr", +- /* 257 */ "cmd ::= REINDEX", +- /* 258 */ "cmd ::= REINDEX nm dbnm", +- /* 259 */ "cmd ::= ANALYZE", +- /* 260 */ "cmd ::= ANALYZE nm dbnm", +- /* 261 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", +- /* 262 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", +- /* 263 */ "add_column_fullname ::= fullname", +- /* 264 */ "cmd ::= create_vtab", +- /* 265 */ "cmd ::= create_vtab LP vtabarglist RP", +- /* 266 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", +- /* 267 */ "vtabarg ::=", +- /* 268 */ "vtabargtoken ::= ANY", +- /* 269 */ "vtabargtoken ::= lp anylist RP", +- /* 270 */ "lp ::= LP", +- /* 271 */ "with ::= WITH wqlist", +- /* 272 */ "with ::= WITH RECURSIVE wqlist", +- /* 273 */ "wqlist ::= nm eidlist_opt AS LP select RP", +- /* 274 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", +- /* 275 */ "input ::= cmdlist", +- /* 276 */ "cmdlist ::= cmdlist ecmd", +- /* 277 */ "cmdlist ::= ecmd", +- /* 278 */ "ecmd ::= SEMI", +- /* 279 */ "ecmd ::= explain cmdx SEMI", +- /* 280 */ "explain ::=", +- /* 281 */ "trans_opt ::=", +- /* 282 */ "trans_opt ::= TRANSACTION", +- /* 283 */ "trans_opt ::= TRANSACTION nm", +- /* 284 */ "savepoint_opt ::= SAVEPOINT", +- /* 285 */ "savepoint_opt ::=", +- /* 286 */ "cmd ::= create_table create_table_args", +- /* 287 */ "columnlist ::= columnlist COMMA columnname carglist", +- /* 288 */ "columnlist ::= columnname carglist", +- /* 289 */ "nm ::= ID|INDEXED", +- /* 290 */ "nm ::= STRING", +- /* 291 */ "nm ::= JOIN_KW", +- /* 292 */ "typetoken ::= typename", +- /* 293 */ "typename ::= ID|STRING", +- /* 294 */ "signed ::= plus_num", +- /* 295 */ "signed ::= minus_num", +- /* 296 */ "carglist ::= carglist ccons", +- /* 297 */ "carglist ::=", +- /* 298 */ "ccons ::= NULL onconf", +- /* 299 */ "conslist_opt ::= COMMA conslist", +- /* 300 */ "conslist ::= conslist tconscomma tcons", +- /* 301 */ "conslist ::= tcons", +- /* 302 */ "tconscomma ::=", +- /* 303 */ "defer_subclause_opt ::= defer_subclause", +- /* 304 */ "resolvetype ::= raisetype", +- /* 305 */ "selectnowith ::= oneselect", +- /* 306 */ "oneselect ::= values", +- /* 307 */ "sclp ::= selcollist COMMA", +- /* 308 */ "as ::= ID|STRING", +- /* 309 */ "expr ::= term", +- /* 310 */ "likeop ::= LIKE_KW|MATCH", +- /* 311 */ "exprlist ::= nexprlist", +- /* 312 */ "nmnum ::= plus_num", +- /* 313 */ "nmnum ::= nm", +- /* 314 */ "nmnum ::= ON", +- /* 315 */ "nmnum ::= DELETE", +- /* 316 */ "nmnum ::= DEFAULT", +- /* 317 */ "plus_num ::= INTEGER|FLOAT", +- /* 318 */ "foreach_clause ::=", +- /* 319 */ "foreach_clause ::= FOR EACH ROW", +- /* 320 */ "trnm ::= nm", +- /* 321 */ "tridxby ::=", +- /* 322 */ "database_kw_opt ::= DATABASE", +- /* 323 */ "database_kw_opt ::=", +- /* 324 */ "kwcolumn_opt ::=", +- /* 325 */ "kwcolumn_opt ::= COLUMNKW", +- /* 326 */ "vtabarglist ::= vtabarg", +- /* 327 */ "vtabarglist ::= vtabarglist COMMA vtabarg", +- /* 328 */ "vtabarg ::= vtabarg vtabargtoken", +- /* 329 */ "anylist ::=", +- /* 330 */ "anylist ::= anylist LP anylist RP", +- /* 331 */ "anylist ::= anylist ANY", +- /* 332 */ "with ::=", ++ /* 88 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt", ++ /* 89 */ "values ::= VALUES LP nexprlist RP", ++ /* 90 */ "values ::= values COMMA LP nexprlist RP", ++ /* 91 */ "distinct ::= DISTINCT", ++ /* 92 */ "distinct ::= ALL", ++ /* 93 */ "distinct ::=", ++ /* 94 */ "sclp ::=", ++ /* 95 */ "selcollist ::= sclp scanpt expr scanpt as", ++ /* 96 */ "selcollist ::= sclp scanpt STAR", ++ /* 97 */ "selcollist ::= sclp scanpt nm DOT STAR", ++ /* 98 */ "as ::= AS nm", ++ /* 99 */ "as ::=", ++ /* 100 */ "from ::=", ++ /* 101 */ "from ::= FROM seltablist", ++ /* 102 */ "stl_prefix ::= seltablist joinop", ++ /* 103 */ "stl_prefix ::=", ++ /* 104 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt", ++ /* 105 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt", ++ /* 106 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt", ++ /* 107 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt", ++ /* 108 */ "dbnm ::=", ++ /* 109 */ "dbnm ::= DOT nm", ++ /* 110 */ "fullname ::= nm", ++ /* 111 */ "fullname ::= nm DOT nm", ++ /* 112 */ "xfullname ::= nm", ++ /* 113 */ "xfullname ::= nm DOT nm", ++ /* 114 */ "xfullname ::= nm DOT nm AS nm", ++ /* 115 */ "xfullname ::= nm AS nm", ++ /* 116 */ "joinop ::= COMMA|JOIN", ++ /* 117 */ "joinop ::= JOIN_KW JOIN", ++ /* 118 */ "joinop ::= JOIN_KW nm JOIN", ++ /* 119 */ "joinop ::= JOIN_KW nm nm JOIN", ++ /* 120 */ "on_opt ::= ON expr", ++ /* 121 */ "on_opt ::=", ++ /* 122 */ "indexed_opt ::=", ++ /* 123 */ "indexed_opt ::= INDEXED BY nm", ++ /* 124 */ "indexed_opt ::= NOT INDEXED", ++ /* 125 */ "using_opt ::= USING LP idlist RP", ++ /* 126 */ "using_opt ::=", ++ /* 127 */ "orderby_opt ::=", ++ /* 128 */ "orderby_opt ::= ORDER BY sortlist", ++ /* 129 */ "sortlist ::= sortlist COMMA expr sortorder", ++ /* 130 */ "sortlist ::= expr sortorder", ++ /* 131 */ "sortorder ::= ASC", ++ /* 132 */ "sortorder ::= DESC", ++ /* 133 */ "sortorder ::=", ++ /* 134 */ "groupby_opt ::=", ++ /* 135 */ "groupby_opt ::= GROUP BY nexprlist", ++ /* 136 */ "having_opt ::=", ++ /* 137 */ "having_opt ::= HAVING expr", ++ /* 138 */ "limit_opt ::=", ++ /* 139 */ "limit_opt ::= LIMIT expr", ++ /* 140 */ "limit_opt ::= LIMIT expr OFFSET expr", ++ /* 141 */ "limit_opt ::= LIMIT expr COMMA expr", ++ /* 142 */ "cmd ::= with DELETE FROM xfullname indexed_opt where_opt", ++ /* 143 */ "where_opt ::=", ++ /* 144 */ "where_opt ::= WHERE expr", ++ /* 145 */ "cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt", ++ /* 146 */ "setlist ::= setlist COMMA nm EQ expr", ++ /* 147 */ "setlist ::= setlist COMMA LP idlist RP EQ expr", ++ /* 148 */ "setlist ::= nm EQ expr", ++ /* 149 */ "setlist ::= LP idlist RP EQ expr", ++ /* 150 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert", ++ /* 151 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES", ++ /* 152 */ "upsert ::=", ++ /* 153 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt", ++ /* 154 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING", ++ /* 155 */ "upsert ::= ON CONFLICT DO NOTHING", ++ /* 156 */ "insert_cmd ::= INSERT orconf", ++ /* 157 */ "insert_cmd ::= REPLACE", ++ /* 158 */ "idlist_opt ::=", ++ /* 159 */ "idlist_opt ::= LP idlist RP", ++ /* 160 */ "idlist ::= idlist COMMA nm", ++ /* 161 */ "idlist ::= nm", ++ /* 162 */ "expr ::= LP expr RP", ++ /* 163 */ "expr ::= ID|INDEXED", ++ /* 164 */ "expr ::= JOIN_KW", ++ /* 165 */ "expr ::= nm DOT nm", ++ /* 166 */ "expr ::= nm DOT nm DOT nm", ++ /* 167 */ "term ::= NULL|FLOAT|BLOB", ++ /* 168 */ "term ::= STRING", ++ /* 169 */ "term ::= INTEGER", ++ /* 170 */ "expr ::= VARIABLE", ++ /* 171 */ "expr ::= expr COLLATE ID|STRING", ++ /* 172 */ "expr ::= CAST LP expr AS typetoken RP", ++ /* 173 */ "expr ::= ID|INDEXED LP distinct exprlist RP", ++ /* 174 */ "expr ::= ID|INDEXED LP STAR RP", ++ /* 175 */ "expr ::= ID|INDEXED LP distinct exprlist RP over_clause", ++ /* 176 */ "expr ::= ID|INDEXED LP STAR RP over_clause", ++ /* 177 */ "term ::= CTIME_KW", ++ /* 178 */ "expr ::= LP nexprlist COMMA expr RP", ++ /* 179 */ "expr ::= expr AND expr", ++ /* 180 */ "expr ::= expr OR expr", ++ /* 181 */ "expr ::= expr LT|GT|GE|LE expr", ++ /* 182 */ "expr ::= expr EQ|NE expr", ++ /* 183 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", ++ /* 184 */ "expr ::= expr PLUS|MINUS expr", ++ /* 185 */ "expr ::= expr STAR|SLASH|REM expr", ++ /* 186 */ "expr ::= expr CONCAT expr", ++ /* 187 */ "likeop ::= NOT LIKE_KW|MATCH", ++ /* 188 */ "expr ::= expr likeop expr", ++ /* 189 */ "expr ::= expr likeop expr ESCAPE expr", ++ /* 190 */ "expr ::= expr ISNULL|NOTNULL", ++ /* 191 */ "expr ::= expr NOT NULL", ++ /* 192 */ "expr ::= expr IS expr", ++ /* 193 */ "expr ::= expr IS NOT expr", ++ /* 194 */ "expr ::= NOT expr", ++ /* 195 */ "expr ::= BITNOT expr", ++ /* 196 */ "expr ::= PLUS|MINUS expr", ++ /* 197 */ "between_op ::= BETWEEN", ++ /* 198 */ "between_op ::= NOT BETWEEN", ++ /* 199 */ "expr ::= expr between_op expr AND expr", ++ /* 200 */ "in_op ::= IN", ++ /* 201 */ "in_op ::= NOT IN", ++ /* 202 */ "expr ::= expr in_op LP exprlist RP", ++ /* 203 */ "expr ::= LP select RP", ++ /* 204 */ "expr ::= expr in_op LP select RP", ++ /* 205 */ "expr ::= expr in_op nm dbnm paren_exprlist", ++ /* 206 */ "expr ::= EXISTS LP select RP", ++ /* 207 */ "expr ::= CASE case_operand case_exprlist case_else END", ++ /* 208 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", ++ /* 209 */ "case_exprlist ::= WHEN expr THEN expr", ++ /* 210 */ "case_else ::= ELSE expr", ++ /* 211 */ "case_else ::=", ++ /* 212 */ "case_operand ::= expr", ++ /* 213 */ "case_operand ::=", ++ /* 214 */ "exprlist ::=", ++ /* 215 */ "nexprlist ::= nexprlist COMMA expr", ++ /* 216 */ "nexprlist ::= expr", ++ /* 217 */ "paren_exprlist ::=", ++ /* 218 */ "paren_exprlist ::= LP exprlist RP", ++ /* 219 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", ++ /* 220 */ "uniqueflag ::= UNIQUE", ++ /* 221 */ "uniqueflag ::=", ++ /* 222 */ "eidlist_opt ::=", ++ /* 223 */ "eidlist_opt ::= LP eidlist RP", ++ /* 224 */ "eidlist ::= eidlist COMMA nm collate sortorder", ++ /* 225 */ "eidlist ::= nm collate sortorder", ++ /* 226 */ "collate ::=", ++ /* 227 */ "collate ::= COLLATE ID|STRING", ++ /* 228 */ "cmd ::= DROP INDEX ifexists fullname", ++ /* 229 */ "cmd ::= VACUUM", ++ /* 230 */ "cmd ::= VACUUM nm", ++ /* 231 */ "cmd ::= PRAGMA nm dbnm", ++ /* 232 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", ++ /* 233 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", ++ /* 234 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", ++ /* 235 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", ++ /* 236 */ "plus_num ::= PLUS INTEGER|FLOAT", ++ /* 237 */ "minus_num ::= MINUS INTEGER|FLOAT", ++ /* 238 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", ++ /* 239 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", ++ /* 240 */ "trigger_time ::= BEFORE|AFTER", ++ /* 241 */ "trigger_time ::= INSTEAD OF", ++ /* 242 */ "trigger_time ::=", ++ /* 243 */ "trigger_event ::= DELETE|INSERT", ++ /* 244 */ "trigger_event ::= UPDATE", ++ /* 245 */ "trigger_event ::= UPDATE OF idlist", ++ /* 246 */ "when_clause ::=", ++ /* 247 */ "when_clause ::= WHEN expr", ++ /* 248 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", ++ /* 249 */ "trigger_cmd_list ::= trigger_cmd SEMI", ++ /* 250 */ "trnm ::= nm DOT nm", ++ /* 251 */ "tridxby ::= INDEXED BY nm", ++ /* 252 */ "tridxby ::= NOT INDEXED", ++ /* 253 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt", ++ /* 254 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt", ++ /* 255 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt", ++ /* 256 */ "trigger_cmd ::= scanpt select scanpt", ++ /* 257 */ "expr ::= RAISE LP IGNORE RP", ++ /* 258 */ "expr ::= RAISE LP raisetype COMMA nm RP", ++ /* 259 */ "raisetype ::= ROLLBACK", ++ /* 260 */ "raisetype ::= ABORT", ++ /* 261 */ "raisetype ::= FAIL", ++ /* 262 */ "cmd ::= DROP TRIGGER ifexists fullname", ++ /* 263 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", ++ /* 264 */ "cmd ::= DETACH database_kw_opt expr", ++ /* 265 */ "key_opt ::=", ++ /* 266 */ "key_opt ::= KEY expr", ++ /* 267 */ "cmd ::= REINDEX", ++ /* 268 */ "cmd ::= REINDEX nm dbnm", ++ /* 269 */ "cmd ::= ANALYZE", ++ /* 270 */ "cmd ::= ANALYZE nm dbnm", ++ /* 271 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", ++ /* 272 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", ++ /* 273 */ "add_column_fullname ::= fullname", ++ /* 274 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm", ++ /* 275 */ "cmd ::= create_vtab", ++ /* 276 */ "cmd ::= create_vtab LP vtabarglist RP", ++ /* 277 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", ++ /* 278 */ "vtabarg ::=", ++ /* 279 */ "vtabargtoken ::= ANY", ++ /* 280 */ "vtabargtoken ::= lp anylist RP", ++ /* 281 */ "lp ::= LP", ++ /* 282 */ "with ::= WITH wqlist", ++ /* 283 */ "with ::= WITH RECURSIVE wqlist", ++ /* 284 */ "wqlist ::= nm eidlist_opt AS LP select RP", ++ /* 285 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", ++ /* 286 */ "windowdefn_list ::= windowdefn", ++ /* 287 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn", ++ /* 288 */ "windowdefn ::= nm AS window", ++ /* 289 */ "window ::= LP part_opt orderby_opt frame_opt RP", ++ /* 290 */ "part_opt ::= PARTITION BY nexprlist", ++ /* 291 */ "part_opt ::=", ++ /* 292 */ "frame_opt ::=", ++ /* 293 */ "frame_opt ::= range_or_rows frame_bound_s", ++ /* 294 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e", ++ /* 295 */ "range_or_rows ::= RANGE", ++ /* 296 */ "range_or_rows ::= ROWS", ++ /* 297 */ "frame_bound_s ::= frame_bound", ++ /* 298 */ "frame_bound_s ::= UNBOUNDED PRECEDING", ++ /* 299 */ "frame_bound_e ::= frame_bound", ++ /* 300 */ "frame_bound_e ::= UNBOUNDED FOLLOWING", ++ /* 301 */ "frame_bound ::= expr PRECEDING", ++ /* 302 */ "frame_bound ::= CURRENT ROW", ++ /* 303 */ "frame_bound ::= expr FOLLOWING", ++ /* 304 */ "window_clause ::= WINDOW windowdefn_list", ++ /* 305 */ "over_clause ::= filter_opt OVER window", ++ /* 306 */ "over_clause ::= filter_opt OVER nm", ++ /* 307 */ "filter_opt ::=", ++ /* 308 */ "filter_opt ::= FILTER LP WHERE expr RP", ++ /* 309 */ "input ::= cmdlist", ++ /* 310 */ "cmdlist ::= cmdlist ecmd", ++ /* 311 */ "cmdlist ::= ecmd", ++ /* 312 */ "ecmd ::= SEMI", ++ /* 313 */ "ecmd ::= cmdx SEMI", ++ /* 314 */ "ecmd ::= explain cmdx", ++ /* 315 */ "trans_opt ::=", ++ /* 316 */ "trans_opt ::= TRANSACTION", ++ /* 317 */ "trans_opt ::= TRANSACTION nm", ++ /* 318 */ "savepoint_opt ::= SAVEPOINT", ++ /* 319 */ "savepoint_opt ::=", ++ /* 320 */ "cmd ::= create_table create_table_args", ++ /* 321 */ "columnlist ::= columnlist COMMA columnname carglist", ++ /* 322 */ "columnlist ::= columnname carglist", ++ /* 323 */ "nm ::= ID|INDEXED", ++ /* 324 */ "nm ::= STRING", ++ /* 325 */ "nm ::= JOIN_KW", ++ /* 326 */ "typetoken ::= typename", ++ /* 327 */ "typename ::= ID|STRING", ++ /* 328 */ "signed ::= plus_num", ++ /* 329 */ "signed ::= minus_num", ++ /* 330 */ "carglist ::= carglist ccons", ++ /* 331 */ "carglist ::=", ++ /* 332 */ "ccons ::= NULL onconf", ++ /* 333 */ "conslist_opt ::= COMMA conslist", ++ /* 334 */ "conslist ::= conslist tconscomma tcons", ++ /* 335 */ "conslist ::= tcons", ++ /* 336 */ "tconscomma ::=", ++ /* 337 */ "defer_subclause_opt ::= defer_subclause", ++ /* 338 */ "resolvetype ::= raisetype", ++ /* 339 */ "selectnowith ::= oneselect", ++ /* 340 */ "oneselect ::= values", ++ /* 341 */ "sclp ::= selcollist COMMA", ++ /* 342 */ "as ::= ID|STRING", ++ /* 343 */ "expr ::= term", ++ /* 344 */ "likeop ::= LIKE_KW|MATCH", ++ /* 345 */ "exprlist ::= nexprlist", ++ /* 346 */ "nmnum ::= plus_num", ++ /* 347 */ "nmnum ::= nm", ++ /* 348 */ "nmnum ::= ON", ++ /* 349 */ "nmnum ::= DELETE", ++ /* 350 */ "nmnum ::= DEFAULT", ++ /* 351 */ "plus_num ::= INTEGER|FLOAT", ++ /* 352 */ "foreach_clause ::=", ++ /* 353 */ "foreach_clause ::= FOR EACH ROW", ++ /* 354 */ "trnm ::= nm", ++ /* 355 */ "tridxby ::=", ++ /* 356 */ "database_kw_opt ::= DATABASE", ++ /* 357 */ "database_kw_opt ::=", ++ /* 358 */ "kwcolumn_opt ::=", ++ /* 359 */ "kwcolumn_opt ::= COLUMNKW", ++ /* 360 */ "vtabarglist ::= vtabarg", ++ /* 361 */ "vtabarglist ::= vtabarglist COMMA vtabarg", ++ /* 362 */ "vtabarg ::= vtabarg vtabargtoken", ++ /* 363 */ "anylist ::=", ++ /* 364 */ "anylist ::= anylist LP anylist RP", ++ /* 365 */ "anylist ::= anylist ANY", ++ /* 366 */ "with ::=", + }; + #endif /* NDEBUG */ + +@@ -141412,28 +148620,29 @@ + + /* Initialize a new parser that has already been allocated. + */ +-SQLITE_PRIVATE void sqlite3ParserInit(void *yypParser){ +- yyParser *pParser = (yyParser*)yypParser; ++SQLITE_PRIVATE void sqlite3ParserInit(void *yypRawParser sqlite3ParserCTX_PDECL){ ++ yyParser *yypParser = (yyParser*)yypRawParser; ++ sqlite3ParserCTX_STORE + #ifdef YYTRACKMAXSTACKDEPTH +- pParser->yyhwm = 0; ++ yypParser->yyhwm = 0; + #endif + #if YYSTACKDEPTH<=0 +- pParser->yytos = NULL; +- pParser->yystack = NULL; +- pParser->yystksz = 0; +- if( yyGrowStack(pParser) ){ +- pParser->yystack = &pParser->yystk0; +- pParser->yystksz = 1; ++ yypParser->yytos = NULL; ++ yypParser->yystack = NULL; ++ yypParser->yystksz = 0; ++ if( yyGrowStack(yypParser) ){ ++ yypParser->yystack = &yypParser->yystk0; ++ yypParser->yystksz = 1; + } + #endif + #ifndef YYNOERRORRECOVERY +- pParser->yyerrcnt = -1; ++ yypParser->yyerrcnt = -1; + #endif +- pParser->yytos = pParser->yystack; +- pParser->yystack[0].stateno = 0; +- pParser->yystack[0].major = 0; ++ yypParser->yytos = yypParser->yystack; ++ yypParser->yystack[0].stateno = 0; ++ yypParser->yystack[0].major = 0; + #if YYSTACKDEPTH>0 +- pParser->yystackEnd = &pParser->yystack[YYSTACKDEPTH-1]; ++ yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1]; + #endif + } + +@@ -141450,11 +148659,14 @@ + ** A pointer to a parser. This pointer is used in subsequent calls + ** to sqlite3Parser and sqlite3ParserFree. + */ +-SQLITE_PRIVATE void *sqlite3ParserAlloc(void *(*mallocProc)(YYMALLOCARGTYPE)){ +- yyParser *pParser; +- pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); +- if( pParser ) sqlite3ParserInit(pParser); +- return pParser; ++SQLITE_PRIVATE void *sqlite3ParserAlloc(void *(*mallocProc)(YYMALLOCARGTYPE) sqlite3ParserCTX_PDECL){ ++ yyParser *yypParser; ++ yypParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); ++ if( yypParser ){ ++ sqlite3ParserCTX_STORE ++ sqlite3ParserInit(yypParser sqlite3ParserCTX_PARAM); ++ } ++ return (void*)yypParser; + } + #endif /* sqlite3Parser_ENGINEALWAYSONSTACK */ + +@@ -141471,7 +148683,8 @@ + YYCODETYPE yymajor, /* Type code for object to destroy */ + YYMINORTYPE *yypminor /* The object to be destroyed */ + ){ +- sqlite3ParserARG_FETCH; ++ sqlite3ParserARG_FETCH ++ sqlite3ParserCTX_FETCH + switch( yymajor ){ + /* Here is inserted the actions which take place when a + ** terminal or non-terminal is destroyed. This can happen +@@ -141484,74 +148697,98 @@ + ** inside the C code. + */ + /********* Begin destructor definitions ***************************************/ +- case 163: /* select */ +- case 195: /* selectnowith */ +- case 196: /* oneselect */ +- case 207: /* values */ ++ case 174: /* select */ ++ case 206: /* selectnowith */ ++ case 207: /* oneselect */ ++ case 219: /* values */ + { +-sqlite3SelectDelete(pParse->db, (yypminor->yy387)); ++sqlite3SelectDelete(pParse->db, (yypminor->yy489)); + } + break; +- case 173: /* term */ +- case 174: /* expr */ +- case 202: /* where_opt */ +- case 204: /* having_opt */ +- case 216: /* on_opt */ +- case 227: /* case_operand */ +- case 229: /* case_else */ +- case 238: /* when_clause */ +- case 243: /* key_opt */ ++ case 184: /* term */ ++ case 185: /* expr */ ++ case 213: /* where_opt */ ++ case 215: /* having_opt */ ++ case 227: /* on_opt */ ++ case 242: /* case_operand */ ++ case 244: /* case_else */ ++ case 253: /* when_clause */ ++ case 258: /* key_opt */ ++ case 272: /* filter_opt */ + { +-sqlite3ExprDelete(pParse->db, (yypminor->yy314)); ++sqlite3ExprDelete(pParse->db, (yypminor->yy18)); + } + break; +- case 178: /* eidlist_opt */ +- case 187: /* sortlist */ +- case 188: /* eidlist */ +- case 200: /* selcollist */ +- case 203: /* groupby_opt */ +- case 205: /* orderby_opt */ +- case 208: /* nexprlist */ +- case 209: /* exprlist */ +- case 210: /* sclp */ +- case 220: /* setlist */ +- case 226: /* paren_exprlist */ +- case 228: /* case_exprlist */ ++ case 189: /* eidlist_opt */ ++ case 198: /* sortlist */ ++ case 199: /* eidlist */ ++ case 211: /* selcollist */ ++ case 214: /* groupby_opt */ ++ case 216: /* orderby_opt */ ++ case 220: /* nexprlist */ ++ case 221: /* sclp */ ++ case 229: /* exprlist */ ++ case 233: /* setlist */ ++ case 241: /* paren_exprlist */ ++ case 243: /* case_exprlist */ ++ case 271: /* part_opt */ + { +-sqlite3ExprListDelete(pParse->db, (yypminor->yy322)); ++sqlite3ExprListDelete(pParse->db, (yypminor->yy420)); + } + break; +- case 194: /* fullname */ +- case 201: /* from */ +- case 212: /* seltablist */ +- case 213: /* stl_prefix */ ++ case 205: /* fullname */ ++ case 212: /* from */ ++ case 223: /* seltablist */ ++ case 224: /* stl_prefix */ ++ case 230: /* xfullname */ + { +-sqlite3SrcListDelete(pParse->db, (yypminor->yy259)); ++sqlite3SrcListDelete(pParse->db, (yypminor->yy135)); + } + break; +- case 197: /* wqlist */ ++ case 208: /* wqlist */ + { +-sqlite3WithDelete(pParse->db, (yypminor->yy451)); ++sqlite3WithDelete(pParse->db, (yypminor->yy449)); + } + break; +- case 217: /* using_opt */ +- case 218: /* idlist */ +- case 222: /* idlist_opt */ ++ case 218: /* window_clause */ ++ case 267: /* windowdefn_list */ + { +-sqlite3IdListDelete(pParse->db, (yypminor->yy384)); ++sqlite3WindowListDelete(pParse->db, (yypminor->yy327)); + } + break; +- case 234: /* trigger_cmd_list */ +- case 239: /* trigger_cmd */ ++ case 228: /* using_opt */ ++ case 231: /* idlist */ ++ case 235: /* idlist_opt */ + { +-sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy203)); ++sqlite3IdListDelete(pParse->db, (yypminor->yy48)); + } + break; +- case 236: /* trigger_event */ ++ case 237: /* over_clause */ ++ case 268: /* windowdefn */ ++ case 269: /* window */ ++ case 270: /* frame_opt */ + { +-sqlite3IdListDelete(pParse->db, (yypminor->yy90).b); ++sqlite3WindowDelete(pParse->db, (yypminor->yy327)); + } + break; ++ case 249: /* trigger_cmd_list */ ++ case 254: /* trigger_cmd */ ++{ ++sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy207)); ++} ++ break; ++ case 251: /* trigger_event */ ++{ ++sqlite3IdListDelete(pParse->db, (yypminor->yy34).b); ++} ++ break; ++ case 274: /* frame_bound */ ++ case 275: /* frame_bound_s */ ++ case 276: /* frame_bound_e */ ++{ ++sqlite3ExprDelete(pParse->db, (yypminor->yy119).pExpr); ++} ++ break; + /********* End destructor definitions *****************************************/ + default: break; /* If no destructor action specified: do nothing */ + } +@@ -141661,13 +148898,12 @@ + ** Find the appropriate action for a parser given the terminal + ** look-ahead token iLookAhead. + */ +-static unsigned int yy_find_shift_action( +- yyParser *pParser, /* The parser */ +- YYCODETYPE iLookAhead /* The look-ahead token */ ++static YYACTIONTYPE yy_find_shift_action( ++ YYCODETYPE iLookAhead, /* The look-ahead token */ ++ YYACTIONTYPE stateno /* Current state number */ + ){ + int i; +- int stateno = pParser->yytos->stateno; +- ++ + if( stateno>YY_MAX_SHIFT ) return stateno; + assert( stateno <= YY_SHIFT_COUNT ); + #if defined(YYCOVERAGE) +@@ -141676,11 +148912,11 @@ + do{ + i = yy_shift_ofst[stateno]; + assert( i>=0 ); +- assert( i+YYNTOKEN<=(int)sizeof(yy_lookahead)/sizeof(yy_lookahead[0]) ); ++ /* assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD ); */ + assert( iLookAhead!=YYNOCODE ); + assert( iLookAhead < YYNTOKEN ); + i += iLookAhead; +- if( yy_lookahead[i]!=iLookAhead ){ ++ if( i>=YY_NLOOKAHEAD || yy_lookahead[i]!=iLookAhead ){ + #ifdef YYFALLBACK + YYCODETYPE iFallback; /* Fallback token */ + if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0]) +@@ -141706,6 +148942,7 @@ + #if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT + j<YY_ACTTAB_COUNT && + #endif ++ j<(int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])) && + yy_lookahead[j]==YYWILDCARD && iLookAhead>0 + ){ + #ifndef NDEBUG +@@ -141730,8 +148967,8 @@ + ** Find the appropriate action for a parser given the non-terminal + ** look-ahead token iLookAhead. + */ +-static int yy_find_reduce_action( +- int stateno, /* Current state number */ ++static YYACTIONTYPE yy_find_reduce_action( ++ YYACTIONTYPE stateno, /* Current state number */ + YYCODETYPE iLookAhead /* The look-ahead token */ + ){ + int i; +@@ -141760,7 +148997,8 @@ + ** The following routine is called if the stack overflows. + */ + static void yyStackOverflow(yyParser *yypParser){ +- sqlite3ParserARG_FETCH; ++ sqlite3ParserARG_FETCH ++ sqlite3ParserCTX_FETCH + #ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); +@@ -141773,7 +149011,8 @@ + + sqlite3ErrorMsg(pParse, "parser stack overflow"); + /******** End %stack_overflow code ********************************************/ +- sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument var */ ++ sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument var */ ++ sqlite3ParserCTX_STORE + } + + /* +@@ -141802,8 +149041,8 @@ + */ + static void yy_shift( + yyParser *yypParser, /* The parser to be shifted */ +- int yyNewState, /* The new state to shift in */ +- int yyMajor, /* The major token to shift in */ ++ YYACTIONTYPE yyNewState, /* The new state to shift in */ ++ YYCODETYPE yyMajor, /* The major token to shift in */ + sqlite3ParserTOKENTYPE yyMinor /* The minor token to shift in */ + ){ + yyStackEntry *yytos; +@@ -141833,8 +149072,8 @@ + yyNewState += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; + } + yytos = yypParser->yytos; +- yytos->stateno = (YYACTIONTYPE)yyNewState; +- yytos->major = (YYCODETYPE)yyMajor; ++ yytos->stateno = yyNewState; ++ yytos->major = yyMajor; + yytos->minor.yy0 = yyMinor; + yyTraceShift(yypParser, yyNewState, "Shift"); + } +@@ -141846,339 +149085,373 @@ + YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ + signed char nrhs; /* Negative of the number of RHS symbols in the rule */ + } yyRuleInfo[] = { +- { 147, -1 }, /* (0) explain ::= EXPLAIN */ +- { 147, -3 }, /* (1) explain ::= EXPLAIN QUERY PLAN */ +- { 148, -1 }, /* (2) cmdx ::= cmd */ +- { 149, -3 }, /* (3) cmd ::= BEGIN transtype trans_opt */ +- { 150, 0 }, /* (4) transtype ::= */ +- { 150, -1 }, /* (5) transtype ::= DEFERRED */ +- { 150, -1 }, /* (6) transtype ::= IMMEDIATE */ +- { 150, -1 }, /* (7) transtype ::= EXCLUSIVE */ +- { 149, -2 }, /* (8) cmd ::= COMMIT|END trans_opt */ +- { 149, -2 }, /* (9) cmd ::= ROLLBACK trans_opt */ +- { 149, -2 }, /* (10) cmd ::= SAVEPOINT nm */ +- { 149, -3 }, /* (11) cmd ::= RELEASE savepoint_opt nm */ +- { 149, -5 }, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */ +- { 154, -6 }, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */ +- { 156, -1 }, /* (14) createkw ::= CREATE */ +- { 158, 0 }, /* (15) ifnotexists ::= */ +- { 158, -3 }, /* (16) ifnotexists ::= IF NOT EXISTS */ +- { 157, -1 }, /* (17) temp ::= TEMP */ +- { 157, 0 }, /* (18) temp ::= */ +- { 155, -5 }, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_options */ +- { 155, -2 }, /* (20) create_table_args ::= AS select */ +- { 162, 0 }, /* (21) table_options ::= */ +- { 162, -2 }, /* (22) table_options ::= WITHOUT nm */ +- { 164, -2 }, /* (23) columnname ::= nm typetoken */ +- { 166, 0 }, /* (24) typetoken ::= */ +- { 166, -4 }, /* (25) typetoken ::= typename LP signed RP */ +- { 166, -6 }, /* (26) typetoken ::= typename LP signed COMMA signed RP */ +- { 167, -2 }, /* (27) typename ::= typename ID|STRING */ +- { 171, 0 }, /* (28) scanpt ::= */ +- { 172, -2 }, /* (29) ccons ::= CONSTRAINT nm */ +- { 172, -4 }, /* (30) ccons ::= DEFAULT scanpt term scanpt */ +- { 172, -4 }, /* (31) ccons ::= DEFAULT LP expr RP */ +- { 172, -4 }, /* (32) ccons ::= DEFAULT PLUS term scanpt */ +- { 172, -4 }, /* (33) ccons ::= DEFAULT MINUS term scanpt */ +- { 172, -3 }, /* (34) ccons ::= DEFAULT scanpt ID|INDEXED */ +- { 172, -3 }, /* (35) ccons ::= NOT NULL onconf */ +- { 172, -5 }, /* (36) ccons ::= PRIMARY KEY sortorder onconf autoinc */ +- { 172, -2 }, /* (37) ccons ::= UNIQUE onconf */ +- { 172, -4 }, /* (38) ccons ::= CHECK LP expr RP */ +- { 172, -4 }, /* (39) ccons ::= REFERENCES nm eidlist_opt refargs */ +- { 172, -1 }, /* (40) ccons ::= defer_subclause */ +- { 172, -2 }, /* (41) ccons ::= COLLATE ID|STRING */ +- { 177, 0 }, /* (42) autoinc ::= */ +- { 177, -1 }, /* (43) autoinc ::= AUTOINCR */ +- { 179, 0 }, /* (44) refargs ::= */ +- { 179, -2 }, /* (45) refargs ::= refargs refarg */ +- { 181, -2 }, /* (46) refarg ::= MATCH nm */ +- { 181, -3 }, /* (47) refarg ::= ON INSERT refact */ +- { 181, -3 }, /* (48) refarg ::= ON DELETE refact */ +- { 181, -3 }, /* (49) refarg ::= ON UPDATE refact */ +- { 182, -2 }, /* (50) refact ::= SET NULL */ +- { 182, -2 }, /* (51) refact ::= SET DEFAULT */ +- { 182, -1 }, /* (52) refact ::= CASCADE */ +- { 182, -1 }, /* (53) refact ::= RESTRICT */ +- { 182, -2 }, /* (54) refact ::= NO ACTION */ +- { 180, -3 }, /* (55) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ +- { 180, -2 }, /* (56) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ +- { 183, 0 }, /* (57) init_deferred_pred_opt ::= */ +- { 183, -2 }, /* (58) init_deferred_pred_opt ::= INITIALLY DEFERRED */ +- { 183, -2 }, /* (59) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ +- { 161, 0 }, /* (60) conslist_opt ::= */ +- { 185, -1 }, /* (61) tconscomma ::= COMMA */ +- { 186, -2 }, /* (62) tcons ::= CONSTRAINT nm */ +- { 186, -7 }, /* (63) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ +- { 186, -5 }, /* (64) tcons ::= UNIQUE LP sortlist RP onconf */ +- { 186, -5 }, /* (65) tcons ::= CHECK LP expr RP onconf */ +- { 186, -10 }, /* (66) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ +- { 189, 0 }, /* (67) defer_subclause_opt ::= */ +- { 175, 0 }, /* (68) onconf ::= */ +- { 175, -3 }, /* (69) onconf ::= ON CONFLICT resolvetype */ +- { 190, 0 }, /* (70) orconf ::= */ +- { 190, -2 }, /* (71) orconf ::= OR resolvetype */ +- { 191, -1 }, /* (72) resolvetype ::= IGNORE */ +- { 191, -1 }, /* (73) resolvetype ::= REPLACE */ +- { 149, -4 }, /* (74) cmd ::= DROP TABLE ifexists fullname */ +- { 193, -2 }, /* (75) ifexists ::= IF EXISTS */ +- { 193, 0 }, /* (76) ifexists ::= */ +- { 149, -9 }, /* (77) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ +- { 149, -4 }, /* (78) cmd ::= DROP VIEW ifexists fullname */ +- { 149, -1 }, /* (79) cmd ::= select */ +- { 163, -3 }, /* (80) select ::= WITH wqlist selectnowith */ +- { 163, -4 }, /* (81) select ::= WITH RECURSIVE wqlist selectnowith */ +- { 163, -1 }, /* (82) select ::= selectnowith */ +- { 195, -3 }, /* (83) selectnowith ::= selectnowith multiselect_op oneselect */ +- { 198, -1 }, /* (84) multiselect_op ::= UNION */ +- { 198, -2 }, /* (85) multiselect_op ::= UNION ALL */ +- { 198, -1 }, /* (86) multiselect_op ::= EXCEPT|INTERSECT */ +- { 196, -9 }, /* (87) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ +- { 207, -4 }, /* (88) values ::= VALUES LP nexprlist RP */ +- { 207, -5 }, /* (89) values ::= values COMMA LP exprlist RP */ +- { 199, -1 }, /* (90) distinct ::= DISTINCT */ +- { 199, -1 }, /* (91) distinct ::= ALL */ +- { 199, 0 }, /* (92) distinct ::= */ +- { 210, 0 }, /* (93) sclp ::= */ +- { 200, -5 }, /* (94) selcollist ::= sclp scanpt expr scanpt as */ +- { 200, -3 }, /* (95) selcollist ::= sclp scanpt STAR */ +- { 200, -5 }, /* (96) selcollist ::= sclp scanpt nm DOT STAR */ +- { 211, -2 }, /* (97) as ::= AS nm */ +- { 211, 0 }, /* (98) as ::= */ +- { 201, 0 }, /* (99) from ::= */ +- { 201, -2 }, /* (100) from ::= FROM seltablist */ +- { 213, -2 }, /* (101) stl_prefix ::= seltablist joinop */ +- { 213, 0 }, /* (102) stl_prefix ::= */ +- { 212, -7 }, /* (103) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ +- { 212, -9 }, /* (104) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */ +- { 212, -7 }, /* (105) seltablist ::= stl_prefix LP select RP as on_opt using_opt */ +- { 212, -7 }, /* (106) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ +- { 159, 0 }, /* (107) dbnm ::= */ +- { 159, -2 }, /* (108) dbnm ::= DOT nm */ +- { 194, -1 }, /* (109) fullname ::= nm */ +- { 194, -3 }, /* (110) fullname ::= nm DOT nm */ +- { 214, -1 }, /* (111) joinop ::= COMMA|JOIN */ +- { 214, -2 }, /* (112) joinop ::= JOIN_KW JOIN */ +- { 214, -3 }, /* (113) joinop ::= JOIN_KW nm JOIN */ +- { 214, -4 }, /* (114) joinop ::= JOIN_KW nm nm JOIN */ +- { 216, -2 }, /* (115) on_opt ::= ON expr */ +- { 216, 0 }, /* (116) on_opt ::= */ +- { 215, 0 }, /* (117) indexed_opt ::= */ +- { 215, -3 }, /* (118) indexed_opt ::= INDEXED BY nm */ +- { 215, -2 }, /* (119) indexed_opt ::= NOT INDEXED */ +- { 217, -4 }, /* (120) using_opt ::= USING LP idlist RP */ +- { 217, 0 }, /* (121) using_opt ::= */ +- { 205, 0 }, /* (122) orderby_opt ::= */ +- { 205, -3 }, /* (123) orderby_opt ::= ORDER BY sortlist */ +- { 187, -4 }, /* (124) sortlist ::= sortlist COMMA expr sortorder */ +- { 187, -2 }, /* (125) sortlist ::= expr sortorder */ +- { 176, -1 }, /* (126) sortorder ::= ASC */ +- { 176, -1 }, /* (127) sortorder ::= DESC */ +- { 176, 0 }, /* (128) sortorder ::= */ +- { 203, 0 }, /* (129) groupby_opt ::= */ +- { 203, -3 }, /* (130) groupby_opt ::= GROUP BY nexprlist */ +- { 204, 0 }, /* (131) having_opt ::= */ +- { 204, -2 }, /* (132) having_opt ::= HAVING expr */ +- { 206, 0 }, /* (133) limit_opt ::= */ +- { 206, -2 }, /* (134) limit_opt ::= LIMIT expr */ +- { 206, -4 }, /* (135) limit_opt ::= LIMIT expr OFFSET expr */ +- { 206, -4 }, /* (136) limit_opt ::= LIMIT expr COMMA expr */ +- { 149, -6 }, /* (137) cmd ::= with DELETE FROM fullname indexed_opt where_opt */ +- { 202, 0 }, /* (138) where_opt ::= */ +- { 202, -2 }, /* (139) where_opt ::= WHERE expr */ +- { 149, -8 }, /* (140) cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt */ +- { 220, -5 }, /* (141) setlist ::= setlist COMMA nm EQ expr */ +- { 220, -7 }, /* (142) setlist ::= setlist COMMA LP idlist RP EQ expr */ +- { 220, -3 }, /* (143) setlist ::= nm EQ expr */ +- { 220, -5 }, /* (144) setlist ::= LP idlist RP EQ expr */ +- { 149, -6 }, /* (145) cmd ::= with insert_cmd INTO fullname idlist_opt select */ +- { 149, -7 }, /* (146) cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES */ +- { 221, -2 }, /* (147) insert_cmd ::= INSERT orconf */ +- { 221, -1 }, /* (148) insert_cmd ::= REPLACE */ +- { 222, 0 }, /* (149) idlist_opt ::= */ +- { 222, -3 }, /* (150) idlist_opt ::= LP idlist RP */ +- { 218, -3 }, /* (151) idlist ::= idlist COMMA nm */ +- { 218, -1 }, /* (152) idlist ::= nm */ +- { 174, -3 }, /* (153) expr ::= LP expr RP */ +- { 174, -1 }, /* (154) expr ::= ID|INDEXED */ +- { 174, -1 }, /* (155) expr ::= JOIN_KW */ +- { 174, -3 }, /* (156) expr ::= nm DOT nm */ +- { 174, -5 }, /* (157) expr ::= nm DOT nm DOT nm */ +- { 173, -1 }, /* (158) term ::= NULL|FLOAT|BLOB */ +- { 173, -1 }, /* (159) term ::= STRING */ +- { 173, -1 }, /* (160) term ::= INTEGER */ +- { 174, -1 }, /* (161) expr ::= VARIABLE */ +- { 174, -3 }, /* (162) expr ::= expr COLLATE ID|STRING */ +- { 174, -6 }, /* (163) expr ::= CAST LP expr AS typetoken RP */ +- { 174, -5 }, /* (164) expr ::= ID|INDEXED LP distinct exprlist RP */ +- { 174, -4 }, /* (165) expr ::= ID|INDEXED LP STAR RP */ +- { 173, -1 }, /* (166) term ::= CTIME_KW */ +- { 174, -5 }, /* (167) expr ::= LP nexprlist COMMA expr RP */ +- { 174, -3 }, /* (168) expr ::= expr AND expr */ +- { 174, -3 }, /* (169) expr ::= expr OR expr */ +- { 174, -3 }, /* (170) expr ::= expr LT|GT|GE|LE expr */ +- { 174, -3 }, /* (171) expr ::= expr EQ|NE expr */ +- { 174, -3 }, /* (172) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ +- { 174, -3 }, /* (173) expr ::= expr PLUS|MINUS expr */ +- { 174, -3 }, /* (174) expr ::= expr STAR|SLASH|REM expr */ +- { 174, -3 }, /* (175) expr ::= expr CONCAT expr */ +- { 223, -2 }, /* (176) likeop ::= NOT LIKE_KW|MATCH */ +- { 174, -3 }, /* (177) expr ::= expr likeop expr */ +- { 174, -5 }, /* (178) expr ::= expr likeop expr ESCAPE expr */ +- { 174, -2 }, /* (179) expr ::= expr ISNULL|NOTNULL */ +- { 174, -3 }, /* (180) expr ::= expr NOT NULL */ +- { 174, -3 }, /* (181) expr ::= expr IS expr */ +- { 174, -4 }, /* (182) expr ::= expr IS NOT expr */ +- { 174, -2 }, /* (183) expr ::= NOT expr */ +- { 174, -2 }, /* (184) expr ::= BITNOT expr */ +- { 174, -2 }, /* (185) expr ::= MINUS expr */ +- { 174, -2 }, /* (186) expr ::= PLUS expr */ +- { 224, -1 }, /* (187) between_op ::= BETWEEN */ +- { 224, -2 }, /* (188) between_op ::= NOT BETWEEN */ +- { 174, -5 }, /* (189) expr ::= expr between_op expr AND expr */ +- { 225, -1 }, /* (190) in_op ::= IN */ +- { 225, -2 }, /* (191) in_op ::= NOT IN */ +- { 174, -5 }, /* (192) expr ::= expr in_op LP exprlist RP */ +- { 174, -3 }, /* (193) expr ::= LP select RP */ +- { 174, -5 }, /* (194) expr ::= expr in_op LP select RP */ +- { 174, -5 }, /* (195) expr ::= expr in_op nm dbnm paren_exprlist */ +- { 174, -4 }, /* (196) expr ::= EXISTS LP select RP */ +- { 174, -5 }, /* (197) expr ::= CASE case_operand case_exprlist case_else END */ +- { 228, -5 }, /* (198) case_exprlist ::= case_exprlist WHEN expr THEN expr */ +- { 228, -4 }, /* (199) case_exprlist ::= WHEN expr THEN expr */ +- { 229, -2 }, /* (200) case_else ::= ELSE expr */ +- { 229, 0 }, /* (201) case_else ::= */ +- { 227, -1 }, /* (202) case_operand ::= expr */ +- { 227, 0 }, /* (203) case_operand ::= */ +- { 209, 0 }, /* (204) exprlist ::= */ +- { 208, -3 }, /* (205) nexprlist ::= nexprlist COMMA expr */ +- { 208, -1 }, /* (206) nexprlist ::= expr */ +- { 226, 0 }, /* (207) paren_exprlist ::= */ +- { 226, -3 }, /* (208) paren_exprlist ::= LP exprlist RP */ +- { 149, -12 }, /* (209) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ +- { 230, -1 }, /* (210) uniqueflag ::= UNIQUE */ +- { 230, 0 }, /* (211) uniqueflag ::= */ +- { 178, 0 }, /* (212) eidlist_opt ::= */ +- { 178, -3 }, /* (213) eidlist_opt ::= LP eidlist RP */ +- { 188, -5 }, /* (214) eidlist ::= eidlist COMMA nm collate sortorder */ +- { 188, -3 }, /* (215) eidlist ::= nm collate sortorder */ +- { 231, 0 }, /* (216) collate ::= */ +- { 231, -2 }, /* (217) collate ::= COLLATE ID|STRING */ +- { 149, -4 }, /* (218) cmd ::= DROP INDEX ifexists fullname */ +- { 149, -1 }, /* (219) cmd ::= VACUUM */ +- { 149, -2 }, /* (220) cmd ::= VACUUM nm */ +- { 149, -3 }, /* (221) cmd ::= PRAGMA nm dbnm */ +- { 149, -5 }, /* (222) cmd ::= PRAGMA nm dbnm EQ nmnum */ +- { 149, -6 }, /* (223) cmd ::= PRAGMA nm dbnm LP nmnum RP */ +- { 149, -5 }, /* (224) cmd ::= PRAGMA nm dbnm EQ minus_num */ +- { 149, -6 }, /* (225) cmd ::= PRAGMA nm dbnm LP minus_num RP */ +- { 169, -2 }, /* (226) plus_num ::= PLUS INTEGER|FLOAT */ +- { 170, -2 }, /* (227) minus_num ::= MINUS INTEGER|FLOAT */ +- { 149, -5 }, /* (228) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ +- { 233, -11 }, /* (229) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ +- { 235, -1 }, /* (230) trigger_time ::= BEFORE|AFTER */ +- { 235, -2 }, /* (231) trigger_time ::= INSTEAD OF */ +- { 235, 0 }, /* (232) trigger_time ::= */ +- { 236, -1 }, /* (233) trigger_event ::= DELETE|INSERT */ +- { 236, -1 }, /* (234) trigger_event ::= UPDATE */ +- { 236, -3 }, /* (235) trigger_event ::= UPDATE OF idlist */ +- { 238, 0 }, /* (236) when_clause ::= */ +- { 238, -2 }, /* (237) when_clause ::= WHEN expr */ +- { 234, -3 }, /* (238) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ +- { 234, -2 }, /* (239) trigger_cmd_list ::= trigger_cmd SEMI */ +- { 240, -3 }, /* (240) trnm ::= nm DOT nm */ +- { 241, -3 }, /* (241) tridxby ::= INDEXED BY nm */ +- { 241, -2 }, /* (242) tridxby ::= NOT INDEXED */ +- { 239, -8 }, /* (243) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */ +- { 239, -7 }, /* (244) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select scanpt */ +- { 239, -6 }, /* (245) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ +- { 239, -3 }, /* (246) trigger_cmd ::= scanpt select scanpt */ +- { 174, -4 }, /* (247) expr ::= RAISE LP IGNORE RP */ +- { 174, -6 }, /* (248) expr ::= RAISE LP raisetype COMMA nm RP */ +- { 192, -1 }, /* (249) raisetype ::= ROLLBACK */ +- { 192, -1 }, /* (250) raisetype ::= ABORT */ +- { 192, -1 }, /* (251) raisetype ::= FAIL */ +- { 149, -4 }, /* (252) cmd ::= DROP TRIGGER ifexists fullname */ +- { 149, -6 }, /* (253) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ +- { 149, -3 }, /* (254) cmd ::= DETACH database_kw_opt expr */ +- { 243, 0 }, /* (255) key_opt ::= */ +- { 243, -2 }, /* (256) key_opt ::= KEY expr */ +- { 149, -1 }, /* (257) cmd ::= REINDEX */ +- { 149, -3 }, /* (258) cmd ::= REINDEX nm dbnm */ +- { 149, -1 }, /* (259) cmd ::= ANALYZE */ +- { 149, -3 }, /* (260) cmd ::= ANALYZE nm dbnm */ +- { 149, -6 }, /* (261) cmd ::= ALTER TABLE fullname RENAME TO nm */ +- { 149, -7 }, /* (262) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ +- { 244, -1 }, /* (263) add_column_fullname ::= fullname */ +- { 149, -1 }, /* (264) cmd ::= create_vtab */ +- { 149, -4 }, /* (265) cmd ::= create_vtab LP vtabarglist RP */ +- { 246, -8 }, /* (266) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ +- { 248, 0 }, /* (267) vtabarg ::= */ +- { 249, -1 }, /* (268) vtabargtoken ::= ANY */ +- { 249, -3 }, /* (269) vtabargtoken ::= lp anylist RP */ +- { 250, -1 }, /* (270) lp ::= LP */ +- { 219, -2 }, /* (271) with ::= WITH wqlist */ +- { 219, -3 }, /* (272) with ::= WITH RECURSIVE wqlist */ +- { 197, -6 }, /* (273) wqlist ::= nm eidlist_opt AS LP select RP */ +- { 197, -8 }, /* (274) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ +- { 144, -1 }, /* (275) input ::= cmdlist */ +- { 145, -2 }, /* (276) cmdlist ::= cmdlist ecmd */ +- { 145, -1 }, /* (277) cmdlist ::= ecmd */ +- { 146, -1 }, /* (278) ecmd ::= SEMI */ +- { 146, -3 }, /* (279) ecmd ::= explain cmdx SEMI */ +- { 147, 0 }, /* (280) explain ::= */ +- { 151, 0 }, /* (281) trans_opt ::= */ +- { 151, -1 }, /* (282) trans_opt ::= TRANSACTION */ +- { 151, -2 }, /* (283) trans_opt ::= TRANSACTION nm */ +- { 153, -1 }, /* (284) savepoint_opt ::= SAVEPOINT */ +- { 153, 0 }, /* (285) savepoint_opt ::= */ +- { 149, -2 }, /* (286) cmd ::= create_table create_table_args */ +- { 160, -4 }, /* (287) columnlist ::= columnlist COMMA columnname carglist */ +- { 160, -2 }, /* (288) columnlist ::= columnname carglist */ +- { 152, -1 }, /* (289) nm ::= ID|INDEXED */ +- { 152, -1 }, /* (290) nm ::= STRING */ +- { 152, -1 }, /* (291) nm ::= JOIN_KW */ +- { 166, -1 }, /* (292) typetoken ::= typename */ +- { 167, -1 }, /* (293) typename ::= ID|STRING */ +- { 168, -1 }, /* (294) signed ::= plus_num */ +- { 168, -1 }, /* (295) signed ::= minus_num */ +- { 165, -2 }, /* (296) carglist ::= carglist ccons */ +- { 165, 0 }, /* (297) carglist ::= */ +- { 172, -2 }, /* (298) ccons ::= NULL onconf */ +- { 161, -2 }, /* (299) conslist_opt ::= COMMA conslist */ +- { 184, -3 }, /* (300) conslist ::= conslist tconscomma tcons */ +- { 184, -1 }, /* (301) conslist ::= tcons */ +- { 185, 0 }, /* (302) tconscomma ::= */ +- { 189, -1 }, /* (303) defer_subclause_opt ::= defer_subclause */ +- { 191, -1 }, /* (304) resolvetype ::= raisetype */ +- { 195, -1 }, /* (305) selectnowith ::= oneselect */ +- { 196, -1 }, /* (306) oneselect ::= values */ +- { 210, -2 }, /* (307) sclp ::= selcollist COMMA */ +- { 211, -1 }, /* (308) as ::= ID|STRING */ +- { 174, -1 }, /* (309) expr ::= term */ +- { 223, -1 }, /* (310) likeop ::= LIKE_KW|MATCH */ +- { 209, -1 }, /* (311) exprlist ::= nexprlist */ +- { 232, -1 }, /* (312) nmnum ::= plus_num */ +- { 232, -1 }, /* (313) nmnum ::= nm */ +- { 232, -1 }, /* (314) nmnum ::= ON */ +- { 232, -1 }, /* (315) nmnum ::= DELETE */ +- { 232, -1 }, /* (316) nmnum ::= DEFAULT */ +- { 169, -1 }, /* (317) plus_num ::= INTEGER|FLOAT */ +- { 237, 0 }, /* (318) foreach_clause ::= */ +- { 237, -3 }, /* (319) foreach_clause ::= FOR EACH ROW */ +- { 240, -1 }, /* (320) trnm ::= nm */ +- { 241, 0 }, /* (321) tridxby ::= */ +- { 242, -1 }, /* (322) database_kw_opt ::= DATABASE */ +- { 242, 0 }, /* (323) database_kw_opt ::= */ +- { 245, 0 }, /* (324) kwcolumn_opt ::= */ +- { 245, -1 }, /* (325) kwcolumn_opt ::= COLUMNKW */ +- { 247, -1 }, /* (326) vtabarglist ::= vtabarg */ +- { 247, -3 }, /* (327) vtabarglist ::= vtabarglist COMMA vtabarg */ +- { 248, -2 }, /* (328) vtabarg ::= vtabarg vtabargtoken */ +- { 251, 0 }, /* (329) anylist ::= */ +- { 251, -4 }, /* (330) anylist ::= anylist LP anylist RP */ +- { 251, -2 }, /* (331) anylist ::= anylist ANY */ +- { 219, 0 }, /* (332) with ::= */ ++ { 159, -1 }, /* (0) explain ::= EXPLAIN */ ++ { 159, -3 }, /* (1) explain ::= EXPLAIN QUERY PLAN */ ++ { 158, -1 }, /* (2) cmdx ::= cmd */ ++ { 160, -3 }, /* (3) cmd ::= BEGIN transtype trans_opt */ ++ { 161, 0 }, /* (4) transtype ::= */ ++ { 161, -1 }, /* (5) transtype ::= DEFERRED */ ++ { 161, -1 }, /* (6) transtype ::= IMMEDIATE */ ++ { 161, -1 }, /* (7) transtype ::= EXCLUSIVE */ ++ { 160, -2 }, /* (8) cmd ::= COMMIT|END trans_opt */ ++ { 160, -2 }, /* (9) cmd ::= ROLLBACK trans_opt */ ++ { 160, -2 }, /* (10) cmd ::= SAVEPOINT nm */ ++ { 160, -3 }, /* (11) cmd ::= RELEASE savepoint_opt nm */ ++ { 160, -5 }, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */ ++ { 165, -6 }, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */ ++ { 167, -1 }, /* (14) createkw ::= CREATE */ ++ { 169, 0 }, /* (15) ifnotexists ::= */ ++ { 169, -3 }, /* (16) ifnotexists ::= IF NOT EXISTS */ ++ { 168, -1 }, /* (17) temp ::= TEMP */ ++ { 168, 0 }, /* (18) temp ::= */ ++ { 166, -5 }, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_options */ ++ { 166, -2 }, /* (20) create_table_args ::= AS select */ ++ { 173, 0 }, /* (21) table_options ::= */ ++ { 173, -2 }, /* (22) table_options ::= WITHOUT nm */ ++ { 175, -2 }, /* (23) columnname ::= nm typetoken */ ++ { 177, 0 }, /* (24) typetoken ::= */ ++ { 177, -4 }, /* (25) typetoken ::= typename LP signed RP */ ++ { 177, -6 }, /* (26) typetoken ::= typename LP signed COMMA signed RP */ ++ { 178, -2 }, /* (27) typename ::= typename ID|STRING */ ++ { 182, 0 }, /* (28) scanpt ::= */ ++ { 183, -2 }, /* (29) ccons ::= CONSTRAINT nm */ ++ { 183, -4 }, /* (30) ccons ::= DEFAULT scanpt term scanpt */ ++ { 183, -4 }, /* (31) ccons ::= DEFAULT LP expr RP */ ++ { 183, -4 }, /* (32) ccons ::= DEFAULT PLUS term scanpt */ ++ { 183, -4 }, /* (33) ccons ::= DEFAULT MINUS term scanpt */ ++ { 183, -3 }, /* (34) ccons ::= DEFAULT scanpt ID|INDEXED */ ++ { 183, -3 }, /* (35) ccons ::= NOT NULL onconf */ ++ { 183, -5 }, /* (36) ccons ::= PRIMARY KEY sortorder onconf autoinc */ ++ { 183, -2 }, /* (37) ccons ::= UNIQUE onconf */ ++ { 183, -4 }, /* (38) ccons ::= CHECK LP expr RP */ ++ { 183, -4 }, /* (39) ccons ::= REFERENCES nm eidlist_opt refargs */ ++ { 183, -1 }, /* (40) ccons ::= defer_subclause */ ++ { 183, -2 }, /* (41) ccons ::= COLLATE ID|STRING */ ++ { 188, 0 }, /* (42) autoinc ::= */ ++ { 188, -1 }, /* (43) autoinc ::= AUTOINCR */ ++ { 190, 0 }, /* (44) refargs ::= */ ++ { 190, -2 }, /* (45) refargs ::= refargs refarg */ ++ { 192, -2 }, /* (46) refarg ::= MATCH nm */ ++ { 192, -3 }, /* (47) refarg ::= ON INSERT refact */ ++ { 192, -3 }, /* (48) refarg ::= ON DELETE refact */ ++ { 192, -3 }, /* (49) refarg ::= ON UPDATE refact */ ++ { 193, -2 }, /* (50) refact ::= SET NULL */ ++ { 193, -2 }, /* (51) refact ::= SET DEFAULT */ ++ { 193, -1 }, /* (52) refact ::= CASCADE */ ++ { 193, -1 }, /* (53) refact ::= RESTRICT */ ++ { 193, -2 }, /* (54) refact ::= NO ACTION */ ++ { 191, -3 }, /* (55) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ ++ { 191, -2 }, /* (56) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ ++ { 194, 0 }, /* (57) init_deferred_pred_opt ::= */ ++ { 194, -2 }, /* (58) init_deferred_pred_opt ::= INITIALLY DEFERRED */ ++ { 194, -2 }, /* (59) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ ++ { 172, 0 }, /* (60) conslist_opt ::= */ ++ { 196, -1 }, /* (61) tconscomma ::= COMMA */ ++ { 197, -2 }, /* (62) tcons ::= CONSTRAINT nm */ ++ { 197, -7 }, /* (63) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ ++ { 197, -5 }, /* (64) tcons ::= UNIQUE LP sortlist RP onconf */ ++ { 197, -5 }, /* (65) tcons ::= CHECK LP expr RP onconf */ ++ { 197, -10 }, /* (66) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ ++ { 200, 0 }, /* (67) defer_subclause_opt ::= */ ++ { 186, 0 }, /* (68) onconf ::= */ ++ { 186, -3 }, /* (69) onconf ::= ON CONFLICT resolvetype */ ++ { 201, 0 }, /* (70) orconf ::= */ ++ { 201, -2 }, /* (71) orconf ::= OR resolvetype */ ++ { 202, -1 }, /* (72) resolvetype ::= IGNORE */ ++ { 202, -1 }, /* (73) resolvetype ::= REPLACE */ ++ { 160, -4 }, /* (74) cmd ::= DROP TABLE ifexists fullname */ ++ { 204, -2 }, /* (75) ifexists ::= IF EXISTS */ ++ { 204, 0 }, /* (76) ifexists ::= */ ++ { 160, -9 }, /* (77) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ ++ { 160, -4 }, /* (78) cmd ::= DROP VIEW ifexists fullname */ ++ { 160, -1 }, /* (79) cmd ::= select */ ++ { 174, -3 }, /* (80) select ::= WITH wqlist selectnowith */ ++ { 174, -4 }, /* (81) select ::= WITH RECURSIVE wqlist selectnowith */ ++ { 174, -1 }, /* (82) select ::= selectnowith */ ++ { 206, -3 }, /* (83) selectnowith ::= selectnowith multiselect_op oneselect */ ++ { 209, -1 }, /* (84) multiselect_op ::= UNION */ ++ { 209, -2 }, /* (85) multiselect_op ::= UNION ALL */ ++ { 209, -1 }, /* (86) multiselect_op ::= EXCEPT|INTERSECT */ ++ { 207, -9 }, /* (87) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ ++ { 207, -10 }, /* (88) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ ++ { 219, -4 }, /* (89) values ::= VALUES LP nexprlist RP */ ++ { 219, -5 }, /* (90) values ::= values COMMA LP nexprlist RP */ ++ { 210, -1 }, /* (91) distinct ::= DISTINCT */ ++ { 210, -1 }, /* (92) distinct ::= ALL */ ++ { 210, 0 }, /* (93) distinct ::= */ ++ { 221, 0 }, /* (94) sclp ::= */ ++ { 211, -5 }, /* (95) selcollist ::= sclp scanpt expr scanpt as */ ++ { 211, -3 }, /* (96) selcollist ::= sclp scanpt STAR */ ++ { 211, -5 }, /* (97) selcollist ::= sclp scanpt nm DOT STAR */ ++ { 222, -2 }, /* (98) as ::= AS nm */ ++ { 222, 0 }, /* (99) as ::= */ ++ { 212, 0 }, /* (100) from ::= */ ++ { 212, -2 }, /* (101) from ::= FROM seltablist */ ++ { 224, -2 }, /* (102) stl_prefix ::= seltablist joinop */ ++ { 224, 0 }, /* (103) stl_prefix ::= */ ++ { 223, -7 }, /* (104) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ ++ { 223, -9 }, /* (105) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */ ++ { 223, -7 }, /* (106) seltablist ::= stl_prefix LP select RP as on_opt using_opt */ ++ { 223, -7 }, /* (107) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ ++ { 170, 0 }, /* (108) dbnm ::= */ ++ { 170, -2 }, /* (109) dbnm ::= DOT nm */ ++ { 205, -1 }, /* (110) fullname ::= nm */ ++ { 205, -3 }, /* (111) fullname ::= nm DOT nm */ ++ { 230, -1 }, /* (112) xfullname ::= nm */ ++ { 230, -3 }, /* (113) xfullname ::= nm DOT nm */ ++ { 230, -5 }, /* (114) xfullname ::= nm DOT nm AS nm */ ++ { 230, -3 }, /* (115) xfullname ::= nm AS nm */ ++ { 225, -1 }, /* (116) joinop ::= COMMA|JOIN */ ++ { 225, -2 }, /* (117) joinop ::= JOIN_KW JOIN */ ++ { 225, -3 }, /* (118) joinop ::= JOIN_KW nm JOIN */ ++ { 225, -4 }, /* (119) joinop ::= JOIN_KW nm nm JOIN */ ++ { 227, -2 }, /* (120) on_opt ::= ON expr */ ++ { 227, 0 }, /* (121) on_opt ::= */ ++ { 226, 0 }, /* (122) indexed_opt ::= */ ++ { 226, -3 }, /* (123) indexed_opt ::= INDEXED BY nm */ ++ { 226, -2 }, /* (124) indexed_opt ::= NOT INDEXED */ ++ { 228, -4 }, /* (125) using_opt ::= USING LP idlist RP */ ++ { 228, 0 }, /* (126) using_opt ::= */ ++ { 216, 0 }, /* (127) orderby_opt ::= */ ++ { 216, -3 }, /* (128) orderby_opt ::= ORDER BY sortlist */ ++ { 198, -4 }, /* (129) sortlist ::= sortlist COMMA expr sortorder */ ++ { 198, -2 }, /* (130) sortlist ::= expr sortorder */ ++ { 187, -1 }, /* (131) sortorder ::= ASC */ ++ { 187, -1 }, /* (132) sortorder ::= DESC */ ++ { 187, 0 }, /* (133) sortorder ::= */ ++ { 214, 0 }, /* (134) groupby_opt ::= */ ++ { 214, -3 }, /* (135) groupby_opt ::= GROUP BY nexprlist */ ++ { 215, 0 }, /* (136) having_opt ::= */ ++ { 215, -2 }, /* (137) having_opt ::= HAVING expr */ ++ { 217, 0 }, /* (138) limit_opt ::= */ ++ { 217, -2 }, /* (139) limit_opt ::= LIMIT expr */ ++ { 217, -4 }, /* (140) limit_opt ::= LIMIT expr OFFSET expr */ ++ { 217, -4 }, /* (141) limit_opt ::= LIMIT expr COMMA expr */ ++ { 160, -6 }, /* (142) cmd ::= with DELETE FROM xfullname indexed_opt where_opt */ ++ { 213, 0 }, /* (143) where_opt ::= */ ++ { 213, -2 }, /* (144) where_opt ::= WHERE expr */ ++ { 160, -8 }, /* (145) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */ ++ { 233, -5 }, /* (146) setlist ::= setlist COMMA nm EQ expr */ ++ { 233, -7 }, /* (147) setlist ::= setlist COMMA LP idlist RP EQ expr */ ++ { 233, -3 }, /* (148) setlist ::= nm EQ expr */ ++ { 233, -5 }, /* (149) setlist ::= LP idlist RP EQ expr */ ++ { 160, -7 }, /* (150) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ ++ { 160, -7 }, /* (151) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */ ++ { 236, 0 }, /* (152) upsert ::= */ ++ { 236, -11 }, /* (153) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */ ++ { 236, -8 }, /* (154) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */ ++ { 236, -4 }, /* (155) upsert ::= ON CONFLICT DO NOTHING */ ++ { 234, -2 }, /* (156) insert_cmd ::= INSERT orconf */ ++ { 234, -1 }, /* (157) insert_cmd ::= REPLACE */ ++ { 235, 0 }, /* (158) idlist_opt ::= */ ++ { 235, -3 }, /* (159) idlist_opt ::= LP idlist RP */ ++ { 231, -3 }, /* (160) idlist ::= idlist COMMA nm */ ++ { 231, -1 }, /* (161) idlist ::= nm */ ++ { 185, -3 }, /* (162) expr ::= LP expr RP */ ++ { 185, -1 }, /* (163) expr ::= ID|INDEXED */ ++ { 185, -1 }, /* (164) expr ::= JOIN_KW */ ++ { 185, -3 }, /* (165) expr ::= nm DOT nm */ ++ { 185, -5 }, /* (166) expr ::= nm DOT nm DOT nm */ ++ { 184, -1 }, /* (167) term ::= NULL|FLOAT|BLOB */ ++ { 184, -1 }, /* (168) term ::= STRING */ ++ { 184, -1 }, /* (169) term ::= INTEGER */ ++ { 185, -1 }, /* (170) expr ::= VARIABLE */ ++ { 185, -3 }, /* (171) expr ::= expr COLLATE ID|STRING */ ++ { 185, -6 }, /* (172) expr ::= CAST LP expr AS typetoken RP */ ++ { 185, -5 }, /* (173) expr ::= ID|INDEXED LP distinct exprlist RP */ ++ { 185, -4 }, /* (174) expr ::= ID|INDEXED LP STAR RP */ ++ { 185, -6 }, /* (175) expr ::= ID|INDEXED LP distinct exprlist RP over_clause */ ++ { 185, -5 }, /* (176) expr ::= ID|INDEXED LP STAR RP over_clause */ ++ { 184, -1 }, /* (177) term ::= CTIME_KW */ ++ { 185, -5 }, /* (178) expr ::= LP nexprlist COMMA expr RP */ ++ { 185, -3 }, /* (179) expr ::= expr AND expr */ ++ { 185, -3 }, /* (180) expr ::= expr OR expr */ ++ { 185, -3 }, /* (181) expr ::= expr LT|GT|GE|LE expr */ ++ { 185, -3 }, /* (182) expr ::= expr EQ|NE expr */ ++ { 185, -3 }, /* (183) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ ++ { 185, -3 }, /* (184) expr ::= expr PLUS|MINUS expr */ ++ { 185, -3 }, /* (185) expr ::= expr STAR|SLASH|REM expr */ ++ { 185, -3 }, /* (186) expr ::= expr CONCAT expr */ ++ { 238, -2 }, /* (187) likeop ::= NOT LIKE_KW|MATCH */ ++ { 185, -3 }, /* (188) expr ::= expr likeop expr */ ++ { 185, -5 }, /* (189) expr ::= expr likeop expr ESCAPE expr */ ++ { 185, -2 }, /* (190) expr ::= expr ISNULL|NOTNULL */ ++ { 185, -3 }, /* (191) expr ::= expr NOT NULL */ ++ { 185, -3 }, /* (192) expr ::= expr IS expr */ ++ { 185, -4 }, /* (193) expr ::= expr IS NOT expr */ ++ { 185, -2 }, /* (194) expr ::= NOT expr */ ++ { 185, -2 }, /* (195) expr ::= BITNOT expr */ ++ { 185, -2 }, /* (196) expr ::= PLUS|MINUS expr */ ++ { 239, -1 }, /* (197) between_op ::= BETWEEN */ ++ { 239, -2 }, /* (198) between_op ::= NOT BETWEEN */ ++ { 185, -5 }, /* (199) expr ::= expr between_op expr AND expr */ ++ { 240, -1 }, /* (200) in_op ::= IN */ ++ { 240, -2 }, /* (201) in_op ::= NOT IN */ ++ { 185, -5 }, /* (202) expr ::= expr in_op LP exprlist RP */ ++ { 185, -3 }, /* (203) expr ::= LP select RP */ ++ { 185, -5 }, /* (204) expr ::= expr in_op LP select RP */ ++ { 185, -5 }, /* (205) expr ::= expr in_op nm dbnm paren_exprlist */ ++ { 185, -4 }, /* (206) expr ::= EXISTS LP select RP */ ++ { 185, -5 }, /* (207) expr ::= CASE case_operand case_exprlist case_else END */ ++ { 243, -5 }, /* (208) case_exprlist ::= case_exprlist WHEN expr THEN expr */ ++ { 243, -4 }, /* (209) case_exprlist ::= WHEN expr THEN expr */ ++ { 244, -2 }, /* (210) case_else ::= ELSE expr */ ++ { 244, 0 }, /* (211) case_else ::= */ ++ { 242, -1 }, /* (212) case_operand ::= expr */ ++ { 242, 0 }, /* (213) case_operand ::= */ ++ { 229, 0 }, /* (214) exprlist ::= */ ++ { 220, -3 }, /* (215) nexprlist ::= nexprlist COMMA expr */ ++ { 220, -1 }, /* (216) nexprlist ::= expr */ ++ { 241, 0 }, /* (217) paren_exprlist ::= */ ++ { 241, -3 }, /* (218) paren_exprlist ::= LP exprlist RP */ ++ { 160, -12 }, /* (219) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ ++ { 245, -1 }, /* (220) uniqueflag ::= UNIQUE */ ++ { 245, 0 }, /* (221) uniqueflag ::= */ ++ { 189, 0 }, /* (222) eidlist_opt ::= */ ++ { 189, -3 }, /* (223) eidlist_opt ::= LP eidlist RP */ ++ { 199, -5 }, /* (224) eidlist ::= eidlist COMMA nm collate sortorder */ ++ { 199, -3 }, /* (225) eidlist ::= nm collate sortorder */ ++ { 246, 0 }, /* (226) collate ::= */ ++ { 246, -2 }, /* (227) collate ::= COLLATE ID|STRING */ ++ { 160, -4 }, /* (228) cmd ::= DROP INDEX ifexists fullname */ ++ { 160, -1 }, /* (229) cmd ::= VACUUM */ ++ { 160, -2 }, /* (230) cmd ::= VACUUM nm */ ++ { 160, -3 }, /* (231) cmd ::= PRAGMA nm dbnm */ ++ { 160, -5 }, /* (232) cmd ::= PRAGMA nm dbnm EQ nmnum */ ++ { 160, -6 }, /* (233) cmd ::= PRAGMA nm dbnm LP nmnum RP */ ++ { 160, -5 }, /* (234) cmd ::= PRAGMA nm dbnm EQ minus_num */ ++ { 160, -6 }, /* (235) cmd ::= PRAGMA nm dbnm LP minus_num RP */ ++ { 180, -2 }, /* (236) plus_num ::= PLUS INTEGER|FLOAT */ ++ { 181, -2 }, /* (237) minus_num ::= MINUS INTEGER|FLOAT */ ++ { 160, -5 }, /* (238) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ ++ { 248, -11 }, /* (239) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ ++ { 250, -1 }, /* (240) trigger_time ::= BEFORE|AFTER */ ++ { 250, -2 }, /* (241) trigger_time ::= INSTEAD OF */ ++ { 250, 0 }, /* (242) trigger_time ::= */ ++ { 251, -1 }, /* (243) trigger_event ::= DELETE|INSERT */ ++ { 251, -1 }, /* (244) trigger_event ::= UPDATE */ ++ { 251, -3 }, /* (245) trigger_event ::= UPDATE OF idlist */ ++ { 253, 0 }, /* (246) when_clause ::= */ ++ { 253, -2 }, /* (247) when_clause ::= WHEN expr */ ++ { 249, -3 }, /* (248) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ ++ { 249, -2 }, /* (249) trigger_cmd_list ::= trigger_cmd SEMI */ ++ { 255, -3 }, /* (250) trnm ::= nm DOT nm */ ++ { 256, -3 }, /* (251) tridxby ::= INDEXED BY nm */ ++ { 256, -2 }, /* (252) tridxby ::= NOT INDEXED */ ++ { 254, -8 }, /* (253) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */ ++ { 254, -8 }, /* (254) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ ++ { 254, -6 }, /* (255) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ ++ { 254, -3 }, /* (256) trigger_cmd ::= scanpt select scanpt */ ++ { 185, -4 }, /* (257) expr ::= RAISE LP IGNORE RP */ ++ { 185, -6 }, /* (258) expr ::= RAISE LP raisetype COMMA nm RP */ ++ { 203, -1 }, /* (259) raisetype ::= ROLLBACK */ ++ { 203, -1 }, /* (260) raisetype ::= ABORT */ ++ { 203, -1 }, /* (261) raisetype ::= FAIL */ ++ { 160, -4 }, /* (262) cmd ::= DROP TRIGGER ifexists fullname */ ++ { 160, -6 }, /* (263) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ ++ { 160, -3 }, /* (264) cmd ::= DETACH database_kw_opt expr */ ++ { 258, 0 }, /* (265) key_opt ::= */ ++ { 258, -2 }, /* (266) key_opt ::= KEY expr */ ++ { 160, -1 }, /* (267) cmd ::= REINDEX */ ++ { 160, -3 }, /* (268) cmd ::= REINDEX nm dbnm */ ++ { 160, -1 }, /* (269) cmd ::= ANALYZE */ ++ { 160, -3 }, /* (270) cmd ::= ANALYZE nm dbnm */ ++ { 160, -6 }, /* (271) cmd ::= ALTER TABLE fullname RENAME TO nm */ ++ { 160, -7 }, /* (272) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ ++ { 259, -1 }, /* (273) add_column_fullname ::= fullname */ ++ { 160, -8 }, /* (274) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ ++ { 160, -1 }, /* (275) cmd ::= create_vtab */ ++ { 160, -4 }, /* (276) cmd ::= create_vtab LP vtabarglist RP */ ++ { 261, -8 }, /* (277) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ ++ { 263, 0 }, /* (278) vtabarg ::= */ ++ { 264, -1 }, /* (279) vtabargtoken ::= ANY */ ++ { 264, -3 }, /* (280) vtabargtoken ::= lp anylist RP */ ++ { 265, -1 }, /* (281) lp ::= LP */ ++ { 232, -2 }, /* (282) with ::= WITH wqlist */ ++ { 232, -3 }, /* (283) with ::= WITH RECURSIVE wqlist */ ++ { 208, -6 }, /* (284) wqlist ::= nm eidlist_opt AS LP select RP */ ++ { 208, -8 }, /* (285) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ ++ { 267, -1 }, /* (286) windowdefn_list ::= windowdefn */ ++ { 267, -3 }, /* (287) windowdefn_list ::= windowdefn_list COMMA windowdefn */ ++ { 268, -3 }, /* (288) windowdefn ::= nm AS window */ ++ { 269, -5 }, /* (289) window ::= LP part_opt orderby_opt frame_opt RP */ ++ { 271, -3 }, /* (290) part_opt ::= PARTITION BY nexprlist */ ++ { 271, 0 }, /* (291) part_opt ::= */ ++ { 270, 0 }, /* (292) frame_opt ::= */ ++ { 270, -2 }, /* (293) frame_opt ::= range_or_rows frame_bound_s */ ++ { 270, -5 }, /* (294) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e */ ++ { 273, -1 }, /* (295) range_or_rows ::= RANGE */ ++ { 273, -1 }, /* (296) range_or_rows ::= ROWS */ ++ { 275, -1 }, /* (297) frame_bound_s ::= frame_bound */ ++ { 275, -2 }, /* (298) frame_bound_s ::= UNBOUNDED PRECEDING */ ++ { 276, -1 }, /* (299) frame_bound_e ::= frame_bound */ ++ { 276, -2 }, /* (300) frame_bound_e ::= UNBOUNDED FOLLOWING */ ++ { 274, -2 }, /* (301) frame_bound ::= expr PRECEDING */ ++ { 274, -2 }, /* (302) frame_bound ::= CURRENT ROW */ ++ { 274, -2 }, /* (303) frame_bound ::= expr FOLLOWING */ ++ { 218, -2 }, /* (304) window_clause ::= WINDOW windowdefn_list */ ++ { 237, -3 }, /* (305) over_clause ::= filter_opt OVER window */ ++ { 237, -3 }, /* (306) over_clause ::= filter_opt OVER nm */ ++ { 272, 0 }, /* (307) filter_opt ::= */ ++ { 272, -5 }, /* (308) filter_opt ::= FILTER LP WHERE expr RP */ ++ { 155, -1 }, /* (309) input ::= cmdlist */ ++ { 156, -2 }, /* (310) cmdlist ::= cmdlist ecmd */ ++ { 156, -1 }, /* (311) cmdlist ::= ecmd */ ++ { 157, -1 }, /* (312) ecmd ::= SEMI */ ++ { 157, -2 }, /* (313) ecmd ::= cmdx SEMI */ ++ { 157, -2 }, /* (314) ecmd ::= explain cmdx */ ++ { 162, 0 }, /* (315) trans_opt ::= */ ++ { 162, -1 }, /* (316) trans_opt ::= TRANSACTION */ ++ { 162, -2 }, /* (317) trans_opt ::= TRANSACTION nm */ ++ { 164, -1 }, /* (318) savepoint_opt ::= SAVEPOINT */ ++ { 164, 0 }, /* (319) savepoint_opt ::= */ ++ { 160, -2 }, /* (320) cmd ::= create_table create_table_args */ ++ { 171, -4 }, /* (321) columnlist ::= columnlist COMMA columnname carglist */ ++ { 171, -2 }, /* (322) columnlist ::= columnname carglist */ ++ { 163, -1 }, /* (323) nm ::= ID|INDEXED */ ++ { 163, -1 }, /* (324) nm ::= STRING */ ++ { 163, -1 }, /* (325) nm ::= JOIN_KW */ ++ { 177, -1 }, /* (326) typetoken ::= typename */ ++ { 178, -1 }, /* (327) typename ::= ID|STRING */ ++ { 179, -1 }, /* (328) signed ::= plus_num */ ++ { 179, -1 }, /* (329) signed ::= minus_num */ ++ { 176, -2 }, /* (330) carglist ::= carglist ccons */ ++ { 176, 0 }, /* (331) carglist ::= */ ++ { 183, -2 }, /* (332) ccons ::= NULL onconf */ ++ { 172, -2 }, /* (333) conslist_opt ::= COMMA conslist */ ++ { 195, -3 }, /* (334) conslist ::= conslist tconscomma tcons */ ++ { 195, -1 }, /* (335) conslist ::= tcons */ ++ { 196, 0 }, /* (336) tconscomma ::= */ ++ { 200, -1 }, /* (337) defer_subclause_opt ::= defer_subclause */ ++ { 202, -1 }, /* (338) resolvetype ::= raisetype */ ++ { 206, -1 }, /* (339) selectnowith ::= oneselect */ ++ { 207, -1 }, /* (340) oneselect ::= values */ ++ { 221, -2 }, /* (341) sclp ::= selcollist COMMA */ ++ { 222, -1 }, /* (342) as ::= ID|STRING */ ++ { 185, -1 }, /* (343) expr ::= term */ ++ { 238, -1 }, /* (344) likeop ::= LIKE_KW|MATCH */ ++ { 229, -1 }, /* (345) exprlist ::= nexprlist */ ++ { 247, -1 }, /* (346) nmnum ::= plus_num */ ++ { 247, -1 }, /* (347) nmnum ::= nm */ ++ { 247, -1 }, /* (348) nmnum ::= ON */ ++ { 247, -1 }, /* (349) nmnum ::= DELETE */ ++ { 247, -1 }, /* (350) nmnum ::= DEFAULT */ ++ { 180, -1 }, /* (351) plus_num ::= INTEGER|FLOAT */ ++ { 252, 0 }, /* (352) foreach_clause ::= */ ++ { 252, -3 }, /* (353) foreach_clause ::= FOR EACH ROW */ ++ { 255, -1 }, /* (354) trnm ::= nm */ ++ { 256, 0 }, /* (355) tridxby ::= */ ++ { 257, -1 }, /* (356) database_kw_opt ::= DATABASE */ ++ { 257, 0 }, /* (357) database_kw_opt ::= */ ++ { 260, 0 }, /* (358) kwcolumn_opt ::= */ ++ { 260, -1 }, /* (359) kwcolumn_opt ::= COLUMNKW */ ++ { 262, -1 }, /* (360) vtabarglist ::= vtabarg */ ++ { 262, -3 }, /* (361) vtabarglist ::= vtabarglist COMMA vtabarg */ ++ { 263, -2 }, /* (362) vtabarg ::= vtabarg vtabargtoken */ ++ { 266, 0 }, /* (363) anylist ::= */ ++ { 266, -4 }, /* (364) anylist ::= anylist LP anylist RP */ ++ { 266, -2 }, /* (365) anylist ::= anylist ANY */ ++ { 232, 0 }, /* (366) with ::= */ + }; + + static void yy_accept(yyParser*); /* Forward Declaration */ +@@ -142193,17 +149466,18 @@ + ** only called from one place, optimizing compilers will in-line it, which + ** means that the extra parameters have no performance impact. + */ +-static void yy_reduce( ++static YYACTIONTYPE yy_reduce( + yyParser *yypParser, /* The parser */ + unsigned int yyruleno, /* Number of the rule by which to reduce */ + int yyLookahead, /* Lookahead token, or YYNOCODE if none */ + sqlite3ParserTOKENTYPE yyLookaheadToken /* Value of the lookahead token */ ++ sqlite3ParserCTX_PDECL /* %extra_context */ + ){ + int yygoto; /* The next state */ +- int yyact; /* The next action */ ++ YYACTIONTYPE yyact; /* The next action */ + yyStackEntry *yymsp; /* The top of the parser's stack */ + int yysize; /* Amount to pop the stack */ +- sqlite3ParserARG_FETCH; ++ sqlite3ParserARG_FETCH + (void)yyLookahead; + (void)yyLookaheadToken; + yymsp = yypParser->yytos; +@@ -142234,13 +149508,19 @@ + #if YYSTACKDEPTH>0 + if( yypParser->yytos>=yypParser->yystackEnd ){ + yyStackOverflow(yypParser); +- return; ++ /* The call to yyStackOverflow() above pops the stack until it is ++ ** empty, causing the main parser loop to exit. So the return value ++ ** is never used and does not matter. */ ++ return 0; + } + #else + if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){ + if( yyGrowStack(yypParser) ){ + yyStackOverflow(yypParser); +- return; ++ /* The call to yyStackOverflow() above pops the stack until it is ++ ** empty, causing the main parser loop to exit. So the return value ++ ** is never used and does not matter. */ ++ return 0; + } + yymsp = yypParser->yytos; + } +@@ -142268,15 +149548,15 @@ + { sqlite3FinishCoding(pParse); } + break; + case 3: /* cmd ::= BEGIN transtype trans_opt */ +-{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy4);} ++{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy70);} + break; + case 4: /* transtype ::= */ +-{yymsp[1].minor.yy4 = TK_DEFERRED;} ++{yymsp[1].minor.yy70 = TK_DEFERRED;} + break; + case 5: /* transtype ::= DEFERRED */ + case 6: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==6); + case 7: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7); +-{yymsp[0].minor.yy4 = yymsp[0].major; /*A-overwrites-X*/} ++{yymsp[0].minor.yy70 = yymsp[0].major; /*A-overwrites-X*/} + break; + case 8: /* cmd ::= COMMIT|END trans_opt */ + case 9: /* cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==9); +@@ -142299,7 +149579,7 @@ + break; + case 13: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */ + { +- sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy4,0,0,yymsp[-2].minor.yy4); ++ sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy70,0,0,yymsp[-2].minor.yy70); + } + break; + case 14: /* createkw ::= CREATE */ +@@ -142312,34 +149592,34 @@ + case 57: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==57); + case 67: /* defer_subclause_opt ::= */ yytestcase(yyruleno==67); + case 76: /* ifexists ::= */ yytestcase(yyruleno==76); +- case 92: /* distinct ::= */ yytestcase(yyruleno==92); +- case 216: /* collate ::= */ yytestcase(yyruleno==216); +-{yymsp[1].minor.yy4 = 0;} ++ case 93: /* distinct ::= */ yytestcase(yyruleno==93); ++ case 226: /* collate ::= */ yytestcase(yyruleno==226); ++{yymsp[1].minor.yy70 = 0;} + break; + case 16: /* ifnotexists ::= IF NOT EXISTS */ +-{yymsp[-2].minor.yy4 = 1;} ++{yymsp[-2].minor.yy70 = 1;} + break; + case 17: /* temp ::= TEMP */ + case 43: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==43); +-{yymsp[0].minor.yy4 = 1;} ++{yymsp[0].minor.yy70 = 1;} + break; + case 19: /* create_table_args ::= LP columnlist conslist_opt RP table_options */ + { +- sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy4,0); ++ sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy70,0); + } + break; + case 20: /* create_table_args ::= AS select */ + { +- sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy387); +- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy387); ++ sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy489); ++ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy489); + } + break; + case 22: /* table_options ::= WITHOUT nm */ + { + if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){ +- yymsp[-1].minor.yy4 = TF_WithoutRowid | TF_NoVisibleRowid; ++ yymsp[-1].minor.yy70 = TF_WithoutRowid | TF_NoVisibleRowid; + }else{ +- yymsp[-1].minor.yy4 = 0; ++ yymsp[-1].minor.yy70 = 0; + sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z); + } + } +@@ -142349,7 +149629,7 @@ + break; + case 24: /* typetoken ::= */ + case 60: /* conslist_opt ::= */ yytestcase(yyruleno==60); +- case 98: /* as ::= */ yytestcase(yyruleno==98); ++ case 99: /* as ::= */ yytestcase(yyruleno==99); + {yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = 0;} + break; + case 25: /* typetoken ::= typename LP signed RP */ +@@ -142368,7 +149648,7 @@ + case 28: /* scanpt ::= */ + { + assert( yyLookahead!=YYNOCODE ); +- yymsp[1].minor.yy336 = yyLookaheadToken.z; ++ yymsp[1].minor.yy392 = yyLookaheadToken.z; + } + break; + case 29: /* ccons ::= CONSTRAINT nm */ +@@ -142376,18 +149656,18 @@ + {pParse->constraintName = yymsp[0].minor.yy0;} + break; + case 30: /* ccons ::= DEFAULT scanpt term scanpt */ +-{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy314,yymsp[-2].minor.yy336,yymsp[0].minor.yy336);} ++{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy18,yymsp[-2].minor.yy392,yymsp[0].minor.yy392);} + break; + case 31: /* ccons ::= DEFAULT LP expr RP */ +-{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy314,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);} ++{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy18,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);} + break; + case 32: /* ccons ::= DEFAULT PLUS term scanpt */ +-{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy314,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy336);} ++{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy18,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy392);} + break; + case 33: /* ccons ::= DEFAULT MINUS term scanpt */ + { +- Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[-1].minor.yy314, 0); +- sqlite3AddDefaultValue(pParse,p,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy336); ++ Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[-1].minor.yy18, 0); ++ sqlite3AddDefaultValue(pParse,p,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy392); + } + break; + case 34: /* ccons ::= DEFAULT scanpt ID|INDEXED */ +@@ -142397,174 +149677,174 @@ + sqlite3ExprIdToTrueFalse(p); + testcase( p->op==TK_TRUEFALSE && sqlite3ExprTruthValue(p) ); + } +- sqlite3AddDefaultValue(pParse,p,yymsp[0].minor.yy0.z,yymsp[0].minor.yy0.z+yymsp[0].minor.yy0.n); ++ sqlite3AddDefaultValue(pParse,p,yymsp[0].minor.yy0.z,yymsp[0].minor.yy0.z+yymsp[0].minor.yy0.n); + } + break; + case 35: /* ccons ::= NOT NULL onconf */ +-{sqlite3AddNotNull(pParse, yymsp[0].minor.yy4);} ++{sqlite3AddNotNull(pParse, yymsp[0].minor.yy70);} + break; + case 36: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ +-{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy4,yymsp[0].minor.yy4,yymsp[-2].minor.yy4);} ++{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy70,yymsp[0].minor.yy70,yymsp[-2].minor.yy70);} + break; + case 37: /* ccons ::= UNIQUE onconf */ +-{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy4,0,0,0,0, ++{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy70,0,0,0,0, + SQLITE_IDXTYPE_UNIQUE);} + break; + case 38: /* ccons ::= CHECK LP expr RP */ +-{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy314);} ++{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy18);} + break; + case 39: /* ccons ::= REFERENCES nm eidlist_opt refargs */ +-{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy322,yymsp[0].minor.yy4);} ++{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy420,yymsp[0].minor.yy70);} + break; + case 40: /* ccons ::= defer_subclause */ +-{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy4);} ++{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy70);} + break; + case 41: /* ccons ::= COLLATE ID|STRING */ + {sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);} + break; + case 44: /* refargs ::= */ +-{ yymsp[1].minor.yy4 = OE_None*0x0101; /* EV: R-19803-45884 */} ++{ yymsp[1].minor.yy70 = OE_None*0x0101; /* EV: R-19803-45884 */} + break; + case 45: /* refargs ::= refargs refarg */ +-{ yymsp[-1].minor.yy4 = (yymsp[-1].minor.yy4 & ~yymsp[0].minor.yy215.mask) | yymsp[0].minor.yy215.value; } ++{ yymsp[-1].minor.yy70 = (yymsp[-1].minor.yy70 & ~yymsp[0].minor.yy111.mask) | yymsp[0].minor.yy111.value; } + break; + case 46: /* refarg ::= MATCH nm */ +-{ yymsp[-1].minor.yy215.value = 0; yymsp[-1].minor.yy215.mask = 0x000000; } ++{ yymsp[-1].minor.yy111.value = 0; yymsp[-1].minor.yy111.mask = 0x000000; } + break; + case 47: /* refarg ::= ON INSERT refact */ +-{ yymsp[-2].minor.yy215.value = 0; yymsp[-2].minor.yy215.mask = 0x000000; } ++{ yymsp[-2].minor.yy111.value = 0; yymsp[-2].minor.yy111.mask = 0x000000; } + break; + case 48: /* refarg ::= ON DELETE refact */ +-{ yymsp[-2].minor.yy215.value = yymsp[0].minor.yy4; yymsp[-2].minor.yy215.mask = 0x0000ff; } ++{ yymsp[-2].minor.yy111.value = yymsp[0].minor.yy70; yymsp[-2].minor.yy111.mask = 0x0000ff; } + break; + case 49: /* refarg ::= ON UPDATE refact */ +-{ yymsp[-2].minor.yy215.value = yymsp[0].minor.yy4<<8; yymsp[-2].minor.yy215.mask = 0x00ff00; } ++{ yymsp[-2].minor.yy111.value = yymsp[0].minor.yy70<<8; yymsp[-2].minor.yy111.mask = 0x00ff00; } + break; + case 50: /* refact ::= SET NULL */ +-{ yymsp[-1].minor.yy4 = OE_SetNull; /* EV: R-33326-45252 */} ++{ yymsp[-1].minor.yy70 = OE_SetNull; /* EV: R-33326-45252 */} + break; + case 51: /* refact ::= SET DEFAULT */ +-{ yymsp[-1].minor.yy4 = OE_SetDflt; /* EV: R-33326-45252 */} ++{ yymsp[-1].minor.yy70 = OE_SetDflt; /* EV: R-33326-45252 */} + break; + case 52: /* refact ::= CASCADE */ +-{ yymsp[0].minor.yy4 = OE_Cascade; /* EV: R-33326-45252 */} ++{ yymsp[0].minor.yy70 = OE_Cascade; /* EV: R-33326-45252 */} + break; + case 53: /* refact ::= RESTRICT */ +-{ yymsp[0].minor.yy4 = OE_Restrict; /* EV: R-33326-45252 */} ++{ yymsp[0].minor.yy70 = OE_Restrict; /* EV: R-33326-45252 */} + break; + case 54: /* refact ::= NO ACTION */ +-{ yymsp[-1].minor.yy4 = OE_None; /* EV: R-33326-45252 */} ++{ yymsp[-1].minor.yy70 = OE_None; /* EV: R-33326-45252 */} + break; + case 55: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ +-{yymsp[-2].minor.yy4 = 0;} ++{yymsp[-2].minor.yy70 = 0;} + break; + case 56: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ + case 71: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==71); +- case 147: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==147); +-{yymsp[-1].minor.yy4 = yymsp[0].minor.yy4;} ++ case 156: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==156); ++{yymsp[-1].minor.yy70 = yymsp[0].minor.yy70;} + break; + case 58: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ + case 75: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==75); +- case 188: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==188); +- case 191: /* in_op ::= NOT IN */ yytestcase(yyruleno==191); +- case 217: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==217); +-{yymsp[-1].minor.yy4 = 1;} ++ case 198: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==198); ++ case 201: /* in_op ::= NOT IN */ yytestcase(yyruleno==201); ++ case 227: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==227); ++{yymsp[-1].minor.yy70 = 1;} + break; + case 59: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ +-{yymsp[-1].minor.yy4 = 0;} ++{yymsp[-1].minor.yy70 = 0;} + break; + case 61: /* tconscomma ::= COMMA */ + {pParse->constraintName.n = 0;} + break; + case 63: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ +-{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy322,yymsp[0].minor.yy4,yymsp[-2].minor.yy4,0);} ++{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy420,yymsp[0].minor.yy70,yymsp[-2].minor.yy70,0);} + break; + case 64: /* tcons ::= UNIQUE LP sortlist RP onconf */ +-{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy322,yymsp[0].minor.yy4,0,0,0,0, ++{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy420,yymsp[0].minor.yy70,0,0,0,0, + SQLITE_IDXTYPE_UNIQUE);} + break; + case 65: /* tcons ::= CHECK LP expr RP onconf */ +-{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy314);} ++{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy18);} + break; + case 66: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ + { +- sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy322, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy322, yymsp[-1].minor.yy4); +- sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy4); ++ sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy420, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy420, yymsp[-1].minor.yy70); ++ sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy70); + } + break; + case 68: /* onconf ::= */ + case 70: /* orconf ::= */ yytestcase(yyruleno==70); +-{yymsp[1].minor.yy4 = OE_Default;} ++{yymsp[1].minor.yy70 = OE_Default;} + break; + case 69: /* onconf ::= ON CONFLICT resolvetype */ +-{yymsp[-2].minor.yy4 = yymsp[0].minor.yy4;} ++{yymsp[-2].minor.yy70 = yymsp[0].minor.yy70;} + break; + case 72: /* resolvetype ::= IGNORE */ +-{yymsp[0].minor.yy4 = OE_Ignore;} ++{yymsp[0].minor.yy70 = OE_Ignore;} + break; + case 73: /* resolvetype ::= REPLACE */ +- case 148: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==148); +-{yymsp[0].minor.yy4 = OE_Replace;} ++ case 157: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==157); ++{yymsp[0].minor.yy70 = OE_Replace;} + break; + case 74: /* cmd ::= DROP TABLE ifexists fullname */ + { +- sqlite3DropTable(pParse, yymsp[0].minor.yy259, 0, yymsp[-1].minor.yy4); ++ sqlite3DropTable(pParse, yymsp[0].minor.yy135, 0, yymsp[-1].minor.yy70); + } + break; + case 77: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ + { +- sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy322, yymsp[0].minor.yy387, yymsp[-7].minor.yy4, yymsp[-5].minor.yy4); ++ sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy420, yymsp[0].minor.yy489, yymsp[-7].minor.yy70, yymsp[-5].minor.yy70); + } + break; + case 78: /* cmd ::= DROP VIEW ifexists fullname */ + { +- sqlite3DropTable(pParse, yymsp[0].minor.yy259, 1, yymsp[-1].minor.yy4); ++ sqlite3DropTable(pParse, yymsp[0].minor.yy135, 1, yymsp[-1].minor.yy70); + } + break; + case 79: /* cmd ::= select */ + { + SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0}; +- sqlite3Select(pParse, yymsp[0].minor.yy387, &dest); +- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy387); ++ sqlite3Select(pParse, yymsp[0].minor.yy489, &dest); ++ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy489); + } + break; + case 80: /* select ::= WITH wqlist selectnowith */ + { +- Select *p = yymsp[0].minor.yy387; ++ Select *p = yymsp[0].minor.yy489; + if( p ){ +- p->pWith = yymsp[-1].minor.yy451; ++ p->pWith = yymsp[-1].minor.yy449; + parserDoubleLinkSelect(pParse, p); + }else{ +- sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy451); ++ sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy449); + } +- yymsp[-2].minor.yy387 = p; ++ yymsp[-2].minor.yy489 = p; + } + break; + case 81: /* select ::= WITH RECURSIVE wqlist selectnowith */ + { +- Select *p = yymsp[0].minor.yy387; ++ Select *p = yymsp[0].minor.yy489; + if( p ){ +- p->pWith = yymsp[-1].minor.yy451; ++ p->pWith = yymsp[-1].minor.yy449; + parserDoubleLinkSelect(pParse, p); + }else{ +- sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy451); ++ sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy449); + } +- yymsp[-3].minor.yy387 = p; ++ yymsp[-3].minor.yy489 = p; + } + break; + case 82: /* select ::= selectnowith */ + { +- Select *p = yymsp[0].minor.yy387; ++ Select *p = yymsp[0].minor.yy489; + if( p ){ + parserDoubleLinkSelect(pParse, p); + } +- yymsp[0].minor.yy387 = p; /*A-overwrites-X*/ ++ yymsp[0].minor.yy489 = p; /*A-overwrites-X*/ + } + break; + case 83: /* selectnowith ::= selectnowith multiselect_op oneselect */ + { +- Select *pRhs = yymsp[0].minor.yy387; +- Select *pLhs = yymsp[-2].minor.yy387; ++ Select *pRhs = yymsp[0].minor.yy489; ++ Select *pLhs = yymsp[-2].minor.yy489; + if( pRhs && pRhs->pPrior ){ + SrcList *pFrom; + Token x; +@@ -142574,158 +149854,142 @@ + pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0); + } + if( pRhs ){ +- pRhs->op = (u8)yymsp[-1].minor.yy4; ++ pRhs->op = (u8)yymsp[-1].minor.yy70; + pRhs->pPrior = pLhs; + if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue; + pRhs->selFlags &= ~SF_MultiValue; +- if( yymsp[-1].minor.yy4!=TK_ALL ) pParse->hasCompound = 1; ++ if( yymsp[-1].minor.yy70!=TK_ALL ) pParse->hasCompound = 1; + }else{ + sqlite3SelectDelete(pParse->db, pLhs); + } +- yymsp[-2].minor.yy387 = pRhs; ++ yymsp[-2].minor.yy489 = pRhs; + } + break; + case 84: /* multiselect_op ::= UNION */ + case 86: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==86); +-{yymsp[0].minor.yy4 = yymsp[0].major; /*A-overwrites-OP*/} ++{yymsp[0].minor.yy70 = yymsp[0].major; /*A-overwrites-OP*/} + break; + case 85: /* multiselect_op ::= UNION ALL */ +-{yymsp[-1].minor.yy4 = TK_ALL;} ++{yymsp[-1].minor.yy70 = TK_ALL;} + break; + case 87: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ + { +-#if SELECTTRACE_ENABLED +- Token s = yymsp[-8].minor.yy0; /*A-overwrites-S*/ +-#endif +- yymsp[-8].minor.yy387 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy322,yymsp[-5].minor.yy259,yymsp[-4].minor.yy314,yymsp[-3].minor.yy322,yymsp[-2].minor.yy314,yymsp[-1].minor.yy322,yymsp[-7].minor.yy4,yymsp[0].minor.yy314); +-#if SELECTTRACE_ENABLED +- /* Populate the Select.zSelName[] string that is used to help with +- ** query planner debugging, to differentiate between multiple Select +- ** objects in a complex query. +- ** +- ** If the SELECT keyword is immediately followed by a C-style comment +- ** then extract the first few alphanumeric characters from within that +- ** comment to be the zSelName value. Otherwise, the label is #N where +- ** is an integer that is incremented with each SELECT statement seen. +- */ +- if( yymsp[-8].minor.yy387!=0 ){ +- const char *z = s.z+6; +- int i; +- sqlite3_snprintf(sizeof(yymsp[-8].minor.yy387->zSelName), yymsp[-8].minor.yy387->zSelName,"#%d",++pParse->nSelect); +- while( z[0]==' ' ) z++; +- if( z[0]=='/' && z[1]=='*' ){ +- z += 2; +- while( z[0]==' ' ) z++; +- for(i=0; sqlite3Isalnum(z[i]); i++){} +- sqlite3_snprintf(sizeof(yymsp[-8].minor.yy387->zSelName), yymsp[-8].minor.yy387->zSelName, "%.*s", i, z); +- } ++ yymsp[-8].minor.yy489 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy420,yymsp[-5].minor.yy135,yymsp[-4].minor.yy18,yymsp[-3].minor.yy420,yymsp[-2].minor.yy18,yymsp[-1].minor.yy420,yymsp[-7].minor.yy70,yymsp[0].minor.yy18); ++} ++ break; ++ case 88: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ ++{ ++ yymsp[-9].minor.yy489 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy420,yymsp[-6].minor.yy135,yymsp[-5].minor.yy18,yymsp[-4].minor.yy420,yymsp[-3].minor.yy18,yymsp[-1].minor.yy420,yymsp[-8].minor.yy70,yymsp[0].minor.yy18); ++ if( yymsp[-9].minor.yy489 ){ ++ yymsp[-9].minor.yy489->pWinDefn = yymsp[-2].minor.yy327; ++ }else{ ++ sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy327); + } +-#endif /* SELECTRACE_ENABLED */ + } + break; +- case 88: /* values ::= VALUES LP nexprlist RP */ ++ case 89: /* values ::= VALUES LP nexprlist RP */ + { +- yymsp[-3].minor.yy387 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy322,0,0,0,0,0,SF_Values,0); ++ yymsp[-3].minor.yy489 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy420,0,0,0,0,0,SF_Values,0); + } + break; +- case 89: /* values ::= values COMMA LP exprlist RP */ ++ case 90: /* values ::= values COMMA LP nexprlist RP */ + { +- Select *pRight, *pLeft = yymsp[-4].minor.yy387; +- pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy322,0,0,0,0,0,SF_Values|SF_MultiValue,0); ++ Select *pRight, *pLeft = yymsp[-4].minor.yy489; ++ pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy420,0,0,0,0,0,SF_Values|SF_MultiValue,0); + if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue; + if( pRight ){ + pRight->op = TK_ALL; + pRight->pPrior = pLeft; +- yymsp[-4].minor.yy387 = pRight; ++ yymsp[-4].minor.yy489 = pRight; + }else{ +- yymsp[-4].minor.yy387 = pLeft; ++ yymsp[-4].minor.yy489 = pLeft; + } + } + break; +- case 90: /* distinct ::= DISTINCT */ +-{yymsp[0].minor.yy4 = SF_Distinct;} ++ case 91: /* distinct ::= DISTINCT */ ++{yymsp[0].minor.yy70 = SF_Distinct;} + break; +- case 91: /* distinct ::= ALL */ +-{yymsp[0].minor.yy4 = SF_All;} ++ case 92: /* distinct ::= ALL */ ++{yymsp[0].minor.yy70 = SF_All;} + break; +- case 93: /* sclp ::= */ +- case 122: /* orderby_opt ::= */ yytestcase(yyruleno==122); +- case 129: /* groupby_opt ::= */ yytestcase(yyruleno==129); +- case 204: /* exprlist ::= */ yytestcase(yyruleno==204); +- case 207: /* paren_exprlist ::= */ yytestcase(yyruleno==207); +- case 212: /* eidlist_opt ::= */ yytestcase(yyruleno==212); +-{yymsp[1].minor.yy322 = 0;} ++ case 94: /* sclp ::= */ ++ case 127: /* orderby_opt ::= */ yytestcase(yyruleno==127); ++ case 134: /* groupby_opt ::= */ yytestcase(yyruleno==134); ++ case 214: /* exprlist ::= */ yytestcase(yyruleno==214); ++ case 217: /* paren_exprlist ::= */ yytestcase(yyruleno==217); ++ case 222: /* eidlist_opt ::= */ yytestcase(yyruleno==222); ++{yymsp[1].minor.yy420 = 0;} + break; +- case 94: /* selcollist ::= sclp scanpt expr scanpt as */ ++ case 95: /* selcollist ::= sclp scanpt expr scanpt as */ + { +- yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy322, yymsp[-2].minor.yy314); +- if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy322, &yymsp[0].minor.yy0, 1); +- sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy322,yymsp[-3].minor.yy336,yymsp[-1].minor.yy336); ++ yymsp[-4].minor.yy420 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy420, yymsp[-2].minor.yy18); ++ if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy420, &yymsp[0].minor.yy0, 1); ++ sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy420,yymsp[-3].minor.yy392,yymsp[-1].minor.yy392); + } + break; +- case 95: /* selcollist ::= sclp scanpt STAR */ ++ case 96: /* selcollist ::= sclp scanpt STAR */ + { + Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0); +- yymsp[-2].minor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy322, p); ++ yymsp[-2].minor.yy420 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy420, p); + } + break; +- case 96: /* selcollist ::= sclp scanpt nm DOT STAR */ ++ case 97: /* selcollist ::= sclp scanpt nm DOT STAR */ + { + Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0); + Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); + Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight); +- yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, pDot); ++ yymsp[-4].minor.yy420 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy420, pDot); + } + break; +- case 97: /* as ::= AS nm */ +- case 108: /* dbnm ::= DOT nm */ yytestcase(yyruleno==108); +- case 226: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==226); +- case 227: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==227); ++ case 98: /* as ::= AS nm */ ++ case 109: /* dbnm ::= DOT nm */ yytestcase(yyruleno==109); ++ case 236: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==236); ++ case 237: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==237); + {yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;} + break; +- case 99: /* from ::= */ +-{yymsp[1].minor.yy259 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy259));} ++ case 100: /* from ::= */ ++{yymsp[1].minor.yy135 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy135));} + break; +- case 100: /* from ::= FROM seltablist */ ++ case 101: /* from ::= FROM seltablist */ + { +- yymsp[-1].minor.yy259 = yymsp[0].minor.yy259; +- sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy259); ++ yymsp[-1].minor.yy135 = yymsp[0].minor.yy135; ++ sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy135); + } + break; +- case 101: /* stl_prefix ::= seltablist joinop */ ++ case 102: /* stl_prefix ::= seltablist joinop */ + { +- if( ALWAYS(yymsp[-1].minor.yy259 && yymsp[-1].minor.yy259->nSrc>0) ) yymsp[-1].minor.yy259->a[yymsp[-1].minor.yy259->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy4; ++ if( ALWAYS(yymsp[-1].minor.yy135 && yymsp[-1].minor.yy135->nSrc>0) ) yymsp[-1].minor.yy135->a[yymsp[-1].minor.yy135->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy70; + } + break; +- case 102: /* stl_prefix ::= */ +-{yymsp[1].minor.yy259 = 0;} ++ case 103: /* stl_prefix ::= */ ++{yymsp[1].minor.yy135 = 0;} + break; +- case 103: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ ++ case 104: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ + { +- yymsp[-6].minor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy314,yymsp[0].minor.yy384); +- sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy259, &yymsp[-2].minor.yy0); ++ yymsp[-6].minor.yy135 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy135,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy18,yymsp[0].minor.yy48); ++ sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy135, &yymsp[-2].minor.yy0); + } + break; +- case 104: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */ ++ case 105: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */ + { +- yymsp[-8].minor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy259,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy314,yymsp[0].minor.yy384); +- sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy259, yymsp[-4].minor.yy322); ++ yymsp[-8].minor.yy135 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy135,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy18,yymsp[0].minor.yy48); ++ sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy135, yymsp[-4].minor.yy420); + } + break; +- case 105: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */ ++ case 106: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */ + { +- yymsp[-6].minor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy387,yymsp[-1].minor.yy314,yymsp[0].minor.yy384); ++ yymsp[-6].minor.yy135 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy135,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy489,yymsp[-1].minor.yy18,yymsp[0].minor.yy48); + } + break; +- case 106: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ ++ case 107: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ + { +- if( yymsp[-6].minor.yy259==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy314==0 && yymsp[0].minor.yy384==0 ){ +- yymsp[-6].minor.yy259 = yymsp[-4].minor.yy259; +- }else if( yymsp[-4].minor.yy259->nSrc==1 ){ +- yymsp[-6].minor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy314,yymsp[0].minor.yy384); +- if( yymsp[-6].minor.yy259 ){ +- struct SrcList_item *pNew = &yymsp[-6].minor.yy259->a[yymsp[-6].minor.yy259->nSrc-1]; +- struct SrcList_item *pOld = yymsp[-4].minor.yy259->a; ++ if( yymsp[-6].minor.yy135==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy18==0 && yymsp[0].minor.yy48==0 ){ ++ yymsp[-6].minor.yy135 = yymsp[-4].minor.yy135; ++ }else if( yymsp[-4].minor.yy135->nSrc==1 ){ ++ yymsp[-6].minor.yy135 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy135,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy18,yymsp[0].minor.yy48); ++ if( yymsp[-6].minor.yy135 ){ ++ struct SrcList_item *pNew = &yymsp[-6].minor.yy135->a[yymsp[-6].minor.yy135->nSrc-1]; ++ struct SrcList_item *pOld = yymsp[-4].minor.yy135->a; + pNew->zName = pOld->zName; + pNew->zDatabase = pOld->zDatabase; + pNew->pSelect = pOld->pSelect; +@@ -142732,194 +149996,240 @@ + pOld->zName = pOld->zDatabase = 0; + pOld->pSelect = 0; + } +- sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy259); ++ sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy135); + }else{ + Select *pSubquery; +- sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy259); +- pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy259,0,0,0,0,SF_NestedFrom,0); +- yymsp[-6].minor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy314,yymsp[0].minor.yy384); ++ sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy135); ++ pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy135,0,0,0,0,SF_NestedFrom,0); ++ yymsp[-6].minor.yy135 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy135,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy18,yymsp[0].minor.yy48); + } + } + break; +- case 107: /* dbnm ::= */ +- case 117: /* indexed_opt ::= */ yytestcase(yyruleno==117); ++ case 108: /* dbnm ::= */ ++ case 122: /* indexed_opt ::= */ yytestcase(yyruleno==122); + {yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;} + break; +- case 109: /* fullname ::= nm */ +-{yymsp[0].minor.yy259 = sqlite3SrcListAppend(pParse->db,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/} ++ case 110: /* fullname ::= nm */ ++{ ++ yylhsminor.yy135 = sqlite3SrcListAppend(pParse->db,0,&yymsp[0].minor.yy0,0); ++ if( IN_RENAME_OBJECT && yylhsminor.yy135 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy135->a[0].zName, &yymsp[0].minor.yy0); ++} ++ yymsp[0].minor.yy135 = yylhsminor.yy135; + break; +- case 110: /* fullname ::= nm DOT nm */ +-{yymsp[-2].minor.yy259 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/} ++ case 111: /* fullname ::= nm DOT nm */ ++{ ++ yylhsminor.yy135 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); ++ if( IN_RENAME_OBJECT && yylhsminor.yy135 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy135->a[0].zName, &yymsp[0].minor.yy0); ++} ++ yymsp[-2].minor.yy135 = yylhsminor.yy135; + break; +- case 111: /* joinop ::= COMMA|JOIN */ +-{ yymsp[0].minor.yy4 = JT_INNER; } ++ case 112: /* xfullname ::= nm */ ++{yymsp[0].minor.yy135 = sqlite3SrcListAppend(pParse->db,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/} + break; +- case 112: /* joinop ::= JOIN_KW JOIN */ +-{yymsp[-1].minor.yy4 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} ++ case 113: /* xfullname ::= nm DOT nm */ ++{yymsp[-2].minor.yy135 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/} + break; +- case 113: /* joinop ::= JOIN_KW nm JOIN */ +-{yymsp[-2].minor.yy4 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/} ++ case 114: /* xfullname ::= nm DOT nm AS nm */ ++{ ++ yymsp[-4].minor.yy135 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/ ++ if( yymsp[-4].minor.yy135 ) yymsp[-4].minor.yy135->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); ++} + break; +- case 114: /* joinop ::= JOIN_KW nm nm JOIN */ +-{yymsp[-3].minor.yy4 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} ++ case 115: /* xfullname ::= nm AS nm */ ++{ ++ yymsp[-2].minor.yy135 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/ ++ if( yymsp[-2].minor.yy135 ) yymsp[-2].minor.yy135->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); ++} + break; +- case 115: /* on_opt ::= ON expr */ +- case 132: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==132); +- case 139: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==139); +- case 200: /* case_else ::= ELSE expr */ yytestcase(yyruleno==200); +-{yymsp[-1].minor.yy314 = yymsp[0].minor.yy314;} ++ case 116: /* joinop ::= COMMA|JOIN */ ++{ yymsp[0].minor.yy70 = JT_INNER; } + break; +- case 116: /* on_opt ::= */ +- case 131: /* having_opt ::= */ yytestcase(yyruleno==131); +- case 133: /* limit_opt ::= */ yytestcase(yyruleno==133); +- case 138: /* where_opt ::= */ yytestcase(yyruleno==138); +- case 201: /* case_else ::= */ yytestcase(yyruleno==201); +- case 203: /* case_operand ::= */ yytestcase(yyruleno==203); +-{yymsp[1].minor.yy314 = 0;} ++ case 117: /* joinop ::= JOIN_KW JOIN */ ++{yymsp[-1].minor.yy70 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} + break; +- case 118: /* indexed_opt ::= INDEXED BY nm */ ++ case 118: /* joinop ::= JOIN_KW nm JOIN */ ++{yymsp[-2].minor.yy70 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/} ++ break; ++ case 119: /* joinop ::= JOIN_KW nm nm JOIN */ ++{yymsp[-3].minor.yy70 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} ++ break; ++ case 120: /* on_opt ::= ON expr */ ++ case 137: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==137); ++ case 144: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==144); ++ case 210: /* case_else ::= ELSE expr */ yytestcase(yyruleno==210); ++{yymsp[-1].minor.yy18 = yymsp[0].minor.yy18;} ++ break; ++ case 121: /* on_opt ::= */ ++ case 136: /* having_opt ::= */ yytestcase(yyruleno==136); ++ case 138: /* limit_opt ::= */ yytestcase(yyruleno==138); ++ case 143: /* where_opt ::= */ yytestcase(yyruleno==143); ++ case 211: /* case_else ::= */ yytestcase(yyruleno==211); ++ case 213: /* case_operand ::= */ yytestcase(yyruleno==213); ++{yymsp[1].minor.yy18 = 0;} ++ break; ++ case 123: /* indexed_opt ::= INDEXED BY nm */ + {yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;} + break; +- case 119: /* indexed_opt ::= NOT INDEXED */ ++ case 124: /* indexed_opt ::= NOT INDEXED */ + {yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;} + break; +- case 120: /* using_opt ::= USING LP idlist RP */ +-{yymsp[-3].minor.yy384 = yymsp[-1].minor.yy384;} ++ case 125: /* using_opt ::= USING LP idlist RP */ ++{yymsp[-3].minor.yy48 = yymsp[-1].minor.yy48;} + break; +- case 121: /* using_opt ::= */ +- case 149: /* idlist_opt ::= */ yytestcase(yyruleno==149); +-{yymsp[1].minor.yy384 = 0;} ++ case 126: /* using_opt ::= */ ++ case 158: /* idlist_opt ::= */ yytestcase(yyruleno==158); ++{yymsp[1].minor.yy48 = 0;} + break; +- case 123: /* orderby_opt ::= ORDER BY sortlist */ +- case 130: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==130); +-{yymsp[-2].minor.yy322 = yymsp[0].minor.yy322;} ++ case 128: /* orderby_opt ::= ORDER BY sortlist */ ++ case 135: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==135); ++{yymsp[-2].minor.yy420 = yymsp[0].minor.yy420;} + break; +- case 124: /* sortlist ::= sortlist COMMA expr sortorder */ ++ case 129: /* sortlist ::= sortlist COMMA expr sortorder */ + { +- yymsp[-3].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy322,yymsp[-1].minor.yy314); +- sqlite3ExprListSetSortOrder(yymsp[-3].minor.yy322,yymsp[0].minor.yy4); ++ yymsp[-3].minor.yy420 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy420,yymsp[-1].minor.yy18); ++ sqlite3ExprListSetSortOrder(yymsp[-3].minor.yy420,yymsp[0].minor.yy70); + } + break; +- case 125: /* sortlist ::= expr sortorder */ ++ case 130: /* sortlist ::= expr sortorder */ + { +- yymsp[-1].minor.yy322 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy314); /*A-overwrites-Y*/ +- sqlite3ExprListSetSortOrder(yymsp[-1].minor.yy322,yymsp[0].minor.yy4); ++ yymsp[-1].minor.yy420 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy18); /*A-overwrites-Y*/ ++ sqlite3ExprListSetSortOrder(yymsp[-1].minor.yy420,yymsp[0].minor.yy70); + } + break; +- case 126: /* sortorder ::= ASC */ +-{yymsp[0].minor.yy4 = SQLITE_SO_ASC;} ++ case 131: /* sortorder ::= ASC */ ++{yymsp[0].minor.yy70 = SQLITE_SO_ASC;} + break; +- case 127: /* sortorder ::= DESC */ +-{yymsp[0].minor.yy4 = SQLITE_SO_DESC;} ++ case 132: /* sortorder ::= DESC */ ++{yymsp[0].minor.yy70 = SQLITE_SO_DESC;} + break; +- case 128: /* sortorder ::= */ +-{yymsp[1].minor.yy4 = SQLITE_SO_UNDEFINED;} ++ case 133: /* sortorder ::= */ ++{yymsp[1].minor.yy70 = SQLITE_SO_UNDEFINED;} + break; +- case 134: /* limit_opt ::= LIMIT expr */ +-{yymsp[-1].minor.yy314 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy314,0);} ++ case 139: /* limit_opt ::= LIMIT expr */ ++{yymsp[-1].minor.yy18 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy18,0);} + break; +- case 135: /* limit_opt ::= LIMIT expr OFFSET expr */ +-{yymsp[-3].minor.yy314 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy314,yymsp[0].minor.yy314);} ++ case 140: /* limit_opt ::= LIMIT expr OFFSET expr */ ++{yymsp[-3].minor.yy18 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy18,yymsp[0].minor.yy18);} + break; +- case 136: /* limit_opt ::= LIMIT expr COMMA expr */ +-{yymsp[-3].minor.yy314 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy314,yymsp[-2].minor.yy314);} ++ case 141: /* limit_opt ::= LIMIT expr COMMA expr */ ++{yymsp[-3].minor.yy18 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy18,yymsp[-2].minor.yy18);} + break; +- case 137: /* cmd ::= with DELETE FROM fullname indexed_opt where_opt */ ++ case 142: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt */ + { +- sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy259, &yymsp[-1].minor.yy0); +- sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy259,yymsp[0].minor.yy314,0,0); ++ sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy135, &yymsp[-1].minor.yy0); ++ sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy135,yymsp[0].minor.yy18,0,0); + } + break; +- case 140: /* cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt */ ++ case 145: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */ + { +- sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy259, &yymsp[-3].minor.yy0); +- sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy322,"set list"); +- sqlite3Update(pParse,yymsp[-4].minor.yy259,yymsp[-1].minor.yy322,yymsp[0].minor.yy314,yymsp[-5].minor.yy4,0,0); ++ sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy135, &yymsp[-3].minor.yy0); ++ sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy420,"set list"); ++ sqlite3Update(pParse,yymsp[-4].minor.yy135,yymsp[-1].minor.yy420,yymsp[0].minor.yy18,yymsp[-5].minor.yy70,0,0,0); + } + break; +- case 141: /* setlist ::= setlist COMMA nm EQ expr */ ++ case 146: /* setlist ::= setlist COMMA nm EQ expr */ + { +- yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy322, yymsp[0].minor.yy314); +- sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy322, &yymsp[-2].minor.yy0, 1); ++ yymsp[-4].minor.yy420 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy420, yymsp[0].minor.yy18); ++ sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy420, &yymsp[-2].minor.yy0, 1); + } + break; +- case 142: /* setlist ::= setlist COMMA LP idlist RP EQ expr */ ++ case 147: /* setlist ::= setlist COMMA LP idlist RP EQ expr */ + { +- yymsp[-6].minor.yy322 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy322, yymsp[-3].minor.yy384, yymsp[0].minor.yy314); ++ yymsp[-6].minor.yy420 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy420, yymsp[-3].minor.yy48, yymsp[0].minor.yy18); + } + break; +- case 143: /* setlist ::= nm EQ expr */ ++ case 148: /* setlist ::= nm EQ expr */ + { +- yylhsminor.yy322 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy314); +- sqlite3ExprListSetName(pParse, yylhsminor.yy322, &yymsp[-2].minor.yy0, 1); ++ yylhsminor.yy420 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy18); ++ sqlite3ExprListSetName(pParse, yylhsminor.yy420, &yymsp[-2].minor.yy0, 1); + } +- yymsp[-2].minor.yy322 = yylhsminor.yy322; ++ yymsp[-2].minor.yy420 = yylhsminor.yy420; + break; +- case 144: /* setlist ::= LP idlist RP EQ expr */ ++ case 149: /* setlist ::= LP idlist RP EQ expr */ + { +- yymsp[-4].minor.yy322 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy384, yymsp[0].minor.yy314); ++ yymsp[-4].minor.yy420 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy48, yymsp[0].minor.yy18); + } + break; +- case 145: /* cmd ::= with insert_cmd INTO fullname idlist_opt select */ ++ case 150: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ + { +- sqlite3Insert(pParse, yymsp[-2].minor.yy259, yymsp[0].minor.yy387, yymsp[-1].minor.yy384, yymsp[-4].minor.yy4); ++ sqlite3Insert(pParse, yymsp[-3].minor.yy135, yymsp[-1].minor.yy489, yymsp[-2].minor.yy48, yymsp[-5].minor.yy70, yymsp[0].minor.yy340); + } + break; +- case 146: /* cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES */ ++ case 151: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */ + { +- sqlite3Insert(pParse, yymsp[-3].minor.yy259, 0, yymsp[-2].minor.yy384, yymsp[-5].minor.yy4); ++ sqlite3Insert(pParse, yymsp[-3].minor.yy135, 0, yymsp[-2].minor.yy48, yymsp[-5].minor.yy70, 0); + } + break; +- case 150: /* idlist_opt ::= LP idlist RP */ +-{yymsp[-2].minor.yy384 = yymsp[-1].minor.yy384;} ++ case 152: /* upsert ::= */ ++{ yymsp[1].minor.yy340 = 0; } + break; +- case 151: /* idlist ::= idlist COMMA nm */ +-{yymsp[-2].minor.yy384 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy384,&yymsp[0].minor.yy0);} ++ case 153: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */ ++{ yymsp[-10].minor.yy340 = sqlite3UpsertNew(pParse->db,yymsp[-7].minor.yy420,yymsp[-5].minor.yy18,yymsp[-1].minor.yy420,yymsp[0].minor.yy18);} + break; +- case 152: /* idlist ::= nm */ +-{yymsp[0].minor.yy384 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} ++ case 154: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */ ++{ yymsp[-7].minor.yy340 = sqlite3UpsertNew(pParse->db,yymsp[-4].minor.yy420,yymsp[-2].minor.yy18,0,0); } + break; +- case 153: /* expr ::= LP expr RP */ +-{yymsp[-2].minor.yy314 = yymsp[-1].minor.yy314;} ++ case 155: /* upsert ::= ON CONFLICT DO NOTHING */ ++{ yymsp[-3].minor.yy340 = sqlite3UpsertNew(pParse->db,0,0,0,0); } + break; +- case 154: /* expr ::= ID|INDEXED */ +- case 155: /* expr ::= JOIN_KW */ yytestcase(yyruleno==155); +-{yymsp[0].minor.yy314=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} ++ case 159: /* idlist_opt ::= LP idlist RP */ ++{yymsp[-2].minor.yy48 = yymsp[-1].minor.yy48;} + break; +- case 156: /* expr ::= nm DOT nm */ ++ case 160: /* idlist ::= idlist COMMA nm */ ++{yymsp[-2].minor.yy48 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy48,&yymsp[0].minor.yy0);} ++ break; ++ case 161: /* idlist ::= nm */ ++{yymsp[0].minor.yy48 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} ++ break; ++ case 162: /* expr ::= LP expr RP */ ++{yymsp[-2].minor.yy18 = yymsp[-1].minor.yy18;} ++ break; ++ case 163: /* expr ::= ID|INDEXED */ ++ case 164: /* expr ::= JOIN_KW */ yytestcase(yyruleno==164); ++{yymsp[0].minor.yy18=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} ++ break; ++ case 165: /* expr ::= nm DOT nm */ + { + Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); + Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1); +- yylhsminor.yy314 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameTokenMap(pParse, (void*)temp2, &yymsp[0].minor.yy0); ++ sqlite3RenameTokenMap(pParse, (void*)temp1, &yymsp[-2].minor.yy0); ++ } ++ yylhsminor.yy18 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); + } +- yymsp[-2].minor.yy314 = yylhsminor.yy314; ++ yymsp[-2].minor.yy18 = yylhsminor.yy18; + break; +- case 157: /* expr ::= nm DOT nm DOT nm */ ++ case 166: /* expr ::= nm DOT nm DOT nm */ + { + Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-4].minor.yy0, 1); + Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); + Expr *temp3 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1); + Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3); +- yylhsminor.yy314 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); ++ if( IN_RENAME_OBJECT ){ ++ sqlite3RenameTokenMap(pParse, (void*)temp3, &yymsp[0].minor.yy0); ++ sqlite3RenameTokenMap(pParse, (void*)temp2, &yymsp[-2].minor.yy0); ++ } ++ yylhsminor.yy18 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); + } +- yymsp[-4].minor.yy314 = yylhsminor.yy314; ++ yymsp[-4].minor.yy18 = yylhsminor.yy18; + break; +- case 158: /* term ::= NULL|FLOAT|BLOB */ +- case 159: /* term ::= STRING */ yytestcase(yyruleno==159); +-{yymsp[0].minor.yy314=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/} ++ case 167: /* term ::= NULL|FLOAT|BLOB */ ++ case 168: /* term ::= STRING */ yytestcase(yyruleno==168); ++{yymsp[0].minor.yy18=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/} + break; +- case 160: /* term ::= INTEGER */ ++ case 169: /* term ::= INTEGER */ + { +- yylhsminor.yy314 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); ++ yylhsminor.yy18 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); + } +- yymsp[0].minor.yy314 = yylhsminor.yy314; ++ yymsp[0].minor.yy18 = yylhsminor.yy18; + break; +- case 161: /* expr ::= VARIABLE */ ++ case 170: /* expr ::= VARIABLE */ + { + if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){ + u32 n = yymsp[0].minor.yy0.n; +- yymsp[0].minor.yy314 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0); +- sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy314, n); ++ yymsp[0].minor.yy18 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0); ++ sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy18, n); + }else{ + /* When doing a nested parse, one can include terms in an expression + ** that look like this: #1 #2 ... These terms refer to registers +@@ -142928,146 +150238,154 @@ + assert( t.n>=2 ); + if( pParse->nested==0 ){ + sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t); +- yymsp[0].minor.yy314 = 0; ++ yymsp[0].minor.yy18 = 0; + }else{ +- yymsp[0].minor.yy314 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); +- if( yymsp[0].minor.yy314 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy314->iTable); ++ yymsp[0].minor.yy18 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); ++ if( yymsp[0].minor.yy18 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy18->iTable); + } + } + } + break; +- case 162: /* expr ::= expr COLLATE ID|STRING */ ++ case 171: /* expr ::= expr COLLATE ID|STRING */ + { +- yymsp[-2].minor.yy314 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy314, &yymsp[0].minor.yy0, 1); ++ yymsp[-2].minor.yy18 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy18, &yymsp[0].minor.yy0, 1); + } + break; +- case 163: /* expr ::= CAST LP expr AS typetoken RP */ ++ case 172: /* expr ::= CAST LP expr AS typetoken RP */ + { +- yymsp[-5].minor.yy314 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); +- sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy314, yymsp[-3].minor.yy314, 0); ++ yymsp[-5].minor.yy18 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); ++ sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy18, yymsp[-3].minor.yy18, 0); + } + break; +- case 164: /* expr ::= ID|INDEXED LP distinct exprlist RP */ ++ case 173: /* expr ::= ID|INDEXED LP distinct exprlist RP */ + { +- if( yymsp[-1].minor.yy322 && yymsp[-1].minor.yy322->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ +- sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); +- } +- yylhsminor.yy314 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy322, &yymsp[-4].minor.yy0); +- if( yymsp[-2].minor.yy4==SF_Distinct && yylhsminor.yy314 ){ +- yylhsminor.yy314->flags |= EP_Distinct; +- } ++ yylhsminor.yy18 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy420, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy70); + } +- yymsp[-4].minor.yy314 = yylhsminor.yy314; ++ yymsp[-4].minor.yy18 = yylhsminor.yy18; + break; +- case 165: /* expr ::= ID|INDEXED LP STAR RP */ ++ case 174: /* expr ::= ID|INDEXED LP STAR RP */ + { +- yylhsminor.yy314 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); ++ yylhsminor.yy18 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0); + } +- yymsp[-3].minor.yy314 = yylhsminor.yy314; ++ yymsp[-3].minor.yy18 = yylhsminor.yy18; + break; +- case 166: /* term ::= CTIME_KW */ ++ case 175: /* expr ::= ID|INDEXED LP distinct exprlist RP over_clause */ + { +- yylhsminor.yy314 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0); ++ yylhsminor.yy18 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy420, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy70); ++ sqlite3WindowAttach(pParse, yylhsminor.yy18, yymsp[0].minor.yy327); + } +- yymsp[0].minor.yy314 = yylhsminor.yy314; ++ yymsp[-5].minor.yy18 = yylhsminor.yy18; + break; +- case 167: /* expr ::= LP nexprlist COMMA expr RP */ ++ case 176: /* expr ::= ID|INDEXED LP STAR RP over_clause */ + { +- ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy322, yymsp[-1].minor.yy314); +- yymsp[-4].minor.yy314 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); +- if( yymsp[-4].minor.yy314 ){ +- yymsp[-4].minor.yy314->x.pList = pList; ++ yylhsminor.yy18 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0); ++ sqlite3WindowAttach(pParse, yylhsminor.yy18, yymsp[0].minor.yy327); ++} ++ yymsp[-4].minor.yy18 = yylhsminor.yy18; ++ break; ++ case 177: /* term ::= CTIME_KW */ ++{ ++ yylhsminor.yy18 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0); ++} ++ yymsp[0].minor.yy18 = yylhsminor.yy18; ++ break; ++ case 178: /* expr ::= LP nexprlist COMMA expr RP */ ++{ ++ ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy420, yymsp[-1].minor.yy18); ++ yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); ++ if( yymsp[-4].minor.yy18 ){ ++ yymsp[-4].minor.yy18->x.pList = pList; + }else{ + sqlite3ExprListDelete(pParse->db, pList); + } + } + break; +- case 168: /* expr ::= expr AND expr */ +- case 169: /* expr ::= expr OR expr */ yytestcase(yyruleno==169); +- case 170: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==170); +- case 171: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==171); +- case 172: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==172); +- case 173: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==173); +- case 174: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==174); +- case 175: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==175); +-{yymsp[-2].minor.yy314=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy314,yymsp[0].minor.yy314);} ++ case 179: /* expr ::= expr AND expr */ ++ case 180: /* expr ::= expr OR expr */ yytestcase(yyruleno==180); ++ case 181: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==181); ++ case 182: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==182); ++ case 183: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==183); ++ case 184: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==184); ++ case 185: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==185); ++ case 186: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==186); ++{yymsp[-2].minor.yy18=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy18,yymsp[0].minor.yy18);} + break; +- case 176: /* likeop ::= NOT LIKE_KW|MATCH */ ++ case 187: /* likeop ::= NOT LIKE_KW|MATCH */ + {yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/} + break; +- case 177: /* expr ::= expr likeop expr */ ++ case 188: /* expr ::= expr likeop expr */ + { + ExprList *pList; + int bNot = yymsp[-1].minor.yy0.n & 0x80000000; + yymsp[-1].minor.yy0.n &= 0x7fffffff; +- pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy314); +- pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy314); +- yymsp[-2].minor.yy314 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0); +- if( bNot ) yymsp[-2].minor.yy314 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy314, 0); +- if( yymsp[-2].minor.yy314 ) yymsp[-2].minor.yy314->flags |= EP_InfixFunc; ++ pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy18); ++ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy18); ++ yymsp[-2].minor.yy18 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); ++ if( bNot ) yymsp[-2].minor.yy18 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy18, 0); ++ if( yymsp[-2].minor.yy18 ) yymsp[-2].minor.yy18->flags |= EP_InfixFunc; + } + break; +- case 178: /* expr ::= expr likeop expr ESCAPE expr */ ++ case 189: /* expr ::= expr likeop expr ESCAPE expr */ + { + ExprList *pList; + int bNot = yymsp[-3].minor.yy0.n & 0x80000000; + yymsp[-3].minor.yy0.n &= 0x7fffffff; +- pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy314); +- pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy314); +- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy314); +- yymsp[-4].minor.yy314 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0); +- if( bNot ) yymsp[-4].minor.yy314 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy314, 0); +- if( yymsp[-4].minor.yy314 ) yymsp[-4].minor.yy314->flags |= EP_InfixFunc; ++ pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy18); ++ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy18); ++ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy18); ++ yymsp[-4].minor.yy18 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0); ++ if( bNot ) yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy18, 0); ++ if( yymsp[-4].minor.yy18 ) yymsp[-4].minor.yy18->flags |= EP_InfixFunc; + } + break; +- case 179: /* expr ::= expr ISNULL|NOTNULL */ +-{yymsp[-1].minor.yy314 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy314,0);} ++ case 190: /* expr ::= expr ISNULL|NOTNULL */ ++{yymsp[-1].minor.yy18 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy18,0);} + break; +- case 180: /* expr ::= expr NOT NULL */ +-{yymsp[-2].minor.yy314 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy314,0);} ++ case 191: /* expr ::= expr NOT NULL */ ++{yymsp[-2].minor.yy18 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy18,0);} + break; +- case 181: /* expr ::= expr IS expr */ ++ case 192: /* expr ::= expr IS expr */ + { +- yymsp[-2].minor.yy314 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy314,yymsp[0].minor.yy314); +- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy314, yymsp[-2].minor.yy314, TK_ISNULL); ++ yymsp[-2].minor.yy18 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy18,yymsp[0].minor.yy18); ++ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy18, yymsp[-2].minor.yy18, TK_ISNULL); + } + break; +- case 182: /* expr ::= expr IS NOT expr */ ++ case 193: /* expr ::= expr IS NOT expr */ + { +- yymsp[-3].minor.yy314 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy314,yymsp[0].minor.yy314); +- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy314, yymsp[-3].minor.yy314, TK_NOTNULL); ++ yymsp[-3].minor.yy18 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy18,yymsp[0].minor.yy18); ++ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy18, yymsp[-3].minor.yy18, TK_NOTNULL); + } + break; +- case 183: /* expr ::= NOT expr */ +- case 184: /* expr ::= BITNOT expr */ yytestcase(yyruleno==184); +-{yymsp[-1].minor.yy314 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy314, 0);/*A-overwrites-B*/} ++ case 194: /* expr ::= NOT expr */ ++ case 195: /* expr ::= BITNOT expr */ yytestcase(yyruleno==195); ++{yymsp[-1].minor.yy18 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy18, 0);/*A-overwrites-B*/} + break; +- case 185: /* expr ::= MINUS expr */ +-{yymsp[-1].minor.yy314 = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy314, 0);} ++ case 196: /* expr ::= PLUS|MINUS expr */ ++{ ++ yymsp[-1].minor.yy18 = sqlite3PExpr(pParse, yymsp[-1].major==TK_PLUS ? TK_UPLUS : TK_UMINUS, yymsp[0].minor.yy18, 0); ++ /*A-overwrites-B*/ ++} + break; +- case 186: /* expr ::= PLUS expr */ +-{yymsp[-1].minor.yy314 = sqlite3PExpr(pParse, TK_UPLUS, yymsp[0].minor.yy314, 0);} ++ case 197: /* between_op ::= BETWEEN */ ++ case 200: /* in_op ::= IN */ yytestcase(yyruleno==200); ++{yymsp[0].minor.yy70 = 0;} + break; +- case 187: /* between_op ::= BETWEEN */ +- case 190: /* in_op ::= IN */ yytestcase(yyruleno==190); +-{yymsp[0].minor.yy4 = 0;} +- break; +- case 189: /* expr ::= expr between_op expr AND expr */ ++ case 199: /* expr ::= expr between_op expr AND expr */ + { +- ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy314); +- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy314); +- yymsp[-4].minor.yy314 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy314, 0); +- if( yymsp[-4].minor.yy314 ){ +- yymsp[-4].minor.yy314->x.pList = pList; ++ ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy18); ++ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy18); ++ yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy18, 0); ++ if( yymsp[-4].minor.yy18 ){ ++ yymsp[-4].minor.yy18->x.pList = pList; + }else{ + sqlite3ExprListDelete(pParse->db, pList); + } +- if( yymsp[-3].minor.yy4 ) yymsp[-4].minor.yy314 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy314, 0); ++ if( yymsp[-3].minor.yy70 ) yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy18, 0); + } + break; +- case 192: /* expr ::= expr in_op LP exprlist RP */ ++ case 202: /* expr ::= expr in_op LP exprlist RP */ + { +- if( yymsp[-1].minor.yy322==0 ){ ++ if( yymsp[-1].minor.yy420==0 ){ + /* Expressions of the form + ** + ** expr1 IN () +@@ -143076,9 +150394,9 @@ + ** simplify to constants 0 (false) and 1 (true), respectively, + ** regardless of the value of expr1. + */ +- sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy314); +- yymsp[-4].minor.yy314 = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[yymsp[-3].minor.yy4],1); +- }else if( yymsp[-1].minor.yy322->nExpr==1 ){ ++ sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy18); ++ yymsp[-4].minor.yy18 = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[yymsp[-3].minor.yy70],1); ++ }else if( yymsp[-1].minor.yy420->nExpr==1 ){ + /* Expressions of the form: + ** + ** expr1 IN (?1) +@@ -143095,9 +150413,9 @@ + ** affinity or the collating sequence to use for comparison. Otherwise, + ** the semantics would be subtly different from IN or NOT IN. + */ +- Expr *pRHS = yymsp[-1].minor.yy322->a[0].pExpr; +- yymsp[-1].minor.yy322->a[0].pExpr = 0; +- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy322); ++ Expr *pRHS = yymsp[-1].minor.yy420->a[0].pExpr; ++ yymsp[-1].minor.yy420->a[0].pExpr = 0; ++ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy420); + /* pRHS cannot be NULL because a malloc error would have been detected + ** before now and control would have never reached this point */ + if( ALWAYS(pRHS) ){ +@@ -143104,186 +150422,190 @@ + pRHS->flags &= ~EP_Collate; + pRHS->flags |= EP_Generic; + } +- yymsp[-4].minor.yy314 = sqlite3PExpr(pParse, yymsp[-3].minor.yy4 ? TK_NE : TK_EQ, yymsp[-4].minor.yy314, pRHS); ++ yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, yymsp[-3].minor.yy70 ? TK_NE : TK_EQ, yymsp[-4].minor.yy18, pRHS); + }else{ +- yymsp[-4].minor.yy314 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy314, 0); +- if( yymsp[-4].minor.yy314 ){ +- yymsp[-4].minor.yy314->x.pList = yymsp[-1].minor.yy322; +- sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy314); ++ yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy18, 0); ++ if( yymsp[-4].minor.yy18 ){ ++ yymsp[-4].minor.yy18->x.pList = yymsp[-1].minor.yy420; ++ sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy18); + }else{ +- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy322); ++ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy420); + } +- if( yymsp[-3].minor.yy4 ) yymsp[-4].minor.yy314 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy314, 0); ++ if( yymsp[-3].minor.yy70 ) yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy18, 0); + } + } + break; +- case 193: /* expr ::= LP select RP */ ++ case 203: /* expr ::= LP select RP */ + { +- yymsp[-2].minor.yy314 = sqlite3PExpr(pParse, TK_SELECT, 0, 0); +- sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy314, yymsp[-1].minor.yy387); ++ yymsp[-2].minor.yy18 = sqlite3PExpr(pParse, TK_SELECT, 0, 0); ++ sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy18, yymsp[-1].minor.yy489); + } + break; +- case 194: /* expr ::= expr in_op LP select RP */ ++ case 204: /* expr ::= expr in_op LP select RP */ + { +- yymsp[-4].minor.yy314 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy314, 0); +- sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy314, yymsp[-1].minor.yy387); +- if( yymsp[-3].minor.yy4 ) yymsp[-4].minor.yy314 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy314, 0); ++ yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy18, 0); ++ sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy18, yymsp[-1].minor.yy489); ++ if( yymsp[-3].minor.yy70 ) yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy18, 0); + } + break; +- case 195: /* expr ::= expr in_op nm dbnm paren_exprlist */ ++ case 205: /* expr ::= expr in_op nm dbnm paren_exprlist */ + { + SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); + Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0); +- if( yymsp[0].minor.yy322 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy322); +- yymsp[-4].minor.yy314 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy314, 0); +- sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy314, pSelect); +- if( yymsp[-3].minor.yy4 ) yymsp[-4].minor.yy314 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy314, 0); ++ if( yymsp[0].minor.yy420 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy420); ++ yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy18, 0); ++ sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy18, pSelect); ++ if( yymsp[-3].minor.yy70 ) yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy18, 0); + } + break; +- case 196: /* expr ::= EXISTS LP select RP */ ++ case 206: /* expr ::= EXISTS LP select RP */ + { + Expr *p; +- p = yymsp[-3].minor.yy314 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); +- sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy387); ++ p = yymsp[-3].minor.yy18 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); ++ sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy489); + } + break; +- case 197: /* expr ::= CASE case_operand case_exprlist case_else END */ ++ case 207: /* expr ::= CASE case_operand case_exprlist case_else END */ + { +- yymsp[-4].minor.yy314 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy314, 0); +- if( yymsp[-4].minor.yy314 ){ +- yymsp[-4].minor.yy314->x.pList = yymsp[-1].minor.yy314 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy322,yymsp[-1].minor.yy314) : yymsp[-2].minor.yy322; +- sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy314); ++ yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy18, 0); ++ if( yymsp[-4].minor.yy18 ){ ++ yymsp[-4].minor.yy18->x.pList = yymsp[-1].minor.yy18 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy420,yymsp[-1].minor.yy18) : yymsp[-2].minor.yy420; ++ sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy18); + }else{ +- sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy322); +- sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy314); ++ sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy420); ++ sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy18); + } + } + break; +- case 198: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ ++ case 208: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ + { +- yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, yymsp[-2].minor.yy314); +- yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, yymsp[0].minor.yy314); ++ yymsp[-4].minor.yy420 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy420, yymsp[-2].minor.yy18); ++ yymsp[-4].minor.yy420 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy420, yymsp[0].minor.yy18); + } + break; +- case 199: /* case_exprlist ::= WHEN expr THEN expr */ ++ case 209: /* case_exprlist ::= WHEN expr THEN expr */ + { +- yymsp[-3].minor.yy322 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy314); +- yymsp[-3].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy322, yymsp[0].minor.yy314); ++ yymsp[-3].minor.yy420 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy18); ++ yymsp[-3].minor.yy420 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy420, yymsp[0].minor.yy18); + } + break; +- case 202: /* case_operand ::= expr */ +-{yymsp[0].minor.yy314 = yymsp[0].minor.yy314; /*A-overwrites-X*/} ++ case 212: /* case_operand ::= expr */ ++{yymsp[0].minor.yy18 = yymsp[0].minor.yy18; /*A-overwrites-X*/} + break; +- case 205: /* nexprlist ::= nexprlist COMMA expr */ +-{yymsp[-2].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy322,yymsp[0].minor.yy314);} ++ case 215: /* nexprlist ::= nexprlist COMMA expr */ ++{yymsp[-2].minor.yy420 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy420,yymsp[0].minor.yy18);} + break; +- case 206: /* nexprlist ::= expr */ +-{yymsp[0].minor.yy322 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy314); /*A-overwrites-Y*/} ++ case 216: /* nexprlist ::= expr */ ++{yymsp[0].minor.yy420 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy18); /*A-overwrites-Y*/} + break; +- case 208: /* paren_exprlist ::= LP exprlist RP */ +- case 213: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==213); +-{yymsp[-2].minor.yy322 = yymsp[-1].minor.yy322;} ++ case 218: /* paren_exprlist ::= LP exprlist RP */ ++ case 223: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==223); ++{yymsp[-2].minor.yy420 = yymsp[-1].minor.yy420;} + break; +- case 209: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ ++ case 219: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ + { + sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, +- sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy322, yymsp[-10].minor.yy4, +- &yymsp[-11].minor.yy0, yymsp[0].minor.yy314, SQLITE_SO_ASC, yymsp[-8].minor.yy4, SQLITE_IDXTYPE_APPDEF); ++ sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy420, yymsp[-10].minor.yy70, ++ &yymsp[-11].minor.yy0, yymsp[0].minor.yy18, SQLITE_SO_ASC, yymsp[-8].minor.yy70, SQLITE_IDXTYPE_APPDEF); ++ if( IN_RENAME_OBJECT && pParse->pNewIndex ){ ++ sqlite3RenameTokenMap(pParse, pParse->pNewIndex->zName, &yymsp[-4].minor.yy0); ++ } + } + break; +- case 210: /* uniqueflag ::= UNIQUE */ +- case 250: /* raisetype ::= ABORT */ yytestcase(yyruleno==250); +-{yymsp[0].minor.yy4 = OE_Abort;} ++ case 220: /* uniqueflag ::= UNIQUE */ ++ case 260: /* raisetype ::= ABORT */ yytestcase(yyruleno==260); ++{yymsp[0].minor.yy70 = OE_Abort;} + break; +- case 211: /* uniqueflag ::= */ +-{yymsp[1].minor.yy4 = OE_None;} ++ case 221: /* uniqueflag ::= */ ++{yymsp[1].minor.yy70 = OE_None;} + break; +- case 214: /* eidlist ::= eidlist COMMA nm collate sortorder */ ++ case 224: /* eidlist ::= eidlist COMMA nm collate sortorder */ + { +- yymsp[-4].minor.yy322 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy322, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy4, yymsp[0].minor.yy4); ++ yymsp[-4].minor.yy420 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy420, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy70, yymsp[0].minor.yy70); + } + break; +- case 215: /* eidlist ::= nm collate sortorder */ ++ case 225: /* eidlist ::= nm collate sortorder */ + { +- yymsp[-2].minor.yy322 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy4, yymsp[0].minor.yy4); /*A-overwrites-Y*/ ++ yymsp[-2].minor.yy420 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy70, yymsp[0].minor.yy70); /*A-overwrites-Y*/ + } + break; +- case 218: /* cmd ::= DROP INDEX ifexists fullname */ +-{sqlite3DropIndex(pParse, yymsp[0].minor.yy259, yymsp[-1].minor.yy4);} ++ case 228: /* cmd ::= DROP INDEX ifexists fullname */ ++{sqlite3DropIndex(pParse, yymsp[0].minor.yy135, yymsp[-1].minor.yy70);} + break; +- case 219: /* cmd ::= VACUUM */ ++ case 229: /* cmd ::= VACUUM */ + {sqlite3Vacuum(pParse,0);} + break; +- case 220: /* cmd ::= VACUUM nm */ ++ case 230: /* cmd ::= VACUUM nm */ + {sqlite3Vacuum(pParse,&yymsp[0].minor.yy0);} + break; +- case 221: /* cmd ::= PRAGMA nm dbnm */ ++ case 231: /* cmd ::= PRAGMA nm dbnm */ + {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} + break; +- case 222: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ ++ case 232: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ + {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);} + break; +- case 223: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ ++ case 233: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ + {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);} + break; +- case 224: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ ++ case 234: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ + {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);} + break; +- case 225: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ ++ case 235: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ + {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);} + break; +- case 228: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ ++ case 238: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ + { + Token all; + all.z = yymsp[-3].minor.yy0.z; + all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n; +- sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy203, &all); ++ sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy207, &all); + } + break; +- case 229: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ ++ case 239: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + { +- sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy4, yymsp[-4].minor.yy90.a, yymsp[-4].minor.yy90.b, yymsp[-2].minor.yy259, yymsp[0].minor.yy314, yymsp[-10].minor.yy4, yymsp[-8].minor.yy4); ++ sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy70, yymsp[-4].minor.yy34.a, yymsp[-4].minor.yy34.b, yymsp[-2].minor.yy135, yymsp[0].minor.yy18, yymsp[-10].minor.yy70, yymsp[-8].minor.yy70); + yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/ + } + break; +- case 230: /* trigger_time ::= BEFORE|AFTER */ +-{ yymsp[0].minor.yy4 = yymsp[0].major; /*A-overwrites-X*/ } ++ case 240: /* trigger_time ::= BEFORE|AFTER */ ++{ yymsp[0].minor.yy70 = yymsp[0].major; /*A-overwrites-X*/ } + break; +- case 231: /* trigger_time ::= INSTEAD OF */ +-{ yymsp[-1].minor.yy4 = TK_INSTEAD;} ++ case 241: /* trigger_time ::= INSTEAD OF */ ++{ yymsp[-1].minor.yy70 = TK_INSTEAD;} + break; +- case 232: /* trigger_time ::= */ +-{ yymsp[1].minor.yy4 = TK_BEFORE; } ++ case 242: /* trigger_time ::= */ ++{ yymsp[1].minor.yy70 = TK_BEFORE; } + break; +- case 233: /* trigger_event ::= DELETE|INSERT */ +- case 234: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==234); +-{yymsp[0].minor.yy90.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy90.b = 0;} ++ case 243: /* trigger_event ::= DELETE|INSERT */ ++ case 244: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==244); ++{yymsp[0].minor.yy34.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy34.b = 0;} + break; +- case 235: /* trigger_event ::= UPDATE OF idlist */ +-{yymsp[-2].minor.yy90.a = TK_UPDATE; yymsp[-2].minor.yy90.b = yymsp[0].minor.yy384;} ++ case 245: /* trigger_event ::= UPDATE OF idlist */ ++{yymsp[-2].minor.yy34.a = TK_UPDATE; yymsp[-2].minor.yy34.b = yymsp[0].minor.yy48;} + break; +- case 236: /* when_clause ::= */ +- case 255: /* key_opt ::= */ yytestcase(yyruleno==255); +-{ yymsp[1].minor.yy314 = 0; } ++ case 246: /* when_clause ::= */ ++ case 265: /* key_opt ::= */ yytestcase(yyruleno==265); ++ case 307: /* filter_opt ::= */ yytestcase(yyruleno==307); ++{ yymsp[1].minor.yy18 = 0; } + break; +- case 237: /* when_clause ::= WHEN expr */ +- case 256: /* key_opt ::= KEY expr */ yytestcase(yyruleno==256); +-{ yymsp[-1].minor.yy314 = yymsp[0].minor.yy314; } ++ case 247: /* when_clause ::= WHEN expr */ ++ case 266: /* key_opt ::= KEY expr */ yytestcase(yyruleno==266); ++{ yymsp[-1].minor.yy18 = yymsp[0].minor.yy18; } + break; +- case 238: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ ++ case 248: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + { +- assert( yymsp[-2].minor.yy203!=0 ); +- yymsp[-2].minor.yy203->pLast->pNext = yymsp[-1].minor.yy203; +- yymsp[-2].minor.yy203->pLast = yymsp[-1].minor.yy203; ++ assert( yymsp[-2].minor.yy207!=0 ); ++ yymsp[-2].minor.yy207->pLast->pNext = yymsp[-1].minor.yy207; ++ yymsp[-2].minor.yy207->pLast = yymsp[-1].minor.yy207; + } + break; +- case 239: /* trigger_cmd_list ::= trigger_cmd SEMI */ ++ case 249: /* trigger_cmd_list ::= trigger_cmd SEMI */ + { +- assert( yymsp[-1].minor.yy203!=0 ); +- yymsp[-1].minor.yy203->pLast = yymsp[-1].minor.yy203; ++ assert( yymsp[-1].minor.yy207!=0 ); ++ yymsp[-1].minor.yy207->pLast = yymsp[-1].minor.yy207; + } + break; +- case 240: /* trnm ::= nm DOT nm */ ++ case 250: /* trnm ::= nm DOT nm */ + { + yymsp[-2].minor.yy0 = yymsp[0].minor.yy0; + sqlite3ErrorMsg(pParse, +@@ -143291,7 +150613,7 @@ + "statements within triggers"); + } + break; +- case 241: /* tridxby ::= INDEXED BY nm */ ++ case 251: /* tridxby ::= INDEXED BY nm */ + { + sqlite3ErrorMsg(pParse, + "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " +@@ -143298,7 +150620,7 @@ + "within triggers"); + } + break; +- case 242: /* tridxby ::= NOT INDEXED */ ++ case 252: /* tridxby ::= NOT INDEXED */ + { + sqlite3ErrorMsg(pParse, + "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " +@@ -143305,180 +150627,292 @@ + "within triggers"); + } + break; +- case 243: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */ +-{yylhsminor.yy203 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-5].minor.yy0, yymsp[-2].minor.yy322, yymsp[-1].minor.yy314, yymsp[-6].minor.yy4, yymsp[-7].minor.yy0.z, yymsp[0].minor.yy336);} +- yymsp[-7].minor.yy203 = yylhsminor.yy203; ++ case 253: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */ ++{yylhsminor.yy207 = sqlite3TriggerUpdateStep(pParse, &yymsp[-5].minor.yy0, yymsp[-2].minor.yy420, yymsp[-1].minor.yy18, yymsp[-6].minor.yy70, yymsp[-7].minor.yy0.z, yymsp[0].minor.yy392);} ++ yymsp[-7].minor.yy207 = yylhsminor.yy207; + break; +- case 244: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select scanpt */ +-{yylhsminor.yy203 = sqlite3TriggerInsertStep(pParse->db,&yymsp[-3].minor.yy0,yymsp[-2].minor.yy384,yymsp[-1].minor.yy387,yymsp[-5].minor.yy4,yymsp[-6].minor.yy336,yymsp[0].minor.yy336);/*yylhsminor.yy203-overwrites-yymsp[-5].minor.yy4*/} +- yymsp[-6].minor.yy203 = yylhsminor.yy203; ++ case 254: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ ++{ ++ yylhsminor.yy207 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy48,yymsp[-2].minor.yy489,yymsp[-6].minor.yy70,yymsp[-1].minor.yy340,yymsp[-7].minor.yy392,yymsp[0].minor.yy392);/*yylhsminor.yy207-overwrites-yymsp[-6].minor.yy70*/ ++} ++ yymsp[-7].minor.yy207 = yylhsminor.yy207; + break; +- case 245: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ +-{yylhsminor.yy203 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy314, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy336);} +- yymsp[-5].minor.yy203 = yylhsminor.yy203; ++ case 255: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ ++{yylhsminor.yy207 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy18, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy392);} ++ yymsp[-5].minor.yy207 = yylhsminor.yy207; + break; +- case 246: /* trigger_cmd ::= scanpt select scanpt */ +-{yylhsminor.yy203 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy387, yymsp[-2].minor.yy336, yymsp[0].minor.yy336); /*yylhsminor.yy203-overwrites-yymsp[-1].minor.yy387*/} +- yymsp[-2].minor.yy203 = yylhsminor.yy203; ++ case 256: /* trigger_cmd ::= scanpt select scanpt */ ++{yylhsminor.yy207 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy489, yymsp[-2].minor.yy392, yymsp[0].minor.yy392); /*yylhsminor.yy207-overwrites-yymsp[-1].minor.yy489*/} ++ yymsp[-2].minor.yy207 = yylhsminor.yy207; + break; +- case 247: /* expr ::= RAISE LP IGNORE RP */ ++ case 257: /* expr ::= RAISE LP IGNORE RP */ + { +- yymsp[-3].minor.yy314 = sqlite3PExpr(pParse, TK_RAISE, 0, 0); +- if( yymsp[-3].minor.yy314 ){ +- yymsp[-3].minor.yy314->affinity = OE_Ignore; ++ yymsp[-3].minor.yy18 = sqlite3PExpr(pParse, TK_RAISE, 0, 0); ++ if( yymsp[-3].minor.yy18 ){ ++ yymsp[-3].minor.yy18->affinity = OE_Ignore; + } + } + break; +- case 248: /* expr ::= RAISE LP raisetype COMMA nm RP */ ++ case 258: /* expr ::= RAISE LP raisetype COMMA nm RP */ + { +- yymsp[-5].minor.yy314 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); +- if( yymsp[-5].minor.yy314 ) { +- yymsp[-5].minor.yy314->affinity = (char)yymsp[-3].minor.yy4; ++ yymsp[-5].minor.yy18 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); ++ if( yymsp[-5].minor.yy18 ) { ++ yymsp[-5].minor.yy18->affinity = (char)yymsp[-3].minor.yy70; + } + } + break; +- case 249: /* raisetype ::= ROLLBACK */ +-{yymsp[0].minor.yy4 = OE_Rollback;} ++ case 259: /* raisetype ::= ROLLBACK */ ++{yymsp[0].minor.yy70 = OE_Rollback;} + break; +- case 251: /* raisetype ::= FAIL */ +-{yymsp[0].minor.yy4 = OE_Fail;} ++ case 261: /* raisetype ::= FAIL */ ++{yymsp[0].minor.yy70 = OE_Fail;} + break; +- case 252: /* cmd ::= DROP TRIGGER ifexists fullname */ ++ case 262: /* cmd ::= DROP TRIGGER ifexists fullname */ + { +- sqlite3DropTrigger(pParse,yymsp[0].minor.yy259,yymsp[-1].minor.yy4); ++ sqlite3DropTrigger(pParse,yymsp[0].minor.yy135,yymsp[-1].minor.yy70); + } + break; +- case 253: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ ++ case 263: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + { +- sqlite3Attach(pParse, yymsp[-3].minor.yy314, yymsp[-1].minor.yy314, yymsp[0].minor.yy314); ++ sqlite3Attach(pParse, yymsp[-3].minor.yy18, yymsp[-1].minor.yy18, yymsp[0].minor.yy18); + } + break; +- case 254: /* cmd ::= DETACH database_kw_opt expr */ ++ case 264: /* cmd ::= DETACH database_kw_opt expr */ + { +- sqlite3Detach(pParse, yymsp[0].minor.yy314); ++ sqlite3Detach(pParse, yymsp[0].minor.yy18); + } + break; +- case 257: /* cmd ::= REINDEX */ ++ case 267: /* cmd ::= REINDEX */ + {sqlite3Reindex(pParse, 0, 0);} + break; +- case 258: /* cmd ::= REINDEX nm dbnm */ ++ case 268: /* cmd ::= REINDEX nm dbnm */ + {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} + break; +- case 259: /* cmd ::= ANALYZE */ ++ case 269: /* cmd ::= ANALYZE */ + {sqlite3Analyze(pParse, 0, 0);} + break; +- case 260: /* cmd ::= ANALYZE nm dbnm */ ++ case 270: /* cmd ::= ANALYZE nm dbnm */ + {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} + break; +- case 261: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ ++ case 271: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ + { +- sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy259,&yymsp[0].minor.yy0); ++ sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy135,&yymsp[0].minor.yy0); + } + break; +- case 262: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ ++ case 272: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ + { + yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n; + sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0); + } + break; +- case 263: /* add_column_fullname ::= fullname */ ++ case 273: /* add_column_fullname ::= fullname */ + { + disableLookaside(pParse); +- sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy259); ++ sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy135); + } + break; +- case 264: /* cmd ::= create_vtab */ ++ case 274: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ ++{ ++ sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy135, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); ++} ++ break; ++ case 275: /* cmd ::= create_vtab */ + {sqlite3VtabFinishParse(pParse,0);} + break; +- case 265: /* cmd ::= create_vtab LP vtabarglist RP */ ++ case 276: /* cmd ::= create_vtab LP vtabarglist RP */ + {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} + break; +- case 266: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ ++ case 277: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + { +- sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy4); ++ sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy70); + } + break; +- case 267: /* vtabarg ::= */ ++ case 278: /* vtabarg ::= */ + {sqlite3VtabArgInit(pParse);} + break; +- case 268: /* vtabargtoken ::= ANY */ +- case 269: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==269); +- case 270: /* lp ::= LP */ yytestcase(yyruleno==270); ++ case 279: /* vtabargtoken ::= ANY */ ++ case 280: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==280); ++ case 281: /* lp ::= LP */ yytestcase(yyruleno==281); + {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} + break; +- case 271: /* with ::= WITH wqlist */ +- case 272: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==272); +-{ sqlite3WithPush(pParse, yymsp[0].minor.yy451, 1); } ++ case 282: /* with ::= WITH wqlist */ ++ case 283: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==283); ++{ sqlite3WithPush(pParse, yymsp[0].minor.yy449, 1); } + break; +- case 273: /* wqlist ::= nm eidlist_opt AS LP select RP */ ++ case 284: /* wqlist ::= nm eidlist_opt AS LP select RP */ + { +- yymsp[-5].minor.yy451 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy322, yymsp[-1].minor.yy387); /*A-overwrites-X*/ ++ yymsp[-5].minor.yy449 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy420, yymsp[-1].minor.yy489); /*A-overwrites-X*/ + } + break; +- case 274: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ ++ case 285: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ + { +- yymsp[-7].minor.yy451 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy451, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy322, yymsp[-1].minor.yy387); ++ yymsp[-7].minor.yy449 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy449, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy420, yymsp[-1].minor.yy489); + } + break; ++ case 286: /* windowdefn_list ::= windowdefn */ ++{ yylhsminor.yy327 = yymsp[0].minor.yy327; } ++ yymsp[0].minor.yy327 = yylhsminor.yy327; ++ break; ++ case 287: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */ ++{ ++ assert( yymsp[0].minor.yy327!=0 ); ++ yymsp[0].minor.yy327->pNextWin = yymsp[-2].minor.yy327; ++ yylhsminor.yy327 = yymsp[0].minor.yy327; ++} ++ yymsp[-2].minor.yy327 = yylhsminor.yy327; ++ break; ++ case 288: /* windowdefn ::= nm AS window */ ++{ ++ if( ALWAYS(yymsp[0].minor.yy327) ){ ++ yymsp[0].minor.yy327->zName = sqlite3DbStrNDup(pParse->db, yymsp[-2].minor.yy0.z, yymsp[-2].minor.yy0.n); ++ } ++ yylhsminor.yy327 = yymsp[0].minor.yy327; ++} ++ yymsp[-2].minor.yy327 = yylhsminor.yy327; ++ break; ++ case 289: /* window ::= LP part_opt orderby_opt frame_opt RP */ ++{ ++ yymsp[-4].minor.yy327 = yymsp[-1].minor.yy327; ++ if( ALWAYS(yymsp[-4].minor.yy327) ){ ++ yymsp[-4].minor.yy327->pPartition = yymsp[-3].minor.yy420; ++ yymsp[-4].minor.yy327->pOrderBy = yymsp[-2].minor.yy420; ++ } ++} ++ break; ++ case 290: /* part_opt ::= PARTITION BY nexprlist */ ++{ yymsp[-2].minor.yy420 = yymsp[0].minor.yy420; } ++ break; ++ case 291: /* part_opt ::= */ ++{ yymsp[1].minor.yy420 = 0; } ++ break; ++ case 292: /* frame_opt ::= */ ++{ ++ yymsp[1].minor.yy327 = sqlite3WindowAlloc(pParse, TK_RANGE, TK_UNBOUNDED, 0, TK_CURRENT, 0); ++} ++ break; ++ case 293: /* frame_opt ::= range_or_rows frame_bound_s */ ++{ ++ yylhsminor.yy327 = sqlite3WindowAlloc(pParse, yymsp[-1].minor.yy70, yymsp[0].minor.yy119.eType, yymsp[0].minor.yy119.pExpr, TK_CURRENT, 0); ++} ++ yymsp[-1].minor.yy327 = yylhsminor.yy327; ++ break; ++ case 294: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e */ ++{ ++ yylhsminor.yy327 = sqlite3WindowAlloc(pParse, yymsp[-4].minor.yy70, yymsp[-2].minor.yy119.eType, yymsp[-2].minor.yy119.pExpr, yymsp[0].minor.yy119.eType, yymsp[0].minor.yy119.pExpr); ++} ++ yymsp[-4].minor.yy327 = yylhsminor.yy327; ++ break; ++ case 295: /* range_or_rows ::= RANGE */ ++{ yymsp[0].minor.yy70 = TK_RANGE; } ++ break; ++ case 296: /* range_or_rows ::= ROWS */ ++{ yymsp[0].minor.yy70 = TK_ROWS; } ++ break; ++ case 297: /* frame_bound_s ::= frame_bound */ ++ case 299: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==299); ++{ yylhsminor.yy119 = yymsp[0].minor.yy119; } ++ yymsp[0].minor.yy119 = yylhsminor.yy119; ++ break; ++ case 298: /* frame_bound_s ::= UNBOUNDED PRECEDING */ ++ case 300: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==300); ++{yymsp[-1].minor.yy119.eType = TK_UNBOUNDED; yymsp[-1].minor.yy119.pExpr = 0;} ++ break; ++ case 301: /* frame_bound ::= expr PRECEDING */ ++{ yylhsminor.yy119.eType = TK_PRECEDING; yylhsminor.yy119.pExpr = yymsp[-1].minor.yy18; } ++ yymsp[-1].minor.yy119 = yylhsminor.yy119; ++ break; ++ case 302: /* frame_bound ::= CURRENT ROW */ ++{ yymsp[-1].minor.yy119.eType = TK_CURRENT ; yymsp[-1].minor.yy119.pExpr = 0; } ++ break; ++ case 303: /* frame_bound ::= expr FOLLOWING */ ++{ yylhsminor.yy119.eType = TK_FOLLOWING; yylhsminor.yy119.pExpr = yymsp[-1].minor.yy18; } ++ yymsp[-1].minor.yy119 = yylhsminor.yy119; ++ break; ++ case 304: /* window_clause ::= WINDOW windowdefn_list */ ++{ yymsp[-1].minor.yy327 = yymsp[0].minor.yy327; } ++ break; ++ case 305: /* over_clause ::= filter_opt OVER window */ ++{ ++ yylhsminor.yy327 = yymsp[0].minor.yy327; ++ assert( yylhsminor.yy327!=0 ); ++ yylhsminor.yy327->pFilter = yymsp[-2].minor.yy18; ++} ++ yymsp[-2].minor.yy327 = yylhsminor.yy327; ++ break; ++ case 306: /* over_clause ::= filter_opt OVER nm */ ++{ ++ yylhsminor.yy327 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); ++ if( yylhsminor.yy327 ){ ++ yylhsminor.yy327->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n); ++ yylhsminor.yy327->pFilter = yymsp[-2].minor.yy18; ++ }else{ ++ sqlite3ExprDelete(pParse->db, yymsp[-2].minor.yy18); ++ } ++} ++ yymsp[-2].minor.yy327 = yylhsminor.yy327; ++ break; ++ case 308: /* filter_opt ::= FILTER LP WHERE expr RP */ ++{ yymsp[-4].minor.yy18 = yymsp[-1].minor.yy18; } ++ break; + default: +- /* (275) input ::= cmdlist */ yytestcase(yyruleno==275); +- /* (276) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==276); +- /* (277) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=277); +- /* (278) ecmd ::= SEMI */ yytestcase(yyruleno==278); +- /* (279) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==279); +- /* (280) explain ::= */ yytestcase(yyruleno==280); +- /* (281) trans_opt ::= */ yytestcase(yyruleno==281); +- /* (282) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==282); +- /* (283) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==283); +- /* (284) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==284); +- /* (285) savepoint_opt ::= */ yytestcase(yyruleno==285); +- /* (286) cmd ::= create_table create_table_args */ yytestcase(yyruleno==286); +- /* (287) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==287); +- /* (288) columnlist ::= columnname carglist */ yytestcase(yyruleno==288); +- /* (289) nm ::= ID|INDEXED */ yytestcase(yyruleno==289); +- /* (290) nm ::= STRING */ yytestcase(yyruleno==290); +- /* (291) nm ::= JOIN_KW */ yytestcase(yyruleno==291); +- /* (292) typetoken ::= typename */ yytestcase(yyruleno==292); +- /* (293) typename ::= ID|STRING */ yytestcase(yyruleno==293); +- /* (294) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=294); +- /* (295) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=295); +- /* (296) carglist ::= carglist ccons */ yytestcase(yyruleno==296); +- /* (297) carglist ::= */ yytestcase(yyruleno==297); +- /* (298) ccons ::= NULL onconf */ yytestcase(yyruleno==298); +- /* (299) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==299); +- /* (300) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==300); +- /* (301) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=301); +- /* (302) tconscomma ::= */ yytestcase(yyruleno==302); +- /* (303) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=303); +- /* (304) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=304); +- /* (305) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=305); +- /* (306) oneselect ::= values */ yytestcase(yyruleno==306); +- /* (307) sclp ::= selcollist COMMA */ yytestcase(yyruleno==307); +- /* (308) as ::= ID|STRING */ yytestcase(yyruleno==308); +- /* (309) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=309); +- /* (310) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==310); +- /* (311) exprlist ::= nexprlist */ yytestcase(yyruleno==311); +- /* (312) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=312); +- /* (313) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=313); +- /* (314) nmnum ::= ON */ yytestcase(yyruleno==314); +- /* (315) nmnum ::= DELETE */ yytestcase(yyruleno==315); +- /* (316) nmnum ::= DEFAULT */ yytestcase(yyruleno==316); +- /* (317) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==317); +- /* (318) foreach_clause ::= */ yytestcase(yyruleno==318); +- /* (319) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==319); +- /* (320) trnm ::= nm */ yytestcase(yyruleno==320); +- /* (321) tridxby ::= */ yytestcase(yyruleno==321); +- /* (322) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==322); +- /* (323) database_kw_opt ::= */ yytestcase(yyruleno==323); +- /* (324) kwcolumn_opt ::= */ yytestcase(yyruleno==324); +- /* (325) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==325); +- /* (326) vtabarglist ::= vtabarg */ yytestcase(yyruleno==326); +- /* (327) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==327); +- /* (328) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==328); +- /* (329) anylist ::= */ yytestcase(yyruleno==329); +- /* (330) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==330); +- /* (331) anylist ::= anylist ANY */ yytestcase(yyruleno==331); +- /* (332) with ::= */ yytestcase(yyruleno==332); ++ /* (309) input ::= cmdlist */ yytestcase(yyruleno==309); ++ /* (310) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==310); ++ /* (311) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=311); ++ /* (312) ecmd ::= SEMI */ yytestcase(yyruleno==312); ++ /* (313) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==313); ++ /* (314) ecmd ::= explain cmdx */ yytestcase(yyruleno==314); ++ /* (315) trans_opt ::= */ yytestcase(yyruleno==315); ++ /* (316) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==316); ++ /* (317) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==317); ++ /* (318) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==318); ++ /* (319) savepoint_opt ::= */ yytestcase(yyruleno==319); ++ /* (320) cmd ::= create_table create_table_args */ yytestcase(yyruleno==320); ++ /* (321) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==321); ++ /* (322) columnlist ::= columnname carglist */ yytestcase(yyruleno==322); ++ /* (323) nm ::= ID|INDEXED */ yytestcase(yyruleno==323); ++ /* (324) nm ::= STRING */ yytestcase(yyruleno==324); ++ /* (325) nm ::= JOIN_KW */ yytestcase(yyruleno==325); ++ /* (326) typetoken ::= typename */ yytestcase(yyruleno==326); ++ /* (327) typename ::= ID|STRING */ yytestcase(yyruleno==327); ++ /* (328) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=328); ++ /* (329) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=329); ++ /* (330) carglist ::= carglist ccons */ yytestcase(yyruleno==330); ++ /* (331) carglist ::= */ yytestcase(yyruleno==331); ++ /* (332) ccons ::= NULL onconf */ yytestcase(yyruleno==332); ++ /* (333) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==333); ++ /* (334) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==334); ++ /* (335) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=335); ++ /* (336) tconscomma ::= */ yytestcase(yyruleno==336); ++ /* (337) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=337); ++ /* (338) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=338); ++ /* (339) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=339); ++ /* (340) oneselect ::= values */ yytestcase(yyruleno==340); ++ /* (341) sclp ::= selcollist COMMA */ yytestcase(yyruleno==341); ++ /* (342) as ::= ID|STRING */ yytestcase(yyruleno==342); ++ /* (343) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=343); ++ /* (344) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==344); ++ /* (345) exprlist ::= nexprlist */ yytestcase(yyruleno==345); ++ /* (346) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=346); ++ /* (347) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=347); ++ /* (348) nmnum ::= ON */ yytestcase(yyruleno==348); ++ /* (349) nmnum ::= DELETE */ yytestcase(yyruleno==349); ++ /* (350) nmnum ::= DEFAULT */ yytestcase(yyruleno==350); ++ /* (351) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==351); ++ /* (352) foreach_clause ::= */ yytestcase(yyruleno==352); ++ /* (353) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==353); ++ /* (354) trnm ::= nm */ yytestcase(yyruleno==354); ++ /* (355) tridxby ::= */ yytestcase(yyruleno==355); ++ /* (356) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==356); ++ /* (357) database_kw_opt ::= */ yytestcase(yyruleno==357); ++ /* (358) kwcolumn_opt ::= */ yytestcase(yyruleno==358); ++ /* (359) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==359); ++ /* (360) vtabarglist ::= vtabarg */ yytestcase(yyruleno==360); ++ /* (361) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==361); ++ /* (362) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==362); ++ /* (363) anylist ::= */ yytestcase(yyruleno==363); ++ /* (364) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==364); ++ /* (365) anylist ::= anylist ANY */ yytestcase(yyruleno==365); ++ /* (366) with ::= */ yytestcase(yyruleno==366); + break; + /********** End reduce actions ************************************************/ + }; +@@ -143499,6 +150933,7 @@ + yymsp->stateno = (YYACTIONTYPE)yyact; + yymsp->major = (YYCODETYPE)yygoto; + yyTraceShift(yypParser, yyact, "... then shift"); ++ return yyact; + } + + /* +@@ -143508,7 +150943,8 @@ + static void yy_parse_failed( + yyParser *yypParser /* The parser */ + ){ +- sqlite3ParserARG_FETCH; ++ sqlite3ParserARG_FETCH ++ sqlite3ParserCTX_FETCH + #ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); +@@ -143519,7 +150955,8 @@ + ** parser fails */ + /************ Begin %parse_failure code ***************************************/ + /************ End %parse_failure code *****************************************/ +- sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ ++ sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ ++ sqlite3ParserCTX_STORE + } + #endif /* YYNOERRORRECOVERY */ + +@@ -143531,7 +150968,8 @@ + int yymajor, /* The major type of the error token */ + sqlite3ParserTOKENTYPE yyminor /* The minor type of the error token */ + ){ +- sqlite3ParserARG_FETCH; ++ sqlite3ParserARG_FETCH ++ sqlite3ParserCTX_FETCH + #define TOKEN yyminor + /************ Begin %syntax_error code ****************************************/ + +@@ -143542,7 +150980,8 @@ + sqlite3ErrorMsg(pParse, "incomplete input"); + } + /************ End %syntax_error code ******************************************/ +- sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ ++ sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ ++ sqlite3ParserCTX_STORE + } + + /* +@@ -143551,7 +150990,8 @@ + static void yy_accept( + yyParser *yypParser /* The parser */ + ){ +- sqlite3ParserARG_FETCH; ++ sqlite3ParserARG_FETCH ++ sqlite3ParserCTX_FETCH + #ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); +@@ -143565,7 +151005,8 @@ + ** parser accepts */ + /*********** Begin %parse_accept code *****************************************/ + /*********** End %parse_accept code *******************************************/ +- sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ ++ sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ ++ sqlite3ParserCTX_STORE + } + + /* The main parser program. +@@ -143594,7 +151035,7 @@ + sqlite3ParserARG_PDECL /* Optional %extra_argument parameter */ + ){ + YYMINORTYPE yyminorunion; +- unsigned int yyact; /* The parser action. */ ++ YYACTIONTYPE yyact; /* The parser action. */ + #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) + int yyendofinput; /* True if we are at the end of input */ + #endif +@@ -143601,38 +151042,40 @@ + #ifdef YYERRORSYMBOL + int yyerrorhit = 0; /* True if yymajor has invoked an error */ + #endif +- yyParser *yypParser; /* The parser */ ++ yyParser *yypParser = (yyParser*)yyp; /* The parser */ ++ sqlite3ParserCTX_FETCH ++ sqlite3ParserARG_STORE + +- yypParser = (yyParser*)yyp; + assert( yypParser->yytos!=0 ); + #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) + yyendofinput = (yymajor==0); + #endif +- sqlite3ParserARG_STORE; + ++ yyact = yypParser->yytos->stateno; + #ifndef NDEBUG + if( yyTraceFILE ){ +- int stateno = yypParser->yytos->stateno; +- if( stateno < YY_MIN_REDUCE ){ ++ if( yyact < YY_MIN_REDUCE ){ + fprintf(yyTraceFILE,"%sInput '%s' in state %d\n", +- yyTracePrompt,yyTokenName[yymajor],stateno); ++ yyTracePrompt,yyTokenName[yymajor],yyact); + }else{ + fprintf(yyTraceFILE,"%sInput '%s' with pending reduce %d\n", +- yyTracePrompt,yyTokenName[yymajor],stateno-YY_MIN_REDUCE); ++ yyTracePrompt,yyTokenName[yymajor],yyact-YY_MIN_REDUCE); + } + } + #endif + + do{ +- yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor); ++ assert( yyact==yypParser->yytos->stateno ); ++ yyact = yy_find_shift_action((YYCODETYPE)yymajor,yyact); + if( yyact >= YY_MIN_REDUCE ){ +- yy_reduce(yypParser,yyact-YY_MIN_REDUCE,yymajor,yyminor); ++ yyact = yy_reduce(yypParser,yyact-YY_MIN_REDUCE,yymajor, ++ yyminor sqlite3ParserCTX_PARAM); + }else if( yyact <= YY_MAX_SHIFTREDUCE ){ +- yy_shift(yypParser,yyact,yymajor,yyminor); ++ yy_shift(yypParser,yyact,(YYCODETYPE)yymajor,yyminor); + #ifndef YYNOERRORRECOVERY + yypParser->yyerrcnt--; + #endif +- yymajor = YYNOCODE; ++ break; + }else if( yyact==YY_ACCEPT_ACTION ){ + yypParser->yytos--; + yy_accept(yypParser); +@@ -143683,10 +151126,9 @@ + yymajor = YYNOCODE; + }else{ + while( yypParser->yytos >= yypParser->yystack +- && yymx != YYERRORSYMBOL + && (yyact = yy_find_reduce_action( + yypParser->yytos->stateno, +- YYERRORSYMBOL)) >= YY_MIN_REDUCE ++ YYERRORSYMBOL)) > YY_MAX_SHIFTREDUCE + ){ + yy_pop_parser_stack(yypParser); + } +@@ -143703,6 +151145,8 @@ + } + yypParser->yyerrcnt = 3; + yyerrorhit = 1; ++ if( yymajor==YYNOCODE ) break; ++ yyact = yypParser->yytos->stateno; + #elif defined(YYNOERRORRECOVERY) + /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to + ** do any kind of error recovery. Instead, simply invoke the syntax +@@ -143713,8 +151157,7 @@ + */ + yy_syntax_error(yypParser,yymajor, yyminor); + yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); +- yymajor = YYNOCODE; +- ++ break; + #else /* YYERRORSYMBOL is not defined */ + /* This is what we do if the grammar does not define ERROR: + ** +@@ -143736,10 +151179,10 @@ + yypParser->yyerrcnt = -1; + #endif + } +- yymajor = YYNOCODE; ++ break; + #endif + } +- }while( yymajor!=YYNOCODE && yypParser->yytos>yypParser->yystack ); ++ }while( yypParser->yytos>yypParser->yystack ); + #ifndef NDEBUG + if( yyTraceFILE ){ + yyStackEntry *i; +@@ -143755,6 +151198,21 @@ + return; + } + ++/* ++** Return the fallback token corresponding to canonical token iToken, or ++** 0 if iToken has no fallback. ++*/ ++SQLITE_PRIVATE int sqlite3ParserFallback(int iToken){ ++#ifdef YYFALLBACK ++ if( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ){ ++ return yyFallback[iToken]; ++ } ++#else ++ (void)iToken; ++#endif ++ return 0; ++} ++ + /************** End of parse.c ***********************************************/ + /************** Begin file tokenize.c ****************************************/ + /* +@@ -143813,11 +151271,12 @@ + #define CC_TILDA 25 /* '~' */ + #define CC_DOT 26 /* '.' */ + #define CC_ILLEGAL 27 /* Illegal character */ ++#define CC_NUL 28 /* 0x00 */ + + static const unsigned char aiClass[] = { + #ifdef SQLITE_ASCII + /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ +-/* 0x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 27, 7, 7, 27, 27, ++/* 0x */ 28, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 27, 7, 7, 27, 27, + /* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + /* 2x */ 7, 15, 8, 5, 4, 22, 24, 8, 17, 18, 21, 20, 23, 11, 26, 16, + /* 3x */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 19, 12, 14, 13, 6, +@@ -143916,19 +151375,20 @@ + ** is substantially reduced. This is important for embedded applications + ** on platforms with limited memory. + */ +-/* Hash score: 182 */ +-/* zKWText[] encodes 834 bytes of keyword text in 554 bytes */ ++/* Hash score: 208 */ ++/* zKWText[] encodes 923 bytes of keyword text in 614 bytes */ + /* REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT */ + /* ABLEFTHENDEFERRABLELSEXCEPTRANSACTIONATURALTERAISEXCLUSIVE */ + /* XISTSAVEPOINTERSECTRIGGEREFERENCESCONSTRAINTOFFSETEMPORARY */ +-/* UNIQUERYWITHOUTERELEASEATTACHAVINGROUPDATEBEGINNERECURSIVE */ +-/* BETWEENOTNULLIKECASCADELETECASECOLLATECREATECURRENT_DATEDETACH */ +-/* IMMEDIATEJOINSERTMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMITWHEN */ +-/* WHERENAMEAFTEREPLACEANDEFAULTAUTOINCREMENTCASTCOLUMNCOMMIT */ +-/* CONFLICTCROSSCURRENT_TIMESTAMPRIMARYDEFERREDISTINCTDROPFAIL */ +-/* FROMFULLGLOBYIFISNULLORDERESTRICTRIGHTROLLBACKROWUNIONUSING */ +-/* VACUUMVIEWINITIALLY */ +-static const char zKWText[553] = { ++/* UNIQUERYWITHOUTERELEASEATTACHAVINGROUPDATEBEGINNERANGEBETWEEN */ ++/* OTHINGLOBYCASCADELETECASECOLLATECREATECURRENT_DATEDETACH */ ++/* IMMEDIATEJOINSERTLIKEMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMIT */ ++/* WHENOTNULLWHERECURSIVEAFTERENAMEANDEFAULTAUTOINCREMENTCAST */ ++/* COLUMNCOMMITCONFLICTCROSSCURRENT_TIMESTAMPARTITIONDEFERRED */ ++/* ISTINCTDROPRECEDINGFAILFILTEREPLACEFOLLOWINGFROMFULLIFISNULL */ ++/* ORDERESTRICTOVERIGHTROLLBACKROWSUNBOUNDEDUNIONUSINGVACUUMVIEW */ ++/* INDOWINITIALLYPRIMARY */ ++static const char zKWText[613] = { + 'R','E','I','N','D','E','X','E','D','E','S','C','A','P','E','A','C','H', + 'E','C','K','E','Y','B','E','F','O','R','E','I','G','N','O','R','E','G', + 'E','X','P','L','A','I','N','S','T','E','A','D','D','A','T','A','B','A', +@@ -143941,83 +151401,90 @@ + 'O','F','F','S','E','T','E','M','P','O','R','A','R','Y','U','N','I','Q', + 'U','E','R','Y','W','I','T','H','O','U','T','E','R','E','L','E','A','S', + 'E','A','T','T','A','C','H','A','V','I','N','G','R','O','U','P','D','A', +- 'T','E','B','E','G','I','N','N','E','R','E','C','U','R','S','I','V','E', +- 'B','E','T','W','E','E','N','O','T','N','U','L','L','I','K','E','C','A', +- 'S','C','A','D','E','L','E','T','E','C','A','S','E','C','O','L','L','A', +- 'T','E','C','R','E','A','T','E','C','U','R','R','E','N','T','_','D','A', +- 'T','E','D','E','T','A','C','H','I','M','M','E','D','I','A','T','E','J', +- 'O','I','N','S','E','R','T','M','A','T','C','H','P','L','A','N','A','L', +- 'Y','Z','E','P','R','A','G','M','A','B','O','R','T','V','A','L','U','E', +- 'S','V','I','R','T','U','A','L','I','M','I','T','W','H','E','N','W','H', +- 'E','R','E','N','A','M','E','A','F','T','E','R','E','P','L','A','C','E', +- 'A','N','D','E','F','A','U','L','T','A','U','T','O','I','N','C','R','E', +- 'M','E','N','T','C','A','S','T','C','O','L','U','M','N','C','O','M','M', +- 'I','T','C','O','N','F','L','I','C','T','C','R','O','S','S','C','U','R', +- 'R','E','N','T','_','T','I','M','E','S','T','A','M','P','R','I','M','A', +- 'R','Y','D','E','F','E','R','R','E','D','I','S','T','I','N','C','T','D', +- 'R','O','P','F','A','I','L','F','R','O','M','F','U','L','L','G','L','O', +- 'B','Y','I','F','I','S','N','U','L','L','O','R','D','E','R','E','S','T', +- 'R','I','C','T','R','I','G','H','T','R','O','L','L','B','A','C','K','R', +- 'O','W','U','N','I','O','N','U','S','I','N','G','V','A','C','U','U','M', +- 'V','I','E','W','I','N','I','T','I','A','L','L','Y', ++ 'T','E','B','E','G','I','N','N','E','R','A','N','G','E','B','E','T','W', ++ 'E','E','N','O','T','H','I','N','G','L','O','B','Y','C','A','S','C','A', ++ 'D','E','L','E','T','E','C','A','S','E','C','O','L','L','A','T','E','C', ++ 'R','E','A','T','E','C','U','R','R','E','N','T','_','D','A','T','E','D', ++ 'E','T','A','C','H','I','M','M','E','D','I','A','T','E','J','O','I','N', ++ 'S','E','R','T','L','I','K','E','M','A','T','C','H','P','L','A','N','A', ++ 'L','Y','Z','E','P','R','A','G','M','A','B','O','R','T','V','A','L','U', ++ 'E','S','V','I','R','T','U','A','L','I','M','I','T','W','H','E','N','O', ++ 'T','N','U','L','L','W','H','E','R','E','C','U','R','S','I','V','E','A', ++ 'F','T','E','R','E','N','A','M','E','A','N','D','E','F','A','U','L','T', ++ 'A','U','T','O','I','N','C','R','E','M','E','N','T','C','A','S','T','C', ++ 'O','L','U','M','N','C','O','M','M','I','T','C','O','N','F','L','I','C', ++ 'T','C','R','O','S','S','C','U','R','R','E','N','T','_','T','I','M','E', ++ 'S','T','A','M','P','A','R','T','I','T','I','O','N','D','E','F','E','R', ++ 'R','E','D','I','S','T','I','N','C','T','D','R','O','P','R','E','C','E', ++ 'D','I','N','G','F','A','I','L','F','I','L','T','E','R','E','P','L','A', ++ 'C','E','F','O','L','L','O','W','I','N','G','F','R','O','M','F','U','L', ++ 'L','I','F','I','S','N','U','L','L','O','R','D','E','R','E','S','T','R', ++ 'I','C','T','O','V','E','R','I','G','H','T','R','O','L','L','B','A','C', ++ 'K','R','O','W','S','U','N','B','O','U','N','D','E','D','U','N','I','O', ++ 'N','U','S','I','N','G','V','A','C','U','U','M','V','I','E','W','I','N', ++ 'D','O','W','I','N','I','T','I','A','L','L','Y','P','R','I','M','A','R', ++ 'Y', + }; + /* aKWHash[i] is the hash value for the i-th keyword */ + static const unsigned char aKWHash[127] = { +- 76, 105, 117, 74, 0, 45, 0, 0, 82, 0, 77, 0, 0, +- 42, 12, 78, 15, 0, 116, 85, 54, 112, 0, 19, 0, 0, +- 121, 0, 119, 115, 0, 22, 93, 0, 9, 0, 0, 70, 71, +- 0, 69, 6, 0, 48, 90, 102, 0, 118, 101, 0, 0, 44, +- 0, 103, 24, 0, 17, 0, 122, 53, 23, 0, 5, 110, 25, +- 96, 0, 0, 124, 106, 60, 123, 57, 28, 55, 0, 91, 0, +- 100, 26, 0, 99, 0, 0, 0, 95, 92, 97, 88, 109, 14, +- 39, 108, 0, 81, 0, 18, 89, 111, 32, 0, 120, 80, 113, +- 62, 46, 84, 0, 0, 94, 40, 59, 114, 0, 36, 0, 0, +- 29, 0, 86, 63, 64, 0, 20, 61, 0, 56, ++ 74, 109, 124, 72, 106, 45, 0, 0, 81, 0, 76, 61, 0, ++ 42, 12, 77, 15, 0, 123, 84, 54, 118, 125, 19, 0, 0, ++ 130, 0, 128, 121, 0, 22, 96, 0, 9, 0, 0, 115, 69, ++ 0, 67, 6, 0, 48, 93, 136, 0, 126, 104, 0, 0, 44, ++ 0, 107, 24, 0, 17, 0, 131, 53, 23, 0, 5, 62, 132, ++ 99, 0, 0, 135, 110, 60, 134, 57, 113, 55, 0, 94, 0, ++ 103, 26, 0, 102, 0, 0, 0, 98, 95, 100, 105, 117, 14, ++ 39, 116, 0, 80, 0, 133, 114, 92, 59, 0, 129, 79, 119, ++ 86, 46, 83, 0, 0, 97, 40, 122, 120, 0, 127, 0, 0, ++ 29, 0, 89, 87, 88, 0, 20, 85, 111, 56, + }; + /* aKWNext[] forms the hash collision chain. If aKWHash[i]==0 + ** then the i-th keyword has no more hash collisions. Otherwise, + ** the next keyword with the same hash is aKWHash[i]-1. */ +-static const unsigned char aKWNext[124] = { ++static const unsigned char aKWNext[136] = { + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, + 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 33, 0, 21, 0, 0, 0, 0, 0, 50, +- 0, 43, 3, 47, 0, 0, 0, 0, 30, 0, 58, 0, 38, +- 0, 0, 0, 1, 66, 0, 0, 67, 0, 41, 0, 0, 0, +- 0, 0, 0, 49, 65, 0, 0, 0, 0, 31, 52, 16, 34, +- 10, 0, 0, 0, 0, 0, 0, 0, 11, 72, 79, 0, 8, +- 0, 104, 98, 0, 107, 0, 87, 0, 75, 51, 0, 27, 37, +- 73, 83, 0, 35, 68, 0, 0, ++ 0, 43, 3, 47, 0, 0, 32, 0, 0, 0, 0, 0, 0, ++ 0, 1, 64, 0, 0, 65, 0, 41, 0, 38, 0, 0, 0, ++ 0, 0, 49, 75, 0, 0, 30, 0, 58, 0, 0, 0, 31, ++ 63, 16, 34, 10, 0, 0, 0, 0, 0, 0, 0, 11, 70, ++ 91, 0, 0, 8, 0, 108, 0, 101, 28, 52, 68, 0, 112, ++ 0, 73, 51, 0, 90, 27, 37, 0, 71, 36, 82, 0, 35, ++ 66, 25, 18, 0, 0, 78, + }; + /* aKWLen[i] is the length (in bytes) of the i-th keyword */ +-static const unsigned char aKWLen[124] = { ++static const unsigned char aKWLen[136] = { + 7, 7, 5, 4, 6, 4, 5, 3, 6, 7, 3, 6, 6, + 7, 7, 3, 8, 2, 6, 5, 4, 4, 3, 10, 4, 6, + 11, 6, 2, 7, 5, 5, 9, 6, 9, 9, 7, 10, 10, + 4, 6, 2, 3, 9, 4, 2, 6, 5, 7, 4, 5, 7, +- 6, 6, 5, 6, 5, 5, 9, 7, 7, 3, 2, 4, 4, +- 7, 3, 6, 4, 7, 6, 12, 6, 9, 4, 6, 5, 4, +- 7, 6, 5, 6, 7, 5, 4, 5, 6, 5, 7, 3, 7, +- 13, 2, 2, 4, 6, 6, 8, 5, 17, 12, 7, 8, 8, +- 2, 4, 4, 4, 4, 4, 2, 2, 6, 5, 8, 5, 8, +- 3, 5, 5, 6, 4, 9, 3, ++ 6, 6, 5, 6, 5, 5, 5, 7, 7, 4, 2, 7, 3, ++ 6, 4, 7, 6, 12, 6, 9, 4, 6, 4, 5, 4, 7, ++ 6, 5, 6, 7, 5, 4, 7, 3, 2, 4, 5, 9, 5, ++ 6, 3, 7, 13, 2, 2, 4, 6, 6, 8, 5, 17, 12, ++ 7, 9, 8, 8, 2, 4, 9, 4, 6, 7, 9, 4, 4, ++ 2, 6, 5, 8, 4, 5, 8, 4, 3, 9, 5, 5, 6, ++ 4, 6, 2, 9, 3, 7, + }; + /* aKWOffset[i] is the index into zKWText[] of the start of + ** the text for the i-th keyword. */ +-static const unsigned short int aKWOffset[124] = { ++static const unsigned short int aKWOffset[136] = { + 0, 2, 2, 8, 9, 14, 16, 20, 23, 25, 25, 29, 33, + 36, 41, 46, 48, 53, 54, 59, 62, 65, 67, 69, 78, 81, + 86, 91, 95, 96, 101, 105, 109, 117, 122, 128, 136, 142, 152, + 159, 162, 162, 165, 167, 167, 171, 176, 179, 184, 184, 188, 192, +- 199, 204, 209, 212, 218, 221, 225, 234, 240, 240, 240, 243, 246, +- 250, 251, 255, 261, 265, 272, 278, 290, 296, 305, 307, 313, 318, +- 320, 327, 332, 337, 343, 349, 354, 358, 361, 367, 371, 378, 380, +- 387, 389, 391, 400, 404, 410, 416, 424, 429, 429, 445, 452, 459, +- 460, 467, 471, 475, 479, 483, 486, 488, 490, 496, 500, 508, 513, +- 521, 524, 529, 534, 540, 544, 549, ++ 199, 204, 209, 212, 218, 221, 225, 230, 236, 242, 245, 247, 248, ++ 252, 258, 262, 269, 275, 287, 293, 302, 304, 310, 314, 319, 321, ++ 328, 333, 338, 344, 350, 355, 358, 358, 358, 361, 365, 368, 377, ++ 381, 387, 389, 396, 398, 400, 409, 413, 419, 425, 433, 438, 438, ++ 438, 454, 463, 470, 471, 478, 481, 490, 494, 499, 506, 515, 519, ++ 523, 525, 531, 535, 543, 546, 551, 559, 559, 563, 572, 577, 582, ++ 588, 591, 594, 597, 602, 606, + }; + /* aKWCode[i] is the parser symbol code for the i-th keyword */ +-static const unsigned char aKWCode[124] = { ++static const unsigned char aKWCode[136] = { + TK_REINDEX, TK_INDEXED, TK_INDEX, TK_DESC, TK_ESCAPE, + TK_EACH, TK_CHECK, TK_KEY, TK_BEFORE, TK_FOREIGN, + TK_FOR, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD, +@@ -144029,20 +151496,23 @@ + TK_OFFSET, TK_OF, TK_SET, TK_TEMP, TK_TEMP, + TK_OR, TK_UNIQUE, TK_QUERY, TK_WITHOUT, TK_WITH, + TK_JOIN_KW, TK_RELEASE, TK_ATTACH, TK_HAVING, TK_GROUP, +- TK_UPDATE, TK_BEGIN, TK_JOIN_KW, TK_RECURSIVE, TK_BETWEEN, +- TK_NOTNULL, TK_NOT, TK_NO, TK_NULL, TK_LIKE_KW, +- TK_CASCADE, TK_ASC, TK_DELETE, TK_CASE, TK_COLLATE, +- TK_CREATE, TK_CTIME_KW, TK_DETACH, TK_IMMEDIATE, TK_JOIN, +- TK_INSERT, TK_MATCH, TK_PLAN, TK_ANALYZE, TK_PRAGMA, +- TK_ABORT, TK_VALUES, TK_VIRTUAL, TK_LIMIT, TK_WHEN, +- TK_WHERE, TK_RENAME, TK_AFTER, TK_REPLACE, TK_AND, +- TK_DEFAULT, TK_AUTOINCR, TK_TO, TK_IN, TK_CAST, +- TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_JOIN_KW, TK_CTIME_KW, +- TK_CTIME_KW, TK_PRIMARY, TK_DEFERRED, TK_DISTINCT, TK_IS, +- TK_DROP, TK_FAIL, TK_FROM, TK_JOIN_KW, TK_LIKE_KW, +- TK_BY, TK_IF, TK_ISNULL, TK_ORDER, TK_RESTRICT, +- TK_JOIN_KW, TK_ROLLBACK, TK_ROW, TK_UNION, TK_USING, +- TK_VACUUM, TK_VIEW, TK_INITIALLY, TK_ALL, ++ TK_UPDATE, TK_BEGIN, TK_JOIN_KW, TK_RANGE, TK_BETWEEN, ++ TK_NOTHING, TK_LIKE_KW, TK_BY, TK_CASCADE, TK_ASC, ++ TK_DELETE, TK_CASE, TK_COLLATE, TK_CREATE, TK_CTIME_KW, ++ TK_DETACH, TK_IMMEDIATE, TK_JOIN, TK_INSERT, TK_LIKE_KW, ++ TK_MATCH, TK_PLAN, TK_ANALYZE, TK_PRAGMA, TK_ABORT, ++ TK_VALUES, TK_VIRTUAL, TK_LIMIT, TK_WHEN, TK_NOTNULL, ++ TK_NOT, TK_NO, TK_NULL, TK_WHERE, TK_RECURSIVE, ++ TK_AFTER, TK_RENAME, TK_AND, TK_DEFAULT, TK_AUTOINCR, ++ TK_TO, TK_IN, TK_CAST, TK_COLUMNKW, TK_COMMIT, ++ TK_CONFLICT, TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW, TK_CURRENT, ++ TK_PARTITION, TK_DEFERRED, TK_DISTINCT, TK_IS, TK_DROP, ++ TK_PRECEDING, TK_FAIL, TK_FILTER, TK_REPLACE, TK_FOLLOWING, ++ TK_FROM, TK_JOIN_KW, TK_IF, TK_ISNULL, TK_ORDER, ++ TK_RESTRICT, TK_OVER, TK_JOIN_KW, TK_ROLLBACK, TK_ROWS, ++ TK_ROW, TK_UNBOUNDED, TK_UNION, TK_USING, TK_VACUUM, ++ TK_VIEW, TK_WINDOW, TK_DO, TK_INITIALLY, TK_ALL, ++ TK_PRIMARY, + }; + /* Check to see if z[0..n-1] is a keyword. If it is, write the + ** parser symbol code for that keyword into *pType. Always +@@ -144121,72 +151591,84 @@ + testcase( i==55 ); /* UPDATE */ + testcase( i==56 ); /* BEGIN */ + testcase( i==57 ); /* INNER */ +- testcase( i==58 ); /* RECURSIVE */ ++ testcase( i==58 ); /* RANGE */ + testcase( i==59 ); /* BETWEEN */ +- testcase( i==60 ); /* NOTNULL */ +- testcase( i==61 ); /* NOT */ +- testcase( i==62 ); /* NO */ +- testcase( i==63 ); /* NULL */ +- testcase( i==64 ); /* LIKE */ +- testcase( i==65 ); /* CASCADE */ +- testcase( i==66 ); /* ASC */ +- testcase( i==67 ); /* DELETE */ +- testcase( i==68 ); /* CASE */ +- testcase( i==69 ); /* COLLATE */ +- testcase( i==70 ); /* CREATE */ +- testcase( i==71 ); /* CURRENT_DATE */ +- testcase( i==72 ); /* DETACH */ +- testcase( i==73 ); /* IMMEDIATE */ +- testcase( i==74 ); /* JOIN */ +- testcase( i==75 ); /* INSERT */ +- testcase( i==76 ); /* MATCH */ +- testcase( i==77 ); /* PLAN */ +- testcase( i==78 ); /* ANALYZE */ +- testcase( i==79 ); /* PRAGMA */ +- testcase( i==80 ); /* ABORT */ +- testcase( i==81 ); /* VALUES */ +- testcase( i==82 ); /* VIRTUAL */ +- testcase( i==83 ); /* LIMIT */ +- testcase( i==84 ); /* WHEN */ +- testcase( i==85 ); /* WHERE */ +- testcase( i==86 ); /* RENAME */ +- testcase( i==87 ); /* AFTER */ +- testcase( i==88 ); /* REPLACE */ +- testcase( i==89 ); /* AND */ +- testcase( i==90 ); /* DEFAULT */ +- testcase( i==91 ); /* AUTOINCREMENT */ +- testcase( i==92 ); /* TO */ +- testcase( i==93 ); /* IN */ +- testcase( i==94 ); /* CAST */ +- testcase( i==95 ); /* COLUMN */ +- testcase( i==96 ); /* COMMIT */ +- testcase( i==97 ); /* CONFLICT */ +- testcase( i==98 ); /* CROSS */ +- testcase( i==99 ); /* CURRENT_TIMESTAMP */ +- testcase( i==100 ); /* CURRENT_TIME */ +- testcase( i==101 ); /* PRIMARY */ +- testcase( i==102 ); /* DEFERRED */ +- testcase( i==103 ); /* DISTINCT */ +- testcase( i==104 ); /* IS */ +- testcase( i==105 ); /* DROP */ +- testcase( i==106 ); /* FAIL */ +- testcase( i==107 ); /* FROM */ +- testcase( i==108 ); /* FULL */ +- testcase( i==109 ); /* GLOB */ +- testcase( i==110 ); /* BY */ +- testcase( i==111 ); /* IF */ +- testcase( i==112 ); /* ISNULL */ +- testcase( i==113 ); /* ORDER */ +- testcase( i==114 ); /* RESTRICT */ +- testcase( i==115 ); /* RIGHT */ +- testcase( i==116 ); /* ROLLBACK */ +- testcase( i==117 ); /* ROW */ +- testcase( i==118 ); /* UNION */ +- testcase( i==119 ); /* USING */ +- testcase( i==120 ); /* VACUUM */ +- testcase( i==121 ); /* VIEW */ +- testcase( i==122 ); /* INITIALLY */ +- testcase( i==123 ); /* ALL */ ++ testcase( i==60 ); /* NOTHING */ ++ testcase( i==61 ); /* GLOB */ ++ testcase( i==62 ); /* BY */ ++ testcase( i==63 ); /* CASCADE */ ++ testcase( i==64 ); /* ASC */ ++ testcase( i==65 ); /* DELETE */ ++ testcase( i==66 ); /* CASE */ ++ testcase( i==67 ); /* COLLATE */ ++ testcase( i==68 ); /* CREATE */ ++ testcase( i==69 ); /* CURRENT_DATE */ ++ testcase( i==70 ); /* DETACH */ ++ testcase( i==71 ); /* IMMEDIATE */ ++ testcase( i==72 ); /* JOIN */ ++ testcase( i==73 ); /* INSERT */ ++ testcase( i==74 ); /* LIKE */ ++ testcase( i==75 ); /* MATCH */ ++ testcase( i==76 ); /* PLAN */ ++ testcase( i==77 ); /* ANALYZE */ ++ testcase( i==78 ); /* PRAGMA */ ++ testcase( i==79 ); /* ABORT */ ++ testcase( i==80 ); /* VALUES */ ++ testcase( i==81 ); /* VIRTUAL */ ++ testcase( i==82 ); /* LIMIT */ ++ testcase( i==83 ); /* WHEN */ ++ testcase( i==84 ); /* NOTNULL */ ++ testcase( i==85 ); /* NOT */ ++ testcase( i==86 ); /* NO */ ++ testcase( i==87 ); /* NULL */ ++ testcase( i==88 ); /* WHERE */ ++ testcase( i==89 ); /* RECURSIVE */ ++ testcase( i==90 ); /* AFTER */ ++ testcase( i==91 ); /* RENAME */ ++ testcase( i==92 ); /* AND */ ++ testcase( i==93 ); /* DEFAULT */ ++ testcase( i==94 ); /* AUTOINCREMENT */ ++ testcase( i==95 ); /* TO */ ++ testcase( i==96 ); /* IN */ ++ testcase( i==97 ); /* CAST */ ++ testcase( i==98 ); /* COLUMN */ ++ testcase( i==99 ); /* COMMIT */ ++ testcase( i==100 ); /* CONFLICT */ ++ testcase( i==101 ); /* CROSS */ ++ testcase( i==102 ); /* CURRENT_TIMESTAMP */ ++ testcase( i==103 ); /* CURRENT_TIME */ ++ testcase( i==104 ); /* CURRENT */ ++ testcase( i==105 ); /* PARTITION */ ++ testcase( i==106 ); /* DEFERRED */ ++ testcase( i==107 ); /* DISTINCT */ ++ testcase( i==108 ); /* IS */ ++ testcase( i==109 ); /* DROP */ ++ testcase( i==110 ); /* PRECEDING */ ++ testcase( i==111 ); /* FAIL */ ++ testcase( i==112 ); /* FILTER */ ++ testcase( i==113 ); /* REPLACE */ ++ testcase( i==114 ); /* FOLLOWING */ ++ testcase( i==115 ); /* FROM */ ++ testcase( i==116 ); /* FULL */ ++ testcase( i==117 ); /* IF */ ++ testcase( i==118 ); /* ISNULL */ ++ testcase( i==119 ); /* ORDER */ ++ testcase( i==120 ); /* RESTRICT */ ++ testcase( i==121 ); /* OVER */ ++ testcase( i==122 ); /* RIGHT */ ++ testcase( i==123 ); /* ROLLBACK */ ++ testcase( i==124 ); /* ROWS */ ++ testcase( i==125 ); /* ROW */ ++ testcase( i==126 ); /* UNBOUNDED */ ++ testcase( i==127 ); /* UNION */ ++ testcase( i==128 ); /* USING */ ++ testcase( i==129 ); /* VACUUM */ ++ testcase( i==130 ); /* VIEW */ ++ testcase( i==131 ); /* WINDOW */ ++ testcase( i==132 ); /* DO */ ++ testcase( i==133 ); /* INITIALLY */ ++ testcase( i==134 ); /* ALL */ ++ testcase( i==135 ); /* PRIMARY */ + *pType = aKWCode[i]; + break; + } +@@ -144198,7 +151680,17 @@ + keywordCode((char*)z, n, &id); + return id; + } +-#define SQLITE_N_KEYWORD 124 ++#define SQLITE_N_KEYWORD 136 ++SQLITE_API int sqlite3_keyword_name(int i,const char **pzName,int *pnName){ ++ if( i<0 || i>=SQLITE_N_KEYWORD ) return SQLITE_ERROR; ++ *pzName = zKWText + aKWOffset[i]; ++ *pnName = aKWLen[i]; ++ return SQLITE_OK; ++} ++SQLITE_API int sqlite3_keyword_count(void){ return SQLITE_N_KEYWORD; } ++SQLITE_API int sqlite3_keyword_check(const char *zName, int nName){ ++ return TK_ID!=sqlite3KeywordCode((const u8*)zName, nName); ++} + + /************** End of keywordhash.h *****************************************/ + /************** Continuing where we left off in tokenize.c *******************/ +@@ -144242,13 +151734,87 @@ + #define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40])) + #endif + +-/* Make the IdChar function accessible from ctime.c */ +-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS ++/* Make the IdChar function accessible from ctime.c and alter.c */ + SQLITE_PRIVATE int sqlite3IsIdChar(u8 c){ return IdChar(c); } +-#endif + ++#ifndef SQLITE_OMIT_WINDOWFUNC ++/* ++** Return the id of the next token in string (*pz). Before returning, set ++** (*pz) to point to the byte following the parsed token. ++*/ ++static int getToken(const unsigned char **pz){ ++ const unsigned char *z = *pz; ++ int t; /* Token type to return */ ++ do { ++ z += sqlite3GetToken(z, &t); ++ }while( t==TK_SPACE ); ++ if( t==TK_ID ++ || t==TK_STRING ++ || t==TK_JOIN_KW ++ || t==TK_WINDOW ++ || t==TK_OVER ++ || sqlite3ParserFallback(t)==TK_ID ++ ){ ++ t = TK_ID; ++ } ++ *pz = z; ++ return t; ++} + + /* ++** The following three functions are called immediately after the tokenizer ++** reads the keywords WINDOW, OVER and FILTER, respectively, to determine ++** whether the token should be treated as a keyword or an SQL identifier. ++** This cannot be handled by the usual lemon %fallback method, due to ++** the ambiguity in some constructions. e.g. ++** ++** SELECT sum(x) OVER ... ++** ++** In the above, "OVER" might be a keyword, or it might be an alias for the ++** sum(x) expression. If a "%fallback ID OVER" directive were added to ++** grammar, then SQLite would always treat "OVER" as an alias, making it ++** impossible to call a window-function without a FILTER clause. ++** ++** WINDOW is treated as a keyword if: ++** ++** * the following token is an identifier, or a keyword that can fallback ++** to being an identifier, and ++** * the token after than one is TK_AS. ++** ++** OVER is a keyword if: ++** ++** * the previous token was TK_RP, and ++** * the next token is either TK_LP or an identifier. ++** ++** FILTER is a keyword if: ++** ++** * the previous token was TK_RP, and ++** * the next token is TK_LP. ++*/ ++static int analyzeWindowKeyword(const unsigned char *z){ ++ int t; ++ t = getToken(&z); ++ if( t!=TK_ID ) return TK_ID; ++ t = getToken(&z); ++ if( t!=TK_AS ) return TK_ID; ++ return TK_WINDOW; ++} ++static int analyzeOverKeyword(const unsigned char *z, int lastToken){ ++ if( lastToken==TK_RP ){ ++ int t = getToken(&z); ++ if( t==TK_LP || t==TK_ID ) return TK_OVER; ++ } ++ return TK_ID; ++} ++static int analyzeFilterKeyword(const unsigned char *z, int lastToken){ ++ if( lastToken==TK_RP && getToken(&z)==TK_LP ){ ++ return TK_FILTER; ++ } ++ return TK_ID; ++} ++#endif /* SQLITE_OMIT_WINDOWFUNC */ ++ ++/* + ** Return the length (in bytes) of the token that begins at z[0]. + ** Store the token type in *tokenType before returning. + */ +@@ -144515,6 +152081,10 @@ + i = 1; + break; + } ++ case CC_NUL: { ++ *tokenType = TK_ILLEGAL; ++ return 0; ++ } + default: { + *tokenType = TK_ILLEGAL; + return 1; +@@ -144525,7 +152095,74 @@ + return i; + } + ++#ifdef SQLITE_ENABLE_NORMALIZE + /* ++** Return the length (in bytes) of the token that begins at z[0]. ++** Store the token type in *tokenType before returning. If flags has ++** SQLITE_TOKEN_NORMALIZE flag enabled, use the identifier token type ++** for keywords. Add SQLITE_TOKEN_QUOTED to flags if the token was ++** actually a quoted identifier. Add SQLITE_TOKEN_KEYWORD to flags ++** if the token was recognized as a keyword; this is useful when the ++** SQLITE_TOKEN_NORMALIZE flag is used, because it enables the caller ++** to differentiate between a keyword being treated as an identifier ++** (for normalization purposes) and an actual identifier. ++*/ ++SQLITE_PRIVATE int sqlite3GetTokenNormalized( ++ const unsigned char *z, ++ int *tokenType, ++ int *flags ++){ ++ int n; ++ unsigned char iClass = aiClass[*z]; ++ if( iClass==CC_KYWD ){ ++ int i; ++ for(i=1; aiClass[z[i]]<=CC_KYWD; i++){} ++ if( IdChar(z[i]) ){ ++ /* This token started out using characters that can appear in keywords, ++ ** but z[i] is a character not allowed within keywords, so this must ++ ** be an identifier instead */ ++ i++; ++ while( IdChar(z[i]) ){ i++; } ++ *tokenType = TK_ID; ++ return i; ++ } ++ *tokenType = TK_ID; ++ n = keywordCode((char*)z, i, tokenType); ++ /* If the token is no longer considered to be an identifier, then it is a ++ ** keyword of some kind. Make the token back into an identifier and then ++ ** set the SQLITE_TOKEN_KEYWORD flag. Several non-identifier tokens are ++ ** used verbatim, including IN, IS, NOT, and NULL. */ ++ switch( *tokenType ){ ++ case TK_ID: { ++ /* do nothing, handled by caller */ ++ break; ++ } ++ case TK_IN: ++ case TK_IS: ++ case TK_NOT: ++ case TK_NULL: { ++ *flags |= SQLITE_TOKEN_KEYWORD; ++ break; ++ } ++ default: { ++ *tokenType = TK_ID; ++ *flags |= SQLITE_TOKEN_KEYWORD; ++ break; ++ } ++ } ++ }else{ ++ n = sqlite3GetToken(z, tokenType); ++ /* If the token is considered to be an identifier and the character class ++ ** of the first character is a quote, set the SQLITE_TOKEN_QUOTED flag. */ ++ if( *tokenType==TK_ID && (iClass==CC_QUOTE || iClass==CC_QUOTE2) ){ ++ *flags |= SQLITE_TOKEN_QUOTED; ++ } ++ } ++ return n; ++} ++#endif /* SQLITE_ENABLE_NORMALIZE */ ++ ++/* + ** Run the parser on the given SQL string. The parser structure is + ** passed in. An SQLITE_ status code is returned. If an error occurs + ** then an and attempt is made to write an error message into +@@ -144555,9 +152192,9 @@ + /* sqlite3ParserTrace(stdout, "parser: "); */ + #ifdef sqlite3Parser_ENGINEALWAYSONSTACK + pEngine = &sEngine; +- sqlite3ParserInit(pEngine); ++ sqlite3ParserInit(pEngine, pParse); + #else +- pEngine = sqlite3ParserAlloc(sqlite3Malloc); ++ pEngine = sqlite3ParserAlloc(sqlite3Malloc, pParse); + if( pEngine==0 ){ + sqlite3OomFault(db); + return SQLITE_NOMEM_BKPT; +@@ -144568,47 +152205,64 @@ + assert( pParse->nVar==0 ); + assert( pParse->pVList==0 ); + while( 1 ){ +- if( zSql[0]!=0 ){ +- n = sqlite3GetToken((u8*)zSql, &tokenType); +- mxSqlLen -= n; +- if( mxSqlLen<0 ){ +- pParse->rc = SQLITE_TOOBIG; +- break; +- } +- }else{ +- /* Upon reaching the end of input, call the parser two more times +- ** with tokens TK_SEMI and 0, in that order. */ +- if( lastTokenParsed==TK_SEMI ){ +- tokenType = 0; +- }else if( lastTokenParsed==0 ){ +- break; +- }else{ +- tokenType = TK_SEMI; +- } +- n = 0; ++ n = sqlite3GetToken((u8*)zSql, &tokenType); ++ mxSqlLen -= n; ++ if( mxSqlLen<0 ){ ++ pParse->rc = SQLITE_TOOBIG; ++ break; + } ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ if( tokenType>=TK_WINDOW ){ ++ assert( tokenType==TK_SPACE || tokenType==TK_OVER || tokenType==TK_FILTER ++ || tokenType==TK_ILLEGAL || tokenType==TK_WINDOW ++ ); ++#else + if( tokenType>=TK_SPACE ){ + assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL ); ++#endif /* SQLITE_OMIT_WINDOWFUNC */ + if( db->u1.isInterrupted ){ + pParse->rc = SQLITE_INTERRUPT; + break; + } +- if( tokenType==TK_ILLEGAL ){ ++ if( tokenType==TK_SPACE ){ ++ zSql += n; ++ continue; ++ } ++ if( zSql[0]==0 ){ ++ /* Upon reaching the end of input, call the parser two more times ++ ** with tokens TK_SEMI and 0, in that order. */ ++ if( lastTokenParsed==TK_SEMI ){ ++ tokenType = 0; ++ }else if( lastTokenParsed==0 ){ ++ break; ++ }else{ ++ tokenType = TK_SEMI; ++ } ++ n = 0; ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ }else if( tokenType==TK_WINDOW ){ ++ assert( n==6 ); ++ tokenType = analyzeWindowKeyword((const u8*)&zSql[6]); ++ }else if( tokenType==TK_OVER ){ ++ assert( n==4 ); ++ tokenType = analyzeOverKeyword((const u8*)&zSql[4], lastTokenParsed); ++ }else if( tokenType==TK_FILTER ){ ++ assert( n==6 ); ++ tokenType = analyzeFilterKeyword((const u8*)&zSql[6], lastTokenParsed); ++#endif /* SQLITE_OMIT_WINDOWFUNC */ ++ }else{ + sqlite3ErrorMsg(pParse, "unrecognized token: \"%.*s\"", n, zSql); + break; + } +- zSql += n; +- }else{ +- pParse->sLastToken.z = zSql; +- pParse->sLastToken.n = n; +- sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse); +- lastTokenParsed = tokenType; +- zSql += n; +- if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break; + } ++ pParse->sLastToken.z = zSql; ++ pParse->sLastToken.n = n; ++ sqlite3Parser(pEngine, tokenType, pParse->sLastToken); ++ lastTokenParsed = tokenType; ++ zSql += n; ++ if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break; + } + assert( nErr==0 ); +- pParse->zTail = zSql; + #ifdef YYTRACKMAXSTACKDEPTH + sqlite3_mutex_enter(sqlite3MallocMutex()); + sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK, +@@ -144630,10 +152284,12 @@ + assert( pzErrMsg!=0 ); + if( pParse->zErrMsg ){ + *pzErrMsg = pParse->zErrMsg; +- sqlite3_log(pParse->rc, "%s", *pzErrMsg); ++ sqlite3_log(pParse->rc, "%s in \"%s\"", ++ *pzErrMsg, pParse->zTail); + pParse->zErrMsg = 0; + nErr++; + } ++ pParse->zTail = zSql; + if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){ + sqlite3VdbeDelete(pParse->pVdbe); + pParse->pVdbe = 0; +@@ -144649,7 +152305,7 @@ + sqlite3_free(pParse->apVtabLock); + #endif + +- if( !IN_DECLARE_VTAB ){ ++ if( !IN_SPECIAL_PARSE ){ + /* If the pParse->declareVtab flag is set, do not delete any table + ** structure built up in pParse->pNewTable. The calling code (see vtab.c) + ** will take responsibility for freeing the Table structure. +@@ -144656,9 +152312,11 @@ + */ + sqlite3DeleteTable(db, pParse->pNewTable); + } ++ if( !IN_RENAME_OBJECT ){ ++ sqlite3DeleteTrigger(db, pParse->pNewTrigger); ++ } + + if( pParse->pWithToFree ) sqlite3WithDelete(db, pParse->pWithToFree); +- sqlite3DeleteTrigger(db, pParse->pNewTrigger); + sqlite3DbFree(db, pParse->pVList); + while( pParse->pAinc ){ + AutoincInfo *p = pParse->pAinc; +@@ -145708,6 +153366,17 @@ + break; + } + ++#ifdef SQLITE_ENABLE_SORTER_REFERENCES ++ case SQLITE_CONFIG_SORTERREF_SIZE: { ++ int iVal = va_arg(ap, int); ++ if( iVal<0 ){ ++ iVal = SQLITE_DEFAULT_SORTERREF_SIZE; ++ } ++ sqlite3GlobalConfig.szSorterRef = (u32)iVal; ++ break; ++ } ++#endif /* SQLITE_ENABLE_SORTER_REFERENCES */ ++ + default: { + rc = SQLITE_ERROR; + break; +@@ -145889,6 +153558,8 @@ + { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose }, + { SQLITE_DBCONFIG_ENABLE_QPSG, SQLITE_EnableQPSG }, + { SQLITE_DBCONFIG_TRIGGER_EQP, SQLITE_TriggerEQP }, ++ { SQLITE_DBCONFIG_RESET_DATABASE, SQLITE_ResetDatabase }, ++ { SQLITE_DBCONFIG_DEFENSIVE, SQLITE_Defensive }, + }; + unsigned int i; + rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ +@@ -145903,7 +153574,7 @@ + db->flags &= ~aFlagOp[i].mask; + } + if( oldFlags!=db->flags ){ +- sqlite3ExpirePreparedStatements(db); ++ sqlite3ExpirePreparedStatements(db, 0); + } + if( pRes ){ + *pRes = (db->flags & aFlagOp[i].mask)!=0; +@@ -145965,6 +153636,15 @@ + } + + /* ++** Return true if CollSeq is the default built-in BINARY. ++*/ ++SQLITE_PRIVATE int sqlite3IsBinary(const CollSeq *p){ ++ assert( p==0 || p->xCmp!=binCollFunc || p->pUser!=0 ++ || strcmp(p->zName,"BINARY")==0 ); ++ return p==0 || (p->xCmp==binCollFunc && p->pUser==0); ++} ++ ++/* + ** Another built-in collating sequence: NOCASE. + ** + ** This collating sequence is intended to be used for "case independent +@@ -146085,7 +153765,7 @@ + sqlite3BtreeEnterAll(db); + for(i=0; i<db->nDb; i++){ + Schema *pSchema = db->aDb[i].pSchema; +- if( db->aDb[i].pSchema ){ ++ if( pSchema ){ + for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){ + Table *pTab = (Table *)sqliteHashData(p); + if( IsVirtual(pTab) ) sqlite3VtabDisconnect(db, pTab); +@@ -146345,8 +154025,8 @@ + sqlite3VtabRollback(db); + sqlite3EndBenignMalloc(); + +- if( (db->mDbFlags&DBFLAG_SchemaChange)!=0 && db->init.busy==0 ){ +- sqlite3ExpirePreparedStatements(db); ++ if( schemaChange ){ ++ sqlite3ExpirePreparedStatements(db, 0); + sqlite3ResetAllSchemasOfConnection(db); + } + sqlite3BtreeLeaveAll(db); +@@ -146374,6 +154054,7 @@ + switch( rc ){ + case SQLITE_OK: zName = "SQLITE_OK"; break; + case SQLITE_ERROR: zName = "SQLITE_ERROR"; break; ++ case SQLITE_ERROR_SNAPSHOT: zName = "SQLITE_ERROR_SNAPSHOT"; break; + case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break; + case SQLITE_PERM: zName = "SQLITE_PERM"; break; + case SQLITE_ABORT: zName = "SQLITE_ABORT"; break; +@@ -146737,6 +154418,8 @@ + void (*xSFunc)(sqlite3_context*,int,sqlite3_value **), + void (*xStep)(sqlite3_context*,int,sqlite3_value **), + void (*xFinal)(sqlite3_context*), ++ void (*xValue)(sqlite3_context*), ++ void (*xInverse)(sqlite3_context*,int,sqlite3_value **), + FuncDestructor *pDestructor + ){ + FuncDef *p; +@@ -146744,12 +154427,14 @@ + int extraFlags; + + assert( sqlite3_mutex_held(db->mutex) ); +- if( zFunctionName==0 || +- (xSFunc && (xFinal || xStep)) || +- (!xSFunc && (xFinal && !xStep)) || +- (!xSFunc && (!xFinal && xStep)) || +- (nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) || +- (255<(nName = sqlite3Strlen30( zFunctionName))) ){ ++ assert( xValue==0 || xSFunc==0 ); ++ if( zFunctionName==0 /* Must have a valid name */ ++ || (xSFunc!=0 && xFinal!=0) /* Not both xSFunc and xFinal */ ++ || ((xFinal==0)!=(xStep==0)) /* Both or neither of xFinal and xStep */ ++ || ((xValue==0)!=(xInverse==0)) /* Both or neither of xValue, xInverse */ ++ || (nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) ++ || (255<(nName = sqlite3Strlen30( zFunctionName))) ++ ){ + return SQLITE_MISUSE_BKPT; + } + +@@ -146770,10 +154455,10 @@ + }else if( enc==SQLITE_ANY ){ + int rc; + rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8|extraFlags, +- pUserData, xSFunc, xStep, xFinal, pDestructor); ++ pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor); + if( rc==SQLITE_OK ){ + rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE|extraFlags, +- pUserData, xSFunc, xStep, xFinal, pDestructor); ++ pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor); + } + if( rc!=SQLITE_OK ){ + return rc; +@@ -146790,7 +154475,7 @@ + ** operation to continue but invalidate all precompiled statements. + */ + p = sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 0); +- if( p && (p->funcFlags & SQLITE_FUNC_ENCMASK)==enc && p->nArg==nArg ){ ++ if( p && (p->funcFlags & SQLITE_FUNC_ENCMASK)==(u32)enc && p->nArg==nArg ){ + if( db->nVdbeActive ){ + sqlite3ErrorWithMsg(db, SQLITE_BUSY, + "unable to delete/modify user-function due to active statements"); +@@ -146797,7 +154482,7 @@ + assert( !db->mallocFailed ); + return SQLITE_BUSY; + }else{ +- sqlite3ExpirePreparedStatements(db); ++ sqlite3ExpirePreparedStatements(db, 0); + } + } + +@@ -146819,6 +154504,8 @@ + testcase( p->funcFlags & SQLITE_DETERMINISTIC ); + p->xSFunc = xSFunc ? xSFunc : xStep; + p->xFinalize = xFinal; ++ p->xValue = xValue; ++ p->xInverse = xInverse; + p->pUserData = pUserData; + p->nArg = (u16)nArg; + return SQLITE_OK; +@@ -146825,32 +154512,24 @@ + } + + /* +-** Create new user functions. ++** Worker function used by utf-8 APIs that create new functions: ++** ++** sqlite3_create_function() ++** sqlite3_create_function_v2() ++** sqlite3_create_window_function() + */ +-SQLITE_API int sqlite3_create_function( ++static int createFunctionApi( + sqlite3 *db, + const char *zFunc, + int nArg, + int enc, + void *p, +- void (*xSFunc)(sqlite3_context*,int,sqlite3_value **), +- void (*xStep)(sqlite3_context*,int,sqlite3_value **), +- void (*xFinal)(sqlite3_context*) +-){ +- return sqlite3_create_function_v2(db, zFunc, nArg, enc, p, xSFunc, xStep, +- xFinal, 0); +-} +- +-SQLITE_API int sqlite3_create_function_v2( +- sqlite3 *db, +- const char *zFunc, +- int nArg, +- int enc, +- void *p, +- void (*xSFunc)(sqlite3_context*,int,sqlite3_value **), +- void (*xStep)(sqlite3_context*,int,sqlite3_value **), ++ void (*xSFunc)(sqlite3_context*,int,sqlite3_value**), ++ void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*), +- void (*xDestroy)(void *) ++ void (*xValue)(sqlite3_context*), ++ void (*xInverse)(sqlite3_context*,int,sqlite3_value**), ++ void(*xDestroy)(void*) + ){ + int rc = SQLITE_ERROR; + FuncDestructor *pArg = 0; +@@ -146862,19 +154541,23 @@ + #endif + sqlite3_mutex_enter(db->mutex); + if( xDestroy ){ +- pArg = (FuncDestructor *)sqlite3DbMallocZero(db, sizeof(FuncDestructor)); ++ pArg = (FuncDestructor *)sqlite3Malloc(sizeof(FuncDestructor)); + if( !pArg ){ ++ sqlite3OomFault(db); + xDestroy(p); + goto out; + } ++ pArg->nRef = 0; + pArg->xDestroy = xDestroy; + pArg->pUserData = p; + } +- rc = sqlite3CreateFunc(db, zFunc, nArg, enc, p, xSFunc, xStep, xFinal, pArg); ++ rc = sqlite3CreateFunc(db, zFunc, nArg, enc, p, ++ xSFunc, xStep, xFinal, xValue, xInverse, pArg ++ ); + if( pArg && pArg->nRef==0 ){ + assert( rc!=SQLITE_OK ); + xDestroy(p); +- sqlite3DbFree(db, pArg); ++ sqlite3_free(pArg); + } + + out: +@@ -146883,6 +154566,52 @@ + return rc; + } + ++/* ++** Create new user functions. ++*/ ++SQLITE_API int sqlite3_create_function( ++ sqlite3 *db, ++ const char *zFunc, ++ int nArg, ++ int enc, ++ void *p, ++ void (*xSFunc)(sqlite3_context*,int,sqlite3_value **), ++ void (*xStep)(sqlite3_context*,int,sqlite3_value **), ++ void (*xFinal)(sqlite3_context*) ++){ ++ return createFunctionApi(db, zFunc, nArg, enc, p, xSFunc, xStep, ++ xFinal, 0, 0, 0); ++} ++SQLITE_API int sqlite3_create_function_v2( ++ sqlite3 *db, ++ const char *zFunc, ++ int nArg, ++ int enc, ++ void *p, ++ void (*xSFunc)(sqlite3_context*,int,sqlite3_value **), ++ void (*xStep)(sqlite3_context*,int,sqlite3_value **), ++ void (*xFinal)(sqlite3_context*), ++ void (*xDestroy)(void *) ++){ ++ return createFunctionApi(db, zFunc, nArg, enc, p, xSFunc, xStep, ++ xFinal, 0, 0, xDestroy); ++} ++SQLITE_API int sqlite3_create_window_function( ++ sqlite3 *db, ++ const char *zFunc, ++ int nArg, ++ int enc, ++ void *p, ++ void (*xStep)(sqlite3_context*,int,sqlite3_value **), ++ void (*xFinal)(sqlite3_context*), ++ void (*xValue)(sqlite3_context*), ++ void (*xInverse)(sqlite3_context*,int,sqlite3_value **), ++ void (*xDestroy)(void *) ++){ ++ return createFunctionApi(db, zFunc, nArg, enc, p, 0, xStep, ++ xFinal, xValue, xInverse, xDestroy); ++} ++ + #ifndef SQLITE_OMIT_UTF16 + SQLITE_API int sqlite3_create_function16( + sqlite3 *db, +@@ -146903,7 +154632,7 @@ + sqlite3_mutex_enter(db->mutex); + assert( !db->mallocFailed ); + zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1, SQLITE_UTF16NATIVE); +- rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xSFunc,xStep,xFinal,0); ++ rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xSFunc,xStep,xFinal,0,0,0); + sqlite3DbFree(db, zFunc8); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); +@@ -146913,6 +154642,28 @@ + + + /* ++** The following is the implementation of an SQL function that always ++** fails with an error message stating that the function is used in the ++** wrong context. The sqlite3_overload_function() API might construct ++** SQL function that use this routine so that the functions will exist ++** for name resolution but are actually overloaded by the xFindFunction ++** method of virtual tables. ++*/ ++static void sqlite3InvalidFunction( ++ sqlite3_context *context, /* The function calling context */ ++ int NotUsed, /* Number of arguments to the function */ ++ sqlite3_value **NotUsed2 /* Value of each argument */ ++){ ++ const char *zName = (const char*)sqlite3_user_data(context); ++ char *zErr; ++ UNUSED_PARAMETER2(NotUsed, NotUsed2); ++ zErr = sqlite3_mprintf( ++ "unable to use function %s in the requested context", zName); ++ sqlite3_result_error(context, zErr, -1); ++ sqlite3_free(zErr); ++} ++ ++/* + ** Declare that a function has been overloaded by a virtual table. + ** + ** If the function already exists as a regular global function, then +@@ -146929,7 +154680,8 @@ + const char *zName, + int nArg + ){ +- int rc = SQLITE_OK; ++ int rc; ++ char *zCopy; + + #ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) || zName==0 || nArg<-2 ){ +@@ -146937,13 +154689,13 @@ + } + #endif + sqlite3_mutex_enter(db->mutex); +- if( sqlite3FindFunction(db, zName, nArg, SQLITE_UTF8, 0)==0 ){ +- rc = sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8, +- 0, sqlite3InvalidFunction, 0, 0, 0); +- } +- rc = sqlite3ApiExit(db, rc); ++ rc = sqlite3FindFunction(db, zName, nArg, SQLITE_UTF8, 0)!=0; + sqlite3_mutex_leave(db->mutex); +- return rc; ++ if( rc ) return SQLITE_OK; ++ zCopy = sqlite3_mprintf(zName); ++ if( zCopy==0 ) return SQLITE_NOMEM; ++ return sqlite3_create_function_v2(db, zName, nArg, SQLITE_UTF8, ++ zCopy, sqlite3InvalidFunction, 0, 0, sqlite3_free); + } + + #ifndef SQLITE_OMIT_TRACE +@@ -147505,7 +155257,7 @@ + "unable to delete/modify collation sequence due to active statements"); + return SQLITE_BUSY; + } +- sqlite3ExpirePreparedStatements(db); ++ sqlite3ExpirePreparedStatements(db, 0); + + /* If collation sequence pColl was created directly by a call to + ** sqlite3_create_collation, and not generated by synthCollSeq(), +@@ -147994,6 +155746,7 @@ + db->nDb = 2; + db->magic = SQLITE_MAGIC_BUSY; + db->aDb = db->aDbStatic; ++ db->lookaside.bDisable = 1; + + assert( sizeof(db->aLimit)==sizeof(aHardLimit) ); + memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit)); +@@ -148034,6 +155787,9 @@ + #if defined(SQLITE_ENABLE_QPSG) + | SQLITE_EnableQPSG + #endif ++#if defined(SQLITE_DEFAULT_DEFENSIVE) ++ | SQLITE_Defensive ++#endif + ; + sqlite3HashInit(&db->aCollSeq); + #ifndef SQLITE_OMIT_VIRTUALTABLE +@@ -148694,6 +156450,9 @@ + }else if( op==SQLITE_FCNTL_JOURNAL_POINTER ){ + *(sqlite3_file**)pArg = sqlite3PagerJrnlFile(pPager); + rc = SQLITE_OK; ++ }else if( op==SQLITE_FCNTL_DATA_VERSION ){ ++ *(unsigned int*)pArg = sqlite3PagerDataVersion(pPager); ++ rc = SQLITE_OK; + }else{ + rc = sqlite3OsFileControl(fd, op, pArg); + } +@@ -148916,32 +156675,25 @@ + break; + } + +-#ifdef SQLITE_N_KEYWORD +- /* sqlite3_test_control(SQLITE_TESTCTRL_ISKEYWORD, const char *zWord) ++ /* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff); + ** +- ** If zWord is a keyword recognized by the parser, then return the +- ** number of keywords. Or if zWord is not a keyword, return 0. +- ** +- ** This test feature is only available in the amalgamation since +- ** the SQLITE_N_KEYWORD macro is not defined in this file if SQLite +- ** is built using separate source files. ++ ** If parameter onoff is non-zero, subsequent calls to localtime() ++ ** and its variants fail. If onoff is zero, undo this setting. + */ +- case SQLITE_TESTCTRL_ISKEYWORD: { +- const char *zWord = va_arg(ap, const char*); +- int n = sqlite3Strlen30(zWord); +- rc = (sqlite3KeywordCode((u8*)zWord, n)!=TK_ID) ? SQLITE_N_KEYWORD : 0; ++ case SQLITE_TESTCTRL_LOCALTIME_FAULT: { ++ sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int); + break; + } +-#endif + +- /* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff); ++ /* sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCS, int onoff); + ** +- ** If parameter onoff is non-zero, configure the wrappers so that all +- ** subsequent calls to localtime() and variants fail. If onoff is zero, +- ** undo this setting. ++ ** If parameter onoff is non-zero, internal-use-only SQL functions ++ ** are visible to ordinary SQL. This is useful for testing but is ++ ** unsafe because invalid parameters to those internal-use-only functions ++ ** can result in crashes or segfaults. + */ +- case SQLITE_TESTCTRL_LOCALTIME_FAULT: { +- sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int); ++ case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: { ++ sqlite3GlobalConfig.bInternalFunctions = va_arg(ap, int); + break; + } + +@@ -148975,7 +156727,8 @@ + */ + case SQLITE_TESTCTRL_VDBE_COVERAGE: { + #ifdef SQLITE_VDBE_COVERAGE +- typedef void (*branch_callback)(void*,int,u8,u8); ++ typedef void (*branch_callback)(void*,unsigned int, ++ unsigned char,unsigned char); + sqlite3GlobalConfig.xVdbeBranch = va_arg(ap,branch_callback); + sqlite3GlobalConfig.pVdbeBranchArg = va_arg(ap,void*); + #endif +@@ -149162,7 +156915,7 @@ + if( iDb==0 || iDb>1 ){ + Btree *pBt = db->aDb[iDb].pBt; + if( 0==sqlite3BtreeIsInTrans(pBt) ){ +- rc = sqlite3BtreeBeginTrans(pBt, 0); ++ rc = sqlite3BtreeBeginTrans(pBt, 0, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot); + } +@@ -149197,12 +156950,30 @@ + iDb = sqlite3FindDbName(db, zDb); + if( iDb==0 || iDb>1 ){ + Btree *pBt = db->aDb[iDb].pBt; +- if( 0==sqlite3BtreeIsInReadTrans(pBt) ){ +- rc = sqlite3PagerSnapshotOpen(sqlite3BtreePager(pBt), pSnapshot); ++ if( sqlite3BtreeIsInTrans(pBt)==0 ){ ++ Pager *pPager = sqlite3BtreePager(pBt); ++ int bUnlock = 0; ++ if( sqlite3BtreeIsInReadTrans(pBt) ){ ++ if( db->nVdbeActive==0 ){ ++ rc = sqlite3PagerSnapshotCheck(pPager, pSnapshot); ++ if( rc==SQLITE_OK ){ ++ bUnlock = 1; ++ rc = sqlite3BtreeCommit(pBt); ++ } ++ } ++ }else{ ++ rc = SQLITE_OK; ++ } + if( rc==SQLITE_OK ){ +- rc = sqlite3BtreeBeginTrans(pBt, 0); +- sqlite3PagerSnapshotOpen(sqlite3BtreePager(pBt), 0); ++ rc = sqlite3PagerSnapshotOpen(pPager, pSnapshot); + } ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3BtreeBeginTrans(pBt, 0, 0); ++ sqlite3PagerSnapshotOpen(pPager, 0); ++ } ++ if( bUnlock ){ ++ sqlite3PagerSnapshotUnlock(pPager); ++ } + } + } + } +@@ -149232,7 +157003,7 @@ + if( iDb==0 || iDb>1 ){ + Btree *pBt = db->aDb[iDb].pBt; + if( 0==sqlite3BtreeIsInReadTrans(pBt) ){ +- rc = sqlite3BtreeBeginTrans(pBt, 0); ++ rc = sqlite3BtreeBeginTrans(pBt, 0, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerSnapshotRecover(sqlite3BtreePager(pBt)); + sqlite3BtreeCommit(pBt); +@@ -150800,7 +158571,7 @@ + ); + SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *); + #ifdef SQLITE_TEST +-SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db); ++SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash*); + SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db); + #endif + +@@ -152368,7 +160139,7 @@ + const char *zCsr = zNode; /* Cursor to iterate through node */ + const char *zEnd = &zCsr[nNode];/* End of interior node buffer */ + char *zBuffer = 0; /* Buffer to load terms into */ +- int nAlloc = 0; /* Size of allocated buffer */ ++ i64 nAlloc = 0; /* Size of allocated buffer */ + int isFirstTerm = 1; /* True when processing first term on page */ + sqlite3_int64 iChild; /* Block id of child node to descend to */ + +@@ -152406,14 +160177,14 @@ + zCsr += fts3GetVarint32(zCsr, &nSuffix); + + assert( nPrefix>=0 && nSuffix>=0 ); +- if( &zCsr[nSuffix]>zEnd ){ ++ if( nPrefix>zCsr-zNode || nSuffix>zEnd-zCsr ){ + rc = FTS_CORRUPT_VTAB; + goto finish_scan; + } +- if( nPrefix+nSuffix>nAlloc ){ ++ if( (i64)nPrefix+nSuffix>nAlloc ){ + char *zNew; +- nAlloc = (nPrefix+nSuffix) * 2; +- zNew = (char *)sqlite3_realloc(zBuffer, nAlloc); ++ nAlloc = ((i64)nPrefix+nSuffix) * 2; ++ zNew = (char *)sqlite3_realloc64(zBuffer, nAlloc); + if( !zNew ){ + rc = SQLITE_NOMEM; + goto finish_scan; +@@ -154355,7 +162126,7 @@ + int rc = SQLITE_OK; + UNUSED_PARAMETER(iSavepoint); + assert( ((Fts3Table *)pVtab)->inTransaction ); +- assert( ((Fts3Table *)pVtab)->mxSavepoint < iSavepoint ); ++ assert( ((Fts3Table *)pVtab)->mxSavepoint <= iSavepoint ); + TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint ); + if( ((Fts3Table *)pVtab)->bIgnoreSavepoint==0 ){ + rc = fts3SyncMethod(pVtab); +@@ -154393,8 +162164,23 @@ + return SQLITE_OK; + } + ++/* ++** Return true if zName is the extension on one of the shadow tables used ++** by this module. ++*/ ++static int fts3ShadowName(const char *zName){ ++ static const char *azName[] = { ++ "content", "docsize", "segdir", "segments", "stat", ++ }; ++ unsigned int i; ++ for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){ ++ if( sqlite3_stricmp(zName, azName[i])==0 ) return 1; ++ } ++ return 0; ++} ++ + static const sqlite3_module fts3Module = { +- /* iVersion */ 2, ++ /* iVersion */ 3, + /* xCreate */ fts3CreateMethod, + /* xConnect */ fts3ConnectMethod, + /* xBestIndex */ fts3BestIndexMethod, +@@ -154417,6 +162203,7 @@ + /* xSavepoint */ fts3SavepointMethod, + /* xRelease */ fts3ReleaseMethod, + /* xRollbackTo */ fts3RollbackToMethod, ++ /* xShadowName */ fts3ShadowName, + }; + + /* +@@ -154510,7 +162297,7 @@ + + #ifdef SQLITE_TEST + if( rc==SQLITE_OK ){ +- rc = sqlite3Fts3ExprInitTestInterface(db); ++ rc = sqlite3Fts3ExprInitTestInterface(db, pHash); + } + #endif + +@@ -154697,6 +162484,7 @@ + return rc; + } + ++#ifndef SQLITE_DISABLE_FTS4_DEFERRED + /* + ** This function is called on each phrase after the position lists for + ** any deferred tokens have been loaded into memory. It updates the phrases +@@ -154800,6 +162588,7 @@ + + return SQLITE_OK; + } ++#endif /* SQLITE_DISABLE_FTS4_DEFERRED */ + + /* + ** Maximum number of tokens a phrase may have to be considered for the +@@ -157048,7 +164837,8 @@ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ +- 0 /* xRollbackTo */ ++ 0, /* xRollbackTo */ ++ 0 /* xShadowName */ + }; + int rc; /* Return code */ + +@@ -158171,34 +165961,6 @@ + /* #include <stdio.h> */ + + /* +-** Function to query the hash-table of tokenizers (see README.tokenizers). +-*/ +-static int queryTestTokenizer( +- sqlite3 *db, +- const char *zName, +- const sqlite3_tokenizer_module **pp +-){ +- int rc; +- sqlite3_stmt *pStmt; +- const char zSql[] = "SELECT fts3_tokenizer(?)"; +- +- *pp = 0; +- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); +- if( rc!=SQLITE_OK ){ +- return rc; +- } +- +- sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); +- if( SQLITE_ROW==sqlite3_step(pStmt) ){ +- if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){ +- memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp)); +- } +- } +- +- return sqlite3_finalize(pStmt); +-} +- +-/* + ** Return a pointer to a buffer containing a text representation of the + ** expression passed as the first argument. The buffer is obtained from + ** sqlite3_malloc(). It is the responsibility of the caller to use +@@ -158265,12 +166027,12 @@ + ** + ** SELECT fts3_exprtest('simple', 'Bill col2:Bloggs', 'col1', 'col2'); + */ +-static void fts3ExprTest( ++static void fts3ExprTestCommon( ++ int bRebalance, + sqlite3_context *context, + int argc, + sqlite3_value **argv + ){ +- sqlite3_tokenizer_module const *pModule = 0; + sqlite3_tokenizer *pTokenizer = 0; + int rc; + char **azCol = 0; +@@ -158280,7 +166042,9 @@ + int ii; + Fts3Expr *pExpr; + char *zBuf = 0; +- sqlite3 *db = sqlite3_context_db_handle(context); ++ Fts3Hash *pHash = (Fts3Hash*)sqlite3_user_data(context); ++ const char *zTokenizer = 0; ++ char *zErr = 0; + + if( argc<3 ){ + sqlite3_result_error(context, +@@ -158289,24 +166053,18 @@ + return; + } + +- rc = queryTestTokenizer(db, +- (const char *)sqlite3_value_text(argv[0]), &pModule); +- if( rc==SQLITE_NOMEM ){ +- sqlite3_result_error_nomem(context); +- goto exprtest_out; +- }else if( !pModule ){ +- sqlite3_result_error(context, "No such tokenizer module", -1); +- goto exprtest_out; ++ zTokenizer = (const char*)sqlite3_value_text(argv[0]); ++ rc = sqlite3Fts3InitTokenizer(pHash, zTokenizer, &pTokenizer, &zErr); ++ if( rc!=SQLITE_OK ){ ++ if( rc==SQLITE_NOMEM ){ ++ sqlite3_result_error_nomem(context); ++ }else{ ++ sqlite3_result_error(context, zErr, -1); ++ } ++ sqlite3_free(zErr); ++ return; + } + +- rc = pModule->xCreate(0, 0, &pTokenizer); +- assert( rc==SQLITE_NOMEM || rc==SQLITE_OK ); +- if( rc==SQLITE_NOMEM ){ +- sqlite3_result_error_nomem(context); +- goto exprtest_out; +- } +- pTokenizer->pModule = pModule; +- + zExpr = (const char *)sqlite3_value_text(argv[1]); + nExpr = sqlite3_value_bytes(argv[1]); + nCol = argc-2; +@@ -158319,7 +166077,7 @@ + azCol[ii] = (char *)sqlite3_value_text(argv[ii+2]); + } + +- if( sqlite3_user_data(context) ){ ++ if( bRebalance ){ + char *zDummy = 0; + rc = sqlite3Fts3ExprParse( + pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr, &zDummy +@@ -158345,23 +166103,38 @@ + sqlite3Fts3ExprFree(pExpr); + + exprtest_out: +- if( pModule && pTokenizer ){ +- rc = pModule->xDestroy(pTokenizer); ++ if( pTokenizer ){ ++ rc = pTokenizer->pModule->xDestroy(pTokenizer); + } + sqlite3_free(azCol); + } + ++static void fts3ExprTest( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ fts3ExprTestCommon(0, context, argc, argv); ++} ++static void fts3ExprTestRebalance( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ fts3ExprTestCommon(1, context, argc, argv); ++} ++ + /* + ** Register the query expression parser test function fts3_exprtest() + ** with database connection db. + */ +-SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3* db){ ++SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash *pHash){ + int rc = sqlite3_create_function( +- db, "fts3_exprtest", -1, SQLITE_UTF8, 0, fts3ExprTest, 0, 0 ++ db, "fts3_exprtest", -1, SQLITE_UTF8, (void*)pHash, fts3ExprTest, 0, 0 + ); + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "fts3_exprtest_rebalance", +- -1, SQLITE_UTF8, (void *)1, fts3ExprTest, 0, 0 ++ -1, SQLITE_UTF8, (void*)pHash, fts3ExprTestRebalance, 0, 0 + ); + } + return rc; +@@ -160624,7 +168397,8 @@ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ +- 0 /* xRollbackTo */ ++ 0, /* xRollbackTo */ ++ 0 /* xShadowName */ + }; + int rc; /* Return code */ + +@@ -162012,15 +169786,19 @@ + ** safe (no risk of overread) even if the node data is corrupted. */ + pNext += fts3GetVarint32(pNext, &nPrefix); + pNext += fts3GetVarint32(pNext, &nSuffix); +- if( nPrefix<0 || nSuffix<=0 +- || &pNext[nSuffix]>&pReader->aNode[pReader->nNode] ++ if( nSuffix<=0 ++ || (&pReader->aNode[pReader->nNode] - pNext)<nSuffix ++ || nPrefix>pReader->nTermAlloc + ){ + return FTS_CORRUPT_VTAB; + } + +- if( nPrefix+nSuffix>pReader->nTermAlloc ){ +- int nNew = (nPrefix+nSuffix)*2; +- char *zNew = sqlite3_realloc(pReader->zTerm, nNew); ++ /* Both nPrefix and nSuffix were read by fts3GetVarint32() and so are ++ ** between 0 and 0x7FFFFFFF. But the sum of the two may cause integer ++ ** overflow - hence the (i64) casts. */ ++ if( (i64)nPrefix+nSuffix>(i64)pReader->nTermAlloc ){ ++ i64 nNew = ((i64)nPrefix+nSuffix)*2; ++ char *zNew = sqlite3_realloc64(pReader->zTerm, nNew); + if( !zNew ){ + return SQLITE_NOMEM; + } +@@ -162042,7 +169820,7 @@ + ** b-tree node. And that the final byte of the doclist is 0x00. If either + ** of these statements is untrue, then the data structure is corrupt. + */ +- if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode] ++ if( (&pReader->aNode[pReader->nNode] - pReader->aDoclist)<pReader->nDoclist + || (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1]) + ){ + return FTS_CORRUPT_VTAB; +@@ -164368,6 +172146,9 @@ + } + p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nSuffix); + ++ if( nPrefix>p->iOff || nSuffix>p->nNode-p->iOff ){ ++ return SQLITE_CORRUPT_VTAB; ++ } + blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc); + if( rc==SQLITE_OK ){ + memcpy(&p->term.a[nPrefix], &p->aNode[p->iOff], nSuffix); +@@ -164375,6 +172156,9 @@ + p->iOff += nSuffix; + if( p->iChild==0 ){ + p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist); ++ if( (p->nNode-p->iOff)<p->nDoclist ){ ++ return SQLITE_CORRUPT_VTAB; ++ } + p->aDoclist = &p->aNode[p->iOff]; + p->iOff += p->nDoclist; + } +@@ -164382,7 +172166,6 @@ + } + + assert( p->iOff<=p->nNode ); +- + return rc; + } + +@@ -168795,6 +176578,2550 @@ + #endif /* !defined(SQLITE_DISABLE_FTS3_UNICODE) */ + + /************** End of fts3_unicode2.c ***************************************/ ++/************** Begin file json1.c *******************************************/ ++/* ++** 2015-08-12 ++** ++** 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 JSON functions. The interface is ++** modeled after MySQL JSON functions: ++** ++** https://dev.mysql.com/doc/refman/5.7/en/json.html ++** ++** For the time being, all JSON is stored as pure text. (We might add ++** a JSONB type in the future which stores a binary encoding of JSON in ++** a BLOB, but there is no support for JSONB in the current implementation. ++** This implementation parses JSON text at 250 MB/s, so it is hard to see ++** how JSONB might improve on that.) ++*/ ++#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1) ++#if !defined(SQLITEINT_H) ++/* #include "sqlite3ext.h" */ ++#endif ++SQLITE_EXTENSION_INIT1 ++/* #include <assert.h> */ ++/* #include <string.h> */ ++/* #include <stdlib.h> */ ++/* #include <stdarg.h> */ ++ ++/* Mark a function parameter as unused, to suppress nuisance compiler ++** warnings. */ ++#ifndef UNUSED_PARAM ++# define UNUSED_PARAM(X) (void)(X) ++#endif ++ ++#ifndef LARGEST_INT64 ++# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32)) ++# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64) ++#endif ++ ++/* ++** Versions of isspace(), isalnum() and isdigit() to which it is safe ++** to pass signed char values. ++*/ ++#ifdef sqlite3Isdigit ++ /* Use the SQLite core versions if this routine is part of the ++ ** SQLite amalgamation */ ++# define safe_isdigit(x) sqlite3Isdigit(x) ++# define safe_isalnum(x) sqlite3Isalnum(x) ++# define safe_isxdigit(x) sqlite3Isxdigit(x) ++#else ++ /* Use the standard library for separate compilation */ ++#include <ctype.h> /* amalgamator: keep */ ++# define safe_isdigit(x) isdigit((unsigned char)(x)) ++# define safe_isalnum(x) isalnum((unsigned char)(x)) ++# define safe_isxdigit(x) isxdigit((unsigned char)(x)) ++#endif ++ ++/* ++** Growing our own isspace() routine this way is twice as fast as ++** the library isspace() function, resulting in a 7% overall performance ++** increase for the parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os). ++*/ ++static const char jsonIsSpace[] = { ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++}; ++#define safe_isspace(x) (jsonIsSpace[(unsigned char)x]) ++ ++#ifndef SQLITE_AMALGAMATION ++ /* Unsigned integer types. These are already defined in the sqliteInt.h, ++ ** but the definitions need to be repeated for separate compilation. */ ++ typedef sqlite3_uint64 u64; ++ typedef unsigned int u32; ++ typedef unsigned short int u16; ++ typedef unsigned char u8; ++#endif ++ ++/* Objects */ ++typedef struct JsonString JsonString; ++typedef struct JsonNode JsonNode; ++typedef struct JsonParse JsonParse; ++ ++/* An instance of this object represents a JSON string ++** under construction. Really, this is a generic string accumulator ++** that can be and is used to create strings other than JSON. ++*/ ++struct JsonString { ++ sqlite3_context *pCtx; /* Function context - put error messages here */ ++ char *zBuf; /* Append JSON content here */ ++ u64 nAlloc; /* Bytes of storage available in zBuf[] */ ++ u64 nUsed; /* Bytes of zBuf[] currently used */ ++ u8 bStatic; /* True if zBuf is static space */ ++ u8 bErr; /* True if an error has been encountered */ ++ char zSpace[100]; /* Initial static space */ ++}; ++ ++/* JSON type values ++*/ ++#define JSON_NULL 0 ++#define JSON_TRUE 1 ++#define JSON_FALSE 2 ++#define JSON_INT 3 ++#define JSON_REAL 4 ++#define JSON_STRING 5 ++#define JSON_ARRAY 6 ++#define JSON_OBJECT 7 ++ ++/* The "subtype" set for JSON values */ ++#define JSON_SUBTYPE 74 /* Ascii for "J" */ ++ ++/* ++** Names of the various JSON types: ++*/ ++static const char * const jsonType[] = { ++ "null", "true", "false", "integer", "real", "text", "array", "object" ++}; ++ ++/* Bit values for the JsonNode.jnFlag field ++*/ ++#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 */ ++ u32 n; /* Bytes of content, or number of sub-nodes */ ++ union { ++ const char *zJContent; /* Content for INT, REAL, and STRING */ ++ u32 iAppend; /* More terms for ARRAY and OBJECT */ ++ u32 iKey; /* Key for ARRAY objects in json_tree() */ ++ u32 iReplace; /* Replacement content for JNODE_REPLACE */ ++ JsonNode *pPatch; /* Node chain of patch for JNODE_PATCH */ ++ } u; ++}; ++ ++/* A completely parsed JSON string ++*/ ++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 ++** descent parser. A depth of 2000 is far deeper than any sane JSON ++** should go. ++*/ ++#define JSON_MAX_DEPTH 2000 ++ ++/************************************************************************** ++** Utility routines for dealing with JsonString objects ++**************************************************************************/ ++ ++/* Set the JsonString object to an empty string ++*/ ++static void jsonZero(JsonString *p){ ++ p->zBuf = p->zSpace; ++ p->nAlloc = sizeof(p->zSpace); ++ p->nUsed = 0; ++ p->bStatic = 1; ++} ++ ++/* Initialize the JsonString object ++*/ ++static void jsonInit(JsonString *p, sqlite3_context *pCtx){ ++ p->pCtx = pCtx; ++ p->bErr = 0; ++ jsonZero(p); ++} ++ ++ ++/* Free all allocated memory and reset the JsonString object back to its ++** initial state. ++*/ ++static void jsonReset(JsonString *p){ ++ if( !p->bStatic ) sqlite3_free(p->zBuf); ++ jsonZero(p); ++} ++ ++ ++/* Report an out-of-memory (OOM) condition ++*/ ++static void jsonOom(JsonString *p){ ++ p->bErr = 1; ++ sqlite3_result_error_nomem(p->pCtx); ++ jsonReset(p); ++} ++ ++/* Enlarge pJson->zBuf so that it can hold at least N more bytes. ++** Return zero on success. Return non-zero on an OOM error ++*/ ++static int jsonGrow(JsonString *p, u32 N){ ++ u64 nTotal = N<p->nAlloc ? p->nAlloc*2 : p->nAlloc+N+10; ++ char *zNew; ++ if( p->bStatic ){ ++ if( p->bErr ) return 1; ++ zNew = sqlite3_malloc64(nTotal); ++ if( zNew==0 ){ ++ jsonOom(p); ++ return SQLITE_NOMEM; ++ } ++ memcpy(zNew, p->zBuf, (size_t)p->nUsed); ++ p->zBuf = zNew; ++ p->bStatic = 0; ++ }else{ ++ zNew = sqlite3_realloc64(p->zBuf, nTotal); ++ if( zNew==0 ){ ++ jsonOom(p); ++ return SQLITE_NOMEM; ++ } ++ p->zBuf = zNew; ++ } ++ p->nAlloc = nTotal; ++ return SQLITE_OK; ++} ++ ++/* Append N bytes from zIn onto the end of the JsonString string. ++*/ ++static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){ ++ if( (N+p->nUsed >= p->nAlloc) && jsonGrow(p,N)!=0 ) return; ++ memcpy(p->zBuf+p->nUsed, zIn, N); ++ p->nUsed += N; ++} ++ ++/* Append formatted text (not to exceed N bytes) to the JsonString. ++*/ ++static void jsonPrintf(int N, JsonString *p, const char *zFormat, ...){ ++ va_list ap; ++ if( (p->nUsed + N >= p->nAlloc) && jsonGrow(p, N) ) return; ++ va_start(ap, zFormat); ++ sqlite3_vsnprintf(N, p->zBuf+p->nUsed, zFormat, ap); ++ va_end(ap); ++ p->nUsed += (int)strlen(p->zBuf+p->nUsed); ++} ++ ++/* Append a single character ++*/ ++static void jsonAppendChar(JsonString *p, char c){ ++ if( p->nUsed>=p->nAlloc && jsonGrow(p,1)!=0 ) return; ++ p->zBuf[p->nUsed++] = c; ++} ++ ++/* Append a comma separator to the output buffer, if the previous ++** character is not '[' or '{'. ++*/ ++static void jsonAppendSeparator(JsonString *p){ ++ char c; ++ if( p->nUsed==0 ) return; ++ c = p->zBuf[p->nUsed-1]; ++ if( c!='[' && c!='{' ) jsonAppendChar(p, ','); ++} ++ ++/* Append the N-byte string in zIn to the end of the JsonString string ++** under construction. Enclose the string in "..." and escape ++** any double-quotes or backslash characters contained within the ++** string. ++*/ ++static void jsonAppendString(JsonString *p, const char *zIn, u32 N){ ++ u32 i; ++ if( (N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0 ) return; ++ p->zBuf[p->nUsed++] = '"'; ++ for(i=0; i<N; i++){ ++ unsigned char c = ((unsigned const char*)zIn)[i]; ++ if( c=='"' || c=='\\' ){ ++ json_simple_escape: ++ if( (p->nUsed+N+3-i > p->nAlloc) && jsonGrow(p,N+3-i)!=0 ) return; ++ p->zBuf[p->nUsed++] = '\\'; ++ }else if( c<=0x1f ){ ++ static const char aSpecial[] = { ++ 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ++ }; ++ assert( sizeof(aSpecial)==32 ); ++ assert( aSpecial['\b']=='b' ); ++ assert( aSpecial['\f']=='f' ); ++ assert( aSpecial['\n']=='n' ); ++ assert( aSpecial['\r']=='r' ); ++ assert( aSpecial['\t']=='t' ); ++ if( aSpecial[c] ){ ++ c = aSpecial[c]; ++ goto json_simple_escape; ++ } ++ if( (p->nUsed+N+7+i > p->nAlloc) && jsonGrow(p,N+7-i)!=0 ) return; ++ p->zBuf[p->nUsed++] = '\\'; ++ p->zBuf[p->nUsed++] = 'u'; ++ p->zBuf[p->nUsed++] = '0'; ++ p->zBuf[p->nUsed++] = '0'; ++ p->zBuf[p->nUsed++] = '0' + (c>>4); ++ 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); ++ u32 n = (u32)sqlite3_value_bytes(pValue); ++ if( sqlite3_value_subtype(pValue)==JSON_SUBTYPE ){ ++ jsonAppendRaw(p, z, n); ++ }else{ ++ jsonAppendString(p, z, n); ++ } ++ break; ++ } ++ default: { ++ if( p->bErr==0 ){ ++ sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1); ++ p->bErr = 2; ++ jsonReset(p); ++ } ++ break; ++ } ++ } ++} ++ ++ ++/* Make the JSON in p the result of the SQL function. ++*/ ++static void jsonResult(JsonString *p){ ++ if( p->bErr==0 ){ ++ sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed, ++ p->bStatic ? SQLITE_TRANSIENT : sqlite3_free, ++ SQLITE_UTF8); ++ jsonZero(p); ++ } ++ assert( p->bStatic ); ++} ++ ++/************************************************************************** ++** Utility routines for dealing with JsonNode and JsonParse objects ++**************************************************************************/ ++ ++/* ++** Return the number of consecutive JsonNode slots need to represent ++** the parsed JSON at pNode. The minimum answer is 1. For ARRAY and ++** OBJECT types, the number might be larger. ++** ++** Appended elements are not counted. The value returned is the number ++** by which the JsonNode counter should increment in order to go to the ++** next peer value. ++*/ ++static u32 jsonNodeSize(JsonNode *pNode){ ++ return pNode->eType>=JSON_ARRAY ? pNode->n+1 : 1; ++} ++ ++/* ++** Reclaim all memory allocated by a JsonParse object. But do not ++** delete the JsonParse object itself. ++*/ ++static void jsonParseReset(JsonParse *pParse){ ++ sqlite3_free(pParse->aNode); ++ pParse->aNode = 0; ++ pParse->nNode = 0; ++ pParse->nAlloc = 0; ++ sqlite3_free(pParse->aUp); ++ pParse->aUp = 0; ++} ++ ++/* ++** Free a JsonParse object that was obtained from sqlite3_malloc(). ++*/ ++static void jsonParseFree(JsonParse *pParse){ ++ jsonParseReset(pParse); ++ sqlite3_free(pParse); ++} ++ ++/* ++** Convert the JsonNode pNode into a pure JSON string and ++** append to pOut. Subsubstructure is also included. Return ++** the number of JsonNode objects that are encoded. ++*/ ++static void jsonRenderNode( ++ JsonNode *pNode, /* The node to render */ ++ JsonString *pOut, /* Write JSON here */ ++ sqlite3_value **aReplace /* Replacement values */ ++){ ++ if( pNode->jnFlags & (JNODE_REPLACE|JNODE_PATCH) ){ ++ if( pNode->jnFlags & JNODE_REPLACE ){ ++ jsonAppendValue(pOut, aReplace[pNode->u.iReplace]); ++ return; ++ } ++ pNode = pNode->u.pPatch; ++ } ++ switch( pNode->eType ){ ++ default: { ++ assert( pNode->eType==JSON_NULL ); ++ jsonAppendRaw(pOut, "null", 4); ++ break; ++ } ++ case JSON_TRUE: { ++ jsonAppendRaw(pOut, "true", 4); ++ break; ++ } ++ case JSON_FALSE: { ++ jsonAppendRaw(pOut, "false", 5); ++ break; ++ } ++ case JSON_STRING: { ++ if( pNode->jnFlags & JNODE_RAW ){ ++ jsonAppendString(pOut, pNode->u.zJContent, pNode->n); ++ break; ++ } ++ /* Fall through into the next case */ ++ } ++ case JSON_REAL: ++ case JSON_INT: { ++ jsonAppendRaw(pOut, pNode->u.zJContent, pNode->n); ++ break; ++ } ++ case JSON_ARRAY: { ++ u32 j = 1; ++ jsonAppendChar(pOut, '['); ++ for(;;){ ++ while( j<=pNode->n ){ ++ if( (pNode[j].jnFlags & JNODE_REMOVE)==0 ){ ++ jsonAppendSeparator(pOut); ++ jsonRenderNode(&pNode[j], pOut, aReplace); ++ } ++ j += jsonNodeSize(&pNode[j]); ++ } ++ if( (pNode->jnFlags & JNODE_APPEND)==0 ) break; ++ pNode = &pNode[pNode->u.iAppend]; ++ j = 1; ++ } ++ jsonAppendChar(pOut, ']'); ++ break; ++ } ++ case JSON_OBJECT: { ++ u32 j = 1; ++ jsonAppendChar(pOut, '{'); ++ for(;;){ ++ while( j<=pNode->n ){ ++ if( (pNode[j+1].jnFlags & JNODE_REMOVE)==0 ){ ++ jsonAppendSeparator(pOut); ++ jsonRenderNode(&pNode[j], pOut, aReplace); ++ jsonAppendChar(pOut, ':'); ++ jsonRenderNode(&pNode[j+1], pOut, aReplace); ++ } ++ j += 1 + jsonNodeSize(&pNode[j+1]); ++ } ++ if( (pNode->jnFlags & JNODE_APPEND)==0 ) break; ++ pNode = &pNode[pNode->u.iAppend]; ++ j = 1; ++ } ++ jsonAppendChar(pOut, '}'); ++ break; ++ } ++ } ++} ++ ++/* ++** Return a JsonNode and all its descendents as a JSON string. ++*/ ++static void jsonReturnJson( ++ JsonNode *pNode, /* Node to return */ ++ sqlite3_context *pCtx, /* Return value for this function */ ++ sqlite3_value **aReplace /* Array of replacement values */ ++){ ++ JsonString s; ++ jsonInit(&s, pCtx); ++ jsonRenderNode(pNode, &s, aReplace); ++ jsonResult(&s); ++ sqlite3_result_subtype(pCtx, JSON_SUBTYPE); ++} ++ ++/* ++** Make the JsonNode the return value of the function. ++*/ ++static void jsonReturn( ++ JsonNode *pNode, /* Node to return */ ++ sqlite3_context *pCtx, /* Return value for this function */ ++ sqlite3_value **aReplace /* Array of replacement values */ ++){ ++ switch( pNode->eType ){ ++ default: { ++ assert( pNode->eType==JSON_NULL ); ++ sqlite3_result_null(pCtx); ++ break; ++ } ++ case JSON_TRUE: { ++ sqlite3_result_int(pCtx, 1); ++ break; ++ } ++ case JSON_FALSE: { ++ sqlite3_result_int(pCtx, 0); ++ break; ++ } ++ case JSON_INT: { ++ sqlite3_int64 i = 0; ++ const char *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: /* fall through to real */; ++ } ++ case JSON_REAL: { ++ double r; ++#ifdef SQLITE_AMALGAMATION ++ const char *z = pNode->u.zJContent; ++ sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8); ++#else ++ 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 ){ ++ 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 */ ++ 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 = pNode->u.zJContent; ++ char *zOut; ++ u32 j; ++ 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 = 0, k; ++ for(k=0; k<4; i++, k++){ ++ assert( i<n-2 ); ++ c = z[i+1]; ++ assert( safe_isxdigit(c) ); ++ if( c<='9' ) v = v*16 + c - '0'; ++ else if( c<='F' ) v = v*16 + c - 'A' + 10; ++ else v = v*16 + c - 'a' + 10; ++ } ++ if( v==0 ) break; ++ if( v<=0x7f ){ ++ zOut[j++] = (char)v; ++ }else if( v<=0x7ff ){ ++ zOut[j++] = (char)(0xc0 | (v>>6)); ++ zOut[j++] = 0x80 | (v&0x3f); ++ }else{ ++ zOut[j++] = (char)(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: { ++ jsonReturnJson(pNode, pCtx, aReplace); ++ break; ++ } ++ } ++} ++ ++/* Forward reference */ ++static int jsonParseAddNode(JsonParse*,u32,u32,const char*); ++ ++/* ++** A macro to hint to the compiler that a function should not be ++** inlined. ++*/ ++#if defined(__GNUC__) ++# define JSON_NOINLINE __attribute__((noinline)) ++#elif defined(_MSC_VER) && _MSC_VER>=1310 ++# define JSON_NOINLINE __declspec(noinline) ++#else ++# define JSON_NOINLINE ++#endif ++ ++ ++static JSON_NOINLINE int jsonParseAddNodeExpand( ++ JsonParse *pParse, /* Append the node to this object */ ++ u32 eType, /* Node type */ ++ u32 n, /* Content size or sub-node count */ ++ const char *zContent /* Content */ ++){ ++ u32 nNew; ++ JsonNode *pNew; ++ assert( pParse->nNode>=pParse->nAlloc ); ++ if( pParse->oom ) return -1; ++ nNew = pParse->nAlloc*2 + 10; ++ pNew = sqlite3_realloc(pParse->aNode, sizeof(JsonNode)*nNew); ++ if( pNew==0 ){ ++ pParse->oom = 1; ++ return -1; ++ } ++ pParse->nAlloc = nNew; ++ pParse->aNode = pNew; ++ assert( pParse->nNode<pParse->nAlloc ); ++ return jsonParseAddNode(pParse, eType, n, zContent); ++} ++ ++/* ++** Create a new JsonNode instance based on the arguments and append that ++** instance to the JsonParse. Return the index in pParse->aNode[] of the ++** new node, or -1 if a memory allocation fails. ++*/ ++static int jsonParseAddNode( ++ JsonParse *pParse, /* Append the node to this object */ ++ u32 eType, /* Node type */ ++ u32 n, /* Content size or sub-node count */ ++ const char *zContent /* Content */ ++){ ++ JsonNode *p; ++ if( pParse->nNode>=pParse->nAlloc ){ ++ return jsonParseAddNodeExpand(pParse, eType, n, zContent); ++ } ++ p = &pParse->aNode[pParse->nNode]; ++ p->eType = (u8)eType; ++ p->jnFlags = 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( !safe_isxdigit(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( safe_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( safe_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( safe_isspace(z[j]) ){ j++; } ++ if( z[j]!=':' ) return -1; ++ j++; ++ x = jsonParseValue(pParse, j); ++ pParse->iDepth--; ++ if( x<0 ) return -1; ++ j = x; ++ while( safe_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; ++ for(j=i+1;;j++){ ++ while( safe_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( safe_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 ++ && !safe_isalnum(z[i+4]) ){ ++ jsonParseAddNode(pParse, JSON_NULL, 0, 0); ++ return i+4; ++ }else if( c=='t' ++ && strncmp(z+i,"true",4)==0 ++ && !safe_isalnum(z[i+4]) ){ ++ jsonParseAddNode(pParse, JSON_TRUE, 0, 0); ++ return i+4; ++ }else if( c=='f' ++ && strncmp(z+i,"false",5)==0 ++ && !safe_isalnum(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. ++** ++** pParse is uninitialized when this routine is called. ++*/ ++static int jsonParse( ++ JsonParse *pParse, /* Initialize and fill this JsonParse object */ ++ sqlite3_context *pCtx, /* Report errors here */ ++ const char *zJson /* Input JSON text to be parsed */ ++){ ++ int i; ++ memset(pParse, 0, sizeof(*pParse)); ++ 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( safe_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); ++ } ++ } ++ jsonParseReset(pParse); ++ return 1; ++ } ++ return 0; ++} ++ ++/* Mark node i of pParse as being a child of iParent. Call recursively ++** to fill in all the descendants of node i. ++*/ ++static void jsonParseFillInParentage(JsonParse *pParse, u32 i, u32 iParent){ ++ JsonNode *pNode = &pParse->aNode[i]; ++ u32 j; ++ pParse->aUp[i] = iParent; ++ switch( pNode->eType ){ ++ case JSON_ARRAY: { ++ for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j)){ ++ jsonParseFillInParentage(pParse, i+j, i); ++ } ++ break; ++ } ++ case JSON_OBJECT: { ++ for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j+1)+1){ ++ pParse->aUp[i+j] = i; ++ jsonParseFillInParentage(pParse, i+j+1, i); ++ } ++ break; ++ } ++ default: { ++ break; ++ } ++ } ++} ++ ++/* ++** Compute the parentage of all nodes in a completed parse. ++*/ ++static int jsonParseFindParents(JsonParse *pParse){ ++ u32 *aUp; ++ assert( pParse->aUp==0 ); ++ aUp = pParse->aUp = sqlite3_malloc( sizeof(u32)*pParse->nNode ); ++ if( aUp==0 ){ ++ pParse->oom = 1; ++ return SQLITE_NOMEM; ++ } ++ jsonParseFillInParentage(pParse, 0, 0); ++ return SQLITE_OK; ++} ++ ++/* ++** Magic number used for the JSON parse cache in sqlite3_get_auxdata() ++*/ ++#define JSON_CACHE_ID (-429938) /* First cache entry */ ++#define JSON_CACHE_SZ 4 /* Max number of cache entries */ ++ ++/* ++** 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]); ++ int nJson = sqlite3_value_bytes(argv[0]); ++ JsonParse *p; ++ JsonParse *pMatch = 0; ++ int iKey; ++ int iMinKey = 0; ++ u32 iMinHold = 0xffffffff; ++ u32 iMaxHold = 0; ++ if( zJson==0 ) return 0; ++ for(iKey=0; iKey<JSON_CACHE_SZ; iKey++){ ++ p = (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID+iKey); ++ if( p==0 ){ ++ iMinKey = iKey; ++ break; ++ } ++ if( pMatch==0 ++ && p->nJson==nJson ++ && memcmp(p->zJson,zJson,nJson)==0 ++ ){ ++ p->nErr = 0; ++ pMatch = p; ++ }else if( p->iHold<iMinHold ){ ++ iMinHold = p->iHold; ++ iMinKey = iKey; ++ } ++ if( p->iHold>iMaxHold ){ ++ iMaxHold = p->iHold; ++ } ++ } ++ if( pMatch ){ ++ pMatch->nErr = 0; ++ pMatch->iHold = iMaxHold+1; ++ return pMatch; ++ } ++ p = sqlite3_malloc( sizeof(*p) + nJson + 1 ); ++ if( p==0 ){ ++ 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){ ++ 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 ++** node. ++** ++** If pApnd!=0, then try to append new nodes to complete zPath if it is ++** possible to do so and if no existing node corresponds to zPath. If ++** new nodes are appended *pApnd is set to 1. ++*/ ++static JsonNode *jsonLookupStep( ++ JsonParse *pParse, /* The JSON to search */ ++ u32 iRoot, /* Begin the search at this node */ ++ const char *zPath, /* The path to search */ ++ int *pApnd, /* Append nodes to complete path if not NULL */ ++ const char **pzErr /* Make *pzErr point to any syntax error in zPath */ ++){ ++ u32 i, j, nKey; ++ const char *zKey; ++ JsonNode *pRoot = &pParse->aNode[iRoot]; ++ if( zPath[0]==0 ) return pRoot; ++ if( zPath[0]=='.' ){ ++ if( pRoot->eType!=JSON_OBJECT ) return 0; ++ zPath++; ++ if( zPath[0]=='"' ){ ++ zKey = zPath + 1; ++ for(i=1; zPath[i] && zPath[i]!='"'; i++){} ++ nKey = i-1; ++ if( zPath[i] ){ ++ i++; ++ }else{ ++ *pzErr = zPath; ++ return 0; ++ } ++ }else{ ++ zKey = zPath; ++ for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){} ++ nKey = i; ++ } ++ if( nKey==0 ){ ++ *pzErr = zPath; ++ return 0; ++ } ++ j = 1; ++ for(;;){ ++ while( j<=pRoot->n ){ ++ if( jsonLabelCompare(pRoot+j, zKey, nKey) ){ ++ return jsonLookupStep(pParse, iRoot+j+1, &zPath[i], pApnd, pzErr); ++ } ++ j++; ++ j += jsonNodeSize(&pRoot[j]); ++ } ++ if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break; ++ iRoot += pRoot->u.iAppend; ++ pRoot = &pParse->aNode[iRoot]; ++ j = 1; ++ } ++ if( pApnd ){ ++ u32 iStart, iLabel; ++ JsonNode *pNode; ++ iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0); ++ iLabel = jsonParseAddNode(pParse, JSON_STRING, i, zPath); ++ zPath += i; ++ pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr); ++ if( pParse->oom ) return 0; ++ if( pNode ){ ++ pRoot = &pParse->aNode[iRoot]; ++ pRoot->u.iAppend = iStart - iRoot; ++ pRoot->jnFlags |= JNODE_APPEND; ++ pParse->aNode[iLabel].jnFlags |= JNODE_RAW; ++ } ++ return pNode; ++ } ++ }else if( zPath[0]=='[' && safe_isdigit(zPath[1]) ){ ++ if( pRoot->eType!=JSON_ARRAY ) return 0; ++ i = 0; ++ j = 1; ++ while( safe_isdigit(zPath[j]) ){ ++ i = i*10 + zPath[j] - '0'; ++ j++; ++ } ++ if( zPath[j]!=']' ){ ++ *pzErr = zPath; ++ return 0; ++ } ++ zPath += j + 1; ++ j = 1; ++ for(;;){ ++ while( j<=pRoot->n && (i>0 || (pRoot[j].jnFlags & JNODE_REMOVE)!=0) ){ ++ if( (pRoot[j].jnFlags & JNODE_REMOVE)==0 ) i--; ++ j += jsonNodeSize(&pRoot[j]); ++ } ++ if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break; ++ iRoot += pRoot->u.iAppend; ++ pRoot = &pParse->aNode[iRoot]; ++ j = 1; ++ } ++ if( j<=pRoot->n ){ ++ return jsonLookupStep(pParse, iRoot+j, zPath, pApnd, pzErr); ++ } ++ if( i==0 && pApnd ){ ++ u32 iStart; ++ JsonNode *pNode; ++ iStart = jsonParseAddNode(pParse, JSON_ARRAY, 1, 0); ++ pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr); ++ if( pParse->oom ) return 0; ++ if( pNode ){ ++ pRoot = &pParse->aNode[iRoot]; ++ pRoot->u.iAppend = iStart - iRoot; ++ pRoot->jnFlags |= JNODE_APPEND; ++ } ++ return pNode; ++ } ++ }else{ ++ *pzErr = zPath; ++ } ++ return 0; ++} ++ ++/* ++** Append content to pParse that will complete zPath. Return a pointer ++** to the inserted node, or return NULL if the append fails. ++*/ ++static JsonNode *jsonLookupAppend( ++ JsonParse *pParse, /* Append content to the JSON parse */ ++ const char *zPath, /* Description of content to append */ ++ int *pApnd, /* Set this flag to 1 */ ++ const char **pzErr /* Make this point to any syntax error */ ++){ ++ *pApnd = 1; ++ if( zPath[0]==0 ){ ++ jsonParseAddNode(pParse, JSON_NULL, 0, 0); ++ return pParse->oom ? 0 : &pParse->aNode[pParse->nNode-1]; ++ } ++ if( zPath[0]=='.' ){ ++ jsonParseAddNode(pParse, JSON_OBJECT, 0, 0); ++ }else if( strncmp(zPath,"[0]",3)==0 ){ ++ jsonParseAddNode(pParse, JSON_ARRAY, 0, 0); ++ }else{ ++ return 0; ++ } ++ if( pParse->oom ) return 0; ++ return jsonLookupStep(pParse, pParse->nNode-1, zPath, pApnd, pzErr); ++} ++ ++/* ++** Return the text of a syntax error message on a JSON path. Space is ++** obtained from sqlite3_malloc(). ++*/ ++static char *jsonPathSyntaxError(const char *zErr){ ++ return sqlite3_mprintf("JSON path error near '%q'", zErr); ++} ++ ++/* ++** Do a node lookup using zPath. Return a pointer to the node on success. ++** Return NULL if not found or if there is an error. ++** ++** On an error, write an error message into pCtx and increment the ++** pParse->nErr counter. ++** ++** If pApnd!=NULL then try to append missing nodes and set *pApnd = 1 if ++** nodes are appended. ++*/ ++static JsonNode *jsonLookup( ++ JsonParse *pParse, /* The JSON to search */ ++ const char *zPath, /* The path to search */ ++ int *pApnd, /* Append nodes to complete path if not NULL */ ++ sqlite3_context *pCtx /* Report errors here, if not NULL */ ++){ ++ const char *zErr = 0; ++ JsonNode *pNode = 0; ++ char *zMsg; ++ ++ if( zPath==0 ) return 0; ++ if( zPath[0]!='$' ){ ++ zErr = zPath; ++ goto lookup_err; ++ } ++ zPath++; ++ pNode = jsonLookupStep(pParse, 0, zPath, pApnd, &zErr); ++ if( zErr==0 ) return pNode; ++ ++lookup_err: ++ pParse->nErr++; ++ assert( zErr!=0 && pCtx!=0 ); ++ zMsg = jsonPathSyntaxError(zErr); ++ if( zMsg ){ ++ sqlite3_result_error(pCtx, zMsg, -1); ++ sqlite3_free(zMsg); ++ }else{ ++ sqlite3_result_error_nomem(pCtx); ++ } ++ return 0; ++} ++ ++ ++/* ++** Report the wrong number of arguments for json_insert(), json_replace() ++** or json_set(). ++*/ ++static void jsonWrongNumArgs( ++ sqlite3_context *pCtx, ++ const char *zFuncName ++){ ++ char *zMsg = sqlite3_mprintf("json_%s() needs an odd number of arguments", ++ zFuncName); ++ sqlite3_result_error(pCtx, zMsg, -1); ++ sqlite3_free(zMsg); ++} ++ ++/* ++** Mark all NULL entries in the Object passed in as JNODE_REMOVE. ++*/ ++static void jsonRemoveAllNulls(JsonNode *pNode){ ++ int i, n; ++ assert( pNode->eType==JSON_OBJECT ); ++ n = pNode->n; ++ for(i=2; i<=n; i += jsonNodeSize(&pNode[i])+1){ ++ switch( pNode[i].eType ){ ++ case JSON_NULL: ++ pNode[i].jnFlags |= JNODE_REMOVE; ++ break; ++ case JSON_OBJECT: ++ jsonRemoveAllNulls(&pNode[i]); ++ break; ++ } ++ } ++} ++ ++ ++/**************************************************************************** ++** SQL functions used for testing and debugging ++****************************************************************************/ ++ ++#ifdef SQLITE_DEBUG ++/* ++** The json_parse(JSON) function returns a string which describes ++** a parse of the JSON provided. Or it returns NULL if JSON is not ++** well-formed. ++*/ ++static void jsonParseFunc( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ JsonString s; /* Output string - not real JSON */ ++ JsonParse x; /* The parse */ ++ u32 i; ++ ++ assert( argc==1 ); ++ if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; ++ jsonParseFindParents(&x); ++ jsonInit(&s, ctx); ++ for(i=0; i<x.nNode; i++){ ++ const char *zType; ++ if( x.aNode[i].jnFlags & JNODE_LABEL ){ ++ assert( x.aNode[i].eType==JSON_STRING ); ++ zType = "label"; ++ }else{ ++ zType = jsonType[x.aNode[i].eType]; ++ } ++ jsonPrintf(100, &s,"node %3u: %7s n=%-4d up=%-4d", ++ i, zType, x.aNode[i].n, x.aUp[i]); ++ if( x.aNode[i].u.zJContent!=0 ){ ++ jsonAppendRaw(&s, " ", 1); ++ jsonAppendRaw(&s, x.aNode[i].u.zJContent, x.aNode[i].n); ++ } ++ jsonAppendRaw(&s, "\n", 1); ++ } ++ jsonParseReset(&x); ++ jsonResult(&s); ++} ++ ++/* ++** The json_test1(JSON) function return true (1) if the input is JSON ++** text generated by another json function. It returns (0) if the input ++** is not known to be JSON. ++*/ ++static void jsonTest1Func( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ UNUSED_PARAM(argc); ++ sqlite3_result_int(ctx, sqlite3_value_subtype(argv[0])==JSON_SUBTYPE); ++} ++#endif /* SQLITE_DEBUG */ ++ ++/**************************************************************************** ++** Scalar SQL function implementations ++****************************************************************************/ ++ ++/* ++** Implementation of the json_QUOTE(VALUE) function. Return a JSON value ++** corresponding to the SQL value input. Mostly this means putting ++** double-quotes around strings and returning the unquoted string "null" ++** when given a NULL input. ++*/ ++static void jsonQuoteFunc( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ JsonString jx; ++ UNUSED_PARAM(argc); ++ ++ jsonInit(&jx, ctx); ++ jsonAppendValue(&jx, argv[0]); ++ jsonResult(&jx); ++ sqlite3_result_subtype(ctx, JSON_SUBTYPE); ++} ++ ++/* ++** Implementation of the json_array(VALUE,...) function. Return a JSON ++** array that contains all values given in arguments. Or if any argument ++** is a BLOB, throw an error. ++*/ ++static void jsonArrayFunc( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ int i; ++ JsonString jx; ++ ++ jsonInit(&jx, ctx); ++ jsonAppendChar(&jx, '['); ++ for(i=0; i<argc; i++){ ++ jsonAppendSeparator(&jx); ++ jsonAppendValue(&jx, argv[i]); ++ } ++ jsonAppendChar(&jx, ']'); ++ jsonResult(&jx); ++ sqlite3_result_subtype(ctx, JSON_SUBTYPE); ++} ++ ++ ++/* ++** json_array_length(JSON) ++** json_array_length(JSON, PATH) ++** ++** Return the number of elements in the top-level JSON array. ++** Return 0 if the input is not a well-formed JSON array. ++*/ ++static void jsonArrayLengthFunc( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ JsonParse *p; /* The parse */ ++ sqlite3_int64 n = 0; ++ u32 i; ++ JsonNode *pNode; ++ ++ p = jsonParseCached(ctx, argv, ctx); ++ if( p==0 ) return; ++ assert( p->nNode ); ++ if( argc==2 ){ ++ const char *zPath = (const char*)sqlite3_value_text(argv[1]); ++ pNode = jsonLookup(p, zPath, 0, ctx); ++ }else{ ++ pNode = p->aNode; ++ } ++ if( pNode==0 ){ ++ return; ++ } ++ if( pNode->eType==JSON_ARRAY ){ ++ assert( (pNode->jnFlags & JNODE_APPEND)==0 ); ++ for(i=1; i<=pNode->n; n++){ ++ i += jsonNodeSize(&pNode[i]); ++ } ++ } ++ sqlite3_result_int64(ctx, n); ++} ++ ++/* ++** json_extract(JSON, PATH, ...) ++** ++** Return the element described by PATH. Return NULL if there is no ++** PATH element. If there are multiple PATHs, then return a JSON array ++** with the result from each path. Throw an error if the JSON or any PATH ++** is malformed. ++*/ ++static void jsonExtractFunc( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ JsonParse *p; /* The parse */ ++ JsonNode *pNode; ++ const char *zPath; ++ JsonString jx; ++ int i; ++ ++ if( argc<2 ) return; ++ p = jsonParseCached(ctx, argv, ctx); ++ if( p==0 ) return; ++ jsonInit(&jx, ctx); ++ jsonAppendChar(&jx, '['); ++ for(i=1; i<argc; i++){ ++ zPath = (const char*)sqlite3_value_text(argv[i]); ++ pNode = jsonLookup(p, zPath, 0, ctx); ++ if( p->nErr ) break; ++ if( argc>2 ){ ++ jsonAppendSeparator(&jx); ++ if( pNode ){ ++ jsonRenderNode(pNode, &jx, 0); ++ }else{ ++ jsonAppendRaw(&jx, "null", 4); ++ } ++ }else if( pNode ){ ++ jsonReturn(pNode, ctx, 0); ++ } ++ } ++ if( argc>2 && i==argc ){ ++ jsonAppendChar(&jx, ']'); ++ jsonResult(&jx); ++ sqlite3_result_subtype(ctx, JSON_SUBTYPE); ++ } ++ jsonReset(&jx); ++} ++ ++/* This is the RFC 7396 MergePatch algorithm. ++*/ ++static JsonNode *jsonMergePatch( ++ JsonParse *pParse, /* The JSON parser that contains the TARGET */ ++ u32 iTarget, /* Node of the TARGET in pParse */ ++ JsonNode *pPatch /* The PATCH */ ++){ ++ u32 i, j; ++ u32 iRoot; ++ JsonNode *pTarget; ++ if( pPatch->eType!=JSON_OBJECT ){ ++ return pPatch; ++ } ++ assert( iTarget>=0 && iTarget<pParse->nNode ); ++ pTarget = &pParse->aNode[iTarget]; ++ assert( (pPatch->jnFlags & JNODE_APPEND)==0 ); ++ if( pTarget->eType!=JSON_OBJECT ){ ++ jsonRemoveAllNulls(pPatch); ++ return pPatch; ++ } ++ iRoot = iTarget; ++ for(i=1; i<pPatch->n; i += jsonNodeSize(&pPatch[i+1])+1){ ++ u32 nKey; ++ const char *zKey; ++ assert( pPatch[i].eType==JSON_STRING ); ++ assert( pPatch[i].jnFlags & JNODE_LABEL ); ++ 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]; ++ if( pNew!=&pTarget[j+1] ){ ++ pTarget[j+1].u.pPatch = pNew; ++ pTarget[j+1].jnFlags |= JNODE_PATCH; ++ } ++ } ++ break; ++ } ++ } ++ if( j>=pTarget->n && pPatch[i+1].eType!=JSON_NULL ){ ++ int iStart, iPatch; ++ iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0); ++ jsonParseAddNode(pParse, JSON_STRING, nKey, zKey); ++ iPatch = jsonParseAddNode(pParse, JSON_TRUE, 0, 0); ++ if( pParse->oom ) return 0; ++ jsonRemoveAllNulls(pPatch); ++ pTarget = &pParse->aNode[iTarget]; ++ pParse->aNode[iRoot].jnFlags |= JNODE_APPEND; ++ pParse->aNode[iRoot].u.iAppend = iStart - iRoot; ++ iRoot = iStart; ++ pParse->aNode[iPatch].jnFlags |= JNODE_PATCH; ++ pParse->aNode[iPatch].u.pPatch = &pPatch[i+1]; ++ } ++ } ++ return pTarget; ++} ++ ++/* ++** Implementation of the json_mergepatch(JSON1,JSON2) function. Return a JSON ++** object that is the result of running the RFC 7396 MergePatch() algorithm ++** on the two arguments. ++*/ ++static void jsonPatchFunc( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ JsonParse x; /* The JSON that is being patched */ ++ JsonParse y; /* The patch */ ++ JsonNode *pResult; /* The result of the merge */ ++ ++ UNUSED_PARAM(argc); ++ if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; ++ if( jsonParse(&y, ctx, (const char*)sqlite3_value_text(argv[1])) ){ ++ jsonParseReset(&x); ++ return; ++ } ++ pResult = jsonMergePatch(&x, 0, y.aNode); ++ assert( pResult!=0 || x.oom ); ++ if( pResult ){ ++ jsonReturnJson(pResult, ctx, 0); ++ }else{ ++ sqlite3_result_error_nomem(ctx); ++ } ++ jsonParseReset(&x); ++ jsonParseReset(&y); ++} ++ ++ ++/* ++** Implementation of the json_object(NAME,VALUE,...) function. Return a JSON ++** object that contains all name/value given in arguments. Or if any name ++** is not a string or if any value is a BLOB, throw an error. ++*/ ++static void jsonObjectFunc( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ int i; ++ JsonString jx; ++ const char *z; ++ u32 n; ++ ++ if( argc&1 ){ ++ sqlite3_result_error(ctx, "json_object() requires an even number " ++ "of arguments", -1); ++ return; ++ } ++ jsonInit(&jx, ctx); ++ jsonAppendChar(&jx, '{'); ++ for(i=0; i<argc; i+=2){ ++ if( sqlite3_value_type(argv[i])!=SQLITE_TEXT ){ ++ sqlite3_result_error(ctx, "json_object() labels must be TEXT", -1); ++ jsonReset(&jx); ++ return; ++ } ++ jsonAppendSeparator(&jx); ++ z = (const char*)sqlite3_value_text(argv[i]); ++ n = (u32)sqlite3_value_bytes(argv[i]); ++ jsonAppendString(&jx, z, n); ++ jsonAppendChar(&jx, ':'); ++ jsonAppendValue(&jx, argv[i+1]); ++ } ++ jsonAppendChar(&jx, '}'); ++ jsonResult(&jx); ++ sqlite3_result_subtype(ctx, JSON_SUBTYPE); ++} ++ ++ ++/* ++** json_remove(JSON, PATH, ...) ++** ++** Remove the named elements from JSON and return the result. malformed ++** JSON or PATH arguments result in an error. ++*/ ++static void jsonRemoveFunc( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ JsonParse x; /* The parse */ ++ JsonNode *pNode; ++ const char *zPath; ++ u32 i; ++ ++ if( argc<1 ) return; ++ if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; ++ assert( x.nNode ); ++ for(i=1; i<(u32)argc; i++){ ++ zPath = (const char*)sqlite3_value_text(argv[i]); ++ if( zPath==0 ) goto remove_done; ++ pNode = jsonLookup(&x, zPath, 0, ctx); ++ if( x.nErr ) goto remove_done; ++ if( pNode ) pNode->jnFlags |= JNODE_REMOVE; ++ } ++ if( (x.aNode[0].jnFlags & JNODE_REMOVE)==0 ){ ++ jsonReturnJson(x.aNode, ctx, 0); ++ } ++remove_done: ++ jsonParseReset(&x); ++} ++ ++/* ++** json_replace(JSON, PATH, VALUE, ...) ++** ++** Replace the value at PATH with VALUE. If PATH does not already exist, ++** this routine is a no-op. If JSON or PATH is malformed, throw an error. ++*/ ++static void jsonReplaceFunc( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ JsonParse x; /* The parse */ ++ JsonNode *pNode; ++ const char *zPath; ++ u32 i; ++ ++ if( argc<1 ) return; ++ if( (argc&1)==0 ) { ++ jsonWrongNumArgs(ctx, "replace"); ++ return; ++ } ++ if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; ++ assert( x.nNode ); ++ for(i=1; i<(u32)argc; i+=2){ ++ zPath = (const char*)sqlite3_value_text(argv[i]); ++ pNode = jsonLookup(&x, zPath, 0, ctx); ++ if( x.nErr ) goto replace_err; ++ if( pNode ){ ++ pNode->jnFlags |= (u8)JNODE_REPLACE; ++ pNode->u.iReplace = i + 1; ++ } ++ } ++ if( x.aNode[0].jnFlags & JNODE_REPLACE ){ ++ sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]); ++ }else{ ++ jsonReturnJson(x.aNode, ctx, argv); ++ } ++replace_err: ++ jsonParseReset(&x); ++} ++ ++/* ++** json_set(JSON, PATH, VALUE, ...) ++** ++** Set the value at PATH to VALUE. Create the PATH if it does not already ++** exist. Overwrite existing values that do exist. ++** If JSON or PATH is malformed, throw an error. ++** ++** json_insert(JSON, PATH, VALUE, ...) ++** ++** Create PATH and initialize it to VALUE. If PATH already exists, this ++** routine is a no-op. If JSON or PATH is malformed, throw an error. ++*/ ++static void jsonSetFunc( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ JsonParse x; /* The parse */ ++ JsonNode *pNode; ++ const char *zPath; ++ u32 i; ++ int bApnd; ++ int bIsSet = *(int*)sqlite3_user_data(ctx); ++ ++ if( argc<1 ) return; ++ if( (argc&1)==0 ) { ++ jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert"); ++ return; ++ } ++ if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; ++ assert( x.nNode ); ++ for(i=1; i<(u32)argc; i+=2){ ++ zPath = (const char*)sqlite3_value_text(argv[i]); ++ bApnd = 0; ++ pNode = jsonLookup(&x, zPath, &bApnd, ctx); ++ if( x.oom ){ ++ sqlite3_result_error_nomem(ctx); ++ goto jsonSetDone; ++ }else if( x.nErr ){ ++ goto jsonSetDone; ++ }else if( pNode && (bApnd || bIsSet) ){ ++ pNode->jnFlags |= (u8)JNODE_REPLACE; ++ pNode->u.iReplace = i + 1; ++ } ++ } ++ if( x.aNode[0].jnFlags & JNODE_REPLACE ){ ++ sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]); ++ }else{ ++ jsonReturnJson(x.aNode, ctx, argv); ++ } ++jsonSetDone: ++ jsonParseReset(&x); ++} ++ ++/* ++** json_type(JSON) ++** json_type(JSON, PATH) ++** ++** Return the top-level "type" of a JSON string. Throw an error if ++** either the JSON or PATH inputs are not well-formed. ++*/ ++static void jsonTypeFunc( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ JsonParse *p; /* The parse */ ++ const char *zPath; ++ JsonNode *pNode; ++ ++ p = jsonParseCached(ctx, argv, ctx); ++ if( p==0 ) return; ++ if( argc==2 ){ ++ zPath = (const char*)sqlite3_value_text(argv[1]); ++ pNode = jsonLookup(p, zPath, 0, ctx); ++ }else{ ++ pNode = p->aNode; ++ } ++ if( pNode ){ ++ 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_PARAM(argc); ++ p = jsonParseCached(ctx, argv, 0); ++ sqlite3_result_int(ctx, p!=0); ++} ++ ++ ++/**************************************************************************** ++** Aggregate SQL function implementations ++****************************************************************************/ ++/* ++** json_group_array(VALUE) ++** ++** Return a JSON array composed of all values in the aggregate. ++*/ ++static void jsonArrayStep( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ JsonString *pStr; ++ UNUSED_PARAM(argc); ++ pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); ++ if( pStr ){ ++ if( pStr->zBuf==0 ){ ++ jsonInit(pStr, ctx); ++ jsonAppendChar(pStr, '['); ++ }else{ ++ jsonAppendChar(pStr, ','); ++ pStr->pCtx = ctx; ++ } ++ jsonAppendValue(pStr, argv[0]); ++ } ++} ++static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){ ++ JsonString *pStr; ++ pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); ++ if( pStr ){ ++ pStr->pCtx = ctx; ++ jsonAppendChar(pStr, ']'); ++ if( pStr->bErr ){ ++ if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); ++ assert( pStr->bStatic ); ++ }else if( isFinal ){ ++ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, ++ pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); ++ pStr->bStatic = 1; ++ }else{ ++ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); ++ pStr->nUsed--; ++ } ++ }else{ ++ sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC); ++ } ++ sqlite3_result_subtype(ctx, JSON_SUBTYPE); ++} ++static void jsonArrayValue(sqlite3_context *ctx){ ++ jsonArrayCompute(ctx, 0); ++} ++static void jsonArrayFinal(sqlite3_context *ctx){ ++ jsonArrayCompute(ctx, 1); ++} ++ ++#ifndef SQLITE_OMIT_WINDOWFUNC ++/* ++** This method works for both json_group_array() and json_group_object(). ++** It works by removing the first element of the group by searching forward ++** to the first comma (",") that is not within a string and deleting all ++** text through that comma. ++*/ ++static void jsonGroupInverse( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ int i; ++ int inStr = 0; ++ char *z; ++ JsonString *pStr; ++ UNUSED_PARAM(argc); ++ UNUSED_PARAM(argv); ++ pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); ++#ifdef NEVER ++ /* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will ++ ** always have been called to initalize it */ ++ if( NEVER(!pStr) ) return; ++#endif ++ z = pStr->zBuf; ++ for(i=1; z[i]!=',' || inStr; i++){ ++ assert( i<pStr->nUsed ); ++ if( z[i]=='"' ){ ++ inStr = !inStr; ++ }else if( z[i]=='\\' ){ ++ i++; ++ } ++ } ++ pStr->nUsed -= i; ++ memmove(&z[1], &z[i+1], (size_t)pStr->nUsed-1); ++} ++#else ++# define jsonGroupInverse 0 ++#endif ++ ++ ++/* ++** json_group_obj(NAME,VALUE) ++** ++** Return a JSON object composed of all names and values in the aggregate. ++*/ ++static void jsonObjectStep( ++ sqlite3_context *ctx, ++ int argc, ++ sqlite3_value **argv ++){ ++ JsonString *pStr; ++ const char *z; ++ u32 n; ++ UNUSED_PARAM(argc); ++ pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); ++ if( pStr ){ ++ if( pStr->zBuf==0 ){ ++ jsonInit(pStr, ctx); ++ jsonAppendChar(pStr, '{'); ++ }else{ ++ jsonAppendChar(pStr, ','); ++ pStr->pCtx = ctx; ++ } ++ z = (const char*)sqlite3_value_text(argv[0]); ++ n = (u32)sqlite3_value_bytes(argv[0]); ++ jsonAppendString(pStr, z, n); ++ jsonAppendChar(pStr, ':'); ++ jsonAppendValue(pStr, argv[1]); ++ } ++} ++static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){ ++ JsonString *pStr; ++ pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); ++ if( pStr ){ ++ jsonAppendChar(pStr, '}'); ++ if( pStr->bErr ){ ++ if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); ++ assert( pStr->bStatic ); ++ }else if( isFinal ){ ++ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, ++ pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); ++ pStr->bStatic = 1; ++ }else{ ++ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); ++ pStr->nUsed--; ++ } ++ }else{ ++ sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC); ++ } ++ sqlite3_result_subtype(ctx, JSON_SUBTYPE); ++} ++static void jsonObjectValue(sqlite3_context *ctx){ ++ jsonObjectCompute(ctx, 0); ++} ++static void jsonObjectFinal(sqlite3_context *ctx){ ++ jsonObjectCompute(ctx, 1); ++} ++ ++ ++ ++#ifndef SQLITE_OMIT_VIRTUALTABLE ++/**************************************************************************** ++** The json_each virtual table ++****************************************************************************/ ++typedef struct JsonEachCursor JsonEachCursor; ++struct JsonEachCursor { ++ sqlite3_vtab_cursor base; /* Base class - must be first */ ++ u32 iRowid; /* The rowid */ ++ u32 iBegin; /* The first node of the scan */ ++ u32 i; /* Index in sParse.aNode[] of current row */ ++ u32 iEnd; /* EOF when i equals or exceeds this value */ ++ u8 eType; /* Type of top-level element */ ++ u8 bRecursive; /* True for json_tree(). False for json_each() */ ++ char *zJson; /* Input JSON */ ++ char *zRoot; /* Path by which to filter zJson */ ++ JsonParse sParse; /* Parse of the input JSON */ ++}; ++ ++/* Constructor for the json_each virtual table */ ++static int jsonEachConnect( ++ sqlite3 *db, ++ void *pAux, ++ int argc, const char *const*argv, ++ sqlite3_vtab **ppVtab, ++ char **pzErr ++){ ++ sqlite3_vtab *pNew; ++ int rc; ++ ++/* Column numbers */ ++#define JEACH_KEY 0 ++#define JEACH_VALUE 1 ++#define JEACH_TYPE 2 ++#define JEACH_ATOM 3 ++#define JEACH_ID 4 ++#define JEACH_PARENT 5 ++#define JEACH_FULLKEY 6 ++#define JEACH_PATH 7 ++/* The xBestIndex method assumes that the JSON and ROOT columns are ++** the last two columns in the table. Should this ever changes, be ++** sure to update the xBestIndex method. */ ++#define JEACH_JSON 8 ++#define JEACH_ROOT 9 ++ ++ UNUSED_PARAM(pzErr); ++ UNUSED_PARAM(argv); ++ UNUSED_PARAM(argc); ++ UNUSED_PARAM(pAux); ++ rc = sqlite3_declare_vtab(db, ++ "CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path," ++ "json HIDDEN,root HIDDEN)"); ++ if( rc==SQLITE_OK ){ ++ pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) ); ++ if( pNew==0 ) return SQLITE_NOMEM; ++ memset(pNew, 0, sizeof(*pNew)); ++ } ++ return rc; ++} ++ ++/* destructor for json_each virtual table */ ++static int jsonEachDisconnect(sqlite3_vtab *pVtab){ ++ sqlite3_free(pVtab); ++ return SQLITE_OK; ++} ++ ++/* constructor for a JsonEachCursor object for json_each(). */ ++static int jsonEachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ ++ JsonEachCursor *pCur; ++ ++ UNUSED_PARAM(p); ++ pCur = sqlite3_malloc( sizeof(*pCur) ); ++ if( pCur==0 ) return SQLITE_NOMEM; ++ memset(pCur, 0, sizeof(*pCur)); ++ *ppCursor = &pCur->base; ++ return SQLITE_OK; ++} ++ ++/* constructor for a JsonEachCursor object for json_tree(). */ ++static int jsonEachOpenTree(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ ++ int rc = jsonEachOpenEach(p, ppCursor); ++ if( rc==SQLITE_OK ){ ++ JsonEachCursor *pCur = (JsonEachCursor*)*ppCursor; ++ pCur->bRecursive = 1; ++ } ++ return rc; ++} ++ ++/* Reset a JsonEachCursor back to its original state. Free any memory ++** held. */ ++static void jsonEachCursorReset(JsonEachCursor *p){ ++ sqlite3_free(p->zJson); ++ sqlite3_free(p->zRoot); ++ jsonParseReset(&p->sParse); ++ p->iRowid = 0; ++ p->i = 0; ++ p->iEnd = 0; ++ p->eType = 0; ++ p->zJson = 0; ++ p->zRoot = 0; ++} ++ ++/* Destructor for a jsonEachCursor object */ ++static int jsonEachClose(sqlite3_vtab_cursor *cur){ ++ JsonEachCursor *p = (JsonEachCursor*)cur; ++ jsonEachCursorReset(p); ++ sqlite3_free(cur); ++ return SQLITE_OK; ++} ++ ++/* Return TRUE if the jsonEachCursor object has been advanced off the end ++** of the JSON object */ ++static int jsonEachEof(sqlite3_vtab_cursor *cur){ ++ JsonEachCursor *p = (JsonEachCursor*)cur; ++ return p->i >= p->iEnd; ++} ++ ++/* Advance the cursor to the next element for json_tree() */ ++static int jsonEachNext(sqlite3_vtab_cursor *cur){ ++ JsonEachCursor *p = (JsonEachCursor*)cur; ++ if( p->bRecursive ){ ++ if( p->sParse.aNode[p->i].jnFlags & JNODE_LABEL ) p->i++; ++ p->i++; ++ p->iRowid++; ++ if( p->i<p->iEnd ){ ++ u32 iUp = p->sParse.aUp[p->i]; ++ JsonNode *pUp = &p->sParse.aNode[iUp]; ++ p->eType = pUp->eType; ++ if( pUp->eType==JSON_ARRAY ){ ++ if( iUp==p->i-1 ){ ++ pUp->u.iKey = 0; ++ }else{ ++ pUp->u.iKey++; ++ } ++ } ++ } ++ }else{ ++ switch( p->eType ){ ++ case JSON_ARRAY: { ++ p->i += jsonNodeSize(&p->sParse.aNode[p->i]); ++ p->iRowid++; ++ break; ++ } ++ case JSON_OBJECT: { ++ p->i += 1 + jsonNodeSize(&p->sParse.aNode[p->i+1]); ++ p->iRowid++; ++ break; ++ } ++ default: { ++ p->i = p->iEnd; ++ break; ++ } ++ } ++ } ++ return SQLITE_OK; ++} ++ ++/* Append the name of the path for element i to pStr ++*/ ++static void jsonEachComputePath( ++ JsonEachCursor *p, /* The cursor */ ++ JsonString *pStr, /* Write the path here */ ++ u32 i /* Path to this element */ ++){ ++ JsonNode *pNode, *pUp; ++ u32 iUp; ++ if( i==0 ){ ++ jsonAppendChar(pStr, '$'); ++ return; ++ } ++ iUp = p->sParse.aUp[i]; ++ jsonEachComputePath(p, pStr, iUp); ++ pNode = &p->sParse.aNode[i]; ++ pUp = &p->sParse.aNode[iUp]; ++ if( pUp->eType==JSON_ARRAY ){ ++ jsonPrintf(30, pStr, "[%d]", pUp->u.iKey); ++ }else{ ++ assert( pUp->eType==JSON_OBJECT ); ++ if( (pNode->jnFlags & JNODE_LABEL)==0 ) pNode--; ++ assert( pNode->eType==JSON_STRING ); ++ assert( pNode->jnFlags & JNODE_LABEL ); ++ jsonPrintf(pNode->n+1, pStr, ".%.*s", pNode->n-2, pNode->u.zJContent+1); ++ } ++} ++ ++/* Return the value of a column */ ++static int jsonEachColumn( ++ sqlite3_vtab_cursor *cur, /* The cursor */ ++ sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ ++ int i /* Which column to return */ ++){ ++ JsonEachCursor *p = (JsonEachCursor*)cur; ++ JsonNode *pThis = &p->sParse.aNode[p->i]; ++ switch( i ){ ++ case JEACH_KEY: { ++ if( p->i==0 ) break; ++ if( p->eType==JSON_OBJECT ){ ++ jsonReturn(pThis, ctx, 0); ++ }else if( p->eType==JSON_ARRAY ){ ++ u32 iKey; ++ if( p->bRecursive ){ ++ if( p->iRowid==0 ) break; ++ iKey = p->sParse.aNode[p->sParse.aUp[p->i]].u.iKey; ++ }else{ ++ iKey = p->iRowid; ++ } ++ sqlite3_result_int64(ctx, (sqlite3_int64)iKey); ++ } ++ break; ++ } ++ case JEACH_VALUE: { ++ if( pThis->jnFlags & JNODE_LABEL ) pThis++; ++ jsonReturn(pThis, ctx, 0); ++ break; ++ } ++ case JEACH_TYPE: { ++ if( pThis->jnFlags & JNODE_LABEL ) pThis++; ++ sqlite3_result_text(ctx, jsonType[pThis->eType], -1, SQLITE_STATIC); ++ break; ++ } ++ case JEACH_ATOM: { ++ if( pThis->jnFlags & JNODE_LABEL ) pThis++; ++ if( pThis->eType>=JSON_ARRAY ) break; ++ jsonReturn(pThis, ctx, 0); ++ break; ++ } ++ case JEACH_ID: { ++ sqlite3_result_int64(ctx, ++ (sqlite3_int64)p->i + ((pThis->jnFlags & JNODE_LABEL)!=0)); ++ break; ++ } ++ case JEACH_PARENT: { ++ if( p->i>p->iBegin && p->bRecursive ){ ++ sqlite3_result_int64(ctx, (sqlite3_int64)p->sParse.aUp[p->i]); ++ } ++ break; ++ } ++ case JEACH_FULLKEY: { ++ JsonString x; ++ jsonInit(&x, ctx); ++ if( p->bRecursive ){ ++ jsonEachComputePath(p, &x, p->i); ++ }else{ ++ if( p->zRoot ){ ++ jsonAppendRaw(&x, p->zRoot, (int)strlen(p->zRoot)); ++ }else{ ++ jsonAppendChar(&x, '$'); ++ } ++ if( p->eType==JSON_ARRAY ){ ++ jsonPrintf(30, &x, "[%d]", p->iRowid); ++ }else if( p->eType==JSON_OBJECT ){ ++ jsonPrintf(pThis->n, &x, ".%.*s", pThis->n-2, pThis->u.zJContent+1); ++ } ++ } ++ jsonResult(&x); ++ break; ++ } ++ case JEACH_PATH: { ++ if( p->bRecursive ){ ++ JsonString x; ++ jsonInit(&x, ctx); ++ jsonEachComputePath(p, &x, p->sParse.aUp[p->i]); ++ jsonResult(&x); ++ break; ++ } ++ /* For json_each() path and root are the same so fall through ++ ** into the root case */ ++ } ++ default: { ++ const char *zRoot = p->zRoot; ++ if( zRoot==0 ) zRoot = "$"; ++ sqlite3_result_text(ctx, zRoot, -1, SQLITE_STATIC); ++ break; ++ } ++ case JEACH_JSON: { ++ assert( i==JEACH_JSON ); ++ sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_STATIC); ++ break; ++ } ++ } ++ return SQLITE_OK; ++} ++ ++/* Return the current rowid value */ ++static int jsonEachRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ ++ JsonEachCursor *p = (JsonEachCursor*)cur; ++ *pRowid = p->iRowid; ++ return SQLITE_OK; ++} ++ ++/* The query strategy is to look for an equality constraint on the json ++** column. Without such a constraint, the table cannot operate. idxNum is ++** 1 if the constraint is found, 3 if the constraint and zRoot are found, ++** and 0 otherwise. ++*/ ++static int jsonEachBestIndex( ++ sqlite3_vtab *tab, ++ sqlite3_index_info *pIdxInfo ++){ ++ int i; /* Loop counter or computed array index */ ++ int aIdx[2]; /* Index of constraints for JSON and ROOT */ ++ int unusableMask = 0; /* Mask of unusable JSON and ROOT constraints */ ++ int idxMask = 0; /* Mask of usable == constraints JSON and ROOT */ ++ const struct sqlite3_index_constraint *pConstraint; ++ ++ /* This implementation assumes that JSON and ROOT are the last two ++ ** columns in the table */ ++ assert( JEACH_ROOT == JEACH_JSON+1 ); ++ UNUSED_PARAM(tab); ++ aIdx[0] = aIdx[1] = -1; ++ pConstraint = pIdxInfo->aConstraint; ++ for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ ++ int iCol; ++ int iMask; ++ if( pConstraint->iColumn < JEACH_JSON ) continue; ++ iCol = pConstraint->iColumn - JEACH_JSON; ++ assert( iCol==0 || iCol==1 ); ++ iMask = 1 << iCol; ++ if( pConstraint->usable==0 ){ ++ unusableMask |= iMask; ++ }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ ++ aIdx[iCol] = i; ++ idxMask |= iMask; ++ } ++ } ++ if( (unusableMask & ~idxMask)!=0 ){ ++ /* If there are any unusable constraints on JSON or ROOT, then reject ++ ** this entire plan */ ++ return SQLITE_CONSTRAINT; ++ } ++ if( aIdx[0]<0 ){ ++ /* No JSON input. Leave estimatedCost at the huge value that it was ++ ** initialized to to discourage the query planner from selecting this ++ ** plan. */ ++ pIdxInfo->idxNum = 0; ++ }else{ ++ pIdxInfo->estimatedCost = 1.0; ++ i = aIdx[0]; ++ pIdxInfo->aConstraintUsage[i].argvIndex = 1; ++ pIdxInfo->aConstraintUsage[i].omit = 1; ++ if( aIdx[1]<0 ){ ++ pIdxInfo->idxNum = 1; /* Only JSON supplied. Plan 1 */ ++ }else{ ++ i = aIdx[1]; ++ pIdxInfo->aConstraintUsage[i].argvIndex = 2; ++ pIdxInfo->aConstraintUsage[i].omit = 1; ++ pIdxInfo->idxNum = 3; /* Both JSON and ROOT are supplied. Plan 3 */ ++ } ++ } ++ return SQLITE_OK; ++} ++ ++/* Start a search on a new JSON string */ ++static int jsonEachFilter( ++ sqlite3_vtab_cursor *cur, ++ int idxNum, const char *idxStr, ++ int argc, sqlite3_value **argv ++){ ++ JsonEachCursor *p = (JsonEachCursor*)cur; ++ const char *z; ++ const char *zRoot = 0; ++ sqlite3_int64 n; ++ ++ UNUSED_PARAM(idxStr); ++ UNUSED_PARAM(argc); ++ jsonEachCursorReset(p); ++ if( idxNum==0 ) return SQLITE_OK; ++ z = (const char*)sqlite3_value_text(argv[0]); ++ if( z==0 ) return SQLITE_OK; ++ n = sqlite3_value_bytes(argv[0]); ++ p->zJson = sqlite3_malloc64( n+1 ); ++ if( p->zJson==0 ) return SQLITE_NOMEM; ++ memcpy(p->zJson, z, (size_t)n+1); ++ if( jsonParse(&p->sParse, 0, p->zJson) ){ ++ int rc = SQLITE_NOMEM; ++ if( p->sParse.oom==0 ){ ++ sqlite3_free(cur->pVtab->zErrMsg); ++ cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON"); ++ if( cur->pVtab->zErrMsg ) rc = SQLITE_ERROR; ++ } ++ jsonEachCursorReset(p); ++ return rc; ++ }else if( p->bRecursive && jsonParseFindParents(&p->sParse) ){ ++ jsonEachCursorReset(p); ++ return SQLITE_NOMEM; ++ }else{ ++ JsonNode *pNode = 0; ++ if( idxNum==3 ){ ++ const char *zErr = 0; ++ zRoot = (const char*)sqlite3_value_text(argv[1]); ++ if( zRoot==0 ) return SQLITE_OK; ++ n = sqlite3_value_bytes(argv[1]); ++ p->zRoot = sqlite3_malloc64( n+1 ); ++ if( p->zRoot==0 ) return SQLITE_NOMEM; ++ memcpy(p->zRoot, zRoot, (size_t)n+1); ++ if( zRoot[0]!='$' ){ ++ zErr = zRoot; ++ }else{ ++ pNode = jsonLookupStep(&p->sParse, 0, p->zRoot+1, 0, &zErr); ++ } ++ if( zErr ){ ++ sqlite3_free(cur->pVtab->zErrMsg); ++ cur->pVtab->zErrMsg = jsonPathSyntaxError(zErr); ++ jsonEachCursorReset(p); ++ return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; ++ }else if( pNode==0 ){ ++ return SQLITE_OK; ++ } ++ }else{ ++ pNode = p->sParse.aNode; ++ } ++ p->iBegin = p->i = (int)(pNode - p->sParse.aNode); ++ p->eType = pNode->eType; ++ if( p->eType>=JSON_ARRAY ){ ++ pNode->u.iKey = 0; ++ p->iEnd = p->i + pNode->n + 1; ++ if( p->bRecursive ){ ++ p->eType = p->sParse.aNode[p->sParse.aUp[p->i]].eType; ++ if( p->i>0 && (p->sParse.aNode[p->i-1].jnFlags & JNODE_LABEL)!=0 ){ ++ p->i--; ++ } ++ }else{ ++ p->i++; ++ } ++ }else{ ++ p->iEnd = p->i+1; ++ } ++ } ++ return SQLITE_OK; ++} ++ ++/* The methods of the json_each virtual table */ ++static sqlite3_module jsonEachModule = { ++ 0, /* iVersion */ ++ 0, /* xCreate */ ++ jsonEachConnect, /* xConnect */ ++ jsonEachBestIndex, /* xBestIndex */ ++ jsonEachDisconnect, /* xDisconnect */ ++ 0, /* xDestroy */ ++ jsonEachOpenEach, /* xOpen - open a cursor */ ++ jsonEachClose, /* xClose - close a cursor */ ++ jsonEachFilter, /* xFilter - configure scan constraints */ ++ jsonEachNext, /* xNext - advance a cursor */ ++ jsonEachEof, /* xEof - check for end of scan */ ++ jsonEachColumn, /* xColumn - read data */ ++ jsonEachRowid, /* xRowid - read data */ ++ 0, /* xUpdate */ ++ 0, /* xBegin */ ++ 0, /* xSync */ ++ 0, /* xCommit */ ++ 0, /* xRollback */ ++ 0, /* xFindMethod */ ++ 0, /* xRename */ ++ 0, /* xSavepoint */ ++ 0, /* xRelease */ ++ 0, /* xRollbackTo */ ++ 0 /* xShadowName */ ++}; ++ ++/* The methods of the json_tree virtual table. */ ++static sqlite3_module jsonTreeModule = { ++ 0, /* iVersion */ ++ 0, /* xCreate */ ++ jsonEachConnect, /* xConnect */ ++ jsonEachBestIndex, /* xBestIndex */ ++ jsonEachDisconnect, /* xDisconnect */ ++ 0, /* xDestroy */ ++ jsonEachOpenTree, /* xOpen - open a cursor */ ++ jsonEachClose, /* xClose - close a cursor */ ++ jsonEachFilter, /* xFilter - configure scan constraints */ ++ jsonEachNext, /* xNext - advance a cursor */ ++ jsonEachEof, /* xEof - check for end of scan */ ++ jsonEachColumn, /* xColumn - read data */ ++ jsonEachRowid, /* xRowid - read data */ ++ 0, /* xUpdate */ ++ 0, /* xBegin */ ++ 0, /* xSync */ ++ 0, /* xCommit */ ++ 0, /* xRollback */ ++ 0, /* xFindMethod */ ++ 0, /* xRename */ ++ 0, /* xSavepoint */ ++ 0, /* xRelease */ ++ 0, /* xRollbackTo */ ++ 0 /* xShadowName */ ++}; ++#endif /* SQLITE_OMIT_VIRTUALTABLE */ ++ ++/**************************************************************************** ++** The following routines are the only publically visible identifiers in this ++** file. Call the following routines in order to register the various SQL ++** functions and the virtual table implemented by this file. ++****************************************************************************/ ++ ++SQLITE_PRIVATE int sqlite3Json1Init(sqlite3 *db){ ++ int rc = SQLITE_OK; ++ unsigned int i; ++ static const struct { ++ const char *zName; ++ int nArg; ++ int flag; ++ void (*xFunc)(sqlite3_context*,int,sqlite3_value**); ++ } aFunc[] = { ++ { "json", 1, 0, jsonRemoveFunc }, ++ { "json_array", -1, 0, jsonArrayFunc }, ++ { "json_array_length", 1, 0, jsonArrayLengthFunc }, ++ { "json_array_length", 2, 0, jsonArrayLengthFunc }, ++ { "json_extract", -1, 0, jsonExtractFunc }, ++ { "json_insert", -1, 0, jsonSetFunc }, ++ { "json_object", -1, 0, jsonObjectFunc }, ++ { "json_patch", 2, 0, jsonPatchFunc }, ++ { "json_quote", 1, 0, jsonQuoteFunc }, ++ { "json_remove", -1, 0, jsonRemoveFunc }, ++ { "json_replace", -1, 0, jsonReplaceFunc }, ++ { "json_set", -1, 1, jsonSetFunc }, ++ { "json_type", 1, 0, jsonTypeFunc }, ++ { "json_type", 2, 0, jsonTypeFunc }, ++ { "json_valid", 1, 0, jsonValidFunc }, ++ ++#if SQLITE_DEBUG ++ /* DEBUG and TESTING functions */ ++ { "json_parse", 1, 0, jsonParseFunc }, ++ { "json_test1", 1, 0, jsonTest1Func }, ++#endif ++ }; ++ static const struct { ++ const char *zName; ++ int nArg; ++ void (*xStep)(sqlite3_context*,int,sqlite3_value**); ++ void (*xFinal)(sqlite3_context*); ++ void (*xValue)(sqlite3_context*); ++ } aAgg[] = { ++ { "json_group_array", 1, ++ jsonArrayStep, jsonArrayFinal, jsonArrayValue }, ++ { "json_group_object", 2, ++ jsonObjectStep, jsonObjectFinal, jsonObjectValue }, ++ }; ++#ifndef SQLITE_OMIT_VIRTUALTABLE ++ static const struct { ++ const char *zName; ++ sqlite3_module *pModule; ++ } aMod[] = { ++ { "json_each", &jsonEachModule }, ++ { "json_tree", &jsonTreeModule }, ++ }; ++#endif ++ for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){ ++ rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg, ++ SQLITE_UTF8 | SQLITE_DETERMINISTIC, ++ (void*)&aFunc[i].flag, ++ aFunc[i].xFunc, 0, 0); ++ } ++#ifndef SQLITE_OMIT_WINDOWFUNC ++ for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){ ++ rc = sqlite3_create_window_function(db, aAgg[i].zName, aAgg[i].nArg, ++ SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0, ++ aAgg[i].xStep, aAgg[i].xFinal, ++ aAgg[i].xValue, jsonGroupInverse, 0); ++ } ++#endif ++#ifndef SQLITE_OMIT_VIRTUALTABLE ++ for(i=0; i<sizeof(aMod)/sizeof(aMod[0]) && rc==SQLITE_OK; i++){ ++ rc = sqlite3_create_module(db, aMod[i].zName, aMod[i].pModule, 0); ++ } ++#endif ++ return rc; ++} ++ ++ ++#ifndef SQLITE_CORE ++#ifdef _WIN32 ++__declspec(dllexport) ++#endif ++SQLITE_API int sqlite3_json_init( ++ sqlite3 *db, ++ char **pzErrMsg, ++ const sqlite3_api_routines *pApi ++){ ++ SQLITE_EXTENSION_INIT2(pApi); ++ (void)pzErrMsg; /* Unused parameter */ ++ return sqlite3Json1Init(db); ++} ++#endif ++#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1) */ ++ ++/************** End of json1.c ***********************************************/ + /************** Begin file rtree.c *******************************************/ + /* + ** 2001 September 15 +@@ -168822,7 +179149,7 @@ + ** + ** CREATE TABLE %_node(nodeno INTEGER PRIMARY KEY, data BLOB) + ** CREATE TABLE %_parent(nodeno INTEGER PRIMARY KEY, parentnode INTEGER) +-** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER) ++** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER, ...) + ** + ** The data for each node of the r-tree structure is stored in the %_node + ** table. For each node that is not the root node of the r-tree, there is +@@ -168829,7 +179156,8 @@ + ** an entry in the %_parent table associating the node with its parent. + ** And for each row of data in the table, there is an entry in the %_rowid + ** table that maps from the entries rowid to the id of the node that it +-** is stored on. ++** is stored on. If the r-tree contains auxiliary columns, those are stored ++** on the end of the %_rowid table. + ** + ** The root node of an r-tree always exists, even if the r-tree table is + ** empty. The nodeno of the root node is always 1. All other nodes in the +@@ -168892,6 +179220,9 @@ + /* The rtree may have between 1 and RTREE_MAX_DIMENSIONS dimensions. */ + #define RTREE_MAX_DIMENSIONS 5 + ++/* Maximum number of auxiliary columns */ ++#define RTREE_MAX_AUX_COLUMN 100 ++ + /* Size of hash table Rtree.aHash. This hash table is not expected to + ** ever contain very many entries, so a fixed number of buckets is + ** used. +@@ -168920,6 +179251,8 @@ + u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */ + u8 nBytesPerCell; /* Bytes consumed per cell */ + u8 inWrTrans; /* True if inside write transaction */ ++ u8 nAux; /* # of auxiliary columns in %_rowid */ ++ u8 nAuxNotNull; /* Number of initial not-null aux columns */ + int iDepth; /* Current depth of the r-tree structure */ + char *zDb; /* Name of database containing r-tree table */ + char *zName; /* Name of r-tree table */ +@@ -168926,6 +179259,8 @@ + u32 nBusy; /* Current number of users of this structure */ + i64 nRowEst; /* Estimated number of rows in this table */ + u32 nCursor; /* Number of open cursors */ ++ u32 nNodeRef; /* Number RtreeNodes with positive nRef */ ++ char *zReadAuxSql; /* SQL for statement to read aux data */ + + /* List of nodes removed during a CondenseTree operation. List is + ** linked together via the pointer normally used for hash chains - +@@ -168952,6 +179287,9 @@ + sqlite3_stmt *pWriteParent; + sqlite3_stmt *pDeleteParent; + ++ /* Statement for writing to the "aux:" fields, if there are any */ ++ sqlite3_stmt *pWriteAux; ++ + RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */ + }; + +@@ -169028,6 +179366,7 @@ + sqlite3_vtab_cursor base; /* Base class. Must be first */ + u8 atEOF; /* True if at end of search */ + u8 bPoint; /* True if sPoint is valid */ ++ u8 bAuxValid; /* True if pReadAux is valid */ + int iStrategy; /* Copy of idxNum search parameter */ + int nConstraint; /* Number of entries in aConstraint */ + RtreeConstraint *aConstraint; /* Search constraints. */ +@@ -169035,6 +179374,7 @@ + int nPoint; /* Number of slots used in aPoint[] */ + int mxLevel; /* iLevel value for root of the tree */ + RtreeSearchPoint *aPoint; /* Priority queue for search points */ ++ sqlite3_stmt *pReadAux; /* Statement to read aux-data */ + RtreeSearchPoint sPoint; /* Cached next search point */ + RtreeNode *aNode[RTREE_CACHE_SZ]; /* Rtree node cache */ + u32 anQueue[RTREE_MAX_DEPTH+1]; /* Number of queued entries by iLevel */ +@@ -169321,6 +179661,7 @@ + */ + static void nodeReference(RtreeNode *p){ + if( p ){ ++ assert( p->nRef>0 ); + p->nRef++; + } + } +@@ -169388,6 +179729,7 @@ + memset(pNode, 0, sizeof(RtreeNode) + pRtree->iNodeSize); + pNode->zData = (u8 *)&pNode[1]; + pNode->nRef = 1; ++ pRtree->nNodeRef++; + pNode->pParent = pParent; + pNode->isDirty = 1; + nodeReference(pParent); +@@ -169421,10 +179763,10 @@ + /* Check if the requested node is already in the hash table. If so, + ** increase its reference count and return it. + */ +- if( (pNode = nodeHashLookup(pRtree, iNode)) ){ ++ if( (pNode = nodeHashLookup(pRtree, iNode))!=0 ){ + assert( !pParent || !pNode->pParent || pNode->pParent==pParent ); + if( pParent && !pNode->pParent ){ +- nodeReference(pParent); ++ pParent->nRef++; + pNode->pParent = pParent; + } + pNode->nRef++; +@@ -169463,6 +179805,7 @@ + pNode->pParent = pParent; + pNode->zData = (u8 *)&pNode[1]; + pNode->nRef = 1; ++ pRtree->nNodeRef++; + pNode->iNode = iNode; + pNode->isDirty = 0; + pNode->pNext = 0; +@@ -169503,7 +179846,10 @@ + } + *ppNode = pNode; + }else{ +- sqlite3_free(pNode); ++ if( pNode ){ ++ pRtree->nNodeRef--; ++ sqlite3_free(pNode); ++ } + *ppNode = 0; + } + +@@ -169600,8 +179946,10 @@ + int rc = SQLITE_OK; + if( pNode ){ + assert( pNode->nRef>0 ); ++ assert( pRtree->nNodeRef>0 ); + pNode->nRef--; + if( pNode->nRef==0 ){ ++ pRtree->nNodeRef--; + if( pNode->iNode==1 ){ + pRtree->iDepth = -1; + } +@@ -169718,8 +180066,9 @@ + pRtree->nBusy--; + if( pRtree->nBusy==0 ){ + pRtree->inWrTrans = 0; +- pRtree->nCursor = 0; ++ assert( pRtree->nCursor==0 ); + nodeBlobReset(pRtree); ++ assert( pRtree->nNodeRef==0 ); + sqlite3_finalize(pRtree->pWriteNode); + sqlite3_finalize(pRtree->pDeleteNode); + sqlite3_finalize(pRtree->pReadRowid); +@@ -169728,6 +180077,8 @@ + sqlite3_finalize(pRtree->pReadParent); + sqlite3_finalize(pRtree->pWriteParent); + sqlite3_finalize(pRtree->pDeleteParent); ++ sqlite3_finalize(pRtree->pWriteAux); ++ sqlite3_free(pRtree->zReadAuxSql); + sqlite3_free(pRtree); + } + } +@@ -169816,6 +180167,7 @@ + RtreeCursor *pCsr = (RtreeCursor *)cur; + assert( pRtree->nCursor>0 ); + freeCursorConstraints(pCsr); ++ sqlite3_finalize(pCsr->pReadAux); + sqlite3_free(pCsr->aPoint); + for(ii=0; ii<RTREE_CACHE_SZ; ii++) nodeRelease(pRtree, pCsr->aNode[ii]); + sqlite3_free(pCsr); +@@ -170187,7 +180539,7 @@ + if( ii<RTREE_CACHE_SZ ){ + assert( pCur->aNode[ii]==0 ); + pCur->aNode[ii] = pCur->aNode[0]; +- }else{ ++ }else{ + nodeRelease(RTREE_OF_CURSOR(pCur), pCur->aNode[0]); + } + pCur->aNode[0] = 0; +@@ -170358,6 +180710,10 @@ + + /* Move to the next entry that matches the configured constraints. */ + RTREE_QUEUE_TRACE(pCsr, "POP-Nx:"); ++ if( pCsr->bAuxValid ){ ++ pCsr->bAuxValid = 0; ++ sqlite3_reset(pCsr->pReadAux); ++ } + rtreeSearchPointPop(pCsr); + rc = rtreeStepToLeaf(pCsr); + return rc; +@@ -170392,7 +180748,7 @@ + if( p==0 ) return SQLITE_OK; + if( i==0 ){ + sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell)); +- }else{ ++ }else if( i<=pRtree->nDim2 ){ + nodeGetCoord(pRtree, pNode, p->iCell, i-1, &c); + #ifndef SQLITE_RTREE_INT_ONLY + if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ +@@ -170403,7 +180759,27 @@ + assert( pRtree->eCoordType==RTREE_COORD_INT32 ); + sqlite3_result_int(ctx, c.i); + } +- } ++ }else{ ++ if( !pCsr->bAuxValid ){ ++ if( pCsr->pReadAux==0 ){ ++ rc = sqlite3_prepare_v3(pRtree->db, pRtree->zReadAuxSql, -1, 0, ++ &pCsr->pReadAux, 0); ++ if( rc ) return rc; ++ } ++ sqlite3_bind_int64(pCsr->pReadAux, 1, ++ nodeGetRowid(pRtree, pNode, p->iCell)); ++ rc = sqlite3_step(pCsr->pReadAux); ++ if( rc==SQLITE_ROW ){ ++ pCsr->bAuxValid = 1; ++ }else{ ++ sqlite3_reset(pCsr->pReadAux); ++ if( rc==SQLITE_DONE ) rc = SQLITE_OK; ++ return rc; ++ } ++ } ++ sqlite3_result_value(ctx, ++ sqlite3_column_value(pCsr->pReadAux, i - pRtree->nDim2 + 1)); ++ } + return SQLITE_OK; + } + +@@ -170481,6 +180857,7 @@ + int ii; + int rc = SQLITE_OK; + int iCell = 0; ++ sqlite3_stmt *pStmt; + + rtreeReference(pRtree); + +@@ -170487,8 +180864,10 @@ + /* Reset the cursor to the same state as rtreeOpen() leaves it in. */ + freeCursorConstraints(pCsr); + sqlite3_free(pCsr->aPoint); ++ pStmt = pCsr->pReadAux; + memset(pCsr, 0, sizeof(RtreeCursor)); + pCsr->base.pVtab = (sqlite3_vtab*)pRtree; ++ pCsr->pReadAux = pStmt; + + pCsr->iStrategy = idxNum; + if( idxNum==1 ){ +@@ -170651,10 +181030,14 @@ + */ + pIdxInfo->estimatedCost = 30.0; + pIdxInfo->estimatedRows = 1; ++ pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE; + return SQLITE_OK; + } + +- if( p->usable && (p->iColumn>0 || p->op==SQLITE_INDEX_CONSTRAINT_MATCH) ){ ++ if( p->usable ++ && ((p->iColumn>0 && p->iColumn<=pRtree->nDim2) ++ || p->op==SQLITE_INDEX_CONSTRAINT_MATCH) ++ ){ + u8 op; + switch( p->op ){ + case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break; +@@ -171227,7 +181610,7 @@ + }else{ + pLeft = pNode; + pRight = nodeNew(pRtree, pLeft->pParent); +- nodeReference(pLeft); ++ pLeft->nRef++; + } + + if( !pLeft || !pRight ){ +@@ -171636,7 +182019,7 @@ + /* + ** Select a currently unused rowid for a new r-tree record. + */ +-static int newRowid(Rtree *pRtree, i64 *piRowid){ ++static int rtreeNewRowid(Rtree *pRtree, i64 *piRowid){ + int rc; + sqlite3_bind_null(pRtree->pWriteRowid, 1); + sqlite3_bind_null(pRtree->pWriteRowid, 2); +@@ -171717,6 +182100,7 @@ + rc = reinsertNodeContent(pRtree, pLeaf); + } + pRtree->pDeleted = pLeaf->pNext; ++ pRtree->nNodeRef--; + sqlite3_free(pLeaf); + } + +@@ -171813,7 +182197,7 @@ + static int rtreeUpdate( + sqlite3_vtab *pVtab, + int nData, +- sqlite3_value **azData, ++ sqlite3_value **aData, + sqlite_int64 *pRowid + ){ + Rtree *pRtree = (Rtree *)pVtab; +@@ -171821,6 +182205,12 @@ + RtreeCell cell; /* New cell to insert if nData>1 */ + int bHaveRowid = 0; /* Set to 1 after new rowid is determined */ + ++ if( pRtree->nNodeRef ){ ++ /* Unable to write to the btree while another cursor is reading from it, ++ ** since the write might do a rebalance which would disrupt the read ++ ** cursor. */ ++ return SQLITE_LOCKED_VTAB; ++ } + rtreeReference(pRtree); + assert(nData>=1); + +@@ -171839,8 +182229,10 @@ + */ + if( nData>1 ){ + int ii; ++ int nn = nData - 4; + +- /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. ++ if( nn > pRtree->nDim2 ) nn = pRtree->nDim2; ++ /* Populate the cell.aCoord[] array. The first coordinate is aData[3]. + ** + ** NB: nData can only be less than nDim*2+3 if the rtree is mis-declared + ** with "column" that are interpreted as table constraints. +@@ -171848,13 +182240,12 @@ + ** This problem was discovered after years of use, so we silently ignore + ** these kinds of misdeclared tables to avoid breaking any legacy. + */ +- assert( nData<=(pRtree->nDim2 + 3) ); + + #ifndef SQLITE_RTREE_INT_ONLY + if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ +- for(ii=0; ii<nData-4; ii+=2){ +- cell.aCoord[ii].f = rtreeValueDown(azData[ii+3]); +- cell.aCoord[ii+1].f = rtreeValueUp(azData[ii+4]); ++ for(ii=0; ii<nn; ii+=2){ ++ cell.aCoord[ii].f = rtreeValueDown(aData[ii+3]); ++ cell.aCoord[ii+1].f = rtreeValueUp(aData[ii+4]); + if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){ + rc = rtreeConstraintError(pRtree, ii+1); + goto constraint; +@@ -171863,9 +182254,9 @@ + }else + #endif + { +- for(ii=0; ii<nData-4; ii+=2){ +- cell.aCoord[ii].i = sqlite3_value_int(azData[ii+3]); +- cell.aCoord[ii+1].i = sqlite3_value_int(azData[ii+4]); ++ for(ii=0; ii<nn; ii+=2){ ++ cell.aCoord[ii].i = sqlite3_value_int(aData[ii+3]); ++ cell.aCoord[ii+1].i = sqlite3_value_int(aData[ii+4]); + if( cell.aCoord[ii].i>cell.aCoord[ii+1].i ){ + rc = rtreeConstraintError(pRtree, ii+1); + goto constraint; +@@ -171875,10 +182266,10 @@ + + /* If a rowid value was supplied, check if it is already present in + ** the table. If so, the constraint has failed. */ +- if( sqlite3_value_type(azData[2])!=SQLITE_NULL ){ +- cell.iRowid = sqlite3_value_int64(azData[2]); +- if( sqlite3_value_type(azData[0])==SQLITE_NULL +- || sqlite3_value_int64(azData[0])!=cell.iRowid ++ if( sqlite3_value_type(aData[2])!=SQLITE_NULL ){ ++ cell.iRowid = sqlite3_value_int64(aData[2]); ++ if( sqlite3_value_type(aData[0])==SQLITE_NULL ++ || sqlite3_value_int64(aData[0])!=cell.iRowid + ){ + int steprc; + sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid); +@@ -171897,16 +182288,16 @@ + } + } + +- /* If azData[0] is not an SQL NULL value, it is the rowid of a ++ /* If aData[0] is not an SQL NULL value, it is the rowid of a + ** record to delete from the r-tree table. The following block does + ** just that. + */ +- if( sqlite3_value_type(azData[0])!=SQLITE_NULL ){ +- rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(azData[0])); ++ if( sqlite3_value_type(aData[0])!=SQLITE_NULL ){ ++ rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(aData[0])); + } + +- /* If the azData[] array contains more than one element, elements +- ** (azData[2]..azData[argc-1]) contain a new record to insert into ++ /* If the aData[] array contains more than one element, elements ++ ** (aData[2]..aData[argc-1]) contain a new record to insert into + ** the r-tree structure. + */ + if( rc==SQLITE_OK && nData>1 ){ +@@ -171915,7 +182306,7 @@ + + /* Figure out the rowid of the new row. */ + if( bHaveRowid==0 ){ +- rc = newRowid(pRtree, &cell.iRowid); ++ rc = rtreeNewRowid(pRtree, &cell.iRowid); + } + *pRowid = cell.iRowid; + +@@ -171931,6 +182322,16 @@ + rc = rc2; + } + } ++ if( pRtree->nAux ){ ++ sqlite3_stmt *pUp = pRtree->pWriteAux; ++ int jj; ++ sqlite3_bind_int64(pUp, 1, *pRowid); ++ for(jj=0; jj<pRtree->nAux; jj++){ ++ sqlite3_bind_value(pUp, jj+2, aData[pRtree->nDim2+3+jj]); ++ } ++ sqlite3_step(pUp); ++ rc = sqlite3_reset(pUp); ++ } + } + + constraint: +@@ -171997,7 +182398,7 @@ + */ + static int rtreeSavepoint(sqlite3_vtab *pVtab, int iSavepoint){ + Rtree *pRtree = (Rtree *)pVtab; +- int iwt = pRtree->inWrTrans; ++ u8 iwt = pRtree->inWrTrans; + UNUSED_PARAMETER(iSavepoint); + pRtree->inWrTrans = 0; + nodeBlobReset(pRtree); +@@ -172049,8 +182450,24 @@ + return rc; + } + ++ ++/* ++** Return true if zName is the extension on one of the shadow tables used ++** by this module. ++*/ ++static int rtreeShadowName(const char *zName){ ++ static const char *azName[] = { ++ "node", "parent", "rowid" ++ }; ++ unsigned int i; ++ for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){ ++ if( sqlite3_stricmp(zName, azName[i])==0 ) return 1; ++ } ++ return 0; ++} ++ + static sqlite3_module rtreeModule = { +- 2, /* iVersion */ ++ 3, /* iVersion */ + rtreeCreate, /* xCreate - create a table */ + rtreeConnect, /* xConnect - connect to an existing table */ + rtreeBestIndex, /* xBestIndex - Determine search strategy */ +@@ -172073,6 +182490,7 @@ + rtreeSavepoint, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ ++ rtreeShadowName /* xShadowName */ + }; + + static int rtreeSqlInit( +@@ -172087,18 +182505,18 @@ + #define N_STATEMENT 8 + static const char *azSql[N_STATEMENT] = { + /* Write the xxx_node table */ +- "INSERT OR REPLACE INTO '%q'.'%q_node' VALUES(:1, :2)", +- "DELETE FROM '%q'.'%q_node' WHERE nodeno = :1", ++ "INSERT OR REPLACE INTO '%q'.'%q_node' VALUES(?1, ?2)", ++ "DELETE FROM '%q'.'%q_node' WHERE nodeno = ?1", + + /* Read and write the xxx_rowid table */ +- "SELECT nodeno FROM '%q'.'%q_rowid' WHERE rowid = :1", +- "INSERT OR REPLACE INTO '%q'.'%q_rowid' VALUES(:1, :2)", +- "DELETE FROM '%q'.'%q_rowid' WHERE rowid = :1", ++ "SELECT nodeno FROM '%q'.'%q_rowid' WHERE rowid = ?1", ++ "INSERT OR REPLACE INTO '%q'.'%q_rowid' VALUES(?1, ?2)", ++ "DELETE FROM '%q'.'%q_rowid' WHERE rowid = ?1", + + /* Read and write the xxx_parent table */ +- "SELECT parentnode FROM '%q'.'%q_parent' WHERE nodeno = :1", +- "INSERT OR REPLACE INTO '%q'.'%q_parent' VALUES(:1, :2)", +- "DELETE FROM '%q'.'%q_parent' WHERE nodeno = :1" ++ "SELECT parentnode FROM '%q'.'%q_parent' WHERE nodeno = ?1", ++ "INSERT OR REPLACE INTO '%q'.'%q_parent' VALUES(?1, ?2)", ++ "DELETE FROM '%q'.'%q_parent' WHERE nodeno = ?1" + }; + sqlite3_stmt **appStmt[N_STATEMENT]; + int i; +@@ -172106,14 +182524,25 @@ + pRtree->db = db; + + if( isCreate ){ +- char *zCreate = sqlite3_mprintf( +-"CREATE TABLE \"%w\".\"%w_node\"(nodeno INTEGER PRIMARY KEY, data BLOB);" +-"CREATE TABLE \"%w\".\"%w_rowid\"(rowid INTEGER PRIMARY KEY, nodeno INTEGER);" +-"CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY," +- " parentnode INTEGER);" +-"INSERT INTO '%q'.'%q_node' VALUES(1, zeroblob(%d))", +- zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, pRtree->iNodeSize +- ); ++ char *zCreate; ++ sqlite3_str *p = sqlite3_str_new(db); ++ int ii; ++ sqlite3_str_appendf(p, ++ "CREATE TABLE \"%w\".\"%w_rowid\"(rowid INTEGER PRIMARY KEY,nodeno", ++ zDb, zPrefix); ++ for(ii=0; ii<pRtree->nAux; ii++){ ++ sqlite3_str_appendf(p,",a%d",ii); ++ } ++ sqlite3_str_appendf(p, ++ ");CREATE TABLE \"%w\".\"%w_node\"(nodeno INTEGER PRIMARY KEY,data);", ++ zDb, zPrefix); ++ sqlite3_str_appendf(p, ++ "CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY,parentnode);", ++ zDb, zPrefix); ++ sqlite3_str_appendf(p, ++ "INSERT INTO \"%w\".\"%w_node\"VALUES(1,zeroblob(%d))", ++ zDb, zPrefix, pRtree->iNodeSize); ++ zCreate = sqlite3_str_finish(p); + if( !zCreate ){ + return SQLITE_NOMEM; + } +@@ -172135,7 +182564,17 @@ + + rc = rtreeQueryStat1(db, pRtree); + for(i=0; i<N_STATEMENT && rc==SQLITE_OK; i++){ +- char *zSql = sqlite3_mprintf(azSql[i], zDb, zPrefix); ++ char *zSql; ++ const char *zFormat; ++ if( i!=3 || pRtree->nAux==0 ){ ++ zFormat = azSql[i]; ++ }else { ++ /* An UPSERT is very slightly slower than REPLACE, but it is needed ++ ** if there are auxiliary columns */ ++ zFormat = "INSERT INTO\"%w\".\"%w_rowid\"(rowid,nodeno)VALUES(?1,?2)" ++ "ON CONFLICT(rowid)DO UPDATE SET nodeno=excluded.nodeno"; ++ } ++ zSql = sqlite3_mprintf(zFormat, zDb, zPrefix); + if( zSql ){ + rc = sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_PERSISTENT, + appStmt[i], 0); +@@ -172144,6 +182583,36 @@ + } + sqlite3_free(zSql); + } ++ if( pRtree->nAux ){ ++ pRtree->zReadAuxSql = sqlite3_mprintf( ++ "SELECT * FROM \"%w\".\"%w_rowid\" WHERE rowid=?1", ++ zDb, zPrefix); ++ if( pRtree->zReadAuxSql==0 ){ ++ rc = SQLITE_NOMEM; ++ }else{ ++ sqlite3_str *p = sqlite3_str_new(db); ++ int ii; ++ char *zSql; ++ sqlite3_str_appendf(p, "UPDATE \"%w\".\"%w_rowid\"SET ", zDb, zPrefix); ++ for(ii=0; ii<pRtree->nAux; ii++){ ++ if( ii ) sqlite3_str_append(p, ",", 1); ++ if( ii<pRtree->nAuxNotNull ){ ++ sqlite3_str_appendf(p,"a%d=coalesce(?%d,a%d)",ii,ii+2,ii); ++ }else{ ++ sqlite3_str_appendf(p,"a%d=?%d",ii,ii+2); ++ } ++ } ++ sqlite3_str_appendf(p, " WHERE rowid=?1"); ++ zSql = sqlite3_str_finish(p); ++ if( zSql==0 ){ ++ rc = SQLITE_NOMEM; ++ }else{ ++ rc = sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_PERSISTENT, ++ &pRtree->pWriteAux, 0); ++ sqlite3_free(zSql); ++ } ++ } ++ } + + return rc; + } +@@ -172246,17 +182715,22 @@ + int nDb; /* Length of string argv[1] */ + int nName; /* Length of string argv[2] */ + int eCoordType = (pAux ? RTREE_COORD_INT32 : RTREE_COORD_REAL32); ++ sqlite3_str *pSql; ++ char *zSql; ++ int ii = 4; ++ int iErr; + + const char *aErrMsg[] = { + 0, /* 0 */ + "Wrong number of columns for an rtree table", /* 1 */ + "Too few columns for an rtree table", /* 2 */ +- "Too many columns for an rtree table" /* 3 */ ++ "Too many columns for an rtree table", /* 3 */ ++ "Auxiliary rtree columns must be last" /* 4 */ + }; + +- int iErr = (argc<6) ? 2 : argc>(RTREE_MAX_DIMENSIONS*2+4) ? 3 : argc%2; +- if( aErrMsg[iErr] ){ +- *pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]); ++ assert( RTREE_MAX_AUX_COLUMN<256 ); /* Aux columns counted by a u8 */ ++ if( argc>RTREE_MAX_AUX_COLUMN+3 ){ ++ *pzErr = sqlite3_mprintf("%s", aErrMsg[3]); + return SQLITE_ERROR; + } + +@@ -172274,53 +182748,73 @@ + pRtree->base.pModule = &rtreeModule; + pRtree->zDb = (char *)&pRtree[1]; + pRtree->zName = &pRtree->zDb[nDb+1]; +- pRtree->nDim = (u8)((argc-4)/2); +- pRtree->nDim2 = pRtree->nDim*2; +- pRtree->nBytesPerCell = 8 + pRtree->nDim2*4; + pRtree->eCoordType = (u8)eCoordType; + memcpy(pRtree->zDb, argv[1], nDb); + memcpy(pRtree->zName, argv[2], nName); + +- /* Figure out the node size to use. */ +- rc = getNodeSize(db, pRtree, isCreate, pzErr); + + /* Create/Connect to the underlying relational database schema. If + ** that is successful, call sqlite3_declare_vtab() to configure + ** the r-tree table schema. + */ +- if( rc==SQLITE_OK ){ +- if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){ +- *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); ++ pSql = sqlite3_str_new(db); ++ sqlite3_str_appendf(pSql, "CREATE TABLE x(%s", argv[3]); ++ for(ii=4; ii<argc; ii++){ ++ if( argv[ii][0]=='+' ){ ++ pRtree->nAux++; ++ sqlite3_str_appendf(pSql, ",%s", argv[ii]+1); ++ }else if( pRtree->nAux>0 ){ ++ break; + }else{ +- char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]); +- char *zTmp; +- int ii; +- for(ii=4; zSql && ii<argc; ii++){ +- zTmp = zSql; +- zSql = sqlite3_mprintf("%s, %s", zTmp, argv[ii]); +- sqlite3_free(zTmp); +- } +- if( zSql ){ +- zTmp = zSql; +- zSql = sqlite3_mprintf("%s);", zTmp); +- sqlite3_free(zTmp); +- } +- if( !zSql ){ +- rc = SQLITE_NOMEM; +- }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){ +- *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); +- } +- sqlite3_free(zSql); ++ pRtree->nDim2++; ++ sqlite3_str_appendf(pSql, ",%s", argv[ii]); + } + } +- +- if( rc==SQLITE_OK ){ +- *ppVtab = (sqlite3_vtab *)pRtree; ++ sqlite3_str_appendf(pSql, ");"); ++ zSql = sqlite3_str_finish(pSql); ++ if( !zSql ){ ++ rc = SQLITE_NOMEM; ++ }else if( ii<argc ){ ++ *pzErr = sqlite3_mprintf("%s", aErrMsg[4]); ++ rc = SQLITE_ERROR; ++ }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){ ++ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); ++ } ++ sqlite3_free(zSql); ++ if( rc ) goto rtreeInit_fail; ++ pRtree->nDim = pRtree->nDim2/2; ++ if( pRtree->nDim<1 ){ ++ iErr = 2; ++ }else if( pRtree->nDim2>RTREE_MAX_DIMENSIONS*2 ){ ++ iErr = 3; ++ }else if( pRtree->nDim2 % 2 ){ ++ iErr = 1; + }else{ +- assert( *ppVtab==0 ); +- assert( pRtree->nBusy==1 ); +- rtreeRelease(pRtree); ++ iErr = 0; + } ++ if( iErr ){ ++ *pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]); ++ goto rtreeInit_fail; ++ } ++ pRtree->nBytesPerCell = 8 + pRtree->nDim2*4; ++ ++ /* Figure out the node size to use. */ ++ rc = getNodeSize(db, pRtree, isCreate, pzErr); ++ if( rc ) goto rtreeInit_fail; ++ rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate); ++ if( rc ){ ++ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); ++ goto rtreeInit_fail; ++ } ++ ++ *ppVtab = (sqlite3_vtab *)pRtree; ++ return SQLITE_OK; ++ ++rtreeInit_fail: ++ if( rc==SQLITE_OK ) rc = SQLITE_ERROR; ++ assert( *ppVtab==0 ); ++ assert( pRtree->nBusy==1 ); ++ rtreeRelease(pRtree); + return rc; + } + +@@ -172549,7 +183043,7 @@ + ** two tables are: + ** + ** CREATE TABLE %_parent(nodeno INTEGER PRIMARY KEY, parentnode INTEGER) +-** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER) ++** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER, ...) + ** + ** In both cases, this function checks that there exists an entry with + ** IPK value iKey and the second column set to iVal. +@@ -172564,8 +183058,8 @@ + int rc; + sqlite3_stmt *pStmt; + const char *azSql[2] = { +- "SELECT parentnode FROM %Q.'%q_parent' WHERE nodeno=?", +- "SELECT nodeno FROM %Q.'%q_rowid' WHERE rowid=?" ++ "SELECT parentnode FROM %Q.'%q_parent' WHERE nodeno=?1", ++ "SELECT nodeno FROM %Q.'%q_rowid' WHERE rowid=?1" + }; + + assert( bLeaf==0 || bLeaf==1 ); +@@ -172749,6 +183243,7 @@ + RtreeCheck check; /* Common context for various routines */ + sqlite3_stmt *pStmt = 0; /* Used to find column count of rtree table */ + int bEnd = 0; /* True if transaction should be closed */ ++ int nAux = 0; /* Number of extra columns. */ + + /* Initialize the context object */ + memset(&check, 0, sizeof(check)); +@@ -172764,11 +183259,21 @@ + bEnd = 1; + } + ++ /* Find the number of auxiliary columns */ ++ if( check.rc==SQLITE_OK ){ ++ pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.'%q_rowid'", zDb, zTab); ++ if( pStmt ){ ++ nAux = sqlite3_column_count(pStmt) - 2; ++ sqlite3_finalize(pStmt); ++ } ++ check.rc = SQLITE_OK; ++ } ++ + /* Find number of dimensions in the rtree table. */ + pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.%Q", zDb, zTab); + if( pStmt ){ + int rc; +- check.nDim = (sqlite3_column_count(pStmt) - 1) / 2; ++ check.nDim = (sqlite3_column_count(pStmt) - 1 - nAux) / 2; + if( check.nDim<1 ){ + rtreeCheckAppendMsg(&check, "Schema corrupt or not an rtree"); + }else if( SQLITE_ROW==sqlite3_step(pStmt) ){ +@@ -172864,8 +183369,1813 @@ + } + } + ++/* Conditionally include the geopoly code */ ++#ifdef SQLITE_ENABLE_GEOPOLY ++/************** Include geopoly.c in the middle of rtree.c *******************/ ++/************** Begin file geopoly.c *****************************************/ ++/* ++** 2018-05-25 ++** ++** The author disclaims copyright to this source code. In place of ++** a legal notice, here is a blessing: ++** ++** May you do good and not evil. ++** May you find forgiveness for yourself and forgive others. ++** May you share freely, never taking more than you give. ++** ++****************************************************************************** ++** ++** This file implements an alternative R-Tree virtual table that ++** uses polygons to express the boundaries of 2-dimensional objects. ++** ++** This file is #include-ed onto the end of "rtree.c" so that it has ++** access to all of the R-Tree internals. ++*/ ++/* #include <stdlib.h> */ + ++/* Enable -DGEOPOLY_ENABLE_DEBUG for debugging facilities */ ++#ifdef GEOPOLY_ENABLE_DEBUG ++ static int geo_debug = 0; ++# define GEODEBUG(X) if(geo_debug)printf X ++#else ++# define GEODEBUG(X) ++#endif ++ ++#ifndef JSON_NULL /* The following stuff repeats things found in json1 */ + /* ++** Versions of isspace(), isalnum() and isdigit() to which it is safe ++** to pass signed char values. ++*/ ++#ifdef sqlite3Isdigit ++ /* Use the SQLite core versions if this routine is part of the ++ ** SQLite amalgamation */ ++# define safe_isdigit(x) sqlite3Isdigit(x) ++# define safe_isalnum(x) sqlite3Isalnum(x) ++# define safe_isxdigit(x) sqlite3Isxdigit(x) ++#else ++ /* Use the standard library for separate compilation */ ++#include <ctype.h> /* amalgamator: keep */ ++# define safe_isdigit(x) isdigit((unsigned char)(x)) ++# define safe_isalnum(x) isalnum((unsigned char)(x)) ++# define safe_isxdigit(x) isxdigit((unsigned char)(x)) ++#endif ++ ++/* ++** Growing our own isspace() routine this way is twice as fast as ++** the library isspace() function. ++*/ ++static const char geopolyIsSpace[] = { ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++}; ++#define safe_isspace(x) (geopolyIsSpace[(unsigned char)x]) ++#endif /* JSON NULL - back to original code */ ++ ++/* Compiler and version */ ++#ifndef GCC_VERSION ++#if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC) ++# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__) ++#else ++# define GCC_VERSION 0 ++#endif ++#endif ++#ifndef MSVC_VERSION ++#if defined(_MSC_VER) && !defined(SQLITE_DISABLE_INTRINSIC) ++# define MSVC_VERSION _MSC_VER ++#else ++# define MSVC_VERSION 0 ++#endif ++#endif ++ ++/* Datatype for coordinates ++*/ ++typedef float GeoCoord; ++ ++/* ++** Internal representation of a polygon. ++** ++** The polygon consists of a sequence of vertexes. There is a line ++** segment between each pair of vertexes, and one final segment from ++** the last vertex back to the first. (This differs from the GeoJSON ++** standard in which the final vertex is a repeat of the first.) ++** ++** The polygon follows the right-hand rule. The area to the right of ++** each segment is "outside" and the area to the left is "inside". ++** ++** The on-disk representation consists of a 4-byte header followed by ++** the values. The 4-byte header is: ++** ++** encoding (1 byte) 0=big-endian, 1=little-endian ++** nvertex (3 bytes) Number of vertexes as a big-endian integer ++** ++** Enough space is allocated for 4 coordinates, to work around over-zealous ++** warnings coming from some compiler (notably, clang). In reality, the size ++** of each GeoPoly memory allocate is adjusted as necessary so that the ++** GeoPoly.a[] array at the end is the appropriate size. ++*/ ++typedef struct GeoPoly GeoPoly; ++struct GeoPoly { ++ int nVertex; /* Number of vertexes */ ++ unsigned char hdr[4]; /* Header for on-disk representation */ ++ GeoCoord a[8]; /* 2*nVertex values. X (longitude) first, then Y */ ++}; ++ ++/* The size of a memory allocation needed for a GeoPoly object sufficient ++** to hold N coordinate pairs. ++*/ ++#define GEOPOLY_SZ(N) (sizeof(GeoPoly) + sizeof(GeoCoord)*2*((N)-4)) ++ ++/* ++** State of a parse of a GeoJSON input. ++*/ ++typedef struct GeoParse GeoParse; ++struct GeoParse { ++ const unsigned char *z; /* Unparsed input */ ++ int nVertex; /* Number of vertexes in a[] */ ++ int nAlloc; /* Space allocated to a[] */ ++ int nErr; /* Number of errors encountered */ ++ GeoCoord *a; /* Array of vertexes. From sqlite3_malloc64() */ ++}; ++ ++/* Do a 4-byte byte swap */ ++static void geopolySwab32(unsigned char *a){ ++ unsigned char t = a[0]; ++ a[0] = a[3]; ++ a[3] = t; ++ t = a[1]; ++ a[1] = a[2]; ++ a[2] = t; ++} ++ ++/* Skip whitespace. Return the next non-whitespace character. */ ++static char geopolySkipSpace(GeoParse *p){ ++ while( safe_isspace(p->z[0]) ) p->z++; ++ return p->z[0]; ++} ++ ++/* Parse out a number. Write the value into *pVal if pVal!=0. ++** return non-zero on success and zero if the next token is not a number. ++*/ ++static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){ ++ char c = geopolySkipSpace(p); ++ const unsigned char *z = p->z; ++ int j = 0; ++ int seenDP = 0; ++ int seenE = 0; ++ if( c=='-' ){ ++ j = 1; ++ c = z[j]; ++ } ++ if( c=='0' && z[j+1]>='0' && z[j+1]<='9' ) return 0; ++ for(;; j++){ ++ c = z[j]; ++ if( safe_isdigit(c) ) continue; ++ if( c=='.' ){ ++ if( z[j-1]=='-' ) return 0; ++ if( seenDP ) return 0; ++ seenDP = 1; ++ continue; ++ } ++ if( c=='e' || c=='E' ){ ++ if( z[j-1]<'0' ) return 0; ++ 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 0; ++ continue; ++ } ++ break; ++ } ++ if( z[j-1]<'0' ) return 0; ++ if( pVal ){ ++#ifdef SQLITE_AMALGAMATION ++ /* The sqlite3AtoF() routine is much much faster than atof(), if it ++ ** is available */ ++ double r; ++ (void)sqlite3AtoF((const char*)p->z, &r, j, SQLITE_UTF8); ++ *pVal = r; ++#else ++ *pVal = (GeoCoord)atof((const char*)p->z); ++#endif ++ } ++ p->z += j; ++ return 1; ++} ++ ++/* ++** If the input is a well-formed JSON array of coordinates with at least ++** four coordinates and where each coordinate is itself a two-value array, ++** then convert the JSON into a GeoPoly object and return a pointer to ++** that object. ++** ++** If any error occurs, return NULL. ++*/ ++static GeoPoly *geopolyParseJson(const unsigned char *z, int *pRc){ ++ GeoParse s; ++ int rc = SQLITE_OK; ++ memset(&s, 0, sizeof(s)); ++ s.z = z; ++ if( geopolySkipSpace(&s)=='[' ){ ++ s.z++; ++ while( geopolySkipSpace(&s)=='[' ){ ++ int ii = 0; ++ char c; ++ s.z++; ++ if( s.nVertex>=s.nAlloc ){ ++ GeoCoord *aNew; ++ s.nAlloc = s.nAlloc*2 + 16; ++ aNew = sqlite3_realloc64(s.a, s.nAlloc*sizeof(GeoCoord)*2 ); ++ if( aNew==0 ){ ++ rc = SQLITE_NOMEM; ++ s.nErr++; ++ break; ++ } ++ s.a = aNew; ++ } ++ while( geopolyParseNumber(&s, ii<=1 ? &s.a[s.nVertex*2+ii] : 0) ){ ++ ii++; ++ if( ii==2 ) s.nVertex++; ++ c = geopolySkipSpace(&s); ++ s.z++; ++ if( c==',' ) continue; ++ if( c==']' && ii>=2 ) break; ++ s.nErr++; ++ rc = SQLITE_ERROR; ++ goto parse_json_err; ++ } ++ if( geopolySkipSpace(&s)==',' ){ ++ s.z++; ++ continue; ++ } ++ break; ++ } ++ if( geopolySkipSpace(&s)==']' ++ && s.nVertex>=4 ++ && s.a[0]==s.a[s.nVertex*2-2] ++ && s.a[1]==s.a[s.nVertex*2-1] ++ && (s.z++, geopolySkipSpace(&s)==0) ++ ){ ++ GeoPoly *pOut; ++ int x = 1; ++ s.nVertex--; /* Remove the redundant vertex at the end */ ++ pOut = sqlite3_malloc64( GEOPOLY_SZ(s.nVertex) ); ++ x = 1; ++ if( pOut==0 ) goto parse_json_err; ++ pOut->nVertex = s.nVertex; ++ memcpy(pOut->a, s.a, s.nVertex*2*sizeof(GeoCoord)); ++ pOut->hdr[0] = *(unsigned char*)&x; ++ pOut->hdr[1] = (s.nVertex>>16)&0xff; ++ pOut->hdr[2] = (s.nVertex>>8)&0xff; ++ pOut->hdr[3] = s.nVertex&0xff; ++ sqlite3_free(s.a); ++ if( pRc ) *pRc = SQLITE_OK; ++ return pOut; ++ }else{ ++ s.nErr++; ++ rc = SQLITE_ERROR; ++ } ++ } ++parse_json_err: ++ if( pRc ) *pRc = rc; ++ sqlite3_free(s.a); ++ return 0; ++} ++ ++/* ++** Given a function parameter, try to interpret it as a polygon, either ++** in the binary format or JSON text. Compute a GeoPoly object and ++** return a pointer to that object. Or if the input is not a well-formed ++** polygon, put an error message in sqlite3_context and return NULL. ++*/ ++static GeoPoly *geopolyFuncParam( ++ sqlite3_context *pCtx, /* Context for error messages */ ++ sqlite3_value *pVal, /* The value to decode */ ++ int *pRc /* Write error here */ ++){ ++ GeoPoly *p = 0; ++ int nByte; ++ if( sqlite3_value_type(pVal)==SQLITE_BLOB ++ && (nByte = sqlite3_value_bytes(pVal))>=(4+6*sizeof(GeoCoord)) ++ ){ ++ const unsigned char *a = sqlite3_value_blob(pVal); ++ int nVertex; ++ nVertex = (a[1]<<16) + (a[2]<<8) + a[3]; ++ if( (a[0]==0 || a[0]==1) ++ && (nVertex*2*sizeof(GeoCoord) + 4)==(unsigned int)nByte ++ ){ ++ p = sqlite3_malloc64( sizeof(*p) + (nVertex-1)*2*sizeof(GeoCoord) ); ++ if( p==0 ){ ++ if( pRc ) *pRc = SQLITE_NOMEM; ++ if( pCtx ) sqlite3_result_error_nomem(pCtx); ++ }else{ ++ int x = 1; ++ p->nVertex = nVertex; ++ memcpy(p->hdr, a, nByte); ++ if( a[0] != *(unsigned char*)&x ){ ++ int ii; ++ for(ii=0; ii<nVertex*2; ii++){ ++ geopolySwab32((unsigned char*)&p->a[ii]); ++ } ++ p->hdr[0] ^= 1; ++ } ++ } ++ } ++ if( pRc ) *pRc = SQLITE_OK; ++ return p; ++ }else if( sqlite3_value_type(pVal)==SQLITE_TEXT ){ ++ const unsigned char *zJson = sqlite3_value_text(pVal); ++ if( zJson==0 ){ ++ if( pRc ) *pRc = SQLITE_NOMEM; ++ return 0; ++ } ++ return geopolyParseJson(zJson, pRc); ++ }else{ ++ if( pRc ) *pRc = SQLITE_ERROR; ++ return 0; ++ } ++} ++ ++/* ++** Implementation of the geopoly_blob(X) function. ++** ++** If the input is a well-formed Geopoly BLOB or JSON string ++** then return the BLOB representation of the polygon. Otherwise ++** return NULL. ++*/ ++static void geopolyBlobFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ GeoPoly *p = geopolyFuncParam(context, argv[0], 0); ++ if( p ){ ++ sqlite3_result_blob(context, p->hdr, ++ 4+8*p->nVertex, SQLITE_TRANSIENT); ++ sqlite3_free(p); ++ } ++} ++ ++/* ++** SQL function: geopoly_json(X) ++** ++** Interpret X as a polygon and render it as a JSON array ++** of coordinates. Or, if X is not a valid polygon, return NULL. ++*/ ++static void geopolyJsonFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ GeoPoly *p = geopolyFuncParam(context, argv[0], 0); ++ if( p ){ ++ sqlite3 *db = sqlite3_context_db_handle(context); ++ sqlite3_str *x = sqlite3_str_new(db); ++ int i; ++ sqlite3_str_append(x, "[", 1); ++ for(i=0; i<p->nVertex; i++){ ++ sqlite3_str_appendf(x, "[%!g,%!g],", p->a[i*2], p->a[i*2+1]); ++ } ++ sqlite3_str_appendf(x, "[%!g,%!g]]", p->a[0], p->a[1]); ++ sqlite3_result_text(context, sqlite3_str_finish(x), -1, sqlite3_free); ++ sqlite3_free(p); ++ } ++} ++ ++/* ++** SQL function: geopoly_svg(X, ....) ++** ++** Interpret X as a polygon and render it as a SVG <polyline>. ++** Additional arguments are added as attributes to the <polyline>. ++*/ ++static void geopolySvgFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ GeoPoly *p = geopolyFuncParam(context, argv[0], 0); ++ if( p ){ ++ sqlite3 *db = sqlite3_context_db_handle(context); ++ sqlite3_str *x = sqlite3_str_new(db); ++ int i; ++ char cSep = '\''; ++ sqlite3_str_appendf(x, "<polyline points="); ++ for(i=0; i<p->nVertex; i++){ ++ sqlite3_str_appendf(x, "%c%g,%g", cSep, p->a[i*2], p->a[i*2+1]); ++ cSep = ' '; ++ } ++ sqlite3_str_appendf(x, " %g,%g'", p->a[0], p->a[1]); ++ for(i=1; i<argc; i++){ ++ const char *z = (const char*)sqlite3_value_text(argv[i]); ++ if( z && z[0] ){ ++ sqlite3_str_appendf(x, " %s", z); ++ } ++ } ++ sqlite3_str_appendf(x, "></polyline>"); ++ sqlite3_result_text(context, sqlite3_str_finish(x), -1, sqlite3_free); ++ sqlite3_free(p); ++ } ++} ++ ++/* ++** SQL Function: geopoly_xform(poly, A, B, C, D, E, F) ++** ++** Transform and/or translate a polygon as follows: ++** ++** x1 = A*x0 + B*y0 + E ++** y1 = C*x0 + D*y0 + F ++** ++** For a translation: ++** ++** geopoly_xform(poly, 1, 0, 0, 1, x-offset, y-offset) ++** ++** Rotate by R around the point (0,0): ++** ++** geopoly_xform(poly, cos(R), sin(R), -sin(R), cos(R), 0, 0) ++*/ ++static void geopolyXformFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ GeoPoly *p = geopolyFuncParam(context, argv[0], 0); ++ double A = sqlite3_value_double(argv[1]); ++ double B = sqlite3_value_double(argv[2]); ++ double C = sqlite3_value_double(argv[3]); ++ double D = sqlite3_value_double(argv[4]); ++ double E = sqlite3_value_double(argv[5]); ++ double F = sqlite3_value_double(argv[6]); ++ GeoCoord x1, y1, x0, y0; ++ int ii; ++ if( p ){ ++ for(ii=0; ii<p->nVertex; ii++){ ++ x0 = p->a[ii*2]; ++ y0 = p->a[ii*2+1]; ++ x1 = (GeoCoord)(A*x0 + B*y0 + E); ++ y1 = (GeoCoord)(C*x0 + D*y0 + F); ++ p->a[ii*2] = x1; ++ p->a[ii*2+1] = y1; ++ } ++ sqlite3_result_blob(context, p->hdr, ++ 4+8*p->nVertex, SQLITE_TRANSIENT); ++ sqlite3_free(p); ++ } ++} ++ ++/* ++** Compute the area enclosed by the polygon. ++** ++** This routine can also be used to detect polygons that rotate in ++** the wrong direction. Polygons are suppose to be counter-clockwise (CCW). ++** This routine returns a negative value for clockwise (CW) polygons. ++*/ ++static double geopolyArea(GeoPoly *p){ ++ double rArea = 0.0; ++ int ii; ++ for(ii=0; ii<p->nVertex-1; ii++){ ++ rArea += (p->a[ii*2] - p->a[ii*2+2]) /* (x0 - x1) */ ++ * (p->a[ii*2+1] + p->a[ii*2+3]) /* (y0 + y1) */ ++ * 0.5; ++ } ++ rArea += (p->a[ii*2] - p->a[0]) /* (xN - x0) */ ++ * (p->a[ii*2+1] + p->a[1]) /* (yN + y0) */ ++ * 0.5; ++ return rArea; ++} ++ ++/* ++** Implementation of the geopoly_area(X) function. ++** ++** If the input is a well-formed Geopoly BLOB then return the area ++** enclosed by the polygon. If the polygon circulates clockwise instead ++** of counterclockwise (as it should) then return the negative of the ++** enclosed area. Otherwise return NULL. ++*/ ++static void geopolyAreaFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ GeoPoly *p = geopolyFuncParam(context, argv[0], 0); ++ if( p ){ ++ sqlite3_result_double(context, geopolyArea(p)); ++ sqlite3_free(p); ++ } ++} ++ ++/* ++** Implementation of the geopoly_ccw(X) function. ++** ++** If the rotation of polygon X is clockwise (incorrect) instead of ++** counter-clockwise (the correct winding order according to RFC7946) ++** then reverse the order of the vertexes in polygon X. ++** ++** In other words, this routine returns a CCW polygon regardless of the ++** winding order of its input. ++** ++** Use this routine to sanitize historical inputs that that sometimes ++** contain polygons that wind in the wrong direction. ++*/ ++static void geopolyCcwFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ GeoPoly *p = geopolyFuncParam(context, argv[0], 0); ++ if( p ){ ++ if( geopolyArea(p)<0.0 ){ ++ int ii, jj; ++ for(ii=2, jj=p->nVertex*2 - 2; ii<jj; ii+=2, jj-=2){ ++ GeoCoord t = p->a[ii]; ++ p->a[ii] = p->a[jj]; ++ p->a[jj] = t; ++ t = p->a[ii+1]; ++ p->a[ii+1] = p->a[jj+1]; ++ p->a[jj+1] = t; ++ } ++ } ++ sqlite3_result_blob(context, p->hdr, ++ 4+8*p->nVertex, SQLITE_TRANSIENT); ++ sqlite3_free(p); ++ } ++} ++ ++#define GEOPOLY_PI 3.1415926535897932385 ++ ++/* Fast approximation for sine(X) for X between -0.5*pi and 2*pi ++*/ ++static double geopolySine(double r){ ++ assert( r>=-0.5*GEOPOLY_PI && r<=2.0*GEOPOLY_PI ); ++ if( r>=1.5*GEOPOLY_PI ){ ++ r -= 2.0*GEOPOLY_PI; ++ } ++ if( r>=0.5*GEOPOLY_PI ){ ++ return -geopolySine(r-GEOPOLY_PI); ++ }else{ ++ double r2 = r*r; ++ double r3 = r2*r; ++ double r5 = r3*r2; ++ return 0.9996949*r - 0.1656700*r3 + 0.0075134*r5; ++ } ++} ++ ++/* ++** Function: geopoly_regular(X,Y,R,N) ++** ++** Construct a simple, convex, regular polygon centered at X, Y ++** with circumradius R and with N sides. ++*/ ++static void geopolyRegularFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ double x = sqlite3_value_double(argv[0]); ++ double y = sqlite3_value_double(argv[1]); ++ double r = sqlite3_value_double(argv[2]); ++ int n = sqlite3_value_int(argv[3]); ++ int i; ++ GeoPoly *p; ++ ++ if( n<3 || r<=0.0 ) return; ++ if( n>1000 ) n = 1000; ++ p = sqlite3_malloc64( sizeof(*p) + (n-1)*2*sizeof(GeoCoord) ); ++ if( p==0 ){ ++ sqlite3_result_error_nomem(context); ++ return; ++ } ++ i = 1; ++ p->hdr[0] = *(unsigned char*)&i; ++ p->hdr[1] = 0; ++ p->hdr[2] = (n>>8)&0xff; ++ p->hdr[3] = n&0xff; ++ for(i=0; i<n; i++){ ++ double rAngle = 2.0*GEOPOLY_PI*i/n; ++ p->a[i*2] = x - r*geopolySine(rAngle-0.5*GEOPOLY_PI); ++ p->a[i*2+1] = y + r*geopolySine(rAngle); ++ } ++ sqlite3_result_blob(context, p->hdr, 4+8*n, SQLITE_TRANSIENT); ++ sqlite3_free(p); ++} ++ ++/* ++** If pPoly is a polygon, compute its bounding box. Then: ++** ++** (1) if aCoord!=0 store the bounding box in aCoord, returning NULL ++** (2) otherwise, compute a GeoPoly for the bounding box and return the ++** new GeoPoly ++** ++** If pPoly is NULL but aCoord is not NULL, then compute a new GeoPoly from ++** the bounding box in aCoord and return a pointer to that GeoPoly. ++*/ ++static GeoPoly *geopolyBBox( ++ sqlite3_context *context, /* For recording the error */ ++ sqlite3_value *pPoly, /* The polygon */ ++ RtreeCoord *aCoord, /* Results here */ ++ int *pRc /* Error code here */ ++){ ++ GeoPoly *pOut = 0; ++ GeoPoly *p; ++ float mnX, mxX, mnY, mxY; ++ if( pPoly==0 && aCoord!=0 ){ ++ p = 0; ++ mnX = aCoord[0].f; ++ mxX = aCoord[1].f; ++ mnY = aCoord[2].f; ++ mxY = aCoord[3].f; ++ goto geopolyBboxFill; ++ }else{ ++ p = geopolyFuncParam(context, pPoly, pRc); ++ } ++ if( p ){ ++ int ii; ++ mnX = mxX = p->a[0]; ++ mnY = mxY = p->a[1]; ++ for(ii=1; ii<p->nVertex; ii++){ ++ double r = p->a[ii*2]; ++ if( r<mnX ) mnX = (float)r; ++ else if( r>mxX ) mxX = (float)r; ++ r = p->a[ii*2+1]; ++ if( r<mnY ) mnY = (float)r; ++ else if( r>mxY ) mxY = (float)r; ++ } ++ if( pRc ) *pRc = SQLITE_OK; ++ if( aCoord==0 ){ ++ geopolyBboxFill: ++ pOut = sqlite3_realloc(p, GEOPOLY_SZ(4)); ++ if( pOut==0 ){ ++ sqlite3_free(p); ++ if( context ) sqlite3_result_error_nomem(context); ++ if( pRc ) *pRc = SQLITE_NOMEM; ++ return 0; ++ } ++ pOut->nVertex = 4; ++ ii = 1; ++ pOut->hdr[0] = *(unsigned char*)ⅈ ++ pOut->hdr[1] = 0; ++ pOut->hdr[2] = 0; ++ pOut->hdr[3] = 4; ++ pOut->a[0] = mnX; ++ pOut->a[1] = mnY; ++ pOut->a[2] = mxX; ++ pOut->a[3] = mnY; ++ pOut->a[4] = mxX; ++ pOut->a[5] = mxY; ++ pOut->a[6] = mnX; ++ pOut->a[7] = mxY; ++ }else{ ++ sqlite3_free(p); ++ aCoord[0].f = mnX; ++ aCoord[1].f = mxX; ++ aCoord[2].f = mnY; ++ aCoord[3].f = mxY; ++ } ++ } ++ return pOut; ++} ++ ++/* ++** Implementation of the geopoly_bbox(X) SQL function. ++*/ ++static void geopolyBBoxFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ GeoPoly *p = geopolyBBox(context, argv[0], 0, 0); ++ if( p ){ ++ sqlite3_result_blob(context, p->hdr, ++ 4+8*p->nVertex, SQLITE_TRANSIENT); ++ sqlite3_free(p); ++ } ++} ++ ++/* ++** State vector for the geopoly_group_bbox() aggregate function. ++*/ ++typedef struct GeoBBox GeoBBox; ++struct GeoBBox { ++ int isInit; ++ RtreeCoord a[4]; ++}; ++ ++ ++/* ++** Implementation of the geopoly_group_bbox(X) aggregate SQL function. ++*/ ++static void geopolyBBoxStep( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ RtreeCoord a[4]; ++ int rc = SQLITE_OK; ++ (void)geopolyBBox(context, argv[0], a, &rc); ++ if( rc==SQLITE_OK ){ ++ GeoBBox *pBBox; ++ pBBox = (GeoBBox*)sqlite3_aggregate_context(context, sizeof(*pBBox)); ++ if( pBBox==0 ) return; ++ if( pBBox->isInit==0 ){ ++ pBBox->isInit = 1; ++ memcpy(pBBox->a, a, sizeof(RtreeCoord)*4); ++ }else{ ++ if( a[0].f < pBBox->a[0].f ) pBBox->a[0] = a[0]; ++ if( a[1].f > pBBox->a[1].f ) pBBox->a[1] = a[1]; ++ if( a[2].f < pBBox->a[2].f ) pBBox->a[2] = a[2]; ++ if( a[3].f > pBBox->a[3].f ) pBBox->a[3] = a[3]; ++ } ++ } ++} ++static void geopolyBBoxFinal( ++ sqlite3_context *context ++){ ++ GeoPoly *p; ++ GeoBBox *pBBox; ++ pBBox = (GeoBBox*)sqlite3_aggregate_context(context, 0); ++ if( pBBox==0 ) return; ++ p = geopolyBBox(context, 0, pBBox->a, 0); ++ if( p ){ ++ sqlite3_result_blob(context, p->hdr, ++ 4+8*p->nVertex, SQLITE_TRANSIENT); ++ sqlite3_free(p); ++ } ++} ++ ++ ++/* ++** Determine if point (x0,y0) is beneath line segment (x1,y1)->(x2,y2). ++** Returns: ++** ++** +2 x0,y0 is on the line segement ++** ++** +1 x0,y0 is beneath line segment ++** ++** 0 x0,y0 is not on or beneath the line segment or the line segment ++** is vertical and x0,y0 is not on the line segment ++** ++** The left-most coordinate min(x1,x2) is not considered to be part of ++** the line segment for the purposes of this analysis. ++*/ ++static int pointBeneathLine( ++ double x0, double y0, ++ double x1, double y1, ++ double x2, double y2 ++){ ++ double y; ++ if( x0==x1 && y0==y1 ) return 2; ++ if( x1<x2 ){ ++ if( x0<=x1 || x0>x2 ) return 0; ++ }else if( x1>x2 ){ ++ if( x0<=x2 || x0>x1 ) return 0; ++ }else{ ++ /* Vertical line segment */ ++ if( x0!=x1 ) return 0; ++ if( y0<y1 && y0<y2 ) return 0; ++ if( y0>y1 && y0>y2 ) return 0; ++ return 2; ++ } ++ y = y1 + (y2-y1)*(x0-x1)/(x2-x1); ++ if( y0==y ) return 2; ++ if( y0<y ) return 1; ++ return 0; ++} ++ ++/* ++** SQL function: geopoly_contains_point(P,X,Y) ++** ++** Return +2 if point X,Y is within polygon P. ++** Return +1 if point X,Y is on the polygon boundary. ++** Return 0 if point X,Y is outside the polygon ++*/ ++static void geopolyContainsPointFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0); ++ double x0 = sqlite3_value_double(argv[1]); ++ double y0 = sqlite3_value_double(argv[2]); ++ int v = 0; ++ int cnt = 0; ++ int ii; ++ if( p1==0 ) return; ++ for(ii=0; ii<p1->nVertex-1; ii++){ ++ v = pointBeneathLine(x0,y0,p1->a[ii*2],p1->a[ii*2+1], ++ p1->a[ii*2+2],p1->a[ii*2+3]); ++ if( v==2 ) break; ++ cnt += v; ++ } ++ if( v!=2 ){ ++ v = pointBeneathLine(x0,y0,p1->a[ii*2],p1->a[ii*2+1], ++ p1->a[0],p1->a[1]); ++ } ++ if( v==2 ){ ++ sqlite3_result_int(context, 1); ++ }else if( ((v+cnt)&1)==0 ){ ++ sqlite3_result_int(context, 0); ++ }else{ ++ sqlite3_result_int(context, 2); ++ } ++ sqlite3_free(p1); ++} ++ ++/* Forward declaration */ ++static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2); ++ ++/* ++** SQL function: geopoly_within(P1,P2) ++** ++** Return +2 if P1 and P2 are the same polygon ++** Return +1 if P2 is contained within P1 ++** Return 0 if any part of P2 is on the outside of P1 ++** ++*/ ++static void geopolyWithinFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0); ++ GeoPoly *p2 = geopolyFuncParam(context, argv[1], 0); ++ if( p1 && p2 ){ ++ int x = geopolyOverlap(p1, p2); ++ if( x<0 ){ ++ sqlite3_result_error_nomem(context); ++ }else{ ++ sqlite3_result_int(context, x==2 ? 1 : x==4 ? 2 : 0); ++ } ++ } ++ sqlite3_free(p1); ++ sqlite3_free(p2); ++} ++ ++/* Objects used by the overlap algorihm. */ ++typedef struct GeoEvent GeoEvent; ++typedef struct GeoSegment GeoSegment; ++typedef struct GeoOverlap GeoOverlap; ++struct GeoEvent { ++ double x; /* X coordinate at which event occurs */ ++ int eType; /* 0 for ADD, 1 for REMOVE */ ++ GeoSegment *pSeg; /* The segment to be added or removed */ ++ GeoEvent *pNext; /* Next event in the sorted list */ ++}; ++struct GeoSegment { ++ double C, B; /* y = C*x + B */ ++ double y; /* Current y value */ ++ float y0; /* Initial y value */ ++ unsigned char side; /* 1 for p1, 2 for p2 */ ++ unsigned int idx; /* Which segment within the side */ ++ GeoSegment *pNext; /* Next segment in a list sorted by y */ ++}; ++struct GeoOverlap { ++ GeoEvent *aEvent; /* Array of all events */ ++ GeoSegment *aSegment; /* Array of all segments */ ++ int nEvent; /* Number of events */ ++ int nSegment; /* Number of segments */ ++}; ++ ++/* ++** Add a single segment and its associated events. ++*/ ++static void geopolyAddOneSegment( ++ GeoOverlap *p, ++ GeoCoord x0, ++ GeoCoord y0, ++ GeoCoord x1, ++ GeoCoord y1, ++ unsigned char side, ++ unsigned int idx ++){ ++ GeoSegment *pSeg; ++ GeoEvent *pEvent; ++ if( x0==x1 ) return; /* Ignore vertical segments */ ++ if( x0>x1 ){ ++ GeoCoord t = x0; ++ x0 = x1; ++ x1 = t; ++ t = y0; ++ y0 = y1; ++ y1 = t; ++ } ++ pSeg = p->aSegment + p->nSegment; ++ p->nSegment++; ++ pSeg->C = (y1-y0)/(x1-x0); ++ pSeg->B = y1 - x1*pSeg->C; ++ pSeg->y0 = y0; ++ pSeg->side = side; ++ pSeg->idx = idx; ++ pEvent = p->aEvent + p->nEvent; ++ p->nEvent++; ++ pEvent->x = x0; ++ pEvent->eType = 0; ++ pEvent->pSeg = pSeg; ++ pEvent = p->aEvent + p->nEvent; ++ p->nEvent++; ++ pEvent->x = x1; ++ pEvent->eType = 1; ++ pEvent->pSeg = pSeg; ++} ++ ++ ++ ++/* ++** Insert all segments and events for polygon pPoly. ++*/ ++static void geopolyAddSegments( ++ GeoOverlap *p, /* Add segments to this Overlap object */ ++ GeoPoly *pPoly, /* Take all segments from this polygon */ ++ unsigned char side /* The side of pPoly */ ++){ ++ unsigned int i; ++ GeoCoord *x; ++ for(i=0; i<(unsigned)pPoly->nVertex-1; i++){ ++ x = pPoly->a + (i*2); ++ geopolyAddOneSegment(p, x[0], x[1], x[2], x[3], side, i); ++ } ++ x = pPoly->a + (i*2); ++ geopolyAddOneSegment(p, x[0], x[1], pPoly->a[0], pPoly->a[1], side, i); ++} ++ ++/* ++** Merge two lists of sorted events by X coordinate ++*/ ++static GeoEvent *geopolyEventMerge(GeoEvent *pLeft, GeoEvent *pRight){ ++ GeoEvent head, *pLast; ++ head.pNext = 0; ++ pLast = &head; ++ while( pRight && pLeft ){ ++ if( pRight->x <= pLeft->x ){ ++ pLast->pNext = pRight; ++ pLast = pRight; ++ pRight = pRight->pNext; ++ }else{ ++ pLast->pNext = pLeft; ++ pLast = pLeft; ++ pLeft = pLeft->pNext; ++ } ++ } ++ pLast->pNext = pRight ? pRight : pLeft; ++ return head.pNext; ++} ++ ++/* ++** Sort an array of nEvent event objects into a list. ++*/ ++static GeoEvent *geopolySortEventsByX(GeoEvent *aEvent, int nEvent){ ++ int mx = 0; ++ int i, j; ++ GeoEvent *p; ++ GeoEvent *a[50]; ++ for(i=0; i<nEvent; i++){ ++ p = &aEvent[i]; ++ p->pNext = 0; ++ for(j=0; j<mx && a[j]; j++){ ++ p = geopolyEventMerge(a[j], p); ++ a[j] = 0; ++ } ++ a[j] = p; ++ if( j>=mx ) mx = j+1; ++ } ++ p = 0; ++ for(i=0; i<mx; i++){ ++ p = geopolyEventMerge(a[i], p); ++ } ++ return p; ++} ++ ++/* ++** Merge two lists of sorted segments by Y, and then by C. ++*/ ++static GeoSegment *geopolySegmentMerge(GeoSegment *pLeft, GeoSegment *pRight){ ++ GeoSegment head, *pLast; ++ head.pNext = 0; ++ pLast = &head; ++ while( pRight && pLeft ){ ++ double r = pRight->y - pLeft->y; ++ if( r==0.0 ) r = pRight->C - pLeft->C; ++ if( r<0.0 ){ ++ pLast->pNext = pRight; ++ pLast = pRight; ++ pRight = pRight->pNext; ++ }else{ ++ pLast->pNext = pLeft; ++ pLast = pLeft; ++ pLeft = pLeft->pNext; ++ } ++ } ++ pLast->pNext = pRight ? pRight : pLeft; ++ return head.pNext; ++} ++ ++/* ++** Sort a list of GeoSegments in order of increasing Y and in the event of ++** a tie, increasing C (slope). ++*/ ++static GeoSegment *geopolySortSegmentsByYAndC(GeoSegment *pList){ ++ int mx = 0; ++ int i; ++ GeoSegment *p; ++ GeoSegment *a[50]; ++ while( pList ){ ++ p = pList; ++ pList = pList->pNext; ++ p->pNext = 0; ++ for(i=0; i<mx && a[i]; i++){ ++ p = geopolySegmentMerge(a[i], p); ++ a[i] = 0; ++ } ++ a[i] = p; ++ if( i>=mx ) mx = i+1; ++ } ++ p = 0; ++ for(i=0; i<mx; i++){ ++ p = geopolySegmentMerge(a[i], p); ++ } ++ return p; ++} ++ ++/* ++** Determine the overlap between two polygons ++*/ ++static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2){ ++ int nVertex = p1->nVertex + p2->nVertex + 2; ++ GeoOverlap *p; ++ int nByte; ++ GeoEvent *pThisEvent; ++ double rX; ++ int rc = 0; ++ int needSort = 0; ++ GeoSegment *pActive = 0; ++ GeoSegment *pSeg; ++ unsigned char aOverlap[4]; ++ ++ nByte = sizeof(GeoEvent)*nVertex*2 ++ + sizeof(GeoSegment)*nVertex ++ + sizeof(GeoOverlap); ++ p = sqlite3_malloc( nByte ); ++ if( p==0 ) return -1; ++ p->aEvent = (GeoEvent*)&p[1]; ++ p->aSegment = (GeoSegment*)&p->aEvent[nVertex*2]; ++ p->nEvent = p->nSegment = 0; ++ geopolyAddSegments(p, p1, 1); ++ geopolyAddSegments(p, p2, 2); ++ pThisEvent = geopolySortEventsByX(p->aEvent, p->nEvent); ++ rX = pThisEvent->x==0.0 ? -1.0 : 0.0; ++ memset(aOverlap, 0, sizeof(aOverlap)); ++ while( pThisEvent ){ ++ if( pThisEvent->x!=rX ){ ++ GeoSegment *pPrev = 0; ++ int iMask = 0; ++ GEODEBUG(("Distinct X: %g\n", pThisEvent->x)); ++ rX = pThisEvent->x; ++ if( needSort ){ ++ GEODEBUG(("SORT\n")); ++ pActive = geopolySortSegmentsByYAndC(pActive); ++ needSort = 0; ++ } ++ for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){ ++ if( pPrev ){ ++ if( pPrev->y!=pSeg->y ){ ++ GEODEBUG(("MASK: %d\n", iMask)); ++ aOverlap[iMask] = 1; ++ } ++ } ++ iMask ^= pSeg->side; ++ pPrev = pSeg; ++ } ++ pPrev = 0; ++ for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){ ++ double y = pSeg->C*rX + pSeg->B; ++ GEODEBUG(("Segment %d.%d %g->%g\n", pSeg->side, pSeg->idx, pSeg->y, y)); ++ pSeg->y = y; ++ if( pPrev ){ ++ if( pPrev->y>pSeg->y && pPrev->side!=pSeg->side ){ ++ rc = 1; ++ GEODEBUG(("Crossing: %d.%d and %d.%d\n", ++ pPrev->side, pPrev->idx, ++ pSeg->side, pSeg->idx)); ++ goto geopolyOverlapDone; ++ }else if( pPrev->y!=pSeg->y ){ ++ GEODEBUG(("MASK: %d\n", iMask)); ++ aOverlap[iMask] = 1; ++ } ++ } ++ iMask ^= pSeg->side; ++ pPrev = pSeg; ++ } ++ } ++ GEODEBUG(("%s %d.%d C=%g B=%g\n", ++ pThisEvent->eType ? "RM " : "ADD", ++ pThisEvent->pSeg->side, pThisEvent->pSeg->idx, ++ pThisEvent->pSeg->C, ++ pThisEvent->pSeg->B)); ++ if( pThisEvent->eType==0 ){ ++ /* Add a segment */ ++ pSeg = pThisEvent->pSeg; ++ pSeg->y = pSeg->y0; ++ pSeg->pNext = pActive; ++ pActive = pSeg; ++ needSort = 1; ++ }else{ ++ /* Remove a segment */ ++ if( pActive==pThisEvent->pSeg ){ ++ pActive = pActive->pNext; ++ }else{ ++ for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){ ++ if( pSeg->pNext==pThisEvent->pSeg ){ ++ pSeg->pNext = pSeg->pNext->pNext; ++ break; ++ } ++ } ++ } ++ } ++ pThisEvent = pThisEvent->pNext; ++ } ++ if( aOverlap[3]==0 ){ ++ rc = 0; ++ }else if( aOverlap[1]!=0 && aOverlap[2]==0 ){ ++ rc = 3; ++ }else if( aOverlap[1]==0 && aOverlap[2]!=0 ){ ++ rc = 2; ++ }else if( aOverlap[1]==0 && aOverlap[2]==0 ){ ++ rc = 4; ++ }else{ ++ rc = 1; ++ } ++ ++geopolyOverlapDone: ++ sqlite3_free(p); ++ return rc; ++} ++ ++/* ++** SQL function: geopoly_overlap(P1,P2) ++** ++** Determine whether or not P1 and P2 overlap. Return value: ++** ++** 0 The two polygons are disjoint ++** 1 They overlap ++** 2 P1 is completely contained within P2 ++** 3 P2 is completely contained within P1 ++** 4 P1 and P2 are the same polygon ++** NULL Either P1 or P2 or both are not valid polygons ++*/ ++static void geopolyOverlapFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++ GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0); ++ GeoPoly *p2 = geopolyFuncParam(context, argv[1], 0); ++ if( p1 && p2 ){ ++ int x = geopolyOverlap(p1, p2); ++ if( x<0 ){ ++ sqlite3_result_error_nomem(context); ++ }else{ ++ sqlite3_result_int(context, x); ++ } ++ } ++ sqlite3_free(p1); ++ sqlite3_free(p2); ++} ++ ++/* ++** Enable or disable debugging output ++*/ ++static void geopolyDebugFunc( ++ sqlite3_context *context, ++ int argc, ++ sqlite3_value **argv ++){ ++#ifdef GEOPOLY_ENABLE_DEBUG ++ geo_debug = sqlite3_value_int(argv[0]); ++#endif ++} ++ ++/* ++** This function is the implementation of both the xConnect and xCreate ++** methods of the geopoly virtual table. ++** ++** argv[0] -> module name ++** argv[1] -> database name ++** argv[2] -> table name ++** argv[...] -> column names... ++*/ ++static int geopolyInit( ++ sqlite3 *db, /* Database connection */ ++ void *pAux, /* One of the RTREE_COORD_* constants */ ++ int argc, const char *const*argv, /* Parameters to CREATE TABLE statement */ ++ sqlite3_vtab **ppVtab, /* OUT: New virtual table */ ++ char **pzErr, /* OUT: Error message, if any */ ++ int isCreate /* True for xCreate, false for xConnect */ ++){ ++ int rc = SQLITE_OK; ++ Rtree *pRtree; ++ int nDb; /* Length of string argv[1] */ ++ int nName; /* Length of string argv[2] */ ++ sqlite3_str *pSql; ++ char *zSql; ++ int ii; ++ ++ sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); ++ ++ /* Allocate the sqlite3_vtab structure */ ++ nDb = (int)strlen(argv[1]); ++ nName = (int)strlen(argv[2]); ++ pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2); ++ if( !pRtree ){ ++ return SQLITE_NOMEM; ++ } ++ memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2); ++ pRtree->nBusy = 1; ++ pRtree->base.pModule = &rtreeModule; ++ pRtree->zDb = (char *)&pRtree[1]; ++ pRtree->zName = &pRtree->zDb[nDb+1]; ++ pRtree->eCoordType = RTREE_COORD_REAL32; ++ pRtree->nDim = 2; ++ pRtree->nDim2 = 4; ++ memcpy(pRtree->zDb, argv[1], nDb); ++ memcpy(pRtree->zName, argv[2], nName); ++ ++ ++ /* Create/Connect to the underlying relational database schema. If ++ ** that is successful, call sqlite3_declare_vtab() to configure ++ ** the r-tree table schema. ++ */ ++ pSql = sqlite3_str_new(db); ++ sqlite3_str_appendf(pSql, "CREATE TABLE x(_shape"); ++ pRtree->nAux = 1; /* Add one for _shape */ ++ pRtree->nAuxNotNull = 1; /* The _shape column is always not-null */ ++ for(ii=3; ii<argc; ii++){ ++ pRtree->nAux++; ++ sqlite3_str_appendf(pSql, ",%s", argv[ii]); ++ } ++ sqlite3_str_appendf(pSql, ");"); ++ zSql = sqlite3_str_finish(pSql); ++ if( !zSql ){ ++ rc = SQLITE_NOMEM; ++ }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){ ++ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); ++ } ++ sqlite3_free(zSql); ++ if( rc ) goto geopolyInit_fail; ++ pRtree->nBytesPerCell = 8 + pRtree->nDim2*4; ++ ++ /* Figure out the node size to use. */ ++ rc = getNodeSize(db, pRtree, isCreate, pzErr); ++ if( rc ) goto geopolyInit_fail; ++ rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate); ++ if( rc ){ ++ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); ++ goto geopolyInit_fail; ++ } ++ ++ *ppVtab = (sqlite3_vtab *)pRtree; ++ return SQLITE_OK; ++ ++geopolyInit_fail: ++ if( rc==SQLITE_OK ) rc = SQLITE_ERROR; ++ assert( *ppVtab==0 ); ++ assert( pRtree->nBusy==1 ); ++ rtreeRelease(pRtree); ++ return rc; ++} ++ ++ ++/* ++** GEOPOLY virtual table module xCreate method. ++*/ ++static int geopolyCreate( ++ sqlite3 *db, ++ void *pAux, ++ int argc, const char *const*argv, ++ sqlite3_vtab **ppVtab, ++ char **pzErr ++){ ++ return geopolyInit(db, pAux, argc, argv, ppVtab, pzErr, 1); ++} ++ ++/* ++** GEOPOLY virtual table module xConnect method. ++*/ ++static int geopolyConnect( ++ sqlite3 *db, ++ void *pAux, ++ int argc, const char *const*argv, ++ sqlite3_vtab **ppVtab, ++ char **pzErr ++){ ++ return geopolyInit(db, pAux, argc, argv, ppVtab, pzErr, 0); ++} ++ ++ ++/* ++** GEOPOLY virtual table module xFilter method. ++** ++** Query plans: ++** ++** 1 rowid lookup ++** 2 search for objects overlapping the same bounding box ++** that contains polygon argv[0] ++** 3 search for objects overlapping the same bounding box ++** that contains polygon argv[0] ++** 4 full table scan ++*/ ++static int geopolyFilter( ++ sqlite3_vtab_cursor *pVtabCursor, /* The cursor to initialize */ ++ int idxNum, /* Query plan */ ++ const char *idxStr, /* Not Used */ ++ int argc, sqlite3_value **argv /* Parameters to the query plan */ ++){ ++ Rtree *pRtree = (Rtree *)pVtabCursor->pVtab; ++ RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; ++ RtreeNode *pRoot = 0; ++ int rc = SQLITE_OK; ++ int iCell = 0; ++ sqlite3_stmt *pStmt; ++ ++ rtreeReference(pRtree); ++ ++ /* Reset the cursor to the same state as rtreeOpen() leaves it in. */ ++ freeCursorConstraints(pCsr); ++ sqlite3_free(pCsr->aPoint); ++ pStmt = pCsr->pReadAux; ++ memset(pCsr, 0, sizeof(RtreeCursor)); ++ pCsr->base.pVtab = (sqlite3_vtab*)pRtree; ++ pCsr->pReadAux = pStmt; ++ ++ pCsr->iStrategy = idxNum; ++ if( idxNum==1 ){ ++ /* Special case - lookup by rowid. */ ++ RtreeNode *pLeaf; /* Leaf on which the required cell resides */ ++ RtreeSearchPoint *p; /* Search point for the leaf */ ++ i64 iRowid = sqlite3_value_int64(argv[0]); ++ i64 iNode = 0; ++ rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode); ++ if( rc==SQLITE_OK && pLeaf!=0 ){ ++ p = rtreeSearchPointNew(pCsr, RTREE_ZERO, 0); ++ assert( p!=0 ); /* Always returns pCsr->sPoint */ ++ pCsr->aNode[0] = pLeaf; ++ p->id = iNode; ++ p->eWithin = PARTLY_WITHIN; ++ rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &iCell); ++ p->iCell = (u8)iCell; ++ RTREE_QUEUE_TRACE(pCsr, "PUSH-F1:"); ++ }else{ ++ pCsr->atEOF = 1; ++ } ++ }else{ ++ /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array ++ ** with the configured constraints. ++ */ ++ rc = nodeAcquire(pRtree, 1, 0, &pRoot); ++ if( rc==SQLITE_OK && idxNum<=3 ){ ++ RtreeCoord bbox[4]; ++ RtreeConstraint *p; ++ assert( argc==1 ); ++ geopolyBBox(0, argv[0], bbox, &rc); ++ if( rc ){ ++ goto geopoly_filter_end; ++ } ++ pCsr->aConstraint = p = sqlite3_malloc(sizeof(RtreeConstraint)*4); ++ pCsr->nConstraint = 4; ++ if( p==0 ){ ++ rc = SQLITE_NOMEM; ++ }else{ ++ memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*4); ++ memset(pCsr->anQueue, 0, sizeof(u32)*(pRtree->iDepth + 1)); ++ if( idxNum==2 ){ ++ /* Overlap query */ ++ p->op = 'B'; ++ p->iCoord = 0; ++ p->u.rValue = bbox[1].f; ++ p++; ++ p->op = 'D'; ++ p->iCoord = 1; ++ p->u.rValue = bbox[0].f; ++ p++; ++ p->op = 'B'; ++ p->iCoord = 2; ++ p->u.rValue = bbox[3].f; ++ p++; ++ p->op = 'D'; ++ p->iCoord = 3; ++ p->u.rValue = bbox[2].f; ++ }else{ ++ /* Within query */ ++ p->op = 'D'; ++ p->iCoord = 0; ++ p->u.rValue = bbox[0].f; ++ p++; ++ p->op = 'B'; ++ p->iCoord = 1; ++ p->u.rValue = bbox[1].f; ++ p++; ++ p->op = 'D'; ++ p->iCoord = 2; ++ p->u.rValue = bbox[2].f; ++ p++; ++ p->op = 'B'; ++ p->iCoord = 3; ++ p->u.rValue = bbox[3].f; ++ } ++ } ++ } ++ if( rc==SQLITE_OK ){ ++ RtreeSearchPoint *pNew; ++ pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, (u8)(pRtree->iDepth+1)); ++ if( pNew==0 ){ ++ rc = SQLITE_NOMEM; ++ goto geopoly_filter_end; ++ } ++ pNew->id = 1; ++ pNew->iCell = 0; ++ pNew->eWithin = PARTLY_WITHIN; ++ assert( pCsr->bPoint==1 ); ++ pCsr->aNode[0] = pRoot; ++ pRoot = 0; ++ RTREE_QUEUE_TRACE(pCsr, "PUSH-Fm:"); ++ rc = rtreeStepToLeaf(pCsr); ++ } ++ } ++ ++geopoly_filter_end: ++ nodeRelease(pRtree, pRoot); ++ rtreeRelease(pRtree); ++ return rc; ++} ++ ++/* ++** Rtree virtual table module xBestIndex method. There are three ++** table scan strategies to choose from (in order from most to ++** least desirable): ++** ++** idxNum idxStr Strategy ++** ------------------------------------------------ ++** 1 "rowid" Direct lookup by rowid. ++** 2 "rtree" R-tree overlap query using geopoly_overlap() ++** 3 "rtree" R-tree within query using geopoly_within() ++** 4 "fullscan" full-table scan. ++** ------------------------------------------------ ++*/ ++static int geopolyBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ ++ int ii; ++ int iRowidTerm = -1; ++ int iFuncTerm = -1; ++ int idxNum = 0; ++ ++ for(ii=0; ii<pIdxInfo->nConstraint; ii++){ ++ struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii]; ++ if( !p->usable ) continue; ++ if( p->iColumn<0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ ++ iRowidTerm = ii; ++ break; ++ } ++ if( p->iColumn==0 && p->op>=SQLITE_INDEX_CONSTRAINT_FUNCTION ){ ++ /* p->op==SQLITE_INDEX_CONSTRAINT_FUNCTION for geopoly_overlap() ++ ** p->op==(SQLITE_INDEX_CONTRAINT_FUNCTION+1) for geopoly_within(). ++ ** See geopolyFindFunction() */ ++ iFuncTerm = ii; ++ idxNum = p->op - SQLITE_INDEX_CONSTRAINT_FUNCTION + 2; ++ } ++ } ++ ++ if( iRowidTerm>=0 ){ ++ pIdxInfo->idxNum = 1; ++ pIdxInfo->idxStr = "rowid"; ++ pIdxInfo->aConstraintUsage[iRowidTerm].argvIndex = 1; ++ pIdxInfo->aConstraintUsage[iRowidTerm].omit = 1; ++ pIdxInfo->estimatedCost = 30.0; ++ pIdxInfo->estimatedRows = 1; ++ pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE; ++ return SQLITE_OK; ++ } ++ if( iFuncTerm>=0 ){ ++ pIdxInfo->idxNum = idxNum; ++ pIdxInfo->idxStr = "rtree"; ++ pIdxInfo->aConstraintUsage[iFuncTerm].argvIndex = 1; ++ pIdxInfo->aConstraintUsage[iFuncTerm].omit = 0; ++ pIdxInfo->estimatedCost = 300.0; ++ pIdxInfo->estimatedRows = 10; ++ return SQLITE_OK; ++ } ++ pIdxInfo->idxNum = 4; ++ pIdxInfo->idxStr = "fullscan"; ++ pIdxInfo->estimatedCost = 3000000.0; ++ pIdxInfo->estimatedRows = 100000; ++ return SQLITE_OK; ++} ++ ++ ++/* ++** GEOPOLY virtual table module xColumn method. ++*/ ++static int geopolyColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ ++ Rtree *pRtree = (Rtree *)cur->pVtab; ++ RtreeCursor *pCsr = (RtreeCursor *)cur; ++ RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr); ++ int rc = SQLITE_OK; ++ RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc); ++ ++ if( rc ) return rc; ++ if( p==0 ) return SQLITE_OK; ++ if( i==0 && sqlite3_vtab_nochange(ctx) ) return SQLITE_OK; ++ if( i<=pRtree->nAux ){ ++ if( !pCsr->bAuxValid ){ ++ if( pCsr->pReadAux==0 ){ ++ rc = sqlite3_prepare_v3(pRtree->db, pRtree->zReadAuxSql, -1, 0, ++ &pCsr->pReadAux, 0); ++ if( rc ) return rc; ++ } ++ sqlite3_bind_int64(pCsr->pReadAux, 1, ++ nodeGetRowid(pRtree, pNode, p->iCell)); ++ rc = sqlite3_step(pCsr->pReadAux); ++ if( rc==SQLITE_ROW ){ ++ pCsr->bAuxValid = 1; ++ }else{ ++ sqlite3_reset(pCsr->pReadAux); ++ if( rc==SQLITE_DONE ) rc = SQLITE_OK; ++ return rc; ++ } ++ } ++ sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pReadAux, i+2)); ++ } ++ return SQLITE_OK; ++} ++ ++ ++/* ++** The xUpdate method for GEOPOLY module virtual tables. ++** ++** For DELETE: ++** ++** argv[0] = the rowid to be deleted ++** ++** For INSERT: ++** ++** argv[0] = SQL NULL ++** argv[1] = rowid to insert, or an SQL NULL to select automatically ++** argv[2] = _shape column ++** argv[3] = first application-defined column.... ++** ++** For UPDATE: ++** ++** argv[0] = rowid to modify. Never NULL ++** argv[1] = rowid after the change. Never NULL ++** argv[2] = new value for _shape ++** argv[3] = new value for first application-defined column.... ++*/ ++static int geopolyUpdate( ++ sqlite3_vtab *pVtab, ++ int nData, ++ sqlite3_value **aData, ++ sqlite_int64 *pRowid ++){ ++ Rtree *pRtree = (Rtree *)pVtab; ++ int rc = SQLITE_OK; ++ RtreeCell cell; /* New cell to insert if nData>1 */ ++ i64 oldRowid; /* The old rowid */ ++ int oldRowidValid; /* True if oldRowid is valid */ ++ i64 newRowid; /* The new rowid */ ++ int newRowidValid; /* True if newRowid is valid */ ++ int coordChange = 0; /* Change in coordinates */ ++ ++ if( pRtree->nNodeRef ){ ++ /* Unable to write to the btree while another cursor is reading from it, ++ ** since the write might do a rebalance which would disrupt the read ++ ** cursor. */ ++ return SQLITE_LOCKED_VTAB; ++ } ++ rtreeReference(pRtree); ++ assert(nData>=1); ++ ++ oldRowidValid = sqlite3_value_type(aData[0])!=SQLITE_NULL;; ++ oldRowid = oldRowidValid ? sqlite3_value_int64(aData[0]) : 0; ++ newRowidValid = nData>1 && sqlite3_value_type(aData[1])!=SQLITE_NULL; ++ newRowid = newRowidValid ? sqlite3_value_int64(aData[1]) : 0; ++ cell.iRowid = newRowid; ++ ++ if( nData>1 /* not a DELETE */ ++ && (!oldRowidValid /* INSERT */ ++ || !sqlite3_value_nochange(aData[2]) /* UPDATE _shape */ ++ || oldRowid!=newRowid) /* Rowid change */ ++ ){ ++ geopolyBBox(0, aData[2], cell.aCoord, &rc); ++ if( rc ){ ++ if( rc==SQLITE_ERROR ){ ++ pVtab->zErrMsg = ++ sqlite3_mprintf("_shape does not contain a valid polygon"); ++ } ++ goto geopoly_update_end; ++ } ++ coordChange = 1; ++ ++ /* If a rowid value was supplied, check if it is already present in ++ ** the table. If so, the constraint has failed. */ ++ if( newRowidValid && (!oldRowidValid || oldRowid!=newRowid) ){ ++ int steprc; ++ sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid); ++ steprc = sqlite3_step(pRtree->pReadRowid); ++ rc = sqlite3_reset(pRtree->pReadRowid); ++ if( SQLITE_ROW==steprc ){ ++ if( sqlite3_vtab_on_conflict(pRtree->db)==SQLITE_REPLACE ){ ++ rc = rtreeDeleteRowid(pRtree, cell.iRowid); ++ }else{ ++ rc = rtreeConstraintError(pRtree, 0); ++ } ++ } ++ } ++ } ++ ++ /* If aData[0] is not an SQL NULL value, it is the rowid of a ++ ** record to delete from the r-tree table. The following block does ++ ** just that. ++ */ ++ if( rc==SQLITE_OK && (nData==1 || (coordChange && oldRowidValid)) ){ ++ rc = rtreeDeleteRowid(pRtree, oldRowid); ++ } ++ ++ /* If the aData[] array contains more than one element, elements ++ ** (aData[2]..aData[argc-1]) contain a new record to insert into ++ ** the r-tree structure. ++ */ ++ if( rc==SQLITE_OK && nData>1 && coordChange ){ ++ /* Insert the new record into the r-tree */ ++ RtreeNode *pLeaf = 0; ++ if( !newRowidValid ){ ++ rc = rtreeNewRowid(pRtree, &cell.iRowid); ++ } ++ *pRowid = cell.iRowid; ++ if( rc==SQLITE_OK ){ ++ rc = ChooseLeaf(pRtree, &cell, 0, &pLeaf); ++ } ++ if( rc==SQLITE_OK ){ ++ int rc2; ++ pRtree->iReinsertHeight = -1; ++ rc = rtreeInsertCell(pRtree, pLeaf, &cell, 0); ++ rc2 = nodeRelease(pRtree, pLeaf); ++ if( rc==SQLITE_OK ){ ++ rc = rc2; ++ } ++ } ++ } ++ ++ /* Change the data */ ++ if( rc==SQLITE_OK && nData>1 ){ ++ sqlite3_stmt *pUp = pRtree->pWriteAux; ++ int jj; ++ int nChange = 0; ++ sqlite3_bind_int64(pUp, 1, cell.iRowid); ++ assert( pRtree->nAux>=1 ); ++ if( sqlite3_value_nochange(aData[2]) ){ ++ sqlite3_bind_null(pUp, 2); ++ }else{ ++ GeoPoly *p = 0; ++ if( sqlite3_value_type(aData[2])==SQLITE_TEXT ++ && (p = geopolyFuncParam(0, aData[2], &rc))!=0 ++ && rc==SQLITE_OK ++ ){ ++ sqlite3_bind_blob(pUp, 2, p->hdr, 4+8*p->nVertex, SQLITE_TRANSIENT); ++ }else{ ++ sqlite3_bind_value(pUp, 2, aData[2]); ++ } ++ sqlite3_free(p); ++ nChange = 1; ++ } ++ for(jj=1; jj<pRtree->nAux; jj++){ ++ nChange++; ++ sqlite3_bind_value(pUp, jj+2, aData[jj+2]); ++ } ++ if( nChange ){ ++ sqlite3_step(pUp); ++ rc = sqlite3_reset(pUp); ++ } ++ } ++ ++geopoly_update_end: ++ rtreeRelease(pRtree); ++ return rc; ++} ++ ++/* ++** Report that geopoly_overlap() is an overloaded function suitable ++** for use in xBestIndex. ++*/ ++static int geopolyFindFunction( ++ sqlite3_vtab *pVtab, ++ int nArg, ++ const char *zName, ++ void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), ++ void **ppArg ++){ ++ if( sqlite3_stricmp(zName, "geopoly_overlap")==0 ){ ++ *pxFunc = geopolyOverlapFunc; ++ *ppArg = 0; ++ return SQLITE_INDEX_CONSTRAINT_FUNCTION; ++ } ++ if( sqlite3_stricmp(zName, "geopoly_within")==0 ){ ++ *pxFunc = geopolyWithinFunc; ++ *ppArg = 0; ++ return SQLITE_INDEX_CONSTRAINT_FUNCTION+1; ++ } ++ return 0; ++} ++ ++ ++static sqlite3_module geopolyModule = { ++ 3, /* iVersion */ ++ geopolyCreate, /* xCreate - create a table */ ++ geopolyConnect, /* xConnect - connect to an existing table */ ++ geopolyBestIndex, /* xBestIndex - Determine search strategy */ ++ rtreeDisconnect, /* xDisconnect - Disconnect from a table */ ++ rtreeDestroy, /* xDestroy - Drop a table */ ++ rtreeOpen, /* xOpen - open a cursor */ ++ rtreeClose, /* xClose - close a cursor */ ++ geopolyFilter, /* xFilter - configure scan constraints */ ++ rtreeNext, /* xNext - advance a cursor */ ++ rtreeEof, /* xEof */ ++ geopolyColumn, /* xColumn - read data */ ++ rtreeRowid, /* xRowid - read data */ ++ geopolyUpdate, /* xUpdate - write data */ ++ rtreeBeginTransaction, /* xBegin - begin transaction */ ++ rtreeEndTransaction, /* xSync - sync transaction */ ++ rtreeEndTransaction, /* xCommit - commit transaction */ ++ rtreeEndTransaction, /* xRollback - rollback transaction */ ++ geopolyFindFunction, /* xFindFunction - function overloading */ ++ rtreeRename, /* xRename - rename the table */ ++ rtreeSavepoint, /* xSavepoint */ ++ 0, /* xRelease */ ++ 0, /* xRollbackTo */ ++ rtreeShadowName /* xShadowName */ ++}; ++ ++static int sqlite3_geopoly_init(sqlite3 *db){ ++ int rc = SQLITE_OK; ++ static const struct { ++ void (*xFunc)(sqlite3_context*,int,sqlite3_value**); ++ signed char nArg; ++ unsigned char bPure; ++ const char *zName; ++ } aFunc[] = { ++ { geopolyAreaFunc, 1, 1, "geopoly_area" }, ++ { geopolyBlobFunc, 1, 1, "geopoly_blob" }, ++ { geopolyJsonFunc, 1, 1, "geopoly_json" }, ++ { geopolySvgFunc, -1, 1, "geopoly_svg" }, ++ { geopolyWithinFunc, 2, 1, "geopoly_within" }, ++ { geopolyContainsPointFunc, 3, 1, "geopoly_contains_point" }, ++ { geopolyOverlapFunc, 2, 1, "geopoly_overlap" }, ++ { geopolyDebugFunc, 1, 0, "geopoly_debug" }, ++ { geopolyBBoxFunc, 1, 1, "geopoly_bbox" }, ++ { geopolyXformFunc, 7, 1, "geopoly_xform" }, ++ { geopolyRegularFunc, 4, 1, "geopoly_regular" }, ++ { geopolyCcwFunc, 1, 1, "geopoly_ccw" }, ++ }; ++ static const struct { ++ void (*xStep)(sqlite3_context*,int,sqlite3_value**); ++ void (*xFinal)(sqlite3_context*); ++ const char *zName; ++ } aAgg[] = { ++ { geopolyBBoxStep, geopolyBBoxFinal, "geopoly_group_bbox" }, ++ }; ++ int i; ++ for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){ ++ int enc = aFunc[i].bPure ? SQLITE_UTF8|SQLITE_DETERMINISTIC : SQLITE_UTF8; ++ rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg, ++ enc, 0, ++ aFunc[i].xFunc, 0, 0); ++ } ++ for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){ ++ rc = sqlite3_create_function(db, aAgg[i].zName, 1, SQLITE_UTF8, 0, ++ 0, aAgg[i].xStep, aAgg[i].xFinal); ++ } ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3_create_module_v2(db, "geopoly", &geopolyModule, 0, 0); ++ } ++ return rc; ++} ++ ++/************** End of geopoly.c *********************************************/ ++/************** Continuing where we left off in rtree.c **********************/ ++#endif ++ ++/* + ** Register the r-tree module with database handle db. This creates the + ** virtual table module "rtree" and the debugging/analysis scalar + ** function "rtreenode". +@@ -172893,6 +185203,11 @@ + void *c = (void *)RTREE_COORD_INT32; + rc = sqlite3_create_module_v2(db, "rtree_i32", &rtreeModule, c, 0); + } ++#ifdef SQLITE_ENABLE_GEOPOLY ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3_geopoly_init(db); ++ } ++#endif + + return rc; + } +@@ -174618,6 +186933,10 @@ + ** + ** RBU_STATE_OALSZ: + ** Valid if STAGE==1. The size in bytes of the *-oal file. ++** ++** RBU_STATE_DATATBL: ++** Only valid if STAGE==1. The RBU database name of the table ++** currently being read. + */ + #define RBU_STATE_STAGE 1 + #define RBU_STATE_TBL 2 +@@ -174628,6 +186947,7 @@ + #define RBU_STATE_COOKIE 7 + #define RBU_STATE_OALSZ 8 + #define RBU_STATE_PHASEONESTEP 9 ++#define RBU_STATE_DATATBL 10 + + #define RBU_STAGE_OAL 1 + #define RBU_STAGE_MOVE 2 +@@ -174670,6 +186990,7 @@ + struct RbuState { + int eStage; + char *zTbl; ++ char *zDataTbl; + char *zIdx; + i64 iWalCksum; + int nRow; +@@ -174864,7 +187185,8 @@ + sqlite3_vfs *pRealVfs; /* Underlying VFS */ + sqlite3_mutex *mutex; /* Mutex to protect pMain */ + sqlite3rbu *pRbu; /* Owner RBU object */ +- rbu_file *pMain; /* Linked list of main db files */ ++ rbu_file *pMain; /* List of main db files */ ++ rbu_file *pMainRbu; /* List of main db files with pRbu!=0 */ + }; + + /* +@@ -174893,6 +187215,7 @@ + const char *zWal; /* Wal filename for this main db file */ + rbu_file *pWalFd; /* Wal file descriptor for this main db */ + rbu_file *pMainNext; /* Next MAIN_DB file */ ++ rbu_file *pMainRbuNext; /* Next MAIN_DB file with pRbu!=0 */ + }; + + /* +@@ -176733,6 +189056,7 @@ + static void rbuFreeState(RbuState *p){ + if( p ){ + sqlite3_free(p->zTbl); ++ sqlite3_free(p->zDataTbl); + sqlite3_free(p->zIdx); + sqlite3_free(p); + } +@@ -176803,6 +189127,10 @@ + pRet->nPhaseOneStep = sqlite3_column_int64(pStmt, 1); + break; + ++ case RBU_STATE_DATATBL: ++ pRet->zDataTbl = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc); ++ break; ++ + default: + rc = SQLITE_CORRUPT; + break; +@@ -177577,7 +189905,8 @@ + "(%d, %lld), " + "(%d, %lld), " + "(%d, %lld), " +- "(%d, %lld) ", ++ "(%d, %lld), " ++ "(%d, %Q) ", + p->zStateDb, + RBU_STATE_STAGE, eStage, + RBU_STATE_TBL, p->objiter.zTbl, +@@ -177587,7 +189916,8 @@ + RBU_STATE_CKPT, p->iWalCksum, + RBU_STATE_COOKIE, (i64)pFd->iCookie, + RBU_STATE_OALSZ, p->iOalSz, +- RBU_STATE_PHASEONESTEP, p->nPhaseOneStep ++ RBU_STATE_PHASEONESTEP, p->nPhaseOneStep, ++ RBU_STATE_DATATBL, p->objiter.zDataTbl + ) + ); + assert( pInsert==0 || rc==SQLITE_OK ); +@@ -177843,7 +190173,8 @@ + + while( rc==SQLITE_OK && pIter->zTbl && (pIter->bCleanup + || rbuStrCompare(pIter->zIdx, pState->zIdx) +- || rbuStrCompare(pIter->zTbl, pState->zTbl) ++ || (pState->zDataTbl==0 && rbuStrCompare(pIter->zTbl, pState->zTbl)) ++ || (pState->zDataTbl && rbuStrCompare(pIter->zDataTbl, pState->zDataTbl)) + )){ + rc = rbuObjIterNext(p, pIter); + } +@@ -178482,6 +190813,69 @@ + } + + /* ++** Add an item to the main-db lists, if it is not already present. ++** ++** There are two main-db lists. One for all file descriptors, and one ++** for all file descriptors with rbu_file.pDb!=0. If the argument has ++** rbu_file.pDb!=0, then it is assumed to already be present on the ++** main list and is only added to the pDb!=0 list. ++*/ ++static void rbuMainlistAdd(rbu_file *p){ ++ rbu_vfs *pRbuVfs = p->pRbuVfs; ++ rbu_file *pIter; ++ assert( (p->openFlags & SQLITE_OPEN_MAIN_DB) ); ++ sqlite3_mutex_enter(pRbuVfs->mutex); ++ if( p->pRbu==0 ){ ++ for(pIter=pRbuVfs->pMain; pIter; pIter=pIter->pMainNext); ++ p->pMainNext = pRbuVfs->pMain; ++ pRbuVfs->pMain = p; ++ }else{ ++ for(pIter=pRbuVfs->pMainRbu; pIter && pIter!=p; pIter=pIter->pMainRbuNext){} ++ if( pIter==0 ){ ++ p->pMainRbuNext = pRbuVfs->pMainRbu; ++ pRbuVfs->pMainRbu = p; ++ } ++ } ++ sqlite3_mutex_leave(pRbuVfs->mutex); ++} ++ ++/* ++** Remove an item from the main-db lists. ++*/ ++static void rbuMainlistRemove(rbu_file *p){ ++ rbu_file **pp; ++ sqlite3_mutex_enter(p->pRbuVfs->mutex); ++ for(pp=&p->pRbuVfs->pMain; *pp && *pp!=p; pp=&((*pp)->pMainNext)){} ++ if( *pp ) *pp = p->pMainNext; ++ p->pMainNext = 0; ++ for(pp=&p->pRbuVfs->pMainRbu; *pp && *pp!=p; pp=&((*pp)->pMainRbuNext)){} ++ if( *pp ) *pp = p->pMainRbuNext; ++ p->pMainRbuNext = 0; ++ sqlite3_mutex_leave(p->pRbuVfs->mutex); ++} ++ ++/* ++** Given that zWal points to a buffer containing a wal file name passed to ++** either the xOpen() or xAccess() VFS method, search the main-db list for ++** a file-handle opened by the same database connection on the corresponding ++** database file. ++** ++** If parameter bRbu is true, only search for file-descriptors with ++** rbu_file.pDb!=0. ++*/ ++static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal, int bRbu){ ++ rbu_file *pDb; ++ sqlite3_mutex_enter(pRbuVfs->mutex); ++ if( bRbu ){ ++ for(pDb=pRbuVfs->pMainRbu; pDb && pDb->zWal!=zWal; pDb=pDb->pMainRbuNext){} ++ }else{ ++ for(pDb=pRbuVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext){} ++ } ++ sqlite3_mutex_leave(pRbuVfs->mutex); ++ return pDb; ++} ++ ++/* + ** Close an rbu file. + */ + static int rbuVfsClose(sqlite3_file *pFile){ +@@ -178498,11 +190892,7 @@ + sqlite3_free(p->zDel); + + if( p->openFlags & SQLITE_OPEN_MAIN_DB ){ +- rbu_file **pp; +- sqlite3_mutex_enter(p->pRbuVfs->mutex); +- for(pp=&p->pRbuVfs->pMain; *pp!=p; pp=&((*pp)->pMainNext)); +- *pp = p->pMainNext; +- sqlite3_mutex_leave(p->pRbuVfs->mutex); ++ rbuMainlistRemove(p); + rbuUnlockShm(p); + p->pReal->pMethods->xShmUnmap(p->pReal, 0); + } +@@ -178509,6 +190899,7 @@ + else if( (p->openFlags & SQLITE_OPEN_DELETEONCLOSE) && p->pRbu ){ + rbuUpdateTempSize(p, 0); + } ++ assert( p->pMainNext==0 && p->pRbuVfs->pMain!=p ); + + /* Close the underlying file handle */ + rc = p->pReal->pMethods->xClose(p->pReal); +@@ -178767,6 +191158,9 @@ + }else if( rc==SQLITE_NOTFOUND ){ + pRbu->pTargetFd = p; + p->pRbu = pRbu; ++ if( p->openFlags & SQLITE_OPEN_MAIN_DB ){ ++ rbuMainlistAdd(p); ++ } + if( p->pWalFd ) p->pWalFd->pRbu = pRbu; + rc = SQLITE_OK; + } +@@ -178928,20 +191322,6 @@ + return rc; + } + +-/* +-** Given that zWal points to a buffer containing a wal file name passed to +-** either the xOpen() or xAccess() VFS method, return a pointer to the +-** file-handle opened by the same database connection on the corresponding +-** database file. +-*/ +-static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal){ +- rbu_file *pDb; +- sqlite3_mutex_enter(pRbuVfs->mutex); +- for(pDb=pRbuVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext){} +- sqlite3_mutex_leave(pRbuVfs->mutex); +- return pDb; +-} +- + /* + ** A main database named zName has just been opened. The following + ** function returns a pointer to a buffer owned by SQLite that contains +@@ -179020,7 +191400,7 @@ + pFd->zWal = rbuMainToWal(zName, flags); + } + else if( flags & SQLITE_OPEN_WAL ){ +- rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName); ++ rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName, 0); + if( pDb ){ + if( pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){ + /* This call is to open a *-wal file. Intead, open the *-oal. This +@@ -179072,10 +191452,7 @@ + ** mutex protected linked list of all such files. */ + pFile->pMethods = &rbuvfs_io_methods; + if( flags & SQLITE_OPEN_MAIN_DB ){ +- sqlite3_mutex_enter(pRbuVfs->mutex); +- pFd->pMainNext = pRbuVfs->pMain; +- pRbuVfs->pMain = pFd; +- sqlite3_mutex_leave(pRbuVfs->mutex); ++ rbuMainlistAdd(pFd); + } + }else{ + sqlite3_free(pFd->zDel); +@@ -179123,7 +191500,7 @@ + ** file opened instead. + */ + if( rc==SQLITE_OK && flags==SQLITE_ACCESS_EXISTS ){ +- rbu_file *pDb = rbuFindMaindb(pRbuVfs, zPath); ++ rbu_file *pDb = rbuFindMaindb(pRbuVfs, zPath, 1); + if( pDb && pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){ + if( *pResOut ){ + rc = SQLITE_CANTOPEN; +@@ -179536,8 +191913,6 @@ + static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ + int i; + +- pIdxInfo->estimatedCost = 1.0e6; /* Initial cost estimate */ +- + /* Look for a valid schema=? constraint. If found, change the idxNum to + ** 1 and request the value of that constraint be sent to xFilter. And + ** lower the cost estimate to encourage the constrained version to be +@@ -179544,9 +191919,9 @@ + ** used. + */ + for(i=0; i<pIdxInfo->nConstraint; i++){ +- if( pIdxInfo->aConstraint[i].usable==0 ) continue; ++ if( pIdxInfo->aConstraint[i].iColumn!=10 ) continue; ++ if( pIdxInfo->aConstraint[i].usable==0 ) return SQLITE_CONSTRAINT; + if( pIdxInfo->aConstraint[i].op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; +- if( pIdxInfo->aConstraint[i].iColumn!=10 ) continue; + pIdxInfo->idxNum = 1; + pIdxInfo->estimatedCost = 1.0; + pIdxInfo->aConstraintUsage[i].argvIndex = 1; +@@ -179596,7 +191971,7 @@ + return SQLITE_OK; + } + +-static void statClearPage(StatPage *p){ ++static void statClearCells(StatPage *p){ + int i; + if( p->aCell ){ + for(i=0; i<p->nCell; i++){ +@@ -179604,6 +191979,12 @@ + } + sqlite3_free(p->aCell); + } ++ p->nCell = 0; ++ p->aCell = 0; ++} ++ ++static void statClearPage(StatPage *p){ ++ statClearCells(p); + sqlite3PagerUnref(p->pPg); + sqlite3_free(p->zPath); + memset(p, 0, sizeof(StatPage)); +@@ -179666,22 +192047,33 @@ + u8 *aHdr = &aData[p->iPgno==1 ? 100 : 0]; + + p->flags = aHdr[0]; ++ if( p->flags==0x0A || p->flags==0x0D ){ ++ isLeaf = 1; ++ nHdr = 8; ++ }else if( p->flags==0x05 || p->flags==0x02 ){ ++ isLeaf = 0; ++ nHdr = 12; ++ }else{ ++ goto statPageIsCorrupt; ++ } ++ if( p->iPgno==1 ) nHdr += 100; + p->nCell = get2byte(&aHdr[3]); + p->nMxPayload = 0; ++ szPage = sqlite3BtreeGetPageSize(pBt); + +- isLeaf = (p->flags==0x0A || p->flags==0x0D); +- nHdr = 12 - isLeaf*4 + (p->iPgno==1)*100; +- + nUnused = get2byte(&aHdr[5]) - nHdr - 2*p->nCell; + nUnused += (int)aHdr[7]; + iOff = get2byte(&aHdr[1]); + while( iOff ){ ++ int iNext; ++ if( iOff>=szPage ) goto statPageIsCorrupt; + nUnused += get2byte(&aData[iOff+2]); +- iOff = get2byte(&aData[iOff]); ++ iNext = get2byte(&aData[iOff]); ++ if( iNext<iOff+4 && iNext>0 ) goto statPageIsCorrupt; ++ iOff = iNext; + } + p->nUnused = nUnused; + p->iRightChildPg = isLeaf ? 0 : sqlite3Get4byte(&aHdr[8]); +- szPage = sqlite3BtreeGetPageSize(pBt); + + if( p->nCell ){ + int i; /* Used to iterate through cells */ +@@ -179698,6 +192090,7 @@ + StatCell *pCell = &p->aCell[i]; + + iOff = get2byte(&aData[nHdr+i*2]); ++ if( iOff<nHdr || iOff>=szPage ) goto statPageIsCorrupt; + if( !isLeaf ){ + pCell->iChildPg = sqlite3Get4byte(&aData[iOff]); + iOff += 4; +@@ -179714,13 +192107,14 @@ + } + if( nPayload>(u32)p->nMxPayload ) p->nMxPayload = nPayload; + getLocalPayload(nUsable, p->flags, nPayload, &nLocal); ++ if( nLocal<0 ) goto statPageIsCorrupt; + pCell->nLocal = nLocal; +- assert( nLocal>=0 ); + assert( nPayload>=(u32)nLocal ); + assert( nLocal<=(nUsable-35) ); + if( nPayload>(u32)nLocal ){ + int j; + int nOvfl = ((nPayload - nLocal) + nUsable-4 - 1) / (nUsable - 4); ++ if( iOff+nLocal>nUsable ) goto statPageIsCorrupt; + pCell->nLastOvfl = (nPayload-nLocal) - (nOvfl-1) * (nUsable-4); + pCell->nOvfl = nOvfl; + pCell->aOvfl = sqlite3_malloc64(sizeof(u32)*nOvfl); +@@ -179744,6 +192138,11 @@ + } + + return SQLITE_OK; ++ ++statPageIsCorrupt: ++ p->flags = 0; ++ statClearCells(p); ++ return SQLITE_OK; + } + + /* +@@ -180039,6 +192438,7 @@ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ ++ 0 /* xShadowName */ + }; + return sqlite3_create_module(db, "dbstat", &dbstat_module, 0); + } +@@ -180169,9 +192569,8 @@ + if( p->iColumn!=DBPAGE_COLUMN_SCHEMA ) continue; + if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; + if( !p->usable ){ +- /* No solution. Use the default SQLITE_BIG_DBL cost */ +- pIdxInfo->estimatedRows = 0x7fffffff; +- return SQLITE_OK; ++ /* No solution. */ ++ return SQLITE_CONSTRAINT; + } + iPlan = 2; + pIdxInfo->aConstraintUsage[i].argvIndex = 1; +@@ -180363,6 +192762,10 @@ + Pager *pPager; + int szPage; + ++ if( pTab->db->flags & SQLITE_Defensive ){ ++ zErr = "read-only"; ++ goto update_fail; ++ } + if( argc==1 ){ + zErr = "cannot delete"; + goto update_fail; +@@ -180419,7 +192822,7 @@ + int i; + for(i=0; i<db->nDb; i++){ + Btree *pBt = db->aDb[i].pBt; +- if( pBt ) sqlite3BtreeBeginTrans(pBt, 1); ++ if( pBt ) sqlite3BtreeBeginTrans(pBt, 1, 0); + } + return SQLITE_OK; + } +@@ -180453,6 +192856,7 @@ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ ++ 0 /* xShadowName */ + }; + return sqlite3_create_module(db, "sqlite_dbpage", &dbpage_module, 0); + } +@@ -180489,6 +192893,8 @@ + # endif + #endif + ++static int sessions_strm_chunk_size = SESSIONS_STRM_CHUNK_SIZE; ++ + typedef struct SessionHook SessionHook; + struct SessionHook { + void *pCtx; +@@ -180551,6 +192957,7 @@ + SessionInput in; /* Input buffer or stream */ + SessionBuffer tblhdr; /* Buffer to hold apValue/zTab/abPK/ */ + int bPatchset; /* True if this is a patchset */ ++ int bInvert; /* True to invert changeset */ + int rc; /* Iterator error code */ + sqlite3_stmt *pConflict; /* Points to conflicting row, if any */ + char *zTab; /* Current table */ +@@ -180707,6 +193114,42 @@ + ** The records associated with INSERT changes are in the same format as for + ** changesets. It is not possible for a record associated with an INSERT + ** change to contain a field set to "undefined". ++** ++** REBASE BLOB FORMAT: ++** ++** A rebase blob may be output by sqlite3changeset_apply_v2() and its ++** streaming equivalent for use with the sqlite3_rebaser APIs to rebase ++** existing changesets. A rebase blob contains one entry for each conflict ++** resolved using either the OMIT or REPLACE strategies within the apply_v2() ++** call. ++** ++** The format used for a rebase blob is very similar to that used for ++** changesets. All entries related to a single table are grouped together. ++** ++** Each group of entries begins with a table header in changeset format: ++** ++** 1 byte: Constant 0x54 (capital 'T') ++** Varint: Number of columns in the table. ++** nCol bytes: 0x01 for PK columns, 0x00 otherwise. ++** N bytes: Unqualified table name (encoded using UTF-8). Nul-terminated. ++** ++** Followed by one or more entries associated with the table. ++** ++** 1 byte: Either SQLITE_INSERT (0x12), DELETE (0x09). ++** 1 byte: Flag. 0x01 for REPLACE, 0x00 for OMIT. ++** record: (in the record format defined above). ++** ++** In a rebase blob, the first field is set to SQLITE_INSERT if the change ++** that caused the conflict was an INSERT or UPDATE, or to SQLITE_DELETE if ++** it was a DELETE. The second field is set to 0x01 if the conflict ++** resolution strategy was REPLACE, or 0x00 if it was OMIT. ++** ++** If the change that caused the conflict was a DELETE, then the single ++** record is a copy of the old.* record from the original changeset. If it ++** was an INSERT, then the single record is a copy of the new.* record. If ++** the conflicting change was an UPDATE, then the single record is a copy ++** of the new.* record with the PK fields filled in based on the original ++** old.* record. + */ + + /* +@@ -182257,12 +194700,12 @@ + static int sessionBufferGrow(SessionBuffer *p, int nByte, int *pRc){ + if( *pRc==SQLITE_OK && p->nAlloc-p->nBuf<nByte ){ + u8 *aNew; +- int nNew = p->nAlloc ? p->nAlloc : 128; ++ i64 nNew = p->nAlloc ? p->nAlloc : 128; + do { + nNew = nNew*2; +- }while( nNew<(p->nBuf+nByte) ); ++ }while( (nNew-p->nBuf)<nByte ); + +- aNew = (u8 *)sqlite3_realloc(p->aBuf, nNew); ++ aNew = (u8 *)sqlite3_realloc64(p->aBuf, nNew); + if( 0==aNew ){ + *pRc = SQLITE_NOMEM; + }else{ +@@ -182860,12 +195303,12 @@ + rc = sqlite3_reset(pSel); + } + +- /* If the buffer is now larger than SESSIONS_STRM_CHUNK_SIZE, pass ++ /* If the buffer is now larger than sessions_strm_chunk_size, pass + ** its contents to the xOutput() callback. */ + if( xOutput + && rc==SQLITE_OK + && buf.nBuf>nNoop +- && buf.nBuf>SESSIONS_STRM_CHUNK_SIZE ++ && buf.nBuf>sessions_strm_chunk_size + ){ + rc = xOutput(pOut, (void*)buf.aBuf, buf.nBuf); + nNoop = -1; +@@ -183004,7 +195447,8 @@ + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int nChangeset, /* Size of buffer pChangeset in bytes */ +- void *pChangeset /* Pointer to buffer containing changeset */ ++ void *pChangeset, /* Pointer to buffer containing changeset */ ++ int bInvert /* True to invert changeset */ + ){ + sqlite3_changeset_iter *pRet; /* Iterator to return */ + int nByte; /* Number of bytes to allocate for iterator */ +@@ -183024,6 +195468,7 @@ + pRet->in.xInput = xInput; + pRet->in.pIn = pIn; + pRet->in.bEof = (xInput ? 0 : 1); ++ pRet->bInvert = bInvert; + + /* Populate the output variable and return success. */ + *pp = pRet; +@@ -183038,8 +195483,17 @@ + int nChangeset, /* Size of buffer pChangeset in bytes */ + void *pChangeset /* Pointer to buffer containing changeset */ + ){ +- return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset); ++ return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, 0); + } ++SQLITE_API int sqlite3changeset_start_v2( ++ sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ ++ int nChangeset, /* Size of buffer pChangeset in bytes */ ++ void *pChangeset, /* Pointer to buffer containing changeset */ ++ int flags ++){ ++ int bInvert = !!(flags & SQLITE_CHANGESETSTART_INVERT); ++ return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, bInvert); ++} + + /* + ** Streaming version of sqlite3changeset_start(). +@@ -183049,8 +195503,17 @@ + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn + ){ +- return sessionChangesetStart(pp, xInput, pIn, 0, 0); ++ return sessionChangesetStart(pp, xInput, pIn, 0, 0, 0); + } ++SQLITE_API int sqlite3changeset_start_v2_strm( ++ sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ ++ int (*xInput)(void *pIn, void *pData, int *pnData), ++ void *pIn, ++ int flags ++){ ++ int bInvert = !!(flags & SQLITE_CHANGESETSTART_INVERT); ++ return sessionChangesetStart(pp, xInput, pIn, 0, 0, bInvert); ++} + + /* + ** If the SessionInput object passed as the only argument is a streaming +@@ -183057,7 +195520,7 @@ + ** object and the buffer is full, discard some data to free up space. + */ + static void sessionDiscardData(SessionInput *pIn){ +- if( pIn->xInput && pIn->iNext>=SESSIONS_STRM_CHUNK_SIZE ){ ++ if( pIn->xInput && pIn->iNext>=sessions_strm_chunk_size ){ + int nMove = pIn->buf.nBuf - pIn->iNext; + assert( nMove>=0 ); + if( nMove>0 ){ +@@ -183080,7 +195543,7 @@ + int rc = SQLITE_OK; + if( pIn->xInput ){ + while( !pIn->bEof && (pIn->iNext+nByte)>=pIn->nData && rc==SQLITE_OK ){ +- int nNew = SESSIONS_STRM_CHUNK_SIZE; ++ int nNew = sessions_strm_chunk_size; + + if( pIn->bNoDiscard==0 ) sessionDiscardData(pIn); + if( SQLITE_OK==sessionBufferGrow(&pIn->buf, nNew, &rc) ){ +@@ -183428,10 +195891,10 @@ + op = p->in.aData[p->in.iNext++]; + } + +- if( p->zTab==0 ){ ++ if( p->zTab==0 || (p->bPatchset && p->bInvert) ){ + /* The first record in the changeset is not a table header. Must be a + ** corrupt changeset. */ +- assert( p->in.iNext==1 ); ++ assert( p->in.iNext==1 || p->zTab ); + return (p->rc = SQLITE_CORRUPT_BKPT); + } + +@@ -183456,33 +195919,39 @@ + *paRec = &p->in.aData[p->in.iNext]; + p->in.iNext += *pnRec; + }else{ ++ sqlite3_value **apOld = (p->bInvert ? &p->apValue[p->nCol] : p->apValue); ++ sqlite3_value **apNew = (p->bInvert ? p->apValue : &p->apValue[p->nCol]); + + /* If this is an UPDATE or DELETE, read the old.* record. */ + if( p->op!=SQLITE_INSERT && (p->bPatchset==0 || p->op==SQLITE_DELETE) ){ + u8 *abPK = p->bPatchset ? p->abPK : 0; +- p->rc = sessionReadRecord(&p->in, p->nCol, abPK, p->apValue); ++ p->rc = sessionReadRecord(&p->in, p->nCol, abPK, apOld); + if( p->rc!=SQLITE_OK ) return p->rc; + } + + /* If this is an INSERT or UPDATE, read the new.* record. */ + if( p->op!=SQLITE_DELETE ){ +- p->rc = sessionReadRecord(&p->in, p->nCol, 0, &p->apValue[p->nCol]); ++ p->rc = sessionReadRecord(&p->in, p->nCol, 0, apNew); + if( p->rc!=SQLITE_OK ) return p->rc; + } + +- if( p->bPatchset && p->op==SQLITE_UPDATE ){ ++ if( (p->bPatchset || p->bInvert) && p->op==SQLITE_UPDATE ){ + /* If this is an UPDATE that is part of a patchset, then all PK and + ** modified fields are present in the new.* record. The old.* record + ** is currently completely empty. This block shifts the PK fields from + ** new.* to old.*, to accommodate the code that reads these arrays. */ + for(i=0; i<p->nCol; i++){ +- assert( p->apValue[i]==0 ); ++ assert( p->bPatchset==0 || p->apValue[i]==0 ); + if( p->abPK[i] ){ ++ assert( p->apValue[i]==0 ); + p->apValue[i] = p->apValue[i+p->nCol]; + if( p->apValue[i]==0 ) return (p->rc = SQLITE_CORRUPT_BKPT); + p->apValue[i+p->nCol] = 0; + } + } ++ }else if( p->bInvert ){ ++ if( p->op==SQLITE_INSERT ) p->op = SQLITE_DELETE; ++ else if( p->op==SQLITE_DELETE ) p->op = SQLITE_INSERT; + } + } + +@@ -183799,7 +196268,7 @@ + } + + assert( rc==SQLITE_OK ); +- if( xOutput && sOut.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){ ++ if( xOutput && sOut.nBuf>=sessions_strm_chunk_size ){ + rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); + sOut.nBuf = 0; + if( rc!=SQLITE_OK ) goto finished_invert; +@@ -183878,7 +196347,8 @@ + int bDeferConstraints; /* True to defer constraints */ + SessionBuffer constraints; /* Deferred constraints are stored here */ + SessionBuffer rebase; /* Rebase information (if any) here */ +- int bRebaseStarted; /* If table header is already in rebase */ ++ u8 bRebaseStarted; /* If table header is already in rebase */ ++ u8 bRebase; /* True to collect rebase information */ + }; + + /* +@@ -184275,35 +196745,36 @@ + sqlite3_changeset_iter *pIter /* Iterator pointing at current change */ + ){ + int rc = SQLITE_OK; +- int i; +- int eOp = pIter->op; +- if( p->bRebaseStarted==0 ){ +- /* Append a table-header to the rebase buffer */ +- const char *zTab = pIter->zTab; +- sessionAppendByte(&p->rebase, 'T', &rc); +- sessionAppendVarint(&p->rebase, p->nCol, &rc); +- sessionAppendBlob(&p->rebase, p->abPK, p->nCol, &rc); +- sessionAppendBlob(&p->rebase, (u8*)zTab, (int)strlen(zTab)+1, &rc); +- p->bRebaseStarted = 1; +- } ++ if( p->bRebase ){ ++ int i; ++ int eOp = pIter->op; ++ if( p->bRebaseStarted==0 ){ ++ /* Append a table-header to the rebase buffer */ ++ const char *zTab = pIter->zTab; ++ sessionAppendByte(&p->rebase, 'T', &rc); ++ sessionAppendVarint(&p->rebase, p->nCol, &rc); ++ sessionAppendBlob(&p->rebase, p->abPK, p->nCol, &rc); ++ sessionAppendBlob(&p->rebase, (u8*)zTab, (int)strlen(zTab)+1, &rc); ++ p->bRebaseStarted = 1; ++ } + +- assert( eType==SQLITE_CHANGESET_REPLACE||eType==SQLITE_CHANGESET_OMIT ); +- assert( eOp==SQLITE_DELETE || eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE ); ++ assert( eType==SQLITE_CHANGESET_REPLACE||eType==SQLITE_CHANGESET_OMIT ); ++ assert( eOp==SQLITE_DELETE || eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE ); + +- sessionAppendByte(&p->rebase, +- (eOp==SQLITE_DELETE ? SQLITE_DELETE : SQLITE_INSERT), &rc +- ); +- sessionAppendByte(&p->rebase, (eType==SQLITE_CHANGESET_REPLACE), &rc); +- for(i=0; i<p->nCol; i++){ +- sqlite3_value *pVal = 0; +- if( eOp==SQLITE_DELETE || (eOp==SQLITE_UPDATE && p->abPK[i]) ){ +- sqlite3changeset_old(pIter, i, &pVal); +- }else{ +- sqlite3changeset_new(pIter, i, &pVal); ++ sessionAppendByte(&p->rebase, ++ (eOp==SQLITE_DELETE ? SQLITE_DELETE : SQLITE_INSERT), &rc ++ ); ++ sessionAppendByte(&p->rebase, (eType==SQLITE_CHANGESET_REPLACE), &rc); ++ for(i=0; i<p->nCol; i++){ ++ sqlite3_value *pVal = 0; ++ if( eOp==SQLITE_DELETE || (eOp==SQLITE_UPDATE && p->abPK[i]) ){ ++ sqlite3changeset_old(pIter, i, &pVal); ++ }else{ ++ sqlite3changeset_new(pIter, i, &pVal); ++ } ++ sessionAppendValue(&p->rebase, pVal, &rc); + } +- sessionAppendValue(&p->rebase, pVal, &rc); + } +- + return rc; + } + +@@ -184646,7 +197117,7 @@ + SessionBuffer cons = pApply->constraints; + memset(&pApply->constraints, 0, sizeof(SessionBuffer)); + +- rc = sessionChangesetStart(&pIter2, 0, 0, cons.nBuf, cons.aBuf); ++ rc = sessionChangesetStart(&pIter2, 0, 0, cons.nBuf, cons.aBuf, 0); + if( rc==SQLITE_OK ){ + int nByte = 2*pApply->nCol*sizeof(sqlite3_value*); + int rc2; +@@ -184712,6 +197183,7 @@ + + pIter->in.bNoDiscard = 1; + memset(&sApply, 0, sizeof(sApply)); ++ sApply.bRebase = (ppRebase && pnRebase); + sqlite3_mutex_enter(sqlite3_db_mutex(db)); + if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){ + rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0); +@@ -184862,7 +197334,8 @@ + } + } + +- if( rc==SQLITE_OK && bPatchset==0 && ppRebase && pnRebase ){ ++ assert( sApply.bRebase || sApply.rebase.nBuf==0 ); ++ if( rc==SQLITE_OK && bPatchset==0 && sApply.bRebase ){ + *ppRebase = (void*)sApply.rebase.aBuf; + *pnRebase = sApply.rebase.nBuf; + sApply.rebase.aBuf = 0; +@@ -184900,7 +197373,8 @@ + int flags + ){ + sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ +- int rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset); ++ int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT); ++ int rc = sessionChangesetStart(&pIter, 0, 0, nChangeset, pChangeset,bInverse); + if( rc==SQLITE_OK ){ + rc = sessionChangesetApply( + db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags +@@ -184957,7 +197431,8 @@ + int flags + ){ + sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ +- int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); ++ int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT); ++ int rc = sessionChangesetStart(&pIter, xInput, pIn, 0, 0, bInverse); + if( rc==SQLITE_OK ){ + rc = sessionChangesetApply( + db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags +@@ -185330,13 +197805,12 @@ + sessionAppendByte(&buf, p->op, &rc); + sessionAppendByte(&buf, p->bIndirect, &rc); + sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); ++ if( rc==SQLITE_OK && xOutput && buf.nBuf>=sessions_strm_chunk_size ){ ++ rc = xOutput(pOut, buf.aBuf, buf.nBuf); ++ buf.nBuf = 0; ++ } + } + } +- +- if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){ +- rc = xOutput(pOut, buf.aBuf, buf.nBuf); +- buf.nBuf = 0; +- } + } + + if( rc==SQLITE_OK ){ +@@ -185727,7 +198201,7 @@ + sessionAppendByte(&sOut, pIter->bIndirect, &rc); + sessionAppendBlob(&sOut, aRec, nRec, &rc); + } +- if( rc==SQLITE_OK && xOutput && sOut.nBuf>SESSIONS_STRM_CHUNK_SIZE ){ ++ if( rc==SQLITE_OK && xOutput && sOut.nBuf>sessions_strm_chunk_size ){ + rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); + sOut.nBuf = 0; + } +@@ -185838,2439 +198312,30 @@ + } + } + +-#endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */ +- +-/************** End of sqlite3session.c **************************************/ +-/************** Begin file json1.c *******************************************/ +-/* +-** 2015-08-12 +-** +-** 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 JSON functions. The interface is +-** modeled after MySQL JSON functions: +-** +-** https://dev.mysql.com/doc/refman/5.7/en/json.html +-** +-** For the time being, all JSON is stored as pure text. (We might add +-** a JSONB type in the future which stores a binary encoding of JSON in +-** a BLOB, but there is no support for JSONB in the current implementation. +-** This implementation parses JSON text at 250 MB/s, so it is hard to see +-** how JSONB might improve on that.) ++/* ++** Global configuration + */ +-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1) +-#if !defined(SQLITEINT_H) +-/* #include "sqlite3ext.h" */ +-#endif +-SQLITE_EXTENSION_INIT1 +-/* #include <assert.h> */ +-/* #include <string.h> */ +-/* #include <stdlib.h> */ +-/* #include <stdarg.h> */ +- +-/* Mark a function parameter as unused, to suppress nuisance compiler +-** warnings. */ +-#ifndef UNUSED_PARAM +-# define UNUSED_PARAM(X) (void)(X) +-#endif +- +-#ifndef LARGEST_INT64 +-# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32)) +-# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64) +-#endif +- +-/* +-** Versions of isspace(), isalnum() and isdigit() to which it is safe +-** to pass signed char values. +-*/ +-#ifdef sqlite3Isdigit +- /* Use the SQLite core versions if this routine is part of the +- ** SQLite amalgamation */ +-# define safe_isdigit(x) sqlite3Isdigit(x) +-# define safe_isalnum(x) sqlite3Isalnum(x) +-# define safe_isxdigit(x) sqlite3Isxdigit(x) +-#else +- /* Use the standard library for separate compilation */ +-#include <ctype.h> /* amalgamator: keep */ +-# define safe_isdigit(x) isdigit((unsigned char)(x)) +-# define safe_isalnum(x) isalnum((unsigned char)(x)) +-# define safe_isxdigit(x) isxdigit((unsigned char)(x)) +-#endif +- +-/* +-** Growing our own isspace() routine this way is twice as fast as +-** the library isspace() function, resulting in a 7% overall performance +-** increase for the parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os). +-*/ +-static const char jsonIsSpace[] = { +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +-}; +-#define safe_isspace(x) (jsonIsSpace[(unsigned char)x]) +- +-#ifndef SQLITE_AMALGAMATION +- /* Unsigned integer types. These are already defined in the sqliteInt.h, +- ** but the definitions need to be repeated for separate compilation. */ +- typedef sqlite3_uint64 u64; +- typedef unsigned int u32; +- typedef unsigned short int u16; +- typedef unsigned char u8; +-#endif +- +-/* Objects */ +-typedef struct JsonString JsonString; +-typedef struct JsonNode JsonNode; +-typedef struct JsonParse JsonParse; +- +-/* An instance of this object represents a JSON string +-** under construction. Really, this is a generic string accumulator +-** that can be and is used to create strings other than JSON. +-*/ +-struct JsonString { +- sqlite3_context *pCtx; /* Function context - put error messages here */ +- char *zBuf; /* Append JSON content here */ +- u64 nAlloc; /* Bytes of storage available in zBuf[] */ +- u64 nUsed; /* Bytes of zBuf[] currently used */ +- u8 bStatic; /* True if zBuf is static space */ +- u8 bErr; /* True if an error has been encountered */ +- char zSpace[100]; /* Initial static space */ +-}; +- +-/* JSON type values +-*/ +-#define JSON_NULL 0 +-#define JSON_TRUE 1 +-#define JSON_FALSE 2 +-#define JSON_INT 3 +-#define JSON_REAL 4 +-#define JSON_STRING 5 +-#define JSON_ARRAY 6 +-#define JSON_OBJECT 7 +- +-/* The "subtype" set for JSON values */ +-#define JSON_SUBTYPE 74 /* Ascii for "J" */ +- +-/* +-** Names of the various JSON types: +-*/ +-static const char * const jsonType[] = { +- "null", "true", "false", "integer", "real", "text", "array", "object" +-}; +- +-/* Bit values for the JsonNode.jnFlag field +-*/ +-#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 */ +- u32 n; /* Bytes of content, or number of sub-nodes */ +- union { +- const char *zJContent; /* Content for INT, REAL, and STRING */ +- u32 iAppend; /* More terms for ARRAY and OBJECT */ +- u32 iKey; /* Key for ARRAY objects in json_tree() */ +- u32 iReplace; /* Replacement content for JNODE_REPLACE */ +- JsonNode *pPatch; /* Node chain of patch for JNODE_PATCH */ +- } u; +-}; +- +-/* A completely parsed JSON string +-*/ +-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 */ +-}; +- +-/* +-** Maximum nesting depth of JSON for this implementation. +-** +-** This limit is needed to avoid a stack overflow in the recursive +-** descent parser. A depth of 2000 is far deeper than any sane JSON +-** should go. +-*/ +-#define JSON_MAX_DEPTH 2000 +- +-/************************************************************************** +-** Utility routines for dealing with JsonString objects +-**************************************************************************/ +- +-/* Set the JsonString object to an empty string +-*/ +-static void jsonZero(JsonString *p){ +- p->zBuf = p->zSpace; +- p->nAlloc = sizeof(p->zSpace); +- p->nUsed = 0; +- p->bStatic = 1; +-} +- +-/* Initialize the JsonString object +-*/ +-static void jsonInit(JsonString *p, sqlite3_context *pCtx){ +- p->pCtx = pCtx; +- p->bErr = 0; +- jsonZero(p); +-} +- +- +-/* Free all allocated memory and reset the JsonString object back to its +-** initial state. +-*/ +-static void jsonReset(JsonString *p){ +- if( !p->bStatic ) sqlite3_free(p->zBuf); +- jsonZero(p); +-} +- +- +-/* Report an out-of-memory (OOM) condition +-*/ +-static void jsonOom(JsonString *p){ +- p->bErr = 1; +- sqlite3_result_error_nomem(p->pCtx); +- jsonReset(p); +-} +- +-/* Enlarge pJson->zBuf so that it can hold at least N more bytes. +-** Return zero on success. Return non-zero on an OOM error +-*/ +-static int jsonGrow(JsonString *p, u32 N){ +- u64 nTotal = N<p->nAlloc ? p->nAlloc*2 : p->nAlloc+N+10; +- char *zNew; +- if( p->bStatic ){ +- if( p->bErr ) return 1; +- zNew = sqlite3_malloc64(nTotal); +- if( zNew==0 ){ +- jsonOom(p); +- return SQLITE_NOMEM; +- } +- memcpy(zNew, p->zBuf, (size_t)p->nUsed); +- p->zBuf = zNew; +- p->bStatic = 0; +- }else{ +- zNew = sqlite3_realloc64(p->zBuf, nTotal); +- if( zNew==0 ){ +- jsonOom(p); +- return SQLITE_NOMEM; +- } +- p->zBuf = zNew; +- } +- p->nAlloc = nTotal; +- return SQLITE_OK; +-} +- +-/* Append N bytes from zIn onto the end of the JsonString string. +-*/ +-static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){ +- if( (N+p->nUsed >= p->nAlloc) && jsonGrow(p,N)!=0 ) return; +- memcpy(p->zBuf+p->nUsed, zIn, N); +- p->nUsed += N; +-} +- +-/* Append formatted text (not to exceed N bytes) to the JsonString. +-*/ +-static void jsonPrintf(int N, JsonString *p, const char *zFormat, ...){ +- va_list ap; +- if( (p->nUsed + N >= p->nAlloc) && jsonGrow(p, N) ) return; +- va_start(ap, zFormat); +- sqlite3_vsnprintf(N, p->zBuf+p->nUsed, zFormat, ap); +- va_end(ap); +- p->nUsed += (int)strlen(p->zBuf+p->nUsed); +-} +- +-/* Append a single character +-*/ +-static void jsonAppendChar(JsonString *p, char c){ +- if( p->nUsed>=p->nAlloc && jsonGrow(p,1)!=0 ) return; +- p->zBuf[p->nUsed++] = c; +-} +- +-/* Append a comma separator to the output buffer, if the previous +-** character is not '[' or '{'. +-*/ +-static void jsonAppendSeparator(JsonString *p){ +- char c; +- if( p->nUsed==0 ) return; +- c = p->zBuf[p->nUsed-1]; +- if( c!='[' && c!='{' ) jsonAppendChar(p, ','); +-} +- +-/* Append the N-byte string in zIn to the end of the JsonString string +-** under construction. Enclose the string in "..." and escape +-** any double-quotes or backslash characters contained within the +-** string. +-*/ +-static void jsonAppendString(JsonString *p, const char *zIn, u32 N){ +- u32 i; +- if( (N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0 ) return; +- p->zBuf[p->nUsed++] = '"'; +- for(i=0; i<N; i++){ +- unsigned char c = ((unsigned const char*)zIn)[i]; +- if( c=='"' || c=='\\' ){ +- json_simple_escape: +- if( (p->nUsed+N+3-i > p->nAlloc) && jsonGrow(p,N+3-i)!=0 ) return; +- p->zBuf[p->nUsed++] = '\\'; +- }else if( c<=0x1f ){ +- static const char aSpecial[] = { +- 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +- }; +- assert( sizeof(aSpecial)==32 ); +- assert( aSpecial['\b']=='b' ); +- assert( aSpecial['\f']=='f' ); +- assert( aSpecial['\n']=='n' ); +- assert( aSpecial['\r']=='r' ); +- assert( aSpecial['\t']=='t' ); +- if( aSpecial[c] ){ +- c = aSpecial[c]; +- goto json_simple_escape; ++SQLITE_API int sqlite3session_config(int op, void *pArg){ ++ int rc = SQLITE_OK; ++ switch( op ){ ++ case SQLITE_SESSION_CONFIG_STRMSIZE: { ++ int *pInt = (int*)pArg; ++ if( *pInt>0 ){ ++ sessions_strm_chunk_size = *pInt; + } +- if( (p->nUsed+N+7+i > p->nAlloc) && jsonGrow(p,N+7-i)!=0 ) return; +- p->zBuf[p->nUsed++] = '\\'; +- p->zBuf[p->nUsed++] = 'u'; +- p->zBuf[p->nUsed++] = '0'; +- p->zBuf[p->nUsed++] = '0'; +- p->zBuf[p->nUsed++] = '0' + (c>>4); +- 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); ++ *pInt = sessions_strm_chunk_size; + 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); ++ default: ++ rc = SQLITE_MISUSE; + break; +- } +- case SQLITE_TEXT: { +- const char *z = (const char*)sqlite3_value_text(pValue); +- u32 n = (u32)sqlite3_value_bytes(pValue); +- if( sqlite3_value_subtype(pValue)==JSON_SUBTYPE ){ +- jsonAppendRaw(p, z, n); +- }else{ +- jsonAppendString(p, z, n); +- } +- break; +- } +- default: { +- if( p->bErr==0 ){ +- sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1); +- p->bErr = 2; +- jsonReset(p); +- } +- break; +- } + } +-} +- +- +-/* Make the JSON in p the result of the SQL function. +-*/ +-static void jsonResult(JsonString *p){ +- if( p->bErr==0 ){ +- sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed, +- p->bStatic ? SQLITE_TRANSIENT : sqlite3_free, +- SQLITE_UTF8); +- jsonZero(p); +- } +- assert( p->bStatic ); +-} +- +-/************************************************************************** +-** Utility routines for dealing with JsonNode and JsonParse objects +-**************************************************************************/ +- +-/* +-** Return the number of consecutive JsonNode slots need to represent +-** the parsed JSON at pNode. The minimum answer is 1. For ARRAY and +-** OBJECT types, the number might be larger. +-** +-** Appended elements are not counted. The value returned is the number +-** by which the JsonNode counter should increment in order to go to the +-** next peer value. +-*/ +-static u32 jsonNodeSize(JsonNode *pNode){ +- return pNode->eType>=JSON_ARRAY ? pNode->n+1 : 1; +-} +- +-/* +-** Reclaim all memory allocated by a JsonParse object. But do not +-** delete the JsonParse object itself. +-*/ +-static void jsonParseReset(JsonParse *pParse){ +- sqlite3_free(pParse->aNode); +- pParse->aNode = 0; +- pParse->nNode = 0; +- pParse->nAlloc = 0; +- sqlite3_free(pParse->aUp); +- pParse->aUp = 0; +-} +- +-/* +-** Free a JsonParse object that was obtained from sqlite3_malloc(). +-*/ +-static void jsonParseFree(JsonParse *pParse){ +- jsonParseReset(pParse); +- sqlite3_free(pParse); +-} +- +-/* +-** Convert the JsonNode pNode into a pure JSON string and +-** append to pOut. Subsubstructure is also included. Return +-** the number of JsonNode objects that are encoded. +-*/ +-static void jsonRenderNode( +- JsonNode *pNode, /* The node to render */ +- JsonString *pOut, /* Write JSON here */ +- sqlite3_value **aReplace /* Replacement values */ +-){ +- if( pNode->jnFlags & (JNODE_REPLACE|JNODE_PATCH) ){ +- if( pNode->jnFlags & JNODE_REPLACE ){ +- jsonAppendValue(pOut, aReplace[pNode->u.iReplace]); +- return; +- } +- pNode = pNode->u.pPatch; +- } +- switch( pNode->eType ){ +- default: { +- assert( pNode->eType==JSON_NULL ); +- jsonAppendRaw(pOut, "null", 4); +- break; +- } +- case JSON_TRUE: { +- jsonAppendRaw(pOut, "true", 4); +- break; +- } +- case JSON_FALSE: { +- jsonAppendRaw(pOut, "false", 5); +- break; +- } +- case JSON_STRING: { +- if( pNode->jnFlags & JNODE_RAW ){ +- jsonAppendString(pOut, pNode->u.zJContent, pNode->n); +- break; +- } +- /* Fall through into the next case */ +- } +- case JSON_REAL: +- case JSON_INT: { +- jsonAppendRaw(pOut, pNode->u.zJContent, pNode->n); +- break; +- } +- case JSON_ARRAY: { +- u32 j = 1; +- jsonAppendChar(pOut, '['); +- for(;;){ +- while( j<=pNode->n ){ +- if( (pNode[j].jnFlags & JNODE_REMOVE)==0 ){ +- jsonAppendSeparator(pOut); +- jsonRenderNode(&pNode[j], pOut, aReplace); +- } +- j += jsonNodeSize(&pNode[j]); +- } +- if( (pNode->jnFlags & JNODE_APPEND)==0 ) break; +- pNode = &pNode[pNode->u.iAppend]; +- j = 1; +- } +- jsonAppendChar(pOut, ']'); +- break; +- } +- case JSON_OBJECT: { +- u32 j = 1; +- jsonAppendChar(pOut, '{'); +- for(;;){ +- while( j<=pNode->n ){ +- if( (pNode[j+1].jnFlags & JNODE_REMOVE)==0 ){ +- jsonAppendSeparator(pOut); +- jsonRenderNode(&pNode[j], pOut, aReplace); +- jsonAppendChar(pOut, ':'); +- jsonRenderNode(&pNode[j+1], pOut, aReplace); +- } +- j += 1 + jsonNodeSize(&pNode[j+1]); +- } +- if( (pNode->jnFlags & JNODE_APPEND)==0 ) break; +- pNode = &pNode[pNode->u.iAppend]; +- j = 1; +- } +- jsonAppendChar(pOut, '}'); +- break; +- } +- } +-} +- +-/* +-** Return a JsonNode and all its descendents as a JSON string. +-*/ +-static void jsonReturnJson( +- JsonNode *pNode, /* Node to return */ +- sqlite3_context *pCtx, /* Return value for this function */ +- sqlite3_value **aReplace /* Array of replacement values */ +-){ +- JsonString s; +- jsonInit(&s, pCtx); +- jsonRenderNode(pNode, &s, aReplace); +- jsonResult(&s); +- sqlite3_result_subtype(pCtx, JSON_SUBTYPE); +-} +- +-/* +-** Make the JsonNode the return value of the function. +-*/ +-static void jsonReturn( +- JsonNode *pNode, /* Node to return */ +- sqlite3_context *pCtx, /* Return value for this function */ +- sqlite3_value **aReplace /* Array of replacement values */ +-){ +- switch( pNode->eType ){ +- default: { +- assert( pNode->eType==JSON_NULL ); +- sqlite3_result_null(pCtx); +- break; +- } +- case JSON_TRUE: { +- sqlite3_result_int(pCtx, 1); +- break; +- } +- case JSON_FALSE: { +- sqlite3_result_int(pCtx, 0); +- break; +- } +- case JSON_INT: { +- sqlite3_int64 i = 0; +- const char *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: /* fall through to real */; +- } +- case JSON_REAL: { +- double r; +-#ifdef SQLITE_AMALGAMATION +- const char *z = pNode->u.zJContent; +- sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8); +-#else +- 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 ){ +- 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 */ +- 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 = pNode->u.zJContent; +- char *zOut; +- u32 j; +- 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 = 0, k; +- for(k=0; k<4; i++, k++){ +- assert( i<n-2 ); +- c = z[i+1]; +- assert( safe_isxdigit(c) ); +- if( c<='9' ) v = v*16 + c - '0'; +- else if( c<='F' ) v = v*16 + c - 'A' + 10; +- else v = v*16 + c - 'a' + 10; +- } +- if( v==0 ) break; +- if( v<=0x7f ){ +- zOut[j++] = (char)v; +- }else if( v<=0x7ff ){ +- zOut[j++] = (char)(0xc0 | (v>>6)); +- zOut[j++] = 0x80 | (v&0x3f); +- }else{ +- zOut[j++] = (char)(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: { +- jsonReturnJson(pNode, pCtx, aReplace); +- break; +- } +- } +-} +- +-/* Forward reference */ +-static int jsonParseAddNode(JsonParse*,u32,u32,const char*); +- +-/* +-** A macro to hint to the compiler that a function should not be +-** inlined. +-*/ +-#if defined(__GNUC__) +-# define JSON_NOINLINE __attribute__((noinline)) +-#elif defined(_MSC_VER) && _MSC_VER>=1310 +-# define JSON_NOINLINE __declspec(noinline) +-#else +-# define JSON_NOINLINE +-#endif +- +- +-static JSON_NOINLINE int jsonParseAddNodeExpand( +- JsonParse *pParse, /* Append the node to this object */ +- u32 eType, /* Node type */ +- u32 n, /* Content size or sub-node count */ +- const char *zContent /* Content */ +-){ +- u32 nNew; +- JsonNode *pNew; +- assert( pParse->nNode>=pParse->nAlloc ); +- if( pParse->oom ) return -1; +- nNew = pParse->nAlloc*2 + 10; +- pNew = sqlite3_realloc(pParse->aNode, sizeof(JsonNode)*nNew); +- if( pNew==0 ){ +- pParse->oom = 1; +- return -1; +- } +- pParse->nAlloc = nNew; +- pParse->aNode = pNew; +- assert( pParse->nNode<pParse->nAlloc ); +- return jsonParseAddNode(pParse, eType, n, zContent); +-} +- +-/* +-** Create a new JsonNode instance based on the arguments and append that +-** instance to the JsonParse. Return the index in pParse->aNode[] of the +-** new node, or -1 if a memory allocation fails. +-*/ +-static int jsonParseAddNode( +- JsonParse *pParse, /* Append the node to this object */ +- u32 eType, /* Node type */ +- u32 n, /* Content size or sub-node count */ +- const char *zContent /* Content */ +-){ +- JsonNode *p; +- if( pParse->nNode>=pParse->nAlloc ){ +- return jsonParseAddNodeExpand(pParse, eType, n, zContent); +- } +- p = &pParse->aNode[pParse->nNode]; +- p->eType = (u8)eType; +- p->jnFlags = 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( !safe_isxdigit(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( safe_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( safe_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( safe_isspace(z[j]) ){ j++; } +- if( z[j]!=':' ) return -1; +- j++; +- x = jsonParseValue(pParse, j); +- pParse->iDepth--; +- if( x<0 ) return -1; +- j = x; +- while( safe_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; +- for(j=i+1;;j++){ +- while( safe_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( safe_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 +- && !safe_isalnum(z[i+4]) ){ +- jsonParseAddNode(pParse, JSON_NULL, 0, 0); +- return i+4; +- }else if( c=='t' +- && strncmp(z+i,"true",4)==0 +- && !safe_isalnum(z[i+4]) ){ +- jsonParseAddNode(pParse, JSON_TRUE, 0, 0); +- return i+4; +- }else if( c=='f' +- && strncmp(z+i,"false",5)==0 +- && !safe_isalnum(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. +-** +-** pParse is uninitialized when this routine is called. +-*/ +-static int jsonParse( +- JsonParse *pParse, /* Initialize and fill this JsonParse object */ +- sqlite3_context *pCtx, /* Report errors here */ +- const char *zJson /* Input JSON text to be parsed */ +-){ +- int i; +- memset(pParse, 0, sizeof(*pParse)); +- 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( safe_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); +- } +- } +- jsonParseReset(pParse); +- return 1; +- } +- return 0; +-} +- +-/* Mark node i of pParse as being a child of iParent. Call recursively +-** to fill in all the descendants of node i. +-*/ +-static void jsonParseFillInParentage(JsonParse *pParse, u32 i, u32 iParent){ +- JsonNode *pNode = &pParse->aNode[i]; +- u32 j; +- pParse->aUp[i] = iParent; +- switch( pNode->eType ){ +- case JSON_ARRAY: { +- for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j)){ +- jsonParseFillInParentage(pParse, i+j, i); +- } +- break; +- } +- case JSON_OBJECT: { +- for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j+1)+1){ +- pParse->aUp[i+j] = i; +- jsonParseFillInParentage(pParse, i+j+1, i); +- } +- break; +- } +- default: { +- break; +- } +- } +-} +- +-/* +-** Compute the parentage of all nodes in a completed parse. +-*/ +-static int jsonParseFindParents(JsonParse *pParse){ +- u32 *aUp; +- assert( pParse->aUp==0 ); +- aUp = pParse->aUp = sqlite3_malloc( sizeof(u32)*pParse->nNode ); +- if( aUp==0 ){ +- pParse->oom = 1; +- return SQLITE_NOMEM; +- } +- jsonParseFillInParentage(pParse, 0, 0); +- return SQLITE_OK; +-} +- +-/* +-** Magic number used for the JSON parse cache in sqlite3_get_auxdata() +-*/ +-#define JSON_CACHE_ID (-429938) +- +-/* +-** 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 +-){ +- const char *zJson = (const char*)sqlite3_value_text(argv[0]); +- int nJson = sqlite3_value_bytes(argv[0]); +- JsonParse *p; +- if( zJson==0 ) return 0; +- p = (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID); +- if( p && p->nJson==nJson && memcmp(p->zJson,zJson,nJson)==0 ){ +- p->nErr = 0; +- return p; /* The cached entry matches, so return it */ +- } +- p = sqlite3_malloc( sizeof(*p) + nJson + 1 ); +- if( p==0 ){ +- 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, pCtx, p->zJson) ){ +- sqlite3_free(p); +- return 0; +- } +- p->nJson = nJson; +- sqlite3_set_auxdata(pCtx, JSON_CACHE_ID, p, (void(*)(void*))jsonParseFree); +- return (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID); +-} +- +-/* +-** Compare the OBJECT label at pNode against zKey,nKey. Return true on +-** a match. +-*/ +-static int jsonLabelCompare(JsonNode *pNode, const char *zKey, u32 nKey){ +- 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 +-** node. +-** +-** If pApnd!=0, then try to append new nodes to complete zPath if it is +-** possible to do so and if no existing node corresponds to zPath. If +-** new nodes are appended *pApnd is set to 1. +-*/ +-static JsonNode *jsonLookupStep( +- JsonParse *pParse, /* The JSON to search */ +- u32 iRoot, /* Begin the search at this node */ +- const char *zPath, /* The path to search */ +- int *pApnd, /* Append nodes to complete path if not NULL */ +- const char **pzErr /* Make *pzErr point to any syntax error in zPath */ +-){ +- u32 i, j, nKey; +- const char *zKey; +- JsonNode *pRoot = &pParse->aNode[iRoot]; +- if( zPath[0]==0 ) return pRoot; +- if( zPath[0]=='.' ){ +- if( pRoot->eType!=JSON_OBJECT ) return 0; +- zPath++; +- if( zPath[0]=='"' ){ +- zKey = zPath + 1; +- for(i=1; zPath[i] && zPath[i]!='"'; i++){} +- nKey = i-1; +- if( zPath[i] ){ +- i++; +- }else{ +- *pzErr = zPath; +- return 0; +- } +- }else{ +- zKey = zPath; +- for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){} +- nKey = i; +- } +- if( nKey==0 ){ +- *pzErr = zPath; +- return 0; +- } +- j = 1; +- for(;;){ +- while( j<=pRoot->n ){ +- if( jsonLabelCompare(pRoot+j, zKey, nKey) ){ +- return jsonLookupStep(pParse, iRoot+j+1, &zPath[i], pApnd, pzErr); +- } +- j++; +- j += jsonNodeSize(&pRoot[j]); +- } +- if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break; +- iRoot += pRoot->u.iAppend; +- pRoot = &pParse->aNode[iRoot]; +- j = 1; +- } +- if( pApnd ){ +- u32 iStart, iLabel; +- JsonNode *pNode; +- iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0); +- iLabel = jsonParseAddNode(pParse, JSON_STRING, i, zPath); +- zPath += i; +- pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr); +- if( pParse->oom ) return 0; +- if( pNode ){ +- pRoot = &pParse->aNode[iRoot]; +- pRoot->u.iAppend = iStart - iRoot; +- pRoot->jnFlags |= JNODE_APPEND; +- pParse->aNode[iLabel].jnFlags |= JNODE_RAW; +- } +- return pNode; +- } +- }else if( zPath[0]=='[' && safe_isdigit(zPath[1]) ){ +- if( pRoot->eType!=JSON_ARRAY ) return 0; +- i = 0; +- j = 1; +- while( safe_isdigit(zPath[j]) ){ +- i = i*10 + zPath[j] - '0'; +- j++; +- } +- if( zPath[j]!=']' ){ +- *pzErr = zPath; +- return 0; +- } +- zPath += j + 1; +- j = 1; +- for(;;){ +- while( j<=pRoot->n && (i>0 || (pRoot[j].jnFlags & JNODE_REMOVE)!=0) ){ +- if( (pRoot[j].jnFlags & JNODE_REMOVE)==0 ) i--; +- j += jsonNodeSize(&pRoot[j]); +- } +- if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break; +- iRoot += pRoot->u.iAppend; +- pRoot = &pParse->aNode[iRoot]; +- j = 1; +- } +- if( j<=pRoot->n ){ +- return jsonLookupStep(pParse, iRoot+j, zPath, pApnd, pzErr); +- } +- if( i==0 && pApnd ){ +- u32 iStart; +- JsonNode *pNode; +- iStart = jsonParseAddNode(pParse, JSON_ARRAY, 1, 0); +- pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr); +- if( pParse->oom ) return 0; +- if( pNode ){ +- pRoot = &pParse->aNode[iRoot]; +- pRoot->u.iAppend = iStart - iRoot; +- pRoot->jnFlags |= JNODE_APPEND; +- } +- return pNode; +- } +- }else{ +- *pzErr = zPath; +- } +- return 0; +-} +- +-/* +-** Append content to pParse that will complete zPath. Return a pointer +-** to the inserted node, or return NULL if the append fails. +-*/ +-static JsonNode *jsonLookupAppend( +- JsonParse *pParse, /* Append content to the JSON parse */ +- const char *zPath, /* Description of content to append */ +- int *pApnd, /* Set this flag to 1 */ +- const char **pzErr /* Make this point to any syntax error */ +-){ +- *pApnd = 1; +- if( zPath[0]==0 ){ +- jsonParseAddNode(pParse, JSON_NULL, 0, 0); +- return pParse->oom ? 0 : &pParse->aNode[pParse->nNode-1]; +- } +- if( zPath[0]=='.' ){ +- jsonParseAddNode(pParse, JSON_OBJECT, 0, 0); +- }else if( strncmp(zPath,"[0]",3)==0 ){ +- jsonParseAddNode(pParse, JSON_ARRAY, 0, 0); +- }else{ +- return 0; +- } +- if( pParse->oom ) return 0; +- return jsonLookupStep(pParse, pParse->nNode-1, zPath, pApnd, pzErr); +-} +- +-/* +-** Return the text of a syntax error message on a JSON path. Space is +-** obtained from sqlite3_malloc(). +-*/ +-static char *jsonPathSyntaxError(const char *zErr){ +- return sqlite3_mprintf("JSON path error near '%q'", zErr); +-} +- +-/* +-** Do a node lookup using zPath. Return a pointer to the node on success. +-** Return NULL if not found or if there is an error. +-** +-** On an error, write an error message into pCtx and increment the +-** pParse->nErr counter. +-** +-** If pApnd!=NULL then try to append missing nodes and set *pApnd = 1 if +-** nodes are appended. +-*/ +-static JsonNode *jsonLookup( +- JsonParse *pParse, /* The JSON to search */ +- const char *zPath, /* The path to search */ +- int *pApnd, /* Append nodes to complete path if not NULL */ +- sqlite3_context *pCtx /* Report errors here, if not NULL */ +-){ +- const char *zErr = 0; +- JsonNode *pNode = 0; +- char *zMsg; +- +- if( zPath==0 ) return 0; +- if( zPath[0]!='$' ){ +- zErr = zPath; +- goto lookup_err; +- } +- zPath++; +- pNode = jsonLookupStep(pParse, 0, zPath, pApnd, &zErr); +- if( zErr==0 ) return pNode; +- +-lookup_err: +- pParse->nErr++; +- assert( zErr!=0 && pCtx!=0 ); +- zMsg = jsonPathSyntaxError(zErr); +- if( zMsg ){ +- sqlite3_result_error(pCtx, zMsg, -1); +- sqlite3_free(zMsg); +- }else{ +- sqlite3_result_error_nomem(pCtx); +- } +- return 0; +-} +- +- +-/* +-** Report the wrong number of arguments for json_insert(), json_replace() +-** or json_set(). +-*/ +-static void jsonWrongNumArgs( +- sqlite3_context *pCtx, +- const char *zFuncName +-){ +- char *zMsg = sqlite3_mprintf("json_%s() needs an odd number of arguments", +- zFuncName); +- sqlite3_result_error(pCtx, zMsg, -1); +- sqlite3_free(zMsg); +-} +- +-/* +-** Mark all NULL entries in the Object passed in as JNODE_REMOVE. +-*/ +-static void jsonRemoveAllNulls(JsonNode *pNode){ +- int i, n; +- assert( pNode->eType==JSON_OBJECT ); +- n = pNode->n; +- for(i=2; i<=n; i += jsonNodeSize(&pNode[i])+1){ +- switch( pNode[i].eType ){ +- case JSON_NULL: +- pNode[i].jnFlags |= JNODE_REMOVE; +- break; +- case JSON_OBJECT: +- jsonRemoveAllNulls(&pNode[i]); +- break; +- } +- } +-} +- +- +-/**************************************************************************** +-** SQL functions used for testing and debugging +-****************************************************************************/ +- +-#ifdef SQLITE_DEBUG +-/* +-** The json_parse(JSON) function returns a string which describes +-** a parse of the JSON provided. Or it returns NULL if JSON is not +-** well-formed. +-*/ +-static void jsonParseFunc( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- JsonString s; /* Output string - not real JSON */ +- JsonParse x; /* The parse */ +- u32 i; +- +- assert( argc==1 ); +- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; +- jsonParseFindParents(&x); +- jsonInit(&s, ctx); +- for(i=0; i<x.nNode; i++){ +- const char *zType; +- if( x.aNode[i].jnFlags & JNODE_LABEL ){ +- assert( x.aNode[i].eType==JSON_STRING ); +- zType = "label"; +- }else{ +- zType = jsonType[x.aNode[i].eType]; +- } +- jsonPrintf(100, &s,"node %3u: %7s n=%-4d up=%-4d", +- i, zType, x.aNode[i].n, x.aUp[i]); +- if( x.aNode[i].u.zJContent!=0 ){ +- jsonAppendRaw(&s, " ", 1); +- jsonAppendRaw(&s, x.aNode[i].u.zJContent, x.aNode[i].n); +- } +- jsonAppendRaw(&s, "\n", 1); +- } +- jsonParseReset(&x); +- jsonResult(&s); +-} +- +-/* +-** The json_test1(JSON) function return true (1) if the input is JSON +-** text generated by another json function. It returns (0) if the input +-** is not known to be JSON. +-*/ +-static void jsonTest1Func( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- UNUSED_PARAM(argc); +- sqlite3_result_int(ctx, sqlite3_value_subtype(argv[0])==JSON_SUBTYPE); +-} +-#endif /* SQLITE_DEBUG */ +- +-/**************************************************************************** +-** Scalar SQL function implementations +-****************************************************************************/ +- +-/* +-** Implementation of the json_QUOTE(VALUE) function. Return a JSON value +-** corresponding to the SQL value input. Mostly this means putting +-** double-quotes around strings and returning the unquoted string "null" +-** when given a NULL input. +-*/ +-static void jsonQuoteFunc( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- JsonString jx; +- UNUSED_PARAM(argc); +- +- jsonInit(&jx, ctx); +- jsonAppendValue(&jx, argv[0]); +- jsonResult(&jx); +- sqlite3_result_subtype(ctx, JSON_SUBTYPE); +-} +- +-/* +-** Implementation of the json_array(VALUE,...) function. Return a JSON +-** array that contains all values given in arguments. Or if any argument +-** is a BLOB, throw an error. +-*/ +-static void jsonArrayFunc( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- int i; +- JsonString jx; +- +- jsonInit(&jx, ctx); +- jsonAppendChar(&jx, '['); +- for(i=0; i<argc; i++){ +- jsonAppendSeparator(&jx); +- jsonAppendValue(&jx, argv[i]); +- } +- jsonAppendChar(&jx, ']'); +- jsonResult(&jx); +- sqlite3_result_subtype(ctx, JSON_SUBTYPE); +-} +- +- +-/* +-** json_array_length(JSON) +-** json_array_length(JSON, PATH) +-** +-** Return the number of elements in the top-level JSON array. +-** Return 0 if the input is not a well-formed JSON array. +-*/ +-static void jsonArrayLengthFunc( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- JsonParse *p; /* The parse */ +- sqlite3_int64 n = 0; +- u32 i; +- JsonNode *pNode; +- +- p = jsonParseCached(ctx, argv); +- if( p==0 ) return; +- assert( p->nNode ); +- if( argc==2 ){ +- const char *zPath = (const char*)sqlite3_value_text(argv[1]); +- pNode = jsonLookup(p, zPath, 0, ctx); +- }else{ +- pNode = p->aNode; +- } +- if( pNode==0 ){ +- return; +- } +- if( pNode->eType==JSON_ARRAY ){ +- assert( (pNode->jnFlags & JNODE_APPEND)==0 ); +- for(i=1; i<=pNode->n; n++){ +- i += jsonNodeSize(&pNode[i]); +- } +- } +- sqlite3_result_int64(ctx, n); +-} +- +-/* +-** json_extract(JSON, PATH, ...) +-** +-** Return the element described by PATH. Return NULL if there is no +-** PATH element. If there are multiple PATHs, then return a JSON array +-** with the result from each path. Throw an error if the JSON or any PATH +-** is malformed. +-*/ +-static void jsonExtractFunc( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- JsonParse *p; /* The parse */ +- JsonNode *pNode; +- const char *zPath; +- JsonString jx; +- int i; +- +- if( argc<2 ) return; +- p = jsonParseCached(ctx, argv); +- if( p==0 ) return; +- jsonInit(&jx, ctx); +- jsonAppendChar(&jx, '['); +- for(i=1; i<argc; i++){ +- zPath = (const char*)sqlite3_value_text(argv[i]); +- pNode = jsonLookup(p, zPath, 0, ctx); +- if( p->nErr ) break; +- if( argc>2 ){ +- jsonAppendSeparator(&jx); +- if( pNode ){ +- jsonRenderNode(pNode, &jx, 0); +- }else{ +- jsonAppendRaw(&jx, "null", 4); +- } +- }else if( pNode ){ +- jsonReturn(pNode, ctx, 0); +- } +- } +- if( argc>2 && i==argc ){ +- jsonAppendChar(&jx, ']'); +- jsonResult(&jx); +- sqlite3_result_subtype(ctx, JSON_SUBTYPE); +- } +- jsonReset(&jx); +-} +- +-/* This is the RFC 7396 MergePatch algorithm. +-*/ +-static JsonNode *jsonMergePatch( +- JsonParse *pParse, /* The JSON parser that contains the TARGET */ +- u32 iTarget, /* Node of the TARGET in pParse */ +- JsonNode *pPatch /* The PATCH */ +-){ +- u32 i, j; +- u32 iRoot; +- JsonNode *pTarget; +- if( pPatch->eType!=JSON_OBJECT ){ +- return pPatch; +- } +- assert( iTarget>=0 && iTarget<pParse->nNode ); +- pTarget = &pParse->aNode[iTarget]; +- assert( (pPatch->jnFlags & JNODE_APPEND)==0 ); +- if( pTarget->eType!=JSON_OBJECT ){ +- jsonRemoveAllNulls(pPatch); +- return pPatch; +- } +- iRoot = iTarget; +- for(i=1; i<pPatch->n; i += jsonNodeSize(&pPatch[i+1])+1){ +- u32 nKey; +- const char *zKey; +- assert( pPatch[i].eType==JSON_STRING ); +- assert( pPatch[i].jnFlags & JNODE_LABEL ); +- 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]; +- if( pNew!=&pTarget[j+1] ){ +- pTarget[j+1].u.pPatch = pNew; +- pTarget[j+1].jnFlags |= JNODE_PATCH; +- } +- } +- break; +- } +- } +- if( j>=pTarget->n && pPatch[i+1].eType!=JSON_NULL ){ +- int iStart, iPatch; +- iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0); +- jsonParseAddNode(pParse, JSON_STRING, nKey, zKey); +- iPatch = jsonParseAddNode(pParse, JSON_TRUE, 0, 0); +- if( pParse->oom ) return 0; +- jsonRemoveAllNulls(pPatch); +- pTarget = &pParse->aNode[iTarget]; +- pParse->aNode[iRoot].jnFlags |= JNODE_APPEND; +- pParse->aNode[iRoot].u.iAppend = iStart - iRoot; +- iRoot = iStart; +- pParse->aNode[iPatch].jnFlags |= JNODE_PATCH; +- pParse->aNode[iPatch].u.pPatch = &pPatch[i+1]; +- } +- } +- return pTarget; +-} +- +-/* +-** Implementation of the json_mergepatch(JSON1,JSON2) function. Return a JSON +-** object that is the result of running the RFC 7396 MergePatch() algorithm +-** on the two arguments. +-*/ +-static void jsonPatchFunc( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- JsonParse x; /* The JSON that is being patched */ +- JsonParse y; /* The patch */ +- JsonNode *pResult; /* The result of the merge */ +- +- UNUSED_PARAM(argc); +- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; +- if( jsonParse(&y, ctx, (const char*)sqlite3_value_text(argv[1])) ){ +- jsonParseReset(&x); +- return; +- } +- pResult = jsonMergePatch(&x, 0, y.aNode); +- assert( pResult!=0 || x.oom ); +- if( pResult ){ +- jsonReturnJson(pResult, ctx, 0); +- }else{ +- sqlite3_result_error_nomem(ctx); +- } +- jsonParseReset(&x); +- jsonParseReset(&y); +-} +- +- +-/* +-** Implementation of the json_object(NAME,VALUE,...) function. Return a JSON +-** object that contains all name/value given in arguments. Or if any name +-** is not a string or if any value is a BLOB, throw an error. +-*/ +-static void jsonObjectFunc( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- int i; +- JsonString jx; +- const char *z; +- u32 n; +- +- if( argc&1 ){ +- sqlite3_result_error(ctx, "json_object() requires an even number " +- "of arguments", -1); +- return; +- } +- jsonInit(&jx, ctx); +- jsonAppendChar(&jx, '{'); +- for(i=0; i<argc; i+=2){ +- if( sqlite3_value_type(argv[i])!=SQLITE_TEXT ){ +- sqlite3_result_error(ctx, "json_object() labels must be TEXT", -1); +- jsonReset(&jx); +- return; +- } +- jsonAppendSeparator(&jx); +- z = (const char*)sqlite3_value_text(argv[i]); +- n = (u32)sqlite3_value_bytes(argv[i]); +- jsonAppendString(&jx, z, n); +- jsonAppendChar(&jx, ':'); +- jsonAppendValue(&jx, argv[i+1]); +- } +- jsonAppendChar(&jx, '}'); +- jsonResult(&jx); +- sqlite3_result_subtype(ctx, JSON_SUBTYPE); +-} +- +- +-/* +-** json_remove(JSON, PATH, ...) +-** +-** Remove the named elements from JSON and return the result. malformed +-** JSON or PATH arguments result in an error. +-*/ +-static void jsonRemoveFunc( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- JsonParse x; /* The parse */ +- JsonNode *pNode; +- const char *zPath; +- u32 i; +- +- if( argc<1 ) return; +- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; +- assert( x.nNode ); +- for(i=1; i<(u32)argc; i++){ +- zPath = (const char*)sqlite3_value_text(argv[i]); +- if( zPath==0 ) goto remove_done; +- pNode = jsonLookup(&x, zPath, 0, ctx); +- if( x.nErr ) goto remove_done; +- if( pNode ) pNode->jnFlags |= JNODE_REMOVE; +- } +- if( (x.aNode[0].jnFlags & JNODE_REMOVE)==0 ){ +- jsonReturnJson(x.aNode, ctx, 0); +- } +-remove_done: +- jsonParseReset(&x); +-} +- +-/* +-** json_replace(JSON, PATH, VALUE, ...) +-** +-** Replace the value at PATH with VALUE. If PATH does not already exist, +-** this routine is a no-op. If JSON or PATH is malformed, throw an error. +-*/ +-static void jsonReplaceFunc( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- JsonParse x; /* The parse */ +- JsonNode *pNode; +- const char *zPath; +- u32 i; +- +- if( argc<1 ) return; +- if( (argc&1)==0 ) { +- jsonWrongNumArgs(ctx, "replace"); +- return; +- } +- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; +- assert( x.nNode ); +- for(i=1; i<(u32)argc; i+=2){ +- zPath = (const char*)sqlite3_value_text(argv[i]); +- pNode = jsonLookup(&x, zPath, 0, ctx); +- if( x.nErr ) goto replace_err; +- if( pNode ){ +- pNode->jnFlags |= (u8)JNODE_REPLACE; +- pNode->u.iReplace = i + 1; +- } +- } +- if( x.aNode[0].jnFlags & JNODE_REPLACE ){ +- sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]); +- }else{ +- jsonReturnJson(x.aNode, ctx, argv); +- } +-replace_err: +- jsonParseReset(&x); +-} +- +-/* +-** json_set(JSON, PATH, VALUE, ...) +-** +-** Set the value at PATH to VALUE. Create the PATH if it does not already +-** exist. Overwrite existing values that do exist. +-** If JSON or PATH is malformed, throw an error. +-** +-** json_insert(JSON, PATH, VALUE, ...) +-** +-** Create PATH and initialize it to VALUE. If PATH already exists, this +-** routine is a no-op. If JSON or PATH is malformed, throw an error. +-*/ +-static void jsonSetFunc( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- JsonParse x; /* The parse */ +- JsonNode *pNode; +- const char *zPath; +- u32 i; +- int bApnd; +- int bIsSet = *(int*)sqlite3_user_data(ctx); +- +- if( argc<1 ) return; +- if( (argc&1)==0 ) { +- jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert"); +- return; +- } +- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; +- assert( x.nNode ); +- for(i=1; i<(u32)argc; i+=2){ +- zPath = (const char*)sqlite3_value_text(argv[i]); +- bApnd = 0; +- pNode = jsonLookup(&x, zPath, &bApnd, ctx); +- if( x.oom ){ +- sqlite3_result_error_nomem(ctx); +- goto jsonSetDone; +- }else if( x.nErr ){ +- goto jsonSetDone; +- }else if( pNode && (bApnd || bIsSet) ){ +- pNode->jnFlags |= (u8)JNODE_REPLACE; +- pNode->u.iReplace = i + 1; +- } +- } +- if( x.aNode[0].jnFlags & JNODE_REPLACE ){ +- sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]); +- }else{ +- jsonReturnJson(x.aNode, ctx, argv); +- } +-jsonSetDone: +- jsonParseReset(&x); +-} +- +-/* +-** json_type(JSON) +-** json_type(JSON, PATH) +-** +-** Return the top-level "type" of a JSON string. Throw an error if +-** either the JSON or PATH inputs are not well-formed. +-*/ +-static void jsonTypeFunc( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- JsonParse x; /* The parse */ +- const char *zPath; +- JsonNode *pNode; +- +- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; +- assert( x.nNode ); +- if( argc==2 ){ +- zPath = (const char*)sqlite3_value_text(argv[1]); +- pNode = jsonLookup(&x, zPath, 0, ctx); +- }else{ +- pNode = x.aNode; +- } +- if( pNode ){ +- sqlite3_result_text(ctx, jsonType[pNode->eType], -1, SQLITE_STATIC); +- } +- jsonParseReset(&x); +-} +- +-/* +-** 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 x; /* The parse */ +- int rc = 0; +- +- UNUSED_PARAM(argc); +- if( jsonParse(&x, 0, (const char*)sqlite3_value_text(argv[0]))==0 ){ +- rc = 1; +- } +- jsonParseReset(&x); +- sqlite3_result_int(ctx, rc); +-} +- +- +-/**************************************************************************** +-** Aggregate SQL function implementations +-****************************************************************************/ +-/* +-** json_group_array(VALUE) +-** +-** Return a JSON array composed of all values in the aggregate. +-*/ +-static void jsonArrayStep( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- JsonString *pStr; +- UNUSED_PARAM(argc); +- pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); +- if( pStr ){ +- if( pStr->zBuf==0 ){ +- jsonInit(pStr, ctx); +- jsonAppendChar(pStr, '['); +- }else{ +- jsonAppendChar(pStr, ','); +- pStr->pCtx = ctx; +- } +- jsonAppendValue(pStr, argv[0]); +- } +-} +-static void jsonArrayFinal(sqlite3_context *ctx){ +- JsonString *pStr; +- pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); +- if( pStr ){ +- pStr->pCtx = ctx; +- jsonAppendChar(pStr, ']'); +- if( pStr->bErr ){ +- if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); +- assert( pStr->bStatic ); +- }else{ +- sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed, +- pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); +- pStr->bStatic = 1; +- } +- }else{ +- sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC); +- } +- sqlite3_result_subtype(ctx, JSON_SUBTYPE); +-} +- +-/* +-** json_group_obj(NAME,VALUE) +-** +-** Return a JSON object composed of all names and values in the aggregate. +-*/ +-static void jsonObjectStep( +- sqlite3_context *ctx, +- int argc, +- sqlite3_value **argv +-){ +- JsonString *pStr; +- const char *z; +- u32 n; +- UNUSED_PARAM(argc); +- pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); +- if( pStr ){ +- if( pStr->zBuf==0 ){ +- jsonInit(pStr, ctx); +- jsonAppendChar(pStr, '{'); +- }else{ +- jsonAppendChar(pStr, ','); +- pStr->pCtx = ctx; +- } +- z = (const char*)sqlite3_value_text(argv[0]); +- n = (u32)sqlite3_value_bytes(argv[0]); +- jsonAppendString(pStr, z, n); +- jsonAppendChar(pStr, ':'); +- jsonAppendValue(pStr, argv[1]); +- } +-} +-static void jsonObjectFinal(sqlite3_context *ctx){ +- JsonString *pStr; +- pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); +- if( pStr ){ +- jsonAppendChar(pStr, '}'); +- if( pStr->bErr ){ +- if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); +- assert( pStr->bStatic ); +- }else{ +- sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed, +- pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); +- pStr->bStatic = 1; +- } +- }else{ +- sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC); +- } +- sqlite3_result_subtype(ctx, JSON_SUBTYPE); +-} +- +- +-#ifndef SQLITE_OMIT_VIRTUALTABLE +-/**************************************************************************** +-** The json_each virtual table +-****************************************************************************/ +-typedef struct JsonEachCursor JsonEachCursor; +-struct JsonEachCursor { +- sqlite3_vtab_cursor base; /* Base class - must be first */ +- u32 iRowid; /* The rowid */ +- u32 iBegin; /* The first node of the scan */ +- u32 i; /* Index in sParse.aNode[] of current row */ +- u32 iEnd; /* EOF when i equals or exceeds this value */ +- u8 eType; /* Type of top-level element */ +- u8 bRecursive; /* True for json_tree(). False for json_each() */ +- char *zJson; /* Input JSON */ +- char *zRoot; /* Path by which to filter zJson */ +- JsonParse sParse; /* Parse of the input JSON */ +-}; +- +-/* Constructor for the json_each virtual table */ +-static int jsonEachConnect( +- sqlite3 *db, +- void *pAux, +- int argc, const char *const*argv, +- sqlite3_vtab **ppVtab, +- char **pzErr +-){ +- sqlite3_vtab *pNew; +- int rc; +- +-/* Column numbers */ +-#define JEACH_KEY 0 +-#define JEACH_VALUE 1 +-#define JEACH_TYPE 2 +-#define JEACH_ATOM 3 +-#define JEACH_ID 4 +-#define JEACH_PARENT 5 +-#define JEACH_FULLKEY 6 +-#define JEACH_PATH 7 +-#define JEACH_JSON 8 +-#define JEACH_ROOT 9 +- +- UNUSED_PARAM(pzErr); +- UNUSED_PARAM(argv); +- UNUSED_PARAM(argc); +- UNUSED_PARAM(pAux); +- rc = sqlite3_declare_vtab(db, +- "CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path," +- "json HIDDEN,root HIDDEN)"); +- if( rc==SQLITE_OK ){ +- pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) ); +- if( pNew==0 ) return SQLITE_NOMEM; +- memset(pNew, 0, sizeof(*pNew)); +- } + return rc; + } + +-/* destructor for json_each virtual table */ +-static int jsonEachDisconnect(sqlite3_vtab *pVtab){ +- sqlite3_free(pVtab); +- return SQLITE_OK; +-} ++#endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */ + +-/* constructor for a JsonEachCursor object for json_each(). */ +-static int jsonEachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ +- JsonEachCursor *pCur; +- +- UNUSED_PARAM(p); +- pCur = sqlite3_malloc( sizeof(*pCur) ); +- if( pCur==0 ) return SQLITE_NOMEM; +- memset(pCur, 0, sizeof(*pCur)); +- *ppCursor = &pCur->base; +- return SQLITE_OK; +-} +- +-/* constructor for a JsonEachCursor object for json_tree(). */ +-static int jsonEachOpenTree(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ +- int rc = jsonEachOpenEach(p, ppCursor); +- if( rc==SQLITE_OK ){ +- JsonEachCursor *pCur = (JsonEachCursor*)*ppCursor; +- pCur->bRecursive = 1; +- } +- return rc; +-} +- +-/* Reset a JsonEachCursor back to its original state. Free any memory +-** held. */ +-static void jsonEachCursorReset(JsonEachCursor *p){ +- sqlite3_free(p->zJson); +- sqlite3_free(p->zRoot); +- jsonParseReset(&p->sParse); +- p->iRowid = 0; +- p->i = 0; +- p->iEnd = 0; +- p->eType = 0; +- p->zJson = 0; +- p->zRoot = 0; +-} +- +-/* Destructor for a jsonEachCursor object */ +-static int jsonEachClose(sqlite3_vtab_cursor *cur){ +- JsonEachCursor *p = (JsonEachCursor*)cur; +- jsonEachCursorReset(p); +- sqlite3_free(cur); +- return SQLITE_OK; +-} +- +-/* Return TRUE if the jsonEachCursor object has been advanced off the end +-** of the JSON object */ +-static int jsonEachEof(sqlite3_vtab_cursor *cur){ +- JsonEachCursor *p = (JsonEachCursor*)cur; +- return p->i >= p->iEnd; +-} +- +-/* Advance the cursor to the next element for json_tree() */ +-static int jsonEachNext(sqlite3_vtab_cursor *cur){ +- JsonEachCursor *p = (JsonEachCursor*)cur; +- if( p->bRecursive ){ +- if( p->sParse.aNode[p->i].jnFlags & JNODE_LABEL ) p->i++; +- p->i++; +- p->iRowid++; +- if( p->i<p->iEnd ){ +- u32 iUp = p->sParse.aUp[p->i]; +- JsonNode *pUp = &p->sParse.aNode[iUp]; +- p->eType = pUp->eType; +- if( pUp->eType==JSON_ARRAY ){ +- if( iUp==p->i-1 ){ +- pUp->u.iKey = 0; +- }else{ +- pUp->u.iKey++; +- } +- } +- } +- }else{ +- switch( p->eType ){ +- case JSON_ARRAY: { +- p->i += jsonNodeSize(&p->sParse.aNode[p->i]); +- p->iRowid++; +- break; +- } +- case JSON_OBJECT: { +- p->i += 1 + jsonNodeSize(&p->sParse.aNode[p->i+1]); +- p->iRowid++; +- break; +- } +- default: { +- p->i = p->iEnd; +- break; +- } +- } +- } +- return SQLITE_OK; +-} +- +-/* Append the name of the path for element i to pStr +-*/ +-static void jsonEachComputePath( +- JsonEachCursor *p, /* The cursor */ +- JsonString *pStr, /* Write the path here */ +- u32 i /* Path to this element */ +-){ +- JsonNode *pNode, *pUp; +- u32 iUp; +- if( i==0 ){ +- jsonAppendChar(pStr, '$'); +- return; +- } +- iUp = p->sParse.aUp[i]; +- jsonEachComputePath(p, pStr, iUp); +- pNode = &p->sParse.aNode[i]; +- pUp = &p->sParse.aNode[iUp]; +- if( pUp->eType==JSON_ARRAY ){ +- jsonPrintf(30, pStr, "[%d]", pUp->u.iKey); +- }else{ +- assert( pUp->eType==JSON_OBJECT ); +- if( (pNode->jnFlags & JNODE_LABEL)==0 ) pNode--; +- assert( pNode->eType==JSON_STRING ); +- assert( pNode->jnFlags & JNODE_LABEL ); +- jsonPrintf(pNode->n+1, pStr, ".%.*s", pNode->n-2, pNode->u.zJContent+1); +- } +-} +- +-/* Return the value of a column */ +-static int jsonEachColumn( +- sqlite3_vtab_cursor *cur, /* The cursor */ +- sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ +- int i /* Which column to return */ +-){ +- JsonEachCursor *p = (JsonEachCursor*)cur; +- JsonNode *pThis = &p->sParse.aNode[p->i]; +- switch( i ){ +- case JEACH_KEY: { +- if( p->i==0 ) break; +- if( p->eType==JSON_OBJECT ){ +- jsonReturn(pThis, ctx, 0); +- }else if( p->eType==JSON_ARRAY ){ +- u32 iKey; +- if( p->bRecursive ){ +- if( p->iRowid==0 ) break; +- iKey = p->sParse.aNode[p->sParse.aUp[p->i]].u.iKey; +- }else{ +- iKey = p->iRowid; +- } +- sqlite3_result_int64(ctx, (sqlite3_int64)iKey); +- } +- break; +- } +- case JEACH_VALUE: { +- if( pThis->jnFlags & JNODE_LABEL ) pThis++; +- jsonReturn(pThis, ctx, 0); +- break; +- } +- case JEACH_TYPE: { +- if( pThis->jnFlags & JNODE_LABEL ) pThis++; +- sqlite3_result_text(ctx, jsonType[pThis->eType], -1, SQLITE_STATIC); +- break; +- } +- case JEACH_ATOM: { +- if( pThis->jnFlags & JNODE_LABEL ) pThis++; +- if( pThis->eType>=JSON_ARRAY ) break; +- jsonReturn(pThis, ctx, 0); +- break; +- } +- case JEACH_ID: { +- sqlite3_result_int64(ctx, +- (sqlite3_int64)p->i + ((pThis->jnFlags & JNODE_LABEL)!=0)); +- break; +- } +- case JEACH_PARENT: { +- if( p->i>p->iBegin && p->bRecursive ){ +- sqlite3_result_int64(ctx, (sqlite3_int64)p->sParse.aUp[p->i]); +- } +- break; +- } +- case JEACH_FULLKEY: { +- JsonString x; +- jsonInit(&x, ctx); +- if( p->bRecursive ){ +- jsonEachComputePath(p, &x, p->i); +- }else{ +- if( p->zRoot ){ +- jsonAppendRaw(&x, p->zRoot, (int)strlen(p->zRoot)); +- }else{ +- jsonAppendChar(&x, '$'); +- } +- if( p->eType==JSON_ARRAY ){ +- jsonPrintf(30, &x, "[%d]", p->iRowid); +- }else{ +- jsonPrintf(pThis->n, &x, ".%.*s", pThis->n-2, pThis->u.zJContent+1); +- } +- } +- jsonResult(&x); +- break; +- } +- case JEACH_PATH: { +- if( p->bRecursive ){ +- JsonString x; +- jsonInit(&x, ctx); +- jsonEachComputePath(p, &x, p->sParse.aUp[p->i]); +- jsonResult(&x); +- break; +- } +- /* For json_each() path and root are the same so fall through +- ** into the root case */ +- } +- default: { +- const char *zRoot = p->zRoot; +- if( zRoot==0 ) zRoot = "$"; +- sqlite3_result_text(ctx, zRoot, -1, SQLITE_STATIC); +- break; +- } +- case JEACH_JSON: { +- assert( i==JEACH_JSON ); +- sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_STATIC); +- break; +- } +- } +- return SQLITE_OK; +-} +- +-/* Return the current rowid value */ +-static int jsonEachRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ +- JsonEachCursor *p = (JsonEachCursor*)cur; +- *pRowid = p->iRowid; +- return SQLITE_OK; +-} +- +-/* The query strategy is to look for an equality constraint on the json +-** column. Without such a constraint, the table cannot operate. idxNum is +-** 1 if the constraint is found, 3 if the constraint and zRoot are found, +-** and 0 otherwise. +-*/ +-static int jsonEachBestIndex( +- sqlite3_vtab *tab, +- sqlite3_index_info *pIdxInfo +-){ +- int i; +- int jsonIdx = -1; +- int rootIdx = -1; +- const struct sqlite3_index_constraint *pConstraint; +- +- UNUSED_PARAM(tab); +- pConstraint = pIdxInfo->aConstraint; +- for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ +- if( pConstraint->usable==0 ) continue; +- if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; +- switch( pConstraint->iColumn ){ +- case JEACH_JSON: jsonIdx = i; break; +- case JEACH_ROOT: rootIdx = i; break; +- default: /* no-op */ break; +- } +- } +- if( jsonIdx<0 ){ +- pIdxInfo->idxNum = 0; +- pIdxInfo->estimatedCost = 1e99; +- }else{ +- pIdxInfo->estimatedCost = 1.0; +- pIdxInfo->aConstraintUsage[jsonIdx].argvIndex = 1; +- pIdxInfo->aConstraintUsage[jsonIdx].omit = 1; +- if( rootIdx<0 ){ +- pIdxInfo->idxNum = 1; +- }else{ +- pIdxInfo->aConstraintUsage[rootIdx].argvIndex = 2; +- pIdxInfo->aConstraintUsage[rootIdx].omit = 1; +- pIdxInfo->idxNum = 3; +- } +- } +- return SQLITE_OK; +-} +- +-/* Start a search on a new JSON string */ +-static int jsonEachFilter( +- sqlite3_vtab_cursor *cur, +- int idxNum, const char *idxStr, +- int argc, sqlite3_value **argv +-){ +- JsonEachCursor *p = (JsonEachCursor*)cur; +- const char *z; +- const char *zRoot = 0; +- sqlite3_int64 n; +- +- UNUSED_PARAM(idxStr); +- UNUSED_PARAM(argc); +- jsonEachCursorReset(p); +- if( idxNum==0 ) return SQLITE_OK; +- z = (const char*)sqlite3_value_text(argv[0]); +- if( z==0 ) return SQLITE_OK; +- n = sqlite3_value_bytes(argv[0]); +- p->zJson = sqlite3_malloc64( n+1 ); +- if( p->zJson==0 ) return SQLITE_NOMEM; +- memcpy(p->zJson, z, (size_t)n+1); +- if( jsonParse(&p->sParse, 0, p->zJson) ){ +- int rc = SQLITE_NOMEM; +- if( p->sParse.oom==0 ){ +- sqlite3_free(cur->pVtab->zErrMsg); +- cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON"); +- if( cur->pVtab->zErrMsg ) rc = SQLITE_ERROR; +- } +- jsonEachCursorReset(p); +- return rc; +- }else if( p->bRecursive && jsonParseFindParents(&p->sParse) ){ +- jsonEachCursorReset(p); +- return SQLITE_NOMEM; +- }else{ +- JsonNode *pNode = 0; +- if( idxNum==3 ){ +- const char *zErr = 0; +- zRoot = (const char*)sqlite3_value_text(argv[1]); +- if( zRoot==0 ) return SQLITE_OK; +- n = sqlite3_value_bytes(argv[1]); +- p->zRoot = sqlite3_malloc64( n+1 ); +- if( p->zRoot==0 ) return SQLITE_NOMEM; +- memcpy(p->zRoot, zRoot, (size_t)n+1); +- if( zRoot[0]!='$' ){ +- zErr = zRoot; +- }else{ +- pNode = jsonLookupStep(&p->sParse, 0, p->zRoot+1, 0, &zErr); +- } +- if( zErr ){ +- sqlite3_free(cur->pVtab->zErrMsg); +- cur->pVtab->zErrMsg = jsonPathSyntaxError(zErr); +- jsonEachCursorReset(p); +- return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; +- }else if( pNode==0 ){ +- return SQLITE_OK; +- } +- }else{ +- pNode = p->sParse.aNode; +- } +- p->iBegin = p->i = (int)(pNode - p->sParse.aNode); +- p->eType = pNode->eType; +- if( p->eType>=JSON_ARRAY ){ +- pNode->u.iKey = 0; +- p->iEnd = p->i + pNode->n + 1; +- if( p->bRecursive ){ +- p->eType = p->sParse.aNode[p->sParse.aUp[p->i]].eType; +- if( p->i>0 && (p->sParse.aNode[p->i-1].jnFlags & JNODE_LABEL)!=0 ){ +- p->i--; +- } +- }else{ +- p->i++; +- } +- }else{ +- p->iEnd = p->i+1; +- } +- } +- return SQLITE_OK; +-} +- +-/* The methods of the json_each virtual table */ +-static sqlite3_module jsonEachModule = { +- 0, /* iVersion */ +- 0, /* xCreate */ +- jsonEachConnect, /* xConnect */ +- jsonEachBestIndex, /* xBestIndex */ +- jsonEachDisconnect, /* xDisconnect */ +- 0, /* xDestroy */ +- jsonEachOpenEach, /* xOpen - open a cursor */ +- jsonEachClose, /* xClose - close a cursor */ +- jsonEachFilter, /* xFilter - configure scan constraints */ +- jsonEachNext, /* xNext - advance a cursor */ +- jsonEachEof, /* xEof - check for end of scan */ +- jsonEachColumn, /* xColumn - read data */ +- jsonEachRowid, /* xRowid - read data */ +- 0, /* xUpdate */ +- 0, /* xBegin */ +- 0, /* xSync */ +- 0, /* xCommit */ +- 0, /* xRollback */ +- 0, /* xFindMethod */ +- 0, /* xRename */ +- 0, /* xSavepoint */ +- 0, /* xRelease */ +- 0 /* xRollbackTo */ +-}; +- +-/* The methods of the json_tree virtual table. */ +-static sqlite3_module jsonTreeModule = { +- 0, /* iVersion */ +- 0, /* xCreate */ +- jsonEachConnect, /* xConnect */ +- jsonEachBestIndex, /* xBestIndex */ +- jsonEachDisconnect, /* xDisconnect */ +- 0, /* xDestroy */ +- jsonEachOpenTree, /* xOpen - open a cursor */ +- jsonEachClose, /* xClose - close a cursor */ +- jsonEachFilter, /* xFilter - configure scan constraints */ +- jsonEachNext, /* xNext - advance a cursor */ +- jsonEachEof, /* xEof - check for end of scan */ +- jsonEachColumn, /* xColumn - read data */ +- jsonEachRowid, /* xRowid - read data */ +- 0, /* xUpdate */ +- 0, /* xBegin */ +- 0, /* xSync */ +- 0, /* xCommit */ +- 0, /* xRollback */ +- 0, /* xFindMethod */ +- 0, /* xRename */ +- 0, /* xSavepoint */ +- 0, /* xRelease */ +- 0 /* xRollbackTo */ +-}; +-#endif /* SQLITE_OMIT_VIRTUALTABLE */ +- +-/**************************************************************************** +-** The following routines are the only publically visible identifiers in this +-** file. Call the following routines in order to register the various SQL +-** functions and the virtual table implemented by this file. +-****************************************************************************/ +- +-SQLITE_PRIVATE int sqlite3Json1Init(sqlite3 *db){ +- int rc = SQLITE_OK; +- unsigned int i; +- static const struct { +- const char *zName; +- int nArg; +- int flag; +- void (*xFunc)(sqlite3_context*,int,sqlite3_value**); +- } aFunc[] = { +- { "json", 1, 0, jsonRemoveFunc }, +- { "json_array", -1, 0, jsonArrayFunc }, +- { "json_array_length", 1, 0, jsonArrayLengthFunc }, +- { "json_array_length", 2, 0, jsonArrayLengthFunc }, +- { "json_extract", -1, 0, jsonExtractFunc }, +- { "json_insert", -1, 0, jsonSetFunc }, +- { "json_object", -1, 0, jsonObjectFunc }, +- { "json_patch", 2, 0, jsonPatchFunc }, +- { "json_quote", 1, 0, jsonQuoteFunc }, +- { "json_remove", -1, 0, jsonRemoveFunc }, +- { "json_replace", -1, 0, jsonReplaceFunc }, +- { "json_set", -1, 1, jsonSetFunc }, +- { "json_type", 1, 0, jsonTypeFunc }, +- { "json_type", 2, 0, jsonTypeFunc }, +- { "json_valid", 1, 0, jsonValidFunc }, +- +-#if SQLITE_DEBUG +- /* DEBUG and TESTING functions */ +- { "json_parse", 1, 0, jsonParseFunc }, +- { "json_test1", 1, 0, jsonTest1Func }, +-#endif +- }; +- static const struct { +- const char *zName; +- int nArg; +- void (*xStep)(sqlite3_context*,int,sqlite3_value**); +- void (*xFinal)(sqlite3_context*); +- } aAgg[] = { +- { "json_group_array", 1, jsonArrayStep, jsonArrayFinal }, +- { "json_group_object", 2, jsonObjectStep, jsonObjectFinal }, +- }; +-#ifndef SQLITE_OMIT_VIRTUALTABLE +- static const struct { +- const char *zName; +- sqlite3_module *pModule; +- } aMod[] = { +- { "json_each", &jsonEachModule }, +- { "json_tree", &jsonTreeModule }, +- }; +-#endif +- for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){ +- rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg, +- SQLITE_UTF8 | SQLITE_DETERMINISTIC, +- (void*)&aFunc[i].flag, +- aFunc[i].xFunc, 0, 0); +- } +- for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){ +- rc = sqlite3_create_function(db, aAgg[i].zName, aAgg[i].nArg, +- SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0, +- 0, aAgg[i].xStep, aAgg[i].xFinal); +- } +-#ifndef SQLITE_OMIT_VIRTUALTABLE +- for(i=0; i<sizeof(aMod)/sizeof(aMod[0]) && rc==SQLITE_OK; i++){ +- rc = sqlite3_create_module(db, aMod[i].zName, aMod[i].pModule, 0); +- } +-#endif +- return rc; +-} +- +- +-#ifndef SQLITE_CORE +-#ifdef _WIN32 +-__declspec(dllexport) +-#endif +-SQLITE_API int sqlite3_json_init( +- sqlite3 *db, +- char **pzErrMsg, +- const sqlite3_api_routines *pApi +-){ +- SQLITE_EXTENSION_INIT2(pApi); +- (void)pzErrMsg; /* Unused parameter */ +- return sqlite3Json1Init(db); +-} +-#endif +-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1) */ +- +-/************** End of json1.c ***********************************************/ ++/************** End of sqlite3session.c **************************************/ + /************** Begin file fts5.c ********************************************/ + + +@@ -188729,7 +198794,7 @@ + ** This way, even if the tokenizer does not provide synonyms + ** when tokenizing query text (it should not - to do would be + ** inefficient), it doesn't matter if the user queries for +-** 'first + place' or '1st + place', as there are entires in the ++** 'first + place' or '1st + place', as there are entries in the + ** FTS index corresponding to both forms of the first token. + ** </ol> + ** +@@ -188757,7 +198822,7 @@ + ** extra data to the FTS index or require FTS5 to query for multiple terms, + ** so it is efficient in terms of disk space and query speed. However, it + ** does not support prefix queries very well. If, as suggested above, the +-** token "first" is subsituted for "1st" by the tokenizer, then the query: ++** token "first" is substituted for "1st" by the tokenizer, then the query: + ** + ** <codeblock> + ** ... MATCH '1s*'</codeblock> +@@ -189649,9 +199714,12 @@ + /************************************************************************** + ** Interface to automatically generated code in fts5_unicode2.c. + */ +-static int sqlite3Fts5UnicodeIsalnum(int c); + static int sqlite3Fts5UnicodeIsdiacritic(int c); + static int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic); ++ ++static int sqlite3Fts5UnicodeCatParse(const char*, u8*); ++static int sqlite3Fts5UnicodeCategory(int iCode); ++static void sqlite3Fts5UnicodeAscii(u8*, u8*); + /* + ** End of interface to code in fts5_unicode2.c. + **************************************************************************/ +@@ -189699,6 +199767,7 @@ + ** input grammar file: + */ + /* #include <stdio.h> */ ++/* #include <assert.h> */ + /************ Begin %include sections from the grammar ************************/ + + /* #include "fts5Int.h" */ +@@ -189767,8 +199836,10 @@ + ** zero the stack is dynamically sized using realloc() + ** sqlite3Fts5ParserARG_SDECL A static variable declaration for the %extra_argument + ** sqlite3Fts5ParserARG_PDECL A parameter declaration for the %extra_argument ++** sqlite3Fts5ParserARG_PARAM Code to pass %extra_argument as a subroutine parameter + ** sqlite3Fts5ParserARG_STORE Code to store %extra_argument into fts5yypParser + ** sqlite3Fts5ParserARG_FETCH Code to extract %extra_argument from fts5yypParser ++** sqlite3Fts5ParserCTX_* As sqlite3Fts5ParserARG_ except for %extra_context + ** fts5YYERRORSYMBOL is the code number of the error symbol. If not + ** defined, then do no error processing. + ** fts5YYNSTATE the combined number of states. +@@ -189788,7 +199859,7 @@ + #endif + /************* Begin control #defines *****************************************/ + #define fts5YYCODETYPE unsigned char +-#define fts5YYNOCODE 29 ++#define fts5YYNOCODE 27 + #define fts5YYACTIONTYPE unsigned char + #define sqlite3Fts5ParserFTS5TOKENTYPE Fts5Token + typedef union { +@@ -189795,10 +199866,10 @@ + int fts5yyinit; + sqlite3Fts5ParserFTS5TOKENTYPE fts5yy0; + int fts5yy4; +- Fts5ExprPhrase* fts5yy11; +- Fts5ExprNearset* fts5yy14; +- Fts5Colset* fts5yy43; +- Fts5ExprNode* fts5yy54; ++ Fts5Colset* fts5yy11; ++ Fts5ExprNode* fts5yy24; ++ Fts5ExprNearset* fts5yy46; ++ Fts5ExprPhrase* fts5yy53; + } fts5YYMINORTYPE; + #ifndef fts5YYSTACKDEPTH + #define fts5YYSTACKDEPTH 100 +@@ -189805,8 +199876,14 @@ + #endif + #define sqlite3Fts5ParserARG_SDECL Fts5Parse *pParse; + #define sqlite3Fts5ParserARG_PDECL ,Fts5Parse *pParse +-#define sqlite3Fts5ParserARG_FETCH Fts5Parse *pParse = fts5yypParser->pParse +-#define sqlite3Fts5ParserARG_STORE fts5yypParser->pParse = pParse ++#define sqlite3Fts5ParserARG_PARAM ,pParse ++#define sqlite3Fts5ParserARG_FETCH Fts5Parse *pParse=fts5yypParser->pParse; ++#define sqlite3Fts5ParserARG_STORE fts5yypParser->pParse=pParse; ++#define sqlite3Fts5ParserCTX_SDECL ++#define sqlite3Fts5ParserCTX_PDECL ++#define sqlite3Fts5ParserCTX_PARAM ++#define sqlite3Fts5ParserCTX_FETCH ++#define sqlite3Fts5ParserCTX_STORE + #define fts5YYNSTATE 35 + #define fts5YYNRULE 28 + #define fts5YYNFTS5TOKEN 16 +@@ -189819,6 +199896,7 @@ + #define fts5YY_MIN_REDUCE 83 + #define fts5YY_MAX_REDUCE 110 + /************* End control #defines *******************************************/ ++#define fts5YY_NLOOKAHEAD ((int)(sizeof(fts5yy_lookahead)/sizeof(fts5yy_lookahead[0]))) + + /* Define the fts5yytestcase() macro to be a no-op if is not already defined + ** otherwise. +@@ -189887,46 +199965,46 @@ + static const fts5YYACTIONTYPE fts5yy_action[] = { + /* 0 */ 81, 20, 96, 6, 28, 99, 98, 26, 26, 18, + /* 10 */ 96, 6, 28, 17, 98, 56, 26, 19, 96, 6, +- /* 20 */ 28, 14, 98, 108, 26, 92, 96, 6, 28, 25, +- /* 30 */ 98, 78, 26, 21, 96, 6, 28, 107, 98, 58, +- /* 40 */ 26, 29, 96, 6, 28, 32, 98, 22, 26, 24, +- /* 50 */ 16, 23, 11, 1, 14, 13, 24, 16, 31, 11, +- /* 60 */ 3, 97, 13, 27, 8, 98, 82, 26, 7, 4, +- /* 70 */ 5, 3, 4, 5, 3, 83, 4, 5, 3, 63, +- /* 80 */ 33, 34, 62, 12, 2, 86, 13, 10, 12, 71, +- /* 90 */ 10, 13, 78, 5, 3, 78, 9, 30, 75, 82, +- /* 100 */ 54, 57, 53, 57, 15, ++ /* 20 */ 28, 14, 98, 14, 26, 31, 92, 96, 6, 28, ++ /* 30 */ 108, 98, 25, 26, 21, 96, 6, 28, 78, 98, ++ /* 40 */ 58, 26, 29, 96, 6, 28, 107, 98, 22, 26, ++ /* 50 */ 24, 16, 12, 11, 1, 13, 13, 24, 16, 23, ++ /* 60 */ 11, 33, 34, 13, 97, 8, 27, 32, 98, 7, ++ /* 70 */ 26, 3, 4, 5, 3, 4, 5, 3, 83, 4, ++ /* 80 */ 5, 3, 63, 5, 3, 62, 12, 2, 86, 13, ++ /* 90 */ 9, 30, 10, 10, 54, 57, 75, 78, 78, 53, ++ /* 100 */ 57, 15, 82, 82, 71, + }; + static const fts5YYCODETYPE fts5yy_lookahead[] = { +- /* 0 */ 17, 18, 19, 20, 21, 23, 23, 25, 25, 18, +- /* 10 */ 19, 20, 21, 7, 23, 9, 25, 18, 19, 20, +- /* 20 */ 21, 9, 23, 27, 25, 18, 19, 20, 21, 25, +- /* 30 */ 23, 15, 25, 18, 19, 20, 21, 27, 23, 9, +- /* 40 */ 25, 18, 19, 20, 21, 14, 23, 22, 25, 6, +- /* 50 */ 7, 22, 9, 10, 9, 12, 6, 7, 13, 9, +- /* 60 */ 3, 19, 12, 21, 5, 23, 28, 25, 5, 1, +- /* 70 */ 2, 3, 1, 2, 3, 0, 1, 2, 3, 11, +- /* 80 */ 25, 26, 11, 9, 10, 5, 12, 10, 9, 11, +- /* 90 */ 10, 12, 15, 2, 3, 15, 24, 25, 9, 28, +- /* 100 */ 8, 9, 8, 9, 9, 28, 28, 28, 28, 28, +- /* 110 */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +- /* 120 */ 28, ++ /* 0 */ 16, 17, 18, 19, 20, 22, 22, 24, 24, 17, ++ /* 10 */ 18, 19, 20, 7, 22, 9, 24, 17, 18, 19, ++ /* 20 */ 20, 9, 22, 9, 24, 13, 17, 18, 19, 20, ++ /* 30 */ 26, 22, 24, 24, 17, 18, 19, 20, 15, 22, ++ /* 40 */ 9, 24, 17, 18, 19, 20, 26, 22, 21, 24, ++ /* 50 */ 6, 7, 9, 9, 10, 12, 12, 6, 7, 21, ++ /* 60 */ 9, 24, 25, 12, 18, 5, 20, 14, 22, 5, ++ /* 70 */ 24, 3, 1, 2, 3, 1, 2, 3, 0, 1, ++ /* 80 */ 2, 3, 11, 2, 3, 11, 9, 10, 5, 12, ++ /* 90 */ 23, 24, 10, 10, 8, 9, 9, 15, 15, 8, ++ /* 100 */ 9, 9, 27, 27, 11, 27, 27, 27, 27, 27, ++ /* 110 */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, ++ /* 120 */ 27, + }; + #define fts5YY_SHIFT_COUNT (34) + #define fts5YY_SHIFT_MIN (0) +-#define fts5YY_SHIFT_MAX (95) ++#define fts5YY_SHIFT_MAX (93) + static const unsigned char fts5yy_shift_ofst[] = { +- /* 0 */ 43, 43, 43, 43, 43, 43, 50, 74, 79, 45, +- /* 10 */ 12, 80, 77, 12, 16, 16, 30, 30, 68, 71, +- /* 20 */ 75, 91, 92, 94, 6, 31, 31, 59, 63, 57, +- /* 30 */ 31, 89, 95, 31, 78, ++ /* 0 */ 44, 44, 44, 44, 44, 44, 51, 77, 43, 12, ++ /* 10 */ 14, 83, 82, 14, 23, 23, 31, 31, 71, 74, ++ /* 20 */ 78, 81, 86, 91, 6, 53, 53, 60, 64, 68, ++ /* 30 */ 53, 87, 92, 53, 93, + }; + #define fts5YY_REDUCE_COUNT (17) +-#define fts5YY_REDUCE_MIN (-18) +-#define fts5YY_REDUCE_MAX (72) ++#define fts5YY_REDUCE_MIN (-17) ++#define fts5YY_REDUCE_MAX (67) + static const signed char fts5yy_reduce_ofst[] = { +- /* 0 */ -17, -9, -1, 7, 15, 23, 42, -18, -18, 55, +- /* 10 */ 72, -4, -4, 4, -4, 10, 25, 29, ++ /* 0 */ -16, -8, 0, 9, 17, 25, 46, -17, -17, 37, ++ /* 10 */ 67, 4, 4, 8, 4, 20, 27, 38, + }; + static const fts5YYACTIONTYPE fts5yy_default[] = { + /* 0 */ 80, 80, 80, 80, 80, 80, 95, 80, 80, 105, +@@ -189991,6 +200069,7 @@ + int fts5yyerrcnt; /* Shifts left before out of the error */ + #endif + sqlite3Fts5ParserARG_SDECL /* A place to hold %extra_argument */ ++ sqlite3Fts5ParserCTX_SDECL /* A place to hold %extra_context */ + #if fts5YYSTACKDEPTH<=0 + int fts5yystksz; /* Current side of the stack */ + fts5yyStackEntry *fts5yystack; /* The parser's stack */ +@@ -190054,18 +200133,17 @@ + /* 13 */ "COMMA", + /* 14 */ "PLUS", + /* 15 */ "STAR", +- /* 16 */ "error", +- /* 17 */ "input", +- /* 18 */ "expr", +- /* 19 */ "cnearset", +- /* 20 */ "exprlist", +- /* 21 */ "colset", +- /* 22 */ "colsetlist", +- /* 23 */ "nearset", +- /* 24 */ "nearphrases", +- /* 25 */ "phrase", +- /* 26 */ "neardist_opt", +- /* 27 */ "star_opt", ++ /* 16 */ "input", ++ /* 17 */ "expr", ++ /* 18 */ "cnearset", ++ /* 19 */ "exprlist", ++ /* 20 */ "colset", ++ /* 21 */ "colsetlist", ++ /* 22 */ "nearset", ++ /* 23 */ "nearphrases", ++ /* 24 */ "phrase", ++ /* 25 */ "neardist_opt", ++ /* 26 */ "star_opt", + }; + #endif /* defined(fts5YYCOVERAGE) || !defined(NDEBUG) */ + +@@ -190149,28 +200227,29 @@ + + /* Initialize a new parser that has already been allocated. + */ +-static void sqlite3Fts5ParserInit(void *fts5yypParser){ +- fts5yyParser *pParser = (fts5yyParser*)fts5yypParser; ++static void sqlite3Fts5ParserInit(void *fts5yypRawParser sqlite3Fts5ParserCTX_PDECL){ ++ fts5yyParser *fts5yypParser = (fts5yyParser*)fts5yypRawParser; ++ sqlite3Fts5ParserCTX_STORE + #ifdef fts5YYTRACKMAXSTACKDEPTH +- pParser->fts5yyhwm = 0; ++ fts5yypParser->fts5yyhwm = 0; + #endif + #if fts5YYSTACKDEPTH<=0 +- pParser->fts5yytos = NULL; +- pParser->fts5yystack = NULL; +- pParser->fts5yystksz = 0; +- if( fts5yyGrowStack(pParser) ){ +- pParser->fts5yystack = &pParser->fts5yystk0; +- pParser->fts5yystksz = 1; ++ fts5yypParser->fts5yytos = NULL; ++ fts5yypParser->fts5yystack = NULL; ++ fts5yypParser->fts5yystksz = 0; ++ if( fts5yyGrowStack(fts5yypParser) ){ ++ fts5yypParser->fts5yystack = &fts5yypParser->fts5yystk0; ++ fts5yypParser->fts5yystksz = 1; + } + #endif + #ifndef fts5YYNOERRORRECOVERY +- pParser->fts5yyerrcnt = -1; ++ fts5yypParser->fts5yyerrcnt = -1; + #endif +- pParser->fts5yytos = pParser->fts5yystack; +- pParser->fts5yystack[0].stateno = 0; +- pParser->fts5yystack[0].major = 0; ++ fts5yypParser->fts5yytos = fts5yypParser->fts5yystack; ++ fts5yypParser->fts5yystack[0].stateno = 0; ++ fts5yypParser->fts5yystack[0].major = 0; + #if fts5YYSTACKDEPTH>0 +- pParser->fts5yystackEnd = &pParser->fts5yystack[fts5YYSTACKDEPTH-1]; ++ fts5yypParser->fts5yystackEnd = &fts5yypParser->fts5yystack[fts5YYSTACKDEPTH-1]; + #endif + } + +@@ -190187,11 +200266,14 @@ + ** A pointer to a parser. This pointer is used in subsequent calls + ** to sqlite3Fts5Parser and sqlite3Fts5ParserFree. + */ +-static void *sqlite3Fts5ParserAlloc(void *(*mallocProc)(fts5YYMALLOCARGTYPE)){ +- fts5yyParser *pParser; +- pParser = (fts5yyParser*)(*mallocProc)( (fts5YYMALLOCARGTYPE)sizeof(fts5yyParser) ); +- if( pParser ) sqlite3Fts5ParserInit(pParser); +- return pParser; ++static void *sqlite3Fts5ParserAlloc(void *(*mallocProc)(fts5YYMALLOCARGTYPE) sqlite3Fts5ParserCTX_PDECL){ ++ fts5yyParser *fts5yypParser; ++ fts5yypParser = (fts5yyParser*)(*mallocProc)( (fts5YYMALLOCARGTYPE)sizeof(fts5yyParser) ); ++ if( fts5yypParser ){ ++ sqlite3Fts5ParserCTX_STORE ++ sqlite3Fts5ParserInit(fts5yypParser sqlite3Fts5ParserCTX_PARAM); ++ } ++ return (void*)fts5yypParser; + } + #endif /* sqlite3Fts5Parser_ENGINEALWAYSONSTACK */ + +@@ -190208,7 +200290,8 @@ + fts5YYCODETYPE fts5yymajor, /* Type code for object to destroy */ + fts5YYMINORTYPE *fts5yypminor /* The object to be destroyed */ + ){ +- sqlite3Fts5ParserARG_FETCH; ++ sqlite3Fts5ParserARG_FETCH ++ sqlite3Fts5ParserCTX_FETCH + switch( fts5yymajor ){ + /* Here is inserted the actions which take place when a + ** terminal or non-terminal is destroyed. This can happen +@@ -190221,33 +200304,33 @@ + ** inside the C code. + */ + /********* Begin destructor definitions ***************************************/ +- case 17: /* input */ ++ case 16: /* input */ + { + (void)pParse; + } + break; +- case 18: /* expr */ +- case 19: /* cnearset */ +- case 20: /* exprlist */ ++ case 17: /* expr */ ++ case 18: /* cnearset */ ++ case 19: /* exprlist */ + { +- sqlite3Fts5ParseNodeFree((fts5yypminor->fts5yy54)); ++ sqlite3Fts5ParseNodeFree((fts5yypminor->fts5yy24)); + } + break; +- case 21: /* colset */ +- case 22: /* colsetlist */ ++ case 20: /* colset */ ++ case 21: /* colsetlist */ + { +- sqlite3_free((fts5yypminor->fts5yy43)); ++ sqlite3_free((fts5yypminor->fts5yy11)); + } + break; +- case 23: /* nearset */ +- case 24: /* nearphrases */ ++ case 22: /* nearset */ ++ case 23: /* nearphrases */ + { +- sqlite3Fts5ParseNearsetFree((fts5yypminor->fts5yy14)); ++ sqlite3Fts5ParseNearsetFree((fts5yypminor->fts5yy46)); + } + break; +- case 25: /* phrase */ ++ case 24: /* phrase */ + { +- sqlite3Fts5ParsePhraseFree((fts5yypminor->fts5yy11)); ++ sqlite3Fts5ParsePhraseFree((fts5yypminor->fts5yy53)); + } + break; + /********* End destructor definitions *****************************************/ +@@ -190359,13 +200442,12 @@ + ** Find the appropriate action for a parser given the terminal + ** look-ahead token iLookAhead. + */ +-static unsigned int fts5yy_find_shift_action( +- fts5yyParser *pParser, /* The parser */ +- fts5YYCODETYPE iLookAhead /* The look-ahead token */ ++static fts5YYACTIONTYPE fts5yy_find_shift_action( ++ fts5YYCODETYPE iLookAhead, /* The look-ahead token */ ++ fts5YYACTIONTYPE stateno /* Current state number */ + ){ + int i; +- int stateno = pParser->fts5yytos->stateno; +- ++ + if( stateno>fts5YY_MAX_SHIFT ) return stateno; + assert( stateno <= fts5YY_SHIFT_COUNT ); + #if defined(fts5YYCOVERAGE) +@@ -190374,11 +200456,11 @@ + do{ + i = fts5yy_shift_ofst[stateno]; + assert( i>=0 ); +- assert( i+fts5YYNFTS5TOKEN<=(int)sizeof(fts5yy_lookahead)/sizeof(fts5yy_lookahead[0]) ); ++ /* assert( i+fts5YYNFTS5TOKEN<=(int)fts5YY_NLOOKAHEAD ); */ + assert( iLookAhead!=fts5YYNOCODE ); + assert( iLookAhead < fts5YYNFTS5TOKEN ); + i += iLookAhead; +- if( fts5yy_lookahead[i]!=iLookAhead ){ ++ if( i>=fts5YY_NLOOKAHEAD || fts5yy_lookahead[i]!=iLookAhead ){ + #ifdef fts5YYFALLBACK + fts5YYCODETYPE iFallback; /* Fallback token */ + if( iLookAhead<sizeof(fts5yyFallback)/sizeof(fts5yyFallback[0]) +@@ -190404,6 +200486,7 @@ + #if fts5YY_SHIFT_MAX+fts5YYWILDCARD>=fts5YY_ACTTAB_COUNT + j<fts5YY_ACTTAB_COUNT && + #endif ++ j<(int)(sizeof(fts5yy_lookahead)/sizeof(fts5yy_lookahead[0])) && + fts5yy_lookahead[j]==fts5YYWILDCARD && iLookAhead>0 + ){ + #ifndef NDEBUG +@@ -190428,8 +200511,8 @@ + ** Find the appropriate action for a parser given the non-terminal + ** look-ahead token iLookAhead. + */ +-static int fts5yy_find_reduce_action( +- int stateno, /* Current state number */ ++static fts5YYACTIONTYPE fts5yy_find_reduce_action( ++ fts5YYACTIONTYPE stateno, /* Current state number */ + fts5YYCODETYPE iLookAhead /* The look-ahead token */ + ){ + int i; +@@ -190458,7 +200541,8 @@ + ** The following routine is called if the stack overflows. + */ + static void fts5yyStackOverflow(fts5yyParser *fts5yypParser){ +- sqlite3Fts5ParserARG_FETCH; ++ sqlite3Fts5ParserARG_FETCH ++ sqlite3Fts5ParserCTX_FETCH + #ifndef NDEBUG + if( fts5yyTraceFILE ){ + fprintf(fts5yyTraceFILE,"%sStack Overflow!\n",fts5yyTracePrompt); +@@ -190471,7 +200555,8 @@ + + sqlite3Fts5ParseError(pParse, "fts5: parser stack overflow"); + /******** End %stack_overflow code ********************************************/ +- sqlite3Fts5ParserARG_STORE; /* Suppress warning about unused %extra_argument var */ ++ sqlite3Fts5ParserARG_STORE /* Suppress warning about unused %extra_argument var */ ++ sqlite3Fts5ParserCTX_STORE + } + + /* +@@ -190500,8 +200585,8 @@ + */ + static void fts5yy_shift( + fts5yyParser *fts5yypParser, /* The parser to be shifted */ +- int fts5yyNewState, /* The new state to shift in */ +- int fts5yyMajor, /* The major token to shift in */ ++ fts5YYACTIONTYPE fts5yyNewState, /* The new state to shift in */ ++ fts5YYCODETYPE fts5yyMajor, /* The major token to shift in */ + sqlite3Fts5ParserFTS5TOKENTYPE fts5yyMinor /* The minor token to shift in */ + ){ + fts5yyStackEntry *fts5yytos; +@@ -190531,8 +200616,8 @@ + fts5yyNewState += fts5YY_MIN_REDUCE - fts5YY_MIN_SHIFTREDUCE; + } + fts5yytos = fts5yypParser->fts5yytos; +- fts5yytos->stateno = (fts5YYACTIONTYPE)fts5yyNewState; +- fts5yytos->major = (fts5YYCODETYPE)fts5yyMajor; ++ fts5yytos->stateno = fts5yyNewState; ++ fts5yytos->major = fts5yyMajor; + fts5yytos->minor.fts5yy0 = fts5yyMinor; + fts5yyTraceShift(fts5yypParser, fts5yyNewState, "Shift"); + } +@@ -190544,34 +200629,34 @@ + fts5YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ + signed char nrhs; /* Negative of the number of RHS symbols in the rule */ + } fts5yyRuleInfo[] = { +- { 17, -1 }, /* (0) input ::= expr */ +- { 21, -4 }, /* (1) colset ::= MINUS LCP colsetlist RCP */ +- { 21, -3 }, /* (2) colset ::= LCP colsetlist RCP */ +- { 21, -1 }, /* (3) colset ::= STRING */ +- { 21, -2 }, /* (4) colset ::= MINUS STRING */ +- { 22, -2 }, /* (5) colsetlist ::= colsetlist STRING */ +- { 22, -1 }, /* (6) colsetlist ::= STRING */ +- { 18, -3 }, /* (7) expr ::= expr AND expr */ +- { 18, -3 }, /* (8) expr ::= expr OR expr */ +- { 18, -3 }, /* (9) expr ::= expr NOT expr */ +- { 18, -5 }, /* (10) expr ::= colset COLON LP expr RP */ +- { 18, -3 }, /* (11) expr ::= LP expr RP */ +- { 18, -1 }, /* (12) expr ::= exprlist */ +- { 20, -1 }, /* (13) exprlist ::= cnearset */ +- { 20, -2 }, /* (14) exprlist ::= exprlist cnearset */ +- { 19, -1 }, /* (15) cnearset ::= nearset */ +- { 19, -3 }, /* (16) cnearset ::= colset COLON nearset */ +- { 23, -1 }, /* (17) nearset ::= phrase */ +- { 23, -2 }, /* (18) nearset ::= CARET phrase */ +- { 23, -5 }, /* (19) nearset ::= STRING LP nearphrases neardist_opt RP */ +- { 24, -1 }, /* (20) nearphrases ::= phrase */ +- { 24, -2 }, /* (21) nearphrases ::= nearphrases phrase */ +- { 26, 0 }, /* (22) neardist_opt ::= */ +- { 26, -2 }, /* (23) neardist_opt ::= COMMA STRING */ +- { 25, -4 }, /* (24) phrase ::= phrase PLUS STRING star_opt */ +- { 25, -2 }, /* (25) phrase ::= STRING star_opt */ +- { 27, -1 }, /* (26) star_opt ::= STAR */ +- { 27, 0 }, /* (27) star_opt ::= */ ++ { 16, -1 }, /* (0) input ::= expr */ ++ { 20, -4 }, /* (1) colset ::= MINUS LCP colsetlist RCP */ ++ { 20, -3 }, /* (2) colset ::= LCP colsetlist RCP */ ++ { 20, -1 }, /* (3) colset ::= STRING */ ++ { 20, -2 }, /* (4) colset ::= MINUS STRING */ ++ { 21, -2 }, /* (5) colsetlist ::= colsetlist STRING */ ++ { 21, -1 }, /* (6) colsetlist ::= STRING */ ++ { 17, -3 }, /* (7) expr ::= expr AND expr */ ++ { 17, -3 }, /* (8) expr ::= expr OR expr */ ++ { 17, -3 }, /* (9) expr ::= expr NOT expr */ ++ { 17, -5 }, /* (10) expr ::= colset COLON LP expr RP */ ++ { 17, -3 }, /* (11) expr ::= LP expr RP */ ++ { 17, -1 }, /* (12) expr ::= exprlist */ ++ { 19, -1 }, /* (13) exprlist ::= cnearset */ ++ { 19, -2 }, /* (14) exprlist ::= exprlist cnearset */ ++ { 18, -1 }, /* (15) cnearset ::= nearset */ ++ { 18, -3 }, /* (16) cnearset ::= colset COLON nearset */ ++ { 22, -1 }, /* (17) nearset ::= phrase */ ++ { 22, -2 }, /* (18) nearset ::= CARET phrase */ ++ { 22, -5 }, /* (19) nearset ::= STRING LP nearphrases neardist_opt RP */ ++ { 23, -1 }, /* (20) nearphrases ::= phrase */ ++ { 23, -2 }, /* (21) nearphrases ::= nearphrases phrase */ ++ { 25, 0 }, /* (22) neardist_opt ::= */ ++ { 25, -2 }, /* (23) neardist_opt ::= COMMA STRING */ ++ { 24, -4 }, /* (24) phrase ::= phrase PLUS STRING star_opt */ ++ { 24, -2 }, /* (25) phrase ::= STRING star_opt */ ++ { 26, -1 }, /* (26) star_opt ::= STAR */ ++ { 26, 0 }, /* (27) star_opt ::= */ + }; + + static void fts5yy_accept(fts5yyParser*); /* Forward Declaration */ +@@ -190586,17 +200671,18 @@ + ** only called from one place, optimizing compilers will in-line it, which + ** means that the extra parameters have no performance impact. + */ +-static void fts5yy_reduce( ++static fts5YYACTIONTYPE fts5yy_reduce( + fts5yyParser *fts5yypParser, /* The parser */ + unsigned int fts5yyruleno, /* Number of the rule by which to reduce */ + int fts5yyLookahead, /* Lookahead token, or fts5YYNOCODE if none */ + sqlite3Fts5ParserFTS5TOKENTYPE fts5yyLookaheadToken /* Value of the lookahead token */ ++ sqlite3Fts5ParserCTX_PDECL /* %extra_context */ + ){ + int fts5yygoto; /* The next state */ +- int fts5yyact; /* The next action */ ++ fts5YYACTIONTYPE fts5yyact; /* The next action */ + fts5yyStackEntry *fts5yymsp; /* The top of the parser's stack */ + int fts5yysize; /* Amount to pop the stack */ +- sqlite3Fts5ParserARG_FETCH; ++ sqlite3Fts5ParserARG_FETCH + (void)fts5yyLookahead; + (void)fts5yyLookaheadToken; + fts5yymsp = fts5yypParser->fts5yytos; +@@ -190627,13 +200713,19 @@ + #if fts5YYSTACKDEPTH>0 + if( fts5yypParser->fts5yytos>=fts5yypParser->fts5yystackEnd ){ + fts5yyStackOverflow(fts5yypParser); +- return; ++ /* The call to fts5yyStackOverflow() above pops the stack until it is ++ ** empty, causing the main parser loop to exit. So the return value ++ ** is never used and does not matter. */ ++ return 0; + } + #else + if( fts5yypParser->fts5yytos>=&fts5yypParser->fts5yystack[fts5yypParser->fts5yystksz-1] ){ + if( fts5yyGrowStack(fts5yypParser) ){ + fts5yyStackOverflow(fts5yypParser); +- return; ++ /* The call to fts5yyStackOverflow() above pops the stack until it is ++ ** empty, causing the main parser loop to exit. So the return value ++ ** is never used and does not matter. */ ++ return 0; + } + fts5yymsp = fts5yypParser->fts5yytos; + } +@@ -190652,120 +200744,120 @@ + /********** Begin reduce actions **********************************************/ + fts5YYMINORTYPE fts5yylhsminor; + case 0: /* input ::= expr */ +-{ sqlite3Fts5ParseFinished(pParse, fts5yymsp[0].minor.fts5yy54); } ++{ sqlite3Fts5ParseFinished(pParse, fts5yymsp[0].minor.fts5yy24); } + break; + case 1: /* colset ::= MINUS LCP colsetlist RCP */ + { +- fts5yymsp[-3].minor.fts5yy43 = sqlite3Fts5ParseColsetInvert(pParse, fts5yymsp[-1].minor.fts5yy43); ++ fts5yymsp[-3].minor.fts5yy11 = sqlite3Fts5ParseColsetInvert(pParse, fts5yymsp[-1].minor.fts5yy11); + } + break; + case 2: /* colset ::= LCP colsetlist RCP */ +-{ fts5yymsp[-2].minor.fts5yy43 = fts5yymsp[-1].minor.fts5yy43; } ++{ fts5yymsp[-2].minor.fts5yy11 = fts5yymsp[-1].minor.fts5yy11; } + break; + case 3: /* colset ::= STRING */ + { +- fts5yylhsminor.fts5yy43 = sqlite3Fts5ParseColset(pParse, 0, &fts5yymsp[0].minor.fts5yy0); ++ fts5yylhsminor.fts5yy11 = sqlite3Fts5ParseColset(pParse, 0, &fts5yymsp[0].minor.fts5yy0); + } +- fts5yymsp[0].minor.fts5yy43 = fts5yylhsminor.fts5yy43; ++ fts5yymsp[0].minor.fts5yy11 = fts5yylhsminor.fts5yy11; + break; + case 4: /* colset ::= MINUS STRING */ + { +- fts5yymsp[-1].minor.fts5yy43 = sqlite3Fts5ParseColset(pParse, 0, &fts5yymsp[0].minor.fts5yy0); +- fts5yymsp[-1].minor.fts5yy43 = sqlite3Fts5ParseColsetInvert(pParse, fts5yymsp[-1].minor.fts5yy43); ++ fts5yymsp[-1].minor.fts5yy11 = sqlite3Fts5ParseColset(pParse, 0, &fts5yymsp[0].minor.fts5yy0); ++ fts5yymsp[-1].minor.fts5yy11 = sqlite3Fts5ParseColsetInvert(pParse, fts5yymsp[-1].minor.fts5yy11); + } + break; + case 5: /* colsetlist ::= colsetlist STRING */ + { +- fts5yylhsminor.fts5yy43 = sqlite3Fts5ParseColset(pParse, fts5yymsp[-1].minor.fts5yy43, &fts5yymsp[0].minor.fts5yy0); } +- fts5yymsp[-1].minor.fts5yy43 = fts5yylhsminor.fts5yy43; ++ fts5yylhsminor.fts5yy11 = sqlite3Fts5ParseColset(pParse, fts5yymsp[-1].minor.fts5yy11, &fts5yymsp[0].minor.fts5yy0); } ++ fts5yymsp[-1].minor.fts5yy11 = fts5yylhsminor.fts5yy11; + break; + case 6: /* colsetlist ::= STRING */ + { +- fts5yylhsminor.fts5yy43 = sqlite3Fts5ParseColset(pParse, 0, &fts5yymsp[0].minor.fts5yy0); ++ fts5yylhsminor.fts5yy11 = sqlite3Fts5ParseColset(pParse, 0, &fts5yymsp[0].minor.fts5yy0); + } +- fts5yymsp[0].minor.fts5yy43 = fts5yylhsminor.fts5yy43; ++ fts5yymsp[0].minor.fts5yy11 = fts5yylhsminor.fts5yy11; + break; + case 7: /* expr ::= expr AND expr */ + { +- fts5yylhsminor.fts5yy54 = sqlite3Fts5ParseNode(pParse, FTS5_AND, fts5yymsp[-2].minor.fts5yy54, fts5yymsp[0].minor.fts5yy54, 0); ++ fts5yylhsminor.fts5yy24 = sqlite3Fts5ParseNode(pParse, FTS5_AND, fts5yymsp[-2].minor.fts5yy24, fts5yymsp[0].minor.fts5yy24, 0); + } +- fts5yymsp[-2].minor.fts5yy54 = fts5yylhsminor.fts5yy54; ++ fts5yymsp[-2].minor.fts5yy24 = fts5yylhsminor.fts5yy24; + break; + case 8: /* expr ::= expr OR expr */ + { +- fts5yylhsminor.fts5yy54 = sqlite3Fts5ParseNode(pParse, FTS5_OR, fts5yymsp[-2].minor.fts5yy54, fts5yymsp[0].minor.fts5yy54, 0); ++ fts5yylhsminor.fts5yy24 = sqlite3Fts5ParseNode(pParse, FTS5_OR, fts5yymsp[-2].minor.fts5yy24, fts5yymsp[0].minor.fts5yy24, 0); + } +- fts5yymsp[-2].minor.fts5yy54 = fts5yylhsminor.fts5yy54; ++ fts5yymsp[-2].minor.fts5yy24 = fts5yylhsminor.fts5yy24; + break; + case 9: /* expr ::= expr NOT expr */ + { +- fts5yylhsminor.fts5yy54 = sqlite3Fts5ParseNode(pParse, FTS5_NOT, fts5yymsp[-2].minor.fts5yy54, fts5yymsp[0].minor.fts5yy54, 0); ++ fts5yylhsminor.fts5yy24 = sqlite3Fts5ParseNode(pParse, FTS5_NOT, fts5yymsp[-2].minor.fts5yy24, fts5yymsp[0].minor.fts5yy24, 0); + } +- fts5yymsp[-2].minor.fts5yy54 = fts5yylhsminor.fts5yy54; ++ fts5yymsp[-2].minor.fts5yy24 = fts5yylhsminor.fts5yy24; + break; + case 10: /* expr ::= colset COLON LP expr RP */ + { +- sqlite3Fts5ParseSetColset(pParse, fts5yymsp[-1].minor.fts5yy54, fts5yymsp[-4].minor.fts5yy43); +- fts5yylhsminor.fts5yy54 = fts5yymsp[-1].minor.fts5yy54; ++ sqlite3Fts5ParseSetColset(pParse, fts5yymsp[-1].minor.fts5yy24, fts5yymsp[-4].minor.fts5yy11); ++ fts5yylhsminor.fts5yy24 = fts5yymsp[-1].minor.fts5yy24; + } +- fts5yymsp[-4].minor.fts5yy54 = fts5yylhsminor.fts5yy54; ++ fts5yymsp[-4].minor.fts5yy24 = fts5yylhsminor.fts5yy24; + break; + case 11: /* expr ::= LP expr RP */ +-{fts5yymsp[-2].minor.fts5yy54 = fts5yymsp[-1].minor.fts5yy54;} ++{fts5yymsp[-2].minor.fts5yy24 = fts5yymsp[-1].minor.fts5yy24;} + break; + case 12: /* expr ::= exprlist */ + case 13: /* exprlist ::= cnearset */ fts5yytestcase(fts5yyruleno==13); +-{fts5yylhsminor.fts5yy54 = fts5yymsp[0].minor.fts5yy54;} +- fts5yymsp[0].minor.fts5yy54 = fts5yylhsminor.fts5yy54; ++{fts5yylhsminor.fts5yy24 = fts5yymsp[0].minor.fts5yy24;} ++ fts5yymsp[0].minor.fts5yy24 = fts5yylhsminor.fts5yy24; + break; + case 14: /* exprlist ::= exprlist cnearset */ + { +- fts5yylhsminor.fts5yy54 = sqlite3Fts5ParseImplicitAnd(pParse, fts5yymsp[-1].minor.fts5yy54, fts5yymsp[0].minor.fts5yy54); ++ fts5yylhsminor.fts5yy24 = sqlite3Fts5ParseImplicitAnd(pParse, fts5yymsp[-1].minor.fts5yy24, fts5yymsp[0].minor.fts5yy24); + } +- fts5yymsp[-1].minor.fts5yy54 = fts5yylhsminor.fts5yy54; ++ fts5yymsp[-1].minor.fts5yy24 = fts5yylhsminor.fts5yy24; + break; + case 15: /* cnearset ::= nearset */ + { +- fts5yylhsminor.fts5yy54 = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, fts5yymsp[0].minor.fts5yy14); ++ fts5yylhsminor.fts5yy24 = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, fts5yymsp[0].minor.fts5yy46); + } +- fts5yymsp[0].minor.fts5yy54 = fts5yylhsminor.fts5yy54; ++ fts5yymsp[0].minor.fts5yy24 = fts5yylhsminor.fts5yy24; + break; + case 16: /* cnearset ::= colset COLON nearset */ + { +- fts5yylhsminor.fts5yy54 = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, fts5yymsp[0].minor.fts5yy14); +- sqlite3Fts5ParseSetColset(pParse, fts5yylhsminor.fts5yy54, fts5yymsp[-2].minor.fts5yy43); ++ fts5yylhsminor.fts5yy24 = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, fts5yymsp[0].minor.fts5yy46); ++ sqlite3Fts5ParseSetColset(pParse, fts5yylhsminor.fts5yy24, fts5yymsp[-2].minor.fts5yy11); + } +- fts5yymsp[-2].minor.fts5yy54 = fts5yylhsminor.fts5yy54; ++ fts5yymsp[-2].minor.fts5yy24 = fts5yylhsminor.fts5yy24; + break; + case 17: /* nearset ::= phrase */ +-{ fts5yylhsminor.fts5yy14 = sqlite3Fts5ParseNearset(pParse, 0, fts5yymsp[0].minor.fts5yy11); } +- fts5yymsp[0].minor.fts5yy14 = fts5yylhsminor.fts5yy14; ++{ fts5yylhsminor.fts5yy46 = sqlite3Fts5ParseNearset(pParse, 0, fts5yymsp[0].minor.fts5yy53); } ++ fts5yymsp[0].minor.fts5yy46 = fts5yylhsminor.fts5yy46; + break; + case 18: /* nearset ::= CARET phrase */ + { +- sqlite3Fts5ParseSetCaret(fts5yymsp[0].minor.fts5yy11); +- fts5yymsp[-1].minor.fts5yy14 = sqlite3Fts5ParseNearset(pParse, 0, fts5yymsp[0].minor.fts5yy11); ++ sqlite3Fts5ParseSetCaret(fts5yymsp[0].minor.fts5yy53); ++ fts5yymsp[-1].minor.fts5yy46 = sqlite3Fts5ParseNearset(pParse, 0, fts5yymsp[0].minor.fts5yy53); + } + break; + case 19: /* nearset ::= STRING LP nearphrases neardist_opt RP */ + { + sqlite3Fts5ParseNear(pParse, &fts5yymsp[-4].minor.fts5yy0); +- sqlite3Fts5ParseSetDistance(pParse, fts5yymsp[-2].minor.fts5yy14, &fts5yymsp[-1].minor.fts5yy0); +- fts5yylhsminor.fts5yy14 = fts5yymsp[-2].minor.fts5yy14; ++ sqlite3Fts5ParseSetDistance(pParse, fts5yymsp[-2].minor.fts5yy46, &fts5yymsp[-1].minor.fts5yy0); ++ fts5yylhsminor.fts5yy46 = fts5yymsp[-2].minor.fts5yy46; + } +- fts5yymsp[-4].minor.fts5yy14 = fts5yylhsminor.fts5yy14; ++ fts5yymsp[-4].minor.fts5yy46 = fts5yylhsminor.fts5yy46; + break; + case 20: /* nearphrases ::= phrase */ + { +- fts5yylhsminor.fts5yy14 = sqlite3Fts5ParseNearset(pParse, 0, fts5yymsp[0].minor.fts5yy11); ++ fts5yylhsminor.fts5yy46 = sqlite3Fts5ParseNearset(pParse, 0, fts5yymsp[0].minor.fts5yy53); + } +- fts5yymsp[0].minor.fts5yy14 = fts5yylhsminor.fts5yy14; ++ fts5yymsp[0].minor.fts5yy46 = fts5yylhsminor.fts5yy46; + break; + case 21: /* nearphrases ::= nearphrases phrase */ + { +- fts5yylhsminor.fts5yy14 = sqlite3Fts5ParseNearset(pParse, fts5yymsp[-1].minor.fts5yy14, fts5yymsp[0].minor.fts5yy11); ++ fts5yylhsminor.fts5yy46 = sqlite3Fts5ParseNearset(pParse, fts5yymsp[-1].minor.fts5yy46, fts5yymsp[0].minor.fts5yy53); + } +- fts5yymsp[-1].minor.fts5yy14 = fts5yylhsminor.fts5yy14; ++ fts5yymsp[-1].minor.fts5yy46 = fts5yylhsminor.fts5yy46; + break; + case 22: /* neardist_opt ::= */ + { fts5yymsp[1].minor.fts5yy0.p = 0; fts5yymsp[1].minor.fts5yy0.n = 0; } +@@ -190775,15 +200867,15 @@ + break; + case 24: /* phrase ::= phrase PLUS STRING star_opt */ + { +- fts5yylhsminor.fts5yy11 = sqlite3Fts5ParseTerm(pParse, fts5yymsp[-3].minor.fts5yy11, &fts5yymsp[-1].minor.fts5yy0, fts5yymsp[0].minor.fts5yy4); ++ fts5yylhsminor.fts5yy53 = sqlite3Fts5ParseTerm(pParse, fts5yymsp[-3].minor.fts5yy53, &fts5yymsp[-1].minor.fts5yy0, fts5yymsp[0].minor.fts5yy4); + } +- fts5yymsp[-3].minor.fts5yy11 = fts5yylhsminor.fts5yy11; ++ fts5yymsp[-3].minor.fts5yy53 = fts5yylhsminor.fts5yy53; + break; + case 25: /* phrase ::= STRING star_opt */ + { +- fts5yylhsminor.fts5yy11 = sqlite3Fts5ParseTerm(pParse, 0, &fts5yymsp[-1].minor.fts5yy0, fts5yymsp[0].minor.fts5yy4); ++ fts5yylhsminor.fts5yy53 = sqlite3Fts5ParseTerm(pParse, 0, &fts5yymsp[-1].minor.fts5yy0, fts5yymsp[0].minor.fts5yy4); + } +- fts5yymsp[-1].minor.fts5yy11 = fts5yylhsminor.fts5yy11; ++ fts5yymsp[-1].minor.fts5yy53 = fts5yylhsminor.fts5yy53; + break; + case 26: /* star_opt ::= STAR */ + { fts5yymsp[0].minor.fts5yy4 = 1; } +@@ -190812,6 +200904,7 @@ + fts5yymsp->stateno = (fts5YYACTIONTYPE)fts5yyact; + fts5yymsp->major = (fts5YYCODETYPE)fts5yygoto; + fts5yyTraceShift(fts5yypParser, fts5yyact, "... then shift"); ++ return fts5yyact; + } + + /* +@@ -190821,7 +200914,8 @@ + static void fts5yy_parse_failed( + fts5yyParser *fts5yypParser /* The parser */ + ){ +- sqlite3Fts5ParserARG_FETCH; ++ sqlite3Fts5ParserARG_FETCH ++ sqlite3Fts5ParserCTX_FETCH + #ifndef NDEBUG + if( fts5yyTraceFILE ){ + fprintf(fts5yyTraceFILE,"%sFail!\n",fts5yyTracePrompt); +@@ -190832,7 +200926,8 @@ + ** parser fails */ + /************ Begin %parse_failure code ***************************************/ + /************ End %parse_failure code *****************************************/ +- sqlite3Fts5ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ ++ sqlite3Fts5ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ ++ sqlite3Fts5ParserCTX_STORE + } + #endif /* fts5YYNOERRORRECOVERY */ + +@@ -190844,7 +200939,8 @@ + int fts5yymajor, /* The major type of the error token */ + sqlite3Fts5ParserFTS5TOKENTYPE fts5yyminor /* The minor type of the error token */ + ){ +- sqlite3Fts5ParserARG_FETCH; ++ sqlite3Fts5ParserARG_FETCH ++ sqlite3Fts5ParserCTX_FETCH + #define FTS5TOKEN fts5yyminor + /************ Begin %syntax_error code ****************************************/ + +@@ -190853,7 +200949,8 @@ + pParse, "fts5: syntax error near \"%.*s\"",FTS5TOKEN.n,FTS5TOKEN.p + ); + /************ End %syntax_error code ******************************************/ +- sqlite3Fts5ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ ++ sqlite3Fts5ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ ++ sqlite3Fts5ParserCTX_STORE + } + + /* +@@ -190862,7 +200959,8 @@ + static void fts5yy_accept( + fts5yyParser *fts5yypParser /* The parser */ + ){ +- sqlite3Fts5ParserARG_FETCH; ++ sqlite3Fts5ParserARG_FETCH ++ sqlite3Fts5ParserCTX_FETCH + #ifndef NDEBUG + if( fts5yyTraceFILE ){ + fprintf(fts5yyTraceFILE,"%sAccept!\n",fts5yyTracePrompt); +@@ -190876,7 +200974,8 @@ + ** parser accepts */ + /*********** Begin %parse_accept code *****************************************/ + /*********** End %parse_accept code *******************************************/ +- sqlite3Fts5ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ ++ sqlite3Fts5ParserARG_STORE /* Suppress warning about unused %extra_argument variable */ ++ sqlite3Fts5ParserCTX_STORE + } + + /* The main parser program. +@@ -190905,7 +201004,7 @@ + sqlite3Fts5ParserARG_PDECL /* Optional %extra_argument parameter */ + ){ + fts5YYMINORTYPE fts5yyminorunion; +- unsigned int fts5yyact; /* The parser action. */ ++ fts5YYACTIONTYPE fts5yyact; /* The parser action. */ + #if !defined(fts5YYERRORSYMBOL) && !defined(fts5YYNOERRORRECOVERY) + int fts5yyendofinput; /* True if we are at the end of input */ + #endif +@@ -190912,38 +201011,40 @@ + #ifdef fts5YYERRORSYMBOL + int fts5yyerrorhit = 0; /* True if fts5yymajor has invoked an error */ + #endif +- fts5yyParser *fts5yypParser; /* The parser */ ++ fts5yyParser *fts5yypParser = (fts5yyParser*)fts5yyp; /* The parser */ ++ sqlite3Fts5ParserCTX_FETCH ++ sqlite3Fts5ParserARG_STORE + +- fts5yypParser = (fts5yyParser*)fts5yyp; + assert( fts5yypParser->fts5yytos!=0 ); + #if !defined(fts5YYERRORSYMBOL) && !defined(fts5YYNOERRORRECOVERY) + fts5yyendofinput = (fts5yymajor==0); + #endif +- sqlite3Fts5ParserARG_STORE; + ++ fts5yyact = fts5yypParser->fts5yytos->stateno; + #ifndef NDEBUG + if( fts5yyTraceFILE ){ +- int stateno = fts5yypParser->fts5yytos->stateno; +- if( stateno < fts5YY_MIN_REDUCE ){ ++ if( fts5yyact < fts5YY_MIN_REDUCE ){ + fprintf(fts5yyTraceFILE,"%sInput '%s' in state %d\n", +- fts5yyTracePrompt,fts5yyTokenName[fts5yymajor],stateno); ++ fts5yyTracePrompt,fts5yyTokenName[fts5yymajor],fts5yyact); + }else{ + fprintf(fts5yyTraceFILE,"%sInput '%s' with pending reduce %d\n", +- fts5yyTracePrompt,fts5yyTokenName[fts5yymajor],stateno-fts5YY_MIN_REDUCE); ++ fts5yyTracePrompt,fts5yyTokenName[fts5yymajor],fts5yyact-fts5YY_MIN_REDUCE); + } + } + #endif + + do{ +- fts5yyact = fts5yy_find_shift_action(fts5yypParser,(fts5YYCODETYPE)fts5yymajor); ++ assert( fts5yyact==fts5yypParser->fts5yytos->stateno ); ++ fts5yyact = fts5yy_find_shift_action((fts5YYCODETYPE)fts5yymajor,fts5yyact); + if( fts5yyact >= fts5YY_MIN_REDUCE ){ +- fts5yy_reduce(fts5yypParser,fts5yyact-fts5YY_MIN_REDUCE,fts5yymajor,fts5yyminor); ++ fts5yyact = fts5yy_reduce(fts5yypParser,fts5yyact-fts5YY_MIN_REDUCE,fts5yymajor, ++ fts5yyminor sqlite3Fts5ParserCTX_PARAM); + }else if( fts5yyact <= fts5YY_MAX_SHIFTREDUCE ){ +- fts5yy_shift(fts5yypParser,fts5yyact,fts5yymajor,fts5yyminor); ++ fts5yy_shift(fts5yypParser,fts5yyact,(fts5YYCODETYPE)fts5yymajor,fts5yyminor); + #ifndef fts5YYNOERRORRECOVERY + fts5yypParser->fts5yyerrcnt--; + #endif +- fts5yymajor = fts5YYNOCODE; ++ break; + }else if( fts5yyact==fts5YY_ACCEPT_ACTION ){ + fts5yypParser->fts5yytos--; + fts5yy_accept(fts5yypParser); +@@ -190994,10 +201095,9 @@ + fts5yymajor = fts5YYNOCODE; + }else{ + while( fts5yypParser->fts5yytos >= fts5yypParser->fts5yystack +- && fts5yymx != fts5YYERRORSYMBOL + && (fts5yyact = fts5yy_find_reduce_action( + fts5yypParser->fts5yytos->stateno, +- fts5YYERRORSYMBOL)) >= fts5YY_MIN_REDUCE ++ fts5YYERRORSYMBOL)) > fts5YY_MAX_SHIFTREDUCE + ){ + fts5yy_pop_parser_stack(fts5yypParser); + } +@@ -191014,6 +201114,8 @@ + } + fts5yypParser->fts5yyerrcnt = 3; + fts5yyerrorhit = 1; ++ if( fts5yymajor==fts5YYNOCODE ) break; ++ fts5yyact = fts5yypParser->fts5yytos->stateno; + #elif defined(fts5YYNOERRORRECOVERY) + /* If the fts5YYNOERRORRECOVERY macro is defined, then do not attempt to + ** do any kind of error recovery. Instead, simply invoke the syntax +@@ -191024,8 +201126,7 @@ + */ + fts5yy_syntax_error(fts5yypParser,fts5yymajor, fts5yyminor); + fts5yy_destructor(fts5yypParser,(fts5YYCODETYPE)fts5yymajor,&fts5yyminorunion); +- fts5yymajor = fts5YYNOCODE; +- ++ break; + #else /* fts5YYERRORSYMBOL is not defined */ + /* This is what we do if the grammar does not define ERROR: + ** +@@ -191047,10 +201148,10 @@ + fts5yypParser->fts5yyerrcnt = -1; + #endif + } +- fts5yymajor = fts5YYNOCODE; ++ break; + #endif + } +- }while( fts5yymajor!=fts5YYNOCODE && fts5yypParser->fts5yytos>fts5yypParser->fts5yystack ); ++ }while( fts5yypParser->fts5yytos>fts5yypParser->fts5yystack ); + #ifndef NDEBUG + if( fts5yyTraceFILE ){ + fts5yyStackEntry *i; +@@ -191067,6 +201168,21 @@ + } + + /* ++** Return the fallback token corresponding to canonical token iToken, or ++** 0 if iToken has no fallback. ++*/ ++static int sqlite3Fts5ParserFallback(int iToken){ ++#ifdef fts5YYFALLBACK ++ if( iToken<(int)(sizeof(fts5yyFallback)/sizeof(fts5yyFallback[0])) ){ ++ return fts5yyFallback[iToken]; ++ } ++#else ++ (void)iToken; ++#endif ++ return 0; ++} ++ ++/* + ** 2014 May 31 + ** + ** The author disclaims copyright to this source code. In place of +@@ -193176,6 +203292,7 @@ + /* #include <stdio.h> */ + static void sqlite3Fts5ParserTrace(FILE*, char*); + #endif ++static int sqlite3Fts5ParserFallback(int); + + + struct Fts5Expr { +@@ -195680,6 +205797,7 @@ + sqlite3_value **apVal /* Function arguments */ + ){ + int iCode; ++ u8 aArr[32]; + if( nArg!=1 ){ + sqlite3_result_error(pCtx, + "wrong number of arguments to function fts5_isalnum", -1 +@@ -195686,8 +205804,12 @@ + ); + return; + } ++ memset(aArr, 0, sizeof(aArr)); ++ sqlite3Fts5UnicodeCatParse("L*", aArr); ++ sqlite3Fts5UnicodeCatParse("N*", aArr); ++ sqlite3Fts5UnicodeCatParse("Co", aArr); + iCode = sqlite3_value_int(apVal[0]); +- sqlite3_result_int(pCtx, sqlite3Fts5UnicodeIsalnum(iCode)); ++ sqlite3_result_int(pCtx, aArr[sqlite3Fts5UnicodeCategory(iCode)]); + } + + static void fts5ExprFold( +@@ -195731,10 +205853,12 @@ + rc = sqlite3_create_function(db, p->z, -1, SQLITE_UTF8, pCtx, p->x, 0, 0); + } + +- /* Avoid a warning indicating that sqlite3Fts5ParserTrace() is unused */ ++ /* Avoid warnings indicating that sqlite3Fts5ParserTrace() and ++ ** sqlite3Fts5ParserFallback() are unused */ + #ifndef NDEBUG + (void)sqlite3Fts5ParserTrace; + #endif ++ (void)sqlite3Fts5ParserFallback; + + return rc; + } +@@ -201782,7 +211906,10 @@ + for(i=0; i<nChar; i++){ + if( n>=nByte ) return 0; /* Input contains fewer than nChar chars */ + if( (unsigned char)p[n++]>=0xc0 ){ +- while( (p[n] & 0xc0)==0x80 ) n++; ++ while( (p[n] & 0xc0)==0x80 ){ ++ n++; ++ if( n>=nByte ) break; ++ } + } + } + return n; +@@ -201920,7 +212047,7 @@ + fts5CloseReader(p); + } + +- *ppIter = &pRet->base; ++ *ppIter = (Fts5IndexIter*)pRet; + sqlite3Fts5BufferFree(&buf); + } + return fts5IndexReturn(p); +@@ -203307,7 +213434,7 @@ + case FTS5_SAVEPOINT: + assert( p->ts.eState==1 ); + assert( iSavepoint>=0 ); +- assert( iSavepoint>p->ts.iSavepoint ); ++ assert( iSavepoint>=p->ts.iSavepoint ); + p->ts.iSavepoint = iSavepoint; + break; + +@@ -204232,6 +214359,13 @@ + assert( nVal==0 && pMatch==0 && bOrderByRank==0 && bDesc==0 ); + assert( pCsr->iLastRowid==LARGEST_INT64 ); + assert( pCsr->iFirstRowid==SMALLEST_INT64 ); ++ if( pTab->pSortCsr->bDesc ){ ++ pCsr->iLastRowid = pTab->pSortCsr->iFirstRowid; ++ pCsr->iFirstRowid = pTab->pSortCsr->iLastRowid; ++ }else{ ++ pCsr->iLastRowid = pTab->pSortCsr->iLastRowid; ++ pCsr->iFirstRowid = pTab->pSortCsr->iFirstRowid; ++ } + pCsr->ePlan = FTS5_PLAN_SOURCE; + pCsr->pExpr = pTab->pSortCsr->pExpr; + rc = fts5CursorFirst(pTab, pCsr, bDesc); +@@ -205662,12 +215796,27 @@ + ){ + assert( nArg==0 ); + UNUSED_PARAM2(nArg, apUnused); +- sqlite3_result_text(pCtx, "fts5: 2018-04-10 17:39:29 4bb2294022060e61de7da5c227a69ccd846ba330e31626ebcd59a94efd148b3b", -1, SQLITE_TRANSIENT); ++ sqlite3_result_text(pCtx, "fts5: 2018-12-01 12:34:55 bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238b4f9", -1, SQLITE_TRANSIENT); + } + ++/* ++** Return true if zName is the extension on one of the shadow tables used ++** by this module. ++*/ ++static int fts5ShadowName(const char *zName){ ++ static const char *azName[] = { ++ "config", "content", "data", "docsize", "idx" ++ }; ++ unsigned int i; ++ for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){ ++ if( sqlite3_stricmp(zName, azName[i])==0 ) return 1; ++ } ++ return 0; ++} ++ + static int fts5Init(sqlite3 *db){ + static const sqlite3_module fts5Mod = { +- /* iVersion */ 2, ++ /* iVersion */ 3, + /* xCreate */ fts5CreateMethod, + /* xConnect */ fts5ConnectMethod, + /* xBestIndex */ fts5BestIndexMethod, +@@ -205690,6 +215839,7 @@ + /* xSavepoint */ fts5SavepointMethod, + /* xRelease */ fts5ReleaseMethod, + /* xRollbackTo */ fts5RollbackToMethod, ++ /* xShadowName */ fts5ShadowName + }; + + int rc; +@@ -207150,6 +217300,8 @@ + int bRemoveDiacritic; /* True if remove_diacritics=1 is set */ + int nException; + int *aiException; ++ ++ unsigned char aCategory[32]; /* True for token char categories */ + }; + + static int fts5UnicodeAddExceptions( +@@ -207174,7 +217326,7 @@ + if( iCode<128 ){ + p->aTokenChar[iCode] = (unsigned char)bTokenChars; + }else{ +- bToken = sqlite3Fts5UnicodeIsalnum(iCode); ++ bToken = p->aCategory[sqlite3Fts5UnicodeCategory(iCode)]; + assert( (bToken==0 || bToken==1) ); + assert( (bTokenChars==0 || bTokenChars==1) ); + if( bToken!=bTokenChars && sqlite3Fts5UnicodeIsdiacritic(iCode)==0 ){ +@@ -207235,6 +217387,21 @@ + return; + } + ++static int unicodeSetCategories(Unicode61Tokenizer *p, const char *zCat){ ++ const char *z = zCat; ++ ++ while( *z ){ ++ while( *z==' ' || *z=='\t' ) z++; ++ if( *z && sqlite3Fts5UnicodeCatParse(z, p->aCategory) ){ ++ return SQLITE_ERROR; ++ } ++ while( *z!=' ' && *z!='\t' && *z!='\0' ) z++; ++ } ++ ++ sqlite3Fts5UnicodeAscii(p->aCategory, p->aTokenChar); ++ return SQLITE_OK; ++} ++ + /* + ** Create a "unicode61" tokenizer. + */ +@@ -207253,9 +217420,10 @@ + }else{ + p = (Unicode61Tokenizer*)sqlite3_malloc(sizeof(Unicode61Tokenizer)); + if( p ){ ++ const char *zCat = "L* N* Co"; + int i; + memset(p, 0, sizeof(Unicode61Tokenizer)); +- memcpy(p->aTokenChar, aAsciiTokenChar, sizeof(aAsciiTokenChar)); ++ + p->bRemoveDiacritic = 1; + p->nFold = 64; + p->aFold = sqlite3_malloc(p->nFold * sizeof(char)); +@@ -207262,7 +217430,19 @@ + if( p->aFold==0 ){ + rc = SQLITE_NOMEM; + } ++ ++ /* Search for a "categories" argument */ + for(i=0; rc==SQLITE_OK && i<nArg; i+=2){ ++ if( 0==sqlite3_stricmp(azArg[i], "categories") ){ ++ zCat = azArg[i+1]; ++ } ++ } ++ ++ if( rc==SQLITE_OK ){ ++ rc = unicodeSetCategories(p, zCat); ++ } ++ ++ for(i=0; rc==SQLITE_OK && i<nArg; i+=2){ + const char *zArg = azArg[i+1]; + if( 0==sqlite3_stricmp(azArg[i], "remove_diacritics") ){ + if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){ +@@ -207275,10 +217455,14 @@ + }else + if( 0==sqlite3_stricmp(azArg[i], "separators") ){ + rc = fts5UnicodeAddExceptions(p, zArg, 0); ++ }else ++ if( 0==sqlite3_stricmp(azArg[i], "categories") ){ ++ /* no-op */ + }else{ + rc = SQLITE_ERROR; + } + } ++ + }else{ + rc = SQLITE_NOMEM; + } +@@ -207297,8 +217481,10 @@ + ** character (not a separator). + */ + static int fts5UnicodeIsAlnum(Unicode61Tokenizer *p, int iCode){ +- assert( (sqlite3Fts5UnicodeIsalnum(iCode) & 0xFFFFFFFE)==0 ); +- return sqlite3Fts5UnicodeIsalnum(iCode) ^ fts5UnicodeIsException(p, iCode); ++ return ( ++ p->aCategory[sqlite3Fts5UnicodeCategory(iCode)] ++ ^ fts5UnicodeIsException(p, iCode) ++ ); + } + + static int fts5UnicodeTokenize( +@@ -208174,137 +218360,8 @@ + + /* #include <assert.h> */ + +-/* +-** Return true if the argument corresponds to a unicode codepoint +-** classified as either a letter or a number. Otherwise false. +-** +-** The results are undefined if the value passed to this function +-** is less than zero. +-*/ +-static int sqlite3Fts5UnicodeIsalnum(int c){ +- /* Each unsigned integer in the following array corresponds to a contiguous +- ** range of unicode codepoints that are not either letters or numbers (i.e. +- ** codepoints for which this function should return 0). +- ** +- ** The most significant 22 bits in each 32-bit value contain the first +- ** codepoint in the range. The least significant 10 bits are used to store +- ** the size of the range (always at least 1). In other words, the value +- ** ((C<<22) + N) represents a range of N codepoints starting with codepoint +- ** C. It is not possible to represent a range larger than 1023 codepoints +- ** using this format. +- */ +- static const unsigned int aEntry[] = { +- 0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07, +- 0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01, +- 0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401, +- 0x000BBC81, 0x000DD401, 0x000DF801, 0x000E1002, 0x000E1C01, +- 0x000FD801, 0x00120808, 0x00156806, 0x00162402, 0x00163C01, +- 0x00164437, 0x0017CC02, 0x00180005, 0x00181816, 0x00187802, +- 0x00192C15, 0x0019A804, 0x0019C001, 0x001B5001, 0x001B580F, +- 0x001B9C07, 0x001BF402, 0x001C000E, 0x001C3C01, 0x001C4401, +- 0x001CC01B, 0x001E980B, 0x001FAC09, 0x001FD804, 0x00205804, +- 0x00206C09, 0x00209403, 0x0020A405, 0x0020C00F, 0x00216403, +- 0x00217801, 0x0023901B, 0x00240004, 0x0024E803, 0x0024F812, +- 0x00254407, 0x00258804, 0x0025C001, 0x00260403, 0x0026F001, +- 0x0026F807, 0x00271C02, 0x00272C03, 0x00275C01, 0x00278802, +- 0x0027C802, 0x0027E802, 0x00280403, 0x0028F001, 0x0028F805, +- 0x00291C02, 0x00292C03, 0x00294401, 0x0029C002, 0x0029D401, +- 0x002A0403, 0x002AF001, 0x002AF808, 0x002B1C03, 0x002B2C03, +- 0x002B8802, 0x002BC002, 0x002C0403, 0x002CF001, 0x002CF807, +- 0x002D1C02, 0x002D2C03, 0x002D5802, 0x002D8802, 0x002DC001, +- 0x002E0801, 0x002EF805, 0x002F1803, 0x002F2804, 0x002F5C01, +- 0x002FCC08, 0x00300403, 0x0030F807, 0x00311803, 0x00312804, +- 0x00315402, 0x00318802, 0x0031FC01, 0x00320802, 0x0032F001, +- 0x0032F807, 0x00331803, 0x00332804, 0x00335402, 0x00338802, +- 0x00340802, 0x0034F807, 0x00351803, 0x00352804, 0x00355C01, +- 0x00358802, 0x0035E401, 0x00360802, 0x00372801, 0x00373C06, +- 0x00375801, 0x00376008, 0x0037C803, 0x0038C401, 0x0038D007, +- 0x0038FC01, 0x00391C09, 0x00396802, 0x003AC401, 0x003AD006, +- 0x003AEC02, 0x003B2006, 0x003C041F, 0x003CD00C, 0x003DC417, +- 0x003E340B, 0x003E6424, 0x003EF80F, 0x003F380D, 0x0040AC14, +- 0x00412806, 0x00415804, 0x00417803, 0x00418803, 0x00419C07, +- 0x0041C404, 0x0042080C, 0x00423C01, 0x00426806, 0x0043EC01, +- 0x004D740C, 0x004E400A, 0x00500001, 0x0059B402, 0x005A0001, +- 0x005A6C02, 0x005BAC03, 0x005C4803, 0x005CC805, 0x005D4802, +- 0x005DC802, 0x005ED023, 0x005F6004, 0x005F7401, 0x0060000F, +- 0x0062A401, 0x0064800C, 0x0064C00C, 0x00650001, 0x00651002, +- 0x0066C011, 0x00672002, 0x00677822, 0x00685C05, 0x00687802, +- 0x0069540A, 0x0069801D, 0x0069FC01, 0x006A8007, 0x006AA006, +- 0x006C0005, 0x006CD011, 0x006D6823, 0x006E0003, 0x006E840D, +- 0x006F980E, 0x006FF004, 0x00709014, 0x0070EC05, 0x0071F802, +- 0x00730008, 0x00734019, 0x0073B401, 0x0073C803, 0x00770027, +- 0x0077F004, 0x007EF401, 0x007EFC03, 0x007F3403, 0x007F7403, +- 0x007FB403, 0x007FF402, 0x00800065, 0x0081A806, 0x0081E805, +- 0x00822805, 0x0082801A, 0x00834021, 0x00840002, 0x00840C04, +- 0x00842002, 0x00845001, 0x00845803, 0x00847806, 0x00849401, +- 0x00849C01, 0x0084A401, 0x0084B801, 0x0084E802, 0x00850005, +- 0x00852804, 0x00853C01, 0x00864264, 0x00900027, 0x0091000B, +- 0x0092704E, 0x00940200, 0x009C0475, 0x009E53B9, 0x00AD400A, +- 0x00B39406, 0x00B3BC03, 0x00B3E404, 0x00B3F802, 0x00B5C001, +- 0x00B5FC01, 0x00B7804F, 0x00B8C00C, 0x00BA001A, 0x00BA6C59, +- 0x00BC00D6, 0x00BFC00C, 0x00C00005, 0x00C02019, 0x00C0A807, +- 0x00C0D802, 0x00C0F403, 0x00C26404, 0x00C28001, 0x00C3EC01, +- 0x00C64002, 0x00C6580A, 0x00C70024, 0x00C8001F, 0x00C8A81E, +- 0x00C94001, 0x00C98020, 0x00CA2827, 0x00CB003F, 0x00CC0100, +- 0x01370040, 0x02924037, 0x0293F802, 0x02983403, 0x0299BC10, +- 0x029A7C01, 0x029BC008, 0x029C0017, 0x029C8002, 0x029E2402, +- 0x02A00801, 0x02A01801, 0x02A02C01, 0x02A08C09, 0x02A0D804, +- 0x02A1D004, 0x02A20002, 0x02A2D011, 0x02A33802, 0x02A38012, +- 0x02A3E003, 0x02A4980A, 0x02A51C0D, 0x02A57C01, 0x02A60004, +- 0x02A6CC1B, 0x02A77802, 0x02A8A40E, 0x02A90C01, 0x02A93002, +- 0x02A97004, 0x02A9DC03, 0x02A9EC01, 0x02AAC001, 0x02AAC803, +- 0x02AADC02, 0x02AAF802, 0x02AB0401, 0x02AB7802, 0x02ABAC07, +- 0x02ABD402, 0x02AF8C0B, 0x03600001, 0x036DFC02, 0x036FFC02, +- 0x037FFC01, 0x03EC7801, 0x03ECA401, 0x03EEC810, 0x03F4F802, +- 0x03F7F002, 0x03F8001A, 0x03F88007, 0x03F8C023, 0x03F95013, +- 0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807, 0x03FCEC06, +- 0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405, 0x04040003, +- 0x0404DC09, 0x0405E411, 0x0406400C, 0x0407402E, 0x040E7C01, +- 0x040F4001, 0x04215C01, 0x04247C01, 0x0424FC01, 0x04280403, +- 0x04281402, 0x04283004, 0x0428E003, 0x0428FC01, 0x04294009, +- 0x0429FC01, 0x042CE407, 0x04400003, 0x0440E016, 0x04420003, +- 0x0442C012, 0x04440003, 0x04449C0E, 0x04450004, 0x04460003, +- 0x0446CC0E, 0x04471404, 0x045AAC0D, 0x0491C004, 0x05BD442E, +- 0x05BE3C04, 0x074000F6, 0x07440027, 0x0744A4B5, 0x07480046, +- 0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01, 0x075C5401, +- 0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401, 0x075EA401, +- 0x075F0C01, 0x07BBC002, 0x07C0002C, 0x07C0C064, 0x07C2800F, +- 0x07C2C40E, 0x07C3040F, 0x07C3440F, 0x07C4401F, 0x07C4C03C, +- 0x07C5C02B, 0x07C7981D, 0x07C8402B, 0x07C90009, 0x07C94002, +- 0x07CC0021, 0x07CCC006, 0x07CCDC46, 0x07CE0014, 0x07CE8025, +- 0x07CF1805, 0x07CF8011, 0x07D0003F, 0x07D10001, 0x07D108B6, +- 0x07D3E404, 0x07D4003E, 0x07D50004, 0x07D54018, 0x07D7EC46, +- 0x07D9140B, 0x07DA0046, 0x07DC0074, 0x38000401, 0x38008060, +- 0x380400F0, +- }; +- static const unsigned int aAscii[4] = { +- 0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001, +- }; + +- if( (unsigned int)c<128 ){ +- return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 ); +- }else if( (unsigned int)c<(1<<22) ){ +- unsigned int key = (((unsigned int)c)<<10) | 0x000003FF; +- int iRes = 0; +- int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; +- int iLo = 0; +- while( iHi>=iLo ){ +- int iTest = (iHi + iLo) / 2; +- if( key >= aEntry[iTest] ){ +- iRes = iTest; +- iLo = iTest+1; +- }else{ +- iHi = iTest-1; +- } +- } +- assert( aEntry[0]<key ); +- assert( key>=aEntry[iRes] ); +- return (((unsigned int)c) >= ((aEntry[iRes]>>10) + (aEntry[iRes]&0x3FF))); +- } +- return 1; +-} + +- + /* + ** If the argument is a codepoint corresponding to a lowercase letter + ** in the ASCII range with a diacritic added, return the codepoint +@@ -208515,6 +218572,539 @@ + return ret; + } + ++ ++#if 0 ++static int sqlite3Fts5UnicodeNCat(void) { ++ return 32; ++} ++#endif ++ ++static int sqlite3Fts5UnicodeCatParse(const char *zCat, u8 *aArray){ ++ aArray[0] = 1; ++ switch( zCat[0] ){ ++ case 'C': ++ switch( zCat[1] ){ ++ case 'c': aArray[1] = 1; break; ++ case 'f': aArray[2] = 1; break; ++ case 'n': aArray[3] = 1; break; ++ case 's': aArray[4] = 1; break; ++ case 'o': aArray[31] = 1; break; ++ case '*': ++ aArray[1] = 1; ++ aArray[2] = 1; ++ aArray[3] = 1; ++ aArray[4] = 1; ++ aArray[31] = 1; ++ break; ++ default: return 1; } ++ break; ++ ++ case 'L': ++ switch( zCat[1] ){ ++ case 'l': aArray[5] = 1; break; ++ case 'm': aArray[6] = 1; break; ++ case 'o': aArray[7] = 1; break; ++ case 't': aArray[8] = 1; break; ++ case 'u': aArray[9] = 1; break; ++ case 'C': aArray[30] = 1; break; ++ case '*': ++ aArray[5] = 1; ++ aArray[6] = 1; ++ aArray[7] = 1; ++ aArray[8] = 1; ++ aArray[9] = 1; ++ aArray[30] = 1; ++ break; ++ default: return 1; } ++ break; ++ ++ case 'M': ++ switch( zCat[1] ){ ++ case 'c': aArray[10] = 1; break; ++ case 'e': aArray[11] = 1; break; ++ case 'n': aArray[12] = 1; break; ++ case '*': ++ aArray[10] = 1; ++ aArray[11] = 1; ++ aArray[12] = 1; ++ break; ++ default: return 1; } ++ break; ++ ++ case 'N': ++ switch( zCat[1] ){ ++ case 'd': aArray[13] = 1; break; ++ case 'l': aArray[14] = 1; break; ++ case 'o': aArray[15] = 1; break; ++ case '*': ++ aArray[13] = 1; ++ aArray[14] = 1; ++ aArray[15] = 1; ++ break; ++ default: return 1; } ++ break; ++ ++ case 'P': ++ switch( zCat[1] ){ ++ case 'c': aArray[16] = 1; break; ++ case 'd': aArray[17] = 1; break; ++ case 'e': aArray[18] = 1; break; ++ case 'f': aArray[19] = 1; break; ++ case 'i': aArray[20] = 1; break; ++ case 'o': aArray[21] = 1; break; ++ case 's': aArray[22] = 1; break; ++ case '*': ++ aArray[16] = 1; ++ aArray[17] = 1; ++ aArray[18] = 1; ++ aArray[19] = 1; ++ aArray[20] = 1; ++ aArray[21] = 1; ++ aArray[22] = 1; ++ break; ++ default: return 1; } ++ break; ++ ++ case 'S': ++ switch( zCat[1] ){ ++ case 'c': aArray[23] = 1; break; ++ case 'k': aArray[24] = 1; break; ++ case 'm': aArray[25] = 1; break; ++ case 'o': aArray[26] = 1; break; ++ case '*': ++ aArray[23] = 1; ++ aArray[24] = 1; ++ aArray[25] = 1; ++ aArray[26] = 1; ++ break; ++ default: return 1; } ++ break; ++ ++ case 'Z': ++ switch( zCat[1] ){ ++ case 'l': aArray[27] = 1; break; ++ case 'p': aArray[28] = 1; break; ++ case 's': aArray[29] = 1; break; ++ case '*': ++ aArray[27] = 1; ++ aArray[28] = 1; ++ aArray[29] = 1; ++ break; ++ default: return 1; } ++ break; ++ ++ } ++ return 0; ++} ++ ++static u16 aFts5UnicodeBlock[] = { ++ 0, 1471, 1753, 1760, 1760, 1760, 1760, 1760, 1760, 1760, ++ 1760, 1760, 1760, 1760, 1760, 1763, 1765, ++ }; ++static u16 aFts5UnicodeMap[] = { ++ 0, 32, 33, 36, 37, 40, 41, 42, 43, 44, ++ 45, 46, 48, 58, 60, 63, 65, 91, 92, 93, ++ 94, 95, 96, 97, 123, 124, 125, 126, 127, 160, ++ 161, 162, 166, 167, 168, 169, 170, 171, 172, 173, ++ 174, 175, 176, 177, 178, 180, 181, 182, 184, 185, ++ 186, 187, 188, 191, 192, 215, 216, 223, 247, 248, ++ 256, 312, 313, 329, 330, 377, 383, 385, 387, 388, ++ 391, 394, 396, 398, 402, 403, 405, 406, 409, 412, ++ 414, 415, 417, 418, 423, 427, 428, 431, 434, 436, ++ 437, 440, 442, 443, 444, 446, 448, 452, 453, 454, ++ 455, 456, 457, 458, 459, 460, 461, 477, 478, 496, ++ 497, 498, 499, 500, 503, 505, 506, 564, 570, 572, ++ 573, 575, 577, 580, 583, 584, 592, 660, 661, 688, ++ 706, 710, 722, 736, 741, 748, 749, 750, 751, 768, ++ 880, 884, 885, 886, 890, 891, 894, 900, 902, 903, ++ 904, 908, 910, 912, 913, 931, 940, 975, 977, 978, ++ 981, 984, 1008, 1012, 1014, 1015, 1018, 1020, 1021, 1072, ++ 1120, 1154, 1155, 1160, 1162, 1217, 1231, 1232, 1329, 1369, ++ 1370, 1377, 1417, 1418, 1423, 1425, 1470, 1471, 1472, 1473, ++ 1475, 1476, 1478, 1479, 1488, 1520, 1523, 1536, 1542, 1545, ++ 1547, 1548, 1550, 1552, 1563, 1566, 1568, 1600, 1601, 1611, ++ 1632, 1642, 1646, 1648, 1649, 1748, 1749, 1750, 1757, 1758, ++ 1759, 1765, 1767, 1769, 1770, 1774, 1776, 1786, 1789, 1791, ++ 1792, 1807, 1808, 1809, 1810, 1840, 1869, 1958, 1969, 1984, ++ 1994, 2027, 2036, 2038, 2039, 2042, 2048, 2070, 2074, 2075, ++ 2084, 2085, 2088, 2089, 2096, 2112, 2137, 2142, 2208, 2210, ++ 2276, 2304, 2307, 2308, 2362, 2363, 2364, 2365, 2366, 2369, ++ 2377, 2381, 2382, 2384, 2385, 2392, 2402, 2404, 2406, 2416, ++ 2417, 2418, 2425, 2433, 2434, 2437, 2447, 2451, 2474, 2482, ++ 2486, 2492, 2493, 2494, 2497, 2503, 2507, 2509, 2510, 2519, ++ 2524, 2527, 2530, 2534, 2544, 2546, 2548, 2554, 2555, 2561, ++ 2563, 2565, 2575, 2579, 2602, 2610, 2613, 2616, 2620, 2622, ++ 2625, 2631, 2635, 2641, 2649, 2654, 2662, 2672, 2674, 2677, ++ 2689, 2691, 2693, 2703, 2707, 2730, 2738, 2741, 2748, 2749, ++ 2750, 2753, 2759, 2761, 2763, 2765, 2768, 2784, 2786, 2790, ++ 2800, 2801, 2817, 2818, 2821, 2831, 2835, 2858, 2866, 2869, ++ 2876, 2877, 2878, 2879, 2880, 2881, 2887, 2891, 2893, 2902, ++ 2903, 2908, 2911, 2914, 2918, 2928, 2929, 2930, 2946, 2947, ++ 2949, 2958, 2962, 2969, 2972, 2974, 2979, 2984, 2990, 3006, ++ 3008, 3009, 3014, 3018, 3021, 3024, 3031, 3046, 3056, 3059, ++ 3065, 3066, 3073, 3077, 3086, 3090, 3114, 3125, 3133, 3134, ++ 3137, 3142, 3146, 3157, 3160, 3168, 3170, 3174, 3192, 3199, ++ 3202, 3205, 3214, 3218, 3242, 3253, 3260, 3261, 3262, 3263, ++ 3264, 3270, 3271, 3274, 3276, 3285, 3294, 3296, 3298, 3302, ++ 3313, 3330, 3333, 3342, 3346, 3389, 3390, 3393, 3398, 3402, ++ 3405, 3406, 3415, 3424, 3426, 3430, 3440, 3449, 3450, 3458, ++ 3461, 3482, 3507, 3517, 3520, 3530, 3535, 3538, 3542, 3544, ++ 3570, 3572, 3585, 3633, 3634, 3636, 3647, 3648, 3654, 3655, ++ 3663, 3664, 3674, 3713, 3716, 3719, 3722, 3725, 3732, 3737, ++ 3745, 3749, 3751, 3754, 3757, 3761, 3762, 3764, 3771, 3773, ++ 3776, 3782, 3784, 3792, 3804, 3840, 3841, 3844, 3859, 3860, ++ 3861, 3864, 3866, 3872, 3882, 3892, 3893, 3894, 3895, 3896, ++ 3897, 3898, 3899, 3900, 3901, 3902, 3904, 3913, 3953, 3967, ++ 3968, 3973, 3974, 3976, 3981, 3993, 4030, 4038, 4039, 4046, ++ 4048, 4053, 4057, 4096, 4139, 4141, 4145, 4146, 4152, 4153, ++ 4155, 4157, 4159, 4160, 4170, 4176, 4182, 4184, 4186, 4190, ++ 4193, 4194, 4197, 4199, 4206, 4209, 4213, 4226, 4227, 4229, ++ 4231, 4237, 4238, 4239, 4240, 4250, 4253, 4254, 4256, 4295, ++ 4301, 4304, 4347, 4348, 4349, 4682, 4688, 4696, 4698, 4704, ++ 4746, 4752, 4786, 4792, 4800, 4802, 4808, 4824, 4882, 4888, ++ 4957, 4960, 4969, 4992, 5008, 5024, 5120, 5121, 5741, 5743, ++ 5760, 5761, 5787, 5788, 5792, 5867, 5870, 5888, 5902, 5906, ++ 5920, 5938, 5941, 5952, 5970, 5984, 5998, 6002, 6016, 6068, ++ 6070, 6071, 6078, 6086, 6087, 6089, 6100, 6103, 6104, 6107, ++ 6108, 6109, 6112, 6128, 6144, 6150, 6151, 6155, 6158, 6160, ++ 6176, 6211, 6212, 6272, 6313, 6314, 6320, 6400, 6432, 6435, ++ 6439, 6441, 6448, 6450, 6451, 6457, 6464, 6468, 6470, 6480, ++ 6512, 6528, 6576, 6593, 6600, 6608, 6618, 6622, 6656, 6679, ++ 6681, 6686, 6688, 6741, 6742, 6743, 6744, 6752, 6753, 6754, ++ 6755, 6757, 6765, 6771, 6783, 6784, 6800, 6816, 6823, 6824, ++ 6912, 6916, 6917, 6964, 6965, 6966, 6971, 6972, 6973, 6978, ++ 6979, 6981, 6992, 7002, 7009, 7019, 7028, 7040, 7042, 7043, ++ 7073, 7074, 7078, 7080, 7082, 7083, 7084, 7086, 7088, 7098, ++ 7142, 7143, 7144, 7146, 7149, 7150, 7151, 7154, 7164, 7168, ++ 7204, 7212, 7220, 7222, 7227, 7232, 7245, 7248, 7258, 7288, ++ 7294, 7360, 7376, 7379, 7380, 7393, 7394, 7401, 7405, 7406, ++ 7410, 7412, 7413, 7424, 7468, 7531, 7544, 7545, 7579, 7616, ++ 7676, 7680, 7830, 7838, 7936, 7944, 7952, 7960, 7968, 7976, ++ 7984, 7992, 8000, 8008, 8016, 8025, 8027, 8029, 8031, 8033, ++ 8040, 8048, 8064, 8072, 8080, 8088, 8096, 8104, 8112, 8118, ++ 8120, 8124, 8125, 8126, 8127, 8130, 8134, 8136, 8140, 8141, ++ 8144, 8150, 8152, 8157, 8160, 8168, 8173, 8178, 8182, 8184, ++ 8188, 8189, 8192, 8203, 8208, 8214, 8216, 8217, 8218, 8219, ++ 8221, 8222, 8223, 8224, 8232, 8233, 8234, 8239, 8240, 8249, ++ 8250, 8251, 8255, 8257, 8260, 8261, 8262, 8263, 8274, 8275, ++ 8276, 8277, 8287, 8288, 8298, 8304, 8305, 8308, 8314, 8317, ++ 8318, 8319, 8320, 8330, 8333, 8334, 8336, 8352, 8400, 8413, ++ 8417, 8418, 8421, 8448, 8450, 8451, 8455, 8456, 8458, 8459, ++ 8462, 8464, 8467, 8468, 8469, 8470, 8472, 8473, 8478, 8484, ++ 8485, 8486, 8487, 8488, 8489, 8490, 8494, 8495, 8496, 8500, ++ 8501, 8505, 8506, 8508, 8510, 8512, 8517, 8519, 8522, 8523, ++ 8524, 8526, 8527, 8528, 8544, 8579, 8581, 8585, 8592, 8597, ++ 8602, 8604, 8608, 8609, 8611, 8612, 8614, 8615, 8622, 8623, ++ 8654, 8656, 8658, 8659, 8660, 8661, 8692, 8960, 8968, 8972, ++ 8992, 8994, 9001, 9002, 9003, 9084, 9085, 9115, 9140, 9180, ++ 9186, 9216, 9280, 9312, 9372, 9450, 9472, 9655, 9656, 9665, ++ 9666, 9720, 9728, 9839, 9840, 9985, 10088, 10089, 10090, 10091, ++ 10092, 10093, 10094, 10095, 10096, 10097, 10098, 10099, 10100, 10101, ++ 10102, 10132, 10176, 10181, 10182, 10183, 10214, 10215, 10216, 10217, ++ 10218, 10219, 10220, 10221, 10222, 10223, 10224, 10240, 10496, 10627, ++ 10628, 10629, 10630, 10631, 10632, 10633, 10634, 10635, 10636, 10637, ++ 10638, 10639, 10640, 10641, 10642, 10643, 10644, 10645, 10646, 10647, ++ 10648, 10649, 10712, 10713, 10714, 10715, 10716, 10748, 10749, 10750, ++ 11008, 11056, 11077, 11079, 11088, 11264, 11312, 11360, 11363, 11365, ++ 11367, 11374, 11377, 11378, 11380, 11381, 11383, 11388, 11390, 11393, ++ 11394, 11492, 11493, 11499, 11503, 11506, 11513, 11517, 11518, 11520, ++ 11559, 11565, 11568, 11631, 11632, 11647, 11648, 11680, 11688, 11696, ++ 11704, 11712, 11720, 11728, 11736, 11744, 11776, 11778, 11779, 11780, ++ 11781, 11782, 11785, 11786, 11787, 11788, 11789, 11790, 11799, 11800, ++ 11802, 11803, 11804, 11805, 11806, 11808, 11809, 11810, 11811, 11812, ++ 11813, 11814, 11815, 11816, 11817, 11818, 11823, 11824, 11834, 11904, ++ 11931, 12032, 12272, 12288, 12289, 12292, 12293, 12294, 12295, 12296, ++ 12297, 12298, 12299, 12300, 12301, 12302, 12303, 12304, 12305, 12306, ++ 12308, 12309, 12310, 12311, 12312, 12313, 12314, 12315, 12316, 12317, ++ 12318, 12320, 12321, 12330, 12334, 12336, 12337, 12342, 12344, 12347, ++ 12348, 12349, 12350, 12353, 12441, 12443, 12445, 12447, 12448, 12449, ++ 12539, 12540, 12543, 12549, 12593, 12688, 12690, 12694, 12704, 12736, ++ 12784, 12800, 12832, 12842, 12872, 12880, 12881, 12896, 12928, 12938, ++ 12977, 12992, 13056, 13312, 19893, 19904, 19968, 40908, 40960, 40981, ++ 40982, 42128, 42192, 42232, 42238, 42240, 42508, 42509, 42512, 42528, ++ 42538, 42560, 42606, 42607, 42608, 42611, 42612, 42622, 42623, 42624, ++ 42655, 42656, 42726, 42736, 42738, 42752, 42775, 42784, 42786, 42800, ++ 42802, 42864, 42865, 42873, 42878, 42888, 42889, 42891, 42896, 42912, ++ 43000, 43002, 43003, 43010, 43011, 43014, 43015, 43019, 43020, 43043, ++ 43045, 43047, 43048, 43056, 43062, 43064, 43065, 43072, 43124, 43136, ++ 43138, 43188, 43204, 43214, 43216, 43232, 43250, 43256, 43259, 43264, ++ 43274, 43302, 43310, 43312, 43335, 43346, 43359, 43360, 43392, 43395, ++ 43396, 43443, 43444, 43446, 43450, 43452, 43453, 43457, 43471, 43472, ++ 43486, 43520, 43561, 43567, 43569, 43571, 43573, 43584, 43587, 43588, ++ 43596, 43597, 43600, 43612, 43616, 43632, 43633, 43639, 43642, 43643, ++ 43648, 43696, 43697, 43698, 43701, 43703, 43705, 43710, 43712, 43713, ++ 43714, 43739, 43741, 43742, 43744, 43755, 43756, 43758, 43760, 43762, ++ 43763, 43765, 43766, 43777, 43785, 43793, 43808, 43816, 43968, 44003, ++ 44005, 44006, 44008, 44009, 44011, 44012, 44013, 44016, 44032, 55203, ++ 55216, 55243, 55296, 56191, 56319, 57343, 57344, 63743, 63744, 64112, ++ 64256, 64275, 64285, 64286, 64287, 64297, 64298, 64312, 64318, 64320, ++ 64323, 64326, 64434, 64467, 64830, 64831, 64848, 64914, 65008, 65020, ++ 65021, 65024, 65040, 65047, 65048, 65049, 65056, 65072, 65073, 65075, ++ 65077, 65078, 65079, 65080, 65081, 65082, 65083, 65084, 65085, 65086, ++ 65087, 65088, 65089, 65090, 65091, 65092, 65093, 65095, 65096, 65097, ++ 65101, 65104, 65108, 65112, 65113, 65114, 65115, 65116, 65117, 65118, ++ 65119, 65122, 65123, 65124, 65128, 65129, 65130, 65136, 65142, 65279, ++ 65281, 65284, 65285, 65288, 65289, 65290, 65291, 65292, 65293, 65294, ++ 65296, 65306, 65308, 65311, 65313, 65339, 65340, 65341, 65342, 65343, ++ 65344, 65345, 65371, 65372, 65373, 65374, 65375, 65376, 65377, 65378, ++ 65379, 65380, 65382, 65392, 65393, 65438, 65440, 65474, 65482, 65490, ++ 65498, 65504, 65506, 65507, 65508, 65509, 65512, 65513, 65517, 65529, ++ 65532, 0, 13, 40, 60, 63, 80, 128, 256, 263, ++ 311, 320, 373, 377, 394, 400, 464, 509, 640, 672, ++ 768, 800, 816, 833, 834, 842, 896, 927, 928, 968, ++ 976, 977, 1024, 1064, 1104, 1184, 2048, 2056, 2058, 2103, ++ 2108, 2111, 2135, 2136, 2304, 2326, 2335, 2336, 2367, 2432, ++ 2494, 2560, 2561, 2565, 2572, 2576, 2581, 2585, 2616, 2623, ++ 2624, 2640, 2656, 2685, 2687, 2816, 2873, 2880, 2904, 2912, ++ 2936, 3072, 3680, 4096, 4097, 4098, 4099, 4152, 4167, 4178, ++ 4198, 4224, 4226, 4227, 4272, 4275, 4279, 4281, 4283, 4285, ++ 4286, 4304, 4336, 4352, 4355, 4391, 4396, 4397, 4406, 4416, ++ 4480, 4482, 4483, 4531, 4534, 4543, 4545, 4549, 4560, 5760, ++ 5803, 5804, 5805, 5806, 5808, 5814, 5815, 5824, 8192, 9216, ++ 9328, 12288, 26624, 28416, 28496, 28497, 28559, 28563, 45056, 53248, ++ 53504, 53545, 53605, 53607, 53610, 53613, 53619, 53627, 53635, 53637, ++ 53644, 53674, 53678, 53760, 53826, 53829, 54016, 54112, 54272, 54298, ++ 54324, 54350, 54358, 54376, 54402, 54428, 54430, 54434, 54437, 54441, ++ 54446, 54454, 54459, 54461, 54469, 54480, 54506, 54532, 54535, 54541, ++ 54550, 54558, 54584, 54587, 54592, 54598, 54602, 54610, 54636, 54662, ++ 54688, 54714, 54740, 54766, 54792, 54818, 54844, 54870, 54896, 54922, ++ 54952, 54977, 54978, 55003, 55004, 55010, 55035, 55036, 55061, 55062, ++ 55068, 55093, 55094, 55119, 55120, 55126, 55151, 55152, 55177, 55178, ++ 55184, 55209, 55210, 55235, 55236, 55242, 55246, 60928, 60933, 60961, ++ 60964, 60967, 60969, 60980, 60985, 60987, 60994, 60999, 61001, 61003, ++ 61005, 61009, 61012, 61015, 61017, 61019, 61021, 61023, 61025, 61028, ++ 61031, 61036, 61044, 61049, 61054, 61056, 61067, 61089, 61093, 61099, ++ 61168, 61440, 61488, 61600, 61617, 61633, 61649, 61696, 61712, 61744, ++ 61808, 61926, 61968, 62016, 62032, 62208, 62256, 62263, 62336, 62368, ++ 62406, 62432, 62464, 62528, 62530, 62713, 62720, 62784, 62800, 62971, ++ 63045, 63104, 63232, 0, 42710, 42752, 46900, 46912, 47133, 63488, ++ 1, 32, 256, 0, 65533, ++ }; ++static u16 aFts5UnicodeData[] = { ++ 1025, 61, 117, 55, 117, 54, 50, 53, 57, 53, ++ 49, 85, 333, 85, 121, 85, 841, 54, 53, 50, ++ 56, 48, 56, 837, 54, 57, 50, 57, 1057, 61, ++ 53, 151, 58, 53, 56, 58, 39, 52, 57, 34, ++ 58, 56, 58, 57, 79, 56, 37, 85, 56, 47, ++ 39, 51, 111, 53, 745, 57, 233, 773, 57, 261, ++ 1822, 37, 542, 37, 1534, 222, 69, 73, 37, 126, ++ 126, 73, 69, 137, 37, 73, 37, 105, 101, 73, ++ 37, 73, 37, 190, 158, 37, 126, 126, 73, 37, ++ 126, 94, 37, 39, 94, 69, 135, 41, 40, 37, ++ 41, 40, 37, 41, 40, 37, 542, 37, 606, 37, ++ 41, 40, 37, 126, 73, 37, 1886, 197, 73, 37, ++ 73, 69, 126, 105, 37, 286, 2181, 39, 869, 582, ++ 152, 390, 472, 166, 248, 38, 56, 38, 568, 3596, ++ 158, 38, 56, 94, 38, 101, 53, 88, 41, 53, ++ 105, 41, 73, 37, 553, 297, 1125, 94, 37, 105, ++ 101, 798, 133, 94, 57, 126, 94, 37, 1641, 1541, ++ 1118, 58, 172, 75, 1790, 478, 37, 2846, 1225, 38, ++ 213, 1253, 53, 49, 55, 1452, 49, 44, 53, 76, ++ 53, 76, 53, 44, 871, 103, 85, 162, 121, 85, ++ 55, 85, 90, 364, 53, 85, 1031, 38, 327, 684, ++ 333, 149, 71, 44, 3175, 53, 39, 236, 34, 58, ++ 204, 70, 76, 58, 140, 71, 333, 103, 90, 39, ++ 469, 34, 39, 44, 967, 876, 2855, 364, 39, 333, ++ 1063, 300, 70, 58, 117, 38, 711, 140, 38, 300, ++ 38, 108, 38, 172, 501, 807, 108, 53, 39, 359, ++ 876, 108, 42, 1735, 44, 42, 44, 39, 106, 268, ++ 138, 44, 74, 39, 236, 327, 76, 85, 333, 53, ++ 38, 199, 231, 44, 74, 263, 71, 711, 231, 39, ++ 135, 44, 39, 106, 140, 74, 74, 44, 39, 42, ++ 71, 103, 76, 333, 71, 87, 207, 58, 55, 76, ++ 42, 199, 71, 711, 231, 71, 71, 71, 44, 106, ++ 76, 76, 108, 44, 135, 39, 333, 76, 103, 44, ++ 76, 42, 295, 103, 711, 231, 71, 167, 44, 39, ++ 106, 172, 76, 42, 74, 44, 39, 71, 76, 333, ++ 53, 55, 44, 74, 263, 71, 711, 231, 71, 167, ++ 44, 39, 42, 44, 42, 140, 74, 74, 44, 44, ++ 42, 71, 103, 76, 333, 58, 39, 207, 44, 39, ++ 199, 103, 135, 71, 39, 71, 71, 103, 391, 74, ++ 44, 74, 106, 106, 44, 39, 42, 333, 111, 218, ++ 55, 58, 106, 263, 103, 743, 327, 167, 39, 108, ++ 138, 108, 140, 76, 71, 71, 76, 333, 239, 58, ++ 74, 263, 103, 743, 327, 167, 44, 39, 42, 44, ++ 170, 44, 74, 74, 76, 74, 39, 71, 76, 333, ++ 71, 74, 263, 103, 1319, 39, 106, 140, 106, 106, ++ 44, 39, 42, 71, 76, 333, 207, 58, 199, 74, ++ 583, 775, 295, 39, 231, 44, 106, 108, 44, 266, ++ 74, 53, 1543, 44, 71, 236, 55, 199, 38, 268, ++ 53, 333, 85, 71, 39, 71, 39, 39, 135, 231, ++ 103, 39, 39, 71, 135, 44, 71, 204, 76, 39, ++ 167, 38, 204, 333, 135, 39, 122, 501, 58, 53, ++ 122, 76, 218, 333, 335, 58, 44, 58, 44, 58, ++ 44, 54, 50, 54, 50, 74, 263, 1159, 460, 42, ++ 172, 53, 76, 167, 364, 1164, 282, 44, 218, 90, ++ 181, 154, 85, 1383, 74, 140, 42, 204, 42, 76, ++ 74, 76, 39, 333, 213, 199, 74, 76, 135, 108, ++ 39, 106, 71, 234, 103, 140, 423, 44, 74, 76, ++ 202, 44, 39, 42, 333, 106, 44, 90, 1225, 41, ++ 41, 1383, 53, 38, 10631, 135, 231, 39, 135, 1319, ++ 135, 1063, 135, 231, 39, 135, 487, 1831, 135, 2151, ++ 108, 309, 655, 519, 346, 2727, 49, 19847, 85, 551, ++ 61, 839, 54, 50, 2407, 117, 110, 423, 135, 108, ++ 583, 108, 85, 583, 76, 423, 103, 76, 1671, 76, ++ 42, 236, 266, 44, 74, 364, 117, 38, 117, 55, ++ 39, 44, 333, 335, 213, 49, 149, 108, 61, 333, ++ 1127, 38, 1671, 1319, 44, 39, 2247, 935, 108, 138, ++ 76, 106, 74, 44, 202, 108, 58, 85, 333, 967, ++ 167, 1415, 554, 231, 74, 333, 47, 1114, 743, 76, ++ 106, 85, 1703, 42, 44, 42, 236, 44, 42, 44, ++ 74, 268, 202, 332, 44, 333, 333, 245, 38, 213, ++ 140, 42, 1511, 44, 42, 172, 42, 44, 170, 44, ++ 74, 231, 333, 245, 346, 300, 314, 76, 42, 967, ++ 42, 140, 74, 76, 42, 44, 74, 71, 333, 1415, ++ 44, 42, 76, 106, 44, 42, 108, 74, 149, 1159, ++ 266, 268, 74, 76, 181, 333, 103, 333, 967, 198, ++ 85, 277, 108, 53, 428, 42, 236, 135, 44, 135, ++ 74, 44, 71, 1413, 2022, 421, 38, 1093, 1190, 1260, ++ 140, 4830, 261, 3166, 261, 265, 197, 201, 261, 265, ++ 261, 265, 197, 201, 261, 41, 41, 41, 94, 229, ++ 265, 453, 261, 264, 261, 264, 261, 264, 165, 69, ++ 137, 40, 56, 37, 120, 101, 69, 137, 40, 120, ++ 133, 69, 137, 120, 261, 169, 120, 101, 69, 137, ++ 40, 88, 381, 162, 209, 85, 52, 51, 54, 84, ++ 51, 54, 52, 277, 59, 60, 162, 61, 309, 52, ++ 51, 149, 80, 117, 57, 54, 50, 373, 57, 53, ++ 48, 341, 61, 162, 194, 47, 38, 207, 121, 54, ++ 50, 38, 335, 121, 54, 50, 422, 855, 428, 139, ++ 44, 107, 396, 90, 41, 154, 41, 90, 37, 105, ++ 69, 105, 37, 58, 41, 90, 57, 169, 218, 41, ++ 58, 41, 58, 41, 58, 137, 58, 37, 137, 37, ++ 135, 37, 90, 69, 73, 185, 94, 101, 58, 57, ++ 90, 37, 58, 527, 1134, 94, 142, 47, 185, 186, ++ 89, 154, 57, 90, 57, 90, 57, 250, 57, 1018, ++ 89, 90, 57, 58, 57, 1018, 8601, 282, 153, 666, ++ 89, 250, 54, 50, 2618, 57, 986, 825, 1306, 217, ++ 602, 1274, 378, 1935, 2522, 719, 5882, 57, 314, 57, ++ 1754, 281, 3578, 57, 4634, 3322, 54, 50, 54, 50, ++ 54, 50, 54, 50, 54, 50, 54, 50, 54, 50, ++ 975, 1434, 185, 54, 50, 1017, 54, 50, 54, 50, ++ 54, 50, 54, 50, 54, 50, 537, 8218, 4217, 54, ++ 50, 54, 50, 54, 50, 54, 50, 54, 50, 54, ++ 50, 54, 50, 54, 50, 54, 50, 54, 50, 54, ++ 50, 2041, 54, 50, 54, 50, 1049, 54, 50, 8281, ++ 1562, 697, 90, 217, 346, 1513, 1509, 126, 73, 69, ++ 254, 105, 37, 94, 37, 94, 165, 70, 105, 37, ++ 3166, 37, 218, 158, 108, 94, 149, 47, 85, 1221, ++ 37, 37, 1799, 38, 53, 44, 743, 231, 231, 231, ++ 231, 231, 231, 231, 231, 1036, 85, 52, 51, 52, ++ 51, 117, 52, 51, 53, 52, 51, 309, 49, 85, ++ 49, 53, 52, 51, 85, 52, 51, 54, 50, 54, ++ 50, 54, 50, 54, 50, 181, 38, 341, 81, 858, ++ 2874, 6874, 410, 61, 117, 58, 38, 39, 46, 54, ++ 50, 54, 50, 54, 50, 54, 50, 54, 50, 90, ++ 54, 50, 54, 50, 54, 50, 54, 50, 49, 54, ++ 82, 58, 302, 140, 74, 49, 166, 90, 110, 38, ++ 39, 53, 90, 2759, 76, 88, 70, 39, 49, 2887, ++ 53, 102, 39, 1319, 3015, 90, 143, 346, 871, 1178, ++ 519, 1018, 335, 986, 271, 58, 495, 1050, 335, 1274, ++ 495, 2042, 8218, 39, 39, 2074, 39, 39, 679, 38, ++ 36583, 1786, 1287, 198, 85, 8583, 38, 117, 519, 333, ++ 71, 1502, 39, 44, 107, 53, 332, 53, 38, 798, ++ 44, 2247, 334, 76, 213, 760, 294, 88, 478, 69, ++ 2014, 38, 261, 190, 350, 38, 88, 158, 158, 382, ++ 70, 37, 231, 44, 103, 44, 135, 44, 743, 74, ++ 76, 42, 154, 207, 90, 55, 58, 1671, 149, 74, ++ 1607, 522, 44, 85, 333, 588, 199, 117, 39, 333, ++ 903, 268, 85, 743, 364, 74, 53, 935, 108, 42, ++ 1511, 44, 74, 140, 74, 44, 138, 437, 38, 333, ++ 85, 1319, 204, 74, 76, 74, 76, 103, 44, 263, ++ 44, 42, 333, 149, 519, 38, 199, 122, 39, 42, ++ 1543, 44, 39, 108, 71, 76, 167, 76, 39, 44, ++ 39, 71, 38, 85, 359, 42, 76, 74, 85, 39, ++ 70, 42, 44, 199, 199, 199, 231, 231, 1127, 74, ++ 44, 74, 44, 74, 53, 42, 44, 333, 39, 39, ++ 743, 1575, 36, 68, 68, 36, 63, 63, 11719, 3399, ++ 229, 165, 39, 44, 327, 57, 423, 167, 39, 71, ++ 71, 3463, 536, 11623, 54, 50, 2055, 1735, 391, 55, ++ 58, 524, 245, 54, 50, 53, 236, 53, 81, 80, ++ 54, 50, 54, 50, 54, 50, 54, 50, 54, 50, ++ 54, 50, 54, 50, 54, 50, 85, 54, 50, 149, ++ 112, 117, 149, 49, 54, 50, 54, 50, 54, 50, ++ 117, 57, 49, 121, 53, 55, 85, 167, 4327, 34, ++ 117, 55, 117, 54, 50, 53, 57, 53, 49, 85, ++ 333, 85, 121, 85, 841, 54, 53, 50, 56, 48, ++ 56, 837, 54, 57, 50, 57, 54, 50, 53, 54, ++ 50, 85, 327, 38, 1447, 70, 999, 199, 199, 199, ++ 103, 87, 57, 56, 58, 87, 58, 153, 90, 98, ++ 90, 391, 839, 615, 71, 487, 455, 3943, 117, 1455, ++ 314, 1710, 143, 570, 47, 410, 1466, 44, 935, 1575, ++ 999, 143, 551, 46, 263, 46, 967, 53, 1159, 263, ++ 53, 174, 1289, 1285, 2503, 333, 199, 39, 1415, 71, ++ 39, 743, 53, 271, 711, 207, 53, 839, 53, 1799, ++ 71, 39, 108, 76, 140, 135, 103, 871, 108, 44, ++ 271, 309, 935, 79, 53, 1735, 245, 711, 271, 615, ++ 271, 2343, 1007, 42, 44, 42, 1703, 492, 245, 655, ++ 333, 76, 42, 1447, 106, 140, 74, 76, 85, 34, ++ 149, 807, 333, 108, 1159, 172, 42, 268, 333, 149, ++ 76, 42, 1543, 106, 300, 74, 135, 149, 333, 1383, ++ 44, 42, 44, 74, 204, 42, 44, 333, 28135, 3182, ++ 149, 34279, 18215, 2215, 39, 1482, 140, 422, 71, 7898, ++ 1274, 1946, 74, 108, 122, 202, 258, 268, 90, 236, ++ 986, 140, 1562, 2138, 108, 58, 2810, 591, 841, 837, ++ 841, 229, 581, 841, 837, 41, 73, 41, 73, 137, ++ 265, 133, 37, 229, 357, 841, 837, 73, 137, 265, ++ 233, 837, 73, 137, 169, 41, 233, 837, 841, 837, ++ 841, 837, 841, 837, 841, 837, 841, 837, 841, 901, ++ 809, 57, 805, 57, 197, 809, 57, 805, 57, 197, ++ 809, 57, 805, 57, 197, 809, 57, 805, 57, 197, ++ 809, 57, 805, 57, 197, 94, 1613, 135, 871, 71, ++ 39, 39, 327, 135, 39, 39, 39, 39, 39, 39, ++ 103, 71, 39, 39, 39, 39, 39, 39, 71, 39, ++ 135, 231, 135, 135, 39, 327, 551, 103, 167, 551, ++ 89, 1434, 3226, 506, 474, 506, 506, 367, 1018, 1946, ++ 1402, 954, 1402, 314, 90, 1082, 218, 2266, 666, 1210, ++ 186, 570, 2042, 58, 5850, 154, 2010, 154, 794, 2266, ++ 378, 2266, 3738, 39, 39, 39, 39, 39, 39, 17351, ++ 34, 3074, 7692, 63, 63, ++ }; ++ ++static int sqlite3Fts5UnicodeCategory(int iCode) { ++ int iRes = -1; ++ int iHi; ++ int iLo; ++ int ret; ++ u16 iKey; ++ ++ if( iCode>=(1<<20) ){ ++ return 0; ++ } ++ iLo = aFts5UnicodeBlock[(iCode>>16)]; ++ iHi = aFts5UnicodeBlock[1+(iCode>>16)]; ++ iKey = (iCode & 0xFFFF); ++ while( iHi>iLo ){ ++ int iTest = (iHi + iLo) / 2; ++ assert( iTest>=iLo && iTest<iHi ); ++ if( iKey>=aFts5UnicodeMap[iTest] ){ ++ iRes = iTest; ++ iLo = iTest+1; ++ }else{ ++ iHi = iTest; ++ } ++ } ++ ++ if( iRes<0 ) return 0; ++ if( iKey>=(aFts5UnicodeMap[iRes]+(aFts5UnicodeData[iRes]>>5)) ) return 0; ++ ret = aFts5UnicodeData[iRes] & 0x1F; ++ if( ret!=30 ) return ret; ++ return ((iKey - aFts5UnicodeMap[iRes]) & 0x01) ? 5 : 9; ++} ++ ++static void sqlite3Fts5UnicodeAscii(u8 *aArray, u8 *aAscii){ ++ int i = 0; ++ int iTbl = 0; ++ while( i<128 ){ ++ int bToken = aArray[ aFts5UnicodeData[iTbl] & 0x1F ]; ++ int n = (aFts5UnicodeData[iTbl] >> 5) + i; ++ for(; i<128 && i<n; i++){ ++ aAscii[i] = (u8)bToken; ++ } ++ iTbl++; ++ } ++} ++ ++ + /* + ** 2015 May 30 + ** +@@ -209294,6 +219884,8 @@ + i64 *pp = &pCsr->iInstPos; + int *po = &pCsr->iInstOff; + ++ assert( sqlite3Fts5IterEof(pIter)==0 ); ++ assert( pCsr->bEof==0 ); + while( eDetail==FTS5_DETAIL_NONE + || sqlite3Fts5PoslistNext64(pIter->pData, pIter->nData, po, pp) + ){ +@@ -209303,7 +219895,7 @@ + rc = sqlite3Fts5IterNextScan(pCsr->pIter); + if( rc==SQLITE_OK ){ + rc = fts5VocabInstanceNewTerm(pCsr); +- if( eDetail==FTS5_DETAIL_NONE ) break; ++ if( pCsr->bEof || eDetail==FTS5_DETAIL_NONE ) break; + } + if( rc ){ + pCsr->bEof = 1; +@@ -209618,6 +220210,7 @@ + /* xSavepoint */ 0, + /* xRelease */ 0, + /* xRollbackTo */ 0, ++ /* xShadowName */ 0 + }; + void *p = (void*)pGlobal; + +@@ -209625,8 +220218,6 @@ + } + + +- +- + + #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5) */ + +@@ -209900,6 +220491,7 @@ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ ++ 0, /* xShadowName */ + }; + + #endif /* SQLITE_OMIT_VIRTUALTABLE */ +@@ -209932,9 +220524,9 @@ + #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ + + /************** End of stmt.c ************************************************/ +-#if __LINE__!=209935 ++#if __LINE__!=220527 + #undef SQLITE_SOURCE_ID +-#define SQLITE_SOURCE_ID "2018-04-10 17:39:29 4bb2294022060e61de7da5c227a69ccd846ba330e31626ebcd59a94efd14alt2" ++#define SQLITE_SOURCE_ID "2018-12-01 12:34:55 bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238alt2" + #endif + /* Return the source-id for this library */ + SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } +--- contrib/sqlite3/sqlite3.h.orig ++++ contrib/sqlite3/sqlite3.h +@@ -123,9 +123,9 @@ + ** [sqlite3_libversion_number()], [sqlite3_sourceid()], + ** [sqlite_version()] and [sqlite_source_id()]. + */ +-#define SQLITE_VERSION "3.23.1" +-#define SQLITE_VERSION_NUMBER 3023001 +-#define SQLITE_SOURCE_ID "2018-04-10 17:39:29 4bb2294022060e61de7da5c227a69ccd846ba330e31626ebcd59a94efd148b3b" ++#define SQLITE_VERSION "3.26.0" ++#define SQLITE_VERSION_NUMBER 3026000 ++#define SQLITE_SOURCE_ID "2018-12-01 12:34:55 bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238b4f9" + + /* + ** CAPI3REF: Run-Time Library Version Numbers +@@ -472,6 +472,7 @@ + */ + #define SQLITE_ERROR_MISSING_COLLSEQ (SQLITE_ERROR | (1<<8)) + #define SQLITE_ERROR_RETRY (SQLITE_ERROR | (2<<8)) ++#define SQLITE_ERROR_SNAPSHOT (SQLITE_ERROR | (3<<8)) + #define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) + #define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) + #define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) +@@ -504,6 +505,7 @@ + #define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8)) + #define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8)) + #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) ++#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) + #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) + #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) + #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) +@@ -510,7 +512,9 @@ + #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) + #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) + #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) ++#define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */ + #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) ++#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8)) + #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) + #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) + #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) +@@ -884,7 +888,8 @@ + ** <li>[[SQLITE_FCNTL_PERSIST_WAL]] + ** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the + ** persistent [WAL | Write Ahead Log] setting. By default, the auxiliary +-** write ahead log and shared memory files used for transaction control ++** write ahead log ([WAL file]) and shared memory ++** files used for transaction control + ** are automatically deleted when the latest connection to the database + ** closes. Setting persistent WAL mode causes those files to persist after + ** close. Persisting the files is useful when other processes that do not +@@ -1070,6 +1075,26 @@ + ** a file lock using the xLock or xShmLock methods of the VFS to wait + ** for up to M milliseconds before failing, where M is the single + ** unsigned integer parameter. ++** ++** <li>[[SQLITE_FCNTL_DATA_VERSION]] ++** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to ++** a database file. The argument is a pointer to a 32-bit unsigned integer. ++** The "data version" for the pager is written into the pointer. The ++** "data version" changes whenever any change occurs to the corresponding ++** database file, either through SQL statements on the same database ++** connection or through transactions committed by separate database ++** connections possibly in other processes. The [sqlite3_total_changes()] ++** interface can be used to find if any database on the connection has changed, ++** but that interface responds to changes on TEMP as well as MAIN and does ++** not provide a mechanism to detect changes to MAIN only. Also, the ++** [sqlite3_total_changes()] interface responds to internal changes only and ++** omits changes made by other database connections. The ++** [PRAGMA data_version] command provide a mechanism to detect changes to ++** a single attached database that occur due to other database connections, ++** but omits changes implemented by the database connection on which it is ++** called. This file control is the only mechanism to detect changes that ++** happen either internally or externally and that are associated with ++** a particular attached database. + ** </ul> + */ + #define SQLITE_FCNTL_LOCKSTATE 1 +@@ -1105,6 +1130,7 @@ + #define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32 + #define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33 + #define SQLITE_FCNTL_LOCK_TIMEOUT 34 ++#define SQLITE_FCNTL_DATA_VERSION 35 + + /* deprecated names */ + #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE +@@ -1930,6 +1956,22 @@ + ** I/O required to support statement rollback. + ** The default value for this setting is controlled by the + ** [SQLITE_STMTJRNL_SPILL] compile-time option. ++** ++** [[SQLITE_CONFIG_SORTERREF_SIZE]] ++** <dt>SQLITE_CONFIG_SORTERREF_SIZE ++** <dd>The SQLITE_CONFIG_SORTERREF_SIZE option accepts a single parameter ++** of type (int) - the new value of the sorter-reference size threshold. ++** Usually, when SQLite uses an external sort to order records according ++** to an ORDER BY clause, all fields required by the caller are present in the ++** sorted records. However, if SQLite determines based on the declared type ++** of a table column that its values are likely to be very large - larger ++** than the configured sorter-reference size threshold - then a reference ++** is stored in each sorted record and the required column values loaded ++** from the database as records are returned in sorted order. The default ++** value for this option is to never use this optimization. Specifying a ++** negative value for this option restores the default behaviour. ++** This option is only available if SQLite is compiled with the ++** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option. + ** </dl> + */ + #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ +@@ -1959,6 +2001,7 @@ + #define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */ + #define SQLITE_CONFIG_STMTJRNL_SPILL 26 /* int nByte */ + #define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */ ++#define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */ + + /* + ** CAPI3REF: Database Connection Configuration Options +@@ -1974,6 +2017,7 @@ + ** is invoked. + ** + ** <dl> ++** [[SQLITE_DBCONFIG_LOOKASIDE]] + ** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt> + ** <dd> ^This option takes three additional arguments that determine the + ** [lookaside memory allocator] configuration for the [database connection]. +@@ -1996,6 +2040,7 @@ + ** memory is in use leaves the configuration unchanged and returns + ** [SQLITE_BUSY].)^</dd> + ** ++** [[SQLITE_DBCONFIG_ENABLE_FKEY]] + ** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt> + ** <dd> ^This option is used to enable or disable the enforcement of + ** [foreign key constraints]. There should be two additional arguments. +@@ -2006,6 +2051,7 @@ + ** following this call. The second parameter may be a NULL pointer, in + ** which case the FK enforcement setting is not reported back. </dd> + ** ++** [[SQLITE_DBCONFIG_ENABLE_TRIGGER]] + ** <dt>SQLITE_DBCONFIG_ENABLE_TRIGGER</dt> + ** <dd> ^This option is used to enable or disable [CREATE TRIGGER | triggers]. + ** There should be two additional arguments. +@@ -2016,6 +2062,7 @@ + ** following this call. The second parameter may be a NULL pointer, in + ** which case the trigger setting is not reported back. </dd> + ** ++** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]] + ** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt> + ** <dd> ^This option is used to enable or disable the two-argument + ** version of the [fts3_tokenizer()] function which is part of the +@@ -2029,6 +2076,7 @@ + ** following this call. The second parameter may be a NULL pointer, in + ** which case the new setting is not reported back. </dd> + ** ++** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]] + ** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt> + ** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()] + ** interface independently of the [load_extension()] SQL function. +@@ -2046,7 +2094,7 @@ + ** be a NULL pointer, in which case the new setting is not reported back. + ** </dd> + ** +-** <dt>SQLITE_DBCONFIG_MAINDBNAME</dt> ++** [[SQLITE_DBCONFIG_MAINDBNAME]] <dt>SQLITE_DBCONFIG_MAINDBNAME</dt> + ** <dd> ^This option is used to change the name of the "main" database + ** schema. ^The sole argument is a pointer to a constant UTF8 string + ** which will become the new schema name in place of "main". ^SQLite +@@ -2055,6 +2103,7 @@ + ** until after the database connection closes. + ** </dd> + ** ++** [[SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE]] + ** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt> + ** <dd> Usually, when a database in wal mode is closed or detached from a + ** database handle, SQLite checks if this will mean that there are now no +@@ -2068,7 +2117,7 @@ + ** have been disabled - 0 if they are not disabled, 1 if they are. + ** </dd> + ** +-** <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt> ++** [[SQLITE_DBCONFIG_ENABLE_QPSG]] <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt> + ** <dd>^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates + ** the [query planner stability guarantee] (QPSG). When the QPSG is active, + ** a single SQL query statement will always use the same algorithm regardless +@@ -2084,7 +2133,7 @@ + ** following this call. + ** </dd> + ** +-** <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt> ++** [[SQLITE_DBCONFIG_TRIGGER_EQP]] <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt> + ** <dd> By default, the output of EXPLAIN QUERY PLAN commands does not + ** include output for any operations performed by trigger programs. This + ** option is used to set or clear (the default) a flag that governs this +@@ -2095,6 +2144,39 @@ + ** 0 or 1 to indicate whether output-for-triggers has been disabled - 0 if + ** it is not disabled, 1 if it is. + ** </dd> ++** ++** [[SQLITE_DBCONFIG_RESET_DATABASE]] <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt> ++** <dd> Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run ++** [VACUUM] in order to reset a database back to an empty database ++** with no schema and no content. The following process works even for ++** a badly corrupted database file: ++** <ol> ++** <li> If the database connection is newly opened, make sure it has read the ++** database schema by preparing then discarding some query against the ++** database, or calling sqlite3_table_column_metadata(), ignoring any ++** errors. This step is only necessary if the application desires to keep ++** the database in WAL mode after the reset if it was in WAL mode before ++** the reset. ++** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0); ++** <li> [sqlite3_exec](db, "[VACUUM]", 0, 0, 0); ++** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0); ++** </ol> ++** Because resetting a database is destructive and irreversible, the ++** process requires the use of this obscure API and multiple steps to help ++** ensure that it does not happen by accident. ++** ++** [[SQLITE_DBCONFIG_DEFENSIVE]] <dt>SQLITE_DBCONFIG_DEFENSIVE</dt> ++** <dd>The SQLITE_DBCONFIG_DEFENSIVE option activates or deactivates the ++** "defensive" flag for a database connection. When the defensive ++** flag is enabled, language features that allow ordinary SQL to ++** deliberately corrupt the database file are disabled. The disabled ++** features include but are not limited to the following: ++** <ul> ++** <li> The [PRAGMA writable_schema=ON] statement. ++** <li> Writes to the [sqlite_dbpage] virtual table. ++** <li> Direct writes to [shadow tables]. ++** </ul> ++** </dd> + ** </dl> + */ + #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ +@@ -2106,7 +2188,9 @@ + #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_MAX 1008 /* Largest DBCONFIG */ ++#define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */ ++#define SQLITE_DBCONFIG_DEFENSIVE 1010 /* int int* */ ++#define SQLITE_DBCONFIG_MAX 1010 /* Largest DBCONFIG */ + + /* + ** CAPI3REF: Enable Or Disable Extended Result Codes +@@ -2234,12 +2318,17 @@ + ** program, the value returned reflects the number of rows modified by the + ** previous INSERT, UPDATE or DELETE statement within the same trigger. + ** +-** See also the [sqlite3_total_changes()] interface, the +-** [count_changes pragma], and the [changes() SQL function]. +-** + ** If a separate thread makes changes on the same database connection + ** while [sqlite3_changes()] is running then the value returned + ** is unpredictable and not meaningful. ++** ++** See also: ++** <ul> ++** <li> the [sqlite3_total_changes()] interface ++** <li> the [count_changes pragma] ++** <li> the [changes() SQL function] ++** <li> the [data_version pragma] ++** </ul> + */ + SQLITE_API int sqlite3_changes(sqlite3*); + +@@ -2257,13 +2346,26 @@ + ** count, but those made as part of REPLACE constraint resolution are + ** not. ^Changes to a view that are intercepted by INSTEAD OF triggers + ** are not counted. ++** ++** This the [sqlite3_total_changes(D)] interface only reports the number ++** of rows that changed due to SQL statement run against database ++** connection D. Any changes by other database connections are ignored. ++** To detect changes against a database file from other database ++** connections use the [PRAGMA data_version] command or the ++** [SQLITE_FCNTL_DATA_VERSION] [file control]. + ** +-** See also the [sqlite3_changes()] interface, the +-** [count_changes pragma], and the [total_changes() SQL function]. +-** + ** If a separate thread makes changes on the same database connection + ** while [sqlite3_total_changes()] is running then the value + ** returned is unpredictable and not meaningful. ++** ++** See also: ++** <ul> ++** <li> the [sqlite3_changes()] interface ++** <li> the [count_changes pragma] ++** <li> the [changes() SQL function] ++** <li> the [data_version pragma] ++** <li> the [SQLITE_FCNTL_DATA_VERSION] [file control] ++** </ul> + */ + SQLITE_API int sqlite3_total_changes(sqlite3*); + +@@ -3319,13 +3421,24 @@ + ** [database connection] D failed, then the sqlite3_errcode(D) interface + ** returns the numeric [result code] or [extended result code] for that + ** API call. +-** If the most recent API call was successful, +-** then the return value from sqlite3_errcode() is undefined. + ** ^The sqlite3_extended_errcode() + ** interface is the same except that it always returns the + ** [extended result code] even when extended result codes are + ** disabled. + ** ++** The values returned by sqlite3_errcode() and/or ++** sqlite3_extended_errcode() might change with each API call. ++** Except, there are some interfaces that are guaranteed to never ++** change the value of the error code. The error-code preserving ++** interfaces are: ++** ++** <ul> ++** <li> sqlite3_errcode() ++** <li> sqlite3_extended_errcode() ++** <li> sqlite3_errmsg() ++** <li> sqlite3_errmsg16() ++** </ul> ++** + ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language + ** text that describes the error, as either UTF-8 or UTF-16 respectively. + ** ^(Memory to hold the error message string is managed internally. +@@ -3515,9 +3628,19 @@ + ** on this hint by avoiding the use of [lookaside memory] so as not to + ** deplete the limited store of lookaside memory. Future versions of + ** SQLite may act on this hint differently. ++** ++** [[SQLITE_PREPARE_NORMALIZE]] ^(<dt>SQLITE_PREPARE_NORMALIZE</dt> ++** <dd>The SQLITE_PREPARE_NORMALIZE flag indicates that a normalized ++** representation of the SQL statement should be calculated and then ++** associated with the prepared statement, which can be obtained via ++** the [sqlite3_normalized_sql()] interface.)^ The semantics used to ++** normalize a SQL statement are unspecified and subject to change. ++** At a minimum, literal values will be replaced with suitable ++** placeholders. + ** </dl> + */ + #define SQLITE_PREPARE_PERSISTENT 0x01 ++#define SQLITE_PREPARE_NORMALIZE 0x02 + + /* + ** CAPI3REF: Compiling An SQL Statement +@@ -3675,6 +3798,11 @@ + ** ^The sqlite3_expanded_sql(P) interface returns a pointer to a UTF-8 + ** string containing the SQL text of prepared statement P with + ** [bound parameters] expanded. ++** ^The sqlite3_normalized_sql(P) interface returns a pointer to a UTF-8 ++** string containing the normalized SQL text of prepared statement P. The ++** semantics used to normalize a SQL statement are unspecified and subject ++** to change. At a minimum, literal values will be replaced with suitable ++** placeholders. + ** + ** ^(For example, if a prepared statement is created using the SQL + ** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345 +@@ -3690,8 +3818,9 @@ + ** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time + ** option causes sqlite3_expanded_sql() to always return NULL. + ** +-** ^The string returned by sqlite3_sql(P) is managed by SQLite and is +-** automatically freed when the prepared statement is finalized. ++** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P) ++** are managed by SQLite and are automatically freed when the prepared ++** statement is finalized. + ** ^The string returned by sqlite3_expanded_sql(P), on the other hand, + ** is obtained from [sqlite3_malloc()] and must be free by the application + ** by passing it to [sqlite3_free()]. +@@ -3698,6 +3827,7 @@ + */ + SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); + SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt); ++SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt); + + /* + ** CAPI3REF: Determine If An SQL Statement Writes The Database +@@ -4479,11 +4609,25 @@ + ** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into + ** [sqlite3_free()]. + ** +-** ^(If a memory allocation error occurs during the evaluation of any +-** of these routines, a default value is returned. The default value +-** is either the integer 0, the floating point number 0.0, or a NULL +-** pointer. Subsequent calls to [sqlite3_errcode()] will return +-** [SQLITE_NOMEM].)^ ++** As long as the input parameters are correct, these routines will only ++** fail if an out-of-memory error occurs during a format conversion. ++** Only the following subset of interfaces are subject to out-of-memory ++** errors: ++** ++** <ul> ++** <li> sqlite3_column_blob() ++** <li> sqlite3_column_text() ++** <li> sqlite3_column_text16() ++** <li> sqlite3_column_bytes() ++** <li> sqlite3_column_bytes16() ++** </ul> ++** ++** If an out-of-memory error occurs, then the return value from these ++** routines is the same as if the column had contained an SQL NULL value. ++** Valid SQL NULL returns can be distinguished from out-of-memory errors ++** by invoking the [sqlite3_errcode()] immediately after the suspect ++** return value is obtained and before any ++** other SQLite interface is called on the same [database connection]. + */ + SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); + SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol); +@@ -4560,11 +4704,13 @@ + ** + ** ^These functions (collectively known as "function creation routines") + ** are used to add SQL functions or aggregates or to redefine the behavior +-** of existing SQL functions or aggregates. The only differences between +-** these routines are the text encoding expected for +-** the second parameter (the name of the function being created) +-** and the presence or absence of a destructor callback for +-** the application data pointer. ++** of existing SQL functions or aggregates. The only differences between ++** the three "sqlite3_create_function*" routines are the text encoding ++** expected for the second parameter (the name of the function being ++** created) and the presence or absence of a destructor callback for ++** the application data pointer. Function sqlite3_create_window_function() ++** is similar, but allows the user to supply the extra callback functions ++** needed by [aggregate window functions]. + ** + ** ^The first parameter is the [database connection] to which the SQL + ** function is to be added. ^If an application uses more than one database +@@ -4610,7 +4756,8 @@ + ** ^(The fifth parameter is an arbitrary pointer. The implementation of the + ** function can gain access to this pointer using [sqlite3_user_data()].)^ + ** +-** ^The sixth, seventh and eighth parameters, xFunc, xStep and xFinal, are ++** ^The sixth, seventh and eighth parameters passed to the three ++** "sqlite3_create_function*" functions, xFunc, xStep and xFinal, are + ** pointers to C-language functions that implement the SQL function or + ** aggregate. ^A scalar SQL function requires an implementation of the xFunc + ** callback only; NULL pointers must be passed as the xStep and xFinal +@@ -4619,16 +4766,25 @@ + ** SQL function or aggregate, pass NULL pointers for all three function + ** callbacks. + ** +-** ^(If the ninth parameter to sqlite3_create_function_v2() is not NULL, +-** then it is destructor for the application data pointer. +-** The destructor is invoked when the function is deleted, either by being +-** overloaded or when the database connection closes.)^ +-** ^The destructor is also invoked if the call to +-** sqlite3_create_function_v2() fails. +-** ^When the destructor callback of the tenth parameter is invoked, it +-** is passed a single argument which is a copy of the application data +-** pointer which was the fifth parameter to sqlite3_create_function_v2(). ++** ^The sixth, seventh, eighth and ninth parameters (xStep, xFinal, xValue ++** and xInverse) passed to sqlite3_create_window_function are pointers to ++** C-language callbacks that implement the new function. xStep and xFinal ++** must both be non-NULL. xValue and xInverse may either both be NULL, in ++** which case a regular aggregate function is created, or must both be ++** non-NULL, in which case the new function may be used as either an aggregate ++** or aggregate window function. More details regarding the implementation ++** of aggregate window functions are ++** [user-defined window functions|available here]. + ** ++** ^(If the final parameter to sqlite3_create_function_v2() or ++** sqlite3_create_window_function() is not NULL, then it is destructor for ++** the application data pointer. The destructor is invoked when the function ++** is deleted, either by being overloaded or when the database connection ++** closes.)^ ^The destructor is also invoked if the call to ++** sqlite3_create_function_v2() fails. ^When the destructor callback is ++** invoked, it is passed a single argument which is a copy of the application ++** data pointer which was the fifth parameter to sqlite3_create_function_v2(). ++** + ** ^It is permitted to register multiple implementations of the same + ** functions with the same name but with either differing numbers of + ** arguments or differing preferred text encodings. ^SQLite will use +@@ -4680,6 +4836,18 @@ + void (*xFinal)(sqlite3_context*), + void(*xDestroy)(void*) + ); ++SQLITE_API int sqlite3_create_window_function( ++ sqlite3 *db, ++ const char *zFunctionName, ++ int nArg, ++ int eTextRep, ++ void *pApp, ++ void (*xStep)(sqlite3_context*,int,sqlite3_value**), ++ void (*xFinal)(sqlite3_context*), ++ void (*xValue)(sqlite3_context*), ++ void (*xInverse)(sqlite3_context*,int,sqlite3_value**), ++ void(*xDestroy)(void*) ++); + + /* + ** CAPI3REF: Text Encodings +@@ -4822,6 +4990,28 @@ + ** + ** These routines must be called from the same thread as + ** the SQL function that supplied the [sqlite3_value*] parameters. ++** ++** As long as the input parameter is correct, these routines can only ++** fail if an out-of-memory error occurs during a format conversion. ++** Only the following subset of interfaces are subject to out-of-memory ++** errors: ++** ++** <ul> ++** <li> sqlite3_value_blob() ++** <li> sqlite3_value_text() ++** <li> sqlite3_value_text16() ++** <li> sqlite3_value_text16le() ++** <li> sqlite3_value_text16be() ++** <li> sqlite3_value_bytes() ++** <li> sqlite3_value_bytes16() ++** </ul> ++** ++** If an out-of-memory error occurs, then the return value from these ++** routines is the same as if the column had contained an SQL NULL value. ++** Valid SQL NULL returns can be distinguished from out-of-memory errors ++** by invoking the [sqlite3_errcode()] immediately after the suspect ++** return value is obtained and before any ++** other SQLite interface is called on the same [database connection]. + */ + SQLITE_API const void *sqlite3_value_blob(sqlite3_value*); + SQLITE_API double sqlite3_value_double(sqlite3_value*); +@@ -5493,6 +5683,41 @@ + SQLITE_API SQLITE_EXTERN char *sqlite3_data_directory; + + /* ++** CAPI3REF: Win32 Specific Interface ++** ++** These interfaces are available only on Windows. The ++** [sqlite3_win32_set_directory] interface is used to set the value associated ++** with the [sqlite3_temp_directory] or [sqlite3_data_directory] variable, to ++** zValue, depending on the value of the type parameter. The zValue parameter ++** should be NULL to cause the previous value to be freed via [sqlite3_free]; ++** a non-NULL value will be copied into memory obtained from [sqlite3_malloc] ++** prior to being used. The [sqlite3_win32_set_directory] interface returns ++** [SQLITE_OK] to indicate success, [SQLITE_ERROR] if the type is unsupported, ++** or [SQLITE_NOMEM] if memory could not be allocated. The value of the ++** [sqlite3_data_directory] variable is intended to act as a replacement for ++** the current directory on the sub-platforms of Win32 where that concept is ++** not present, e.g. WinRT and UWP. The [sqlite3_win32_set_directory8] and ++** [sqlite3_win32_set_directory16] interfaces behave exactly the same as the ++** sqlite3_win32_set_directory interface except the string parameter must be ++** UTF-8 or UTF-16, respectively. ++*/ ++SQLITE_API int sqlite3_win32_set_directory( ++ unsigned long type, /* Identifier for directory being set or reset */ ++ void *zValue /* New value for directory being set or reset */ ++); ++SQLITE_API int sqlite3_win32_set_directory8(unsigned long type, const char *zValue); ++SQLITE_API int sqlite3_win32_set_directory16(unsigned long type, const void *zValue); ++ ++/* ++** CAPI3REF: Win32 Directory Types ++** ++** These macros are only available on Windows. They define the allowed values ++** for the type argument to the [sqlite3_win32_set_directory] interface. ++*/ ++#define SQLITE_WIN32_DATA_DIRECTORY_TYPE 1 ++#define SQLITE_WIN32_TEMP_DIRECTORY_TYPE 2 ++ ++/* + ** CAPI3REF: Test For Auto-Commit Mode + ** KEYWORDS: {autocommit mode} + ** METHOD: sqlite3 +@@ -6092,6 +6317,9 @@ + int (*xSavepoint)(sqlite3_vtab *pVTab, int); + int (*xRelease)(sqlite3_vtab *pVTab, int); + int (*xRollbackTo)(sqlite3_vtab *pVTab, int); ++ /* The methods above are in versions 1 and 2 of the sqlite_module object. ++ ** Those below are for version 3 and greater. */ ++ int (*xShadowName)(const char*); + }; + + /* +@@ -6224,6 +6452,10 @@ + + /* + ** CAPI3REF: Virtual Table Scan Flags ++** ++** Virtual table implementations are allowed to set the ++** [sqlite3_index_info].idxFlags field to some combination of ++** these bits. + */ + #define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */ + +@@ -6249,6 +6481,7 @@ + #define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70 + #define SQLITE_INDEX_CONSTRAINT_ISNULL 71 + #define SQLITE_INDEX_CONSTRAINT_IS 72 ++#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150 + + /* + ** CAPI3REF: Register A Virtual Table Implementation +@@ -6925,6 +7158,7 @@ + /* + ** CAPI3REF: Low-Level Control Of Database Files + ** METHOD: sqlite3 ++** KEYWORDS: {file control} + ** + ** ^The [sqlite3_file_control()] interface makes a direct call to the + ** xFileControl method for the [sqlite3_io_methods] object associated +@@ -6939,11 +7173,18 @@ + ** the xFileControl method. ^The return value of the xFileControl + ** method becomes the return value of this routine. + ** ++** A few opcodes for [sqlite3_file_control()] are handled directly ++** by the SQLite core and never invoke the ++** sqlite3_io_methods.xFileControl method. + ** ^The [SQLITE_FCNTL_FILE_POINTER] value for the op parameter causes + ** a pointer to the underlying [sqlite3_file] object to be written into +-** the space pointed to by the 4th parameter. ^The [SQLITE_FCNTL_FILE_POINTER] +-** case is a short-circuit path which does not actually invoke the +-** underlying sqlite3_io_methods.xFileControl method. ++** the space pointed to by the 4th parameter. The ++** [SQLITE_FCNTL_JOURNAL_POINTER] works similarly except that it returns ++** the [sqlite3_file] object associated with the journal file instead of ++** the main database. The [SQLITE_FCNTL_VFS_POINTER] opcode returns ++** a pointer to the underlying [sqlite3_vfs] object for the file. ++** The [SQLITE_FCNTL_DATA_VERSION] returns the data version counter ++** from the pager. + ** + ** ^If the second parameter (zDbName) does not match the name of any + ** open database file, then SQLITE_ERROR is returned. ^This error +@@ -6999,8 +7240,9 @@ + #define SQLITE_TESTCTRL_ALWAYS 13 + #define SQLITE_TESTCTRL_RESERVE 14 + #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 +-#define SQLITE_TESTCTRL_ISKEYWORD 16 ++#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ + #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ ++#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17 + #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 + #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ + #define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19 +@@ -7014,6 +7256,189 @@ + #define SQLITE_TESTCTRL_LAST 26 /* Largest TESTCTRL */ + + /* ++** CAPI3REF: SQL Keyword Checking ++** ++** These routines provide access to the set of SQL language keywords ++** recognized by SQLite. Applications can uses these routines to determine ++** whether or not a specific identifier needs to be escaped (for example, ++** by enclosing in double-quotes) so as not to confuse the parser. ++** ++** The sqlite3_keyword_count() interface returns the number of distinct ++** keywords understood by SQLite. ++** ++** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and ++** makes *Z point to that keyword expressed as UTF8 and writes the number ++** of bytes in the keyword into *L. The string that *Z points to is not ++** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns ++** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z ++** or L are NULL or invalid pointers then calls to ++** sqlite3_keyword_name(N,Z,L) result in undefined behavior. ++** ++** The sqlite3_keyword_check(Z,L) interface checks to see whether or not ++** the L-byte UTF8 identifier that Z points to is a keyword, returning non-zero ++** if it is and zero if not. ++** ++** The parser used by SQLite is forgiving. It is often possible to use ++** a keyword as an identifier as long as such use does not result in a ++** parsing ambiguity. For example, the statement ++** "CREATE TABLE BEGIN(REPLACE,PRAGMA,END);" is accepted by SQLite, and ++** creates a new table named "BEGIN" with three columns named ++** "REPLACE", "PRAGMA", and "END". Nevertheless, best practice is to avoid ++** using keywords as identifiers. Common techniques used to avoid keyword ++** name collisions include: ++** <ul> ++** <li> Put all identifier names inside double-quotes. This is the official ++** SQL way to escape identifier names. ++** <li> Put identifier names inside [...]. This is not standard SQL, ++** but it is what SQL Server does and so lots of programmers use this ++** technique. ++** <li> Begin every identifier with the letter "Z" as no SQL keywords start ++** with "Z". ++** <li> Include a digit somewhere in every identifier name. ++** </ul> ++** ++** Note that the number of keywords understood by SQLite can depend on ++** compile-time options. For example, "VACUUM" is not a keyword if ++** SQLite is compiled with the [-DSQLITE_OMIT_VACUUM] option. Also, ++** new keywords may be added to future releases of SQLite. ++*/ ++SQLITE_API int sqlite3_keyword_count(void); ++SQLITE_API int sqlite3_keyword_name(int,const char**,int*); ++SQLITE_API int sqlite3_keyword_check(const char*,int); ++ ++/* ++** CAPI3REF: Dynamic String Object ++** KEYWORDS: {dynamic string} ++** ++** An instance of the sqlite3_str object contains a dynamically-sized ++** string under construction. ++** ++** The lifecycle of an sqlite3_str object is as follows: ++** <ol> ++** <li> ^The sqlite3_str object is created using [sqlite3_str_new()]. ++** <li> ^Text is appended to the sqlite3_str object using various ++** methods, such as [sqlite3_str_appendf()]. ++** <li> ^The sqlite3_str object is destroyed and the string it created ++** is returned using the [sqlite3_str_finish()] interface. ++** </ol> ++*/ ++typedef struct sqlite3_str sqlite3_str; ++ ++/* ++** CAPI3REF: Create A New Dynamic String Object ++** CONSTRUCTOR: sqlite3_str ++** ++** ^The [sqlite3_str_new(D)] interface allocates and initializes ++** a new [sqlite3_str] object. To avoid memory leaks, the object returned by ++** [sqlite3_str_new()] must be freed by a subsequent call to ++** [sqlite3_str_finish(X)]. ++** ++** ^The [sqlite3_str_new(D)] interface always returns a pointer to a ++** valid [sqlite3_str] object, though in the event of an out-of-memory ++** error the returned object might be a special singleton that will ++** silently reject new text, always return SQLITE_NOMEM from ++** [sqlite3_str_errcode()], always return 0 for ++** [sqlite3_str_length()], and always return NULL from ++** [sqlite3_str_finish(X)]. It is always safe to use the value ++** returned by [sqlite3_str_new(D)] as the sqlite3_str parameter ++** to any of the other [sqlite3_str] methods. ++** ++** The D parameter to [sqlite3_str_new(D)] may be NULL. If the ++** D parameter in [sqlite3_str_new(D)] is not NULL, then the maximum ++** length of the string contained in the [sqlite3_str] object will be ++** the value set for [sqlite3_limit](D,[SQLITE_LIMIT_LENGTH]) instead ++** of [SQLITE_MAX_LENGTH]. ++*/ ++SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3*); ++ ++/* ++** CAPI3REF: Finalize A Dynamic String ++** DESTRUCTOR: sqlite3_str ++** ++** ^The [sqlite3_str_finish(X)] interface destroys the sqlite3_str object X ++** and returns a pointer to a memory buffer obtained from [sqlite3_malloc64()] ++** that contains the constructed string. The calling application should ++** pass the returned value to [sqlite3_free()] to avoid a memory leak. ++** ^The [sqlite3_str_finish(X)] interface may return a NULL pointer if any ++** errors were encountered during construction of the string. ^The ++** [sqlite3_str_finish(X)] interface will also return a NULL pointer if the ++** string in [sqlite3_str] object X is zero bytes long. ++*/ ++SQLITE_API char *sqlite3_str_finish(sqlite3_str*); ++ ++/* ++** CAPI3REF: Add Content To A Dynamic String ++** METHOD: sqlite3_str ++** ++** These interfaces add content to an sqlite3_str object previously obtained ++** from [sqlite3_str_new()]. ++** ++** ^The [sqlite3_str_appendf(X,F,...)] and ++** [sqlite3_str_vappendf(X,F,V)] interfaces uses the [built-in printf] ++** functionality of SQLite to append formatted text onto the end of ++** [sqlite3_str] object X. ++** ++** ^The [sqlite3_str_append(X,S,N)] method appends exactly N bytes from string S ++** onto the end of the [sqlite3_str] object X. N must be non-negative. ++** S must contain at least N non-zero bytes of content. To append a ++** zero-terminated string in its entirety, use the [sqlite3_str_appendall()] ++** method instead. ++** ++** ^The [sqlite3_str_appendall(X,S)] method appends the complete content of ++** zero-terminated string S onto the end of [sqlite3_str] object X. ++** ++** ^The [sqlite3_str_appendchar(X,N,C)] method appends N copies of the ++** single-byte character C onto the end of [sqlite3_str] object X. ++** ^This method can be used, for example, to add whitespace indentation. ++** ++** ^The [sqlite3_str_reset(X)] method resets the string under construction ++** inside [sqlite3_str] object X back to zero bytes in length. ++** ++** These methods do not return a result code. ^If an error occurs, that fact ++** is recorded in the [sqlite3_str] object and can be recovered by a ++** subsequent call to [sqlite3_str_errcode(X)]. ++*/ ++SQLITE_API void sqlite3_str_appendf(sqlite3_str*, const char *zFormat, ...); ++SQLITE_API void sqlite3_str_vappendf(sqlite3_str*, const char *zFormat, va_list); ++SQLITE_API void sqlite3_str_append(sqlite3_str*, const char *zIn, int N); ++SQLITE_API void sqlite3_str_appendall(sqlite3_str*, const char *zIn); ++SQLITE_API void sqlite3_str_appendchar(sqlite3_str*, int N, char C); ++SQLITE_API void sqlite3_str_reset(sqlite3_str*); ++ ++/* ++** CAPI3REF: Status Of A Dynamic String ++** METHOD: sqlite3_str ++** ++** These interfaces return the current status of an [sqlite3_str] object. ++** ++** ^If any prior errors have occurred while constructing the dynamic string ++** in sqlite3_str X, then the [sqlite3_str_errcode(X)] method will return ++** an appropriate error code. ^The [sqlite3_str_errcode(X)] method returns ++** [SQLITE_NOMEM] following any out-of-memory error, or ++** [SQLITE_TOOBIG] if the size of the dynamic string exceeds ++** [SQLITE_MAX_LENGTH], or [SQLITE_OK] if there have been no errors. ++** ++** ^The [sqlite3_str_length(X)] method returns the current length, in bytes, ++** of the dynamic string under construction in [sqlite3_str] object X. ++** ^The length returned by [sqlite3_str_length(X)] does not include the ++** zero-termination byte. ++** ++** ^The [sqlite3_str_value(X)] method returns a pointer to the current ++** content of the dynamic string under construction in X. The value ++** returned by [sqlite3_str_value(X)] is managed by the sqlite3_str object X ++** and might be freed or altered by any subsequent method on the same ++** [sqlite3_str] object. Applications must not used the pointer returned ++** [sqlite3_str_value(X)] after any subsequent method call on the same ++** object. ^Applications may change the content of the string returned ++** by [sqlite3_str_value(X)] as long as they do not write into any bytes ++** outside the range of 0 to [sqlite3_str_length(X)] and do not read or ++** write any byte after any subsequent sqlite3_str method call. ++*/ ++SQLITE_API int sqlite3_str_errcode(sqlite3_str*); ++SQLITE_API int sqlite3_str_length(sqlite3_str*); ++SQLITE_API char *sqlite3_str_value(sqlite3_str*); ++ ++/* + ** CAPI3REF: SQLite Runtime Status + ** + ** ^These interfaces are used to retrieve runtime status information +@@ -8230,6 +8655,7 @@ + ** can use to customize and optimize their behavior. + ** + ** <dl> ++** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]] + ** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT + ** <dd>Calls of the form + ** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported, +@@ -8282,11 +8708,11 @@ + ** method of a [virtual table], then it returns true if and only if the + ** column is being fetched as part of an UPDATE operation during which the + ** column value will not change. Applications might use this to substitute +-** a lighter-weight value to return that the corresponding [xUpdate] method +-** understands as a "no-change" value. ++** a return value that is less expensive to compute and that the corresponding ++** [xUpdate] method understands as a "no-change" value. + ** + ** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that +-** the column is not changed by the UPDATE statement, they the xColumn ++** the column is not changed by the UPDATE statement, then the xColumn + ** method can optionally return without setting a result, without calling + ** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces]. + ** In that case, [sqlite3_value_nochange(X)] will return true for the +@@ -8579,7 +9005,6 @@ + /* + ** CAPI3REF: Database Snapshot + ** KEYWORDS: {snapshot} {sqlite3_snapshot} +-** EXPERIMENTAL + ** + ** An instance of the snapshot object records the state of a [WAL mode] + ** database for some specific point in history. +@@ -8596,11 +9021,6 @@ + ** version of the database file so that it is possible to later open a new read + ** transaction that sees that historical version of the database rather than + ** the most recent version. +-** +-** The constructor for this object is [sqlite3_snapshot_get()]. The +-** [sqlite3_snapshot_open()] method causes a fresh read transaction to refer +-** to an historical snapshot (if possible). The destructor for +-** sqlite3_snapshot objects is [sqlite3_snapshot_free()]. + */ + typedef struct sqlite3_snapshot { + unsigned char hidden[48]; +@@ -8608,7 +9028,7 @@ + + /* + ** CAPI3REF: Record A Database Snapshot +-** EXPERIMENTAL ++** CONSTRUCTOR: sqlite3_snapshot + ** + ** ^The [sqlite3_snapshot_get(D,S,P)] interface attempts to make a + ** new [sqlite3_snapshot] object that records the current state of +@@ -8624,7 +9044,7 @@ + ** in this case. + ** + ** <ul> +-** <li> The database handle must be in [autocommit mode]. ++** <li> The database handle must not be in [autocommit mode]. + ** + ** <li> Schema S of [database connection] D must be a [WAL mode] database. + ** +@@ -8647,7 +9067,7 @@ + ** to avoid a memory leak. + ** + ** The [sqlite3_snapshot_get()] interface is only available when the +-** SQLITE_ENABLE_SNAPSHOT compile-time option is used. ++** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. + */ + SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get( + sqlite3 *db, +@@ -8657,24 +9077,35 @@ + + /* + ** CAPI3REF: Start a read transaction on an historical snapshot +-** EXPERIMENTAL ++** METHOD: sqlite3_snapshot + ** +-** ^The [sqlite3_snapshot_open(D,S,P)] interface starts a +-** read transaction for schema S of +-** [database connection] D such that the read transaction +-** refers to historical [snapshot] P, rather than the most +-** recent change to the database. +-** ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK on success +-** or an appropriate [error code] if it fails. ++** ^The [sqlite3_snapshot_open(D,S,P)] interface either starts a new read ++** transaction or upgrades an existing one for schema S of ++** [database connection] D such that the read transaction refers to ++** historical [snapshot] P, rather than the most recent change to the ++** database. ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK ++** on success or an appropriate [error code] if it fails. + ** +-** ^In order to succeed, a call to [sqlite3_snapshot_open(D,S,P)] must be +-** the first operation following the [BEGIN] that takes the schema S +-** out of [autocommit mode]. +-** ^In other words, schema S must not currently be in +-** a transaction for [sqlite3_snapshot_open(D,S,P)] to work, but the +-** database connection D must be out of [autocommit mode]. +-** ^A [snapshot] will fail to open if it has been overwritten by a +-** [checkpoint]. ++** ^In order to succeed, the database connection must not be in ++** [autocommit mode] when [sqlite3_snapshot_open(D,S,P)] is called. If there ++** is already a read transaction open on schema S, then the database handle ++** must have no active statements (SELECT statements that have been passed ++** to sqlite3_step() but not sqlite3_reset() or sqlite3_finalize()). ++** SQLITE_ERROR is returned if either of these conditions is violated, or ++** if schema S does not exist, or if the snapshot object is invalid. ++** ++** ^A call to sqlite3_snapshot_open() will fail to open if the specified ++** snapshot has been overwritten by a [checkpoint]. In this case ++** SQLITE_ERROR_SNAPSHOT is returned. ++** ++** If there is already a read transaction open when this function is ++** invoked, then the same read transaction remains open (on the same ++** database snapshot) if SQLITE_ERROR, SQLITE_BUSY or SQLITE_ERROR_SNAPSHOT ++** is returned. If another error code - for example SQLITE_PROTOCOL or an ++** SQLITE_IOERR error code - is returned, then the final state of the ++** read transaction is undefined. If SQLITE_OK is returned, then the ++** read transaction is now open on database snapshot P. ++** + ** ^(A call to [sqlite3_snapshot_open(D,S,P)] will fail if the + ** database connection D does not know that the database file for + ** schema S is in [WAL mode]. A database connection might not know +@@ -8685,7 +9116,7 @@ + ** database connection in order to make it ready to use snapshots.) + ** + ** The [sqlite3_snapshot_open()] interface is only available when the +-** SQLITE_ENABLE_SNAPSHOT compile-time option is used. ++** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. + */ + SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open( + sqlite3 *db, +@@ -8695,7 +9126,7 @@ + + /* + ** CAPI3REF: Destroy a snapshot +-** EXPERIMENTAL ++** DESTRUCTOR: sqlite3_snapshot + ** + ** ^The [sqlite3_snapshot_free(P)] interface destroys [sqlite3_snapshot] P. + ** The application must eventually free every [sqlite3_snapshot] object +@@ -8702,13 +9133,13 @@ + ** using this routine to avoid a memory leak. + ** + ** The [sqlite3_snapshot_free()] interface is only available when the +-** SQLITE_ENABLE_SNAPSHOT compile-time option is used. ++** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. + */ + SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*); + + /* + ** CAPI3REF: Compare the ages of two snapshot handles. +-** EXPERIMENTAL ++** METHOD: sqlite3_snapshot + ** + ** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages + ** of two valid snapshot handles. +@@ -8727,6 +9158,9 @@ + ** Otherwise, this API returns a negative value if P1 refers to an older + ** snapshot than P2, zero if the two handles refer to the same database + ** snapshot, and a positive value if P1 is a newer snapshot than P2. ++** ++** This interface is only available if SQLite is compiled with the ++** [SQLITE_ENABLE_SNAPSHOT] option. + */ + SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( + sqlite3_snapshot *p1, +@@ -8735,23 +9169,26 @@ + + /* + ** CAPI3REF: Recover snapshots from a wal file +-** EXPERIMENTAL ++** METHOD: sqlite3_snapshot + ** +-** If all connections disconnect from a database file but do not perform +-** a checkpoint, the existing wal file is opened along with the database +-** file the next time the database is opened. At this point it is only +-** possible to successfully call sqlite3_snapshot_open() to open the most +-** recent snapshot of the database (the one at the head of the wal file), +-** even though the wal file may contain other valid snapshots for which +-** clients have sqlite3_snapshot handles. ++** If a [WAL file] remains on disk after all database connections close ++** (either through the use of the [SQLITE_FCNTL_PERSIST_WAL] [file control] ++** or because the last process to have the database opened exited without ++** calling [sqlite3_close()]) and a new connection is subsequently opened ++** on that database and [WAL file], the [sqlite3_snapshot_open()] interface ++** will only be able to open the last transaction added to the WAL file ++** even though the WAL file contains other valid transactions. + ** +-** This function attempts to scan the wal file associated with database zDb ++** This function attempts to scan the WAL file associated with database zDb + ** of database handle db and make all valid snapshots available to + ** sqlite3_snapshot_open(). It is an error if there is already a read +-** transaction open on the database, or if the database is not a wal mode ++** transaction open on the database, or if the database is not a WAL mode + ** database. + ** + ** SQLITE_OK is returned if successful, or an SQLite error code otherwise. ++** ++** This interface is only available if SQLite is compiled with the ++** [SQLITE_ENABLE_SNAPSHOT] option. + */ + SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); + +@@ -8781,7 +9218,7 @@ + ** been a prior call to [sqlite3_deserialize(D,S,...)] with the same + ** values of D and S. + ** The size of the database is written into *P even if the +-** SQLITE_SERIALIZE_NOCOPY bit is set but no contigious copy ++** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy + ** of the database exists. + ** + ** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the +@@ -8862,7 +9299,7 @@ + ** in the P argument is held in memory obtained from [sqlite3_malloc64()] + ** and that SQLite should take ownership of this memory and automatically + ** free it when it has finished using it. Without this flag, the caller +-** is resposible for freeing any dynamically allocated memory. ++** is responsible for freeing any dynamically allocated memory. + ** + ** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to + ** grow the size of the database using calls to [sqlite3_realloc64()]. This +@@ -8988,7 +9425,7 @@ + sqlite3_int64 iRowid; /* Rowid for current entry */ + sqlite3_rtree_dbl rParentScore; /* Score of parent node */ + int eParentWithin; /* Visibility of parent node */ +- int eWithin; /* OUT: Visiblity */ ++ int eWithin; /* OUT: Visibility */ + sqlite3_rtree_dbl rScore; /* OUT: Write the score here */ + /* The following fields are only available in 3.8.11 and later */ + sqlite3_value **apSqlParam; /* Original SQL values of parameters */ +@@ -9484,6 +9921,13 @@ + ** consecutively. There is no chance that the iterator will visit a change + ** the applies to table X, then one for table Y, and then later on visit + ** another change for table X. ++** ++** The behavior of sqlite3changeset_start_v2() and its streaming equivalent ++** may be modified by passing a combination of ++** [SQLITE_CHANGESETSTART_INVERT | supported flags] as the 4th parameter. ++** ++** Note that the sqlite3changeset_start_v2() API is still <b>experimental</b> ++** and therefore subject to change. + */ + SQLITE_API int sqlite3changeset_start( + sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ +@@ -9490,8 +9934,27 @@ + int nChangeset, /* Size of changeset blob in bytes */ + void *pChangeset /* Pointer to blob containing changeset */ + ); ++SQLITE_API int sqlite3changeset_start_v2( ++ sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ ++ int nChangeset, /* Size of changeset blob in bytes */ ++ void *pChangeset, /* Pointer to blob containing changeset */ ++ int flags /* SESSION_CHANGESETSTART_* flags */ ++); + ++/* ++** CAPI3REF: Flags for sqlite3changeset_start_v2 ++** ++** The following flags may passed via the 4th parameter to ++** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]: ++** ++** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd> ++** Invert the changeset while iterating through 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_CHANGESETSTART_INVERT 0x0002 + ++ + /* + ** CAPI3REF: Advance A Changeset Iterator + ** METHOD: sqlite3_changeset_iter +@@ -10144,7 +10607,7 @@ + ), + void *pCtx, /* First argument passed to xConflict */ + void **ppRebase, int *pnRebase, /* OUT: Rebase data */ +- int flags /* Combination of SESSION_APPLY_* flags */ ++ int flags /* SESSION_CHANGESETAPPLY_* flags */ + ); + + /* +@@ -10162,8 +10625,14 @@ + ** causes the sessions module to omit this savepoint. In this case, if the + ** 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 +@@ -10557,6 +11026,12 @@ + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn + ); ++SQLITE_API int sqlite3changeset_start_v2_strm( ++ sqlite3_changeset_iter **pp, ++ int (*xInput)(void *pIn, void *pData, int *pnData), ++ void *pIn, ++ int flags ++); + SQLITE_API int sqlite3session_changeset_strm( + sqlite3_session *pSession, + int (*xOutput)(void *pOut, const void *pData, int nData), +@@ -10583,8 +11058,47 @@ + void *pOut + ); + ++/* ++** CAPI3REF: Configure global parameters ++** ++** The sqlite3session_config() interface is used to make global configuration ++** changes to the sessions module in order to tune it to the specific needs ++** of the application. ++** ++** The sqlite3session_config() interface is not threadsafe. If it is invoked ++** while any other thread is inside any other sessions method then the ++** results are undefined. Furthermore, if it is invoked after any sessions ++** related objects have been created, the results are also undefined. ++** ++** The first argument to the sqlite3session_config() function must be one ++** of the SQLITE_SESSION_CONFIG_XXX constants defined below. The ++** interpretation of the (void*) value passed as the second parameter and ++** the effect of calling this function depends on the value of the first ++** parameter. ++** ++** <dl> ++** <dt>SQLITE_SESSION_CONFIG_STRMSIZE<dd> ++** By default, the sessions module streaming interfaces attempt to input ++** and output data in approximately 1 KiB chunks. This operand may be used ++** to set and query the value of this configuration setting. The pointer ++** passed as the second argument must point to a value of type (int). ++** If this value is greater than 0, it is used as the new streaming data ++** chunk size for both input and output. Before returning, the (int) value ++** pointed to by pArg is set to the final value of the streaming interface ++** chunk size. ++** </dl> ++** ++** This function returns SQLITE_OK if successful, or an SQLite error code ++** otherwise. ++*/ ++SQLITE_API int sqlite3session_config(int op, void *pArg); + + /* ++** CAPI3REF: Values for sqlite3session_config(). ++*/ ++#define SQLITE_SESSION_CONFIG_STRMSIZE 1 ++ ++/* + ** Make sure we can call this stuff from C++. + */ + #ifdef __cplusplus +@@ -11040,7 +11554,7 @@ + ** This way, even if the tokenizer does not provide synonyms + ** when tokenizing query text (it should not - to do would be + ** inefficient), it doesn't matter if the user queries for +-** 'first + place' or '1st + place', as there are entires in the ++** 'first + place' or '1st + place', as there are entries in the + ** FTS index corresponding to both forms of the first token. + ** </ol> + ** +@@ -11068,7 +11582,7 @@ + ** extra data to the FTS index or require FTS5 to query for multiple terms, + ** so it is efficient in terms of disk space and query speed. However, it + ** does not support prefix queries very well. If, as suggested above, the +-** token "first" is subsituted for "1st" by the tokenizer, then the query: ++** token "first" is substituted for "1st" by the tokenizer, then the query: + ** + ** <codeblock> + ** ... MATCH '1s*'</codeblock> +--- contrib/sqlite3/sqlite3ext.h.orig ++++ contrib/sqlite3/sqlite3ext.h +@@ -295,6 +295,30 @@ + int (*vtab_nochange)(sqlite3_context*); + int (*value_nochange)(sqlite3_value*); + const char *(*vtab_collation)(sqlite3_index_info*,int); ++ /* Version 3.24.0 and later */ ++ int (*keyword_count)(void); ++ int (*keyword_name)(int,const char**,int*); ++ int (*keyword_check)(const char*,int); ++ sqlite3_str *(*str_new)(sqlite3*); ++ char *(*str_finish)(sqlite3_str*); ++ void (*str_appendf)(sqlite3_str*, const char *zFormat, ...); ++ void (*str_vappendf)(sqlite3_str*, const char *zFormat, va_list); ++ void (*str_append)(sqlite3_str*, const char *zIn, int N); ++ void (*str_appendall)(sqlite3_str*, const char *zIn); ++ void (*str_appendchar)(sqlite3_str*, int N, char C); ++ void (*str_reset)(sqlite3_str*); ++ int (*str_errcode)(sqlite3_str*); ++ int (*str_length)(sqlite3_str*); ++ char *(*str_value)(sqlite3_str*); ++ /* Version 3.25.0 and later */ ++ int (*create_window_function)(sqlite3*,const char*,int,int,void*, ++ void (*xStep)(sqlite3_context*,int,sqlite3_value**), ++ void (*xFinal)(sqlite3_context*), ++ void (*xValue)(sqlite3_context*), ++ void (*xInv)(sqlite3_context*,int,sqlite3_value**), ++ void(*xDestroy)(void*)); ++ /* Version 3.26.0 and later */ ++ const char *(*normalized_sql)(sqlite3_stmt*); + }; + + /* +@@ -565,6 +589,25 @@ + #define sqlite3_vtab_nochange sqlite3_api->vtab_nochange + #define sqlite3_value_nochange sqlite3_api->value_nochange + #define sqlite3_vtab_collation sqlite3_api->vtab_collation ++/* Version 3.24.0 and later */ ++#define sqlite3_keyword_count sqlite3_api->keyword_count ++#define sqlite3_keyword_name sqlite3_api->keyword_name ++#define sqlite3_keyword_check sqlite3_api->keyword_check ++#define sqlite3_str_new sqlite3_api->str_new ++#define sqlite3_str_finish sqlite3_api->str_finish ++#define sqlite3_str_appendf sqlite3_api->str_appendf ++#define sqlite3_str_vappendf sqlite3_api->str_vappendf ++#define sqlite3_str_append sqlite3_api->str_append ++#define sqlite3_str_appendall sqlite3_api->str_appendall ++#define sqlite3_str_appendchar sqlite3_api->str_appendchar ++#define sqlite3_str_reset sqlite3_api->str_reset ++#define sqlite3_str_errcode sqlite3_api->str_errcode ++#define sqlite3_str_length sqlite3_api->str_length ++#define sqlite3_str_value sqlite3_api->str_value ++/* Version 3.25.0 and later */ ++#define sqlite3_create_window_function sqlite3_api->create_window_function ++/* Version 3.26.0 and later */ ++#define sqlite3_normalized_sql sqlite3_api->normalized_sql + #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ + + #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) +--- contrib/sqlite3/tea/Makefile.in.orig ++++ contrib/sqlite3/tea/Makefile.in +@@ -0,0 +1,440 @@ ++# Makefile.in -- ++# ++# This file is a Makefile for Sample TEA Extension. If it has the name ++# "Makefile.in" then it is a template for a Makefile; to generate the ++# actual Makefile, run "./configure", which is a configuration script ++# generated by the "autoconf" program (constructs like "@foo@" will get ++# replaced in the actual Makefile. ++# ++# Copyright (c) 1999 Scriptics Corporation. ++# Copyright (c) 2002-2005 ActiveState Corporation. ++# ++# See the file "license.terms" for information on usage and redistribution ++# of this file, and for a DISCLAIMER OF ALL WARRANTIES. ++# ++# RCS: @(#) $Id: Makefile.in,v 1.59 2005/07/26 19:17:02 mdejong Exp $ ++ ++#======================================================================== ++# Add additional lines to handle any additional AC_SUBST cases that ++# have been added in a customized configure script. ++#======================================================================== ++ ++#SAMPLE_NEW_VAR = @SAMPLE_NEW_VAR@ ++ ++#======================================================================== ++# Nothing of the variables below this line should need to be changed. ++# Please check the TARGETS section below to make sure the make targets ++# are correct. ++#======================================================================== ++ ++#======================================================================== ++# The names of the source files is defined in the configure script. ++# The object files are used for linking into the final library. ++# This will be used when a dist target is added to the Makefile. ++# It is not important to specify the directory, as long as it is the ++# $(srcdir) or in the generic, win or unix subdirectory. ++#======================================================================== ++ ++PKG_SOURCES = @PKG_SOURCES@ ++PKG_OBJECTS = @PKG_OBJECTS@ ++ ++PKG_STUB_SOURCES = @PKG_STUB_SOURCES@ ++PKG_STUB_OBJECTS = @PKG_STUB_OBJECTS@ ++ ++#======================================================================== ++# PKG_TCL_SOURCES identifies Tcl runtime files that are associated with ++# this package that need to be installed, if any. ++#======================================================================== ++ ++PKG_TCL_SOURCES = @PKG_TCL_SOURCES@ ++ ++#======================================================================== ++# This is a list of public header files to be installed, if any. ++#======================================================================== ++ ++PKG_HEADERS = @PKG_HEADERS@ ++ ++#======================================================================== ++# "PKG_LIB_FILE" refers to the library (dynamic or static as per ++# configuration options) composed of the named objects. ++#======================================================================== ++ ++PKG_LIB_FILE = @PKG_LIB_FILE@ ++PKG_STUB_LIB_FILE = @PKG_STUB_LIB_FILE@ ++ ++lib_BINARIES = $(PKG_LIB_FILE) ++BINARIES = $(lib_BINARIES) ++ ++SHELL = @SHELL@ ++ ++srcdir = @srcdir@ ++prefix = @prefix@ ++exec_prefix = @exec_prefix@ ++ ++bindir = @bindir@ ++libdir = @libdir@ ++datarootdir = @datarootdir@ ++datadir = @datadir@ ++mandir = @mandir@ ++includedir = @includedir@ ++ ++DESTDIR = ++ ++PKG_DIR = $(PACKAGE_NAME)$(PACKAGE_VERSION) ++pkgdatadir = $(datadir)/$(PKG_DIR) ++pkglibdir = $(libdir)/$(PKG_DIR) ++pkgincludedir = $(includedir)/$(PKG_DIR) ++ ++top_builddir = . ++ ++INSTALL = @INSTALL@ ++INSTALL_PROGRAM = @INSTALL_PROGRAM@ ++INSTALL_DATA = @INSTALL_DATA@ ++INSTALL_SCRIPT = @INSTALL_SCRIPT@ ++ ++PACKAGE_NAME = @PACKAGE_NAME@ ++PACKAGE_VERSION = @PACKAGE_VERSION@ ++CC = @CC@ ++CFLAGS_DEFAULT = @CFLAGS_DEFAULT@ ++CFLAGS_WARNING = @CFLAGS_WARNING@ ++CLEANFILES = @CLEANFILES@ ++EXEEXT = @EXEEXT@ ++LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@ ++MAKE_LIB = @MAKE_LIB@ ++MAKE_SHARED_LIB = @MAKE_SHARED_LIB@ ++MAKE_STATIC_LIB = @MAKE_STATIC_LIB@ ++MAKE_STUB_LIB = @MAKE_STUB_LIB@ ++OBJEXT = @OBJEXT@ ++RANLIB = @RANLIB@ ++RANLIB_STUB = @RANLIB_STUB@ ++SHLIB_CFLAGS = @SHLIB_CFLAGS@ ++SHLIB_LD = @SHLIB_LD@ ++SHLIB_LD_LIBS = @SHLIB_LD_LIBS@ ++STLIB_LD = @STLIB_LD@ ++#TCL_DEFS = @TCL_DEFS@ ++TCL_BIN_DIR = @TCL_BIN_DIR@ ++TCL_SRC_DIR = @TCL_SRC_DIR@ ++#TK_BIN_DIR = @TK_BIN_DIR@ ++#TK_SRC_DIR = @TK_SRC_DIR@ ++ ++# This is no longer necessary even for packages that use private Tcl headers ++#TCL_TOP_DIR_NATIVE = @TCL_TOP_DIR_NATIVE@ ++# Not used, but retained for reference of what libs Tcl required ++#TCL_LIBS = @TCL_LIBS@ ++ ++#======================================================================== ++# TCLLIBPATH seeds the auto_path in Tcl's init.tcl so we can test our ++# package without installing. The other environment variables allow us ++# to test against an uninstalled Tcl. Add special env vars that you ++# require for testing here (like TCLX_LIBRARY). ++#======================================================================== ++ ++EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR) ++#EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR):$(TK_BIN_DIR) ++TCLLIBPATH = $(top_builddir) ++TCLSH_ENV = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library` \ ++ @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \ ++ PATH="$(EXTRA_PATH):$(PATH)" \ ++ TCLLIBPATH="$(TCLLIBPATH)" ++# TK_LIBRARY=`@CYGPATH@ $(TK_SRC_DIR)/library` ++ ++TCLSH_PROG = @TCLSH_PROG@ ++TCLSH = $(TCLSH_ENV) $(TCLSH_PROG) ++ ++#WISH_PROG = @WISH_PROG@ ++#WISH = $(TCLSH_ENV) $(WISH_PROG) ++ ++ ++SHARED_BUILD = @SHARED_BUILD@ ++ ++INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ -I$(srcdir)/.. ++#INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@ ++ ++PKG_CFLAGS = @PKG_CFLAGS@ ++ ++# TCL_DEFS is not strictly need here, but if you remove it, then you ++# must make sure that configure.in checks for the necessary components ++# that your library may use. TCL_DEFS can actually be a problem if ++# you do not compile with a similar machine setup as the Tcl core was ++# compiled with. ++#DEFS = $(TCL_DEFS) @DEFS@ $(PKG_CFLAGS) ++DEFS = @DEFS@ $(PKG_CFLAGS) ++ ++CONFIG_CLEAN_FILES = Makefile pkgIndex.tcl ++ ++CPPFLAGS = @CPPFLAGS@ ++LIBS = @PKG_LIBS@ @LIBS@ ++AR = @AR@ ++CFLAGS = @CFLAGS@ ++COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) ++ ++#======================================================================== ++# Start of user-definable TARGETS section ++#======================================================================== ++ ++#======================================================================== ++# TEA TARGETS. Please note that the "libraries:" target refers to platform ++# independent files, and the "binaries:" target inclues executable programs and ++# platform-dependent libraries. Modify these targets so that they install ++# the various pieces of your package. The make and install rules ++# for the BINARIES that you specified above have already been done. ++#======================================================================== ++ ++all: binaries libraries doc ++ ++#======================================================================== ++# The binaries target builds executable programs, Windows .dll's, unix ++# shared/static libraries, and any other platform-dependent files. ++# The list of targets to build for "binaries:" is specified at the top ++# of the Makefile, in the "BINARIES" variable. ++#======================================================================== ++ ++binaries: $(BINARIES) ++ ++libraries: ++ ++ ++#======================================================================== ++# Your doc target should differentiate from doc builds (by the developer) ++# and doc installs (see install-doc), which just install the docs on the ++# end user machine when building from source. ++#======================================================================== ++ ++doc: ++ @echo "If you have documentation to create, place the commands to" ++ @echo "build the docs in the 'doc:' target. For example:" ++ @echo " xml2nroff sample.xml > sample.n" ++ @echo " xml2html sample.xml > sample.html" ++ ++install: all install-binaries install-libraries install-doc ++ ++install-binaries: binaries install-lib-binaries install-bin-binaries ++ ++#======================================================================== ++# This rule installs platform-independent files, such as header files. ++# The list=...; for p in $$list handles the empty list case x-platform. ++#======================================================================== ++ ++install-libraries: libraries ++ @mkdir -p $(DESTDIR)$(includedir) ++ @echo "Installing header files in $(DESTDIR)$(includedir)" ++ @list='$(PKG_HEADERS)'; for i in $$list; do \ ++ echo "Installing $(srcdir)/$$i" ; \ ++ $(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(includedir) ; \ ++ done; ++ ++#======================================================================== ++# Install documentation. Unix manpages should go in the $(mandir) ++# directory. ++#======================================================================== ++ ++install-doc: doc ++ @mkdir -p $(DESTDIR)$(mandir)/mann ++ @echo "Installing documentation in $(DESTDIR)$(mandir)" ++ @list='$(srcdir)/doc/*.n'; for i in $$list; do \ ++ echo "Installing $$i"; \ ++ rm -f $(DESTDIR)$(mandir)/mann/`basename $$i`; \ ++ $(INSTALL_DATA) $$i $(DESTDIR)$(mandir)/mann ; \ ++ done ++ ++test: binaries libraries ++ @echo "SQLite TEA distribution does not include tests" ++ ++shell: binaries libraries ++ @$(TCLSH) $(SCRIPT) ++ ++gdb: ++ $(TCLSH_ENV) gdb $(TCLSH_PROG) $(SCRIPT) ++ ++depend: ++ ++#======================================================================== ++# $(PKG_LIB_FILE) should be listed as part of the BINARIES variable ++# mentioned above. That will ensure that this target is built when you ++# run "make binaries". ++# ++# The $(PKG_OBJECTS) objects are created and linked into the final ++# library. In most cases these object files will correspond to the ++# source files above. ++#======================================================================== ++ ++$(PKG_LIB_FILE): $(PKG_OBJECTS) ++ -rm -f $(PKG_LIB_FILE) ++ ${MAKE_LIB} ++ $(RANLIB) $(PKG_LIB_FILE) ++ ++$(PKG_STUB_LIB_FILE): $(PKG_STUB_OBJECTS) ++ -rm -f $(PKG_STUB_LIB_FILE) ++ ${MAKE_STUB_LIB} ++ $(RANLIB_STUB) $(PKG_STUB_LIB_FILE) ++ ++#======================================================================== ++# We need to enumerate the list of .c to .o lines here. ++# ++# In the following lines, $(srcdir) refers to the toplevel directory ++# containing your extension. If your sources are in a subdirectory, ++# you will have to modify the paths to reflect this: ++# ++# sample.$(OBJEXT): $(srcdir)/generic/sample.c ++# $(COMPILE) -c `@CYGPATH@ $(srcdir)/generic/sample.c` -o $@ ++# ++# Setting the VPATH variable to a list of paths will cause the makefile ++# to look into these paths when resolving .c to .obj dependencies. ++# As necessary, add $(srcdir):$(srcdir)/compat:.... ++#======================================================================== ++ ++VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win ++ ++.c.@OBJEXT@: ++ $(COMPILE) -c `@CYGPATH@ $<` -o $@ ++ ++#======================================================================== ++# Distribution creation ++# You may need to tweak this target to make it work correctly. ++#======================================================================== ++ ++#COMPRESS = tar cvf $(PKG_DIR).tar $(PKG_DIR); compress $(PKG_DIR).tar ++COMPRESS = gtar zcvf $(PKG_DIR).tar.gz $(PKG_DIR) ++DIST_ROOT = /tmp/dist ++DIST_DIR = $(DIST_ROOT)/$(PKG_DIR) ++ ++dist-clean: ++ rm -rf $(DIST_DIR) $(DIST_ROOT)/$(PKG_DIR).tar.* ++ ++dist: dist-clean ++ mkdir -p $(DIST_DIR) ++ cp -p $(srcdir)/README* $(srcdir)/license* \ ++ $(srcdir)/aclocal.m4 $(srcdir)/configure $(srcdir)/*.in \ ++ $(DIST_DIR)/ ++ chmod 664 $(DIST_DIR)/Makefile.in $(DIST_DIR)/aclocal.m4 ++ chmod 775 $(DIST_DIR)/configure $(DIST_DIR)/configure.in ++ ++ for i in $(srcdir)/*.[ch]; do \ ++ if [ -f $$i ]; then \ ++ cp -p $$i $(DIST_DIR)/ ; \ ++ fi; \ ++ done; ++ ++ mkdir $(DIST_DIR)/tclconfig ++ cp $(srcdir)/tclconfig/install-sh $(srcdir)/tclconfig/tcl.m4 \ ++ $(DIST_DIR)/tclconfig/ ++ chmod 664 $(DIST_DIR)/tclconfig/tcl.m4 ++ chmod +x $(DIST_DIR)/tclconfig/install-sh ++ ++ list='demos doc generic library mac tests unix win'; \ ++ for p in $$list; do \ ++ if test -d $(srcdir)/$$p ; then \ ++ mkdir $(DIST_DIR)/$$p; \ ++ cp -p $(srcdir)/$$p/*.* $(DIST_DIR)/$$p/; \ ++ fi; \ ++ done ++ ++ (cd $(DIST_ROOT); $(COMPRESS);) ++ ++#======================================================================== ++# End of user-definable section ++#======================================================================== ++ ++#======================================================================== ++# Don't modify the file to clean here. Instead, set the "CLEANFILES" ++# variable in configure.in ++#======================================================================== ++ ++clean: ++ -test -z "$(BINARIES)" || rm -f $(BINARIES) ++ -rm -f *.$(OBJEXT) core *.core ++ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) ++ ++distclean: clean ++ -rm -f *.tab.c ++ -rm -f $(CONFIG_CLEAN_FILES) ++ -rm -f config.h config.cache config.log config.status ++ ++#======================================================================== ++# Install binary object libraries. On Windows this includes both .dll and ++# .lib files. Because the .lib files are not explicitly listed anywhere, ++# we need to deduce their existence from the .dll file of the same name. ++# Library files go into the lib directory. ++# In addition, this will generate the pkgIndex.tcl ++# file in the install location (assuming it can find a usable tclsh shell) ++# ++# You should not have to modify this target. ++#======================================================================== ++ ++install-lib-binaries: binaries ++ @mkdir -p $(DESTDIR)$(pkglibdir) ++ @list='$(lib_BINARIES)'; for p in $$list; do \ ++ if test -f $$p; then \ ++ echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p"; \ ++ $(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p; \ ++ stub=`echo $$p|sed -e "s/.*\(stub\).*/\1/"`; \ ++ if test "x$$stub" = "xstub"; then \ ++ echo " $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p"; \ ++ $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p; \ ++ else \ ++ echo " $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p"; \ ++ $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p; \ ++ fi; \ ++ ext=`echo $$p|sed -e "s/.*\.//"`; \ ++ if test "x$$ext" = "xdll"; then \ ++ lib=`basename $$p|sed -e 's/.[^.]*$$//'`.lib; \ ++ if test -f $$lib; then \ ++ echo " $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib"; \ ++ $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib; \ ++ fi; \ ++ fi; \ ++ fi; \ ++ done ++ @list='$(PKG_TCL_SOURCES)'; for p in $$list; do \ ++ if test -f $(srcdir)/$$p; then \ ++ destp=`basename $$p`; \ ++ echo " Install $$destp $(DESTDIR)$(pkglibdir)/$$destp"; \ ++ $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkglibdir)/$$destp; \ ++ fi; \ ++ done ++ @if test "x$(SHARED_BUILD)" = "x1"; then \ ++ echo " Install pkgIndex.tcl $(DESTDIR)$(pkglibdir)"; \ ++ $(INSTALL_DATA) pkgIndex.tcl $(DESTDIR)$(pkglibdir); \ ++ fi ++ ++#======================================================================== ++# Install binary executables (e.g. .exe files and dependent .dll files) ++# This is for files that must go in the bin directory (located next to ++# wish and tclsh), like dependent .dll files on Windows. ++# ++# You should not have to modify this target, except to define bin_BINARIES ++# above if necessary. ++#======================================================================== ++ ++install-bin-binaries: binaries ++ @mkdir -p $(DESTDIR)$(bindir) ++ @list='$(bin_BINARIES)'; for p in $$list; do \ ++ if test -f $$p; then \ ++ echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p"; \ ++ $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p; \ ++ fi; \ ++ done ++ ++.SUFFIXES: .c .$(OBJEXT) ++ ++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status ++ cd $(top_builddir) \ ++ && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status ++ ++uninstall-binaries: ++ list='$(lib_BINARIES)'; for p in $$list; do \ ++ rm -f $(DESTDIR)$(pkglibdir)/$$p; \ ++ done ++ list='$(PKG_TCL_SOURCES)'; for p in $$list; do \ ++ p=`basename $$p`; \ ++ rm -f $(DESTDIR)$(pkglibdir)/$$p; \ ++ done ++ list='$(bin_BINARIES)'; for p in $$list; do \ ++ rm -f $(DESTDIR)$(bindir)/$$p; \ ++ done ++ ++.PHONY: all binaries clean depend distclean doc install libraries test ++ ++# Tell versions [3.59,3.63) of GNU make to not export all variables. ++# Otherwise a system limit (for SysV at least) may be exceeded. ++.NOEXPORT: +--- contrib/sqlite3/tea/README.orig ++++ contrib/sqlite3/tea/README +@@ -0,0 +1,36 @@ ++This is the SQLite extension for Tcl using the Tcl Extension ++Architecture (TEA). For additional information on SQLite see ++ ++ http://www.sqlite.org/ ++ ++ ++UNIX BUILD ++========== ++ ++Building under most UNIX systems is easy, just run the configure script ++and then run make. For more information about the build process, see ++the tcl/unix/README file in the Tcl src dist. The following minimal ++example will install the extension in the /opt/tcl directory. ++ ++ $ cd sqlite-*-tea ++ $ ./configure --prefix=/opt/tcl ++ $ make ++ $ make install ++ ++WINDOWS BUILD ++============= ++ ++The recommended method to build extensions under windows is to use the ++Msys + Mingw build process. This provides a Unix-style build while ++generating native Windows binaries. Using the Msys + Mingw build tools ++means that you can use the same configure script as per the Unix build ++to create a Makefile. See the tcl/win/README file for the URL of ++the Msys + Mingw download. ++ ++If you have VC++ then you may wish to use the files in the win ++subdirectory and build the extension using just VC++. These files have ++been designed to be as generic as possible but will require some ++additional maintenance by the project developer to synchronise with ++the TEA configure.in and Makefile.in files. Instructions for using the ++VC++ makefile are written in the first part of the Makefile.vc ++file. +--- contrib/sqlite3/tea/aclocal.m4.orig ++++ contrib/sqlite3/tea/aclocal.m4 +@@ -0,0 +1,9 @@ ++# ++# Include the TEA standard macro set ++# ++ ++builtin(include,tclconfig/tcl.m4) ++ ++# ++# Add here whatever m4 macros you want to define for your package ++# +--- contrib/sqlite3/tea/configure.orig ++++ contrib/sqlite3/tea/configure +@@ -0,0 +1,9977 @@ ++#! /bin/sh ++# Guess values for system-dependent variables and create Makefiles. ++# Generated by GNU Autoconf 2.69 for sqlite 3.26.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. ++## -------------------- ## ++## M4sh Initialization. ## ++## -------------------- ## ++ ++# Be more Bourne compatible ++DUALCASE=1; export DUALCASE # for MKS sh ++if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : ++ emulate sh ++ NULLCMD=: ++ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which ++ # is contrary to our usage. Disable this feature. ++ alias -g '${1+"$@"}'='"$@"' ++ setopt NO_GLOB_SUBST ++else ++ case `(set -o) 2>/dev/null` in #( ++ *posix*) : ++ set -o posix ;; #( ++ *) : ++ ;; ++esac ++fi ++ ++ ++as_nl=' ++' ++export as_nl ++# Printing a long string crashes Solaris 7 /usr/bin/printf. ++as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ++as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo ++as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo ++# Prefer a ksh shell builtin over an external printf program on Solaris, ++# but without wasting forks for bash or zsh. ++if test -z "$BASH_VERSION$ZSH_VERSION" \ ++ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then ++ as_echo='print -r --' ++ as_echo_n='print -rn --' ++elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then ++ as_echo='printf %s\n' ++ as_echo_n='printf %s' ++else ++ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then ++ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' ++ as_echo_n='/usr/ucb/echo -n' ++ else ++ as_echo_body='eval expr "X$1" : "X\\(.*\\)"' ++ as_echo_n_body='eval ++ arg=$1; ++ case $arg in #( ++ *"$as_nl"*) ++ expr "X$arg" : "X\\(.*\\)$as_nl"; ++ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; ++ esac; ++ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ++ ' ++ export as_echo_n_body ++ as_echo_n='sh -c $as_echo_n_body as_echo' ++ fi ++ export as_echo_body ++ as_echo='sh -c $as_echo_body as_echo' ++fi ++ ++# The user is always right. ++if test "${PATH_SEPARATOR+set}" != set; then ++ PATH_SEPARATOR=: ++ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { ++ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || ++ PATH_SEPARATOR=';' ++ } ++fi ++ ++ ++# IFS ++# We need space, tab and new line, in precisely that order. Quoting is ++# there to prevent editors from complaining about space-tab. ++# (If _AS_PATH_WALK were called with IFS unset, it would disable word ++# splitting by setting IFS to empty value.) ++IFS=" "" $as_nl" ++ ++# Find who we are. Look in the path if we contain no directory separator. ++as_myself= ++case $0 in #(( ++ *[\\/]* ) as_myself=$0 ;; ++ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break ++ done ++IFS=$as_save_IFS ++ ++ ;; ++esac ++# We did not find ourselves, most probably we were run as `sh COMMAND' ++# in which case we are not to be found in the path. ++if test "x$as_myself" = x; then ++ as_myself=$0 ++fi ++if test ! -f "$as_myself"; then ++ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 ++ exit 1 ++fi ++ ++# Unset variables that we do not need and which cause bugs (e.g. in ++# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" ++# suppresses any "Segmentation fault" message there. '((' could ++# trigger a bug in pdksh 5.2.14. ++for as_var in BASH_ENV ENV MAIL MAILPATH ++do eval test x\${$as_var+set} = xset \ ++ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : ++done ++PS1='$ ' ++PS2='> ' ++PS4='+ ' ++ ++# NLS nuisances. ++LC_ALL=C ++export LC_ALL ++LANGUAGE=C ++export LANGUAGE ++ ++# CDPATH. ++(unset CDPATH) >/dev/null 2>&1 && unset CDPATH ++ ++# Use a proper internal environment variable to ensure we don't fall ++ # into an infinite loop, continuously re-executing ourselves. ++ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then ++ _as_can_reexec=no; export _as_can_reexec; ++ # We cannot yet assume a decent shell, so we have to provide a ++# neutralization value for shells without unset; and this also ++# works around shells that cannot unset nonexistent variables. ++# Preserve -v and -x to the replacement shell. ++BASH_ENV=/dev/null ++ENV=/dev/null ++(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV ++case $- in # (((( ++ *v*x* | *x*v* ) as_opts=-vx ;; ++ *v* ) as_opts=-v ;; ++ *x* ) as_opts=-x ;; ++ * ) as_opts= ;; ++esac ++exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} ++# Admittedly, this is quite paranoid, since all the known shells bail ++# out after a failed `exec'. ++$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 ++as_fn_exit 255 ++ fi ++ # We don't want this to propagate to other subprocesses. ++ { _as_can_reexec=; unset _as_can_reexec;} ++if test "x$CONFIG_SHELL" = x; then ++ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : ++ emulate sh ++ NULLCMD=: ++ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which ++ # is contrary to our usage. Disable this feature. ++ alias -g '\${1+\"\$@\"}'='\"\$@\"' ++ setopt NO_GLOB_SUBST ++else ++ case \`(set -o) 2>/dev/null\` in #( ++ *posix*) : ++ set -o posix ;; #( ++ *) : ++ ;; ++esac ++fi ++" ++ as_required="as_fn_return () { (exit \$1); } ++as_fn_success () { as_fn_return 0; } ++as_fn_failure () { as_fn_return 1; } ++as_fn_ret_success () { return 0; } ++as_fn_ret_failure () { return 1; } ++ ++exitcode=0 ++as_fn_success || { exitcode=1; echo as_fn_success failed.; } ++as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } ++as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } ++as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } ++if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : ++ ++else ++ exitcode=1; echo positional parameters were not saved. ++fi ++test x\$exitcode = x0 || exit 1 ++test -x / || exit 1" ++ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO ++ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO ++ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && ++ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 ++test \$(( 1 + 1 )) = 2 || exit 1" ++ if (eval "$as_required") 2>/dev/null; then : ++ as_have_required=yes ++else ++ as_have_required=no ++fi ++ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : ++ ++else ++ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++as_found=false ++for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ as_found=: ++ case $as_dir in #( ++ /*) ++ for as_base in sh bash ksh sh5; do ++ # Try only shells that exist, to save several forks. ++ as_shell=$as_dir/$as_base ++ if { test -f "$as_shell" || test -f "$as_shell.exe"; } && ++ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : ++ CONFIG_SHELL=$as_shell as_have_required=yes ++ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : ++ break 2 ++fi ++fi ++ done;; ++ esac ++ as_found=false ++done ++$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && ++ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : ++ CONFIG_SHELL=$SHELL as_have_required=yes ++fi; } ++IFS=$as_save_IFS ++ ++ ++ if test "x$CONFIG_SHELL" != x; then : ++ export CONFIG_SHELL ++ # We cannot yet assume a decent shell, so we have to provide a ++# neutralization value for shells without unset; and this also ++# works around shells that cannot unset nonexistent variables. ++# Preserve -v and -x to the replacement shell. ++BASH_ENV=/dev/null ++ENV=/dev/null ++(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV ++case $- in # (((( ++ *v*x* | *x*v* ) as_opts=-vx ;; ++ *v* ) as_opts=-v ;; ++ *x* ) as_opts=-x ;; ++ * ) as_opts= ;; ++esac ++exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} ++# Admittedly, this is quite paranoid, since all the known shells bail ++# out after a failed `exec'. ++$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 ++exit 255 ++fi ++ ++ if test x$as_have_required = xno; then : ++ $as_echo "$0: This script requires a shell more modern than all" ++ $as_echo "$0: the shells that I found on your system." ++ if test x${ZSH_VERSION+set} = xset ; then ++ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" ++ $as_echo "$0: be upgraded to zsh 4.3.4 or later." ++ else ++ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, ++$0: including any error possibly output before this ++$0: message. Then install a modern shell, or manually run ++$0: the script under such a shell if you do have one." ++ fi ++ exit 1 ++fi ++fi ++fi ++SHELL=${CONFIG_SHELL-/bin/sh} ++export SHELL ++# Unset more variables known to interfere with behavior of common tools. ++CLICOLOR_FORCE= GREP_OPTIONS= ++unset CLICOLOR_FORCE GREP_OPTIONS ++ ++## --------------------- ## ++## M4sh Shell Functions. ## ++## --------------------- ## ++# as_fn_unset VAR ++# --------------- ++# Portably unset VAR. ++as_fn_unset () ++{ ++ { eval $1=; unset $1;} ++} ++as_unset=as_fn_unset ++ ++# as_fn_set_status STATUS ++# ----------------------- ++# Set $? to STATUS, without forking. ++as_fn_set_status () ++{ ++ return $1 ++} # as_fn_set_status ++ ++# as_fn_exit STATUS ++# ----------------- ++# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. ++as_fn_exit () ++{ ++ set +e ++ as_fn_set_status $1 ++ exit $1 ++} # as_fn_exit ++ ++# as_fn_mkdir_p ++# ------------- ++# Create "$as_dir" as a directory, including parents if necessary. ++as_fn_mkdir_p () ++{ ++ ++ case $as_dir in #( ++ -*) as_dir=./$as_dir;; ++ esac ++ test -d "$as_dir" || eval $as_mkdir_p || { ++ as_dirs= ++ while :; do ++ case $as_dir in #( ++ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( ++ *) as_qdir=$as_dir;; ++ esac ++ as_dirs="'$as_qdir' $as_dirs" ++ as_dir=`$as_dirname -- "$as_dir" || ++$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ ++ X"$as_dir" : 'X\(//\)[^/]' \| \ ++ X"$as_dir" : 'X\(//\)$' \| \ ++ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || ++$as_echo X"$as_dir" | ++ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ ++ s//\1/ ++ q ++ } ++ /^X\(\/\/\)[^/].*/{ ++ s//\1/ ++ q ++ } ++ /^X\(\/\/\)$/{ ++ s//\1/ ++ q ++ } ++ /^X\(\/\).*/{ ++ s//\1/ ++ q ++ } ++ s/.*/./; q'` ++ test -d "$as_dir" && break ++ done ++ test -z "$as_dirs" || eval "mkdir $as_dirs" ++ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" ++ ++ ++} # as_fn_mkdir_p ++ ++# as_fn_executable_p FILE ++# ----------------------- ++# Test if FILE is an executable regular file. ++as_fn_executable_p () ++{ ++ test -f "$1" && test -x "$1" ++} # as_fn_executable_p ++# as_fn_append VAR VALUE ++# ---------------------- ++# Append the text in VALUE to the end of the definition contained in VAR. Take ++# advantage of any shell optimizations that allow amortized linear growth over ++# repeated appends, instead of the typical quadratic growth present in naive ++# implementations. ++if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : ++ eval 'as_fn_append () ++ { ++ eval $1+=\$2 ++ }' ++else ++ as_fn_append () ++ { ++ eval $1=\$$1\$2 ++ } ++fi # as_fn_append ++ ++# as_fn_arith ARG... ++# ------------------ ++# Perform arithmetic evaluation on the ARGs, and store the result in the ++# global $as_val. Take advantage of shells that can avoid forks. The arguments ++# must be portable across $(()) and expr. ++if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : ++ eval 'as_fn_arith () ++ { ++ as_val=$(( $* )) ++ }' ++else ++ as_fn_arith () ++ { ++ as_val=`expr "$@" || test $? -eq 1` ++ } ++fi # as_fn_arith ++ ++ ++# as_fn_error STATUS ERROR [LINENO LOG_FD] ++# ---------------------------------------- ++# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are ++# provided, also output the error to LOG_FD, referencing LINENO. Then exit the ++# script with STATUS, using 1 if that was 0. ++as_fn_error () ++{ ++ as_status=$1; test $as_status -eq 0 && as_status=1 ++ if test "$4"; then ++ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack ++ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 ++ fi ++ $as_echo "$as_me: error: $2" >&2 ++ as_fn_exit $as_status ++} # as_fn_error ++ ++if expr a : '\(a\)' >/dev/null 2>&1 && ++ test "X`expr 00001 : '.*\(...\)'`" = X001; then ++ as_expr=expr ++else ++ as_expr=false ++fi ++ ++if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then ++ as_basename=basename ++else ++ as_basename=false ++fi ++ ++if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then ++ as_dirname=dirname ++else ++ as_dirname=false ++fi ++ ++as_me=`$as_basename -- "$0" || ++$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ ++ X"$0" : 'X\(//\)$' \| \ ++ X"$0" : 'X\(/\)' \| . 2>/dev/null || ++$as_echo X/"$0" | ++ sed '/^.*\/\([^/][^/]*\)\/*$/{ ++ s//\1/ ++ q ++ } ++ /^X\/\(\/\/\)$/{ ++ s//\1/ ++ q ++ } ++ /^X\/\(\/\).*/{ ++ s//\1/ ++ q ++ } ++ s/.*/./; q'` ++ ++# Avoid depending upon Character Ranges. ++as_cr_letters='abcdefghijklmnopqrstuvwxyz' ++as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' ++as_cr_Letters=$as_cr_letters$as_cr_LETTERS ++as_cr_digits='0123456789' ++as_cr_alnum=$as_cr_Letters$as_cr_digits ++ ++ ++ as_lineno_1=$LINENO as_lineno_1a=$LINENO ++ as_lineno_2=$LINENO as_lineno_2a=$LINENO ++ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && ++ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { ++ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) ++ sed -n ' ++ p ++ /[$]LINENO/= ++ ' <$as_myself | ++ sed ' ++ s/[$]LINENO.*/&-/ ++ t lineno ++ b ++ :lineno ++ N ++ :loop ++ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ ++ t loop ++ s/-\n.*// ++ ' >$as_me.lineno && ++ chmod +x "$as_me.lineno" || ++ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } ++ ++ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have ++ # already done that, so ensure we don't try to do so again and fall ++ # in an infinite loop. This has already happened in practice. ++ _as_can_reexec=no; export _as_can_reexec ++ # Don't try to exec as it changes $[0], causing all sort of problems ++ # (the dirname of $[0] is not the place where we might find the ++ # original and so on. Autoconf is especially sensitive to this). ++ . "./$as_me.lineno" ++ # Exit status is that of the last command. ++ exit ++} ++ ++ECHO_C= ECHO_N= ECHO_T= ++case `echo -n x` in #((((( ++-n*) ++ case `echo 'xy\c'` in ++ *c*) ECHO_T=' ';; # ECHO_T is single tab character. ++ xy) ECHO_C='\c';; ++ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ++ ECHO_T=' ';; ++ esac;; ++*) ++ ECHO_N='-n';; ++esac ++ ++rm -f conf$$ conf$$.exe conf$$.file ++if test -d conf$$.dir; then ++ rm -f conf$$.dir/conf$$.file ++else ++ rm -f conf$$.dir ++ mkdir conf$$.dir 2>/dev/null ++fi ++if (echo >conf$$.file) 2>/dev/null; then ++ if ln -s conf$$.file conf$$ 2>/dev/null; then ++ as_ln_s='ln -s' ++ # ... but there are two gotchas: ++ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. ++ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. ++ # In both cases, we have to default to `cp -pR'. ++ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || ++ as_ln_s='cp -pR' ++ elif ln conf$$.file conf$$ 2>/dev/null; then ++ as_ln_s=ln ++ else ++ as_ln_s='cp -pR' ++ fi ++else ++ as_ln_s='cp -pR' ++fi ++rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file ++rmdir conf$$.dir 2>/dev/null ++ ++if mkdir -p . 2>/dev/null; then ++ as_mkdir_p='mkdir -p "$as_dir"' ++else ++ test -d ./-p && rmdir ./-p ++ as_mkdir_p=false ++fi ++ ++as_test_x='test -x' ++as_executable_p=as_fn_executable_p ++ ++# Sed expression to map a string onto a valid CPP name. ++as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" ++ ++# Sed expression to map a string onto a valid variable name. ++as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" ++ ++ ++test -n "$DJDIR" || exec 7<&0 </dev/null ++exec 6>&1 ++ ++# Name of the host. ++# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, ++# so uname gets run too. ++ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` ++ ++# ++# Initializations. ++# ++ac_default_prefix=/usr/local ++ac_clean_files= ++ac_config_libobj_dir=. ++LIBOBJS= ++cross_compiling=no ++subdirs= ++MFLAGS= ++MAKEFLAGS= ++ ++# Identity of this package. ++PACKAGE_NAME='sqlite' ++PACKAGE_TARNAME='sqlite' ++PACKAGE_VERSION='3.26.0' ++PACKAGE_STRING='sqlite 3.26.0' ++PACKAGE_BUGREPORT='' ++PACKAGE_URL='' ++ ++# Factoring default headers for most tests. ++ac_includes_default="\ ++#include <stdio.h> ++#ifdef HAVE_SYS_TYPES_H ++# include <sys/types.h> ++#endif ++#ifdef HAVE_SYS_STAT_H ++# include <sys/stat.h> ++#endif ++#ifdef STDC_HEADERS ++# include <stdlib.h> ++# include <stddef.h> ++#else ++# ifdef HAVE_STDLIB_H ++# include <stdlib.h> ++# endif ++#endif ++#ifdef HAVE_STRING_H ++# if !defined STDC_HEADERS && defined HAVE_MEMORY_H ++# include <memory.h> ++# endif ++# include <string.h> ++#endif ++#ifdef HAVE_STRINGS_H ++# include <strings.h> ++#endif ++#ifdef HAVE_INTTYPES_H ++# include <inttypes.h> ++#endif ++#ifdef HAVE_STDINT_H ++# include <stdint.h> ++#endif ++#ifdef HAVE_UNISTD_H ++# include <unistd.h> ++#endif" ++ ++ac_subst_vars='LTLIBOBJS ++LIBOBJS ++TCLSH_PROG ++VC_MANIFEST_EMBED_EXE ++VC_MANIFEST_EMBED_DLL ++RANLIB_STUB ++MAKE_STUB_LIB ++MAKE_STATIC_LIB ++MAKE_SHARED_LIB ++MAKE_LIB ++TCL_DBGX ++LDFLAGS_DEFAULT ++CFLAGS_DEFAULT ++LD_LIBRARY_PATH_VAR ++SHLIB_CFLAGS ++SHLIB_LD_LIBS ++SHLIB_LD ++STLIB_LD ++CFLAGS_WARNING ++CFLAGS_OPTIMIZE ++CFLAGS_DEBUG ++RC ++CELIB_DIR ++AR ++SHARED_BUILD ++TCL_THREADS ++TCL_INCLUDES ++PKG_OBJECTS ++PKG_SOURCES ++MATH_LIBS ++EGREP ++GREP ++RANLIB ++SET_MAKE ++INSTALL_SCRIPT ++INSTALL_PROGRAM ++INSTALL_DATA ++INSTALL ++CPP ++TCL_SHLIB_LD_LIBS ++TCL_LD_FLAGS ++TCL_EXTRA_CFLAGS ++TCL_DEFS ++TCL_LIBS ++CLEANFILES ++OBJEXT ++ac_ct_CC ++CPPFLAGS ++LDFLAGS ++CFLAGS ++CC ++TCL_STUB_LIB_SPEC ++TCL_STUB_LIB_FLAG ++TCL_STUB_LIB_FILE ++TCL_LIB_SPEC ++TCL_LIB_FLAG ++TCL_LIB_FILE ++TCL_SRC_DIR ++TCL_BIN_DIR ++TCL_PATCH_LEVEL ++TCL_VERSION ++PKG_CFLAGS ++PKG_LIBS ++PKG_INCLUDES ++PKG_HEADERS ++PKG_TCL_SOURCES ++PKG_STUB_OBJECTS ++PKG_STUB_SOURCES ++PKG_STUB_LIB_FILE ++PKG_LIB_FILE ++EXEEXT ++CYGPATH ++target_alias ++host_alias ++build_alias ++LIBS ++ECHO_T ++ECHO_N ++ECHO_C ++DEFS ++mandir ++localedir ++libdir ++psdir ++pdfdir ++dvidir ++htmldir ++infodir ++docdir ++oldincludedir ++includedir ++localstatedir ++sharedstatedir ++sysconfdir ++datadir ++datarootdir ++libexecdir ++sbindir ++bindir ++program_transform_name ++prefix ++exec_prefix ++PACKAGE_URL ++PACKAGE_BUGREPORT ++PACKAGE_STRING ++PACKAGE_VERSION ++PACKAGE_TARNAME ++PACKAGE_NAME ++PATH_SEPARATOR ++SHELL' ++ac_subst_files='' ++ac_user_opts=' ++enable_option_checking ++with_tcl ++with_system_sqlite ++with_tclinclude ++enable_threads ++enable_shared ++enable_64bit ++enable_64bit_vis ++enable_rpath ++enable_wince ++with_celib ++enable_symbols ++' ++ ac_precious_vars='build_alias ++host_alias ++target_alias ++CC ++CFLAGS ++LDFLAGS ++LIBS ++CPPFLAGS ++CPP' ++ ++ ++# Initialize some variables set by options. ++ac_init_help= ++ac_init_version=false ++ac_unrecognized_opts= ++ac_unrecognized_sep= ++# The variables have the same names as the options, with ++# dashes changed to underlines. ++cache_file=/dev/null ++exec_prefix=NONE ++no_create= ++no_recursion= ++prefix=NONE ++program_prefix=NONE ++program_suffix=NONE ++program_transform_name=s,x,x, ++silent= ++site= ++srcdir= ++verbose= ++x_includes=NONE ++x_libraries=NONE ++ ++# Installation directory options. ++# These are left unexpanded so users can "make install exec_prefix=/foo" ++# and all the variables that are supposed to be based on exec_prefix ++# by default will actually change. ++# Use braces instead of parens because sh, perl, etc. also accept them. ++# (The list follows the same order as the GNU Coding Standards.) ++bindir='${exec_prefix}/bin' ++sbindir='${exec_prefix}/sbin' ++libexecdir='${exec_prefix}/libexec' ++datarootdir='${prefix}/share' ++datadir='${datarootdir}' ++sysconfdir='${prefix}/etc' ++sharedstatedir='${prefix}/com' ++localstatedir='${prefix}/var' ++includedir='${prefix}/include' ++oldincludedir='/usr/include' ++docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' ++infodir='${datarootdir}/info' ++htmldir='${docdir}' ++dvidir='${docdir}' ++pdfdir='${docdir}' ++psdir='${docdir}' ++libdir='${exec_prefix}/lib' ++localedir='${datarootdir}/locale' ++mandir='${datarootdir}/man' ++ ++ac_prev= ++ac_dashdash= ++for ac_option ++do ++ # If the previous option needs an argument, assign it. ++ if test -n "$ac_prev"; then ++ eval $ac_prev=\$ac_option ++ ac_prev= ++ continue ++ fi ++ ++ case $ac_option in ++ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; ++ *=) ac_optarg= ;; ++ *) ac_optarg=yes ;; ++ esac ++ ++ # Accept the important Cygnus configure options, so we can diagnose typos. ++ ++ case $ac_dashdash$ac_option in ++ --) ++ ac_dashdash=yes ;; ++ ++ -bindir | --bindir | --bindi | --bind | --bin | --bi) ++ ac_prev=bindir ;; ++ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) ++ bindir=$ac_optarg ;; ++ ++ -build | --build | --buil | --bui | --bu) ++ ac_prev=build_alias ;; ++ -build=* | --build=* | --buil=* | --bui=* | --bu=*) ++ build_alias=$ac_optarg ;; ++ ++ -cache-file | --cache-file | --cache-fil | --cache-fi \ ++ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ++ ac_prev=cache_file ;; ++ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ ++ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) ++ cache_file=$ac_optarg ;; ++ ++ --config-cache | -C) ++ cache_file=config.cache ;; ++ ++ -datadir | --datadir | --datadi | --datad) ++ ac_prev=datadir ;; ++ -datadir=* | --datadir=* | --datadi=* | --datad=*) ++ datadir=$ac_optarg ;; ++ ++ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ ++ | --dataroo | --dataro | --datar) ++ ac_prev=datarootdir ;; ++ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ ++ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) ++ datarootdir=$ac_optarg ;; ++ ++ -disable-* | --disable-*) ++ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` ++ # Reject names that are not valid shell variable names. ++ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && ++ as_fn_error $? "invalid feature name: $ac_useropt" ++ ac_useropt_orig=$ac_useropt ++ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` ++ case $ac_user_opts in ++ *" ++"enable_$ac_useropt" ++"*) ;; ++ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ++ ac_unrecognized_sep=', ';; ++ esac ++ eval enable_$ac_useropt=no ;; ++ ++ -docdir | --docdir | --docdi | --doc | --do) ++ ac_prev=docdir ;; ++ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) ++ docdir=$ac_optarg ;; ++ ++ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ++ ac_prev=dvidir ;; ++ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) ++ dvidir=$ac_optarg ;; ++ ++ -enable-* | --enable-*) ++ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` ++ # Reject names that are not valid shell variable names. ++ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && ++ as_fn_error $? "invalid feature name: $ac_useropt" ++ ac_useropt_orig=$ac_useropt ++ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` ++ case $ac_user_opts in ++ *" ++"enable_$ac_useropt" ++"*) ;; ++ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ++ ac_unrecognized_sep=', ';; ++ esac ++ eval enable_$ac_useropt=\$ac_optarg ;; ++ ++ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ ++ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ ++ | --exec | --exe | --ex) ++ ac_prev=exec_prefix ;; ++ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ ++ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ ++ | --exec=* | --exe=* | --ex=*) ++ exec_prefix=$ac_optarg ;; ++ ++ -gas | --gas | --ga | --g) ++ # Obsolete; use --with-gas. ++ with_gas=yes ;; ++ ++ -help | --help | --hel | --he | -h) ++ ac_init_help=long ;; ++ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ++ ac_init_help=recursive ;; ++ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ++ ac_init_help=short ;; ++ ++ -host | --host | --hos | --ho) ++ ac_prev=host_alias ;; ++ -host=* | --host=* | --hos=* | --ho=*) ++ host_alias=$ac_optarg ;; ++ ++ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ++ ac_prev=htmldir ;; ++ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ ++ | --ht=*) ++ htmldir=$ac_optarg ;; ++ ++ -includedir | --includedir | --includedi | --included | --include \ ++ | --includ | --inclu | --incl | --inc) ++ ac_prev=includedir ;; ++ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ ++ | --includ=* | --inclu=* | --incl=* | --inc=*) ++ includedir=$ac_optarg ;; ++ ++ -infodir | --infodir | --infodi | --infod | --info | --inf) ++ ac_prev=infodir ;; ++ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) ++ infodir=$ac_optarg ;; ++ ++ -libdir | --libdir | --libdi | --libd) ++ ac_prev=libdir ;; ++ -libdir=* | --libdir=* | --libdi=* | --libd=*) ++ libdir=$ac_optarg ;; ++ ++ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ ++ | --libexe | --libex | --libe) ++ ac_prev=libexecdir ;; ++ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ ++ | --libexe=* | --libex=* | --libe=*) ++ libexecdir=$ac_optarg ;; ++ ++ -localedir | --localedir | --localedi | --localed | --locale) ++ ac_prev=localedir ;; ++ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) ++ localedir=$ac_optarg ;; ++ ++ -localstatedir | --localstatedir | --localstatedi | --localstated \ ++ | --localstate | --localstat | --localsta | --localst | --locals) ++ ac_prev=localstatedir ;; ++ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ ++ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) ++ localstatedir=$ac_optarg ;; ++ ++ -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ++ ac_prev=mandir ;; ++ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) ++ mandir=$ac_optarg ;; ++ ++ -nfp | --nfp | --nf) ++ # Obsolete; use --without-fp. ++ with_fp=no ;; ++ ++ -no-create | --no-create | --no-creat | --no-crea | --no-cre \ ++ | --no-cr | --no-c | -n) ++ no_create=yes ;; ++ ++ -no-recursion | --no-recursion | --no-recursio | --no-recursi \ ++ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ++ no_recursion=yes ;; ++ ++ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ ++ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ ++ | --oldin | --oldi | --old | --ol | --o) ++ ac_prev=oldincludedir ;; ++ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ ++ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ ++ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) ++ oldincludedir=$ac_optarg ;; ++ ++ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ++ ac_prev=prefix ;; ++ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) ++ prefix=$ac_optarg ;; ++ ++ -program-prefix | --program-prefix | --program-prefi | --program-pref \ ++ | --program-pre | --program-pr | --program-p) ++ ac_prev=program_prefix ;; ++ -program-prefix=* | --program-prefix=* | --program-prefi=* \ ++ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) ++ program_prefix=$ac_optarg ;; ++ ++ -program-suffix | --program-suffix | --program-suffi | --program-suff \ ++ | --program-suf | --program-su | --program-s) ++ ac_prev=program_suffix ;; ++ -program-suffix=* | --program-suffix=* | --program-suffi=* \ ++ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) ++ program_suffix=$ac_optarg ;; ++ ++ -program-transform-name | --program-transform-name \ ++ | --program-transform-nam | --program-transform-na \ ++ | --program-transform-n | --program-transform- \ ++ | --program-transform | --program-transfor \ ++ | --program-transfo | --program-transf \ ++ | --program-trans | --program-tran \ ++ | --progr-tra | --program-tr | --program-t) ++ ac_prev=program_transform_name ;; ++ -program-transform-name=* | --program-transform-name=* \ ++ | --program-transform-nam=* | --program-transform-na=* \ ++ | --program-transform-n=* | --program-transform-=* \ ++ | --program-transform=* | --program-transfor=* \ ++ | --program-transfo=* | --program-transf=* \ ++ | --program-trans=* | --program-tran=* \ ++ | --progr-tra=* | --program-tr=* | --program-t=*) ++ program_transform_name=$ac_optarg ;; ++ ++ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ++ ac_prev=pdfdir ;; ++ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) ++ pdfdir=$ac_optarg ;; ++ ++ -psdir | --psdir | --psdi | --psd | --ps) ++ ac_prev=psdir ;; ++ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) ++ psdir=$ac_optarg ;; ++ ++ -q | -quiet | --quiet | --quie | --qui | --qu | --q \ ++ | -silent | --silent | --silen | --sile | --sil) ++ silent=yes ;; ++ ++ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ++ ac_prev=sbindir ;; ++ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ ++ | --sbi=* | --sb=*) ++ sbindir=$ac_optarg ;; ++ ++ -sharedstatedir | --sharedstatedir | --sharedstatedi \ ++ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ ++ | --sharedst | --shareds | --shared | --share | --shar \ ++ | --sha | --sh) ++ ac_prev=sharedstatedir ;; ++ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ ++ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ ++ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ ++ | --sha=* | --sh=*) ++ sharedstatedir=$ac_optarg ;; ++ ++ -site | --site | --sit) ++ ac_prev=site ;; ++ -site=* | --site=* | --sit=*) ++ site=$ac_optarg ;; ++ ++ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ++ ac_prev=srcdir ;; ++ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) ++ srcdir=$ac_optarg ;; ++ ++ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ ++ | --syscon | --sysco | --sysc | --sys | --sy) ++ ac_prev=sysconfdir ;; ++ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ ++ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) ++ sysconfdir=$ac_optarg ;; ++ ++ -target | --target | --targe | --targ | --tar | --ta | --t) ++ ac_prev=target_alias ;; ++ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) ++ target_alias=$ac_optarg ;; ++ ++ -v | -verbose | --verbose | --verbos | --verbo | --verb) ++ verbose=yes ;; ++ ++ -version | --version | --versio | --versi | --vers | -V) ++ ac_init_version=: ;; ++ ++ -with-* | --with-*) ++ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` ++ # Reject names that are not valid shell variable names. ++ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && ++ as_fn_error $? "invalid package name: $ac_useropt" ++ ac_useropt_orig=$ac_useropt ++ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` ++ case $ac_user_opts in ++ *" ++"with_$ac_useropt" ++"*) ;; ++ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ++ ac_unrecognized_sep=', ';; ++ esac ++ eval with_$ac_useropt=\$ac_optarg ;; ++ ++ -without-* | --without-*) ++ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` ++ # Reject names that are not valid shell variable names. ++ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && ++ as_fn_error $? "invalid package name: $ac_useropt" ++ ac_useropt_orig=$ac_useropt ++ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` ++ case $ac_user_opts in ++ *" ++"with_$ac_useropt" ++"*) ;; ++ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ++ ac_unrecognized_sep=', ';; ++ esac ++ eval with_$ac_useropt=no ;; ++ ++ --x) ++ # Obsolete; use --with-x. ++ with_x=yes ;; ++ ++ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ ++ | --x-incl | --x-inc | --x-in | --x-i) ++ ac_prev=x_includes ;; ++ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ ++ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) ++ x_includes=$ac_optarg ;; ++ ++ -x-libraries | --x-libraries | --x-librarie | --x-librari \ ++ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ++ ac_prev=x_libraries ;; ++ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ ++ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) ++ x_libraries=$ac_optarg ;; ++ ++ -*) as_fn_error $? "unrecognized option: \`$ac_option' ++Try \`$0 --help' for more information" ++ ;; ++ ++ *=*) ++ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` ++ # Reject names that are not valid shell variable names. ++ case $ac_envvar in #( ++ '' | [0-9]* | *[!_$as_cr_alnum]* ) ++ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; ++ esac ++ eval $ac_envvar=\$ac_optarg ++ export $ac_envvar ;; ++ ++ *) ++ # FIXME: should be removed in autoconf 3.0. ++ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 ++ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && ++ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 ++ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ++ ;; ++ ++ esac ++done ++ ++if test -n "$ac_prev"; then ++ ac_option=--`echo $ac_prev | sed 's/_/-/g'` ++ as_fn_error $? "missing argument to $ac_option" ++fi ++ ++if test -n "$ac_unrecognized_opts"; then ++ case $enable_option_checking in ++ no) ;; ++ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; ++ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; ++ esac ++fi ++ ++# Check all directory arguments for consistency. ++for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ ++ datadir sysconfdir sharedstatedir localstatedir includedir \ ++ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ ++ libdir localedir mandir ++do ++ eval ac_val=\$$ac_var ++ # Remove trailing slashes. ++ case $ac_val in ++ */ ) ++ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` ++ eval $ac_var=\$ac_val;; ++ esac ++ # Be sure to have absolute directory names. ++ case $ac_val in ++ [\\/$]* | ?:[\\/]* ) continue;; ++ NONE | '' ) case $ac_var in *prefix ) continue;; esac;; ++ esac ++ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" ++done ++ ++# There might be people who depend on the old broken behavior: `$host' ++# used to hold the argument of --host etc. ++# FIXME: To remove some day. ++build=$build_alias ++host=$host_alias ++target=$target_alias ++ ++# FIXME: To remove some day. ++if test "x$host_alias" != x; then ++ if test "x$build_alias" = x; then ++ cross_compiling=maybe ++ elif test "x$build_alias" != "x$host_alias"; then ++ cross_compiling=yes ++ fi ++fi ++ ++ac_tool_prefix= ++test -n "$host_alias" && ac_tool_prefix=$host_alias- ++ ++test "$silent" = yes && exec 6>/dev/null ++ ++ ++ac_pwd=`pwd` && test -n "$ac_pwd" && ++ac_ls_di=`ls -di .` && ++ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || ++ as_fn_error $? "working directory cannot be determined" ++test "X$ac_ls_di" = "X$ac_pwd_ls_di" || ++ as_fn_error $? "pwd does not report name of working directory" ++ ++ ++# Find the source files, if location was not specified. ++if test -z "$srcdir"; then ++ ac_srcdir_defaulted=yes ++ # Try the directory containing this script, then the parent directory. ++ ac_confdir=`$as_dirname -- "$as_myself" || ++$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ ++ X"$as_myself" : 'X\(//\)[^/]' \| \ ++ X"$as_myself" : 'X\(//\)$' \| \ ++ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || ++$as_echo X"$as_myself" | ++ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ ++ s//\1/ ++ q ++ } ++ /^X\(\/\/\)[^/].*/{ ++ s//\1/ ++ q ++ } ++ /^X\(\/\/\)$/{ ++ s//\1/ ++ q ++ } ++ /^X\(\/\).*/{ ++ s//\1/ ++ q ++ } ++ s/.*/./; q'` ++ srcdir=$ac_confdir ++ if test ! -r "$srcdir/$ac_unique_file"; then ++ srcdir=.. ++ fi ++else ++ ac_srcdir_defaulted=no ++fi ++if test ! -r "$srcdir/$ac_unique_file"; then ++ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." ++ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" ++fi ++ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ++ac_abs_confdir=`( ++ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" ++ pwd)` ++# When building in place, set srcdir=. ++if test "$ac_abs_confdir" = "$ac_pwd"; then ++ srcdir=. ++fi ++# Remove unnecessary trailing slashes from srcdir. ++# Double slashes in file names in object file debugging info ++# mess up M-x gdb in Emacs. ++case $srcdir in ++*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; ++esac ++for ac_var in $ac_precious_vars; do ++ eval ac_env_${ac_var}_set=\${${ac_var}+set} ++ eval ac_env_${ac_var}_value=\$${ac_var} ++ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} ++ eval ac_cv_env_${ac_var}_value=\$${ac_var} ++done ++ ++# ++# 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.26.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. ++ ++Configuration: ++ -h, --help display this help and exit ++ --help=short display options specific to this package ++ --help=recursive display the short help of all the included packages ++ -V, --version display version information and exit ++ -q, --quiet, --silent do not print \`checking ...' messages ++ --cache-file=FILE cache test results in FILE [disabled] ++ -C, --config-cache alias for \`--cache-file=config.cache' ++ -n, --no-create do not create output files ++ --srcdir=DIR find the sources in DIR [configure dir or \`..'] ++ ++Installation directories: ++ --prefix=PREFIX install architecture-independent files in PREFIX ++ [$ac_default_prefix] ++ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX ++ [PREFIX] ++ ++By default, \`make install' will install all the files in ++\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify ++an installation prefix other than \`$ac_default_prefix' using \`--prefix', ++for instance \`--prefix=\$HOME'. ++ ++For better control, use the options below. ++ ++Fine tuning of the installation directories: ++ --bindir=DIR user executables [EPREFIX/bin] ++ --sbindir=DIR system admin executables [EPREFIX/sbin] ++ --libexecdir=DIR program executables [EPREFIX/libexec] ++ --sysconfdir=DIR read-only single-machine data [PREFIX/etc] ++ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] ++ --localstatedir=DIR modifiable single-machine data [PREFIX/var] ++ --libdir=DIR object code libraries [EPREFIX/lib] ++ --includedir=DIR C header files [PREFIX/include] ++ --oldincludedir=DIR C header files for non-gcc [/usr/include] ++ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] ++ --datadir=DIR read-only architecture-independent data [DATAROOTDIR] ++ --infodir=DIR info documentation [DATAROOTDIR/info] ++ --localedir=DIR locale-dependent data [DATAROOTDIR/locale] ++ --mandir=DIR man documentation [DATAROOTDIR/man] ++ --docdir=DIR documentation root [DATAROOTDIR/doc/sqlite] ++ --htmldir=DIR html documentation [DOCDIR] ++ --dvidir=DIR dvi documentation [DOCDIR] ++ --pdfdir=DIR pdf documentation [DOCDIR] ++ --psdir=DIR ps documentation [DOCDIR] ++_ACEOF ++ ++ cat <<\_ACEOF ++_ACEOF ++fi ++ ++if test -n "$ac_init_help"; then ++ case $ac_init_help in ++ short | recursive ) echo "Configuration of sqlite 3.26.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] ++ --enable-threads build with threads ++ --enable-shared build and link with shared libraries (default: on) ++ --enable-64bit enable 64bit support (default: off) ++ --enable-64bit-vis enable 64bit Sparc VIS support (default: off) ++ --disable-rpath disable rpath support (default: on) ++ --enable-wince enable Win/CE support (where applicable) ++ --enable-symbols build with debugging symbols (default: off) ++ ++Optional Packages: ++ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] ++ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) ++ --with-tcl directory containing tcl configuration ++ (tclConfig.sh) ++ --with-system-sqlite use a system-supplied libsqlite3 instead of the ++ bundled one ++ --with-tclinclude directory containing the public Tcl header files ++ --with-celib=DIR use Windows/CE support library from DIR ++ ++Some influential environment variables: ++ CC C compiler command ++ CFLAGS C compiler flags ++ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a ++ nonstandard directory <lib dir> ++ LIBS libraries to pass to the linker, e.g. -l<library> ++ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if ++ you have headers in a nonstandard directory <include dir> ++ CPP C preprocessor ++ ++Use these variables to override the choices made by `configure' or to help ++it to find libraries and programs with nonstandard names/locations. ++ ++Report bugs to the package provider. ++_ACEOF ++ac_status=$? ++fi ++ ++if test "$ac_init_help" = "recursive"; then ++ # If there are subdirs, report their specific --help. ++ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue ++ test -d "$ac_dir" || ++ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || ++ continue ++ ac_builddir=. ++ ++case "$ac_dir" in ++.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; ++*) ++ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` ++ # A ".." for each directory in $ac_dir_suffix. ++ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` ++ case $ac_top_builddir_sub in ++ "") ac_top_builddir_sub=. ac_top_build_prefix= ;; ++ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; ++ esac ;; ++esac ++ac_abs_top_builddir=$ac_pwd ++ac_abs_builddir=$ac_pwd$ac_dir_suffix ++# for backward compatibility: ++ac_top_builddir=$ac_top_build_prefix ++ ++case $srcdir in ++ .) # We are building in place. ++ ac_srcdir=. ++ ac_top_srcdir=$ac_top_builddir_sub ++ ac_abs_top_srcdir=$ac_pwd ;; ++ [\\/]* | ?:[\\/]* ) # Absolute name. ++ ac_srcdir=$srcdir$ac_dir_suffix; ++ ac_top_srcdir=$srcdir ++ ac_abs_top_srcdir=$srcdir ;; ++ *) # Relative name. ++ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ++ ac_top_srcdir=$ac_top_build_prefix$srcdir ++ ac_abs_top_srcdir=$ac_pwd/$srcdir ;; ++esac ++ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix ++ ++ cd "$ac_dir" || { ac_status=$?; continue; } ++ # Check for guested configure. ++ if test -f "$ac_srcdir/configure.gnu"; then ++ echo && ++ $SHELL "$ac_srcdir/configure.gnu" --help=recursive ++ elif test -f "$ac_srcdir/configure"; then ++ echo && ++ $SHELL "$ac_srcdir/configure" --help=recursive ++ else ++ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 ++ fi || ac_status=$? ++ 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.26.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 ++fi ++ ++## ------------------------ ## ++## Autoconf initialization. ## ++## ------------------------ ## ++ ++# ac_fn_c_try_compile LINENO ++# -------------------------- ++# Try to compile conftest.$ac_ext, and return whether this succeeded. ++ac_fn_c_try_compile () ++{ ++ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack ++ rm -f conftest.$ac_objext ++ if { { ac_try="$ac_compile" ++case "(($ac_try" in ++ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; ++ *) ac_try_echo=$ac_try;; ++esac ++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" ++$as_echo "$ac_try_echo"; } >&5 ++ (eval "$ac_compile") 2>conftest.err ++ ac_status=$? ++ if test -s conftest.err; then ++ grep -v '^ *+' conftest.err >conftest.er1 ++ cat conftest.er1 >&5 ++ mv -f conftest.er1 conftest.err ++ fi ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; } && { ++ test -z "$ac_c_werror_flag" || ++ test ! -s conftest.err ++ } && test -s conftest.$ac_objext; then : ++ ac_retval=0 ++else ++ $as_echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++ ac_retval=1 ++fi ++ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno ++ as_fn_set_status $ac_retval ++ ++} # ac_fn_c_try_compile ++ ++# ac_fn_c_try_cpp LINENO ++# ---------------------- ++# Try to preprocess conftest.$ac_ext, and return whether this succeeded. ++ac_fn_c_try_cpp () ++{ ++ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack ++ if { { ac_try="$ac_cpp conftest.$ac_ext" ++case "(($ac_try" in ++ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; ++ *) ac_try_echo=$ac_try;; ++esac ++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" ++$as_echo "$ac_try_echo"; } >&5 ++ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ++ ac_status=$? ++ if test -s conftest.err; then ++ grep -v '^ *+' conftest.err >conftest.er1 ++ cat conftest.er1 >&5 ++ mv -f conftest.er1 conftest.err ++ fi ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; } > conftest.i && { ++ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || ++ test ! -s conftest.err ++ }; then : ++ ac_retval=0 ++else ++ $as_echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++ ac_retval=1 ++fi ++ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno ++ as_fn_set_status $ac_retval ++ ++} # ac_fn_c_try_cpp ++ ++# ac_fn_c_try_run LINENO ++# ---------------------- ++# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes ++# that executables *can* be run. ++ac_fn_c_try_run () ++{ ++ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack ++ if { { ac_try="$ac_link" ++case "(($ac_try" in ++ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; ++ *) ac_try_echo=$ac_try;; ++esac ++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" ++$as_echo "$ac_try_echo"; } >&5 ++ (eval "$ac_link") 2>&5 ++ ac_status=$? ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' ++ { { case "(($ac_try" in ++ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; ++ *) ac_try_echo=$ac_try;; ++esac ++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" ++$as_echo "$ac_try_echo"; } >&5 ++ (eval "$ac_try") 2>&5 ++ ac_status=$? ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; }; }; then : ++ ac_retval=0 ++else ++ $as_echo "$as_me: program exited with status $ac_status" >&5 ++ $as_echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++ ac_retval=$ac_status ++fi ++ rm -rf conftest.dSYM conftest_ipa8_conftest.oo ++ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno ++ as_fn_set_status $ac_retval ++ ++} # ac_fn_c_try_run ++ ++# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES ++# ------------------------------------------------------- ++# Tests whether HEADER exists and can be compiled using the include files in ++# INCLUDES, setting the cache variable VAR accordingly. ++ac_fn_c_check_header_compile () ++{ ++ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 ++$as_echo_n "checking for $2... " >&6; } ++if eval \${$3+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++$4 ++#include <$2> ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ eval "$3=yes" ++else ++ eval "$3=no" ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++fi ++eval ac_res=\$$3 ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 ++$as_echo "$ac_res" >&6; } ++ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno ++ ++} # ac_fn_c_check_header_compile ++ ++# ac_fn_c_try_link LINENO ++# ----------------------- ++# Try to link conftest.$ac_ext, and return whether this succeeded. ++ac_fn_c_try_link () ++{ ++ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack ++ rm -f conftest.$ac_objext conftest$ac_exeext ++ if { { ac_try="$ac_link" ++case "(($ac_try" in ++ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; ++ *) ac_try_echo=$ac_try;; ++esac ++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" ++$as_echo "$ac_try_echo"; } >&5 ++ (eval "$ac_link") 2>conftest.err ++ ac_status=$? ++ if test -s conftest.err; then ++ grep -v '^ *+' conftest.err >conftest.er1 ++ cat conftest.er1 >&5 ++ mv -f conftest.er1 conftest.err ++ fi ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; } && { ++ test -z "$ac_c_werror_flag" || ++ test ! -s conftest.err ++ } && test -s conftest$ac_exeext && { ++ test "$cross_compiling" = yes || ++ test -x conftest$ac_exeext ++ }; then : ++ ac_retval=0 ++else ++ $as_echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++ ac_retval=1 ++fi ++ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information ++ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would ++ # interfere with the next link command; also delete a directory that is ++ # left behind by Apple's compiler. We do this before executing the actions. ++ rm -rf conftest.dSYM conftest_ipa8_conftest.oo ++ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno ++ as_fn_set_status $ac_retval ++ ++} # ac_fn_c_try_link ++ ++# ac_fn_c_check_func LINENO FUNC VAR ++# ---------------------------------- ++# Tests whether FUNC exists, setting the cache variable VAR accordingly ++ac_fn_c_check_func () ++{ ++ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 ++$as_echo_n "checking for $2... " >&6; } ++if eval \${$3+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++/* Define $2 to an innocuous variant, in case <limits.h> declares $2. ++ For example, HP-UX 11i <limits.h> declares gettimeofday. */ ++#define $2 innocuous_$2 ++ ++/* System header to define __stub macros and hopefully few prototypes, ++ which can conflict with char $2 (); below. ++ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since ++ <limits.h> exists even on freestanding compilers. */ ++ ++#ifdef __STDC__ ++# include <limits.h> ++#else ++# include <assert.h> ++#endif ++ ++#undef $2 ++ ++/* Override any GCC internal prototype to avoid an error. ++ Use char because int might match the return type of a GCC ++ builtin and then its argument prototype would still apply. */ ++#ifdef __cplusplus ++extern "C" ++#endif ++char $2 (); ++/* The GNU C library defines this for functions which it implements ++ to always fail with ENOSYS. Some functions are actually named ++ something starting with __ and the normal name is an alias. */ ++#if defined __stub_$2 || defined __stub___$2 ++choke me ++#endif ++ ++int ++main () ++{ ++return $2 (); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ eval "$3=yes" ++else ++ eval "$3=no" ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++fi ++eval ac_res=\$$3 ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 ++$as_echo "$ac_res" >&6; } ++ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno ++ ++} # ac_fn_c_check_func ++ ++# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES ++# ------------------------------------------------------- ++# Tests whether HEADER exists, giving a warning if it cannot be compiled using ++# the include files in INCLUDES and setting the cache variable VAR ++# accordingly. ++ac_fn_c_check_header_mongrel () ++{ ++ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack ++ if eval \${$3+:} false; then : ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 ++$as_echo_n "checking for $2... " >&6; } ++if eval \${$3+:} false; then : ++ $as_echo_n "(cached) " >&6 ++fi ++eval ac_res=\$$3 ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 ++$as_echo "$ac_res" >&6; } ++else ++ # Is the header compilable? ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 ++$as_echo_n "checking $2 usability... " >&6; } ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++$4 ++#include <$2> ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ ac_header_compiler=yes ++else ++ ac_header_compiler=no ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 ++$as_echo "$ac_header_compiler" >&6; } ++ ++# Is the header present? ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 ++$as_echo_n "checking $2 presence... " >&6; } ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <$2> ++_ACEOF ++if ac_fn_c_try_cpp "$LINENO"; then : ++ ac_header_preproc=yes ++else ++ ac_header_preproc=no ++fi ++rm -f conftest.err conftest.i conftest.$ac_ext ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 ++$as_echo "$ac_header_preproc" >&6; } ++ ++# So? What about this header? ++case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( ++ yes:no: ) ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 ++$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 ++$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ++ ;; ++ no:yes:* ) ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 ++$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 ++$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 ++$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 ++$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 ++$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ++ ;; ++esac ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 ++$as_echo_n "checking for $2... " >&6; } ++if eval \${$3+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ eval "$3=\$ac_header_compiler" ++fi ++eval ac_res=\$$3 ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 ++$as_echo "$ac_res" >&6; } ++fi ++ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno ++ ++} # ac_fn_c_check_header_mongrel ++ ++# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES ++# --------------------------------------------- ++# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR ++# accordingly. ++ac_fn_c_check_decl () ++{ ++ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack ++ as_decl_name=`echo $2|sed 's/ *(.*//'` ++ as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 ++$as_echo_n "checking whether $as_decl_name is declared... " >&6; } ++if eval \${$3+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++$4 ++int ++main () ++{ ++#ifndef $as_decl_name ++#ifdef __cplusplus ++ (void) $as_decl_use; ++#else ++ (void) $as_decl_name; ++#endif ++#endif ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ eval "$3=yes" ++else ++ eval "$3=no" ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++fi ++eval ac_res=\$$3 ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 ++$as_echo "$ac_res" >&6; } ++ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno ++ ++} # ac_fn_c_check_decl ++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.26.0, which was ++generated by GNU Autoconf 2.69. Invocation command line was ++ ++ $ $0 $@ ++ ++_ACEOF ++exec 5>>config.log ++{ ++cat <<_ASUNAME ++## --------- ## ++## Platform. ## ++## --------- ## ++ ++hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` ++uname -m = `(uname -m) 2>/dev/null || echo unknown` ++uname -r = `(uname -r) 2>/dev/null || echo unknown` ++uname -s = `(uname -s) 2>/dev/null || echo unknown` ++uname -v = `(uname -v) 2>/dev/null || echo unknown` ++ ++/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` ++/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` ++ ++/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` ++/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` ++/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` ++/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` ++/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` ++/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` ++/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` ++ ++_ASUNAME ++ ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ $as_echo "PATH: $as_dir" ++ done ++IFS=$as_save_IFS ++ ++} >&5 ++ ++cat >&5 <<_ACEOF ++ ++ ++## ----------- ## ++## Core tests. ## ++## ----------- ## ++ ++_ACEOF ++ ++ ++# Keep a trace of the command line. ++# Strip out --no-create and --no-recursion so they do not pile up. ++# Strip out --silent because we don't want to record it for future runs. ++# Also quote any args containing shell meta-characters. ++# Make two passes to allow for proper duplicate-argument suppression. ++ac_configure_args= ++ac_configure_args0= ++ac_configure_args1= ++ac_must_keep_next=false ++for ac_pass in 1 2 ++do ++ for ac_arg ++ do ++ case $ac_arg in ++ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; ++ -q | -quiet | --quiet | --quie | --qui | --qu | --q \ ++ | -silent | --silent | --silen | --sile | --sil) ++ continue ;; ++ *\'*) ++ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; ++ esac ++ case $ac_pass in ++ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; ++ 2) ++ as_fn_append ac_configure_args1 " '$ac_arg'" ++ if test $ac_must_keep_next = true; then ++ ac_must_keep_next=false # Got value, back to normal. ++ else ++ case $ac_arg in ++ *=* | --config-cache | -C | -disable-* | --disable-* \ ++ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ ++ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ ++ | -with-* | --with-* | -without-* | --without-* | --x) ++ case "$ac_configure_args0 " in ++ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; ++ esac ++ ;; ++ -* ) ac_must_keep_next=true ;; ++ esac ++ fi ++ as_fn_append ac_configure_args " '$ac_arg'" ++ ;; ++ esac ++ done ++done ++{ ac_configure_args0=; unset ac_configure_args0;} ++{ ac_configure_args1=; unset ac_configure_args1;} ++ ++# When interrupted or exit'd, cleanup temporary files, and complete ++# config.log. We remove comments because anyway the quotes in there ++# would cause problems or look ugly. ++# WARNING: Use '\'' to represent an apostrophe within the trap. ++# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. ++trap 'exit_status=$? ++ # Save into config.log some information that might help in debugging. ++ { ++ echo ++ ++ $as_echo "## ---------------- ## ++## Cache variables. ## ++## ---------------- ##" ++ echo ++ # The following way of writing the cache mishandles newlines in values, ++( ++ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do ++ eval ac_val=\$$ac_var ++ case $ac_val in #( ++ *${as_nl}*) ++ case $ac_var in #( ++ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 ++$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; ++ esac ++ case $ac_var in #( ++ _ | IFS | as_nl) ;; #( ++ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( ++ *) { eval $ac_var=; unset $ac_var;} ;; ++ esac ;; ++ esac ++ done ++ (set) 2>&1 | ++ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( ++ *${as_nl}ac_space=\ *) ++ sed -n \ ++ "s/'\''/'\''\\\\'\'''\''/g; ++ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ++ ;; #( ++ *) ++ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ++ ;; ++ esac | ++ sort ++) ++ echo ++ ++ $as_echo "## ----------------- ## ++## Output variables. ## ++## ----------------- ##" ++ echo ++ for ac_var in $ac_subst_vars ++ do ++ eval ac_val=\$$ac_var ++ case $ac_val in ++ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; ++ esac ++ $as_echo "$ac_var='\''$ac_val'\''" ++ done | sort ++ echo ++ ++ if test -n "$ac_subst_files"; then ++ $as_echo "## ------------------- ## ++## File substitutions. ## ++## ------------------- ##" ++ echo ++ for ac_var in $ac_subst_files ++ do ++ eval ac_val=\$$ac_var ++ case $ac_val in ++ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; ++ esac ++ $as_echo "$ac_var='\''$ac_val'\''" ++ done | sort ++ echo ++ fi ++ ++ if test -s confdefs.h; then ++ $as_echo "## ----------- ## ++## confdefs.h. ## ++## ----------- ##" ++ echo ++ cat confdefs.h ++ echo ++ fi ++ test "$ac_signal" != 0 && ++ $as_echo "$as_me: caught signal $ac_signal" ++ $as_echo "$as_me: exit $exit_status" ++ } >&5 ++ rm -f core *.core core.conftest.* && ++ rm -f -r conftest* confdefs* conf$$* $ac_clean_files && ++ exit $exit_status ++' 0 ++for ac_signal in 1 2 13 15; do ++ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal ++done ++ac_signal=0 ++ ++# confdefs.h avoids OS command line length limits that DEFS can exceed. ++rm -f -r conftest* confdefs.h ++ ++$as_echo "/* confdefs.h */" > confdefs.h ++ ++# Predefined preprocessor variables. ++ ++cat >>confdefs.h <<_ACEOF ++#define PACKAGE_NAME "$PACKAGE_NAME" ++_ACEOF ++ ++cat >>confdefs.h <<_ACEOF ++#define PACKAGE_TARNAME "$PACKAGE_TARNAME" ++_ACEOF ++ ++cat >>confdefs.h <<_ACEOF ++#define PACKAGE_VERSION "$PACKAGE_VERSION" ++_ACEOF ++ ++cat >>confdefs.h <<_ACEOF ++#define PACKAGE_STRING "$PACKAGE_STRING" ++_ACEOF ++ ++cat >>confdefs.h <<_ACEOF ++#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" ++_ACEOF ++ ++cat >>confdefs.h <<_ACEOF ++#define PACKAGE_URL "$PACKAGE_URL" ++_ACEOF ++ ++ ++# Let the site file select an alternate cache file if it wants to. ++# Prefer an explicitly selected file to automatically selected ones. ++ac_site_file1=NONE ++ac_site_file2=NONE ++if test -n "$CONFIG_SITE"; then ++ # We do not want a PATH search for config.site. ++ case $CONFIG_SITE in #(( ++ -*) ac_site_file1=./$CONFIG_SITE;; ++ */*) ac_site_file1=$CONFIG_SITE;; ++ *) ac_site_file1=./$CONFIG_SITE;; ++ esac ++elif test "x$prefix" != xNONE; then ++ ac_site_file1=$prefix/share/config.site ++ ac_site_file2=$prefix/etc/config.site ++else ++ ac_site_file1=$ac_default_prefix/share/config.site ++ ac_site_file2=$ac_default_prefix/etc/config.site ++fi ++for ac_site_file in "$ac_site_file1" "$ac_site_file2" ++do ++ test "x$ac_site_file" = xNONE && continue ++ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 ++$as_echo "$as_me: loading site script $ac_site_file" >&6;} ++ sed 's/^/| /' "$ac_site_file" >&5 ++ . "$ac_site_file" \ ++ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 ++$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} ++as_fn_error $? "failed to load site script $ac_site_file ++See \`config.log' for more details" "$LINENO" 5; } ++ fi ++done ++ ++if test -r "$cache_file"; then ++ # Some versions of bash will fail to source /dev/null (special files ++ # actually), so we avoid doing that. DJGPP emulates it as a regular file. ++ if test /dev/null != "$cache_file" && test -f "$cache_file"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 ++$as_echo "$as_me: loading cache $cache_file" >&6;} ++ case $cache_file in ++ [\\/]* | ?:[\\/]* ) . "$cache_file";; ++ *) . "./$cache_file";; ++ esac ++ fi ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 ++$as_echo "$as_me: creating cache $cache_file" >&6;} ++ >$cache_file ++fi ++ ++# Check that the precious variables saved in the cache have kept the same ++# value. ++ac_cache_corrupted=false ++for ac_var in $ac_precious_vars; do ++ eval ac_old_set=\$ac_cv_env_${ac_var}_set ++ eval ac_new_set=\$ac_env_${ac_var}_set ++ eval ac_old_val=\$ac_cv_env_${ac_var}_value ++ eval ac_new_val=\$ac_env_${ac_var}_value ++ case $ac_old_set,$ac_new_set in ++ set,) ++ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 ++$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ++ ac_cache_corrupted=: ;; ++ ,set) ++ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 ++$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ++ ac_cache_corrupted=: ;; ++ ,);; ++ *) ++ if test "x$ac_old_val" != "x$ac_new_val"; then ++ # differences in whitespace do not lead to failure. ++ ac_old_val_w=`echo x $ac_old_val` ++ ac_new_val_w=`echo x $ac_new_val` ++ if test "$ac_old_val_w" != "$ac_new_val_w"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 ++$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ++ ac_cache_corrupted=: ++ else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 ++$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} ++ eval $ac_var=\$ac_old_val ++ fi ++ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 ++$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} ++ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 ++$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} ++ fi;; ++ esac ++ # Pass precious variables to config.status. ++ if test "$ac_new_set" = set; then ++ case $ac_new_val in ++ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; ++ *) ac_arg=$ac_var=$ac_new_val ;; ++ esac ++ case " $ac_configure_args " in ++ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. ++ *) as_fn_append ac_configure_args " '$ac_arg'" ;; ++ esac ++ fi ++done ++if $ac_cache_corrupted; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 ++$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} ++ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 ++$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} ++ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 ++fi ++## -------------------- ## ++## Main body of script. ## ++## -------------------- ## ++ ++ac_ext=c ++ac_cpp='$CPP $CPPFLAGS' ++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ++ac_compiler_gnu=$ac_cv_c_compiler_gnu ++ ++ ++ ++#-------------------------------------------------------------------- ++# 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. ++#-------------------------------------------------------------------- ++ ++ ++ # TEA extensions pass this us the version of TEA they think they ++ # are compatible with. ++ TEA_VERSION="3.9" ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for correct TEA configuration" >&5 ++$as_echo_n "checking for correct TEA configuration... " >&6; } ++ if test x"${PACKAGE_NAME}" = x ; then ++ as_fn_error $? " ++The PACKAGE_NAME variable must be defined by your TEA configure.in" "$LINENO" 5 ++ fi ++ if test x"3.9" = x ; then ++ as_fn_error $? " ++TEA version not specified." "$LINENO" 5 ++ elif test "3.9" != "${TEA_VERSION}" ; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: warning: requested TEA version \"3.9\", have \"${TEA_VERSION}\"" >&5 ++$as_echo "warning: requested TEA version \"3.9\", have \"${TEA_VERSION}\"" >&6; } ++ else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok (TEA ${TEA_VERSION})" >&5 ++$as_echo "ok (TEA ${TEA_VERSION})" >&6; } ++ fi ++ ++ # If the user did not set CFLAGS, set it now to keep macros ++ # like AC_PROG_CC and AC_TRY_COMPILE from adding "-g -O2". ++ if test "${CFLAGS+set}" != "set" ; then ++ CFLAGS="" ++ fi ++ ++ case "`uname -s`" in ++ *win32*|*WIN32*|*MINGW32_*) ++ # Extract the first word of "cygpath", so it can be a program name with args. ++set dummy cygpath; ac_word=$2 ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 ++$as_echo_n "checking for $ac_word... " >&6; } ++if ${ac_cv_prog_CYGPATH+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if test -n "$CYGPATH"; then ++ ac_cv_prog_CYGPATH="$CYGPATH" # Let the user override the test. ++else ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ++ ac_cv_prog_CYGPATH="cygpath -w" ++ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++ done ++IFS=$as_save_IFS ++ ++ test -z "$ac_cv_prog_CYGPATH" && ac_cv_prog_CYGPATH="echo" ++fi ++fi ++CYGPATH=$ac_cv_prog_CYGPATH ++if test -n "$CYGPATH"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CYGPATH" >&5 ++$as_echo "$CYGPATH" >&6; } ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++fi ++ ++ ++ EXEEXT=".exe" ++ TEA_PLATFORM="windows" ++ ;; ++ *CYGWIN_*) ++ CYGPATH=echo ++ EXEEXT=".exe" ++ # TEA_PLATFORM is determined later in LOAD_TCLCONFIG ++ ;; ++ *) ++ CYGPATH=echo ++ # Maybe we are cross-compiling.... ++ case ${host_alias} in ++ *mingw32*) ++ EXEEXT=".exe" ++ TEA_PLATFORM="windows" ++ ;; ++ *) ++ EXEEXT="" ++ TEA_PLATFORM="unix" ++ ;; ++ esac ++ ;; ++ esac ++ ++ # Check if exec_prefix is set. If not use fall back to prefix. ++ # Note when adjusted, so that TEA_PREFIX can correct for this. ++ # This is needed for recursive configures, since autoconf propagates ++ # $prefix, but not $exec_prefix (doh!). ++ if test x$exec_prefix = xNONE ; then ++ exec_prefix_default=yes ++ exec_prefix=$prefix ++ fi ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}" >&5 ++$as_echo "$as_me: configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}" >&6;} ++ ++ ++ ++ ++ # This package name must be replaced statically for AC_SUBST to work ++ ++ # Substitute STUB_LIB_FILE in case package creates a stub library too. ++ ++ ++ # We AC_SUBST these here to ensure they are subst'ed, ++ # in case the user doesn't call TEA_ADD_... ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ac_aux_dir= ++for ac_dir in tclconfig "$srcdir"/tclconfig; do ++ if test -f "$ac_dir/install-sh"; then ++ ac_aux_dir=$ac_dir ++ ac_install_sh="$ac_aux_dir/install-sh -c" ++ break ++ elif test -f "$ac_dir/install.sh"; then ++ ac_aux_dir=$ac_dir ++ ac_install_sh="$ac_aux_dir/install.sh -c" ++ break ++ elif test -f "$ac_dir/shtool"; then ++ ac_aux_dir=$ac_dir ++ ac_install_sh="$ac_aux_dir/shtool install -c" ++ break ++ fi ++done ++if test -z "$ac_aux_dir"; then ++ as_fn_error $? "cannot find install-sh, install.sh, or shtool in tclconfig \"$srcdir\"/tclconfig" "$LINENO" 5 ++fi ++ ++# These three variables are undocumented and unsupported, ++# and are intended to be withdrawn in a future Autoconf release. ++# They can cause serious problems if a builder's source tree is in a directory ++# whose full name contains unusual characters. ++ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ++ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ++ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. ++ ++ ++ ++#-------------------------------------------------------------------- ++# Load the tclConfig.sh file ++#-------------------------------------------------------------------- ++ ++ ++ ++ # ++ # Ok, lets find the tcl configuration ++ # First, look for one uninstalled. ++ # the alternative search directory is invoked by --with-tcl ++ # ++ ++ if test x"${no_tcl}" = x ; then ++ # we reset no_tcl in case something fails here ++ no_tcl=true ++ ++# Check whether --with-tcl was given. ++if test "${with_tcl+set}" = set; then : ++ withval=$with_tcl; with_tclconfig="${withval}" ++fi ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tcl configuration" >&5 ++$as_echo_n "checking for Tcl configuration... " >&6; } ++ if ${ac_cv_c_tclconfig+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ++ ++ # First check to see if --with-tcl was specified. ++ if test x"${with_tclconfig}" != x ; then ++ case "${with_tclconfig}" in ++ */tclConfig.sh ) ++ if test -f "${with_tclconfig}"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&5 ++$as_echo "$as_me: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&2;} ++ with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`" ++ fi ;; ++ esac ++ if test -f "${with_tclconfig}/tclConfig.sh" ; then ++ ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`" ++ else ++ as_fn_error $? "${with_tclconfig} directory doesn't contain tclConfig.sh" "$LINENO" 5 ++ fi ++ fi ++ ++ # then check for a private Tcl installation ++ if test x"${ac_cv_c_tclconfig}" = x ; then ++ for i in \ ++ ../tcl \ ++ `ls -dr ../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ ++ `ls -dr ../tcl[8-9].[0-9] 2>/dev/null` \ ++ `ls -dr ../tcl[8-9].[0-9]* 2>/dev/null` \ ++ ../../tcl \ ++ `ls -dr ../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ ++ `ls -dr ../../tcl[8-9].[0-9] 2>/dev/null` \ ++ `ls -dr ../../tcl[8-9].[0-9]* 2>/dev/null` \ ++ ../../../tcl \ ++ `ls -dr ../../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ ++ `ls -dr ../../../tcl[8-9].[0-9] 2>/dev/null` \ ++ `ls -dr ../../../tcl[8-9].[0-9]* 2>/dev/null` ; do ++ if test "${TEA_PLATFORM}" = "windows" \ ++ -a -f "$i/win/tclConfig.sh" ; then ++ ac_cv_c_tclconfig="`(cd $i/win; pwd)`" ++ break ++ fi ++ if test -f "$i/unix/tclConfig.sh" ; then ++ ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" ++ break ++ fi ++ done ++ fi ++ ++ # on Darwin, check in Framework installation locations ++ if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then ++ for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ ++ `ls -d /Library/Frameworks 2>/dev/null` \ ++ `ls -d /Network/Library/Frameworks 2>/dev/null` \ ++ `ls -d /System/Library/Frameworks 2>/dev/null` \ ++ ; do ++ if test -f "$i/Tcl.framework/tclConfig.sh" ; then ++ ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`" ++ break ++ fi ++ done ++ fi ++ ++ # TEA specific: on Windows, check in common installation locations ++ if test "${TEA_PLATFORM}" = "windows" \ ++ -a x"${ac_cv_c_tclconfig}" = x ; then ++ for i in `ls -d C:/Tcl/lib 2>/dev/null` \ ++ `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ ++ ; do ++ if test -f "$i/tclConfig.sh" ; then ++ ac_cv_c_tclconfig="`(cd $i; pwd)`" ++ break ++ fi ++ done ++ fi ++ ++ # check in a few common install locations ++ if test x"${ac_cv_c_tclconfig}" = x ; then ++ for i in `ls -d ${libdir} 2>/dev/null` \ ++ `ls -d ${exec_prefix}/lib 2>/dev/null` \ ++ `ls -d ${prefix}/lib 2>/dev/null` \ ++ `ls -d /usr/local/lib 2>/dev/null` \ ++ `ls -d /usr/contrib/lib 2>/dev/null` \ ++ `ls -d /usr/lib 2>/dev/null` \ ++ `ls -d /usr/lib64 2>/dev/null` \ ++ `ls -d /usr/lib/tcl8.6 2>/dev/null` \ ++ `ls -d /usr/lib/tcl8.5 2>/dev/null` \ ++ ; do ++ if test -f "$i/tclConfig.sh" ; then ++ ac_cv_c_tclconfig="`(cd $i; pwd)`" ++ break ++ fi ++ done ++ fi ++ ++ # check in a few other private locations ++ if test x"${ac_cv_c_tclconfig}" = x ; then ++ for i in \ ++ ${srcdir}/../tcl \ ++ `ls -dr ${srcdir}/../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ ++ `ls -dr ${srcdir}/../tcl[8-9].[0-9] 2>/dev/null` \ ++ `ls -dr ${srcdir}/../tcl[8-9].[0-9]* 2>/dev/null` ; do ++ if test "${TEA_PLATFORM}" = "windows" \ ++ -a -f "$i/win/tclConfig.sh" ; then ++ ac_cv_c_tclconfig="`(cd $i/win; pwd)`" ++ break ++ fi ++ if test -f "$i/unix/tclConfig.sh" ; then ++ ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" ++ break ++ fi ++ done ++ fi ++ ++fi ++ ++ ++ if test x"${ac_cv_c_tclconfig}" = x ; then ++ TCL_BIN_DIR="# no Tcl configs found" ++ as_fn_error $? "Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh" "$LINENO" 5 ++ else ++ no_tcl= ++ TCL_BIN_DIR="${ac_cv_c_tclconfig}" ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: found ${TCL_BIN_DIR}/tclConfig.sh" >&5 ++$as_echo "found ${TCL_BIN_DIR}/tclConfig.sh" >&6; } ++ fi ++ fi ++ ++ac_ext=c ++ac_cpp='$CPP $CPPFLAGS' ++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ++ac_compiler_gnu=$ac_cv_c_compiler_gnu ++if test -n "$ac_tool_prefix"; then ++ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. ++set dummy ${ac_tool_prefix}gcc; ac_word=$2 ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 ++$as_echo_n "checking for $ac_word... " >&6; } ++if ${ac_cv_prog_CC+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if test -n "$CC"; then ++ ac_cv_prog_CC="$CC" # Let the user override the test. ++else ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ++ ac_cv_prog_CC="${ac_tool_prefix}gcc" ++ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++ done ++IFS=$as_save_IFS ++ ++fi ++fi ++CC=$ac_cv_prog_CC ++if test -n "$CC"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 ++$as_echo "$CC" >&6; } ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++fi ++ ++ ++fi ++if test -z "$ac_cv_prog_CC"; then ++ ac_ct_CC=$CC ++ # Extract the first word of "gcc", so it can be a program name with args. ++set dummy gcc; ac_word=$2 ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 ++$as_echo_n "checking for $ac_word... " >&6; } ++if ${ac_cv_prog_ac_ct_CC+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if test -n "$ac_ct_CC"; then ++ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. ++else ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ++ ac_cv_prog_ac_ct_CC="gcc" ++ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++ done ++IFS=$as_save_IFS ++ ++fi ++fi ++ac_ct_CC=$ac_cv_prog_ac_ct_CC ++if test -n "$ac_ct_CC"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 ++$as_echo "$ac_ct_CC" >&6; } ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++fi ++ ++ if test "x$ac_ct_CC" = x; then ++ CC="" ++ else ++ case $cross_compiling:$ac_tool_warned in ++yes:) ++{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 ++$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ++ac_tool_warned=yes ;; ++esac ++ CC=$ac_ct_CC ++ fi ++else ++ CC="$ac_cv_prog_CC" ++fi ++ ++if test -z "$CC"; then ++ if test -n "$ac_tool_prefix"; then ++ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. ++set dummy ${ac_tool_prefix}cc; ac_word=$2 ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 ++$as_echo_n "checking for $ac_word... " >&6; } ++if ${ac_cv_prog_CC+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if test -n "$CC"; then ++ ac_cv_prog_CC="$CC" # Let the user override the test. ++else ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ++ ac_cv_prog_CC="${ac_tool_prefix}cc" ++ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++ done ++IFS=$as_save_IFS ++ ++fi ++fi ++CC=$ac_cv_prog_CC ++if test -n "$CC"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 ++$as_echo "$CC" >&6; } ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++fi ++ ++ ++ fi ++fi ++if test -z "$CC"; then ++ # Extract the first word of "cc", so it can be a program name with args. ++set dummy cc; ac_word=$2 ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 ++$as_echo_n "checking for $ac_word... " >&6; } ++if ${ac_cv_prog_CC+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if test -n "$CC"; then ++ ac_cv_prog_CC="$CC" # Let the user override the test. ++else ++ ac_prog_rejected=no ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ++ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ++ ac_prog_rejected=yes ++ continue ++ fi ++ ac_cv_prog_CC="cc" ++ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++ done ++IFS=$as_save_IFS ++ ++if test $ac_prog_rejected = yes; then ++ # We found a bogon in the path, so make sure we never use it. ++ set dummy $ac_cv_prog_CC ++ shift ++ if test $# != 0; then ++ # We chose a different compiler from the bogus one. ++ # However, it has the same basename, so the bogon will be chosen ++ # first if we set CC to just the basename; use the full file name. ++ shift ++ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" ++ fi ++fi ++fi ++fi ++CC=$ac_cv_prog_CC ++if test -n "$CC"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 ++$as_echo "$CC" >&6; } ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++fi ++ ++ ++fi ++if test -z "$CC"; then ++ if test -n "$ac_tool_prefix"; then ++ for ac_prog in cl.exe ++ do ++ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. ++set dummy $ac_tool_prefix$ac_prog; ac_word=$2 ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 ++$as_echo_n "checking for $ac_word... " >&6; } ++if ${ac_cv_prog_CC+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if test -n "$CC"; then ++ ac_cv_prog_CC="$CC" # Let the user override the test. ++else ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ++ ac_cv_prog_CC="$ac_tool_prefix$ac_prog" ++ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++ done ++IFS=$as_save_IFS ++ ++fi ++fi ++CC=$ac_cv_prog_CC ++if test -n "$CC"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 ++$as_echo "$CC" >&6; } ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++fi ++ ++ ++ test -n "$CC" && break ++ done ++fi ++if test -z "$CC"; then ++ ac_ct_CC=$CC ++ for ac_prog in cl.exe ++do ++ # Extract the first word of "$ac_prog", so it can be a program name with args. ++set dummy $ac_prog; ac_word=$2 ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 ++$as_echo_n "checking for $ac_word... " >&6; } ++if ${ac_cv_prog_ac_ct_CC+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if test -n "$ac_ct_CC"; then ++ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. ++else ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ++ ac_cv_prog_ac_ct_CC="$ac_prog" ++ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++ done ++IFS=$as_save_IFS ++ ++fi ++fi ++ac_ct_CC=$ac_cv_prog_ac_ct_CC ++if test -n "$ac_ct_CC"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 ++$as_echo "$ac_ct_CC" >&6; } ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++fi ++ ++ ++ test -n "$ac_ct_CC" && break ++done ++ ++ if test "x$ac_ct_CC" = x; then ++ CC="" ++ else ++ case $cross_compiling:$ac_tool_warned in ++yes:) ++{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 ++$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ++ac_tool_warned=yes ;; ++esac ++ CC=$ac_ct_CC ++ fi ++fi ++ ++fi ++ ++ ++test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 ++$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} ++as_fn_error $? "no acceptable C compiler found in \$PATH ++See \`config.log' for more details" "$LINENO" 5; } ++ ++# Provide some information about the compiler. ++$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 ++set X $ac_compile ++ac_compiler=$2 ++for ac_option in --version -v -V -qversion; do ++ { { ac_try="$ac_compiler $ac_option >&5" ++case "(($ac_try" in ++ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; ++ *) ac_try_echo=$ac_try;; ++esac ++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" ++$as_echo "$ac_try_echo"; } >&5 ++ (eval "$ac_compiler $ac_option >&5") 2>conftest.err ++ ac_status=$? ++ if test -s conftest.err; then ++ sed '10a\ ++... rest of stderr output deleted ... ++ 10q' conftest.err >conftest.er1 ++ cat conftest.er1 >&5 ++ fi ++ rm -f conftest.er1 conftest.err ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; } ++done ++ ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++int ++main () ++{ ++ ++ ; ++ return 0; ++} ++_ACEOF ++ac_clean_files_save=$ac_clean_files ++ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" ++# Try to create an executable without -o first, disregard a.out. ++# It will help us diagnose broken compilers, and finding out an intuition ++# of exeext. ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 ++$as_echo_n "checking whether the C compiler works... " >&6; } ++ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` ++ ++# The possible output files: ++ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ++ ++ac_rmfiles= ++for ac_file in $ac_files ++do ++ case $ac_file in ++ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; ++ * ) ac_rmfiles="$ac_rmfiles $ac_file";; ++ esac ++done ++rm -f $ac_rmfiles ++ ++if { { ac_try="$ac_link_default" ++case "(($ac_try" in ++ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; ++ *) ac_try_echo=$ac_try;; ++esac ++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" ++$as_echo "$ac_try_echo"; } >&5 ++ (eval "$ac_link_default") 2>&5 ++ ac_status=$? ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; }; then : ++ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. ++# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' ++# in a Makefile. We should not override ac_cv_exeext if it was cached, ++# so that the user can short-circuit this test for compilers unknown to ++# Autoconf. ++for ac_file in $ac_files '' ++do ++ test -f "$ac_file" || continue ++ case $ac_file in ++ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ++ ;; ++ [ab].out ) ++ # We found the default executable, but exeext='' is most ++ # certainly right. ++ break;; ++ *.* ) ++ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; ++ then :; else ++ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` ++ fi ++ # We set ac_cv_exeext here because the later test for it is not ++ # safe: cross compilers may not add the suffix if given an `-o' ++ # argument, so we may need to know it at that point already. ++ # Even if this section looks crufty: it has the advantage of ++ # actually working. ++ break;; ++ * ) ++ break;; ++ esac ++done ++test "$ac_cv_exeext" = no && ac_cv_exeext= ++ ++else ++ ac_file='' ++fi ++if test -z "$ac_file"; then : ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++$as_echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 ++$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} ++as_fn_error 77 "C compiler cannot create executables ++See \`config.log' for more details" "$LINENO" 5; } ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 ++$as_echo "yes" >&6; } ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 ++$as_echo_n "checking for C compiler default output file name... " >&6; } ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 ++$as_echo "$ac_file" >&6; } ++ac_exeext=$ac_cv_exeext ++ ++rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ++ac_clean_files=$ac_clean_files_save ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 ++$as_echo_n "checking for suffix of executables... " >&6; } ++if { { ac_try="$ac_link" ++case "(($ac_try" in ++ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; ++ *) ac_try_echo=$ac_try;; ++esac ++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" ++$as_echo "$ac_try_echo"; } >&5 ++ (eval "$ac_link") 2>&5 ++ ac_status=$? ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; }; then : ++ # If both `conftest.exe' and `conftest' are `present' (well, observable) ++# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will ++# work properly (i.e., refer to `conftest.exe'), while it won't with ++# `rm'. ++for ac_file in conftest.exe conftest conftest.*; do ++ test -f "$ac_file" || continue ++ case $ac_file in ++ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; ++ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` ++ break;; ++ * ) break;; ++ esac ++done ++else ++ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 ++$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} ++as_fn_error $? "cannot compute suffix of executables: cannot compile and link ++See \`config.log' for more details" "$LINENO" 5; } ++fi ++rm -f conftest conftest$ac_cv_exeext ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 ++$as_echo "$ac_cv_exeext" >&6; } ++ ++rm -f conftest.$ac_ext ++EXEEXT=$ac_cv_exeext ++ac_exeext=$EXEEXT ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <stdio.h> ++int ++main () ++{ ++FILE *f = fopen ("conftest.out", "w"); ++ return ferror (f) || fclose (f) != 0; ++ ++ ; ++ return 0; ++} ++_ACEOF ++ac_clean_files="$ac_clean_files conftest.out" ++# Check that the compiler produces executables we can run. If not, either ++# the compiler is broken, or we cross compile. ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 ++$as_echo_n "checking whether we are cross compiling... " >&6; } ++if test "$cross_compiling" != yes; then ++ { { ac_try="$ac_link" ++case "(($ac_try" in ++ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; ++ *) ac_try_echo=$ac_try;; ++esac ++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" ++$as_echo "$ac_try_echo"; } >&5 ++ (eval "$ac_link") 2>&5 ++ ac_status=$? ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; } ++ if { ac_try='./conftest$ac_cv_exeext' ++ { { case "(($ac_try" in ++ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; ++ *) ac_try_echo=$ac_try;; ++esac ++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" ++$as_echo "$ac_try_echo"; } >&5 ++ (eval "$ac_try") 2>&5 ++ ac_status=$? ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; }; }; then ++ cross_compiling=no ++ else ++ if test "$cross_compiling" = maybe; then ++ cross_compiling=yes ++ else ++ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 ++$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} ++as_fn_error $? "cannot run C compiled programs. ++If you meant to cross compile, use \`--host'. ++See \`config.log' for more details" "$LINENO" 5; } ++ fi ++ fi ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 ++$as_echo "$cross_compiling" >&6; } ++ ++rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ++ac_clean_files=$ac_clean_files_save ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 ++$as_echo_n "checking for suffix of object files... " >&6; } ++if ${ac_cv_objext+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++int ++main () ++{ ++ ++ ; ++ return 0; ++} ++_ACEOF ++rm -f conftest.o conftest.obj ++if { { ac_try="$ac_compile" ++case "(($ac_try" in ++ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; ++ *) ac_try_echo=$ac_try;; ++esac ++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" ++$as_echo "$ac_try_echo"; } >&5 ++ (eval "$ac_compile") 2>&5 ++ ac_status=$? ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; }; then : ++ for ac_file in conftest.o conftest.obj conftest.*; do ++ test -f "$ac_file" || continue; ++ case $ac_file in ++ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; ++ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` ++ break;; ++ esac ++done ++else ++ $as_echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 ++$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} ++as_fn_error $? "cannot compute suffix of object files: cannot compile ++See \`config.log' for more details" "$LINENO" 5; } ++fi ++rm -f conftest.$ac_cv_objext conftest.$ac_ext ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 ++$as_echo "$ac_cv_objext" >&6; } ++OBJEXT=$ac_cv_objext ++ac_objext=$OBJEXT ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 ++$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } ++if ${ac_cv_c_compiler_gnu+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++int ++main () ++{ ++#ifndef __GNUC__ ++ choke me ++#endif ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ ac_compiler_gnu=yes ++else ++ ac_compiler_gnu=no ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++ac_cv_c_compiler_gnu=$ac_compiler_gnu ++ ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 ++$as_echo "$ac_cv_c_compiler_gnu" >&6; } ++if test $ac_compiler_gnu = yes; then ++ GCC=yes ++else ++ GCC= ++fi ++ac_test_CFLAGS=${CFLAGS+set} ++ac_save_CFLAGS=$CFLAGS ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 ++$as_echo_n "checking whether $CC accepts -g... " >&6; } ++if ${ac_cv_prog_cc_g+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_save_c_werror_flag=$ac_c_werror_flag ++ ac_c_werror_flag=yes ++ ac_cv_prog_cc_g=no ++ CFLAGS="-g" ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++int ++main () ++{ ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ ac_cv_prog_cc_g=yes ++else ++ CFLAGS="" ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++int ++main () ++{ ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ ++else ++ ac_c_werror_flag=$ac_save_c_werror_flag ++ CFLAGS="-g" ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++int ++main () ++{ ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ ac_cv_prog_cc_g=yes ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++ ac_c_werror_flag=$ac_save_c_werror_flag ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 ++$as_echo "$ac_cv_prog_cc_g" >&6; } ++if test "$ac_test_CFLAGS" = set; then ++ CFLAGS=$ac_save_CFLAGS ++elif test $ac_cv_prog_cc_g = yes; then ++ if test "$GCC" = yes; then ++ CFLAGS="-g -O2" ++ else ++ CFLAGS="-g" ++ fi ++else ++ if test "$GCC" = yes; then ++ CFLAGS="-O2" ++ else ++ CFLAGS= ++ fi ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 ++$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } ++if ${ac_cv_prog_cc_c89+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_cv_prog_cc_c89=no ++ac_save_CC=$CC ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <stdarg.h> ++#include <stdio.h> ++struct stat; ++/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ ++struct buf { int x; }; ++FILE * (*rcsopen) (struct buf *, struct stat *, int); ++static char *e (p, i) ++ char **p; ++ int i; ++{ ++ return p[i]; ++} ++static char *f (char * (*g) (char **, int), char **p, ...) ++{ ++ char *s; ++ va_list v; ++ va_start (v,p); ++ s = g (p, va_arg (v,int)); ++ va_end (v); ++ return s; ++} ++ ++/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has ++ function prototypes and stuff, but not '\xHH' hex character constants. ++ These don't provoke an error unfortunately, instead are silently treated ++ as 'x'. The following induces an error, until -std is added to get ++ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an ++ array size at least. It's necessary to write '\x00'==0 to get something ++ that's true only with -std. */ ++int osf4_cc_array ['\x00' == 0 ? 1 : -1]; ++ ++/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters ++ inside strings and character constants. */ ++#define FOO(x) 'x' ++int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; ++ ++int test (int i, double x); ++struct s1 {int (*f) (int a);}; ++struct s2 {int (*f) (double a);}; ++int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); ++int argc; ++char **argv; ++int ++main () ++{ ++return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ++ ; ++ return 0; ++} ++_ACEOF ++for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ ++ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" ++do ++ CC="$ac_save_CC $ac_arg" ++ if ac_fn_c_try_compile "$LINENO"; then : ++ ac_cv_prog_cc_c89=$ac_arg ++fi ++rm -f core conftest.err conftest.$ac_objext ++ test "x$ac_cv_prog_cc_c89" != "xno" && break ++done ++rm -f conftest.$ac_ext ++CC=$ac_save_CC ++ ++fi ++# AC_CACHE_VAL ++case "x$ac_cv_prog_cc_c89" in ++ x) ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 ++$as_echo "none needed" >&6; } ;; ++ xno) ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 ++$as_echo "unsupported" >&6; } ;; ++ *) ++ CC="$CC $ac_cv_prog_cc_c89" ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 ++$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; ++esac ++if test "x$ac_cv_prog_cc_c89" != xno; then : ++ ++fi ++ ++ac_ext=c ++ac_cpp='$CPP $CPPFLAGS' ++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ++ac_compiler_gnu=$ac_cv_c_compiler_gnu ++ ++ ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for existence of ${TCL_BIN_DIR}/tclConfig.sh" >&5 ++$as_echo_n "checking for existence of ${TCL_BIN_DIR}/tclConfig.sh... " >&6; } ++ ++ if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: loading" >&5 ++$as_echo "loading" >&6; } ++ . "${TCL_BIN_DIR}/tclConfig.sh" ++ else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: could not find ${TCL_BIN_DIR}/tclConfig.sh" >&5 ++$as_echo "could not find ${TCL_BIN_DIR}/tclConfig.sh" >&6; } ++ fi ++ ++ # eval is required to do the TCL_DBGX substitution ++ eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\"" ++ eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\"" ++ ++ # If the TCL_BIN_DIR is the build directory (not the install directory), ++ # then set the common variable name to the value of the build variables. ++ # For example, the variable TCL_LIB_SPEC will be set to the value ++ # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC ++ # instead of TCL_BUILD_LIB_SPEC since it will work with both an ++ # installed and uninstalled version of Tcl. ++ if test -f "${TCL_BIN_DIR}/Makefile" ; then ++ TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}" ++ TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}" ++ TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}" ++ elif test "`uname -s`" = "Darwin"; then ++ # If Tcl was built as a framework, attempt to use the libraries ++ # from the framework at the given location so that linking works ++ # against Tcl.framework installed in an arbitrary location. ++ case ${TCL_DEFS} in ++ *TCL_FRAMEWORK*) ++ if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then ++ for i in "`cd "${TCL_BIN_DIR}"; pwd`" \ ++ "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do ++ if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then ++ TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}" ++ break ++ fi ++ done ++ fi ++ if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then ++ TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}" ++ TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}" ++ fi ++ ;; ++ esac ++ fi ++ ++ # eval is required to do the TCL_DBGX substitution ++ eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\"" ++ eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\"" ++ eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\"" ++ eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\"" ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking platform" >&5 ++$as_echo_n "checking platform... " >&6; } ++ hold_cc=$CC; CC="$TCL_CC" ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++int ++main () ++{ ++ ++ #ifdef _WIN32 ++ #error win32 ++ #endif ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ TEA_PLATFORM="unix" ++else ++ TEA_PLATFORM="windows" ++ ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++ CC=$hold_cc ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TEA_PLATFORM" >&5 ++$as_echo "$TEA_PLATFORM" >&6; } ++ ++ # The BUILD_$pkg is to define the correct extern storage class ++ # handling when making this package ++ ++cat >>confdefs.h <<_ACEOF ++#define BUILD_${PACKAGE_NAME} /**/ ++_ACEOF ++ ++ # Do this here as we have fully defined TEA_PLATFORM now ++ if test "${TEA_PLATFORM}" = "windows" ; then ++ EXEEXT=".exe" ++ CLEANFILES="$CLEANFILES *.lib *.dll *.pdb *.exp" ++ fi ++ ++ # TEA specific: ++ ++ ++ ++ ++ ++ ++ ++ ++#-------------------------------------------------------------------- ++# Load the tkConfig.sh file if necessary (Tk extension) ++#-------------------------------------------------------------------- ++ ++#TEA_PATH_TKCONFIG ++#TEA_LOAD_TKCONFIG ++ ++#----------------------------------------------------------------------- ++# Handle the --prefix=... option by defaulting to what Tcl gave. ++# Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER. ++#----------------------------------------------------------------------- ++ ++ ++ if test "${prefix}" = "NONE"; then ++ prefix_default=yes ++ if test x"${TCL_PREFIX}" != x; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}" >&5 ++$as_echo "$as_me: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}" >&6;} ++ prefix=${TCL_PREFIX} ++ else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: --prefix defaulting to /usr/local" >&5 ++$as_echo "$as_me: --prefix defaulting to /usr/local" >&6;} ++ prefix=/usr/local ++ fi ++ fi ++ if test "${exec_prefix}" = "NONE" -a x"${prefix_default}" = x"yes" \ ++ -o x"${exec_prefix_default}" = x"yes" ; then ++ if test x"${TCL_EXEC_PREFIX}" != x; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}" >&5 ++$as_echo "$as_me: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}" >&6;} ++ exec_prefix=${TCL_EXEC_PREFIX} ++ else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: --exec-prefix defaulting to ${prefix}" >&5 ++$as_echo "$as_me: --exec-prefix defaulting to ${prefix}" >&6;} ++ exec_prefix=$prefix ++ fi ++ fi ++ ++ ++#----------------------------------------------------------------------- ++# Standard compiler checks. ++# This sets up CC by using the CC env var, or looks for gcc otherwise. ++# This also calls AC_PROG_CC, AC_PROG_INSTALL and a few others to create ++# the basic setup necessary to compile executables. ++#----------------------------------------------------------------------- ++ ++ ++ # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE) ++ # in this macro, they need to go into TEA_SETUP_COMPILER instead. ++ ++ ac_ext=c ++ac_cpp='$CPP $CPPFLAGS' ++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ++ac_compiler_gnu=$ac_cv_c_compiler_gnu ++if test -n "$ac_tool_prefix"; then ++ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. ++set dummy ${ac_tool_prefix}gcc; ac_word=$2 ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 ++$as_echo_n "checking for $ac_word... " >&6; } ++if ${ac_cv_prog_CC+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if test -n "$CC"; then ++ ac_cv_prog_CC="$CC" # Let the user override the test. ++else ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ++ ac_cv_prog_CC="${ac_tool_prefix}gcc" ++ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++ done ++IFS=$as_save_IFS ++ ++fi ++fi ++CC=$ac_cv_prog_CC ++if test -n "$CC"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 ++$as_echo "$CC" >&6; } ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++fi ++ ++ ++fi ++if test -z "$ac_cv_prog_CC"; then ++ ac_ct_CC=$CC ++ # Extract the first word of "gcc", so it can be a program name with args. ++set dummy gcc; ac_word=$2 ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 ++$as_echo_n "checking for $ac_word... " >&6; } ++if ${ac_cv_prog_ac_ct_CC+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if test -n "$ac_ct_CC"; then ++ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. ++else ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ++ ac_cv_prog_ac_ct_CC="gcc" ++ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++ done ++IFS=$as_save_IFS ++ ++fi ++fi ++ac_ct_CC=$ac_cv_prog_ac_ct_CC ++if test -n "$ac_ct_CC"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 ++$as_echo "$ac_ct_CC" >&6; } ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++fi ++ ++ if test "x$ac_ct_CC" = x; then ++ CC="" ++ else ++ case $cross_compiling:$ac_tool_warned in ++yes:) ++{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 ++$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ++ac_tool_warned=yes ;; ++esac ++ CC=$ac_ct_CC ++ fi ++else ++ CC="$ac_cv_prog_CC" ++fi ++ ++if test -z "$CC"; then ++ if test -n "$ac_tool_prefix"; then ++ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. ++set dummy ${ac_tool_prefix}cc; ac_word=$2 ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 ++$as_echo_n "checking for $ac_word... " >&6; } ++if ${ac_cv_prog_CC+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if test -n "$CC"; then ++ ac_cv_prog_CC="$CC" # Let the user override the test. ++else ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ++ ac_cv_prog_CC="${ac_tool_prefix}cc" ++ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++ done ++IFS=$as_save_IFS ++ ++fi ++fi ++CC=$ac_cv_prog_CC ++if test -n "$CC"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 ++$as_echo "$CC" >&6; } ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++fi ++ ++ ++ fi ++fi ++if test -z "$CC"; then ++ # Extract the first word of "cc", so it can be a program name with args. ++set dummy cc; ac_word=$2 ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 ++$as_echo_n "checking for $ac_word... " >&6; } ++if ${ac_cv_prog_CC+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if test -n "$CC"; then ++ ac_cv_prog_CC="$CC" # Let the user override the test. ++else ++ ac_prog_rejected=no ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ++ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ++ ac_prog_rejected=yes ++ continue ++ fi ++ ac_cv_prog_CC="cc" ++ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++ done ++IFS=$as_save_IFS ++ ++if test $ac_prog_rejected = yes; then ++ # We found a bogon in the path, so make sure we never use it. ++ set dummy $ac_cv_prog_CC ++ shift ++ if test $# != 0; then ++ # We chose a different compiler from the bogus one. ++ # However, it has the same basename, so the bogon will be chosen ++ # first if we set CC to just the basename; use the full file name. ++ shift ++ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" ++ fi ++fi ++fi ++fi ++CC=$ac_cv_prog_CC ++if test -n "$CC"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 ++$as_echo "$CC" >&6; } ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++fi ++ ++ ++fi ++if test -z "$CC"; then ++ if test -n "$ac_tool_prefix"; then ++ for ac_prog in cl.exe ++ do ++ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. ++set dummy $ac_tool_prefix$ac_prog; ac_word=$2 ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 ++$as_echo_n "checking for $ac_word... " >&6; } ++if ${ac_cv_prog_CC+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if test -n "$CC"; then ++ ac_cv_prog_CC="$CC" # Let the user override the test. ++else ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ++ ac_cv_prog_CC="$ac_tool_prefix$ac_prog" ++ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++ done ++IFS=$as_save_IFS ++ ++fi ++fi ++CC=$ac_cv_prog_CC ++if test -n "$CC"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 ++$as_echo "$CC" >&6; } ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++fi ++ ++ ++ test -n "$CC" && break ++ done ++fi ++if test -z "$CC"; then ++ ac_ct_CC=$CC ++ for ac_prog in cl.exe ++do ++ # Extract the first word of "$ac_prog", so it can be a program name with args. ++set dummy $ac_prog; ac_word=$2 ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 ++$as_echo_n "checking for $ac_word... " >&6; } ++if ${ac_cv_prog_ac_ct_CC+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if test -n "$ac_ct_CC"; then ++ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. ++else ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ++ ac_cv_prog_ac_ct_CC="$ac_prog" ++ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++ done ++IFS=$as_save_IFS ++ ++fi ++fi ++ac_ct_CC=$ac_cv_prog_ac_ct_CC ++if test -n "$ac_ct_CC"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 ++$as_echo "$ac_ct_CC" >&6; } ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++fi ++ ++ ++ test -n "$ac_ct_CC" && break ++done ++ ++ if test "x$ac_ct_CC" = x; then ++ CC="" ++ else ++ case $cross_compiling:$ac_tool_warned in ++yes:) ++{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 ++$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ++ac_tool_warned=yes ;; ++esac ++ CC=$ac_ct_CC ++ fi ++fi ++ ++fi ++ ++ ++test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 ++$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} ++as_fn_error $? "no acceptable C compiler found in \$PATH ++See \`config.log' for more details" "$LINENO" 5; } ++ ++# Provide some information about the compiler. ++$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 ++set X $ac_compile ++ac_compiler=$2 ++for ac_option in --version -v -V -qversion; do ++ { { ac_try="$ac_compiler $ac_option >&5" ++case "(($ac_try" in ++ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; ++ *) ac_try_echo=$ac_try;; ++esac ++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" ++$as_echo "$ac_try_echo"; } >&5 ++ (eval "$ac_compiler $ac_option >&5") 2>conftest.err ++ ac_status=$? ++ if test -s conftest.err; then ++ sed '10a\ ++... rest of stderr output deleted ... ++ 10q' conftest.err >conftest.er1 ++ cat conftest.er1 >&5 ++ fi ++ rm -f conftest.er1 conftest.err ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; } ++done ++ ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 ++$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } ++if ${ac_cv_c_compiler_gnu+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++int ++main () ++{ ++#ifndef __GNUC__ ++ choke me ++#endif ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ ac_compiler_gnu=yes ++else ++ ac_compiler_gnu=no ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++ac_cv_c_compiler_gnu=$ac_compiler_gnu ++ ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 ++$as_echo "$ac_cv_c_compiler_gnu" >&6; } ++if test $ac_compiler_gnu = yes; then ++ GCC=yes ++else ++ GCC= ++fi ++ac_test_CFLAGS=${CFLAGS+set} ++ac_save_CFLAGS=$CFLAGS ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 ++$as_echo_n "checking whether $CC accepts -g... " >&6; } ++if ${ac_cv_prog_cc_g+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_save_c_werror_flag=$ac_c_werror_flag ++ ac_c_werror_flag=yes ++ ac_cv_prog_cc_g=no ++ CFLAGS="-g" ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++int ++main () ++{ ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ ac_cv_prog_cc_g=yes ++else ++ CFLAGS="" ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++int ++main () ++{ ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ ++else ++ ac_c_werror_flag=$ac_save_c_werror_flag ++ CFLAGS="-g" ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++int ++main () ++{ ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ ac_cv_prog_cc_g=yes ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++ ac_c_werror_flag=$ac_save_c_werror_flag ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 ++$as_echo "$ac_cv_prog_cc_g" >&6; } ++if test "$ac_test_CFLAGS" = set; then ++ CFLAGS=$ac_save_CFLAGS ++elif test $ac_cv_prog_cc_g = yes; then ++ if test "$GCC" = yes; then ++ CFLAGS="-g -O2" ++ else ++ CFLAGS="-g" ++ fi ++else ++ if test "$GCC" = yes; then ++ CFLAGS="-O2" ++ else ++ CFLAGS= ++ fi ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 ++$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } ++if ${ac_cv_prog_cc_c89+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_cv_prog_cc_c89=no ++ac_save_CC=$CC ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <stdarg.h> ++#include <stdio.h> ++struct stat; ++/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ ++struct buf { int x; }; ++FILE * (*rcsopen) (struct buf *, struct stat *, int); ++static char *e (p, i) ++ char **p; ++ int i; ++{ ++ return p[i]; ++} ++static char *f (char * (*g) (char **, int), char **p, ...) ++{ ++ char *s; ++ va_list v; ++ va_start (v,p); ++ s = g (p, va_arg (v,int)); ++ va_end (v); ++ return s; ++} ++ ++/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has ++ function prototypes and stuff, but not '\xHH' hex character constants. ++ These don't provoke an error unfortunately, instead are silently treated ++ as 'x'. The following induces an error, until -std is added to get ++ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an ++ array size at least. It's necessary to write '\x00'==0 to get something ++ that's true only with -std. */ ++int osf4_cc_array ['\x00' == 0 ? 1 : -1]; ++ ++/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters ++ inside strings and character constants. */ ++#define FOO(x) 'x' ++int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; ++ ++int test (int i, double x); ++struct s1 {int (*f) (int a);}; ++struct s2 {int (*f) (double a);}; ++int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); ++int argc; ++char **argv; ++int ++main () ++{ ++return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ++ ; ++ return 0; ++} ++_ACEOF ++for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ ++ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" ++do ++ CC="$ac_save_CC $ac_arg" ++ if ac_fn_c_try_compile "$LINENO"; then : ++ ac_cv_prog_cc_c89=$ac_arg ++fi ++rm -f core conftest.err conftest.$ac_objext ++ test "x$ac_cv_prog_cc_c89" != "xno" && break ++done ++rm -f conftest.$ac_ext ++CC=$ac_save_CC ++ ++fi ++# AC_CACHE_VAL ++case "x$ac_cv_prog_cc_c89" in ++ x) ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 ++$as_echo "none needed" >&6; } ;; ++ xno) ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 ++$as_echo "unsupported" >&6; } ;; ++ *) ++ CC="$CC $ac_cv_prog_cc_c89" ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 ++$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; ++esac ++if test "x$ac_cv_prog_cc_c89" != xno; then : ++ ++fi ++ ++ac_ext=c ++ac_cpp='$CPP $CPPFLAGS' ++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ++ac_compiler_gnu=$ac_cv_c_compiler_gnu ++ ++ ac_ext=c ++ac_cpp='$CPP $CPPFLAGS' ++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ++ac_compiler_gnu=$ac_cv_c_compiler_gnu ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 ++$as_echo_n "checking how to run the C preprocessor... " >&6; } ++# On Suns, sometimes $CPP names a directory. ++if test -n "$CPP" && test -d "$CPP"; then ++ CPP= ++fi ++if test -z "$CPP"; then ++ if ${ac_cv_prog_CPP+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ # Double quotes because CPP needs to be expanded ++ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" ++ do ++ ac_preproc_ok=false ++for ac_c_preproc_warn_flag in '' yes ++do ++ # Use a header file that comes with gcc, so configuring glibc ++ # with a fresh cross-compiler works. ++ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since ++ # <limits.h> exists even on freestanding compilers. ++ # On the NeXT, cc -E runs the code through the compiler's parser, ++ # not just through cpp. "Syntax error" is here to catch this case. ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#ifdef __STDC__ ++# include <limits.h> ++#else ++# include <assert.h> ++#endif ++ Syntax error ++_ACEOF ++if ac_fn_c_try_cpp "$LINENO"; then : ++ ++else ++ # Broken: fails on valid input. ++continue ++fi ++rm -f conftest.err conftest.i conftest.$ac_ext ++ ++ # OK, works on sane cases. Now check whether nonexistent headers ++ # can be detected and how. ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <ac_nonexistent.h> ++_ACEOF ++if ac_fn_c_try_cpp "$LINENO"; then : ++ # Broken: success on invalid input. ++continue ++else ++ # Passes both tests. ++ac_preproc_ok=: ++break ++fi ++rm -f conftest.err conftest.i conftest.$ac_ext ++ ++done ++# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. ++rm -f conftest.i conftest.err conftest.$ac_ext ++if $ac_preproc_ok; then : ++ break ++fi ++ ++ done ++ ac_cv_prog_CPP=$CPP ++ ++fi ++ CPP=$ac_cv_prog_CPP ++else ++ ac_cv_prog_CPP=$CPP ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 ++$as_echo "$CPP" >&6; } ++ac_preproc_ok=false ++for ac_c_preproc_warn_flag in '' yes ++do ++ # Use a header file that comes with gcc, so configuring glibc ++ # with a fresh cross-compiler works. ++ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since ++ # <limits.h> exists even on freestanding compilers. ++ # On the NeXT, cc -E runs the code through the compiler's parser, ++ # not just through cpp. "Syntax error" is here to catch this case. ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#ifdef __STDC__ ++# include <limits.h> ++#else ++# include <assert.h> ++#endif ++ Syntax error ++_ACEOF ++if ac_fn_c_try_cpp "$LINENO"; then : ++ ++else ++ # Broken: fails on valid input. ++continue ++fi ++rm -f conftest.err conftest.i conftest.$ac_ext ++ ++ # OK, works on sane cases. Now check whether nonexistent headers ++ # can be detected and how. ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <ac_nonexistent.h> ++_ACEOF ++if ac_fn_c_try_cpp "$LINENO"; then : ++ # Broken: success on invalid input. ++continue ++else ++ # Passes both tests. ++ac_preproc_ok=: ++break ++fi ++rm -f conftest.err conftest.i conftest.$ac_ext ++ ++done ++# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. ++rm -f conftest.i conftest.err conftest.$ac_ext ++if $ac_preproc_ok; then : ++ ++else ++ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 ++$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} ++as_fn_error $? "C preprocessor \"$CPP\" fails sanity check ++See \`config.log' for more details" "$LINENO" 5; } ++fi ++ ++ac_ext=c ++ac_cpp='$CPP $CPPFLAGS' ++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ++ac_compiler_gnu=$ac_cv_c_compiler_gnu ++ ++ ++ INSTALL="\$(SHELL) \$(srcdir)/tclconfig/install-sh -c" ++ ++ INSTALL_DATA="\${INSTALL} -m 644" ++ ++ INSTALL_PROGRAM="\${INSTALL}" ++ ++ INSTALL_SCRIPT="\${INSTALL}" ++ ++ ++ #-------------------------------------------------------------------- ++ # Checks to see if the make program sets the $MAKE variable. ++ #-------------------------------------------------------------------- ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 ++$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } ++set x ${MAKE-make} ++ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` ++if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ cat >conftest.make <<\_ACEOF ++SHELL = /bin/sh ++all: ++ @echo '@@@%%%=$(MAKE)=@@@%%%' ++_ACEOF ++# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. ++case `${MAKE-make} -f conftest.make 2>/dev/null` in ++ *@@@%%%=?*=@@@%%%*) ++ eval ac_cv_prog_make_${ac_make}_set=yes;; ++ *) ++ eval ac_cv_prog_make_${ac_make}_set=no;; ++esac ++rm -f conftest.make ++fi ++if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 ++$as_echo "yes" >&6; } ++ SET_MAKE= ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++ SET_MAKE="MAKE=${MAKE-make}" ++fi ++ ++ ++ #-------------------------------------------------------------------- ++ # Find ranlib ++ #-------------------------------------------------------------------- ++ ++ if test -n "$ac_tool_prefix"; then ++ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. ++set dummy ${ac_tool_prefix}ranlib; ac_word=$2 ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 ++$as_echo_n "checking for $ac_word... " >&6; } ++if ${ac_cv_prog_RANLIB+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if test -n "$RANLIB"; then ++ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. ++else ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ++ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" ++ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++ done ++IFS=$as_save_IFS ++ ++fi ++fi ++RANLIB=$ac_cv_prog_RANLIB ++if test -n "$RANLIB"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 ++$as_echo "$RANLIB" >&6; } ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++fi ++ ++ ++fi ++if test -z "$ac_cv_prog_RANLIB"; then ++ ac_ct_RANLIB=$RANLIB ++ # Extract the first word of "ranlib", so it can be a program name with args. ++set dummy ranlib; ac_word=$2 ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 ++$as_echo_n "checking for $ac_word... " >&6; } ++if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if test -n "$ac_ct_RANLIB"; then ++ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. ++else ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ++ ac_cv_prog_ac_ct_RANLIB="ranlib" ++ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++ done ++IFS=$as_save_IFS ++ ++fi ++fi ++ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB ++if test -n "$ac_ct_RANLIB"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 ++$as_echo "$ac_ct_RANLIB" >&6; } ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++fi ++ ++ if test "x$ac_ct_RANLIB" = x; then ++ RANLIB="" ++ else ++ case $cross_compiling:$ac_tool_warned in ++yes:) ++{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 ++$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ++ac_tool_warned=yes ;; ++esac ++ RANLIB=$ac_ct_RANLIB ++ fi ++else ++ RANLIB="$ac_cv_prog_RANLIB" ++fi ++ ++ ++ #-------------------------------------------------------------------- ++ # Determines the correct binary file extension (.o, .obj, .exe etc.) ++ #-------------------------------------------------------------------- ++ ++ ++ ++ ++ ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 ++$as_echo_n "checking for grep that handles long lines and -e... " >&6; } ++if ${ac_cv_path_GREP+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if test -z "$GREP"; then ++ ac_path_GREP_found=false ++ # Loop through the user's path and test for each of PROGNAME-LIST ++ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_prog in grep ggrep; do ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" ++ as_fn_executable_p "$ac_path_GREP" || continue ++# Check for GNU ac_path_GREP and select it if it is found. ++ # Check for GNU $ac_path_GREP ++case `"$ac_path_GREP" --version 2>&1` in ++*GNU*) ++ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; ++*) ++ ac_count=0 ++ $as_echo_n 0123456789 >"conftest.in" ++ while : ++ do ++ cat "conftest.in" "conftest.in" >"conftest.tmp" ++ mv "conftest.tmp" "conftest.in" ++ cp "conftest.in" "conftest.nl" ++ $as_echo 'GREP' >> "conftest.nl" ++ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break ++ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break ++ as_fn_arith $ac_count + 1 && ac_count=$as_val ++ if test $ac_count -gt ${ac_path_GREP_max-0}; then ++ # Best one so far, save it but keep looking for a better one ++ ac_cv_path_GREP="$ac_path_GREP" ++ ac_path_GREP_max=$ac_count ++ fi ++ # 10*(2^10) chars as input seems more than enough ++ test $ac_count -gt 10 && break ++ done ++ rm -f conftest.in conftest.tmp conftest.nl conftest.out;; ++esac ++ ++ $ac_path_GREP_found && break 3 ++ done ++ done ++ done ++IFS=$as_save_IFS ++ if test -z "$ac_cv_path_GREP"; then ++ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 ++ fi ++else ++ ac_cv_path_GREP=$GREP ++fi ++ ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 ++$as_echo "$ac_cv_path_GREP" >&6; } ++ GREP="$ac_cv_path_GREP" ++ ++ ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 ++$as_echo_n "checking for egrep... " >&6; } ++if ${ac_cv_path_EGREP+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 ++ then ac_cv_path_EGREP="$GREP -E" ++ else ++ if test -z "$EGREP"; then ++ ac_path_EGREP_found=false ++ # Loop through the user's path and test for each of PROGNAME-LIST ++ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_prog in egrep; do ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" ++ as_fn_executable_p "$ac_path_EGREP" || continue ++# Check for GNU ac_path_EGREP and select it if it is found. ++ # Check for GNU $ac_path_EGREP ++case `"$ac_path_EGREP" --version 2>&1` in ++*GNU*) ++ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; ++*) ++ ac_count=0 ++ $as_echo_n 0123456789 >"conftest.in" ++ while : ++ do ++ cat "conftest.in" "conftest.in" >"conftest.tmp" ++ mv "conftest.tmp" "conftest.in" ++ cp "conftest.in" "conftest.nl" ++ $as_echo 'EGREP' >> "conftest.nl" ++ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break ++ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break ++ as_fn_arith $ac_count + 1 && ac_count=$as_val ++ if test $ac_count -gt ${ac_path_EGREP_max-0}; then ++ # Best one so far, save it but keep looking for a better one ++ ac_cv_path_EGREP="$ac_path_EGREP" ++ ac_path_EGREP_max=$ac_count ++ fi ++ # 10*(2^10) chars as input seems more than enough ++ test $ac_count -gt 10 && break ++ done ++ rm -f conftest.in conftest.tmp conftest.nl conftest.out;; ++esac ++ ++ $ac_path_EGREP_found && break 3 ++ done ++ done ++ done ++IFS=$as_save_IFS ++ if test -z "$ac_cv_path_EGREP"; then ++ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 ++ fi ++else ++ ac_cv_path_EGREP=$EGREP ++fi ++ ++ fi ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 ++$as_echo "$ac_cv_path_EGREP" >&6; } ++ EGREP="$ac_cv_path_EGREP" ++ ++ ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 ++$as_echo_n "checking for ANSI C header files... " >&6; } ++if ${ac_cv_header_stdc+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <stdlib.h> ++#include <stdarg.h> ++#include <string.h> ++#include <float.h> ++ ++int ++main () ++{ ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ ac_cv_header_stdc=yes ++else ++ ac_cv_header_stdc=no ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++ ++if test $ac_cv_header_stdc = yes; then ++ # SunOS 4.x string.h does not declare mem*, contrary to ANSI. ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <string.h> ++ ++_ACEOF ++if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | ++ $EGREP "memchr" >/dev/null 2>&1; then : ++ ++else ++ ac_cv_header_stdc=no ++fi ++rm -f conftest* ++ ++fi ++ ++if test $ac_cv_header_stdc = yes; then ++ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <stdlib.h> ++ ++_ACEOF ++if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | ++ $EGREP "free" >/dev/null 2>&1; then : ++ ++else ++ ac_cv_header_stdc=no ++fi ++rm -f conftest* ++ ++fi ++ ++if test $ac_cv_header_stdc = yes; then ++ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. ++ if test "$cross_compiling" = yes; then : ++ : ++else ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <ctype.h> ++#include <stdlib.h> ++#if ((' ' & 0x0FF) == 0x020) ++# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') ++# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) ++#else ++# define ISLOWER(c) \ ++ (('a' <= (c) && (c) <= 'i') \ ++ || ('j' <= (c) && (c) <= 'r') \ ++ || ('s' <= (c) && (c) <= 'z')) ++# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) ++#endif ++ ++#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) ++int ++main () ++{ ++ int i; ++ for (i = 0; i < 256; i++) ++ if (XOR (islower (i), ISLOWER (i)) ++ || toupper (i) != TOUPPER (i)) ++ return 2; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_run "$LINENO"; then : ++ ++else ++ ac_cv_header_stdc=no ++fi ++rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ ++ conftest.$ac_objext conftest.beam conftest.$ac_ext ++fi ++ ++fi ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 ++$as_echo "$ac_cv_header_stdc" >&6; } ++if test $ac_cv_header_stdc = yes; then ++ ++$as_echo "#define STDC_HEADERS 1" >>confdefs.h ++ ++fi ++ ++# On IRIX 5.3, sys/types and inttypes.h are conflicting. ++for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ ++ inttypes.h stdint.h unistd.h ++do : ++ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ++ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default ++" ++if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : ++ cat >>confdefs.h <<_ACEOF ++#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 ++_ACEOF ++ ++fi ++ ++done ++ ++ ++ ++ # Any macros that use the compiler (e.g. AC_TRY_COMPILE) have to go here. ++ ++ ++ #------------------------------------------------------------------------ ++ # If we're using GCC, see if the compiler understands -pipe. If so, use it. ++ # It makes compiling go faster. (This is only a performance feature.) ++ #------------------------------------------------------------------------ ++ ++ if test -z "$no_pipe" -a -n "$GCC"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the compiler understands -pipe" >&5 ++$as_echo_n "checking if the compiler understands -pipe... " >&6; } ++if ${tcl_cv_cc_pipe+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ++ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe" ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++int ++main () ++{ ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ tcl_cv_cc_pipe=yes ++else ++ tcl_cv_cc_pipe=no ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++ CFLAGS=$hold_cflags ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_pipe" >&5 ++$as_echo "$tcl_cv_cc_pipe" >&6; } ++ if test $tcl_cv_cc_pipe = yes; then ++ CFLAGS="$CFLAGS -pipe" ++ fi ++ fi ++ ++ #-------------------------------------------------------------------- ++ # Common compiler flag setup ++ #-------------------------------------------------------------------- ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 ++$as_echo_n "checking whether byte ordering is bigendian... " >&6; } ++if ${ac_cv_c_bigendian+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_cv_c_bigendian=unknown ++ # See if we're dealing with a universal compiler. ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#ifndef __APPLE_CC__ ++ not a universal capable compiler ++ #endif ++ typedef int dummy; ++ ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ ++ # Check for potential -arch flags. It is not universal unless ++ # there are at least two -arch flags with different values. ++ ac_arch= ++ ac_prev= ++ for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do ++ if test -n "$ac_prev"; then ++ case $ac_word in ++ i?86 | x86_64 | ppc | ppc64) ++ if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then ++ ac_arch=$ac_word ++ else ++ ac_cv_c_bigendian=universal ++ break ++ fi ++ ;; ++ esac ++ ac_prev= ++ elif test "x$ac_word" = "x-arch"; then ++ ac_prev=arch ++ fi ++ done ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++ if test $ac_cv_c_bigendian = unknown; then ++ # See if sys/param.h defines the BYTE_ORDER macro. ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <sys/types.h> ++ #include <sys/param.h> ++ ++int ++main () ++{ ++#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ ++ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ ++ && LITTLE_ENDIAN) ++ bogus endian macros ++ #endif ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ # It does; now see whether it defined to BIG_ENDIAN or not. ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <sys/types.h> ++ #include <sys/param.h> ++ ++int ++main () ++{ ++#if BYTE_ORDER != BIG_ENDIAN ++ not big endian ++ #endif ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ ac_cv_c_bigendian=yes ++else ++ ac_cv_c_bigendian=no ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++ fi ++ if test $ac_cv_c_bigendian = unknown; then ++ # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <limits.h> ++ ++int ++main () ++{ ++#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) ++ bogus endian macros ++ #endif ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ # It does; now see whether it defined to _BIG_ENDIAN or not. ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <limits.h> ++ ++int ++main () ++{ ++#ifndef _BIG_ENDIAN ++ not big endian ++ #endif ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ ac_cv_c_bigendian=yes ++else ++ ac_cv_c_bigendian=no ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++ fi ++ if test $ac_cv_c_bigendian = unknown; then ++ # Compile a test program. ++ if test "$cross_compiling" = yes; then : ++ # Try to guess by grepping values from an object file. ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++short int ascii_mm[] = ++ { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; ++ short int ascii_ii[] = ++ { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; ++ int use_ascii (int i) { ++ return ascii_mm[i] + ascii_ii[i]; ++ } ++ short int ebcdic_ii[] = ++ { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; ++ short int ebcdic_mm[] = ++ { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; ++ int use_ebcdic (int i) { ++ return ebcdic_mm[i] + ebcdic_ii[i]; ++ } ++ extern int foo; ++ ++int ++main () ++{ ++return use_ascii (foo) == use_ebcdic (foo); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then ++ ac_cv_c_bigendian=yes ++ fi ++ if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then ++ if test "$ac_cv_c_bigendian" = unknown; then ++ ac_cv_c_bigendian=no ++ else ++ # finding both strings is unlikely to happen, but who knows? ++ ac_cv_c_bigendian=unknown ++ fi ++ fi ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++else ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++$ac_includes_default ++int ++main () ++{ ++ ++ /* Are we little or big endian? From Harbison&Steele. */ ++ union ++ { ++ long int l; ++ char c[sizeof (long int)]; ++ } u; ++ u.l = 1; ++ return u.c[sizeof (long int) - 1] == 1; ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_run "$LINENO"; then : ++ ac_cv_c_bigendian=no ++else ++ ac_cv_c_bigendian=yes ++fi ++rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ ++ conftest.$ac_objext conftest.beam conftest.$ac_ext ++fi ++ ++ fi ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 ++$as_echo "$ac_cv_c_bigendian" >&6; } ++ case $ac_cv_c_bigendian in #( ++ yes) ++ $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h ++;; #( ++ no) ++ ;; #( ++ universal) ++ ++$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h ++ ++ ;; #( ++ *) ++ as_fn_error $? "unknown endianness ++ presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; ++ esac ++ ++ if test "${TEA_PLATFORM}" = "unix" ; then ++ ++ #-------------------------------------------------------------------- ++ # On a few very rare systems, all of the libm.a stuff is ++ # already in libc.a. Set compiler flags accordingly. ++ # Also, Linux requires the "ieee" library for math to work ++ # right (and it must appear before "-lm"). ++ #-------------------------------------------------------------------- ++ ++ ac_fn_c_check_func "$LINENO" "sin" "ac_cv_func_sin" ++if test "x$ac_cv_func_sin" = xyes; then : ++ MATH_LIBS="" ++else ++ MATH_LIBS="-lm" ++fi ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lieee" >&5 ++$as_echo_n "checking for main in -lieee... " >&6; } ++if ${ac_cv_lib_ieee_main+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_check_lib_save_LIBS=$LIBS ++LIBS="-lieee $LIBS" ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++ ++int ++main () ++{ ++return main (); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ ac_cv_lib_ieee_main=yes ++else ++ ac_cv_lib_ieee_main=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++LIBS=$ac_check_lib_save_LIBS ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ieee_main" >&5 ++$as_echo "$ac_cv_lib_ieee_main" >&6; } ++if test "x$ac_cv_lib_ieee_main" = xyes; then : ++ MATH_LIBS="-lieee $MATH_LIBS" ++fi ++ ++ ++ #-------------------------------------------------------------------- ++ # Interactive UNIX requires -linet instead of -lsocket, plus it ++ # needs net/errno.h to define the socket-related error codes. ++ #-------------------------------------------------------------------- ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -linet" >&5 ++$as_echo_n "checking for main in -linet... " >&6; } ++if ${ac_cv_lib_inet_main+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_check_lib_save_LIBS=$LIBS ++LIBS="-linet $LIBS" ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++ ++int ++main () ++{ ++return main (); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ ac_cv_lib_inet_main=yes ++else ++ ac_cv_lib_inet_main=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++LIBS=$ac_check_lib_save_LIBS ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_inet_main" >&5 ++$as_echo "$ac_cv_lib_inet_main" >&6; } ++if test "x$ac_cv_lib_inet_main" = xyes; then : ++ LIBS="$LIBS -linet" ++fi ++ ++ ac_fn_c_check_header_mongrel "$LINENO" "net/errno.h" "ac_cv_header_net_errno_h" "$ac_includes_default" ++if test "x$ac_cv_header_net_errno_h" = xyes; then : ++ ++ ++$as_echo "#define HAVE_NET_ERRNO_H 1" >>confdefs.h ++ ++fi ++ ++ ++ ++ #-------------------------------------------------------------------- ++ # Check for the existence of the -lsocket and -lnsl libraries. ++ # The order here is important, so that they end up in the right ++ # order in the command line generated by make. Here are some ++ # special considerations: ++ # 1. Use "connect" and "accept" to check for -lsocket, and ++ # "gethostbyname" to check for -lnsl. ++ # 2. Use each function name only once: can't redo a check because ++ # autoconf caches the results of the last check and won't redo it. ++ # 3. Use -lnsl and -lsocket only if they supply procedures that ++ # aren't already present in the normal libraries. This is because ++ # IRIX 5.2 has libraries, but they aren't needed and they're ++ # bogus: they goof up name resolution if used. ++ # 4. On some SVR4 systems, can't use -lsocket without -lnsl too. ++ # To get around this problem, check for both libraries together ++ # if -lsocket doesn't work by itself. ++ #-------------------------------------------------------------------- ++ ++ tcl_checkBoth=0 ++ ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect" ++if test "x$ac_cv_func_connect" = xyes; then : ++ tcl_checkSocket=0 ++else ++ tcl_checkSocket=1 ++fi ++ ++ if test "$tcl_checkSocket" = 1; then ++ ac_fn_c_check_func "$LINENO" "setsockopt" "ac_cv_func_setsockopt" ++if test "x$ac_cv_func_setsockopt" = xyes; then : ++ ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for setsockopt in -lsocket" >&5 ++$as_echo_n "checking for setsockopt in -lsocket... " >&6; } ++if ${ac_cv_lib_socket_setsockopt+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_check_lib_save_LIBS=$LIBS ++LIBS="-lsocket $LIBS" ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++/* Override any GCC internal prototype to avoid an error. ++ Use char because int might match the return type of a GCC ++ builtin and then its argument prototype would still apply. */ ++#ifdef __cplusplus ++extern "C" ++#endif ++char setsockopt (); ++int ++main () ++{ ++return setsockopt (); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ ac_cv_lib_socket_setsockopt=yes ++else ++ ac_cv_lib_socket_setsockopt=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++LIBS=$ac_check_lib_save_LIBS ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_setsockopt" >&5 ++$as_echo "$ac_cv_lib_socket_setsockopt" >&6; } ++if test "x$ac_cv_lib_socket_setsockopt" = xyes; then : ++ LIBS="$LIBS -lsocket" ++else ++ tcl_checkBoth=1 ++fi ++ ++fi ++ ++ fi ++ if test "$tcl_checkBoth" = 1; then ++ tk_oldLibs=$LIBS ++ LIBS="$LIBS -lsocket -lnsl" ++ ac_fn_c_check_func "$LINENO" "accept" "ac_cv_func_accept" ++if test "x$ac_cv_func_accept" = xyes; then : ++ tcl_checkNsl=0 ++else ++ LIBS=$tk_oldLibs ++fi ++ ++ fi ++ ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname" ++if test "x$ac_cv_func_gethostbyname" = xyes; then : ++ ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5 ++$as_echo_n "checking for gethostbyname in -lnsl... " >&6; } ++if ${ac_cv_lib_nsl_gethostbyname+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_check_lib_save_LIBS=$LIBS ++LIBS="-lnsl $LIBS" ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++/* Override any GCC internal prototype to avoid an error. ++ Use char because int might match the return type of a GCC ++ builtin and then its argument prototype would still apply. */ ++#ifdef __cplusplus ++extern "C" ++#endif ++char gethostbyname (); ++int ++main () ++{ ++return gethostbyname (); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ ac_cv_lib_nsl_gethostbyname=yes ++else ++ ac_cv_lib_nsl_gethostbyname=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++LIBS=$ac_check_lib_save_LIBS ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5 ++$as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; } ++if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then : ++ LIBS="$LIBS -lnsl" ++fi ++ ++fi ++ ++ ++ # TEA specific: Don't perform the eval of the libraries here because ++ # DL_LIBS won't be set until we call TEA_CONFIG_CFLAGS ++ ++ TCL_LIBS='${DL_LIBS} ${LIBS} ${MATH_LIBS}' ++ ++ ++ ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking dirent.h" >&5 ++$as_echo_n "checking dirent.h... " >&6; } ++if ${tcl_cv_dirent_h+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <sys/types.h> ++#include <dirent.h> ++int ++main () ++{ ++ ++#ifndef _POSIX_SOURCE ++# ifdef __Lynx__ ++ /* ++ * Generate compilation error to make the test fail: Lynx headers ++ * are only valid if really in the POSIX environment. ++ */ ++ ++ missing_procedure(); ++# endif ++#endif ++DIR *d; ++struct dirent *entryPtr; ++char *p; ++d = opendir("foobar"); ++entryPtr = readdir(d); ++p = entryPtr->d_name; ++closedir(d); ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ tcl_cv_dirent_h=yes ++else ++ tcl_cv_dirent_h=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_dirent_h" >&5 ++$as_echo "$tcl_cv_dirent_h" >&6; } ++ ++ if test $tcl_cv_dirent_h = no; then ++ ++$as_echo "#define NO_DIRENT_H 1" >>confdefs.h ++ ++ fi ++ ++ # TEA specific: ++ ac_fn_c_check_header_mongrel "$LINENO" "errno.h" "ac_cv_header_errno_h" "$ac_includes_default" ++if test "x$ac_cv_header_errno_h" = xyes; then : ++ ++else ++ ++$as_echo "#define NO_ERRNO_H 1" >>confdefs.h ++ ++fi ++ ++ ++ ac_fn_c_check_header_mongrel "$LINENO" "float.h" "ac_cv_header_float_h" "$ac_includes_default" ++if test "x$ac_cv_header_float_h" = xyes; then : ++ ++else ++ ++$as_echo "#define NO_FLOAT_H 1" >>confdefs.h ++ ++fi ++ ++ ++ ac_fn_c_check_header_mongrel "$LINENO" "values.h" "ac_cv_header_values_h" "$ac_includes_default" ++if test "x$ac_cv_header_values_h" = xyes; then : ++ ++else ++ ++$as_echo "#define NO_VALUES_H 1" >>confdefs.h ++ ++fi ++ ++ ++ ac_fn_c_check_header_mongrel "$LINENO" "limits.h" "ac_cv_header_limits_h" "$ac_includes_default" ++if test "x$ac_cv_header_limits_h" = xyes; then : ++ ++$as_echo "#define HAVE_LIMITS_H 1" >>confdefs.h ++ ++else ++ ++$as_echo "#define NO_LIMITS_H 1" >>confdefs.h ++ ++fi ++ ++ ++ ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" ++if test "x$ac_cv_header_stdlib_h" = xyes; then : ++ tcl_ok=1 ++else ++ tcl_ok=0 ++fi ++ ++ ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <stdlib.h> ++ ++_ACEOF ++if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | ++ $EGREP "strtol" >/dev/null 2>&1; then : ++ ++else ++ tcl_ok=0 ++fi ++rm -f conftest* ++ ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <stdlib.h> ++ ++_ACEOF ++if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | ++ $EGREP "strtoul" >/dev/null 2>&1; then : ++ ++else ++ tcl_ok=0 ++fi ++rm -f conftest* ++ ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <stdlib.h> ++ ++_ACEOF ++if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | ++ $EGREP "strtod" >/dev/null 2>&1; then : ++ ++else ++ tcl_ok=0 ++fi ++rm -f conftest* ++ ++ if test $tcl_ok = 0; then ++ ++$as_echo "#define NO_STDLIB_H 1" >>confdefs.h ++ ++ fi ++ ac_fn_c_check_header_mongrel "$LINENO" "string.h" "ac_cv_header_string_h" "$ac_includes_default" ++if test "x$ac_cv_header_string_h" = xyes; then : ++ tcl_ok=1 ++else ++ tcl_ok=0 ++fi ++ ++ ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <string.h> ++ ++_ACEOF ++if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | ++ $EGREP "strstr" >/dev/null 2>&1; then : ++ ++else ++ tcl_ok=0 ++fi ++rm -f conftest* ++ ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <string.h> ++ ++_ACEOF ++if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | ++ $EGREP "strerror" >/dev/null 2>&1; then : ++ ++else ++ tcl_ok=0 ++fi ++rm -f conftest* ++ ++ ++ # See also memmove check below for a place where NO_STRING_H can be ++ # set and why. ++ ++ if test $tcl_ok = 0; then ++ ++$as_echo "#define NO_STRING_H 1" >>confdefs.h ++ ++ fi ++ ++ ac_fn_c_check_header_mongrel "$LINENO" "sys/wait.h" "ac_cv_header_sys_wait_h" "$ac_includes_default" ++if test "x$ac_cv_header_sys_wait_h" = xyes; then : ++ ++else ++ ++$as_echo "#define NO_SYS_WAIT_H 1" >>confdefs.h ++ ++fi ++ ++ ++ ac_fn_c_check_header_mongrel "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default" ++if test "x$ac_cv_header_dlfcn_h" = xyes; then : ++ ++else ++ ++$as_echo "#define NO_DLFCN_H 1" >>confdefs.h ++ ++fi ++ ++ ++ ++ # OS/390 lacks sys/param.h (and doesn't need it, by chance). ++ for ac_header in sys/param.h ++do : ++ ac_fn_c_check_header_mongrel "$LINENO" "sys/param.h" "ac_cv_header_sys_param_h" "$ac_includes_default" ++if test "x$ac_cv_header_sys_param_h" = xyes; then : ++ cat >>confdefs.h <<_ACEOF ++#define HAVE_SYS_PARAM_H 1 ++_ACEOF ++ ++fi ++ ++done ++ ++ ++ # Let the user call this, because if it triggers, they will ++ # need a compat/strtod.c that is correct. Users can also ++ # use Tcl_GetDouble(FromObj) instead. ++ #TEA_BUGGY_STRTOD ++ fi ++ ++ ++#----------------------------------------------------------------------- ++# __CHANGE__ ++# Specify the C source files to compile in TEA_ADD_SOURCES, ++# public headers that need to be installed in TEA_ADD_HEADERS, ++# stub library C source files to compile in TEA_ADD_STUB_SOURCES, ++# and runtime Tcl library files in TEA_ADD_TCL_SOURCES. ++# This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS ++# and PKG_TCL_SOURCES. ++#----------------------------------------------------------------------- ++ ++ ++ vars="tclsqlite3.c" ++ for i in $vars; do ++ case $i in ++ \$*) ++ # allow $-var names ++ PKG_SOURCES="$PKG_SOURCES $i" ++ PKG_OBJECTS="$PKG_OBJECTS $i" ++ ;; ++ *) ++ # check for existence - allows for generic/win/unix VPATH ++ # To add more dirs here (like 'src'), you have to update VPATH ++ # in Makefile.in as well ++ if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ ++ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ ++ -a ! -f "${srcdir}/macosx/$i" \ ++ ; then ++ as_fn_error $? "could not find source file '$i'" "$LINENO" 5 ++ fi ++ PKG_SOURCES="$PKG_SOURCES $i" ++ # this assumes it is in a VPATH dir ++ i=`basename $i` ++ # handle user calling this before or after TEA_SETUP_COMPILER ++ if test x"${OBJEXT}" != x ; then ++ j="`echo $i | sed -e 's/\.[^.]*$//'`.${OBJEXT}" ++ else ++ j="`echo $i | sed -e 's/\.[^.]*$//'`.\${OBJEXT}" ++ fi ++ PKG_OBJECTS="$PKG_OBJECTS $j" ++ ;; ++ esac ++ done ++ ++ ++ ++ ++ vars="" ++ for i in $vars; do ++ # check for existence, be strict because it is installed ++ if test ! -f "${srcdir}/$i" ; then ++ as_fn_error $? "could not find header file '${srcdir}/$i'" "$LINENO" 5 ++ fi ++ PKG_HEADERS="$PKG_HEADERS $i" ++ done ++ ++ ++ ++ vars="-I\"`\${CYGPATH} \${srcdir}/generic`\"" ++ for i in $vars; do ++ PKG_INCLUDES="$PKG_INCLUDES $i" ++ done ++ ++ ++ ++ vars="" ++ for i in $vars; do ++ if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then ++ # Convert foo.lib to -lfoo for GCC. No-op if not *.lib ++ i=`echo "$i" | sed -e 's/^\([^-].*\)\.lib$/-l\1/i'` ++ fi ++ PKG_LIBS="$PKG_LIBS $i" ++ done ++ ++ ++ ++ PKG_CFLAGS="$PKG_CFLAGS -DSQLITE_ENABLE_FTS3=1" ++ ++ ++ ++ PKG_CFLAGS="$PKG_CFLAGS -DSQLITE_3_SUFFIX_ONLY=1" ++ ++ ++ ++ PKG_CFLAGS="$PKG_CFLAGS -DSQLITE_ENABLE_RTREE=1" ++ ++ ++ ++ vars="" ++ for i in $vars; do ++ # check for existence - allows for generic/win/unix VPATH ++ if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ ++ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ ++ -a ! -f "${srcdir}/macosx/$i" \ ++ ; then ++ as_fn_error $? "could not find stub source file '$i'" "$LINENO" 5 ++ fi ++ PKG_STUB_SOURCES="$PKG_STUB_SOURCES $i" ++ # this assumes it is in a VPATH dir ++ i=`basename $i` ++ # handle user calling this before or after TEA_SETUP_COMPILER ++ if test x"${OBJEXT}" != x ; then ++ j="`echo $i | sed -e 's/\.[^.]*$//'`.${OBJEXT}" ++ else ++ j="`echo $i | sed -e 's/\.[^.]*$//'`.\${OBJEXT}" ++ fi ++ PKG_STUB_OBJECTS="$PKG_STUB_OBJECTS $j" ++ done ++ ++ ++ ++ ++ vars="" ++ for i in $vars; do ++ # check for existence, be strict because it is installed ++ if test ! -f "${srcdir}/$i" ; then ++ as_fn_error $? "could not find tcl source file '${srcdir}/$i'" "$LINENO" 5 ++ fi ++ PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i" ++ done ++ ++ ++ ++#-------------------------------------------------------------------- ++# The --with-system-sqlite causes the TCL bindings to SQLite to use ++# the system shared library for SQLite rather than statically linking ++# against its own private copy. This is dangerous and leads to ++# undersirable dependences and is not recommended. ++# Patchs from rmax. ++#-------------------------------------------------------------------- ++ ++# Check whether --with-system-sqlite was given. ++if test "${with_system_sqlite+set}" = set; then : ++ withval=$with_system_sqlite; ++else ++ with_system_sqlite=no ++fi ++ ++if test x$with_system_sqlite != xno; then ++ ac_fn_c_check_header_mongrel "$LINENO" "sqlite3.h" "ac_cv_header_sqlite3_h" "$ac_includes_default" ++if test "x$ac_cv_header_sqlite3_h" = xyes; then : ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sqlite3_initialize in -lsqlite3" >&5 ++$as_echo_n "checking for sqlite3_initialize in -lsqlite3... " >&6; } ++if ${ac_cv_lib_sqlite3_sqlite3_initialize+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_check_lib_save_LIBS=$LIBS ++LIBS="-lsqlite3 $LIBS" ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++/* Override any GCC internal prototype to avoid an error. ++ Use char because int might match the return type of a GCC ++ builtin and then its argument prototype would still apply. */ ++#ifdef __cplusplus ++extern "C" ++#endif ++char sqlite3_initialize (); ++int ++main () ++{ ++return sqlite3_initialize (); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ ac_cv_lib_sqlite3_sqlite3_initialize=yes ++else ++ ac_cv_lib_sqlite3_sqlite3_initialize=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++LIBS=$ac_check_lib_save_LIBS ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sqlite3_sqlite3_initialize" >&5 ++$as_echo "$ac_cv_lib_sqlite3_sqlite3_initialize" >&6; } ++if test "x$ac_cv_lib_sqlite3_sqlite3_initialize" = xyes; then : ++ $as_echo "#define USE_SYSTEM_SQLITE 1" >>confdefs.h ++ ++ LIBS="$LIBS -lsqlite3" ++fi ++ ++fi ++ ++ ++fi ++ ++#-------------------------------------------------------------------- ++# __CHANGE__ ++# Choose which headers you need. Extension authors should try very ++# hard to only rely on the Tcl public header files. Internal headers ++# contain private data structures and are subject to change without ++# notice. ++# This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG ++#-------------------------------------------------------------------- ++ ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tcl public headers" >&5 ++$as_echo_n "checking for Tcl public headers... " >&6; } ++ ++ ++# Check whether --with-tclinclude was given. ++if test "${with_tclinclude+set}" = set; then : ++ withval=$with_tclinclude; with_tclinclude=${withval} ++fi ++ ++ ++ if ${ac_cv_c_tclh+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ++ # Use the value from --with-tclinclude, if it was given ++ ++ if test x"${with_tclinclude}" != x ; then ++ if test -f "${with_tclinclude}/tcl.h" ; then ++ ac_cv_c_tclh=${with_tclinclude} ++ else ++ as_fn_error $? "${with_tclinclude} directory does not contain tcl.h" "$LINENO" 5 ++ fi ++ else ++ list="" ++ if test "`uname -s`" = "Darwin"; then ++ # If Tcl was built as a framework, attempt to use ++ # the framework's Headers directory ++ case ${TCL_DEFS} in ++ *TCL_FRAMEWORK*) ++ list="`ls -d ${TCL_BIN_DIR}/Headers 2>/dev/null`" ++ ;; ++ esac ++ fi ++ ++ # Look in the source dir only if Tcl is not installed, ++ # and in that situation, look there before installed locations. ++ if test -f "${TCL_BIN_DIR}/Makefile" ; then ++ list="$list `ls -d ${TCL_SRC_DIR}/generic 2>/dev/null`" ++ fi ++ ++ # Check order: pkg --prefix location, Tcl's --prefix location, ++ # relative to directory of tclConfig.sh. ++ ++ eval "temp_includedir=${includedir}" ++ list="$list \ ++ `ls -d ${temp_includedir} 2>/dev/null` \ ++ `ls -d ${TCL_PREFIX}/include 2>/dev/null` \ ++ `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`" ++ if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then ++ list="$list /usr/local/include /usr/include" ++ if test x"${TCL_INCLUDE_SPEC}" != x ; then ++ d=`echo "${TCL_INCLUDE_SPEC}" | sed -e 's/^-I//'` ++ list="$list `ls -d ${d} 2>/dev/null`" ++ fi ++ fi ++ for i in $list ; do ++ if test -f "$i/tcl.h" ; then ++ ac_cv_c_tclh=$i ++ break ++ fi ++ done ++ fi ++ ++fi ++ ++ ++ # Print a message based on how we determined the include path ++ ++ if test x"${ac_cv_c_tclh}" = x ; then ++ as_fn_error $? "tcl.h not found. Please specify its location with --with-tclinclude" "$LINENO" 5 ++ else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ac_cv_c_tclh}" >&5 ++$as_echo "${ac_cv_c_tclh}" >&6; } ++ fi ++ ++ # Convert to a native path and substitute into the output files. ++ ++ INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclh}` ++ ++ TCL_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" ++ ++ ++ ++#TEA_PRIVATE_TCL_HEADERS ++ ++#TEA_PUBLIC_TK_HEADERS ++#TEA_PRIVATE_TK_HEADERS ++#TEA_PATH_X ++ ++#-------------------------------------------------------------------- ++# Check whether --enable-threads or --disable-threads was given. ++# This auto-enables if Tcl was compiled threaded. ++#-------------------------------------------------------------------- ++ ++ ++ # Check whether --enable-threads was given. ++if test "${enable_threads+set}" = set; then : ++ enableval=$enable_threads; tcl_ok=$enableval ++else ++ tcl_ok=yes ++fi ++ ++ ++ if test "${enable_threads+set}" = set; then ++ enableval="$enable_threads" ++ tcl_ok=$enableval ++ else ++ tcl_ok=yes ++ fi ++ ++ if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then ++ TCL_THREADS=1 ++ ++ if test "${TEA_PLATFORM}" != "windows" ; then ++ # We are always OK on Windows, so check what this platform wants: ++ ++ # USE_THREAD_ALLOC tells us to try the special thread-based ++ # allocator that significantly reduces lock contention ++ ++$as_echo "#define USE_THREAD_ALLOC 1" >>confdefs.h ++ ++ ++$as_echo "#define _REENTRANT 1" >>confdefs.h ++ ++ if test "`uname -s`" = "SunOS" ; then ++ ++$as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h ++ ++ fi ++ ++$as_echo "#define _THREAD_SAFE 1" >>confdefs.h ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthread" >&5 ++$as_echo_n "checking for pthread_mutex_init in -lpthread... " >&6; } ++if ${ac_cv_lib_pthread_pthread_mutex_init+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_check_lib_save_LIBS=$LIBS ++LIBS="-lpthread $LIBS" ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++/* Override any GCC internal prototype to avoid an error. ++ Use char because int might match the return type of a GCC ++ builtin and then its argument prototype would still apply. */ ++#ifdef __cplusplus ++extern "C" ++#endif ++char pthread_mutex_init (); ++int ++main () ++{ ++return pthread_mutex_init (); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ ac_cv_lib_pthread_pthread_mutex_init=yes ++else ++ ac_cv_lib_pthread_pthread_mutex_init=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++LIBS=$ac_check_lib_save_LIBS ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5 ++$as_echo "$ac_cv_lib_pthread_pthread_mutex_init" >&6; } ++if test "x$ac_cv_lib_pthread_pthread_mutex_init" = xyes; then : ++ tcl_ok=yes ++else ++ tcl_ok=no ++fi ++ ++ if test "$tcl_ok" = "no"; then ++ # Check a little harder for __pthread_mutex_init in the same ++ # library, as some systems hide it there until pthread.h is ++ # defined. We could alternatively do an AC_TRY_COMPILE with ++ # pthread.h, but that will work with libpthread really doesn't ++ # exist, like AIX 4.2. [Bug: 4359] ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __pthread_mutex_init in -lpthread" >&5 ++$as_echo_n "checking for __pthread_mutex_init in -lpthread... " >&6; } ++if ${ac_cv_lib_pthread___pthread_mutex_init+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_check_lib_save_LIBS=$LIBS ++LIBS="-lpthread $LIBS" ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++/* Override any GCC internal prototype to avoid an error. ++ Use char because int might match the return type of a GCC ++ builtin and then its argument prototype would still apply. */ ++#ifdef __cplusplus ++extern "C" ++#endif ++char __pthread_mutex_init (); ++int ++main () ++{ ++return __pthread_mutex_init (); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ ac_cv_lib_pthread___pthread_mutex_init=yes ++else ++ ac_cv_lib_pthread___pthread_mutex_init=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++LIBS=$ac_check_lib_save_LIBS ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread___pthread_mutex_init" >&5 ++$as_echo "$ac_cv_lib_pthread___pthread_mutex_init" >&6; } ++if test "x$ac_cv_lib_pthread___pthread_mutex_init" = xyes; then : ++ tcl_ok=yes ++else ++ tcl_ok=no ++fi ++ ++ fi ++ ++ if test "$tcl_ok" = "yes"; then ++ # The space is needed ++ THREADS_LIBS=" -lpthread" ++ else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthreads" >&5 ++$as_echo_n "checking for pthread_mutex_init in -lpthreads... " >&6; } ++if ${ac_cv_lib_pthreads_pthread_mutex_init+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_check_lib_save_LIBS=$LIBS ++LIBS="-lpthreads $LIBS" ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++/* Override any GCC internal prototype to avoid an error. ++ Use char because int might match the return type of a GCC ++ builtin and then its argument prototype would still apply. */ ++#ifdef __cplusplus ++extern "C" ++#endif ++char pthread_mutex_init (); ++int ++main () ++{ ++return pthread_mutex_init (); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ ac_cv_lib_pthreads_pthread_mutex_init=yes ++else ++ ac_cv_lib_pthreads_pthread_mutex_init=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++LIBS=$ac_check_lib_save_LIBS ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthreads_pthread_mutex_init" >&5 ++$as_echo "$ac_cv_lib_pthreads_pthread_mutex_init" >&6; } ++if test "x$ac_cv_lib_pthreads_pthread_mutex_init" = xyes; then : ++ tcl_ok=yes ++else ++ tcl_ok=no ++fi ++ ++ if test "$tcl_ok" = "yes"; then ++ # The space is needed ++ THREADS_LIBS=" -lpthreads" ++ else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc" >&5 ++$as_echo_n "checking for pthread_mutex_init in -lc... " >&6; } ++if ${ac_cv_lib_c_pthread_mutex_init+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_check_lib_save_LIBS=$LIBS ++LIBS="-lc $LIBS" ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++/* Override any GCC internal prototype to avoid an error. ++ Use char because int might match the return type of a GCC ++ builtin and then its argument prototype would still apply. */ ++#ifdef __cplusplus ++extern "C" ++#endif ++char pthread_mutex_init (); ++int ++main () ++{ ++return pthread_mutex_init (); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ ac_cv_lib_c_pthread_mutex_init=yes ++else ++ ac_cv_lib_c_pthread_mutex_init=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++LIBS=$ac_check_lib_save_LIBS ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_pthread_mutex_init" >&5 ++$as_echo "$ac_cv_lib_c_pthread_mutex_init" >&6; } ++if test "x$ac_cv_lib_c_pthread_mutex_init" = xyes; then : ++ tcl_ok=yes ++else ++ tcl_ok=no ++fi ++ ++ if test "$tcl_ok" = "no"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc_r" >&5 ++$as_echo_n "checking for pthread_mutex_init in -lc_r... " >&6; } ++if ${ac_cv_lib_c_r_pthread_mutex_init+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_check_lib_save_LIBS=$LIBS ++LIBS="-lc_r $LIBS" ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++/* Override any GCC internal prototype to avoid an error. ++ Use char because int might match the return type of a GCC ++ builtin and then its argument prototype would still apply. */ ++#ifdef __cplusplus ++extern "C" ++#endif ++char pthread_mutex_init (); ++int ++main () ++{ ++return pthread_mutex_init (); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ ac_cv_lib_c_r_pthread_mutex_init=yes ++else ++ ac_cv_lib_c_r_pthread_mutex_init=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++LIBS=$ac_check_lib_save_LIBS ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_mutex_init" >&5 ++$as_echo "$ac_cv_lib_c_r_pthread_mutex_init" >&6; } ++if test "x$ac_cv_lib_c_r_pthread_mutex_init" = xyes; then : ++ tcl_ok=yes ++else ++ tcl_ok=no ++fi ++ ++ if test "$tcl_ok" = "yes"; then ++ # The space is needed ++ THREADS_LIBS=" -pthread" ++ else ++ TCL_THREADS=0 ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Do not know how to find pthread lib on your system - thread support disabled" >&5 ++$as_echo "$as_me: WARNING: Do not know how to find pthread lib on your system - thread support disabled" >&2;} ++ fi ++ fi ++ fi ++ fi ++ fi ++ else ++ TCL_THREADS=0 ++ fi ++ # Do checking message here to not mess up interleaved configure output ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for building with threads" >&5 ++$as_echo_n "checking for building with threads... " >&6; } ++ if test "${TCL_THREADS}" = 1; then ++ ++$as_echo "#define TCL_THREADS 1" >>confdefs.h ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (default)" >&5 ++$as_echo "yes (default)" >&6; } ++ else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++ fi ++ # TCL_THREADS sanity checking. See if our request for building with ++ # threads is the same as the way Tcl was built. If not, warn the user. ++ case ${TCL_DEFS} in ++ *THREADS=1*) ++ if test "${TCL_THREADS}" = "0"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ++ Building ${PACKAGE_NAME} without threads enabled, but building against Tcl ++ that IS thread-enabled. It is recommended to use --enable-threads." >&5 ++$as_echo "$as_me: WARNING: ++ Building ${PACKAGE_NAME} without threads enabled, but building against Tcl ++ that IS thread-enabled. It is recommended to use --enable-threads." >&2;} ++ fi ++ ;; ++ *) ++ if test "${TCL_THREADS}" = "1"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ++ --enable-threads requested, but building against a Tcl that is NOT ++ thread-enabled. This is an OK configuration that will also run in ++ a thread-enabled core." >&5 ++$as_echo "$as_me: WARNING: ++ --enable-threads requested, but building against a Tcl that is NOT ++ thread-enabled. This is an OK configuration that will also run in ++ a thread-enabled core." >&2;} ++ fi ++ ;; ++ esac ++ ++ ++if test "${TCL_THREADS}" = "1" ; then ++ ++$as_echo "#define SQLITE_THREADSAFE 1" >>confdefs.h ++ ++ # Not automatically added by Tcl because its assumed Tcl links to them, ++ # but it may not if it isn't really a threaded build. ++ ++ vars="$THREADS_LIBS" ++ for i in $vars; do ++ if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then ++ # Convert foo.lib to -lfoo for GCC. No-op if not *.lib ++ i=`echo "$i" | sed -e 's/^\([^-].*\)\.lib$/-l\1/i'` ++ fi ++ PKG_LIBS="$PKG_LIBS $i" ++ done ++ ++ ++else ++ ++$as_echo "#define SQLITE_THREADSAFE 0" >>confdefs.h ++ ++fi ++ ++#-------------------------------------------------------------------- ++# The statement below defines a collection of symbols related to ++# building as a shared library instead of a static library. ++#-------------------------------------------------------------------- ++ ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to build libraries" >&5 ++$as_echo_n "checking how to build libraries... " >&6; } ++ # Check whether --enable-shared was given. ++if test "${enable_shared+set}" = set; then : ++ enableval=$enable_shared; tcl_ok=$enableval ++else ++ tcl_ok=yes ++fi ++ ++ ++ if test "${enable_shared+set}" = set; then ++ enableval="$enable_shared" ++ tcl_ok=$enableval ++ else ++ tcl_ok=yes ++ fi ++ ++ if test "$tcl_ok" = "yes" ; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: shared" >&5 ++$as_echo "shared" >&6; } ++ SHARED_BUILD=1 ++ else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: static" >&5 ++$as_echo "static" >&6; } ++ SHARED_BUILD=0 ++ ++$as_echo "#define STATIC_BUILD 1" >>confdefs.h ++ ++ fi ++ ++ ++ ++#-------------------------------------------------------------------- ++# This macro figures out what flags to use with the compiler/linker ++# when building shared/static debug/optimized objects. This information ++# can be taken from the tclConfig.sh file, but this figures it all out. ++#-------------------------------------------------------------------- ++ ++if test -n "$ac_tool_prefix"; then ++ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. ++set dummy ${ac_tool_prefix}ranlib; ac_word=$2 ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 ++$as_echo_n "checking for $ac_word... " >&6; } ++if ${ac_cv_prog_RANLIB+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if test -n "$RANLIB"; then ++ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. ++else ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ++ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" ++ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++ done ++IFS=$as_save_IFS ++ ++fi ++fi ++RANLIB=$ac_cv_prog_RANLIB ++if test -n "$RANLIB"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 ++$as_echo "$RANLIB" >&6; } ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++fi ++ ++ ++fi ++if test -z "$ac_cv_prog_RANLIB"; then ++ ac_ct_RANLIB=$RANLIB ++ # Extract the first word of "ranlib", so it can be a program name with args. ++set dummy ranlib; ac_word=$2 ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 ++$as_echo_n "checking for $ac_word... " >&6; } ++if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if test -n "$ac_ct_RANLIB"; then ++ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. ++else ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ++ ac_cv_prog_ac_ct_RANLIB="ranlib" ++ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++ done ++IFS=$as_save_IFS ++ ++fi ++fi ++ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB ++if test -n "$ac_ct_RANLIB"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 ++$as_echo "$ac_ct_RANLIB" >&6; } ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++fi ++ ++ if test "x$ac_ct_RANLIB" = x; then ++ RANLIB=":" ++ else ++ case $cross_compiling:$ac_tool_warned in ++yes:) ++{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 ++$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ++ac_tool_warned=yes ;; ++esac ++ RANLIB=$ac_ct_RANLIB ++ fi ++else ++ RANLIB="$ac_cv_prog_RANLIB" ++fi ++ ++ ++ ++ ++ # Step 0.a: Enable 64 bit support? ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 64bit support is requested" >&5 ++$as_echo_n "checking if 64bit support is requested... " >&6; } ++ # Check whether --enable-64bit was given. ++if test "${enable_64bit+set}" = set; then : ++ enableval=$enable_64bit; do64bit=$enableval ++else ++ do64bit=no ++fi ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bit" >&5 ++$as_echo "$do64bit" >&6; } ++ ++ # Step 0.b: Enable Solaris 64 bit VIS support? ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 64bit Sparc VIS support is requested" >&5 ++$as_echo_n "checking if 64bit Sparc VIS support is requested... " >&6; } ++ # Check whether --enable-64bit-vis was given. ++if test "${enable_64bit_vis+set}" = set; then : ++ enableval=$enable_64bit_vis; do64bitVIS=$enableval ++else ++ do64bitVIS=no ++fi ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bitVIS" >&5 ++$as_echo "$do64bitVIS" >&6; } ++ # Force 64bit on with VIS ++ if test "$do64bitVIS" = "yes"; then : ++ do64bit=yes ++fi ++ ++ # Step 0.c: Check if visibility support is available. Do this here so ++ # that platform specific alternatives can be used below if this fails. ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports visibility \"hidden\"" >&5 ++$as_echo_n "checking if compiler supports visibility \"hidden\"... " >&6; } ++if ${tcl_cv_cc_visibility_hidden+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ++ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++ extern __attribute__((__visibility__("hidden"))) void f(void); ++ void f(void) {} ++int ++main () ++{ ++f(); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ tcl_cv_cc_visibility_hidden=yes ++else ++ tcl_cv_cc_visibility_hidden=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++ CFLAGS=$hold_cflags ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_visibility_hidden" >&5 ++$as_echo "$tcl_cv_cc_visibility_hidden" >&6; } ++ if test $tcl_cv_cc_visibility_hidden = yes; then : ++ ++ ++$as_echo "#define MODULE_SCOPE extern __attribute__((__visibility__(\"hidden\")))" >>confdefs.h ++ ++ ++$as_echo "#define HAVE_HIDDEN 1" >>confdefs.h ++ ++ ++fi ++ ++ # Step 0.d: Disable -rpath support? ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if rpath support is requested" >&5 ++$as_echo_n "checking if rpath support is requested... " >&6; } ++ # Check whether --enable-rpath was given. ++if test "${enable_rpath+set}" = set; then : ++ enableval=$enable_rpath; doRpath=$enableval ++else ++ doRpath=yes ++fi ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $doRpath" >&5 ++$as_echo "$doRpath" >&6; } ++ ++ # TEA specific: Cross-compiling options for Windows/CE builds? ++ ++ if test "${TEA_PLATFORM}" = windows; then : ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Windows/CE build is requested" >&5 ++$as_echo_n "checking if Windows/CE build is requested... " >&6; } ++ # Check whether --enable-wince was given. ++if test "${enable_wince+set}" = set; then : ++ enableval=$enable_wince; doWince=$enableval ++else ++ doWince=no ++fi ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $doWince" >&5 ++$as_echo "$doWince" >&6; } ++ ++fi ++ ++ # Set the variable "system" to hold the name and version number ++ # for the system. ++ ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking system version" >&5 ++$as_echo_n "checking system version... " >&6; } ++if ${tcl_cv_sys_version+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ++ # TEA specific: ++ if test "${TEA_PLATFORM}" = "windows" ; then ++ tcl_cv_sys_version=windows ++ else ++ tcl_cv_sys_version=`uname -s`-`uname -r` ++ if test "$?" -ne 0 ; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command" >&5 ++$as_echo "$as_me: WARNING: can't find uname command" >&2;} ++ tcl_cv_sys_version=unknown ++ else ++ if test "`uname -s`" = "AIX" ; then ++ tcl_cv_sys_version=AIX-`uname -v`.`uname -r` ++ fi ++ fi ++ fi ++ ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5 ++$as_echo "$tcl_cv_sys_version" >&6; } ++ system=$tcl_cv_sys_version ++ ++ ++ # Require ranlib early so we can override it in special cases below. ++ ++ ++ ++ # Set configuration options based on system name and version. ++ # This is similar to Tcl's unix/tcl.m4 except that we've added a ++ # "windows" case and removed some core-only vars. ++ ++ do64bit_ok=no ++ # default to '{$LIBS}' and set to "" on per-platform necessary basis ++ SHLIB_LD_LIBS='${LIBS}' ++ # When ld needs options to work in 64-bit mode, put them in ++ # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load] ++ # is disabled by the user. [Bug 1016796] ++ LDFLAGS_ARCH="" ++ UNSHARED_LIB_SUFFIX="" ++ # TEA specific: use PACKAGE_VERSION instead of VERSION ++ TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`' ++ ECHO_VERSION='`echo ${PACKAGE_VERSION}`' ++ TCL_LIB_VERSIONS_OK=ok ++ CFLAGS_DEBUG=-g ++ if test "$GCC" = yes; then : ++ ++ CFLAGS_OPTIMIZE=-O2 ++ CFLAGS_WARNING="-Wall" ++ ++else ++ ++ CFLAGS_OPTIMIZE=-O ++ CFLAGS_WARNING="" ++ ++fi ++ if test -n "$ac_tool_prefix"; then ++ # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. ++set dummy ${ac_tool_prefix}ar; ac_word=$2 ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 ++$as_echo_n "checking for $ac_word... " >&6; } ++if ${ac_cv_prog_AR+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if test -n "$AR"; then ++ ac_cv_prog_AR="$AR" # Let the user override the test. ++else ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ++ ac_cv_prog_AR="${ac_tool_prefix}ar" ++ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++ done ++IFS=$as_save_IFS ++ ++fi ++fi ++AR=$ac_cv_prog_AR ++if test -n "$AR"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 ++$as_echo "$AR" >&6; } ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++fi ++ ++ ++fi ++if test -z "$ac_cv_prog_AR"; then ++ ac_ct_AR=$AR ++ # Extract the first word of "ar", so it can be a program name with args. ++set dummy ar; ac_word=$2 ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 ++$as_echo_n "checking for $ac_word... " >&6; } ++if ${ac_cv_prog_ac_ct_AR+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if test -n "$ac_ct_AR"; then ++ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. ++else ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ++ ac_cv_prog_ac_ct_AR="ar" ++ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++ done ++IFS=$as_save_IFS ++ ++fi ++fi ++ac_ct_AR=$ac_cv_prog_ac_ct_AR ++if test -n "$ac_ct_AR"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 ++$as_echo "$ac_ct_AR" >&6; } ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++fi ++ ++ if test "x$ac_ct_AR" = x; then ++ AR="" ++ else ++ case $cross_compiling:$ac_tool_warned in ++yes:) ++{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 ++$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ++ac_tool_warned=yes ;; ++esac ++ AR=$ac_ct_AR ++ fi ++else ++ AR="$ac_cv_prog_AR" ++fi ++ ++ STLIB_LD='${AR} cr' ++ LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" ++ if test "x$SHLIB_VERSION" = x; then : ++ SHLIB_VERSION="1.0" ++fi ++ case $system in ++ # TEA specific: ++ windows) ++ # This is a 2-stage check to make sure we have the 64-bit SDK ++ # We have to know where the SDK is installed. ++ # This magic is based on MS Platform SDK for Win2003 SP1 - hobbs ++ # MACHINE is IX86 for LINK, but this is used by the manifest, ++ # which requires x86|amd64|ia64. ++ MACHINE="X86" ++ if test "$do64bit" != "no" ; then ++ if test "x${MSSDK}x" = "xx" ; then ++ MSSDK="C:/Progra~1/Microsoft Platform SDK" ++ fi ++ MSSDK=`echo "$MSSDK" | sed -e 's!\\\!/!g'` ++ PATH64="" ++ case "$do64bit" in ++ amd64|x64|yes) ++ MACHINE="AMD64" ; # default to AMD64 64-bit build ++ PATH64="${MSSDK}/Bin/Win64/x86/AMD64" ++ ;; ++ ia64) ++ MACHINE="IA64" ++ PATH64="${MSSDK}/Bin/Win64" ++ ;; ++ esac ++ if test "$GCC" != "yes" -a ! -d "${PATH64}" ; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Could not find 64-bit $MACHINE SDK to enable 64bit mode" >&5 ++$as_echo "$as_me: WARNING: Could not find 64-bit $MACHINE SDK to enable 64bit mode" >&2;} ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ensure latest Platform SDK is installed" >&5 ++$as_echo "$as_me: WARNING: Ensure latest Platform SDK is installed" >&2;} ++ do64bit="no" ++ else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using 64-bit $MACHINE mode" >&5 ++$as_echo " Using 64-bit $MACHINE mode" >&6; } ++ do64bit_ok="yes" ++ fi ++ fi ++ ++ if test "$doWince" != "no" ; then ++ if test "$do64bit" != "no" ; then ++ as_fn_error $? "Windows/CE and 64-bit builds incompatible" "$LINENO" 5 ++ fi ++ if test "$GCC" = "yes" ; then ++ as_fn_error $? "Windows/CE and GCC builds incompatible" "$LINENO" 5 ++ fi ++ ++ # First, look for one uninstalled. ++ # the alternative search directory is invoked by --with-celib ++ ++ if test x"${no_celib}" = x ; then ++ # we reset no_celib in case something fails here ++ no_celib=true ++ ++# Check whether --with-celib was given. ++if test "${with_celib+set}" = set; then : ++ withval=$with_celib; with_celibconfig=${withval} ++fi ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Windows/CE celib directory" >&5 ++$as_echo_n "checking for Windows/CE celib directory... " >&6; } ++ if ${ac_cv_c_celibconfig+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ++ # First check to see if --with-celibconfig was specified. ++ if test x"${with_celibconfig}" != x ; then ++ if test -d "${with_celibconfig}/inc" ; then ++ ac_cv_c_celibconfig=`(cd ${with_celibconfig}; pwd)` ++ else ++ as_fn_error $? "${with_celibconfig} directory doesn't contain inc directory" "$LINENO" 5 ++ fi ++ fi ++ ++ # then check for a celib library ++ if test x"${ac_cv_c_celibconfig}" = x ; then ++ for i in \ ++ ../celib-palm-3.0 \ ++ ../celib \ ++ ../../celib-palm-3.0 \ ++ ../../celib \ ++ `ls -dr ../celib-*3.[0-9]* 2>/dev/null` \ ++ ${srcdir}/../celib-palm-3.0 \ ++ ${srcdir}/../celib \ ++ `ls -dr ${srcdir}/../celib-*3.[0-9]* 2>/dev/null` \ ++ ; do ++ if test -d "$i/inc" ; then ++ ac_cv_c_celibconfig=`(cd $i; pwd)` ++ break ++ fi ++ done ++ fi ++ ++fi ++ ++ if test x"${ac_cv_c_celibconfig}" = x ; then ++ as_fn_error $? "Cannot find celib support library directory" "$LINENO" 5 ++ else ++ no_celib= ++ CELIB_DIR=${ac_cv_c_celibconfig} ++ CELIB_DIR=`echo "$CELIB_DIR" | sed -e 's!\\\!/!g'` ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: found $CELIB_DIR" >&5 ++$as_echo "found $CELIB_DIR" >&6; } ++ fi ++ fi ++ ++ # Set defaults for common evc4/PPC2003 setup ++ # Currently Tcl requires 300+, possibly 420+ for sockets ++ CEVERSION=420; # could be 211 300 301 400 420 ... ++ TARGETCPU=ARMV4; # could be ARMV4 ARM MIPS SH3 X86 ... ++ ARCH=ARM; # could be ARM MIPS X86EM ... ++ PLATFORM="Pocket PC 2003"; # or "Pocket PC 2002" ++ if test "$doWince" != "yes"; then ++ # If !yes then the user specified something ++ # Reset ARCH to allow user to skip specifying it ++ ARCH= ++ eval `echo $doWince | awk -F, '{ \ ++ if (length($1)) { printf "CEVERSION=\"%s\"\n", $1; \ ++ if ($1 < 400) { printf "PLATFORM=\"Pocket PC 2002\"\n" } }; \ ++ if (length($2)) { printf "TARGETCPU=\"%s\"\n", toupper($2) }; \ ++ if (length($3)) { printf "ARCH=\"%s\"\n", toupper($3) }; \ ++ if (length($4)) { printf "PLATFORM=\"%s\"\n", $4 }; \ ++ }'` ++ if test "x${ARCH}" = "x" ; then ++ ARCH=$TARGETCPU; ++ fi ++ fi ++ OSVERSION=WCE$CEVERSION; ++ if test "x${WCEROOT}" = "x" ; then ++ WCEROOT="C:/Program Files/Microsoft eMbedded C++ 4.0" ++ if test ! -d "${WCEROOT}" ; then ++ WCEROOT="C:/Program Files/Microsoft eMbedded Tools" ++ fi ++ fi ++ if test "x${SDKROOT}" = "x" ; then ++ SDKROOT="C:/Program Files/Windows CE Tools" ++ if test ! -d "${SDKROOT}" ; then ++ SDKROOT="C:/Windows CE Tools" ++ fi ++ fi ++ WCEROOT=`echo "$WCEROOT" | sed -e 's!\\\!/!g'` ++ SDKROOT=`echo "$SDKROOT" | sed -e 's!\\\!/!g'` ++ if test ! -d "${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" \ ++ -o ! -d "${WCEROOT}/EVC/${OSVERSION}/bin"; then ++ as_fn_error $? "could not find PocketPC SDK or target compiler to enable WinCE mode $CEVERSION,$TARGETCPU,$ARCH,$PLATFORM" "$LINENO" 5 ++ doWince="no" ++ else ++ # We could PATH_NOSPACE these, but that's not important, ++ # as long as we quote them when used. ++ CEINCLUDE="${SDKROOT}/${OSVERSION}/${PLATFORM}/include" ++ if test -d "${CEINCLUDE}/${TARGETCPU}" ; then ++ CEINCLUDE="${CEINCLUDE}/${TARGETCPU}" ++ fi ++ CELIBPATH="${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" ++ fi ++ fi ++ ++ if test "$GCC" != "yes" ; then ++ if test "${SHARED_BUILD}" = "0" ; then ++ runtime=-MT ++ else ++ runtime=-MD ++ fi ++ ++ if test "$do64bit" != "no" ; then ++ # All this magic is necessary for the Win64 SDK RC1 - hobbs ++ CC="\"${PATH64}/cl.exe\"" ++ CFLAGS="${CFLAGS} -I\"${MSSDK}/Include\" -I\"${MSSDK}/Include/crt\" -I\"${MSSDK}/Include/crt/sys\"" ++ RC="\"${MSSDK}/bin/rc.exe\"" ++ lflags="-nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\"" ++ LINKBIN="\"${PATH64}/link.exe\"" ++ CFLAGS_DEBUG="-nologo -Zi -Od -W3 ${runtime}d" ++ CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" ++ # Avoid 'unresolved external symbol __security_cookie' ++ # errors, c.f. http://support.microsoft.com/?id=894573 ++ ++ vars="bufferoverflowU.lib" ++ for i in $vars; do ++ if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then ++ # Convert foo.lib to -lfoo for GCC. No-op if not *.lib ++ i=`echo "$i" | sed -e 's/^\([^-].*\)\.lib$/-l\1/i'` ++ fi ++ PKG_LIBS="$PKG_LIBS $i" ++ done ++ ++ ++ elif test "$doWince" != "no" ; then ++ CEBINROOT="${WCEROOT}/EVC/${OSVERSION}/bin" ++ if test "${TARGETCPU}" = "X86"; then ++ CC="\"${CEBINROOT}/cl.exe\"" ++ else ++ CC="\"${CEBINROOT}/cl${ARCH}.exe\"" ++ fi ++ CFLAGS="$CFLAGS -I\"${CELIB_DIR}/inc\" -I\"${CEINCLUDE}\"" ++ RC="\"${WCEROOT}/Common/EVC/bin/rc.exe\"" ++ arch=`echo ${ARCH} | awk '{print tolower($0)}'` ++ defs="${ARCH} _${ARCH}_ ${arch} PALM_SIZE _MT _WINDOWS" ++ if test "${SHARED_BUILD}" = "1" ; then ++ # Static CE builds require static celib as well ++ defs="${defs} _DLL" ++ fi ++ for i in $defs ; do ++ ++cat >>confdefs.h <<_ACEOF ++#define $i 1 ++_ACEOF ++ ++ done ++ ++cat >>confdefs.h <<_ACEOF ++#define _WIN32_WCE $CEVERSION ++_ACEOF ++ ++ ++cat >>confdefs.h <<_ACEOF ++#define UNDER_CE $CEVERSION ++_ACEOF ++ ++ CFLAGS_DEBUG="-nologo -Zi -Od" ++ CFLAGS_OPTIMIZE="-nologo -Ox" ++ lversion=`echo ${CEVERSION} | sed -e 's/\(.\)\(..\)/\1\.\2/'` ++ lflags="-MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo" ++ LINKBIN="\"${CEBINROOT}/link.exe\"" ++ ++ else ++ RC="rc" ++ lflags="-nologo" ++ LINKBIN="link" ++ CFLAGS_DEBUG="-nologo -Z7 -Od -W3 -WX ${runtime}d" ++ CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" ++ fi ++ fi ++ ++ if test "$GCC" = "yes"; then ++ # mingw gcc mode ++ if test -n "$ac_tool_prefix"; then ++ # Extract the first word of "${ac_tool_prefix}windres", so it can be a program name with args. ++set dummy ${ac_tool_prefix}windres; ac_word=$2 ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 ++$as_echo_n "checking for $ac_word... " >&6; } ++if ${ac_cv_prog_RC+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if test -n "$RC"; then ++ ac_cv_prog_RC="$RC" # Let the user override the test. ++else ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ++ ac_cv_prog_RC="${ac_tool_prefix}windres" ++ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++ done ++IFS=$as_save_IFS ++ ++fi ++fi ++RC=$ac_cv_prog_RC ++if test -n "$RC"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RC" >&5 ++$as_echo "$RC" >&6; } ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++fi ++ ++ ++fi ++if test -z "$ac_cv_prog_RC"; then ++ ac_ct_RC=$RC ++ # Extract the first word of "windres", so it can be a program name with args. ++set dummy windres; ac_word=$2 ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 ++$as_echo_n "checking for $ac_word... " >&6; } ++if ${ac_cv_prog_ac_ct_RC+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if test -n "$ac_ct_RC"; then ++ ac_cv_prog_ac_ct_RC="$ac_ct_RC" # Let the user override the test. ++else ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ++ ac_cv_prog_ac_ct_RC="windres" ++ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++ done ++IFS=$as_save_IFS ++ ++fi ++fi ++ac_ct_RC=$ac_cv_prog_ac_ct_RC ++if test -n "$ac_ct_RC"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RC" >&5 ++$as_echo "$ac_ct_RC" >&6; } ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++fi ++ ++ if test "x$ac_ct_RC" = x; then ++ RC="" ++ else ++ case $cross_compiling:$ac_tool_warned in ++yes:) ++{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 ++$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ++ac_tool_warned=yes ;; ++esac ++ RC=$ac_ct_RC ++ fi ++else ++ RC="$ac_cv_prog_RC" ++fi ++ ++ CFLAGS_DEBUG="-g" ++ CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" ++ SHLIB_LD='${CC} -shared' ++ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' ++ LDFLAGS_CONSOLE="-wl,--subsystem,console ${lflags}" ++ LDFLAGS_WINDOW="-wl,--subsystem,windows ${lflags}" ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cross-compile version of gcc" >&5 ++$as_echo_n "checking for cross-compile version of gcc... " >&6; } ++if ${ac_cv_cross+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++ #ifdef _WIN32 ++ #error cross-compiler ++ #endif ++ ++int ++main () ++{ ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ ac_cv_cross=yes ++else ++ ac_cv_cross=no ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++ ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cross" >&5 ++$as_echo "$ac_cv_cross" >&6; } ++ if test "$ac_cv_cross" = "yes"; then ++ case "$do64bit" in ++ amd64|x64|yes) ++ CC="x86_64-w64-mingw32-gcc" ++ LD="x86_64-w64-mingw32-ld" ++ AR="x86_64-w64-mingw32-ar" ++ RANLIB="x86_64-w64-mingw32-ranlib" ++ RC="x86_64-w64-mingw32-windres" ++ ;; ++ *) ++ CC="i686-w64-mingw32-gcc" ++ LD="i686-w64-mingw32-ld" ++ AR="i686-w64-mingw32-ar" ++ RANLIB="i686-w64-mingw32-ranlib" ++ RC="i686-w64-mingw32-windres" ++ ;; ++ esac ++ fi ++ ++ else ++ SHLIB_LD="${LINKBIN} -dll ${lflags}" ++ # link -lib only works when -lib is the first arg ++ STLIB_LD="${LINKBIN} -lib ${lflags}" ++ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.lib' ++ PATHTYPE=-w ++ # For information on what debugtype is most useful, see: ++ # http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp ++ # and also ++ # http://msdn2.microsoft.com/en-us/library/y0zzbyt4%28VS.80%29.aspx ++ # This essentially turns it all on. ++ LDFLAGS_DEBUG="-debug -debugtype:cv" ++ LDFLAGS_OPTIMIZE="-release" ++ if test "$doWince" != "no" ; then ++ LDFLAGS_CONSOLE="-link ${lflags}" ++ LDFLAGS_WINDOW=${LDFLAGS_CONSOLE} ++ else ++ LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}" ++ LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}" ++ fi ++ fi ++ ++ SHLIB_SUFFIX=".dll" ++ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll' ++ ++ TCL_LIB_VERSIONS_OK=nodots ++ ;; ++ AIX-*) ++ if test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"; then : ++ ++ # AIX requires the _r compiler when gcc isn't being used ++ case "${CC}" in ++ *_r|*_r\ *) ++ # ok ... ++ ;; ++ *) ++ # Make sure only first arg gets _r ++ CC=`echo "$CC" | sed -e 's/^\([^ ]*\)/\1_r/'` ++ ;; ++ esac ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using $CC for compiling with threads" >&5 ++$as_echo "Using $CC for compiling with threads" >&6; } ++ ++fi ++ LIBS="$LIBS -lc" ++ SHLIB_CFLAGS="" ++ SHLIB_SUFFIX=".so" ++ ++ LD_LIBRARY_PATH_VAR="LIBPATH" ++ ++ # Check to enable 64-bit flags for compiler/linker ++ if test "$do64bit" = yes; then : ++ ++ if test "$GCC" = yes; then : ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 ++$as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;} ++ ++else ++ ++ do64bit_ok=yes ++ CFLAGS="$CFLAGS -q64" ++ LDFLAGS_ARCH="-q64" ++ RANLIB="${RANLIB} -X64" ++ AR="${AR} -X64" ++ SHLIB_LD_FLAGS="-b64" ++ ++fi ++ ++fi ++ ++ if test "`uname -m`" = ia64; then : ++ ++ # AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC ++ SHLIB_LD="/usr/ccs/bin/ld -G -z text" ++ if test "$GCC" = yes; then : ++ ++ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' ++ ++else ++ ++ CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}' ++ ++fi ++ LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' ++ ++else ++ ++ if test "$GCC" = yes; then : ++ ++ SHLIB_LD='${CC} -shared -Wl,-bexpall' ++ ++else ++ ++ SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry" ++ LDFLAGS="$LDFLAGS -brtl" ++ ++fi ++ SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}" ++ CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' ++ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ++ ++fi ++ ;; ++ BeOS*) ++ SHLIB_CFLAGS="-fPIC" ++ SHLIB_LD='${CC} -nostart' ++ SHLIB_SUFFIX=".so" ++ ++ #----------------------------------------------------------- ++ # Check for inet_ntoa in -lbind, for BeOS (which also needs ++ # -lsocket, even if the network functions are in -lnet which ++ # is always linked to, for compatibility. ++ #----------------------------------------------------------- ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lbind" >&5 ++$as_echo_n "checking for inet_ntoa in -lbind... " >&6; } ++if ${ac_cv_lib_bind_inet_ntoa+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_check_lib_save_LIBS=$LIBS ++LIBS="-lbind $LIBS" ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++/* Override any GCC internal prototype to avoid an error. ++ Use char because int might match the return type of a GCC ++ builtin and then its argument prototype would still apply. */ ++#ifdef __cplusplus ++extern "C" ++#endif ++char inet_ntoa (); ++int ++main () ++{ ++return inet_ntoa (); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ ac_cv_lib_bind_inet_ntoa=yes ++else ++ ac_cv_lib_bind_inet_ntoa=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++LIBS=$ac_check_lib_save_LIBS ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bind_inet_ntoa" >&5 ++$as_echo "$ac_cv_lib_bind_inet_ntoa" >&6; } ++if test "x$ac_cv_lib_bind_inet_ntoa" = xyes; then : ++ LIBS="$LIBS -lbind -lsocket" ++fi ++ ++ ;; ++ BSD/OS-4.*) ++ SHLIB_CFLAGS="-export-dynamic -fPIC" ++ SHLIB_LD='${CC} -shared' ++ SHLIB_SUFFIX=".so" ++ LDFLAGS="$LDFLAGS -export-dynamic" ++ CC_SEARCH_FLAGS="" ++ LD_SEARCH_FLAGS="" ++ ;; ++ CYGWIN_*) ++ SHLIB_CFLAGS="" ++ SHLIB_LD='${CC} -shared' ++ SHLIB_SUFFIX=".dll" ++ EXEEXT=".exe" ++ do64bit_ok=yes ++ CC_SEARCH_FLAGS="" ++ LD_SEARCH_FLAGS="" ++ ;; ++ Haiku*) ++ LDFLAGS="$LDFLAGS -Wl,--export-dynamic" ++ SHLIB_CFLAGS="-fPIC" ++ SHLIB_SUFFIX=".so" ++ SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}' ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lnetwork" >&5 ++$as_echo_n "checking for inet_ntoa in -lnetwork... " >&6; } ++if ${ac_cv_lib_network_inet_ntoa+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_check_lib_save_LIBS=$LIBS ++LIBS="-lnetwork $LIBS" ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++/* Override any GCC internal prototype to avoid an error. ++ Use char because int might match the return type of a GCC ++ builtin and then its argument prototype would still apply. */ ++#ifdef __cplusplus ++extern "C" ++#endif ++char inet_ntoa (); ++int ++main () ++{ ++return inet_ntoa (); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ ac_cv_lib_network_inet_ntoa=yes ++else ++ ac_cv_lib_network_inet_ntoa=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++LIBS=$ac_check_lib_save_LIBS ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_inet_ntoa" >&5 ++$as_echo "$ac_cv_lib_network_inet_ntoa" >&6; } ++if test "x$ac_cv_lib_network_inet_ntoa" = xyes; then : ++ LIBS="$LIBS -lnetwork" ++fi ++ ++ ;; ++ HP-UX-*.11.*) ++ # Use updated header definitions where possible ++ ++$as_echo "#define _XOPEN_SOURCE_EXTENDED 1" >>confdefs.h ++ ++ # TEA specific: Needed by Tcl, but not most extensions ++ #AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?]) ++ #LIBS="$LIBS -lxnet" # Use the XOPEN network library ++ ++ if test "`uname -m`" = ia64; then : ++ ++ SHLIB_SUFFIX=".so" ++ # Use newer C++ library for C++ extensions ++ #if test "$GCC" != "yes" ; then ++ # CPPFLAGS="-AA" ++ #fi ++ ++else ++ ++ SHLIB_SUFFIX=".sl" ++ ++fi ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 ++$as_echo_n "checking for shl_load in -ldld... " >&6; } ++if ${ac_cv_lib_dld_shl_load+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_check_lib_save_LIBS=$LIBS ++LIBS="-ldld $LIBS" ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++/* Override any GCC internal prototype to avoid an error. ++ Use char because int might match the return type of a GCC ++ builtin and then its argument prototype would still apply. */ ++#ifdef __cplusplus ++extern "C" ++#endif ++char shl_load (); ++int ++main () ++{ ++return shl_load (); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ ac_cv_lib_dld_shl_load=yes ++else ++ ac_cv_lib_dld_shl_load=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++LIBS=$ac_check_lib_save_LIBS ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 ++$as_echo "$ac_cv_lib_dld_shl_load" >&6; } ++if test "x$ac_cv_lib_dld_shl_load" = xyes; then : ++ tcl_ok=yes ++else ++ tcl_ok=no ++fi ++ ++ if test "$tcl_ok" = yes; then : ++ ++ LDFLAGS="$LDFLAGS -Wl,-E" ++ CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.' ++ LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.' ++ LD_LIBRARY_PATH_VAR="SHLIB_PATH" ++ ++fi ++ if test "$GCC" = yes; then : ++ ++ SHLIB_LD='${CC} -shared' ++ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ++ ++else ++ ++ CFLAGS="$CFLAGS -z" ++ # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc ++ #CFLAGS="$CFLAGS +DAportable" ++ SHLIB_CFLAGS="+z" ++ SHLIB_LD="ld -b" ++ ++fi ++ ++ # Check to enable 64-bit flags for compiler/linker ++ if test "$do64bit" = "yes"; then : ++ ++ if test "$GCC" = yes; then : ++ ++ case `${CC} -dumpmachine` in ++ hppa64*) ++ # 64-bit gcc in use. Fix flags for GNU ld. ++ do64bit_ok=yes ++ SHLIB_LD='${CC} -shared' ++ if test $doRpath = yes; then : ++ ++ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' ++fi ++ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ++ ;; ++ *) ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 ++$as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;} ++ ;; ++ esac ++ ++else ++ ++ do64bit_ok=yes ++ CFLAGS="$CFLAGS +DD64" ++ LDFLAGS_ARCH="+DD64" ++ ++fi ++ ++fi ;; ++ IRIX-6.*) ++ SHLIB_CFLAGS="" ++ SHLIB_LD="ld -n32 -shared -rdata_shared" ++ SHLIB_SUFFIX=".so" ++ if test $doRpath = yes; then : ++ ++ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' ++ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' ++fi ++ if test "$GCC" = yes; then : ++ ++ CFLAGS="$CFLAGS -mabi=n32" ++ LDFLAGS="$LDFLAGS -mabi=n32" ++ ++else ++ ++ case $system in ++ IRIX-6.3) ++ # Use to build 6.2 compatible binaries on 6.3. ++ CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS" ++ ;; ++ *) ++ CFLAGS="$CFLAGS -n32" ++ ;; ++ esac ++ LDFLAGS="$LDFLAGS -n32" ++ ++fi ++ ;; ++ IRIX64-6.*) ++ SHLIB_CFLAGS="" ++ SHLIB_LD="ld -n32 -shared -rdata_shared" ++ SHLIB_SUFFIX=".so" ++ if test $doRpath = yes; then : ++ ++ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' ++ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' ++fi ++ ++ # Check to enable 64-bit flags for compiler/linker ++ ++ if test "$do64bit" = yes; then : ++ ++ if test "$GCC" = yes; then : ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported by gcc" >&5 ++$as_echo "$as_me: WARNING: 64bit mode not supported by gcc" >&2;} ++ ++else ++ ++ do64bit_ok=yes ++ SHLIB_LD="ld -64 -shared -rdata_shared" ++ CFLAGS="$CFLAGS -64" ++ LDFLAGS_ARCH="-64" ++ ++fi ++ ++fi ++ ;; ++ Linux*|GNU*|NetBSD-Debian) ++ SHLIB_CFLAGS="-fPIC" ++ SHLIB_SUFFIX=".so" ++ ++ # TEA specific: ++ CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" ++ ++ # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS ++ SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS_DEFAULT}' ++ LDFLAGS="$LDFLAGS -Wl,--export-dynamic" ++ if test $doRpath = yes; then : ++ ++ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' ++fi ++ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ++ if test "`uname -m`" = "alpha"; then : ++ CFLAGS="$CFLAGS -mieee" ++fi ++ if test $do64bit = yes; then : ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -m64 flag" >&5 ++$as_echo_n "checking if compiler accepts -m64 flag... " >&6; } ++if ${tcl_cv_cc_m64+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ++ hold_cflags=$CFLAGS ++ CFLAGS="$CFLAGS -m64" ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++int ++main () ++{ ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ tcl_cv_cc_m64=yes ++else ++ tcl_cv_cc_m64=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++ CFLAGS=$hold_cflags ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_m64" >&5 ++$as_echo "$tcl_cv_cc_m64" >&6; } ++ if test $tcl_cv_cc_m64 = yes; then : ++ ++ CFLAGS="$CFLAGS -m64" ++ do64bit_ok=yes ++ ++fi ++ ++fi ++ ++ # The combo of gcc + glibc has a bug related to inlining of ++ # functions like strtod(). The -fno-builtin flag should address ++ # this problem but it does not work. The -fno-inline flag is kind ++ # of overkill but it works. Disable inlining only when one of the ++ # files in compat/*.c is being linked in. ++ ++ if test x"${USE_COMPAT}" != x; then : ++ CFLAGS="$CFLAGS -fno-inline" ++fi ++ ;; ++ Lynx*) ++ SHLIB_CFLAGS="-fPIC" ++ SHLIB_SUFFIX=".so" ++ CFLAGS_OPTIMIZE=-02 ++ SHLIB_LD='${CC} -shared' ++ LD_FLAGS="-Wl,--export-dynamic" ++ if test $doRpath = yes; then : ++ ++ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' ++ LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' ++fi ++ ;; ++ OpenBSD-*) ++ arch=`arch -s` ++ case "$arch" in ++ vax) ++ SHLIB_SUFFIX="" ++ SHARED_LIB_SUFFIX="" ++ LDFLAGS="" ++ ;; ++ *) ++ SHLIB_CFLAGS="-fPIC" ++ SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}' ++ SHLIB_SUFFIX=".so" ++ if test $doRpath = yes; then : ++ ++ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' ++fi ++ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ++ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}' ++ LDFLAGS="-Wl,-export-dynamic" ++ ;; ++ esac ++ case "$arch" in ++ vax) ++ CFLAGS_OPTIMIZE="-O1" ++ ;; ++ *) ++ CFLAGS_OPTIMIZE="-O2" ++ ;; ++ esac ++ if test "${TCL_THREADS}" = "1"; then : ++ ++ # On OpenBSD: Compile with -pthread ++ # Don't link with -lpthread ++ LIBS=`echo $LIBS | sed s/-lpthread//` ++ CFLAGS="$CFLAGS -pthread" ++ ++fi ++ # OpenBSD doesn't do version numbers with dots. ++ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' ++ TCL_LIB_VERSIONS_OK=nodots ++ ;; ++ NetBSD-*) ++ # NetBSD has ELF and can use 'cc -shared' to build shared libs ++ SHLIB_CFLAGS="-fPIC" ++ SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}' ++ SHLIB_SUFFIX=".so" ++ LDFLAGS="$LDFLAGS -export-dynamic" ++ if test $doRpath = yes; then : ++ ++ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' ++fi ++ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ++ if test "${TCL_THREADS}" = "1"; then : ++ ++ # The -pthread needs to go in the CFLAGS, not LIBS ++ LIBS=`echo $LIBS | sed s/-pthread//` ++ CFLAGS="$CFLAGS -pthread" ++ LDFLAGS="$LDFLAGS -pthread" ++ ++fi ++ ;; ++ FreeBSD-*) ++ # This configuration from FreeBSD Ports. ++ SHLIB_CFLAGS="-fPIC" ++ SHLIB_LD="${CC} -shared" ++ TCL_SHLIB_LD_EXTRAS="-Wl,-soname=\$@" ++ TK_SHLIB_LD_EXTRAS="-Wl,-soname,\$@" ++ SHLIB_SUFFIX=".so" ++ LDFLAGS="" ++ if test $doRpath = yes; then : ++ ++ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' ++ LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' ++fi ++ if test "${TCL_THREADS}" = "1"; then : ++ ++ # The -pthread needs to go in the LDFLAGS, not LIBS ++ LIBS=`echo $LIBS | sed s/-pthread//` ++ CFLAGS="$CFLAGS $PTHREAD_CFLAGS" ++ LDFLAGS="$LDFLAGS $PTHREAD_LIBS" ++fi ++ case $system in ++ FreeBSD-3.*) ++ # Version numbers are dot-stripped by system policy. ++ TCL_TRIM_DOTS=`echo ${VERSION} | tr -d .` ++ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' ++ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so' ++ TCL_LIB_VERSIONS_OK=nodots ++ ;; ++ esac ++ ;; ++ Darwin-*) ++ CFLAGS_OPTIMIZE="-Os" ++ SHLIB_CFLAGS="-fno-common" ++ # To avoid discrepancies between what headers configure sees during ++ # preprocessing tests and compiling tests, move any -isysroot and ++ # -mmacosx-version-min flags from CFLAGS to CPPFLAGS: ++ CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \ ++ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ ++ if ($i~/^(isysroot|mmacosx-version-min)/) print "-"$i}'`" ++ CFLAGS="`echo " ${CFLAGS}" | \ ++ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ ++ if (!($i~/^(isysroot|mmacosx-version-min)/)) print "-"$i}'`" ++ if test $do64bit = yes; then : ++ ++ case `arch` in ++ ppc) ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch ppc64 flag" >&5 ++$as_echo_n "checking if compiler accepts -arch ppc64 flag... " >&6; } ++if ${tcl_cv_cc_arch_ppc64+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ++ hold_cflags=$CFLAGS ++ CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++int ++main () ++{ ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ tcl_cv_cc_arch_ppc64=yes ++else ++ tcl_cv_cc_arch_ppc64=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++ CFLAGS=$hold_cflags ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_ppc64" >&5 ++$as_echo "$tcl_cv_cc_arch_ppc64" >&6; } ++ if test $tcl_cv_cc_arch_ppc64 = yes; then : ++ ++ CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" ++ do64bit_ok=yes ++ ++fi;; ++ i386) ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch x86_64 flag" >&5 ++$as_echo_n "checking if compiler accepts -arch x86_64 flag... " >&6; } ++if ${tcl_cv_cc_arch_x86_64+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ++ hold_cflags=$CFLAGS ++ CFLAGS="$CFLAGS -arch x86_64" ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++int ++main () ++{ ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ tcl_cv_cc_arch_x86_64=yes ++else ++ tcl_cv_cc_arch_x86_64=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++ CFLAGS=$hold_cflags ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_x86_64" >&5 ++$as_echo "$tcl_cv_cc_arch_x86_64" >&6; } ++ if test $tcl_cv_cc_arch_x86_64 = yes; then : ++ ++ CFLAGS="$CFLAGS -arch x86_64" ++ do64bit_ok=yes ++ ++fi;; ++ *) ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&5 ++$as_echo "$as_me: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&2;};; ++ esac ++ ++else ++ ++ # Check for combined 32-bit and 64-bit fat build ++ if echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \ ++ && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '; then : ++ ++ fat_32_64=yes ++fi ++ ++fi ++ # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS ++ SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}' ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ld accepts -single_module flag" >&5 ++$as_echo_n "checking if ld accepts -single_module flag... " >&6; } ++if ${tcl_cv_ld_single_module+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ++ hold_ldflags=$LDFLAGS ++ LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module" ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++int ++main () ++{ ++int i; ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ tcl_cv_ld_single_module=yes ++else ++ tcl_cv_ld_single_module=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++ LDFLAGS=$hold_ldflags ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_single_module" >&5 ++$as_echo "$tcl_cv_ld_single_module" >&6; } ++ if test $tcl_cv_ld_single_module = yes; then : ++ ++ SHLIB_LD="${SHLIB_LD} -Wl,-single_module" ++ ++fi ++ # TEA specific: link shlib with current and compatibility version flags ++ vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\([0-9]\{1,5\}\)\(\(\.[0-9]\{1,3\}\)\{0,2\}\).*$/\1\2/p' -e d` ++ SHLIB_LD="${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}" ++ SHLIB_SUFFIX=".dylib" ++ # Don't use -prebind when building for Mac OS X 10.4 or later only: ++ if test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int($2)}'`" -lt 4 -a \ ++ "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int($2)}'`" -lt 4; then : ++ ++ LDFLAGS="$LDFLAGS -prebind" ++fi ++ LDFLAGS="$LDFLAGS -headerpad_max_install_names" ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ld accepts -search_paths_first flag" >&5 ++$as_echo_n "checking if ld accepts -search_paths_first flag... " >&6; } ++if ${tcl_cv_ld_search_paths_first+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ++ hold_ldflags=$LDFLAGS ++ LDFLAGS="$LDFLAGS -Wl,-search_paths_first" ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++int ++main () ++{ ++int i; ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ tcl_cv_ld_search_paths_first=yes ++else ++ tcl_cv_ld_search_paths_first=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++ LDFLAGS=$hold_ldflags ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_search_paths_first" >&5 ++$as_echo "$tcl_cv_ld_search_paths_first" >&6; } ++ if test $tcl_cv_ld_search_paths_first = yes; then : ++ ++ LDFLAGS="$LDFLAGS -Wl,-search_paths_first" ++ ++fi ++ if test "$tcl_cv_cc_visibility_hidden" != yes; then : ++ ++ ++$as_echo "#define MODULE_SCOPE __private_extern__" >>confdefs.h ++ ++ tcl_cv_cc_visibility_hidden=yes ++ ++fi ++ CC_SEARCH_FLAGS="" ++ LD_SEARCH_FLAGS="" ++ LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH" ++ # TEA specific: for combined 32 & 64 bit fat builds of Tk ++ # extensions, verify that 64-bit build is possible. ++ if test "$fat_32_64" = yes && test -n "${TK_BIN_DIR}"; then : ++ ++ if test "${TEA_WINDOWINGSYSTEM}" = x11; then : ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit X11" >&5 ++$as_echo_n "checking for 64-bit X11... " >&6; } ++if ${tcl_cv_lib_x11_64+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ++ for v in CFLAGS CPPFLAGS LDFLAGS; do ++ eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' ++ done ++ CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include" ++ LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11" ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <X11/Xlib.h> ++int ++main () ++{ ++XrmInitialize(); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ tcl_cv_lib_x11_64=yes ++else ++ tcl_cv_lib_x11_64=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++ for v in CFLAGS CPPFLAGS LDFLAGS; do ++ eval $v'="$hold_'$v'"' ++ done ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_x11_64" >&5 ++$as_echo "$tcl_cv_lib_x11_64" >&6; } ++ ++fi ++ if test "${TEA_WINDOWINGSYSTEM}" = aqua; then : ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit Tk" >&5 ++$as_echo_n "checking for 64-bit Tk... " >&6; } ++if ${tcl_cv_lib_tk_64+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ++ for v in CFLAGS CPPFLAGS LDFLAGS; do ++ eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' ++ done ++ CPPFLAGS="$CPPFLAGS -DUSE_TCL_STUBS=1 -DUSE_TK_STUBS=1 ${TCL_INCLUDES} ${TK_INCLUDES}" ++ LDFLAGS="$LDFLAGS ${TCL_STUB_LIB_SPEC} ${TK_STUB_LIB_SPEC}" ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <tk.h> ++int ++main () ++{ ++Tk_InitStubs(NULL, "", 0); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ tcl_cv_lib_tk_64=yes ++else ++ tcl_cv_lib_tk_64=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++ for v in CFLAGS CPPFLAGS LDFLAGS; do ++ eval $v'="$hold_'$v'"' ++ done ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_tk_64" >&5 ++$as_echo "$tcl_cv_lib_tk_64" >&6; } ++ ++fi ++ # remove 64-bit arch flags from CFLAGS et al. if configuration ++ # does not support 64-bit. ++ if test "$tcl_cv_lib_tk_64" = no -o "$tcl_cv_lib_x11_64" = no; then : ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: Removing 64-bit architectures from compiler & linker flags" >&5 ++$as_echo "$as_me: Removing 64-bit architectures from compiler & linker flags" >&6;} ++ for v in CFLAGS CPPFLAGS LDFLAGS; do ++ eval $v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"' ++ done ++fi ++ ++fi ++ ;; ++ OS/390-*) ++ CFLAGS_OPTIMIZE="" # Optimizer is buggy ++ ++$as_echo "#define _OE_SOCKETS 1" >>confdefs.h ++ ++ ;; ++ OSF1-V*) ++ # Digital OSF/1 ++ SHLIB_CFLAGS="" ++ if test "$SHARED_BUILD" = 1; then : ++ ++ SHLIB_LD='ld -shared -expect_unresolved "*"' ++ ++else ++ ++ SHLIB_LD='ld -non_shared -expect_unresolved "*"' ++ ++fi ++ SHLIB_SUFFIX=".so" ++ if test $doRpath = yes; then : ++ ++ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' ++ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' ++fi ++ if test "$GCC" = yes; then : ++ CFLAGS="$CFLAGS -mieee" ++else ++ ++ CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee" ++fi ++ # see pthread_intro(3) for pthread support on osf1, k.furukawa ++ if test "${TCL_THREADS}" = 1; then : ++ ++ CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE" ++ CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64" ++ LIBS=`echo $LIBS | sed s/-lpthreads//` ++ if test "$GCC" = yes; then : ++ ++ LIBS="$LIBS -lpthread -lmach -lexc" ++ ++else ++ ++ CFLAGS="$CFLAGS -pthread" ++ LDFLAGS="$LDFLAGS -pthread" ++ ++fi ++ ++fi ++ ;; ++ QNX-6*) ++ # QNX RTP ++ # This may work for all QNX, but it was only reported for v6. ++ SHLIB_CFLAGS="-fPIC" ++ SHLIB_LD="ld -Bshareable -x" ++ SHLIB_LD_LIBS="" ++ SHLIB_SUFFIX=".so" ++ CC_SEARCH_FLAGS="" ++ LD_SEARCH_FLAGS="" ++ ;; ++ SCO_SV-3.2*) ++ if test "$GCC" = yes; then : ++ ++ SHLIB_CFLAGS="-fPIC -melf" ++ LDFLAGS="$LDFLAGS -melf -Wl,-Bexport" ++ ++else ++ ++ SHLIB_CFLAGS="-Kpic -belf" ++ LDFLAGS="$LDFLAGS -belf -Wl,-Bexport" ++ ++fi ++ SHLIB_LD="ld -G" ++ SHLIB_LD_LIBS="" ++ SHLIB_SUFFIX=".so" ++ CC_SEARCH_FLAGS="" ++ LD_SEARCH_FLAGS="" ++ ;; ++ SunOS-5.[0-6]) ++ # Careful to not let 5.10+ fall into this case ++ ++ # Note: If _REENTRANT isn't defined, then Solaris ++ # won't define thread-safe library routines. ++ ++ ++$as_echo "#define _REENTRANT 1" >>confdefs.h ++ ++ ++$as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h ++ ++ ++ SHLIB_CFLAGS="-KPIC" ++ SHLIB_SUFFIX=".so" ++ if test "$GCC" = yes; then : ++ ++ SHLIB_LD='${CC} -shared' ++ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' ++ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ++ ++else ++ ++ SHLIB_LD="/usr/ccs/bin/ld -G -z text" ++ CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' ++ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ++ ++fi ++ ;; ++ SunOS-5*) ++ # Note: If _REENTRANT isn't defined, then Solaris ++ # won't define thread-safe library routines. ++ ++ ++$as_echo "#define _REENTRANT 1" >>confdefs.h ++ ++ ++$as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h ++ ++ ++ SHLIB_CFLAGS="-KPIC" ++ ++ # Check to enable 64-bit flags for compiler/linker ++ if test "$do64bit" = yes; then : ++ ++ arch=`isainfo` ++ if test "$arch" = "sparcv9 sparc"; then : ++ ++ if test "$GCC" = yes; then : ++ ++ if test "`${CC} -dumpversion | awk -F. '{print $1}'`" -lt 3; then : ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&5 ++$as_echo "$as_me: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&2;} ++ ++else ++ ++ do64bit_ok=yes ++ CFLAGS="$CFLAGS -m64 -mcpu=v9" ++ LDFLAGS="$LDFLAGS -m64 -mcpu=v9" ++ SHLIB_CFLAGS="-fPIC" ++ ++fi ++ ++else ++ ++ do64bit_ok=yes ++ if test "$do64bitVIS" = yes; then : ++ ++ CFLAGS="$CFLAGS -xarch=v9a" ++ LDFLAGS_ARCH="-xarch=v9a" ++ ++else ++ ++ CFLAGS="$CFLAGS -xarch=v9" ++ LDFLAGS_ARCH="-xarch=v9" ++ ++fi ++ # Solaris 64 uses this as well ++ #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64" ++ ++fi ++ ++else ++ if test "$arch" = "amd64 i386"; then : ++ ++ if test "$GCC" = yes; then : ++ ++ case $system in ++ SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*) ++ do64bit_ok=yes ++ CFLAGS="$CFLAGS -m64" ++ LDFLAGS="$LDFLAGS -m64";; ++ *) ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 ++$as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;};; ++ esac ++ ++else ++ ++ do64bit_ok=yes ++ case $system in ++ SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*) ++ CFLAGS="$CFLAGS -m64" ++ LDFLAGS="$LDFLAGS -m64";; ++ *) ++ CFLAGS="$CFLAGS -xarch=amd64" ++ LDFLAGS="$LDFLAGS -xarch=amd64";; ++ esac ++ ++fi ++ ++else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported for $arch" >&5 ++$as_echo "$as_me: WARNING: 64bit mode not supported for $arch" >&2;} ++fi ++fi ++ ++fi ++ ++ SHLIB_SUFFIX=".so" ++ if test "$GCC" = yes; then : ++ ++ SHLIB_LD='${CC} -shared' ++ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' ++ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ++ if test "$do64bit_ok" = yes; then : ++ ++ if test "$arch" = "sparcv9 sparc"; then : ++ ++ # We need to specify -static-libgcc or we need to ++ # add the path to the sparv9 libgcc. ++ # JH: static-libgcc is necessary for core Tcl, but may ++ # not be necessary for extensions. ++ SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc" ++ # for finding sparcv9 libgcc, get the regular libgcc ++ # path, remove so name and append 'sparcv9' ++ #v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..." ++ #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir" ++ ++else ++ if test "$arch" = "amd64 i386"; then : ++ ++ # JH: static-libgcc is necessary for core Tcl, but may ++ # not be necessary for extensions. ++ SHLIB_LD="$SHLIB_LD -m64 -static-libgcc" ++ ++fi ++fi ++ ++fi ++ ++else ++ ++ case $system in ++ SunOS-5.[1-9][0-9]*) ++ # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS ++ SHLIB_LD='${CC} -G -z text ${LDFLAGS_DEFAULT}';; ++ *) ++ SHLIB_LD='/usr/ccs/bin/ld -G -z text';; ++ esac ++ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' ++ LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' ++ ++fi ++ ;; ++ UNIX_SV* | UnixWare-5*) ++ SHLIB_CFLAGS="-KPIC" ++ SHLIB_LD='${CC} -G' ++ SHLIB_LD_LIBS="" ++ SHLIB_SUFFIX=".so" ++ # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers ++ # that don't grok the -Bexport option. Test that it does. ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld accepts -Bexport flag" >&5 ++$as_echo_n "checking for ld accepts -Bexport flag... " >&6; } ++if ${tcl_cv_ld_Bexport+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ++ hold_ldflags=$LDFLAGS ++ LDFLAGS="$LDFLAGS -Wl,-Bexport" ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++int ++main () ++{ ++int i; ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ tcl_cv_ld_Bexport=yes ++else ++ tcl_cv_ld_Bexport=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++ LDFLAGS=$hold_ldflags ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_Bexport" >&5 ++$as_echo "$tcl_cv_ld_Bexport" >&6; } ++ if test $tcl_cv_ld_Bexport = yes; then : ++ ++ LDFLAGS="$LDFLAGS -Wl,-Bexport" ++ ++fi ++ CC_SEARCH_FLAGS="" ++ LD_SEARCH_FLAGS="" ++ ;; ++ esac ++ ++ if test "$do64bit" = yes -a "$do64bit_ok" = no; then : ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit support being disabled -- don't know magic for this platform" >&5 ++$as_echo "$as_me: WARNING: 64bit support being disabled -- don't know magic for this platform" >&2;} ++ ++fi ++ ++ ++ ++ # Add in the arch flags late to ensure it wasn't removed. ++ # Not necessary in TEA, but this is aligned with core ++ LDFLAGS="$LDFLAGS $LDFLAGS_ARCH" ++ ++ # If we're running gcc, then change the C flags for compiling shared ++ # libraries to the right flags for gcc, instead of those for the ++ # standard manufacturer compiler. ++ ++ if test "$GCC" = yes; then : ++ ++ case $system in ++ AIX-*) ;; ++ BSD/OS*) ;; ++ CYGWIN_*|MINGW32_*) ;; ++ IRIX*) ;; ++ NetBSD-*|FreeBSD-*|OpenBSD-*) ;; ++ Darwin-*) ;; ++ SCO_SV-3.2*) ;; ++ windows) ;; ++ *) SHLIB_CFLAGS="-fPIC" ;; ++ esac ++fi ++ ++ if test "$tcl_cv_cc_visibility_hidden" != yes; then : ++ ++ ++$as_echo "#define MODULE_SCOPE extern" >>confdefs.h ++ ++ ++fi ++ ++ if test "$SHARED_LIB_SUFFIX" = ""; then : ++ ++ # TEA specific: use PACKAGE_VERSION instead of VERSION ++ SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}' ++fi ++ if test "$UNSHARED_LIB_SUFFIX" = ""; then : ++ ++ # TEA specific: use PACKAGE_VERSION instead of VERSION ++ UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a' ++fi ++ ++ if test "${GCC}" = "yes" -a ${SHLIB_SUFFIX} = ".dll"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SEH support in compiler" >&5 ++$as_echo_n "checking for SEH support in compiler... " >&6; } ++if ${tcl_cv_seh+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ if test "$cross_compiling" = yes; then : ++ tcl_cv_seh=no ++else ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++#define WIN32_LEAN_AND_MEAN ++#include <windows.h> ++#undef WIN32_LEAN_AND_MEAN ++ ++ int main(int argc, char** argv) { ++ int a, b = 0; ++ __try { ++ a = 666 / b; ++ } ++ __except (EXCEPTION_EXECUTE_HANDLER) { ++ return 0; ++ } ++ return 1; ++ } ++ ++_ACEOF ++if ac_fn_c_try_run "$LINENO"; then : ++ tcl_cv_seh=yes ++else ++ tcl_cv_seh=no ++fi ++rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ ++ conftest.$ac_objext conftest.beam conftest.$ac_ext ++fi ++ ++ ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_seh" >&5 ++$as_echo "$tcl_cv_seh" >&6; } ++ if test "$tcl_cv_seh" = "no" ; then ++ ++$as_echo "#define HAVE_NO_SEH 1" >>confdefs.h ++ ++ fi ++ ++ # ++ # Check to see if the excpt.h include file provided contains the ++ # definition for EXCEPTION_DISPOSITION; if not, which is the case ++ # with Cygwin's version as of 2002-04-10, define it to be int, ++ # sufficient for getting the current code to work. ++ # ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EXCEPTION_DISPOSITION support in include files" >&5 ++$as_echo_n "checking for EXCEPTION_DISPOSITION support in include files... " >&6; } ++if ${tcl_cv_eh_disposition+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++# define WIN32_LEAN_AND_MEAN ++# include <windows.h> ++# undef WIN32_LEAN_AND_MEAN ++ ++int ++main () ++{ ++ ++ EXCEPTION_DISPOSITION x; ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ tcl_cv_eh_disposition=yes ++else ++ tcl_cv_eh_disposition=no ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++ ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_eh_disposition" >&5 ++$as_echo "$tcl_cv_eh_disposition" >&6; } ++ if test "$tcl_cv_eh_disposition" = "no" ; then ++ ++$as_echo "#define EXCEPTION_DISPOSITION int" >>confdefs.h ++ ++ fi ++ ++ # Check to see if winnt.h defines CHAR, SHORT, and LONG ++ # even if VOID has already been #defined. The win32api ++ # used by mingw and cygwin is known to do this. ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for winnt.h that ignores VOID define" >&5 ++$as_echo_n "checking for winnt.h that ignores VOID define... " >&6; } ++if ${tcl_cv_winnt_ignore_void+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++#define VOID void ++#define WIN32_LEAN_AND_MEAN ++#include <windows.h> ++#undef WIN32_LEAN_AND_MEAN ++ ++int ++main () ++{ ++ ++ CHAR c; ++ SHORT s; ++ LONG l; ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ tcl_cv_winnt_ignore_void=yes ++else ++ tcl_cv_winnt_ignore_void=no ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++ ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_winnt_ignore_void" >&5 ++$as_echo "$tcl_cv_winnt_ignore_void" >&6; } ++ if test "$tcl_cv_winnt_ignore_void" = "yes" ; then ++ ++$as_echo "#define HAVE_WINNT_IGNORE_VOID 1" >>confdefs.h ++ ++ fi ++ fi ++ ++ # See if the compiler supports casting to a union type. ++ # This is used to stop gcc from printing a compiler ++ # warning when initializing a union member. ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cast to union support" >&5 ++$as_echo_n "checking for cast to union support... " >&6; } ++if ${tcl_cv_cast_to_union+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++int ++main () ++{ ++ ++ union foo { int i; double d; }; ++ union foo f = (union foo) (int) 0; ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ tcl_cv_cast_to_union=yes ++else ++ tcl_cv_cast_to_union=no ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++ ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cast_to_union" >&5 ++$as_echo "$tcl_cv_cast_to_union" >&6; } ++ if test "$tcl_cv_cast_to_union" = "yes"; then ++ ++$as_echo "#define HAVE_CAST_TO_UNION 1" >>confdefs.h ++ ++ fi ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ # These must be called after we do the basic CFLAGS checks and ++ # verify any possible 64-bit or similar switches are necessary ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for required early compiler flags" >&5 ++$as_echo_n "checking for required early compiler flags... " >&6; } ++ tcl_flags="" ++ ++ if ${tcl_cv_flag__isoc99_source+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <stdlib.h> ++int ++main () ++{ ++char *p = (char *)strtoll; char *q = (char *)strtoull; ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ tcl_cv_flag__isoc99_source=no ++else ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#define _ISOC99_SOURCE 1 ++#include <stdlib.h> ++int ++main () ++{ ++char *p = (char *)strtoll; char *q = (char *)strtoull; ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ tcl_cv_flag__isoc99_source=yes ++else ++ tcl_cv_flag__isoc99_source=no ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++fi ++ ++ if test "x${tcl_cv_flag__isoc99_source}" = "xyes" ; then ++ ++$as_echo "#define _ISOC99_SOURCE 1" >>confdefs.h ++ ++ tcl_flags="$tcl_flags _ISOC99_SOURCE" ++ fi ++ ++ ++ if ${tcl_cv_flag__largefile64_source+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <sys/stat.h> ++int ++main () ++{ ++struct stat64 buf; int i = stat64("/", &buf); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ tcl_cv_flag__largefile64_source=no ++else ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#define _LARGEFILE64_SOURCE 1 ++#include <sys/stat.h> ++int ++main () ++{ ++struct stat64 buf; int i = stat64("/", &buf); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ tcl_cv_flag__largefile64_source=yes ++else ++ tcl_cv_flag__largefile64_source=no ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++fi ++ ++ if test "x${tcl_cv_flag__largefile64_source}" = "xyes" ; then ++ ++$as_echo "#define _LARGEFILE64_SOURCE 1" >>confdefs.h ++ ++ tcl_flags="$tcl_flags _LARGEFILE64_SOURCE" ++ fi ++ ++ ++ if ${tcl_cv_flag__largefile_source64+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <sys/stat.h> ++int ++main () ++{ ++char *p = (char *)open64; ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ tcl_cv_flag__largefile_source64=no ++else ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#define _LARGEFILE_SOURCE64 1 ++#include <sys/stat.h> ++int ++main () ++{ ++char *p = (char *)open64; ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ tcl_cv_flag__largefile_source64=yes ++else ++ tcl_cv_flag__largefile_source64=no ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++fi ++ ++ if test "x${tcl_cv_flag__largefile_source64}" = "xyes" ; then ++ ++$as_echo "#define _LARGEFILE_SOURCE64 1" >>confdefs.h ++ ++ tcl_flags="$tcl_flags _LARGEFILE_SOURCE64" ++ fi ++ ++ if test "x${tcl_flags}" = "x" ; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 ++$as_echo "none" >&6; } ++ else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${tcl_flags}" >&5 ++$as_echo "${tcl_flags}" >&6; } ++ fi ++ ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit integer type" >&5 ++$as_echo_n "checking for 64-bit integer type... " >&6; } ++ if ${tcl_cv_type_64bit+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ++ tcl_cv_type_64bit=none ++ # See if the compiler knows natively about __int64 ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++int ++main () ++{ ++__int64 value = (__int64) 0; ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ tcl_type_64bit=__int64 ++else ++ tcl_type_64bit="long long" ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++ # See if we should use long anyway Note that we substitute in the ++ # type that is our current guess for a 64-bit type inside this check ++ # program, so it should be modified only carefully... ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++int ++main () ++{ ++switch (0) { ++ case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ; ++ } ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ tcl_cv_type_64bit=${tcl_type_64bit} ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++fi ++ ++ if test "${tcl_cv_type_64bit}" = none ; then ++ ++$as_echo "#define TCL_WIDE_INT_IS_LONG 1" >>confdefs.h ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: using long" >&5 ++$as_echo "using long" >&6; } ++ elif test "${tcl_cv_type_64bit}" = "__int64" \ ++ -a "${TEA_PLATFORM}" = "windows" ; then ++ # TEA specific: We actually want to use the default tcl.h checks in ++ # this case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER* ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: using Tcl header defaults" >&5 ++$as_echo "using Tcl header defaults" >&6; } ++ else ++ ++cat >>confdefs.h <<_ACEOF ++#define TCL_WIDE_INT_TYPE ${tcl_cv_type_64bit} ++_ACEOF ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${tcl_cv_type_64bit}" >&5 ++$as_echo "${tcl_cv_type_64bit}" >&6; } ++ ++ # Now check for auxiliary declarations ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct dirent64" >&5 ++$as_echo_n "checking for struct dirent64... " >&6; } ++if ${tcl_cv_struct_dirent64+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <sys/types.h> ++#include <dirent.h> ++int ++main () ++{ ++struct dirent64 p; ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ tcl_cv_struct_dirent64=yes ++else ++ tcl_cv_struct_dirent64=no ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_dirent64" >&5 ++$as_echo "$tcl_cv_struct_dirent64" >&6; } ++ if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then ++ ++$as_echo "#define HAVE_STRUCT_DIRENT64 1" >>confdefs.h ++ ++ fi ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct stat64" >&5 ++$as_echo_n "checking for struct stat64... " >&6; } ++if ${tcl_cv_struct_stat64+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <sys/stat.h> ++int ++main () ++{ ++struct stat64 p; ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ tcl_cv_struct_stat64=yes ++else ++ tcl_cv_struct_stat64=no ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_stat64" >&5 ++$as_echo "$tcl_cv_struct_stat64" >&6; } ++ if test "x${tcl_cv_struct_stat64}" = "xyes" ; then ++ ++$as_echo "#define HAVE_STRUCT_STAT64 1" >>confdefs.h ++ ++ fi ++ ++ for ac_func in open64 lseek64 ++do : ++ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ++ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" ++if eval test \"x\$"$as_ac_var"\" = x"yes"; then : ++ cat >>confdefs.h <<_ACEOF ++#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 ++_ACEOF ++ ++fi ++done ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for off64_t" >&5 ++$as_echo_n "checking for off64_t... " >&6; } ++ if ${tcl_cv_type_off64_t+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#include <sys/types.h> ++int ++main () ++{ ++off64_t offset; ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ tcl_cv_type_off64_t=yes ++else ++ tcl_cv_type_off64_t=no ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++fi ++ ++ if test "x${tcl_cv_type_off64_t}" = "xyes" && \ ++ test "x${ac_cv_func_lseek64}" = "xyes" && \ ++ test "x${ac_cv_func_open64}" = "xyes" ; then ++ ++$as_echo "#define HAVE_TYPE_OFF64_T 1" >>confdefs.h ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 ++$as_echo "yes" >&6; } ++ else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++ fi ++ fi ++ ++ ++ ++#-------------------------------------------------------------------- ++# Set the default compiler switches based on the --enable-symbols option. ++#-------------------------------------------------------------------- ++ ++ ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for build with symbols" >&5 ++$as_echo_n "checking for build with symbols... " >&6; } ++ # Check whether --enable-symbols was given. ++if test "${enable_symbols+set}" = set; then : ++ enableval=$enable_symbols; tcl_ok=$enableval ++else ++ tcl_ok=no ++fi ++ ++ DBGX="" ++ if test "$tcl_ok" = "no"; then ++ CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE} -DNDEBUG" ++ LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}" ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++ else ++ CFLAGS_DEFAULT="${CFLAGS_DEBUG}" ++ LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}" ++ if test "$tcl_ok" = "yes"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (standard debugging)" >&5 ++$as_echo "yes (standard debugging)" >&6; } ++ fi ++ fi ++ # TEA specific: ++ if test "${TEA_PLATFORM}" != "windows" ; then ++ LDFLAGS_DEFAULT="${LDFLAGS}" ++ fi ++ ++ ++ ++ ++ if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then ++ ++$as_echo "#define TCL_MEM_DEBUG 1" >>confdefs.h ++ ++ fi ++ ++ if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then ++ if test "$tcl_ok" = "all"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled symbols mem debugging" >&5 ++$as_echo "enabled symbols mem debugging" >&6; } ++ else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled $tcl_ok debugging" >&5 ++$as_echo "enabled $tcl_ok debugging" >&6; } ++ fi ++ fi ++ ++ ++#-------------------------------------------------------------------- ++# Everyone should be linking against the Tcl stub library. If you ++# can't for some reason, remove this definition. If you aren't using ++# stubs, you also need to modify the SHLIB_LD_LIBS setting below to ++# link against the non-stubbed Tcl library. Add Tk too if necessary. ++#-------------------------------------------------------------------- ++ ++ ++$as_echo "#define USE_TCL_STUBS 1" >>confdefs.h ++ ++#AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs]) ++ ++ ++#-------------------------------------------------------------------- ++# Redefine fdatasync as fsync on systems that lack fdatasync ++#-------------------------------------------------------------------- ++# ++#AC_CHECK_FUNC(fdatasync, , AC_DEFINE(fdatasync, fsync)) ++# Check for library functions that SQLite can optionally use. ++for ac_func in fdatasync usleep fullfsync localtime_r gmtime_r ++do : ++ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ++ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" ++if eval test \"x\$"$as_ac_var"\" = x"yes"; then : ++ cat >>confdefs.h <<_ACEOF ++#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 ++_ACEOF ++ ++fi ++done ++ ++ ++ac_fn_c_check_decl "$LINENO" "strerror_r" "ac_cv_have_decl_strerror_r" "$ac_includes_default" ++if test "x$ac_cv_have_decl_strerror_r" = xyes; then : ++ ac_have_decl=1 ++else ++ ac_have_decl=0 ++fi ++ ++cat >>confdefs.h <<_ACEOF ++#define HAVE_DECL_STRERROR_R $ac_have_decl ++_ACEOF ++ ++for ac_func in strerror_r ++do : ++ ac_fn_c_check_func "$LINENO" "strerror_r" "ac_cv_func_strerror_r" ++if test "x$ac_cv_func_strerror_r" = xyes; then : ++ cat >>confdefs.h <<_ACEOF ++#define HAVE_STRERROR_R 1 ++_ACEOF ++ ++fi ++done ++ ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether strerror_r returns char *" >&5 ++$as_echo_n "checking whether strerror_r returns char *... " >&6; } ++if ${ac_cv_func_strerror_r_char_p+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ++ ac_cv_func_strerror_r_char_p=no ++ if test $ac_cv_have_decl_strerror_r = yes; then ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++$ac_includes_default ++int ++main () ++{ ++ ++ char buf[100]; ++ char x = *strerror_r (0, buf, sizeof buf); ++ char *p = strerror_r (0, buf, sizeof buf); ++ return !p || x; ++ ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ ac_cv_func_strerror_r_char_p=yes ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++ else ++ # strerror_r is not declared. Choose between ++ # systems that have relatively inaccessible declarations for the ++ # function. BeOS and DEC UNIX 4.0 fall in this category, but the ++ # former has a strerror_r that returns char*, while the latter ++ # has a strerror_r that returns `int'. ++ # This test should segfault on the DEC system. ++ if test "$cross_compiling" = yes; then : ++ : ++else ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++$ac_includes_default ++ extern char *strerror_r (); ++int ++main () ++{ ++char buf[100]; ++ char x = *strerror_r (0, buf, sizeof buf); ++ return ! isalpha (x); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_run "$LINENO"; then : ++ ac_cv_func_strerror_r_char_p=yes ++fi ++rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ ++ conftest.$ac_objext conftest.beam conftest.$ac_ext ++fi ++ ++ fi ++ ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_strerror_r_char_p" >&5 ++$as_echo "$ac_cv_func_strerror_r_char_p" >&6; } ++if test $ac_cv_func_strerror_r_char_p = yes; then ++ ++$as_echo "#define STRERROR_R_CHAR_P 1" >>confdefs.h ++ ++fi ++ ++ ++ ++#-------------------------------------------------------------------- ++# This macro generates a line to use when building a library. It ++# depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS, ++# and TEA_LOAD_TCLCONFIG macros above. ++#-------------------------------------------------------------------- ++ ++ ++ if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then ++ MAKE_STATIC_LIB="\${STLIB_LD} -out:\$@ \$(PKG_OBJECTS)" ++ MAKE_SHARED_LIB="\${SHLIB_LD} \${SHLIB_LD_LIBS} \${LDFLAGS_DEFAULT} -out:\$@ \$(PKG_OBJECTS)" ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++#if defined(_MSC_VER) && _MSC_VER >= 1400 ++print("manifest needed") ++#endif ++ ++_ACEOF ++if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | ++ $EGREP "manifest needed" >/dev/null 2>&1; then : ++ ++ # Could do a CHECK_PROG for mt, but should always be with MSVC8+ ++ VC_MANIFEST_EMBED_DLL="if test -f \$@.manifest ; then mt.exe -nologo -manifest \$@.manifest -outputresource:\$@\;2 ; fi" ++ VC_MANIFEST_EMBED_EXE="if test -f \$@.manifest ; then mt.exe -nologo -manifest \$@.manifest -outputresource:\$@\;1 ; fi" ++ MAKE_SHARED_LIB="${MAKE_SHARED_LIB} ; ${VC_MANIFEST_EMBED_DLL}" ++ ++ CLEANFILES="$CLEANFILES *.manifest" ++ ++ ++fi ++rm -f conftest* ++ ++ MAKE_STUB_LIB="\${STLIB_LD} -nodefaultlib -out:\$@ \$(PKG_STUB_OBJECTS)" ++ else ++ MAKE_STATIC_LIB="\${STLIB_LD} \$@ \$(PKG_OBJECTS)" ++ MAKE_SHARED_LIB="\${SHLIB_LD} -o \$@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}" ++ MAKE_STUB_LIB="\${STLIB_LD} \$@ \$(PKG_STUB_OBJECTS)" ++ fi ++ ++ if test "${SHARED_BUILD}" = "1" ; then ++ MAKE_LIB="${MAKE_SHARED_LIB} " ++ else ++ MAKE_LIB="${MAKE_STATIC_LIB} " ++ fi ++ ++ #-------------------------------------------------------------------- ++ # Shared libraries and static libraries have different names. ++ # Use the double eval to make sure any variables in the suffix is ++ # substituted. (@@@ Might not be necessary anymore) ++ #-------------------------------------------------------------------- ++ ++ if test "${TEA_PLATFORM}" = "windows" ; then ++ if test "${SHARED_BUILD}" = "1" ; then ++ # We force the unresolved linking of symbols that are really in ++ # the private libraries of Tcl and Tk. ++ if test x"${TK_BIN_DIR}" != x ; then ++ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\"" ++ fi ++ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\"" ++ if test "$GCC" = "yes"; then ++ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -static-libgcc" ++ fi ++ eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" ++ else ++ eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" ++ if test "$GCC" = "yes"; then ++ PKG_LIB_FILE=lib${PKG_LIB_FILE} ++ fi ++ fi ++ # Some packages build their own stubs libraries ++ eval eval "PKG_STUB_LIB_FILE=${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" ++ if test "$GCC" = "yes"; then ++ PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE} ++ fi ++ # These aren't needed on Windows (either MSVC or gcc) ++ RANLIB=: ++ RANLIB_STUB=: ++ else ++ RANLIB_STUB="${RANLIB}" ++ if test "${SHARED_BUILD}" = "1" ; then ++ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}" ++ if test x"${TK_BIN_DIR}" != x ; then ++ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}" ++ fi ++ eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" ++ RANLIB=: ++ else ++ eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" ++ fi ++ # Some packages build their own stubs libraries ++ eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" ++ fi ++ ++ # These are escaped so that only CFLAGS is picked up at configure time. ++ # The other values will be substituted at make time. ++ CFLAGS="${CFLAGS} \${CFLAGS_DEFAULT} \${CFLAGS_WARNING}" ++ if test "${SHARED_BUILD}" = "1" ; then ++ CFLAGS="${CFLAGS} \${SHLIB_CFLAGS}" ++ fi ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++#-------------------------------------------------------------------- ++# Determine the name of the tclsh and/or wish executables in the ++# Tcl and Tk build directories or the location they were installed ++# into. These paths are used to support running test cases only, ++# the Makefile should not be making use of these paths to generate ++# a pkgIndex.tcl file or anything else at extension build time. ++#-------------------------------------------------------------------- ++ ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tclsh" >&5 ++$as_echo_n "checking for tclsh... " >&6; } ++ if test -f "${TCL_BIN_DIR}/Makefile" ; then ++ # tclConfig.sh is in Tcl build directory ++ if test "${TEA_PLATFORM}" = "windows"; then ++ TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" ++ else ++ TCLSH_PROG="${TCL_BIN_DIR}/tclsh" ++ fi ++ else ++ # tclConfig.sh is in install location ++ if test "${TEA_PLATFORM}" = "windows"; then ++ TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" ++ else ++ TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_DBGX}" ++ fi ++ list="`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \ ++ `ls -d ${TCL_BIN_DIR}/.. 2>/dev/null` \ ++ `ls -d ${TCL_PREFIX}/bin 2>/dev/null`" ++ for i in $list ; do ++ if test -f "$i/${TCLSH_PROG}" ; then ++ REAL_TCL_BIN_DIR="`cd "$i"; pwd`/" ++ break ++ fi ++ done ++ TCLSH_PROG="${REAL_TCL_BIN_DIR}${TCLSH_PROG}" ++ fi ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${TCLSH_PROG}" >&5 ++$as_echo "${TCLSH_PROG}" >&6; } ++ ++ ++#TEA_PROG_WISH ++ ++#-------------------------------------------------------------------- ++# Finally, substitute all of the various values into the Makefile. ++# You may alternatively have a special pkgIndex.tcl.in or other files ++# which require substituting th AC variables in. Include these here. ++#-------------------------------------------------------------------- ++ ++ac_config_files="$ac_config_files Makefile pkgIndex.tcl" ++ ++cat >confcache <<\_ACEOF ++# This file is a shell script that caches the results of configure ++# tests run on this system so they can be shared between configure ++# scripts and configure runs, see configure's option --config-cache. ++# It is not useful on other systems. If it contains results you don't ++# want to keep, you may remove or edit it. ++# ++# config.status only pays attention to the cache file if you give it ++# the --recheck option to rerun configure. ++# ++# `ac_cv_env_foo' variables (set or unset) will be overridden when ++# loading this file, other *unset* `ac_cv_foo' will be assigned the ++# following values. ++ ++_ACEOF ++ ++# The following way of writing the cache mishandles newlines in values, ++# but we know of no workaround that is simple, portable, and efficient. ++# So, we kill variables containing newlines. ++# Ultrix sh set writes to stderr and can't be redirected directly, ++# and sets the high bit in the cache file unless we assign to the vars. ++( ++ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do ++ eval ac_val=\$$ac_var ++ case $ac_val in #( ++ *${as_nl}*) ++ case $ac_var in #( ++ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 ++$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; ++ esac ++ case $ac_var in #( ++ _ | IFS | as_nl) ;; #( ++ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( ++ *) { eval $ac_var=; unset $ac_var;} ;; ++ esac ;; ++ esac ++ done ++ ++ (set) 2>&1 | ++ case $as_nl`(ac_space=' '; set) 2>&1` in #( ++ *${as_nl}ac_space=\ *) ++ # `set' does not quote correctly, so add quotes: double-quote ++ # substitution turns \\\\ into \\, and sed turns \\ into \. ++ sed -n \ ++ "s/'/'\\\\''/g; ++ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ++ ;; #( ++ *) ++ # `set' quotes correctly as required by POSIX, so do not add quotes. ++ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ++ ;; ++ esac | ++ sort ++) | ++ sed ' ++ /^ac_cv_env_/b end ++ t clear ++ :clear ++ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ ++ t end ++ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ ++ :end' >>confcache ++if diff "$cache_file" confcache >/dev/null 2>&1; then :; else ++ if test -w "$cache_file"; then ++ if test "x$cache_file" != "x/dev/null"; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 ++$as_echo "$as_me: updating cache $cache_file" >&6;} ++ if test ! -f "$cache_file" || test -h "$cache_file"; then ++ cat confcache >"$cache_file" ++ else ++ case $cache_file in #( ++ */* | ?:*) ++ mv -f confcache "$cache_file"$$ && ++ mv -f "$cache_file"$$ "$cache_file" ;; #( ++ *) ++ mv -f confcache "$cache_file" ;; ++ esac ++ fi ++ fi ++ else ++ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 ++$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} ++ fi ++fi ++rm -f confcache ++ ++test "x$prefix" = xNONE && prefix=$ac_default_prefix ++# Let make expand exec_prefix. ++test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' ++ ++# Transform confdefs.h into DEFS. ++# Protect against shell expansion while executing Makefile rules. ++# Protect against Makefile macro expansion. ++# ++# If the first sed substitution is executed (which looks for macros that ++# take arguments), then branch to the quote section. Otherwise, ++# look for a macro that doesn't take arguments. ++ac_script=' ++:mline ++/\\$/{ ++ N ++ s,\\\n,, ++ b mline ++} ++t clear ++:clear ++s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g ++t quote ++s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g ++t quote ++b any ++:quote ++s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g ++s/\[/\\&/g ++s/\]/\\&/g ++s/\$/$$/g ++H ++:any ++${ ++ g ++ s/^\n// ++ s/\n/ /g ++ p ++} ++' ++DEFS=`sed -n "$ac_script" confdefs.h` ++ ++ ++ac_libobjs= ++ac_ltlibobjs= ++U= ++for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue ++ # 1. Remove the extension, and $U if already installed. ++ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ++ ac_i=`$as_echo "$ac_i" | sed "$ac_script"` ++ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR ++ # will be set to the directory where LIBOBJS objects are built. ++ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" ++ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' ++done ++LIBOBJS=$ac_libobjs ++ ++LTLIBOBJS=$ac_ltlibobjs ++ ++ ++ ++CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS="" ++ ++: "${CONFIG_STATUS=./config.status}" ++ac_write_fail=0 ++ac_clean_files_save=$ac_clean_files ++ac_clean_files="$ac_clean_files $CONFIG_STATUS" ++{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 ++$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} ++as_write_fail=0 ++cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 ++#! $SHELL ++# Generated by $as_me. ++# Run this file to recreate the current configuration. ++# Compiler output produced by configure, useful for debugging ++# configure, is in config.log if it exists. ++ ++debug=false ++ac_cs_recheck=false ++ac_cs_silent=false ++ ++SHELL=\${CONFIG_SHELL-$SHELL} ++export SHELL ++_ASEOF ++cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ++## -------------------- ## ++## M4sh Initialization. ## ++## -------------------- ## ++ ++# Be more Bourne compatible ++DUALCASE=1; export DUALCASE # for MKS sh ++if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : ++ emulate sh ++ NULLCMD=: ++ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which ++ # is contrary to our usage. Disable this feature. ++ alias -g '${1+"$@"}'='"$@"' ++ setopt NO_GLOB_SUBST ++else ++ case `(set -o) 2>/dev/null` in #( ++ *posix*) : ++ set -o posix ;; #( ++ *) : ++ ;; ++esac ++fi ++ ++ ++as_nl=' ++' ++export as_nl ++# Printing a long string crashes Solaris 7 /usr/bin/printf. ++as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ++as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo ++as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo ++# Prefer a ksh shell builtin over an external printf program on Solaris, ++# but without wasting forks for bash or zsh. ++if test -z "$BASH_VERSION$ZSH_VERSION" \ ++ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then ++ as_echo='print -r --' ++ as_echo_n='print -rn --' ++elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then ++ as_echo='printf %s\n' ++ as_echo_n='printf %s' ++else ++ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then ++ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' ++ as_echo_n='/usr/ucb/echo -n' ++ else ++ as_echo_body='eval expr "X$1" : "X\\(.*\\)"' ++ as_echo_n_body='eval ++ arg=$1; ++ case $arg in #( ++ *"$as_nl"*) ++ expr "X$arg" : "X\\(.*\\)$as_nl"; ++ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; ++ esac; ++ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ++ ' ++ export as_echo_n_body ++ as_echo_n='sh -c $as_echo_n_body as_echo' ++ fi ++ export as_echo_body ++ as_echo='sh -c $as_echo_body as_echo' ++fi ++ ++# The user is always right. ++if test "${PATH_SEPARATOR+set}" != set; then ++ PATH_SEPARATOR=: ++ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { ++ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || ++ PATH_SEPARATOR=';' ++ } ++fi ++ ++ ++# IFS ++# We need space, tab and new line, in precisely that order. Quoting is ++# there to prevent editors from complaining about space-tab. ++# (If _AS_PATH_WALK were called with IFS unset, it would disable word ++# splitting by setting IFS to empty value.) ++IFS=" "" $as_nl" ++ ++# Find who we are. Look in the path if we contain no directory separator. ++as_myself= ++case $0 in #(( ++ *[\\/]* ) as_myself=$0 ;; ++ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break ++ done ++IFS=$as_save_IFS ++ ++ ;; ++esac ++# We did not find ourselves, most probably we were run as `sh COMMAND' ++# in which case we are not to be found in the path. ++if test "x$as_myself" = x; then ++ as_myself=$0 ++fi ++if test ! -f "$as_myself"; then ++ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 ++ exit 1 ++fi ++ ++# Unset variables that we do not need and which cause bugs (e.g. in ++# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" ++# suppresses any "Segmentation fault" message there. '((' could ++# trigger a bug in pdksh 5.2.14. ++for as_var in BASH_ENV ENV MAIL MAILPATH ++do eval test x\${$as_var+set} = xset \ ++ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : ++done ++PS1='$ ' ++PS2='> ' ++PS4='+ ' ++ ++# NLS nuisances. ++LC_ALL=C ++export LC_ALL ++LANGUAGE=C ++export LANGUAGE ++ ++# CDPATH. ++(unset CDPATH) >/dev/null 2>&1 && unset CDPATH ++ ++ ++# as_fn_error STATUS ERROR [LINENO LOG_FD] ++# ---------------------------------------- ++# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are ++# provided, also output the error to LOG_FD, referencing LINENO. Then exit the ++# script with STATUS, using 1 if that was 0. ++as_fn_error () ++{ ++ as_status=$1; test $as_status -eq 0 && as_status=1 ++ if test "$4"; then ++ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack ++ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 ++ fi ++ $as_echo "$as_me: error: $2" >&2 ++ as_fn_exit $as_status ++} # as_fn_error ++ ++ ++# as_fn_set_status STATUS ++# ----------------------- ++# Set $? to STATUS, without forking. ++as_fn_set_status () ++{ ++ return $1 ++} # as_fn_set_status ++ ++# as_fn_exit STATUS ++# ----------------- ++# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. ++as_fn_exit () ++{ ++ set +e ++ as_fn_set_status $1 ++ exit $1 ++} # as_fn_exit ++ ++# as_fn_unset VAR ++# --------------- ++# Portably unset VAR. ++as_fn_unset () ++{ ++ { eval $1=; unset $1;} ++} ++as_unset=as_fn_unset ++# as_fn_append VAR VALUE ++# ---------------------- ++# Append the text in VALUE to the end of the definition contained in VAR. Take ++# advantage of any shell optimizations that allow amortized linear growth over ++# repeated appends, instead of the typical quadratic growth present in naive ++# implementations. ++if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : ++ eval 'as_fn_append () ++ { ++ eval $1+=\$2 ++ }' ++else ++ as_fn_append () ++ { ++ eval $1=\$$1\$2 ++ } ++fi # as_fn_append ++ ++# as_fn_arith ARG... ++# ------------------ ++# Perform arithmetic evaluation on the ARGs, and store the result in the ++# global $as_val. Take advantage of shells that can avoid forks. The arguments ++# must be portable across $(()) and expr. ++if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : ++ eval 'as_fn_arith () ++ { ++ as_val=$(( $* )) ++ }' ++else ++ as_fn_arith () ++ { ++ as_val=`expr "$@" || test $? -eq 1` ++ } ++fi # as_fn_arith ++ ++ ++if expr a : '\(a\)' >/dev/null 2>&1 && ++ test "X`expr 00001 : '.*\(...\)'`" = X001; then ++ as_expr=expr ++else ++ as_expr=false ++fi ++ ++if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then ++ as_basename=basename ++else ++ as_basename=false ++fi ++ ++if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then ++ as_dirname=dirname ++else ++ as_dirname=false ++fi ++ ++as_me=`$as_basename -- "$0" || ++$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ ++ X"$0" : 'X\(//\)$' \| \ ++ X"$0" : 'X\(/\)' \| . 2>/dev/null || ++$as_echo X/"$0" | ++ sed '/^.*\/\([^/][^/]*\)\/*$/{ ++ s//\1/ ++ q ++ } ++ /^X\/\(\/\/\)$/{ ++ s//\1/ ++ q ++ } ++ /^X\/\(\/\).*/{ ++ s//\1/ ++ q ++ } ++ s/.*/./; q'` ++ ++# Avoid depending upon Character Ranges. ++as_cr_letters='abcdefghijklmnopqrstuvwxyz' ++as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' ++as_cr_Letters=$as_cr_letters$as_cr_LETTERS ++as_cr_digits='0123456789' ++as_cr_alnum=$as_cr_Letters$as_cr_digits ++ ++ECHO_C= ECHO_N= ECHO_T= ++case `echo -n x` in #((((( ++-n*) ++ case `echo 'xy\c'` in ++ *c*) ECHO_T=' ';; # ECHO_T is single tab character. ++ xy) ECHO_C='\c';; ++ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ++ ECHO_T=' ';; ++ esac;; ++*) ++ ECHO_N='-n';; ++esac ++ ++rm -f conf$$ conf$$.exe conf$$.file ++if test -d conf$$.dir; then ++ rm -f conf$$.dir/conf$$.file ++else ++ rm -f conf$$.dir ++ mkdir conf$$.dir 2>/dev/null ++fi ++if (echo >conf$$.file) 2>/dev/null; then ++ if ln -s conf$$.file conf$$ 2>/dev/null; then ++ as_ln_s='ln -s' ++ # ... but there are two gotchas: ++ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. ++ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. ++ # In both cases, we have to default to `cp -pR'. ++ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || ++ as_ln_s='cp -pR' ++ elif ln conf$$.file conf$$ 2>/dev/null; then ++ as_ln_s=ln ++ else ++ as_ln_s='cp -pR' ++ fi ++else ++ as_ln_s='cp -pR' ++fi ++rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file ++rmdir conf$$.dir 2>/dev/null ++ ++ ++# as_fn_mkdir_p ++# ------------- ++# Create "$as_dir" as a directory, including parents if necessary. ++as_fn_mkdir_p () ++{ ++ ++ case $as_dir in #( ++ -*) as_dir=./$as_dir;; ++ esac ++ test -d "$as_dir" || eval $as_mkdir_p || { ++ as_dirs= ++ while :; do ++ case $as_dir in #( ++ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( ++ *) as_qdir=$as_dir;; ++ esac ++ as_dirs="'$as_qdir' $as_dirs" ++ as_dir=`$as_dirname -- "$as_dir" || ++$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ ++ X"$as_dir" : 'X\(//\)[^/]' \| \ ++ X"$as_dir" : 'X\(//\)$' \| \ ++ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || ++$as_echo X"$as_dir" | ++ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ ++ s//\1/ ++ q ++ } ++ /^X\(\/\/\)[^/].*/{ ++ s//\1/ ++ q ++ } ++ /^X\(\/\/\)$/{ ++ s//\1/ ++ q ++ } ++ /^X\(\/\).*/{ ++ s//\1/ ++ q ++ } ++ s/.*/./; q'` ++ test -d "$as_dir" && break ++ done ++ test -z "$as_dirs" || eval "mkdir $as_dirs" ++ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" ++ ++ ++} # as_fn_mkdir_p ++if mkdir -p . 2>/dev/null; then ++ as_mkdir_p='mkdir -p "$as_dir"' ++else ++ test -d ./-p && rmdir ./-p ++ as_mkdir_p=false ++fi ++ ++ ++# as_fn_executable_p FILE ++# ----------------------- ++# Test if FILE is an executable regular file. ++as_fn_executable_p () ++{ ++ test -f "$1" && test -x "$1" ++} # as_fn_executable_p ++as_test_x='test -x' ++as_executable_p=as_fn_executable_p ++ ++# Sed expression to map a string onto a valid CPP name. ++as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" ++ ++# Sed expression to map a string onto a valid variable name. ++as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" ++ ++ ++exec 6>&1 ++## ----------------------------------- ## ++## Main body of $CONFIG_STATUS script. ## ++## ----------------------------------- ## ++_ASEOF ++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.26.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 $@ ++ ++on `(hostname || uname -n) 2>/dev/null | sed 1q` ++" ++ ++_ACEOF ++ ++case $ac_config_files in *" ++"*) set x $ac_config_files; shift; ac_config_files=$*;; ++esac ++ ++ ++ ++cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ++# Files that config.status was made for. ++config_files="$ac_config_files" ++ ++_ACEOF ++ ++cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ++ac_cs_usage="\ ++\`$as_me' instantiates files and other configuration actions ++from templates according to the current configuration. Unless the files ++and actions are specified as TAGs, all are instantiated by default. ++ ++Usage: $0 [OPTION]... [TAG]... ++ ++ -h, --help print this help, then exit ++ -V, --version print version number and configuration settings, then exit ++ --config print configuration, then exit ++ -q, --quiet, --silent ++ do not print progress messages ++ -d, --debug don't remove temporary files ++ --recheck update $as_me by reconfiguring in the same conditions ++ --file=FILE[:TEMPLATE] ++ instantiate the configuration file FILE ++ ++Configuration files: ++$config_files ++ ++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.26.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." ++ ++ac_pwd='$ac_pwd' ++srcdir='$srcdir' ++test -n "\$AWK" || AWK=awk ++_ACEOF ++ ++cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ++# The default lists apply if the user does not specify any file. ++ac_need_defaults=: ++while test $# != 0 ++do ++ case $1 in ++ --*=?*) ++ ac_option=`expr "X$1" : 'X\([^=]*\)='` ++ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ++ ac_shift=: ++ ;; ++ --*=) ++ ac_option=`expr "X$1" : 'X\([^=]*\)='` ++ ac_optarg= ++ ac_shift=: ++ ;; ++ *) ++ ac_option=$1 ++ ac_optarg=$2 ++ ac_shift=shift ++ ;; ++ esac ++ ++ case $ac_option in ++ # Handling of the options. ++ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ++ ac_cs_recheck=: ;; ++ --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) ++ $as_echo "$ac_cs_version"; exit ;; ++ --config | --confi | --conf | --con | --co | --c ) ++ $as_echo "$ac_cs_config"; exit ;; ++ --debug | --debu | --deb | --de | --d | -d ) ++ debug=: ;; ++ --file | --fil | --fi | --f ) ++ $ac_shift ++ case $ac_optarg in ++ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; ++ '') as_fn_error $? "missing file argument" ;; ++ esac ++ as_fn_append CONFIG_FILES " '$ac_optarg'" ++ ac_need_defaults=false;; ++ --he | --h | --help | --hel | -h ) ++ $as_echo "$ac_cs_usage"; exit ;; ++ -q | -quiet | --quiet | --quie | --qui | --qu | --q \ ++ | -silent | --silent | --silen | --sile | --sil | --si | --s) ++ ac_cs_silent=: ;; ++ ++ # This is an error. ++ -*) as_fn_error $? "unrecognized option: \`$1' ++Try \`$0 --help' for more information." ;; ++ ++ *) as_fn_append ac_config_targets " $1" ++ ac_need_defaults=false ;; ++ ++ esac ++ shift ++done ++ ++ac_configure_extra_args= ++ ++if $ac_cs_silent; then ++ exec 6>/dev/null ++ ac_configure_extra_args="$ac_configure_extra_args --silent" ++fi ++ ++_ACEOF ++cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ++if \$ac_cs_recheck; then ++ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion ++ shift ++ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 ++ CONFIG_SHELL='$SHELL' ++ export CONFIG_SHELL ++ exec "\$@" ++fi ++ ++_ACEOF ++cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ++exec 5>>config.log ++{ ++ echo ++ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ++## Running $as_me. ## ++_ASBOX ++ $as_echo "$ac_log" ++} >&5 ++ ++_ACEOF ++cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ++_ACEOF ++ ++cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ++ ++# Handling of arguments. ++for ac_config_target in $ac_config_targets ++do ++ case $ac_config_target in ++ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; ++ "pkgIndex.tcl") CONFIG_FILES="$CONFIG_FILES pkgIndex.tcl" ;; ++ ++ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; ++ esac ++done ++ ++ ++# If the user did not use the arguments to specify the items to instantiate, ++# then the envvar interface is used. Set only those that are not. ++# We use the long form for the default assignment because of an extremely ++# bizarre bug on SunOS 4.1.3. ++if $ac_need_defaults; then ++ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files ++fi ++ ++# Have a temporary directory for convenience. Make it in the build tree ++# simply because there is no reason against having it here, and in addition, ++# creating and moving files from /tmp can sometimes cause problems. ++# Hook for its removal unless debugging. ++# Note that there is a small window in which the directory will not be cleaned: ++# after its creation but before its name has been assigned to `$tmp'. ++$debug || ++{ ++ tmp= ac_tmp= ++ trap 'exit_status=$? ++ : "${ac_tmp:=$tmp}" ++ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ++' 0 ++ trap 'as_fn_exit 1' 1 2 13 15 ++} ++# Create a (secure) tmp directory for tmp files. ++ ++{ ++ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && ++ test -d "$tmp" ++} || ++{ ++ tmp=./conf$$-$RANDOM ++ (umask 077 && mkdir "$tmp") ++} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ++ac_tmp=$tmp ++ ++# Set up the scripts for CONFIG_FILES section. ++# No need to generate them if there are no CONFIG_FILES. ++# This happens for instance with `./config.status config.h'. ++if test -n "$CONFIG_FILES"; then ++ ++ ++ac_cr=`echo X | tr X '\015'` ++# On cygwin, bash can eat \r inside `` if the user requested igncr. ++# But we know of no other shell where ac_cr would be empty at this ++# point, so we can use a bashism as a fallback. ++if test "x$ac_cr" = x; then ++ eval ac_cr=\$\'\\r\' ++fi ++ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null` ++if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ++ ac_cs_awk_cr='\\r' ++else ++ ac_cs_awk_cr=$ac_cr ++fi ++ ++echo 'BEGIN {' >"$ac_tmp/subs1.awk" && ++_ACEOF ++ ++ ++{ ++ echo "cat >conf$$subs.awk <<_ACEOF" && ++ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && ++ echo "_ACEOF" ++} >conf$$subs.sh || ++ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ++ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ++ac_delim='%!_!# ' ++for ac_last_try in false false false false false :; do ++ . ./conf$$subs.sh || ++ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ++ ++ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` ++ if test $ac_delim_n = $ac_delim_num; then ++ break ++ elif $ac_last_try; then ++ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ++ else ++ ac_delim="$ac_delim!$ac_delim _$ac_delim!! " ++ fi ++done ++rm -f conf$$subs.sh ++ ++cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ++cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && ++_ACEOF ++sed -n ' ++h ++s/^/S["/; s/!.*/"]=/ ++p ++g ++s/^[^!]*!// ++:repl ++t repl ++s/'"$ac_delim"'$// ++t delim ++:nl ++h ++s/\(.\{148\}\)..*/\1/ ++t more1 ++s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ ++p ++n ++b repl ++:more1 ++s/["\\]/\\&/g; s/^/"/; s/$/"\\/ ++p ++g ++s/.\{148\}// ++t nl ++:delim ++h ++s/\(.\{148\}\)..*/\1/ ++t more2 ++s/["\\]/\\&/g; s/^/"/; s/$/"/ ++p ++b ++:more2 ++s/["\\]/\\&/g; s/^/"/; s/$/"\\/ ++p ++g ++s/.\{148\}// ++t delim ++' <conf$$subs.awk | sed ' ++/^[^""]/{ ++ N ++ s/\n// ++} ++' >>$CONFIG_STATUS || ac_write_fail=1 ++rm -f conf$$subs.awk ++cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ++_ACAWK ++cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && ++ for (key in S) S_is_set[key] = 1 ++ FS = "" ++ ++} ++{ ++ line = $ 0 ++ nfields = split(line, field, "@") ++ substed = 0 ++ len = length(field[1]) ++ for (i = 2; i < nfields; i++) { ++ key = field[i] ++ keylen = length(key) ++ if (S_is_set[key]) { ++ value = S[key] ++ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) ++ len += length(value) + length(field[++i]) ++ substed = 1 ++ } else ++ len += 1 + keylen ++ } ++ ++ print line ++} ++ ++_ACAWK ++_ACEOF ++cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ++if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then ++ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" ++else ++ cat ++fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ ++ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 ++_ACEOF ++ ++# VPATH may cause trouble with some makes, so we remove sole $(srcdir), ++# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and ++# trailing colons and then remove the whole line if VPATH becomes empty ++# (actually we leave an empty line to preserve line numbers). ++if test "x$srcdir" = x.; then ++ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ ++h ++s/// ++s/^/:/ ++s/[ ]*$/:/ ++s/:\$(srcdir):/:/g ++s/:\${srcdir}:/:/g ++s/:@srcdir@:/:/g ++s/^:*// ++s/:*$// ++x ++s/\(=[ ]*\).*/\1/ ++G ++s/\n// ++s/^[^=]*=[ ]*$// ++}' ++fi ++ ++cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ++fi # test -n "$CONFIG_FILES" ++ ++ ++eval set X " :F $CONFIG_FILES " ++shift ++for ac_tag ++do ++ case $ac_tag in ++ :[FHLC]) ac_mode=$ac_tag; continue;; ++ esac ++ case $ac_mode$ac_tag in ++ :[FHL]*:*);; ++ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; ++ :[FH]-) ac_tag=-:-;; ++ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; ++ esac ++ ac_save_IFS=$IFS ++ IFS=: ++ set x $ac_tag ++ IFS=$ac_save_IFS ++ shift ++ ac_file=$1 ++ shift ++ ++ case $ac_mode in ++ :L) ac_source=$1;; ++ :[FH]) ++ ac_file_inputs= ++ for ac_f ++ do ++ case $ac_f in ++ -) ac_f="$ac_tmp/stdin";; ++ *) # Look for the file first in the build tree, then in the source tree ++ # (if the path is not absolute). The absolute path cannot be DOS-style, ++ # because $ac_f cannot contain `:'. ++ test -f "$ac_f" || ++ case $ac_f in ++ [\\/$]*) false;; ++ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; ++ esac || ++ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; ++ esac ++ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac ++ as_fn_append ac_file_inputs " '$ac_f'" ++ done ++ ++ # Let's still pretend it is `configure' which instantiates (i.e., don't ++ # use $as_me), people would be surprised to read: ++ # /* config.h. Generated by config.status. */ ++ configure_input='Generated from '` ++ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' ++ `' by configure.' ++ if test x"$ac_file" != x-; then ++ configure_input="$ac_file. $configure_input" ++ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 ++$as_echo "$as_me: creating $ac_file" >&6;} ++ fi ++ # Neutralize special characters interpreted by sed in replacement strings. ++ case $configure_input in #( ++ *\&* | *\|* | *\\* ) ++ ac_sed_conf_input=`$as_echo "$configure_input" | ++ sed 's/[\\\\&|]/\\\\&/g'`;; #( ++ *) ac_sed_conf_input=$configure_input;; ++ esac ++ ++ case $ac_tag in ++ *:-:* | *:-) cat >"$ac_tmp/stdin" \ ++ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; ++ esac ++ ;; ++ esac ++ ++ ac_dir=`$as_dirname -- "$ac_file" || ++$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ ++ X"$ac_file" : 'X\(//\)[^/]' \| \ ++ X"$ac_file" : 'X\(//\)$' \| \ ++ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || ++$as_echo X"$ac_file" | ++ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ ++ s//\1/ ++ q ++ } ++ /^X\(\/\/\)[^/].*/{ ++ s//\1/ ++ q ++ } ++ /^X\(\/\/\)$/{ ++ s//\1/ ++ q ++ } ++ /^X\(\/\).*/{ ++ s//\1/ ++ q ++ } ++ s/.*/./; q'` ++ as_dir="$ac_dir"; as_fn_mkdir_p ++ ac_builddir=. ++ ++case "$ac_dir" in ++.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; ++*) ++ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` ++ # A ".." for each directory in $ac_dir_suffix. ++ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` ++ case $ac_top_builddir_sub in ++ "") ac_top_builddir_sub=. ac_top_build_prefix= ;; ++ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; ++ esac ;; ++esac ++ac_abs_top_builddir=$ac_pwd ++ac_abs_builddir=$ac_pwd$ac_dir_suffix ++# for backward compatibility: ++ac_top_builddir=$ac_top_build_prefix ++ ++case $srcdir in ++ .) # We are building in place. ++ ac_srcdir=. ++ ac_top_srcdir=$ac_top_builddir_sub ++ ac_abs_top_srcdir=$ac_pwd ;; ++ [\\/]* | ?:[\\/]* ) # Absolute name. ++ ac_srcdir=$srcdir$ac_dir_suffix; ++ ac_top_srcdir=$srcdir ++ ac_abs_top_srcdir=$srcdir ;; ++ *) # Relative name. ++ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ++ ac_top_srcdir=$ac_top_build_prefix$srcdir ++ ac_abs_top_srcdir=$ac_pwd/$srcdir ;; ++esac ++ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix ++ ++ ++ case $ac_mode in ++ :F) ++ # ++ # CONFIG_FILE ++ # ++ ++_ACEOF ++ ++cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ++# If the template does not know about datarootdir, expand it. ++# FIXME: This hack should be removed a few years after 2.60. ++ac_datarootdir_hack=; ac_datarootdir_seen= ++ac_sed_dataroot=' ++/datarootdir/ { ++ p ++ q ++} ++/@datadir@/p ++/@docdir@/p ++/@infodir@/p ++/@localedir@/p ++/@mandir@/p' ++case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in ++*datarootdir*) ac_datarootdir_seen=yes;; ++*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 ++$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} ++_ACEOF ++cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ++ ac_datarootdir_hack=' ++ s&@datadir@&$datadir&g ++ s&@docdir@&$docdir&g ++ s&@infodir@&$infodir&g ++ s&@localedir@&$localedir&g ++ s&@mandir@&$mandir&g ++ s&\\\${datarootdir}&$datarootdir&g' ;; ++esac ++_ACEOF ++ ++# Neutralize VPATH when `$srcdir' = `.'. ++# Shell code in configure.ac might set extrasub. ++# FIXME: do we really want to maintain this feature? ++cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ++ac_sed_extra="$ac_vpsub ++$extrasub ++_ACEOF ++cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ++:t ++/@[a-zA-Z_][a-zA-Z_0-9]*@/!b ++s|@configure_input@|$ac_sed_conf_input|;t t ++s&@top_builddir@&$ac_top_builddir_sub&;t t ++s&@top_build_prefix@&$ac_top_build_prefix&;t t ++s&@srcdir@&$ac_srcdir&;t t ++s&@abs_srcdir@&$ac_abs_srcdir&;t t ++s&@top_srcdir@&$ac_top_srcdir&;t t ++s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t ++s&@builddir@&$ac_builddir&;t t ++s&@abs_builddir@&$ac_abs_builddir&;t t ++s&@abs_top_builddir@&$ac_abs_top_builddir&;t t ++$ac_datarootdir_hack ++" ++eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ ++ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ++ ++test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && ++ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && ++ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ ++ "$ac_tmp/out"`; test -z "$ac_out"; } && ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' ++which seems to be undefined. Please make sure it is defined" >&5 ++$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' ++which seems to be undefined. Please make sure it is defined" >&2;} ++ ++ rm -f "$ac_tmp/stdin" ++ case $ac_file in ++ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; ++ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; ++ esac \ ++ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ++ ;; ++ ++ ++ ++ esac ++ ++done # for ac_tag ++ ++ ++as_fn_exit 0 ++_ACEOF ++ac_clean_files=$ac_clean_files_save ++ ++test $ac_write_fail = 0 || ++ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 ++ ++ ++# configure is writing to config.log, and then calls config.status. ++# config.status does its own redirection, appending to config.log. ++# Unfortunately, on DOS this fails, as config.log is still kept open ++# by configure, so config.status won't be able to write to it; its ++# output is simply discarded. So we exec the FD to /dev/null, ++# effectively closing config.log, so it can be properly (re)opened and ++# appended to by config.status. When coming back to configure, we ++# need to make the FD available again. ++if test "$no_create" != yes; then ++ ac_cs_success=: ++ ac_config_status_args= ++ test "$silent" = yes && ++ ac_config_status_args="$ac_config_status_args --quiet" ++ exec 5>/dev/null ++ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false ++ exec 5>>config.log ++ # Use ||, not &&, to avoid exiting from the if with $? = 1, which ++ # would make configure fail if this is the last instruction. ++ $ac_cs_success || as_fn_exit 1 ++fi ++if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then ++ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 ++$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} ++fi ++ +--- contrib/sqlite3/tea/configure.ac.orig ++++ contrib/sqlite3/tea/configure.ac +@@ -0,0 +1,201 @@ ++#!/bin/bash -norc ++dnl This file is an input file used by the GNU "autoconf" program to ++dnl generate the file "configure", which is run during Tcl installation ++dnl to configure the system for the local environment. ++# ++# RCS: @(#) $Id: configure.in,v 1.43 2005/07/26 19:17:05 mdejong Exp $ ++ ++#----------------------------------------------------------------------- ++# Sample configure.in for Tcl Extensions. The only places you should ++# need to modify this file are marked by the string __CHANGE__ ++#----------------------------------------------------------------------- ++ ++#----------------------------------------------------------------------- ++# __CHANGE__ ++# Set your package name and version numbers here. ++# ++# 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. ++#----------------------------------------------------------------------- ++ ++AC_INIT([sqlite], [3.26.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. ++#-------------------------------------------------------------------- ++ ++TEA_INIT([3.9]) ++ ++AC_CONFIG_AUX_DIR(tclconfig) ++ ++#-------------------------------------------------------------------- ++# Load the tclConfig.sh file ++#-------------------------------------------------------------------- ++ ++TEA_PATH_TCLCONFIG ++TEA_LOAD_TCLCONFIG ++ ++#-------------------------------------------------------------------- ++# Load the tkConfig.sh file if necessary (Tk extension) ++#-------------------------------------------------------------------- ++ ++#TEA_PATH_TKCONFIG ++#TEA_LOAD_TKCONFIG ++ ++#----------------------------------------------------------------------- ++# Handle the --prefix=... option by defaulting to what Tcl gave. ++# Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER. ++#----------------------------------------------------------------------- ++ ++TEA_PREFIX ++ ++#----------------------------------------------------------------------- ++# Standard compiler checks. ++# This sets up CC by using the CC env var, or looks for gcc otherwise. ++# This also calls AC_PROG_CC, AC_PROG_INSTALL and a few others to create ++# the basic setup necessary to compile executables. ++#----------------------------------------------------------------------- ++ ++TEA_SETUP_COMPILER ++ ++#----------------------------------------------------------------------- ++# __CHANGE__ ++# Specify the C source files to compile in TEA_ADD_SOURCES, ++# public headers that need to be installed in TEA_ADD_HEADERS, ++# stub library C source files to compile in TEA_ADD_STUB_SOURCES, ++# and runtime Tcl library files in TEA_ADD_TCL_SOURCES. ++# This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS ++# and PKG_TCL_SOURCES. ++#----------------------------------------------------------------------- ++ ++TEA_ADD_SOURCES([tclsqlite3.c]) ++TEA_ADD_HEADERS([]) ++TEA_ADD_INCLUDES([-I\"`\${CYGPATH} \${srcdir}/generic`\"]) ++TEA_ADD_LIBS([]) ++TEA_ADD_CFLAGS([-DSQLITE_ENABLE_FTS3=1]) ++TEA_ADD_CFLAGS([-DSQLITE_3_SUFFIX_ONLY=1]) ++TEA_ADD_CFLAGS([-DSQLITE_ENABLE_RTREE=1]) ++TEA_ADD_STUB_SOURCES([]) ++TEA_ADD_TCL_SOURCES([]) ++ ++#-------------------------------------------------------------------- ++# The --with-system-sqlite causes the TCL bindings to SQLite to use ++# the system shared library for SQLite rather than statically linking ++# against its own private copy. This is dangerous and leads to ++# undersirable dependences and is not recommended. ++# Patchs from rmax. ++#-------------------------------------------------------------------- ++AC_ARG_WITH([system-sqlite], ++ [AC_HELP_STRING([--with-system-sqlite], ++ [use a system-supplied libsqlite3 instead of the bundled one])], ++ [], [with_system_sqlite=no]) ++if test x$with_system_sqlite != xno; then ++ AC_CHECK_HEADER([sqlite3.h], ++ [AC_CHECK_LIB([sqlite3],[sqlite3_initialize], ++ [AC_DEFINE(USE_SYSTEM_SQLITE) ++ LIBS="$LIBS -lsqlite3"])]) ++fi ++ ++#-------------------------------------------------------------------- ++# __CHANGE__ ++# Choose which headers you need. Extension authors should try very ++# hard to only rely on the Tcl public header files. Internal headers ++# contain private data structures and are subject to change without ++# notice. ++# This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG ++#-------------------------------------------------------------------- ++ ++TEA_PUBLIC_TCL_HEADERS ++#TEA_PRIVATE_TCL_HEADERS ++ ++#TEA_PUBLIC_TK_HEADERS ++#TEA_PRIVATE_TK_HEADERS ++#TEA_PATH_X ++ ++#-------------------------------------------------------------------- ++# Check whether --enable-threads or --disable-threads was given. ++# This auto-enables if Tcl was compiled threaded. ++#-------------------------------------------------------------------- ++ ++TEA_ENABLE_THREADS ++if test "${TCL_THREADS}" = "1" ; then ++ AC_DEFINE(SQLITE_THREADSAFE, 1, [Trigger sqlite threadsafe build]) ++ # Not automatically added by Tcl because its assumed Tcl links to them, ++ # but it may not if it isn't really a threaded build. ++ TEA_ADD_LIBS([$THREADS_LIBS]) ++else ++ AC_DEFINE(SQLITE_THREADSAFE, 0, [Trigger sqlite non-threadsafe build]) ++fi ++ ++#-------------------------------------------------------------------- ++# The statement below defines a collection of symbols related to ++# building as a shared library instead of a static library. ++#-------------------------------------------------------------------- ++ ++TEA_ENABLE_SHARED ++ ++#-------------------------------------------------------------------- ++# This macro figures out what flags to use with the compiler/linker ++# when building shared/static debug/optimized objects. This information ++# can be taken from the tclConfig.sh file, but this figures it all out. ++#-------------------------------------------------------------------- ++ ++TEA_CONFIG_CFLAGS ++ ++#-------------------------------------------------------------------- ++# Set the default compiler switches based on the --enable-symbols option. ++#-------------------------------------------------------------------- ++ ++TEA_ENABLE_SYMBOLS ++ ++#-------------------------------------------------------------------- ++# Everyone should be linking against the Tcl stub library. If you ++# can't for some reason, remove this definition. If you aren't using ++# stubs, you also need to modify the SHLIB_LD_LIBS setting below to ++# link against the non-stubbed Tcl library. Add Tk too if necessary. ++#-------------------------------------------------------------------- ++ ++AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs]) ++#AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs]) ++ ++ ++#-------------------------------------------------------------------- ++# Redefine fdatasync as fsync on systems that lack fdatasync ++#-------------------------------------------------------------------- ++# ++#AC_CHECK_FUNC(fdatasync, , AC_DEFINE(fdatasync, fsync)) ++# Check for library functions that SQLite can optionally use. ++AC_CHECK_FUNCS([fdatasync usleep fullfsync localtime_r gmtime_r]) ++ ++AC_FUNC_STRERROR_R ++ ++ ++#-------------------------------------------------------------------- ++# This macro generates a line to use when building a library. It ++# depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS, ++# and TEA_LOAD_TCLCONFIG macros above. ++#-------------------------------------------------------------------- ++ ++TEA_MAKE_LIB ++ ++#-------------------------------------------------------------------- ++# Determine the name of the tclsh and/or wish executables in the ++# Tcl and Tk build directories or the location they were installed ++# into. These paths are used to support running test cases only, ++# the Makefile should not be making use of these paths to generate ++# a pkgIndex.tcl file or anything else at extension build time. ++#-------------------------------------------------------------------- ++ ++TEA_PROG_TCLSH ++#TEA_PROG_WISH ++ ++#-------------------------------------------------------------------- ++# Finally, substitute all of the various values into the Makefile. ++# You may alternatively have a special pkgIndex.tcl.in or other files ++# which require substituting th AC variables in. Include these here. ++#-------------------------------------------------------------------- ++ ++AC_OUTPUT([Makefile pkgIndex.tcl]) +--- contrib/sqlite3/tea/doc/sqlite3.n.orig ++++ contrib/sqlite3/tea/doc/sqlite3.n +@@ -0,0 +1,15 @@ ++.TH sqlite3 n 4.1 "Tcl-Extensions" ++.HS sqlite3 tcl ++.BS ++.SH NAME ++sqlite3 \- an interface to the SQLite3 database engine ++.SH SYNOPSIS ++\fBsqlite3\fI command_name ?filename?\fR ++.br ++.SH DESCRIPTION ++SQLite3 is a self-contains, zero-configuration, transactional SQL database ++engine. This extension provides an easy to use interface for accessing ++SQLite database files from Tcl. ++.PP ++For full documentation see \fIhttp://www.sqlite.org/\fR and ++in particular \fIhttp://www.sqlite.org/tclsqlite.html\fR. +--- contrib/sqlite3/tea/generic/tclsqlite3.c.orig ++++ contrib/sqlite3/tea/generic/tclsqlite3.c +@@ -0,0 +1,3793 @@ ++#ifdef USE_SYSTEM_SQLITE ++# include <sqlite3.h> ++#else ++#include "sqlite3.c" ++#endif ++/* ++** 2001 September 15 ++** ++** The author disclaims copyright to this source code. In place of ++** a legal notice, here is a blessing: ++** ++** May you do good and not evil. ++** May you find forgiveness for yourself and forgive others. ++** May you share freely, never taking more than you give. ++** ++************************************************************************* ++** A TCL Interface to SQLite. Append this file to sqlite3.c and ++** compile the whole thing to build a TCL-enabled version of SQLite. ++** ++** Compile-time options: ++** ++** -DTCLSH Add a "main()" routine that works as a tclsh. ++** ++** -DTCLSH_INIT_PROC=name ++** ++** Invoke name(interp) to initialize the Tcl interpreter. ++** If name(interp) returns a non-NULL string, then run ++** that string as a Tcl script to launch the application. ++** If name(interp) returns NULL, then run the regular ++** tclsh-emulator code. ++*/ ++#ifdef TCLSH_INIT_PROC ++# define TCLSH 1 ++#endif ++ ++/* ++** If requested, include the SQLite compiler options file for MSVC. ++*/ ++#if defined(INCLUDE_MSVC_H) ++# include "msvc.h" ++#endif ++ ++#if defined(INCLUDE_SQLITE_TCL_H) ++# include "sqlite_tcl.h" ++#else ++# include "tcl.h" ++# ifndef SQLITE_TCLAPI ++# define SQLITE_TCLAPI ++# endif ++#endif ++#include <errno.h> ++ ++/* ++** Some additional include files are needed if this file is not ++** appended to the amalgamation. ++*/ ++#ifndef SQLITE_AMALGAMATION ++# include "sqlite3.h" ++# include <stdlib.h> ++# include <string.h> ++# include <assert.h> ++ typedef unsigned char u8; ++#endif ++#include <ctype.h> ++ ++/* Used to get the current process ID */ ++#if !defined(_WIN32) ++# include <signal.h> ++# include <unistd.h> ++# define GETPID getpid ++#elif !defined(_WIN32_WCE) ++# ifndef SQLITE_AMALGAMATION ++# ifndef WIN32_LEAN_AND_MEAN ++# define WIN32_LEAN_AND_MEAN ++# endif ++# include <windows.h> ++# endif ++# include <io.h> ++# define isatty(h) _isatty(h) ++# define GETPID (int)GetCurrentProcessId ++#endif ++ ++/* ++ * Windows needs to know which symbols to export. Unix does not. ++ * BUILD_sqlite should be undefined for Unix. ++ */ ++#ifdef BUILD_sqlite ++#undef TCL_STORAGE_CLASS ++#define TCL_STORAGE_CLASS DLLEXPORT ++#endif /* BUILD_sqlite */ ++ ++#define NUM_PREPARED_STMTS 10 ++#define MAX_PREPARED_STMTS 100 ++ ++/* Forward declaration */ ++typedef struct SqliteDb SqliteDb; ++ ++/* ++** New SQL functions can be created as TCL scripts. Each such function ++** is described by an instance of the following structure. ++*/ ++typedef struct SqlFunc SqlFunc; ++struct SqlFunc { ++ Tcl_Interp *interp; /* The TCL interpret to execute the function */ ++ Tcl_Obj *pScript; /* The Tcl_Obj representation of the script */ ++ SqliteDb *pDb; /* Database connection that owns this function */ ++ int useEvalObjv; /* True if it is safe to use Tcl_EvalObjv */ ++ char *zName; /* Name of this function */ ++ SqlFunc *pNext; /* Next function on the list of them all */ ++}; ++ ++/* ++** New collation sequences function can be created as TCL scripts. Each such ++** function is described by an instance of the following structure. ++*/ ++typedef struct SqlCollate SqlCollate; ++struct SqlCollate { ++ Tcl_Interp *interp; /* The TCL interpret to execute the function */ ++ char *zScript; /* The script to be run */ ++ SqlCollate *pNext; /* Next function on the list of them all */ ++}; ++ ++/* ++** Prepared statements are cached for faster execution. Each prepared ++** statement is described by an instance of the following structure. ++*/ ++typedef struct SqlPreparedStmt SqlPreparedStmt; ++struct SqlPreparedStmt { ++ SqlPreparedStmt *pNext; /* Next in linked list */ ++ SqlPreparedStmt *pPrev; /* Previous on the list */ ++ sqlite3_stmt *pStmt; /* The prepared statement */ ++ int nSql; /* chars in zSql[] */ ++ const char *zSql; /* Text of the SQL statement */ ++ int nParm; /* Size of apParm array */ ++ Tcl_Obj **apParm; /* Array of referenced object pointers */ ++}; ++ ++typedef struct IncrblobChannel IncrblobChannel; ++ ++/* ++** There is one instance of this structure for each SQLite database ++** that has been opened by the SQLite TCL interface. ++** ++** If this module is built with SQLITE_TEST defined (to create the SQLite ++** testfixture executable), then it may be configured to use either ++** sqlite3_prepare_v2() or sqlite3_prepare() to prepare SQL statements. ++** If SqliteDb.bLegacyPrepare is true, sqlite3_prepare() is used. ++*/ ++struct SqliteDb { ++ sqlite3 *db; /* The "real" database structure. MUST BE FIRST */ ++ Tcl_Interp *interp; /* The interpreter used for this database */ ++ char *zBusy; /* The busy callback routine */ ++ char *zCommit; /* The commit hook callback routine */ ++ char *zTrace; /* The trace callback routine */ ++ char *zTraceV2; /* The trace_v2 callback routine */ ++ char *zProfile; /* The profile callback routine */ ++ char *zProgress; /* The progress callback routine */ ++ char *zAuth; /* The authorization callback routine */ ++ int disableAuth; /* Disable the authorizer if it exists */ ++ char *zNull; /* Text to substitute for an SQL NULL value */ ++ SqlFunc *pFunc; /* List of SQL functions */ ++ Tcl_Obj *pUpdateHook; /* Update hook script (if any) */ ++ Tcl_Obj *pPreUpdateHook; /* Pre-update hook script (if any) */ ++ Tcl_Obj *pRollbackHook; /* Rollback hook script (if any) */ ++ Tcl_Obj *pWalHook; /* WAL hook script (if any) */ ++ Tcl_Obj *pUnlockNotify; /* Unlock notify script (if any) */ ++ SqlCollate *pCollate; /* List of SQL collation functions */ ++ int rc; /* Return code of most recent sqlite3_exec() */ ++ Tcl_Obj *pCollateNeeded; /* Collation needed script */ ++ SqlPreparedStmt *stmtList; /* List of prepared statements*/ ++ SqlPreparedStmt *stmtLast; /* Last statement in the list */ ++ int maxStmt; /* The next maximum number of stmtList */ ++ int nStmt; /* Number of statements in stmtList */ ++ IncrblobChannel *pIncrblob;/* Linked list of open incrblob channels */ ++ int nStep, nSort, nIndex; /* Statistics for most recent operation */ ++ int nVMStep; /* Another statistic for most recent operation */ ++ int nTransaction; /* Number of nested [transaction] methods */ ++ int openFlags; /* Flags used to open. (SQLITE_OPEN_URI) */ ++#ifdef SQLITE_TEST ++ int bLegacyPrepare; /* True to use sqlite3_prepare() */ ++#endif ++}; ++ ++struct IncrblobChannel { ++ sqlite3_blob *pBlob; /* sqlite3 blob handle */ ++ SqliteDb *pDb; /* Associated database connection */ ++ int iSeek; /* Current seek offset */ ++ Tcl_Channel channel; /* Channel identifier */ ++ IncrblobChannel *pNext; /* Linked list of all open incrblob channels */ ++ IncrblobChannel *pPrev; /* Linked list of all open incrblob channels */ ++}; ++ ++/* ++** Compute a string length that is limited to what can be stored in ++** lower 30 bits of a 32-bit signed integer. ++*/ ++static int strlen30(const char *z){ ++ const char *z2 = z; ++ while( *z2 ){ z2++; } ++ return 0x3fffffff & (int)(z2 - z); ++} ++ ++ ++#ifndef SQLITE_OMIT_INCRBLOB ++/* ++** Close all incrblob channels opened using database connection pDb. ++** This is called when shutting down the database connection. ++*/ ++static void closeIncrblobChannels(SqliteDb *pDb){ ++ IncrblobChannel *p; ++ IncrblobChannel *pNext; ++ ++ for(p=pDb->pIncrblob; p; p=pNext){ ++ pNext = p->pNext; ++ ++ /* Note: Calling unregister here call Tcl_Close on the incrblob channel, ++ ** which deletes the IncrblobChannel structure at *p. So do not ++ ** call Tcl_Free() here. ++ */ ++ Tcl_UnregisterChannel(pDb->interp, p->channel); ++ } ++} ++ ++/* ++** Close an incremental blob channel. ++*/ ++static int SQLITE_TCLAPI incrblobClose( ++ ClientData instanceData, ++ Tcl_Interp *interp ++){ ++ IncrblobChannel *p = (IncrblobChannel *)instanceData; ++ int rc = sqlite3_blob_close(p->pBlob); ++ sqlite3 *db = p->pDb->db; ++ ++ /* Remove the channel from the SqliteDb.pIncrblob list. */ ++ if( p->pNext ){ ++ p->pNext->pPrev = p->pPrev; ++ } ++ if( p->pPrev ){ ++ p->pPrev->pNext = p->pNext; ++ } ++ if( p->pDb->pIncrblob==p ){ ++ p->pDb->pIncrblob = p->pNext; ++ } ++ ++ /* Free the IncrblobChannel structure */ ++ Tcl_Free((char *)p); ++ ++ if( rc!=SQLITE_OK ){ ++ Tcl_SetResult(interp, (char *)sqlite3_errmsg(db), TCL_VOLATILE); ++ return TCL_ERROR; ++ } ++ return TCL_OK; ++} ++ ++/* ++** Read data from an incremental blob channel. ++*/ ++static int SQLITE_TCLAPI incrblobInput( ++ ClientData instanceData, ++ char *buf, ++ int bufSize, ++ int *errorCodePtr ++){ ++ IncrblobChannel *p = (IncrblobChannel *)instanceData; ++ int nRead = bufSize; /* Number of bytes to read */ ++ int nBlob; /* Total size of the blob */ ++ int rc; /* sqlite error code */ ++ ++ nBlob = sqlite3_blob_bytes(p->pBlob); ++ if( (p->iSeek+nRead)>nBlob ){ ++ nRead = nBlob-p->iSeek; ++ } ++ if( nRead<=0 ){ ++ return 0; ++ } ++ ++ rc = sqlite3_blob_read(p->pBlob, (void *)buf, nRead, p->iSeek); ++ if( rc!=SQLITE_OK ){ ++ *errorCodePtr = rc; ++ return -1; ++ } ++ ++ p->iSeek += nRead; ++ return nRead; ++} ++ ++/* ++** Write data to an incremental blob channel. ++*/ ++static int SQLITE_TCLAPI incrblobOutput( ++ ClientData instanceData, ++ CONST char *buf, ++ int toWrite, ++ int *errorCodePtr ++){ ++ IncrblobChannel *p = (IncrblobChannel *)instanceData; ++ int nWrite = toWrite; /* Number of bytes to write */ ++ int nBlob; /* Total size of the blob */ ++ int rc; /* sqlite error code */ ++ ++ nBlob = sqlite3_blob_bytes(p->pBlob); ++ if( (p->iSeek+nWrite)>nBlob ){ ++ *errorCodePtr = EINVAL; ++ return -1; ++ } ++ if( nWrite<=0 ){ ++ return 0; ++ } ++ ++ rc = sqlite3_blob_write(p->pBlob, (void *)buf, nWrite, p->iSeek); ++ if( rc!=SQLITE_OK ){ ++ *errorCodePtr = EIO; ++ return -1; ++ } ++ ++ p->iSeek += nWrite; ++ return nWrite; ++} ++ ++/* ++** Seek an incremental blob channel. ++*/ ++static int SQLITE_TCLAPI incrblobSeek( ++ ClientData instanceData, ++ long offset, ++ int seekMode, ++ int *errorCodePtr ++){ ++ IncrblobChannel *p = (IncrblobChannel *)instanceData; ++ ++ switch( seekMode ){ ++ case SEEK_SET: ++ p->iSeek = offset; ++ break; ++ case SEEK_CUR: ++ p->iSeek += offset; ++ break; ++ case SEEK_END: ++ p->iSeek = sqlite3_blob_bytes(p->pBlob) + offset; ++ break; ++ ++ default: assert(!"Bad seekMode"); ++ } ++ ++ return p->iSeek; ++} ++ ++ ++static void SQLITE_TCLAPI incrblobWatch( ++ ClientData instanceData, ++ int mode ++){ ++ /* NO-OP */ ++} ++static int SQLITE_TCLAPI incrblobHandle( ++ ClientData instanceData, ++ int dir, ++ ClientData *hPtr ++){ ++ return TCL_ERROR; ++} ++ ++static Tcl_ChannelType IncrblobChannelType = { ++ "incrblob", /* typeName */ ++ TCL_CHANNEL_VERSION_2, /* version */ ++ incrblobClose, /* closeProc */ ++ incrblobInput, /* inputProc */ ++ incrblobOutput, /* outputProc */ ++ incrblobSeek, /* seekProc */ ++ 0, /* setOptionProc */ ++ 0, /* getOptionProc */ ++ incrblobWatch, /* watchProc (this is a no-op) */ ++ incrblobHandle, /* getHandleProc (always returns error) */ ++ 0, /* close2Proc */ ++ 0, /* blockModeProc */ ++ 0, /* flushProc */ ++ 0, /* handlerProc */ ++ 0, /* wideSeekProc */ ++}; ++ ++/* ++** Create a new incrblob channel. ++*/ ++static int createIncrblobChannel( ++ Tcl_Interp *interp, ++ SqliteDb *pDb, ++ const char *zDb, ++ const char *zTable, ++ const char *zColumn, ++ sqlite_int64 iRow, ++ int isReadonly ++){ ++ IncrblobChannel *p; ++ sqlite3 *db = pDb->db; ++ sqlite3_blob *pBlob; ++ int rc; ++ int flags = TCL_READABLE|(isReadonly ? 0 : TCL_WRITABLE); ++ ++ /* This variable is used to name the channels: "incrblob_[incr count]" */ ++ static int count = 0; ++ char zChannel[64]; ++ ++ rc = sqlite3_blob_open(db, zDb, zTable, zColumn, iRow, !isReadonly, &pBlob); ++ if( rc!=SQLITE_OK ){ ++ Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE); ++ return TCL_ERROR; ++ } ++ ++ p = (IncrblobChannel *)Tcl_Alloc(sizeof(IncrblobChannel)); ++ p->iSeek = 0; ++ p->pBlob = pBlob; ++ ++ sqlite3_snprintf(sizeof(zChannel), zChannel, "incrblob_%d", ++count); ++ p->channel = Tcl_CreateChannel(&IncrblobChannelType, zChannel, p, flags); ++ Tcl_RegisterChannel(interp, p->channel); ++ ++ /* Link the new channel into the SqliteDb.pIncrblob list. */ ++ p->pNext = pDb->pIncrblob; ++ p->pPrev = 0; ++ if( p->pNext ){ ++ p->pNext->pPrev = p; ++ } ++ pDb->pIncrblob = p; ++ p->pDb = pDb; ++ ++ Tcl_SetResult(interp, (char *)Tcl_GetChannelName(p->channel), TCL_VOLATILE); ++ return TCL_OK; ++} ++#else /* else clause for "#ifndef SQLITE_OMIT_INCRBLOB" */ ++ #define closeIncrblobChannels(pDb) ++#endif ++ ++/* ++** Look at the script prefix in pCmd. We will be executing this script ++** after first appending one or more arguments. This routine analyzes ++** the script to see if it is safe to use Tcl_EvalObjv() on the script ++** rather than the more general Tcl_EvalEx(). Tcl_EvalObjv() is much ++** faster. ++** ++** Scripts that are safe to use with Tcl_EvalObjv() consists of a ++** command name followed by zero or more arguments with no [...] or $ ++** or {...} or ; to be seen anywhere. Most callback scripts consist ++** of just a single procedure name and they meet this requirement. ++*/ ++static int safeToUseEvalObjv(Tcl_Interp *interp, Tcl_Obj *pCmd){ ++ /* We could try to do something with Tcl_Parse(). But we will instead ++ ** just do a search for forbidden characters. If any of the forbidden ++ ** characters appear in pCmd, we will report the string as unsafe. ++ */ ++ const char *z; ++ int n; ++ z = Tcl_GetStringFromObj(pCmd, &n); ++ while( n-- > 0 ){ ++ int c = *(z++); ++ if( c=='$' || c=='[' || c==';' ) return 0; ++ } ++ return 1; ++} ++ ++/* ++** Find an SqlFunc structure with the given name. Or create a new ++** one if an existing one cannot be found. Return a pointer to the ++** structure. ++*/ ++static SqlFunc *findSqlFunc(SqliteDb *pDb, const char *zName){ ++ SqlFunc *p, *pNew; ++ int nName = strlen30(zName); ++ pNew = (SqlFunc*)Tcl_Alloc( sizeof(*pNew) + nName + 1 ); ++ pNew->zName = (char*)&pNew[1]; ++ memcpy(pNew->zName, zName, nName+1); ++ for(p=pDb->pFunc; p; p=p->pNext){ ++ if( sqlite3_stricmp(p->zName, pNew->zName)==0 ){ ++ Tcl_Free((char*)pNew); ++ return p; ++ } ++ } ++ pNew->interp = pDb->interp; ++ pNew->pDb = pDb; ++ pNew->pScript = 0; ++ pNew->pNext = pDb->pFunc; ++ pDb->pFunc = pNew; ++ return pNew; ++} ++ ++/* ++** Free a single SqlPreparedStmt object. ++*/ ++static void dbFreeStmt(SqlPreparedStmt *pStmt){ ++#ifdef SQLITE_TEST ++ if( sqlite3_sql(pStmt->pStmt)==0 ){ ++ Tcl_Free((char *)pStmt->zSql); ++ } ++#endif ++ sqlite3_finalize(pStmt->pStmt); ++ Tcl_Free((char *)pStmt); ++} ++ ++/* ++** Finalize and free a list of prepared statements ++*/ ++static void flushStmtCache(SqliteDb *pDb){ ++ SqlPreparedStmt *pPreStmt; ++ SqlPreparedStmt *pNext; ++ ++ for(pPreStmt = pDb->stmtList; pPreStmt; pPreStmt=pNext){ ++ pNext = pPreStmt->pNext; ++ dbFreeStmt(pPreStmt); ++ } ++ pDb->nStmt = 0; ++ pDb->stmtLast = 0; ++ pDb->stmtList = 0; ++} ++ ++/* ++** TCL calls this procedure when an sqlite3 database command is ++** deleted. ++*/ ++static void SQLITE_TCLAPI DbDeleteCmd(void *db){ ++ SqliteDb *pDb = (SqliteDb*)db; ++ flushStmtCache(pDb); ++ closeIncrblobChannels(pDb); ++ sqlite3_close(pDb->db); ++ while( pDb->pFunc ){ ++ SqlFunc *pFunc = pDb->pFunc; ++ pDb->pFunc = pFunc->pNext; ++ assert( pFunc->pDb==pDb ); ++ Tcl_DecrRefCount(pFunc->pScript); ++ Tcl_Free((char*)pFunc); ++ } ++ while( pDb->pCollate ){ ++ SqlCollate *pCollate = pDb->pCollate; ++ pDb->pCollate = pCollate->pNext; ++ Tcl_Free((char*)pCollate); ++ } ++ if( pDb->zBusy ){ ++ Tcl_Free(pDb->zBusy); ++ } ++ if( pDb->zTrace ){ ++ Tcl_Free(pDb->zTrace); ++ } ++ if( pDb->zTraceV2 ){ ++ Tcl_Free(pDb->zTraceV2); ++ } ++ if( pDb->zProfile ){ ++ Tcl_Free(pDb->zProfile); ++ } ++ if( pDb->zAuth ){ ++ Tcl_Free(pDb->zAuth); ++ } ++ if( pDb->zNull ){ ++ Tcl_Free(pDb->zNull); ++ } ++ if( pDb->pUpdateHook ){ ++ Tcl_DecrRefCount(pDb->pUpdateHook); ++ } ++ if( pDb->pPreUpdateHook ){ ++ Tcl_DecrRefCount(pDb->pPreUpdateHook); ++ } ++ if( pDb->pRollbackHook ){ ++ Tcl_DecrRefCount(pDb->pRollbackHook); ++ } ++ if( pDb->pWalHook ){ ++ Tcl_DecrRefCount(pDb->pWalHook); ++ } ++ if( pDb->pCollateNeeded ){ ++ Tcl_DecrRefCount(pDb->pCollateNeeded); ++ } ++ Tcl_Free((char*)pDb); ++} ++ ++/* ++** This routine is called when a database file is locked while trying ++** to execute SQL. ++*/ ++static int DbBusyHandler(void *cd, int nTries){ ++ SqliteDb *pDb = (SqliteDb*)cd; ++ int rc; ++ char zVal[30]; ++ ++ sqlite3_snprintf(sizeof(zVal), zVal, "%d", nTries); ++ rc = Tcl_VarEval(pDb->interp, pDb->zBusy, " ", zVal, (char*)0); ++ if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){ ++ return 0; ++ } ++ return 1; ++} ++ ++#ifndef SQLITE_OMIT_PROGRESS_CALLBACK ++/* ++** This routine is invoked as the 'progress callback' for the database. ++*/ ++static int DbProgressHandler(void *cd){ ++ SqliteDb *pDb = (SqliteDb*)cd; ++ int rc; ++ ++ assert( pDb->zProgress ); ++ rc = Tcl_Eval(pDb->interp, pDb->zProgress); ++ if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){ ++ return 1; ++ } ++ return 0; ++} ++#endif ++ ++#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) && \ ++ !defined(SQLITE_OMIT_DEPRECATED) ++/* ++** This routine is called by the SQLite trace handler whenever a new ++** block of SQL is executed. The TCL script in pDb->zTrace is executed. ++*/ ++static void DbTraceHandler(void *cd, const char *zSql){ ++ SqliteDb *pDb = (SqliteDb*)cd; ++ Tcl_DString str; ++ ++ Tcl_DStringInit(&str); ++ Tcl_DStringAppend(&str, pDb->zTrace, -1); ++ Tcl_DStringAppendElement(&str, zSql); ++ Tcl_Eval(pDb->interp, Tcl_DStringValue(&str)); ++ Tcl_DStringFree(&str); ++ Tcl_ResetResult(pDb->interp); ++} ++#endif ++ ++#ifndef SQLITE_OMIT_TRACE ++/* ++** This routine is called by the SQLite trace_v2 handler whenever a new ++** supported event is generated. Unsupported event types are ignored. ++** The TCL script in pDb->zTraceV2 is executed, with the arguments for ++** the event appended to it (as list elements). ++*/ ++static int DbTraceV2Handler( ++ unsigned type, /* One of the SQLITE_TRACE_* event types. */ ++ void *cd, /* The original context data pointer. */ ++ void *pd, /* Primary event data, depends on event type. */ ++ void *xd /* Extra event data, depends on event type. */ ++){ ++ SqliteDb *pDb = (SqliteDb*)cd; ++ Tcl_Obj *pCmd; ++ ++ switch( type ){ ++ case SQLITE_TRACE_STMT: { ++ sqlite3_stmt *pStmt = (sqlite3_stmt *)pd; ++ char *zSql = (char *)xd; ++ ++ pCmd = Tcl_NewStringObj(pDb->zTraceV2, -1); ++ Tcl_IncrRefCount(pCmd); ++ Tcl_ListObjAppendElement(pDb->interp, pCmd, ++ Tcl_NewWideIntObj((Tcl_WideInt)pStmt)); ++ Tcl_ListObjAppendElement(pDb->interp, pCmd, ++ Tcl_NewStringObj(zSql, -1)); ++ Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT); ++ Tcl_DecrRefCount(pCmd); ++ Tcl_ResetResult(pDb->interp); ++ break; ++ } ++ case SQLITE_TRACE_PROFILE: { ++ sqlite3_stmt *pStmt = (sqlite3_stmt *)pd; ++ sqlite3_int64 ns = *(sqlite3_int64*)xd; ++ ++ pCmd = Tcl_NewStringObj(pDb->zTraceV2, -1); ++ Tcl_IncrRefCount(pCmd); ++ Tcl_ListObjAppendElement(pDb->interp, pCmd, ++ Tcl_NewWideIntObj((Tcl_WideInt)pStmt)); ++ Tcl_ListObjAppendElement(pDb->interp, pCmd, ++ Tcl_NewWideIntObj((Tcl_WideInt)ns)); ++ Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT); ++ Tcl_DecrRefCount(pCmd); ++ Tcl_ResetResult(pDb->interp); ++ break; ++ } ++ case SQLITE_TRACE_ROW: { ++ sqlite3_stmt *pStmt = (sqlite3_stmt *)pd; ++ ++ pCmd = Tcl_NewStringObj(pDb->zTraceV2, -1); ++ Tcl_IncrRefCount(pCmd); ++ Tcl_ListObjAppendElement(pDb->interp, pCmd, ++ Tcl_NewWideIntObj((Tcl_WideInt)pStmt)); ++ Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT); ++ Tcl_DecrRefCount(pCmd); ++ Tcl_ResetResult(pDb->interp); ++ break; ++ } ++ case SQLITE_TRACE_CLOSE: { ++ sqlite3 *db = (sqlite3 *)pd; ++ ++ pCmd = Tcl_NewStringObj(pDb->zTraceV2, -1); ++ Tcl_IncrRefCount(pCmd); ++ Tcl_ListObjAppendElement(pDb->interp, pCmd, ++ Tcl_NewWideIntObj((Tcl_WideInt)db)); ++ Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT); ++ Tcl_DecrRefCount(pCmd); ++ Tcl_ResetResult(pDb->interp); ++ break; ++ } ++ } ++ return SQLITE_OK; ++} ++#endif ++ ++#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) && \ ++ !defined(SQLITE_OMIT_DEPRECATED) ++/* ++** This routine is called by the SQLite profile handler after a statement ++** SQL has executed. The TCL script in pDb->zProfile is evaluated. ++*/ ++static void DbProfileHandler(void *cd, const char *zSql, sqlite_uint64 tm){ ++ SqliteDb *pDb = (SqliteDb*)cd; ++ Tcl_DString str; ++ char zTm[100]; ++ ++ sqlite3_snprintf(sizeof(zTm)-1, zTm, "%lld", tm); ++ Tcl_DStringInit(&str); ++ Tcl_DStringAppend(&str, pDb->zProfile, -1); ++ Tcl_DStringAppendElement(&str, zSql); ++ Tcl_DStringAppendElement(&str, zTm); ++ Tcl_Eval(pDb->interp, Tcl_DStringValue(&str)); ++ Tcl_DStringFree(&str); ++ Tcl_ResetResult(pDb->interp); ++} ++#endif ++ ++/* ++** This routine is called when a transaction is committed. The ++** TCL script in pDb->zCommit is executed. If it returns non-zero or ++** if it throws an exception, the transaction is rolled back instead ++** of being committed. ++*/ ++static int DbCommitHandler(void *cd){ ++ SqliteDb *pDb = (SqliteDb*)cd; ++ int rc; ++ ++ rc = Tcl_Eval(pDb->interp, pDb->zCommit); ++ if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){ ++ return 1; ++ } ++ return 0; ++} ++ ++static void DbRollbackHandler(void *clientData){ ++ SqliteDb *pDb = (SqliteDb*)clientData; ++ assert(pDb->pRollbackHook); ++ if( TCL_OK!=Tcl_EvalObjEx(pDb->interp, pDb->pRollbackHook, 0) ){ ++ Tcl_BackgroundError(pDb->interp); ++ } ++} ++ ++/* ++** This procedure handles wal_hook callbacks. ++*/ ++static int DbWalHandler( ++ void *clientData, ++ sqlite3 *db, ++ const char *zDb, ++ int nEntry ++){ ++ int ret = SQLITE_OK; ++ Tcl_Obj *p; ++ SqliteDb *pDb = (SqliteDb*)clientData; ++ Tcl_Interp *interp = pDb->interp; ++ assert(pDb->pWalHook); ++ ++ assert( db==pDb->db ); ++ p = Tcl_DuplicateObj(pDb->pWalHook); ++ Tcl_IncrRefCount(p); ++ Tcl_ListObjAppendElement(interp, p, Tcl_NewStringObj(zDb, -1)); ++ Tcl_ListObjAppendElement(interp, p, Tcl_NewIntObj(nEntry)); ++ if( TCL_OK!=Tcl_EvalObjEx(interp, p, 0) ++ || TCL_OK!=Tcl_GetIntFromObj(interp, Tcl_GetObjResult(interp), &ret) ++ ){ ++ Tcl_BackgroundError(interp); ++ } ++ Tcl_DecrRefCount(p); ++ ++ return ret; ++} ++ ++#if defined(SQLITE_TEST) && defined(SQLITE_ENABLE_UNLOCK_NOTIFY) ++static void setTestUnlockNotifyVars(Tcl_Interp *interp, int iArg, int nArg){ ++ char zBuf[64]; ++ sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", iArg); ++ Tcl_SetVar(interp, "sqlite_unlock_notify_arg", zBuf, TCL_GLOBAL_ONLY); ++ sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nArg); ++ Tcl_SetVar(interp, "sqlite_unlock_notify_argcount", zBuf, TCL_GLOBAL_ONLY); ++} ++#else ++# define setTestUnlockNotifyVars(x,y,z) ++#endif ++ ++#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY ++static void DbUnlockNotify(void **apArg, int nArg){ ++ int i; ++ for(i=0; i<nArg; i++){ ++ const int flags = (TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT); ++ SqliteDb *pDb = (SqliteDb *)apArg[i]; ++ setTestUnlockNotifyVars(pDb->interp, i, nArg); ++ assert( pDb->pUnlockNotify); ++ Tcl_EvalObjEx(pDb->interp, pDb->pUnlockNotify, flags); ++ Tcl_DecrRefCount(pDb->pUnlockNotify); ++ pDb->pUnlockNotify = 0; ++ } ++} ++#endif ++ ++#ifdef SQLITE_ENABLE_PREUPDATE_HOOK ++/* ++** Pre-update hook callback. ++*/ ++static void DbPreUpdateHandler( ++ void *p, ++ sqlite3 *db, ++ int op, ++ const char *zDb, ++ const char *zTbl, ++ sqlite_int64 iKey1, ++ sqlite_int64 iKey2 ++){ ++ SqliteDb *pDb = (SqliteDb *)p; ++ Tcl_Obj *pCmd; ++ static const char *azStr[] = {"DELETE", "INSERT", "UPDATE"}; ++ ++ assert( (SQLITE_DELETE-1)/9 == 0 ); ++ assert( (SQLITE_INSERT-1)/9 == 1 ); ++ assert( (SQLITE_UPDATE-1)/9 == 2 ); ++ assert( pDb->pPreUpdateHook ); ++ assert( db==pDb->db ); ++ assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE ); ++ ++ pCmd = Tcl_DuplicateObj(pDb->pPreUpdateHook); ++ Tcl_IncrRefCount(pCmd); ++ Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(azStr[(op-1)/9], -1)); ++ Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zDb, -1)); ++ Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zTbl, -1)); ++ Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(iKey1)); ++ Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(iKey2)); ++ Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT); ++ Tcl_DecrRefCount(pCmd); ++} ++#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ ++ ++static void DbUpdateHandler( ++ void *p, ++ int op, ++ const char *zDb, ++ const char *zTbl, ++ sqlite_int64 rowid ++){ ++ SqliteDb *pDb = (SqliteDb *)p; ++ Tcl_Obj *pCmd; ++ static const char *azStr[] = {"DELETE", "INSERT", "UPDATE"}; ++ ++ assert( (SQLITE_DELETE-1)/9 == 0 ); ++ assert( (SQLITE_INSERT-1)/9 == 1 ); ++ assert( (SQLITE_UPDATE-1)/9 == 2 ); ++ ++ assert( pDb->pUpdateHook ); ++ assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE ); ++ ++ pCmd = Tcl_DuplicateObj(pDb->pUpdateHook); ++ Tcl_IncrRefCount(pCmd); ++ Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(azStr[(op-1)/9], -1)); ++ Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zDb, -1)); ++ Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zTbl, -1)); ++ Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(rowid)); ++ Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT); ++ Tcl_DecrRefCount(pCmd); ++} ++ ++static void tclCollateNeeded( ++ void *pCtx, ++ sqlite3 *db, ++ int enc, ++ const char *zName ++){ ++ SqliteDb *pDb = (SqliteDb *)pCtx; ++ Tcl_Obj *pScript = Tcl_DuplicateObj(pDb->pCollateNeeded); ++ Tcl_IncrRefCount(pScript); ++ Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj(zName, -1)); ++ Tcl_EvalObjEx(pDb->interp, pScript, 0); ++ Tcl_DecrRefCount(pScript); ++} ++ ++/* ++** This routine is called to evaluate an SQL collation function implemented ++** using TCL script. ++*/ ++static int tclSqlCollate( ++ void *pCtx, ++ int nA, ++ const void *zA, ++ int nB, ++ const void *zB ++){ ++ SqlCollate *p = (SqlCollate *)pCtx; ++ Tcl_Obj *pCmd; ++ ++ pCmd = Tcl_NewStringObj(p->zScript, -1); ++ Tcl_IncrRefCount(pCmd); ++ Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zA, nA)); ++ Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zB, nB)); ++ Tcl_EvalObjEx(p->interp, pCmd, TCL_EVAL_DIRECT); ++ Tcl_DecrRefCount(pCmd); ++ return (atoi(Tcl_GetStringResult(p->interp))); ++} ++ ++/* ++** This routine is called to evaluate an SQL function implemented ++** using TCL script. ++*/ ++static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){ ++ SqlFunc *p = sqlite3_user_data(context); ++ Tcl_Obj *pCmd; ++ int i; ++ int rc; ++ ++ if( argc==0 ){ ++ /* If there are no arguments to the function, call Tcl_EvalObjEx on the ++ ** script object directly. This allows the TCL compiler to generate ++ ** bytecode for the command on the first invocation and thus make ++ ** subsequent invocations much faster. */ ++ pCmd = p->pScript; ++ Tcl_IncrRefCount(pCmd); ++ rc = Tcl_EvalObjEx(p->interp, pCmd, 0); ++ Tcl_DecrRefCount(pCmd); ++ }else{ ++ /* If there are arguments to the function, make a shallow copy of the ++ ** script object, lappend the arguments, then evaluate the copy. ++ ** ++ ** By "shallow" copy, we mean only the outer list Tcl_Obj is duplicated. ++ ** The new Tcl_Obj contains pointers to the original list elements. ++ ** That way, when Tcl_EvalObjv() is run and shimmers the first element ++ ** of the list to tclCmdNameType, that alternate representation will ++ ** be preserved and reused on the next invocation. ++ */ ++ Tcl_Obj **aArg; ++ int nArg; ++ if( Tcl_ListObjGetElements(p->interp, p->pScript, &nArg, &aArg) ){ ++ sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1); ++ return; ++ } ++ pCmd = Tcl_NewListObj(nArg, aArg); ++ Tcl_IncrRefCount(pCmd); ++ for(i=0; i<argc; i++){ ++ sqlite3_value *pIn = argv[i]; ++ Tcl_Obj *pVal; ++ ++ /* Set pVal to contain the i'th column of this row. */ ++ switch( sqlite3_value_type(pIn) ){ ++ case SQLITE_BLOB: { ++ int bytes = sqlite3_value_bytes(pIn); ++ pVal = Tcl_NewByteArrayObj(sqlite3_value_blob(pIn), bytes); ++ break; ++ } ++ case SQLITE_INTEGER: { ++ sqlite_int64 v = sqlite3_value_int64(pIn); ++ if( v>=-2147483647 && v<=2147483647 ){ ++ pVal = Tcl_NewIntObj((int)v); ++ }else{ ++ pVal = Tcl_NewWideIntObj(v); ++ } ++ break; ++ } ++ case SQLITE_FLOAT: { ++ double r = sqlite3_value_double(pIn); ++ pVal = Tcl_NewDoubleObj(r); ++ break; ++ } ++ case SQLITE_NULL: { ++ pVal = Tcl_NewStringObj(p->pDb->zNull, -1); ++ break; ++ } ++ default: { ++ int bytes = sqlite3_value_bytes(pIn); ++ pVal = Tcl_NewStringObj((char *)sqlite3_value_text(pIn), bytes); ++ break; ++ } ++ } ++ rc = Tcl_ListObjAppendElement(p->interp, pCmd, pVal); ++ if( rc ){ ++ Tcl_DecrRefCount(pCmd); ++ sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1); ++ return; ++ } ++ } ++ if( !p->useEvalObjv ){ ++ /* Tcl_EvalObjEx() will automatically call Tcl_EvalObjv() if pCmd ++ ** is a list without a string representation. To prevent this from ++ ** happening, make sure pCmd has a valid string representation */ ++ Tcl_GetString(pCmd); ++ } ++ rc = Tcl_EvalObjEx(p->interp, pCmd, TCL_EVAL_DIRECT); ++ Tcl_DecrRefCount(pCmd); ++ } ++ ++ if( rc && rc!=TCL_RETURN ){ ++ sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1); ++ }else{ ++ Tcl_Obj *pVar = Tcl_GetObjResult(p->interp); ++ int n; ++ u8 *data; ++ const char *zType = (pVar->typePtr ? pVar->typePtr->name : ""); ++ char c = zType[0]; ++ if( c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0 ){ ++ /* Only return a BLOB type if the Tcl variable is a bytearray and ++ ** has no string representation. */ ++ data = Tcl_GetByteArrayFromObj(pVar, &n); ++ sqlite3_result_blob(context, data, n, SQLITE_TRANSIENT); ++ }else if( c=='b' && strcmp(zType,"boolean")==0 ){ ++ Tcl_GetIntFromObj(0, pVar, &n); ++ sqlite3_result_int(context, n); ++ }else if( c=='d' && strcmp(zType,"double")==0 ){ ++ double r; ++ Tcl_GetDoubleFromObj(0, pVar, &r); ++ sqlite3_result_double(context, r); ++ }else if( (c=='w' && strcmp(zType,"wideInt")==0) || ++ (c=='i' && strcmp(zType,"int")==0) ){ ++ Tcl_WideInt v; ++ Tcl_GetWideIntFromObj(0, pVar, &v); ++ sqlite3_result_int64(context, v); ++ }else{ ++ data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n); ++ sqlite3_result_text(context, (char *)data, n, SQLITE_TRANSIENT); ++ } ++ } ++} ++ ++#ifndef SQLITE_OMIT_AUTHORIZATION ++/* ++** This is the authentication function. It appends the authentication ++** type code and the two arguments to zCmd[] then invokes the result ++** on the interpreter. The reply is examined to determine if the ++** authentication fails or succeeds. ++*/ ++static int auth_callback( ++ void *pArg, ++ int code, ++ const char *zArg1, ++ const char *zArg2, ++ const char *zArg3, ++ const char *zArg4 ++#ifdef SQLITE_USER_AUTHENTICATION ++ ,const char *zArg5 ++#endif ++){ ++ const char *zCode; ++ Tcl_DString str; ++ int rc; ++ const char *zReply; ++ /* EVIDENCE-OF: R-38590-62769 The first parameter to the authorizer ++ ** callback is a copy of the third parameter to the ++ ** sqlite3_set_authorizer() interface. ++ */ ++ SqliteDb *pDb = (SqliteDb*)pArg; ++ if( pDb->disableAuth ) return SQLITE_OK; ++ ++ /* EVIDENCE-OF: R-56518-44310 The second parameter to the callback is an ++ ** integer action code that specifies the particular action to be ++ ** authorized. */ ++ switch( code ){ ++ case SQLITE_COPY : zCode="SQLITE_COPY"; break; ++ case SQLITE_CREATE_INDEX : zCode="SQLITE_CREATE_INDEX"; break; ++ case SQLITE_CREATE_TABLE : zCode="SQLITE_CREATE_TABLE"; break; ++ case SQLITE_CREATE_TEMP_INDEX : zCode="SQLITE_CREATE_TEMP_INDEX"; break; ++ case SQLITE_CREATE_TEMP_TABLE : zCode="SQLITE_CREATE_TEMP_TABLE"; break; ++ case SQLITE_CREATE_TEMP_TRIGGER: zCode="SQLITE_CREATE_TEMP_TRIGGER"; break; ++ case SQLITE_CREATE_TEMP_VIEW : zCode="SQLITE_CREATE_TEMP_VIEW"; break; ++ case SQLITE_CREATE_TRIGGER : zCode="SQLITE_CREATE_TRIGGER"; break; ++ case SQLITE_CREATE_VIEW : zCode="SQLITE_CREATE_VIEW"; break; ++ case SQLITE_DELETE : zCode="SQLITE_DELETE"; break; ++ case SQLITE_DROP_INDEX : zCode="SQLITE_DROP_INDEX"; break; ++ case SQLITE_DROP_TABLE : zCode="SQLITE_DROP_TABLE"; break; ++ case SQLITE_DROP_TEMP_INDEX : zCode="SQLITE_DROP_TEMP_INDEX"; break; ++ case SQLITE_DROP_TEMP_TABLE : zCode="SQLITE_DROP_TEMP_TABLE"; break; ++ case SQLITE_DROP_TEMP_TRIGGER : zCode="SQLITE_DROP_TEMP_TRIGGER"; break; ++ case SQLITE_DROP_TEMP_VIEW : zCode="SQLITE_DROP_TEMP_VIEW"; break; ++ case SQLITE_DROP_TRIGGER : zCode="SQLITE_DROP_TRIGGER"; break; ++ case SQLITE_DROP_VIEW : zCode="SQLITE_DROP_VIEW"; break; ++ case SQLITE_INSERT : zCode="SQLITE_INSERT"; break; ++ case SQLITE_PRAGMA : zCode="SQLITE_PRAGMA"; break; ++ case SQLITE_READ : zCode="SQLITE_READ"; break; ++ case SQLITE_SELECT : zCode="SQLITE_SELECT"; break; ++ case SQLITE_TRANSACTION : zCode="SQLITE_TRANSACTION"; break; ++ case SQLITE_UPDATE : zCode="SQLITE_UPDATE"; break; ++ case SQLITE_ATTACH : zCode="SQLITE_ATTACH"; break; ++ case SQLITE_DETACH : zCode="SQLITE_DETACH"; break; ++ case SQLITE_ALTER_TABLE : zCode="SQLITE_ALTER_TABLE"; break; ++ case SQLITE_REINDEX : zCode="SQLITE_REINDEX"; break; ++ case SQLITE_ANALYZE : zCode="SQLITE_ANALYZE"; break; ++ case SQLITE_CREATE_VTABLE : zCode="SQLITE_CREATE_VTABLE"; break; ++ case SQLITE_DROP_VTABLE : zCode="SQLITE_DROP_VTABLE"; break; ++ case SQLITE_FUNCTION : zCode="SQLITE_FUNCTION"; break; ++ case SQLITE_SAVEPOINT : zCode="SQLITE_SAVEPOINT"; break; ++ case SQLITE_RECURSIVE : zCode="SQLITE_RECURSIVE"; break; ++ default : zCode="????"; break; ++ } ++ Tcl_DStringInit(&str); ++ Tcl_DStringAppend(&str, pDb->zAuth, -1); ++ Tcl_DStringAppendElement(&str, zCode); ++ Tcl_DStringAppendElement(&str, zArg1 ? zArg1 : ""); ++ Tcl_DStringAppendElement(&str, zArg2 ? zArg2 : ""); ++ Tcl_DStringAppendElement(&str, zArg3 ? zArg3 : ""); ++ Tcl_DStringAppendElement(&str, zArg4 ? zArg4 : ""); ++#ifdef SQLITE_USER_AUTHENTICATION ++ Tcl_DStringAppendElement(&str, zArg5 ? zArg5 : ""); ++#endif ++ rc = Tcl_GlobalEval(pDb->interp, Tcl_DStringValue(&str)); ++ Tcl_DStringFree(&str); ++ zReply = rc==TCL_OK ? Tcl_GetStringResult(pDb->interp) : "SQLITE_DENY"; ++ if( strcmp(zReply,"SQLITE_OK")==0 ){ ++ rc = SQLITE_OK; ++ }else if( strcmp(zReply,"SQLITE_DENY")==0 ){ ++ rc = SQLITE_DENY; ++ }else if( strcmp(zReply,"SQLITE_IGNORE")==0 ){ ++ rc = SQLITE_IGNORE; ++ }else{ ++ rc = 999; ++ } ++ return rc; ++} ++#endif /* SQLITE_OMIT_AUTHORIZATION */ ++ ++/* ++** This routine reads a line of text from FILE in, stores ++** the text in memory obtained from malloc() and returns a pointer ++** to the text. NULL is returned at end of file, or if malloc() ++** fails. ++** ++** The interface is like "readline" but no command-line editing ++** is done. ++** ++** copied from shell.c from '.import' command ++*/ ++static char *local_getline(char *zPrompt, FILE *in){ ++ char *zLine; ++ int nLine; ++ int n; ++ ++ nLine = 100; ++ zLine = malloc( nLine ); ++ if( zLine==0 ) return 0; ++ n = 0; ++ while( 1 ){ ++ if( n+100>nLine ){ ++ nLine = nLine*2 + 100; ++ zLine = realloc(zLine, nLine); ++ if( zLine==0 ) return 0; ++ } ++ if( fgets(&zLine[n], nLine - n, in)==0 ){ ++ if( n==0 ){ ++ free(zLine); ++ return 0; ++ } ++ zLine[n] = 0; ++ break; ++ } ++ while( zLine[n] ){ n++; } ++ if( n>0 && zLine[n-1]=='\n' ){ ++ n--; ++ zLine[n] = 0; ++ break; ++ } ++ } ++ zLine = realloc( zLine, n+1 ); ++ return zLine; ++} ++ ++ ++/* ++** This function is part of the implementation of the command: ++** ++** $db transaction [-deferred|-immediate|-exclusive] SCRIPT ++** ++** It is invoked after evaluating the script SCRIPT to commit or rollback ++** the transaction or savepoint opened by the [transaction] command. ++*/ ++static int SQLITE_TCLAPI DbTransPostCmd( ++ ClientData data[], /* data[0] is the Sqlite3Db* for $db */ ++ Tcl_Interp *interp, /* Tcl interpreter */ ++ int result /* Result of evaluating SCRIPT */ ++){ ++ static const char *const azEnd[] = { ++ "RELEASE _tcl_transaction", /* rc==TCL_ERROR, nTransaction!=0 */ ++ "COMMIT", /* rc!=TCL_ERROR, nTransaction==0 */ ++ "ROLLBACK TO _tcl_transaction ; RELEASE _tcl_transaction", ++ "ROLLBACK" /* rc==TCL_ERROR, nTransaction==0 */ ++ }; ++ SqliteDb *pDb = (SqliteDb*)data[0]; ++ int rc = result; ++ const char *zEnd; ++ ++ pDb->nTransaction--; ++ zEnd = azEnd[(rc==TCL_ERROR)*2 + (pDb->nTransaction==0)]; ++ ++ pDb->disableAuth++; ++ if( sqlite3_exec(pDb->db, zEnd, 0, 0, 0) ){ ++ /* This is a tricky scenario to handle. The most likely cause of an ++ ** error is that the exec() above was an attempt to commit the ++ ** top-level transaction that returned SQLITE_BUSY. Or, less likely, ++ ** that an IO-error has occurred. In either case, throw a Tcl exception ++ ** and try to rollback the transaction. ++ ** ++ ** But it could also be that the user executed one or more BEGIN, ++ ** COMMIT, SAVEPOINT, RELEASE or ROLLBACK commands that are confusing ++ ** this method's logic. Not clear how this would be best handled. ++ */ ++ if( rc!=TCL_ERROR ){ ++ Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0); ++ rc = TCL_ERROR; ++ } ++ sqlite3_exec(pDb->db, "ROLLBACK", 0, 0, 0); ++ } ++ pDb->disableAuth--; ++ ++ return rc; ++} ++ ++/* ++** Unless SQLITE_TEST is defined, this function is a simple wrapper around ++** sqlite3_prepare_v2(). If SQLITE_TEST is defined, then it uses either ++** sqlite3_prepare_v2() or legacy interface sqlite3_prepare(), depending ++** on whether or not the [db_use_legacy_prepare] command has been used to ++** configure the connection. ++*/ ++static int dbPrepare( ++ SqliteDb *pDb, /* Database object */ ++ const char *zSql, /* SQL to compile */ ++ sqlite3_stmt **ppStmt, /* OUT: Prepared statement */ ++ const char **pzOut /* OUT: Pointer to next SQL statement */ ++){ ++ unsigned int prepFlags = 0; ++#ifdef SQLITE_TEST ++ if( pDb->bLegacyPrepare ){ ++ return sqlite3_prepare(pDb->db, zSql, -1, ppStmt, pzOut); ++ } ++#endif ++ /* If the statement cache is large, use the SQLITE_PREPARE_PERSISTENT ++ ** flags, which uses less lookaside memory. But if the cache is small, ++ ** omit that flag to make full use of lookaside */ ++ if( pDb->maxStmt>5 ) prepFlags = SQLITE_PREPARE_PERSISTENT; ++ ++ return sqlite3_prepare_v3(pDb->db, zSql, -1, prepFlags, ppStmt, pzOut); ++} ++ ++/* ++** Search the cache for a prepared-statement object that implements the ++** first SQL statement in the buffer pointed to by parameter zIn. If ++** no such prepared-statement can be found, allocate and prepare a new ++** one. In either case, bind the current values of the relevant Tcl ++** variables to any $var, :var or @var variables in the statement. Before ++** returning, set *ppPreStmt to point to the prepared-statement object. ++** ++** Output parameter *pzOut is set to point to the next SQL statement in ++** buffer zIn, or to the '\0' byte at the end of zIn if there is no ++** next statement. ++** ++** If successful, TCL_OK is returned. Otherwise, TCL_ERROR is returned ++** and an error message loaded into interpreter pDb->interp. ++*/ ++static int dbPrepareAndBind( ++ SqliteDb *pDb, /* Database object */ ++ char const *zIn, /* SQL to compile */ ++ char const **pzOut, /* OUT: Pointer to next SQL statement */ ++ SqlPreparedStmt **ppPreStmt /* OUT: Object used to cache statement */ ++){ ++ const char *zSql = zIn; /* Pointer to first SQL statement in zIn */ ++ sqlite3_stmt *pStmt = 0; /* Prepared statement object */ ++ SqlPreparedStmt *pPreStmt; /* Pointer to cached statement */ ++ int nSql; /* Length of zSql in bytes */ ++ int nVar = 0; /* Number of variables in statement */ ++ int iParm = 0; /* Next free entry in apParm */ ++ char c; ++ int i; ++ Tcl_Interp *interp = pDb->interp; ++ ++ *ppPreStmt = 0; ++ ++ /* Trim spaces from the start of zSql and calculate the remaining length. */ ++ while( (c = zSql[0])==' ' || c=='\t' || c=='\r' || c=='\n' ){ zSql++; } ++ nSql = strlen30(zSql); ++ ++ for(pPreStmt = pDb->stmtList; pPreStmt; pPreStmt=pPreStmt->pNext){ ++ int n = pPreStmt->nSql; ++ if( nSql>=n ++ && memcmp(pPreStmt->zSql, zSql, n)==0 ++ && (zSql[n]==0 || zSql[n-1]==';') ++ ){ ++ pStmt = pPreStmt->pStmt; ++ *pzOut = &zSql[pPreStmt->nSql]; ++ ++ /* When a prepared statement is found, unlink it from the ++ ** cache list. It will later be added back to the beginning ++ ** of the cache list in order to implement LRU replacement. ++ */ ++ if( pPreStmt->pPrev ){ ++ pPreStmt->pPrev->pNext = pPreStmt->pNext; ++ }else{ ++ pDb->stmtList = pPreStmt->pNext; ++ } ++ if( pPreStmt->pNext ){ ++ pPreStmt->pNext->pPrev = pPreStmt->pPrev; ++ }else{ ++ pDb->stmtLast = pPreStmt->pPrev; ++ } ++ pDb->nStmt--; ++ nVar = sqlite3_bind_parameter_count(pStmt); ++ break; ++ } ++ } ++ ++ /* If no prepared statement was found. Compile the SQL text. Also allocate ++ ** a new SqlPreparedStmt structure. */ ++ if( pPreStmt==0 ){ ++ int nByte; ++ ++ if( SQLITE_OK!=dbPrepare(pDb, zSql, &pStmt, pzOut) ){ ++ Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1)); ++ return TCL_ERROR; ++ } ++ if( pStmt==0 ){ ++ if( SQLITE_OK!=sqlite3_errcode(pDb->db) ){ ++ /* A compile-time error in the statement. */ ++ Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1)); ++ return TCL_ERROR; ++ }else{ ++ /* The statement was a no-op. Continue to the next statement ++ ** in the SQL string. ++ */ ++ return TCL_OK; ++ } ++ } ++ ++ assert( pPreStmt==0 ); ++ nVar = sqlite3_bind_parameter_count(pStmt); ++ nByte = sizeof(SqlPreparedStmt) + nVar*sizeof(Tcl_Obj *); ++ pPreStmt = (SqlPreparedStmt*)Tcl_Alloc(nByte); ++ memset(pPreStmt, 0, nByte); ++ ++ pPreStmt->pStmt = pStmt; ++ pPreStmt->nSql = (int)(*pzOut - zSql); ++ pPreStmt->zSql = sqlite3_sql(pStmt); ++ pPreStmt->apParm = (Tcl_Obj **)&pPreStmt[1]; ++#ifdef SQLITE_TEST ++ if( pPreStmt->zSql==0 ){ ++ char *zCopy = Tcl_Alloc(pPreStmt->nSql + 1); ++ memcpy(zCopy, zSql, pPreStmt->nSql); ++ zCopy[pPreStmt->nSql] = '\0'; ++ pPreStmt->zSql = zCopy; ++ } ++#endif ++ } ++ assert( pPreStmt ); ++ assert( strlen30(pPreStmt->zSql)==pPreStmt->nSql ); ++ assert( 0==memcmp(pPreStmt->zSql, zSql, pPreStmt->nSql) ); ++ ++ /* Bind values to parameters that begin with $ or : */ ++ for(i=1; i<=nVar; i++){ ++ const char *zVar = sqlite3_bind_parameter_name(pStmt, i); ++ if( zVar!=0 && (zVar[0]=='$' || zVar[0]==':' || zVar[0]=='@') ){ ++ Tcl_Obj *pVar = Tcl_GetVar2Ex(interp, &zVar[1], 0, 0); ++ if( pVar ){ ++ int n; ++ u8 *data; ++ const char *zType = (pVar->typePtr ? pVar->typePtr->name : ""); ++ c = zType[0]; ++ if( zVar[0]=='@' || ++ (c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0) ){ ++ /* Load a BLOB type if the Tcl variable is a bytearray and ++ ** it has no string representation or the host ++ ** parameter name begins with "@". */ ++ data = Tcl_GetByteArrayFromObj(pVar, &n); ++ sqlite3_bind_blob(pStmt, i, data, n, SQLITE_STATIC); ++ Tcl_IncrRefCount(pVar); ++ pPreStmt->apParm[iParm++] = pVar; ++ }else if( c=='b' && strcmp(zType,"boolean")==0 ){ ++ Tcl_GetIntFromObj(interp, pVar, &n); ++ sqlite3_bind_int(pStmt, i, n); ++ }else if( c=='d' && strcmp(zType,"double")==0 ){ ++ double r; ++ Tcl_GetDoubleFromObj(interp, pVar, &r); ++ sqlite3_bind_double(pStmt, i, r); ++ }else if( (c=='w' && strcmp(zType,"wideInt")==0) || ++ (c=='i' && strcmp(zType,"int")==0) ){ ++ Tcl_WideInt v; ++ Tcl_GetWideIntFromObj(interp, pVar, &v); ++ sqlite3_bind_int64(pStmt, i, v); ++ }else{ ++ data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n); ++ sqlite3_bind_text(pStmt, i, (char *)data, n, SQLITE_STATIC); ++ Tcl_IncrRefCount(pVar); ++ pPreStmt->apParm[iParm++] = pVar; ++ } ++ }else{ ++ sqlite3_bind_null(pStmt, i); ++ } ++ } ++ } ++ pPreStmt->nParm = iParm; ++ *ppPreStmt = pPreStmt; ++ ++ return TCL_OK; ++} ++ ++/* ++** Release a statement reference obtained by calling dbPrepareAndBind(). ++** There should be exactly one call to this function for each call to ++** dbPrepareAndBind(). ++** ++** If the discard parameter is non-zero, then the statement is deleted ++** immediately. Otherwise it is added to the LRU list and may be returned ++** by a subsequent call to dbPrepareAndBind(). ++*/ ++static void dbReleaseStmt( ++ SqliteDb *pDb, /* Database handle */ ++ SqlPreparedStmt *pPreStmt, /* Prepared statement handle to release */ ++ int discard /* True to delete (not cache) the pPreStmt */ ++){ ++ int i; ++ ++ /* Free the bound string and blob parameters */ ++ for(i=0; i<pPreStmt->nParm; i++){ ++ Tcl_DecrRefCount(pPreStmt->apParm[i]); ++ } ++ pPreStmt->nParm = 0; ++ ++ if( pDb->maxStmt<=0 || discard ){ ++ /* If the cache is turned off, deallocated the statement */ ++ dbFreeStmt(pPreStmt); ++ }else{ ++ /* Add the prepared statement to the beginning of the cache list. */ ++ pPreStmt->pNext = pDb->stmtList; ++ pPreStmt->pPrev = 0; ++ if( pDb->stmtList ){ ++ pDb->stmtList->pPrev = pPreStmt; ++ } ++ pDb->stmtList = pPreStmt; ++ if( pDb->stmtLast==0 ){ ++ assert( pDb->nStmt==0 ); ++ pDb->stmtLast = pPreStmt; ++ }else{ ++ assert( pDb->nStmt>0 ); ++ } ++ pDb->nStmt++; ++ ++ /* If we have too many statement in cache, remove the surplus from ++ ** the end of the cache list. */ ++ while( pDb->nStmt>pDb->maxStmt ){ ++ SqlPreparedStmt *pLast = pDb->stmtLast; ++ pDb->stmtLast = pLast->pPrev; ++ pDb->stmtLast->pNext = 0; ++ pDb->nStmt--; ++ dbFreeStmt(pLast); ++ } ++ } ++} ++ ++/* ++** Structure used with dbEvalXXX() functions: ++** ++** dbEvalInit() ++** dbEvalStep() ++** dbEvalFinalize() ++** dbEvalRowInfo() ++** dbEvalColumnValue() ++*/ ++typedef struct DbEvalContext DbEvalContext; ++struct DbEvalContext { ++ SqliteDb *pDb; /* Database handle */ ++ Tcl_Obj *pSql; /* Object holding string zSql */ ++ const char *zSql; /* Remaining SQL to execute */ ++ SqlPreparedStmt *pPreStmt; /* Current statement */ ++ int nCol; /* Number of columns returned by pStmt */ ++ int evalFlags; /* Flags used */ ++ Tcl_Obj *pArray; /* Name of array variable */ ++ Tcl_Obj **apColName; /* Array of column names */ ++}; ++ ++#define SQLITE_EVAL_WITHOUTNULLS 0x00001 /* Unset array(*) for NULL */ ++ ++/* ++** Release any cache of column names currently held as part of ++** the DbEvalContext structure passed as the first argument. ++*/ ++static void dbReleaseColumnNames(DbEvalContext *p){ ++ if( p->apColName ){ ++ int i; ++ for(i=0; i<p->nCol; i++){ ++ Tcl_DecrRefCount(p->apColName[i]); ++ } ++ Tcl_Free((char *)p->apColName); ++ p->apColName = 0; ++ } ++ p->nCol = 0; ++} ++ ++/* ++** Initialize a DbEvalContext structure. ++** ++** If pArray is not NULL, then it contains the name of a Tcl array ++** variable. The "*" member of this array is set to a list containing ++** the names of the columns returned by the statement as part of each ++** call to dbEvalStep(), in order from left to right. e.g. if the names ++** of the returned columns are a, b and c, it does the equivalent of the ++** tcl command: ++** ++** set ${pArray}(*) {a b c} ++*/ ++static void dbEvalInit( ++ DbEvalContext *p, /* Pointer to structure to initialize */ ++ SqliteDb *pDb, /* Database handle */ ++ Tcl_Obj *pSql, /* Object containing SQL script */ ++ Tcl_Obj *pArray, /* Name of Tcl array to set (*) element of */ ++ int evalFlags /* Flags controlling evaluation */ ++){ ++ memset(p, 0, sizeof(DbEvalContext)); ++ p->pDb = pDb; ++ p->zSql = Tcl_GetString(pSql); ++ p->pSql = pSql; ++ Tcl_IncrRefCount(pSql); ++ if( pArray ){ ++ p->pArray = pArray; ++ Tcl_IncrRefCount(pArray); ++ } ++ p->evalFlags = evalFlags; ++} ++ ++/* ++** Obtain information about the row that the DbEvalContext passed as the ++** first argument currently points to. ++*/ ++static void dbEvalRowInfo( ++ DbEvalContext *p, /* Evaluation context */ ++ int *pnCol, /* OUT: Number of column names */ ++ Tcl_Obj ***papColName /* OUT: Array of column names */ ++){ ++ /* Compute column names */ ++ if( 0==p->apColName ){ ++ sqlite3_stmt *pStmt = p->pPreStmt->pStmt; ++ int i; /* Iterator variable */ ++ int nCol; /* Number of columns returned by pStmt */ ++ Tcl_Obj **apColName = 0; /* Array of column names */ ++ ++ p->nCol = nCol = sqlite3_column_count(pStmt); ++ if( nCol>0 && (papColName || p->pArray) ){ ++ apColName = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*)*nCol ); ++ for(i=0; i<nCol; i++){ ++ apColName[i] = Tcl_NewStringObj(sqlite3_column_name(pStmt,i), -1); ++ Tcl_IncrRefCount(apColName[i]); ++ } ++ p->apColName = apColName; ++ } ++ ++ /* If results are being stored in an array variable, then create ++ ** the array(*) entry for that array ++ */ ++ if( p->pArray ){ ++ Tcl_Interp *interp = p->pDb->interp; ++ Tcl_Obj *pColList = Tcl_NewObj(); ++ Tcl_Obj *pStar = Tcl_NewStringObj("*", -1); ++ ++ for(i=0; i<nCol; i++){ ++ Tcl_ListObjAppendElement(interp, pColList, apColName[i]); ++ } ++ Tcl_IncrRefCount(pStar); ++ Tcl_ObjSetVar2(interp, p->pArray, pStar, pColList, 0); ++ Tcl_DecrRefCount(pStar); ++ } ++ } ++ ++ if( papColName ){ ++ *papColName = p->apColName; ++ } ++ if( pnCol ){ ++ *pnCol = p->nCol; ++ } ++} ++ ++/* ++** Return one of TCL_OK, TCL_BREAK or TCL_ERROR. If TCL_ERROR is ++** returned, then an error message is stored in the interpreter before ++** returning. ++** ++** A return value of TCL_OK means there is a row of data available. The ++** data may be accessed using dbEvalRowInfo() and dbEvalColumnValue(). This ++** is analogous to a return of SQLITE_ROW from sqlite3_step(). If TCL_BREAK ++** is returned, then the SQL script has finished executing and there are ++** no further rows available. This is similar to SQLITE_DONE. ++*/ ++static int dbEvalStep(DbEvalContext *p){ ++ const char *zPrevSql = 0; /* Previous value of p->zSql */ ++ ++ while( p->zSql[0] || p->pPreStmt ){ ++ int rc; ++ if( p->pPreStmt==0 ){ ++ zPrevSql = (p->zSql==zPrevSql ? 0 : p->zSql); ++ rc = dbPrepareAndBind(p->pDb, p->zSql, &p->zSql, &p->pPreStmt); ++ if( rc!=TCL_OK ) return rc; ++ }else{ ++ int rcs; ++ SqliteDb *pDb = p->pDb; ++ SqlPreparedStmt *pPreStmt = p->pPreStmt; ++ sqlite3_stmt *pStmt = pPreStmt->pStmt; ++ ++ rcs = sqlite3_step(pStmt); ++ if( rcs==SQLITE_ROW ){ ++ return TCL_OK; ++ } ++ if( p->pArray ){ ++ dbEvalRowInfo(p, 0, 0); ++ } ++ rcs = sqlite3_reset(pStmt); ++ ++ pDb->nStep = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_FULLSCAN_STEP,1); ++ pDb->nSort = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_SORT,1); ++ pDb->nIndex = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_AUTOINDEX,1); ++ pDb->nVMStep = sqlite3_stmt_status(pStmt,SQLITE_STMTSTATUS_VM_STEP,1); ++ dbReleaseColumnNames(p); ++ p->pPreStmt = 0; ++ ++ if( rcs!=SQLITE_OK ){ ++ /* If a run-time error occurs, report the error and stop reading ++ ** the SQL. */ ++ dbReleaseStmt(pDb, pPreStmt, 1); ++#if SQLITE_TEST ++ if( p->pDb->bLegacyPrepare && rcs==SQLITE_SCHEMA && zPrevSql ){ ++ /* If the runtime error was an SQLITE_SCHEMA, and the database ++ ** handle is configured to use the legacy sqlite3_prepare() ++ ** interface, retry prepare()/step() on the same SQL statement. ++ ** This only happens once. If there is a second SQLITE_SCHEMA ++ ** error, the error will be returned to the caller. */ ++ p->zSql = zPrevSql; ++ continue; ++ } ++#endif ++ Tcl_SetObjResult(pDb->interp, ++ Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1)); ++ return TCL_ERROR; ++ }else{ ++ dbReleaseStmt(pDb, pPreStmt, 0); ++ } ++ } ++ } ++ ++ /* Finished */ ++ return TCL_BREAK; ++} ++ ++/* ++** Free all resources currently held by the DbEvalContext structure passed ++** as the first argument. There should be exactly one call to this function ++** for each call to dbEvalInit(). ++*/ ++static void dbEvalFinalize(DbEvalContext *p){ ++ if( p->pPreStmt ){ ++ sqlite3_reset(p->pPreStmt->pStmt); ++ dbReleaseStmt(p->pDb, p->pPreStmt, 0); ++ p->pPreStmt = 0; ++ } ++ if( p->pArray ){ ++ Tcl_DecrRefCount(p->pArray); ++ p->pArray = 0; ++ } ++ Tcl_DecrRefCount(p->pSql); ++ dbReleaseColumnNames(p); ++} ++ ++/* ++** Return a pointer to a Tcl_Obj structure with ref-count 0 that contains ++** the value for the iCol'th column of the row currently pointed to by ++** the DbEvalContext structure passed as the first argument. ++*/ ++static Tcl_Obj *dbEvalColumnValue(DbEvalContext *p, int iCol){ ++ sqlite3_stmt *pStmt = p->pPreStmt->pStmt; ++ switch( sqlite3_column_type(pStmt, iCol) ){ ++ case SQLITE_BLOB: { ++ int bytes = sqlite3_column_bytes(pStmt, iCol); ++ const char *zBlob = sqlite3_column_blob(pStmt, iCol); ++ if( !zBlob ) bytes = 0; ++ return Tcl_NewByteArrayObj((u8*)zBlob, bytes); ++ } ++ case SQLITE_INTEGER: { ++ sqlite_int64 v = sqlite3_column_int64(pStmt, iCol); ++ if( v>=-2147483647 && v<=2147483647 ){ ++ return Tcl_NewIntObj((int)v); ++ }else{ ++ return Tcl_NewWideIntObj(v); ++ } ++ } ++ case SQLITE_FLOAT: { ++ return Tcl_NewDoubleObj(sqlite3_column_double(pStmt, iCol)); ++ } ++ case SQLITE_NULL: { ++ return Tcl_NewStringObj(p->pDb->zNull, -1); ++ } ++ } ++ ++ return Tcl_NewStringObj((char*)sqlite3_column_text(pStmt, iCol), -1); ++} ++ ++/* ++** If using Tcl version 8.6 or greater, use the NR functions to avoid ++** recursive evalution of scripts by the [db eval] and [db trans] ++** commands. Even if the headers used while compiling the extension ++** are 8.6 or newer, the code still tests the Tcl version at runtime. ++** This allows stubs-enabled builds to be used with older Tcl libraries. ++*/ ++#if TCL_MAJOR_VERSION>8 || (TCL_MAJOR_VERSION==8 && TCL_MINOR_VERSION>=6) ++# define SQLITE_TCL_NRE 1 ++static int DbUseNre(void){ ++ int major, minor; ++ Tcl_GetVersion(&major, &minor, 0, 0); ++ return( (major==8 && minor>=6) || major>8 ); ++} ++#else ++/* ++** Compiling using headers earlier than 8.6. In this case NR cannot be ++** used, so DbUseNre() to always return zero. Add #defines for the other ++** Tcl_NRxxx() functions to prevent them from causing compilation errors, ++** even though the only invocations of them are within conditional blocks ++** of the form: ++** ++** if( DbUseNre() ) { ... } ++*/ ++# define SQLITE_TCL_NRE 0 ++# define DbUseNre() 0 ++# define Tcl_NRAddCallback(a,b,c,d,e,f) (void)0 ++# define Tcl_NREvalObj(a,b,c) 0 ++# define Tcl_NRCreateCommand(a,b,c,d,e,f) (void)0 ++#endif ++ ++/* ++** This function is part of the implementation of the command: ++** ++** $db eval SQL ?ARRAYNAME? SCRIPT ++*/ ++static int SQLITE_TCLAPI DbEvalNextCmd( ++ ClientData data[], /* data[0] is the (DbEvalContext*) */ ++ Tcl_Interp *interp, /* Tcl interpreter */ ++ int result /* Result so far */ ++){ ++ int rc = result; /* Return code */ ++ ++ /* The first element of the data[] array is a pointer to a DbEvalContext ++ ** structure allocated using Tcl_Alloc(). The second element of data[] ++ ** is a pointer to a Tcl_Obj containing the script to run for each row ++ ** returned by the queries encapsulated in data[0]. */ ++ DbEvalContext *p = (DbEvalContext *)data[0]; ++ Tcl_Obj *pScript = (Tcl_Obj *)data[1]; ++ Tcl_Obj *pArray = p->pArray; ++ ++ while( (rc==TCL_OK || rc==TCL_CONTINUE) && TCL_OK==(rc = dbEvalStep(p)) ){ ++ int i; ++ int nCol; ++ Tcl_Obj **apColName; ++ dbEvalRowInfo(p, &nCol, &apColName); ++ for(i=0; i<nCol; i++){ ++ if( pArray==0 ){ ++ Tcl_ObjSetVar2(interp, apColName[i], 0, dbEvalColumnValue(p,i), 0); ++ }else if( (p->evalFlags & SQLITE_EVAL_WITHOUTNULLS)!=0 ++ && sqlite3_column_type(p->pPreStmt->pStmt, i)==SQLITE_NULL ++ ){ ++ Tcl_UnsetVar2(interp, Tcl_GetString(pArray), ++ Tcl_GetString(apColName[i]), 0); ++ }else{ ++ Tcl_ObjSetVar2(interp, pArray, apColName[i], dbEvalColumnValue(p,i), 0); ++ } ++ } ++ ++ /* The required interpreter variables are now populated with the data ++ ** from the current row. If using NRE, schedule callbacks to evaluate ++ ** script pScript, then to invoke this function again to fetch the next ++ ** row (or clean up if there is no next row or the script throws an ++ ** exception). After scheduling the callbacks, return control to the ++ ** caller. ++ ** ++ ** If not using NRE, evaluate pScript directly and continue with the ++ ** next iteration of this while(...) loop. */ ++ if( DbUseNre() ){ ++ Tcl_NRAddCallback(interp, DbEvalNextCmd, (void*)p, (void*)pScript, 0, 0); ++ return Tcl_NREvalObj(interp, pScript, 0); ++ }else{ ++ rc = Tcl_EvalObjEx(interp, pScript, 0); ++ } ++ } ++ ++ Tcl_DecrRefCount(pScript); ++ dbEvalFinalize(p); ++ Tcl_Free((char *)p); ++ ++ if( rc==TCL_OK || rc==TCL_BREAK ){ ++ Tcl_ResetResult(interp); ++ rc = TCL_OK; ++ } ++ return rc; ++} ++ ++/* ++** This function is used by the implementations of the following database ++** handle sub-commands: ++** ++** $db update_hook ?SCRIPT? ++** $db wal_hook ?SCRIPT? ++** $db commit_hook ?SCRIPT? ++** $db preupdate hook ?SCRIPT? ++*/ ++static void DbHookCmd( ++ Tcl_Interp *interp, /* Tcl interpreter */ ++ SqliteDb *pDb, /* Database handle */ ++ Tcl_Obj *pArg, /* SCRIPT argument (or NULL) */ ++ Tcl_Obj **ppHook /* Pointer to member of SqliteDb */ ++){ ++ sqlite3 *db = pDb->db; ++ ++ if( *ppHook ){ ++ Tcl_SetObjResult(interp, *ppHook); ++ if( pArg ){ ++ Tcl_DecrRefCount(*ppHook); ++ *ppHook = 0; ++ } ++ } ++ if( pArg ){ ++ assert( !(*ppHook) ); ++ if( Tcl_GetCharLength(pArg)>0 ){ ++ *ppHook = pArg; ++ Tcl_IncrRefCount(*ppHook); ++ } ++ } ++ ++#ifdef SQLITE_ENABLE_PREUPDATE_HOOK ++ sqlite3_preupdate_hook(db, (pDb->pPreUpdateHook?DbPreUpdateHandler:0), pDb); ++#endif ++ sqlite3_update_hook(db, (pDb->pUpdateHook?DbUpdateHandler:0), pDb); ++ sqlite3_rollback_hook(db, (pDb->pRollbackHook?DbRollbackHandler:0), pDb); ++ sqlite3_wal_hook(db, (pDb->pWalHook?DbWalHandler:0), pDb); ++} ++ ++/* ++** The "sqlite" command below creates a new Tcl command for each ++** connection it opens to an SQLite database. This routine is invoked ++** whenever one of those connection-specific commands is executed ++** in Tcl. For example, if you run Tcl code like this: ++** ++** sqlite3 db1 "my_database" ++** db1 close ++** ++** The first command opens a connection to the "my_database" database ++** and calls that connection "db1". The second command causes this ++** subroutine to be invoked. ++*/ ++static int SQLITE_TCLAPI DbObjCmd( ++ void *cd, ++ Tcl_Interp *interp, ++ int objc, ++ Tcl_Obj *const*objv ++){ ++ SqliteDb *pDb = (SqliteDb*)cd; ++ int choice; ++ int rc = TCL_OK; ++ static const char *DB_strs[] = { ++ "authorizer", "backup", "busy", ++ "cache", "changes", "close", ++ "collate", "collation_needed", "commit_hook", ++ "complete", "copy", "deserialize", ++ "enable_load_extension", "errorcode", "eval", ++ "exists", "function", "incrblob", ++ "interrupt", "last_insert_rowid", "nullvalue", ++ "onecolumn", "preupdate", "profile", ++ "progress", "rekey", "restore", ++ "rollback_hook", "serialize", "status", ++ "timeout", "total_changes", "trace", ++ "trace_v2", "transaction", "unlock_notify", ++ "update_hook", "version", "wal_hook", ++ 0 ++ }; ++ enum DB_enum { ++ DB_AUTHORIZER, DB_BACKUP, DB_BUSY, ++ DB_CACHE, DB_CHANGES, DB_CLOSE, ++ DB_COLLATE, DB_COLLATION_NEEDED, DB_COMMIT_HOOK, ++ DB_COMPLETE, DB_COPY, DB_DESERIALIZE, ++ DB_ENABLE_LOAD_EXTENSION, DB_ERRORCODE, DB_EVAL, ++ DB_EXISTS, DB_FUNCTION, DB_INCRBLOB, ++ DB_INTERRUPT, DB_LAST_INSERT_ROWID, DB_NULLVALUE, ++ DB_ONECOLUMN, DB_PREUPDATE, DB_PROFILE, ++ DB_PROGRESS, DB_REKEY, DB_RESTORE, ++ DB_ROLLBACK_HOOK, DB_SERIALIZE, DB_STATUS, ++ DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE, ++ DB_TRACE_V2, DB_TRANSACTION, DB_UNLOCK_NOTIFY, ++ DB_UPDATE_HOOK, DB_VERSION, DB_WAL_HOOK ++ }; ++ /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */ ++ ++ if( objc<2 ){ ++ Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ..."); ++ return TCL_ERROR; ++ } ++ if( Tcl_GetIndexFromObj(interp, objv[1], DB_strs, "option", 0, &choice) ){ ++ return TCL_ERROR; ++ } ++ ++ switch( (enum DB_enum)choice ){ ++ ++ /* $db authorizer ?CALLBACK? ++ ** ++ ** Invoke the given callback to authorize each SQL operation as it is ++ ** compiled. 5 arguments are appended to the callback before it is ++ ** invoked: ++ ** ++ ** (1) The authorization type (ex: SQLITE_CREATE_TABLE, SQLITE_INSERT, ...) ++ ** (2) First descriptive name (depends on authorization type) ++ ** (3) Second descriptive name ++ ** (4) Name of the database (ex: "main", "temp") ++ ** (5) Name of trigger that is doing the access ++ ** ++ ** The callback should return on of the following strings: SQLITE_OK, ++ ** SQLITE_IGNORE, or SQLITE_DENY. Any other return value is an error. ++ ** ++ ** If this method is invoked with no arguments, the current authorization ++ ** callback string is returned. ++ */ ++ case DB_AUTHORIZER: { ++#ifdef SQLITE_OMIT_AUTHORIZATION ++ Tcl_AppendResult(interp, "authorization not available in this build", ++ (char*)0); ++ return TCL_ERROR; ++#else ++ if( objc>3 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); ++ return TCL_ERROR; ++ }else if( objc==2 ){ ++ if( pDb->zAuth ){ ++ Tcl_AppendResult(interp, pDb->zAuth, (char*)0); ++ } ++ }else{ ++ char *zAuth; ++ int len; ++ if( pDb->zAuth ){ ++ Tcl_Free(pDb->zAuth); ++ } ++ zAuth = Tcl_GetStringFromObj(objv[2], &len); ++ if( zAuth && len>0 ){ ++ pDb->zAuth = Tcl_Alloc( len + 1 ); ++ memcpy(pDb->zAuth, zAuth, len+1); ++ }else{ ++ pDb->zAuth = 0; ++ } ++ if( pDb->zAuth ){ ++ typedef int (*sqlite3_auth_cb)( ++ void*,int,const char*,const char*, ++ const char*,const char*); ++ pDb->interp = interp; ++ sqlite3_set_authorizer(pDb->db,(sqlite3_auth_cb)auth_callback,pDb); ++ }else{ ++ sqlite3_set_authorizer(pDb->db, 0, 0); ++ } ++ } ++#endif ++ break; ++ } ++ ++ /* $db backup ?DATABASE? FILENAME ++ ** ++ ** Open or create a database file named FILENAME. Transfer the ++ ** content of local database DATABASE (default: "main") into the ++ ** FILENAME database. ++ */ ++ case DB_BACKUP: { ++ const char *zDestFile; ++ const char *zSrcDb; ++ sqlite3 *pDest; ++ sqlite3_backup *pBackup; ++ ++ if( objc==3 ){ ++ zSrcDb = "main"; ++ zDestFile = Tcl_GetString(objv[2]); ++ }else if( objc==4 ){ ++ zSrcDb = Tcl_GetString(objv[2]); ++ zDestFile = Tcl_GetString(objv[3]); ++ }else{ ++ Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME"); ++ return TCL_ERROR; ++ } ++ rc = sqlite3_open_v2(zDestFile, &pDest, ++ SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE| pDb->openFlags, 0); ++ if( rc!=SQLITE_OK ){ ++ Tcl_AppendResult(interp, "cannot open target database: ", ++ sqlite3_errmsg(pDest), (char*)0); ++ sqlite3_close(pDest); ++ return TCL_ERROR; ++ } ++ pBackup = sqlite3_backup_init(pDest, "main", pDb->db, zSrcDb); ++ if( pBackup==0 ){ ++ Tcl_AppendResult(interp, "backup failed: ", ++ sqlite3_errmsg(pDest), (char*)0); ++ sqlite3_close(pDest); ++ return TCL_ERROR; ++ } ++ while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){} ++ sqlite3_backup_finish(pBackup); ++ if( rc==SQLITE_DONE ){ ++ rc = TCL_OK; ++ }else{ ++ Tcl_AppendResult(interp, "backup failed: ", ++ sqlite3_errmsg(pDest), (char*)0); ++ rc = TCL_ERROR; ++ } ++ sqlite3_close(pDest); ++ break; ++ } ++ ++ /* $db busy ?CALLBACK? ++ ** ++ ** Invoke the given callback if an SQL statement attempts to open ++ ** a locked database file. ++ */ ++ case DB_BUSY: { ++ if( objc>3 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "CALLBACK"); ++ return TCL_ERROR; ++ }else if( objc==2 ){ ++ if( pDb->zBusy ){ ++ Tcl_AppendResult(interp, pDb->zBusy, (char*)0); ++ } ++ }else{ ++ char *zBusy; ++ int len; ++ if( pDb->zBusy ){ ++ Tcl_Free(pDb->zBusy); ++ } ++ zBusy = Tcl_GetStringFromObj(objv[2], &len); ++ if( zBusy && len>0 ){ ++ pDb->zBusy = Tcl_Alloc( len + 1 ); ++ memcpy(pDb->zBusy, zBusy, len+1); ++ }else{ ++ pDb->zBusy = 0; ++ } ++ if( pDb->zBusy ){ ++ pDb->interp = interp; ++ sqlite3_busy_handler(pDb->db, DbBusyHandler, pDb); ++ }else{ ++ sqlite3_busy_handler(pDb->db, 0, 0); ++ } ++ } ++ break; ++ } ++ ++ /* $db cache flush ++ ** $db cache size n ++ ** ++ ** Flush the prepared statement cache, or set the maximum number of ++ ** cached statements. ++ */ ++ case DB_CACHE: { ++ char *subCmd; ++ int n; ++ ++ if( objc<=2 ){ ++ Tcl_WrongNumArgs(interp, 1, objv, "cache option ?arg?"); ++ return TCL_ERROR; ++ } ++ subCmd = Tcl_GetStringFromObj( objv[2], 0 ); ++ if( *subCmd=='f' && strcmp(subCmd,"flush")==0 ){ ++ if( objc!=3 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "flush"); ++ return TCL_ERROR; ++ }else{ ++ flushStmtCache( pDb ); ++ } ++ }else if( *subCmd=='s' && strcmp(subCmd,"size")==0 ){ ++ if( objc!=4 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "size n"); ++ return TCL_ERROR; ++ }else{ ++ if( TCL_ERROR==Tcl_GetIntFromObj(interp, objv[3], &n) ){ ++ Tcl_AppendResult( interp, "cannot convert \"", ++ Tcl_GetStringFromObj(objv[3],0), "\" to integer", (char*)0); ++ return TCL_ERROR; ++ }else{ ++ if( n<0 ){ ++ flushStmtCache( pDb ); ++ n = 0; ++ }else if( n>MAX_PREPARED_STMTS ){ ++ n = MAX_PREPARED_STMTS; ++ } ++ pDb->maxStmt = n; ++ } ++ } ++ }else{ ++ Tcl_AppendResult( interp, "bad option \"", ++ Tcl_GetStringFromObj(objv[2],0), "\": must be flush or size", ++ (char*)0); ++ return TCL_ERROR; ++ } ++ break; ++ } ++ ++ /* $db changes ++ ** ++ ** Return the number of rows that were modified, inserted, or deleted by ++ ** the most recent INSERT, UPDATE or DELETE statement, not including ++ ** any changes made by trigger programs. ++ */ ++ case DB_CHANGES: { ++ Tcl_Obj *pResult; ++ if( objc!=2 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, ""); ++ return TCL_ERROR; ++ } ++ pResult = Tcl_GetObjResult(interp); ++ Tcl_SetIntObj(pResult, sqlite3_changes(pDb->db)); ++ break; ++ } ++ ++ /* $db close ++ ** ++ ** Shutdown the database ++ */ ++ case DB_CLOSE: { ++ Tcl_DeleteCommand(interp, Tcl_GetStringFromObj(objv[0], 0)); ++ break; ++ } ++ ++ /* ++ ** $db collate NAME SCRIPT ++ ** ++ ** Create a new SQL collation function called NAME. Whenever ++ ** that function is called, invoke SCRIPT to evaluate the function. ++ */ ++ case DB_COLLATE: { ++ SqlCollate *pCollate; ++ char *zName; ++ char *zScript; ++ int nScript; ++ if( objc!=4 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "NAME SCRIPT"); ++ return TCL_ERROR; ++ } ++ zName = Tcl_GetStringFromObj(objv[2], 0); ++ zScript = Tcl_GetStringFromObj(objv[3], &nScript); ++ pCollate = (SqlCollate*)Tcl_Alloc( sizeof(*pCollate) + nScript + 1 ); ++ if( pCollate==0 ) return TCL_ERROR; ++ pCollate->interp = interp; ++ pCollate->pNext = pDb->pCollate; ++ pCollate->zScript = (char*)&pCollate[1]; ++ pDb->pCollate = pCollate; ++ memcpy(pCollate->zScript, zScript, nScript+1); ++ if( sqlite3_create_collation(pDb->db, zName, SQLITE_UTF8, ++ pCollate, tclSqlCollate) ){ ++ Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE); ++ return TCL_ERROR; ++ } ++ break; ++ } ++ ++ /* ++ ** $db collation_needed SCRIPT ++ ** ++ ** Create a new SQL collation function called NAME. Whenever ++ ** that function is called, invoke SCRIPT to evaluate the function. ++ */ ++ case DB_COLLATION_NEEDED: { ++ if( objc!=3 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "SCRIPT"); ++ return TCL_ERROR; ++ } ++ if( pDb->pCollateNeeded ){ ++ Tcl_DecrRefCount(pDb->pCollateNeeded); ++ } ++ pDb->pCollateNeeded = Tcl_DuplicateObj(objv[2]); ++ Tcl_IncrRefCount(pDb->pCollateNeeded); ++ sqlite3_collation_needed(pDb->db, pDb, tclCollateNeeded); ++ break; ++ } ++ ++ /* $db commit_hook ?CALLBACK? ++ ** ++ ** Invoke the given callback just before committing every SQL transaction. ++ ** If the callback throws an exception or returns non-zero, then the ++ ** transaction is aborted. If CALLBACK is an empty string, the callback ++ ** is disabled. ++ */ ++ case DB_COMMIT_HOOK: { ++ if( objc>3 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); ++ return TCL_ERROR; ++ }else if( objc==2 ){ ++ if( pDb->zCommit ){ ++ Tcl_AppendResult(interp, pDb->zCommit, (char*)0); ++ } ++ }else{ ++ const char *zCommit; ++ int len; ++ if( pDb->zCommit ){ ++ Tcl_Free(pDb->zCommit); ++ } ++ zCommit = Tcl_GetStringFromObj(objv[2], &len); ++ if( zCommit && len>0 ){ ++ pDb->zCommit = Tcl_Alloc( len + 1 ); ++ memcpy(pDb->zCommit, zCommit, len+1); ++ }else{ ++ pDb->zCommit = 0; ++ } ++ if( pDb->zCommit ){ ++ pDb->interp = interp; ++ sqlite3_commit_hook(pDb->db, DbCommitHandler, pDb); ++ }else{ ++ sqlite3_commit_hook(pDb->db, 0, 0); ++ } ++ } ++ break; ++ } ++ ++ /* $db complete SQL ++ ** ++ ** Return TRUE if SQL is a complete SQL statement. Return FALSE if ++ ** additional lines of input are needed. This is similar to the ++ ** built-in "info complete" command of Tcl. ++ */ ++ case DB_COMPLETE: { ++#ifndef SQLITE_OMIT_COMPLETE ++ Tcl_Obj *pResult; ++ int isComplete; ++ if( objc!=3 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "SQL"); ++ return TCL_ERROR; ++ } ++ isComplete = sqlite3_complete( Tcl_GetStringFromObj(objv[2], 0) ); ++ pResult = Tcl_GetObjResult(interp); ++ Tcl_SetBooleanObj(pResult, isComplete); ++#endif ++ break; ++ } ++ ++ /* $db copy conflict-algorithm table filename ?SEPARATOR? ?NULLINDICATOR? ++ ** ++ ** Copy data into table from filename, optionally using SEPARATOR ++ ** as column separators. If a column contains a null string, or the ++ ** value of NULLINDICATOR, a NULL is inserted for the column. ++ ** conflict-algorithm is one of the sqlite conflict algorithms: ++ ** rollback, abort, fail, ignore, replace ++ ** On success, return the number of lines processed, not necessarily same ++ ** as 'db changes' due to conflict-algorithm selected. ++ ** ++ ** This code is basically an implementation/enhancement of ++ ** the sqlite3 shell.c ".import" command. ++ ** ++ ** This command usage is equivalent to the sqlite2.x COPY statement, ++ ** which imports file data into a table using the PostgreSQL COPY file format: ++ ** $db copy $conflit_algo $table_name $filename \t \\N ++ */ ++ case DB_COPY: { ++ char *zTable; /* Insert data into this table */ ++ char *zFile; /* The file from which to extract data */ ++ char *zConflict; /* The conflict algorithm to use */ ++ sqlite3_stmt *pStmt; /* A statement */ ++ int nCol; /* Number of columns in the table */ ++ int nByte; /* Number of bytes in an SQL string */ ++ int i, j; /* Loop counters */ ++ int nSep; /* Number of bytes in zSep[] */ ++ int nNull; /* Number of bytes in zNull[] */ ++ char *zSql; /* An SQL statement */ ++ char *zLine; /* A single line of input from the file */ ++ char **azCol; /* zLine[] broken up into columns */ ++ const char *zCommit; /* How to commit changes */ ++ FILE *in; /* The input file */ ++ int lineno = 0; /* Line number of input file */ ++ char zLineNum[80]; /* Line number print buffer */ ++ Tcl_Obj *pResult; /* interp result */ ++ ++ const char *zSep; ++ const char *zNull; ++ if( objc<5 || objc>7 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, ++ "CONFLICT-ALGORITHM TABLE FILENAME ?SEPARATOR? ?NULLINDICATOR?"); ++ return TCL_ERROR; ++ } ++ if( objc>=6 ){ ++ zSep = Tcl_GetStringFromObj(objv[5], 0); ++ }else{ ++ zSep = "\t"; ++ } ++ if( objc>=7 ){ ++ zNull = Tcl_GetStringFromObj(objv[6], 0); ++ }else{ ++ zNull = ""; ++ } ++ zConflict = Tcl_GetStringFromObj(objv[2], 0); ++ zTable = Tcl_GetStringFromObj(objv[3], 0); ++ zFile = Tcl_GetStringFromObj(objv[4], 0); ++ nSep = strlen30(zSep); ++ nNull = strlen30(zNull); ++ if( nSep==0 ){ ++ Tcl_AppendResult(interp,"Error: non-null separator required for copy", ++ (char*)0); ++ return TCL_ERROR; ++ } ++ if(strcmp(zConflict, "rollback") != 0 && ++ strcmp(zConflict, "abort" ) != 0 && ++ strcmp(zConflict, "fail" ) != 0 && ++ strcmp(zConflict, "ignore" ) != 0 && ++ strcmp(zConflict, "replace" ) != 0 ) { ++ Tcl_AppendResult(interp, "Error: \"", zConflict, ++ "\", conflict-algorithm must be one of: rollback, " ++ "abort, fail, ignore, or replace", (char*)0); ++ return TCL_ERROR; ++ } ++ zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable); ++ if( zSql==0 ){ ++ Tcl_AppendResult(interp, "Error: no such table: ", zTable, (char*)0); ++ return TCL_ERROR; ++ } ++ nByte = strlen30(zSql); ++ rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0); ++ sqlite3_free(zSql); ++ if( rc ){ ++ Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), (char*)0); ++ nCol = 0; ++ }else{ ++ nCol = sqlite3_column_count(pStmt); ++ } ++ sqlite3_finalize(pStmt); ++ if( nCol==0 ) { ++ return TCL_ERROR; ++ } ++ zSql = malloc( nByte + 50 + nCol*2 ); ++ if( zSql==0 ) { ++ Tcl_AppendResult(interp, "Error: can't malloc()", (char*)0); ++ return TCL_ERROR; ++ } ++ sqlite3_snprintf(nByte+50, zSql, "INSERT OR %q INTO '%q' VALUES(?", ++ zConflict, zTable); ++ j = strlen30(zSql); ++ for(i=1; i<nCol; i++){ ++ zSql[j++] = ','; ++ zSql[j++] = '?'; ++ } ++ zSql[j++] = ')'; ++ zSql[j] = 0; ++ rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0); ++ free(zSql); ++ if( rc ){ ++ Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), (char*)0); ++ sqlite3_finalize(pStmt); ++ return TCL_ERROR; ++ } ++ in = fopen(zFile, "rb"); ++ if( in==0 ){ ++ Tcl_AppendResult(interp, "Error: cannot open file: ", zFile, (char*)0); ++ sqlite3_finalize(pStmt); ++ return TCL_ERROR; ++ } ++ azCol = malloc( sizeof(azCol[0])*(nCol+1) ); ++ if( azCol==0 ) { ++ Tcl_AppendResult(interp, "Error: can't malloc()", (char*)0); ++ fclose(in); ++ return TCL_ERROR; ++ } ++ (void)sqlite3_exec(pDb->db, "BEGIN", 0, 0, 0); ++ zCommit = "COMMIT"; ++ while( (zLine = local_getline(0, in))!=0 ){ ++ char *z; ++ lineno++; ++ azCol[0] = zLine; ++ for(i=0, z=zLine; *z; z++){ ++ if( *z==zSep[0] && strncmp(z, zSep, nSep)==0 ){ ++ *z = 0; ++ i++; ++ if( i<nCol ){ ++ azCol[i] = &z[nSep]; ++ z += nSep-1; ++ } ++ } ++ } ++ if( i+1!=nCol ){ ++ char *zErr; ++ int nErr = strlen30(zFile) + 200; ++ zErr = malloc(nErr); ++ if( zErr ){ ++ sqlite3_snprintf(nErr, zErr, ++ "Error: %s line %d: expected %d columns of data but found %d", ++ zFile, lineno, nCol, i+1); ++ Tcl_AppendResult(interp, zErr, (char*)0); ++ free(zErr); ++ } ++ zCommit = "ROLLBACK"; ++ break; ++ } ++ for(i=0; i<nCol; i++){ ++ /* check for null data, if so, bind as null */ ++ if( (nNull>0 && strcmp(azCol[i], zNull)==0) ++ || strlen30(azCol[i])==0 ++ ){ ++ sqlite3_bind_null(pStmt, i+1); ++ }else{ ++ sqlite3_bind_text(pStmt, i+1, azCol[i], -1, SQLITE_STATIC); ++ } ++ } ++ sqlite3_step(pStmt); ++ rc = sqlite3_reset(pStmt); ++ free(zLine); ++ if( rc!=SQLITE_OK ){ ++ Tcl_AppendResult(interp,"Error: ", sqlite3_errmsg(pDb->db), (char*)0); ++ zCommit = "ROLLBACK"; ++ break; ++ } ++ } ++ free(azCol); ++ fclose(in); ++ sqlite3_finalize(pStmt); ++ (void)sqlite3_exec(pDb->db, zCommit, 0, 0, 0); ++ ++ if( zCommit[0] == 'C' ){ ++ /* success, set result as number of lines processed */ ++ pResult = Tcl_GetObjResult(interp); ++ Tcl_SetIntObj(pResult, lineno); ++ rc = TCL_OK; ++ }else{ ++ /* failure, append lineno where failed */ ++ sqlite3_snprintf(sizeof(zLineNum), zLineNum,"%d",lineno); ++ Tcl_AppendResult(interp,", failed while processing line: ",zLineNum, ++ (char*)0); ++ rc = TCL_ERROR; ++ } ++ break; ++ } ++ ++ /* ++ ** $db deserialize ?DATABASE? VALUE ++ ** ++ ** Reopen DATABASE (default "main") using the content in $VALUE ++ */ ++ case DB_DESERIALIZE: { ++#ifndef SQLITE_ENABLE_DESERIALIZE ++ Tcl_AppendResult(interp, "MEMDB not available in this build", ++ (char*)0); ++ rc = TCL_ERROR; ++#else ++ const char *zSchema; ++ Tcl_Obj *pValue; ++ unsigned char *pBA; ++ unsigned char *pData; ++ int len, xrc; ++ ++ if( objc==3 ){ ++ zSchema = 0; ++ pValue = objv[2]; ++ }else if( objc==4 ){ ++ zSchema = Tcl_GetString(objv[2]); ++ pValue = objv[3]; ++ }else{ ++ Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? VALUE"); ++ rc = TCL_ERROR; ++ break; ++ } ++ pBA = Tcl_GetByteArrayFromObj(pValue, &len); ++ pData = sqlite3_malloc64( len ); ++ if( pData==0 && len>0 ){ ++ Tcl_AppendResult(interp, "out of memory", (char*)0); ++ rc = TCL_ERROR; ++ }else{ ++ if( len>0 ) memcpy(pData, pBA, len); ++ xrc = sqlite3_deserialize(pDb->db, zSchema, pData, len, len, ++ SQLITE_DESERIALIZE_FREEONCLOSE | ++ SQLITE_DESERIALIZE_RESIZEABLE); ++ if( xrc ){ ++ Tcl_AppendResult(interp, "unable to set MEMDB content", (char*)0); ++ rc = TCL_ERROR; ++ } ++ } ++#endif ++ break; ++ } ++ ++ /* ++ ** $db enable_load_extension BOOLEAN ++ ** ++ ** Turn the extension loading feature on or off. It if off by ++ ** default. ++ */ ++ case DB_ENABLE_LOAD_EXTENSION: { ++#ifndef SQLITE_OMIT_LOAD_EXTENSION ++ int onoff; ++ if( objc!=3 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "BOOLEAN"); ++ return TCL_ERROR; ++ } ++ if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){ ++ return TCL_ERROR; ++ } ++ sqlite3_enable_load_extension(pDb->db, onoff); ++ break; ++#else ++ Tcl_AppendResult(interp, "extension loading is turned off at compile-time", ++ (char*)0); ++ return TCL_ERROR; ++#endif ++ } ++ ++ /* ++ ** $db errorcode ++ ** ++ ** Return the numeric error code that was returned by the most recent ++ ** call to sqlite3_exec(). ++ */ ++ case DB_ERRORCODE: { ++ Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_errcode(pDb->db))); ++ break; ++ } ++ ++ /* ++ ** $db exists $sql ++ ** $db onecolumn $sql ++ ** ++ ** The onecolumn method is the equivalent of: ++ ** lindex [$db eval $sql] 0 ++ */ ++ case DB_EXISTS: ++ case DB_ONECOLUMN: { ++ Tcl_Obj *pResult = 0; ++ DbEvalContext sEval; ++ if( objc!=3 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "SQL"); ++ return TCL_ERROR; ++ } ++ ++ dbEvalInit(&sEval, pDb, objv[2], 0, 0); ++ rc = dbEvalStep(&sEval); ++ if( choice==DB_ONECOLUMN ){ ++ if( rc==TCL_OK ){ ++ pResult = dbEvalColumnValue(&sEval, 0); ++ }else if( rc==TCL_BREAK ){ ++ Tcl_ResetResult(interp); ++ } ++ }else if( rc==TCL_BREAK || rc==TCL_OK ){ ++ pResult = Tcl_NewBooleanObj(rc==TCL_OK); ++ } ++ dbEvalFinalize(&sEval); ++ if( pResult ) Tcl_SetObjResult(interp, pResult); ++ ++ if( rc==TCL_BREAK ){ ++ rc = TCL_OK; ++ } ++ break; ++ } ++ ++ /* ++ ** $db eval ?options? $sql ?array? ?{ ...code... }? ++ ** ++ ** The SQL statement in $sql is evaluated. For each row, the values are ++ ** placed in elements of the array named "array" and ...code... is executed. ++ ** If "array" and "code" are omitted, then no callback is every invoked. ++ ** If "array" is an empty string, then the values are placed in variables ++ ** that have the same name as the fields extracted by the query. ++ */ ++ case DB_EVAL: { ++ int evalFlags = 0; ++ const char *zOpt; ++ while( objc>3 && (zOpt = Tcl_GetString(objv[2]))!=0 && zOpt[0]=='-' ){ ++ if( strcmp(zOpt, "-withoutnulls")==0 ){ ++ evalFlags |= SQLITE_EVAL_WITHOUTNULLS; ++ } ++ else{ ++ Tcl_AppendResult(interp, "unknown option: \"", zOpt, "\"", (void*)0); ++ return TCL_ERROR; ++ } ++ objc--; ++ objv++; ++ } ++ if( objc<3 || objc>5 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, ++ "?OPTIONS? SQL ?ARRAY-NAME? ?SCRIPT?"); ++ return TCL_ERROR; ++ } ++ ++ if( objc==3 ){ ++ DbEvalContext sEval; ++ Tcl_Obj *pRet = Tcl_NewObj(); ++ Tcl_IncrRefCount(pRet); ++ dbEvalInit(&sEval, pDb, objv[2], 0, 0); ++ while( TCL_OK==(rc = dbEvalStep(&sEval)) ){ ++ int i; ++ int nCol; ++ dbEvalRowInfo(&sEval, &nCol, 0); ++ for(i=0; i<nCol; i++){ ++ Tcl_ListObjAppendElement(interp, pRet, dbEvalColumnValue(&sEval, i)); ++ } ++ } ++ dbEvalFinalize(&sEval); ++ if( rc==TCL_BREAK ){ ++ Tcl_SetObjResult(interp, pRet); ++ rc = TCL_OK; ++ } ++ Tcl_DecrRefCount(pRet); ++ }else{ ++ ClientData cd2[2]; ++ DbEvalContext *p; ++ Tcl_Obj *pArray = 0; ++ Tcl_Obj *pScript; ++ ++ if( objc>=5 && *(char *)Tcl_GetString(objv[3]) ){ ++ pArray = objv[3]; ++ } ++ pScript = objv[objc-1]; ++ Tcl_IncrRefCount(pScript); ++ ++ p = (DbEvalContext *)Tcl_Alloc(sizeof(DbEvalContext)); ++ dbEvalInit(p, pDb, objv[2], pArray, evalFlags); ++ ++ cd2[0] = (void *)p; ++ cd2[1] = (void *)pScript; ++ rc = DbEvalNextCmd(cd2, interp, TCL_OK); ++ } ++ break; ++ } ++ ++ /* ++ ** $db function NAME [-argcount N] [-deterministic] SCRIPT ++ ** ++ ** Create a new SQL function called NAME. Whenever that function is ++ ** called, invoke SCRIPT to evaluate the function. ++ */ ++ case DB_FUNCTION: { ++ int flags = SQLITE_UTF8; ++ SqlFunc *pFunc; ++ Tcl_Obj *pScript; ++ char *zName; ++ int nArg = -1; ++ int i; ++ if( objc<4 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "NAME ?SWITCHES? SCRIPT"); ++ return TCL_ERROR; ++ } ++ for(i=3; i<(objc-1); i++){ ++ const char *z = Tcl_GetString(objv[i]); ++ int n = strlen30(z); ++ if( n>2 && strncmp(z, "-argcount",n)==0 ){ ++ if( i==(objc-2) ){ ++ Tcl_AppendResult(interp, "option requires an argument: ", z,(char*)0); ++ return TCL_ERROR; ++ } ++ if( Tcl_GetIntFromObj(interp, objv[i+1], &nArg) ) return TCL_ERROR; ++ if( nArg<0 ){ ++ Tcl_AppendResult(interp, "number of arguments must be non-negative", ++ (char*)0); ++ return TCL_ERROR; ++ } ++ i++; ++ }else ++ if( n>2 && strncmp(z, "-deterministic",n)==0 ){ ++ flags |= SQLITE_DETERMINISTIC; ++ }else{ ++ Tcl_AppendResult(interp, "bad option \"", z, ++ "\": must be -argcount or -deterministic", (char*)0 ++ ); ++ return TCL_ERROR; ++ } ++ } ++ ++ pScript = objv[objc-1]; ++ zName = Tcl_GetStringFromObj(objv[2], 0); ++ pFunc = findSqlFunc(pDb, zName); ++ if( pFunc==0 ) return TCL_ERROR; ++ if( pFunc->pScript ){ ++ Tcl_DecrRefCount(pFunc->pScript); ++ } ++ pFunc->pScript = pScript; ++ Tcl_IncrRefCount(pScript); ++ pFunc->useEvalObjv = safeToUseEvalObjv(interp, pScript); ++ rc = sqlite3_create_function(pDb->db, zName, nArg, flags, ++ pFunc, tclSqlFunc, 0, 0); ++ if( rc!=SQLITE_OK ){ ++ rc = TCL_ERROR; ++ Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE); ++ } ++ break; ++ } ++ ++ /* ++ ** $db incrblob ?-readonly? ?DB? TABLE COLUMN ROWID ++ */ ++ case DB_INCRBLOB: { ++#ifdef SQLITE_OMIT_INCRBLOB ++ Tcl_AppendResult(interp, "incrblob not available in this build", (char*)0); ++ return TCL_ERROR; ++#else ++ int isReadonly = 0; ++ const char *zDb = "main"; ++ const char *zTable; ++ const char *zColumn; ++ Tcl_WideInt iRow; ++ ++ /* Check for the -readonly option */ ++ if( objc>3 && strcmp(Tcl_GetString(objv[2]), "-readonly")==0 ){ ++ isReadonly = 1; ++ } ++ ++ if( objc!=(5+isReadonly) && objc!=(6+isReadonly) ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "?-readonly? ?DB? TABLE COLUMN ROWID"); ++ return TCL_ERROR; ++ } ++ ++ if( objc==(6+isReadonly) ){ ++ zDb = Tcl_GetString(objv[2]); ++ } ++ zTable = Tcl_GetString(objv[objc-3]); ++ zColumn = Tcl_GetString(objv[objc-2]); ++ rc = Tcl_GetWideIntFromObj(interp, objv[objc-1], &iRow); ++ ++ if( rc==TCL_OK ){ ++ rc = createIncrblobChannel( ++ interp, pDb, zDb, zTable, zColumn, (sqlite3_int64)iRow, isReadonly ++ ); ++ } ++#endif ++ break; ++ } ++ ++ /* ++ ** $db interrupt ++ ** ++ ** Interrupt the execution of the inner-most SQL interpreter. This ++ ** causes the SQL statement to return an error of SQLITE_INTERRUPT. ++ */ ++ case DB_INTERRUPT: { ++ sqlite3_interrupt(pDb->db); ++ break; ++ } ++ ++ /* ++ ** $db nullvalue ?STRING? ++ ** ++ ** Change text used when a NULL comes back from the database. If ?STRING? ++ ** is not present, then the current string used for NULL is returned. ++ ** If STRING is present, then STRING is returned. ++ ** ++ */ ++ case DB_NULLVALUE: { ++ if( objc!=2 && objc!=3 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "NULLVALUE"); ++ return TCL_ERROR; ++ } ++ if( objc==3 ){ ++ int len; ++ char *zNull = Tcl_GetStringFromObj(objv[2], &len); ++ if( pDb->zNull ){ ++ Tcl_Free(pDb->zNull); ++ } ++ if( zNull && len>0 ){ ++ pDb->zNull = Tcl_Alloc( len + 1 ); ++ memcpy(pDb->zNull, zNull, len); ++ pDb->zNull[len] = '\0'; ++ }else{ ++ pDb->zNull = 0; ++ } ++ } ++ Tcl_SetObjResult(interp, Tcl_NewStringObj(pDb->zNull, -1)); ++ break; ++ } ++ ++ /* ++ ** $db last_insert_rowid ++ ** ++ ** Return an integer which is the ROWID for the most recent insert. ++ */ ++ case DB_LAST_INSERT_ROWID: { ++ Tcl_Obj *pResult; ++ Tcl_WideInt rowid; ++ if( objc!=2 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, ""); ++ return TCL_ERROR; ++ } ++ rowid = sqlite3_last_insert_rowid(pDb->db); ++ pResult = Tcl_GetObjResult(interp); ++ Tcl_SetWideIntObj(pResult, rowid); ++ break; ++ } ++ ++ /* ++ ** The DB_ONECOLUMN method is implemented together with DB_EXISTS. ++ */ ++ ++ /* $db progress ?N CALLBACK? ++ ** ++ ** Invoke the given callback every N virtual machine opcodes while executing ++ ** queries. ++ */ ++ case DB_PROGRESS: { ++ if( objc==2 ){ ++ if( pDb->zProgress ){ ++ Tcl_AppendResult(interp, pDb->zProgress, (char*)0); ++ } ++ }else if( objc==4 ){ ++ char *zProgress; ++ int len; ++ int N; ++ if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &N) ){ ++ return TCL_ERROR; ++ }; ++ if( pDb->zProgress ){ ++ Tcl_Free(pDb->zProgress); ++ } ++ zProgress = Tcl_GetStringFromObj(objv[3], &len); ++ if( zProgress && len>0 ){ ++ pDb->zProgress = Tcl_Alloc( len + 1 ); ++ memcpy(pDb->zProgress, zProgress, len+1); ++ }else{ ++ pDb->zProgress = 0; ++ } ++#ifndef SQLITE_OMIT_PROGRESS_CALLBACK ++ if( pDb->zProgress ){ ++ pDb->interp = interp; ++ sqlite3_progress_handler(pDb->db, N, DbProgressHandler, pDb); ++ }else{ ++ sqlite3_progress_handler(pDb->db, 0, 0, 0); ++ } ++#endif ++ }else{ ++ Tcl_WrongNumArgs(interp, 2, objv, "N CALLBACK"); ++ return TCL_ERROR; ++ } ++ break; ++ } ++ ++ /* $db profile ?CALLBACK? ++ ** ++ ** Make arrangements to invoke the CALLBACK routine after each SQL statement ++ ** that has run. The text of the SQL and the amount of elapse time are ++ ** appended to CALLBACK before the script is run. ++ */ ++ case DB_PROFILE: { ++ if( objc>3 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); ++ return TCL_ERROR; ++ }else if( objc==2 ){ ++ if( pDb->zProfile ){ ++ Tcl_AppendResult(interp, pDb->zProfile, (char*)0); ++ } ++ }else{ ++ char *zProfile; ++ int len; ++ if( pDb->zProfile ){ ++ Tcl_Free(pDb->zProfile); ++ } ++ zProfile = Tcl_GetStringFromObj(objv[2], &len); ++ if( zProfile && len>0 ){ ++ pDb->zProfile = Tcl_Alloc( len + 1 ); ++ memcpy(pDb->zProfile, zProfile, len+1); ++ }else{ ++ pDb->zProfile = 0; ++ } ++#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) && \ ++ !defined(SQLITE_OMIT_DEPRECATED) ++ if( pDb->zProfile ){ ++ pDb->interp = interp; ++ sqlite3_profile(pDb->db, DbProfileHandler, pDb); ++ }else{ ++ sqlite3_profile(pDb->db, 0, 0); ++ } ++#endif ++ } ++ break; ++ } ++ ++ /* ++ ** $db rekey KEY ++ ** ++ ** Change the encryption key on the currently open database. ++ */ ++ case DB_REKEY: { ++#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL) ++ int nKey; ++ void *pKey; ++#endif ++ if( objc!=3 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "KEY"); ++ return TCL_ERROR; ++ } ++#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL) ++ pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey); ++ rc = sqlite3_rekey(pDb->db, pKey, nKey); ++ if( rc ){ ++ Tcl_AppendResult(interp, sqlite3_errstr(rc), (char*)0); ++ rc = TCL_ERROR; ++ } ++#endif ++ break; ++ } ++ ++ /* $db restore ?DATABASE? FILENAME ++ ** ++ ** Open a database file named FILENAME. Transfer the content ++ ** of FILENAME into the local database DATABASE (default: "main"). ++ */ ++ case DB_RESTORE: { ++ const char *zSrcFile; ++ const char *zDestDb; ++ sqlite3 *pSrc; ++ sqlite3_backup *pBackup; ++ int nTimeout = 0; ++ ++ if( objc==3 ){ ++ zDestDb = "main"; ++ zSrcFile = Tcl_GetString(objv[2]); ++ }else if( objc==4 ){ ++ zDestDb = Tcl_GetString(objv[2]); ++ zSrcFile = Tcl_GetString(objv[3]); ++ }else{ ++ Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME"); ++ return TCL_ERROR; ++ } ++ rc = sqlite3_open_v2(zSrcFile, &pSrc, ++ SQLITE_OPEN_READONLY | pDb->openFlags, 0); ++ if( rc!=SQLITE_OK ){ ++ Tcl_AppendResult(interp, "cannot open source database: ", ++ sqlite3_errmsg(pSrc), (char*)0); ++ sqlite3_close(pSrc); ++ return TCL_ERROR; ++ } ++ pBackup = sqlite3_backup_init(pDb->db, zDestDb, pSrc, "main"); ++ if( pBackup==0 ){ ++ Tcl_AppendResult(interp, "restore failed: ", ++ sqlite3_errmsg(pDb->db), (char*)0); ++ sqlite3_close(pSrc); ++ return TCL_ERROR; ++ } ++ while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ++ || rc==SQLITE_BUSY ){ ++ if( rc==SQLITE_BUSY ){ ++ if( nTimeout++ >= 3 ) break; ++ sqlite3_sleep(100); ++ } ++ } ++ sqlite3_backup_finish(pBackup); ++ if( rc==SQLITE_DONE ){ ++ rc = TCL_OK; ++ }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){ ++ Tcl_AppendResult(interp, "restore failed: source database busy", ++ (char*)0); ++ rc = TCL_ERROR; ++ }else{ ++ Tcl_AppendResult(interp, "restore failed: ", ++ sqlite3_errmsg(pDb->db), (char*)0); ++ rc = TCL_ERROR; ++ } ++ sqlite3_close(pSrc); ++ break; ++ } ++ ++ /* ++ ** $db serialize ?DATABASE? ++ ** ++ ** Return a serialization of a database. ++ */ ++ case DB_SERIALIZE: { ++#ifndef SQLITE_ENABLE_DESERIALIZE ++ Tcl_AppendResult(interp, "MEMDB not available in this build", ++ (char*)0); ++ rc = TCL_ERROR; ++#else ++ const char *zSchema = objc>=3 ? Tcl_GetString(objv[2]) : "main"; ++ sqlite3_int64 sz = 0; ++ unsigned char *pData; ++ if( objc!=2 && objc!=3 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE?"); ++ rc = TCL_ERROR; ++ }else{ ++ int needFree; ++ pData = sqlite3_serialize(pDb->db, zSchema, &sz, SQLITE_SERIALIZE_NOCOPY); ++ if( pData ){ ++ needFree = 0; ++ }else{ ++ pData = sqlite3_serialize(pDb->db, zSchema, &sz, 0); ++ needFree = 1; ++ } ++ Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pData,sz)); ++ if( needFree ) sqlite3_free(pData); ++ } ++#endif ++ break; ++ } ++ ++ /* ++ ** $db status (step|sort|autoindex|vmstep) ++ ** ++ ** Display SQLITE_STMTSTATUS_FULLSCAN_STEP or ++ ** SQLITE_STMTSTATUS_SORT for the most recent eval. ++ */ ++ case DB_STATUS: { ++ int v; ++ const char *zOp; ++ if( objc!=3 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "(step|sort|autoindex)"); ++ return TCL_ERROR; ++ } ++ zOp = Tcl_GetString(objv[2]); ++ if( strcmp(zOp, "step")==0 ){ ++ v = pDb->nStep; ++ }else if( strcmp(zOp, "sort")==0 ){ ++ v = pDb->nSort; ++ }else if( strcmp(zOp, "autoindex")==0 ){ ++ v = pDb->nIndex; ++ }else if( strcmp(zOp, "vmstep")==0 ){ ++ v = pDb->nVMStep; ++ }else{ ++ Tcl_AppendResult(interp, ++ "bad argument: should be autoindex, step, sort or vmstep", ++ (char*)0); ++ return TCL_ERROR; ++ } ++ Tcl_SetObjResult(interp, Tcl_NewIntObj(v)); ++ break; ++ } ++ ++ /* ++ ** $db timeout MILLESECONDS ++ ** ++ ** Delay for the number of milliseconds specified when a file is locked. ++ */ ++ case DB_TIMEOUT: { ++ int ms; ++ if( objc!=3 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "MILLISECONDS"); ++ return TCL_ERROR; ++ } ++ if( Tcl_GetIntFromObj(interp, objv[2], &ms) ) return TCL_ERROR; ++ sqlite3_busy_timeout(pDb->db, ms); ++ break; ++ } ++ ++ /* ++ ** $db total_changes ++ ** ++ ** Return the number of rows that were modified, inserted, or deleted ++ ** since the database handle was created. ++ */ ++ case DB_TOTAL_CHANGES: { ++ Tcl_Obj *pResult; ++ if( objc!=2 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, ""); ++ return TCL_ERROR; ++ } ++ pResult = Tcl_GetObjResult(interp); ++ Tcl_SetIntObj(pResult, sqlite3_total_changes(pDb->db)); ++ break; ++ } ++ ++ /* $db trace ?CALLBACK? ++ ** ++ ** Make arrangements to invoke the CALLBACK routine for each SQL statement ++ ** that is executed. The text of the SQL is appended to CALLBACK before ++ ** it is executed. ++ */ ++ case DB_TRACE: { ++ if( objc>3 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); ++ return TCL_ERROR; ++ }else if( objc==2 ){ ++ if( pDb->zTrace ){ ++ Tcl_AppendResult(interp, pDb->zTrace, (char*)0); ++ } ++ }else{ ++ char *zTrace; ++ int len; ++ if( pDb->zTrace ){ ++ Tcl_Free(pDb->zTrace); ++ } ++ zTrace = Tcl_GetStringFromObj(objv[2], &len); ++ if( zTrace && len>0 ){ ++ pDb->zTrace = Tcl_Alloc( len + 1 ); ++ memcpy(pDb->zTrace, zTrace, len+1); ++ }else{ ++ pDb->zTrace = 0; ++ } ++#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) && \ ++ !defined(SQLITE_OMIT_DEPRECATED) ++ if( pDb->zTrace ){ ++ pDb->interp = interp; ++ sqlite3_trace(pDb->db, DbTraceHandler, pDb); ++ }else{ ++ sqlite3_trace(pDb->db, 0, 0); ++ } ++#endif ++ } ++ break; ++ } ++ ++ /* $db trace_v2 ?CALLBACK? ?MASK? ++ ** ++ ** Make arrangements to invoke the CALLBACK routine for each trace event ++ ** matching the mask that is generated. The parameters are appended to ++ ** CALLBACK before it is executed. ++ */ ++ case DB_TRACE_V2: { ++ if( objc>4 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK? ?MASK?"); ++ return TCL_ERROR; ++ }else if( objc==2 ){ ++ if( pDb->zTraceV2 ){ ++ Tcl_AppendResult(interp, pDb->zTraceV2, (char*)0); ++ } ++ }else{ ++ char *zTraceV2; ++ int len; ++ Tcl_WideInt wMask = 0; ++ if( objc==4 ){ ++ static const char *TTYPE_strs[] = { ++ "statement", "profile", "row", "close", 0 ++ }; ++ enum TTYPE_enum { ++ TTYPE_STMT, TTYPE_PROFILE, TTYPE_ROW, TTYPE_CLOSE ++ }; ++ int i; ++ if( TCL_OK!=Tcl_ListObjLength(interp, objv[3], &len) ){ ++ return TCL_ERROR; ++ } ++ for(i=0; i<len; i++){ ++ Tcl_Obj *pObj; ++ int ttype; ++ if( TCL_OK!=Tcl_ListObjIndex(interp, objv[3], i, &pObj) ){ ++ return TCL_ERROR; ++ } ++ if( Tcl_GetIndexFromObj(interp, pObj, TTYPE_strs, "trace type", ++ 0, &ttype)!=TCL_OK ){ ++ Tcl_WideInt wType; ++ Tcl_Obj *pError = Tcl_DuplicateObj(Tcl_GetObjResult(interp)); ++ Tcl_IncrRefCount(pError); ++ if( TCL_OK==Tcl_GetWideIntFromObj(interp, pObj, &wType) ){ ++ Tcl_DecrRefCount(pError); ++ wMask |= wType; ++ }else{ ++ Tcl_SetObjResult(interp, pError); ++ Tcl_DecrRefCount(pError); ++ return TCL_ERROR; ++ } ++ }else{ ++ switch( (enum TTYPE_enum)ttype ){ ++ case TTYPE_STMT: wMask |= SQLITE_TRACE_STMT; break; ++ case TTYPE_PROFILE: wMask |= SQLITE_TRACE_PROFILE; break; ++ case TTYPE_ROW: wMask |= SQLITE_TRACE_ROW; break; ++ case TTYPE_CLOSE: wMask |= SQLITE_TRACE_CLOSE; break; ++ } ++ } ++ } ++ }else{ ++ wMask = SQLITE_TRACE_STMT; /* use the "legacy" default */ ++ } ++ if( pDb->zTraceV2 ){ ++ Tcl_Free(pDb->zTraceV2); ++ } ++ zTraceV2 = Tcl_GetStringFromObj(objv[2], &len); ++ if( zTraceV2 && len>0 ){ ++ pDb->zTraceV2 = Tcl_Alloc( len + 1 ); ++ memcpy(pDb->zTraceV2, zTraceV2, len+1); ++ }else{ ++ pDb->zTraceV2 = 0; ++ } ++#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) ++ if( pDb->zTraceV2 ){ ++ pDb->interp = interp; ++ sqlite3_trace_v2(pDb->db, (unsigned)wMask, DbTraceV2Handler, pDb); ++ }else{ ++ sqlite3_trace_v2(pDb->db, 0, 0, 0); ++ } ++#endif ++ } ++ break; ++ } ++ ++ /* $db transaction [-deferred|-immediate|-exclusive] SCRIPT ++ ** ++ ** Start a new transaction (if we are not already in the midst of a ++ ** transaction) and execute the TCL script SCRIPT. After SCRIPT ++ ** completes, either commit the transaction or roll it back if SCRIPT ++ ** throws an exception. Or if no new transation was started, do nothing. ++ ** pass the exception on up the stack. ++ ** ++ ** This command was inspired by Dave Thomas's talk on Ruby at the ++ ** 2005 O'Reilly Open Source Convention (OSCON). ++ */ ++ case DB_TRANSACTION: { ++ Tcl_Obj *pScript; ++ const char *zBegin = "SAVEPOINT _tcl_transaction"; ++ if( objc!=3 && objc!=4 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "[TYPE] SCRIPT"); ++ return TCL_ERROR; ++ } ++ ++ if( pDb->nTransaction==0 && objc==4 ){ ++ static const char *TTYPE_strs[] = { ++ "deferred", "exclusive", "immediate", 0 ++ }; ++ enum TTYPE_enum { ++ TTYPE_DEFERRED, TTYPE_EXCLUSIVE, TTYPE_IMMEDIATE ++ }; ++ int ttype; ++ if( Tcl_GetIndexFromObj(interp, objv[2], TTYPE_strs, "transaction type", ++ 0, &ttype) ){ ++ return TCL_ERROR; ++ } ++ switch( (enum TTYPE_enum)ttype ){ ++ case TTYPE_DEFERRED: /* no-op */; break; ++ case TTYPE_EXCLUSIVE: zBegin = "BEGIN EXCLUSIVE"; break; ++ case TTYPE_IMMEDIATE: zBegin = "BEGIN IMMEDIATE"; break; ++ } ++ } ++ pScript = objv[objc-1]; ++ ++ /* Run the SQLite BEGIN command to open a transaction or savepoint. */ ++ pDb->disableAuth++; ++ rc = sqlite3_exec(pDb->db, zBegin, 0, 0, 0); ++ pDb->disableAuth--; ++ if( rc!=SQLITE_OK ){ ++ Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0); ++ return TCL_ERROR; ++ } ++ pDb->nTransaction++; ++ ++ /* If using NRE, schedule a callback to invoke the script pScript, then ++ ** a second callback to commit (or rollback) the transaction or savepoint ++ ** opened above. If not using NRE, evaluate the script directly, then ++ ** call function DbTransPostCmd() to commit (or rollback) the transaction ++ ** or savepoint. */ ++ if( DbUseNre() ){ ++ Tcl_NRAddCallback(interp, DbTransPostCmd, cd, 0, 0, 0); ++ (void)Tcl_NREvalObj(interp, pScript, 0); ++ }else{ ++ rc = DbTransPostCmd(&cd, interp, Tcl_EvalObjEx(interp, pScript, 0)); ++ } ++ break; ++ } ++ ++ /* ++ ** $db unlock_notify ?script? ++ */ ++ case DB_UNLOCK_NOTIFY: { ++#ifndef SQLITE_ENABLE_UNLOCK_NOTIFY ++ Tcl_AppendResult(interp, "unlock_notify not available in this build", ++ (char*)0); ++ rc = TCL_ERROR; ++#else ++ if( objc!=2 && objc!=3 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?"); ++ rc = TCL_ERROR; ++ }else{ ++ void (*xNotify)(void **, int) = 0; ++ void *pNotifyArg = 0; ++ ++ if( pDb->pUnlockNotify ){ ++ Tcl_DecrRefCount(pDb->pUnlockNotify); ++ pDb->pUnlockNotify = 0; ++ } ++ ++ if( objc==3 ){ ++ xNotify = DbUnlockNotify; ++ pNotifyArg = (void *)pDb; ++ pDb->pUnlockNotify = objv[2]; ++ Tcl_IncrRefCount(pDb->pUnlockNotify); ++ } ++ ++ if( sqlite3_unlock_notify(pDb->db, xNotify, pNotifyArg) ){ ++ Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0); ++ rc = TCL_ERROR; ++ } ++ } ++#endif ++ break; ++ } ++ ++ /* ++ ** $db preupdate_hook count ++ ** $db preupdate_hook hook ?SCRIPT? ++ ** $db preupdate_hook new INDEX ++ ** $db preupdate_hook old INDEX ++ */ ++ case DB_PREUPDATE: { ++#ifndef SQLITE_ENABLE_PREUPDATE_HOOK ++ Tcl_AppendResult(interp, "preupdate_hook was omitted at compile-time", ++ (char*)0); ++ rc = TCL_ERROR; ++#else ++ static const char *azSub[] = {"count", "depth", "hook", "new", "old", 0}; ++ enum DbPreupdateSubCmd { ++ PRE_COUNT, PRE_DEPTH, PRE_HOOK, PRE_NEW, PRE_OLD ++ }; ++ int iSub; ++ ++ if( objc<3 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "SUB-COMMAND ?ARGS?"); ++ } ++ if( Tcl_GetIndexFromObj(interp, objv[2], azSub, "sub-command", 0, &iSub) ){ ++ return TCL_ERROR; ++ } ++ ++ switch( (enum DbPreupdateSubCmd)iSub ){ ++ case PRE_COUNT: { ++ int nCol = sqlite3_preupdate_count(pDb->db); ++ Tcl_SetObjResult(interp, Tcl_NewIntObj(nCol)); ++ break; ++ } ++ ++ case PRE_HOOK: { ++ if( objc>4 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "hook ?SCRIPT?"); ++ return TCL_ERROR; ++ } ++ DbHookCmd(interp, pDb, (objc==4 ? objv[3] : 0), &pDb->pPreUpdateHook); ++ break; ++ } ++ ++ case PRE_DEPTH: { ++ Tcl_Obj *pRet; ++ if( objc!=3 ){ ++ Tcl_WrongNumArgs(interp, 3, objv, ""); ++ return TCL_ERROR; ++ } ++ pRet = Tcl_NewIntObj(sqlite3_preupdate_depth(pDb->db)); ++ Tcl_SetObjResult(interp, pRet); ++ break; ++ } ++ ++ case PRE_NEW: ++ case PRE_OLD: { ++ int iIdx; ++ sqlite3_value *pValue; ++ if( objc!=4 ){ ++ Tcl_WrongNumArgs(interp, 3, objv, "INDEX"); ++ return TCL_ERROR; ++ } ++ if( Tcl_GetIntFromObj(interp, objv[3], &iIdx) ){ ++ return TCL_ERROR; ++ } ++ ++ if( iSub==PRE_OLD ){ ++ rc = sqlite3_preupdate_old(pDb->db, iIdx, &pValue); ++ }else{ ++ assert( iSub==PRE_NEW ); ++ rc = sqlite3_preupdate_new(pDb->db, iIdx, &pValue); ++ } ++ ++ if( rc==SQLITE_OK ){ ++ Tcl_Obj *pObj; ++ pObj = Tcl_NewStringObj((char*)sqlite3_value_text(pValue), -1); ++ Tcl_SetObjResult(interp, pObj); ++ }else{ ++ Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0); ++ return TCL_ERROR; ++ } ++ } ++ } ++#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ ++ break; ++ } ++ ++ /* ++ ** $db wal_hook ?script? ++ ** $db update_hook ?script? ++ ** $db rollback_hook ?script? ++ */ ++ case DB_WAL_HOOK: ++ case DB_UPDATE_HOOK: ++ case DB_ROLLBACK_HOOK: { ++ /* set ppHook to point at pUpdateHook or pRollbackHook, depending on ++ ** whether [$db update_hook] or [$db rollback_hook] was invoked. ++ */ ++ Tcl_Obj **ppHook = 0; ++ if( choice==DB_WAL_HOOK ) ppHook = &pDb->pWalHook; ++ if( choice==DB_UPDATE_HOOK ) ppHook = &pDb->pUpdateHook; ++ if( choice==DB_ROLLBACK_HOOK ) ppHook = &pDb->pRollbackHook; ++ if( objc>3 ){ ++ Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?"); ++ return TCL_ERROR; ++ } ++ ++ DbHookCmd(interp, pDb, (objc==3 ? objv[2] : 0), ppHook); ++ break; ++ } ++ ++ /* $db version ++ ** ++ ** Return the version string for this database. ++ */ ++ case DB_VERSION: { ++ int i; ++ for(i=2; i<objc; i++){ ++ const char *zArg = Tcl_GetString(objv[i]); ++ /* Optional arguments to $db version are used for testing purpose */ ++#ifdef SQLITE_TEST ++ /* $db version -use-legacy-prepare BOOLEAN ++ ** ++ ** Turn the use of legacy sqlite3_prepare() on or off. ++ */ ++ if( strcmp(zArg, "-use-legacy-prepare")==0 && i+1<objc ){ ++ i++; ++ if( Tcl_GetBooleanFromObj(interp, objv[i], &pDb->bLegacyPrepare) ){ ++ return TCL_ERROR; ++ } ++ }else ++ ++ /* $db version -last-stmt-ptr ++ ** ++ ** Return a string which is a hex encoding of the pointer to the ++ ** most recent sqlite3_stmt in the statement cache. ++ */ ++ if( strcmp(zArg, "-last-stmt-ptr")==0 ){ ++ char zBuf[100]; ++ sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", ++ pDb->stmtList ? pDb->stmtList->pStmt: 0); ++ Tcl_SetResult(interp, zBuf, TCL_VOLATILE); ++ }else ++#endif /* SQLITE_TEST */ ++ { ++ Tcl_AppendResult(interp, "unknown argument: ", zArg, (char*)0); ++ return TCL_ERROR; ++ } ++ } ++ if( i==2 ){ ++ Tcl_SetResult(interp, (char *)sqlite3_libversion(), TCL_STATIC); ++ } ++ break; ++ } ++ ++ ++ } /* End of the SWITCH statement */ ++ return rc; ++} ++ ++#if SQLITE_TCL_NRE ++/* ++** Adaptor that provides an objCmd interface to the NRE-enabled ++** interface implementation. ++*/ ++static int SQLITE_TCLAPI DbObjCmdAdaptor( ++ void *cd, ++ Tcl_Interp *interp, ++ int objc, ++ Tcl_Obj *const*objv ++){ ++ return Tcl_NRCallObjProc(interp, DbObjCmd, cd, objc, objv); ++} ++#endif /* SQLITE_TCL_NRE */ ++ ++/* ++** Issue the usage message when the "sqlite3" command arguments are ++** incorrect. ++*/ ++static int sqliteCmdUsage( ++ Tcl_Interp *interp, ++ Tcl_Obj *const*objv ++){ ++ Tcl_WrongNumArgs(interp, 1, objv, ++ "HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?" ++ " ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?" ++#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL) ++ " ?-key CODECKEY?" ++#endif ++ ); ++ return TCL_ERROR; ++} ++ ++/* ++** sqlite3 DBNAME FILENAME ?-vfs VFSNAME? ?-key KEY? ?-readonly BOOLEAN? ++** ?-create BOOLEAN? ?-nomutex BOOLEAN? ++** ++** This is the main Tcl command. When the "sqlite" Tcl command is ++** invoked, this routine runs to process that command. ++** ++** The first argument, DBNAME, is an arbitrary name for a new ++** database connection. This command creates a new command named ++** DBNAME that is used to control that connection. The database ++** connection is deleted when the DBNAME command is deleted. ++** ++** The second argument is the name of the database file. ++** ++*/ ++static int SQLITE_TCLAPI DbMain( ++ void *cd, ++ Tcl_Interp *interp, ++ int objc, ++ Tcl_Obj *const*objv ++){ ++ SqliteDb *p; ++ const char *zArg; ++ char *zErrMsg; ++ int i; ++ const char *zFile = 0; ++ const char *zVfs = 0; ++ int flags; ++ Tcl_DString translatedFilename; ++#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL) ++ void *pKey = 0; ++ int nKey = 0; ++#endif ++ int rc; ++ ++ /* In normal use, each TCL interpreter runs in a single thread. So ++ ** by default, we can turn off mutexing on SQLite database connections. ++ ** However, for testing purposes it is useful to have mutexes turned ++ ** on. So, by default, mutexes default off. But if compiled with ++ ** SQLITE_TCL_DEFAULT_FULLMUTEX then mutexes default on. ++ */ ++#ifdef SQLITE_TCL_DEFAULT_FULLMUTEX ++ flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX; ++#else ++ flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX; ++#endif ++ ++ if( objc==1 ) return sqliteCmdUsage(interp, objv); ++ if( objc==2 ){ ++ zArg = Tcl_GetStringFromObj(objv[1], 0); ++ if( strcmp(zArg,"-version")==0 ){ ++ Tcl_AppendResult(interp,sqlite3_libversion(), (char*)0); ++ return TCL_OK; ++ } ++ if( strcmp(zArg,"-sourceid")==0 ){ ++ Tcl_AppendResult(interp,sqlite3_sourceid(), (char*)0); ++ return TCL_OK; ++ } ++ if( strcmp(zArg,"-has-codec")==0 ){ ++#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL) ++ Tcl_AppendResult(interp,"1",(char*)0); ++#else ++ Tcl_AppendResult(interp,"0",(char*)0); ++#endif ++ return TCL_OK; ++ } ++ if( zArg[0]=='-' ) return sqliteCmdUsage(interp, objv); ++ } ++ for(i=2; i<objc; i++){ ++ zArg = Tcl_GetString(objv[i]); ++ if( zArg[0]!='-' ){ ++ if( zFile!=0 ) return sqliteCmdUsage(interp, objv); ++ zFile = zArg; ++ continue; ++ } ++ if( i==objc-1 ) return sqliteCmdUsage(interp, objv); ++ i++; ++ if( strcmp(zArg,"-key")==0 ){ ++#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL) ++ pKey = Tcl_GetByteArrayFromObj(objv[i], &nKey); ++#endif ++ }else if( strcmp(zArg, "-vfs")==0 ){ ++ zVfs = Tcl_GetString(objv[i]); ++ }else if( strcmp(zArg, "-readonly")==0 ){ ++ int b; ++ if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR; ++ if( b ){ ++ flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); ++ flags |= SQLITE_OPEN_READONLY; ++ }else{ ++ flags &= ~SQLITE_OPEN_READONLY; ++ flags |= SQLITE_OPEN_READWRITE; ++ } ++ }else if( strcmp(zArg, "-create")==0 ){ ++ int b; ++ if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR; ++ if( b && (flags & SQLITE_OPEN_READONLY)==0 ){ ++ flags |= SQLITE_OPEN_CREATE; ++ }else{ ++ flags &= ~SQLITE_OPEN_CREATE; ++ } ++ }else if( strcmp(zArg, "-nomutex")==0 ){ ++ int b; ++ if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR; ++ if( b ){ ++ flags |= SQLITE_OPEN_NOMUTEX; ++ flags &= ~SQLITE_OPEN_FULLMUTEX; ++ }else{ ++ flags &= ~SQLITE_OPEN_NOMUTEX; ++ } ++ }else if( strcmp(zArg, "-fullmutex")==0 ){ ++ int b; ++ if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR; ++ if( b ){ ++ flags |= SQLITE_OPEN_FULLMUTEX; ++ flags &= ~SQLITE_OPEN_NOMUTEX; ++ }else{ ++ flags &= ~SQLITE_OPEN_FULLMUTEX; ++ } ++ }else if( strcmp(zArg, "-uri")==0 ){ ++ int b; ++ if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR; ++ if( b ){ ++ flags |= SQLITE_OPEN_URI; ++ }else{ ++ flags &= ~SQLITE_OPEN_URI; ++ } ++ }else{ ++ Tcl_AppendResult(interp, "unknown option: ", zArg, (char*)0); ++ return TCL_ERROR; ++ } ++ } ++ zErrMsg = 0; ++ p = (SqliteDb*)Tcl_Alloc( sizeof(*p) ); ++ memset(p, 0, sizeof(*p)); ++ if( zFile==0 ) zFile = ""; ++ zFile = Tcl_TranslateFileName(interp, zFile, &translatedFilename); ++ rc = sqlite3_open_v2(zFile, &p->db, flags, zVfs); ++ Tcl_DStringFree(&translatedFilename); ++ if( p->db ){ ++ if( SQLITE_OK!=sqlite3_errcode(p->db) ){ ++ zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(p->db)); ++ sqlite3_close(p->db); ++ p->db = 0; ++ } ++ }else{ ++ zErrMsg = sqlite3_mprintf("%s", sqlite3_errstr(rc)); ++ } ++#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL) ++ if( p->db ){ ++ sqlite3_key(p->db, pKey, nKey); ++ } ++#endif ++ if( p->db==0 ){ ++ Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE); ++ Tcl_Free((char*)p); ++ sqlite3_free(zErrMsg); ++ return TCL_ERROR; ++ } ++ p->maxStmt = NUM_PREPARED_STMTS; ++ p->openFlags = flags & SQLITE_OPEN_URI; ++ p->interp = interp; ++ zArg = Tcl_GetStringFromObj(objv[1], 0); ++ if( DbUseNre() ){ ++ Tcl_NRCreateCommand(interp, zArg, DbObjCmdAdaptor, DbObjCmd, ++ (char*)p, DbDeleteCmd); ++ }else{ ++ Tcl_CreateObjCommand(interp, zArg, DbObjCmd, (char*)p, DbDeleteCmd); ++ } ++ return TCL_OK; ++} ++ ++/* ++** Provide a dummy Tcl_InitStubs if we are using this as a static ++** library. ++*/ ++#ifndef USE_TCL_STUBS ++# undef Tcl_InitStubs ++# define Tcl_InitStubs(a,b,c) TCL_VERSION ++#endif ++ ++/* ++** Make sure we have a PACKAGE_VERSION macro defined. This will be ++** defined automatically by the TEA makefile. But other makefiles ++** do not define it. ++*/ ++#ifndef PACKAGE_VERSION ++# define PACKAGE_VERSION SQLITE_VERSION ++#endif ++ ++/* ++** Initialize this module. ++** ++** This Tcl module contains only a single new Tcl command named "sqlite". ++** (Hence there is no namespace. There is no point in using a namespace ++** if the extension only supplies one new name!) The "sqlite" command is ++** used to open a new SQLite database. See the DbMain() routine above ++** for additional information. ++** ++** The EXTERN macros are required by TCL in order to work on windows. ++*/ ++EXTERN int Sqlite3_Init(Tcl_Interp *interp){ ++ int rc = Tcl_InitStubs(interp, "8.4", 0) ? TCL_OK : TCL_ERROR; ++ if( rc==TCL_OK ){ ++ Tcl_CreateObjCommand(interp, "sqlite3", (Tcl_ObjCmdProc*)DbMain, 0, 0); ++#ifndef SQLITE_3_SUFFIX_ONLY ++ /* The "sqlite" alias is undocumented. It is here only to support ++ ** legacy scripts. All new scripts should use only the "sqlite3" ++ ** command. */ ++ Tcl_CreateObjCommand(interp, "sqlite", (Tcl_ObjCmdProc*)DbMain, 0, 0); ++#endif ++ rc = Tcl_PkgProvide(interp, "sqlite3", PACKAGE_VERSION); ++ } ++ return rc; ++} ++EXTERN int Tclsqlite3_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); } ++EXTERN int Sqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; } ++EXTERN int Tclsqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; } ++ ++/* Because it accesses the file-system and uses persistent state, SQLite ++** is not considered appropriate for safe interpreters. Hence, we cause ++** the _SafeInit() interfaces return TCL_ERROR. ++*/ ++EXTERN int Sqlite3_SafeInit(Tcl_Interp *interp){ return TCL_ERROR; } ++EXTERN int Sqlite3_SafeUnload(Tcl_Interp *interp, int flags){return TCL_ERROR;} ++ ++ ++ ++#ifndef SQLITE_3_SUFFIX_ONLY ++int Sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); } ++int Tclsqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); } ++int Sqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; } ++int Tclsqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; } ++#endif ++ ++/* ++** If the TCLSH macro is defined, add code to make a stand-alone program. ++*/ ++#if defined(TCLSH) ++ ++/* This is the main routine for an ordinary TCL shell. If there are ++** are arguments, run the first argument as a script. Otherwise, ++** read TCL commands from standard input ++*/ ++static const char *tclsh_main_loop(void){ ++ static const char zMainloop[] = ++ "if {[llength $argv]>=1} {\n" ++ "set argv0 [lindex $argv 0]\n" ++ "set argv [lrange $argv 1 end]\n" ++ "source $argv0\n" ++ "} else {\n" ++ "set line {}\n" ++ "while {![eof stdin]} {\n" ++ "if {$line!=\"\"} {\n" ++ "puts -nonewline \"> \"\n" ++ "} else {\n" ++ "puts -nonewline \"% \"\n" ++ "}\n" ++ "flush stdout\n" ++ "append line [gets stdin]\n" ++ "if {[info complete $line]} {\n" ++ "if {[catch {uplevel #0 $line} result]} {\n" ++ "puts stderr \"Error: $result\"\n" ++ "} elseif {$result!=\"\"} {\n" ++ "puts $result\n" ++ "}\n" ++ "set line {}\n" ++ "} else {\n" ++ "append line \\n\n" ++ "}\n" ++ "}\n" ++ "}\n" ++ ; ++ return zMainloop; ++} ++ ++#define TCLSH_MAIN main /* Needed to fake out mktclapp */ ++int SQLITE_CDECL TCLSH_MAIN(int argc, char **argv){ ++ Tcl_Interp *interp; ++ int i; ++ const char *zScript = 0; ++ char zArgc[32]; ++#if defined(TCLSH_INIT_PROC) ++ extern const char *TCLSH_INIT_PROC(Tcl_Interp*); ++#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) ++ DebugBreak(); ++#elif defined(SIGTRAP) ++ raise(SIGTRAP); ++#endif ++ } ++ } ++#endif ++ ++ /* Call sqlite3_shutdown() once before doing anything else. This is to ++ ** test that sqlite3_shutdown() can be safely called by a process before ++ ** sqlite3_initialize() is. */ ++ sqlite3_shutdown(); ++ ++ Tcl_FindExecutable(argv[0]); ++ Tcl_SetSystemEncoding(NULL, "utf-8"); ++ interp = Tcl_CreateInterp(); ++ Sqlite3_Init(interp); ++ ++ sqlite3_snprintf(sizeof(zArgc), zArgc, "%d", argc-1); ++ Tcl_SetVar(interp,"argc", zArgc, TCL_GLOBAL_ONLY); ++ Tcl_SetVar(interp,"argv0",argv[0],TCL_GLOBAL_ONLY); ++ Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY); ++ for(i=1; i<argc; i++){ ++ Tcl_SetVar(interp, "argv", argv[i], ++ TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE); ++ } ++#if defined(TCLSH_INIT_PROC) ++ zScript = TCLSH_INIT_PROC(interp); ++#endif ++ if( zScript==0 ){ ++ zScript = tclsh_main_loop(); ++ } ++ if( Tcl_GlobalEval(interp, zScript)!=TCL_OK ){ ++ const char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY); ++ if( zInfo==0 ) zInfo = Tcl_GetStringResult(interp); ++ fprintf(stderr,"%s: %s\n", *argv, zInfo); ++ return 1; ++ } ++ return 0; ++} ++#endif /* TCLSH */ +--- contrib/sqlite3/tea/license.terms.orig ++++ contrib/sqlite3/tea/license.terms +@@ -0,0 +1,6 @@ ++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. +--- contrib/sqlite3/tea/pkgIndex.tcl.in.orig ++++ contrib/sqlite3/tea/pkgIndex.tcl.in +@@ -0,0 +1,7 @@ ++# ++# Tcl package index file ++# ++# Note sqlite*3* init specifically ++# ++package ifneeded sqlite3 @PACKAGE_VERSION@ \ ++ [list load [file join $dir @PKG_LIB_FILE@] Sqlite3] +--- contrib/sqlite3/tea/tclconfig/install-sh.orig ++++ contrib/sqlite3/tea/tclconfig/install-sh +@@ -0,0 +1,528 @@ ++#!/bin/sh ++# install - install a program, script, or datafile ++ ++scriptversion=2011-04-20.01; # UTC ++ ++# This originates from X11R5 (mit/util/scripts/install.sh), which was ++# later released in X11R6 (xc/config/util/install.sh) with the ++# following copyright and license. ++# ++# Copyright (C) 1994 X Consortium ++# ++# Permission is hereby granted, free of charge, to any person obtaining a copy ++# of this software and associated documentation files (the "Software"), to ++# deal in the Software without restriction, including without limitation the ++# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++# sell copies of the Software, and to permit persons to whom the Software is ++# furnished to do so, subject to the following conditions: ++# ++# The above copyright notice and this permission notice shall be included in ++# all copies or substantial portions of the Software. ++# ++# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN ++# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- ++# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++# ++# Except as contained in this notice, the name of the X Consortium shall not ++# be used in advertising or otherwise to promote the sale, use or other deal- ++# ings in this Software without prior written authorization from the X Consor- ++# tium. ++# ++# ++# FSF changes to this file are in the public domain. ++# ++# Calling this script install-sh is preferred over install.sh, to prevent ++# `make' implicit rules from creating a file called install from it ++# when there is no Makefile. ++# ++# This script is compatible with the BSD install script, but was written ++# from scratch. ++ ++nl=' ++' ++IFS=" "" $nl" ++ ++# set DOITPROG to echo to test this script ++ ++# Don't use :- since 4.3BSD and earlier shells don't like it. ++doit=${DOITPROG-} ++if test -z "$doit"; then ++ doit_exec=exec ++else ++ doit_exec=$doit ++fi ++ ++# Put in absolute file names if you don't have them in your path; ++# or use environment vars. ++ ++chgrpprog=${CHGRPPROG-chgrp} ++chmodprog=${CHMODPROG-chmod} ++chownprog=${CHOWNPROG-chown} ++cmpprog=${CMPPROG-cmp} ++cpprog=${CPPROG-cp} ++mkdirprog=${MKDIRPROG-mkdir} ++mvprog=${MVPROG-mv} ++rmprog=${RMPROG-rm} ++stripprog=${STRIPPROG-strip} ++ ++posix_glob='?' ++initialize_posix_glob=' ++ test "$posix_glob" != "?" || { ++ if (set -f) 2>/dev/null; then ++ posix_glob= ++ else ++ posix_glob=: ++ fi ++ } ++' ++ ++posix_mkdir= ++ ++# Desired mode of installed file. ++mode=0755 ++ ++chgrpcmd= ++chmodcmd=$chmodprog ++chowncmd= ++mvcmd=$mvprog ++rmcmd="$rmprog -f" ++stripcmd= ++ ++src= ++dst= ++dir_arg= ++dst_arg= ++ ++copy_on_change=false ++no_target_directory= ++ ++usage="\ ++Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE ++ or: $0 [OPTION]... SRCFILES... DIRECTORY ++ or: $0 [OPTION]... -t DIRECTORY SRCFILES... ++ or: $0 [OPTION]... -d DIRECTORIES... ++ ++In the 1st form, copy SRCFILE to DSTFILE. ++In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. ++In the 4th, create DIRECTORIES. ++ ++Options: ++ --help display this help and exit. ++ --version display version info and exit. ++ ++ -c (ignored) ++ -C install only if different (preserve the last data modification time) ++ -d create directories instead of installing files. ++ -g GROUP $chgrpprog installed files to GROUP. ++ -m MODE $chmodprog installed files to MODE. ++ -o USER $chownprog installed files to USER. ++ -s $stripprog installed files. ++ -S $stripprog installed files. ++ -t DIRECTORY install into DIRECTORY. ++ -T report an error if DSTFILE is a directory. ++ ++Environment variables override the default commands: ++ CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG ++ RMPROG STRIPPROG ++" ++ ++while test $# -ne 0; do ++ case $1 in ++ -c) ;; ++ ++ -C) copy_on_change=true;; ++ ++ -d) dir_arg=true;; ++ ++ -g) chgrpcmd="$chgrpprog $2" ++ shift;; ++ ++ --help) echo "$usage"; exit $?;; ++ ++ -m) mode=$2 ++ case $mode in ++ *' '* | *' '* | *' ++'* | *'*'* | *'?'* | *'['*) ++ echo "$0: invalid mode: $mode" >&2 ++ exit 1;; ++ esac ++ shift;; ++ ++ -o) chowncmd="$chownprog $2" ++ shift;; ++ ++ -s) stripcmd=$stripprog;; ++ ++ -S) stripcmd="$stripprog $2" ++ shift;; ++ ++ -t) dst_arg=$2 ++ shift;; ++ ++ -T) no_target_directory=true;; ++ ++ --version) echo "$0 $scriptversion"; exit $?;; ++ ++ --) shift ++ break;; ++ ++ -*) echo "$0: invalid option: $1" >&2 ++ exit 1;; ++ ++ *) break;; ++ esac ++ shift ++done ++ ++if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then ++ # When -d is used, all remaining arguments are directories to create. ++ # When -t is used, the destination is already specified. ++ # Otherwise, the last argument is the destination. Remove it from $@. ++ for arg ++ do ++ if test -n "$dst_arg"; then ++ # $@ is not empty: it contains at least $arg. ++ set fnord "$@" "$dst_arg" ++ shift # fnord ++ fi ++ shift # arg ++ dst_arg=$arg ++ done ++fi ++ ++if test $# -eq 0; then ++ if test -z "$dir_arg"; then ++ echo "$0: no input file specified." >&2 ++ exit 1 ++ fi ++ # It's OK to call `install-sh -d' without argument. ++ # This can happen when creating conditional directories. ++ exit 0 ++fi ++ ++if test -z "$dir_arg"; then ++ do_exit='(exit $ret); exit $ret' ++ trap "ret=129; $do_exit" 1 ++ trap "ret=130; $do_exit" 2 ++ trap "ret=141; $do_exit" 13 ++ trap "ret=143; $do_exit" 15 ++ ++ # Set umask so as not to create temps with too-generous modes. ++ # However, 'strip' requires both read and write access to temps. ++ case $mode in ++ # Optimize common cases. ++ *644) cp_umask=133;; ++ *755) cp_umask=22;; ++ ++ *[0-7]) ++ if test -z "$stripcmd"; then ++ u_plus_rw= ++ else ++ u_plus_rw='% 200' ++ fi ++ cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; ++ *) ++ if test -z "$stripcmd"; then ++ u_plus_rw= ++ else ++ u_plus_rw=,u+rw ++ fi ++ cp_umask=$mode$u_plus_rw;; ++ esac ++fi ++ ++for src ++do ++ # Protect names starting with `-'. ++ case $src in ++ -*) src=./$src;; ++ esac ++ ++ if test -n "$dir_arg"; then ++ dst=$src ++ dstdir=$dst ++ test -d "$dstdir" ++ dstdir_status=$? ++ else ++ ++ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command ++ # might cause directories to be created, which would be especially bad ++ # if $src (and thus $dsttmp) contains '*'. ++ if test ! -f "$src" && test ! -d "$src"; then ++ echo "$0: $src does not exist." >&2 ++ exit 1 ++ fi ++ ++ if test -z "$dst_arg"; then ++ echo "$0: no destination specified." >&2 ++ exit 1 ++ fi ++ ++ dst=$dst_arg ++ # Protect names starting with `-'. ++ case $dst in ++ -*) dst=./$dst;; ++ esac ++ ++ # If destination is a directory, append the input filename; won't work ++ # if double slashes aren't ignored. ++ if test -d "$dst"; then ++ if test -n "$no_target_directory"; then ++ echo "$0: $dst_arg: Is a directory" >&2 ++ exit 1 ++ fi ++ dstdir=$dst ++ dst=$dstdir/`basename "$src"` ++ dstdir_status=0 ++ else ++ # Prefer dirname, but fall back on a substitute if dirname fails. ++ dstdir=` ++ (dirname "$dst") 2>/dev/null || ++ expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ ++ X"$dst" : 'X\(//\)[^/]' \| \ ++ X"$dst" : 'X\(//\)$' \| \ ++ X"$dst" : 'X\(/\)' \| . 2>/dev/null || ++ echo X"$dst" | ++ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ ++ s//\1/ ++ q ++ } ++ /^X\(\/\/\)[^/].*/{ ++ s//\1/ ++ q ++ } ++ /^X\(\/\/\)$/{ ++ s//\1/ ++ q ++ } ++ /^X\(\/\).*/{ ++ s//\1/ ++ q ++ } ++ s/.*/./; q' ++ ` ++ ++ test -d "$dstdir" ++ dstdir_status=$? ++ fi ++ fi ++ ++ obsolete_mkdir_used=false ++ ++ if test $dstdir_status != 0; then ++ case $posix_mkdir in ++ '') ++ # Create intermediate dirs using mode 755 as modified by the umask. ++ # This is like FreeBSD 'install' as of 1997-10-28. ++ umask=`umask` ++ case $stripcmd.$umask in ++ # Optimize common cases. ++ *[2367][2367]) mkdir_umask=$umask;; ++ .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; ++ ++ *[0-7]) ++ mkdir_umask=`expr $umask + 22 \ ++ - $umask % 100 % 40 + $umask % 20 \ ++ - $umask % 10 % 4 + $umask % 2 ++ `;; ++ *) mkdir_umask=$umask,go-w;; ++ esac ++ ++ # With -d, create the new directory with the user-specified mode. ++ # Otherwise, rely on $mkdir_umask. ++ if test -n "$dir_arg"; then ++ mkdir_mode=-m$mode ++ else ++ mkdir_mode= ++ fi ++ ++ posix_mkdir=false ++ case $umask in ++ *[123567][0-7][0-7]) ++ # POSIX mkdir -p sets u+wx bits regardless of umask, which ++ # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ++ ;; ++ *) ++ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ ++ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 ++ ++ if (umask $mkdir_umask && ++ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 ++ then ++ if test -z "$dir_arg" || { ++ # Check for POSIX incompatibilities with -m. ++ # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or ++ # other-writeable bit of parent directory when it shouldn't. ++ # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ++ ls_ld_tmpdir=`ls -ld "$tmpdir"` ++ case $ls_ld_tmpdir in ++ d????-?r-*) different_mode=700;; ++ d????-?--*) different_mode=755;; ++ *) false;; ++ esac && ++ $mkdirprog -m$different_mode -p -- "$tmpdir" && { ++ ls_ld_tmpdir_1=`ls -ld "$tmpdir"` ++ test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" ++ } ++ } ++ then posix_mkdir=: ++ fi ++ rmdir "$tmpdir/d" "$tmpdir" ++ else ++ # Remove any dirs left behind by ancient mkdir implementations. ++ rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null ++ fi ++ trap '' 0;; ++ esac;; ++ esac ++ ++ if ++ $posix_mkdir && ( ++ umask $mkdir_umask && ++ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ++ ) ++ then : ++ else ++ ++ # The umask is ridiculous, or mkdir does not conform to POSIX, ++ # or it failed possibly due to a race condition. Create the ++ # directory the slow way, step by step, checking for races as we go. ++ ++ case $dstdir in ++ /*) prefix='/';; ++ -*) prefix='./';; ++ *) prefix='';; ++ esac ++ ++ eval "$initialize_posix_glob" ++ ++ oIFS=$IFS ++ IFS=/ ++ $posix_glob set -f ++ set fnord $dstdir ++ shift ++ $posix_glob set +f ++ IFS=$oIFS ++ ++ prefixes= ++ ++ for d ++ do ++ test -z "$d" && continue ++ ++ prefix=$prefix$d ++ if test -d "$prefix"; then ++ prefixes= ++ else ++ if $posix_mkdir; then ++ (umask=$mkdir_umask && ++ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break ++ # Don't fail if two instances are running concurrently. ++ test -d "$prefix" || exit 1 ++ else ++ case $prefix in ++ *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; ++ *) qprefix=$prefix;; ++ esac ++ prefixes="$prefixes '$qprefix'" ++ fi ++ fi ++ prefix=$prefix/ ++ done ++ ++ if test -n "$prefixes"; then ++ # Don't fail if two instances are running concurrently. ++ (umask $mkdir_umask && ++ eval "\$doit_exec \$mkdirprog $prefixes") || ++ test -d "$dstdir" || exit 1 ++ obsolete_mkdir_used=true ++ fi ++ fi ++ fi ++ ++ if test -n "$dir_arg"; then ++ { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && ++ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && ++ { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || ++ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 ++ else ++ ++ # Make a couple of temp file names in the proper directory. ++ dsttmp=$dstdir/_inst.$$_ ++ rmtmp=$dstdir/_rm.$$_ ++ ++ # Trap to clean up those temp files at exit. ++ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 ++ ++ # Copy the file name to the temp name. ++ (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && ++ ++ # and set any options; do chmod last to preserve setuid bits. ++ # ++ # If any of these fail, we abort the whole thing. If we want to ++ # ignore errors from any of these, just make sure not to ignore ++ # errors from the above "$doit $cpprog $src $dsttmp" command. ++ # ++ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && ++ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && ++ { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && ++ { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && ++ ++ # If -C, don't bother to copy if it wouldn't change the file. ++ if $copy_on_change && ++ old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && ++ new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && ++ ++ eval "$initialize_posix_glob" && ++ $posix_glob set -f && ++ set X $old && old=:$2:$4:$5:$6 && ++ set X $new && new=:$2:$4:$5:$6 && ++ $posix_glob set +f && ++ ++ test "$old" = "$new" && ++ $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 ++ then ++ rm -f "$dsttmp" ++ else ++ # Rename the file to the real destination. ++ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || ++ ++ # The rename failed, perhaps because mv can't rename something else ++ # to itself, or perhaps because mv is so ancient that it does not ++ # support -f. ++ { ++ # Now remove or move aside any old file at destination location. ++ # We try this two ways since rm can't unlink itself on some ++ # systems and the destination file might be busy for other ++ # reasons. In this case, the final cleanup might fail but the new ++ # file should still install successfully. ++ { ++ test ! -f "$dst" || ++ $doit $rmcmd -f "$dst" 2>/dev/null || ++ { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && ++ { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } ++ } || ++ { echo "$0: cannot unlink or rename $dst" >&2 ++ (exit 1); exit 1 ++ } ++ } && ++ ++ # Now rename the file to the real destination. ++ $doit $mvcmd "$dsttmp" "$dst" ++ } ++ fi || exit 1 ++ ++ trap '' 0 ++ fi ++done ++ ++# Local variables: ++# eval: (add-hook 'write-file-hooks 'time-stamp) ++# time-stamp-start: "scriptversion=" ++# time-stamp-format: "%:y-%02m-%02d.%02H" ++# time-stamp-time-zone: "UTC" ++# time-stamp-end: "; # UTC" ++# End: +--- contrib/sqlite3/tea/tclconfig/tcl.m4.orig ++++ contrib/sqlite3/tea/tclconfig/tcl.m4 +@@ -0,0 +1,4168 @@ ++# tcl.m4 -- ++# ++# This file provides a set of autoconf macros to help TEA-enable ++# a Tcl extension. ++# ++# Copyright (c) 1999-2000 Ajuba Solutions. ++# Copyright (c) 2002-2005 ActiveState Corporation. ++# ++# See the file "license.terms" for information on usage and redistribution ++# of this file, and for a DISCLAIMER OF ALL WARRANTIES. ++ ++AC_PREREQ(2.57) ++ ++dnl TEA extensions pass us the version of TEA they think they ++dnl are compatible with (must be set in TEA_INIT below) ++dnl TEA_VERSION="3.9" ++ ++# Possible values for key variables defined: ++# ++# TEA_WINDOWINGSYSTEM - win32 aqua x11 (mirrors 'tk windowingsystem') ++# TEA_PLATFORM - windows unix ++# ++ ++#------------------------------------------------------------------------ ++# TEA_PATH_TCLCONFIG -- ++# ++# Locate the tclConfig.sh file and perform a sanity check on ++# the Tcl compile flags ++# ++# Arguments: ++# none ++# ++# Results: ++# ++# Adds the following arguments to configure: ++# --with-tcl=... ++# ++# Defines the following vars: ++# TCL_BIN_DIR Full path to the directory containing ++# the tclConfig.sh file ++#------------------------------------------------------------------------ ++ ++AC_DEFUN([TEA_PATH_TCLCONFIG], [ ++ dnl TEA specific: Make sure we are initialized ++ AC_REQUIRE([TEA_INIT]) ++ # ++ # Ok, lets find the tcl configuration ++ # First, look for one uninstalled. ++ # the alternative search directory is invoked by --with-tcl ++ # ++ ++ if test x"${no_tcl}" = x ; then ++ # we reset no_tcl in case something fails here ++ no_tcl=true ++ AC_ARG_WITH(tcl, ++ AC_HELP_STRING([--with-tcl], ++ [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 ++ case "${with_tclconfig}" in ++ */tclConfig.sh ) ++ if test -f "${with_tclconfig}"; then ++ AC_MSG_WARN([--with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself]) ++ with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`" ++ fi ;; ++ esac ++ if test -f "${with_tclconfig}/tclConfig.sh" ; then ++ ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`" ++ else ++ AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh]) ++ fi ++ fi ++ ++ # then check for a private Tcl installation ++ if test x"${ac_cv_c_tclconfig}" = x ; then ++ for i in \ ++ ../tcl \ ++ `ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ ++ `ls -dr ../tcl[[8-9]].[[0-9]] 2>/dev/null` \ ++ `ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ ++ ../../tcl \ ++ `ls -dr ../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ ++ `ls -dr ../../tcl[[8-9]].[[0-9]] 2>/dev/null` \ ++ `ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ ++ ../../../tcl \ ++ `ls -dr ../../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ ++ `ls -dr ../../../tcl[[8-9]].[[0-9]] 2>/dev/null` \ ++ `ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do ++ if test "${TEA_PLATFORM}" = "windows" \ ++ -a -f "$i/win/tclConfig.sh" ; then ++ ac_cv_c_tclconfig="`(cd $i/win; pwd)`" ++ break ++ fi ++ if test -f "$i/unix/tclConfig.sh" ; then ++ ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" ++ break ++ fi ++ done ++ fi ++ ++ # on Darwin, check in Framework installation locations ++ if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then ++ for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ ++ `ls -d /Library/Frameworks 2>/dev/null` \ ++ `ls -d /Network/Library/Frameworks 2>/dev/null` \ ++ `ls -d /System/Library/Frameworks 2>/dev/null` \ ++ ; do ++ if test -f "$i/Tcl.framework/tclConfig.sh" ; then ++ ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`" ++ break ++ fi ++ done ++ fi ++ ++ # TEA specific: on Windows, check in common installation locations ++ if test "${TEA_PLATFORM}" = "windows" \ ++ -a x"${ac_cv_c_tclconfig}" = x ; then ++ for i in `ls -d C:/Tcl/lib 2>/dev/null` \ ++ `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ ++ ; do ++ if test -f "$i/tclConfig.sh" ; then ++ ac_cv_c_tclconfig="`(cd $i; pwd)`" ++ break ++ fi ++ done ++ fi ++ ++ # check in a few common install locations ++ if test x"${ac_cv_c_tclconfig}" = x ; then ++ for i in `ls -d ${libdir} 2>/dev/null` \ ++ `ls -d ${exec_prefix}/lib 2>/dev/null` \ ++ `ls -d ${prefix}/lib 2>/dev/null` \ ++ `ls -d /usr/local/lib 2>/dev/null` \ ++ `ls -d /usr/contrib/lib 2>/dev/null` \ ++ `ls -d /usr/lib 2>/dev/null` \ ++ `ls -d /usr/lib64 2>/dev/null` \ ++ `ls -d /usr/lib/tcl8.6 2>/dev/null` \ ++ `ls -d /usr/lib/tcl8.5 2>/dev/null` \ ++ ; do ++ if test -f "$i/tclConfig.sh" ; then ++ ac_cv_c_tclconfig="`(cd $i; pwd)`" ++ break ++ fi ++ done ++ fi ++ ++ # check in a few other private locations ++ if test x"${ac_cv_c_tclconfig}" = x ; then ++ for i in \ ++ ${srcdir}/../tcl \ ++ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ ++ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]] 2>/dev/null` \ ++ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do ++ if test "${TEA_PLATFORM}" = "windows" \ ++ -a -f "$i/win/tclConfig.sh" ; then ++ ac_cv_c_tclconfig="`(cd $i/win; pwd)`" ++ break ++ fi ++ if test -f "$i/unix/tclConfig.sh" ; then ++ ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" ++ break ++ fi ++ done ++ fi ++ ]) ++ ++ if test x"${ac_cv_c_tclconfig}" = x ; then ++ TCL_BIN_DIR="# no Tcl configs found" ++ AC_MSG_ERROR([Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh]) ++ else ++ no_tcl= ++ TCL_BIN_DIR="${ac_cv_c_tclconfig}" ++ AC_MSG_RESULT([found ${TCL_BIN_DIR}/tclConfig.sh]) ++ fi ++ fi ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_PATH_TKCONFIG -- ++# ++# Locate the tkConfig.sh file ++# ++# Arguments: ++# none ++# ++# Results: ++# ++# Adds the following arguments to configure: ++# --with-tk=... ++# ++# Defines the following vars: ++# TK_BIN_DIR Full path to the directory containing ++# the tkConfig.sh file ++#------------------------------------------------------------------------ ++ ++AC_DEFUN([TEA_PATH_TKCONFIG], [ ++ # ++ # Ok, lets find the tk configuration ++ # First, look for one uninstalled. ++ # the alternative search directory is invoked by --with-tk ++ # ++ ++ if test x"${no_tk}" = x ; then ++ # we reset no_tk in case something fails here ++ no_tk=true ++ AC_ARG_WITH(tk, ++ AC_HELP_STRING([--with-tk], ++ [directory containing tk configuration (tkConfig.sh)]), ++ with_tkconfig="${withval}") ++ AC_MSG_CHECKING([for Tk configuration]) ++ AC_CACHE_VAL(ac_cv_c_tkconfig,[ ++ ++ # First check to see if --with-tkconfig was specified. ++ if test x"${with_tkconfig}" != x ; then ++ case "${with_tkconfig}" in ++ */tkConfig.sh ) ++ if test -f "${with_tkconfig}"; then ++ AC_MSG_WARN([--with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself]) ++ with_tkconfig="`echo "${with_tkconfig}" | sed 's!/tkConfig\.sh$!!'`" ++ fi ;; ++ esac ++ if test -f "${with_tkconfig}/tkConfig.sh" ; then ++ ac_cv_c_tkconfig="`(cd "${with_tkconfig}"; pwd)`" ++ else ++ AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh]) ++ fi ++ fi ++ ++ # then check for a private Tk library ++ if test x"${ac_cv_c_tkconfig}" = x ; then ++ for i in \ ++ ../tk \ ++ `ls -dr ../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ ++ `ls -dr ../tk[[8-9]].[[0-9]] 2>/dev/null` \ ++ `ls -dr ../tk[[8-9]].[[0-9]]* 2>/dev/null` \ ++ ../../tk \ ++ `ls -dr ../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ ++ `ls -dr ../../tk[[8-9]].[[0-9]] 2>/dev/null` \ ++ `ls -dr ../../tk[[8-9]].[[0-9]]* 2>/dev/null` \ ++ ../../../tk \ ++ `ls -dr ../../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ ++ `ls -dr ../../../tk[[8-9]].[[0-9]] 2>/dev/null` \ ++ `ls -dr ../../../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do ++ if test "${TEA_PLATFORM}" = "windows" \ ++ -a -f "$i/win/tkConfig.sh" ; then ++ ac_cv_c_tkconfig="`(cd $i/win; pwd)`" ++ break ++ fi ++ if test -f "$i/unix/tkConfig.sh" ; then ++ ac_cv_c_tkconfig="`(cd $i/unix; pwd)`" ++ break ++ fi ++ done ++ fi ++ ++ # on Darwin, check in Framework installation locations ++ if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tkconfig}" = x ; then ++ for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ ++ `ls -d /Library/Frameworks 2>/dev/null` \ ++ `ls -d /Network/Library/Frameworks 2>/dev/null` \ ++ `ls -d /System/Library/Frameworks 2>/dev/null` \ ++ ; do ++ if test -f "$i/Tk.framework/tkConfig.sh" ; then ++ ac_cv_c_tkconfig="`(cd $i/Tk.framework; pwd)`" ++ break ++ fi ++ done ++ fi ++ ++ # check in a few common install locations ++ if test x"${ac_cv_c_tkconfig}" = x ; then ++ for i in `ls -d ${libdir} 2>/dev/null` \ ++ `ls -d ${exec_prefix}/lib 2>/dev/null` \ ++ `ls -d ${prefix}/lib 2>/dev/null` \ ++ `ls -d /usr/local/lib 2>/dev/null` \ ++ `ls -d /usr/contrib/lib 2>/dev/null` \ ++ `ls -d /usr/lib 2>/dev/null` \ ++ `ls -d /usr/lib64 2>/dev/null` \ ++ ; do ++ if test -f "$i/tkConfig.sh" ; then ++ ac_cv_c_tkconfig="`(cd $i; pwd)`" ++ break ++ fi ++ done ++ fi ++ ++ # TEA specific: on Windows, check in common installation locations ++ if test "${TEA_PLATFORM}" = "windows" \ ++ -a x"${ac_cv_c_tkconfig}" = x ; then ++ for i in `ls -d C:/Tcl/lib 2>/dev/null` \ ++ `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ ++ ; do ++ if test -f "$i/tkConfig.sh" ; then ++ ac_cv_c_tkconfig="`(cd $i; pwd)`" ++ break ++ fi ++ done ++ fi ++ ++ # check in a few other private locations ++ if test x"${ac_cv_c_tkconfig}" = x ; then ++ for i in \ ++ ${srcdir}/../tk \ ++ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ ++ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]] 2>/dev/null` \ ++ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do ++ if test "${TEA_PLATFORM}" = "windows" \ ++ -a -f "$i/win/tkConfig.sh" ; then ++ ac_cv_c_tkconfig="`(cd $i/win; pwd)`" ++ break ++ fi ++ if test -f "$i/unix/tkConfig.sh" ; then ++ ac_cv_c_tkconfig="`(cd $i/unix; pwd)`" ++ break ++ fi ++ done ++ fi ++ ]) ++ ++ if test x"${ac_cv_c_tkconfig}" = x ; then ++ TK_BIN_DIR="# no Tk configs found" ++ AC_MSG_ERROR([Can't find Tk configuration definitions. Use --with-tk to specify a directory containing tkConfig.sh]) ++ else ++ no_tk= ++ TK_BIN_DIR="${ac_cv_c_tkconfig}" ++ AC_MSG_RESULT([found ${TK_BIN_DIR}/tkConfig.sh]) ++ fi ++ fi ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_LOAD_TCLCONFIG -- ++# ++# Load the tclConfig.sh file ++# ++# Arguments: ++# ++# Requires the following vars to be set: ++# TCL_BIN_DIR ++# ++# Results: ++# ++# Substitutes the following vars: ++# TCL_BIN_DIR ++# TCL_SRC_DIR ++# TCL_LIB_FILE ++#------------------------------------------------------------------------ ++ ++AC_DEFUN([TEA_LOAD_TCLCONFIG], [ ++ AC_MSG_CHECKING([for existence of ${TCL_BIN_DIR}/tclConfig.sh]) ++ ++ if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then ++ AC_MSG_RESULT([loading]) ++ . "${TCL_BIN_DIR}/tclConfig.sh" ++ else ++ AC_MSG_RESULT([could not find ${TCL_BIN_DIR}/tclConfig.sh]) ++ fi ++ ++ # eval is required to do the TCL_DBGX substitution ++ eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\"" ++ eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\"" ++ ++ # If the TCL_BIN_DIR is the build directory (not the install directory), ++ # then set the common variable name to the value of the build variables. ++ # For example, the variable TCL_LIB_SPEC will be set to the value ++ # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC ++ # instead of TCL_BUILD_LIB_SPEC since it will work with both an ++ # installed and uninstalled version of Tcl. ++ if test -f "${TCL_BIN_DIR}/Makefile" ; then ++ TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}" ++ TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}" ++ TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}" ++ elif test "`uname -s`" = "Darwin"; then ++ # If Tcl was built as a framework, attempt to use the libraries ++ # from the framework at the given location so that linking works ++ # against Tcl.framework installed in an arbitrary location. ++ case ${TCL_DEFS} in ++ *TCL_FRAMEWORK*) ++ if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then ++ for i in "`cd "${TCL_BIN_DIR}"; pwd`" \ ++ "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do ++ if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then ++ TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}" ++ break ++ fi ++ done ++ fi ++ if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then ++ TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}" ++ TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}" ++ fi ++ ;; ++ esac ++ fi ++ ++ # eval is required to do the TCL_DBGX substitution ++ eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\"" ++ eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\"" ++ eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\"" ++ eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\"" ++ ++ AC_SUBST(TCL_VERSION) ++ AC_SUBST(TCL_PATCH_LEVEL) ++ AC_SUBST(TCL_BIN_DIR) ++ AC_SUBST(TCL_SRC_DIR) ++ ++ AC_SUBST(TCL_LIB_FILE) ++ AC_SUBST(TCL_LIB_FLAG) ++ AC_SUBST(TCL_LIB_SPEC) ++ ++ AC_SUBST(TCL_STUB_LIB_FILE) ++ AC_SUBST(TCL_STUB_LIB_FLAG) ++ AC_SUBST(TCL_STUB_LIB_SPEC) ++ ++ AC_MSG_CHECKING([platform]) ++ hold_cc=$CC; CC="$TCL_CC" ++ AC_TRY_COMPILE(,[ ++ #ifdef _WIN32 ++ #error win32 ++ #endif ++ ], TEA_PLATFORM="unix", ++ TEA_PLATFORM="windows" ++ ) ++ CC=$hold_cc ++ AC_MSG_RESULT($TEA_PLATFORM) ++ ++ # The BUILD_$pkg is to define the correct extern storage class ++ # handling when making this package ++ AC_DEFINE_UNQUOTED(BUILD_${PACKAGE_NAME}, [], ++ [Building extension source?]) ++ # Do this here as we have fully defined TEA_PLATFORM now ++ if test "${TEA_PLATFORM}" = "windows" ; then ++ EXEEXT=".exe" ++ CLEANFILES="$CLEANFILES *.lib *.dll *.pdb *.exp" ++ fi ++ ++ # TEA specific: ++ AC_SUBST(CLEANFILES) ++ AC_SUBST(TCL_LIBS) ++ AC_SUBST(TCL_DEFS) ++ AC_SUBST(TCL_EXTRA_CFLAGS) ++ AC_SUBST(TCL_LD_FLAGS) ++ AC_SUBST(TCL_SHLIB_LD_LIBS) ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_LOAD_TKCONFIG -- ++# ++# Load the tkConfig.sh file ++# ++# Arguments: ++# ++# Requires the following vars to be set: ++# TK_BIN_DIR ++# ++# Results: ++# ++# Sets the following vars that should be in tkConfig.sh: ++# TK_BIN_DIR ++#------------------------------------------------------------------------ ++ ++AC_DEFUN([TEA_LOAD_TKCONFIG], [ ++ AC_MSG_CHECKING([for existence of ${TK_BIN_DIR}/tkConfig.sh]) ++ ++ if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then ++ AC_MSG_RESULT([loading]) ++ . "${TK_BIN_DIR}/tkConfig.sh" ++ else ++ AC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh]) ++ fi ++ ++ # eval is required to do the TK_DBGX substitution ++ eval "TK_LIB_FILE=\"${TK_LIB_FILE}\"" ++ eval "TK_STUB_LIB_FILE=\"${TK_STUB_LIB_FILE}\"" ++ ++ # If the TK_BIN_DIR is the build directory (not the install directory), ++ # then set the common variable name to the value of the build variables. ++ # For example, the variable TK_LIB_SPEC will be set to the value ++ # of TK_BUILD_LIB_SPEC. An extension should make use of TK_LIB_SPEC ++ # instead of TK_BUILD_LIB_SPEC since it will work with both an ++ # installed and uninstalled version of Tcl. ++ if test -f "${TK_BIN_DIR}/Makefile" ; then ++ TK_LIB_SPEC="${TK_BUILD_LIB_SPEC}" ++ TK_STUB_LIB_SPEC="${TK_BUILD_STUB_LIB_SPEC}" ++ TK_STUB_LIB_PATH="${TK_BUILD_STUB_LIB_PATH}" ++ elif test "`uname -s`" = "Darwin"; then ++ # If Tk was built as a framework, attempt to use the libraries ++ # from the framework at the given location so that linking works ++ # against Tk.framework installed in an arbitrary location. ++ case ${TK_DEFS} in ++ *TK_FRAMEWORK*) ++ if test -f "${TK_BIN_DIR}/${TK_LIB_FILE}"; then ++ for i in "`cd "${TK_BIN_DIR}"; pwd`" \ ++ "`cd "${TK_BIN_DIR}"/../..; pwd`"; do ++ if test "`basename "$i"`" = "${TK_LIB_FILE}.framework"; then ++ TK_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TK_LIB_FILE}" ++ break ++ fi ++ done ++ fi ++ if test -f "${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"; then ++ TK_STUB_LIB_SPEC="-L` echo "${TK_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TK_STUB_LIB_FLAG}" ++ TK_STUB_LIB_PATH="${TK_BIN_DIR}/${TK_STUB_LIB_FILE}" ++ fi ++ ;; ++ esac ++ fi ++ ++ # eval is required to do the TK_DBGX substitution ++ eval "TK_LIB_FLAG=\"${TK_LIB_FLAG}\"" ++ eval "TK_LIB_SPEC=\"${TK_LIB_SPEC}\"" ++ eval "TK_STUB_LIB_FLAG=\"${TK_STUB_LIB_FLAG}\"" ++ eval "TK_STUB_LIB_SPEC=\"${TK_STUB_LIB_SPEC}\"" ++ ++ # TEA specific: Ensure windowingsystem is defined ++ if test "${TEA_PLATFORM}" = "unix" ; then ++ case ${TK_DEFS} in ++ *MAC_OSX_TK*) ++ AC_DEFINE(MAC_OSX_TK, 1, [Are we building against Mac OS X TkAqua?]) ++ TEA_WINDOWINGSYSTEM="aqua" ++ ;; ++ *) ++ TEA_WINDOWINGSYSTEM="x11" ++ ;; ++ esac ++ elif test "${TEA_PLATFORM}" = "windows" ; then ++ TEA_WINDOWINGSYSTEM="win32" ++ fi ++ ++ AC_SUBST(TK_VERSION) ++ AC_SUBST(TK_BIN_DIR) ++ AC_SUBST(TK_SRC_DIR) ++ ++ AC_SUBST(TK_LIB_FILE) ++ AC_SUBST(TK_LIB_FLAG) ++ AC_SUBST(TK_LIB_SPEC) ++ ++ AC_SUBST(TK_STUB_LIB_FILE) ++ AC_SUBST(TK_STUB_LIB_FLAG) ++ AC_SUBST(TK_STUB_LIB_SPEC) ++ ++ # TEA specific: ++ AC_SUBST(TK_LIBS) ++ AC_SUBST(TK_XINCLUDES) ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_PROG_TCLSH ++# Determine the fully qualified path name of the tclsh executable ++# in the Tcl build directory or the tclsh installed in a bin ++# directory. This macro will correctly determine the name ++# of the tclsh executable even if tclsh has not yet been ++# built in the build directory. The tclsh found is always ++# associated with a tclConfig.sh file. This tclsh should be used ++# only for running extension test cases. It should never be ++# or generation of files (like pkgIndex.tcl) at build time. ++# ++# Arguments: ++# none ++# ++# Results: ++# Substitutes the following vars: ++# TCLSH_PROG ++#------------------------------------------------------------------------ ++ ++AC_DEFUN([TEA_PROG_TCLSH], [ ++ AC_MSG_CHECKING([for tclsh]) ++ if test -f "${TCL_BIN_DIR}/Makefile" ; then ++ # tclConfig.sh is in Tcl build directory ++ if test "${TEA_PLATFORM}" = "windows"; then ++ TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" ++ else ++ TCLSH_PROG="${TCL_BIN_DIR}/tclsh" ++ fi ++ else ++ # tclConfig.sh is in install location ++ if test "${TEA_PLATFORM}" = "windows"; then ++ TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" ++ else ++ TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_DBGX}" ++ fi ++ list="`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \ ++ `ls -d ${TCL_BIN_DIR}/.. 2>/dev/null` \ ++ `ls -d ${TCL_PREFIX}/bin 2>/dev/null`" ++ for i in $list ; do ++ if test -f "$i/${TCLSH_PROG}" ; then ++ REAL_TCL_BIN_DIR="`cd "$i"; pwd`/" ++ break ++ fi ++ done ++ TCLSH_PROG="${REAL_TCL_BIN_DIR}${TCLSH_PROG}" ++ fi ++ AC_MSG_RESULT([${TCLSH_PROG}]) ++ AC_SUBST(TCLSH_PROG) ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_PROG_WISH ++# Determine the fully qualified path name of the wish executable ++# in the Tk build directory or the wish installed in a bin ++# directory. This macro will correctly determine the name ++# of the wish executable even if wish has not yet been ++# built in the build directory. The wish found is always ++# associated with a tkConfig.sh file. This wish should be used ++# only for running extension test cases. It should never be ++# or generation of files (like pkgIndex.tcl) at build time. ++# ++# Arguments: ++# none ++# ++# Results: ++# Substitutes the following vars: ++# WISH_PROG ++#------------------------------------------------------------------------ ++ ++AC_DEFUN([TEA_PROG_WISH], [ ++ AC_MSG_CHECKING([for wish]) ++ if test -f "${TK_BIN_DIR}/Makefile" ; then ++ # tkConfig.sh is in Tk build directory ++ if test "${TEA_PLATFORM}" = "windows"; then ++ WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}" ++ else ++ WISH_PROG="${TK_BIN_DIR}/wish" ++ fi ++ else ++ # tkConfig.sh is in install location ++ if test "${TEA_PLATFORM}" = "windows"; then ++ WISH_PROG="wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}" ++ else ++ WISH_PROG="wish${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}${TK_DBGX}" ++ fi ++ list="`ls -d ${TK_BIN_DIR}/../bin 2>/dev/null` \ ++ `ls -d ${TK_BIN_DIR}/.. 2>/dev/null` \ ++ `ls -d ${TK_PREFIX}/bin 2>/dev/null`" ++ for i in $list ; do ++ if test -f "$i/${WISH_PROG}" ; then ++ REAL_TK_BIN_DIR="`cd "$i"; pwd`/" ++ break ++ fi ++ done ++ WISH_PROG="${REAL_TK_BIN_DIR}${WISH_PROG}" ++ fi ++ AC_MSG_RESULT([${WISH_PROG}]) ++ AC_SUBST(WISH_PROG) ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_ENABLE_SHARED -- ++# ++# Allows the building of shared libraries ++# ++# Arguments: ++# none ++# ++# Results: ++# ++# Adds the following arguments to configure: ++# --enable-shared=yes|no ++# ++# Defines the following vars: ++# STATIC_BUILD Used for building import/export libraries ++# on Windows. ++# ++# Sets the following vars: ++# SHARED_BUILD Value of 1 or 0 ++#------------------------------------------------------------------------ ++ ++AC_DEFUN([TEA_ENABLE_SHARED], [ ++ AC_MSG_CHECKING([how to build libraries]) ++ AC_ARG_ENABLE(shared, ++ AC_HELP_STRING([--enable-shared], ++ [build and link with shared libraries (default: on)]), ++ [tcl_ok=$enableval], [tcl_ok=yes]) ++ ++ if test "${enable_shared+set}" = set; then ++ enableval="$enable_shared" ++ tcl_ok=$enableval ++ else ++ tcl_ok=yes ++ fi ++ ++ if test "$tcl_ok" = "yes" ; then ++ AC_MSG_RESULT([shared]) ++ SHARED_BUILD=1 ++ else ++ AC_MSG_RESULT([static]) ++ SHARED_BUILD=0 ++ AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?]) ++ fi ++ AC_SUBST(SHARED_BUILD) ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_ENABLE_THREADS -- ++# ++# Specify if thread support should be enabled. If "yes" is specified ++# as an arg (optional), threads are enabled by default, "no" means ++# threads are disabled. "yes" is the default. ++# ++# TCL_THREADS is checked so that if you are compiling an extension ++# against a threaded core, your extension must be compiled threaded ++# as well. ++# ++# Note that it is legal to have a thread enabled extension run in a ++# threaded or non-threaded Tcl core, but a non-threaded extension may ++# only run in a non-threaded Tcl core. ++# ++# Arguments: ++# none ++# ++# Results: ++# ++# Adds the following arguments to configure: ++# --enable-threads ++# ++# Sets the following vars: ++# THREADS_LIBS Thread library(s) ++# ++# Defines the following vars: ++# TCL_THREADS ++# _REENTRANT ++# _THREAD_SAFE ++#------------------------------------------------------------------------ ++ ++AC_DEFUN([TEA_ENABLE_THREADS], [ ++ AC_ARG_ENABLE(threads, ++ AC_HELP_STRING([--enable-threads], ++ [build with threads]), ++ [tcl_ok=$enableval], [tcl_ok=yes]) ++ ++ if test "${enable_threads+set}" = set; then ++ enableval="$enable_threads" ++ tcl_ok=$enableval ++ else ++ tcl_ok=yes ++ fi ++ ++ if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then ++ TCL_THREADS=1 ++ ++ if test "${TEA_PLATFORM}" != "windows" ; then ++ # We are always OK on Windows, so check what this platform wants: ++ ++ # USE_THREAD_ALLOC tells us to try the special thread-based ++ # allocator that significantly reduces lock contention ++ AC_DEFINE(USE_THREAD_ALLOC, 1, ++ [Do we want to use the threaded memory allocator?]) ++ AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) ++ if test "`uname -s`" = "SunOS" ; then ++ AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, ++ [Do we really want to follow the standard? Yes we do!]) ++ fi ++ AC_DEFINE(_THREAD_SAFE, 1, [Do we want the thread-safe OS API?]) ++ AC_CHECK_LIB(pthread,pthread_mutex_init,tcl_ok=yes,tcl_ok=no) ++ if test "$tcl_ok" = "no"; then ++ # Check a little harder for __pthread_mutex_init in the same ++ # library, as some systems hide it there until pthread.h is ++ # defined. We could alternatively do an AC_TRY_COMPILE with ++ # pthread.h, but that will work with libpthread really doesn't ++ # exist, like AIX 4.2. [Bug: 4359] ++ AC_CHECK_LIB(pthread, __pthread_mutex_init, ++ tcl_ok=yes, tcl_ok=no) ++ fi ++ ++ if test "$tcl_ok" = "yes"; then ++ # The space is needed ++ THREADS_LIBS=" -lpthread" ++ else ++ AC_CHECK_LIB(pthreads, pthread_mutex_init, ++ tcl_ok=yes, tcl_ok=no) ++ if test "$tcl_ok" = "yes"; then ++ # The space is needed ++ THREADS_LIBS=" -lpthreads" ++ else ++ AC_CHECK_LIB(c, pthread_mutex_init, ++ tcl_ok=yes, tcl_ok=no) ++ if test "$tcl_ok" = "no"; then ++ AC_CHECK_LIB(c_r, pthread_mutex_init, ++ tcl_ok=yes, tcl_ok=no) ++ if test "$tcl_ok" = "yes"; then ++ # The space is needed ++ THREADS_LIBS=" -pthread" ++ else ++ TCL_THREADS=0 ++ AC_MSG_WARN([Do not know how to find pthread lib on your system - thread support disabled]) ++ fi ++ fi ++ fi ++ fi ++ fi ++ else ++ TCL_THREADS=0 ++ fi ++ # Do checking message here to not mess up interleaved configure output ++ AC_MSG_CHECKING([for building with threads]) ++ if test "${TCL_THREADS}" = 1; then ++ AC_DEFINE(TCL_THREADS, 1, [Are we building with threads enabled?]) ++ AC_MSG_RESULT([yes (default)]) ++ else ++ AC_MSG_RESULT([no]) ++ fi ++ # TCL_THREADS sanity checking. See if our request for building with ++ # threads is the same as the way Tcl was built. If not, warn the user. ++ case ${TCL_DEFS} in ++ *THREADS=1*) ++ if test "${TCL_THREADS}" = "0"; then ++ AC_MSG_WARN([ ++ Building ${PACKAGE_NAME} without threads enabled, but building against Tcl ++ that IS thread-enabled. It is recommended to use --enable-threads.]) ++ fi ++ ;; ++ *) ++ if test "${TCL_THREADS}" = "1"; then ++ AC_MSG_WARN([ ++ --enable-threads requested, but building against a Tcl that is NOT ++ thread-enabled. This is an OK configuration that will also run in ++ a thread-enabled core.]) ++ fi ++ ;; ++ esac ++ AC_SUBST(TCL_THREADS) ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_ENABLE_SYMBOLS -- ++# ++# Specify if debugging symbols should be used. ++# Memory (TCL_MEM_DEBUG) debugging can also be enabled. ++# ++# Arguments: ++# none ++# ++# TEA varies from core Tcl in that C|LDFLAGS_DEFAULT receives ++# the value of C|LDFLAGS_OPTIMIZE|DEBUG already substituted. ++# Requires the following vars to be set in the Makefile: ++# CFLAGS_DEFAULT ++# LDFLAGS_DEFAULT ++# ++# Results: ++# ++# Adds the following arguments to configure: ++# --enable-symbols ++# ++# Defines the following vars: ++# CFLAGS_DEFAULT Sets to $(CFLAGS_DEBUG) if true ++# Sets to "$(CFLAGS_OPTIMIZE) -DNDEBUG" if false ++# LDFLAGS_DEFAULT Sets to $(LDFLAGS_DEBUG) if true ++# Sets to $(LDFLAGS_OPTIMIZE) if false ++# DBGX Formerly used as debug library extension; ++# always blank now. ++#------------------------------------------------------------------------ ++ ++AC_DEFUN([TEA_ENABLE_SYMBOLS], [ ++ dnl TEA specific: Make sure we are initialized ++ AC_REQUIRE([TEA_CONFIG_CFLAGS]) ++ AC_MSG_CHECKING([for build with symbols]) ++ AC_ARG_ENABLE(symbols, ++ AC_HELP_STRING([--enable-symbols], ++ [build with debugging symbols (default: off)]), ++ [tcl_ok=$enableval], [tcl_ok=no]) ++ DBGX="" ++ if test "$tcl_ok" = "no"; then ++ CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE} -DNDEBUG" ++ LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}" ++ AC_MSG_RESULT([no]) ++ else ++ CFLAGS_DEFAULT="${CFLAGS_DEBUG}" ++ LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}" ++ if test "$tcl_ok" = "yes"; then ++ AC_MSG_RESULT([yes (standard debugging)]) ++ fi ++ fi ++ # TEA specific: ++ if test "${TEA_PLATFORM}" != "windows" ; then ++ LDFLAGS_DEFAULT="${LDFLAGS}" ++ fi ++ AC_SUBST(CFLAGS_DEFAULT) ++ AC_SUBST(LDFLAGS_DEFAULT) ++ AC_SUBST(TCL_DBGX) ++ ++ if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then ++ AC_DEFINE(TCL_MEM_DEBUG, 1, [Is memory debugging enabled?]) ++ fi ++ ++ if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then ++ if test "$tcl_ok" = "all"; then ++ AC_MSG_RESULT([enabled symbols mem debugging]) ++ else ++ AC_MSG_RESULT([enabled $tcl_ok debugging]) ++ fi ++ fi ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_ENABLE_LANGINFO -- ++# ++# Allows use of modern nl_langinfo check for better l10n. ++# This is only relevant for Unix. ++# ++# Arguments: ++# none ++# ++# Results: ++# ++# Adds the following arguments to configure: ++# --enable-langinfo=yes|no (default is yes) ++# ++# Defines the following vars: ++# HAVE_LANGINFO Triggers use of nl_langinfo if defined. ++#------------------------------------------------------------------------ ++ ++AC_DEFUN([TEA_ENABLE_LANGINFO], [ ++ AC_ARG_ENABLE(langinfo, ++ AC_HELP_STRING([--enable-langinfo], ++ [use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on)]), ++ [langinfo_ok=$enableval], [langinfo_ok=yes]) ++ ++ HAVE_LANGINFO=0 ++ if test "$langinfo_ok" = "yes"; then ++ AC_CHECK_HEADER(langinfo.h,[langinfo_ok=yes],[langinfo_ok=no]) ++ fi ++ AC_MSG_CHECKING([whether to use nl_langinfo]) ++ if test "$langinfo_ok" = "yes"; then ++ AC_CACHE_VAL(tcl_cv_langinfo_h, [ ++ AC_TRY_COMPILE([#include <langinfo.h>], [nl_langinfo(CODESET);], ++ [tcl_cv_langinfo_h=yes],[tcl_cv_langinfo_h=no])]) ++ AC_MSG_RESULT([$tcl_cv_langinfo_h]) ++ if test $tcl_cv_langinfo_h = yes; then ++ AC_DEFINE(HAVE_LANGINFO, 1, [Do we have nl_langinfo()?]) ++ fi ++ else ++ AC_MSG_RESULT([$langinfo_ok]) ++ fi ++]) ++ ++#-------------------------------------------------------------------- ++# TEA_CONFIG_SYSTEM ++# ++# Determine what the system is (some things cannot be easily checked ++# on a feature-driven basis, alas). This can usually be done via the ++# "uname" command. ++# ++# Arguments: ++# none ++# ++# Results: ++# Defines the following var: ++# ++# system - System/platform/version identification code. ++#-------------------------------------------------------------------- ++ ++AC_DEFUN([TEA_CONFIG_SYSTEM], [ ++ AC_CACHE_CHECK([system version], tcl_cv_sys_version, [ ++ # TEA specific: ++ if test "${TEA_PLATFORM}" = "windows" ; then ++ tcl_cv_sys_version=windows ++ else ++ tcl_cv_sys_version=`uname -s`-`uname -r` ++ if test "$?" -ne 0 ; then ++ AC_MSG_WARN([can't find uname command]) ++ tcl_cv_sys_version=unknown ++ else ++ if test "`uname -s`" = "AIX" ; then ++ tcl_cv_sys_version=AIX-`uname -v`.`uname -r` ++ fi ++ fi ++ fi ++ ]) ++ system=$tcl_cv_sys_version ++]) ++ ++#-------------------------------------------------------------------- ++# TEA_CONFIG_CFLAGS ++# ++# Try to determine the proper flags to pass to the compiler ++# for building shared libraries and other such nonsense. ++# ++# Arguments: ++# none ++# ++# Results: ++# ++# Defines and substitutes the following vars: ++# ++# DL_OBJS, DL_LIBS - removed for TEA, only needed by core. ++# LDFLAGS - Flags to pass to the compiler when linking object ++# files into an executable application binary such ++# as tclsh. ++# LD_SEARCH_FLAGS-Flags to pass to ld, such as "-R /usr/local/tcl/lib", ++# that tell the run-time dynamic linker where to look ++# for shared libraries such as libtcl.so. Depends on ++# the variable LIB_RUNTIME_DIR in the Makefile. Could ++# be the same as CC_SEARCH_FLAGS if ${CC} is used to link. ++# CC_SEARCH_FLAGS-Flags to pass to ${CC}, such as "-Wl,-rpath,/usr/local/tcl/lib", ++# that tell the run-time dynamic linker where to look ++# for shared libraries such as libtcl.so. Depends on ++# the variable LIB_RUNTIME_DIR in the Makefile. ++# SHLIB_CFLAGS - Flags to pass to cc when compiling the components ++# of a shared library (may request position-independent ++# code, among other things). ++# SHLIB_LD - Base command to use for combining object files ++# into a shared library. ++# SHLIB_LD_LIBS - Dependent libraries for the linker to scan when ++# creating shared libraries. This symbol typically ++# goes at the end of the "ld" commands that build ++# shared libraries. The value of the symbol defaults to ++# "${LIBS}" if all of the dependent libraries should ++# be specified when creating a shared library. If ++# dependent libraries should not be specified (as on ++# SunOS 4.x, where they cause the link to fail, or in ++# general if Tcl and Tk aren't themselves shared ++# libraries), then this symbol has an empty string ++# as its value. ++# SHLIB_SUFFIX - Suffix to use for the names of dynamically loadable ++# extensions. An empty string means we don't know how ++# to use shared libraries on this platform. ++# LIB_SUFFIX - Specifies everything that comes after the "libfoo" ++# in a static or shared library name, using the $PACKAGE_VERSION variable ++# to put the version in the right place. This is used ++# by platforms that need non-standard library names. ++# Examples: ${PACKAGE_VERSION}.so.1.1 on NetBSD, since it needs ++# to have a version after the .so, and ${PACKAGE_VERSION}.a ++# on AIX, since a shared library needs to have ++# a .a extension whereas shared objects for loadable ++# extensions have a .so extension. Defaults to ++# ${PACKAGE_VERSION}${SHLIB_SUFFIX}. ++# CFLAGS_DEBUG - ++# Flags used when running the compiler in debug mode ++# CFLAGS_OPTIMIZE - ++# Flags used when running the compiler in optimize mode ++# CFLAGS - Additional CFLAGS added as necessary (usually 64-bit) ++#-------------------------------------------------------------------- ++ ++AC_DEFUN([TEA_CONFIG_CFLAGS], [ ++ dnl TEA specific: Make sure we are initialized ++ AC_REQUIRE([TEA_INIT]) ++ ++ # Step 0.a: Enable 64 bit support? ++ ++ AC_MSG_CHECKING([if 64bit support is requested]) ++ AC_ARG_ENABLE(64bit, ++ AC_HELP_STRING([--enable-64bit], ++ [enable 64bit support (default: off)]), ++ [do64bit=$enableval], [do64bit=no]) ++ AC_MSG_RESULT([$do64bit]) ++ ++ # Step 0.b: Enable Solaris 64 bit VIS support? ++ ++ AC_MSG_CHECKING([if 64bit Sparc VIS support is requested]) ++ AC_ARG_ENABLE(64bit-vis, ++ AC_HELP_STRING([--enable-64bit-vis], ++ [enable 64bit Sparc VIS support (default: off)]), ++ [do64bitVIS=$enableval], [do64bitVIS=no]) ++ AC_MSG_RESULT([$do64bitVIS]) ++ # Force 64bit on with VIS ++ AS_IF([test "$do64bitVIS" = "yes"], [do64bit=yes]) ++ ++ # Step 0.c: Check if visibility support is available. Do this here so ++ # that platform specific alternatives can be used below if this fails. ++ ++ AC_CACHE_CHECK([if compiler supports visibility "hidden"], ++ tcl_cv_cc_visibility_hidden, [ ++ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" ++ AC_TRY_LINK([ ++ extern __attribute__((__visibility__("hidden"))) void f(void); ++ void f(void) {}], [f();], tcl_cv_cc_visibility_hidden=yes, ++ tcl_cv_cc_visibility_hidden=no) ++ CFLAGS=$hold_cflags]) ++ AS_IF([test $tcl_cv_cc_visibility_hidden = yes], [ ++ AC_DEFINE(MODULE_SCOPE, ++ [extern __attribute__((__visibility__("hidden")))], ++ [Compiler support for module scope symbols]) ++ AC_DEFINE(HAVE_HIDDEN, [1], [Compiler support for module scope symbols]) ++ ]) ++ ++ # Step 0.d: Disable -rpath support? ++ ++ AC_MSG_CHECKING([if rpath support is requested]) ++ AC_ARG_ENABLE(rpath, ++ AC_HELP_STRING([--disable-rpath], ++ [disable rpath support (default: on)]), ++ [doRpath=$enableval], [doRpath=yes]) ++ AC_MSG_RESULT([$doRpath]) ++ ++ # TEA specific: Cross-compiling options for Windows/CE builds? ++ ++ AS_IF([test "${TEA_PLATFORM}" = windows], [ ++ AC_MSG_CHECKING([if Windows/CE build is requested]) ++ AC_ARG_ENABLE(wince, ++ AC_HELP_STRING([--enable-wince], ++ [enable Win/CE support (where applicable)]), ++ [doWince=$enableval], [doWince=no]) ++ AC_MSG_RESULT([$doWince]) ++ ]) ++ ++ # Set the variable "system" to hold the name and version number ++ # for the system. ++ ++ TEA_CONFIG_SYSTEM ++ ++ # Require ranlib early so we can override it in special cases below. ++ ++ AC_REQUIRE([AC_PROG_RANLIB]) ++ ++ # Set configuration options based on system name and version. ++ # This is similar to Tcl's unix/tcl.m4 except that we've added a ++ # "windows" case and removed some core-only vars. ++ ++ do64bit_ok=no ++ # default to '{$LIBS}' and set to "" on per-platform necessary basis ++ SHLIB_LD_LIBS='${LIBS}' ++ # When ld needs options to work in 64-bit mode, put them in ++ # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load] ++ # is disabled by the user. [Bug 1016796] ++ LDFLAGS_ARCH="" ++ UNSHARED_LIB_SUFFIX="" ++ # TEA specific: use PACKAGE_VERSION instead of VERSION ++ TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`' ++ ECHO_VERSION='`echo ${PACKAGE_VERSION}`' ++ TCL_LIB_VERSIONS_OK=ok ++ CFLAGS_DEBUG=-g ++ AS_IF([test "$GCC" = yes], [ ++ CFLAGS_OPTIMIZE=-O2 ++ CFLAGS_WARNING="-Wall" ++ ], [ ++ CFLAGS_OPTIMIZE=-O ++ CFLAGS_WARNING="" ++ ]) ++ AC_CHECK_TOOL(AR, ar) ++ STLIB_LD='${AR} cr' ++ LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" ++ AS_IF([test "x$SHLIB_VERSION" = x],[SHLIB_VERSION="1.0"]) ++ case $system in ++ # TEA specific: ++ windows) ++ # This is a 2-stage check to make sure we have the 64-bit SDK ++ # We have to know where the SDK is installed. ++ # This magic is based on MS Platform SDK for Win2003 SP1 - hobbs ++ # MACHINE is IX86 for LINK, but this is used by the manifest, ++ # which requires x86|amd64|ia64. ++ MACHINE="X86" ++ if test "$do64bit" != "no" ; then ++ if test "x${MSSDK}x" = "xx" ; then ++ MSSDK="C:/Progra~1/Microsoft Platform SDK" ++ fi ++ MSSDK=`echo "$MSSDK" | sed -e 's!\\\!/!g'` ++ PATH64="" ++ case "$do64bit" in ++ amd64|x64|yes) ++ MACHINE="AMD64" ; # default to AMD64 64-bit build ++ PATH64="${MSSDK}/Bin/Win64/x86/AMD64" ++ ;; ++ ia64) ++ MACHINE="IA64" ++ PATH64="${MSSDK}/Bin/Win64" ++ ;; ++ esac ++ if test "$GCC" != "yes" -a ! -d "${PATH64}" ; then ++ AC_MSG_WARN([Could not find 64-bit $MACHINE SDK to enable 64bit mode]) ++ AC_MSG_WARN([Ensure latest Platform SDK is installed]) ++ do64bit="no" ++ else ++ AC_MSG_RESULT([ Using 64-bit $MACHINE mode]) ++ do64bit_ok="yes" ++ fi ++ fi ++ ++ if test "$doWince" != "no" ; then ++ if test "$do64bit" != "no" ; then ++ AC_MSG_ERROR([Windows/CE and 64-bit builds incompatible]) ++ fi ++ if test "$GCC" = "yes" ; then ++ AC_MSG_ERROR([Windows/CE and GCC builds incompatible]) ++ fi ++ TEA_PATH_CELIB ++ # Set defaults for common evc4/PPC2003 setup ++ # Currently Tcl requires 300+, possibly 420+ for sockets ++ CEVERSION=420; # could be 211 300 301 400 420 ... ++ TARGETCPU=ARMV4; # could be ARMV4 ARM MIPS SH3 X86 ... ++ ARCH=ARM; # could be ARM MIPS X86EM ... ++ PLATFORM="Pocket PC 2003"; # or "Pocket PC 2002" ++ if test "$doWince" != "yes"; then ++ # If !yes then the user specified something ++ # Reset ARCH to allow user to skip specifying it ++ ARCH= ++ eval `echo $doWince | awk -F, '{ \ ++ if (length([$]1)) { printf "CEVERSION=\"%s\"\n", [$]1; \ ++ if ([$]1 < 400) { printf "PLATFORM=\"Pocket PC 2002\"\n" } }; \ ++ if (length([$]2)) { printf "TARGETCPU=\"%s\"\n", toupper([$]2) }; \ ++ if (length([$]3)) { printf "ARCH=\"%s\"\n", toupper([$]3) }; \ ++ if (length([$]4)) { printf "PLATFORM=\"%s\"\n", [$]4 }; \ ++ }'` ++ if test "x${ARCH}" = "x" ; then ++ ARCH=$TARGETCPU; ++ fi ++ fi ++ OSVERSION=WCE$CEVERSION; ++ if test "x${WCEROOT}" = "x" ; then ++ WCEROOT="C:/Program Files/Microsoft eMbedded C++ 4.0" ++ if test ! -d "${WCEROOT}" ; then ++ WCEROOT="C:/Program Files/Microsoft eMbedded Tools" ++ fi ++ fi ++ if test "x${SDKROOT}" = "x" ; then ++ SDKROOT="C:/Program Files/Windows CE Tools" ++ if test ! -d "${SDKROOT}" ; then ++ SDKROOT="C:/Windows CE Tools" ++ fi ++ fi ++ WCEROOT=`echo "$WCEROOT" | sed -e 's!\\\!/!g'` ++ SDKROOT=`echo "$SDKROOT" | sed -e 's!\\\!/!g'` ++ if test ! -d "${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" \ ++ -o ! -d "${WCEROOT}/EVC/${OSVERSION}/bin"; then ++ AC_MSG_ERROR([could not find PocketPC SDK or target compiler to enable WinCE mode [$CEVERSION,$TARGETCPU,$ARCH,$PLATFORM]]) ++ doWince="no" ++ else ++ # We could PATH_NOSPACE these, but that's not important, ++ # as long as we quote them when used. ++ CEINCLUDE="${SDKROOT}/${OSVERSION}/${PLATFORM}/include" ++ if test -d "${CEINCLUDE}/${TARGETCPU}" ; then ++ CEINCLUDE="${CEINCLUDE}/${TARGETCPU}" ++ fi ++ CELIBPATH="${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" ++ fi ++ fi ++ ++ if test "$GCC" != "yes" ; then ++ if test "${SHARED_BUILD}" = "0" ; then ++ runtime=-MT ++ else ++ runtime=-MD ++ fi ++ ++ if test "$do64bit" != "no" ; then ++ # All this magic is necessary for the Win64 SDK RC1 - hobbs ++ CC="\"${PATH64}/cl.exe\"" ++ CFLAGS="${CFLAGS} -I\"${MSSDK}/Include\" -I\"${MSSDK}/Include/crt\" -I\"${MSSDK}/Include/crt/sys\"" ++ RC="\"${MSSDK}/bin/rc.exe\"" ++ lflags="-nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\"" ++ LINKBIN="\"${PATH64}/link.exe\"" ++ CFLAGS_DEBUG="-nologo -Zi -Od -W3 ${runtime}d" ++ CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" ++ # Avoid 'unresolved external symbol __security_cookie' ++ # errors, c.f. http://support.microsoft.com/?id=894573 ++ TEA_ADD_LIBS([bufferoverflowU.lib]) ++ elif test "$doWince" != "no" ; then ++ CEBINROOT="${WCEROOT}/EVC/${OSVERSION}/bin" ++ if test "${TARGETCPU}" = "X86"; then ++ CC="\"${CEBINROOT}/cl.exe\"" ++ else ++ CC="\"${CEBINROOT}/cl${ARCH}.exe\"" ++ fi ++ CFLAGS="$CFLAGS -I\"${CELIB_DIR}/inc\" -I\"${CEINCLUDE}\"" ++ RC="\"${WCEROOT}/Common/EVC/bin/rc.exe\"" ++ arch=`echo ${ARCH} | awk '{print tolower([$]0)}'` ++ defs="${ARCH} _${ARCH}_ ${arch} PALM_SIZE _MT _WINDOWS" ++ if test "${SHARED_BUILD}" = "1" ; then ++ # Static CE builds require static celib as well ++ defs="${defs} _DLL" ++ fi ++ for i in $defs ; do ++ AC_DEFINE_UNQUOTED($i, 1, [WinCE def ]$i) ++ done ++ AC_DEFINE_UNQUOTED(_WIN32_WCE, $CEVERSION, [_WIN32_WCE version]) ++ AC_DEFINE_UNQUOTED(UNDER_CE, $CEVERSION, [UNDER_CE version]) ++ CFLAGS_DEBUG="-nologo -Zi -Od" ++ CFLAGS_OPTIMIZE="-nologo -Ox" ++ lversion=`echo ${CEVERSION} | sed -e 's/\(.\)\(..\)/\1\.\2/'` ++ lflags="-MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo" ++ LINKBIN="\"${CEBINROOT}/link.exe\"" ++ AC_SUBST(CELIB_DIR) ++ else ++ RC="rc" ++ lflags="-nologo" ++ LINKBIN="link" ++ CFLAGS_DEBUG="-nologo -Z7 -Od -W3 -WX ${runtime}d" ++ CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" ++ fi ++ fi ++ ++ if test "$GCC" = "yes"; then ++ # mingw gcc mode ++ AC_CHECK_TOOL(RC, windres) ++ CFLAGS_DEBUG="-g" ++ CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" ++ SHLIB_LD='${CC} -shared' ++ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' ++ LDFLAGS_CONSOLE="-wl,--subsystem,console ${lflags}" ++ LDFLAGS_WINDOW="-wl,--subsystem,windows ${lflags}" ++ ++ AC_CACHE_CHECK(for cross-compile version of gcc, ++ ac_cv_cross, ++ AC_TRY_COMPILE([ ++ #ifdef _WIN32 ++ #error cross-compiler ++ #endif ++ ], [], ++ ac_cv_cross=yes, ++ ac_cv_cross=no) ++ ) ++ if test "$ac_cv_cross" = "yes"; then ++ case "$do64bit" in ++ amd64|x64|yes) ++ CC="x86_64-w64-mingw32-gcc" ++ LD="x86_64-w64-mingw32-ld" ++ AR="x86_64-w64-mingw32-ar" ++ RANLIB="x86_64-w64-mingw32-ranlib" ++ RC="x86_64-w64-mingw32-windres" ++ ;; ++ *) ++ CC="i686-w64-mingw32-gcc" ++ LD="i686-w64-mingw32-ld" ++ AR="i686-w64-mingw32-ar" ++ RANLIB="i686-w64-mingw32-ranlib" ++ RC="i686-w64-mingw32-windres" ++ ;; ++ esac ++ fi ++ ++ else ++ SHLIB_LD="${LINKBIN} -dll ${lflags}" ++ # link -lib only works when -lib is the first arg ++ STLIB_LD="${LINKBIN} -lib ${lflags}" ++ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.lib' ++ PATHTYPE=-w ++ # For information on what debugtype is most useful, see: ++ # http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp ++ # and also ++ # http://msdn2.microsoft.com/en-us/library/y0zzbyt4%28VS.80%29.aspx ++ # This essentially turns it all on. ++ LDFLAGS_DEBUG="-debug -debugtype:cv" ++ LDFLAGS_OPTIMIZE="-release" ++ if test "$doWince" != "no" ; then ++ LDFLAGS_CONSOLE="-link ${lflags}" ++ LDFLAGS_WINDOW=${LDFLAGS_CONSOLE} ++ else ++ LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}" ++ LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}" ++ fi ++ fi ++ ++ SHLIB_SUFFIX=".dll" ++ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll' ++ ++ TCL_LIB_VERSIONS_OK=nodots ++ ;; ++ AIX-*) ++ AS_IF([test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"], [ ++ # AIX requires the _r compiler when gcc isn't being used ++ case "${CC}" in ++ *_r|*_r\ *) ++ # ok ... ++ ;; ++ *) ++ # Make sure only first arg gets _r ++ CC=`echo "$CC" | sed -e 's/^\([[^ ]]*\)/\1_r/'` ++ ;; ++ esac ++ AC_MSG_RESULT([Using $CC for compiling with threads]) ++ ]) ++ LIBS="$LIBS -lc" ++ SHLIB_CFLAGS="" ++ SHLIB_SUFFIX=".so" ++ ++ LD_LIBRARY_PATH_VAR="LIBPATH" ++ ++ # Check to enable 64-bit flags for compiler/linker ++ AS_IF([test "$do64bit" = yes], [ ++ AS_IF([test "$GCC" = yes], [ ++ AC_MSG_WARN([64bit mode not supported with GCC on $system]) ++ ], [ ++ do64bit_ok=yes ++ CFLAGS="$CFLAGS -q64" ++ LDFLAGS_ARCH="-q64" ++ RANLIB="${RANLIB} -X64" ++ AR="${AR} -X64" ++ SHLIB_LD_FLAGS="-b64" ++ ]) ++ ]) ++ ++ AS_IF([test "`uname -m`" = ia64], [ ++ # AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC ++ SHLIB_LD="/usr/ccs/bin/ld -G -z text" ++ AS_IF([test "$GCC" = yes], [ ++ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' ++ ], [ ++ CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}' ++ ]) ++ LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' ++ ], [ ++ AS_IF([test "$GCC" = yes], [ ++ SHLIB_LD='${CC} -shared -Wl,-bexpall' ++ ], [ ++ SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry" ++ LDFLAGS="$LDFLAGS -brtl" ++ ]) ++ SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}" ++ CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' ++ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ++ ]) ++ ;; ++ BeOS*) ++ SHLIB_CFLAGS="-fPIC" ++ SHLIB_LD='${CC} -nostart' ++ SHLIB_SUFFIX=".so" ++ ++ #----------------------------------------------------------- ++ # Check for inet_ntoa in -lbind, for BeOS (which also needs ++ # -lsocket, even if the network functions are in -lnet which ++ # is always linked to, for compatibility. ++ #----------------------------------------------------------- ++ AC_CHECK_LIB(bind, inet_ntoa, [LIBS="$LIBS -lbind -lsocket"]) ++ ;; ++ BSD/OS-4.*) ++ SHLIB_CFLAGS="-export-dynamic -fPIC" ++ SHLIB_LD='${CC} -shared' ++ SHLIB_SUFFIX=".so" ++ LDFLAGS="$LDFLAGS -export-dynamic" ++ CC_SEARCH_FLAGS="" ++ LD_SEARCH_FLAGS="" ++ ;; ++ CYGWIN_*) ++ SHLIB_CFLAGS="" ++ SHLIB_LD='${CC} -shared' ++ SHLIB_SUFFIX=".dll" ++ EXEEXT=".exe" ++ do64bit_ok=yes ++ CC_SEARCH_FLAGS="" ++ LD_SEARCH_FLAGS="" ++ ;; ++ Haiku*) ++ LDFLAGS="$LDFLAGS -Wl,--export-dynamic" ++ SHLIB_CFLAGS="-fPIC" ++ SHLIB_SUFFIX=".so" ++ SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}' ++ AC_CHECK_LIB(network, inet_ntoa, [LIBS="$LIBS -lnetwork"]) ++ ;; ++ HP-UX-*.11.*) ++ # Use updated header definitions where possible ++ AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Do we want to use the XOPEN network library?]) ++ # TEA specific: Needed by Tcl, but not most extensions ++ #AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?]) ++ #LIBS="$LIBS -lxnet" # Use the XOPEN network library ++ ++ AS_IF([test "`uname -m`" = ia64], [ ++ SHLIB_SUFFIX=".so" ++ # Use newer C++ library for C++ extensions ++ #if test "$GCC" != "yes" ; then ++ # CPPFLAGS="-AA" ++ #fi ++ ], [ ++ SHLIB_SUFFIX=".sl" ++ ]) ++ AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no) ++ AS_IF([test "$tcl_ok" = yes], [ ++ LDFLAGS="$LDFLAGS -Wl,-E" ++ CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.' ++ LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.' ++ LD_LIBRARY_PATH_VAR="SHLIB_PATH" ++ ]) ++ AS_IF([test "$GCC" = yes], [ ++ SHLIB_LD='${CC} -shared' ++ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ++ ], [ ++ CFLAGS="$CFLAGS -z" ++ # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc ++ #CFLAGS="$CFLAGS +DAportable" ++ SHLIB_CFLAGS="+z" ++ SHLIB_LD="ld -b" ++ ]) ++ ++ # Check to enable 64-bit flags for compiler/linker ++ AS_IF([test "$do64bit" = "yes"], [ ++ AS_IF([test "$GCC" = yes], [ ++ case `${CC} -dumpmachine` in ++ hppa64*) ++ # 64-bit gcc in use. Fix flags for GNU ld. ++ do64bit_ok=yes ++ SHLIB_LD='${CC} -shared' ++ AS_IF([test $doRpath = yes], [ ++ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) ++ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ++ ;; ++ *) ++ AC_MSG_WARN([64bit mode not supported with GCC on $system]) ++ ;; ++ esac ++ ], [ ++ do64bit_ok=yes ++ CFLAGS="$CFLAGS +DD64" ++ LDFLAGS_ARCH="+DD64" ++ ]) ++ ]) ;; ++ IRIX-6.*) ++ SHLIB_CFLAGS="" ++ SHLIB_LD="ld -n32 -shared -rdata_shared" ++ SHLIB_SUFFIX=".so" ++ AS_IF([test $doRpath = yes], [ ++ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' ++ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) ++ AS_IF([test "$GCC" = yes], [ ++ CFLAGS="$CFLAGS -mabi=n32" ++ LDFLAGS="$LDFLAGS -mabi=n32" ++ ], [ ++ case $system in ++ IRIX-6.3) ++ # Use to build 6.2 compatible binaries on 6.3. ++ CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS" ++ ;; ++ *) ++ CFLAGS="$CFLAGS -n32" ++ ;; ++ esac ++ LDFLAGS="$LDFLAGS -n32" ++ ]) ++ ;; ++ IRIX64-6.*) ++ SHLIB_CFLAGS="" ++ SHLIB_LD="ld -n32 -shared -rdata_shared" ++ SHLIB_SUFFIX=".so" ++ AS_IF([test $doRpath = yes], [ ++ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' ++ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) ++ ++ # Check to enable 64-bit flags for compiler/linker ++ ++ AS_IF([test "$do64bit" = yes], [ ++ AS_IF([test "$GCC" = yes], [ ++ AC_MSG_WARN([64bit mode not supported by gcc]) ++ ], [ ++ do64bit_ok=yes ++ SHLIB_LD="ld -64 -shared -rdata_shared" ++ CFLAGS="$CFLAGS -64" ++ LDFLAGS_ARCH="-64" ++ ]) ++ ]) ++ ;; ++ Linux*|GNU*|NetBSD-Debian) ++ SHLIB_CFLAGS="-fPIC" ++ SHLIB_SUFFIX=".so" ++ ++ # TEA specific: ++ CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" ++ ++ # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS ++ SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS_DEFAULT}' ++ LDFLAGS="$LDFLAGS -Wl,--export-dynamic" ++ AS_IF([test $doRpath = yes], [ ++ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) ++ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ++ AS_IF([test "`uname -m`" = "alpha"], [CFLAGS="$CFLAGS -mieee"]) ++ AS_IF([test $do64bit = yes], [ ++ AC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [ ++ hold_cflags=$CFLAGS ++ CFLAGS="$CFLAGS -m64" ++ AC_TRY_LINK(,, tcl_cv_cc_m64=yes, tcl_cv_cc_m64=no) ++ CFLAGS=$hold_cflags]) ++ AS_IF([test $tcl_cv_cc_m64 = yes], [ ++ CFLAGS="$CFLAGS -m64" ++ do64bit_ok=yes ++ ]) ++ ]) ++ ++ # The combo of gcc + glibc has a bug related to inlining of ++ # functions like strtod(). The -fno-builtin flag should address ++ # this problem but it does not work. The -fno-inline flag is kind ++ # of overkill but it works. Disable inlining only when one of the ++ # files in compat/*.c is being linked in. ++ ++ AS_IF([test x"${USE_COMPAT}" != x],[CFLAGS="$CFLAGS -fno-inline"]) ++ ;; ++ Lynx*) ++ SHLIB_CFLAGS="-fPIC" ++ SHLIB_SUFFIX=".so" ++ CFLAGS_OPTIMIZE=-02 ++ SHLIB_LD='${CC} -shared' ++ LD_FLAGS="-Wl,--export-dynamic" ++ AS_IF([test $doRpath = yes], [ ++ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' ++ LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) ++ ;; ++ OpenBSD-*) ++ arch=`arch -s` ++ case "$arch" in ++ vax) ++ SHLIB_SUFFIX="" ++ SHARED_LIB_SUFFIX="" ++ LDFLAGS="" ++ ;; ++ *) ++ SHLIB_CFLAGS="-fPIC" ++ SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}' ++ SHLIB_SUFFIX=".so" ++ AS_IF([test $doRpath = yes], [ ++ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) ++ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ++ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}' ++ LDFLAGS="-Wl,-export-dynamic" ++ ;; ++ esac ++ case "$arch" in ++ vax) ++ CFLAGS_OPTIMIZE="-O1" ++ ;; ++ *) ++ CFLAGS_OPTIMIZE="-O2" ++ ;; ++ esac ++ AS_IF([test "${TCL_THREADS}" = "1"], [ ++ # On OpenBSD: Compile with -pthread ++ # Don't link with -lpthread ++ LIBS=`echo $LIBS | sed s/-lpthread//` ++ CFLAGS="$CFLAGS -pthread" ++ ]) ++ # OpenBSD doesn't do version numbers with dots. ++ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' ++ TCL_LIB_VERSIONS_OK=nodots ++ ;; ++ NetBSD-*) ++ # NetBSD has ELF and can use 'cc -shared' to build shared libs ++ SHLIB_CFLAGS="-fPIC" ++ SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}' ++ SHLIB_SUFFIX=".so" ++ LDFLAGS="$LDFLAGS -export-dynamic" ++ AS_IF([test $doRpath = yes], [ ++ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) ++ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ++ AS_IF([test "${TCL_THREADS}" = "1"], [ ++ # The -pthread needs to go in the CFLAGS, not LIBS ++ LIBS=`echo $LIBS | sed s/-pthread//` ++ CFLAGS="$CFLAGS -pthread" ++ LDFLAGS="$LDFLAGS -pthread" ++ ]) ++ ;; ++ FreeBSD-*) ++ # This configuration from FreeBSD Ports. ++ SHLIB_CFLAGS="-fPIC" ++ SHLIB_LD="${CC} -shared" ++ TCL_SHLIB_LD_EXTRAS="-Wl,-soname=\$[@]" ++ TK_SHLIB_LD_EXTRAS="-Wl,-soname,\$[@]" ++ SHLIB_SUFFIX=".so" ++ LDFLAGS="" ++ AS_IF([test $doRpath = yes], [ ++ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' ++ LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) ++ AS_IF([test "${TCL_THREADS}" = "1"], [ ++ # The -pthread needs to go in the LDFLAGS, not LIBS ++ LIBS=`echo $LIBS | sed s/-pthread//` ++ CFLAGS="$CFLAGS $PTHREAD_CFLAGS" ++ LDFLAGS="$LDFLAGS $PTHREAD_LIBS"]) ++ case $system in ++ FreeBSD-3.*) ++ # Version numbers are dot-stripped by system policy. ++ TCL_TRIM_DOTS=`echo ${VERSION} | tr -d .` ++ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' ++ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so' ++ TCL_LIB_VERSIONS_OK=nodots ++ ;; ++ esac ++ ;; ++ Darwin-*) ++ CFLAGS_OPTIMIZE="-Os" ++ SHLIB_CFLAGS="-fno-common" ++ # To avoid discrepancies between what headers configure sees during ++ # preprocessing tests and compiling tests, move any -isysroot and ++ # -mmacosx-version-min flags from CFLAGS to CPPFLAGS: ++ CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \ ++ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ ++ if ([$]i~/^(isysroot|mmacosx-version-min)/) print "-"[$]i}'`" ++ CFLAGS="`echo " ${CFLAGS}" | \ ++ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ ++ if (!([$]i~/^(isysroot|mmacosx-version-min)/)) print "-"[$]i}'`" ++ AS_IF([test $do64bit = yes], [ ++ case `arch` in ++ ppc) ++ AC_CACHE_CHECK([if compiler accepts -arch ppc64 flag], ++ tcl_cv_cc_arch_ppc64, [ ++ hold_cflags=$CFLAGS ++ CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" ++ AC_TRY_LINK(,, tcl_cv_cc_arch_ppc64=yes, ++ tcl_cv_cc_arch_ppc64=no) ++ CFLAGS=$hold_cflags]) ++ AS_IF([test $tcl_cv_cc_arch_ppc64 = yes], [ ++ CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" ++ do64bit_ok=yes ++ ]);; ++ i386) ++ AC_CACHE_CHECK([if compiler accepts -arch x86_64 flag], ++ tcl_cv_cc_arch_x86_64, [ ++ hold_cflags=$CFLAGS ++ CFLAGS="$CFLAGS -arch x86_64" ++ AC_TRY_LINK(,, tcl_cv_cc_arch_x86_64=yes, ++ tcl_cv_cc_arch_x86_64=no) ++ CFLAGS=$hold_cflags]) ++ AS_IF([test $tcl_cv_cc_arch_x86_64 = yes], [ ++ CFLAGS="$CFLAGS -arch x86_64" ++ do64bit_ok=yes ++ ]);; ++ *) ++ AC_MSG_WARN([Don't know how enable 64-bit on architecture `arch`]);; ++ esac ++ ], [ ++ # Check for combined 32-bit and 64-bit fat build ++ AS_IF([echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \ ++ && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '], [ ++ fat_32_64=yes]) ++ ]) ++ # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS ++ SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}' ++ AC_CACHE_CHECK([if ld accepts -single_module flag], tcl_cv_ld_single_module, [ ++ hold_ldflags=$LDFLAGS ++ LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module" ++ AC_TRY_LINK(, [int i;], tcl_cv_ld_single_module=yes, tcl_cv_ld_single_module=no) ++ LDFLAGS=$hold_ldflags]) ++ AS_IF([test $tcl_cv_ld_single_module = yes], [ ++ SHLIB_LD="${SHLIB_LD} -Wl,-single_module" ++ ]) ++ # TEA specific: link shlib with current and compatibility version flags ++ vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\([[0-9]]\{1,5\}\)\(\(\.[[0-9]]\{1,3\}\)\{0,2\}\).*$/\1\2/p' -e d` ++ SHLIB_LD="${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}" ++ SHLIB_SUFFIX=".dylib" ++ # Don't use -prebind when building for Mac OS X 10.4 or later only: ++ AS_IF([test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int([$]2)}'`" -lt 4 -a \ ++ "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int([$]2)}'`" -lt 4], [ ++ LDFLAGS="$LDFLAGS -prebind"]) ++ LDFLAGS="$LDFLAGS -headerpad_max_install_names" ++ AC_CACHE_CHECK([if ld accepts -search_paths_first flag], ++ tcl_cv_ld_search_paths_first, [ ++ hold_ldflags=$LDFLAGS ++ LDFLAGS="$LDFLAGS -Wl,-search_paths_first" ++ AC_TRY_LINK(, [int i;], tcl_cv_ld_search_paths_first=yes, ++ tcl_cv_ld_search_paths_first=no) ++ LDFLAGS=$hold_ldflags]) ++ AS_IF([test $tcl_cv_ld_search_paths_first = yes], [ ++ LDFLAGS="$LDFLAGS -Wl,-search_paths_first" ++ ]) ++ AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [ ++ AC_DEFINE(MODULE_SCOPE, [__private_extern__], ++ [Compiler support for module scope symbols]) ++ tcl_cv_cc_visibility_hidden=yes ++ ]) ++ CC_SEARCH_FLAGS="" ++ LD_SEARCH_FLAGS="" ++ LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH" ++ # TEA specific: for combined 32 & 64 bit fat builds of Tk ++ # extensions, verify that 64-bit build is possible. ++ AS_IF([test "$fat_32_64" = yes && test -n "${TK_BIN_DIR}"], [ ++ AS_IF([test "${TEA_WINDOWINGSYSTEM}" = x11], [ ++ AC_CACHE_CHECK([for 64-bit X11], tcl_cv_lib_x11_64, [ ++ for v in CFLAGS CPPFLAGS LDFLAGS; do ++ eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' ++ done ++ CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include" ++ LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11" ++ AC_TRY_LINK([#include <X11/Xlib.h>], [XrmInitialize();], ++ tcl_cv_lib_x11_64=yes, tcl_cv_lib_x11_64=no) ++ for v in CFLAGS CPPFLAGS LDFLAGS; do ++ eval $v'="$hold_'$v'"' ++ done]) ++ ]) ++ AS_IF([test "${TEA_WINDOWINGSYSTEM}" = aqua], [ ++ AC_CACHE_CHECK([for 64-bit Tk], tcl_cv_lib_tk_64, [ ++ for v in CFLAGS CPPFLAGS LDFLAGS; do ++ eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' ++ done ++ CPPFLAGS="$CPPFLAGS -DUSE_TCL_STUBS=1 -DUSE_TK_STUBS=1 ${TCL_INCLUDES} ${TK_INCLUDES}" ++ LDFLAGS="$LDFLAGS ${TCL_STUB_LIB_SPEC} ${TK_STUB_LIB_SPEC}" ++ AC_TRY_LINK([#include <tk.h>], [Tk_InitStubs(NULL, "", 0);], ++ tcl_cv_lib_tk_64=yes, tcl_cv_lib_tk_64=no) ++ for v in CFLAGS CPPFLAGS LDFLAGS; do ++ eval $v'="$hold_'$v'"' ++ done]) ++ ]) ++ # remove 64-bit arch flags from CFLAGS et al. if configuration ++ # does not support 64-bit. ++ AS_IF([test "$tcl_cv_lib_tk_64" = no -o "$tcl_cv_lib_x11_64" = no], [ ++ AC_MSG_NOTICE([Removing 64-bit architectures from compiler & linker flags]) ++ for v in CFLAGS CPPFLAGS LDFLAGS; do ++ eval $v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"' ++ done]) ++ ]) ++ ;; ++ OS/390-*) ++ CFLAGS_OPTIMIZE="" # Optimizer is buggy ++ AC_DEFINE(_OE_SOCKETS, 1, # needed in sys/socket.h ++ [Should OS/390 do the right thing with sockets?]) ++ ;; ++ OSF1-V*) ++ # Digital OSF/1 ++ SHLIB_CFLAGS="" ++ AS_IF([test "$SHARED_BUILD" = 1], [ ++ SHLIB_LD='ld -shared -expect_unresolved "*"' ++ ], [ ++ SHLIB_LD='ld -non_shared -expect_unresolved "*"' ++ ]) ++ SHLIB_SUFFIX=".so" ++ AS_IF([test $doRpath = yes], [ ++ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' ++ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) ++ AS_IF([test "$GCC" = yes], [CFLAGS="$CFLAGS -mieee"], [ ++ CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"]) ++ # see pthread_intro(3) for pthread support on osf1, k.furukawa ++ AS_IF([test "${TCL_THREADS}" = 1], [ ++ CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE" ++ CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64" ++ LIBS=`echo $LIBS | sed s/-lpthreads//` ++ AS_IF([test "$GCC" = yes], [ ++ LIBS="$LIBS -lpthread -lmach -lexc" ++ ], [ ++ CFLAGS="$CFLAGS -pthread" ++ LDFLAGS="$LDFLAGS -pthread" ++ ]) ++ ]) ++ ;; ++ QNX-6*) ++ # QNX RTP ++ # This may work for all QNX, but it was only reported for v6. ++ SHLIB_CFLAGS="-fPIC" ++ SHLIB_LD="ld -Bshareable -x" ++ SHLIB_LD_LIBS="" ++ SHLIB_SUFFIX=".so" ++ CC_SEARCH_FLAGS="" ++ LD_SEARCH_FLAGS="" ++ ;; ++ SCO_SV-3.2*) ++ AS_IF([test "$GCC" = yes], [ ++ SHLIB_CFLAGS="-fPIC -melf" ++ LDFLAGS="$LDFLAGS -melf -Wl,-Bexport" ++ ], [ ++ SHLIB_CFLAGS="-Kpic -belf" ++ LDFLAGS="$LDFLAGS -belf -Wl,-Bexport" ++ ]) ++ SHLIB_LD="ld -G" ++ SHLIB_LD_LIBS="" ++ SHLIB_SUFFIX=".so" ++ CC_SEARCH_FLAGS="" ++ LD_SEARCH_FLAGS="" ++ ;; ++ SunOS-5.[[0-6]]) ++ # Careful to not let 5.10+ fall into this case ++ ++ # Note: If _REENTRANT isn't defined, then Solaris ++ # won't define thread-safe library routines. ++ ++ AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) ++ AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, ++ [Do we really want to follow the standard? Yes we do!]) ++ ++ SHLIB_CFLAGS="-KPIC" ++ SHLIB_SUFFIX=".so" ++ AS_IF([test "$GCC" = yes], [ ++ SHLIB_LD='${CC} -shared' ++ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' ++ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ++ ], [ ++ SHLIB_LD="/usr/ccs/bin/ld -G -z text" ++ CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' ++ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ++ ]) ++ ;; ++ SunOS-5*) ++ # Note: If _REENTRANT isn't defined, then Solaris ++ # won't define thread-safe library routines. ++ ++ AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) ++ AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, ++ [Do we really want to follow the standard? Yes we do!]) ++ ++ SHLIB_CFLAGS="-KPIC" ++ ++ # Check to enable 64-bit flags for compiler/linker ++ AS_IF([test "$do64bit" = yes], [ ++ arch=`isainfo` ++ AS_IF([test "$arch" = "sparcv9 sparc"], [ ++ AS_IF([test "$GCC" = yes], [ ++ AS_IF([test "`${CC} -dumpversion | awk -F. '{print [$]1}'`" -lt 3], [ ++ AC_MSG_WARN([64bit mode not supported with GCC < 3.2 on $system]) ++ ], [ ++ do64bit_ok=yes ++ CFLAGS="$CFLAGS -m64 -mcpu=v9" ++ LDFLAGS="$LDFLAGS -m64 -mcpu=v9" ++ SHLIB_CFLAGS="-fPIC" ++ ]) ++ ], [ ++ do64bit_ok=yes ++ AS_IF([test "$do64bitVIS" = yes], [ ++ CFLAGS="$CFLAGS -xarch=v9a" ++ LDFLAGS_ARCH="-xarch=v9a" ++ ], [ ++ CFLAGS="$CFLAGS -xarch=v9" ++ LDFLAGS_ARCH="-xarch=v9" ++ ]) ++ # Solaris 64 uses this as well ++ #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64" ++ ]) ++ ], [AS_IF([test "$arch" = "amd64 i386"], [ ++ AS_IF([test "$GCC" = yes], [ ++ case $system in ++ SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*) ++ do64bit_ok=yes ++ CFLAGS="$CFLAGS -m64" ++ LDFLAGS="$LDFLAGS -m64";; ++ *) ++ AC_MSG_WARN([64bit mode not supported with GCC on $system]);; ++ esac ++ ], [ ++ do64bit_ok=yes ++ case $system in ++ SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*) ++ CFLAGS="$CFLAGS -m64" ++ LDFLAGS="$LDFLAGS -m64";; ++ *) ++ CFLAGS="$CFLAGS -xarch=amd64" ++ LDFLAGS="$LDFLAGS -xarch=amd64";; ++ esac ++ ]) ++ ], [AC_MSG_WARN([64bit mode not supported for $arch])])]) ++ ]) ++ ++ SHLIB_SUFFIX=".so" ++ AS_IF([test "$GCC" = yes], [ ++ SHLIB_LD='${CC} -shared' ++ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' ++ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ++ AS_IF([test "$do64bit_ok" = yes], [ ++ AS_IF([test "$arch" = "sparcv9 sparc"], [ ++ # We need to specify -static-libgcc or we need to ++ # add the path to the sparv9 libgcc. ++ # JH: static-libgcc is necessary for core Tcl, but may ++ # not be necessary for extensions. ++ SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc" ++ # for finding sparcv9 libgcc, get the regular libgcc ++ # path, remove so name and append 'sparcv9' ++ #v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..." ++ #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir" ++ ], [AS_IF([test "$arch" = "amd64 i386"], [ ++ # JH: static-libgcc is necessary for core Tcl, but may ++ # not be necessary for extensions. ++ SHLIB_LD="$SHLIB_LD -m64 -static-libgcc" ++ ])]) ++ ]) ++ ], [ ++ case $system in ++ SunOS-5.[[1-9]][[0-9]]*) ++ # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS ++ SHLIB_LD='${CC} -G -z text ${LDFLAGS_DEFAULT}';; ++ *) ++ SHLIB_LD='/usr/ccs/bin/ld -G -z text';; ++ esac ++ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' ++ LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' ++ ]) ++ ;; ++ UNIX_SV* | UnixWare-5*) ++ SHLIB_CFLAGS="-KPIC" ++ SHLIB_LD='${CC} -G' ++ SHLIB_LD_LIBS="" ++ SHLIB_SUFFIX=".so" ++ # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers ++ # that don't grok the -Bexport option. Test that it does. ++ AC_CACHE_CHECK([for ld accepts -Bexport flag], tcl_cv_ld_Bexport, [ ++ hold_ldflags=$LDFLAGS ++ LDFLAGS="$LDFLAGS -Wl,-Bexport" ++ AC_TRY_LINK(, [int i;], tcl_cv_ld_Bexport=yes, tcl_cv_ld_Bexport=no) ++ LDFLAGS=$hold_ldflags]) ++ AS_IF([test $tcl_cv_ld_Bexport = yes], [ ++ LDFLAGS="$LDFLAGS -Wl,-Bexport" ++ ]) ++ CC_SEARCH_FLAGS="" ++ LD_SEARCH_FLAGS="" ++ ;; ++ esac ++ ++ AS_IF([test "$do64bit" = yes -a "$do64bit_ok" = no], [ ++ AC_MSG_WARN([64bit support being disabled -- don't know magic for this platform]) ++ ]) ++ ++dnl # Add any CPPFLAGS set in the environment to our CFLAGS, but delay doing so ++dnl # until the end of configure, as configure's compile and link tests use ++dnl # both CPPFLAGS and CFLAGS (unlike our compile and link) but configure's ++dnl # preprocessing tests use only CPPFLAGS. ++ AC_CONFIG_COMMANDS_PRE([CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""]) ++ ++ # Add in the arch flags late to ensure it wasn't removed. ++ # Not necessary in TEA, but this is aligned with core ++ LDFLAGS="$LDFLAGS $LDFLAGS_ARCH" ++ ++ # If we're running gcc, then change the C flags for compiling shared ++ # libraries to the right flags for gcc, instead of those for the ++ # standard manufacturer compiler. ++ ++ AS_IF([test "$GCC" = yes], [ ++ case $system in ++ AIX-*) ;; ++ BSD/OS*) ;; ++ CYGWIN_*|MINGW32_*) ;; ++ IRIX*) ;; ++ NetBSD-*|FreeBSD-*|OpenBSD-*) ;; ++ Darwin-*) ;; ++ SCO_SV-3.2*) ;; ++ windows) ;; ++ *) SHLIB_CFLAGS="-fPIC" ;; ++ esac]) ++ ++ AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [ ++ AC_DEFINE(MODULE_SCOPE, [extern], ++ [No Compiler support for module scope symbols]) ++ ]) ++ ++ AS_IF([test "$SHARED_LIB_SUFFIX" = ""], [ ++ # TEA specific: use PACKAGE_VERSION instead of VERSION ++ SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}']) ++ AS_IF([test "$UNSHARED_LIB_SUFFIX" = ""], [ ++ # TEA specific: use PACKAGE_VERSION instead of VERSION ++ UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a']) ++ ++ if test "${GCC}" = "yes" -a ${SHLIB_SUFFIX} = ".dll"; then ++ AC_CACHE_CHECK(for SEH support in compiler, ++ tcl_cv_seh, ++ AC_TRY_RUN([ ++#define WIN32_LEAN_AND_MEAN ++#include <windows.h> ++#undef WIN32_LEAN_AND_MEAN ++ ++ int main(int argc, char** argv) { ++ int a, b = 0; ++ __try { ++ a = 666 / b; ++ } ++ __except (EXCEPTION_EXECUTE_HANDLER) { ++ return 0; ++ } ++ return 1; ++ } ++ ], ++ tcl_cv_seh=yes, ++ tcl_cv_seh=no, ++ tcl_cv_seh=no) ++ ) ++ if test "$tcl_cv_seh" = "no" ; then ++ AC_DEFINE(HAVE_NO_SEH, 1, ++ [Defined when mingw does not support SEH]) ++ fi ++ ++ # ++ # Check to see if the excpt.h include file provided contains the ++ # definition for EXCEPTION_DISPOSITION; if not, which is the case ++ # with Cygwin's version as of 2002-04-10, define it to be int, ++ # sufficient for getting the current code to work. ++ # ++ AC_CACHE_CHECK(for EXCEPTION_DISPOSITION support in include files, ++ tcl_cv_eh_disposition, ++ AC_TRY_COMPILE([ ++# define WIN32_LEAN_AND_MEAN ++# include <windows.h> ++# undef WIN32_LEAN_AND_MEAN ++ ],[ ++ EXCEPTION_DISPOSITION x; ++ ], ++ tcl_cv_eh_disposition=yes, ++ tcl_cv_eh_disposition=no) ++ ) ++ if test "$tcl_cv_eh_disposition" = "no" ; then ++ AC_DEFINE(EXCEPTION_DISPOSITION, int, ++ [Defined when cygwin/mingw does not support EXCEPTION DISPOSITION]) ++ fi ++ ++ # Check to see if winnt.h defines CHAR, SHORT, and LONG ++ # even if VOID has already been #defined. The win32api ++ # used by mingw and cygwin is known to do this. ++ ++ AC_CACHE_CHECK(for winnt.h that ignores VOID define, ++ tcl_cv_winnt_ignore_void, ++ AC_TRY_COMPILE([ ++#define VOID void ++#define WIN32_LEAN_AND_MEAN ++#include <windows.h> ++#undef WIN32_LEAN_AND_MEAN ++ ], [ ++ CHAR c; ++ SHORT s; ++ LONG l; ++ ], ++ tcl_cv_winnt_ignore_void=yes, ++ tcl_cv_winnt_ignore_void=no) ++ ) ++ if test "$tcl_cv_winnt_ignore_void" = "yes" ; then ++ AC_DEFINE(HAVE_WINNT_IGNORE_VOID, 1, ++ [Defined when cygwin/mingw ignores VOID define in winnt.h]) ++ fi ++ fi ++ ++ # See if the compiler supports casting to a union type. ++ # This is used to stop gcc from printing a compiler ++ # warning when initializing a union member. ++ ++ AC_CACHE_CHECK(for cast to union support, ++ tcl_cv_cast_to_union, ++ AC_TRY_COMPILE([], ++ [ ++ union foo { int i; double d; }; ++ union foo f = (union foo) (int) 0; ++ ], ++ tcl_cv_cast_to_union=yes, ++ tcl_cv_cast_to_union=no) ++ ) ++ if test "$tcl_cv_cast_to_union" = "yes"; then ++ AC_DEFINE(HAVE_CAST_TO_UNION, 1, ++ [Defined when compiler supports casting to union type.]) ++ fi ++ ++ AC_SUBST(CFLAGS_DEBUG) ++ AC_SUBST(CFLAGS_OPTIMIZE) ++ AC_SUBST(CFLAGS_WARNING) ++ ++ AC_SUBST(STLIB_LD) ++ AC_SUBST(SHLIB_LD) ++ ++ AC_SUBST(SHLIB_LD_LIBS) ++ AC_SUBST(SHLIB_CFLAGS) ++ ++ AC_SUBST(LD_LIBRARY_PATH_VAR) ++ ++ # These must be called after we do the basic CFLAGS checks and ++ # verify any possible 64-bit or similar switches are necessary ++ TEA_TCL_EARLY_FLAGS ++ TEA_TCL_64BIT_FLAGS ++]) ++ ++#-------------------------------------------------------------------- ++# TEA_SERIAL_PORT ++# ++# Determine which interface to use to talk to the serial port. ++# Note that #include lines must begin in leftmost column for ++# some compilers to recognize them as preprocessor directives, ++# and some build environments have stdin not pointing at a ++# pseudo-terminal (usually /dev/null instead.) ++# ++# Arguments: ++# none ++# ++# Results: ++# ++# Defines only one of the following vars: ++# HAVE_SYS_MODEM_H ++# USE_TERMIOS ++# USE_TERMIO ++# USE_SGTTY ++#-------------------------------------------------------------------- ++ ++AC_DEFUN([TEA_SERIAL_PORT], [ ++ AC_CHECK_HEADERS(sys/modem.h) ++ AC_CACHE_CHECK([termios vs. termio vs. sgtty], tcl_cv_api_serial, [ ++ AC_TRY_RUN([ ++#include <termios.h> ++ ++int main() { ++ struct termios t; ++ if (tcgetattr(0, &t) == 0) { ++ cfsetospeed(&t, 0); ++ t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB; ++ return 0; ++ } ++ return 1; ++}], tcl_cv_api_serial=termios, tcl_cv_api_serial=no, tcl_cv_api_serial=no) ++ if test $tcl_cv_api_serial = no ; then ++ AC_TRY_RUN([ ++#include <termio.h> ++ ++int main() { ++ struct termio t; ++ if (ioctl(0, TCGETA, &t) == 0) { ++ t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB; ++ return 0; ++ } ++ return 1; ++}], tcl_cv_api_serial=termio, tcl_cv_api_serial=no, tcl_cv_api_serial=no) ++ fi ++ if test $tcl_cv_api_serial = no ; then ++ AC_TRY_RUN([ ++#include <sgtty.h> ++ ++int main() { ++ struct sgttyb t; ++ if (ioctl(0, TIOCGETP, &t) == 0) { ++ t.sg_ospeed = 0; ++ t.sg_flags |= ODDP | EVENP | RAW; ++ return 0; ++ } ++ return 1; ++}], tcl_cv_api_serial=sgtty, tcl_cv_api_serial=no, tcl_cv_api_serial=no) ++ fi ++ if test $tcl_cv_api_serial = no ; then ++ AC_TRY_RUN([ ++#include <termios.h> ++#include <errno.h> ++ ++int main() { ++ struct termios t; ++ if (tcgetattr(0, &t) == 0 ++ || errno == ENOTTY || errno == ENXIO || errno == EINVAL) { ++ cfsetospeed(&t, 0); ++ t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB; ++ return 0; ++ } ++ return 1; ++}], tcl_cv_api_serial=termios, tcl_cv_api_serial=no, tcl_cv_api_serial=no) ++ fi ++ if test $tcl_cv_api_serial = no; then ++ AC_TRY_RUN([ ++#include <termio.h> ++#include <errno.h> ++ ++int main() { ++ struct termio t; ++ if (ioctl(0, TCGETA, &t) == 0 ++ || errno == ENOTTY || errno == ENXIO || errno == EINVAL) { ++ t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB; ++ return 0; ++ } ++ return 1; ++ }], tcl_cv_api_serial=termio, tcl_cv_api_serial=no, tcl_cv_api_serial=no) ++ fi ++ if test $tcl_cv_api_serial = no; then ++ AC_TRY_RUN([ ++#include <sgtty.h> ++#include <errno.h> ++ ++int main() { ++ struct sgttyb t; ++ if (ioctl(0, TIOCGETP, &t) == 0 ++ || errno == ENOTTY || errno == ENXIO || errno == EINVAL) { ++ t.sg_ospeed = 0; ++ t.sg_flags |= ODDP | EVENP | RAW; ++ return 0; ++ } ++ return 1; ++}], tcl_cv_api_serial=sgtty, tcl_cv_api_serial=none, tcl_cv_api_serial=none) ++ fi]) ++ case $tcl_cv_api_serial in ++ termios) AC_DEFINE(USE_TERMIOS, 1, [Use the termios API for serial lines]);; ++ termio) AC_DEFINE(USE_TERMIO, 1, [Use the termio API for serial lines]);; ++ sgtty) AC_DEFINE(USE_SGTTY, 1, [Use the sgtty API for serial lines]);; ++ esac ++]) ++ ++#-------------------------------------------------------------------- ++# TEA_MISSING_POSIX_HEADERS ++# ++# Supply substitutes for missing POSIX header files. Special ++# notes: ++# - stdlib.h doesn't define strtol, strtoul, or ++# strtod in some versions of SunOS ++# - some versions of string.h don't declare procedures such ++# as strstr ++# ++# Arguments: ++# none ++# ++# Results: ++# ++# Defines some of the following vars: ++# NO_DIRENT_H ++# NO_ERRNO_H ++# NO_VALUES_H ++# HAVE_LIMITS_H or NO_LIMITS_H ++# NO_STDLIB_H ++# NO_STRING_H ++# NO_SYS_WAIT_H ++# NO_DLFCN_H ++# HAVE_SYS_PARAM_H ++# ++# HAVE_STRING_H ? ++# ++# tkUnixPort.h checks for HAVE_LIMITS_H, so do both HAVE and ++# CHECK on limits.h ++#-------------------------------------------------------------------- ++ ++AC_DEFUN([TEA_MISSING_POSIX_HEADERS], [ ++ AC_CACHE_CHECK([dirent.h], tcl_cv_dirent_h, [ ++ AC_TRY_LINK([#include <sys/types.h> ++#include <dirent.h>], [ ++#ifndef _POSIX_SOURCE ++# ifdef __Lynx__ ++ /* ++ * Generate compilation error to make the test fail: Lynx headers ++ * are only valid if really in the POSIX environment. ++ */ ++ ++ missing_procedure(); ++# endif ++#endif ++DIR *d; ++struct dirent *entryPtr; ++char *p; ++d = opendir("foobar"); ++entryPtr = readdir(d); ++p = entryPtr->d_name; ++closedir(d); ++], tcl_cv_dirent_h=yes, tcl_cv_dirent_h=no)]) ++ ++ if test $tcl_cv_dirent_h = no; then ++ AC_DEFINE(NO_DIRENT_H, 1, [Do we have <dirent.h>?]) ++ fi ++ ++ # TEA specific: ++ AC_CHECK_HEADER(errno.h, , [AC_DEFINE(NO_ERRNO_H, 1, [Do we have <errno.h>?])]) ++ AC_CHECK_HEADER(float.h, , [AC_DEFINE(NO_FLOAT_H, 1, [Do we have <float.h>?])]) ++ AC_CHECK_HEADER(values.h, , [AC_DEFINE(NO_VALUES_H, 1, [Do we have <values.h>?])]) ++ AC_CHECK_HEADER(limits.h, ++ [AC_DEFINE(HAVE_LIMITS_H, 1, [Do we have <limits.h>?])], ++ [AC_DEFINE(NO_LIMITS_H, 1, [Do we have <limits.h>?])]) ++ AC_CHECK_HEADER(stdlib.h, tcl_ok=1, tcl_ok=0) ++ AC_EGREP_HEADER(strtol, stdlib.h, , tcl_ok=0) ++ AC_EGREP_HEADER(strtoul, stdlib.h, , tcl_ok=0) ++ AC_EGREP_HEADER(strtod, stdlib.h, , tcl_ok=0) ++ if test $tcl_ok = 0; then ++ AC_DEFINE(NO_STDLIB_H, 1, [Do we have <stdlib.h>?]) ++ fi ++ AC_CHECK_HEADER(string.h, tcl_ok=1, tcl_ok=0) ++ AC_EGREP_HEADER(strstr, string.h, , tcl_ok=0) ++ AC_EGREP_HEADER(strerror, string.h, , tcl_ok=0) ++ ++ # See also memmove check below for a place where NO_STRING_H can be ++ # set and why. ++ ++ if test $tcl_ok = 0; then ++ AC_DEFINE(NO_STRING_H, 1, [Do we have <string.h>?]) ++ fi ++ ++ AC_CHECK_HEADER(sys/wait.h, , [AC_DEFINE(NO_SYS_WAIT_H, 1, [Do we have <sys/wait.h>?])]) ++ AC_CHECK_HEADER(dlfcn.h, , [AC_DEFINE(NO_DLFCN_H, 1, [Do we have <dlfcn.h>?])]) ++ ++ # OS/390 lacks sys/param.h (and doesn't need it, by chance). ++ AC_HAVE_HEADERS(sys/param.h) ++]) ++ ++#-------------------------------------------------------------------- ++# TEA_PATH_X ++# ++# Locate the X11 header files and the X11 library archive. Try ++# the ac_path_x macro first, but if it doesn't find the X stuff ++# (e.g. because there's no xmkmf program) then check through ++# a list of possible directories. Under some conditions the ++# autoconf macro will return an include directory that contains ++# no include files, so double-check its result just to be safe. ++# ++# This should be called after TEA_CONFIG_CFLAGS as setting the ++# LIBS line can confuse some configure macro magic. ++# ++# Arguments: ++# none ++# ++# Results: ++# ++# Sets the following vars: ++# XINCLUDES ++# XLIBSW ++# PKG_LIBS (appends to) ++#-------------------------------------------------------------------- ++ ++AC_DEFUN([TEA_PATH_X], [ ++ if test "${TEA_WINDOWINGSYSTEM}" = "x11" ; then ++ TEA_PATH_UNIX_X ++ fi ++]) ++ ++AC_DEFUN([TEA_PATH_UNIX_X], [ ++ AC_PATH_X ++ not_really_there="" ++ if test "$no_x" = ""; then ++ if test "$x_includes" = ""; then ++ AC_TRY_CPP([#include <X11/Xlib.h>], , not_really_there="yes") ++ else ++ if test ! -r $x_includes/X11/Xlib.h; then ++ not_really_there="yes" ++ fi ++ fi ++ fi ++ if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then ++ AC_MSG_CHECKING([for X11 header files]) ++ found_xincludes="no" ++ AC_TRY_CPP([#include <X11/Xlib.h>], found_xincludes="yes", found_xincludes="no") ++ if test "$found_xincludes" = "no"; then ++ dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include" ++ for i in $dirs ; do ++ if test -r $i/X11/Xlib.h; then ++ AC_MSG_RESULT([$i]) ++ XINCLUDES=" -I$i" ++ found_xincludes="yes" ++ break ++ fi ++ done ++ fi ++ else ++ if test "$x_includes" != ""; then ++ XINCLUDES="-I$x_includes" ++ found_xincludes="yes" ++ fi ++ fi ++ if test "$found_xincludes" = "no"; then ++ AC_MSG_RESULT([couldn't find any!]) ++ fi ++ ++ if test "$no_x" = yes; then ++ AC_MSG_CHECKING([for X11 libraries]) ++ XLIBSW=nope ++ dirs="/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib" ++ for i in $dirs ; do ++ if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl -o -r $i/libX11.dylib; then ++ AC_MSG_RESULT([$i]) ++ XLIBSW="-L$i -lX11" ++ x_libraries="$i" ++ break ++ fi ++ done ++ else ++ if test "$x_libraries" = ""; then ++ XLIBSW=-lX11 ++ else ++ XLIBSW="-L$x_libraries -lX11" ++ fi ++ fi ++ if test "$XLIBSW" = nope ; then ++ AC_CHECK_LIB(Xwindow, XCreateWindow, XLIBSW=-lXwindow) ++ fi ++ if test "$XLIBSW" = nope ; then ++ AC_MSG_RESULT([could not find any! Using -lX11.]) ++ XLIBSW=-lX11 ++ fi ++ # TEA specific: ++ if test x"${XLIBSW}" != x ; then ++ PKG_LIBS="${PKG_LIBS} ${XLIBSW}" ++ fi ++]) ++ ++#-------------------------------------------------------------------- ++# TEA_BLOCKING_STYLE ++# ++# The statements below check for systems where POSIX-style ++# non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented. ++# On these systems (mostly older ones), use the old BSD-style ++# FIONBIO approach instead. ++# ++# Arguments: ++# none ++# ++# Results: ++# ++# Defines some of the following vars: ++# HAVE_SYS_IOCTL_H ++# HAVE_SYS_FILIO_H ++# USE_FIONBIO ++# O_NONBLOCK ++#-------------------------------------------------------------------- ++ ++AC_DEFUN([TEA_BLOCKING_STYLE], [ ++ AC_CHECK_HEADERS(sys/ioctl.h) ++ AC_CHECK_HEADERS(sys/filio.h) ++ TEA_CONFIG_SYSTEM ++ AC_MSG_CHECKING([FIONBIO vs. O_NONBLOCK for nonblocking I/O]) ++ case $system in ++ OSF*) ++ AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?]) ++ AC_MSG_RESULT([FIONBIO]) ++ ;; ++ *) ++ AC_MSG_RESULT([O_NONBLOCK]) ++ ;; ++ esac ++]) ++ ++#-------------------------------------------------------------------- ++# TEA_TIME_HANDLER ++# ++# Checks how the system deals with time.h, what time structures ++# are used on the system, and what fields the structures have. ++# ++# Arguments: ++# none ++# ++# Results: ++# ++# Defines some of the following vars: ++# USE_DELTA_FOR_TZ ++# HAVE_TM_GMTOFF ++# HAVE_TM_TZADJ ++# HAVE_TIMEZONE_VAR ++#-------------------------------------------------------------------- ++ ++AC_DEFUN([TEA_TIME_HANDLER], [ ++ AC_CHECK_HEADERS(sys/time.h) ++ AC_HEADER_TIME ++ AC_STRUCT_TIMEZONE ++ ++ AC_CHECK_FUNCS(gmtime_r localtime_r) ++ ++ AC_CACHE_CHECK([tm_tzadj in struct tm], tcl_cv_member_tm_tzadj, [ ++ AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_tzadj;], ++ tcl_cv_member_tm_tzadj=yes, tcl_cv_member_tm_tzadj=no)]) ++ if test $tcl_cv_member_tm_tzadj = yes ; then ++ AC_DEFINE(HAVE_TM_TZADJ, 1, [Should we use the tm_tzadj field of struct tm?]) ++ fi ++ ++ AC_CACHE_CHECK([tm_gmtoff in struct tm], tcl_cv_member_tm_gmtoff, [ ++ AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_gmtoff;], ++ tcl_cv_member_tm_gmtoff=yes, tcl_cv_member_tm_gmtoff=no)]) ++ if test $tcl_cv_member_tm_gmtoff = yes ; then ++ AC_DEFINE(HAVE_TM_GMTOFF, 1, [Should we use the tm_gmtoff field of struct tm?]) ++ fi ++ ++ # ++ # Its important to include time.h in this check, as some systems ++ # (like convex) have timezone functions, etc. ++ # ++ AC_CACHE_CHECK([long timezone variable], tcl_cv_timezone_long, [ ++ AC_TRY_COMPILE([#include <time.h>], ++ [extern long timezone; ++ timezone += 1; ++ exit (0);], ++ tcl_cv_timezone_long=yes, tcl_cv_timezone_long=no)]) ++ if test $tcl_cv_timezone_long = yes ; then ++ AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?]) ++ else ++ # ++ # On some systems (eg IRIX 6.2), timezone is a time_t and not a long. ++ # ++ AC_CACHE_CHECK([time_t timezone variable], tcl_cv_timezone_time, [ ++ AC_TRY_COMPILE([#include <time.h>], ++ [extern time_t timezone; ++ timezone += 1; ++ exit (0);], ++ tcl_cv_timezone_time=yes, tcl_cv_timezone_time=no)]) ++ if test $tcl_cv_timezone_time = yes ; then ++ AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?]) ++ fi ++ fi ++]) ++ ++#-------------------------------------------------------------------- ++# TEA_BUGGY_STRTOD ++# ++# Under Solaris 2.4, strtod returns the wrong value for the ++# terminating character under some conditions. Check for this ++# and if the problem exists use a substitute procedure ++# "fixstrtod" (provided by Tcl) that corrects the error. ++# Also, on Compaq's Tru64 Unix 5.0, ++# strtod(" ") returns 0.0 instead of a failure to convert. ++# ++# Arguments: ++# none ++# ++# Results: ++# ++# Might defines some of the following vars: ++# strtod (=fixstrtod) ++#-------------------------------------------------------------------- ++ ++AC_DEFUN([TEA_BUGGY_STRTOD], [ ++ AC_CHECK_FUNC(strtod, tcl_strtod=1, tcl_strtod=0) ++ if test "$tcl_strtod" = 1; then ++ AC_CACHE_CHECK([for Solaris2.4/Tru64 strtod bugs], tcl_cv_strtod_buggy,[ ++ AC_TRY_RUN([ ++ extern double strtod(); ++ int main() { ++ char *infString="Inf", *nanString="NaN", *spaceString=" "; ++ char *term; ++ double value; ++ value = strtod(infString, &term); ++ if ((term != infString) && (term[-1] == 0)) { ++ exit(1); ++ } ++ value = strtod(nanString, &term); ++ if ((term != nanString) && (term[-1] == 0)) { ++ exit(1); ++ } ++ value = strtod(spaceString, &term); ++ if (term == (spaceString+1)) { ++ exit(1); ++ } ++ exit(0); ++ }], tcl_cv_strtod_buggy=ok, tcl_cv_strtod_buggy=buggy, ++ tcl_cv_strtod_buggy=buggy)]) ++ if test "$tcl_cv_strtod_buggy" = buggy; then ++ AC_LIBOBJ([fixstrtod]) ++ USE_COMPAT=1 ++ AC_DEFINE(strtod, fixstrtod, [Do we want to use the strtod() in compat?]) ++ fi ++ fi ++]) ++ ++#-------------------------------------------------------------------- ++# TEA_TCL_LINK_LIBS ++# ++# Search for the libraries needed to link the Tcl shell. ++# Things like the math library (-lm) and socket stuff (-lsocket vs. ++# -lnsl) are dealt with here. ++# ++# Arguments: ++# Requires the following vars to be set in the Makefile: ++# DL_LIBS (not in TEA, only needed in core) ++# LIBS ++# MATH_LIBS ++# ++# Results: ++# ++# Substitutes the following vars: ++# TCL_LIBS ++# MATH_LIBS ++# ++# Might append to the following vars: ++# LIBS ++# ++# Might define the following vars: ++# HAVE_NET_ERRNO_H ++#-------------------------------------------------------------------- ++ ++AC_DEFUN([TEA_TCL_LINK_LIBS], [ ++ #-------------------------------------------------------------------- ++ # On a few very rare systems, all of the libm.a stuff is ++ # already in libc.a. Set compiler flags accordingly. ++ # Also, Linux requires the "ieee" library for math to work ++ # right (and it must appear before "-lm"). ++ #-------------------------------------------------------------------- ++ ++ AC_CHECK_FUNC(sin, MATH_LIBS="", MATH_LIBS="-lm") ++ AC_CHECK_LIB(ieee, main, [MATH_LIBS="-lieee $MATH_LIBS"]) ++ ++ #-------------------------------------------------------------------- ++ # Interactive UNIX requires -linet instead of -lsocket, plus it ++ # needs net/errno.h to define the socket-related error codes. ++ #-------------------------------------------------------------------- ++ ++ AC_CHECK_LIB(inet, main, [LIBS="$LIBS -linet"]) ++ AC_CHECK_HEADER(net/errno.h, [ ++ AC_DEFINE(HAVE_NET_ERRNO_H, 1, [Do we have <net/errno.h>?])]) ++ ++ #-------------------------------------------------------------------- ++ # Check for the existence of the -lsocket and -lnsl libraries. ++ # The order here is important, so that they end up in the right ++ # order in the command line generated by make. Here are some ++ # special considerations: ++ # 1. Use "connect" and "accept" to check for -lsocket, and ++ # "gethostbyname" to check for -lnsl. ++ # 2. Use each function name only once: can't redo a check because ++ # autoconf caches the results of the last check and won't redo it. ++ # 3. Use -lnsl and -lsocket only if they supply procedures that ++ # aren't already present in the normal libraries. This is because ++ # IRIX 5.2 has libraries, but they aren't needed and they're ++ # bogus: they goof up name resolution if used. ++ # 4. On some SVR4 systems, can't use -lsocket without -lnsl too. ++ # To get around this problem, check for both libraries together ++ # if -lsocket doesn't work by itself. ++ #-------------------------------------------------------------------- ++ ++ tcl_checkBoth=0 ++ AC_CHECK_FUNC(connect, tcl_checkSocket=0, tcl_checkSocket=1) ++ if test "$tcl_checkSocket" = 1; then ++ AC_CHECK_FUNC(setsockopt, , [AC_CHECK_LIB(socket, setsockopt, ++ LIBS="$LIBS -lsocket", tcl_checkBoth=1)]) ++ fi ++ if test "$tcl_checkBoth" = 1; then ++ tk_oldLibs=$LIBS ++ LIBS="$LIBS -lsocket -lnsl" ++ AC_CHECK_FUNC(accept, tcl_checkNsl=0, [LIBS=$tk_oldLibs]) ++ fi ++ AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname, ++ [LIBS="$LIBS -lnsl"])]) ++ ++ # TEA specific: Don't perform the eval of the libraries here because ++ # DL_LIBS won't be set until we call TEA_CONFIG_CFLAGS ++ ++ TCL_LIBS='${DL_LIBS} ${LIBS} ${MATH_LIBS}' ++ AC_SUBST(TCL_LIBS) ++ AC_SUBST(MATH_LIBS) ++]) ++ ++#-------------------------------------------------------------------- ++# TEA_TCL_EARLY_FLAGS ++# ++# Check for what flags are needed to be passed so the correct OS ++# features are available. ++# ++# Arguments: ++# None ++# ++# Results: ++# ++# Might define the following vars: ++# _ISOC99_SOURCE ++# _LARGEFILE64_SOURCE ++# _LARGEFILE_SOURCE64 ++#-------------------------------------------------------------------- ++ ++AC_DEFUN([TEA_TCL_EARLY_FLAG],[ ++ AC_CACHE_VAL([tcl_cv_flag_]translit($1,[A-Z],[a-z]), ++ AC_TRY_COMPILE([$2], $3, [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no, ++ AC_TRY_COMPILE([[#define ]$1[ 1 ++]$2], $3, ++ [tcl_cv_flag_]translit($1,[A-Z],[a-z])=yes, ++ [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no))) ++ if test ["x${tcl_cv_flag_]translit($1,[A-Z],[a-z])[}" = "xyes"] ; then ++ AC_DEFINE($1, 1, [Add the ]$1[ flag when building]) ++ tcl_flags="$tcl_flags $1" ++ fi ++]) ++ ++AC_DEFUN([TEA_TCL_EARLY_FLAGS],[ ++ AC_MSG_CHECKING([for required early compiler flags]) ++ tcl_flags="" ++ TEA_TCL_EARLY_FLAG(_ISOC99_SOURCE,[#include <stdlib.h>], ++ [char *p = (char *)strtoll; char *q = (char *)strtoull;]) ++ TEA_TCL_EARLY_FLAG(_LARGEFILE64_SOURCE,[#include <sys/stat.h>], ++ [struct stat64 buf; int i = stat64("/", &buf);]) ++ TEA_TCL_EARLY_FLAG(_LARGEFILE_SOURCE64,[#include <sys/stat.h>], ++ [char *p = (char *)open64;]) ++ if test "x${tcl_flags}" = "x" ; then ++ AC_MSG_RESULT([none]) ++ else ++ AC_MSG_RESULT([${tcl_flags}]) ++ fi ++]) ++ ++#-------------------------------------------------------------------- ++# TEA_TCL_64BIT_FLAGS ++# ++# Check for what is defined in the way of 64-bit features. ++# ++# Arguments: ++# None ++# ++# Results: ++# ++# Might define the following vars: ++# TCL_WIDE_INT_IS_LONG ++# TCL_WIDE_INT_TYPE ++# HAVE_STRUCT_DIRENT64 ++# HAVE_STRUCT_STAT64 ++# HAVE_TYPE_OFF64_T ++#-------------------------------------------------------------------- ++ ++AC_DEFUN([TEA_TCL_64BIT_FLAGS], [ ++ AC_MSG_CHECKING([for 64-bit integer type]) ++ AC_CACHE_VAL(tcl_cv_type_64bit,[ ++ tcl_cv_type_64bit=none ++ # See if the compiler knows natively about __int64 ++ AC_TRY_COMPILE(,[__int64 value = (__int64) 0;], ++ tcl_type_64bit=__int64, tcl_type_64bit="long long") ++ # See if we should use long anyway Note that we substitute in the ++ # type that is our current guess for a 64-bit type inside this check ++ # program, so it should be modified only carefully... ++ AC_TRY_COMPILE(,[switch (0) { ++ case 1: case (sizeof(]${tcl_type_64bit}[)==sizeof(long)): ; ++ }],tcl_cv_type_64bit=${tcl_type_64bit})]) ++ if test "${tcl_cv_type_64bit}" = none ; then ++ AC_DEFINE(TCL_WIDE_INT_IS_LONG, 1, [Are wide integers to be implemented with C 'long's?]) ++ AC_MSG_RESULT([using long]) ++ elif test "${tcl_cv_type_64bit}" = "__int64" \ ++ -a "${TEA_PLATFORM}" = "windows" ; then ++ # TEA specific: We actually want to use the default tcl.h checks in ++ # this case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER* ++ AC_MSG_RESULT([using Tcl header defaults]) ++ else ++ AC_DEFINE_UNQUOTED(TCL_WIDE_INT_TYPE,${tcl_cv_type_64bit}, ++ [What type should be used to define wide integers?]) ++ AC_MSG_RESULT([${tcl_cv_type_64bit}]) ++ ++ # Now check for auxiliary declarations ++ AC_CACHE_CHECK([for struct dirent64], tcl_cv_struct_dirent64,[ ++ AC_TRY_COMPILE([#include <sys/types.h> ++#include <dirent.h>],[struct dirent64 p;], ++ tcl_cv_struct_dirent64=yes,tcl_cv_struct_dirent64=no)]) ++ if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then ++ AC_DEFINE(HAVE_STRUCT_DIRENT64, 1, [Is 'struct dirent64' in <sys/types.h>?]) ++ fi ++ ++ AC_CACHE_CHECK([for struct stat64], tcl_cv_struct_stat64,[ ++ AC_TRY_COMPILE([#include <sys/stat.h>],[struct stat64 p; ++], ++ tcl_cv_struct_stat64=yes,tcl_cv_struct_stat64=no)]) ++ if test "x${tcl_cv_struct_stat64}" = "xyes" ; then ++ AC_DEFINE(HAVE_STRUCT_STAT64, 1, [Is 'struct stat64' in <sys/stat.h>?]) ++ fi ++ ++ AC_CHECK_FUNCS(open64 lseek64) ++ AC_MSG_CHECKING([for off64_t]) ++ AC_CACHE_VAL(tcl_cv_type_off64_t,[ ++ AC_TRY_COMPILE([#include <sys/types.h>],[off64_t offset; ++], ++ tcl_cv_type_off64_t=yes,tcl_cv_type_off64_t=no)]) ++ dnl Define HAVE_TYPE_OFF64_T only when the off64_t type and the ++ dnl functions lseek64 and open64 are defined. ++ if test "x${tcl_cv_type_off64_t}" = "xyes" && \ ++ test "x${ac_cv_func_lseek64}" = "xyes" && \ ++ test "x${ac_cv_func_open64}" = "xyes" ; then ++ AC_DEFINE(HAVE_TYPE_OFF64_T, 1, [Is off64_t in <sys/types.h>?]) ++ AC_MSG_RESULT([yes]) ++ else ++ AC_MSG_RESULT([no]) ++ fi ++ fi ++]) ++ ++## ++## Here ends the standard Tcl configuration bits and starts the ++## TEA specific functions ++## ++ ++#------------------------------------------------------------------------ ++# TEA_INIT -- ++# ++# Init various Tcl Extension Architecture (TEA) variables. ++# This should be the first called TEA_* macro. ++# ++# Arguments: ++# none ++# ++# Results: ++# ++# Defines and substs the following vars: ++# CYGPATH ++# EXEEXT ++# Defines only: ++# TEA_VERSION ++# TEA_INITED ++# TEA_PLATFORM (windows or unix) ++# ++# "cygpath" is used on windows to generate native path names for include ++# files. These variables should only be used with the compiler and linker ++# since they generate native path names. ++# ++# EXEEXT ++# Select the executable extension based on the host type. This ++# is a lightweight replacement for AC_EXEEXT that doesn't require ++# a compiler. ++#------------------------------------------------------------------------ ++ ++AC_DEFUN([TEA_INIT], [ ++ # TEA extensions pass this us the version of TEA they think they ++ # are compatible with. ++ TEA_VERSION="3.9" ++ ++ AC_MSG_CHECKING([for correct TEA configuration]) ++ if test x"${PACKAGE_NAME}" = x ; then ++ AC_MSG_ERROR([ ++The PACKAGE_NAME variable must be defined by your TEA configure.in]) ++ fi ++ if test x"$1" = x ; then ++ AC_MSG_ERROR([ ++TEA version not specified.]) ++ elif test "$1" != "${TEA_VERSION}" ; then ++ AC_MSG_RESULT([warning: requested TEA version "$1", have "${TEA_VERSION}"]) ++ else ++ AC_MSG_RESULT([ok (TEA ${TEA_VERSION})]) ++ fi ++ ++ # If the user did not set CFLAGS, set it now to keep macros ++ # like AC_PROG_CC and AC_TRY_COMPILE from adding "-g -O2". ++ if test "${CFLAGS+set}" != "set" ; then ++ CFLAGS="" ++ fi ++ ++ case "`uname -s`" in ++ *win32*|*WIN32*|*MINGW32_*) ++ AC_CHECK_PROG(CYGPATH, cygpath, cygpath -w, echo) ++ EXEEXT=".exe" ++ TEA_PLATFORM="windows" ++ ;; ++ *CYGWIN_*) ++ CYGPATH=echo ++ EXEEXT=".exe" ++ # TEA_PLATFORM is determined later in LOAD_TCLCONFIG ++ ;; ++ *) ++ CYGPATH=echo ++ # Maybe we are cross-compiling.... ++ case ${host_alias} in ++ *mingw32*) ++ EXEEXT=".exe" ++ TEA_PLATFORM="windows" ++ ;; ++ *) ++ EXEEXT="" ++ TEA_PLATFORM="unix" ++ ;; ++ esac ++ ;; ++ esac ++ ++ # Check if exec_prefix is set. If not use fall back to prefix. ++ # Note when adjusted, so that TEA_PREFIX can correct for this. ++ # This is needed for recursive configures, since autoconf propagates ++ # $prefix, but not $exec_prefix (doh!). ++ if test x$exec_prefix = xNONE ; then ++ exec_prefix_default=yes ++ exec_prefix=$prefix ++ fi ++ ++ AC_MSG_NOTICE([configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}]) ++ ++ AC_SUBST(EXEEXT) ++ AC_SUBST(CYGPATH) ++ ++ # This package name must be replaced statically for AC_SUBST to work ++ AC_SUBST(PKG_LIB_FILE) ++ # Substitute STUB_LIB_FILE in case package creates a stub library too. ++ AC_SUBST(PKG_STUB_LIB_FILE) ++ ++ # We AC_SUBST these here to ensure they are subst'ed, ++ # in case the user doesn't call TEA_ADD_... ++ AC_SUBST(PKG_STUB_SOURCES) ++ AC_SUBST(PKG_STUB_OBJECTS) ++ AC_SUBST(PKG_TCL_SOURCES) ++ AC_SUBST(PKG_HEADERS) ++ AC_SUBST(PKG_INCLUDES) ++ AC_SUBST(PKG_LIBS) ++ AC_SUBST(PKG_CFLAGS) ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_ADD_SOURCES -- ++# ++# Specify one or more source files. Users should check for ++# the right platform before adding to their list. ++# It is not important to specify the directory, as long as it is ++# in the generic, win or unix subdirectory of $(srcdir). ++# ++# Arguments: ++# one or more file names ++# ++# Results: ++# ++# Defines and substs the following vars: ++# PKG_SOURCES ++# PKG_OBJECTS ++#------------------------------------------------------------------------ ++AC_DEFUN([TEA_ADD_SOURCES], [ ++ vars="$@" ++ for i in $vars; do ++ case $i in ++ [\$]*) ++ # allow $-var names ++ PKG_SOURCES="$PKG_SOURCES $i" ++ PKG_OBJECTS="$PKG_OBJECTS $i" ++ ;; ++ *) ++ # check for existence - allows for generic/win/unix VPATH ++ # To add more dirs here (like 'src'), you have to update VPATH ++ # in Makefile.in as well ++ if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ ++ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ ++ -a ! -f "${srcdir}/macosx/$i" \ ++ ; then ++ AC_MSG_ERROR([could not find source file '$i']) ++ fi ++ PKG_SOURCES="$PKG_SOURCES $i" ++ # this assumes it is in a VPATH dir ++ i=`basename $i` ++ # handle user calling this before or after TEA_SETUP_COMPILER ++ if test x"${OBJEXT}" != x ; then ++ j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}" ++ else ++ j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}" ++ fi ++ PKG_OBJECTS="$PKG_OBJECTS $j" ++ ;; ++ esac ++ done ++ AC_SUBST(PKG_SOURCES) ++ AC_SUBST(PKG_OBJECTS) ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_ADD_STUB_SOURCES -- ++# ++# Specify one or more source files. Users should check for ++# the right platform before adding to their list. ++# It is not important to specify the directory, as long as it is ++# in the generic, win or unix subdirectory of $(srcdir). ++# ++# Arguments: ++# one or more file names ++# ++# Results: ++# ++# Defines and substs the following vars: ++# PKG_STUB_SOURCES ++# PKG_STUB_OBJECTS ++#------------------------------------------------------------------------ ++AC_DEFUN([TEA_ADD_STUB_SOURCES], [ ++ vars="$@" ++ for i in $vars; do ++ # check for existence - allows for generic/win/unix VPATH ++ if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ ++ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ ++ -a ! -f "${srcdir}/macosx/$i" \ ++ ; then ++ AC_MSG_ERROR([could not find stub source file '$i']) ++ fi ++ PKG_STUB_SOURCES="$PKG_STUB_SOURCES $i" ++ # this assumes it is in a VPATH dir ++ i=`basename $i` ++ # handle user calling this before or after TEA_SETUP_COMPILER ++ if test x"${OBJEXT}" != x ; then ++ j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}" ++ else ++ j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}" ++ fi ++ PKG_STUB_OBJECTS="$PKG_STUB_OBJECTS $j" ++ done ++ AC_SUBST(PKG_STUB_SOURCES) ++ AC_SUBST(PKG_STUB_OBJECTS) ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_ADD_TCL_SOURCES -- ++# ++# Specify one or more Tcl source files. These should be platform ++# independent runtime files. ++# ++# Arguments: ++# one or more file names ++# ++# Results: ++# ++# Defines and substs the following vars: ++# PKG_TCL_SOURCES ++#------------------------------------------------------------------------ ++AC_DEFUN([TEA_ADD_TCL_SOURCES], [ ++ vars="$@" ++ for i in $vars; do ++ # check for existence, be strict because it is installed ++ if test ! -f "${srcdir}/$i" ; then ++ AC_MSG_ERROR([could not find tcl source file '${srcdir}/$i']) ++ fi ++ PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i" ++ done ++ AC_SUBST(PKG_TCL_SOURCES) ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_ADD_HEADERS -- ++# ++# Specify one or more source headers. Users should check for ++# the right platform before adding to their list. ++# ++# Arguments: ++# one or more file names ++# ++# Results: ++# ++# Defines and substs the following vars: ++# PKG_HEADERS ++#------------------------------------------------------------------------ ++AC_DEFUN([TEA_ADD_HEADERS], [ ++ vars="$@" ++ for i in $vars; do ++ # check for existence, be strict because it is installed ++ if test ! -f "${srcdir}/$i" ; then ++ AC_MSG_ERROR([could not find header file '${srcdir}/$i']) ++ fi ++ PKG_HEADERS="$PKG_HEADERS $i" ++ done ++ AC_SUBST(PKG_HEADERS) ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_ADD_INCLUDES -- ++# ++# Specify one or more include dirs. Users should check for ++# the right platform before adding to their list. ++# ++# Arguments: ++# one or more file names ++# ++# Results: ++# ++# Defines and substs the following vars: ++# PKG_INCLUDES ++#------------------------------------------------------------------------ ++AC_DEFUN([TEA_ADD_INCLUDES], [ ++ vars="$@" ++ for i in $vars; do ++ PKG_INCLUDES="$PKG_INCLUDES $i" ++ done ++ AC_SUBST(PKG_INCLUDES) ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_ADD_LIBS -- ++# ++# Specify one or more libraries. Users should check for ++# the right platform before adding to their list. For Windows, ++# libraries provided in "foo.lib" format will be converted to ++# "-lfoo" when using GCC (mingw). ++# ++# Arguments: ++# one or more file names ++# ++# Results: ++# ++# Defines and substs the following vars: ++# PKG_LIBS ++#------------------------------------------------------------------------ ++AC_DEFUN([TEA_ADD_LIBS], [ ++ vars="$@" ++ for i in $vars; do ++ if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then ++ # Convert foo.lib to -lfoo for GCC. No-op if not *.lib ++ i=`echo "$i" | sed -e 's/^\([[^-]].*\)\.lib[$]/-l\1/i'` ++ fi ++ PKG_LIBS="$PKG_LIBS $i" ++ done ++ AC_SUBST(PKG_LIBS) ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_ADD_CFLAGS -- ++# ++# Specify one or more CFLAGS. Users should check for ++# the right platform before adding to their list. ++# ++# Arguments: ++# one or more file names ++# ++# Results: ++# ++# Defines and substs the following vars: ++# PKG_CFLAGS ++#------------------------------------------------------------------------ ++AC_DEFUN([TEA_ADD_CFLAGS], [ ++ PKG_CFLAGS="$PKG_CFLAGS $@" ++ AC_SUBST(PKG_CFLAGS) ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_ADD_CLEANFILES -- ++# ++# Specify one or more CLEANFILES. ++# ++# Arguments: ++# one or more file names to clean target ++# ++# Results: ++# ++# Appends to CLEANFILES, already defined for subst in LOAD_TCLCONFIG ++#------------------------------------------------------------------------ ++AC_DEFUN([TEA_ADD_CLEANFILES], [ ++ CLEANFILES="$CLEANFILES $@" ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_PREFIX -- ++# ++# Handle the --prefix=... option by defaulting to what Tcl gave ++# ++# Arguments: ++# none ++# ++# Results: ++# ++# If --prefix or --exec-prefix was not specified, $prefix and ++# $exec_prefix will be set to the values given to Tcl when it was ++# configured. ++#------------------------------------------------------------------------ ++AC_DEFUN([TEA_PREFIX], [ ++ if test "${prefix}" = "NONE"; then ++ prefix_default=yes ++ if test x"${TCL_PREFIX}" != x; then ++ AC_MSG_NOTICE([--prefix defaulting to TCL_PREFIX ${TCL_PREFIX}]) ++ prefix=${TCL_PREFIX} ++ else ++ AC_MSG_NOTICE([--prefix defaulting to /usr/local]) ++ prefix=/usr/local ++ fi ++ fi ++ if test "${exec_prefix}" = "NONE" -a x"${prefix_default}" = x"yes" \ ++ -o x"${exec_prefix_default}" = x"yes" ; then ++ if test x"${TCL_EXEC_PREFIX}" != x; then ++ AC_MSG_NOTICE([--exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}]) ++ exec_prefix=${TCL_EXEC_PREFIX} ++ else ++ AC_MSG_NOTICE([--exec-prefix defaulting to ${prefix}]) ++ exec_prefix=$prefix ++ fi ++ fi ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_SETUP_COMPILER_CC -- ++# ++# Do compiler checks the way we want. This is just a replacement ++# for AC_PROG_CC in TEA configure.in files to make them cleaner. ++# ++# Arguments: ++# none ++# ++# Results: ++# ++# Sets up CC var and other standard bits we need to make executables. ++#------------------------------------------------------------------------ ++AC_DEFUN([TEA_SETUP_COMPILER_CC], [ ++ # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE) ++ # in this macro, they need to go into TEA_SETUP_COMPILER instead. ++ ++ AC_PROG_CC ++ AC_PROG_CPP ++ ++ INSTALL="\$(SHELL) \$(srcdir)/tclconfig/install-sh -c" ++ AC_SUBST(INSTALL) ++ INSTALL_DATA="\${INSTALL} -m 644" ++ AC_SUBST(INSTALL_DATA) ++ INSTALL_PROGRAM="\${INSTALL}" ++ AC_SUBST(INSTALL_PROGRAM) ++ INSTALL_SCRIPT="\${INSTALL}" ++ AC_SUBST(INSTALL_SCRIPT) ++ ++ #-------------------------------------------------------------------- ++ # Checks to see if the make program sets the $MAKE variable. ++ #-------------------------------------------------------------------- ++ ++ AC_PROG_MAKE_SET ++ ++ #-------------------------------------------------------------------- ++ # Find ranlib ++ #-------------------------------------------------------------------- ++ ++ AC_CHECK_TOOL(RANLIB, ranlib) ++ ++ #-------------------------------------------------------------------- ++ # Determines the correct binary file extension (.o, .obj, .exe etc.) ++ #-------------------------------------------------------------------- ++ ++ AC_OBJEXT ++ AC_EXEEXT ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_SETUP_COMPILER -- ++# ++# Do compiler checks that use the compiler. This must go after ++# TEA_SETUP_COMPILER_CC, which does the actual compiler check. ++# ++# Arguments: ++# none ++# ++# Results: ++# ++# Sets up CC var and other standard bits we need to make executables. ++#------------------------------------------------------------------------ ++AC_DEFUN([TEA_SETUP_COMPILER], [ ++ # Any macros that use the compiler (e.g. AC_TRY_COMPILE) have to go here. ++ AC_REQUIRE([TEA_SETUP_COMPILER_CC]) ++ ++ #------------------------------------------------------------------------ ++ # If we're using GCC, see if the compiler understands -pipe. If so, use it. ++ # It makes compiling go faster. (This is only a performance feature.) ++ #------------------------------------------------------------------------ ++ ++ if test -z "$no_pipe" -a -n "$GCC"; then ++ AC_CACHE_CHECK([if the compiler understands -pipe], ++ tcl_cv_cc_pipe, [ ++ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe" ++ AC_TRY_COMPILE(,, tcl_cv_cc_pipe=yes, tcl_cv_cc_pipe=no) ++ CFLAGS=$hold_cflags]) ++ if test $tcl_cv_cc_pipe = yes; then ++ CFLAGS="$CFLAGS -pipe" ++ fi ++ fi ++ ++ #-------------------------------------------------------------------- ++ # Common compiler flag setup ++ #-------------------------------------------------------------------- ++ ++ AC_C_BIGENDIAN ++ if test "${TEA_PLATFORM}" = "unix" ; then ++ TEA_TCL_LINK_LIBS ++ TEA_MISSING_POSIX_HEADERS ++ # Let the user call this, because if it triggers, they will ++ # need a compat/strtod.c that is correct. Users can also ++ # use Tcl_GetDouble(FromObj) instead. ++ #TEA_BUGGY_STRTOD ++ fi ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_MAKE_LIB -- ++# ++# Generate a line that can be used to build a shared/unshared library ++# in a platform independent manner. ++# ++# Arguments: ++# none ++# ++# Requires: ++# ++# Results: ++# ++# Defines the following vars: ++# CFLAGS - Done late here to note disturb other AC macros ++# MAKE_LIB - Command to execute to build the Tcl library; ++# differs depending on whether or not Tcl is being ++# compiled as a shared library. ++# MAKE_SHARED_LIB Makefile rule for building a shared library ++# MAKE_STATIC_LIB Makefile rule for building a static library ++# MAKE_STUB_LIB Makefile rule for building a stub library ++# VC_MANIFEST_EMBED_DLL Makefile rule for embedded VC manifest in DLL ++# VC_MANIFEST_EMBED_EXE Makefile rule for embedded VC manifest in EXE ++#------------------------------------------------------------------------ ++ ++AC_DEFUN([TEA_MAKE_LIB], [ ++ if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then ++ MAKE_STATIC_LIB="\${STLIB_LD} -out:\[$]@ \$(PKG_OBJECTS)" ++ MAKE_SHARED_LIB="\${SHLIB_LD} \${SHLIB_LD_LIBS} \${LDFLAGS_DEFAULT} -out:\[$]@ \$(PKG_OBJECTS)" ++ AC_EGREP_CPP([manifest needed], [ ++#if defined(_MSC_VER) && _MSC_VER >= 1400 ++print("manifest needed") ++#endif ++ ], [ ++ # Could do a CHECK_PROG for mt, but should always be with MSVC8+ ++ VC_MANIFEST_EMBED_DLL="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;2 ; fi" ++ VC_MANIFEST_EMBED_EXE="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;1 ; fi" ++ MAKE_SHARED_LIB="${MAKE_SHARED_LIB} ; ${VC_MANIFEST_EMBED_DLL}" ++ TEA_ADD_CLEANFILES([*.manifest]) ++ ]) ++ MAKE_STUB_LIB="\${STLIB_LD} -nodefaultlib -out:\[$]@ \$(PKG_STUB_OBJECTS)" ++ else ++ MAKE_STATIC_LIB="\${STLIB_LD} \[$]@ \$(PKG_OBJECTS)" ++ MAKE_SHARED_LIB="\${SHLIB_LD} -o \[$]@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}" ++ MAKE_STUB_LIB="\${STLIB_LD} \[$]@ \$(PKG_STUB_OBJECTS)" ++ fi ++ ++ if test "${SHARED_BUILD}" = "1" ; then ++ MAKE_LIB="${MAKE_SHARED_LIB} " ++ else ++ MAKE_LIB="${MAKE_STATIC_LIB} " ++ fi ++ ++ #-------------------------------------------------------------------- ++ # Shared libraries and static libraries have different names. ++ # Use the double eval to make sure any variables in the suffix is ++ # substituted. (@@@ Might not be necessary anymore) ++ #-------------------------------------------------------------------- ++ ++ if test "${TEA_PLATFORM}" = "windows" ; then ++ if test "${SHARED_BUILD}" = "1" ; then ++ # We force the unresolved linking of symbols that are really in ++ # the private libraries of Tcl and Tk. ++ if test x"${TK_BIN_DIR}" != x ; then ++ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\"" ++ fi ++ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\"" ++ if test "$GCC" = "yes"; then ++ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -static-libgcc" ++ fi ++ eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" ++ else ++ eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" ++ if test "$GCC" = "yes"; then ++ PKG_LIB_FILE=lib${PKG_LIB_FILE} ++ fi ++ fi ++ # Some packages build their own stubs libraries ++ eval eval "PKG_STUB_LIB_FILE=${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" ++ if test "$GCC" = "yes"; then ++ PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE} ++ fi ++ # These aren't needed on Windows (either MSVC or gcc) ++ RANLIB=: ++ RANLIB_STUB=: ++ else ++ RANLIB_STUB="${RANLIB}" ++ if test "${SHARED_BUILD}" = "1" ; then ++ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}" ++ if test x"${TK_BIN_DIR}" != x ; then ++ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}" ++ fi ++ eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" ++ RANLIB=: ++ else ++ eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" ++ fi ++ # Some packages build their own stubs libraries ++ eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" ++ fi ++ ++ # These are escaped so that only CFLAGS is picked up at configure time. ++ # The other values will be substituted at make time. ++ CFLAGS="${CFLAGS} \${CFLAGS_DEFAULT} \${CFLAGS_WARNING}" ++ if test "${SHARED_BUILD}" = "1" ; then ++ CFLAGS="${CFLAGS} \${SHLIB_CFLAGS}" ++ fi ++ ++ AC_SUBST(MAKE_LIB) ++ AC_SUBST(MAKE_SHARED_LIB) ++ AC_SUBST(MAKE_STATIC_LIB) ++ AC_SUBST(MAKE_STUB_LIB) ++ AC_SUBST(RANLIB_STUB) ++ AC_SUBST(VC_MANIFEST_EMBED_DLL) ++ AC_SUBST(VC_MANIFEST_EMBED_EXE) ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_LIB_SPEC -- ++# ++# Compute the name of an existing object library located in libdir ++# from the given base name and produce the appropriate linker flags. ++# ++# Arguments: ++# basename The base name of the library without version ++# numbers, extensions, or "lib" prefixes. ++# extra_dir Extra directory in which to search for the ++# library. This location is used first, then ++# $prefix/$exec-prefix, then some defaults. ++# ++# Requires: ++# TEA_INIT and TEA_PREFIX must be called first. ++# ++# Results: ++# ++# Defines the following vars: ++# ${basename}_LIB_NAME The computed library name. ++# ${basename}_LIB_SPEC The computed linker flags. ++#------------------------------------------------------------------------ ++ ++AC_DEFUN([TEA_LIB_SPEC], [ ++ AC_MSG_CHECKING([for $1 library]) ++ ++ # Look in exec-prefix for the library (defined by TEA_PREFIX). ++ ++ tea_lib_name_dir="${exec_prefix}/lib" ++ ++ # Or in a user-specified location. ++ ++ if test x"$2" != x ; then ++ tea_extra_lib_dir=$2 ++ else ++ tea_extra_lib_dir=NONE ++ fi ++ ++ for i in \ ++ `ls -dr ${tea_extra_lib_dir}/$1[[0-9]]*.lib 2>/dev/null ` \ ++ `ls -dr ${tea_extra_lib_dir}/lib$1[[0-9]]* 2>/dev/null ` \ ++ `ls -dr ${tea_lib_name_dir}/$1[[0-9]]*.lib 2>/dev/null ` \ ++ `ls -dr ${tea_lib_name_dir}/lib$1[[0-9]]* 2>/dev/null ` \ ++ `ls -dr /usr/lib/$1[[0-9]]*.lib 2>/dev/null ` \ ++ `ls -dr /usr/lib/lib$1[[0-9]]* 2>/dev/null ` \ ++ `ls -dr /usr/lib64/$1[[0-9]]*.lib 2>/dev/null ` \ ++ `ls -dr /usr/lib64/lib$1[[0-9]]* 2>/dev/null ` \ ++ `ls -dr /usr/local/lib/$1[[0-9]]*.lib 2>/dev/null ` \ ++ `ls -dr /usr/local/lib/lib$1[[0-9]]* 2>/dev/null ` ; do ++ if test -f "$i" ; then ++ tea_lib_name_dir=`dirname $i` ++ $1_LIB_NAME=`basename $i` ++ $1_LIB_PATH_NAME=$i ++ break ++ fi ++ done ++ ++ if test "${TEA_PLATFORM}" = "windows"; then ++ $1_LIB_SPEC=\"`${CYGPATH} ${$1_LIB_PATH_NAME} 2>/dev/null`\" ++ else ++ # Strip off the leading "lib" and trailing ".a" or ".so" ++ ++ tea_lib_name_lib=`echo ${$1_LIB_NAME}|sed -e 's/^lib//' -e 's/\.[[^.]]*$//' -e 's/\.so.*//'` ++ $1_LIB_SPEC="-L${tea_lib_name_dir} -l${tea_lib_name_lib}" ++ fi ++ ++ if test "x${$1_LIB_NAME}" = x ; then ++ AC_MSG_ERROR([not found]) ++ else ++ AC_MSG_RESULT([${$1_LIB_SPEC}]) ++ fi ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_PRIVATE_TCL_HEADERS -- ++# ++# Locate the private Tcl include files ++# ++# Arguments: ++# ++# Requires: ++# TCL_SRC_DIR Assumes that TEA_LOAD_TCLCONFIG has ++# already been called. ++# ++# Results: ++# ++# Substitutes the following vars: ++# TCL_TOP_DIR_NATIVE ++# TCL_INCLUDES ++#------------------------------------------------------------------------ ++ ++AC_DEFUN([TEA_PRIVATE_TCL_HEADERS], [ ++ # Allow for --with-tclinclude to take effect and define ${ac_cv_c_tclh} ++ AC_REQUIRE([TEA_PUBLIC_TCL_HEADERS]) ++ AC_MSG_CHECKING([for Tcl private include files]) ++ ++ TCL_SRC_DIR_NATIVE=`${CYGPATH} ${TCL_SRC_DIR}` ++ TCL_TOP_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}\" ++ ++ # Check to see if tcl<Plat>Port.h isn't already with the public headers ++ # Don't look for tclInt.h because that resides with tcl.h in the core ++ # sources, but the <plat>Port headers are in a different directory ++ if test "${TEA_PLATFORM}" = "windows" -a \ ++ -f "${ac_cv_c_tclh}/tclWinPort.h"; then ++ result="private headers found with public headers" ++ elif test "${TEA_PLATFORM}" = "unix" -a \ ++ -f "${ac_cv_c_tclh}/tclUnixPort.h"; then ++ result="private headers found with public headers" ++ else ++ TCL_GENERIC_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/generic\" ++ if test "${TEA_PLATFORM}" = "windows"; then ++ TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/win\" ++ else ++ TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/unix\" ++ fi ++ # Overwrite the previous TCL_INCLUDES as this should capture both ++ # public and private headers in the same set. ++ # We want to ensure these are substituted so as not to require ++ # any *_NATIVE vars be defined in the Makefile ++ TCL_INCLUDES="-I${TCL_GENERIC_DIR_NATIVE} -I${TCL_PLATFORM_DIR_NATIVE}" ++ if test "`uname -s`" = "Darwin"; then ++ # If Tcl was built as a framework, attempt to use ++ # the framework's Headers and PrivateHeaders directories ++ case ${TCL_DEFS} in ++ *TCL_FRAMEWORK*) ++ if test -d "${TCL_BIN_DIR}/Headers" -a \ ++ -d "${TCL_BIN_DIR}/PrivateHeaders"; then ++ TCL_INCLUDES="-I\"${TCL_BIN_DIR}/Headers\" -I\"${TCL_BIN_DIR}/PrivateHeaders\" ${TCL_INCLUDES}" ++ else ++ TCL_INCLUDES="${TCL_INCLUDES} ${TCL_INCLUDE_SPEC} `echo "${TCL_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`" ++ fi ++ ;; ++ esac ++ result="Using ${TCL_INCLUDES}" ++ else ++ if test ! -f "${TCL_SRC_DIR}/generic/tclInt.h" ; then ++ AC_MSG_ERROR([Cannot find private header tclInt.h in ${TCL_SRC_DIR}]) ++ fi ++ result="Using srcdir found in tclConfig.sh: ${TCL_SRC_DIR}" ++ fi ++ fi ++ ++ AC_SUBST(TCL_TOP_DIR_NATIVE) ++ ++ AC_SUBST(TCL_INCLUDES) ++ AC_MSG_RESULT([${result}]) ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_PUBLIC_TCL_HEADERS -- ++# ++# Locate the installed public Tcl header files ++# ++# Arguments: ++# None. ++# ++# Requires: ++# CYGPATH must be set ++# ++# Results: ++# ++# Adds a --with-tclinclude switch to configure. ++# Result is cached. ++# ++# Substitutes the following vars: ++# TCL_INCLUDES ++#------------------------------------------------------------------------ ++ ++AC_DEFUN([TEA_PUBLIC_TCL_HEADERS], [ ++ AC_MSG_CHECKING([for Tcl public headers]) ++ ++ AC_ARG_WITH(tclinclude, [ --with-tclinclude directory containing the public Tcl header files], with_tclinclude=${withval}) ++ ++ AC_CACHE_VAL(ac_cv_c_tclh, [ ++ # Use the value from --with-tclinclude, if it was given ++ ++ if test x"${with_tclinclude}" != x ; then ++ if test -f "${with_tclinclude}/tcl.h" ; then ++ ac_cv_c_tclh=${with_tclinclude} ++ else ++ AC_MSG_ERROR([${with_tclinclude} directory does not contain tcl.h]) ++ fi ++ else ++ list="" ++ if test "`uname -s`" = "Darwin"; then ++ # If Tcl was built as a framework, attempt to use ++ # the framework's Headers directory ++ case ${TCL_DEFS} in ++ *TCL_FRAMEWORK*) ++ list="`ls -d ${TCL_BIN_DIR}/Headers 2>/dev/null`" ++ ;; ++ esac ++ fi ++ ++ # Look in the source dir only if Tcl is not installed, ++ # and in that situation, look there before installed locations. ++ if test -f "${TCL_BIN_DIR}/Makefile" ; then ++ list="$list `ls -d ${TCL_SRC_DIR}/generic 2>/dev/null`" ++ fi ++ ++ # Check order: pkg --prefix location, Tcl's --prefix location, ++ # relative to directory of tclConfig.sh. ++ ++ eval "temp_includedir=${includedir}" ++ list="$list \ ++ `ls -d ${temp_includedir} 2>/dev/null` \ ++ `ls -d ${TCL_PREFIX}/include 2>/dev/null` \ ++ `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`" ++ if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then ++ list="$list /usr/local/include /usr/include" ++ if test x"${TCL_INCLUDE_SPEC}" != x ; then ++ d=`echo "${TCL_INCLUDE_SPEC}" | sed -e 's/^-I//'` ++ list="$list `ls -d ${d} 2>/dev/null`" ++ fi ++ fi ++ for i in $list ; do ++ if test -f "$i/tcl.h" ; then ++ ac_cv_c_tclh=$i ++ break ++ fi ++ done ++ fi ++ ]) ++ ++ # Print a message based on how we determined the include path ++ ++ if test x"${ac_cv_c_tclh}" = x ; then ++ AC_MSG_ERROR([tcl.h not found. Please specify its location with --with-tclinclude]) ++ else ++ AC_MSG_RESULT([${ac_cv_c_tclh}]) ++ fi ++ ++ # Convert to a native path and substitute into the output files. ++ ++ INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclh}` ++ ++ TCL_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" ++ ++ AC_SUBST(TCL_INCLUDES) ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_PRIVATE_TK_HEADERS -- ++# ++# Locate the private Tk include files ++# ++# Arguments: ++# ++# Requires: ++# TK_SRC_DIR Assumes that TEA_LOAD_TKCONFIG has ++# already been called. ++# ++# Results: ++# ++# Substitutes the following vars: ++# TK_INCLUDES ++#------------------------------------------------------------------------ ++ ++AC_DEFUN([TEA_PRIVATE_TK_HEADERS], [ ++ # Allow for --with-tkinclude to take effect and define ${ac_cv_c_tkh} ++ AC_REQUIRE([TEA_PUBLIC_TK_HEADERS]) ++ AC_MSG_CHECKING([for Tk private include files]) ++ ++ TK_SRC_DIR_NATIVE=`${CYGPATH} ${TK_SRC_DIR}` ++ TK_TOP_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}\" ++ ++ # Check to see if tk<Plat>Port.h isn't already with the public headers ++ # Don't look for tkInt.h because that resides with tk.h in the core ++ # sources, but the <plat>Port headers are in a different directory ++ if test "${TEA_PLATFORM}" = "windows" -a \ ++ -f "${ac_cv_c_tkh}/tkWinPort.h"; then ++ result="private headers found with public headers" ++ elif test "${TEA_PLATFORM}" = "unix" -a \ ++ -f "${ac_cv_c_tkh}/tkUnixPort.h"; then ++ result="private headers found with public headers" ++ else ++ TK_GENERIC_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/generic\" ++ TK_XLIB_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/xlib\" ++ if test "${TEA_PLATFORM}" = "windows"; then ++ TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/win\" ++ else ++ TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/unix\" ++ fi ++ # Overwrite the previous TK_INCLUDES as this should capture both ++ # public and private headers in the same set. ++ # We want to ensure these are substituted so as not to require ++ # any *_NATIVE vars be defined in the Makefile ++ TK_INCLUDES="-I${TK_GENERIC_DIR_NATIVE} -I${TK_PLATFORM_DIR_NATIVE}" ++ # Detect and add ttk subdir ++ if test -d "${TK_SRC_DIR}/generic/ttk"; then ++ TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/generic/ttk\"" ++ fi ++ if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then ++ TK_INCLUDES="${TK_INCLUDES} -I\"${TK_XLIB_DIR_NATIVE}\"" ++ fi ++ if test "${TEA_WINDOWINGSYSTEM}" = "aqua"; then ++ TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/macosx\"" ++ fi ++ if test "`uname -s`" = "Darwin"; then ++ # If Tk was built as a framework, attempt to use ++ # the framework's Headers and PrivateHeaders directories ++ case ${TK_DEFS} in ++ *TK_FRAMEWORK*) ++ if test -d "${TK_BIN_DIR}/Headers" -a \ ++ -d "${TK_BIN_DIR}/PrivateHeaders"; then ++ TK_INCLUDES="-I\"${TK_BIN_DIR}/Headers\" -I\"${TK_BIN_DIR}/PrivateHeaders\" ${TK_INCLUDES}" ++ else ++ TK_INCLUDES="${TK_INCLUDES} ${TK_INCLUDE_SPEC} `echo "${TK_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`" ++ fi ++ ;; ++ esac ++ result="Using ${TK_INCLUDES}" ++ else ++ if test ! -f "${TK_SRC_DIR}/generic/tkInt.h" ; then ++ AC_MSG_ERROR([Cannot find private header tkInt.h in ${TK_SRC_DIR}]) ++ fi ++ result="Using srcdir found in tkConfig.sh: ${TK_SRC_DIR}" ++ fi ++ fi ++ ++ AC_SUBST(TK_TOP_DIR_NATIVE) ++ AC_SUBST(TK_XLIB_DIR_NATIVE) ++ ++ AC_SUBST(TK_INCLUDES) ++ AC_MSG_RESULT([${result}]) ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_PUBLIC_TK_HEADERS -- ++# ++# Locate the installed public Tk header files ++# ++# Arguments: ++# None. ++# ++# Requires: ++# CYGPATH must be set ++# ++# Results: ++# ++# Adds a --with-tkinclude switch to configure. ++# Result is cached. ++# ++# Substitutes the following vars: ++# TK_INCLUDES ++#------------------------------------------------------------------------ ++ ++AC_DEFUN([TEA_PUBLIC_TK_HEADERS], [ ++ AC_MSG_CHECKING([for Tk public headers]) ++ ++ AC_ARG_WITH(tkinclude, [ --with-tkinclude directory containing the public Tk header files], with_tkinclude=${withval}) ++ ++ AC_CACHE_VAL(ac_cv_c_tkh, [ ++ # Use the value from --with-tkinclude, if it was given ++ ++ if test x"${with_tkinclude}" != x ; then ++ if test -f "${with_tkinclude}/tk.h" ; then ++ ac_cv_c_tkh=${with_tkinclude} ++ else ++ AC_MSG_ERROR([${with_tkinclude} directory does not contain tk.h]) ++ fi ++ else ++ list="" ++ if test "`uname -s`" = "Darwin"; then ++ # If Tk was built as a framework, attempt to use ++ # the framework's Headers directory. ++ case ${TK_DEFS} in ++ *TK_FRAMEWORK*) ++ list="`ls -d ${TK_BIN_DIR}/Headers 2>/dev/null`" ++ ;; ++ esac ++ fi ++ ++ # Look in the source dir only if Tk is not installed, ++ # and in that situation, look there before installed locations. ++ if test -f "${TK_BIN_DIR}/Makefile" ; then ++ list="$list `ls -d ${TK_SRC_DIR}/generic 2>/dev/null`" ++ fi ++ ++ # Check order: pkg --prefix location, Tk's --prefix location, ++ # relative to directory of tkConfig.sh, Tcl's --prefix location, ++ # relative to directory of tclConfig.sh. ++ ++ eval "temp_includedir=${includedir}" ++ list="$list \ ++ `ls -d ${temp_includedir} 2>/dev/null` \ ++ `ls -d ${TK_PREFIX}/include 2>/dev/null` \ ++ `ls -d ${TK_BIN_DIR}/../include 2>/dev/null` \ ++ `ls -d ${TCL_PREFIX}/include 2>/dev/null` \ ++ `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`" ++ if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then ++ list="$list /usr/local/include /usr/include" ++ if test x"${TK_INCLUDE_SPEC}" != x ; then ++ d=`echo "${TK_INCLUDE_SPEC}" | sed -e 's/^-I//'` ++ list="$list `ls -d ${d} 2>/dev/null`" ++ fi ++ fi ++ for i in $list ; do ++ if test -f "$i/tk.h" ; then ++ ac_cv_c_tkh=$i ++ break ++ fi ++ done ++ fi ++ ]) ++ ++ # Print a message based on how we determined the include path ++ ++ if test x"${ac_cv_c_tkh}" = x ; then ++ AC_MSG_ERROR([tk.h not found. Please specify its location with --with-tkinclude]) ++ else ++ AC_MSG_RESULT([${ac_cv_c_tkh}]) ++ fi ++ ++ # Convert to a native path and substitute into the output files. ++ ++ INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tkh}` ++ ++ TK_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" ++ ++ AC_SUBST(TK_INCLUDES) ++ ++ if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then ++ # On Windows and Aqua, we need the X compat headers ++ AC_MSG_CHECKING([for X11 header files]) ++ if test ! -r "${INCLUDE_DIR_NATIVE}/X11/Xlib.h"; then ++ INCLUDE_DIR_NATIVE="`${CYGPATH} ${TK_SRC_DIR}/xlib`" ++ TK_XINCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" ++ AC_SUBST(TK_XINCLUDES) ++ fi ++ AC_MSG_RESULT([${INCLUDE_DIR_NATIVE}]) ++ fi ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_PATH_CONFIG -- ++# ++# Locate the ${1}Config.sh file and perform a sanity check on ++# the ${1} compile flags. These are used by packages like ++# [incr Tk] that load *Config.sh files from more than Tcl and Tk. ++# ++# Arguments: ++# none ++# ++# Results: ++# ++# Adds the following arguments to configure: ++# --with-$1=... ++# ++# Defines the following vars: ++# $1_BIN_DIR Full path to the directory containing ++# the $1Config.sh file ++#------------------------------------------------------------------------ ++ ++AC_DEFUN([TEA_PATH_CONFIG], [ ++ # ++ # Ok, lets find the $1 configuration ++ # First, look for one uninstalled. ++ # the alternative search directory is invoked by --with-$1 ++ # ++ ++ if test x"${no_$1}" = x ; then ++ # we reset no_$1 in case something fails here ++ no_$1=true ++ AC_ARG_WITH($1, [ --with-$1 directory containing $1 configuration ($1Config.sh)], with_$1config=${withval}) ++ AC_MSG_CHECKING([for $1 configuration]) ++ AC_CACHE_VAL(ac_cv_c_$1config,[ ++ ++ # First check to see if --with-$1 was specified. ++ if test x"${with_$1config}" != x ; then ++ case ${with_$1config} in ++ */$1Config.sh ) ++ if test -f ${with_$1config}; then ++ AC_MSG_WARN([--with-$1 argument should refer to directory containing $1Config.sh, not to $1Config.sh itself]) ++ with_$1config=`echo ${with_$1config} | sed 's!/$1Config\.sh$!!'` ++ fi;; ++ esac ++ if test -f "${with_$1config}/$1Config.sh" ; then ++ ac_cv_c_$1config=`(cd ${with_$1config}; pwd)` ++ else ++ AC_MSG_ERROR([${with_$1config} directory doesn't contain $1Config.sh]) ++ fi ++ fi ++ ++ # then check for a private $1 installation ++ if test x"${ac_cv_c_$1config}" = x ; then ++ for i in \ ++ ../$1 \ ++ `ls -dr ../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ ++ `ls -dr ../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ ++ `ls -dr ../$1*[[0-9]].[[0-9]] 2>/dev/null` \ ++ `ls -dr ../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ ++ ../../$1 \ ++ `ls -dr ../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ ++ `ls -dr ../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ ++ `ls -dr ../../$1*[[0-9]].[[0-9]] 2>/dev/null` \ ++ `ls -dr ../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ ++ ../../../$1 \ ++ `ls -dr ../../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ ++ `ls -dr ../../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ ++ `ls -dr ../../../$1*[[0-9]].[[0-9]] 2>/dev/null` \ ++ `ls -dr ../../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ ++ ${srcdir}/../$1 \ ++ `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ ++ `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ ++ `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]] 2>/dev/null` \ ++ `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ ++ ; do ++ if test -f "$i/$1Config.sh" ; then ++ ac_cv_c_$1config=`(cd $i; pwd)` ++ break ++ fi ++ if test -f "$i/unix/$1Config.sh" ; then ++ ac_cv_c_$1config=`(cd $i/unix; pwd)` ++ break ++ fi ++ done ++ fi ++ ++ # check in a few common install locations ++ if test x"${ac_cv_c_$1config}" = x ; then ++ for i in `ls -d ${libdir} 2>/dev/null` \ ++ `ls -d ${exec_prefix}/lib 2>/dev/null` \ ++ `ls -d ${prefix}/lib 2>/dev/null` \ ++ `ls -d /usr/local/lib 2>/dev/null` \ ++ `ls -d /usr/contrib/lib 2>/dev/null` \ ++ `ls -d /usr/lib 2>/dev/null` \ ++ `ls -d /usr/lib64 2>/dev/null` \ ++ ; do ++ if test -f "$i/$1Config.sh" ; then ++ ac_cv_c_$1config=`(cd $i; pwd)` ++ break ++ fi ++ done ++ fi ++ ]) ++ ++ if test x"${ac_cv_c_$1config}" = x ; then ++ $1_BIN_DIR="# no $1 configs found" ++ AC_MSG_WARN([Cannot find $1 configuration definitions]) ++ exit 0 ++ else ++ no_$1= ++ $1_BIN_DIR=${ac_cv_c_$1config} ++ AC_MSG_RESULT([found $$1_BIN_DIR/$1Config.sh]) ++ fi ++ fi ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_LOAD_CONFIG -- ++# ++# Load the $1Config.sh file ++# ++# Arguments: ++# ++# Requires the following vars to be set: ++# $1_BIN_DIR ++# ++# Results: ++# ++# Substitutes the following vars: ++# $1_SRC_DIR ++# $1_LIB_FILE ++# $1_LIB_SPEC ++#------------------------------------------------------------------------ ++ ++AC_DEFUN([TEA_LOAD_CONFIG], [ ++ AC_MSG_CHECKING([for existence of ${$1_BIN_DIR}/$1Config.sh]) ++ ++ if test -f "${$1_BIN_DIR}/$1Config.sh" ; then ++ AC_MSG_RESULT([loading]) ++ . "${$1_BIN_DIR}/$1Config.sh" ++ else ++ AC_MSG_RESULT([file not found]) ++ fi ++ ++ # ++ # If the $1_BIN_DIR is the build directory (not the install directory), ++ # then set the common variable name to the value of the build variables. ++ # For example, the variable $1_LIB_SPEC will be set to the value ++ # of $1_BUILD_LIB_SPEC. An extension should make use of $1_LIB_SPEC ++ # instead of $1_BUILD_LIB_SPEC since it will work with both an ++ # installed and uninstalled version of Tcl. ++ # ++ ++ if test -f "${$1_BIN_DIR}/Makefile" ; then ++ AC_MSG_WARN([Found Makefile - using build library specs for $1]) ++ $1_LIB_SPEC=${$1_BUILD_LIB_SPEC} ++ $1_STUB_LIB_SPEC=${$1_BUILD_STUB_LIB_SPEC} ++ $1_STUB_LIB_PATH=${$1_BUILD_STUB_LIB_PATH} ++ $1_INCLUDE_SPEC=${$1_BUILD_INCLUDE_SPEC} ++ $1_LIBRARY_PATH=${$1_LIBRARY_PATH} ++ fi ++ ++ AC_SUBST($1_VERSION) ++ AC_SUBST($1_BIN_DIR) ++ AC_SUBST($1_SRC_DIR) ++ ++ AC_SUBST($1_LIB_FILE) ++ AC_SUBST($1_LIB_SPEC) ++ ++ AC_SUBST($1_STUB_LIB_FILE) ++ AC_SUBST($1_STUB_LIB_SPEC) ++ AC_SUBST($1_STUB_LIB_PATH) ++ ++ # Allow the caller to prevent this auto-check by specifying any 2nd arg ++ AS_IF([test "x$2" = x], [ ++ # Check both upper and lower-case variants ++ # If a dev wanted non-stubs libs, this function could take an option ++ # to not use _STUB in the paths below ++ AS_IF([test "x${$1_STUB_LIB_SPEC}" = x], ++ [TEA_LOAD_CONFIG_LIB(translit($1,[a-z],[A-Z])_STUB)], ++ [TEA_LOAD_CONFIG_LIB($1_STUB)]) ++ ]) ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_LOAD_CONFIG_LIB -- ++# ++# Helper function to load correct library from another extension's ++# ${PACKAGE}Config.sh. ++# ++# Results: ++# Adds to LIBS the appropriate extension library ++#------------------------------------------------------------------------ ++AC_DEFUN([TEA_LOAD_CONFIG_LIB], [ ++ AC_MSG_CHECKING([For $1 library for LIBS]) ++ # This simplifies the use of stub libraries by automatically adding ++ # the stub lib to your path. Normally this would add to SHLIB_LD_LIBS, ++ # but this is called before CONFIG_CFLAGS. More importantly, this adds ++ # to PKG_LIBS, which becomes LIBS, and that is only used by SHLIB_LD. ++ if test "x${$1_LIB_SPEC}" != "x" ; then ++ if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes" ; then ++ TEA_ADD_LIBS([\"`${CYGPATH} ${$1_LIB_PATH}`\"]) ++ AC_MSG_RESULT([using $1_LIB_PATH ${$1_LIB_PATH}]) ++ else ++ TEA_ADD_LIBS([${$1_LIB_SPEC}]) ++ AC_MSG_RESULT([using $1_LIB_SPEC ${$1_LIB_SPEC}]) ++ fi ++ else ++ AC_MSG_RESULT([file not found]) ++ fi ++]) ++ ++#------------------------------------------------------------------------ ++# TEA_EXPORT_CONFIG -- ++# ++# Define the data to insert into the ${PACKAGE}Config.sh file ++# ++# Arguments: ++# ++# Requires the following vars to be set: ++# $1 ++# ++# Results: ++# Substitutes the following vars: ++#------------------------------------------------------------------------ ++ ++AC_DEFUN([TEA_EXPORT_CONFIG], [ ++ #-------------------------------------------------------------------- ++ # These are for $1Config.sh ++ #-------------------------------------------------------------------- ++ ++ # pkglibdir must be a fully qualified path and (not ${exec_prefix}/lib) ++ eval pkglibdir="[$]{libdir}/$1${PACKAGE_VERSION}" ++ if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then ++ eval $1_LIB_FLAG="-l$1${PACKAGE_VERSION}${DBGX}" ++ eval $1_STUB_LIB_FLAG="-l$1stub${PACKAGE_VERSION}${DBGX}" ++ else ++ eval $1_LIB_FLAG="-l$1`echo ${PACKAGE_VERSION} | tr -d .`${DBGX}" ++ eval $1_STUB_LIB_FLAG="-l$1stub`echo ${PACKAGE_VERSION} | tr -d .`${DBGX}" ++ fi ++ $1_BUILD_LIB_SPEC="-L`pwd` ${$1_LIB_FLAG}" ++ $1_LIB_SPEC="-L${pkglibdir} ${$1_LIB_FLAG}" ++ $1_BUILD_STUB_LIB_SPEC="-L`pwd` [$]{$1_STUB_LIB_FLAG}" ++ $1_STUB_LIB_SPEC="-L${pkglibdir} [$]{$1_STUB_LIB_FLAG}" ++ $1_BUILD_STUB_LIB_PATH="`pwd`/[$]{PKG_STUB_LIB_FILE}" ++ $1_STUB_LIB_PATH="${pkglibdir}/[$]{PKG_STUB_LIB_FILE}" ++ ++ AC_SUBST($1_BUILD_LIB_SPEC) ++ AC_SUBST($1_LIB_SPEC) ++ AC_SUBST($1_BUILD_STUB_LIB_SPEC) ++ AC_SUBST($1_STUB_LIB_SPEC) ++ AC_SUBST($1_BUILD_STUB_LIB_PATH) ++ AC_SUBST($1_STUB_LIB_PATH) ++ ++ AC_SUBST(MAJOR_VERSION) ++ AC_SUBST(MINOR_VERSION) ++ AC_SUBST(PATCHLEVEL) ++]) ++ ++ ++#------------------------------------------------------------------------ ++# TEA_PATH_CELIB -- ++# ++# Locate Keuchel's celib emulation layer for targeting Win/CE ++# ++# Arguments: ++# none ++# ++# Results: ++# ++# Adds the following arguments to configure: ++# --with-celib=... ++# ++# Defines the following vars: ++# CELIB_DIR Full path to the directory containing ++# the include and platform lib files ++#------------------------------------------------------------------------ ++ ++AC_DEFUN([TEA_PATH_CELIB], [ ++ # First, look for one uninstalled. ++ # the alternative search directory is invoked by --with-celib ++ ++ if test x"${no_celib}" = x ; then ++ # we reset no_celib in case something fails here ++ no_celib=true ++ AC_ARG_WITH(celib,[ --with-celib=DIR use Windows/CE support library from DIR], with_celibconfig=${withval}) ++ AC_MSG_CHECKING([for Windows/CE celib directory]) ++ AC_CACHE_VAL(ac_cv_c_celibconfig,[ ++ # First check to see if --with-celibconfig was specified. ++ if test x"${with_celibconfig}" != x ; then ++ if test -d "${with_celibconfig}/inc" ; then ++ ac_cv_c_celibconfig=`(cd ${with_celibconfig}; pwd)` ++ else ++ AC_MSG_ERROR([${with_celibconfig} directory doesn't contain inc directory]) ++ fi ++ fi ++ ++ # then check for a celib library ++ if test x"${ac_cv_c_celibconfig}" = x ; then ++ for i in \ ++ ../celib-palm-3.0 \ ++ ../celib \ ++ ../../celib-palm-3.0 \ ++ ../../celib \ ++ `ls -dr ../celib-*3.[[0-9]]* 2>/dev/null` \ ++ ${srcdir}/../celib-palm-3.0 \ ++ ${srcdir}/../celib \ ++ `ls -dr ${srcdir}/../celib-*3.[[0-9]]* 2>/dev/null` \ ++ ; do ++ if test -d "$i/inc" ; then ++ ac_cv_c_celibconfig=`(cd $i; pwd)` ++ break ++ fi ++ done ++ fi ++ ]) ++ if test x"${ac_cv_c_celibconfig}" = x ; then ++ AC_MSG_ERROR([Cannot find celib support library directory]) ++ else ++ no_celib= ++ CELIB_DIR=${ac_cv_c_celibconfig} ++ CELIB_DIR=`echo "$CELIB_DIR" | sed -e 's!\\\!/!g'` ++ AC_MSG_RESULT([found $CELIB_DIR]) ++ fi ++ fi ++]) ++# Local Variables: ++# mode: autoconf ++# End: +--- contrib/sqlite3/tea/win/makefile.vc.orig ++++ contrib/sqlite3/tea/win/makefile.vc +@@ -0,0 +1,414 @@ ++# makefile.vc -- -*- Makefile -*- ++# ++# Microsoft Visual C++ makefile for use with nmake.exe v1.62+ (VC++ 5.0+) ++# ++# This makefile is based upon the Tcl 8.4 Makefile.vc and modified to ++# make it suitable as a general package makefile. Look for the word EDIT ++# which marks sections that may need modification. As a minumum you will ++# need to change the PROJECT, DOTVERSION and DLLOBJS variables to values ++# relevant to your package. ++# ++# See the file "license.terms" for information on usage and redistribution ++# of this file, and for a DISCLAIMER OF ALL WARRANTIES. ++# ++# Copyright (c) 1995-1996 Sun Microsystems, Inc. ++# Copyright (c) 1998-2000 Ajuba Solutions. ++# Copyright (c) 2001 ActiveState Corporation. ++# Copyright (c) 2001-2002 David Gravereaux. ++# Copyright (c) 2003 Pat Thoyts ++# ++#------------------------------------------------------------------------- ++# RCS: @(#)$Id: makefile.vc,v 1.4 2004/07/26 08:22:05 patthoyts Exp $ ++#------------------------------------------------------------------------- ++ ++!if !defined(MSDEVDIR) && !defined(MSVCDIR) && !defined(VCINSTALLDIR) && !defined(MSSDK) && !defined(WINDOWSSDKDIR) ++MSG = ^ ++You will need to run vcvars32.bat from Developer Studio, first, to setup^ ++the environment. Jump to this line to read the new instructions. ++!error $(MSG) ++!endif ++ ++#------------------------------------------------------------------------------ ++# HOW TO USE this makefile: ++# ++# 1) It is now necessary to have %MSVCDir% set in the environment. This is ++# used as a check to see if vcvars32.bat had been run prior to running ++# nmake or during the installation of Microsoft Visual C++, MSVCDir had ++# been set globally and the PATH adjusted. Either way is valid. ++# ++# You'll need to run vcvars32.bat contained in the MsDev's vc(98)/bin ++# directory to setup the proper environment, if needed, for your current ++# setup. This is a needed bootstrap requirement and allows the swapping of ++# different environments to be easier. ++# ++# 2) To use the Platform SDK (not expressly needed), run setenv.bat after ++# vcvars32.bat according to the instructions for it. This can also turn on ++# the 64-bit compiler, if your SDK has it. ++# ++# 3) Targets are: ++# all -- Builds everything. ++# <project> -- Builds the project (eg: nmake sample) ++# test -- Builds and runs the test suite. ++# install -- Installs the built binaries and libraries to $(INSTALLDIR) ++# in an appropriate subdirectory. ++# clean/realclean/distclean -- varying levels of cleaning. ++# ++# 4) Macros usable on the commandline: ++# INSTALLDIR=<path> ++# Sets where to install Tcl from the built binaries. ++# C:\Progra~1\Tcl is assumed when not specified. ++# ++# OPTS=static,msvcrt,staticpkg,threads,symbols,profile,loimpact,none ++# Sets special options for the core. The default is for none. ++# Any combination of the above may be used (comma separated). ++# 'none' will over-ride everything to nothing. ++# ++# static = Builds a static library of the core instead of a ++# dll. The shell will be static (and large), as well. ++# msvcrt = Effects the static option only to switch it from ++# using libcmt(d) as the C runtime [by default] to ++# msvcrt(d). This is useful for static embedding ++# support. ++# staticpkg = Effects the static option only to switch ++# tclshXX.exe to have the dde and reg extension linked ++# inside it. ++# threads = Turns on full multithreading support. ++# thrdalloc = Use the thread allocator (shared global free pool). ++# symbols = Adds symbols for step debugging. ++# profile = Adds profiling hooks. Map file is assumed. ++# loimpact = Adds a flag for how NT treats the heap to keep memory ++# in use, low. This is said to impact alloc performance. ++# ++# STATS=memdbg,compdbg,none ++# Sets optional memory and bytecode compiler debugging code added ++# to the core. The default is for none. Any combination of the ++# above may be used (comma separated). 'none' will over-ride ++# everything to nothing. ++# ++# memdbg = Enables the debugging memory allocator. ++# compdbg = Enables byte compilation logging. ++# ++# MACHINE=(IX86|IA64|ALPHA) ++# Set the machine type used for the compiler, linker, and ++# resource compiler. This hook is needed to tell the tools ++# when alternate platforms are requested. IX86 is the default ++# when not specified. ++# ++# TMP_DIR=<path> ++# OUT_DIR=<path> ++# Hooks to allow the intermediate and output directories to be ++# changed. $(OUT_DIR) is assumed to be ++# $(BINROOT)\(Release|Debug) based on if symbols are requested. ++# $(TMP_DIR) will de $(OUT_DIR)\<buildtype> by default. ++# ++# TESTPAT=<file> ++# Reads the tests requested to be run from this file. ++# ++# CFG_ENCODING=encoding ++# name of encoding for configuration information. Defaults ++# to cp1252 ++# ++# 5) Examples: ++# ++# Basic syntax of calling nmake looks like this: ++# nmake [-nologo] -f makefile.vc [target|macrodef [target|macrodef] [...]] ++# ++# Standard (no frills) ++# c:\tcl_src\win\>c:\progra~1\micros~1\vc98\bin\vcvars32.bat ++# Setting environment for using Microsoft Visual C++ tools. ++# c:\tcl_src\win\>nmake -f makefile.vc all ++# c:\tcl_src\win\>nmake -f makefile.vc install INSTALLDIR=c:\progra~1\tcl ++# ++# Building for Win64 ++# c:\tcl_src\win\>c:\progra~1\micros~1\vc98\bin\vcvars32.bat ++# Setting environment for using Microsoft Visual C++ tools. ++# c:\tcl_src\win\>c:\progra~1\platfo~1\setenv.bat /pre64 /RETAIL ++# Targeting Windows pre64 RETAIL ++# c:\tcl_src\win\>nmake -f makefile.vc MACHINE=IA64 ++# ++#------------------------------------------------------------------------------ ++#============================================================================== ++############################################################################### ++#------------------------------------------------------------------------------ ++ ++!if !exist("makefile.vc") ++MSG = ^ ++You must run this makefile only from the directory it is in.^ ++Please `cd` to its location first. ++!error $(MSG) ++!endif ++ ++#------------------------------------------------------------------------- ++# Project specific information (EDIT) ++# ++# You should edit this with the name and version of your project. This ++# information is used to generate the name of the package library and ++# it's install location. ++# ++# For example, the sample extension is going to build sample04.dll and ++# would install it into $(INSTALLDIR)\lib\sample04 ++# ++# You need to specify the object files that need to be linked into your ++# binary here. ++# ++#------------------------------------------------------------------------- ++ ++PROJECT = sqlite3 ++!include "rules.vc" ++ ++# nmakehelp -V <file> <tag> will search the file for tag, skips until a ++# number and returns all character until a character not in [0-9.ab] ++# is read. ++ ++!if [echo REM = This file is generated from Makefile.vc > versions.vc] ++!endif ++# get project version from row "AC_INIT([sqlite], [3.7.14])" ++!if [echo DOTVERSION = \>> versions.vc] \ ++ && [nmakehlp -V ..\configure.in AC_INIT >> versions.vc] ++!endif ++!include "versions.vc" ++ ++VERSION = $(DOTVERSION:.=) ++STUBPREFIX = $(PROJECT)stub ++ ++DLLOBJS = \ ++ $(TMP_DIR)\tclsqlite3.obj ++ ++#------------------------------------------------------------------------- ++# Target names and paths ( shouldn't need changing ) ++#------------------------------------------------------------------------- ++ ++BINROOT = . ++ROOT = .. ++ ++PRJIMPLIB = $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib ++PRJLIBNAME = $(PROJECT)$(VERSION)$(SUFX).$(EXT) ++PRJLIB = $(OUT_DIR)\$(PRJLIBNAME) ++ ++PRJSTUBLIBNAME = $(STUBPREFIX)$(VERSION).lib ++PRJSTUBLIB = $(OUT_DIR)\$(PRJSTUBLIBNAME) ++ ++### Make sure we use backslash only. ++PRJ_INSTALL_DIR = $(_INSTALLDIR)\$(PROJECT)$(DOTVERSION) ++LIB_INSTALL_DIR = $(PRJ_INSTALL_DIR) ++BIN_INSTALL_DIR = $(PRJ_INSTALL_DIR) ++DOC_INSTALL_DIR = $(PRJ_INSTALL_DIR) ++SCRIPT_INSTALL_DIR = $(PRJ_INSTALL_DIR) ++INCLUDE_INSTALL_DIR = $(_TCLDIR)\include ++ ++### The following paths CANNOT have spaces in them. ++GENERICDIR = $(ROOT)\generic ++WINDIR = $(ROOT)\win ++LIBDIR = $(ROOT)\library ++DOCDIR = $(ROOT)\doc ++TOOLSDIR = $(ROOT)\tools ++COMPATDIR = $(ROOT)\compat ++ ++#--------------------------------------------------------------------- ++# Compile flags ++#--------------------------------------------------------------------- ++ ++!if !$(DEBUG) ++!if $(OPTIMIZING) ++### This cranks the optimization level to maximize speed ++cdebug = -O2 -Op -Gs ++!else ++cdebug = ++!endif ++!else if "$(MACHINE)" == "IA64" ++### Warnings are too many, can't support warnings into errors. ++cdebug = -Z7 -Od -GZ ++!else ++cdebug = -Z7 -WX -Od -GZ ++!endif ++ ++### Declarations common to all compiler options ++cflags = -nologo -c -W3 -YX -Fp$(TMP_DIR)^\ ++ ++!if $(MSVCRT) ++!if $(DEBUG) ++crt = -MDd ++!else ++crt = -MD ++!endif ++!else ++!if $(DEBUG) ++crt = -MTd ++!else ++crt = -MT ++!endif ++!endif ++ ++INCLUDES = $(TCL_INCLUDES) -I"$(WINDIR)" -I"$(GENERICDIR)" \ ++ -I"$(ROOT)\.." ++BASE_CLFAGS = $(cflags) $(cdebug) $(crt) $(INCLUDES) \ ++ -DSQLITE_3_SUFFIX_ONLY=1 -DSQLITE_ENABLE_RTREE=1 \ ++ -DSQLITE_ENABLE_FTS3=1 -DSQLITE_OMIT_DEPRECATED=1 ++CON_CFLAGS = $(cflags) $(cdebug) $(crt) -DCONSOLE -DSQLITE_ENABLE_FTS3=1 ++TCL_CFLAGS = -DBUILD_sqlite -DUSE_TCL_STUBS \ ++ -DPACKAGE_VERSION="\"$(DOTVERSION)\"" $(BASE_CLFAGS) \ ++ $(OPTDEFINES) ++ ++#--------------------------------------------------------------------- ++# Link flags ++#--------------------------------------------------------------------- ++ ++!if $(DEBUG) ++ldebug = -debug:full -debugtype:cv ++!else ++ldebug = -release -opt:ref -opt:icf,3 ++!endif ++ ++### Declarations common to all linker options ++lflags = -nologo -machine:$(MACHINE) $(ldebug) ++ ++!if $(PROFILE) ++lflags = $(lflags) -profile ++!endif ++ ++!if $(ALIGN98_HACK) && !$(STATIC_BUILD) ++### Align sections for PE size savings. ++lflags = $(lflags) -opt:nowin98 ++!else if !$(ALIGN98_HACK) && $(STATIC_BUILD) ++### Align sections for speed in loading by choosing the virtual page size. ++lflags = $(lflags) -align:4096 ++!endif ++ ++!if $(LOIMPACT) ++lflags = $(lflags) -ws:aggressive ++!endif ++ ++dlllflags = $(lflags) -dll ++conlflags = $(lflags) -subsystem:console ++guilflags = $(lflags) -subsystem:windows ++baselibs = $(TCLSTUBLIB) ++ ++#--------------------------------------------------------------------- ++# TclTest flags ++#--------------------------------------------------------------------- ++ ++!IF "$(TESTPAT)" != "" ++TESTFLAGS = $(TESTFLAGS) -file $(TESTPAT) ++!ENDIF ++ ++#--------------------------------------------------------------------- ++# Project specific targets (EDIT) ++#--------------------------------------------------------------------- ++ ++all: setup $(PROJECT) ++$(PROJECT): setup $(PRJLIB) ++install: install-binaries install-libraries install-docs ++ ++# Tests need to ensure we load the right dll file we ++# have to handle the output differently on Win9x. ++# ++!if "$(OS)" == "Windows_NT" || "$(MSVCDIR)" == "IDE" ++test: setup $(PROJECT) ++ set TCL_LIBRARY=$(ROOT)/library ++ $(TCLSH) << ++load $(PRJLIB:\=/) ++cd "$(ROOT)/tests" ++set argv "$(TESTFLAGS)" ++source all.tcl ++<< ++!else ++test: setup $(PROJECT) ++ echo Please wait while the test results are collected ++ set TCL_LIBRARY=$(ROOT)/library ++ $(TCLSH) << >tests.log ++load $(PRJLIB:\=/) ++cd "$(ROOT)/tests" ++set argv "$(TESTFLAGS)" ++source all.tcl ++<< ++ type tests.log | more ++!endif ++ ++setup: ++ @if not exist $(OUT_DIR)\nul mkdir $(OUT_DIR) ++ @if not exist $(TMP_DIR)\nul mkdir $(TMP_DIR) ++ ++$(PRJLIB): $(DLLOBJS) ++ $(link32) $(dlllflags) -out:$@ $(baselibs) @<< ++$** ++<< ++ -@del $*.exp ++ ++$(PRJSTUBLIB): $(PRJSTUBOBJS) ++ $(lib32) -nologo -out:$@ $(PRJSTUBOBJS) ++ ++#--------------------------------------------------------------------- ++# Implicit rules ++#--------------------------------------------------------------------- ++ ++{$(WINDIR)}.c{$(TMP_DIR)}.obj:: ++ $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<< ++$< ++<< ++ ++{$(GENERICDIR)}.c{$(TMP_DIR)}.obj:: ++ $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<< ++$< ++<< ++ ++{$(COMPATDIR)}.c{$(TMP_DIR)}.obj:: ++ $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<< ++$< ++<< ++ ++{$(WINDIR)}.rc{$(TMP_DIR)}.res: ++ $(rc32) -fo $@ -r -i "$(GENERICDIR)" -D__WIN32__ \ ++!if $(DEBUG) ++ -d DEBUG \ ++!endif ++!if $(TCL_THREADS) ++ -d TCL_THREADS \ ++!endif ++!if $(STATIC_BUILD) ++ -d STATIC_BUILD \ ++!endif ++ $< ++ ++.SUFFIXES: ++.SUFFIXES:.c .rc ++ ++#--------------------------------------------------------------------- ++# Installation. (EDIT) ++# ++# You may need to modify this section to reflect the final distribution ++# of your files and possibly to generate documentation. ++# ++#--------------------------------------------------------------------- ++ ++install-binaries: ++ @echo Installing binaries to '$(SCRIPT_INSTALL_DIR)' ++ @if not exist "$(SCRIPT_INSTALL_DIR)" mkdir "$(SCRIPT_INSTALL_DIR)" ++ @$(CPY) $(PRJLIB) "$(SCRIPT_INSTALL_DIR)" >NUL ++ ++install-libraries: ++ @echo Installing libraries to '$(SCRIPT_INSTALL_DIR)' ++ @if exist $(LIBDIR) $(CPY) $(LIBDIR)\*.tcl "$(SCRIPT_INSTALL_DIR)" ++ @echo Installing package index in '$(SCRIPT_INSTALL_DIR)' ++ @type << >"$(SCRIPT_INSTALL_DIR)\pkgIndex.tcl" ++package ifneeded $(PROJECT) $(DOTVERSION) \ ++ [list load [file join $$dir $(PRJLIBNAME)] sqlite3] ++<< ++ ++install-docs: ++ @echo Installing documentation files to '$(DOC_INSTALL_DIR)' ++ @if exist $(DOCDIR) $(CPY) $(DOCDIR)\*.n "$(DOC_INSTALL_DIR)" ++ ++#--------------------------------------------------------------------- ++# Clean up ++#--------------------------------------------------------------------- ++ ++clean: ++ @if exist $(TMP_DIR)\nul $(RMDIR) $(TMP_DIR) ++ @if exist $(WINDIR)\version.vc del $(WINDIR)\version.vc ++ ++realclean: clean ++ @if exist $(OUT_DIR)\nul $(RMDIR) $(OUT_DIR) ++ ++distclean: realclean ++ @if exist $(WINDIR)\nmakehlp.exe del $(WINDIR)\nmakehlp.exe ++ @if exist $(WINDIR)\nmakehlp.obj del $(WINDIR)\nmakehlp.obj +--- contrib/sqlite3/tea/win/nmakehlp.c.orig ++++ contrib/sqlite3/tea/win/nmakehlp.c +@@ -0,0 +1,694 @@ ++/* ++ * ---------------------------------------------------------------------------- ++ * nmakehlp.c -- ++ * ++ * This is used to fix limitations within nmake and the environment. ++ * ++ * Copyright (c) 2002 by David Gravereaux. ++ * Copyright (c) 2006 by Pat Thoyts ++ * ++ * See the file "license.terms" for information on usage and redistribution of ++ * this file, and for a DISCLAIMER OF ALL WARRANTIES. ++ * ---------------------------------------------------------------------------- ++ */ ++ ++#define _CRT_SECURE_NO_DEPRECATE ++#include <windows.h> ++#define NO_SHLWAPI_GDI ++#define NO_SHLWAPI_STREAM ++#define NO_SHLWAPI_REG ++#include <shlwapi.h> ++#pragma comment (lib, "user32.lib") ++#pragma comment (lib, "kernel32.lib") ++#pragma comment (lib, "shlwapi.lib") ++#include <stdio.h> ++#include <math.h> ++ ++/* ++ * This library is required for x64 builds with _some_ versions of MSVC ++ */ ++#if defined(_M_IA64) || defined(_M_AMD64) ++#if _MSC_VER >= 1400 && _MSC_VER < 1500 ++#pragma comment(lib, "bufferoverflowU") ++#endif ++#endif ++ ++/* ISO hack for dumb VC++ */ ++#ifdef _MSC_VER ++#define snprintf _snprintf ++#endif ++ ++ ++ ++/* protos */ ++ ++static int CheckForCompilerFeature(const char *option); ++static int CheckForLinkerFeature(const char *option); ++static int IsIn(const char *string, const char *substring); ++static int SubstituteFile(const char *substs, const char *filename); ++static int QualifyPath(const char *path); ++static const char *GetVersionFromFile(const char *filename, const char *match); ++static DWORD WINAPI ReadFromPipe(LPVOID args); ++ ++/* globals */ ++ ++#define CHUNK 25 ++#define STATICBUFFERSIZE 1000 ++typedef struct { ++ HANDLE pipe; ++ char buffer[STATICBUFFERSIZE]; ++} pipeinfo; ++ ++pipeinfo Out = {INVALID_HANDLE_VALUE, '\0'}; ++pipeinfo Err = {INVALID_HANDLE_VALUE, '\0'}; ++ ++/* ++ * exitcodes: 0 == no, 1 == yes, 2 == error ++ */ ++ ++int ++main( ++ int argc, ++ char *argv[]) ++{ ++ char msg[300]; ++ DWORD dwWritten; ++ int chars; ++ ++ /* ++ * Make sure children (cl.exe and link.exe) are kept quiet. ++ */ ++ ++ SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); ++ ++ /* ++ * Make sure the compiler and linker aren't effected by the outside world. ++ */ ++ ++ SetEnvironmentVariable("CL", ""); ++ SetEnvironmentVariable("LINK", ""); ++ ++ if (argc > 1 && *argv[1] == '-') { ++ switch (*(argv[1]+1)) { ++ case 'c': ++ if (argc != 3) { ++ chars = snprintf(msg, sizeof(msg) - 1, ++ "usage: %s -c <compiler option>\n" ++ "Tests for whether cl.exe supports an option\n" ++ "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); ++ WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, ++ &dwWritten, NULL); ++ return 2; ++ } ++ return CheckForCompilerFeature(argv[2]); ++ case 'l': ++ if (argc != 3) { ++ chars = snprintf(msg, sizeof(msg) - 1, ++ "usage: %s -l <linker option>\n" ++ "Tests for whether link.exe supports an option\n" ++ "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); ++ WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, ++ &dwWritten, NULL); ++ return 2; ++ } ++ return CheckForLinkerFeature(argv[2]); ++ case 'f': ++ if (argc == 2) { ++ chars = snprintf(msg, sizeof(msg) - 1, ++ "usage: %s -f <string> <substring>\n" ++ "Find a substring within another\n" ++ "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); ++ WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, ++ &dwWritten, NULL); ++ return 2; ++ } else if (argc == 3) { ++ /* ++ * If the string is blank, there is no match. ++ */ ++ ++ return 0; ++ } else { ++ return IsIn(argv[2], argv[3]); ++ } ++ case 's': ++ if (argc == 2) { ++ chars = snprintf(msg, sizeof(msg) - 1, ++ "usage: %s -s <substitutions file> <file>\n" ++ "Perform a set of string map type substutitions on a file\n" ++ "exitcodes: 0\n", ++ argv[0]); ++ WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, ++ &dwWritten, NULL); ++ return 2; ++ } ++ return SubstituteFile(argv[2], argv[3]); ++ case 'V': ++ if (argc != 4) { ++ chars = snprintf(msg, sizeof(msg) - 1, ++ "usage: %s -V filename matchstring\n" ++ "Extract a version from a file:\n" ++ "eg: pkgIndex.tcl \"package ifneeded http\"", ++ argv[0]); ++ WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, ++ &dwWritten, NULL); ++ return 0; ++ } ++ printf("%s\n", GetVersionFromFile(argv[2], argv[3])); ++ return 0; ++ case 'Q': ++ if (argc != 3) { ++ chars = snprintf(msg, sizeof(msg) - 1, ++ "usage: %s -Q path\n" ++ "Emit the fully qualified path\n" ++ "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); ++ WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, ++ &dwWritten, NULL); ++ return 2; ++ } ++ return QualifyPath(argv[2]); ++ } ++ } ++ chars = snprintf(msg, sizeof(msg) - 1, ++ "usage: %s -c|-f|-l|-Q|-s|-V ...\n" ++ "This is a little helper app to equalize shell differences between WinNT and\n" ++ "Win9x and get nmake.exe to accomplish its job.\n", ++ argv[0]); ++ WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); ++ return 2; ++} ++ ++static int ++CheckForCompilerFeature( ++ const char *option) ++{ ++ STARTUPINFO si; ++ PROCESS_INFORMATION pi; ++ SECURITY_ATTRIBUTES sa; ++ DWORD threadID; ++ char msg[300]; ++ BOOL ok; ++ HANDLE hProcess, h, pipeThreads[2]; ++ char cmdline[100]; ++ ++ hProcess = GetCurrentProcess(); ++ ++ ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); ++ ZeroMemory(&si, sizeof(STARTUPINFO)); ++ si.cb = sizeof(STARTUPINFO); ++ si.dwFlags = STARTF_USESTDHANDLES; ++ si.hStdInput = INVALID_HANDLE_VALUE; ++ ++ ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); ++ sa.nLength = sizeof(SECURITY_ATTRIBUTES); ++ sa.lpSecurityDescriptor = NULL; ++ sa.bInheritHandle = FALSE; ++ ++ /* ++ * Create a non-inheritible pipe. ++ */ ++ ++ CreatePipe(&Out.pipe, &h, &sa, 0); ++ ++ /* ++ * Dupe the write side, make it inheritible, and close the original. ++ */ ++ ++ DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE, ++ DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); ++ ++ /* ++ * Same as above, but for the error side. ++ */ ++ ++ CreatePipe(&Err.pipe, &h, &sa, 0); ++ DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE, ++ DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); ++ ++ /* ++ * Base command line. ++ */ ++ ++ lstrcpy(cmdline, "cl.exe -nologo -c -TC -Zs -X -Fp.\\_junk.pch "); ++ ++ /* ++ * Append our option for testing ++ */ ++ ++ lstrcat(cmdline, option); ++ ++ /* ++ * Filename to compile, which exists, but is nothing and empty. ++ */ ++ ++ lstrcat(cmdline, " .\\nul"); ++ ++ ok = CreateProcess( ++ NULL, /* Module name. */ ++ cmdline, /* Command line. */ ++ NULL, /* Process handle not inheritable. */ ++ NULL, /* Thread handle not inheritable. */ ++ TRUE, /* yes, inherit handles. */ ++ DETACHED_PROCESS, /* No console for you. */ ++ NULL, /* Use parent's environment block. */ ++ NULL, /* Use parent's starting directory. */ ++ &si, /* Pointer to STARTUPINFO structure. */ ++ &pi); /* Pointer to PROCESS_INFORMATION structure. */ ++ ++ if (!ok) { ++ DWORD err = GetLastError(); ++ int chars = snprintf(msg, sizeof(msg) - 1, ++ "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err); ++ ++ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS| ++ FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars], ++ (300-chars), 0); ++ WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL); ++ return 2; ++ } ++ ++ /* ++ * Close our references to the write handles that have now been inherited. ++ */ ++ ++ CloseHandle(si.hStdOutput); ++ CloseHandle(si.hStdError); ++ ++ WaitForInputIdle(pi.hProcess, 5000); ++ CloseHandle(pi.hThread); ++ ++ /* ++ * Start the pipe reader threads. ++ */ ++ ++ pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID); ++ pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID); ++ ++ /* ++ * Block waiting for the process to end. ++ */ ++ ++ WaitForSingleObject(pi.hProcess, INFINITE); ++ CloseHandle(pi.hProcess); ++ ++ /* ++ * Wait for our pipe to get done reading, should it be a little slow. ++ */ ++ ++ WaitForMultipleObjects(2, pipeThreads, TRUE, 500); ++ CloseHandle(pipeThreads[0]); ++ CloseHandle(pipeThreads[1]); ++ ++ /* ++ * Look for the commandline warning code in both streams. ++ * - in MSVC 6 & 7 we get D4002, in MSVC 8 we get D9002. ++ */ ++ ++ return !(strstr(Out.buffer, "D4002") != NULL ++ || strstr(Err.buffer, "D4002") != NULL ++ || strstr(Out.buffer, "D9002") != NULL ++ || strstr(Err.buffer, "D9002") != NULL ++ || strstr(Out.buffer, "D2021") != NULL ++ || strstr(Err.buffer, "D2021") != NULL); ++} ++ ++static int ++CheckForLinkerFeature( ++ const char *option) ++{ ++ STARTUPINFO si; ++ PROCESS_INFORMATION pi; ++ SECURITY_ATTRIBUTES sa; ++ DWORD threadID; ++ char msg[300]; ++ BOOL ok; ++ HANDLE hProcess, h, pipeThreads[2]; ++ char cmdline[100]; ++ ++ hProcess = GetCurrentProcess(); ++ ++ ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); ++ ZeroMemory(&si, sizeof(STARTUPINFO)); ++ si.cb = sizeof(STARTUPINFO); ++ si.dwFlags = STARTF_USESTDHANDLES; ++ si.hStdInput = INVALID_HANDLE_VALUE; ++ ++ ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); ++ sa.nLength = sizeof(SECURITY_ATTRIBUTES); ++ sa.lpSecurityDescriptor = NULL; ++ sa.bInheritHandle = TRUE; ++ ++ /* ++ * Create a non-inheritible pipe. ++ */ ++ ++ CreatePipe(&Out.pipe, &h, &sa, 0); ++ ++ /* ++ * Dupe the write side, make it inheritible, and close the original. ++ */ ++ ++ DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE, ++ DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); ++ ++ /* ++ * Same as above, but for the error side. ++ */ ++ ++ CreatePipe(&Err.pipe, &h, &sa, 0); ++ DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE, ++ DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); ++ ++ /* ++ * Base command line. ++ */ ++ ++ lstrcpy(cmdline, "link.exe -nologo "); ++ ++ /* ++ * Append our option for testing. ++ */ ++ ++ lstrcat(cmdline, option); ++ ++ ok = CreateProcess( ++ NULL, /* Module name. */ ++ cmdline, /* Command line. */ ++ NULL, /* Process handle not inheritable. */ ++ NULL, /* Thread handle not inheritable. */ ++ TRUE, /* yes, inherit handles. */ ++ DETACHED_PROCESS, /* No console for you. */ ++ NULL, /* Use parent's environment block. */ ++ NULL, /* Use parent's starting directory. */ ++ &si, /* Pointer to STARTUPINFO structure. */ ++ &pi); /* Pointer to PROCESS_INFORMATION structure. */ ++ ++ if (!ok) { ++ DWORD err = GetLastError(); ++ int chars = snprintf(msg, sizeof(msg) - 1, ++ "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err); ++ ++ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS| ++ FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars], ++ (300-chars), 0); ++ WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL); ++ return 2; ++ } ++ ++ /* ++ * Close our references to the write handles that have now been inherited. ++ */ ++ ++ CloseHandle(si.hStdOutput); ++ CloseHandle(si.hStdError); ++ ++ WaitForInputIdle(pi.hProcess, 5000); ++ CloseHandle(pi.hThread); ++ ++ /* ++ * Start the pipe reader threads. ++ */ ++ ++ pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID); ++ pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID); ++ ++ /* ++ * Block waiting for the process to end. ++ */ ++ ++ WaitForSingleObject(pi.hProcess, INFINITE); ++ CloseHandle(pi.hProcess); ++ ++ /* ++ * Wait for our pipe to get done reading, should it be a little slow. ++ */ ++ ++ WaitForMultipleObjects(2, pipeThreads, TRUE, 500); ++ CloseHandle(pipeThreads[0]); ++ CloseHandle(pipeThreads[1]); ++ ++ /* ++ * Look for the commandline warning code in the stderr stream. ++ */ ++ ++ return !(strstr(Out.buffer, "LNK1117") != NULL || ++ strstr(Err.buffer, "LNK1117") != NULL || ++ strstr(Out.buffer, "LNK4044") != NULL || ++ strstr(Err.buffer, "LNK4044") != NULL); ++} ++ ++static DWORD WINAPI ++ReadFromPipe( ++ LPVOID args) ++{ ++ pipeinfo *pi = (pipeinfo *) args; ++ char *lastBuf = pi->buffer; ++ DWORD dwRead; ++ BOOL ok; ++ ++ again: ++ if (lastBuf - pi->buffer + CHUNK > STATICBUFFERSIZE) { ++ CloseHandle(pi->pipe); ++ return (DWORD)-1; ++ } ++ ok = ReadFile(pi->pipe, lastBuf, CHUNK, &dwRead, 0L); ++ if (!ok || dwRead == 0) { ++ CloseHandle(pi->pipe); ++ return 0; ++ } ++ lastBuf += dwRead; ++ goto again; ++ ++ return 0; /* makes the compiler happy */ ++} ++ ++static int ++IsIn( ++ const char *string, ++ const char *substring) ++{ ++ return (strstr(string, substring) != NULL); ++} ++ ++/* ++ * GetVersionFromFile -- ++ * Looks for a match string in a file and then returns the version ++ * following the match where a version is anything acceptable to ++ * package provide or package ifneeded. ++ */ ++ ++static const char * ++GetVersionFromFile( ++ const char *filename, ++ const char *match) ++{ ++ size_t cbBuffer = 100; ++ static char szBuffer[100]; ++ char *szResult = NULL; ++ FILE *fp = fopen(filename, "rt"); ++ ++ if (fp != NULL) { ++ /* ++ * Read data until we see our match string. ++ */ ++ ++ while (fgets(szBuffer, cbBuffer, fp) != NULL) { ++ LPSTR p, q; ++ ++ p = strstr(szBuffer, match); ++ if (p != NULL) { ++ /* ++ * Skip to first digit. ++ */ ++ ++ while (*p && !isdigit(*p)) { ++ ++p; ++ } ++ ++ /* ++ * Find ending whitespace. ++ */ ++ ++ q = p; ++ while (*q && (isalnum(*q) || *q == '.')) { ++ ++q; ++ } ++ ++ memcpy(szBuffer, p, q - p); ++ szBuffer[q-p] = 0; ++ szResult = szBuffer; ++ break; ++ } ++ } ++ fclose(fp); ++ } ++ return szResult; ++} ++ ++/* ++ * List helpers for the SubstituteFile function ++ */ ++ ++typedef struct list_item_t { ++ struct list_item_t *nextPtr; ++ char * key; ++ char * value; ++} list_item_t; ++ ++/* insert a list item into the list (list may be null) */ ++static list_item_t * ++list_insert(list_item_t **listPtrPtr, const char *key, const char *value) ++{ ++ list_item_t *itemPtr = malloc(sizeof(list_item_t)); ++ if (itemPtr) { ++ itemPtr->key = strdup(key); ++ itemPtr->value = strdup(value); ++ itemPtr->nextPtr = NULL; ++ ++ while(*listPtrPtr) { ++ listPtrPtr = &(*listPtrPtr)->nextPtr; ++ } ++ *listPtrPtr = itemPtr; ++ } ++ return itemPtr; ++} ++ ++static void ++list_free(list_item_t **listPtrPtr) ++{ ++ list_item_t *tmpPtr, *listPtr = *listPtrPtr; ++ while (listPtr) { ++ tmpPtr = listPtr; ++ listPtr = listPtr->nextPtr; ++ free(tmpPtr->key); ++ free(tmpPtr->value); ++ free(tmpPtr); ++ } ++} ++ ++/* ++ * SubstituteFile -- ++ * As windows doesn't provide anything useful like sed and it's unreliable ++ * to use the tclsh you are building against (consider x-platform builds - ++ * eg compiling AMD64 target from IX86) we provide a simple substitution ++ * option here to handle autoconf style substitutions. ++ * The substitution file is whitespace and line delimited. The file should ++ * consist of lines matching the regular expression: ++ * \s*\S+\s+\S*$ ++ * ++ * Usage is something like: ++ * nmakehlp -S << $** > $@ ++ * @PACKAGE_NAME@ $(PACKAGE_NAME) ++ * @PACKAGE_VERSION@ $(PACKAGE_VERSION) ++ * << ++ */ ++ ++static int ++SubstituteFile( ++ const char *substitutions, ++ const char *filename) ++{ ++ size_t cbBuffer = 1024; ++ static char szBuffer[1024], szCopy[1024]; ++ char *szResult = NULL; ++ list_item_t *substPtr = NULL; ++ FILE *fp, *sp; ++ ++ fp = fopen(filename, "rt"); ++ if (fp != NULL) { ++ ++ /* ++ * Build a list of substutitions from the first filename ++ */ ++ ++ sp = fopen(substitutions, "rt"); ++ if (sp != NULL) { ++ while (fgets(szBuffer, cbBuffer, sp) != NULL) { ++ unsigned char *ks, *ke, *vs, *ve; ++ ks = (unsigned char*)szBuffer; ++ while (ks && *ks && isspace(*ks)) ++ks; ++ ke = ks; ++ while (ke && *ke && !isspace(*ke)) ++ke; ++ vs = ke; ++ while (vs && *vs && isspace(*vs)) ++vs; ++ ve = vs; ++ while (ve && *ve && !(*ve == '\r' || *ve == '\n')) ++ve; ++ *ke = 0, *ve = 0; ++ list_insert(&substPtr, (char*)ks, (char*)vs); ++ } ++ fclose(sp); ++ } ++ ++ /* debug: dump the list */ ++#ifdef _DEBUG ++ { ++ int n = 0; ++ list_item_t *p = NULL; ++ for (p = substPtr; p != NULL; p = p->nextPtr, ++n) { ++ fprintf(stderr, "% 3d '%s' => '%s'\n", n, p->key, p->value); ++ } ++ } ++#endif ++ ++ /* ++ * Run the substitutions over each line of the input ++ */ ++ ++ while (fgets(szBuffer, cbBuffer, fp) != NULL) { ++ list_item_t *p = NULL; ++ for (p = substPtr; p != NULL; p = p->nextPtr) { ++ char *m = strstr(szBuffer, p->key); ++ if (m) { ++ char *cp, *op, *sp; ++ cp = szCopy; ++ op = szBuffer; ++ while (op != m) *cp++ = *op++; ++ sp = p->value; ++ while (sp && *sp) *cp++ = *sp++; ++ op += strlen(p->key); ++ while (*op) *cp++ = *op++; ++ *cp = 0; ++ memcpy(szBuffer, szCopy, sizeof(szCopy)); ++ } ++ } ++ printf(szBuffer); ++ } ++ ++ list_free(&substPtr); ++ } ++ fclose(fp); ++ return 0; ++} ++ ++/* ++ * QualifyPath -- ++ * ++ * This composes the current working directory with a provided path ++ * and returns the fully qualified and normalized path. ++ * Mostly needed to setup paths for testing. ++ */ ++ ++static int ++QualifyPath( ++ const char *szPath) ++{ ++ char szCwd[MAX_PATH + 1]; ++ char szTmp[MAX_PATH + 1]; ++ char *p; ++ GetCurrentDirectory(MAX_PATH, szCwd); ++ while ((p = strchr(szPath, '/')) && *p) ++ *p = '\\'; ++ PathCombine(szTmp, szCwd, szPath); ++ PathCanonicalize(szCwd, szTmp); ++ printf("%s\n", szCwd); ++ return 0; ++} ++ ++/* ++ * Local variables: ++ * mode: c ++ * c-basic-offset: 4 ++ * fill-column: 78 ++ * indent-tabs-mode: t ++ * tab-width: 8 ++ * End: ++ */ +--- contrib/sqlite3/tea/win/rules.vc.orig ++++ contrib/sqlite3/tea/win/rules.vc +@@ -0,0 +1,711 @@ ++#------------------------------------------------------------------------------ ++# rules.vc -- ++# ++# Microsoft Visual C++ makefile include for decoding the commandline ++# macros. This file does not need editing to build Tcl. ++# ++# See the file "license.terms" for information on usage and redistribution ++# of this file, and for a DISCLAIMER OF ALL WARRANTIES. ++# ++# Copyright (c) 2001-2003 David Gravereaux. ++# Copyright (c) 2003-2008 Patrick Thoyts ++#------------------------------------------------------------------------------ ++ ++!ifndef _RULES_VC ++_RULES_VC = 1 ++ ++cc32 = $(CC) # built-in default. ++link32 = link ++lib32 = lib ++rc32 = $(RC) # built-in default. ++ ++!ifndef INSTALLDIR ++### Assume the normal default. ++_INSTALLDIR = C:\Program Files\Tcl ++!else ++### Fix the path separators. ++_INSTALLDIR = $(INSTALLDIR:/=\) ++!endif ++ ++#---------------------------------------------------------- ++# Set the proper copy method to avoid overwrite questions ++# to the user when copying files and selecting the right ++# "delete all" method. ++#---------------------------------------------------------- ++ ++!if "$(OS)" == "Windows_NT" ++RMDIR = rmdir /S /Q ++ERRNULL = 2>NUL ++!if ![ver | find "4.0" > nul] ++CPY = echo y | xcopy /i >NUL ++COPY = copy >NUL ++!else ++CPY = xcopy /i /y >NUL ++COPY = copy /y >NUL ++!endif ++!else # "$(OS)" != "Windows_NT" ++CPY = xcopy /i >_JUNK.OUT # On Win98 NUL does not work here. ++COPY = copy >_JUNK.OUT # On Win98 NUL does not work here. ++RMDIR = deltree /Y ++NULL = \NUL # Used in testing directory existence ++ERRNULL = >NUL # Win9x shell cannot redirect stderr ++!endif ++MKDIR = mkdir ++ ++#------------------------------------------------------------------------------ ++# Determine the host and target architectures and compiler version. ++#------------------------------------------------------------------------------ ++ ++_HASH=^# ++_VC_MANIFEST_EMBED_EXE= ++_VC_MANIFEST_EMBED_DLL= ++VCVER=0 ++!if ![echo VCVERSION=_MSC_VER > vercl.x] \ ++ && ![echo $(_HASH)if defined(_M_IX86) >> vercl.x] \ ++ && ![echo ARCH=IX86 >> vercl.x] \ ++ && ![echo $(_HASH)elif defined(_M_AMD64) >> vercl.x] \ ++ && ![echo ARCH=AMD64 >> vercl.x] \ ++ && ![echo $(_HASH)endif >> vercl.x] \ ++ && ![cl -nologo -TC -P vercl.x $(ERRNULL)] ++!include vercl.i ++!if ![echo VCVER= ^\> vercl.vc] \ ++ && ![set /a $(VCVERSION) / 100 - 6 >> vercl.vc] ++!include vercl.vc ++!endif ++!endif ++!if ![del $(ERRNUL) /q/f vercl.x vercl.i vercl.vc] ++!endif ++ ++!if ![reg query HKLM\Hardware\Description\System\CentralProcessor\0 /v Identifier | findstr /i x86] ++NATIVE_ARCH=IX86 ++!else ++NATIVE_ARCH=AMD64 ++!endif ++ ++# Since MSVC8 we must deal with manifest resources. ++!if $(VCVERSION) >= 1400 ++_VC_MANIFEST_EMBED_EXE=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;1 ++_VC_MANIFEST_EMBED_DLL=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;2 ++!endif ++ ++!ifndef MACHINE ++MACHINE=$(ARCH) ++!endif ++ ++!ifndef CFG_ENCODING ++CFG_ENCODING = \"cp1252\" ++!endif ++ ++!message =============================================================================== ++ ++#---------------------------------------------------------- ++# build the helper app we need to overcome nmake's limiting ++# environment. ++#---------------------------------------------------------- ++ ++!if !exist(nmakehlp.exe) ++!if [$(cc32) -nologo nmakehlp.c -link -subsystem:console > nul] ++!endif ++!endif ++ ++#---------------------------------------------------------- ++# Test for compiler features ++#---------------------------------------------------------- ++ ++### test for optimizations ++!if [nmakehlp -c -Ot] ++!message *** Compiler has 'Optimizations' ++OPTIMIZING = 1 ++!else ++!message *** Compiler does not have 'Optimizations' ++OPTIMIZING = 0 ++!endif ++ ++OPTIMIZATIONS = ++ ++!if [nmakehlp -c -Ot] ++OPTIMIZATIONS = $(OPTIMIZATIONS) -Ot ++!endif ++ ++!if [nmakehlp -c -Oi] ++OPTIMIZATIONS = $(OPTIMIZATIONS) -Oi ++!endif ++ ++!if [nmakehlp -c -Op] ++OPTIMIZATIONS = $(OPTIMIZATIONS) -Op ++!endif ++ ++!if [nmakehlp -c -fp:strict] ++OPTIMIZATIONS = $(OPTIMIZATIONS) -fp:strict ++!endif ++ ++!if [nmakehlp -c -Gs] ++OPTIMIZATIONS = $(OPTIMIZATIONS) -Gs ++!endif ++ ++!if [nmakehlp -c -GS] ++OPTIMIZATIONS = $(OPTIMIZATIONS) -GS ++!endif ++ ++!if [nmakehlp -c -GL] ++OPTIMIZATIONS = $(OPTIMIZATIONS) -GL ++!endif ++ ++DEBUGFLAGS = ++ ++!if [nmakehlp -c -RTC1] ++DEBUGFLAGS = $(DEBUGFLAGS) -RTC1 ++!elseif [nmakehlp -c -GZ] ++DEBUGFLAGS = $(DEBUGFLAGS) -GZ ++!endif ++ ++COMPILERFLAGS =-W3 -DUNICODE -D_UNICODE ++ ++# In v13 -GL and -YX are incompatible. ++!if [nmakehlp -c -YX] ++!if ![nmakehlp -c -GL] ++OPTIMIZATIONS = $(OPTIMIZATIONS) -YX ++!endif ++!endif ++ ++!if "$(MACHINE)" == "IX86" ++### test for pentium errata ++!if [nmakehlp -c -QI0f] ++!message *** Compiler has 'Pentium 0x0f fix' ++COMPILERFLAGS = $(COMPILERFLAGS) -QI0f ++!else ++!message *** Compiler does not have 'Pentium 0x0f fix' ++!endif ++!endif ++ ++!if "$(MACHINE)" == "IA64" ++### test for Itanium errata ++!if [nmakehlp -c -QIA64_Bx] ++!message *** Compiler has 'B-stepping errata workarounds' ++COMPILERFLAGS = $(COMPILERFLAGS) -QIA64_Bx ++!else ++!message *** Compiler does not have 'B-stepping errata workarounds' ++!endif ++!endif ++ ++!if "$(MACHINE)" == "IX86" ++### test for -align:4096, when align:512 will do. ++!if [nmakehlp -l -opt:nowin98] ++!message *** Linker has 'Win98 alignment problem' ++ALIGN98_HACK = 1 ++!else ++!message *** Linker does not have 'Win98 alignment problem' ++ALIGN98_HACK = 0 ++!endif ++!else ++ALIGN98_HACK = 0 ++!endif ++ ++LINKERFLAGS = ++ ++!if [nmakehlp -l -ltcg] ++LINKERFLAGS =-ltcg ++!endif ++ ++#---------------------------------------------------------- ++# Decode the options requested. ++#---------------------------------------------------------- ++ ++!if "$(OPTS)" == "" || [nmakehlp -f "$(OPTS)" "none"] ++STATIC_BUILD = 0 ++TCL_THREADS = 1 ++DEBUG = 0 ++SYMBOLS = 0 ++PROFILE = 0 ++PGO = 0 ++MSVCRT = 0 ++LOIMPACT = 0 ++TCL_USE_STATIC_PACKAGES = 0 ++USE_THREAD_ALLOC = 1 ++UNCHECKED = 0 ++!else ++!if [nmakehlp -f $(OPTS) "static"] ++!message *** Doing static ++STATIC_BUILD = 1 ++!else ++STATIC_BUILD = 0 ++!endif ++!if [nmakehlp -f $(OPTS) "msvcrt"] ++!message *** Doing msvcrt ++MSVCRT = 1 ++!else ++MSVCRT = 0 ++!endif ++!if [nmakehlp -f $(OPTS) "staticpkg"] ++!message *** Doing staticpkg ++TCL_USE_STATIC_PACKAGES = 1 ++!else ++TCL_USE_STATIC_PACKAGES = 0 ++!endif ++!if [nmakehlp -f $(OPTS) "nothreads"] ++!message *** Compile explicitly for non-threaded tcl ++TCL_THREADS = 0 ++!else ++TCL_THREADS = 1 ++USE_THREAD_ALLOC= 1 ++!endif ++!if [nmakehlp -f $(OPTS) "symbols"] ++!message *** Doing symbols ++DEBUG = 1 ++!else ++DEBUG = 0 ++!endif ++!if [nmakehlp -f $(OPTS) "pdbs"] ++!message *** Doing pdbs ++SYMBOLS = 1 ++!else ++SYMBOLS = 0 ++!endif ++!if [nmakehlp -f $(OPTS) "profile"] ++!message *** Doing profile ++PROFILE = 1 ++!else ++PROFILE = 0 ++!endif ++!if [nmakehlp -f $(OPTS) "pgi"] ++!message *** Doing profile guided optimization instrumentation ++PGO = 1 ++!elseif [nmakehlp -f $(OPTS) "pgo"] ++!message *** Doing profile guided optimization ++PGO = 2 ++!else ++PGO = 0 ++!endif ++!if [nmakehlp -f $(OPTS) "loimpact"] ++!message *** Doing loimpact ++LOIMPACT = 1 ++!else ++LOIMPACT = 0 ++!endif ++!if [nmakehlp -f $(OPTS) "thrdalloc"] ++!message *** Doing thrdalloc ++USE_THREAD_ALLOC = 1 ++!endif ++!if [nmakehlp -f $(OPTS) "tclalloc"] ++!message *** Doing tclalloc ++USE_THREAD_ALLOC = 0 ++!endif ++!if [nmakehlp -f $(OPTS) "unchecked"] ++!message *** Doing unchecked ++UNCHECKED = 1 ++!else ++UNCHECKED = 0 ++!endif ++!endif ++ ++ ++!if !$(STATIC_BUILD) ++# Make sure we don't build overly fat DLLs. ++MSVCRT = 1 ++# We shouldn't statically put the extensions inside the shell when dynamic. ++TCL_USE_STATIC_PACKAGES = 0 ++!endif ++ ++ ++#---------------------------------------------------------- ++# Figure-out how to name our intermediate and output directories. ++# We wouldn't want different builds to use the same .obj files ++# by accident. ++#---------------------------------------------------------- ++ ++#---------------------------------------- ++# Naming convention: ++# t = full thread support. ++# s = static library (as opposed to an ++# import library) ++# g = linked to the debug enabled C ++# run-time. ++# x = special static build when it ++# links to the dynamic C run-time. ++#---------------------------------------- ++SUFX = tsgx ++ ++!if $(DEBUG) ++BUILDDIRTOP = Debug ++!else ++BUILDDIRTOP = Release ++!endif ++ ++!if "$(MACHINE)" != "IX86" ++BUILDDIRTOP =$(BUILDDIRTOP)_$(MACHINE) ++!endif ++!if $(VCVER) > 6 ++BUILDDIRTOP =$(BUILDDIRTOP)_VC$(VCVER) ++!endif ++ ++!if !$(DEBUG) || $(DEBUG) && $(UNCHECKED) ++SUFX = $(SUFX:g=) ++!endif ++ ++TMP_DIRFULL = .\$(BUILDDIRTOP)\$(PROJECT)_ThreadedDynamicStaticX ++ ++!if !$(STATIC_BUILD) ++TMP_DIRFULL = $(TMP_DIRFULL:Static=) ++SUFX = $(SUFX:s=) ++EXT = dll ++!if $(MSVCRT) ++TMP_DIRFULL = $(TMP_DIRFULL:X=) ++SUFX = $(SUFX:x=) ++!endif ++!else ++TMP_DIRFULL = $(TMP_DIRFULL:Dynamic=) ++EXT = lib ++!if !$(MSVCRT) ++TMP_DIRFULL = $(TMP_DIRFULL:X=) ++SUFX = $(SUFX:x=) ++!endif ++!endif ++ ++!if !$(TCL_THREADS) ++TMP_DIRFULL = $(TMP_DIRFULL:Threaded=) ++SUFX = $(SUFX:t=) ++!endif ++ ++!ifndef TMP_DIR ++TMP_DIR = $(TMP_DIRFULL) ++!ifndef OUT_DIR ++OUT_DIR = .\$(BUILDDIRTOP) ++!endif ++!else ++!ifndef OUT_DIR ++OUT_DIR = $(TMP_DIR) ++!endif ++!endif ++ ++ ++#---------------------------------------------------------- ++# Decode the statistics requested. ++#---------------------------------------------------------- ++ ++!if "$(STATS)" == "" || [nmakehlp -f "$(STATS)" "none"] ++TCL_MEM_DEBUG = 0 ++TCL_COMPILE_DEBUG = 0 ++!else ++!if [nmakehlp -f $(STATS) "memdbg"] ++!message *** Doing memdbg ++TCL_MEM_DEBUG = 1 ++!else ++TCL_MEM_DEBUG = 0 ++!endif ++!if [nmakehlp -f $(STATS) "compdbg"] ++!message *** Doing compdbg ++TCL_COMPILE_DEBUG = 1 ++!else ++TCL_COMPILE_DEBUG = 0 ++!endif ++!endif ++ ++ ++#---------------------------------------------------------- ++# Decode the checks requested. ++#---------------------------------------------------------- ++ ++!if "$(CHECKS)" == "" || [nmakehlp -f "$(CHECKS)" "none"] ++TCL_NO_DEPRECATED = 0 ++WARNINGS = -W3 ++!else ++!if [nmakehlp -f $(CHECKS) "nodep"] ++!message *** Doing nodep check ++TCL_NO_DEPRECATED = 1 ++!else ++TCL_NO_DEPRECATED = 0 ++!endif ++!if [nmakehlp -f $(CHECKS) "fullwarn"] ++!message *** Doing full warnings check ++WARNINGS = -W4 ++!if [nmakehlp -l -warn:3] ++LINKERFLAGS = $(LINKERFLAGS) -warn:3 ++!endif ++!else ++WARNINGS = -W3 ++!endif ++!if [nmakehlp -f $(CHECKS) "64bit"] && [nmakehlp -c -Wp64] ++!message *** Doing 64bit portability warnings ++WARNINGS = $(WARNINGS) -Wp64 ++!endif ++!endif ++ ++!if $(PGO) > 1 ++!if [nmakehlp -l -ltcg:pgoptimize] ++LINKERFLAGS = $(LINKERFLAGS:-ltcg=) -ltcg:pgoptimize ++!else ++MSG=^ ++This compiler does not support profile guided optimization. ++!error $(MSG) ++!endif ++!elseif $(PGO) > 0 ++!if [nmakehlp -l -ltcg:pginstrument] ++LINKERFLAGS = $(LINKERFLAGS:-ltcg=) -ltcg:pginstrument ++!else ++MSG=^ ++This compiler does not support profile guided optimization. ++!error $(MSG) ++!endif ++!endif ++ ++#---------------------------------------------------------- ++# Set our defines now armed with our options. ++#---------------------------------------------------------- ++ ++OPTDEFINES = -DTCL_CFGVAL_ENCODING=$(CFG_ENCODING) -DSTDC_HEADERS ++ ++!if $(TCL_MEM_DEBUG) ++OPTDEFINES = $(OPTDEFINES) -DTCL_MEM_DEBUG ++!endif ++!if $(TCL_COMPILE_DEBUG) ++OPTDEFINES = $(OPTDEFINES) -DTCL_COMPILE_DEBUG -DTCL_COMPILE_STATS ++!endif ++!if $(TCL_THREADS) ++OPTDEFINES = $(OPTDEFINES) -DTCL_THREADS=1 ++!if $(USE_THREAD_ALLOC) ++OPTDEFINES = $(OPTDEFINES) -DUSE_THREAD_ALLOC=1 ++!endif ++!endif ++!if $(STATIC_BUILD) ++OPTDEFINES = $(OPTDEFINES) -DSTATIC_BUILD ++!endif ++!if $(TCL_NO_DEPRECATED) ++OPTDEFINES = $(OPTDEFINES) -DTCL_NO_DEPRECATED ++!endif ++ ++!if !$(DEBUG) ++OPTDEFINES = $(OPTDEFINES) -DNDEBUG ++!if $(OPTIMIZING) ++OPTDEFINES = $(OPTDEFINES) -DTCL_CFG_OPTIMIZED ++!endif ++!endif ++!if $(PROFILE) ++OPTDEFINES = $(OPTDEFINES) -DTCL_CFG_PROFILED ++!endif ++!if "$(MACHINE)" == "IA64" || "$(MACHINE)" == "AMD64" ++OPTDEFINES = $(OPTDEFINES) -DTCL_CFG_DO64BIT ++!endif ++!if $(VCVERSION) < 1300 ++OPTDEFINES = $(OPTDEFINES) -DNO_STRTOI64 ++!endif ++ ++#---------------------------------------------------------- ++# Locate the Tcl headers to build against ++#---------------------------------------------------------- ++ ++!if "$(PROJECT)" == "tcl" ++ ++_TCL_H = ..\generic\tcl.h ++ ++!else ++ ++# If INSTALLDIR set to tcl root dir then reset to the lib dir. ++!if exist("$(_INSTALLDIR)\include\tcl.h") ++_INSTALLDIR=$(_INSTALLDIR)\lib ++!endif ++ ++!if !defined(TCLDIR) ++!if exist("$(_INSTALLDIR)\..\include\tcl.h") ++TCLINSTALL = 1 ++_TCLDIR = $(_INSTALLDIR)\.. ++_TCL_H = $(_INSTALLDIR)\..\include\tcl.h ++TCLDIR = $(_INSTALLDIR)\.. ++!else ++MSG=^ ++Failed to find tcl.h. Set the TCLDIR macro. ++!error $(MSG) ++!endif ++!else ++_TCLDIR = $(TCLDIR:/=\) ++!if exist("$(_TCLDIR)\include\tcl.h") ++TCLINSTALL = 1 ++_TCL_H = $(_TCLDIR)\include\tcl.h ++!elseif exist("$(_TCLDIR)\generic\tcl.h") ++TCLINSTALL = 0 ++_TCL_H = $(_TCLDIR)\generic\tcl.h ++!else ++MSG =^ ++Failed to find tcl.h. The TCLDIR macro does not appear correct. ++!error $(MSG) ++!endif ++!endif ++!endif ++ ++#-------------------------------------------------------------- ++# Extract various version numbers from tcl headers ++# The generated file is then included in the makefile. ++#-------------------------------------------------------------- ++ ++!if [echo REM = This file is generated from rules.vc > versions.vc] ++!endif ++!if [echo TCL_MAJOR_VERSION = \>> versions.vc] \ ++ && [nmakehlp -V "$(_TCL_H)" TCL_MAJOR_VERSION >> versions.vc] ++!endif ++!if [echo TCL_MINOR_VERSION = \>> versions.vc] \ ++ && [nmakehlp -V "$(_TCL_H)" TCL_MINOR_VERSION >> versions.vc] ++!endif ++!if [echo TCL_PATCH_LEVEL = \>> versions.vc] \ ++ && [nmakehlp -V "$(_TCL_H)" TCL_PATCH_LEVEL >> versions.vc] ++!endif ++ ++# If building the tcl core then we need additional package versions ++!if "$(PROJECT)" == "tcl" ++!if [echo PKG_HTTP_VER = \>> versions.vc] \ ++ && [nmakehlp -V ..\library\http\pkgIndex.tcl http >> versions.vc] ++!endif ++!if [echo PKG_TCLTEST_VER = \>> versions.vc] \ ++ && [nmakehlp -V ..\library\tcltest\pkgIndex.tcl tcltest >> versions.vc] ++!endif ++!if [echo PKG_MSGCAT_VER = \>> versions.vc] \ ++ && [nmakehlp -V ..\library\msgcat\pkgIndex.tcl msgcat >> versions.vc] ++!endif ++!if [echo PKG_PLATFORM_VER = \>> versions.vc] \ ++ && [nmakehlp -V ..\library\platform\pkgIndex.tcl "platform " >> versions.vc] ++!endif ++!if [echo PKG_SHELL_VER = \>> versions.vc] \ ++ && [nmakehlp -V ..\library\platform\pkgIndex.tcl "platform::shell" >> versions.vc] ++!endif ++!if [echo PKG_DDE_VER = \>> versions.vc] \ ++ && [nmakehlp -V ..\library\dde\pkgIndex.tcl "dde " >> versions.vc] ++!endif ++!if [echo PKG_REG_VER =\>> versions.vc] \ ++ && [nmakehlp -V ..\library\reg\pkgIndex.tcl registry >> versions.vc] ++!endif ++!endif ++ ++!include versions.vc ++ ++#-------------------------------------------------------------- ++# Setup tcl version dependent stuff headers ++#-------------------------------------------------------------- ++ ++!if "$(PROJECT)" != "tcl" ++ ++TCL_VERSION = $(TCL_MAJOR_VERSION)$(TCL_MINOR_VERSION) ++ ++!if $(TCL_VERSION) < 81 ++TCL_DOES_STUBS = 0 ++!else ++TCL_DOES_STUBS = 1 ++!endif ++ ++!if $(TCLINSTALL) ++TCLSH = "$(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX).exe" ++!if !exist($(TCLSH)) && $(TCL_THREADS) ++TCLSH = "$(_TCLDIR)\bin\tclsh$(TCL_VERSION)t$(SUFX).exe" ++!endif ++TCLSTUBLIB = "$(_TCLDIR)\lib\tclstub$(TCL_VERSION).lib" ++TCLIMPLIB = "$(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX).lib" ++TCL_LIBRARY = $(_TCLDIR)\lib ++TCLREGLIB = "$(_TCLDIR)\lib\tclreg13$(SUFX:t=).lib" ++TCLDDELIB = "$(_TCLDIR)\lib\tcldde14$(SUFX:t=).lib" ++COFFBASE = \must\have\tcl\sources\to\build\this\target ++TCLTOOLSDIR = \must\have\tcl\sources\to\build\this\target ++TCL_INCLUDES = -I"$(_TCLDIR)\include" ++!else ++TCLSH = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX).exe" ++!if !exist($(TCLSH)) && $(TCL_THREADS) ++TCLSH = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)t$(SUFX).exe" ++!endif ++TCLSTUBLIB = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub$(TCL_VERSION).lib" ++TCLIMPLIB = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX).lib" ++TCL_LIBRARY = $(_TCLDIR)\library ++TCLREGLIB = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclreg13$(SUFX:t=).lib" ++TCLDDELIB = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcldde14$(SUFX:t=).lib" ++COFFBASE = "$(_TCLDIR)\win\coffbase.txt" ++TCLTOOLSDIR = $(_TCLDIR)\tools ++TCL_INCLUDES = -I"$(_TCLDIR)\generic" -I"$(_TCLDIR)\win" ++!endif ++ ++!endif ++ ++#------------------------------------------------------------------------- ++# Locate the Tk headers to build against ++#------------------------------------------------------------------------- ++ ++!if "$(PROJECT)" == "tk" ++_TK_H = ..\generic\tk.h ++_INSTALLDIR = $(_INSTALLDIR)\.. ++!endif ++ ++!ifdef PROJECT_REQUIRES_TK ++!if !defined(TKDIR) ++!if exist("$(_INSTALLDIR)\..\include\tk.h") ++TKINSTALL = 1 ++_TKDIR = $(_INSTALLDIR)\.. ++_TK_H = $(_TKDIR)\include\tk.h ++TKDIR = $(_TKDIR) ++!elseif exist("$(_TCLDIR)\include\tk.h") ++TKINSTALL = 1 ++_TKDIR = $(_TCLDIR) ++_TK_H = $(_TKDIR)\include\tk.h ++TKDIR = $(_TKDIR) ++!endif ++!else ++_TKDIR = $(TKDIR:/=\) ++!if exist("$(_TKDIR)\include\tk.h") ++TKINSTALL = 1 ++_TK_H = $(_TKDIR)\include\tk.h ++!elseif exist("$(_TKDIR)\generic\tk.h") ++TKINSTALL = 0 ++_TK_H = $(_TKDIR)\generic\tk.h ++!else ++MSG =^ ++Failed to find tk.h. The TKDIR macro does not appear correct. ++!error $(MSG) ++!endif ++!endif ++!endif ++ ++#------------------------------------------------------------------------- ++# Extract Tk version numbers ++#------------------------------------------------------------------------- ++ ++!if defined(PROJECT_REQUIRES_TK) || "$(PROJECT)" == "tk" ++ ++!if [echo TK_MAJOR_VERSION = \>> versions.vc] \ ++ && [nmakehlp -V $(_TK_H) TK_MAJOR_VERSION >> versions.vc] ++!endif ++!if [echo TK_MINOR_VERSION = \>> versions.vc] \ ++ && [nmakehlp -V $(_TK_H) TK_MINOR_VERSION >> versions.vc] ++!endif ++!if [echo TK_PATCH_LEVEL = \>> versions.vc] \ ++ && [nmakehlp -V $(_TK_H) TK_PATCH_LEVEL >> versions.vc] ++!endif ++ ++!include versions.vc ++ ++TK_DOTVERSION = $(TK_MAJOR_VERSION).$(TK_MINOR_VERSION) ++TK_VERSION = $(TK_MAJOR_VERSION)$(TK_MINOR_VERSION) ++ ++!if "$(PROJECT)" != "tk" ++!if $(TKINSTALL) ++WISH = "$(_TKDIR)\bin\wish$(TK_VERSION)$(SUFX).exe" ++TKSTUBLIB = "$(_TKDIR)\lib\tkstub$(TK_VERSION).lib" ++TKIMPLIB = "$(_TKDIR)\lib\tk$(TK_VERSION)$(SUFX).lib" ++TK_INCLUDES = -I"$(_TKDIR)\include" ++!else ++WISH = "$(_TKDIR)\win\$(BUILDDIRTOP)\wish$(TCL_VERSION)$(SUFX).exe" ++TKSTUBLIB = "$(_TKDIR)\win\$(BUILDDIRTOP)\tkstub$(TCL_VERSION).lib" ++TKIMPLIB = "$(_TKDIR)\win\$(BUILDDIRTOP)\tk$(TCL_VERSION)$(SUFX).lib" ++TK_INCLUDES = -I"$(_TKDIR)\generic" -I"$(_TKDIR)\win" -I"$(_TKDIR)\xlib" ++!endif ++!endif ++ ++!endif ++ ++#---------------------------------------------------------- ++# Display stats being used. ++#---------------------------------------------------------- ++ ++!message *** Intermediate directory will be '$(TMP_DIR)' ++!message *** Output directory will be '$(OUT_DIR)' ++!message *** Suffix for binaries will be '$(SUFX)' ++!message *** Optional defines are '$(OPTDEFINES)' ++!message *** Compiler version $(VCVER). Target machine is $(MACHINE) ++!message *** Host architecture is $(NATIVE_ARCH) ++!message *** Compiler options '$(COMPILERFLAGS) $(OPTIMIZATIONS) $(DEBUGFLAGS) $(WARNINGS)' ++!message *** Link options '$(LINKERFLAGS)' ++ ++!endif ++ diff --git a/share/security/patches/EN-19:03/sqlite-12.patch.asc b/share/security/patches/EN-19:03/sqlite-12.patch.asc new file mode 100644 index 0000000000..d1709c7258 --- /dev/null +++ b/share/security/patches/EN-19:03/sqlite-12.patch.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- + +iQKTBAABCgB9FiEE/A6HiuWv54gCjWNV05eS9J6n5cIFAlw2RiZfFIAAAAAALgAo +aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldEZD +MEU4NzhBRTVBRkU3ODgwMjhENjM1NUQzOTc5MkY0OUVBN0U1QzIACgkQ05eS9J6n +5cJ1DxAAnbAtjFeY6WfYrVaBB1GHJGdIKQrgq3yzHxd3ycQYguOqjHYkagR7TLM4 +Eo7/hUjTos7yvgw7A7IOVg6HqpcTuQNRHu6T5MjnHoNiB5pNgjN/OYlJ1v1nDSRR +PiNoBX1NhrUiZc8eMblZESdq2COuph9wdLJGiZeA69uTDzLTvnhIvmaFwLBM0ewl +wqK0ND3Z+bVLxuxdeRI7n616HCkQ9EgP2S8uPONZEmMaI1J00018bGOZTmBYaE9x +3/LYfR5F1ggBq5J7Vxa62z0s0vVUu8AAIE422MmqpNONgSqRQ7c2tlYi4x8NLLbs +feKuS6l181m7gN0Jc6OJZfnuEkFC1P8y3Klg9ruERX5kNKGc0cJQ5tTEzGLRxflV +eHHczHFHe6h45W9LDrkhQgOWF/ofATOIjkch0G3i5aoegBMuf0ISFZaqHm11fxnO +AAc8HY1pn6qSgMaJH33xAjCdWvGJHv8Dln08Bag9L80qW+7JoGADVTpDqJ9jqENR +2w/dQH+1AQTH3TVI7GaOYVD2f73o+YJ/SJjJQ6SrvhKaQ0MIzKRwqhsD3DgfG6ux +FYc6/5mv/yljxBPR/K7FNbd+XIz5SyicoXe7Xkk/GxChtjfKrYwK/LyWIHZfrX9N +nBNecHd8XRnpEDqdQ2qStNkWdkaX8KixcBhX18SkHDchhjJF7BY= +=M+mD +-----END PGP SIGNATURE----- diff --git a/share/security/patches/EN-19:04/tzdata-2018i.patch b/share/security/patches/EN-19:04/tzdata-2018i.patch new file mode 100644 index 0000000000..a506ce9e98 --- /dev/null +++ b/share/security/patches/EN-19:04/tzdata-2018i.patch @@ -0,0 +1,1448 @@ +--- contrib/tzdata/Makefile.orig ++++ contrib/tzdata/Makefile +@@ -380,15 +380,18 @@ + # is typically nicer if it works. + KSHELL= /bin/bash + ++# Name of curl <https://curl.haxx.se/>, used for HTML validation. ++CURL= curl ++ + # The path where SGML DTDs are kept and the catalog file(s) to use when +-# validating. The default should work on both Debian and Red Hat. ++# validating HTML 4.01. The default should work on both Debian and Red Hat. + SGML_TOPDIR= /usr + SGML_DTDDIR= $(SGML_TOPDIR)/share/xml/w3c-sgml-lib/schema/dtd + SGML_SEARCH_PATH= $(SGML_DTDDIR)/REC-html401-19991224 + SGML_CATALOG_FILES= \ + $(SGML_TOPDIR)/share/doc/w3-recs/html/www.w3.org/TR/1999/REC-html401-19991224/HTML4.cat:$(SGML_TOPDIR)/share/sgml/html/4.01/HTML4.cat + +-# The name, arguments and environment of a program to validate your web pages. ++# The name, arguments and environment of a program to validate HTML 4.01. + # See <http://openjade.sourceforge.net/doc/> for a validator, and + # <https://validator.w3.org/source/> for a validation library. + # Set VALIDATE=':' if you do not have such a program. +@@ -488,6 +491,7 @@ + COMMON= calendars CONTRIBUTING LICENSE Makefile \ + NEWS README theory.html version + WEB_PAGES= tz-art.html tz-how-to.html tz-link.html ++CHECK_WEB_PAGES=check_tz-art.html check_tz-how-to.html check_tz-link.html + DOCS= $(MANS) date.1 $(MANTXTS) $(WEB_PAGES) + PRIMARY_YDATA= africa antarctica asia australasia \ + europe northamerica southamerica +@@ -799,9 +803,15 @@ + fi + touch $@ + +-# This checks only the HTML 4.01 strict page. +-# To check the the other pages, use <https://validator.w3.org/>. +-check_web: tz-how-to.html ++check_web: $(CHECK_WEB_PAGES) ++check_tz-art.html: tz-art.html ++check_tz-link.html: tz-link.html ++check_tz-art.html check_tz-link.html: ++ $(CURL) -sS --url https://validator.w3.org/nu/ -F out=gnu \ ++ -F file=@$$(expr $@ : 'check_\(.*\)') -o $@.out && \ ++ test ! -s $@.out || { cat $@.out; exit 1; } ++ mv $@.out $@ ++check_tz-how-to.html: tz-how-to.html + $(VALIDATE_ENV) $(VALIDATE) $(VALIDATE_FLAGS) tz-how-to.html + touch $@ + +@@ -1068,7 +1078,7 @@ + + .PHONY: ALL INSTALL all + .PHONY: check check_time_t_alternatives +-.PHONY: check_zishrink ++.PHONY: check_web check_zishrink + .PHONY: clean clean_misc dummy.zd force_tzs + .PHONY: install install_data maintainer-clean names + .PHONY: posix_only posix_packrat posix_right public +--- contrib/tzdata/NEWS.orig ++++ contrib/tzdata/NEWS +@@ -1,14 +1,103 @@ + News for the tz database + ++Release 2018i - 2018-12-30 11:05:43 -0800 ++ ++ Briefly: ++ São Tomé and Príncipe switches from +01 to +00 on 2019-01-01. ++ ++ Changes to future timestamps ++ ++ Due to a change in government, São Tomé and Príncipe switches back ++ from +01 to +00 on 2019-01-01 at 02:00. (Thanks to Vadim ++ Nasardinov and Michael Deckers.) ++ ++ ++Release 2018h - 2018-12-23 17:59:32 -0800 ++ ++ Briefly: ++ Qyzylorda, Kazakhstan moved from +06 to +05 on 2018-12-21. ++ New zone Asia/Qostanay because Qostanay, Kazakhstan didn't move. ++ Metlakatla, Alaska observes PST this winter only. ++ Guess Morocco will continue to adjust clocks around Ramadan. ++ Add predictions for Iran from 2038 through 2090. ++ ++ Changes to future timestamps ++ ++ Guess that Morocco will continue to fall back just before and ++ spring forward just after Ramadan, the practice since 2012. ++ (Thanks to Maamar Abdelkader.) This means Morocco will observe ++ negative DST during Ramadan in main and vanguard formats, and in ++ rearguard format it stays in the +00 timezone and observes ++ ordinary DST in all months other than Ramadan. As before, extend ++ this guesswork to the year 2037. As a consequence, Morocco is ++ scheduled to observe three DST transitions in some Gregorian years ++ (e.g., 2033) due to the mismatch between the Gregorian and Islamic ++ calendars. ++ ++ The table of exact transitions for Iranian DST has been extended. ++ It formerly cut off before the year 2038 in a nod to 32-bit time_t. ++ It now cuts off before 2091 as there is doubt about how the Persian ++ calendar will treat 2091. This change predicts DST transitions in ++ 2038-9, 2042-3, and 2046-7 to occur one day later than previously ++ predicted. As before, post-cutoff transitions are approximated. ++ ++ Changes to past and future timestamps ++ ++ Qyzylorda (aka Kyzylorda) oblast in Kazakhstan moved from +06 to ++ +05 on 2018-12-21. This is a zone split as Qostanay (aka ++ Kostanay) did not switch, so create a zone Asia/Qostanay. ++ ++ Metlakatla moved from Alaska to Pacific standard time on 2018-11-04. ++ It did not change clocks that day and remains on -08 this winter. ++ (Thanks to Ryan Stanley.) It will revert to the usual Alaska ++ rules next spring, so this change affects only timestamps ++ from 2018-11-04 through 2019-03-10. ++ ++ Change to past timestamps ++ ++ Kwajalein's 1993-08-20 transition from -12 to +12 was at 24:00, ++ not 00:00. I transcribed the time incorrectly from Shanks. ++ (Thanks to Phake Nick.) ++ ++ Nauru's 1979 transition was on 02-10 at 02:00, not 05-01 at 00:00. ++ (Thanks to Phake Nick.) ++ ++ Guam observed DST irregularly from 1959 through 1977. ++ (Thanks to Phake Nick.) ++ ++ Hong Kong observed DST in 1941 starting 06-15 (not 04-01), then on ++ 10-01 changed standard time to +08:30 (not +08). Its transition ++ back to +08 after WWII was on 1945-09-15, not the previous day. ++ Its 1904-10-30 change took effect at 01:00 +08 (not 00:00 LMT). ++ (Thanks to Phake Nick, Steve Allen, and Joseph Myers.) Also, ++ its 1952 fallback was on 11-02 (not 10-25). ++ ++ This release contains many changes to timestamps before 1946 due ++ to Japanese possession or occupation of Pacific/Chuuk, ++ Pacific/Guam, Pacific/Kosrae, Pacific/Kwajalein, Pacific/Majuro, ++ Pacific/Nauru, Pacific/Palau, and Pacific/Pohnpei. ++ (Thanks to Phake Nick.) ++ ++ Assume that the Spanish East Indies was like the Philippines and ++ observed American time until the end of 1844. This affects ++ Pacific/Chuuk, Pacific/Kosrae, Pacific/Palau, and Pacific/Pohnpei. ++ ++ Changes to past tm_isdst flags ++ ++ For the recent Morocco change, the tm_isdst flag should be 1 from ++ 2018-10-27 00:00 to 2018-10-28 03:00. (Thanks to Michael Deckers.) ++ Give a URL to the official decree. (Thanks to Matt Johnson.) ++ ++ + Release 2018g - 2018-10-26 22:22:45 -0700 + + Briefly: +- Morocco switches to permanent +01 on 2018-10-27. ++ Morocco switches to permanent +01 on 2018-10-28. + + Changes to future timestamps + +- Morocco switches from +00/+01 to permanent +01 effective 2018-10-27, +- so its clocks will not fall back on 2018-10-28 as previously scheduled. ++ Morocco switches from +00/+01 to permanent +01 effective 2018-10-28, ++ so its clocks will not fall back as previously scheduled. + (Thanks to Mohamed Essedik Najd and Brian Inglis.) + + Changes to code +@@ -119,7 +208,7 @@ + localtime.c no longer ignores TZif POSIX-style TZ strings that + specify only standard time. Instead, these TZ strings now + override the default time type for timestamps after the last +- transition (or for all time stamps if there are no transitions), ++ transition (or for all timestamps if there are no transitions), + just as DST strings specifying DST have always done. + + leapseconds.awk now outputs "#updated" and "#expires" comments, +--- contrib/tzdata/africa.orig ++++ contrib/tzdata/africa +@@ -847,8 +847,41 @@ + # From Mohamed Essedik Najd (2018-10-26): + # Today, a Moroccan government council approved the perpetual addition + # of 60 minutes to the regular Moroccan timezone. +-# From Brian Inglis (2018-10-26): +-# http://www.maroc.ma/fr/actualites/le-conseil-de-gouvernement-adopte-un-projet-de-decret-relatif-lheure-legale-stipulant-le ++# From Matt Johnson (2018-10-28): ++# http://www.sgg.gov.ma/Portals/1/BO/2018/BO_6720-bis_Ar.pdf ++# ++# From Maamar Abdelkader (2018-11-01): ++# We usually move clocks back the previous week end and come back to the +1 ++# the week end after.... The government does not announce yet the decision ++# about this temporary change. But it s 99% sure that it will be the case, ++# as in previous years. An unofficial survey was done these days, showing ++# that 64% of asked peopke are ok for moving from +1 to +0 during Ramadan. ++# https://leconomiste.com/article/1035870-enquete-l-economiste-sunergia-64-des-marocains-plebiscitent-le-gmt-pendant-ramadan ++# ++# From Paul Eggert (2018-11-01): ++# For now, guess that Morocco will fall back at 03:00 the last Sunday ++# before Ramadan, and spring forward at 02:00 the first Sunday after ++# Ramadan, as this has been the practice since 2012. To implement this, ++# transition dates for 2019 through 2037 were determined by running the ++# following program under GNU Emacs 26.1. ++# (let ((islamic-year 1440)) ++# (require 'cal-islam) ++# (while (< islamic-year 1460) ++# (let ((a (calendar-islamic-to-absolute (list 9 1 islamic-year))) ++# (b (calendar-islamic-to-absolute (list 10 1 islamic-year))) ++# (sunday 0)) ++# (while (/= sunday (mod (setq a (1- a)) 7))) ++# (while (/= sunday (mod b 7)) ++# (setq b (1+ b))) ++# (setq a (calendar-gregorian-from-absolute a)) ++# (setq b (calendar-gregorian-from-absolute b)) ++# (insert ++# (format ++# (concat "Rule\tMorocco\t%d\tonly\t-\t%s\t%2d\t 3:00\t-1:00\t-\n" ++# "Rule\tMorocco\t%d\tonly\t-\t%s\t%2d\t 2:00\t0\t-\n") ++# (car (cdr (cdr a))) (calendar-month-name (car a) t) (car (cdr a)) ++# (car (cdr (cdr b))) (calendar-month-name (car b) t) (car (cdr b))))) ++# (setq islamic-year (+ 1 islamic-year)))) + + # RULE NAME FROM TO TYPE IN ON AT SAVE LETTER/S + Rule Morocco 1939 only - Sep 12 0:00 1:00 - +@@ -892,13 +925,53 @@ + Rule Morocco 2017 only - Jul 2 2:00 1:00 - + Rule Morocco 2018 only - May 13 3:00 0 - + Rule Morocco 2018 only - Jun 17 2:00 1:00 - ++Rule Morocco 2019 only - May 5 3:00 -1:00 - ++Rule Morocco 2019 only - Jun 9 2:00 0 - ++Rule Morocco 2020 only - Apr 19 3:00 -1:00 - ++Rule Morocco 2020 only - May 24 2:00 0 - ++Rule Morocco 2021 only - Apr 11 3:00 -1:00 - ++Rule Morocco 2021 only - May 16 2:00 0 - ++Rule Morocco 2022 only - Mar 27 3:00 -1:00 - ++Rule Morocco 2022 only - May 8 2:00 0 - ++Rule Morocco 2023 only - Mar 19 3:00 -1:00 - ++Rule Morocco 2023 only - Apr 23 2:00 0 - ++Rule Morocco 2024 only - Mar 10 3:00 -1:00 - ++Rule Morocco 2024 only - Apr 14 2:00 0 - ++Rule Morocco 2025 only - Feb 23 3:00 -1:00 - ++Rule Morocco 2025 only - Apr 6 2:00 0 - ++Rule Morocco 2026 only - Feb 15 3:00 -1:00 - ++Rule Morocco 2026 only - Mar 22 2:00 0 - ++Rule Morocco 2027 only - Feb 7 3:00 -1:00 - ++Rule Morocco 2027 only - Mar 14 2:00 0 - ++Rule Morocco 2028 only - Jan 23 3:00 -1:00 - ++Rule Morocco 2028 only - Feb 27 2:00 0 - ++Rule Morocco 2029 only - Jan 14 3:00 -1:00 - ++Rule Morocco 2029 only - Feb 18 2:00 0 - ++Rule Morocco 2029 only - Dec 30 3:00 -1:00 - ++Rule Morocco 2030 only - Feb 10 2:00 0 - ++Rule Morocco 2030 only - Dec 22 3:00 -1:00 - ++Rule Morocco 2031 only - Jan 26 2:00 0 - ++Rule Morocco 2031 only - Dec 14 3:00 -1:00 - ++Rule Morocco 2032 only - Jan 18 2:00 0 - ++Rule Morocco 2032 only - Nov 28 3:00 -1:00 - ++Rule Morocco 2033 only - Jan 9 2:00 0 - ++Rule Morocco 2033 only - Nov 20 3:00 -1:00 - ++Rule Morocco 2033 only - Dec 25 2:00 0 - ++Rule Morocco 2034 only - Nov 5 3:00 -1:00 - ++Rule Morocco 2034 only - Dec 17 2:00 0 - ++Rule Morocco 2035 only - Oct 28 3:00 -1:00 - ++Rule Morocco 2035 only - Dec 2 2:00 0 - ++Rule Morocco 2036 only - Oct 19 3:00 -1:00 - ++Rule Morocco 2036 only - Nov 23 2:00 0 - ++Rule Morocco 2037 only - Oct 4 3:00 -1:00 - ++Rule Morocco 2037 only - Nov 15 2:00 0 - + + # Zone NAME GMTOFF RULES FORMAT [UNTIL] + Zone Africa/Casablanca -0:30:20 - LMT 1913 Oct 26 + 0:00 Morocco +00/+01 1984 Mar 16 + 1:00 - +01 1986 +- 0:00 Morocco +00/+01 2018 Oct 27 +- 1:00 - +01 ++ 0:00 Morocco +00/+01 2018 Oct 28 3:00 ++ 1:00 Morocco +01/+00 + + # Western Sahara + # +@@ -913,8 +986,8 @@ + + Zone Africa/El_Aaiun -0:52:48 - LMT 1934 Jan # El Aaiún + -1:00 - -01 1976 Apr 14 +- 0:00 Morocco +00/+01 2018 Oct 27 +- 1:00 - +01 ++ 0:00 Morocco +00/+01 2018 Oct 28 3:00 ++ 1:00 Morocco +01/+00 + + # Mozambique + # +@@ -1071,10 +1144,20 @@ + # the switch is from 01:00 to 02:00 ... [Decree No. 25/2017] + # http://www.mnec.gov.st/index.php/publicacoes/documentos/file/90-decreto-lei-n-25-2017 + ++# From Vadim Nasardinov (2018-12-29): ++# São Tomé and Príncipe is about to do the following on Jan 1, 2019: ++# https://www.stp-press.st/2018/12/05/governo-jesus-ja-decidiu-repor-hora-legal-sao-tomense/ ++# ++# From Michael Deckers (2018-12-30): ++# https://www.legis-palop.org/download.jsp?idFile=102818 ++# ... [The legal time of the country, which coincides with universal ++# coordinated time, will be restituted at 2 o'clock on day 1 of January, 2019.] ++ + Zone Africa/Sao_Tome 0:26:56 - LMT 1884 + -0:36:45 - LMT 1912 Jan 1 00:00u # Lisbon MT + 0:00 - GMT 2018 Jan 1 01:00 +- 1:00 - WAT ++ 1:00 - WAT 2019 Jan 1 02:00 ++ 0:00 - GMT + + # Senegal + # See Africa/Abidjan. +--- contrib/tzdata/asia.orig ++++ contrib/tzdata/asia +@@ -586,12 +586,82 @@ + # obtained from + # http://www.hko.gov.hk/gts/time/Summertime.htm + +-# From Arthur David Olson (2009-10-28): ++# From Phake Nick (2018-10-27): ++# According to Singaporean newspaper ++# http://eresources.nlb.gov.sg/newspapers/Digitised/Article/singfreepresswk19041102-1.2.37 ++# the day that Hong Kong start using GMT+8 should be Oct 30, 1904. ++# ++# From Paul Eggert (2018-11-17): ++# Hong Kong had a time ball near the Marine Police Station, Tsim Sha Tsui. ++# "The ball was raised manually each day and dropped at exactly 1pm ++# (except on Sundays and Government holidays)." ++# Dyson AD. From Time Ball to Atomic Clock. Hong Kong Government. 1983. ++# <https://www.hko.gov.hk/publica/gen_pub/timeball_atomic_clock.pdf> ++# "From 1904 October 30 the time-ball at Hong Kong has been dropped by order ++# of the Governor of the Colony at 17h 0m 0s G.M.T., which is 23m 18s.14 in ++# advance of 1h 0m 0s of Hong Kong mean time." ++# Hollis HP. Universal Time, Longitudes, and Geodesy. Mon Not R Astron Soc. ++# 1905-02-10;65(4):405-6. https://doi.org/10.1093/mnras/65.4.382 ++# ++# From Joseph Myers (2018-11-18): ++# An astronomer before 1925 referring to GMT would have been using the old ++# astronomical convention where the day started at noon, not midnight. ++# ++# From Steve Allen (2018-11-17): ++# Meteorological Observations made at the Hongkong Observatory in the year 1904 ++# page 4 <https://books.google.com/books?id=kgw5AQAAMAAJ&pg=RA4-PA4> ++# ... the log of drop times in Table II shows that on Sunday 1904-10-30 the ++# ball was dropped. So that looks like a special case drop for the sake ++# of broadcasting the new local time. ++# ++# From Phake Nick (2018-11-18): ++# According to The Hong Kong Weekly Press, 1904-10-29, p.324, the ++# governor of Hong Kong at the time stated that "We are further desired to ++# make it known that the change will be effected by firing the gun and by the ++# dropping of the Ball at 23min. 18sec. before one." ++# From Paul Eggert (2018-11-18): ++# See <https://mmis.hkpl.gov.hk> for this; unfortunately Flash is required. ++ ++# From Phake Nick (2018-10-26): ++# I went to check microfilm records stored at Hong Kong Public Library.... ++# on September 30 1941, according to Ta Kung Pao (Hong Kong edition), it was ++# stated that fallback would occur on the next day (the 1st)'s "03:00 am (Hong ++# Kong Time 04:00 am)" and the clock will fall back for a half hour. (03:00 ++# probably refer to the time commonly used in mainland China at the time given ++# the paper's background) ... the sunrise/sunset time given by South China ++# Morning Post for October 1st was indeed moved by half an hour compares to ++# before. After that, in December, the battle to capture Hong Kong started and ++# the library doesn't seems to have any record stored about press during that ++# period of time. Some media resumed publication soon after that within the ++# same month, but there were not much information about time there. Later they ++# started including a radio program guide when they restored radio service, ++# explicitly mentioning it use Tokyo standard time, and later added a note ++# saying it's half an hour ahead of the old Hong Kong standard time, and it ++# also seems to indicate that Hong Kong was not using GMT+8 when it was ++# captured by Japan. ++# ++# Image of related sections on newspaper: ++# * 1941-09-30, Ta Kung Pao (Hong Kong), "Winter Time start tomorrow". ++# https://i.imgur.com/6waY51Z.jpg (Chinese) ++# * 1941-09-29, South China Morning Post, Information on sunrise/sunset ++# time and other things for September 30 and October 1. ++# https://i.imgur.com/kCiUR78.jpg ++# * 1942-02-05. The Hong Kong News, Radio Program Guide. ++# https://i.imgur.com/eVvDMzS.jpg ++# * 1941-06-14. Hong Kong Daily Press, Daylight Saving from 3am Tomorrow. ++# https://i.imgur.com/05KkvtC.png ++# * 1941-09-30, Hong Kong Daily Press, Winter Time Warning. ++# https://i.imgur.com/dge4kFJ.png ++# Also, the Liberation day of Hong Kong after WWII which British rule ++# over the territory resumed was August 30, 1945, which I think should ++# be the termination date for the use of JST in the territory.... ++ ++# From Paul Eggert (2018-11-17): + # Here are the dates given at +-# http://www.hko.gov.hk/gts/time/Summertime.htm +-# as of 2009-10-28: ++# https://www.hko.gov.hk/gts/time/Summertime.htm ++# as of 2014-06-19: + # Year Period +-# 1941 1 Apr to 30 Sep ++# 1941 15 Jun to 30 Sep + # 1942 Whole year + # 1943 Whole year + # 1944 Whole year +@@ -602,7 +672,7 @@ + # 1949 3 Apr to 30 Oct + # 1950 2 Apr to 29 Oct + # 1951 1 Apr to 28 Oct +-# 1952 6 Apr to 25 Oct ++# 1952 6 Apr to 2 Nov + # 1953 5 Apr to 1 Nov + # 1954 21 Mar to 31 Oct + # 1955 20 Mar to 6 Nov +@@ -631,25 +701,25 @@ + # 1978 Nil + # 1979 13 May to 21 Oct + # 1980 to Now Nil +-# The page does not give start or end times of day. +-# The page does not give a start date for 1942. +-# The page does not givw an end date for 1945. +-# The Japanese occupation of Hong Kong began on 1941-12-25. +-# The Japanese surrender of Hong Kong was signed 1945-09-15. +-# For lack of anything better, use start of those days as the transition times. ++# The page does not give times of day for transitions, ++# or dates for the 1942 and 1945 transitions. ++# The Japanese occupation of Hong Kong began 1941-12-25. ++# The Japanese surrender of Hong Kong was signed 1945-09-16; see: ++# Heaver S. The days after the Pacific war ended: unsettling times ++# in Hong Kong. Post Magazine. 2016-06-13. ++# https://www.scmp.com/magazines/post-magazine/article/1852990/days-after-pacific-war-ended-unsettling-times-hong-kong ++# For lack of anything better, use start of those days as the ++# transition times. + + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S +-Rule HK 1941 only - Apr 1 3:30 1:00 S +-Rule HK 1941 only - Sep 30 3:30 0 - + Rule HK 1946 only - Apr 20 3:30 1:00 S + Rule HK 1946 only - Dec 1 3:30 0 - + Rule HK 1947 only - Apr 13 3:30 1:00 S + Rule HK 1947 only - Dec 30 3:30 0 - + Rule HK 1948 only - May 2 3:30 1:00 S + Rule HK 1948 1951 - Oct lastSun 3:30 0 - +-Rule HK 1952 only - Oct 25 3:30 0 - ++Rule HK 1952 1953 - Nov Sun>=1 3:30 0 - + Rule HK 1949 1953 - Apr Sun>=1 3:30 1:00 S +-Rule HK 1953 only - Nov 1 3:30 0 - + Rule HK 1954 1964 - Mar Sun>=18 3:30 1:00 S + Rule HK 1954 only - Oct 31 3:30 0 - + Rule HK 1955 1964 - Nov Sun>=1 3:30 0 - +@@ -659,9 +729,11 @@ + Rule HK 1979 only - May Sun>=8 3:30 1:00 S + Rule HK 1979 only - Oct Sun>=16 3:30 0 - + # Zone NAME GMTOFF RULES FORMAT [UNTIL] +-Zone Asia/Hong_Kong 7:36:42 - LMT 1904 Oct 30 +- 8:00 HK HK%sT 1941 Dec 25 +- 9:00 - JST 1945 Sep 15 ++Zone Asia/Hong_Kong 7:36:42 - LMT 1904 Oct 30 0:36:42 ++ 8:00 - HKT 1941 Jun 15 3:30 ++ 8:00 1:00 HKST 1941 Oct 1 4:00 ++ 8:30 - HKT 1941 Dec 25 ++ 9:00 - JST 1945 Sep 16 + 8:00 HK HK%sT + + ############################################################################### +@@ -1057,6 +1129,16 @@ + + # India + ++# British astronomer Henry Park Hollis disliked India Standard Time's offset: ++# "A new time system has been proposed for India, Further India, and Burmah. ++# The scheme suggested is that the times of the meridians 5½ and 6½ hours ++# east of Greenwich should be adopted in these territories. No reason is ++# given why hourly meridians five hours and six hours east should not be ++# chosen; a plan which would bring the time of India into harmony with ++# that of almost the whole of the civilised world." ++# Hollis HP. Universal Time, Longitudes, and Geodesy. Mon Not R Astron Soc. ++# 1905-02-10;65(4):405-6. https://doi.org/10.1093/mnras/65.4.382 ++ + # From Ian P. Beacock, in "A brief history of (modern) time", The Atlantic + # https://www.theatlantic.com/technology/archive/2015/12/the-creation-of-modern-time/421419/ + # (2015-12-22): +@@ -1227,12 +1309,65 @@ + # leap year calculation involved. There has never been any serious + # plan to change that law.... + # +-# From Paul Eggert (2006-03-22): ++# From Paul Eggert (2018-11-30): + # Go with Shanks & Pottenger before Sept. 1991, and with Pournader thereafter. +-# I used Ed Reingold's cal-persia in GNU Emacs 21.2 to check Persian dates, +-# stopping after 2037 when 32-bit time_t's overflow. +-# That cal-persia used Birashk's approximation, which disagrees with the solar +-# calendar predictions for the year 2025, so I corrected those dates by hand. ++# I used the following code in GNU Emacs 26.1 to generate the "Rule Iran" ++# lines from 2008 through 2087. Emacs 26.1 uses Ed Reingold's ++# cal-persia implementation of Birashk's approximation, which in the ++# 2008-2087 range disagrees with the the astronomical Persian calendar ++# for Persian years 1404 (Gregorian 2025) and 1437 (Gregorian 2058), ++# so the following code special-case those years. See Table 15.1, page 264, of: ++# Edward M. Reingold and Nachum Dershowitz, Calendrical Calculations: ++# The Ultimate Edition, Cambridge University Press (2018). ++# https://www.cambridge.org/fr/academic/subjects/computer-science/computing-general-interest/calendrical-calculations-ultimate-edition-4th-edition ++# Page 258, footnote 2, of this book says there is some dispute over what will ++# happen in 2091 (and some other years after that), so this code ++# stops in 2087, as 2088 and 2089 agree with the "max" rule below. ++# (cl-loop ++# initially (require 'cal-persia) ++# with first-persian-year = 1387 ++# with last-persian-year = 1466 ++# ;; Exceptional years in the above range, ++# ;; from Reingold & Dershowitz Table 15.1, page 264: ++# with exceptional-persian-years = '(1404 1437) ++# with range-start = nil ++# for persian-year from first-persian-year to last-persian-year ++# do ++# (let* ++# ((exceptional-year-offset ++# (if (member persian-year exceptional-persian-years) 1 0)) ++# (beg-dst-absolute ++# (+ (calendar-persian-to-absolute (list 1 1 persian-year)) ++# exceptional-year-offset)) ++# (end-dst-absolute ++# (+ (calendar-persian-to-absolute (list 6 30 persian-year)) ++# exceptional-year-offset)) ++# (next-year-beg-dst-absolute ++# (+ (calendar-persian-to-absolute (list 1 1 (1+ persian-year))) ++# (if (member (1+ persian-year) exceptional-persian-years) 1 0))) ++# (beg-dst (calendar-gregorian-from-absolute beg-dst-absolute)) ++# (end-dst (calendar-gregorian-from-absolute end-dst-absolute)) ++# (next-year-beg-dst (calendar-gregorian-from-absolute ++# next-year-beg-dst-absolute)) ++# (year (calendar-extract-year beg-dst)) ++# (range-end (if range-start year "only"))) ++# (setq range-start (or range-start year)) ++# (when (or (/= (calendar-extract-day beg-dst) ++# (calendar-extract-day next-year-beg-dst)) ++# (= persian-year last-persian-year)) ++# (insert ++# (format ++# "Rule\tIran\t%d\t%s\t-\t%s\t%2d\t24:00\t1:00\t-\n" ++# range-start range-end ++# (calendar-month-name (calendar-extract-month beg-dst) t) ++# (calendar-extract-day beg-dst))) ++# (insert ++# (format ++# "Rule\tIran\t%d\t%s\t-\t%s\t%2d\t24:00\t0\t-\n" ++# range-start range-end ++# (calendar-month-name (calendar-extract-month end-dst) t) ++# (calendar-extract-day end-dst))) ++# (setq range-start nil)))) + # + # From Oscar van Vlijmen (2005-03-30), writing about future + # discrepancies between cal-persia and the Iranian calendar: +@@ -1267,61 +1402,113 @@ + # thirtieth day of Shahrivar. + # + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S +-Rule Iran 1978 1980 - Mar 21 0:00 1:00 - +-Rule Iran 1978 only - Oct 21 0:00 0 - +-Rule Iran 1979 only - Sep 19 0:00 0 - +-Rule Iran 1980 only - Sep 23 0:00 0 - +-Rule Iran 1991 only - May 3 0:00 1:00 - +-Rule Iran 1992 1995 - Mar 22 0:00 1:00 - +-Rule Iran 1991 1995 - Sep 22 0:00 0 - +-Rule Iran 1996 only - Mar 21 0:00 1:00 - +-Rule Iran 1996 only - Sep 21 0:00 0 - +-Rule Iran 1997 1999 - Mar 22 0:00 1:00 - +-Rule Iran 1997 1999 - Sep 22 0:00 0 - +-Rule Iran 2000 only - Mar 21 0:00 1:00 - +-Rule Iran 2000 only - Sep 21 0:00 0 - +-Rule Iran 2001 2003 - Mar 22 0:00 1:00 - +-Rule Iran 2001 2003 - Sep 22 0:00 0 - +-Rule Iran 2004 only - Mar 21 0:00 1:00 - +-Rule Iran 2004 only - Sep 21 0:00 0 - +-Rule Iran 2005 only - Mar 22 0:00 1:00 - +-Rule Iran 2005 only - Sep 22 0:00 0 - +-Rule Iran 2008 only - Mar 21 0:00 1:00 - +-Rule Iran 2008 only - Sep 21 0:00 0 - +-Rule Iran 2009 2011 - Mar 22 0:00 1:00 - +-Rule Iran 2009 2011 - Sep 22 0:00 0 - +-Rule Iran 2012 only - Mar 21 0:00 1:00 - +-Rule Iran 2012 only - Sep 21 0:00 0 - +-Rule Iran 2013 2015 - Mar 22 0:00 1:00 - +-Rule Iran 2013 2015 - Sep 22 0:00 0 - +-Rule Iran 2016 only - Mar 21 0:00 1:00 - +-Rule Iran 2016 only - Sep 21 0:00 0 - +-Rule Iran 2017 2019 - Mar 22 0:00 1:00 - +-Rule Iran 2017 2019 - Sep 22 0:00 0 - +-Rule Iran 2020 only - Mar 21 0:00 1:00 - +-Rule Iran 2020 only - Sep 21 0:00 0 - +-Rule Iran 2021 2023 - Mar 22 0:00 1:00 - +-Rule Iran 2021 2023 - Sep 22 0:00 0 - +-Rule Iran 2024 only - Mar 21 0:00 1:00 - +-Rule Iran 2024 only - Sep 21 0:00 0 - +-Rule Iran 2025 2027 - Mar 22 0:00 1:00 - +-Rule Iran 2025 2027 - Sep 22 0:00 0 - +-Rule Iran 2028 2029 - Mar 21 0:00 1:00 - +-Rule Iran 2028 2029 - Sep 21 0:00 0 - +-Rule Iran 2030 2031 - Mar 22 0:00 1:00 - +-Rule Iran 2030 2031 - Sep 22 0:00 0 - +-Rule Iran 2032 2033 - Mar 21 0:00 1:00 - +-Rule Iran 2032 2033 - Sep 21 0:00 0 - +-Rule Iran 2034 2035 - Mar 22 0:00 1:00 - +-Rule Iran 2034 2035 - Sep 22 0:00 0 - +-# +-# The following rules are approximations starting in the year 2038. +-# These are the best post-2037 approximations available, given the +-# restrictions of a single rule using a Gregorian-based data format. ++Rule Iran 1978 1980 - Mar 20 24:00 1:00 - ++Rule Iran 1978 only - Oct 20 24:00 0 - ++Rule Iran 1979 only - Sep 18 24:00 0 - ++Rule Iran 1980 only - Sep 22 24:00 0 - ++Rule Iran 1991 only - May 2 24:00 1:00 - ++Rule Iran 1992 1995 - Mar 21 24:00 1:00 - ++Rule Iran 1991 1995 - Sep 21 24:00 0 - ++Rule Iran 1996 only - Mar 20 24:00 1:00 - ++Rule Iran 1996 only - Sep 20 24:00 0 - ++Rule Iran 1997 1999 - Mar 21 24:00 1:00 - ++Rule Iran 1997 1999 - Sep 21 24:00 0 - ++Rule Iran 2000 only - Mar 20 24:00 1:00 - ++Rule Iran 2000 only - Sep 20 24:00 0 - ++Rule Iran 2001 2003 - Mar 21 24:00 1:00 - ++Rule Iran 2001 2003 - Sep 21 24:00 0 - ++Rule Iran 2004 only - Mar 20 24:00 1:00 - ++Rule Iran 2004 only - Sep 20 24:00 0 - ++Rule Iran 2005 only - Mar 21 24:00 1:00 - ++Rule Iran 2005 only - Sep 21 24:00 0 - ++Rule Iran 2008 only - Mar 20 24:00 1:00 - ++Rule Iran 2008 only - Sep 20 24:00 0 - ++Rule Iran 2009 2011 - Mar 21 24:00 1:00 - ++Rule Iran 2009 2011 - Sep 21 24:00 0 - ++Rule Iran 2012 only - Mar 20 24:00 1:00 - ++Rule Iran 2012 only - Sep 20 24:00 0 - ++Rule Iran 2013 2015 - Mar 21 24:00 1:00 - ++Rule Iran 2013 2015 - Sep 21 24:00 0 - ++Rule Iran 2016 only - Mar 20 24:00 1:00 - ++Rule Iran 2016 only - Sep 20 24:00 0 - ++Rule Iran 2017 2019 - Mar 21 24:00 1:00 - ++Rule Iran 2017 2019 - Sep 21 24:00 0 - ++Rule Iran 2020 only - Mar 20 24:00 1:00 - ++Rule Iran 2020 only - Sep 20 24:00 0 - ++Rule Iran 2021 2023 - Mar 21 24:00 1:00 - ++Rule Iran 2021 2023 - Sep 21 24:00 0 - ++Rule Iran 2024 only - Mar 20 24:00 1:00 - ++Rule Iran 2024 only - Sep 20 24:00 0 - ++Rule Iran 2025 2027 - Mar 21 24:00 1:00 - ++Rule Iran 2025 2027 - Sep 21 24:00 0 - ++Rule Iran 2028 2029 - Mar 20 24:00 1:00 - ++Rule Iran 2028 2029 - Sep 20 24:00 0 - ++Rule Iran 2030 2031 - Mar 21 24:00 1:00 - ++Rule Iran 2030 2031 - Sep 21 24:00 0 - ++Rule Iran 2032 2033 - Mar 20 24:00 1:00 - ++Rule Iran 2032 2033 - Sep 20 24:00 0 - ++Rule Iran 2034 2035 - Mar 21 24:00 1:00 - ++Rule Iran 2034 2035 - Sep 21 24:00 0 - ++Rule Iran 2036 2037 - Mar 20 24:00 1:00 - ++Rule Iran 2036 2037 - Sep 20 24:00 0 - ++Rule Iran 2038 2039 - Mar 21 24:00 1:00 - ++Rule Iran 2038 2039 - Sep 21 24:00 0 - ++Rule Iran 2040 2041 - Mar 20 24:00 1:00 - ++Rule Iran 2040 2041 - Sep 20 24:00 0 - ++Rule Iran 2042 2043 - Mar 21 24:00 1:00 - ++Rule Iran 2042 2043 - Sep 21 24:00 0 - ++Rule Iran 2044 2045 - Mar 20 24:00 1:00 - ++Rule Iran 2044 2045 - Sep 20 24:00 0 - ++Rule Iran 2046 2047 - Mar 21 24:00 1:00 - ++Rule Iran 2046 2047 - Sep 21 24:00 0 - ++Rule Iran 2048 2049 - Mar 20 24:00 1:00 - ++Rule Iran 2048 2049 - Sep 20 24:00 0 - ++Rule Iran 2050 2051 - Mar 21 24:00 1:00 - ++Rule Iran 2050 2051 - Sep 21 24:00 0 - ++Rule Iran 2052 2053 - Mar 20 24:00 1:00 - ++Rule Iran 2052 2053 - Sep 20 24:00 0 - ++Rule Iran 2054 2055 - Mar 21 24:00 1:00 - ++Rule Iran 2054 2055 - Sep 21 24:00 0 - ++Rule Iran 2056 2057 - Mar 20 24:00 1:00 - ++Rule Iran 2056 2057 - Sep 20 24:00 0 - ++Rule Iran 2058 2059 - Mar 21 24:00 1:00 - ++Rule Iran 2058 2059 - Sep 21 24:00 0 - ++Rule Iran 2060 2062 - Mar 20 24:00 1:00 - ++Rule Iran 2060 2062 - Sep 20 24:00 0 - ++Rule Iran 2063 only - Mar 21 24:00 1:00 - ++Rule Iran 2063 only - Sep 21 24:00 0 - ++Rule Iran 2064 2066 - Mar 20 24:00 1:00 - ++Rule Iran 2064 2066 - Sep 20 24:00 0 - ++Rule Iran 2067 only - Mar 21 24:00 1:00 - ++Rule Iran 2067 only - Sep 21 24:00 0 - ++Rule Iran 2068 2070 - Mar 20 24:00 1:00 - ++Rule Iran 2068 2070 - Sep 20 24:00 0 - ++Rule Iran 2071 only - Mar 21 24:00 1:00 - ++Rule Iran 2071 only - Sep 21 24:00 0 - ++Rule Iran 2072 2074 - Mar 20 24:00 1:00 - ++Rule Iran 2072 2074 - Sep 20 24:00 0 - ++Rule Iran 2075 only - Mar 21 24:00 1:00 - ++Rule Iran 2075 only - Sep 21 24:00 0 - ++Rule Iran 2076 2078 - Mar 20 24:00 1:00 - ++Rule Iran 2076 2078 - Sep 20 24:00 0 - ++Rule Iran 2079 only - Mar 21 24:00 1:00 - ++Rule Iran 2079 only - Sep 21 24:00 0 - ++Rule Iran 2080 2082 - Mar 20 24:00 1:00 - ++Rule Iran 2080 2082 - Sep 20 24:00 0 - ++Rule Iran 2083 only - Mar 21 24:00 1:00 - ++Rule Iran 2083 only - Sep 21 24:00 0 - ++Rule Iran 2084 2086 - Mar 20 24:00 1:00 - ++Rule Iran 2084 2086 - Sep 20 24:00 0 - ++Rule Iran 2087 only - Mar 21 24:00 1:00 - ++Rule Iran 2087 only - Sep 21 24:00 0 - ++# ++# The following rules are approximations starting in the year 2088. ++# These are the best post-2088 approximations available, given the ++# restrictions of a single rule using ordinary Gregorian dates. + # At some point this table will need to be extended, though quite + # possibly Iran will change the rules first. +-Rule Iran 2036 max - Mar 21 0:00 1:00 - +-Rule Iran 2036 max - Sep 21 0:00 0 - ++Rule Iran 2088 max - Mar 20 24:00 1:00 - ++Rule Iran 2088 max - Sep 20 24:00 0 - + + # Zone NAME GMTOFF RULES FORMAT [UNTIL] + Zone Asia/Tehran 3:25:44 - LMT 1916 +@@ -1691,7 +1878,9 @@ + # Zone NAME GMTOFF RULES FORMAT [UNTIL] + Zone Asia/Tokyo 9:18:59 - LMT 1887 Dec 31 15:00u + 9:00 Japan J%sT +-# Since 1938, all Japanese possessions have been like Asia/Tokyo. ++# Since 1938, all Japanese possessions have been like Asia/Tokyo, ++# except that Truk (Chuuk), Ponape (Pohnpei), and Jaluit (Kosrae) did not ++# switch from +10 to +09 until 1941-04-01; see the 'australasia' file. + + # Jordan + # +@@ -1981,8 +2170,10 @@ + # and in Byalokoz) lists Ural river (plus 10 versts on its left bank) in + # the third time belt (before 1930 this means +03). + +-# From Paul Eggert (2016-12-06): +-# The tables below reflect Golosunov's remarks, with exceptions as noted. ++# From Alexander Konzurovski (2018-12-20): ++# Qyzyolrda Region (Asia/Qyzylorda) is changing its time zone from ++# UTC+6 to UTC+5 effective December 21st, 2018. The legal document is ++# located here: http://adilet.zan.kz/rus/docs/P1800000817 (russian language). + + # Zone NAME GMTOFF RULES FORMAT [UNTIL] + # +@@ -1996,8 +2187,6 @@ + 6:00 RussiaAsia +06/+07 2004 Oct 31 2:00s + 6:00 - +06 + # Qyzylorda (aka Kyzylorda, Kizilorda, Kzyl-Orda, etc.) (KZ-KZY) +-# This currently includes Qostanay (aka Kostanay, Kustanay) (KZ-KUS); +-# see comments below. + Zone Asia/Qyzylorda 4:21:52 - LMT 1924 May 2 + 4:00 - +04 1930 Jun 21 + 5:00 - +05 1981 Apr 1 +@@ -2008,21 +2197,22 @@ + 5:00 RussiaAsia +05/+06 1992 Jan 19 2:00s + 6:00 RussiaAsia +06/+07 1992 Mar 29 2:00s + 5:00 RussiaAsia +05/+06 2004 Oct 31 2:00s +- 6:00 - +06 +-# The following zone is like Asia/Qyzylorda except for being one +-# hour earlier from 1991-09-29 to 1992-03-29. The 1991/2 rules for +-# Qostanay are unclear partly because of the 1997 Turgai +-# reorganization, so this zone is commented out for now. +-#Zone Asia/Qostanay 4:14:20 - LMT 1924 May 2 +-# 4:00 - +04 1930 Jun 21 +-# 5:00 - +05 1981 Apr 1 +-# 5:00 1:00 +06 1981 Oct 1 +-# 6:00 - +06 1982 Apr 1 +-# 5:00 RussiaAsia +05/+06 1991 Mar 31 2:00s +-# 4:00 RussiaAsia +04/+05 1992 Jan 19 2:00s +-# 5:00 RussiaAsia +05/+06 2004 Oct 31 2:00s +-# 6:00 - +06 ++ 6:00 - +06 2018 Dec 21 0:00 ++ 5:00 - +05 + # ++# Qostanay (aka Kostanay, Kustanay) (KZ-KUS) ++# The 1991/2 rules are unclear partly because of the 1997 Turgai ++# reorganization. ++Zone Asia/Qostanay 4:14:28 - LMT 1924 May 2 ++ 4:00 - +04 1930 Jun 21 ++ 5:00 - +05 1981 Apr 1 ++ 5:00 1:00 +06 1981 Oct 1 ++ 6:00 - +06 1982 Apr 1 ++ 5:00 RussiaAsia +05/+06 1991 Mar 31 2:00s ++ 4:00 RussiaAsia +04/+05 1992 Jan 19 2:00s ++ 5:00 RussiaAsia +05/+06 2004 Oct 31 2:00s ++ 6:00 - +06 ++ + # Aqtöbe (aka Aktobe, formerly Aktyubinsk) (KZ-AKT) + Zone Asia/Aqtobe 3:48:40 - LMT 1924 May 2 + 4:00 - +04 1930 Jun 21 +@@ -2116,21 +2306,43 @@ + # started at June 1 in that year. For another example, the article in + # 1988 said that DST started at 2:00 AM in that year. + ++# From Phake Nick (2018-10-27): ++# 1. According to official announcement from Korean government, the DST end ++# date in South Korea should be ++# 1955-09-08 without specifying time ++# http://theme.archives.go.kr/next/common/viewEbook.do?singleData=N&archiveEventId=0027977557 ++# 1956-09-29 without specifying time ++# http://theme.archives.go.kr/next/common/viewEbook.do?singleData=N&archiveEventId=0027978341 ++# 1957-09-21 24 o'clock ++# http://theme.archives.go.kr/next/common/viewEbook.do?singleData=N&archiveEventId=0027979690#3 ++# 1958-09-20 24 o'clock ++# http://theme.archives.go.kr/next/common/viewEbook.do?singleData=N&archiveEventId=0027981189 ++# 1959-09-19 24 o'clock ++# http://theme.archives.go.kr/next/common/viewEbook.do?singleData=N&archiveEventId=0027982974#2 ++# 1960-09-17 24 o'clock ++# http://theme.archives.go.kr/next/common/viewEbook.do?singleData=N&archiveEventId=0028044104 ++# ... ++# 2.... https://namu.wiki/w/대한민국%20표준시 ... [says] ++# when Korea was using GMT+8:30 as standard time, the international ++# aviation/marine/meteorological industry in the country refused to ++# follow and continued to use GMT+9:00 for interoperability. ++ ++ + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S +-Rule ROK 1948 only - Jun 1 0:00 1:00 D +-Rule ROK 1948 only - Sep 13 0:00 0 S +-Rule ROK 1949 only - Apr 3 0:00 1:00 D +-Rule ROK 1949 1951 - Sep Sun>=8 0:00 0 S +-Rule ROK 1950 only - Apr 1 0:00 1:00 D +-Rule ROK 1951 only - May 6 0:00 1:00 D +-Rule ROK 1955 only - May 5 0:00 1:00 D +-Rule ROK 1955 only - Sep 9 0:00 0 S +-Rule ROK 1956 only - May 20 0:00 1:00 D +-Rule ROK 1956 only - Sep 30 0:00 0 S +-Rule ROK 1957 1960 - May Sun>=1 0:00 1:00 D +-Rule ROK 1957 1960 - Sep Sun>=18 0:00 0 S +-Rule ROK 1987 1988 - May Sun>=8 2:00 1:00 D +-Rule ROK 1987 1988 - Oct Sun>=8 3:00 0 S ++Rule ROK 1948 only - Jun 1 0:00 1:00 D ++Rule ROK 1948 only - Sep 12 24:00 0 S ++Rule ROK 1949 only - Apr 3 0:00 1:00 D ++Rule ROK 1949 1951 - Sep Sat>=7 24:00 0 S ++Rule ROK 1950 only - Apr 1 0:00 1:00 D ++Rule ROK 1951 only - May 6 0:00 1:00 D ++Rule ROK 1955 only - May 5 0:00 1:00 D ++Rule ROK 1955 only - Sep 8 24:00 0 S ++Rule ROK 1956 only - May 20 0:00 1:00 D ++Rule ROK 1956 only - Sep 29 24:00 0 S ++Rule ROK 1957 1960 - May Sun>=1 0:00 1:00 D ++Rule ROK 1957 1960 - Sep Sat>=17 24:00 0 S ++Rule ROK 1987 1988 - May Sun>=8 2:00 1:00 D ++Rule ROK 1987 1988 - Oct Sun>=8 3:00 0 S + + # From Paul Eggert (2016-08-23): + # The Korean Wikipedia entry gives the following sources for UT offsets: +@@ -2920,6 +3132,11 @@ + # no information + + # Philippines ++ ++# From Paul Eggert (2018-11-18): ++# The Spanish initially used American (west-of-Greenwich) time. ++# It is unknown what time Manila kept when the British occupied it from ++# 1762-10-06 through 1764-04; for now assume it kept American time. + # On 1844-08-16, Narciso Clavería, governor-general of the + # Philippines, issued a proclamation announcing that 1844-12-30 was to + # be immediately followed by 1845-01-01; see R.H. van Gent's +@@ -3005,8 +3222,8 @@ + # going to run on Higgins Time.' And so, until last year, it did." See: + # Antar E. Dinner at When? Saudi Aramco World, 1969 March/April. 2-3. + # http://archive.aramcoworld.com/issue/196902/dinner.at.when.htm +-# newspapers.com says a similar story about Higgins was published in the Port +-# Angeles (WA) Evening News, 1965-03-10, page 5, but I lack access to the text. ++# Also see: Antar EN. Arabian flying is confusing. ++# Port Angeles (WA) Evening News. 1965-03-10. page 3. + # + # The TZ database cannot represent quasi-solar time; airline time is the best + # we can do. The 1946 foreign air news digest of the U.S. Civil Aeronautics +--- contrib/tzdata/australasia.orig ++++ contrib/tzdata/australasia +@@ -402,10 +402,44 @@ + # it is uninhabited. + + # Guam ++ ++# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S ++# http://guamlegislature.com/Public_Laws_5th/PL05-025.pdf ++# http://documents.guam.gov/wp-content/uploads/E.O.-59-7-Guam-Daylight-Savings-Time-May-6-1959.pdf ++Rule Guam 1959 only - Jun 27 2:00 1:00 D ++# http://documents.guam.gov/wp-content/uploads/E.O.-61-5-Revocation-of-Daylight-Saving-Time-and-Restoratio.pdf ++Rule Guam 1961 only - Jan 29 2:00 0 S ++# http://documents.guam.gov/wp-content/uploads/E.O.-67-13-Guam-Daylight-Savings-Time.pdf ++Rule Guam 1967 only - Sep 1 2:00 1:00 D ++# http://documents.guam.gov/wp-content/uploads/E.O.-69-2-Repeal-of-Guam-Daylight-Saving-Time.pdf ++Rule Guam 1969 only - Jan 26 0:01 0 S ++# http://documents.guam.gov/wp-content/uploads/E.O.-69-10-Guam-Daylight-Saving-Time.pdf ++Rule Guam 1969 only - Jun 22 2:00 1:00 D ++Rule Guam 1969 only - Aug 31 2:00 0 S ++# http://documents.guam.gov/wp-content/uploads/E.O.-70-10-Guam-Daylight-Saving-Time.pdf ++# http://documents.guam.gov/wp-content/uploads/E.O.-70-30-End-of-Guam-Daylight-Saving-Time.pdf ++# http://documents.guam.gov/wp-content/uploads/E.O.-71-5-Guam-Daylight-Savings-Time.pdf ++Rule Guam 1970 1971 - Apr lastSun 2:00 1:00 D ++Rule Guam 1970 1971 - Sep Sun>=1 2:00 0 S ++# http://documents.guam.gov/wp-content/uploads/E.O.-73-28.-Guam-Day-light-Saving-Time.pdf ++Rule Guam 1973 only - Dec 16 2:00 1:00 D ++# http://documents.guam.gov/wp-content/uploads/E.O.-74-7-Guam-Daylight-Savings-Time-Rescinded.pdf ++Rule Guam 1974 only - Feb 24 2:00 0 S ++# http://documents.guam.gov/wp-content/uploads/E.O.-76-13-Daylight-Savings-Time.pdf ++Rule Guam 1976 only - May 26 2:00 1:00 D ++# http://documents.guam.gov/wp-content/uploads/E.O.-76-25-Revocation-of-E.O.-76-13.pdf ++Rule Guam 1976 only - Aug 22 2:01 0 S ++# http://documents.guam.gov/wp-content/uploads/E.O.-77-4-Daylight-Savings-Time.pdf ++Rule Guam 1977 only - Apr 24 2:00 1:00 D ++# http://documents.guam.gov/wp-content/uploads/E.O.-77-18-Guam-Standard-Time.pdf ++Rule Guam 1977 only - Aug 28 2:00 0 S ++ + # Zone NAME GMTOFF RULES FORMAT [UNTIL] + Zone Pacific/Guam -14:21:00 - LMT 1844 Dec 31 + 9:39:00 - LMT 1901 # Agana +- 10:00 - GST 2000 Dec 23 # Guam ++ 10:00 - GST 1941 Dec 10 # Guam ++ 9:00 - +09 1944 Jul 31 ++ 10:00 Guam G%sT 2000 Dec 23 + 10:00 - ChST # Chamorro Standard Time + Link Pacific/Guam Pacific/Saipan # N Mariana Is + +@@ -427,31 +461,56 @@ + + # Marshall Is + # Zone NAME GMTOFF RULES FORMAT [UNTIL] +-Zone Pacific/Majuro 11:24:48 - LMT 1901 +- 11:00 - +11 1969 Oct +- 12:00 - +12 +-Zone Pacific/Kwajalein 11:09:20 - LMT 1901 +- 11:00 - +11 1969 Oct +- -12:00 - -12 1993 Aug 20 +- 12:00 - +12 ++Zone Pacific/Majuro 11:24:48 - LMT 1901 ++ 11:00 - +11 1914 Oct ++ 9:00 - +09 1919 Feb 1 ++ 11:00 - +11 1937 ++ 10:00 - +10 1941 Apr 1 ++ 9:00 - +09 1944 Jan 30 ++ 11:00 - +11 1969 Oct ++ 12:00 - +12 ++Zone Pacific/Kwajalein 11:09:20 - LMT 1901 ++ 11:00 - +11 1937 ++ 10:00 - +10 1941 Apr 1 ++ 9:00 - +09 1944 Feb 6 ++ 11:00 - +11 1969 Oct ++ -12:00 - -12 1993 Aug 20 24:00 ++ 12:00 - +12 + + # Micronesia + # Zone NAME GMTOFF RULES FORMAT [UNTIL] +-Zone Pacific/Chuuk 10:07:08 - LMT 1901 +- 10:00 - +10 +-Zone Pacific/Pohnpei 10:32:52 - LMT 1901 # Kolonia +- 11:00 - +11 +-Zone Pacific/Kosrae 10:51:56 - LMT 1901 +- 11:00 - +11 1969 Oct +- 12:00 - +12 1999 +- 11:00 - +11 ++Zone Pacific/Chuuk -13:52:52 - LMT 1844 Dec 31 ++ 10:07:08 - LMT 1901 ++ 10:00 - +10 1914 Oct ++ 9:00 - +09 1919 Feb 1 ++ 10:00 - +10 1941 Apr 1 ++ 9:00 - +09 1945 Aug ++ 10:00 - +10 ++Zone Pacific/Pohnpei -13:27:08 - LMT 1844 Dec 31 # Kolonia ++ 10:32:52 - LMT 1901 ++ 11:00 - +11 1914 Oct ++ 9:00 - +09 1919 Feb 1 ++ 11:00 - +11 1937 ++ 10:00 - +10 1941 Apr 1 ++ 9:00 - +09 1945 Aug ++ 11:00 - +11 ++Zone Pacific/Kosrae -13:08:04 - LMT 1844 Dec 31 ++ 10:51:56 - LMT 1901 ++ 11:00 - +11 1914 Oct ++ 9:00 - +09 1919 Feb 1 ++ 11:00 - +11 1937 ++ 10:00 - +10 1941 Apr 1 ++ 9:00 - +09 1945 Aug ++ 11:00 - +11 1969 Oct ++ 12:00 - +12 1999 ++ 11:00 - +11 + + # Nauru + # Zone NAME GMTOFF RULES FORMAT [UNTIL] + Zone Pacific/Nauru 11:07:40 - LMT 1921 Jan 15 # Uaobe +- 11:30 - +1130 1942 Mar 15 +- 9:00 - +09 1944 Aug 15 +- 11:30 - +1130 1979 May ++ 11:30 - +1130 1942 Aug 29 ++ 9:00 - +09 1945 Sep 8 ++ 11:30 - +1130 1979 Feb 10 2:00 + 12:00 - +12 + + # New Caledonia +@@ -552,8 +611,9 @@ + + # Palau (Belau) + # Zone NAME GMTOFF RULES FORMAT [UNTIL] +-Zone Pacific/Palau 8:57:56 - LMT 1901 # Koror +- 9:00 - +09 ++Zone Pacific/Palau -15:02:04 - LMT 1844 Dec 31 # Koror ++ 8:57:56 - LMT 1901 ++ 9:00 - +09 + + # Papua New Guinea + # Zone NAME GMTOFF RULES FORMAT [UNTIL] +@@ -815,7 +875,7 @@ + # tz@iana.org for general use in the future). For more, please see + # the file CONTRIBUTING in the tz distribution. + +-# From Paul Eggert (2017-02-10): ++# From Paul Eggert (2018-11-18): + # + # Unless otherwise specified, the source for data through 1990 is: + # Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition), +@@ -840,6 +900,7 @@ + # A reliable and entertaining source about time zones is + # Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997). + # ++# I invented the abbreviation marked "*". + # The following abbreviations are from other sources. + # Corrections are welcome! + # std dst +@@ -847,7 +908,7 @@ + # 8:00 AWST AWDT Western Australia + # 9:30 ACST ACDT Central Australia + # 10:00 AEST AEDT Eastern Australia +-# 10:00 GST Guam through 2000 ++# 10:00 GST GDT* Guam through 2000 + # 10:00 ChST Chamorro + # 11:30 NZMT NZST New Zealand through 1945 + # 12:00 NZST NZDT New Zealand 1946-present +@@ -1546,28 +1607,70 @@ + + # Kwajalein + +-# In comp.risks 14.87 (26 August 1993), Peter Neumann writes: +-# I wonder what happened in Kwajalein, where there was NO Friday, +-# 1993-08-20. Thursday night at midnight Kwajalein switched sides with +-# respect to the International Date Line, to rejoin its fellow islands, +-# going from 11:59 p.m. Thursday to 12:00 m. Saturday in a blink. ++# From an AP article (1993-08-22): ++# "The nearly 3,000 Americans living on this remote Pacific atoll have a good ++# excuse for not remembering Saturday night: there wasn't one. Residents were ++# going to bed Friday night and waking up Sunday morning because at midnight ++# -- 8 A.M. Eastern daylight time on Saturday -- Kwajalein was jumping from ++# one side of the international date line to the other." ++# "In Marshall Islands, Friday is followed by Sunday", NY Times. 1993-08-22. ++# https://www.nytimes.com/1993/08/22/world/in-marshall-islands-friday-is-followed-by-sunday.html ++ ++# From Phake Nick (2018-10-27): ++# <https://wiki.suikawiki.org/n/南洋群島の標準時> ... pointed out that ++# currently tzdata say Pacific/Kwajalein switched from GMT+11 to GMT-12 in ++# 1969 October without explanation, however an 1993 article from NYT say it ++# synchorized its day with US mainland about 40 years ago and thus the switch ++# should occur at around 1950s instead. ++# ++# From Paul Eggert (2018-11-18): ++# The NYT (actually, AP) article is vague and possibly wrong about this. ++# The article says the earlier switch was "40 years ago when the United States ++# Army established a missile test range here". However, the Kwajalein Test ++# Center was established on 1960-10-01 and was run by the US Navy. It was ++# transferred to the US Army on 1964-07-01. See "Seize the High Ground" ++# <https://history.army.mil/html/books/070/70-88-1/cmhPub_70-88-1.pdf>. ++# Given that Shanks was right on the money about the 1993 change, I'm inclined ++# to take Shanks's word for the 1969 change unless we find better evidence. + + + # N Mariana Is, Guam + ++# From Phake Nick (2018-10-27): ++# Guam Island was briefly annexed by Japan during ... year 1941-1944 ... ++# however there are no detailed information about what time it use during that ++# period. It would probably be reasonable to assume Guam use GMT+9 during ++# that period of time like the surrounding area. ++ ++# From Paul Eggert (2018-11-18): + # Howse writes (p 153) "The Spaniards, on the other hand, reached the + # Philippines and the Ladrones from America," and implies that the Ladrones + # (now called the Marianas) kept American date for quite some time. + # For now, we assume the Ladrones switched at the same time as the Philippines; + # see Asia/Manila. +- ++# ++# Use 1941-12-10 and 1944-07-31 for Guam WWII transitions, as the rough start ++# and end of Japanese control of Agana. We don't know whether the Northern ++# Marianas followed Guam's DST rules from 1959 through 1977; for now, assume ++# they did as that avoids the need for a separate zone due to our 1970 cutoff. ++# + # US Public Law 106-564 (2000-12-23) made UT +10 the official standard time, + # under the name "Chamorro Standard Time". There is no official abbreviation, + # but Congressman Robert A. Underwood, author of the bill that became law, + # wrote in a press release (2000-12-27) that he will seek the use of "ChST". + ++# See also the commentary for Micronesia. + +-# Micronesia ++ ++# Marshall Is ++# See the commentary for Micronesia. ++ ++ ++# Micronesia (and nearby) ++ ++# From Paul Eggert (2018-11-18): ++# Like the Ladrones (see Guam commentary), assume the Spanish East Indies ++# kept American time until the Philippines switched at the end of 1844. + + # Alan Eugene Davis writes (1996-03-16), + # "I am certain, having lived there for the past decade, that 'Truk' +@@ -1583,6 +1686,95 @@ + # that Truk and Yap are UT +10, and Ponape and Kosrae are +11. + # We don't know when Kosrae switched from +12; assume January 1 for now. + ++# From Phake Nick (2018-10-27): ++# ++# From a Japanese wiki site https://wiki.suikawiki.org/n/南洋群島の標準時 ++# ... ++# For "Southern Islands" (modern region of Mariana + Palau + Federation of ++# Micronesia + Marshall Islands): ++# ++# A 1906 Japanese magazine shown the Caroline Islands and Mariana Islands ++# who was occupied by Germany at the time as GMT+10, together with the like ++# of German New Guinea. However there is a marking saying it have not been ++# implemented (yet). No further information after that were found. ++# ++# Japan invaded those islands in 1914, and records shows that they were ++# instructed to use JST at the time. ++# ++# 1915 January telecommunication record on the Jaluit Atoll shows they use ++# the meridian of 170E as standard time (GMT+11:20), which is similar to the ++# longitude of the atoll. ++# 1915 February record say the 170E standard time is to be used until ++# February 9 noon, and after February 9 noon they are to use JST. ++# However these are time used within the Japanese Military at the time and ++# probably does not reflect the time used by local resident at the time (that ++# is if they keep their own time back then) ++# ++# In January 1919 the occupying force issued a command that split the area ++# into three different timezone with meridian of 135E, 150E, 165E (JST+0, +1, ++# +2), and the command was to become effective from February 1 of the same ++# year. Despite the target of the command is still only for the occupying ++# force itself, further publication have described the time as the standard ++# time for the occupied area and thus it can probably be seen as such. ++# * Area that use meridian of 135E: Palau and Yap civil administration area ++# (Southern Islands Western Standard Time) ++# * Area that use meridian of 150E: Truk (Chuuk) and Saipan civil ++# administration area (Southern Islands Central Standard Time) ++# * Area that use meridian of 165E: Ponape (Pohnpei) and Jaluit civil ++# administration area (Southern Islands Eastern Standard Time). ++# * In the next few years Japanese occupation of those islands have been ++# formalized via League of Nation Mandate (South Pacific Mandate) and formal ++# governance structure have been established, these district [become ++# subprefectures] and timezone classification have been inherited as standard ++# time of the area. ++# * Saipan subprefecture include Mariana islands (exclude Guam which was ++# occupied by America at the time), Palau and Yap subprefecture rule the ++# Western Caroline Islands with 137E longitude as border, Truk and Ponape ++# subprefecture rule the Eastern Caroline Islands with 154E as border, Ponape ++# subprefecture also rule part of Marshall Islands to the west of 164E ++# starting from (1918?) and Jaluit subprefecture rule the rest of the ++# Marshall Islands. ++# ++# And then in year 1937, an announcement was made to change the time in the ++# area into 2 timezones: ++# * Area that use meridian of 135E: area administered by Palau, Yap and ++# Saipan subprefecture (Southern Islands Western Standard Time) ++# * Area that use meridian of 150E: area administered by Truk (Chuuk), ++# Ponape (Pohnpei) and Jaluit subprefecture (Southern Islands Eastern ++# Standard Time) ++# ++# Another announcement issued in 1941 say that on April 1 that year, ++# standard time of the Southern Islands would be changed to use the meridian ++# of 135E (GMT+9), and thus abolishing timezone different within the area. ++# ++# Then Pacific theater of WWII started and Japan slowly lose control on the ++# island. The webpage I linked above contain no information during this ++# period of time.... ++# ++# After the end of WWII, in 1946 February, a document written by the ++# (former?) Japanese military personnel describe there are 3 hours time ++# different between Caroline islands time/Wake island time and the Chungking ++# time, which would mean the time being used there at the time was GMT+10. ++# ++# After that, the area become Trust Territories of the Pacific Islands ++# under American administration from year 1947. The site listed some ++# American/International books/maps/publications about time used in those ++# area during this period of time but they doesn't seems to be reliable ++# information so it would be the best if someone know where can more reliable ++# information can be found. ++# ++# ++# From Paul Eggert (2018-11-18): ++# ++# For the above, use vague dates like "1914" and "1945" for transitions that ++# plausibly exist but for which the details are not known. The information ++# for Wake is too sketchy to act on. ++# ++# The 1906 GMT+10 info about German-controlled islands might not have been ++# done, so omit it from the data for now. ++# ++# The Jaluit info governs Kwajalein. ++ + + # Midway + +@@ -1600,6 +1792,29 @@ + # started DST on June 3. Possibly DST was observed other years + # in Midway, but we have no record of it. + ++# Nauru ++ ++# From Phake Nick (2018-10-31): ++# Currently, the tz database say Nauru use LMT until 1921, and then ++# switched to GMT+11:30 for the next two decades. ++# However, a number of timezone map published in America/Japan back then ++# showed its timezone as GMT+11 per https://wiki.suikawiki.org/n/ナウルの標準時 ++# And it would also be nice if the 1921 transition date could be sourced. ++# ... ++# The "Nauru Standard Time Act 1978 Time Change" ++# http://ronlaw.gov.nr/nauru_lpms/files/gazettes/4b23a17d2030150404db7a5fa5872f52.pdf#page=3 ++# based on "Nauru Standard Time Act 1978 Time Change" ++# http://www.paclii.org/nr/legis/num_act/nsta1978207/ defined that "Nauru ++# Alternative Time" (GMT+12) should be in effect from 1979 Feb. ++# ++# From Paul Eggert (2018-11-19): ++# The 1921-01-15 introduction of standard time is in Shanks; it is also in ++# "Standard Time Throughout the World", US National Bureau of Standards (1935), ++# page 3, which does not give the UT offset. In response to a comment by ++# Phake Nick I set the Nauru time of occupation by Japan to ++# 1942-08-29/1945-09-08 by using dates from: ++# https://en.wikipedia.org/wiki/Japanese_occupation_of_Nauru ++ + # Norfolk + + # From Alexander Krivenyshev (2015-09-23): +@@ -1615,6 +1830,9 @@ + # other than in 1974/5. See: + # https://www.timeanddate.com/time/australia/norfolk-island.html + ++# Palau ++# See commentary for Micronesia. ++ + # Pitcairn + + # From Rives McDow (1999-11-08): +@@ -1779,6 +1997,9 @@ + # From Paul Eggert (2003-03-23): + # We have no other report of DST in Wake Island, so omit this info for now. + ++# See also the commentary for Micronesia. ++ ++ + ############################################################################### + + # The International Date Line +--- contrib/tzdata/leapseconds.orig ++++ contrib/tzdata/leapseconds +@@ -19,9 +19,12 @@ + # See: Levine J. Coordinated Universal Time and the leap second. + # URSI Radio Sci Bull. 2016;89(4):30-6. doi:10.23919/URSIRSB.2016.7909995 + # <https://ieeexplore.ieee.org/document/7909995>. ++ + # There were no leap seconds before 1972, because the official mechanism + # accounting for the discrepancy between atomic time and the earth's rotation +-# did not exist. ++# did not exist. The first ("1 Jan 1972") data line in leap-seconds.list ++# does not denote a leap second; it denotes the start of the current definition ++# of UTC. + + # The correction (+ or -) is made at the given time, so lines + # will typically look like: +--- contrib/tzdata/leapseconds.awk.orig ++++ contrib/tzdata/leapseconds.awk +@@ -24,9 +24,12 @@ + print "# See: Levine J. Coordinated Universal Time and the leap second." + print "# URSI Radio Sci Bull. 2016;89(4):30-6. doi:10.23919/URSIRSB.2016.7909995" + print "# <https://ieeexplore.ieee.org/document/7909995>." ++ print "" + print "# There were no leap seconds before 1972, because the official mechanism" + print "# accounting for the discrepancy between atomic time and the earth's rotation" +- print "# did not exist." ++ print "# did not exist. The first (\"1 Jan 1972\") data line in leap-seconds.list" ++ print "# does not denote a leap second; it denotes the start of the current definition" ++ print"# of UTC." + print "" + print "# The correction (+ or -) is made at the given time, so lines" + print "# will typically look like:" +--- contrib/tzdata/northamerica.orig ++++ contrib/tzdata/northamerica +@@ -599,6 +599,17 @@ + # between AKST and AKDT from now on.... + # https://www.krbd.org/2015/10/30/annette-island-times-they-are-a-changing/ + ++# From Ryan Stanley (2018-11-06): ++# The Metlakatla community in Alaska has decided not to change its ++# clock back an hour starting on November 4th, 2018 (day before yesterday). ++# They will be gmtoff=-28800 year-round. ++# https://www.facebook.com/141055983004923/photos/pb.141055983004923.-2207520000.1541465673./569081370202380/ ++ ++# From Paul Eggert (2018-12-16): ++# In a 2018-12-11 special election, Metlakatla voted to go back to ++# Alaska time (including daylight saving time) starting next year. ++# https://www.krbd.org/2018/12/12/metlakatla-to-follow-alaska-standard-time-allow-liquor-sales/ ++ + # Zone NAME GMTOFF RULES FORMAT [UNTIL] + Zone America/Juneau 15:02:19 - LMT 1867 Oct 19 15:33:32 + -8:57:41 - LMT 1900 Aug 20 12:00 +@@ -625,6 +636,8 @@ + -8:00 - PST 1969 + -8:00 US P%sT 1983 Oct 30 2:00 + -8:00 - PST 2015 Nov 1 2:00 ++ -9:00 US AK%sT 2018 Nov 4 2:00 ++ -8:00 - PST 2019 Mar Sun>=8 3:00 + -9:00 US AK%sT + Zone America/Yakutat 14:41:05 - LMT 1867 Oct 19 15:12:18 + -9:18:55 - LMT 1900 Aug 20 12:00 +@@ -785,6 +798,22 @@ + # For a map of Indiana's time zone regions, see: + # https://en.wikipedia.org/wiki/Time_in_Indiana + # ++# From Paul Eggert (2018-11-30): ++# A brief but entertaining history of time in Indiana describes a 1949 debate ++# in the Indiana House where city legislators (who favored "fast time") ++# tussled with farm legislators (who didn't) over a bill to outlaw DST: ++# "Lacking enough votes, the city faction tries to filibuster until time runs ++# out on the session at midnight, but rural champion Rep. Herbert Copeland, ++# R-Madison, leans over the gallery railing and forces the official clock ++# back to 9 p.m., breaking it in the process. The clock sticks on 9 as the ++# debate rages on into the night. The filibuster finally dies out and the ++# bill passes, while outside the chamber, clocks read 3:30 a.m. In the end, ++# it doesn't matter which side won. The law has no enforcement powers and ++# is simply ignored by fast-time communities." ++# How Indiana went from 'God's time' to split zones and daylight-saving. ++# Indianapolis Star. 2018-11-27 14:58 -05. ++# https://www.indystar.com/story/news/politics/2018/11/27/indianapolis-indiana-time-zone-history-central-eastern-daylight-savings-time/2126300002/ ++# + # From Paul Eggert (2007-08-17): + # Since 1970, most of Indiana has been like America/Indiana/Indianapolis, + # with the following exceptions: +--- contrib/tzdata/theory.html.orig ++++ contrib/tzdata/theory.html +@@ -406,7 +406,7 @@ + EAT East Africa, + EST/EDT/EWT/EPT/EDDT Eastern [North America], + EET/EEST Eastern European, +- GST Guam, ++ GST/GDT Guam, + HST/HDT/HWT/HPT Hawaii, + HKT/HKST Hong Kong, + IST India, +@@ -1238,7 +1238,7 @@ + use <a href="https://en.wikipedia.org/wiki/Timekeeping_on_Mars">Mars time</a>. + Jet Propulsion Laboratory (JPL) coordinators kept Mars time on + and off during the +-<a href="https://en.wikipedia.org/wiki/Mars_Pathfinder#End_of_mission">Mars ++<a href="https://en.wikipedia.org/wiki/Mars_Pathfinder">Mars + Pathfinder</a> mission. + Some of their family members also adapted to Mars time. + Dozens of special Mars watches were built for JPL workers who kept +@@ -1261,8 +1261,7 @@ + honor of the British astronomer who built the Greenwich telescope that + defines Earth's prime meridian. + Mean solar time on the Mars prime meridian is +-called <a href="https://en.wikipedia.org/wiki/Mars_Coordinated_Time">Mars +-Coordinated Time (<abbr>MTC</abbr>)</a>. ++called Mars Coordinated Time (<abbr>MTC</abbr>). + </p> + + <p> +--- contrib/tzdata/version.orig ++++ contrib/tzdata/version +@@ -1 +1 @@ +-2018g ++2018i +--- contrib/tzdata/ziguard.awk.orig ++++ contrib/tzdata/ziguard.awk +@@ -54,7 +54,7 @@ + } + } + +- # If this line should differ due to Namibia using Rule SAVE suffixes, ++ # If this line should differ due to Namibia using negative SAVE values, + # uncomment the desired version and comment out the undesired one. + Rule_Namibia = /^#?Rule[\t ]+Namibia[\t ]/ + Zone_using_Namibia_rule \ +@@ -87,6 +87,23 @@ + sub(/Sat>=8/, "Sun>=9") + sub(/25:00/, " 1:00") + } ++ ++ # In rearguard format, change the Morocco lines with negative SAVE values ++ # to use positive SAVE values. ++ if (!vanguard && $1 == "Rule" && $2 == "Morocco" && $4 == 2018 \ ++ && $6 == "Oct") { ++ sub(/\t2018\t/, "\t2017\t") ++ } ++ if (!vanguard && $1 == "Rule" && $2 == "Morocco" && 2019 <= $3) { ++ if ($9 == "0") { ++ sub(/\t0\t/, "\t1:00\t") ++ } else { ++ sub(/\t-1:00\t/, "\t0\t") ++ } ++ } ++ if (!vanguard && $1 == "1:00" && $2 == "Morocco" && $3 == "+01/+00") { ++ sub(/1:00\tMorocco\t\+01\/\+00$/, "0:00\tMorocco\t+00/+01") ++ } + } + + # If a Link line is followed by a Zone line for the same data, comment +--- contrib/tzdata/zone.tab.orig ++++ contrib/tzdata/zone.tab +@@ -239,6 +239,7 @@ + KY +1918-08123 America/Cayman + KZ +4315+07657 Asia/Almaty Kazakhstan (most areas) + KZ +4448+06528 Asia/Qyzylorda Qyzylorda/Kyzylorda/Kzyl-Orda ++KZ +5312+06337 Asia/Qostanay Qostanay/Kostanay/Kustanay + KZ +5017+05710 Asia/Aqtobe Aqtobe/Aktobe + KZ +4431+05016 Asia/Aqtau Mangghystau/Mankistau + KZ +4707+05156 Asia/Atyrau Atyrau/Atirau/Gur'yev +@@ -332,9 +333,9 @@ + RU +5443+02030 Europe/Kaliningrad MSK-01 - Kaliningrad + RU +554521+0373704 Europe/Moscow MSK+00 - Moscow area + RU +4457+03406 Europe/Simferopol MSK+00 - Crimea +-RU +4844+04425 Europe/Volgograd MSK+00 - Volgograd + RU +5836+04939 Europe/Kirov MSK+00 - Kirov + RU +4621+04803 Europe/Astrakhan MSK+01 - Astrakhan ++RU +4844+04425 Europe/Volgograd MSK+01 - Volgograd + RU +5134+04602 Europe/Saratov MSK+01 - Saratov + RU +5420+04824 Europe/Ulyanovsk MSK+01 - Ulyanovsk + RU +5312+05009 Europe/Samara MSK+01 - Samara, Udmurtia +--- contrib/tzdata/zone1970.tab.orig ++++ contrib/tzdata/zone1970.tab +@@ -212,6 +212,7 @@ + KR +3733+12658 Asia/Seoul + KZ +4315+07657 Asia/Almaty Kazakhstan (most areas) + KZ +4448+06528 Asia/Qyzylorda Qyzylorda/Kyzylorda/Kzyl-Orda ++KZ +5312+06337 Asia/Qostanay Qostanay/Kostanay/Kustanay + KZ +5017+05710 Asia/Aqtobe Aqtöbe/Aktobe + KZ +4431+05016 Asia/Aqtau Mangghystaū/Mankistau + KZ +4707+05156 Asia/Atyrau Atyraū/Atirau/Gur'yev +@@ -290,9 +291,9 @@ + RU +5443+02030 Europe/Kaliningrad MSK-01 - Kaliningrad + RU +554521+0373704 Europe/Moscow MSK+00 - Moscow area + RU +4457+03406 Europe/Simferopol MSK+00 - Crimea +-RU +4844+04425 Europe/Volgograd MSK+00 - Volgograd + RU +5836+04939 Europe/Kirov MSK+00 - Kirov + RU +4621+04803 Europe/Astrakhan MSK+01 - Astrakhan ++RU +4844+04425 Europe/Volgograd MSK+01 - Volgograd + RU +5134+04602 Europe/Saratov MSK+01 - Saratov + RU +5420+04824 Europe/Ulyanovsk MSK+01 - Ulyanovsk + RU +5312+05009 Europe/Samara MSK+01 - Samara, Udmurtia diff --git a/share/security/patches/EN-19:04/tzdata-2018i.patch.asc b/share/security/patches/EN-19:04/tzdata-2018i.patch.asc new file mode 100644 index 0000000000..920b446bcd --- /dev/null +++ b/share/security/patches/EN-19:04/tzdata-2018i.patch.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- + +iQKTBAABCgB9FiEE/A6HiuWv54gCjWNV05eS9J6n5cIFAlw2Ri1fFIAAAAAALgAo +aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldEZD +MEU4NzhBRTVBRkU3ODgwMjhENjM1NUQzOTc5MkY0OUVBN0U1QzIACgkQ05eS9J6n +5cJtHA/+JOl78JntS1QrQn11yftlRvHgwMHbp8tOpQ9TWNsuw0uBpeIbf8ZqGRaK +BGMW+Ph77x2dMD8tt8sGYDWy1xsUUVfy7EGF7zEFjCx69hGFxno652/MrGvCYNgo +tWfbjYJhJsHaplkNFZPdIvtWfQ1IGGHKEUMnTEoCr75NeXscuUCpBtpZFnJdYry+ +EHCHd2/If/49YF0PPs7zctM02KPAb52h+wwdbv19HyBD1UWuqGb3YZEPsH1btSs6 +iAdEut+nrFBt5iL+fJE+CRTFXWyZoU5WD95+fmb4p4dPtisCey5QE0iSN/MCw5xB +Kj6+MuRJ+jAmWufNE+DIJYbSqosIH9zvDt0NXpgWUOlsdE87jdMGl0DgNK7eaScQ +5AqeUFFXgv63kHXl90vln/m+rIYI3xjkrAij6mkjDHAIFpE9rKVtQAezbxZ/6p7v +ZoIY4d8mb8oZhRfwd8/mAvzqTQWFnyw0OImzk7NMLj9a4idq0eTyXq1qbceuc1pt +QUJtbWfKDptN9GDNPE37FulsiLufaeNPleA54U4XRLyBYMnZfc4yPfdcy8b10GCf +zwy6bn+mZaFsOkMoLHd2pRV3erdXF8H42qUGAAW9I9Zqy2+hN87IDZ2ZUPHEYdxF +5+jD/4HsHgFgMjakP/7CJPdcVrf/pyY2PGP1Qf5dS8C4wqvbl/k= +=9pQl +-----END PGP SIGNATURE----- diff --git a/share/security/patches/EN-19:05/kqueue.patch b/share/security/patches/EN-19:05/kqueue.patch new file mode 100644 index 0000000000..944273e4c5 --- /dev/null +++ b/share/security/patches/EN-19:05/kqueue.patch @@ -0,0 +1,49 @@ +--- sys/kern/kern_event.c.orig ++++ sys/kern/kern_event.c +@@ -1296,6 +1296,8 @@ + kn->kn_kevent.flags &= ~(EV_ADD | EV_DELETE | + EV_ENABLE | EV_DISABLE | EV_FORCEONESHOT); + kn->kn_status = KN_INFLUX|KN_DETACHED; ++ if ((kev->flags & EV_DISABLE) != 0) ++ kn->kn_status |= KN_DISABLED; + + error = knote_attach(kn, kq); + KQ_UNLOCK(kq); +@@ -1332,6 +1334,11 @@ + KNOTE_ACTIVATE(kn, 1); + } + ++ if ((kev->flags & EV_ENABLE) != 0) ++ kn->kn_status &= ~KN_DISABLED; ++ else if ((kev->flags & EV_DISABLE) != 0) ++ kn->kn_status |= KN_DISABLED; ++ + /* + * The user may change some filter values after the initial EV_ADD, + * but doing so will not reset any filter which has already been +@@ -1348,19 +1355,17 @@ + kn->kn_sdata = kev->data; + } + ++done_ev_add: + /* + * We can get here with kn->kn_knlist == NULL. This can happen when + * the initial attach event decides that the event is "completed" +- * already. i.e. filt_procattach is called on a zombie process. It +- * will call filt_proc which will remove it from the list, and NULL ++ * already, e.g., filt_procattach() is called on a zombie process. It ++ * will call filt_proc() which will remove it from the list, and NULL + * kn_knlist. ++ * ++ * KN_DISABLED will be stable while the knote is in flux, so the ++ * unlocked read will not race with an update. + */ +-done_ev_add: +- if ((kev->flags & EV_ENABLE) != 0) +- kn->kn_status &= ~KN_DISABLED; +- else if ((kev->flags & EV_DISABLE) != 0) +- kn->kn_status |= KN_DISABLED; +- + if ((kn->kn_status & KN_DISABLED) == 0) + event = kn->kn_fop->f_event(kn, 0); + else diff --git a/share/security/patches/EN-19:05/kqueue.patch.asc b/share/security/patches/EN-19:05/kqueue.patch.asc new file mode 100644 index 0000000000..00d917b91e --- /dev/null +++ b/share/security/patches/EN-19:05/kqueue.patch.asc @@ -0,0 +1,18 @@ +-----BEGIN PGP SIGNATURE----- + +iQKTBAABCgB9FiEE/A6HiuWv54gCjWNV05eS9J6n5cIFAlw2RjRfFIAAAAAALgAo +aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldEZD +MEU4NzhBRTVBRkU3ODgwMjhENjM1NUQzOTc5MkY0OUVBN0U1QzIACgkQ05eS9J6n +5cLrQRAAlMBtUSxbiSdLI8KfeKYj2Xe2cAvVfK+oK+pooErNX6TyofIyewrck4PB +xZ/c7clZg3WRKAZJ1D6RacF02coBlCJHJbajMtjrIO6p3lXLX7FalxrIc9APiDI1 +n5he7Ij5Uu6FedPqJmSu81wOfInI+mX6vhap2UFrajFXI1iexhT4FiANtHGxTQwG +I8GlFfptT7QY1dUugt2+KRoYFobUv4SQynhgDb1CfMZ55SCjnkEPIqE6dMsv/f4d +iKBQoMmI8oBB6LLP1YhsidgG7LS84A+CwGXf9KQHRrugU9pPy2b8nQodGBzfmv4c +UaVJYO7hIkCof+4loloJrxEATWNnb2V5XlJumY6ENQwCCjttD/TOnfAAbUCkajZW +t+LZu5MkTZpx/Zyby9ojHl6yd7u7Cc2klN56vyOjGGBZ9PbXjsrwllEonnlHEThY +NDwcML8kjXPCXwgHtysKTxJKT9HsaG5tL/PMdTeHUwmkAfYyOeOTL14wpoF5//tc +akIcGw5qQjfFFaFCkfdFwktF63Hdsv8/G56sDBYHsdPE7Bwj4cnJhasWWtUTTN5t +XOvxoGUMOKwyQ/tUlNHvuyOEieEy781LYqHhVQObI00qkeSOJmwKaDuOjNd64wjv +2jJ4ZLegckyQlYR4GKGr6L0h6WTyL+d4xXZ7EcOxdkDa/dAYnHQ= +=Er0a +-----END PGP SIGNATURE----- diff --git a/share/xml/notices.xml b/share/xml/notices.xml index 727498cf8f..bfa31e39f9 100644 --- a/share/xml/notices.xml +++ b/share/xml/notices.xml @@ -4,6 +4,39 @@ $FreeBSD$ </cvs:keyword> + <year> + <name>2019</name> + + <month> + <name>1</name> + + <day> + <name>9</name> + + <notice> + <name>FreeBSD-EN-19:05.kqueue</name> + </notice> + + <notice> + <name>FreeBSD-EN-19:04.tzdata</name> + </notice> + + <notice> + <name>FreeBSD-EN-19:03.sqlite</name> + </notice> + + <notice> + <name>FreeBSD-EN-19:02.tcp</name> + </notice> + + <notice> + <name>FreeBSD-EN-19:01.cc_cubic</name> + </notice> + + </day> + </month> + </year> + <year> <name>2018</name>