Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge latest trunk changes into this branch. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | begin-concurrent |
Files: | files | file ages | folders |
SHA3-256: |
b27bd799ea66748b89223044c536813d |
User & Date: | dan 2018-04-24 19:21:38.067 |
Context
2018-04-26
| ||
17:54 | Merge latest changes from trunk. Including the "ORDER BY ... LIMIT" optimization. (check-in: d8ae7ba083 user: dan tags: begin-concurrent) | |
2018-04-24
| ||
19:22 | Update this branch with latest changes from trunk. (check-in: 2d8d13e4a1 user: dan tags: begin-concurrent-pnu) | |
19:21 | Merge latest trunk changes into this branch. (check-in: b27bd799ea user: dan tags: begin-concurrent) | |
18:59 | Remove a recently added NEVER() macro from a branch that can be taken in obscure circumstances. (check-in: 2aa210030a user: dan tags: trunk) | |
2018-03-20
| ||
13:54 | Remove debugging puts from concurrrent3.test. (check-in: 13b4975681 user: drh tags: begin-concurrent) | |
Changes
Changes to Makefile.in.
︙ | ︙ | |||
183 184 185 186 187 188 189 | memdb.lo memjournal.lo \ mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \ notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \ pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \ random.lo resolve.lo rowset.lo rtree.lo \ sqlite3session.lo select.lo sqlite3rbu.lo status.lo stmt.lo \ table.lo threads.lo tokenize.lo treeview.lo trigger.lo \ | | | 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | memdb.lo memjournal.lo \ mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \ notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \ pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \ random.lo resolve.lo rowset.lo rtree.lo \ sqlite3session.lo select.lo sqlite3rbu.lo status.lo stmt.lo \ table.lo threads.lo tokenize.lo treeview.lo trigger.lo \ update.lo upsert.lo util.lo vacuum.lo \ vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \ vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \ utf.lo vtab.lo # Object files for the amalgamation. # LIBOBJS1 = sqlite3.lo |
︙ | ︙ | |||
280 281 282 283 284 285 286 287 288 289 290 291 292 293 | $(TOP)/src/tclsqlite.c \ $(TOP)/src/threads.c \ $(TOP)/src/tokenize.c \ $(TOP)/src/treeview.c \ $(TOP)/src/trigger.c \ $(TOP)/src/utf.c \ $(TOP)/src/update.c \ $(TOP)/src/util.c \ $(TOP)/src/vacuum.c \ $(TOP)/src/vdbe.c \ $(TOP)/src/vdbe.h \ $(TOP)/src/vdbeapi.c \ $(TOP)/src/vdbeaux.c \ $(TOP)/src/vdbeblob.c \ | > | 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 | $(TOP)/src/tclsqlite.c \ $(TOP)/src/threads.c \ $(TOP)/src/tokenize.c \ $(TOP)/src/treeview.c \ $(TOP)/src/trigger.c \ $(TOP)/src/utf.c \ $(TOP)/src/update.c \ $(TOP)/src/upsert.c \ $(TOP)/src/util.c \ $(TOP)/src/vacuum.c \ $(TOP)/src/vdbe.c \ $(TOP)/src/vdbe.h \ $(TOP)/src/vdbeapi.c \ $(TOP)/src/vdbeaux.c \ $(TOP)/src/vdbeblob.c \ |
︙ | ︙ | |||
910 911 912 913 914 915 916 917 918 919 920 921 922 923 | trigger.lo: $(TOP)/src/trigger.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/trigger.c update.lo: $(TOP)/src/update.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/update.c utf.lo: $(TOP)/src/utf.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/utf.c util.lo: $(TOP)/src/util.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/util.c vacuum.lo: $(TOP)/src/vacuum.c $(HDR) | > > > | 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 | trigger.lo: $(TOP)/src/trigger.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/trigger.c update.lo: $(TOP)/src/update.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/update.c upsert.lo: $(TOP)/src/upsert.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/upsert.c utf.lo: $(TOP)/src/utf.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/utf.c util.lo: $(TOP)/src/util.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/util.c vacuum.lo: $(TOP)/src/vacuum.c $(HDR) |
︙ | ︙ |
Changes to Makefile.msc.
︙ | ︙ | |||
1189 1190 1191 1192 1193 1194 1195 | memdb.lo memjournal.lo \ mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \ notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \ pager.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \ random.lo resolve.lo rowset.lo rtree.lo \ sqlite3session.lo select.lo sqlite3rbu.lo status.lo \ table.lo threads.lo tokenize.lo treeview.lo trigger.lo \ | | | 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 | memdb.lo memjournal.lo \ mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \ notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \ pager.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \ random.lo resolve.lo rowset.lo rtree.lo \ sqlite3session.lo select.lo sqlite3rbu.lo status.lo \ table.lo threads.lo tokenize.lo treeview.lo trigger.lo \ update.lo upsert.lo util.lo vacuum.lo \ vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \ vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \ utf.lo vtab.lo # <</mark>> # Object files for the amalgamation. # |
︙ | ︙ | |||
1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 | $(TOP)\src\threads.c \ $(TOP)\src\tclsqlite.c \ $(TOP)\src\tokenize.c \ $(TOP)\src\treeview.c \ $(TOP)\src\trigger.c \ $(TOP)\src\utf.c \ $(TOP)\src\update.c \ $(TOP)\src\util.c \ $(TOP)\src\vacuum.c \ $(TOP)\src\vdbe.c \ $(TOP)\src\vdbeapi.c \ $(TOP)\src\vdbeaux.c \ $(TOP)\src\vdbeblob.c \ $(TOP)\src\vdbemem.c \ | > | 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 | $(TOP)\src\threads.c \ $(TOP)\src\tclsqlite.c \ $(TOP)\src\tokenize.c \ $(TOP)\src\treeview.c \ $(TOP)\src\trigger.c \ $(TOP)\src\utf.c \ $(TOP)\src\update.c \ $(TOP)\src\upsert.c \ $(TOP)\src\util.c \ $(TOP)\src\vacuum.c \ $(TOP)\src\vdbe.c \ $(TOP)\src\vdbeapi.c \ $(TOP)\src\vdbeaux.c \ $(TOP)\src\vdbeblob.c \ $(TOP)\src\vdbemem.c \ |
︙ | ︙ | |||
1668 1669 1670 1671 1672 1673 1674 | $(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP) $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL $(CORE_LINK_OPTS) /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) # <<block2>> sqlite3.def: libsqlite3.lib echo EXPORTS > sqlite3.def dumpbin /all libsqlite3.lib \ | | | 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 | $(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP) $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL $(CORE_LINK_OPTS) /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) # <<block2>> sqlite3.def: libsqlite3.lib echo EXPORTS > sqlite3.def dumpbin /all libsqlite3.lib \ | $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3(?:session|changeset|changegroup|rebaser)?_[^@]*)(?:@\d+)?$$" \1 \ | sort >> sqlite3.def # <</block2>> $(SQLITE3EXE): shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H) $(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) shell.c $(SHELL_CORE_SRC) \ /link $(SQLITE3EXEPDB) $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS) |
︙ | ︙ | |||
1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 | trigger.lo: $(TOP)\src\trigger.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\trigger.c update.lo: $(TOP)\src\update.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\update.c utf.lo: $(TOP)\src\utf.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\utf.c util.lo: $(TOP)\src\util.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\util.c vacuum.lo: $(TOP)\src\vacuum.c $(HDR) | > > > | 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 | trigger.lo: $(TOP)\src\trigger.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\trigger.c update.lo: $(TOP)\src\update.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\update.c upsert.lo: $(TOP)\src\upsert.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\upsert.c utf.lo: $(TOP)\src\utf.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\utf.c util.lo: $(TOP)\src\util.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\util.c vacuum.lo: $(TOP)\src\vacuum.c $(HDR) |
︙ | ︙ | |||
2087 2088 2089 2090 2091 2092 2093 | keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe .\mkkeywordhash.exe > keywordhash.h # Source files that go into making shell.c SHELL_SRC = \ $(TOP)\src\shell.c.in \ | | | 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 | keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe .\mkkeywordhash.exe > keywordhash.h # Source files that go into making shell.c SHELL_SRC = \ $(TOP)\src\shell.c.in \ $(TOP)\ext\misc\appendvfs.c \ $(TOP)\ext\misc\shathree.c \ $(TOP)\ext\misc\fileio.c \ $(TOP)\ext\misc\completion.c \ $(TOP)\ext\expert\sqlite3expert.c \ $(TOP)\ext\expert\sqlite3expert.h \ $(TOP)\src\test_windirent.c |
︙ | ︙ |
Changes to README.md.
1 2 3 4 5 6 | <h1 align="center">SQLite Source Repository</h1> This repository contains the complete source code for the SQLite database engine. Some test scripts are also included. However, many other test scripts and most of the documentation are managed separately. | > | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <h1 align="center">SQLite Source Repository</h1> This repository contains the complete source code for the SQLite database engine. Some test scripts are also included. However, many other test scripts and most of the documentation are managed separately. SQLite [does not use Git](https://sqlite.org/whynotgit.html). If you are reading this on GitHub, then you are looking at an unofficial mirror. See <https://sqlite.org/src> for the official repository. ## Obtaining The Code SQLite sources are managed using the [Fossil](https://www.fossil-scm.org/), a distributed version control system that was specifically designed to support SQLite development. If you do not want to use Fossil, you can download tarballs or ZIP |
︙ | ︙ |
Changes to VERSION.
|
| | | 1 | 3.24.0 |
Changes to autoconf/Makefile.msc.
︙ | ︙ | |||
962 963 964 965 966 967 968 | Replace.exe: $(CSC) /target:exe $(TOP)\Replace.cs sqlite3.def: Replace.exe $(LIBOBJ) echo EXPORTS > sqlite3.def dumpbin /all $(LIBOBJ) \ | | | 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 | Replace.exe: $(CSC) /target:exe $(TOP)\Replace.cs sqlite3.def: Replace.exe $(LIBOBJ) echo EXPORTS > sqlite3.def dumpbin /all $(LIBOBJ) \ | .\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) $(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) shell.c $(SHELL_CORE_SRC) \ /link $(SQLITE3EXEPDB) $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS) |
︙ | ︙ |
Changes to configure.
1 2 | #! /bin/sh # Guess values for system-dependent variables and create Makefiles. | | | 1 2 3 4 5 6 7 8 9 10 | #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for sqlite 3.24.0. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. |
︙ | ︙ | |||
722 723 724 725 726 727 728 | subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' | | | | 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 | subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' PACKAGE_VERSION='3.24.0' PACKAGE_STRING='sqlite 3.24.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include <stdio.h> #ifdef HAVE_SYS_TYPES_H |
︙ | ︙ | |||
1461 1462 1463 1464 1465 1466 1467 | # # 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 | | | 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 | # # 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.24.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. |
︙ | ︙ | |||
1526 1527 1528 1529 1530 1531 1532 | --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in | | | 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 | --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of sqlite 3.24.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] |
︙ | ︙ | |||
1651 1652 1653 1654 1655 1656 1657 | cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF | | | 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 | 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.24.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 |
︙ | ︙ | |||
2070 2071 2072 2073 2074 2075 2076 | eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. | | | 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 | eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by sqlite $as_me 3.24.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { |
︙ | ︙ | |||
12238 12239 12240 12241 12242 12243 12244 | 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=" | | | 12238 12239 12240 12241 12242 12243 12244 12245 12246 12247 12248 12249 12250 12251 12252 | 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.24.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 $@ |
︙ | ︙ | |||
12304 12305 12306 12307 12308 12309 12310 | 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="\\ | | | 12304 12305 12306 12307 12308 12309 12310 12311 12312 12313 12314 12315 12316 12317 12318 | 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.24.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." |
︙ | ︙ |
Changes to doc/lemon.html.
︙ | ︙ | |||
95 96 97 98 99 100 101 102 103 104 105 106 107 108 | As of this writing, the following command-line options are supported: <ul> <li><b>-b</b> Show only the basis for each parser state in the report file. <li><b>-c</b> Do not compress the generated action tables. The parser will be a little larger and slower, but it will detect syntax errors sooner. <li><b>-D<i>name</i></b> Define C preprocessor macro <i>name</i>. This macro is usable by "<tt><a href='#pifdef'>%ifdef</a></tt>" and "<tt><a href='#pifdef'>%ifndef</a></tt>" lines in the grammar file. <li><b>-g</b> Do not generate a parser. Instead write the input grammar to standard | > > > | 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | As of this writing, the following command-line options are supported: <ul> <li><b>-b</b> Show only the basis for each parser state in the report file. <li><b>-c</b> Do not compress the generated action tables. The parser will be a little larger and slower, but it will detect syntax errors sooner. <li><b>-d</b><i>directory</i> Write all output files into <i>directory</i>. Normally, output files are written into the directory that contains the input grammar file. <li><b>-D<i>name</i></b> Define C preprocessor macro <i>name</i>. This macro is usable by "<tt><a href='#pifdef'>%ifdef</a></tt>" and "<tt><a href='#pifdef'>%ifndef</a></tt>" lines in the grammar file. <li><b>-g</b> Do not generate a parser. Instead write the input grammar to standard |
︙ | ︙ | |||
675 676 677 678 679 680 681 682 683 684 685 686 687 688 | </pre></p> <p>Then the Parse() function generated will have an 4th parameter of type "MyStruct*" and all action routines will have access to a variable named "pAbc" that is the value of the 4th parameter in the most recent call to Parse().</p> <a name='pfallback'></a> <h4>The <tt>%fallback</tt> directive</h4> <p>The <tt>%fallback</tt> directive specifies an alternative meaning for one or more tokens. The alternative meaning is tried if the original token would have generated a syntax error.</p> | > > > > > > > > > > > > > > > > > > > > > > > > | 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 | </pre></p> <p>Then the Parse() function generated will have an 4th parameter of type "MyStruct*" and all action routines will have access to a variable named "pAbc" that is the value of the 4th parameter in the most recent call to Parse().</p> <p>The <tt>%extra_context</tt> directive works the same except that it is passed in on the ParseAlloc() or ParseInit() routines instead of on Parse(). <a name='extractx'></a> <h4>The <tt>%extra_context</tt> directive</h4> The <tt>%extra_context</tt> directive instructs Lemon to add a 2th parameter to the parameter list of the ParseAlloc() and ParseInif() functions. Lemon doesn't do anything itself with these extra argument, but it does store the value make it available to C-code action routines, destructors, and so forth. For example, if the grammar file contains:</p> <p><pre> %extra_context { MyStruct *pAbc } </pre></p> <p>Then the ParseAlloc() and ParseInit() functions will have an 2th parameter of type "MyStruct*" and all action routines will have access to a variable named "pAbc" that is the value of that 2th parameter.</p> <p>The <tt>%extra_argument</tt> directive works the same except that it is passed in on the Parse() routine instead of on ParseAlloc()/ParseInit(). <a name='pfallback'></a> <h4>The <tt>%fallback</tt> directive</h4> <p>The <tt>%fallback</tt> directive specifies an alternative meaning for one or more tokens. The alternative meaning is tried if the original token would have generated a syntax error.</p> |
︙ | ︙ |
Changes to ext/expert/expert1.test.
︙ | ︙ | |||
281 282 283 284 285 286 287 288 289 290 291 292 293 294 | CREATE TRIGGER t9t AFTER INSERT ON t9 BEGIN UPDATE t10 SET a=new.a WHERE b = new.b; END; } { INSERT INTO t9 VALUES(?, ?, ?); } { CREATE INDEX t10_idx_00000062 ON t10(b); 0|0|0|SEARCH TABLE t10 USING INDEX t10_idx_00000062 (b=?) } do_setup_rec_test $tn.15 { CREATE TABLE t1(a, b); CREATE TABLE t2(c, d); | > | 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | CREATE TRIGGER t9t AFTER INSERT ON t9 BEGIN UPDATE t10 SET a=new.a WHERE b = new.b; END; } { INSERT INTO t9 VALUES(?, ?, ?); } { CREATE INDEX t10_idx_00000062 ON t10(b); 0|1|0|-- TRIGGER t9t 0|0|0|SEARCH TABLE t10 USING INDEX t10_idx_00000062 (b=?) } do_setup_rec_test $tn.15 { CREATE TABLE t1(a, b); CREATE TABLE t2(c, d); |
︙ | ︙ | |||
375 376 377 378 379 380 381 | t2 t2_idx_00000063 {100 20} t2 t2_idx_00000064 {100 5} t2 t2_idx_0001295b {100 20 5} } finish_test | < | 376 377 378 379 380 381 382 | t2 t2_idx_00000063 {100 20} t2 t2_idx_00000064 {100 5} t2 t2_idx_0001295b {100 20 5} } finish_test |
Changes to ext/fts5/fts5_main.c.
︙ | ︙ | |||
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 | FTS5_BI_ROWID_GE, 0, 0, -1}, }; int aColMap[3]; aColMap[0] = -1; aColMap[1] = nCol; aColMap[2] = nCol+1; /* 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]; int iCol = p->iColumn; if( (p->op==SQLITE_INDEX_CONSTRAINT_MATCH && iCol>=0 && iCol<=nCol) || (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol==nCol) ){ /* A MATCH operator or equivalent */ if( p->usable ){ idxFlags = (idxFlags & 0xFFFF) | FTS5_BI_MATCH | (iCol << 16); aConstraint[0].iConsIndex = i; }else{ /* As there exists an unusable MATCH constraint this is an ** unusable plan. Set a prohibitively high cost. */ pInfo->estimatedCost = 1e50; return SQLITE_OK; } | > > > > > > | | | 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 | FTS5_BI_ROWID_GE, 0, 0, -1}, }; int aColMap[3]; aColMap[0] = -1; 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]; int iCol = p->iColumn; if( (p->op==SQLITE_INDEX_CONSTRAINT_MATCH && iCol>=0 && iCol<=nCol) || (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol==nCol) ){ /* A MATCH operator or equivalent */ if( p->usable ){ idxFlags = (idxFlags & 0xFFFF) | FTS5_BI_MATCH | (iCol << 16); aConstraint[0].iConsIndex = i; }else{ /* As there exists an unusable MATCH constraint this is an ** unusable plan. Set a prohibitively high cost. */ pInfo->estimatedCost = 1e50; return SQLITE_OK; } }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 ){ pC->iConsIndex = i; idxFlags |= pC->fts5op; } } } } |
︙ | ︙ |
Changes to ext/fts5/test/fts5aa.test.
︙ | ︙ | |||
586 587 588 589 590 591 592 593 594 595 596 597 | INSERT INTO t9(rowid, x) VALUES(3, 'bbb'); COMMIT; } do_execsql_test 22.1 { SELECT rowid FROM t9('a*') } {1} } expand_all_sql db finish_test | > > > > > > > > > > > > | 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 | INSERT INTO t9(rowid, x) VALUES(3, 'bbb'); COMMIT; } do_execsql_test 22.1 { SELECT rowid FROM t9('a*') } {1} #------------------------------------------------------------------------- do_execsql_test 23.0 { CREATE VIRTUAL TABLE t10 USING fts5(x, detail=%DETAIL%); CREATE TABLE t11(x); } do_execsql_test 23.1 { SELECT * FROM t11, t10 WHERE t11.x = t10.x AND t10.rowid IS NULL; } do_execsql_test 23.2 { SELECT * FROM t11, t10 WHERE t10.rowid IS NULL; } } expand_all_sql db finish_test |
Changes to ext/icu/README.txt.
︙ | ︙ | |||
35 36 37 38 39 40 41 | http://www.icu-project.org/userguide/caseMappings.html http://www.icu-project.org/userguide/posix.html#case_mappings To utilise "general" case mapping, the upper() or lower() scalar functions are invoked with one argument: | < | > | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | http://www.icu-project.org/userguide/caseMappings.html http://www.icu-project.org/userguide/posix.html#case_mappings To utilise "general" case mapping, the upper() or lower() scalar functions are invoked with one argument: upper('abc') -> 'ABC' lower('ABC') -> 'abc' To access ICU "language specific" case mapping, upper() or lower() should be invoked with two arguments. The second argument is the name of the locale to use. Passing an empty string ("") or SQL NULL value as the second argument is the same as invoking the 1 argument version of upper() or lower(): |
︙ | ︙ |
Changes to ext/misc/csv.c.
︙ | ︙ | |||
128 129 130 131 132 133 134 135 136 137 138 139 140 141 | p->zIn = sqlite3_malloc( CSV_INBUFSZ ); if( p->zIn==0 ){ csv_errmsg(p, "out of memory"); return 1; } p->in = fopen(zFilename, "rb"); if( p->in==0 ){ csv_reader_reset(p); csv_errmsg(p, "cannot open '%s' for reading", zFilename); return 1; } }else{ assert( p->in==0 ); p->zIn = (char*)zData; | > | 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | p->zIn = sqlite3_malloc( CSV_INBUFSZ ); if( p->zIn==0 ){ csv_errmsg(p, "out of memory"); return 1; } p->in = fopen(zFilename, "rb"); if( p->in==0 ){ sqlite3_free(p->zIn); csv_reader_reset(p); csv_errmsg(p, "cannot open '%s' for reading", zFilename); return 1; } }else{ assert( p->in==0 ); p->zIn = (char*)zData; |
︙ | ︙ |
Changes to ext/misc/eval.c.
︙ | ︙ | |||
30 31 32 33 34 35 36 37 38 39 40 41 42 43 | /* ** Callback from sqlite_exec() for the eval() function. */ static int callback(void *pCtx, int argc, char **argv, char **colnames){ struct EvalResult *p = (struct EvalResult*)pCtx; int i; for(i=0; i<argc; i++){ const char *z = argv[i] ? argv[i] : ""; size_t sz = strlen(z); if( (sqlite3_int64)sz+p->nUsed+p->szSep+1 > p->nAlloc ){ char *zNew; p->nAlloc = p->nAlloc*2 + sz + p->szSep + 1; /* Using sqlite3_realloc64() would be better, but it is a recent | > | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | /* ** Callback from sqlite_exec() for the eval() function. */ static int callback(void *pCtx, int argc, char **argv, char **colnames){ struct EvalResult *p = (struct EvalResult*)pCtx; int i; if( argv==0 ) return 0; for(i=0; i<argc; i++){ const char *z = argv[i] ? argv[i] : ""; size_t sz = strlen(z); if( (sqlite3_int64)sz+p->nUsed+p->szSep+1 > p->nAlloc ){ char *zNew; p->nAlloc = p->nAlloc*2 + sz + p->szSep + 1; /* Using sqlite3_realloc64() would be better, but it is a recent |
︙ | ︙ |
Changes to ext/misc/fileio.c.
︙ | ︙ | |||
89 90 91 92 93 94 95 96 97 98 99 100 101 102 | # include <sys/time.h> #else # include "windows.h" # include <io.h> # include <direct.h> # include "test_windirent.h" # define dirent DIRENT # ifndef stat # define stat _stat # endif # define mkdir(path,mode) _mkdir(path) # define lstat(path,buf) stat(path,buf) #endif #include <time.h> | > > > | 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | # 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> |
︙ | ︙ | |||
154 155 156 157 158 159 160 161 162 163 164 165 166 167 | va_list ap; va_start(ap, zFmt); zMsg = sqlite3_vmprintf(zFmt, ap); sqlite3_result_error(ctx, zMsg, -1); sqlite3_free(zMsg); va_end(ap); } /* ** 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). ** | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 | 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_DATA)); 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). ** |
︙ | ︙ | |||
186 187 188 189 190 191 192 | struct stat sStat; int rc2; for(; zCopy[i]!='/' && i<nCopy; i++); if( i==nCopy ) break; zCopy[i] = '\0'; | | | 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 | 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++; |
︙ | ︙ | |||
228 229 230 231 232 233 234 | 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 | | | 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 | 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{ |
︙ | ︙ | |||
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 | 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); 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; } | > > > | | 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 | 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; |
︙ | ︙ | |||
564 565 566 567 568 569 570 | 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; | | | 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 | 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); |
︙ | ︙ | |||
698 699 700 701 702 703 704 | }else{ pCur->zPath = sqlite3_mprintf("%s", zDir); } if( pCur->zPath==0 ){ return SQLITE_NOMEM; } | | | 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 | }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; } |
︙ | ︙ |
Changes to ext/misc/series.c.
︙ | ︙ | |||
265 266 267 268 269 270 271 272 273 274 275 276 277 278 | pCur->mxValue = 0xffffffff; } if( idxNum & 4 ){ pCur->iStep = sqlite3_value_int64(argv[i++]); if( pCur->iStep<1 ) pCur->iStep = 1; }else{ pCur->iStep = 1; } if( idxNum & 8 ){ pCur->isDesc = 1; pCur->iValue = pCur->mxValue; if( pCur->iStep>0 ){ pCur->iValue -= (pCur->mxValue - pCur->mnValue)%pCur->iStep; } | > > > > > > > > > | 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 | pCur->mxValue = 0xffffffff; } if( idxNum & 4 ){ pCur->iStep = sqlite3_value_int64(argv[i++]); if( pCur->iStep<1 ) pCur->iStep = 1; }else{ pCur->iStep = 1; } for(i=0; i<argc; i++){ if( sqlite3_value_type(argv[i])==SQLITE_NULL ){ /* If any of the constraints have a NULL value, then return no rows. ** See ticket https://www.sqlite.org/src/info/fac496b61722daf2 */ pCur->mnValue = 1; pCur->mxValue = 0; break; } } if( idxNum & 8 ){ pCur->isDesc = 1; pCur->iValue = pCur->mxValue; if( pCur->iStep>0 ){ pCur->iValue -= (pCur->mxValue - pCur->mnValue)%pCur->iStep; } |
︙ | ︙ |
Changes to ext/misc/spellfix.c.
︙ | ︙ | |||
760 761 762 763 764 765 766 | int nTo = zTo ? sqlite3_column_bytes(pStmt, 2) : 0; int iCost = sqlite3_column_int(pStmt, 3); assert( zFrom!=0 || nFrom==0 ); assert( zTo!=0 || nTo==0 ); if( nFrom>100 || nTo>100 ) continue; if( iCost<0 ) continue; | | | 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 | int nTo = zTo ? sqlite3_column_bytes(pStmt, 2) : 0; int iCost = sqlite3_column_int(pStmt, 3); assert( zFrom!=0 || nFrom==0 ); assert( zTo!=0 || nTo==0 ); if( nFrom>100 || nTo>100 ) continue; if( iCost<0 ) continue; if( iCost>=10000 ) continue; /* Costs above 10K are considered infinite */ if( pLang==0 || iLang!=iLangPrev ){ EditDist3Lang *pNew; pNew = sqlite3_realloc64(p->a, (p->nLang+1)*sizeof(p->a[0])); if( pNew==0 ){ rc = SQLITE_NOMEM; break; } p->a = pNew; pLang = &p->a[p->nLang]; p->nLang++; |
︙ | ︙ | |||
831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 | } /* ** Return TRUE (non-zero) if the To side of the given cost matches ** the given string. */ static int matchTo(EditDist3Cost *p, const char *z, int n){ if( p->a[p->nFrom]!=z[0] ) return 0; if( p->nTo>n ) return 0; if( strncmp(p->a+p->nFrom, z, p->nTo)!=0 ) return 0; return 1; } /* ** Return TRUE (non-zero) if the From side of the given cost matches ** the given string. */ static int matchFrom(EditDist3Cost *p, const char *z, int n){ assert( p->nFrom<=n ); | > > | | > > | 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 | } /* ** Return TRUE (non-zero) if the To side of the given cost matches ** the given string. */ static int matchTo(EditDist3Cost *p, const char *z, int n){ assert( n>0 ); if( p->a[p->nFrom]!=z[0] ) return 0; if( p->nTo>n ) return 0; if( strncmp(p->a+p->nFrom, z, p->nTo)!=0 ) return 0; return 1; } /* ** Return TRUE (non-zero) if the From side of the given cost matches ** the given string. */ static int matchFrom(EditDist3Cost *p, const char *z, int n){ assert( p->nFrom<=n ); if( p->nFrom ){ if( p->a[0]!=z[0] ) return 0; if( strncmp(p->a, z, p->nFrom)!=0 ) return 0; } return 1; } /* ** Return TRUE (non-zero) of the next FROM character and the next TO ** character are the same. */ static int matchFromTo( EditDist3FromString *pStr, /* Left hand string */ int n1, /* Index of comparison character on the left */ const char *z2, /* Right-handl comparison character */ int n2 /* Bytes remaining in z2[] */ ){ int b1 = pStr->a[n1].nByte; if( b1>n2 ) return 0; assert( b1>0 ); if( pStr->z[n1]!=z2[0] ) return 0; if( strncmp(pStr->z+n1, z2, b1)!=0 ) return 0; return 1; } /* ** Delete an EditDist3FromString objecct |
︙ | ︙ |
Added ext/misc/templatevtab.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | /* ** 2018-04-19 ** ** 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 template virtual-table implementation. ** Developers can make a copy of this file as a baseline for writing ** new virtual tables and/or table-valued functions. ** ** Steps for writing a new virtual table implementation: ** ** (1) Make a copy of this file. Prehaps "mynewvtab.c" ** ** (2) Replace this header comment with something appropriate for ** the new virtual table ** ** (3) Change every occurrence of "templatevtab" to some other string ** appropriate for the new virtual table. Ideally, the new string ** should be the basename of the source file: "mynewvtab". ** ** (4) Run a test compilation to make sure the unmodified virtual ** table works. ** ** (5) Begin making changes to make the new virtual table do what you ** want it to do. ** ** (6) Ensure that all the "FIXME" comments in the file have been dealt ** with. ** ** This template is minimal, in the sense that it uses only the required ** methods on the sqlite3_module object. As a result, templatevtab is ** a read-only and eponymous-only table. Those limitation can be removed ** by adding new methods. */ #if !defined(SQLITEINT_H) #include "sqlite3ext.h" #endif SQLITE_EXTENSION_INIT1 #include <string.h> /* templatevtab_vtab is a subclass of sqlite3_vtab which is ** underlying representation of the virtual table */ typedef struct templatevtab_vtab templatevtab_vtab; struct templatevtab_vtab { sqlite3_vtab base; /* Base class - must be first */ /* Add new fields here, as necessary */ }; /* templatevtab_cursor is a subclass of sqlite3_vtab_cursor which will ** serve as the underlying representation of a cursor that scans ** over rows of the result */ typedef struct templatevtab_cursor templatevtab_cursor; struct templatevtab_cursor { sqlite3_vtab_cursor base; /* Base class - must be first */ /* Insert new fields here. For this templatevtab we only keep track ** of the rowid */ sqlite3_int64 iRowid; /* The rowid */ }; /* ** The templatevtabConnect() method is invoked to create a new ** template virtual table. ** ** Think of this routine as the constructor for templatevtab_vtab objects. ** ** All this routine needs to do is: ** ** (1) Allocate the templatevtab_vtab object and initialize all fields. ** ** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the ** result set of queries against the virtual table will look like. */ static int templatevtabConnect( sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVtab, char **pzErr ){ templatevtab_vtab *pNew; int rc; rc = sqlite3_declare_vtab(db, "CREATE TABLE x(a,b)" ); if( rc==SQLITE_OK ){ pNew = sqlite3_malloc( sizeof(*pNew) ); *ppVtab = (sqlite3_vtab*)pNew; if( pNew==0 ) return SQLITE_NOMEM; memset(pNew, 0, sizeof(*pNew)); } return rc; } /* ** This method is the destructor for templatevtab_vtab objects. */ static int templatevtabDisconnect(sqlite3_vtab *pVtab){ templatevtab_vtab *p = (templatevtab_vtab*)pVtab; sqlite3_free(p); return SQLITE_OK; } /* ** Constructor for a new templatevtab_cursor object. */ static int templatevtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ templatevtab_cursor *pCur; pCur = sqlite3_malloc( sizeof(*pCur) ); if( pCur==0 ) return SQLITE_NOMEM; memset(pCur, 0, sizeof(*pCur)); *ppCursor = &pCur->base; return SQLITE_OK; } /* ** Destructor for a templatevtab_cursor. */ static int templatevtabClose(sqlite3_vtab_cursor *cur){ templatevtab_cursor *pCur = (templatevtab_cursor*)cur; sqlite3_free(pCur); return SQLITE_OK; } /* ** Advance a templatevtab_cursor to its next row of output. */ static int templatevtabNext(sqlite3_vtab_cursor *cur){ templatevtab_cursor *pCur = (templatevtab_cursor*)cur; pCur->iRowid++; return SQLITE_OK; } /* ** Return values of columns for the row at which the templatevtab_cursor ** is currently pointing. */ static int templatevtabColumn( sqlite3_vtab_cursor *cur, /* The cursor */ sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ int i /* Which column to return */ ){ templatevtab_cursor *pCur = (templatevtab_cursor*)cur; sqlite3_result_int(ctx, (i+1)*1000 + pCur->iRowid); return SQLITE_OK; } /* ** Return the rowid for the current row. In this implementation, the ** rowid is the same as the output value. */ static int templatevtabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ templatevtab_cursor *pCur = (templatevtab_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 templatevtabEof(sqlite3_vtab_cursor *cur){ templatevtab_cursor *pCur = (templatevtab_cursor*)cur; return pCur->iRowid>=10; } /* ** This method is called to "rewind" the templatevtab_cursor object back ** to the first row of output. This method is always called at least ** once prior to any call to templatevtabColumn() or templatevtabRowid() or ** templatevtabEof(). */ static int templatevtabFilter( sqlite3_vtab_cursor *pVtabCursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ templatevtab_cursor *pCur = (templatevtab_cursor *)pVtabCursor; pCur->iRowid = 1; return SQLITE_OK; } /* ** SQLite will invoke this method one or more times while planning a query ** that uses the virtual table. This routine needs to create ** a query plan for each invocation and compute an estimated cost for that ** plan. */ static int templatevtabBestIndex( sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo ){ pIdxInfo->estimatedCost = (double)10; pIdxInfo->estimatedRows = 10; return SQLITE_OK; } /* ** This following structure defines all the methods for the ** virtual table. */ static sqlite3_module templatevtabModule = { /* iVersion */ 0, /* xCreate */ 0, /* xConnect */ templatevtabConnect, /* xBestIndex */ templatevtabBestIndex, /* xDisconnect */ templatevtabDisconnect, /* xDestroy */ 0, /* xOpen */ templatevtabOpen, /* xClose */ templatevtabClose, /* xFilter */ templatevtabFilter, /* xNext */ templatevtabNext, /* xEof */ templatevtabEof, /* xColumn */ templatevtabColumn, /* xRowid */ templatevtabRowid, /* xUpdate */ 0, /* xBegin */ 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0 }; #ifdef _WIN32 __declspec(dllexport) #endif int sqlite3_templatevtab_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ int rc = SQLITE_OK; SQLITE_EXTENSION_INIT2(pApi); rc = sqlite3_create_module(db, "templatevtab", &templatevtabModule, 0); return rc; } |
Changes to ext/misc/zipfile.c.
︙ | ︙ | |||
1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 | */ static u32 zipfileGetTime(sqlite3_value *pVal){ if( pVal==0 || sqlite3_value_type(pVal)==SQLITE_NULL ){ return zipfileTime(); } return (u32)sqlite3_value_int64(pVal); } /* ** xUpdate method. */ static int zipfileUpdate( sqlite3_vtab *pVtab, int nVal, | > > > > > > > > > > > > > | 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 | */ 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, |
︙ | ︙ | |||
1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 | 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; 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); for(pOld=pTab->pFirstEntry; 1; pOld=pOld->pNext){ if( zipfileComparePath(pOld->cds.zFile, zDelete, nDelete)==0 ){ break; } assert( pOld->pNext ); } } | > > > > > > > > | 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 | 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 ); } } |
︙ | ︙ | |||
1609 1610 1611 1612 1613 1614 1615 | zFree = sqlite3_mprintf("%s/", zPath); if( zFree==0 ){ rc = SQLITE_NOMEM; } zPath = (const char*)zFree; nPath++; } } | | > | | | 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 | 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; } |
︙ | ︙ | |||
1657 1658 1659 1660 1661 1662 1663 | pNew->mUnixTime = (u32)mTime; rc = zipfileAppendEntry(pTab, pNew, pData, nData); zipfileAddEntry(pTab, pOld, pNew); } } } | | < | | | | | | 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 | 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; } |
︙ | ︙ | |||
2036 2037 2038 2039 2040 2041 2042 | /* 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 */ | > | | | > | 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 | /* 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 */ |
︙ | ︙ |
Changes to ext/rbu/rbu.c.
︙ | ︙ | |||
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | void usage(const char *zArgv0){ fprintf(stderr, "Usage: %s ?OPTIONS? TARGET-DB RBU-DB\n" "\n" "Where options are:\n" "\n" " -step NSTEP\n" " -vacuum\n" "\n" " If the -vacuum switch is not present, argument RBU-DB must be an RBU\n" " database containing an update suitable for target database TARGET-DB.\n" " Or, if -vacuum is specified, then TARGET-DB is a database to vacuum using\n" " RBU, and RBU-DB is used as the state database for the vacuum (refer to\n" " API documentation for details).\n" "\n" | > > | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | void usage(const char *zArgv0){ fprintf(stderr, "Usage: %s ?OPTIONS? TARGET-DB RBU-DB\n" "\n" "Where options are:\n" "\n" " -step NSTEP\n" " -statstep NSTATSTEP\n" " -vacuum\n" " -presql SQL\n" "\n" " If the -vacuum switch is not present, argument RBU-DB must be an RBU\n" " database containing an update suitable for target database TARGET-DB.\n" " Or, if -vacuum is specified, then TARGET-DB is a database to vacuum using\n" " RBU, and RBU-DB is used as the state database for the vacuum (refer to\n" " API documentation for details).\n" "\n" |
︙ | ︙ | |||
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | int i; const char *zTarget; /* Target database to apply RBU to */ const char *zRbu; /* Database containing RBU */ char zBuf[200]; /* Buffer for printf() */ char *zErrmsg; /* Error message, if any */ sqlite3rbu *pRbu; /* RBU handle */ int nStep = 0; /* Maximum number of step() calls */ int bVacuum = 0; int rc; sqlite3_int64 nProgress = 0; int nArgc = argc-2; if( argc<3 ) usage(argv[0]); for(i=1; i<nArgc; i++){ const char *zArg = argv[i]; int nArg = strlen(zArg); if( nArg>1 && nArg<=8 && 0==memcmp(zArg, "-vacuum", nArg) ){ bVacuum = 1; }else if( nArg>1 && nArg<=5 && 0==memcmp(zArg, "-step", nArg) && i<nArg-1 ){ i++; nStep = atoi(argv[i]); }else{ usage(argv[0]); } } zTarget = argv[argc-2]; zRbu = argv[argc-1]; report_default_vfs(); /* Open an RBU handle. A vacuum handle if -vacuum was specified, or a ** regular RBU update handle otherwise. */ if( bVacuum ){ pRbu = sqlite3rbu_vacuum(zTarget, zRbu); }else{ pRbu = sqlite3rbu_open(zTarget, zRbu, 0); } report_rbu_vfs(pRbu); /* If nStep is less than or equal to zero, call ** sqlite3rbu_step() until either the RBU has been completely applied ** or an error occurs. Or, if nStep is greater than zero, call ** sqlite3rbu_step() a maximum of nStep times. */ | > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > | | > | 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | int i; const char *zTarget; /* Target database to apply RBU to */ const char *zRbu; /* Database containing RBU */ char zBuf[200]; /* Buffer for printf() */ char *zErrmsg; /* Error message, if any */ sqlite3rbu *pRbu; /* RBU handle */ int nStep = 0; /* Maximum number of step() calls */ int nStatStep = 0; /* Report stats after this many step calls */ int bVacuum = 0; const char *zPreSql = 0; int rc; sqlite3_int64 nProgress = 0; int nArgc = argc-2; if( argc<3 ) usage(argv[0]); for(i=1; i<nArgc; i++){ const char *zArg = argv[i]; int nArg = strlen(zArg); if( nArg>1 && nArg<=8 && 0==memcmp(zArg, "-vacuum", nArg) ){ bVacuum = 1; }else if( nArg>1 && nArg<=7 && 0==memcmp(zArg, "-presql", nArg) && i<nArg-1 ){ i++; zPreSql = argv[i]; }else if( nArg>1 && nArg<=5 && 0==memcmp(zArg, "-step", nArg) && i<nArg-1 ){ i++; nStep = atoi(argv[i]); }else if( nArg>1 && nArg<=9 && 0==memcmp(zArg, "-statstep", nArg) && i<nArg-1 ){ i++; nStatStep = atoi(argv[i]); }else{ usage(argv[0]); } } zTarget = argv[argc-2]; zRbu = argv[argc-1]; report_default_vfs(); /* Open an RBU handle. A vacuum handle if -vacuum was specified, or a ** regular RBU update handle otherwise. */ if( bVacuum ){ pRbu = sqlite3rbu_vacuum(zTarget, zRbu); }else{ pRbu = sqlite3rbu_open(zTarget, zRbu, 0); } report_rbu_vfs(pRbu); if( zPreSql && pRbu ){ sqlite3 *db = sqlite3rbu_db(pRbu, 0); rc = sqlite3_exec(db, zPreSql, 0, 0, 0); if( rc==SQLITE_OK ){ sqlite3 *db = sqlite3rbu_db(pRbu, 1); rc = sqlite3_exec(db, zPreSql, 0, 0, 0); } } /* If nStep is less than or equal to zero, call ** sqlite3rbu_step() until either the RBU has been completely applied ** or an error occurs. Or, if nStep is greater than zero, call ** sqlite3rbu_step() a maximum of nStep times. */ if( rc==SQLITE_OK ){ for(i=0; (nStep<=0 || i<nStep) && sqlite3rbu_step(pRbu)==SQLITE_OK; i++){ if( nStatStep>0 && (i % nStatStep)==0 ){ sqlite3_int64 nUsed; sqlite3_int64 nHighwater; sqlite3_status64(SQLITE_STATUS_MEMORY_USED, &nUsed, &nHighwater, 0); fprintf(stdout, "memory used=%lld highwater=%lld", nUsed, nHighwater); if( bVacuum==0 ){ int one; int two; sqlite3rbu_bp_progress(pRbu, &one, &two); fprintf(stdout, " progress=%d/%d\n", one, two); }else{ fprintf(stdout, "\n"); } fflush(stdout); } } nProgress = sqlite3rbu_progress(pRbu); rc = sqlite3rbu_close(pRbu, &zErrmsg); } /* Let the user know what happened. */ switch( rc ){ case SQLITE_OK: sqlite3_snprintf(sizeof(zBuf), zBuf, "SQLITE_OK: rbu update incomplete (%lld operations so far)\n", nProgress |
︙ | ︙ |
Changes to ext/rbu/rbu_common.tcl.
︙ | ︙ | |||
67 68 69 70 71 72 73 74 75 76 77 78 79 80 | rbu close if {$rc != "SQLITE_OK"} break } set rc } proc do_rbu_vacuum_test {tn step} { uplevel [list do_test $tn.1 { if {$step==0} { sqlite3rbu_vacuum rbu test.db state.db } while 1 { if {$step==1} { sqlite3rbu_vacuum rbu test.db state.db } set state [rbu state] check_prestep_state test.db $state set rc [rbu step] | > | 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | rbu close if {$rc != "SQLITE_OK"} break } set rc } proc do_rbu_vacuum_test {tn step} { forcedelete state.db uplevel [list do_test $tn.1 { if {$step==0} { sqlite3rbu_vacuum rbu test.db state.db } while 1 { if {$step==1} { sqlite3rbu_vacuum rbu test.db state.db } set state [rbu state] check_prestep_state test.db $state set rc [rbu step] |
︙ | ︙ |
Added ext/rbu/rbucollate.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | # 2018 March 22 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # source [file join [file dirname [info script]] rbu_common.tcl] set ::testprefix rbucollate ifcapable !icu_collations { finish_test return } db close sqlite3_shutdown sqlite3_config_uri 1 reset_db # Create a simple RBU database. That expects to write to a table: # # CREATE TABLE t1(a PRIMARY KEY, b, c); # proc create_rbu1 {filename} { forcedelete $filename sqlite3 rbu1 $filename rbu1 eval { CREATE TABLE data_t1(a, b, c, rbu_control); INSERT INTO data_t1 VALUES('a', 'one', 1, 0); INSERT INTO data_t1 VALUES('b', 'two', 2, 0); INSERT INTO data_t1 VALUES('c', 'three', 3, 0); } rbu1 close return $filename } do_execsql_test 1.0 { SELECT icu_load_collation('en_US', 'my-collate'); CREATE TABLE t1(a COLLATE "my-collate" PRIMARY KEY, b, c); } {{}} do_test 1.2 { create_rbu1 testrbu.db sqlite3rbu rbu test.db testrbu.db rbu dbMain_eval { SELECT icu_load_collation('en_US', 'my-collate') } rbu dbRbu_eval { SELECT icu_load_collation('en_US', 'my-collate') } while 1 { set rc [rbu step] if {$rc!="SQLITE_OK"} break } rbu close db eval { SELECT * FROM t1 } } {a one 1 b two 2 c three 3} #forcedelete testrbu.db finish_test |
Changes to ext/rbu/sqlite3rbu.c.
︙ | ︙ | |||
1802 1803 1804 1805 1806 1807 1808 | while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ int bKey = sqlite3_column_int(pXInfo, 5); if( bKey ){ int iCid = sqlite3_column_int(pXInfo, 1); int bDesc = sqlite3_column_int(pXInfo, 3); const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4); | | | 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 | while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ int bKey = sqlite3_column_int(pXInfo, 5); if( bKey ){ 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 %Q", zCols, zComma, iCid, pIter->azTblType[iCid], zCollate ); zPk = rbuMPrintf(p, "%z%sc%d%s", zPk, zComma, iCid, bDesc?" DESC":""); zComma = ", "; } } zCols = rbuMPrintf(p, "%z, id INTEGER", zCols); |
︙ | ︙ | |||
1863 1864 1865 1866 1867 1868 1869 | ); if( pIter->eType==RBU_PK_IPK && pIter->abTblPk[iCol] ){ /* If the target table column is an "INTEGER PRIMARY KEY", add ** "PRIMARY KEY" to the imposter table column declaration. */ zPk = "PRIMARY KEY "; } | | | 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 | ); if( pIter->eType==RBU_PK_IPK && pIter->abTblPk[iCol] ){ /* If the target table column is an "INTEGER PRIMARY KEY", add ** "PRIMARY KEY" to the imposter table column declaration. */ zPk = "PRIMARY KEY "; } zSql = rbuMPrintf(p, "%z%s\"%w\" %s %sCOLLATE %Q%s", zSql, zComma, zCol, pIter->azTblType[iCol], zPk, zColl, (pIter->abNotNull[iCol] ? " NOT NULL" : "") ); zComma = ", "; } if( pIter->eType==RBU_PK_WITHOUT_ROWID ){ |
︙ | ︙ |
Changes to ext/rbu/test_rbu.c.
︙ | ︙ | |||
77 78 79 80 81 82 83 84 85 86 87 88 89 90 | {"bp_progress", 2, ""}, /* 5 */ {"db", 3, "RBU"}, /* 6 */ {"state", 2, ""}, /* 7 */ {"progress", 2, ""}, /* 8 */ {"close_no_error", 2, ""}, /* 9 */ {"temp_size_limit", 3, "LIMIT"}, /* 10 */ {"temp_size", 2, ""}, /* 11 */ {0,0,0} }; int iCmd; if( objc<2 ){ Tcl_WrongNumArgs(interp, 1, objv, "METHOD"); return TCL_ERROR; | > | 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | {"bp_progress", 2, ""}, /* 5 */ {"db", 3, "RBU"}, /* 6 */ {"state", 2, ""}, /* 7 */ {"progress", 2, ""}, /* 8 */ {"close_no_error", 2, ""}, /* 9 */ {"temp_size_limit", 3, "LIMIT"}, /* 10 */ {"temp_size", 2, ""}, /* 11 */ {"dbRbu_eval", 3, "SQL"}, /* 12 */ {0,0,0} }; int iCmd; if( objc<2 ){ Tcl_WrongNumArgs(interp, 1, objv, "METHOD"); return TCL_ERROR; |
︙ | ︙ | |||
142 143 144 145 146 147 148 | case 3: /* savestate */ { int rc = sqlite3rbu_savestate(pRbu); Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); ret = (rc==SQLITE_OK ? TCL_OK : TCL_ERROR); break; } | > | | | 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | case 3: /* savestate */ { int rc = sqlite3rbu_savestate(pRbu); Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); ret = (rc==SQLITE_OK ? TCL_OK : TCL_ERROR); break; } case 12: /* dbRbu_eval */ case 4: /* dbMain_eval */ { sqlite3 *db = sqlite3rbu_db(pRbu, (iCmd==12)); int rc = sqlite3_exec(db, Tcl_GetString(objv[2]), 0, 0, 0); if( rc!=SQLITE_OK ){ Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(db), -1)); ret = TCL_ERROR; } break; } |
︙ | ︙ |
Changes to ext/session/session1.test.
︙ | ︙ | |||
607 608 609 610 611 612 613 614 615 616 617 618 619 | do_iterator_test $tn.12.2 * { UPDATE t1 SET b='one' WHERE a=1; } { {UPDATE t1 0 X.. {i 1 {} {} i 1} {{} {} {} {} t one}} {UPDATE t1 0 X.. {i 2 {} {} i 2} {{} {} {} {} t one}} {UPDATE t1 0 X.. {i 3 {} {} i 3} {{} {} {} {} t one}} } }] } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 | do_iterator_test $tn.12.2 * { UPDATE t1 SET b='one' WHERE a=1; } { {UPDATE t1 0 X.. {i 1 {} {} i 1} {{} {} {} {} t one}} {UPDATE t1 0 X.. {i 2 {} {} i 2} {{} {} {} {} t one}} {UPDATE t1 0 X.. {i 3 {} {} i 3} {{} {} {} {} t one}} } #------------------------------------------------------------------------- # Test that no savepoint is used if -nosavepoint is specified. # do_execsql_test $tn.13.1 { CREATE TABLE x1(a INTEGER PRIMARY KEY, b)%WR%; } do_test $tn.13.2 { execsql BEGIN set C [changeset_from_sql { INSERT INTO x1 VALUES(1, 'one'); INSERT INTO x1 VALUES(2, 'two'); INSERT INTO x1 VALUES(3, 'three'); }] execsql ROLLBACK execsql { INSERT INTO x1 VALUES(1, 'i'); INSERT INTO x1 VALUES(2, 'ii'); INSERT INTO x1 VALUES(3, 'iii'); } } {} proc xConflict {args} { set ret [lindex $::CONFLICT_HANDLERS 0] set ::CONFLICT_HANDLERS [lrange $::CONFLICT_HANDLERS 1 end] set ret } do_test $tn.13.3 { set CONFLICT_HANDLERS [list REPLACE REPLACE ABORT] execsql BEGIN catch { sqlite3changeset_apply_v2 db $C xConflict } msg execsql { SELECT * FROM x1 } } {1 i 2 ii 3 iii} do_test $tn.13.3 { set CONFLICT_HANDLERS [list REPLACE REPLACE ABORT] execsql ROLLBACK execsql BEGIN catch { sqlite3changeset_apply_v2 -nosavepoint db $C xConflict } msg execsql { SELECT * FROM x1 } } {1 one 2 two 3 iii} execsql ROLLBACK }] } finish_test |
Changes to ext/session/session4.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # 2011 March 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 regression tests for the session module. # if {![info exists testdir]} { set testdir [file join [file dirname [info script]] .. .. test] } source [file join [file dirname [info script]] session_common.tcl] source $testdir/tester.tcl ifcapable !session {finish_test; return} | > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2011 March 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 regression tests for the session module. # package require Tcl 8.6 if {![info exists testdir]} { set testdir [file join [file dirname [info script]] .. .. test] } source [file join [file dirname [info script]] session_common.tcl] source $testdir/tester.tcl ifcapable !session {finish_test; return} |
︙ | ︙ |
Changes to ext/session/sessionG.test.
︙ | ︙ | |||
200 201 202 203 204 205 206 207 208 209 210 211 | db2 eval { SELECT * FROM t1; SELECT * FROM t2; SELECT * FROM t3; } } {1 2 3 7 8 9} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | db2 eval { SELECT * FROM t1; SELECT * FROM t2; SELECT * FROM t3; } } {1 2 3 7 8 9} #------------------------------------------------------------------------- reset_db db func number_name number_name do_execsql_test 6.0 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b); CREATE UNIQUE INDEX t1b ON t1(b); WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<1000 ) INSERT INTO t1 SELECT i, number_name(i) FROM s; } do_test 6.1 { db eval BEGIN set ::C [changeset_from_sql { DELETE FROM t1; WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<1000 ) INSERT INTO t1 SELECT i, number_name(i+1) FROM s; }] db eval ROLLBACK execsql { SELECT count(*) FROM t1 WHERE number_name(a) IS NOT b } } {0} proc xConflict {args} { exit ; return "OMIT" } do_test 6.2 { sqlite3changeset_apply db $C xConflict } {} do_execsql_test 6.3 { SELECT count(*) FROM t1; } {1000} do_execsql_test 6.4 { SELECT count(*) FROM t1 WHERE number_name(a+1) IS NOT b; } {0} # db eval { SELECT * FROM t1 } { puts "$a || $b" } finish_test |
Changes to ext/session/session_common.tcl.
︙ | ︙ | |||
165 166 167 168 169 170 171 | } proc changeset_to_list {c} { set list [list] sqlite3session_foreach elem $c { lappend list $elem } lsort $list } | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | } proc changeset_to_list {c} { set list [list] sqlite3session_foreach elem $c { lappend list $elem } lsort $list } set ones {zero one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen} set tens {{} ten twenty thirty forty fifty sixty seventy eighty ninety} proc number_name {n} { if {$n>=1000} { set txt "[number_name [expr {$n/1000}]] thousand" set n [expr {$n%1000}] } else { set txt {} } if {$n>=100} { append txt " [lindex $::ones [expr {$n/100}]] hundred" set n [expr {$n%100}] } if {$n>=20} { append txt " [lindex $::tens [expr {$n/10}]]" set n [expr {$n%10}] } if {$n>0} { append txt " [lindex $::ones $n]" } set txt [string trim $txt] if {$txt==""} {set txt zero} return $txt } |
Changes to ext/session/sessionfault2.test.
︙ | ︙ | |||
15 16 17 18 19 20 21 22 23 24 25 26 27 28 | if {![info exists testdir]} { set testdir [file join [file dirname [info script]] .. .. test] } source [file join [file dirname [info script]] session_common.tcl] source $testdir/tester.tcl ifcapable !session {finish_test; return} set testprefix sessionfault2 do_execsql_test 1.0.0 { CREATE TABLE t1(a PRIMARY KEY, b UNIQUE); INSERT INTO t1 VALUES(1, 1); INSERT INTO t1 VALUES(2, 2); INSERT INTO t1 VALUES(3, 3); | > > | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | if {![info exists testdir]} { set testdir [file join [file dirname [info script]] .. .. test] } source [file join [file dirname [info script]] session_common.tcl] source $testdir/tester.tcl ifcapable !session {finish_test; return} set testprefix sessionfault2 if 1 { do_execsql_test 1.0.0 { CREATE TABLE t1(a PRIMARY KEY, b UNIQUE); INSERT INTO t1 VALUES(1, 1); INSERT INTO t1 VALUES(2, 2); INSERT INTO t1 VALUES(3, 3); |
︙ | ︙ | |||
98 99 100 101 102 103 104 105 106 107 | faultsim_restore_and_reopen } -body { sqlite3changeset_apply db $::C xConflict } -test { faultsim_test_result {0 {}} {1 SQLITE_NOMEM} faultsim_integrity_check } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | faultsim_restore_and_reopen } -body { sqlite3changeset_apply db $::C xConflict } -test { faultsim_test_result {0 {}} {1 SQLITE_NOMEM} faultsim_integrity_check } #------------------------------------------------------------------------- # OOM when collecting and apply a changeset that uses sqlite_stat1. # reset_db forcedelete test.db2 sqlite3 db2 test.db2 do_common_sql { CREATE TABLE t1(a PRIMARY KEY, b UNIQUE, c); CREATE INDEX i1 ON t1(c); INSERT INTO t1 VALUES(1, 2, 3); INSERT INTO t1 VALUES(4, 5, 6); INSERT INTO t1 VALUES(7, 8, 9); CREATE TABLE t2(a, b, c); INSERT INTO t2 VALUES(1, 2, 3); INSERT INTO t2 VALUES(4, 5, 6); INSERT INTO t2 VALUES(7, 8, 9); ANALYZE; } faultsim_save_and_close db2 close do_faultsim_test 1.1 -faults oom-* -prep { catch {db2 close} catch {db close} faultsim_restore_and_reopen sqlite3 db2 test.db2 } -body { do_then_apply_sql { INSERT INTO sqlite_stat1 VALUES('x', 'y', 45); UPDATE sqlite_stat1 SET stat = 123 WHERE tbl='t1' AND idx='i1'; UPDATE sqlite_stat1 SET stat = 456 WHERE tbl='t2'; } } -test { faultsim_test_result {0 {}} {1 SQLITE_NOMEM} faultsim_integrity_check if {$testrc==0} { compare_db db db2 } } #------------------------------------------------------------------------- # OOM when collecting and using a rebase changeset. # reset_db do_execsql_test 2.0 { CREATE TABLE t3(a, b, c, PRIMARY KEY(b, c)); CREATE TABLE t4(x PRIMARY KEY, y, z); INSERT INTO t3 VALUES(1, 2, 3); INSERT INTO t3 VALUES(4, 2, 5); INSERT INTO t3 VALUES(7, 2, 9); INSERT INTO t4 VALUES('a', 'b', 'c'); INSERT INTO t4 VALUES('d', 'e', 'f'); INSERT INTO t4 VALUES('g', 'h', 'i'); } faultsim_save_and_close db2 close proc xConflict {ret args} { return $ret } do_test 2.1 { faultsim_restore_and_reopen set C1 [changeset_from_sql { INSERT INTO t3 VALUES(10, 11, 12); UPDATE t4 SET y='j' WHERE x='g'; DELETE FROM t4 WHERE x='a'; }] faultsim_restore_and_reopen set C2 [changeset_from_sql { INSERT INTO t3 VALUES(1000, 11, 12); DELETE FROM t4 WHERE x='g'; }] faultsim_restore_and_reopen sqlite3changeset_apply db $C1 [list xConflict OMIT] faultsim_save_and_close } {} do_faultsim_test 2.2 -faults oom* -prep { catch {db2 close} catch {db close} faultsim_restore_and_reopen sqlite3 db2 test.db2 } -body { set rebase [sqlite3changeset_apply_v2 db $::C2 [list xConflict OMIT]] set {} {} } -test { faultsim_test_result {0 {}} {1 SQLITE_NOMEM} } do_faultsim_test 2.3 -faults oom* -prep { catch {db2 close} catch {db close} faultsim_restore_and_reopen sqlite3 db2 test.db2 } -body { set rebase [sqlite3changeset_apply_v2 db $::C2 [list xConflict REPLACE]] set {} {} } -test { faultsim_test_result {0 {}} {1 SQLITE_NOMEM} } do_faultsim_test 2.4 -faults oom* -prep { catch {db2 close} catch {db close} faultsim_restore_and_reopen set ::rebase [sqlite3changeset_apply_v2 db $::C2 [list xConflict REPLACE]] } -body { sqlite3rebaser_create R R configure $::rebase R rebase $::C1 set {} {} } -test { catch { R delete } faultsim_test_result {0 {}} {1 SQLITE_NOMEM} } do_faultsim_test 2.5 -faults oom* -prep { catch {db2 close} catch {db close} faultsim_restore_and_reopen set ::rebase [sqlite3changeset_apply_v2 db $::C2 [list xConflict OMIT]] } -body { sqlite3rebaser_create R R configure $::rebase R rebase $::C1 set {} {} } -test { catch { R delete } faultsim_test_result {0 {}} {1 SQLITE_NOMEM} } } reset_db do_execsql_test 3.0 { CREATE TABLE t1(x PRIMARY KEY, y, z); INSERT INTO t1 VALUES(3, 1, 4); INSERT INTO t1 VALUES(1, 5, 9); } faultsim_save_and_close proc xConflict {ret args} { return $ret } do_test 3.1 { faultsim_restore_and_reopen execsql { BEGIN; UPDATE t1 SET z=11; } set C1 [changeset_from_sql { UPDATE t1 SET z=10 WHERE x=1; }] execsql { ROLLBACK } execsql { BEGIN; UPDATE t1 SET z=11; } set C2 [changeset_from_sql { UPDATE t1 SET z=55 WHERE x=1; }] execsql { ROLLBACK } set ::rebase1 [sqlite3changeset_apply_v2 db $::C1 [list xConflict OMIT]] set ::rebase2 [sqlite3changeset_apply_v2 db $::C2 [list xConflict OMIT]] set {} {} execsql { SELECT * FROM t1 } } {3 1 4 1 5 9} do_faultsim_test 3.2 -faults oom* -prep { faultsim_restore_and_reopen } -body { sqlite3rebaser_create R R configure $::rebase1 R configure $::rebase2 set {} {} } -test { catch { R delete } faultsim_test_result {0 {}} {1 SQLITE_NOMEM} } finish_test |
Added ext/session/sessionrebase.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 | # 2018 March 14 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. # if {![info exists testdir]} { set testdir [file join [file dirname [info script]] .. .. test] } source [file join [file dirname [info script]] session_common.tcl] source $testdir/tester.tcl ifcapable !session {finish_test; return} set testprefix sessionrebase set ::lConflict [list] proc xConflict {args} { set res [lindex $::lConflict 0] set ::lConflict [lrange $::lConflict 1 end] return $res } #------------------------------------------------------------------------- # The following test cases - 1.* - test that the rebase blobs output by # sqlite3_changeset_apply_v2 look correct in some simple cases. The blob # is itself a changeset, containing records determined as follows: # # * For each conflict resolved with REPLACE, the rebase blob contains # a DELETE record. All fields other than the PK fields are undefined. # # * For each conflict resolved with OMIT, the rebase blob contains an # INSERT record. For an INSERT or UPDATE operation, the indirect flag # is clear and all updated fields are defined. For a DELETE operation, # the indirect flag is set and all non-PK fields left undefined. # proc do_apply_v2_test {tn sql modsql conflict_handler res} { execsql BEGIN sqlite3session S db main S attach * execsql $sql set changeset [S changeset] S delete execsql ROLLBACK execsql BEGIN execsql $modsql set ::lConflict $conflict_handler set blob [sqlite3changeset_apply_v2 db $changeset xConflict] execsql ROLLBACK uplevel [list do_test $tn [list changeset_to_list $blob] [list {*}$res]] } set ::lConflict [list] proc xConflict {args} { set res [lindex $::lConflict 0] set ::lConflict [lrange $::lConflict 1 end] return $res } # Take a copy of database test.db in file test.db2. Execute $sql1 # against test.db and $sql2 against test.db2. Capture a changeset # for each. Then send the test.db2 changeset to test.db and apply # it with the conflict handlers in $conflict_handler. Patch the # test.db changeset and then execute it against test.db2. Test that # the two databases come out the same. # proc do_rebase_test {tn sql1 sql2 conflict_handler {testsql ""} {testres ""}} { for {set i 1} {$i <= 2} {incr i} { forcedelete test.db2 test.db2-journal test.db2-wal forcecopy test.db test.db2 sqlite3 db2 test.db2 db eval BEGIN sqlite3session S1 db main S1 attach * execsql $sql1 db set c1 [S1 changeset] S1 delete if {$i==1} { sqlite3session S2 db2 main S2 attach * execsql $sql2 db2 set c2 [S2 changeset] S2 delete } else { set c2 [list] foreach sql [split $sql2 ";"] { if {[string is space $sql]} continue sqlite3session S2 db2 main S2 attach * execsql $sql db2 lappend c2 [S2 changeset] S2 delete } } set ::lConflict $conflict_handler set rebase [list] if {$i==1} { lappend rebase [sqlite3changeset_apply_v2 db $c2 xConflict] } else { foreach c $c2 { #puts "apply_v2: [changeset_to_list $c]" lappend rebase [sqlite3changeset_apply_v2 db $c xConflict] } #puts "llength: [llength $rebase]" } #if {$tn=="2.1.4"} { puts [changeset_to_list $rebase] ; breakpoint } #puts [changeset_to_list [lindex $rebase 0]] ; breakpoint #puts [llength $rebase] sqlite3rebaser_create R foreach r $rebase { #puts [changeset_to_list $r] R configure $r } set c1r [R rebase $c1] R delete #if {$tn=="2.1.4"} { puts [changeset_to_list $c1r] } sqlite3changeset_apply_v2 db2 $c1r xConflictAbort if {[string range $tn end end]!="*"} { uplevel [list do_test $tn.$i.1 [list compare_db db db2] {}] } db2 close if {$testsql!=""} { uplevel [list do_execsql_test $tn.$i.2 $testsql $testres] } db eval ROLLBACK } } do_execsql_test 1.0 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b); INSERT INTO t1 VALUES(1, 'value A'); } do_apply_v2_test 1.1.1 { UPDATE t1 SET b = 'value B' WHERE a=1; } { UPDATE t1 SET b = 'value C' WHERE a=1; } { OMIT } { {INSERT t1 0 X. {} {i 1 t {value B}}} } do_apply_v2_test 1.1.2 { UPDATE t1 SET b = 'value B' WHERE a=1; } { UPDATE t1 SET b = 'value C' WHERE a=1; } { REPLACE } { {INSERT t1 1 X. {} {i 1 t {value B}}} } do_apply_v2_test 1.2.1 { INSERT INTO t1 VALUES(2, 'first'); } { INSERT INTO t1 VALUES(2, 'second'); } { OMIT } { {INSERT t1 0 X. {} {i 2 t first}} } do_apply_v2_test 1.2.2 { INSERT INTO t1 VALUES(2, 'first'); } { INSERT INTO t1 VALUES(2, 'second'); } { REPLACE } { {INSERT t1 1 X. {} {i 2 t first}} } do_apply_v2_test 1.3.1 { DELETE FROM t1 WHERE a=1; } { UPDATE t1 SET b='value D' WHERE a=1; } { OMIT } { {DELETE t1 0 X. {i 1 t {value A}} {}} } do_apply_v2_test 1.3.2 { DELETE FROM t1 WHERE a=1; } { UPDATE t1 SET b='value D' WHERE a=1; } { REPLACE } { {DELETE t1 1 X. {i 1 t {value A}} {}} } #------------------------------------------------------------------------- # Test cases 2.* - simple tests of rebasing actual changesets. # # 2.1.1 - 1u2u1r # 2.1.2 - 1u2u2r # 2.1.3 - 1d2d # 2.1.4 - 1d2u1r # 2.1.5 - 1d2u2r !! # 2.1.6 - 1u2d1r # 2.1.7 - 1u2d2r # # 2.1.8 - 1i2i2r # 2.1.9 - 1i2i1r # proc xConflictAbort {args} { return "ABORT" } reset_db do_execsql_test 2.1.0 { CREATE TABLE t1 (a INTEGER PRIMARY KEY, b TEXT); INSERT INTO t1 VALUES(1, 'one'); INSERT INTO t1 VALUES(2, 'two'); INSERT INTO t1 VALUES(3, 'three'); } do_rebase_test 2.1.1 { UPDATE t1 SET b = 'two.1' WHERE a=2 } { UPDATE t1 SET b = 'two.2' WHERE a=2; } { OMIT } { SELECT * FROM t1 } {1 one 2 two.1 3 three} do_rebase_test 2.1.2 { UPDATE t1 SET b = 'two.1' WHERE a=2 } { UPDATE t1 SET b = 'two.2' WHERE a=2; } { REPLACE } { SELECT * FROM t1 } {1 one 2 two.2 3 three} do_rebase_test 2.1.3 { DELETE FROM t1 WHERE a=3 } { DELETE FROM t1 WHERE a=3; } { OMIT } { SELECT * FROM t1 } {1 one 2 two} do_rebase_test 2.1.4 { DELETE FROM t1 WHERE a=1 } { UPDATE t1 SET b='one.2' WHERE a=1 } { OMIT } { SELECT * FROM t1 } {2 two 3 three} #do_rebase_test 2.1.5 { # DELETE FROM t1 WHERE a=1; #} { # UPDATE t1 SET b='one.2' WHERE a=1 #} { # REPLACE #} { SELECT * FROM t1 } {2 two 3 three} do_rebase_test 2.1.6 { UPDATE t1 SET b='three.1' WHERE a=3 } { DELETE FROM t1 WHERE a=3; } { OMIT } { SELECT * FROM t1 } {1 one 2 two 3 three.1} do_rebase_test 2.1.7 { UPDATE t1 SET b='three.1' WHERE a=3 } { DELETE FROM t1 WHERE a=3; } { REPLACE } { SELECT * FROM t1 } {1 one 2 two} do_rebase_test 2.1.8 { INSERT INTO t1 VALUES(4, 'four.1') } { INSERT INTO t1 VALUES(4, 'four.2'); } { REPLACE } { SELECT * FROM t1 } {1 one 2 two 3 three 4 four.2} do_rebase_test 2.1.9 { INSERT INTO t1 VALUES(4, 'four.1') } { INSERT INTO t1 VALUES(4, 'four.2'); } { OMIT } { SELECT * FROM t1 } {1 one 2 two 3 three 4 four.1} do_execsql_test 2.2.0 { CREATE TABLE t2(x, y, z PRIMARY KEY); INSERT INTO t2 VALUES('i', 'a', 'A'); INSERT INTO t2 VALUES('ii', 'b', 'B'); INSERT INTO t2 VALUES('iii', 'c', 'C'); CREATE TABLE t3(a INTEGER PRIMARY KEY, b, c); INSERT INTO t3 VALUES(-1, 'z', 'Z'); INSERT INTO t3 VALUES(-2, 'y', 'Y'); } do_rebase_test 2.2.1 { UPDATE t2 SET x=1 WHERE z='A' } { UPDATE t2 SET y='one' WHERE z='A'; } { } { SELECT * FROM t2 WHERE z='A' } { 1 one A } do_rebase_test 2.2.2 { UPDATE t2 SET x=1, y='one' WHERE z='B' } { UPDATE t2 SET y='two' WHERE z='B'; } { REPLACE } { SELECT * FROM t2 WHERE z='B' } { 1 two B } do_rebase_test 2.2.3 { UPDATE t2 SET x=1, y='one' WHERE z='B' } { UPDATE t2 SET y='two' WHERE z='B'; } { OMIT } { SELECT * FROM t2 WHERE z='B' } { 1 one B } #------------------------------------------------------------------------- reset_db do_execsql_test 3.0 { CREATE TABLE t3(a, b, c, PRIMARY KEY(b, c)); CREATE TABLE abcdefghijkl(x PRIMARY KEY, y, z); INSERT INTO t3 VALUES(1, 2, 3); INSERT INTO t3 VALUES(4, 2, 5); INSERT INTO t3 VALUES(7, 2, 9); INSERT INTO abcdefghijkl VALUES('a', 'b', 'c'); INSERT INTO abcdefghijkl VALUES('d', 'e', 'f'); INSERT INTO abcdefghijkl VALUES('g', 'h', 'i'); } breakpoint # do_rebase_test 3.6.tn { # UPDATE abcdefghijkl SET z='X', y='X' WHERE x='d'; # } { # UPDATE abcdefghijkl SET y=1 WHERE x='d'; # UPDATE abcdefghijkl SET z=1 WHERE x='d'; # } [list REPLACE REPLACE REPLACE] foreach {tn p} { 1 OMIT 2 REPLACE } { do_rebase_test 3.1.$tn { INSERT INTO t3 VALUES(1, 1, 1); UPDATE abcdefghijkl SET y=2; } { INSERT INTO t3 VALUES(4, 1, 1); DELETE FROM abcdefghijkl; } [list $p $p $p $p $p $p $p $p] do_rebase_test 3.2.$tn { INSERT INTO abcdefghijkl SELECT * FROM t3; UPDATE t3 SET b=b+1; } { INSERT INTO t3 VALUES(3, 3, 3); INSERT INTO abcdefghijkl SELECT * FROM t3; } [list $p $p $p $p $p $p $p $p] do_rebase_test 3.3.$tn { INSERT INTO abcdefghijkl VALUES(22, 23, 24); } { INSERT INTO abcdefghijkl VALUES(22, 25, 26); UPDATE abcdefghijkl SET y=400 WHERE x=22; } [list $p $p $p $p $p $p $p $p] do_rebase_test 3.4.$tn { INSERT INTO abcdefghijkl VALUES(22, 23, 24); } { INSERT INTO abcdefghijkl VALUES(22, 25, 26); UPDATE abcdefghijkl SET y=400 WHERE x=22; } [list REPLACE $p] do_rebase_test 3.5.$tn* { UPDATE abcdefghijkl SET y='X' WHERE x='d'; } { DELETE FROM abcdefghijkl WHERE x='d'; INSERT INTO abcdefghijkl VALUES('d', NULL, NULL); } [list $p $p $p] do_rebase_test 3.5.$tn { UPDATE abcdefghijkl SET y='X' WHERE x='d'; } { DELETE FROM abcdefghijkl WHERE x='d'; INSERT INTO abcdefghijkl VALUES('d', NULL, NULL); } [list REPLACE $p $p] do_rebase_test 3.6.$tn { UPDATE abcdefghijkl SET z='X', y='X' WHERE x='d'; } { UPDATE abcdefghijkl SET y=1 WHERE x='d'; UPDATE abcdefghijkl SET z=1 WHERE x='d'; } [list REPLACE $p $p] } #------------------------------------------------------------------------- # Check that apply_v2() does not create a rebase buffer for a patchset. # And that it is not possible to rebase a patchset. # do_execsql_test 4.0 { CREATE TABLE t5(o PRIMARY KEY, p, q); INSERT INTO t5 VALUES(1, 2, 3); INSERT INTO t5 VALUES(4, 5, 6); } foreach {tn cmd rebasable} { 1 patchset 0 2 changeset 1 } { proc xConflict {args} { return "OMIT" } do_test 4.1.$tn { execsql { BEGIN; DELETE FROM t5 WHERE o=4; } sqlite3session S db main S attach * execsql { INSERT INTO t5 VALUES(4, 'five', 'six'); } set P [S $cmd] S delete execsql ROLLBACK; set ::rebase [sqlite3changeset_apply_v2 db $P xConflict] expr [llength $::rebase]>0 } $rebasable } foreach {tn cmd rebasable} { 1 patchset 0 2 changeset 1 } { do_test 4.2.$tn { sqlite3session S db main S attach * execsql { INSERT INTO t5 VALUES(5+$tn, 'five', 'six'); } set P [S $cmd] S delete sqlite3rebaser_create R R configure $::rebase expr [catch {R rebase $P}]==0 } $rebasable catch { R delete } } finish_test |
Changes to ext/session/sqlite3session.c.
︙ | ︙ | |||
71 72 73 74 75 76 77 | /* ** An object of this type is used internally as an abstraction for ** input data. Input data may be supplied either as a single large buffer ** (e.g. sqlite3changeset_start()) or using a stream function (e.g. ** sqlite3changeset_start_strm()). */ struct SessionInput { | | | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | /* ** An object of this type is used internally as an abstraction for ** input data. Input data may be supplied either as a single large buffer ** (e.g. sqlite3changeset_start()) or using a stream function (e.g. ** sqlite3changeset_start_strm()). */ struct SessionInput { 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 */ int nData; /* Number of bytes in aData */ SessionBuffer buf; /* Current read buffer */ int (*xInput)(void*, void*, int*); /* Input stream call (or NULL) */ |
︙ | ︙ | |||
235 236 237 238 239 240 241 | ** ** As in the changeset format, each field of the single record that is part ** of a patchset change is associated with the correspondingly positioned ** table column, counting from left to right within the CREATE TABLE ** statement. ** ** For a DELETE change, all fields within the record except those associated | | | | 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 | ** ** As in the changeset format, each field of the single record that is part ** of a patchset change is associated with the correspondingly positioned ** table column, counting from left to right within the CREATE TABLE ** statement. ** ** For a DELETE change, all fields within the record except those associated ** 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". ** PRIMARY KEY fields contain the values identifying the table row to update, ** and fields associated with modified columns contain the new column values. ** ** The records associated with INSERT changes are in the same format as for |
︙ | ︙ | |||
519 520 521 522 523 524 525 | ** The buffer that the argument points to contains a serialized SQL value. ** Return the number of bytes of space occupied by the value (including ** the type byte). */ static int sessionSerialLen(u8 *a){ int e = *a; int n; | | | 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 | ** The buffer that the argument points to contains a serialized SQL value. ** Return the number of bytes of space occupied by the value (including ** the type byte). */ static int sessionSerialLen(u8 *a){ int e = *a; int n; 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; } /* ** Based on the primary key values stored in change aRecord, calculate a |
︙ | ︙ | |||
599 600 601 602 603 604 605 | int iCol; /* Used to iterate through table columns */ for(iCol=0; iCol<pTab->nCol; iCol++){ if( pTab->abPK[iCol] ){ int n1 = sessionSerialLen(a1); int n2 = sessionSerialLen(a2); | | | 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 | int iCol; /* Used to iterate through table columns */ for(iCol=0; iCol<pTab->nCol; iCol++){ if( pTab->abPK[iCol] ){ int n1 = sessionSerialLen(a1); int n2 = sessionSerialLen(a2); if( n1!=n2 || memcmp(a1, a2, n1) ){ return 0; } a1 += n1; a2 += n2; }else{ if( bLeftPkOnly==0 ) a1 += sessionSerialLen(a1); if( bRightPkOnly==0 ) a2 += sessionSerialLen(a2); |
︙ | ︙ | |||
842 843 844 845 846 847 848 | a += sessionVarintGet(a, &n); if( sqlite3_value_bytes(pVal)!=n ) return 0; if( eType==SQLITE_TEXT ){ z = sqlite3_value_text(pVal); }else{ z = sqlite3_value_blob(pVal); } | | | 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 | a += sessionVarintGet(a, &n); if( sqlite3_value_bytes(pVal)!=n ) return 0; if( eType==SQLITE_TEXT ){ z = sqlite3_value_text(pVal); }else{ z = sqlite3_value_blob(pVal); } if( n>0 && memcmp(a, z, n) ) return 0; a += n; } } } return 1; } |
︙ | ︙ | |||
2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 | int nSql = -1; if( 0==sqlite3_stricmp("sqlite_stat1", zTab) ){ zSql = sqlite3_mprintf( "SELECT tbl, ?2, stat FROM %Q.sqlite_stat1 WHERE tbl IS ?1 AND " "idx IS (CASE WHEN ?2=X'' THEN NULL ELSE ?2 END)", zDb ); }else{ int i; const char *zSep = ""; SessionBuffer buf = {0, 0, 0}; sessionAppendStr(&buf, "SELECT * FROM ", &rc); sessionAppendIdent(&buf, zDb, &rc); | > | 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 | int nSql = -1; if( 0==sqlite3_stricmp("sqlite_stat1", zTab) ){ zSql = sqlite3_mprintf( "SELECT tbl, ?2, stat FROM %Q.sqlite_stat1 WHERE tbl IS ?1 AND " "idx IS (CASE WHEN ?2=X'' THEN NULL ELSE ?2 END)", zDb ); if( zSql==0 ) rc = SQLITE_NOMEM; }else{ int i; const char *zSep = ""; SessionBuffer buf = {0, 0, 0}; sessionAppendStr(&buf, "SELECT * FROM ", &rc); sessionAppendIdent(&buf, zDb, &rc); |
︙ | ︙ | |||
2609 2610 2611 2612 2613 2614 2615 | } /* ** If the SessionInput object passed as the only argument is a streaming ** object and the buffer is full, discard some data to free up space. */ static void sessionDiscardData(SessionInput *pIn){ | | | 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 | } /* ** If the SessionInput object passed as the only argument is a streaming ** 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 ){ int nMove = pIn->buf.nBuf - pIn->iNext; assert( nMove>=0 ); if( nMove>0 ){ memmove(pIn->buf.aBuf, &pIn->buf.aBuf[pIn->iNext], nMove); } pIn->buf.nBuf -= pIn->iNext; pIn->iNext = 0; |
︙ | ︙ | |||
2935 2936 2937 2938 2939 2940 2941 | ** successfully advanced to the next change in the changeset, an SQLite ** error code if an error occurs, or SQLITE_DONE if there are no further ** changes in the changeset. */ static int sessionChangesetNext( sqlite3_changeset_iter *p, /* Changeset iterator */ u8 **paRec, /* If non-NULL, store record pointer here */ | | > | 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 | ** successfully advanced to the next change in the changeset, an SQLite ** error code if an error occurs, or SQLITE_DONE if there are no further ** changes in the changeset. */ 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 *pbNew /* If non-NULL, true if new table */ ){ int i; u8 op; assert( (paRec==0 && pnRec==0) || (paRec && pnRec) ); /* If the iterator is in the error-state, return immediately. */ |
︙ | ︙ | |||
2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 | } sessionDiscardData(&p->in); p->in.iCurrent = p->in.iNext; op = p->in.aData[p->in.iNext++]; while( op=='T' || op=='P' ){ p->bPatchset = (op=='P'); if( sessionChangesetReadTblhdr(p) ) return p->rc; if( (p->rc = sessionInputBuffer(&p->in, 2)) ) return p->rc; p->in.iCurrent = p->in.iNext; if( p->in.iNext>=p->in.nData ) return SQLITE_DONE; op = p->in.aData[p->in.iNext++]; } | > | 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 | } sessionDiscardData(&p->in); p->in.iCurrent = p->in.iNext; 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; p->in.iCurrent = p->in.iNext; if( p->in.iNext>=p->in.nData ) return SQLITE_DONE; op = p->in.aData[p->in.iNext++]; } |
︙ | ︙ | |||
3048 3049 3050 3051 3052 3053 3054 | ** change in the changeset. This function may return SQLITE_ROW, SQLITE_DONE ** or SQLITE_CORRUPT. ** ** This function may not be called on iterators passed to a conflict handler ** callback by changeset_apply(). */ int sqlite3changeset_next(sqlite3_changeset_iter *p){ | | | 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 | ** change in the changeset. This function may return SQLITE_ROW, SQLITE_DONE ** or SQLITE_CORRUPT. ** ** This function may not be called on iterators passed to a conflict handler ** callback by changeset_apply(). */ int sqlite3changeset_next(sqlite3_changeset_iter *p){ return sessionChangesetNext(p, 0, 0, 0); } /* ** The following function extracts information on the current change ** from a changeset iterator. It may only be called after changeset_next() ** has returned SQLITE_ROW. */ |
︙ | ︙ | |||
3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 | sqlite3_stmt *pSelect; /* SELECT statement */ 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 */ }; /* ** Formulate a statement to DELETE a row from database db. Assuming a table ** structure like this: ** ** CREATE TABLE x(a, b, c, d, PRIMARY KEY(a, c)); | > > | 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 | sqlite3_stmt *pSelect; /* SELECT statement */ 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 */ int bRebaseStarted; /* If table header is already in rebase */ }; /* ** Formulate a statement to DELETE a row from database db. Assuming a table ** structure like this: ** ** CREATE TABLE x(a, b, c, d, PRIMARY KEY(a, c)); |
︙ | ︙ | |||
3693 3694 3695 3696 3697 3698 3699 | 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)" ); } | < | 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 | 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. */ |
︙ | ︙ | |||
3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 | if( rc==SQLITE_OK ){ rc = sqlite3_step(pSelect); if( rc!=SQLITE_ROW ) rc = sqlite3_reset(pSelect); } return rc; } /* ** Invoke the conflict handler for the change that the changeset iterator ** currently points to. ** ** Argument eType must be either CHANGESET_DATA or CHANGESET_CONFLICT. ** If argument pbReplace is NULL, then the type of conflict handler invoked | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 | if( rc==SQLITE_OK ){ rc = sqlite3_step(pSelect); if( rc!=SQLITE_ROW ) rc = sqlite3_reset(pSelect); } return rc; } /* ** 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; 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. ** ** Argument eType must be either CHANGESET_DATA or CHANGESET_CONFLICT. ** If argument pbReplace is NULL, then the type of conflict handler invoked |
︙ | ︙ | |||
3883 3884 3885 3886 3887 3888 3889 | }else if( rc==SQLITE_OK ){ if( p->bDeferConstraints && eType==SQLITE_CHANGESET_CONFLICT ){ /* Instead of invoking the conflict handler, append the change blob ** to the SessionApplyCtx.constraints buffer. */ u8 *aBlob = &pIter->in.aData[pIter->in.iCurrent]; int nBlob = pIter->in.iNext - pIter->in.iCurrent; sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc); | | | 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 | }else if( rc==SQLITE_OK ){ if( p->bDeferConstraints && eType==SQLITE_CHANGESET_CONFLICT ){ /* Instead of invoking the conflict handler, append the change blob ** to the SessionApplyCtx.constraints buffer. */ u8 *aBlob = &pIter->in.aData[pIter->in.iCurrent]; int nBlob = pIter->in.iNext - pIter->in.iCurrent; sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc); return SQLITE_OK; }else{ /* No other row with the new.* primary key. */ res = xConflict(pCtx, eType+1, pIter); if( res==SQLITE_CHANGESET_REPLACE ) rc = SQLITE_MISUSE; } } |
︙ | ︙ | |||
3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 | rc = SQLITE_ABORT; break; default: rc = SQLITE_MISUSE; break; } } return rc; } /* ** Attempt to apply the change that the iterator passed as the first argument | > > > | 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 | rc = SQLITE_ABORT; break; default: rc = SQLITE_MISUSE; break; } if( rc==SQLITE_OK ){ rc = sessionRebaseAdd(p, res, pIter); } } return rc; } /* ** Attempt to apply the change that the iterator passed as the first argument |
︙ | ︙ | |||
4084 4085 4086 4087 4088 4089 4090 | void *pCtx /* First argument passed to xConflict */ ){ int bReplace = 0; int bRetry = 0; int rc; rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, &bReplace, &bRetry); | | < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 | void *pCtx /* First argument passed to xConflict */ ){ int bReplace = 0; int bRetry = 0; int rc; rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, &bReplace, &bRetry); 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 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); } } } return rc; } /* |
︙ | ︙ | |||
4195 4196 4197 4198 4199 4200 4201 | const char *zTab /* Table name */ ), int(*xConflict)( void *pCtx, /* Copy of fifth arg to _apply() */ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ sqlite3_changeset_iter *p /* Handle describing change and conflict */ ), | | > > | > | > | 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 | const char *zTab /* Table name */ ), int(*xConflict)( void *pCtx, /* Copy of fifth 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 information */ int flags /* SESSION_APPLY_XXX flags */ ){ int schemaMismatch = 0; 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 */ int bPatchset; assert( xConflict!=0 ); pIter->in.bNoDiscard = 1; memset(&sApply, 0, sizeof(sApply)); sqlite3_mutex_enter(sqlite3_db_mutex(db)); if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){ rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0); } if( rc==SQLITE_OK ){ rc = sqlite3_exec(db, "PRAGMA defer_foreign_keys = 1", 0, 0, 0); } while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter) ){ int nCol; int op; const char *zNew; |
︙ | ︙ | |||
4233 4234 4235 4236 4237 4238 4239 | if( rc!=SQLITE_OK ) break; sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */ sqlite3_finalize(sApply.pDelete); sqlite3_finalize(sApply.pUpdate); sqlite3_finalize(sApply.pInsert); sqlite3_finalize(sApply.pSelect); | < > > > > > > > > > > | 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 | if( rc!=SQLITE_OK ) break; sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */ sqlite3_finalize(sApply.pDelete); sqlite3_finalize(sApply.pUpdate); sqlite3_finalize(sApply.pInsert); sqlite3_finalize(sApply.pSelect); 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 ** non-zero, proceed. */ schemaMismatch = (xFilter && (0==xFilter(pCtx, zNew))); if( schemaMismatch ){ zTab = sqlite3_mprintf("%s", zNew); |
︙ | ︙ | |||
4338 4339 4340 4341 4342 4343 4344 | if( res!=SQLITE_CHANGESET_OMIT ){ rc = SQLITE_CONSTRAINT; } } } sqlite3_exec(db, "PRAGMA defer_foreign_keys = 0", 0, 0, 0); | > | | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 | if( res!=SQLITE_CHANGESET_OMIT ){ rc = SQLITE_CONSTRAINT; } } } sqlite3_exec(db, "PRAGMA defer_foreign_keys = 0", 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); } } if( rc==SQLITE_OK && bPatchset==0 && ppRebase && pnRebase ){ *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); 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". */ 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 rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset); 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. */ int sqlite3changeset_apply( |
︙ | ︙ | |||
4375 4376 4377 4378 4379 4380 4381 | int(*xConflict)( void *pCtx, /* Copy of fifth 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 */ ){ | < | < | < < > > > > > > > > > > > > > > > > > > > > > > > > > > > < | < | < < > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | > > > > > > > > > > > > > > > > > > > | 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 | int(*xConflict)( void *pCtx, /* Copy of fifth 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( db, nChangeset, pChangeset, xFilter, xConflict, pCtx, 0, 0, 0 ); } /* ** Apply the changeset passed via xInput/pIn to the main database ** attached to handle "db". Invoke the supplied conflict handler callback ** to resolve any conflicts encountered while applying the change. */ 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 ){ sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); if( rc==SQLITE_OK ){ rc = sessionChangesetApply( db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags ); } return rc; } 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. */ struct sqlite3_changegroup { int rc; /* Error code */ int bPatch; /* True to accumulate patchsets */ SessionTable *pList; /* List of tables in current patch */ }; /* ** This function is called to merge two changes to the same row together as ** part of an sqlite3changeset_concat() operation. A new change object is ** allocated and a pointer to it stored in *ppNew. */ 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 */ int bIndirect, /* True if second change is indirect */ u8 *aRec, /* Second change record */ int nRec, /* Number of bytes in aRec */ SessionChange **ppNew /* OUT: Merged change */ ){ SessionChange *pNew = 0; int rc = SQLITE_OK; if( !pExist ){ pNew = (SessionChange *)sqlite3_malloc(sizeof(SessionChange) + nRec); if( !pNew ){ return SQLITE_NOMEM; } memset(pNew, 0, sizeof(SessionChange)); pNew->op = op2; pNew->bIndirect = bIndirect; pNew->aRecord = (u8*)&pNew[1]; 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; /* ** op1=INSERT, op2=INSERT -> Unsupported. Discard op2. ** op1=INSERT, op2=UPDATE -> INSERT. ** op1=INSERT, op2=DELETE -> (none) |
︙ | ︙ | |||
4541 4542 4543 4544 4545 4546 4547 | pNew->nRecord = (int)(aCsr - pNew->aRecord); } sqlite3_free(pExist); } } *ppNew = pNew; | | | > < | | 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 | pNew->nRecord = (int)(aCsr - pNew->aRecord); } sqlite3_free(pExist); } } *ppNew = pNew; return rc; } /* ** Add all changes in the changeset traversed by the iterator passed as ** the first argument to the changegroup hash tables. */ static int sessionChangesetToHash( sqlite3_changeset_iter *pIter, /* Iterator to read from */ sqlite3_changegroup *pGrp, /* Changegroup object to add changeset to */ int bRebase /* True if hash table is for rebasing */ ){ u8 *aRec; int nRec; int rc = SQLITE_OK; SessionTable *pTab = 0; while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec, 0) ){ const char *zNew; int nCol; int op; int iHash; int bIndirect; SessionChange *pChange; SessionChange *pExist = 0; |
︙ | ︙ | |||
4638 4639 4640 4641 4642 4643 4644 | pExist = *pp; *pp = (*pp)->pNext; pTab->nEntry--; break; } } | | | 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 | pExist = *pp; *pp = (*pp)->pNext; pTab->nEntry--; break; } } rc = sessionChangeMerge(pTab, bRebase, pIter->bPatchset, pExist, op, bIndirect, aRec, nRec, &pChange ); if( rc ) break; if( pChange ){ pChange->pNext = pTab->apChange[iHash]; pTab->apChange[iHash] = pChange; pTab->nEntry++; |
︙ | ︙ | |||
4747 4748 4749 4750 4751 4752 4753 | */ int sqlite3changegroup_add(sqlite3_changegroup *pGrp, int nData, void *pData){ sqlite3_changeset_iter *pIter; /* Iterator opened on pData/nData */ int rc; /* Return code */ rc = sqlite3changeset_start(&pIter, nData, pData); if( rc==SQLITE_OK ){ | | | 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 | */ int sqlite3changegroup_add(sqlite3_changegroup *pGrp, int nData, void *pData){ sqlite3_changeset_iter *pIter; /* Iterator opened on pData/nData */ int rc; /* Return code */ rc = sqlite3changeset_start(&pIter, nData, pData); if( rc==SQLITE_OK ){ rc = sessionChangesetToHash(pIter, pGrp, 0); } sqlite3changeset_finalize(pIter); return rc; } /* ** Obtain a buffer containing a changeset representing the concatenation |
︙ | ︙ | |||
4778 4779 4780 4781 4782 4783 4784 | void *pIn ){ sqlite3_changeset_iter *pIter; /* Iterator opened on pData/nData */ int rc; /* Return code */ rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); if( rc==SQLITE_OK ){ | | | 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 | void *pIn ){ sqlite3_changeset_iter *pIter; /* Iterator opened on pData/nData */ int rc; /* Return code */ rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); if( rc==SQLITE_OK ){ rc = sessionChangesetToHash(pIter, pGrp, 0); } sqlite3changeset_finalize(pIter); return rc; } /* ** Streaming versions of changegroup_output(). |
︙ | ︙ | |||
4862 4863 4864 4865 4866 4867 4868 4869 4870 | if( rc==SQLITE_OK ){ rc = sqlite3changegroup_output_strm(pGrp, xOutput, pOut); } sqlite3changegroup_delete(pGrp); return rc; } #endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 | if( rc==SQLITE_OK ){ rc = sqlite3changegroup_output_strm(pGrp, xOutput, pOut); } sqlite3changegroup_delete(pGrp); return rc; } /* ** Changeset rebaser handle. */ struct sqlite3_rebaser { sqlite3_changegroup grp; /* Hash table */ }; /* ** 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 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 */ ){ 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{ memcpy(pOut, a1, nn1); pOut += nn1; } a1 += nn1; a2 += nn2; } pBuf->nBuf = pOut-pBuf->aBuf; assert( pBuf->nBuf<=pBuf->nAlloc ); } } /* ** 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. ** ** 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 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 */ ){ 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; *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'; } a1 += n1; a2 += n2; } 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'; } a1 += n1; a2 += n2; } pBuf->nBuf = (pOut - pBuf->aBuf); } } } /* ** 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. */ 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 */ ){ int rc = SQLITE_OK; u8 *aRec = 0; int nRec = 0; int bNew = 0; SessionTable *pTab = 0; SessionBuffer sOut = {0,0,0}; while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec, &bNew) ){ SessionChange *pChange = 0; int bDone = 0; if( bNew ){ const char *zTab = pIter->zTab; for(pTab=p->grp.pList; pTab; pTab=pTab->pNext){ if( 0==sqlite3_stricmp(pTab->zName, zTab) ) break; } bNew = 0; /* A patchset may not be rebased */ if( pIter->bPatchset ){ rc = SQLITE_ERROR; } /* 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); } if( pTab && rc==SQLITE_OK ){ int iHash = sessionChangeHash(pTab, 0, aRec, pTab->nChange); for(pChange=pTab->apChange[iHash]; pChange; pChange=pChange->pNext){ if( sessionChangeEqual(pTab, 0, aRec, 0, pChange->aRecord) ){ break; } } } 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; 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; 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; } } if( bDone==0 ){ sessionAppendByte(&sOut, pIter->op, &rc); sessionAppendByte(&sOut, pIter->bIndirect, &rc); sessionAppendBlob(&sOut, aRec, nRec, &rc); } if( rc==SQLITE_OK && xOutput && sOut.nBuf>SESSIONS_STRM_CHUNK_SIZE ){ rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); sOut.nBuf = 0; } if( rc ) break; } if( rc!=SQLITE_OK ){ sqlite3_free(sOut.aBuf); memset(&sOut, 0, sizeof(sOut)); } if( rc==SQLITE_OK ){ if( xOutput ){ if( sOut.nBuf>0 ){ rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); } }else{ *ppOut = (void*)sOut.aBuf; *pnOut = sOut.nBuf; sOut.aBuf = 0; } } sqlite3_free(sOut.aBuf); return rc; } /* ** Create a new rebaser object. */ int sqlite3rebaser_create(sqlite3_rebaser **ppNew){ int rc = SQLITE_OK; sqlite3_rebaser *pNew; pNew = sqlite3_malloc(sizeof(sqlite3_rebaser)); if( pNew==0 ){ rc = SQLITE_NOMEM; }else{ memset(pNew, 0, sizeof(sqlite3_rebaser)); } *ppNew = pNew; return rc; } /* ** Call this one or more times to configure a rebaser. */ int sqlite3rebaser_configure( sqlite3_rebaser *p, int nRebase, const void *pRebase ){ 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); } sqlite3changeset_finalize(pIter); return rc; } /* ** Rebase a changeset according to current rebaser configuration */ int sqlite3rebaser_rebase( sqlite3_rebaser *p, int nIn, const void *pIn, int *pnOut, void **ppOut ){ sqlite3_changeset_iter *pIter = 0; /* Iterator to skip through input */ int rc = sqlite3changeset_start(&pIter, nIn, (void*)pIn); if( rc==SQLITE_OK ){ rc = sessionRebase(p, pIter, 0, 0, pnOut, ppOut); sqlite3changeset_finalize(pIter); } return rc; } /* ** Rebase a changeset according to current rebaser configuration */ 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 ){ sqlite3_changeset_iter *pIter = 0; /* Iterator to skip through input */ int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); if( rc==SQLITE_OK ){ rc = sessionRebase(p, pIter, xOutput, pOut, 0, 0); sqlite3changeset_finalize(pIter); } return rc; } /* ** Destroy a rebaser object */ void sqlite3rebaser_delete(sqlite3_rebaser *p){ if( p ){ sessionDeleteTable(p->grp.pList); sqlite3_free(p); } } #endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */ |
Changes to ext/session/sqlite3session.h.
︙ | ︙ | |||
957 958 959 960 961 962 963 | ** DESTRUCTOR: sqlite3_changegroup */ void sqlite3changegroup_delete(sqlite3_changegroup*); /* ** CAPI3REF: Apply A Changeset To A Database ** | | | | | | | | | < | 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 | ** DESTRUCTOR: sqlite3_changegroup */ void sqlite3changegroup_delete(sqlite3_changegroup*); /* ** CAPI3REF: Apply A Changeset To A Database ** ** 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 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 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 ** considered compatible if all of the following are true: ** ** <ul> ** <li> The table has the same name as the name recorded in the |
︙ | ︙ | |||
1014 1015 1016 1017 1018 1019 1020 | ** actions are taken by sqlite3changeset_apply() depending on the value ** returned by each invocation of the conflict-handler function. Refer to ** the documentation for the three ** [SQLITE_CHANGESET_OMIT|available return values] for details. ** ** <dl> ** <dt>DELETE Changes<dd> | | | 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 | ** actions are taken by sqlite3changeset_apply() depending on the value ** returned by each invocation of the conflict-handler function. Refer to ** the documentation for the three ** [SQLITE_CHANGESET_OMIT|available return values] for details. ** ** <dl> ** <dt>DELETE Changes<dd> ** 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 ** the changeset the row is deleted from the target database. ** ** If a row with matching primary key values is found, but one or more of ** the non-primary key fields contains a value different from the original |
︙ | ︙ | |||
1059 1060 1061 1062 1063 1064 1065 | ** violation (e.g. NOT NULL or UNIQUE), the conflict handler function is ** invoked with the second argument set to [SQLITE_CHANGESET_CONSTRAINT]. ** This includes the case where the INSERT operation is re-attempted because ** an earlier call to the conflict handler function returned ** [SQLITE_CHANGESET_REPLACE]. ** ** <dt>UPDATE Changes<dd> | | | 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 | ** violation (e.g. NOT NULL or UNIQUE), the conflict handler function is ** invoked with the second argument set to [SQLITE_CHANGESET_CONSTRAINT]. ** This includes the case where the INSERT operation is re-attempted because ** an earlier call to the conflict handler function returned ** [SQLITE_CHANGESET_REPLACE]. ** ** <dt>UPDATE Changes<dd> ** 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 ** stored in the changeset the row is updated within the target database. ** ** If a row with matching primary key values is found, but one or more of ** the modified non-primary key fields contains a value different from an |
︙ | ︙ | |||
1090 1091 1092 1093 1094 1095 1096 | ** </dl> ** ** It is safe to execute SQL statements, including those that write to the ** table that the callback related to, from within the xConflict callback. ** This can be used to further customize the applications conflict ** resolution strategy. ** | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 | ** </dl> ** ** It is safe to execute SQL statements, including those that write to the ** table that the callback related to, from within the xConflict callback. ** This can be used to further customize the applications conflict ** resolution strategy. ** ** 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. */ int sqlite3changeset_apply( 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 */ ); 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 /* Combination of SESSION_APPLY_* 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. */ #define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001 /* ** CAPI3REF: Constants Passed To The Conflict Handler ** ** Values that may be passed as the second argument to a conflict-handler. ** ** <dl> |
︙ | ︙ | |||
1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 | ** and the call to sqlite3changeset_apply() returns SQLITE_ABORT. ** </dl> */ #define SQLITE_CHANGESET_OMIT 0 #define SQLITE_CHANGESET_REPLACE 1 #define SQLITE_CHANGESET_ABORT 2 /* ** CAPI3REF: Streaming Versions of API functions. ** ** The six streaming API xxx_strm() functions serve similar purposes to the ** corresponding non-streaming API functions: ** ** <table border=1 style="margin-left:8ex;margin-right:8ex"> ** <tr><th>Streaming function<th>Non-streaming equivalent</th> ** <tr><td>sqlite3changeset_apply_strm<td>[sqlite3changeset_apply] ** <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> ** | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 | ** and the call to sqlite3changeset_apply() returns SQLITE_ABORT. ** </dl> */ #define SQLITE_CHANGESET_OMIT 0 #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. */ 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(). */ 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. */ 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(). */ void sqlite3rebaser_delete(sqlite3_rebaser *p); /* ** CAPI3REF: Streaming Versions of API functions. ** ** The six streaming API xxx_strm() functions serve similar purposes to the ** corresponding non-streaming API functions: ** ** <table border=1 style="margin-left:8ex;margin-right:8ex"> ** <tr><th>Streaming function<th>Non-streaming equivalent</th> ** <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> ** |
︙ | ︙ | |||
1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 | ), 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 */ ); int sqlite3changeset_concat_strm( int (*xInputA)(void *pIn, void *pData, int *pnData), void *pInA, int (*xInputB)(void *pIn, void *pData, int *pnData), void *pInB, int (*xOutput)(void *pOut, const void *pData, int nData), | > > > > > > > > > > > > > > > > > | 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 | ), 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 */ ); 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 ); int sqlite3changeset_concat_strm( int (*xInputA)(void *pIn, void *pData, int *pnData), void *pInA, int (*xInputB)(void *pIn, void *pData, int *pnData), void *pInB, int (*xOutput)(void *pOut, const void *pData, int nData), |
︙ | ︙ | |||
1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 | int sqlite3changegroup_add_strm(sqlite3_changegroup*, int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn ); int sqlite3changegroup_output_strm(sqlite3_changegroup*, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); /* ** Make sure we can call this stuff from C++. */ #ifdef __cplusplus } #endif #endif /* !defined(__SQLITESESSION_H_) && defined(SQLITE_ENABLE_SESSION) */ | > > > > > > > | 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 | int sqlite3changegroup_add_strm(sqlite3_changegroup*, int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn ); int sqlite3changegroup_output_strm(sqlite3_changegroup*, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); 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 ); /* ** Make sure we can call this stuff from C++. */ #ifdef __cplusplus } #endif #endif /* !defined(__SQLITESESSION_H_) && defined(SQLITE_ENABLE_SESSION) */ |
Changes to ext/session/test_session.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # include "sqlite_tcl.h" #else # include "tcl.h" # ifndef SQLITE_TCLAPI # define SQLITE_TCLAPI # endif #endif typedef struct TestSession TestSession; struct TestSession { sqlite3_session *pSession; Tcl_Interp *interp; Tcl_Obj *pFilterScript; }; | > > > > | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # include "sqlite_tcl.h" #else # include "tcl.h" # ifndef SQLITE_TCLAPI # define SQLITE_TCLAPI # endif #endif #ifndef SQLITE_AMALGAMATION typedef unsigned char u8; #endif typedef struct TestSession TestSession; struct TestSession { sqlite3_session *pSession; Tcl_Interp *interp; Tcl_Obj *pFilterScript; }; |
︙ | ︙ | |||
712 713 714 715 716 717 718 | } *pnData = nRet; return SQLITE_OK; } | < < < | > > > > > > > > > > > > > > > < > > > > | > | | > | | | | > > > > > > > | | > | > > > > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 | } *pnData = nRet; return SQLITE_OK; } static int SQLITE_TCLAPI testSqlite3changesetApply( int bV2, void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ sqlite3 *db; /* Database handle */ Tcl_CmdInfo info; /* Database Tcl command (objv[1]) info */ int rc; /* Return code from changeset_invert() */ void *pChangeset; /* Buffer containing changeset */ int nChangeset; /* Size of buffer aChangeset in bytes */ TestConflictHandler ctx; TestStreamInput sStr; void *pRebase = 0; int nRebase = 0; int flags = 0; /* Flags for apply_v2() */ memset(&sStr, 0, sizeof(sStr)); sStr.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR); /* Check for the -nosavepoint flag */ if( bV2 && objc>1 ){ const char *z1 = Tcl_GetString(objv[1]); int n = strlen(z1); if( n>1 && n<=12 && 0==sqlite3_strnicmp("-nosavepoint", z1, n) ){ flags = SQLITE_CHANGESETAPPLY_NOSAVEPOINT; objc--; objv++; } } if( objc!=4 && objc!=5 ){ const char *zMsg; if( bV2 ){ zMsg = "?-nosavepoint? DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?"; }else{ zMsg = "DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?"; } Tcl_WrongNumArgs(interp, 1, objv, zMsg); return TCL_ERROR; } if( 0==Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &info) ){ Tcl_AppendResult(interp, "no such handle: ", Tcl_GetString(objv[1]), 0); return TCL_ERROR; } db = *(sqlite3 **)info.objClientData; pChangeset = (void *)Tcl_GetByteArrayFromObj(objv[2], &nChangeset); ctx.pConflictScript = objv[3]; ctx.pFilterScript = objc==5 ? objv[4] : 0; ctx.interp = interp; if( sStr.nStream==0 ){ if( bV2==0 ){ rc = sqlite3changeset_apply(db, nChangeset, pChangeset, (objc==5)?test_filter_handler:0, test_conflict_handler, (void *)&ctx ); }else{ rc = sqlite3changeset_apply_v2(db, nChangeset, pChangeset, (objc==5)?test_filter_handler:0, test_conflict_handler, (void *)&ctx, &pRebase, &nRebase, flags ); } }else{ sStr.aData = (unsigned char*)pChangeset; sStr.nData = nChangeset; if( bV2==0 ){ rc = sqlite3changeset_apply_strm(db, testStreamInput, (void*)&sStr, (objc==5) ? test_filter_handler : 0, test_conflict_handler, (void *)&ctx ); }else{ rc = sqlite3changeset_apply_v2_strm(db, testStreamInput, (void*)&sStr, (objc==5) ? test_filter_handler : 0, test_conflict_handler, (void *)&ctx, &pRebase, &nRebase, flags ); } } if( rc!=SQLITE_OK ){ return test_session_error(interp, rc, 0); }else{ Tcl_ResetResult(interp); if( bV2 && pRebase ){ Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pRebase, nRebase)); } } sqlite3_free(pRebase); return TCL_OK; } /* ** sqlite3changeset_apply DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT? */ static int SQLITE_TCLAPI test_sqlite3changeset_apply( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ return testSqlite3changesetApply(0, clientData, interp, objc, objv); } /* ** sqlite3changeset_apply_v2 DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT? */ static int SQLITE_TCLAPI test_sqlite3changeset_apply_v2( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ return testSqlite3changesetApply(1, clientData, interp, objc, objv); } /* ** sqlite3changeset_apply_replace_all DB CHANGESET */ static int SQLITE_TCLAPI test_sqlite3changeset_apply_replace_all( void * clientData, Tcl_Interp *interp, |
︙ | ︙ | |||
1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 | Tcl_CreateObjCommand( interp, Tcl_GetString(objv[1]), test_changebatch_cmd, (ClientData)p, test_changebatch_del ); Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } int TestSession_Init(Tcl_Interp *interp){ struct Cmd { const char *zCmd; Tcl_ObjCmdProc *xProc; } aCmd[] = { { "sqlite3session", test_sqlite3session }, { "sqlite3session_foreach", test_sqlite3session_foreach }, { "sqlite3changeset_invert", test_sqlite3changeset_invert }, { "sqlite3changeset_concat", test_sqlite3changeset_concat }, { "sqlite3changeset_apply", test_sqlite3changeset_apply }, { "sqlite3changeset_apply_replace_all", test_sqlite3changeset_apply_replace_all }, { "sql_exec_changeset", test_sql_exec_changeset }, }; int i; for(i=0; i<sizeof(aCmd)/sizeof(struct Cmd); i++){ struct Cmd *p = &aCmd[i]; Tcl_CreateObjCommand(interp, p->zCmd, p->xProc, 0, 0); } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 | Tcl_CreateObjCommand( interp, Tcl_GetString(objv[1]), test_changebatch_cmd, (ClientData)p, test_changebatch_del ); Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } /* ** tclcmd: CMD configure REBASE-BLOB ** tclcmd: CMD rebase CHANGESET ** tclcmd: CMD delete */ static int SQLITE_TCLAPI test_rebaser_cmd( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ struct RebaseSubcmd { const char *zSub; int nArg; const char *zMsg; int iSub; } aSub[] = { { "configure", 1, "REBASE-BLOB" }, /* 0 */ { "delete", 0, "" }, /* 1 */ { "rebase", 1, "CHANGESET" }, /* 2 */ { 0 } }; sqlite3_rebaser *p = (sqlite3_rebaser*)clientData; int iSub; int rc; if( objc<2 ){ Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ..."); return TCL_ERROR; } rc = Tcl_GetIndexFromObjStruct(interp, objv[1], aSub, sizeof(aSub[0]), "sub-command", 0, &iSub ); if( rc!=TCL_OK ) return rc; if( objc!=2+aSub[iSub].nArg ){ Tcl_WrongNumArgs(interp, 2, objv, aSub[iSub].zMsg); return TCL_ERROR; } assert( iSub==0 || iSub==1 || iSub==2 ); assert( rc==SQLITE_OK ); switch( iSub ){ case 0: { /* configure */ int nRebase = 0; unsigned char *pRebase = Tcl_GetByteArrayFromObj(objv[2], &nRebase); rc = sqlite3rebaser_configure(p, nRebase, pRebase); break; } case 1: /* delete */ Tcl_DeleteCommand(interp, Tcl_GetString(objv[0])); break; default: { /* rebase */ TestStreamInput sStr; /* Input stream */ TestSessionsBlob sOut; /* Output blob */ memset(&sStr, 0, sizeof(sStr)); memset(&sOut, 0, sizeof(sOut)); sStr.aData = Tcl_GetByteArrayFromObj(objv[2], &sStr.nData); sStr.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR); if( sStr.nStream ){ rc = sqlite3rebaser_rebase_strm(p, testStreamInput, (void*)&sStr, testStreamOutput, (void*)&sOut ); }else{ rc = sqlite3rebaser_rebase(p, sStr.nData, sStr.aData, &sOut.n, &sOut.p); } if( rc==SQLITE_OK ){ Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(sOut.p, sOut.n)); } sqlite3_free(sOut.p); break; } } if( rc!=SQLITE_OK ){ return test_session_error(interp, rc, 0); } return TCL_OK; } static void SQLITE_TCLAPI test_rebaser_del(void *clientData){ sqlite3_rebaser *p = (sqlite3_rebaser*)clientData; sqlite3rebaser_delete(p); } /* ** tclcmd: sqlite3rebaser_create NAME */ static int SQLITE_TCLAPI test_sqlite3rebaser_create( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ int rc; sqlite3_rebaser *pNew = 0; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "NAME"); return SQLITE_ERROR; } rc = sqlite3rebaser_create(&pNew); if( rc!=SQLITE_OK ){ return test_session_error(interp, rc, 0); } Tcl_CreateObjCommand(interp, Tcl_GetString(objv[1]), test_rebaser_cmd, (ClientData)pNew, test_rebaser_del ); Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } int TestSession_Init(Tcl_Interp *interp){ struct Cmd { const char *zCmd; Tcl_ObjCmdProc *xProc; } aCmd[] = { { "sqlite3session", test_sqlite3session }, { "sqlite3session_foreach", test_sqlite3session_foreach }, { "sqlite3changeset_invert", test_sqlite3changeset_invert }, { "sqlite3changeset_concat", test_sqlite3changeset_concat }, { "sqlite3changeset_apply", test_sqlite3changeset_apply }, { "sqlite3changeset_apply_v2", test_sqlite3changeset_apply_v2 }, { "sqlite3changeset_apply_replace_all", test_sqlite3changeset_apply_replace_all }, { "sql_exec_changeset", test_sql_exec_changeset }, { "sqlite3rebaser_create", test_sqlite3rebaser_create }, }; int i; for(i=0; i<sizeof(aCmd)/sizeof(struct Cmd); i++){ struct Cmd *p = &aCmd[i]; Tcl_CreateObjCommand(interp, p->zCmd, p->xProc, 0, 0); } |
︙ | ︙ |
Changes to main.mk.
︙ | ︙ | |||
68 69 70 71 72 73 74 | memdb.o memjournal.o \ mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \ notify.o opcodes.o os.o os_unix.o os_win.o \ pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \ random.o resolve.o rowset.o rtree.o \ select.o sqlite3rbu.o status.o stmt.o \ table.o threads.o tokenize.o treeview.o trigger.o \ | | | 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | memdb.o memjournal.o \ mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \ notify.o opcodes.o os.o os_unix.o os_win.o \ pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \ random.o resolve.o rowset.o rtree.o \ select.o sqlite3rbu.o status.o stmt.o \ table.o threads.o tokenize.o treeview.o trigger.o \ update.o upsert.o userauth.o util.o vacuum.o \ vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \ vdbetrace.o wal.o walker.o where.o wherecode.o whereexpr.o \ utf.o vtab.o LIBOBJ += sqlite3session.o # All of the source code files. |
︙ | ︙ | |||
158 159 160 161 162 163 164 165 166 167 168 169 170 171 | $(TOP)/src/tclsqlite.c \ $(TOP)/src/threads.c \ $(TOP)/src/tokenize.c \ $(TOP)/src/treeview.c \ $(TOP)/src/trigger.c \ $(TOP)/src/utf.c \ $(TOP)/src/update.c \ $(TOP)/src/util.c \ $(TOP)/src/vacuum.c \ $(TOP)/src/vdbe.c \ $(TOP)/src/vdbe.h \ $(TOP)/src/vdbeapi.c \ $(TOP)/src/vdbeaux.c \ $(TOP)/src/vdbeblob.c \ | > | 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | $(TOP)/src/tclsqlite.c \ $(TOP)/src/threads.c \ $(TOP)/src/tokenize.c \ $(TOP)/src/treeview.c \ $(TOP)/src/trigger.c \ $(TOP)/src/utf.c \ $(TOP)/src/update.c \ $(TOP)/src/upsert.c \ $(TOP)/src/util.c \ $(TOP)/src/vacuum.c \ $(TOP)/src/vdbe.c \ $(TOP)/src/vdbe.h \ $(TOP)/src/vdbeapi.c \ $(TOP)/src/vdbeaux.c \ $(TOP)/src/vdbeblob.c \ |
︙ | ︙ |
Changes to src/analyze.c.
︙ | ︙ | |||
1011 1012 1013 1014 1015 1016 1017 | if( v==0 || NEVER(pTab==0) ){ return; } if( pTab->tnum==0 ){ /* Do not gather statistics on views or virtual tables */ return; } | | | 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 | if( v==0 || NEVER(pTab==0) ){ return; } if( pTab->tnum==0 ){ /* Do not gather statistics on views or virtual tables */ return; } if( sqlite3_strlike("sqlite\\_%", pTab->zName, '\\')==0 ){ /* Do not gather statistics on system tables */ return; } assert( sqlite3BtreeHoldsAllMutexes(db) ); iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iDb>=0 ); assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
︙ | ︙ |
Changes to src/attach.c.
︙ | ︙ | |||
498 499 500 501 502 503 504 505 506 507 508 509 510 511 | pItem->zDatabase = 0; pItem->pSchema = pFix->pSchema; } #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1; if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1; #endif } return 0; } #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) int sqlite3FixSelect( DbFixer *pFix, /* Context of the fixation */ Select *pSelect /* The SELECT statement to be fixed to one database */ | > > > | 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 | pItem->zDatabase = 0; pItem->pSchema = pFix->pSchema; } #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1; if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1; #endif if( pItem->fg.isTabFunc && sqlite3FixExprList(pFix, pItem->u1.pFuncArg) ){ return 1; } } return 0; } #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) int sqlite3FixSelect( DbFixer *pFix, /* Context of the fixation */ Select *pSelect /* The SELECT statement to be fixed to one database */ |
︙ | ︙ | |||
597 598 599 600 601 602 603 604 605 606 607 608 | } if( sqlite3FixExpr(pFix, pStep->pWhere) ){ return 1; } if( sqlite3FixExprList(pFix, pStep->pExprList) ){ return 1; } pStep = pStep->pNext; } return 0; } #endif | > > > > > > > > > > > > | 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 | } if( sqlite3FixExpr(pFix, pStep->pWhere) ){ return 1; } 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; } #endif |
Changes to src/btree.c.
︙ | ︙ | |||
2441 2442 2443 2444 2445 2446 2447 | /* ** Invoke the busy handler for a btree. */ static int btreeInvokeBusyHandler(void *pArg){ BtShared *pBt = (BtShared*)pArg; assert( pBt->db ); assert( sqlite3_mutex_held(pBt->db->mutex) ); | | > | 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 | /* ** Invoke the busy handler for a btree. */ static int btreeInvokeBusyHandler(void *pArg){ BtShared *pBt = (BtShared*)pArg; assert( pBt->db ); assert( sqlite3_mutex_held(pBt->db->mutex) ); return sqlite3InvokeBusyHandler(&pBt->db->busyHandler, sqlite3PagerFile(pBt->pPager)); } /* ** Open a database file. ** ** zFilename is the name of the database file. If zFilename is NULL ** then an ephemeral database is created. The ephemeral database might |
︙ | ︙ | |||
2619 2620 2621 2622 2623 2624 2625 | rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader); } if( rc!=SQLITE_OK ){ goto btree_open_out; } pBt->openFlags = (u8)flags; pBt->db = db; | | | 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 | rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader); } if( rc!=SQLITE_OK ){ goto btree_open_out; } pBt->openFlags = (u8)flags; pBt->db = db; sqlite3PagerSetBusyHandler(pBt->pPager, btreeInvokeBusyHandler, pBt); p->pBt = pBt; pBt->pCursor = 0; pBt->pPage1 = 0; if( sqlite3PagerIsreadonly(pBt->pPager) ) pBt->btsFlags |= BTS_READ_ONLY; #if defined(SQLITE_SECURE_DELETE) pBt->btsFlags |= BTS_SECURE_DELETE; |
︙ | ︙ | |||
3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 | } if( rc!=SQLITE_OK ){ unlockBtreeIfUnused(pBt); } }while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE && btreeInvokeBusyHandler(pBt) ); if( rc==SQLITE_OK ){ if( p->inTrans==TRANS_NONE ){ pBt->nTransaction++; #ifndef SQLITE_OMIT_SHARED_CACHE if( p->sharable ){ assert( p->lock.pBtree==p && p->lock.iTable==1 ); | > | 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 | } if( rc!=SQLITE_OK ){ unlockBtreeIfUnused(pBt); } }while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE && btreeInvokeBusyHandler(pBt) ); sqlite3PagerResetLockTimeout(pBt->pPager); if( rc==SQLITE_OK ){ if( p->inTrans==TRANS_NONE ){ pBt->nTransaction++; #ifndef SQLITE_OMIT_SHARED_CACHE if( p->sharable ){ assert( p->lock.pBtree==p && p->lock.iTable==1 ); |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
1093 1094 1095 1096 1097 1098 1099 | pCol = &p->aCol[p->nCol]; memset(pCol, 0, sizeof(p->aCol[0])); pCol->zName = z; sqlite3ColumnPropertiesFromName(p, pCol); if( pType->n==0 ){ /* If there is no type specified, columns have the default affinity | | > > > > > | | 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 | pCol = &p->aCol[p->nCol]; memset(pCol, 0, sizeof(p->aCol[0])); pCol->zName = z; sqlite3ColumnPropertiesFromName(p, pCol); if( pType->n==0 ){ /* If there is no type specified, columns have the default affinity ** '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); pCol->colFlags |= COLFLAG_HASTYPE; } p->nCol++; pParse->constraintName.n = 0; } /* |
︙ | ︙ | |||
1161 1162 1163 1164 1165 1166 1167 | ** 'REAL' | SQLITE_AFF_REAL ** 'FLOA' | SQLITE_AFF_REAL ** 'DOUB' | SQLITE_AFF_REAL ** ** If none of the substrings in the above table are found, ** SQLITE_AFF_NUMERIC is returned. */ | | | 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 | ** 'REAL' | SQLITE_AFF_REAL ** 'FLOA' | SQLITE_AFF_REAL ** 'DOUB' | SQLITE_AFF_REAL ** ** If none of the substrings in the above table are found, ** SQLITE_AFF_NUMERIC is returned. */ char sqlite3AffinityType(const char *zIn, Column *pCol){ u32 h = 0; char aff = SQLITE_AFF_NUMERIC; const char *zChar = 0; assert( zIn!=0 ); while( zIn[0] ){ h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff]; |
︙ | ︙ | |||
1198 1199 1200 1201 1202 1203 1204 | #endif }else if( (h&0x00FFFFFF)==(('i'<<16)+('n'<<8)+'t') ){ /* INT */ aff = SQLITE_AFF_INTEGER; break; } } | | | | | < < < | > > > > > > > > | 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 | #endif }else if( (h&0x00FFFFFF)==(('i'<<16)+('n'<<8)+'t') ){ /* INT */ aff = SQLITE_AFF_INTEGER; break; } } /* 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( pCol ){ int v = 0; /* default size is approx 4 bytes */ if( aff<SQLITE_AFF_NUMERIC ){ if( zChar ){ while( zChar[0] ){ if( sqlite3Isdigit(zChar[0]) ){ /* BLOB(k), VARCHAR(k), CHAR(k) -> r=(k/4+1) */ sqlite3GetInt32(zChar, &v); break; } zChar++; } }else{ 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; } /* ** The expression is the default value for the most recently added column ** of the table currently under construction. |
︙ | ︙ | |||
1250 1251 1252 1253 1254 1255 1256 | if( p!=0 ){ pCol = &(p->aCol[p->nCol-1]); 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 | | | 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 | if( p!=0 ){ pCol = &(p->aCol[p->nCol-1]); 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. */ Expr x; sqlite3ExprDelete(db, pCol->pDflt); memset(&x, 0, sizeof(x)); x.op = TK_SPAN; x.u.zToken = sqlite3DbSpanDup(db, zStart, zEnd); x.pLeft = pExpr; |
︙ | ︙ | |||
1494 1495 1496 1497 1498 1499 1500 | ** the schema-version whenever the schema changes. */ void sqlite3ChangeCookie(Parse *pParse, int iDb){ sqlite3 *db = pParse->db; Vdbe *v = pParse->pVdbe; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, | | | 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 | ** the schema-version whenever the schema changes. */ void sqlite3ChangeCookie(Parse *pParse, int iDb){ sqlite3 *db = pParse->db; Vdbe *v = pParse->pVdbe; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, (int)(1+(unsigned)db->aDb[iDb].pSchema->schema_cookie)); } /* ** Measure the number of characters needed to output the given ** identifier. The number returned includes any quotes used ** but does not include the null terminator. ** |
︙ | ︙ | |||
2172 2173 2174 2175 2176 2177 2178 | */ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ Table *pSelTab; /* A fake table from which we get the result set */ Select *pSel; /* Copy of the SELECT that implements the view */ 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 */ | | | 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 | */ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ Table *pSelTab; /* A fake table from which we get the result set */ Select *pSel; /* Copy of the SELECT that implements the view */ 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 assert( pTable ); |
︙ | ︙ |
Changes to src/ctime.c.
︙ | ︙ | |||
281 282 283 284 285 286 287 288 289 290 291 292 293 294 | "ENABLE_SELECTTRACE", #endif #if SQLITE_ENABLE_SESSION "ENABLE_SESSION", #endif #if SQLITE_ENABLE_SNAPSHOT "ENABLE_SNAPSHOT", #endif #if SQLITE_ENABLE_SQLLOG "ENABLE_SQLLOG", #endif #if defined(SQLITE_ENABLE_STAT4) "ENABLE_STAT4", #elif defined(SQLITE_ENABLE_STAT3) | > > > | 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 | "ENABLE_SELECTTRACE", #endif #if SQLITE_ENABLE_SESSION "ENABLE_SESSION", #endif #if SQLITE_ENABLE_SNAPSHOT "ENABLE_SNAPSHOT", #endif #if SQLITE_ENABLE_SORTER_REFERENCES "ENABLE_SORTER_REFERENCES", #endif #if SQLITE_ENABLE_SQLLOG "ENABLE_SQLLOG", #endif #if defined(SQLITE_ENABLE_STAT4) "ENABLE_STAT4", #elif defined(SQLITE_ENABLE_STAT3) |
︙ | ︙ |
Changes to src/dbstat.c.
︙ | ︙ | |||
420 421 422 423 424 425 426 | pCsr->iOffset = (i64)pCsr->szPage * (pCsr->iPageno - 1); /* If connected to a ZIPVFS backend, override the page size and ** offset with actual values obtained from ZIPVFS. */ fd = sqlite3PagerFile(pPager); x[0] = pCsr->iPageno; | | | 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 | pCsr->iOffset = (i64)pCsr->szPage * (pCsr->iPageno - 1); /* If connected to a ZIPVFS backend, override the page size and ** offset with actual values obtained from ZIPVFS. */ fd = sqlite3PagerFile(pPager); x[0] = pCsr->iPageno; if( sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){ pCsr->iOffset = x[0]; pCsr->szPage = (int)x[1]; } } /* ** Move a statvfs cursor to the next entry in the file. |
︙ | ︙ |
Changes to src/delete.c.
︙ | ︙ | |||
234 235 236 237 238 239 240 | int iDataCur = 0; /* VDBE cursor for the canonical data source */ int iIdxCur = 0; /* Cursor number of the first index */ int nIdx; /* Number of indices */ sqlite3 *db; /* Main database structure */ AuthContext sContext; /* Authorization context */ NameContext sNC; /* Name context to resolve expressions in */ int iDb; /* Database number */ | | | 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | int iDataCur = 0; /* VDBE cursor for the canonical data source */ int iIdxCur = 0; /* Cursor number of the first index */ int nIdx; /* Number of indices */ sqlite3 *db; /* Main database structure */ AuthContext sContext; /* Authorization context */ NameContext sNC; /* Name context to resolve expressions in */ int iDb; /* Database number */ 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 */ u8 *aToOpen = 0; /* Open cursor iTabCur+j if aToOpen[j] is true */ Index *pPk; /* The PRIMARY KEY index on the table */ int iPk = 0; /* First of nPk registers holding PRIMARY KEY value */ i16 nPk = 1; /* Number of columns in the PRIMARY KEY */ |
︙ | ︙ | |||
339 340 341 342 343 344 345 | /* Begin generating code. */ v = sqlite3GetVdbe(pParse); if( v==0 ){ goto delete_from_cleanup; } if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); | | | 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 | /* Begin generating code. */ v = sqlite3GetVdbe(pParse); if( v==0 ){ goto delete_from_cleanup; } if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); sqlite3BeginWriteOperation(pParse, bComplex, iDb); /* If we are trying to delete from a view, realize that view into ** an ephemeral table. */ #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) if( isView ){ sqlite3MaterializeView(pParse, pTab, |
︙ | ︙ | |||
367 368 369 370 371 372 373 | if( sqlite3ResolveExprNames(&sNC, pWhere) ){ goto delete_from_cleanup; } /* Initialize the counter of the number of rows deleted, if ** we are counting rows. */ | | > > > | 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 | if( sqlite3ResolveExprNames(&sNC, pWhere) ){ goto delete_from_cleanup; } /* Initialize the counter of the number of rows deleted, if ** we are counting rows. */ if( (db->flags & SQLITE_CountRows)!=0 && !pParse->nested && !pParse->pTriggerTab ){ memCnt = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt); } #ifndef SQLITE_OMIT_TRUNCATE_OPTIMIZATION /* Special case: A DELETE without a WHERE clause deletes everything. ** It is easier just to erase the whole table. Prior to version 3.6.5, |
︙ | ︙ | |||
395 396 397 398 399 400 401 | #ifdef SQLITE_ENABLE_PREUPDATE_HOOK && db->xPreUpdateCallback==0 #endif ){ assert( !isView ); sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName); if( HasRowid(pTab) ){ | | | 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 | #ifdef SQLITE_ENABLE_PREUPDATE_HOOK && db->xPreUpdateCallback==0 #endif ){ assert( !isView ); sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName); if( HasRowid(pTab) ){ sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt ? memCnt : -1, pTab->zName, P4_STATIC); } for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ assert( pIdx->pSchema==pTab->pSchema ); sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb); } }else |
︙ | ︙ | |||
440 441 442 443 444 445 446 447 448 | ** ONEPASS_MULTI: One-pass approach - any number of rows may be deleted. */ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, wcf, iTabCur+1); if( pWInfo==0 ) goto delete_from_cleanup; eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI ); assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF ); /* Keep track of the number of rows to be deleted */ | > | | 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 | ** ONEPASS_MULTI: One-pass approach - any number of rows may be deleted. */ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, wcf, iTabCur+1); if( pWInfo==0 ) goto delete_from_cleanup; 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( memCnt ){ sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1); } /* Extract the rowid or primary key for the current row */ if( pPk ){ for(i=0; i<nPk; i++){ assert( pPk->aiColumn[i]>=0 ); |
︙ | ︙ | |||
585 586 587 588 589 590 591 | sqlite3AutoincrementEnd(pParse); } /* Return the number of rows that were deleted. If this routine is ** generating code because of a call to sqlite3NestedParse(), do not ** invoke the callback function. */ | | | 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 | sqlite3AutoincrementEnd(pParse); } /* Return the number of rows that were deleted. If this routine is ** generating code because of a call to sqlite3NestedParse(), do not ** invoke the callback function. */ if( memCnt ){ sqlite3VdbeAddOp2(v, OP_ResultRow, memCnt, 1); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC); } delete_from_cleanup: sqlite3AuthContextPop(&sContext); |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 | } } pItem->zName = sqlite3DbStrDup(db, pOldItem->zName); pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan); pItem->sortOrder = pOldItem->sortOrder; pItem->done = 0; pItem->bSpanIsTab = pOldItem->bSpanIsTab; pItem->u = pOldItem->u; } return pNew; } /* ** If cursors, triggers, views and subqueries are all omitted from | > | 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 | } } pItem->zName = sqlite3DbStrDup(db, pOldItem->zName); pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan); pItem->sortOrder = pOldItem->sortOrder; pItem->done = 0; pItem->bSpanIsTab = pOldItem->bSpanIsTab; pItem->bSorterRef = pOldItem->bSorterRef; pItem->u = pOldItem->u; } return pNew; } /* ** If cursors, triggers, views and subqueries are all omitted from |
︙ | ︙ | |||
1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 | testcase( pExpr->op==TK_AGG_FUNCTION ); testcase( pExpr->op==TK_AGG_COLUMN ); if( pWalker->eCode==3 && pExpr->iTable==pWalker->u.iCur ){ return WRC_Continue; } /* Fall through */ case TK_IF_NULL_ROW: testcase( pExpr->op==TK_IF_NULL_ROW ); pWalker->eCode = 0; return WRC_Abort; case TK_VARIABLE: if( pWalker->eCode==5 ){ /* Silently convert bound parameters that appear inside of CREATE ** statements into a NULL when parsing the CREATE statement text out ** of the sqlite_master table */ pExpr->op = TK_NULL; }else if( pWalker->eCode==4 ){ /* A bound parameter in a CREATE statement that originates from ** sqlite3_prepare() causes an error */ pWalker->eCode = 0; return WRC_Abort; } /* Fall through */ default: | > > | | | 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 | testcase( pExpr->op==TK_AGG_FUNCTION ); testcase( pExpr->op==TK_AGG_COLUMN ); 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; case TK_VARIABLE: if( pWalker->eCode==5 ){ /* Silently convert bound parameters that appear inside of CREATE ** statements into a NULL when parsing the CREATE statement text out ** of the sqlite_master table */ pExpr->op = TK_NULL; }else if( pWalker->eCode==4 ){ /* A bound parameter in a CREATE statement that originates from ** sqlite3_prepare() causes an error */ pWalker->eCode = 0; return WRC_Abort; } /* Fall through */ default: testcase( pExpr->op==TK_SELECT ); /* sqlite3SelectWalkFail() disallows */ testcase( pExpr->op==TK_EXISTS ); /* sqlite3SelectWalkFail() disallows */ return WRC_Continue; } } static int exprIsConst(Expr *p, int initFlag, int iCur){ Walker w; w.eCode = initFlag; w.xExprCallback = exprNodeIsConstant; |
︙ | ︙ | |||
2602 2603 2604 2605 2606 2607 2608 | ** If all of the above are false, then we can run this code just once ** save the results, and reuse the same result on subsequent invocations. */ if( !ExprHasProperty(pExpr, EP_VarSelect) ){ jmpIfDynamic = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); } | < < < < < < < < < < < | 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 | ** If all of the above are false, then we can run this code just once ** save the results, and reuse the same result on subsequent invocations. */ if( !ExprHasProperty(pExpr, EP_VarSelect) ){ jmpIfDynamic = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); } switch( pExpr->op ){ case TK_IN: { int addr; /* Address of OP_OpenEphemeral instruction */ Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */ KeyInfo *pKeyInfo = 0; /* Key information */ int nVal; /* Size of vector pLeft */ |
︙ | ︙ | |||
2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 | /* Case 1: expr IN (SELECT ...) ** ** Generate code to write the results of the select into the temporary ** table allocated and opened above. */ Select *pSelect = pExpr->x.pSelect; ExprList *pEList = pSelect->pEList; 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. */ if( ALWAYS(pEList->nExpr==nVal) ){ SelectDest dest; int i; | > > > > > > > > > > > | 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 | /* Case 1: expr IN (SELECT ...) ** ** Generate code to write the results of the select into the temporary ** table allocated and opened above. */ Select *pSelect = pExpr->x.pSelect; ExprList *pEList = pSelect->pEList; #ifndef SQLITE_OMIT_EXPLAIN if( pParse->explain==2 ){ char *zMsg = sqlite3MPrintf(pParse->db, "EXECUTE %sLIST SUBQUERY %d", jmpIfDynamic>=0?"":"CORRELATED ", pParse->iNextSelectId ); sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); } #endif 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. */ if( ALWAYS(pEList->nExpr==nVal) ){ SelectDest dest; int i; |
︙ | ︙ | |||
2691 2692 2693 2694 2695 2696 2697 | ** a column, use numeric affinity. */ char affinity; /* Affinity of the LHS of the IN */ int i; ExprList *pList = pExpr->x.pList; struct ExprList_item *pItem; int r1, r2, r3; | < | 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 | ** a column, use numeric affinity. */ char affinity; /* Affinity of the LHS of the IN */ int i; ExprList *pList = pExpr->x.pList; struct ExprList_item *pItem; int r1, r2, r3; affinity = sqlite3ExprAffinity(pLeft); if( !affinity ){ affinity = SQLITE_AFF_BLOB; } if( pKeyInfo ){ assert( sqlite3KeyInfoIsWriteable(pKeyInfo) ); pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft); |
︙ | ︙ | |||
2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 | int nReg; /* Registers to allocate */ Expr *pLimit; /* New limit expression */ testcase( pExpr->op==TK_EXISTS ); testcase( pExpr->op==TK_SELECT ); assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT ); assert( ExprHasProperty(pExpr, EP_xIsSelect) ); pSel = pExpr->x.pSelect; nReg = pExpr->op==TK_SELECT ? pSel->pEList->nExpr : 1; sqlite3SelectDestInit(&dest, 0, pParse->nMem+1); pParse->nMem += nReg; if( pExpr->op==TK_SELECT ){ dest.eDest = SRT_Mem; | > > > > > > > > > > > | 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 | int nReg; /* Registers to allocate */ Expr *pLimit; /* New limit expression */ testcase( pExpr->op==TK_EXISTS ); testcase( pExpr->op==TK_SELECT ); assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT ); assert( ExprHasProperty(pExpr, EP_xIsSelect) ); #ifndef SQLITE_OMIT_EXPLAIN if( pParse->explain==2 ){ char *zMsg = sqlite3MPrintf(pParse->db, "EXECUTE %sSCALAR SUBQUERY %d", jmpIfDynamic>=0?"":"CORRELATED ", pParse->iNextSelectId ); sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); } #endif pSel = pExpr->x.pSelect; nReg = pExpr->op==TK_SELECT ? pSel->pEList->nExpr : 1; sqlite3SelectDestInit(&dest, 0, pParse->nMem+1); pParse->nMem += nReg; if( pExpr->op==TK_SELECT ){ dest.eDest = SRT_Mem; |
︙ | ︙ | |||
4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 | assert( pList!=0 ); assert( target>0 ); assert( pParse->pVdbe!=0 ); /* Never gets this far otherwise */ n = pList->nExpr; if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR; for(pItem=pList->a, i=0; i<n; i++, pItem++){ Expr *pExpr = pItem->pExpr; if( (flags & SQLITE_ECEL_REF)!=0 && (j = pItem->u.x.iOrderByCol)>0 ){ if( flags & SQLITE_ECEL_OMITREF ){ i--; n--; }else{ sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i); } | > > > > > > | 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 | assert( pList!=0 ); assert( target>0 ); assert( pParse->pVdbe!=0 ); /* Never gets this far otherwise */ n = pList->nExpr; 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--; n--; }else{ sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i); } |
︙ | ︙ | |||
4895 4896 4897 4898 4899 4900 4901 4902 | return 1; } return 2; } 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; }else if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ | > > | | > | 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 | return 1; } return 2; } 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; }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 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( sqlite3ExprCompare(pParse, pA->pRight, pB->pRight, iTab) ) return 2; if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2; 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; } } return 0; } |
︙ | ︙ | |||
4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 | if( pE2->op==TK_NOTNULL && pE1->op!=TK_ISNULL && pE1->op!=TK_IS ){ Expr *pX = sqlite3ExprSkipCollate(pE1->pLeft); testcase( pX!=pE1->pLeft ); if( sqlite3ExprCompare(pParse, pX, pE2->pLeft, iTab)==0 ) return 1; } return 0; } /* ** 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 ** table entry. The IdxCover.pIdx field is the index. IdxCover.iCur ** is the cursor for the table. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 | if( pE2->op==TK_NOTNULL && pE1->op!=TK_ISNULL && pE1->op!=TK_IS ){ Expr *pX = sqlite3ExprSkipCollate(pE1->pLeft); testcase( pX!=pE1->pLeft ); if( sqlite3ExprCompare(pParse, pX, pE2->pLeft, iTab)==0 ) return 1; } return 0; } /* ** 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. */ 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_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->pTab)) || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->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. */ 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 ** table entry. The IdxCover.pIdx field is the index. IdxCover.iCur ** is the cursor for the table. |
︙ | ︙ | |||
5152 5153 5154 5155 5156 5157 5158 | ** for additional information. */ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ int i; NameContext *pNC = pWalker->u.pNC; Parse *pParse = pNC->pParse; SrcList *pSrcList = pNC->pSrcList; | | > | 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 | ** for additional information. */ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ int i; NameContext *pNC = pWalker->u.pNC; Parse *pParse = pNC->pParse; SrcList *pSrcList = pNC->pSrcList; AggInfo *pAggInfo = pNC->uNC.pAggInfo; assert( pNC->ncFlags & NC_UAggInfo ); switch( pExpr->op ){ case TK_AGG_COLUMN: case TK_COLUMN: { testcase( pExpr->op==TK_AGG_COLUMN ); testcase( pExpr->op==TK_COLUMN ); /* Check to see if the column is in one of the tables in the FROM ** clause of the aggregate query */ |
︙ | ︙ |
Changes to src/global.c.
︙ | ︙ | |||
236 237 238 239 240 241 242 | 0, /* xVdbeBranch */ 0, /* pVbeBranchArg */ #endif #ifndef SQLITE_UNTESTABLE 0, /* xTestCallback */ #endif 0, /* bLocaltimeFault */ | | > | 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | 0, /* xVdbeBranch */ 0, /* pVbeBranchArg */ #endif #ifndef SQLITE_UNTESTABLE 0, /* xTestCallback */ #endif 0, /* bLocaltimeFault */ 0x7ffffffe, /* iOnceResetThreshold */ SQLITE_DEFAULT_SORTERREF_SIZE /* szSorterRef */ }; /* ** Hash table for global functions - functions common to all ** database connections. After initialization, this table is ** read-only. */ |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
484 485 486 487 488 489 490 | ** D: cleanup */ void sqlite3Insert( Parse *pParse, /* Parser context */ 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. */ | | > | 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 | ** D: cleanup */ void sqlite3Insert( Parse *pParse, /* Parser context */ 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 */ Upsert *pUpsert /* ON CONFLICT clauses for upsert, or NULL */ ){ sqlite3 *db; /* The main database structure */ Table *pTab; /* The table to insert into. aka TABLE */ int i, j; /* Loop counters */ Vdbe *v; /* Generate code into this virtual machine */ Index *pIdx; /* For looping over indices of the table */ int nColumn; /* Number of columns in the data */ |
︙ | ︙ | |||
779 780 781 782 783 784 785 | if( pColumn!=0 && nColumn!=pColumn->nId ){ sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId); goto insert_cleanup; } /* Initialize the count of rows to be inserted */ | | > > > > > > > > > > > > > > > > | 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 | if( pColumn!=0 && nColumn!=pColumn->nId ){ sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId); goto insert_cleanup; } /* Initialize the count of rows to be inserted */ if( (db->flags & SQLITE_CountRows)!=0 && !pParse->nested && !pParse->pTriggerTab ){ regRowCount = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); } /* If this is not a view, open the table and and all indices */ if( !isView ){ int nIdx; nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, -1, 0, &iDataCur, &iIdxCur); aRegIdx = sqlite3DbMallocRawNN(db, sizeof(int)*(nIdx+1)); if( aRegIdx==0 ){ goto insert_cleanup; } for(i=0, pIdx=pTab->pIndex; i<nIdx; pIdx=pIdx->pNext, i++){ assert( pIdx ); aRegIdx[i] = ++pParse->nMem; 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 ** following pseudocode (template 4): ** ** rewind temp table, if empty goto D |
︙ | ︙ | |||
1001 1002 1003 1004 1005 1006 1007 | sqlite3MayAbort(pParse); }else #endif { int isReplace; /* Set to true if constraints may cause a replace */ int bUseSeek; /* True to use OPFLAG_SEEKRESULT */ sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, | | | 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 | sqlite3MayAbort(pParse); }else #endif { 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, pUpsert ); sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0); /* Set the OPFLAG_USESEEKRESULT flag if either (a) there are no REPLACE ** constraints or (b) there are no triggers and this table is not a ** parent table in a foreign key constraint. It is safe to set the ** flag in the second case as if any REPLACE constraint is hit, an |
︙ | ︙ | |||
1024 1025 1026 1027 1028 1029 1030 | regIns, aRegIdx, 0, appendFlag, bUseSeek ); } } /* Update the count of rows that are inserted */ | | | 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 | regIns, aRegIdx, 0, appendFlag, bUseSeek ); } } /* Update the count of rows that are inserted */ if( regRowCount ){ sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); } if( pTrigger ){ /* Code AFTER triggers */ sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_AFTER, pTab, regData-2-pTab->nCol, onError, endOfLoop); |
︙ | ︙ | |||
1061 1062 1063 1064 1065 1066 1067 | } /* ** Return the number of rows inserted. If this routine is ** generating code because of a call to sqlite3NestedParse(), do not ** invoke the callback function. */ | | > | 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 | } /* ** Return the number of rows inserted. If this routine is ** generating code because of a call to sqlite3NestedParse(), do not ** invoke the callback function. */ if( regRowCount ){ sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC); } insert_cleanup: sqlite3SrcListDelete(db, pTabList); sqlite3ExprListDelete(db, pList); sqlite3UpsertDelete(db, pUpsert); sqlite3SelectDelete(db, pSelect); sqlite3IdListDelete(db, pColumn); sqlite3DbFree(db, aRegIdx); } /* Make sure "isView" and other macros defined above are undefined. Otherwise ** they may interfere with compilation of other functions in this file |
︙ | ︙ | |||
1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 | } testcase( w.eCode==0 ); testcase( w.eCode==CKCNSTRNT_COLUMN ); testcase( w.eCode==CKCNSTRNT_ROWID ); testcase( w.eCode==(CKCNSTRNT_ROWID|CKCNSTRNT_COLUMN) ); return !w.eCode; } /* ** Generate code to do constraint checks prior to an INSERT or an UPDATE ** on table pTab. ** ** The regNewData parameter is the first register in a range that contains ** the data to be inserted or the data after the update. There will be | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 | } testcase( w.eCode==0 ); testcase( w.eCode==CKCNSTRNT_COLUMN ); testcase( w.eCode==CKCNSTRNT_ROWID ); testcase( w.eCode==(CKCNSTRNT_ROWID|CKCNSTRNT_COLUMN) ); return !w.eCode; } /* ** An instance of the ConstraintAddr object remembers the byte-code addresses ** for sections of the constraint checks that deal with uniqueness constraints ** on the rowid and on the upsert constraint. ** ** This information is passed into checkReorderConstraintChecks() to insert ** some OP_Goto operations so that the rowid and upsert constraints occur ** in the correct order relative to other constraints. */ typedef struct ConstraintAddr ConstraintAddr; struct ConstraintAddr { int ipkTop; /* Subroutine for rowid constraint check */ int upsertTop; /* Label for upsert constraint check subroutine */ int upsertTop2; /* Copy of upsertTop not cleared by the call */ int upsertBtm; /* upsert constraint returns to this label */ int ipkBtm; /* Return opcode rowid constraint check */ }; /* ** Generate any OP_Goto operations needed to cause constraints to be ** run that haven't already been run. */ static void reorderConstraintChecks(Vdbe *v, ConstraintAddr *p){ if( p->upsertTop ){ testcase( sqlite3VdbeLabelHasBeenResolved(v, p->upsertTop) ); sqlite3VdbeGoto(v, p->upsertTop); VdbeComment((v, "call upsert subroutine")); sqlite3VdbeResolveLabel(v, p->upsertBtm); p->upsertTop = 0; } if( p->ipkTop ){ sqlite3VdbeGoto(v, p->ipkTop); VdbeComment((v, "call rowid unique-check subroutine")); sqlite3VdbeJumpHere(v, p->ipkBtm); p->ipkTop = 0; } } /* ** Generate code to do constraint checks prior to an INSERT or an UPDATE ** on table pTab. ** ** The regNewData parameter is the first register in a range that contains ** the data to be inserted or the data after the update. There will be |
︙ | ︙ | |||
1236 1237 1238 1239 1240 1241 1242 | int iIdxCur, /* First index cursor */ int regNewData, /* First register in a range holding values to insert */ int regOldData, /* Previous content. 0 for INSERTs */ u8 pkChng, /* Non-zero if the rowid or PRIMARY KEY changed */ 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 */ | | > | | > > | 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 | int iIdxCur, /* First index cursor */ int regNewData, /* First register in a range holding values to insert */ int regOldData, /* Previous content. 0 for INSERTs */ u8 pkChng, /* Non-zero if the rowid or PRIMARY KEY changed */ 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 */ Upsert *pUpsert /* ON CONFLICT clauses, if any. NULL otherwise */ ){ Vdbe *v; /* VDBE under constrution */ Index *pIdx; /* Pointer to one of the indices */ Index *pPk = 0; /* The PRIMARY KEY index */ sqlite3 *db; /* Database connection */ int i; /* loop counter */ int ix; /* Index loop counter */ int nCol; /* Number of columns */ int onError; /* Conflict resolution strategy */ 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 */ ConstraintAddr sAddr;/* Address information for constraint reordering */ 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 */ isUpdate = regOldData!=0; db = pParse->db; v = sqlite3GetVdbe(pParse); assert( v!=0 ); assert( pTab->pSelect==0 ); /* This table is not a VIEW */ nCol = pTab->nCol; memset(&sAddr, 0, sizeof(sAddr)); /* pPk is the PRIMARY KEY index for WITHOUT ROWID tables and NULL for ** normal rowid tables. nPkField is the number of key fields in the ** pPk index or 1 for a rowid table. In other words, nPkField is the ** number of fields in the true primary key of the table. */ if( HasRowid(pTab) ){ pPk = 0; |
︙ | ︙ | |||
1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 | P5_ConstraintCheck); } sqlite3VdbeResolveLabel(v, allOk); } pParse->iSelfTab = 0; } #endif /* !defined(SQLITE_OMIT_CHECK) */ /* If rowid is changing, make sure the new rowid does not previously ** exist in the table. */ if( pkChng && pPk==0 ){ int addrRowidOk = sqlite3VdbeMakeLabel(v); /* Figure out what action to take in case of a rowid collision */ onError = pTab->keyConf; if( overrideError!=OE_Default ){ onError = overrideError; }else if( onError==OE_Default ){ onError = OE_Abort; } 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 ** is unchanged. */ sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRowidOk, regOldData); sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); VdbeCoverage(v); } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < < < < < < < < < < < < < > < > > > | 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 | P5_ConstraintCheck); } sqlite3VdbeResolveLabel(v, allOk); } pParse->iSelfTab = 0; } #endif /* !defined(SQLITE_OMIT_CHECK) */ /* UNIQUE and PRIMARY KEY constraints should be handled in the following ** order: ** ** (1) OE_Abort, OE_Fail, OE_Rollback, OE_Ignore ** (2) OE_Update ** (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. ** ** 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 is on some column other than ** then ROWID, then we might need to move the UPSERT around ** so that it occurs in the correct order. */ sAddr.upsertTop = sAddr.upsertTop2 = sqlite3VdbeMakeLabel(v); sAddr.upsertBtm = sqlite3VdbeMakeLabel(v); } } /* If rowid is changing, make sure the new rowid does not previously ** exist in the table. */ if( pkChng && pPk==0 ){ int addrRowidOk = sqlite3VdbeMakeLabel(v); /* Figure out what action to take in case of a rowid collision */ onError = pTab->keyConf; if( overrideError!=OE_Default ){ onError = overrideError; }else if( onError==OE_Default ){ 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. */ assert( OE_Update>OE_Replace ); assert( OE_Ignore<OE_Replace ); assert( OE_Fail<OE_Replace ); assert( OE_Abort<OE_Replace ); assert( OE_Rollback<OE_Replace ); if( onError>=OE_Replace && (pUpsert || onError!=overrideError) && pTab->pIndex ){ sAddr.ipkTop = sqlite3VdbeAddOp0(v, OP_Goto)+1; } 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 ** is unchanged. */ sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRowidOk, regOldData); sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); VdbeCoverage(v); } /* 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")); sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData); VdbeCoverage(v); switch( onError ){ default: { onError = OE_Abort; /* Fall thru into the next case */ } 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; } case OE_Replace: { /* If there are DELETE triggers on this table and the ** recursive-triggers flag is set, call GenerateRowDelete() to ** remove the conflicting row from the table. This will fire |
︙ | ︙ | |||
1446 1447 1448 1449 1450 1451 1452 | } if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){ sqlite3MultiWrite(pParse); sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, regNewData, 1, 0, OE_Replace, 1, -1); }else{ #ifdef SQLITE_ENABLE_PREUPDATE_HOOK | | | | | | | | < > > > > > > < > | | | > > > > > > > > > | | 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 | } if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){ sqlite3MultiWrite(pParse); sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, regNewData, 1, 0, OE_Replace, 1, -1); }else{ #ifdef SQLITE_ENABLE_PREUPDATE_HOOK 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); sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,-1); } } seenReplace = 1; break; } #ifndef SQLITE_OMIT_UPSERT case OE_Update: { sqlite3UpsertDoUpdate(pParse, pUpsert, pTab, 0, iDataCur); /* Fall through */ } #endif case OE_Ignore: { testcase( onError==OE_Ignore ); sqlite3VdbeGoto(v, ignoreDest); break; } } sqlite3VdbeResolveLabel(v, addrRowidOk); if( sAddr.ipkTop ){ sAddr.ipkBtm = sqlite3VdbeAddOp0(v, OP_Goto); sqlite3VdbeJumpHere(v, sAddr.ipkTop-1); } } /* Test all UNIQUE constraints by creating entries for each UNIQUE ** index and making sure that duplicate entries do not already exist. ** Compute the revised record entries for indices as we go. ** ** This loop also handles the case of the PRIMARY KEY index for a ** WITHOUT ROWID table. */ for(ix=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, ix++){ int regIdx; /* Range of registers hold conent for pIdx */ int regR; /* Range of registers holding conflicting PK */ int iThisCur; /* Cursor for this UNIQUE index */ int addrUniqueOk; /* Jump here if the UNIQUE constraint is satisfied */ if( aRegIdx[ix]==0 ) continue; /* Skip indices that do not change */ if( pUpIdx==pIdx ){ addrUniqueOk = sAddr.upsertBtm; upsertBypass = sqlite3VdbeGoto(v, 0); VdbeComment((v, "Skip upsert subroutine")); sqlite3VdbeResolveLabel(v, sAddr.upsertTop2); }else{ addrUniqueOk = sqlite3VdbeMakeLabel(v); } VdbeNoopComment((v, "uniqueness check for %s", pIdx->zName)); if( bAffinityDone==0 ){ sqlite3TableAffinity(v, pTab, regNewData+1); bAffinityDone = 1; } iThisCur = iIdxCur+ix; /* Skip partial indices for which the WHERE clause is not true */ if( pIdx->pPartIdxWhere ){ sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[ix]); pParse->iSelfTab = -(regNewData+1); sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, addrUniqueOk, SQLITE_JUMPIFNULL); |
︙ | ︙ | |||
1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 | continue; /* pIdx is not a UNIQUE index */ } if( overrideError!=OE_Default ){ onError = overrideError; }else if( onError==OE_Default ){ onError = OE_Abort; } /* 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 ** (3) There are no secondary indexes on the table ** (4) No delete triggers need to be fired if there is a conflict ** (5) No FK constraint counters need to be updated if a conflict occurs. | > > > > > > > > > > > > > > > > > > | 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 | continue; /* pIdx is not a UNIQUE index */ } if( overrideError!=OE_Default ){ onError = overrideError; }else if( onError==OE_Default ){ 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 */ } } /* Invoke subroutines to handle IPK replace and upsert prior to running ** the first REPLACE constraint check. */ if( onError==OE_Replace ){ testcase( sAddr.ipkTop ); testcase( sAddr.upsertTop && sqlite3VdbeLabelHasBeenResolved(v,sAddr.upsertTop) ); reorderConstraintChecks(v, &sAddr); } /* 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 ** (3) There are no secondary indexes on the table ** (4) No delete triggers need to be fired if there is a conflict ** (5) No FK constraint counters need to be updated if a conflict occurs. |
︙ | ︙ | |||
1637 1638 1639 1640 1641 1642 1643 | } } } } /* Generate code that executes if the new index entry is not unique */ assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail | | > > > > > > > > > > > > > | > | < < < > > > > | 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 | } } } } /* 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_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; } default: { Trigger *pTrigger = 0; assert( onError==OE_Replace ); sqlite3MultiWrite(pParse); if( db->flags&SQLITE_RecTriggers ){ pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); } sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, regR, nPkField, 0, OE_Replace, (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur); seenReplace = 1; break; } } if( pUpIdx==pIdx ){ sqlite3VdbeJumpHere(v, upsertBypass); }else{ sqlite3VdbeResolveLabel(v, addrUniqueOk); } sqlite3ExprCachePop(pParse); if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField); } testcase( sAddr.ipkTop!=0 ); testcase( sAddr.upsertTop && sqlite3VdbeLabelHasBeenResolved(v,sAddr.upsertTop) ); reorderConstraintChecks(v, &sAddr); *pbMayReplace = seenReplace; VdbeModuleComment((v, "END: GenCnstCks(%d)", seenReplace)); } #ifdef SQLITE_ENABLE_NULL_TRIM /* |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
638 639 640 641 642 643 644 645 646 647 648 649 650 651 | } case SQLITE_CONFIG_STMTJRNL_SPILL: { sqlite3GlobalConfig.nStmtSpill = va_arg(ap, int); break; } default: { rc = SQLITE_ERROR; break; } } va_end(ap); return rc; | > > > > > > > > > > > | 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 | } case SQLITE_CONFIG_STMTJRNL_SPILL: { sqlite3GlobalConfig.nStmtSpill = va_arg(ap, int); 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; } } va_end(ap); return rc; |
︙ | ︙ | |||
1472 1473 1474 1475 1476 1477 1478 1479 1480 | } /* ** This routine implements a busy callback that sleeps and tries ** again until a timeout value is reached. The timeout value is ** an integer number of milliseconds passed in as the first ** argument. */ static int sqliteDefaultBusyCallback( | > > > | | > > > | > > > > > > > > > > > > > | | > > | > | | > > | | > > > > > > > > | > | 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 | } /* ** This routine implements a busy callback that sleeps and tries ** 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 */ 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[] = { 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228 }; # define NDELAY ArraySize(delays) sqlite3 *db = (sqlite3 *)ptr; 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]; prior = totals[count]; }else{ delay = delays[NDELAY-1]; prior = totals[NDELAY-1] + delay*(count-(NDELAY-1)); } 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 tmout = ((sqlite3 *)ptr)->busyTimeout; UNUSED_PARAMETER(pFile); if( (count+1)*1000 > tmout ){ return 0; } sqlite3OsSleep(db->pVfs, 1000000); return 1; #endif } /* ** Invoke the given busy handler. ** ** 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. */ int sqlite3InvokeBusyHandler(BusyHandler *p, sqlite3_file *pFile){ int rc; 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{ p->nBusy++; } return rc; } |
︙ | ︙ | |||
1544 1545 1546 1547 1548 1549 1550 | int (*xBusy)(void*,int), void *pArg ){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif sqlite3_mutex_enter(db->mutex); | | | > | 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 | int (*xBusy)(void*,int), void *pArg ){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif sqlite3_mutex_enter(db->mutex); 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; } #ifndef SQLITE_OMIT_PROGRESS_CALLBACK /* |
︙ | ︙ | |||
1594 1595 1596 1597 1598 1599 1600 | ** specified number of milliseconds before returning 0. */ int sqlite3_busy_timeout(sqlite3 *db, int ms){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif if( ms>0 ){ | | > > | 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 | ** specified number of milliseconds before returning 0. */ int sqlite3_busy_timeout(sqlite3 *db, int ms){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif if( ms>0 ){ sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback, (void*)db); db->busyTimeout = ms; db->busyHandler.bExtraFileArg = 1; }else{ sqlite3_busy_handler(db, 0, 0); } return SQLITE_OK; } /* |
︙ | ︙ | |||
3588 3589 3590 3591 3592 3593 3594 | rc = SQLITE_OK; }else if( op==SQLITE_FCNTL_VFS_POINTER ){ *(sqlite3_vfs**)pArg = sqlite3PagerVfs(pPager); rc = SQLITE_OK; }else if( op==SQLITE_FCNTL_JOURNAL_POINTER ){ *(sqlite3_file**)pArg = sqlite3PagerJrnlFile(pPager); rc = SQLITE_OK; | | < < | 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 | rc = SQLITE_OK; }else if( op==SQLITE_FCNTL_VFS_POINTER ){ *(sqlite3_vfs**)pArg = sqlite3PagerVfs(pPager); rc = SQLITE_OK; }else if( op==SQLITE_FCNTL_JOURNAL_POINTER ){ *(sqlite3_file**)pArg = sqlite3PagerJrnlFile(pPager); rc = SQLITE_OK; }else{ rc = sqlite3OsFileControl(fd, op, pArg); } sqlite3BtreeLeave(pBtree); } sqlite3_mutex_leave(db->mutex); return rc; } |
︙ | ︙ |
Changes to src/memdb.c.
1 2 3 4 5 6 7 8 9 10 11 12 | /* ** 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. ** ****************************************************************************** ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /* ** 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(). */ #ifdef SQLITE_ENABLE_DESERIALIZE #include "sqliteInt.h" |
︙ | ︙ |
Changes to src/os.c.
︙ | ︙ | |||
121 122 123 124 125 126 127 128 | ** and we need to know about the failures. Use sqlite3OsFileControlHint() ** when simply tossing information over the wall to the VFS and we do not ** really care if the VFS receives and understands the information since it ** is only a hint and can be safely ignored. The sqlite3OsFileControlHint() ** routine has no return value since the return value would be meaningless. */ int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ #ifdef SQLITE_TEST | > | > > | | 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | ** and we need to know about the failures. Use sqlite3OsFileControlHint() ** when simply tossing information over the wall to the VFS and we do not ** really care if the VFS receives and understands the information since it ** is only a hint and can be safely ignored. The sqlite3OsFileControlHint() ** routine has no return value since the return value would be meaningless. */ 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 && 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 ** confuses the test scripts - the COMMIT comand returns SQLITE_NOMEM ** but the transaction is committed anyway. ** ** The core must call OsFileControl() though, not OsFileControlHint(), ** as if a custom VFS (e.g. zipvfs) returns an error here, it probably ** means the commit really has failed and an error should be returned ** to the user. */ DO_OS_MALLOC_TEST(id); } #endif return id->pMethods->xFileControl(id, op, pArg); } void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){ if( id->pMethods ) (void)id->pMethods->xFileControl(id, op, pArg); } int sqlite3OsSectorSize(sqlite3_file *id){ int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize; return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE); } int sqlite3OsDeviceCharacteristics(sqlite3_file *id){ |
︙ | ︙ |
Changes to src/os_unix.c.
︙ | ︙ | |||
225 226 227 228 229 230 231 232 233 234 235 236 237 238 | int deviceCharacteristics; /* Precomputed device characteristics */ #if SQLITE_ENABLE_LOCKING_STYLE int openFlags; /* The flags specified at open() */ #endif #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) unsigned fsFlags; /* cached details from statfs() */ #endif #if OS_VXWORKS struct vxworksFileId *pId; /* Unique file ID */ #endif #ifdef SQLITE_DEBUG /* The next group of variables are used to track whether or not the ** transaction counter in bytes 24-27 of database files are updated ** whenever any part of the database changes. An assertion fault will | > > > | 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | int deviceCharacteristics; /* Precomputed device characteristics */ #if SQLITE_ENABLE_LOCKING_STYLE int openFlags; /* The flags specified at open() */ #endif #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) unsigned fsFlags; /* cached details from statfs() */ #endif #ifdef SQLITE_ENABLE_SETLK_TIMEOUT unsigned iBusyTimeout; /* Wait this many millisec on locks */ #endif #if OS_VXWORKS struct vxworksFileId *pId; /* Unique file ID */ #endif #ifdef SQLITE_DEBUG /* The next group of variables are used to track whether or not the ** transaction counter in bytes 24-27 of database files are updated ** whenever any part of the database changes. An assertion fault will |
︙ | ︙ | |||
1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 | unixLeaveMutex(); OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved)); *pResOut = reserved; return rc; } /* ** Attempt to set a system-lock on the file pFile. The lock is ** described by pLock. ** ** If the pFile was opened read/write from unix-excl, then the only lock ** ever obtained is an exclusive lock, and it is obtained exactly once | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 | unixLeaveMutex(); OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved)); *pResOut = reserved; return rc; } /* ** 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. ** ** If the pFile was opened read/write from unix-excl, then the only lock ** ever obtained is an exclusive lock, and it is obtained exactly once |
︙ | ︙ | |||
1504 1505 1506 1507 1508 1509 1510 | if( pInode->bProcessLock==0 ){ struct flock lock; assert( pInode->nLock==0 ); lock.l_whence = SEEK_SET; lock.l_start = SHARED_FIRST; lock.l_len = SHARED_SIZE; lock.l_type = F_WRLCK; | | | | 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 | if( pInode->bProcessLock==0 ){ struct flock lock; assert( pInode->nLock==0 ); lock.l_whence = SEEK_SET; lock.l_start = SHARED_FIRST; lock.l_len = SHARED_SIZE; lock.l_type = F_WRLCK; rc = osSetPosixAdvisoryLock(pFile->h, &lock, pFile); if( rc<0 ) return rc; pInode->bProcessLock = 1; pInode->nLock++; }else{ rc = 0; } }else{ rc = osSetPosixAdvisoryLock(pFile->h, pLock, pFile); } return rc; } /* ** Lock the file with the lock specified by parameter eFileLock - one ** of the following: |
︙ | ︙ | |||
3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 | } return SQLITE_OK; } case SQLITE_FCNTL_HAS_MOVED: { *(int*)pArg = fileHasMoved(pFile); return SQLITE_OK; } #if SQLITE_MAX_MMAP_SIZE>0 case SQLITE_FCNTL_MMAP_SIZE: { i64 newLimit = *(i64*)pArg; int rc = SQLITE_OK; if( newLimit>sqlite3GlobalConfig.mxMmap ){ newLimit = sqlite3GlobalConfig.mxMmap; } | > > > > > > | 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 | } return SQLITE_OK; } case SQLITE_FCNTL_HAS_MOVED: { *(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; int rc = SQLITE_OK; if( newLimit>sqlite3GlobalConfig.mxMmap ){ newLimit = sqlite3GlobalConfig.mxMmap; } |
︙ | ︙ | |||
4202 4203 4204 4205 4206 4207 4208 | if( pShmNode->h>=0 ){ /* Initialize the locking parameters */ f.l_type = lockType; f.l_whence = SEEK_SET; f.l_start = ofst; f.l_len = n; | | | 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 | if( pShmNode->h>=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 = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY; } /* Update the global lock state and do debug tracing */ #ifdef SQLITE_DEBUG { u16 mask; OSTRACE(("SHM-LOCK ")); |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
2176 2177 2178 2179 2180 2181 2182 | ** successfully committed, but the EXCLUSIVE lock is still held on the ** file. So it is safe to truncate the database file to its minimum ** required size. */ assert( pPager->eLock==EXCLUSIVE_LOCK ); rc = pager_truncate(pPager, pPager->dbSize); } | | | 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 | ** successfully committed, but the EXCLUSIVE lock is still held on the ** file. So it is safe to truncate the database file to its minimum ** required size. */ assert( pPager->eLock==EXCLUSIVE_LOCK ); rc = pager_truncate(pPager, pPager->dbSize); } if( rc==SQLITE_OK && bCommit ){ rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_COMMIT_PHASETWO, 0); if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; } if( !pPager->exclusiveMode && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0)) ){ |
︙ | ︙ | |||
2995 2996 2997 2998 2999 3000 3001 | } /* 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 ** assertion that the transaction counter was modified. */ #ifdef SQLITE_DEBUG | < | < | 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 | } /* 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 ** assertion that the transaction counter was modified. */ #ifdef SQLITE_DEBUG sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0); #endif /* If this playback is happening automatically as a result of an IO or ** malloc error that occurred after the change-counter was updated but ** before the transaction was committed, then the change-counter ** modification may just have been reverted. If this happens in exclusive ** mode, then subsequent transactions performed by the connection will not |
︙ | ︙ | |||
3762 3763 3764 3765 3766 3767 3768 | ** SHARED_LOCK -> EXCLUSIVE_LOCK | No ** RESERVED_LOCK -> EXCLUSIVE_LOCK | Yes ** ** If the busy-handler callback returns non-zero, the lock is ** retried. If it returns zero, then the SQLITE_BUSY error is ** returned to the caller of the pager API function. */ | | > < < | | | | < | 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 | ** SHARED_LOCK -> EXCLUSIVE_LOCK | No ** RESERVED_LOCK -> EXCLUSIVE_LOCK | Yes ** ** If the busy-handler callback returns non-zero, the lock is ** retried. If it returns zero, then the SQLITE_BUSY error is ** returned to the caller of the pager API function. */ 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; ap = (void **)&pPager->xBusyHandler; assert( ((int(*)(void *))(ap[0]))==xBusyHandler ); assert( ap[1]==pBusyHandlerArg ); sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap); } /* ** Change the page size used by the Pager object. The new page size ** is passed in *pPageSize. ** ** If the pager is in the error state when this function is called, it |
︙ | ︙ | |||
5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 | } 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; sqlite3PcacheRelease(pPg); pagerUnlockIfUnused(pPager); } /* ** This function is called at the start of every write transaction. ** There must already be a RESERVED or EXCLUSIVE lock on the database | > | 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 | } 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. ** There must already be a RESERVED or EXCLUSIVE lock on the database |
︙ | ︙ | |||
6367 6368 6369 6370 6371 6372 6373 | ** or pages with the Pager.noSync flag set. ** ** If successful, or if called on a pager for which it is a no-op, this ** function returns SQLITE_OK. Otherwise, an IO error code is returned. */ int sqlite3PagerSync(Pager *pPager, const char *zMaster){ int rc = SQLITE_OK; | < < | | | < | 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 | ** or pages with the Pager.noSync flag set. ** ** If successful, or if called on a pager for which it is a no-op, this ** function returns SQLITE_OK. Otherwise, an IO error code is returned. */ int sqlite3PagerSync(Pager *pPager, const char *zMaster){ int 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); } return rc; } |
︙ | ︙ | |||
7121 7122 7123 7124 7125 7126 7127 7128 7129 7130 7131 7132 7133 7134 | ** with the pager. This might return NULL if the file has ** not yet been opened. */ sqlite3_file *sqlite3PagerFile(Pager *pPager){ return pPager->fd; } /* ** Return the file handle for the journal file (if it exists). ** This will be either the rollback journal or the WAL file. */ sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){ #if SQLITE_OMIT_WAL return pPager->jfd; | > > > > > > > > > > | 7115 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126 7127 7128 7129 7130 7131 7132 7133 7134 7135 7136 7137 7138 | ** with the pager. This might return NULL if the file has ** not yet been opened. */ sqlite3_file *sqlite3PagerFile(Pager *pPager){ return pPager->fd; } #ifdef SQLITE_ENABLE_SETLK_TIMEOUT /* ** Reset the lock timeout for pager. */ 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. */ sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){ #if SQLITE_OMIT_WAL return pPager->jfd; |
︙ | ︙ | |||
7581 7582 7583 7584 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 | if( pPager->pWal ){ rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode, (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), pPager->pBusyHandlerArg, pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, pnLog, pnCkpt ); } return rc; } int sqlite3PagerWalCallback(Pager *pPager){ return sqlite3WalCallback(pPager->pWal); } | > | 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 7598 7599 | if( pPager->pWal ){ rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode, (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), pPager->pBusyHandlerArg, pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, pnLog, pnCkpt ); sqlite3PagerResetLockTimeout(pPager); } return rc; } int sqlite3PagerWalCallback(Pager *pPager){ return sqlite3WalCallback(pPager->pWal); } |
︙ | ︙ |
Changes to src/pager.h.
︙ | ︙ | |||
122 123 124 125 126 127 128 | int, void(*)(DbPage*) ); int sqlite3PagerClose(Pager *pPager, sqlite3*); int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); /* Functions used to configure a Pager object. */ | | | 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | int, void(*)(DbPage*) ); int sqlite3PagerClose(Pager *pPager, sqlite3*); int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); /* Functions used to configure a Pager object. */ void sqlite3PagerSetBusyHandler(Pager*, int(*)(void *), void *); int sqlite3PagerSetPagesize(Pager*, u32*, int); #ifdef SQLITE_HAS_CODEC void sqlite3PagerAlignReserve(Pager*,Pager*); #endif int sqlite3PagerMaxPageCount(Pager*, int); void sqlite3PagerSetCachesize(Pager*, int); int sqlite3PagerSetSpillsize(Pager*, int); |
︙ | ︙ | |||
209 210 211 212 213 214 215 216 217 218 219 220 221 222 | sqlite3_file *sqlite3PagerJrnlFile(Pager*); const char *sqlite3PagerJournalname(Pager*); void *sqlite3PagerTempSpace(Pager*); int sqlite3PagerIsMemdb(Pager*); void sqlite3PagerCacheStat(Pager *, int, int, int *); void sqlite3PagerClearCache(Pager*); int sqlite3SectorSize(sqlite3_file *); /* Functions used to truncate the database file. */ void sqlite3PagerTruncateImage(Pager*,Pgno); void sqlite3PagerRekey(DbPage*, Pgno, u16); #ifndef SQLITE_OMIT_CONCURRENT | > > > > > | 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | sqlite3_file *sqlite3PagerJrnlFile(Pager*); const char *sqlite3PagerJournalname(Pager*); void *sqlite3PagerTempSpace(Pager*); int sqlite3PagerIsMemdb(Pager*); void sqlite3PagerCacheStat(Pager *, int, int, int *); void sqlite3PagerClearCache(Pager*); int sqlite3SectorSize(sqlite3_file *); #ifdef SQLITE_ENABLE_SETLK_TIMEOUT void sqlite3PagerResetLockTimeout(Pager *pPager); #else # define sqlite3PagerResetLockTimeout(X) #endif /* Functions used to truncate the database file. */ void sqlite3PagerTruncateImage(Pager*,Pgno); void sqlite3PagerRekey(DbPage*, Pgno, u16); #ifndef SQLITE_OMIT_CONCURRENT |
︙ | ︙ |
Changes to src/parse.y.
︙ | ︙ | |||
20 21 22 23 24 25 26 | // The type of the data attached to each token is Token. This is also the // default type for non-terminals. // %token_type {Token} %default_type {Token} | > | | | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | // The type of the data attached to each token is Token. This is also the // default type for non-terminals. // %token_type {Token} %default_type {Token} // An extra argument to the constructor for the parser, which is available // to all actions. %extra_context {Parse *pParse} // This code runs whenever there is a syntax error // %syntax_error { UNUSED_PARAMETER(yymajor); /* Silence some compiler warnings */ if( TOKEN.z[0] ){ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN); |
︙ | ︙ | |||
117 118 119 120 121 122 123 | } // end %include // Input is a single SQL command input ::= cmdlist. cmdlist ::= cmdlist ecmd. cmdlist ::= ecmd. ecmd ::= SEMI. | | < > | 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | } // end %include // Input is a single SQL command input ::= cmdlist. cmdlist ::= cmdlist ecmd. cmdlist ::= ecmd. ecmd ::= SEMI. ecmd ::= cmdx SEMI. %ifndef SQLITE_OMIT_EXPLAIN ecmd ::= explain cmdx. explain ::= EXPLAIN. { pParse->explain = 1; } explain ::= EXPLAIN QUERY PLAN. { pParse->explain = 2; } %endif SQLITE_OMIT_EXPLAIN cmdx ::= cmd. { sqlite3FinishCoding(pParse); } ///////////////////// Begin and end transactions. //////////////////////////// // |
︙ | ︙ | |||
217 218 219 220 221 222 223 | // The following directive causes tokens ABORT, AFTER, ASC, etc. to // fallback to ID if they will not parse as their original value. // This obviates the need for the "id" nonterminal. // %fallback ID ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST COLUMNKW | | > | 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | // The following directive causes tokens ABORT, AFTER, ASC, etc. to // fallback to ID if they will not parse as their original value. // This obviates the need for the "id" nonterminal. // %fallback ID ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST COLUMNKW CONFLICT DATABASE DEFERRED DESC DETACH DO EACH END EXCLUSIVE EXPLAIN FAIL FOR IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH NO PLAN QUERY KEY OF OFFSET PRAGMA RAISE RECURSIVE RELEASE REPLACE RESTRICT ROW ROLLBACK SAVEPOINT TEMP TRIGGER VACUUM VIEW VIRTUAL WITH WITHOUT %ifdef SQLITE_OMIT_COMPOUND_SELECT EXCEPT INTERSECT UNION %endif SQLITE_OMIT_COMPOUND_SELECT REINDEX RENAME CTIME_KW IF |
︙ | ︙ | |||
251 252 253 254 255 256 257 258 259 260 261 262 263 264 | %right ESCAPE. %left BITAND BITOR LSHIFT RSHIFT. %left PLUS MINUS. %left STAR SLASH REM. %left CONCAT. %left COLLATE. %right BITNOT. // An IDENTIFIER can be a generic identifier, or one of several // keywords. Any non-standard keyword can also be an identifier. // %token_class id ID|INDEXED. // And "ids" is an identifer-or-string. | > | 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 | %right ESCAPE. %left BITAND BITOR LSHIFT RSHIFT. %left PLUS MINUS. %left STAR SLASH REM. %left CONCAT. %left COLLATE. %right BITNOT. %nonassoc ON. // An IDENTIFIER can be a generic identifier, or one of several // keywords. Any non-standard keyword can also be an identifier. // %token_class id ID|INDEXED. // And "ids" is an identifer-or-string. |
︙ | ︙ | |||
475 476 477 478 479 480 481 | ){ sqlite3ErrorMsg(pParse, "too many terms in compound SELECT"); } } } } | | > > > > > > > > > > > > > > > > > | | 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 | ){ sqlite3ErrorMsg(pParse, "too many terms in compound SELECT"); } } } } select(A) ::= WITH wqlist(W) selectnowith(X). { Select *p = X; if( p ){ p->pWith = W; parserDoubleLinkSelect(pParse, p); }else{ sqlite3WithDelete(pParse->db, W); } A = p; } select(A) ::= WITH RECURSIVE wqlist(W) selectnowith(X). { Select *p = X; if( p ){ p->pWith = W; parserDoubleLinkSelect(pParse, p); }else{ sqlite3WithDelete(pParse->db, W); } A = p; } select(A) ::= selectnowith(X). { Select *p = X; if( p ){ parserDoubleLinkSelect(pParse, p); } A = p; /*A-overwrites-X*/ } selectnowith(A) ::= oneselect(A). %ifndef SQLITE_OMIT_COMPOUND_SELECT selectnowith(A) ::= selectnowith(A) multiselect_op(Y) oneselect(Z). { Select *pRhs = Z; Select *pLhs = A; |
︙ | ︙ | |||
677 678 679 680 681 682 683 | %type dbnm {Token} dbnm(A) ::= . {A.z=0; A.n=0;} dbnm(A) ::= DOT nm(X). {A = X;} %type fullname {SrcList*} %destructor fullname {sqlite3SrcListDelete(pParse->db, $$);} | > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 | %type dbnm {Token} dbnm(A) ::= . {A.z=0; A.n=0;} dbnm(A) ::= DOT nm(X). {A = X;} %type fullname {SrcList*} %destructor fullname {sqlite3SrcListDelete(pParse->db, $$);} fullname(A) ::= nm(X). {A = sqlite3SrcListAppend(pParse->db,0,&X,0); /*A-overwrites-X*/} fullname(A) ::= nm(X) DOT nm(Y). {A = sqlite3SrcListAppend(pParse->db,0,&X,&Y); /*A-overwrites-X*/} %type xfullname {SrcList*} %destructor xfullname {sqlite3SrcListDelete(pParse->db, $$);} xfullname(A) ::= nm(X). {A = sqlite3SrcListAppend(pParse->db,0,&X,0); /*A-overwrites-X*/} xfullname(A) ::= nm(X) DOT nm(Y). {A = sqlite3SrcListAppend(pParse->db,0,&X,&Y); /*A-overwrites-X*/} xfullname(A) ::= nm(X) DOT nm(Y) AS nm(Z). { A = sqlite3SrcListAppend(pParse->db,0,&X,&Y); /*A-overwrites-X*/ if( A ) A->a[0].zAlias = sqlite3NameFromToken(pParse->db, &Z); } xfullname(A) ::= nm(X) AS nm(Z). { A = sqlite3SrcListAppend(pParse->db,0,&X,0); /*A-overwrites-X*/ if( A ) A->a[0].zAlias = sqlite3NameFromToken(pParse->db, &Z); } %type joinop {int} joinop(X) ::= COMMA|JOIN. { X = JT_INNER; } joinop(X) ::= JOIN_KW(A) JOIN. {X = sqlite3JoinType(pParse,&A,0,0); /*X-overwrites-A*/} joinop(X) ::= JOIN_KW(A) nm(B) JOIN. {X = sqlite3JoinType(pParse,&A,&B,0); /*X-overwrites-A*/} joinop(X) ::= JOIN_KW(A) nm(B) nm(C) JOIN. {X = sqlite3JoinType(pParse,&A,&B,&C);/*X-overwrites-A*/} // There is a parsing abiguity in an upsert statement that uses a // SELECT on the RHS of a the INSERT: // // INSERT INTO tab SELECT * FROM aaa JOIN bbb ON CONFLICT ... // here ----^^ // // When the ON token is encountered, the parser does not know if it is // the beginning of an ON CONFLICT clause, or the beginning of an ON // clause associated with the JOIN. The conflict is resolved in favor // of the JOIN. If an ON CONFLICT clause is intended, insert a dummy // WHERE clause in between, like this: // // INSERT INTO tab SELECT * FROM aaa JOIN bbb WHERE true ON CONFLICT ... // // The [AND] and [OR] precedence marks in the rules for on_opt cause the // ON in this context to always be interpreted as belonging to the JOIN. // %type on_opt {Expr*} %destructor on_opt {sqlite3ExprDelete(pParse->db, $$);} on_opt(N) ::= ON expr(E). {N = E;} on_opt(N) ::= . [OR] {N = 0;} // Note that this block abuses the Token type just a little. If there is // no "INDEXED BY" clause, the returned token is empty (z==0 && n==0). If // there is an INDEXED BY clause, then the token is populated as per normal, // with z pointing to the token data and n containing the number of bytes // in the token. // |
︙ | ︙ | |||
773 774 775 776 777 778 779 | {A = sqlite3PExpr(pParse,TK_LIMIT,X,Y);} limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y). {A = sqlite3PExpr(pParse,TK_LIMIT,Y,X);} /////////////////////////// The DELETE statement ///////////////////////////// // %ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT | | < | < | < | | < | | 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 | {A = sqlite3PExpr(pParse,TK_LIMIT,X,Y);} limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y). {A = sqlite3PExpr(pParse,TK_LIMIT,Y,X);} /////////////////////////// The DELETE statement ///////////////////////////// // %ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT cmd ::= with DELETE FROM xfullname(X) indexed_opt(I) where_opt(W) orderby_opt(O) limit_opt(L). { sqlite3SrcListIndexedBy(pParse, X, &I); sqlite3DeleteFrom(pParse,X,W,O,L); } %endif %ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT cmd ::= with DELETE FROM xfullname(X) indexed_opt(I) where_opt(W). { sqlite3SrcListIndexedBy(pParse, X, &I); sqlite3DeleteFrom(pParse,X,W,0,0); } %endif %type where_opt {Expr*} %destructor where_opt {sqlite3ExprDelete(pParse->db, $$);} where_opt(A) ::= . {A = 0;} where_opt(A) ::= WHERE expr(X). {A = X;} ////////////////////////// The UPDATE command //////////////////////////////// // %ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT cmd ::= with UPDATE orconf(R) xfullname(X) indexed_opt(I) SET setlist(Y) where_opt(W) orderby_opt(O) limit_opt(L). { sqlite3SrcListIndexedBy(pParse, X, &I); sqlite3ExprListCheckLength(pParse,Y,"set list"); sqlite3Update(pParse,X,Y,W,R,O,L,0); } %endif %ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT cmd ::= with UPDATE orconf(R) xfullname(X) indexed_opt(I) SET setlist(Y) where_opt(W). { sqlite3SrcListIndexedBy(pParse, X, &I); sqlite3ExprListCheckLength(pParse,Y,"set list"); sqlite3Update(pParse,X,Y,W,R,0,0,0); } %endif %type setlist {ExprList*} %destructor setlist {sqlite3ExprListDelete(pParse->db, $$);} setlist(A) ::= setlist(A) COMMA nm(X) EQ expr(Y). { |
︙ | ︙ | |||
835 836 837 838 839 840 841 | } setlist(A) ::= LP idlist(X) RP EQ expr(Y). { A = sqlite3ExprListAppendVector(pParse, 0, X, Y); } ////////////////////////// The INSERT command ///////////////////////////////// // | | | | | < | > > > > > > > > > > > > > > > > | 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 | } setlist(A) ::= LP idlist(X) RP EQ expr(Y). { A = sqlite3ExprListAppendVector(pParse, 0, X, Y); } ////////////////////////// The INSERT command ///////////////////////////////// // cmd ::= with insert_cmd(R) INTO xfullname(X) idlist_opt(F) select(S) upsert(U). { sqlite3Insert(pParse, X, S, F, R, U); } cmd ::= with insert_cmd(R) INTO xfullname(X) idlist_opt(F) DEFAULT VALUES. { sqlite3Insert(pParse, X, 0, F, R, 0); } %type upsert {Upsert*} // Because upsert only occurs at the tip end of the INSERT rule for cmd, // there is never a case where the value of the upsert pointer will not // be destroyed by the cmd action. So comment-out the destructor to // avoid unreachable code. //%destructor upsert {sqlite3UpsertDelete(pParse->db,$$);} upsert(A) ::= . { A = 0; } upsert(A) ::= ON CONFLICT LP sortlist(T) RP where_opt(TW) DO UPDATE SET setlist(Z) where_opt(W). { A = sqlite3UpsertNew(pParse->db,T,TW,Z,W);} upsert(A) ::= ON CONFLICT LP sortlist(T) RP where_opt(TW) DO NOTHING. { A = sqlite3UpsertNew(pParse->db,T,TW,0,0); } upsert(A) ::= ON CONFLICT DO NOTHING. { A = sqlite3UpsertNew(pParse->db,0,0,0,0); } %type insert_cmd {int} insert_cmd(A) ::= INSERT orconf(R). {A = R;} insert_cmd(A) ::= REPLACE. {A = OE_Replace;} %type idlist_opt {IdList*} %destructor idlist_opt {sqlite3IdListDelete(pParse->db, $$);} |
︙ | ︙ | |||
1390 1391 1392 1393 1394 1395 1396 | // UPDATE trigger_cmd(A) ::= UPDATE(B) orconf(R) trnm(X) tridxby SET setlist(Y) where_opt(Z) scanpt(E). {A = sqlite3TriggerUpdateStep(pParse->db, &X, Y, Z, R, B.z, E);} // INSERT trigger_cmd(A) ::= scanpt(B) insert_cmd(R) INTO | | | | | 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 | // UPDATE trigger_cmd(A) ::= UPDATE(B) orconf(R) trnm(X) tridxby SET setlist(Y) where_opt(Z) scanpt(E). {A = sqlite3TriggerUpdateStep(pParse->db, &X, Y, Z, R, B.z, E);} // INSERT trigger_cmd(A) ::= scanpt(B) insert_cmd(R) INTO trnm(X) idlist_opt(F) select(S) upsert(U) scanpt(Z). { A = sqlite3TriggerInsertStep(pParse->db,&X,F,S,R,U,B,Z);/*A-overwrites-R*/ } // DELETE trigger_cmd(A) ::= DELETE(B) FROM trnm(X) tridxby where_opt(Y) scanpt(E). {A = sqlite3TriggerDeleteStep(pParse->db, &X, Y, B.z, E);} // SELECT trigger_cmd(A) ::= scanpt(B) select(X) scanpt(E). {A = sqlite3TriggerSelectStep(pParse->db, X, B, E); /*A-overwrites-X*/} |
︙ | ︙ | |||
1499 1500 1501 1502 1503 1504 1505 | anylist ::= . anylist ::= anylist LP anylist RP. anylist ::= anylist ANY. %endif SQLITE_OMIT_VIRTUALTABLE //////////////////////// COMMON TABLE EXPRESSIONS //////////////////////////// | < < | | | | 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 | anylist ::= . anylist ::= anylist LP anylist RP. anylist ::= anylist ANY. %endif SQLITE_OMIT_VIRTUALTABLE //////////////////////// COMMON TABLE EXPRESSIONS //////////////////////////// %type wqlist {With*} %destructor wqlist {sqlite3WithDelete(pParse->db, $$);} with ::= . %ifndef SQLITE_OMIT_CTE with ::= WITH wqlist(W). { sqlite3WithPush(pParse, W, 1); } with ::= WITH RECURSIVE wqlist(W). { sqlite3WithPush(pParse, W, 1); } wqlist(A) ::= nm(X) eidlist_opt(Y) AS LP select(Z) RP. { A = sqlite3WithAdd(pParse, 0, &X, Y, Z); /*A-overwrites-X*/ } wqlist(A) ::= wqlist(A) COMMA nm(X) eidlist_opt(Y) AS LP select(Z) RP. { A = sqlite3WithAdd(pParse, A, &X, Y, Z); } %endif SQLITE_OMIT_CTE |
Changes to src/resolve.c.
︙ | ︙ | |||
187 188 189 190 191 192 193 | int cntTab = 0; /* Number of matching table names */ int nSubquery = 0; /* How many levels of subquery */ sqlite3 *db = pParse->db; /* The database connection */ struct SrcList_item *pItem; /* Use for looping over pSrcList items */ struct SrcList_item *pMatch = 0; /* The matching pSrcList item */ NameContext *pTopNC = pNC; /* First namecontext in the list */ Schema *pSchema = 0; /* Schema of the expression */ | | | 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | int cntTab = 0; /* Number of matching table names */ int nSubquery = 0; /* How many levels of subquery */ sqlite3 *db = pParse->db; /* The database connection */ struct SrcList_item *pItem; /* Use for looping over pSrcList items */ 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 eNewExprOp = TK_COLUMN; /* New value for pExpr->op on success */ Table *pTab = 0; /* Table hold the row */ Column *pCol; /* A column of pTab */ assert( pNC ); /* the name context cannot be NULL. */ assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); |
︙ | ︙ | |||
292 293 294 295 296 297 298 | if( (pMatch->fg.jointype & JT_LEFT)!=0 ){ ExprSetProperty(pExpr, EP_CanBeNull); } pSchema = pExpr->pTab->pSchema; } } /* if( pSrcList ) */ | | | > | > > > | | | | | | | | > > > > | > > | > | > > > > > > > > > > > | | | | | | | | | | | > | | < > | | | > | | 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 | if( (pMatch->fg.jointype & JT_LEFT)!=0 ){ ExprSetProperty(pExpr, EP_CanBeNull); } pSchema = pExpr->pTab->pSchema; } } /* if( pSrcList ) */ #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. Or ** maybe it is an excluded.* from an upsert. */ 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; pSchema = pTab->pSchema; cntTab++; for(iCol=0, pCol=pTab->aCol; iCol<pTab->nCol; iCol++, pCol++){ if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ if( iCol==pTab->iPKey ){ iCol = -1; } break; } } if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) && VisibleRowid(pTab) ){ /* IMP: R-51414-32910 */ iCol = -1; } if( iCol<pTab->nCol ){ cnt++; #ifndef SQLITE_OMIT_UPSERT if( pExpr->iTable==2 ){ testcase( iCol==(-1) ); pExpr->iTable = pNC->uNC.pUpsert->regData + iCol; eNewExprOp = TK_REGISTER; }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->pTab = pTab; pExpr->iColumn = (i16)iCol; eNewExprOp = TK_TRIGGER; #endif /* SQLITE_OMIT_TRIGGER */ } } } } #endif /* !defined(SQLITE_OMIT_TRIGGER) || !defined(SQLITE_OMIT_UPSERT) */ /* ** Perhaps the name is a reference to the ROWID */ if( cnt==0 && cntTab==1 && pMatch |
︙ | ︙ | |||
379 380 381 382 383 384 385 | ** ** The ability to use an output result-set column in the WHERE, GROUP BY, ** or HAVING clauses, or as part of a larger expression in the ORDER BY ** clause is not standard SQL. This is a (goofy) SQLite extension, that ** is supported for backwards compatibility only. Hence, we issue a warning ** on sqlite3_log() whenever the capability is used. */ | | < > > > | 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 | ** ** The ability to use an output result-set column in the WHERE, GROUP BY, ** or HAVING clauses, or as part of a larger expression in the ORDER BY ** clause is not standard SQL. This is a (goofy) SQLite extension, that ** is supported for backwards compatibility only. Hence, we issue a warning ** on sqlite3_log() whenever the capability is used. */ if( (pNC->ncFlags & NC_UEList)!=0 && cnt==0 && zTab==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 ){ Expr *pOrig; assert( pExpr->pLeft==0 && pExpr->pRight==0 ); assert( pExpr->x.pList==0 ); assert( pExpr->x.pSelect==0 ); |
︙ | ︙ | |||
479 480 481 482 483 484 485 | /* Clean up and return */ sqlite3ExprDelete(db, pExpr->pLeft); pExpr->pLeft = 0; sqlite3ExprDelete(db, pExpr->pRight); pExpr->pRight = 0; | | | 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 | /* Clean up and return */ sqlite3ExprDelete(db, pExpr->pLeft); pExpr->pLeft = 0; sqlite3ExprDelete(db, pExpr->pRight); pExpr->pRight = 0; pExpr->op = eNewExprOp; ExprSetProperty(pExpr, EP_Leaf); lookupname_end: if( cnt==1 ){ assert( pNC!=0 ); if( !ExprHasProperty(pExpr, EP_Alias) ){ sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList); } |
︙ | ︙ | |||
911 912 913 914 915 916 917 | pEList = pSelect->pEList; /* Resolve all names in the ORDER BY term expression */ memset(&nc, 0, sizeof(nc)); nc.pParse = pParse; nc.pSrcList = pSelect->pSrc; | | | | 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 | pEList = pSelect->pEList; /* Resolve all names in the ORDER BY term expression */ memset(&nc, 0, sizeof(nc)); nc.pParse = pParse; nc.pSrcList = pSelect->pSrc; nc.uNC.pEList = pEList; nc.ncFlags = NC_AllowAgg|NC_UEList; nc.nErr = 0; db = pParse->db; savedSuppErr = db->suppressErr; db->suppressErr = 1; rc = sqlite3ResolveExprNames(&nc, pE); db->suppressErr = savedSuppErr; if( rc ) return 0; |
︙ | ︙ | |||
1295 1296 1297 1298 1299 1300 1301 | ** other expressions in the SELECT statement. This is so that ** expressions in the WHERE clause (etc.) can refer to expressions by ** aliases in the result set. ** ** Minor point: If this is the case, then the expression will be ** re-evaluated for each reference to it. */ | > | > | 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 | ** other expressions in the SELECT statement. This is so that ** expressions in the WHERE clause (etc.) can refer to expressions by ** aliases in the result set. ** ** Minor point: If this is the case, then the expression will be ** re-evaluated for each reference to it. */ 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; /* Resolve names in table-valued-function arguments */ for(i=0; i<p->pSrc->nSrc; i++){ struct SrcList_item *pItem = &p->pSrc->a[i]; if( pItem->fg.isTabFunc |
︙ | ︙ | |||
1528 1529 1530 1531 1532 1533 1534 | ** Any errors cause an error message to be set in pParse. */ void sqlite3ResolveSelfReference( Parse *pParse, /* Parsing context */ Table *pTab, /* The table being referenced */ int type, /* NC_IsCheck or NC_PartIdx or NC_IdxExpr */ Expr *pExpr, /* Expression to resolve. May be NULL. */ | | | 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 | ** Any errors cause an error message to be set in pParse. */ void sqlite3ResolveSelfReference( Parse *pParse, /* Parsing context */ 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 NULL. */ ){ SrcList sSrc; /* Fake SrcList for pParse->pNewTable */ NameContext sNC; /* Name context for pParse->pNewTable */ assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr ); memset(&sNC, 0, sizeof(sNC)); memset(&sSrc, 0, sizeof(sSrc)); |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
17 18 19 20 21 22 23 | /* ** Trace output macros */ #if SELECTTRACE_ENABLED /***/ int sqlite3SelectTrace = 0; # define SELECTTRACE(K,P,S,X) \ if(sqlite3SelectTrace&(K)) \ | | | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | /* ** Trace output macros */ #if SELECTTRACE_ENABLED /***/ int sqlite3SelectTrace = 0; # define SELECTTRACE(K,P,S,X) \ if(sqlite3SelectTrace&(K)) \ sqlite3DebugPrintf("%s/%d/%p: ",(S)->zSelName,(P)->iSelectId,(S)),\ sqlite3DebugPrintf X #else # define SELECTTRACE(K,P,S,X) #endif /* |
︙ | ︙ | |||
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | int tabTnct; /* Ephemeral table used for DISTINCT processing */ int addrTnct; /* Address of OP_OpenEphemeral opcode for tabTnct */ }; /* ** An instance of the following object is used to record information about ** the ORDER BY (or GROUP BY) clause of query is being coded. */ typedef struct SortCtx SortCtx; struct SortCtx { ExprList *pOrderBy; /* The ORDER BY (or GROUP BY clause) */ int nOBSat; /* Number of ORDER BY terms satisfied by indices */ int iECursor; /* Cursor number for the sorter */ int regReturn; /* Register holding block-output return address */ 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 */ u8 sortFlags; /* Zero or more SORTFLAG_* bits */ u8 bOrderedInnerLoop; /* ORDER BY correctly sorts the inner loop */ }; #define SORTFLAG_UseSorter 0x01 /* Use SorterOpen instead of OpenEphemeral */ /* ** Delete all the content of a Select structure. Deallocate the structure ** itself only if bFree is true. */ | > > > > > > > > > > > > > > > > > > > > > > | 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | int tabTnct; /* Ephemeral table used for DISTINCT processing */ int addrTnct; /* Address of OP_OpenEphemeral opcode for tabTnct */ }; /* ** 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 { ExprList *pOrderBy; /* The ORDER BY (or GROUP BY clause) */ int nOBSat; /* Number of ORDER BY terms satisfied by indices */ int iECursor; /* Cursor number for the sorter */ int regReturn; /* Register holding block-output return address */ 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 */ 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 }; #define SORTFLAG_UseSorter 0x01 /* Use SorterOpen instead of OpenEphemeral */ /* ** Delete all the content of a Select structure. Deallocate the structure ** itself only if bFree is true. */ |
︙ | ︙ | |||
377 378 379 380 381 382 383 384 385 386 387 388 389 390 | setJoinExpr(p->x.pList->a[i].pExpr, iTable); } } setJoinExpr(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. ** NATURAL joins also create extra WHERE clause terms. ** ** The terms of a FROM clause are contained in the Select.pSrc structure. | > > > > > > > > > > > > > > > > > > > > > > > | 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 | setJoinExpr(p->x.pList->a[i].pExpr, iTable); } } setJoinExpr(p->pLeft, iTable); p = p->pRight; } } /* 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. ** NATURAL joins also create extra WHERE clause terms. ** ** The terms of a FROM clause are contained in the Select.pSrc structure. |
︙ | ︙ | |||
651 652 653 654 655 656 657 658 659 660 661 662 663 664 | sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1); sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r1, iMem, N); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); sqlite3ReleaseTempReg(pParse, r1); } /* ** This routine generates the code for the inside of the inner loop ** of a SELECT. ** ** 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 p->pEList is used only | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 | sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1); sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r1, iMem, N); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); 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->pTab; if( pExpr->op==TK_COLUMN && pTab && !IsVirtual(pTab) && (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF) #if 0 && pTab->pSchema && pTab->pSelect==0 && !IsVirtual(pTab) #endif ){ 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->pTab = pExpr->pTab; pNew->iColumn = pPk ? pPk->aiColumn[k] : -1; pExtra = sqlite3ExprListAppend(pParse, pExtra, pNew); } } pSort->aDefer[nDefer].pTab = pExpr->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 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 p->pEList is used only |
︙ | ︙ | |||
723 724 725 726 727 728 729 730 731 732 733 734 735 736 | regOrig = regResult = pDest->iSdst; if( srcTab>=0 ){ for(i=0; i<nResultCol; i++){ sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i); VdbeComment((v, "%s", p->pEList->a[i].zName)); } }else if( eDest!=SRT_Exists ){ /* If the destination is an EXISTS(...) expression, the actual ** values returned by the SELECT are not required. */ u8 ecelFlags; if( eDest==SRT_Mem || eDest==SRT_Output || eDest==SRT_Coroutine ){ ecelFlags = SQLITE_ECEL_DUP; }else{ | > > > | 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 | regOrig = regResult = pDest->iSdst; if( srcTab>=0 ){ for(i=0; i<nResultCol; i++){ sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i); 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; if( eDest==SRT_Mem || eDest==SRT_Output || eDest==SRT_Coroutine ){ ecelFlags = SQLITE_ECEL_DUP; }else{ |
︙ | ︙ | |||
746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 | 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 ){ p->pEList->a[j-1].u.x.iOrderByCol = i+1-pSort->nOBSat; } } regOrig = 0; assert( eDest==SRT_Set || eDest==SRT_Mem || eDest==SRT_Coroutine || eDest==SRT_Output ); } nResultCol = sqlite3ExprCodeExprList(pParse,p->pEList,regResult, 0,ecelFlags); } /* If the DISTINCT keyword was present on the SELECT statement ** and this row has been seen before, then do not make this row ** part of the result. */ if( hasDistinct ){ | > > > > > > > > > > > > > > > > > > > > > > | 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 | 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 ){ p->pEList->a[j-1].u.x.iOrderByCol = i+1-pSort->nOBSat; } } #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 regOrig = 0; assert( eDest==SRT_Set || eDest==SRT_Mem || eDest==SRT_Coroutine || eDest==SRT_Output ); } nResultCol = sqlite3ExprCodeExprList(pParse,p->pEList,regResult, 0,ecelFlags); #ifdef SQLITE_ENABLE_SORTER_REFERENCES if( pExtra ){ nResultCol += sqlite3ExprCodeExprList( pParse, pExtra, regResult + nResultCol, 0, 0 ); sqlite3ExprListDelete(pParse->db, pExtra); } #endif } /* If the DISTINCT keyword was present on the SELECT statement ** and this row has been seen before, then do not make this row ** part of the result. */ if( hasDistinct ){ |
︙ | ︙ | |||
1209 1210 1211 1212 1213 1214 1215 | SortCtx *pSort, /* Information on the ORDER BY clause */ int nColumn, /* Number of columns of data */ SelectDest *pDest /* Write the sorted results here */ ){ 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 */ | | | < > > > > > > > > > > > > < < | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > | | | | | | | | > | 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 | SortCtx *pSort, /* Information on the ORDER BY clause */ int nColumn, /* Number of columns of data */ SelectDest *pDest /* Write the sorted results here */ ){ 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; /* Top of output loop. Jump for Next. */ int addrOnce = 0; int iTab; ExprList *pOrderBy = pSort->pOrderBy; int eDest = pDest->eDest; int iParm = pDest->iSDParm; int regRow; int regRowid; int iCol; int nKey; /* Number of key columns in sorter record */ int iSortTab; /* Sorter cursor to read from */ int i; int bSeq; /* True if sorter record includes seq. no. */ int nRefKey = 0; struct ExprList_item *aOutEx = p->pEList->a; assert( addrBreak<0 ); if( pSort->labelBkOut ){ sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut); 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; }else{ regRowid = sqlite3GetTempReg(pParse); regRow = sqlite3GetTempRange(pParse, nColumn); } nKey = pOrderBy->nExpr - pSort->nOBSat; if( pSort->sortFlags & SORTFLAG_UseSorter ){ int regSortOut = ++pParse->nMem; iSortTab = pParse->nTab++; if( pSort->labelBkOut ){ addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); } 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); codeOffset(v, p->iOffset, addrContinue); sqlite3VdbeAddOp3(v, OP_SorterData, iTab, regSortOut, iSortTab); bSeq = 0; }else{ addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v); codeOffset(v, p->iOffset, addrContinue); iSortTab = iTab; bSeq = 1; } 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); } } 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: { sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); |
︙ | ︙ | |||
3610 3611 3612 3613 3614 3615 3616 | if( pNew==0 ){ p->pPrior = pPrior; }else{ pNew->pPrior = pPrior; if( pPrior ) pPrior->pNext = pNew; pNew->pNext = p; p->pPrior = pNew; | | < | | 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 | if( pNew==0 ){ p->pPrior = pPrior; }else{ pNew->pPrior = pPrior; 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)); } if( db->mallocFailed ) return 1; } /* Begin flattening the iFrom-th entry of the FROM clause ** in the outer query. */ |
︙ | ︙ | |||
3746 3747 3748 3749 3750 3751 3752 | ** (the only way this can happen is if the compound sub-query is ** currently part of pSub->pSrc). See ticket [d11a6e908f]. */ ExprList *pOrderBy = pSub->pOrderBy; for(i=0; i<pOrderBy->nExpr; i++){ pOrderBy->a[i].u.x.iOrderByCol = 0; } assert( pParent->pOrderBy==0 ); | < | 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 | ** (the only way this can happen is if the compound sub-query is ** currently part of pSub->pSrc). See ticket [d11a6e908f]. */ ExprList *pOrderBy = pSub->pOrderBy; for(i=0; i<pOrderBy->nExpr; i++){ pOrderBy->a[i].u.x.iOrderByCol = 0; } assert( pParent->pOrderBy==0 ); pParent->pOrderBy = pOrderBy; pSub->pOrderBy = 0; } pWhere = sqlite3ExprDup(db, pSub->pWhere, 0); if( isLeftJoin>0 ){ setJoinExpr(pWhere, iNewParent); } |
︙ | ︙ | |||
3830 3831 3832 3833 3834 3835 3836 | ** 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). ** | | | | | > > > > > > > > > > | > | 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 | ** 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). ** ** (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 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. ** ** Return 0 if no changes are made and non-zero if one or more WHERE clause ** terms are duplicated into the subquery. */ static int pushDownWhereTerms( Parse *pParse, /* Parse context (for malloc() and error reporting) */ Select *pSubq, /* The subquery whose WHERE clause is to be augmented */ Expr *pWhere, /* The WHERE clause of the outer query */ 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; if( pWhere==0 ) return 0; if( pSubq->selFlags & SF_Recursive ) return 0; /* restriction (2) */ #ifdef SQLITE_DEBUG |
︙ | ︙ | |||
3868 3869 3870 3871 3872 3873 3874 | } #endif if( pSubq->pLimit!=0 ){ return 0; /* restriction (3) */ } while( pWhere->op==TK_AND ){ | | > > > > > > > | > > > | 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 | } #endif if( pSubq->pLimit!=0 ){ return 0; /* restriction (3) */ } while( pWhere->op==TK_AND ){ nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, iCursor, isLeftJoin); pWhere = pWhere->pLeft; } 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; x.isLeftJoin = 0; x.pEList = pSubq->pEList; pNew = substExpr(&x, pNew); if( pSubq->selFlags & SF_Aggregate ){ |
︙ | ︙ | |||
4331 4332 4333 4334 4335 4336 4337 | } assert( p->pSrc!=0 ); if( (selFlags & SF_Expanded)!=0 ){ return WRC_Prune; } pTabList = p->pSrc; pEList = p->pEList; | < | < | 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 | } assert( p->pSrc!=0 ); if( (selFlags & SF_Expanded)!=0 ){ return WRC_Prune; } pTabList = p->pSrc; pEList = p->pEList; sqlite3WithPush(pParse, p->pWith, 0); /* Make sure cursor numbers have been assigned to all entries in ** the FROM clause of the SELECT statement. */ sqlite3SrcListAssignCursors(pParse, pTabList); /* Look up every table named in the FROM clause of the select. If |
︙ | ︙ | |||
4908 4909 4910 4911 4912 4913 4914 | ); } } #else # define explainSimpleCount(a,b,c) #endif | < < < < < < < < | | | | > | 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 | ); } } #else # define explainSimpleCount(a,b,c) #endif /* ** sqlite3WalkExpr() callback used by havingToWhere(). ** ** If the node passed to the callback is a TK_AND node, return ** WRC_Continue to tell sqlite3WalkExpr() to iterate through child nodes. ** ** Otherwise, return WRC_Prune. In this case, also check if the ** sub-expression matches the criteria for being moved to the WHERE ** clause. If so, add it to the WHERE clause and replace the sub-expression ** within the HAVING expression with a constant "1". */ static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){ if( pExpr->op!=TK_AND ){ 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 = pS->pWhere; SWAP(Expr, *pNew, *pExpr); pNew = sqlite3ExprAnd(db, pWhere, pNew); pS->pWhere = pNew; pWalker->eCode = 1; } } return WRC_Prune; } return WRC_Continue; } |
︙ | ︙ | |||
4960 4961 4962 4963 4964 4965 4966 | ** ** SELECT * FROM <tables> WHERE a=? AND b=? GROUP BY b HAVING c=? ** ** A term of the HAVING expression is eligible for transfer if it consists ** entirely of constants and expressions that are also GROUP BY terms that ** use the "BINARY" collation sequence. */ | | < < < < < < < < < < | | > > > > > > | 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 | ** ** SELECT * FROM <tables> WHERE a=? AND b=? GROUP BY b HAVING c=? ** ** A term of the HAVING expression is eligible for transfer if it consists ** entirely of constants and expressions that are also GROUP BY terms that ** use the "BINARY" collation sequence. */ static void havingToWhere(Parse *pParse, Select *p){ Walker sWalker; memset(&sWalker, 0, sizeof(sWalker)); sWalker.pParse = pParse; sWalker.xExprCallback = havingToWhereExprCb; 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 } /* ** Check to see if the pThis entry of pTabList is a self-join of a prior view. ** If it is, then return the SrcList_item for the prior view. If it is not, ** then return 0. */ |
︙ | ︙ | |||
5137 5138 5139 5140 5141 5142 5143 | db = pParse->db; if( p==0 || db->mallocFailed || pParse->nErr ){ return 1; } if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; memset(&sAggInfo, 0, sizeof(sAggInfo)); #if SELECTTRACE_ENABLED | > > > | | 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 | db = pParse->db; if( p==0 || db->mallocFailed || pParse->nErr ){ return 1; } if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; memset(&sAggInfo, 0, sizeof(sAggInfo)); #if SELECTTRACE_ENABLED #ifndef SQLITE_OMIT_EXPLAIN p->iSelectId = pParse->iSelectId; #endif SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->iSelectId)); if( sqlite3SelectTrace & 0x100 ){ sqlite3TreeViewSelect(0, p, 0); } #endif assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo ); assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo ); |
︙ | ︙ | |||
5168 5169 5170 5171 5172 5173 5174 | pTabList = p->pSrc; if( pParse->nErr || db->mallocFailed ){ goto select_end; } assert( p->pEList!=0 ); isAgg = (p->selFlags & SF_Aggregate)!=0; #if SELECTTRACE_ENABLED | | | > | > > > > > > > > > > > > > > > | 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 | 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 & 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 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; 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 ** columns in the SELECT on the RHS */ if( pTab->nCol!=pSub->pEList->nExpr ){ sqlite3ErrorMsg(pParse, "expected %d columns for '%s' but got %d", pTab->nCol, pTab->zName, pSub->pEList->nExpr); |
︙ | ︙ | |||
5254 5255 5256 5257 5258 5259 5260 | #ifndef SQLITE_OMIT_COMPOUND_SELECT /* Handle compound SELECT statements using the separate multiSelect() ** procedure. */ if( p->pPrior ){ rc = multiSelect(pParse, p, pDest); | < | > > > > | 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 | #ifndef SQLITE_OMIT_COMPOUND_SELECT /* Handle compound SELECT statements using the separate multiSelect() ** procedure. */ if( p->pPrior ){ rc = multiSelect(pParse, p, pDest); #if SELECTTRACE_ENABLED SELECTTRACE(0x1,pParse,p,("end compound-select processing\n")); if( pParse->iSelectId==0 && (sqlite3SelectTrace & 0x2000)!=0 ){ sqlite3TreeViewSelect(0, p, 0); } #endif explainSetInteger(pParse->iSelectId, iRestoreSelectId); return rc; } #endif /* For each term in the FROM clause, do two things: ** (1) Authorized unreferenced tables ** (2) Generate code for all sub-queries |
︙ | ︙ | |||
5329 5330 5331 5332 5333 5334 5335 | ** an exact limit. */ pParse->nHeight += sqlite3SelectExprHeight(p); /* Make copies of constant WHERE-clause terms in the outer query down ** inside the subquery. This can help the subquery to run more efficiently. */ | < | | > | 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 | ** an exact limit. */ pParse->nHeight += sqlite3SelectExprHeight(p); /* 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( 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")); sqlite3TreeViewSelect(0, p, 0); } #endif |
︙ | ︙ | |||
5636 5637 5638 5639 5640 5641 5642 | /* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in ** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the ** SELECT statement. */ memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; sNC.pSrcList = pTabList; | | > > > | | 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 | /* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in ** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the ** SELECT statement. */ memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; sNC.pSrcList = pTabList; sNC.uNC.pAggInfo = &sAggInfo; VVA_ONLY( sNC.ncFlags = NC_UAggInfo; ) sAggInfo.mnReg = pParse->nMem+1; sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr : 0; sAggInfo.pGroupBy = pGroupBy; sqlite3ExprAnalyzeAggList(&sNC, pEList); sqlite3ExprAnalyzeAggList(&sNC, sSort.pOrderBy); if( pHaving ){ if( pGroupBy ){ assert( pWhere==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); |
︙ | ︙ | |||
6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 | /* If there is an ORDER BY clause, then we need to sort the results ** and send them to the callback one by one. */ if( sSort.pOrderBy ){ explainTempTable(pParse, sSort.nOBSat>0 ? "RIGHT PART OF ORDER BY":"ORDER BY"); generateSortTail(pParse, p, &sSort, pEList->nExpr, pDest); } /* Jump here to skip this query */ sqlite3VdbeResolveLabel(v, iEnd); /* The SELECT has been coded. If there is an error in the Parse structure, ** set the return code to 1. Otherwise 0. */ rc = (pParse->nErr>0); /* Control jumps to here if an error is encountered above, or upon ** successful coding of the SELECT. */ select_end: | > < | > > > > | 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 | /* If there is an ORDER BY clause, then we need to sort the results ** and send them to the callback one by one. */ 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); } /* Jump here to skip this query */ sqlite3VdbeResolveLabel(v, iEnd); /* The SELECT has been coded. If there is an error in the Parse structure, ** set the return code to 1. Otherwise 0. */ rc = (pParse->nErr>0); /* Control jumps to here if an error is encountered above, or upon ** successful coding of the SELECT. */ select_end: sqlite3ExprListDelete(db, pMinMaxOrderBy); sqlite3DbFree(db, sAggInfo.aCol); sqlite3DbFree(db, sAggInfo.aFunc); #if SELECTTRACE_ENABLED SELECTTRACE(0x1,pParse,p,("end processing\n")); if( pParse->iSelectId==0 && (sqlite3SelectTrace & 0x2000)!=0 ){ sqlite3TreeViewSelect(0, p, 0); } #endif explainSetInteger(pParse->iSelectId, iRestoreSelectId); return rc; } |
Changes to src/shell.c.in.
︙ | ︙ | |||
128 129 130 131 132 133 134 135 136 137 138 139 140 141 | #if defined(_WIN32) || defined(WIN32) # include <io.h> # include <fcntl.h> # define isatty(h) _isatty(h) # ifndef access # define access(f,m) _access((f),(m)) # endif # undef popen # define popen _popen # undef pclose # define pclose _pclose #else /* Make sure isatty() has a prototype. */ extern int isatty(int); | > > > | 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | #if defined(_WIN32) || defined(WIN32) # include <io.h> # include <fcntl.h> # define isatty(h) _isatty(h) # ifndef access # define access(f,m) _access((f),(m)) # endif # ifndef unlink # define unlink _unlink # endif # undef popen # define popen _popen # undef pclose # define pclose _pclose #else /* Make sure isatty() has a prototype. */ extern int isatty(int); |
︙ | ︙ | |||
428 429 430 431 432 433 434 435 436 437 438 439 440 441 | /* ** Render output like fprintf(). This should not be used on anything that ** includes string formatting (e.g. "%s"). */ #if !defined(raw_printf) # define raw_printf fprintf #endif /* ** Write I/O traces to the following stream. */ #ifdef SQLITE_ENABLE_IOTRACE static FILE *iotrace = 0; #endif | > > > > > > | 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 | /* ** Render output like fprintf(). This should not be used on anything that ** includes string formatting (e.g. "%s"). */ #if !defined(raw_printf) # 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. */ #ifdef SQLITE_ENABLE_IOTRACE static FILE *iotrace = 0; #endif |
︙ | ︙ | |||
998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 | typedef struct ExpertInfo ExpertInfo; struct ExpertInfo { sqlite3expert *pExpert; int bVerbose; }; /* ** State information about the database connection is contained in an ** instance of the following structure. */ typedef struct ShellState ShellState; struct ShellState { sqlite3 *db; /* The database */ u8 autoExplain; /* Automatically turn on .explain mode */ u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ 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() */ int outCount; /* Revert to stdout when reaching zero */ int cnt; /* Number of records displayed so far */ FILE *out; /* Write results here */ FILE *traceOut; /* Output for sqlite3_trace() */ int nErr; /* Number of errors seen */ int mode; /* An output mode setting */ int modePrior; /* Saved mode */ | > > > > > > > > > > > > > > > > > > | 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 | typedef struct ExpertInfo ExpertInfo; struct ExpertInfo { sqlite3expert *pExpert; int bVerbose; }; /* A single line in the EQP output */ typedef struct EQPGraphRow EQPGraphRow; struct EQPGraphRow { int iSelectId; /* The SelectID for this 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. */ typedef struct ShellState ShellState; struct ShellState { sqlite3 *db; /* The database */ u8 autoExplain; /* Automatically turn on .explain mode */ u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ 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 */ FILE *traceOut; /* Output for sqlite3_trace() */ int nErr; /* Number of errors seen */ int mode; /* An output mode setting */ int modePrior; /* Saved mode */ |
︙ | ︙ | |||
1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 | char *zFreeOnClose; /* Filename to free when closing */ const char *zVfs; /* Name of VFS to use */ sqlite3_stmt *pStmt; /* Current statement if any. */ FILE *pLog; /* Write log output here */ int *aiIndent; /* Array of indents used in MODE_Explain */ int nIndent; /* Size of array aiIndent[] */ int iIndent; /* Index of current op in aiIndent[] */ #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..." */ }; | > | 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 | char *zFreeOnClose; /* Filename to free when closing */ const char *zVfs; /* Name of VFS to use */ sqlite3_stmt *pStmt; /* Current statement if any. */ FILE *pLog; /* Write log output here */ 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..." */ }; |
︙ | ︙ | |||
1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 | #define MODE_Insert 5 /* Generate SQL "insert" statements */ #define MODE_Quote 6 /* Quote values as for SQL */ #define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */ #define MODE_Csv 8 /* Quote strings, numbers are plain */ #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 */ static const char *modeDescr[] = { "line", "column", "list", "semi", "html", "insert", "quote", "tcl", "csv", "explain", "ascii", "prettyprint", }; /* ** These are the column/row/line separators used by the various ** import/export modes. */ #define SEP_Column "|" | > > | 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 | #define MODE_Insert 5 /* Generate SQL "insert" statements */ #define MODE_Quote 6 /* Quote values as for SQL */ #define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */ #define MODE_Csv 8 /* Quote strings, numbers are plain */ #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", "column", "list", "semi", "html", "insert", "quote", "tcl", "csv", "explain", "ascii", "prettyprint", "eqp" }; /* ** These are the column/row/line separators used by the various ** import/export modes. */ #define SEP_Column "|" |
︙ | ︙ | |||
1662 1663 1664 1665 1666 1667 1668 | if( z[i]=='\n' ) return 1; if( IsSpace(z[i]) ) continue; if( z[i]=='-' && z[i+1]=='-' ) return 1; return 0; } return 1; } | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 | 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 iSelectId, const char *zText){ EQPGraphRow *pNew; int nText = strlen30(zText); pNew = sqlite3_malloc64( sizeof(*pNew) + nText ); if( pNew==0 ) shell_out_of_memory(); pNew->iSelectId = iSelectId; 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 iSelectId that occurs after ** pOld, or return the first such line if pOld is NULL */ static EQPGraphRow *eqp_next_row(ShellState *p, int iSelectId, EQPGraphRow *pOld){ EQPGraphRow *pRow = pOld ? pOld->pNext : p->sGraph.pRow; while( pRow && pRow->iSelectId!=iSelectId ) pRow = pRow->pNext; return pRow; } /* Render a single level of the graph shell having iSelectId. Called ** recursively to render sublevels. */ static void eqp_render_level(ShellState *p, int iSelectId){ EQPGraphRow *pRow, *pNext; int i; int n = strlen30(p->sGraph.zPrefix); char *z; for(pRow = eqp_next_row(p, iSelectId, 0); pRow; pRow = pNext){ pNext = eqp_next_row(p, iSelectId, pRow); z = pRow->zText; utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix, pNext ? "|--" : "`--", z); if( n<sizeof(p->sGraph.zPrefix)-7 && (z = strstr(z, " SUBQUER"))!=0 ){ memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4); if( strncmp(z, " SUBQUERY ", 9)==0 && (i = atoi(z+10))>iSelectId ){ eqp_render_level(p, i); }else if( strncmp(z, " SUBQUERIES ", 12)==0 ){ i = atoi(z+12); if( i>iSelectId ){ utf8_printf(p->out, "%s|--SUBQUERY %d\n", p->sGraph.zPrefix, i); memcpy(&p->sGraph.zPrefix[n+3],"| ",4); eqp_render_level(p, i); } z = strstr(z, " AND "); if( z && (i = atoi(z+5))>iSelectId ){ p->sGraph.zPrefix[n+3] = 0; utf8_printf(p->out, "%s`--SUBQUERY %d\n", p->sGraph.zPrefix, i); memcpy(&p->sGraph.zPrefix[n+3]," ",4); eqp_render_level(p, i); } } 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. */ static int shell_callback( void *pArg, |
︙ | ︙ | |||
2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 | for(i=0; i<nArg; i++){ if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator); utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue); } utf8_printf(p->out, "%s", p->rowSeparator); break; } } return 0; } /* ** This is the callback routine that the SQLite library ** invokes for each row of a query result. | > > > > | 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 | for(i=0; i<nArg; i++){ if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator); utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue); } utf8_printf(p->out, "%s", p->rowSeparator); break; } case MODE_EQP: { eqp_append(p, atoi(azArg[0]), azArg[3]); break; } } return 0; } /* ** This is the callback routine that the SQLite library ** invokes for each row of a query result. |
︙ | ︙ | |||
2111 2112 2113 2114 2115 2116 2117 | p->zDestTable = 0; } if( zName==0 ) return; cQuote = quoteChar(zName); n = strlen30(zName); if( cQuote ) n += n+2; z = p->zDestTable = malloc( n+1 ); | | < < < | 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 | p->zDestTable = 0; } if( zName==0 ) return; cQuote = quoteChar(zName); n = strlen30(zName); if( cQuote ) n += n+2; z = p->zDestTable = malloc( n+1 ); if( z==0 ) shell_out_of_memory(); n = 0; if( cQuote ) z[n++] = cQuote; for(i=0; zName[i]; i++){ z[n++] = zName[i]; if( zName[i]==cQuote ) z[n++] = cQuote; } if( cQuote ) z[n++] = cQuote; |
︙ | ︙ | |||
2854 2855 2856 2857 2858 2859 2860 | 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 ){ | | | | | > | 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 | 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 ){ const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3); int iSelectId = sqlite3_column_int(pExplain, 0); if( zEQPLine[0]=='-' ) eqp_render(pArg); eqp_append(pArg, iSelectId, zEQPLine); } eqp_render(pArg); } sqlite3_finalize(pExplain); sqlite3_free(zEQP); 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); |
︙ | ︙ | |||
2886 2887 2888 2889 2890 2891 2892 | sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); } restore_debug_trace_modes(); } if( pArg ){ pArg->cMode = pArg->mode; | | | | | | > > > > > > | 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 | sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); } restore_debug_trace_modes(); } if( pArg ){ pArg->cMode = pArg->mode; 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 ** data required to add indents to the output.*/ if( pArg->cMode==MODE_Explain ){ explain_data_prepare(pArg, pStmt); } } exec_prepared_stmt(pArg, pStmt); explain_data_delete(pArg); eqp_render(pArg); /* print usage stats if stats on */ if( pArg && pArg->statsOn ){ display_stats(db, pArg, 0); } /* print loop-counters if required */ |
︙ | ︙ | |||
2979 2980 2981 2982 2983 2984 2985 | rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); if( rc ) return 0; while( sqlite3_step(pStmt)==SQLITE_ROW ){ if( nCol>=nAlloc-2 ){ nAlloc = nAlloc*2 + nCol + 10; azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0])); | | < < < | 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 | rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); if( rc ) return 0; while( sqlite3_step(pStmt)==SQLITE_ROW ){ if( nCol>=nAlloc-2 ){ nAlloc = nAlloc*2 + nCol + 10; azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0])); if( azCol==0 ) shell_out_of_memory(); } azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1)); if( sqlite3_column_int(pStmt, 5) ){ nPK++; if( nPK==1 && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2), "INTEGER")==0 |
︙ | ︙ | |||
3477 3478 3479 3480 3481 3482 3483 | /* ** 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){ if( p->db==0 ){ | < | 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 | /* ** 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){ if( p->db==0 ){ if( p->openMode==SHELL_OPEN_UNSPEC && access(p->zDbFilename,0)==0 ){ p->openMode = (u8)deduceDatabaseType(p->zDbFilename, 0); } switch( p->openMode ){ case SHELL_OPEN_APPENDVFS: { sqlite3_open_v2(p->zDbFilename, &p->db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, "apndvfs"); |
︙ | ︙ | |||
3726 3727 3728 3729 3730 3731 3732 | if( f==0 ){ utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile); } } return f; } | < | 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 | if( f==0 ){ utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile); } } return f; } #if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) /* ** A routine for handling output from sqlite3_trace(). */ static int sql_trace_callback( unsigned mType, void *pArg, |
︙ | ︙ | |||
3748 3749 3750 3751 3752 3753 3754 | const char *z = (const char*)pX; int i = strlen30(z); while( i>0 && z[i-1]==';' ){ i--; } utf8_printf(f, "%.*s;\n", i, z); } return 0; } | < | 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 | const char *z = (const char*)pX; int i = strlen30(z); while( i>0 && z[i-1]==';' ){ i--; } utf8_printf(f, "%.*s;\n", i, z); } return 0; } #endif /* ** A no-op routine that runs with the ".breakpoint" doc-command. This is ** a useful spot to set a debugger breakpoint. */ static void test_breakpoint(void){ |
︙ | ︙ | |||
3782 3783 3784 3785 3786 3787 3788 | }; /* Append a single byte to z[] */ static void import_append_char(ImportCtx *p, int c){ if( p->n+1>=p->nAlloc ){ p->nAlloc += p->nAlloc + 100; p->z = sqlite3_realloc64(p->z, p->nAlloc); | | < < < | 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 | }; /* Append a single byte to z[] */ static void import_append_char(ImportCtx *p, int c){ if( p->n+1>=p->nAlloc ){ p->nAlloc += p->nAlloc + 100; p->z = sqlite3_realloc64(p->z, p->nAlloc); if( p->z==0 ) shell_out_of_memory(); } p->z[p->n++] = (char)c; } /* Read a single field of CSV text. Compatible with rfc4180 and extended ** with the option of having a separator other than ",". ** |
︙ | ︙ | |||
3946 3947 3948 3949 3950 3951 3952 | utf8_printf(stderr, "Error %d: %s on [%s]\n", sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), zQuery); goto end_data_xfer; } n = sqlite3_column_count(pQuery); zInsert = sqlite3_malloc64(200 + nTable + n*3); | | < < < | 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 | utf8_printf(stderr, "Error %d: %s on [%s]\n", sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), zQuery); goto end_data_xfer; } n = sqlite3_column_count(pQuery); zInsert = sqlite3_malloc64(200 + nTable + n*3); if( zInsert==0 ) shell_out_of_memory(); sqlite3_snprintf(200+nTable,zInsert, "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable); i = strlen30(zInsert); for(j=1; j<n; j++){ memcpy(zInsert+i, ",?", 2); i += 2; } |
︙ | ︙ | |||
4290 4291 4292 4293 4294 4295 4296 | */ static int shellDatabaseError(sqlite3 *db){ const char *zErr = sqlite3_errmsg(db); utf8_printf(stderr, "Error: %s\n", zErr); return 1; } | < < < < < < < < | 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 | */ static int shellDatabaseError(sqlite3 *db){ const char *zErr = sqlite3_errmsg(db); utf8_printf(stderr, "Error: %s\n", zErr); 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. ** ** Globbing rules: ** ** '*' Matches any sequence of zero or more characters. |
︙ | ︙ | |||
5332 5333 5334 5335 5336 5337 5338 | 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++){ | | | | | 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 | 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 ){ |
︙ | ︙ | |||
5991 5992 5993 5994 5995 5996 5997 | utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile); return 1; } sCtx.cColSep = p->colSeparator[0]; sCtx.cRowSep = p->rowSeparator[0]; zSql = sqlite3_mprintf("SELECT * FROM %s", zTable); if( zSql==0 ){ | < < > | 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 | utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile); return 1; } sCtx.cColSep = p->colSeparator[0]; sCtx.cRowSep = p->rowSeparator[0]; zSql = sqlite3_mprintf("SELECT * FROM %s", zTable); if( zSql==0 ){ xCloser(sCtx.in); shell_out_of_memory(); } nByte = strlen30(zSql); rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */ if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){ char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable); char cSep = '('; |
︙ | ︙ | |||
6038 6039 6040 6041 6042 6043 6044 | } nCol = sqlite3_column_count(pStmt); sqlite3_finalize(pStmt); pStmt = 0; if( nCol==0 ) return 0; /* no columns, no error */ zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 ); if( zSql==0 ){ | < < > | 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 | } nCol = sqlite3_column_count(pStmt); sqlite3_finalize(pStmt); pStmt = 0; if( nCol==0 ) return 0; /* no columns, no error */ zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 ); if( zSql==0 ){ xCloser(sCtx.in); shell_out_of_memory(); } sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable); j = strlen30(zSql); for(i=1; i<nCol; i++){ zSql[j++] = ','; zSql[j++] = '?'; } |
︙ | ︙ | |||
6116 6117 6118 6119 6120 6121 6122 | #ifndef SQLITE_UNTESTABLE if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){ char *zSql; char *zCollist = 0; sqlite3_stmt *pStmt; int tnum = 0; int i; | | | > > > > > | 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 | #ifndef SQLITE_UNTESTABLE if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){ char *zSql; char *zCollist = 0; sqlite3_stmt *pStmt; int tnum = 0; int i; 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); sqlite3_free(zSql); if( sqlite3_step(pStmt)==SQLITE_ROW ){ tnum = sqlite3_column_int(pStmt, 0); } |
︙ | ︙ | |||
6614 6615 6616 6617 6618 6619 6620 | }else{ raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n"); rc = 1; goto meta_command_exit; } } if( zName!=0 ){ | | | | 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 | }else{ raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n"); rc = 1; goto meta_command_exit; } } 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] = sqlite3_mprintf( "CREATE TABLE %s (\n" " type text,\n" " name text,\n" " tbl_name text,\n" " rootpage integer,\n" |
︙ | ︙ | |||
6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 | " 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( zName ){ char *zQarg = sqlite3_mprintf("%Q", zName); if( strchr(zName, '.') ){ appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0); }else{ appendText(&sSelect, "lower(tbl_name)", 0); } | > > > | > | > | 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 | " 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( 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, 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); if( bDebug ){ utf8_printf(p->out, "SQL: %s;\n", sSelect.z); |
︙ | ︙ | |||
7096 7097 7098 7099 7100 7101 7102 | }else if( zLike ){ raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n"); rc = 1; goto meta_command_exit; }else{ zLike = z; bSeparate = 1; | | | 7221 7222 7223 7224 7225 7226 7227 7228 7229 7230 7231 7232 7233 7234 7235 | }else if( zLike ){ raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n"); rc = 1; goto meta_command_exit; }else{ zLike = z; bSeparate = 1; if( sqlite3_strlike("sqlite\\_%", zLike, '\\')==0 ) bSchema = 1; } } if( bSchema ){ zSql = "SELECT lower(name) FROM sqlite_master" " WHERE type='table' AND coalesce(rootpage,0)>1" " UNION ALL SELECT 'sqlite_master'" " ORDER BY 1 collate nocase"; |
︙ | ︙ | |||
7301 7302 7303 7304 7305 7306 7307 | sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC); } while( sqlite3_step(pStmt)==SQLITE_ROW ){ if( nRow>=nAlloc ){ char **azNew; int n2 = nAlloc*2 + 10; azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2); | | < < < | < < < | 7426 7427 7428 7429 7430 7431 7432 7433 7434 7435 7436 7437 7438 7439 7440 7441 7442 7443 7444 7445 | sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC); } while( sqlite3_step(pStmt)==SQLITE_ROW ){ if( nRow>=nAlloc ){ char **azNew; int n2 = nAlloc*2 + 10; azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2); 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] ) shell_out_of_memory(); nRow++; } if( sqlite3_finalize(pStmt)!=SQLITE_OK ){ rc = shellDatabaseError(p->db); } /* Pretty-print the contents of array azResult[] to the output */ |
︙ | ︙ | |||
7883 7884 7885 7886 7887 7888 7889 | if( line_is_command_terminator(zLine) && line_is_complete(zSql, nSql) ){ memcpy(zLine,";",2); } nLine = strlen30(zLine); if( nSql+nLine+2>=nAlloc ){ nAlloc = nSql+nLine+100; zSql = realloc(zSql, nAlloc); | | < < < | 8002 8003 8004 8005 8006 8007 8008 8009 8010 8011 8012 8013 8014 8015 8016 | if( line_is_command_terminator(zLine) && line_is_complete(zSql, nSql) ){ memcpy(zLine,";",2); } nLine = strlen30(zLine); if( nSql+nLine+2>=nAlloc ){ nAlloc = nSql+nLine+100; zSql = realloc(zSql, nAlloc); if( zSql==0 ) shell_out_of_memory(); } nSqlPrior = nSql; if( nSql==0 ){ int i; for(i=0; zLine[i] && IsSpace(zLine[i]); i++){} assert( nAlloc>0 && zSql!=0 ); memcpy(zSql, zLine+i, nLine+1-i); |
︙ | ︙ | |||
8015 8016 8017 8018 8019 8020 8021 | if (sqliterc == NULL) { home_dir = find_home_dir(0); if( home_dir==0 ){ raw_printf(stderr, "-- warning: cannot find home directory;" " cannot read ~/.sqliterc\n"); return; } | < | 8131 8132 8133 8134 8135 8136 8137 8138 8139 8140 8141 8142 8143 8144 | if (sqliterc == NULL) { home_dir = find_home_dir(0); if( home_dir==0 ){ raw_printf(stderr, "-- warning: cannot find home directory;" " cannot read ~/.sqliterc\n"); return; } zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir); sqliterc = zBuf; } in = fopen(sqliterc,"rb"); if( in ){ if( stdin_is_interactive ){ utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc); |
︙ | ︙ | |||
8066 8067 8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 | #endif " -newline SEP set output row separator. Default: '\\n'\n" " -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" " -readonly open the database read-only\n" " -separator SEP set output column separator. Default: '|'\n" " -stats print memory stats before each finalize\n" " -version show SQLite version\n" " -vfs NAME use NAME as the default VFS\n" #ifdef SQLITE_ENABLE_VFSTRACE " -vfstrace enable tracing of all VFS calls\n" #endif #ifdef SQLITE_HAVE_ZLIB | > > > | 8181 8182 8183 8184 8185 8186 8187 8188 8189 8190 8191 8192 8193 8194 8195 8196 8197 | #endif " -newline SEP set output row separator. Default: '\\n'\n" " -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" " -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" #ifdef SQLITE_ENABLE_VFSTRACE " -vfstrace enable tracing of all VFS calls\n" #endif #ifdef SQLITE_HAVE_ZLIB |
︙ | ︙ | |||
8088 8089 8090 8091 8092 8093 8094 8095 8096 8097 8098 8099 8100 8101 8102 8103 8104 8105 8106 8107 8108 8109 8110 8111 8112 8113 | if( showDetail ){ utf8_printf(stderr, "OPTIONS include:\n%s", zOptions); }else{ raw_printf(stderr, "Use the -help option for additional information\n"); } exit(1); } /* ** Initialize the state information in data */ static void main_init(ShellState *data) { memset(data, 0, sizeof(*data)); data->normalMode = data->cMode = data->mode = MODE_List; data->autoExplain = 1; memcpy(data->colSeparator,SEP_Column, 2); memcpy(data->rowSeparator,SEP_Row, 2); data->showHeader = 0; data->shellFlgs = SHFLG_Lookaside; sqlite3_config(SQLITE_CONFIG_URI, 1); sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data); sqlite3_config(SQLITE_CONFIG_MULTITHREAD); sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> "); sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> "); } | > > > > > > > > > > > > | 8206 8207 8208 8209 8210 8211 8212 8213 8214 8215 8216 8217 8218 8219 8220 8221 8222 8223 8224 8225 8226 8227 8228 8229 8230 8231 8232 8233 8234 8235 8236 8237 8238 8239 8240 8241 8242 8243 | if( showDetail ){ utf8_printf(stderr, "OPTIONS include:\n%s", zOptions); }else{ raw_printf(stderr, "Use the -help option for additional information\n"); } exit(1); } /* ** 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 configuration SQLite after" " initialization.\n"); } } /* ** Initialize the state information in data */ static void main_init(ShellState *data) { memset(data, 0, sizeof(*data)); data->normalMode = data->cMode = data->mode = MODE_List; data->autoExplain = 1; memcpy(data->colSeparator,SEP_Column, 2); memcpy(data->rowSeparator,SEP_Row, 2); data->showHeader = 0; data->shellFlgs = SHFLG_Lookaside; verify_uninitialized(); sqlite3_config(SQLITE_CONFIG_URI, 1); sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data); sqlite3_config(SQLITE_CONFIG_MULTITHREAD); sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> "); sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> "); } |
︙ | ︙ | |||
8163 8164 8165 8166 8167 8168 8169 8170 8171 8172 8173 8174 8175 8176 | const char *zInitFile = 0; int i; int rc = 0; int warnInmemoryDb = 0; int readStdin = 1; int nCmd = 0; char **azCmd = 0; setBinaryMode(stdin, 0); setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */ stdin_is_interactive = isatty(0); stdout_is_console = isatty(1); #if USE_SYSTEM_SQLITE+0!=1 | > | 8293 8294 8295 8296 8297 8298 8299 8300 8301 8302 8303 8304 8305 8306 8307 | const char *zInitFile = 0; int i; int rc = 0; int warnInmemoryDb = 0; int readStdin = 1; int nCmd = 0; char **azCmd = 0; const char *zVfs = 0; /* Value of -vfs command-line option */ setBinaryMode(stdin, 0); setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */ stdin_is_interactive = isatty(0); stdout_is_console = isatty(1); #if USE_SYSTEM_SQLITE+0!=1 |
︙ | ︙ | |||
8187 8188 8189 8190 8191 8192 8193 | ** 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 = malloc(sizeof(argv[0])*argc); | | < < < | < < < | < < < | 8318 8319 8320 8321 8322 8323 8324 8325 8326 8327 8328 8329 8330 8331 8332 8333 8334 8335 8336 8337 8338 8339 | ** 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 = malloc(sizeof(argv[0])*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 ) 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); sqlite3_free(z); } sqlite3_shutdown(); #endif assert( argc>=1 && argv && argv[0] ); |
︙ | ︙ | |||
8239 8240 8241 8242 8243 8244 8245 8246 8247 8248 8249 8250 8251 8252 8253 8254 8255 8256 8257 | #endif /* Do an initial pass through the command-line argument to locate ** the name of the database file, the name of the initialization file, ** the size of the alternative malloc heap, ** and the first command to execute. */ for(i=1; i<argc; i++){ char *z; z = argv[i]; if( z[0]!='-' ){ if( data.zDbFilename==0 ){ data.zDbFilename = z; }else{ /* Excesss arguments are interpreted as SQL (or dot-commands) and ** mean that nothing is read from stdin */ readStdin = 0; nCmd++; azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd); | > | < < < | 8361 8362 8363 8364 8365 8366 8367 8368 8369 8370 8371 8372 8373 8374 8375 8376 8377 8378 8379 8380 8381 8382 8383 8384 8385 8386 8387 8388 | #endif /* Do an initial pass through the command-line argument to locate ** the name of the database file, the name of the initialization file, ** the size of the alternative malloc heap, ** and the first command to execute. */ verify_uninitialized(); for(i=1; i<argc; i++){ char *z; z = argv[i]; if( z[0]!='-' ){ if( data.zDbFilename==0 ){ data.zDbFilename = z; }else{ /* Excesss arguments are interpreted as SQL (or dot-commands) and ** mean that nothing is read from stdin */ readStdin = 0; nCmd++; azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd); if( azCmd==0 ) shell_out_of_memory(); azCmd[nCmd-1] = z; } } if( z[1]=='-' ) z++; if( strcmp(z,"-separator")==0 || strcmp(z,"-nullvalue")==0 || strcmp(z,"-newline")==0 |
︙ | ︙ | |||
8321 8322 8323 8324 8325 8326 8327 | }else if( strcmp(z,"-multiplex")==0 ){ extern int sqlite3_multiple_initialize(const char*,int); sqlite3_multiplex_initialize(0, 1); #endif }else if( strcmp(z,"-mmap")==0 ){ sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i)); sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz); | > | | > | < | | < < > > > > > > > > > > > > > > > > | 8441 8442 8443 8444 8445 8446 8447 8448 8449 8450 8451 8452 8453 8454 8455 8456 8457 8458 8459 8460 8461 8462 8463 8464 8465 8466 8467 8468 8469 8470 8471 8472 8473 8474 8475 8476 8477 8478 8479 8480 8481 8482 8483 8484 8485 8486 8487 8488 8489 8490 8491 8492 8493 | }else if( strcmp(z,"-multiplex")==0 ){ extern int sqlite3_multiple_initialize(const char*,int); sqlite3_multiplex_initialize(0, 1); #endif }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 ){ 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; }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(); /* 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(); 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:"; warnInmemoryDb = argc==1; #else utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0); return 1; |
︙ | ︙ | |||
8402 8403 8404 8405 8406 8407 8408 8409 8410 8411 8412 8413 8414 8415 | 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; }else if( strcmp(z,"-ascii")==0 ){ data.mode = MODE_Ascii; sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Unit); sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Record); }else if( strcmp(z,"-separator")==0 ){ | > > | 8537 8538 8539 8540 8541 8542 8543 8544 8545 8546 8547 8548 8549 8550 8551 8552 | 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; }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, SEP_Unit); sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Record); }else if( strcmp(z,"-separator")==0 ){ |
︙ | ︙ | |||
8455 8456 8457 8458 8459 8460 8461 8462 8463 8464 8465 8466 8467 8468 | i++; }else if( strcmp(z,"-pagecache")==0 ){ i+=2; }else if( strcmp(z,"-lookaside")==0 ){ i+=2; }else if( strcmp(z,"-mmap")==0 ){ i++; }else if( strcmp(z,"-vfs")==0 ){ i++; #ifdef SQLITE_ENABLE_VFSTRACE }else if( strcmp(z,"-vfstrace")==0 ){ i++; #endif #ifdef SQLITE_ENABLE_MULTIPLEX | > > > > | 8592 8593 8594 8595 8596 8597 8598 8599 8600 8601 8602 8603 8604 8605 8606 8607 8608 8609 | i++; }else if( strcmp(z,"-pagecache")==0 ){ i+=2; }else if( strcmp(z,"-lookaside")==0 ){ 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 }else if( strcmp(z,"-vfstrace")==0 ){ i++; #endif #ifdef SQLITE_ENABLE_MULTIPLEX |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 | ** 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]. ** </ul> */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 #define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 #define SQLITE_FCNTL_LAST_ERRNO 4 #define SQLITE_FCNTL_SIZE_HINT 5 | > > > > > > | 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 | ** 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. ** </ul> */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 #define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 #define SQLITE_FCNTL_LAST_ERRNO 4 #define SQLITE_FCNTL_SIZE_HINT 5 |
︙ | ︙ | |||
1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 | #define SQLITE_FCNTL_VFS_POINTER 27 #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 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO | > | 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 | #define SQLITE_FCNTL_VFS_POINTER 27 #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 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
︙ | ︙ | |||
1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 | ** Or if the threshold is -1, statement journals are always held ** exclusively in memory. ** Since many statement journals never become large, setting the spill ** threshold to a value such as 64KiB can greatly reduce the amount of ** I/O required to support statement rollback. ** The default value for this setting is controlled by the ** [SQLITE_STMTJRNL_SPILL] compile-time option. ** </dl> */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ #define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ #define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */ | > > > > > > > > > > > > > > > > | 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 | ** Or if the threshold is -1, statement journals are always held ** exclusively in memory. ** Since many statement journals never become large, setting the spill ** threshold to a value such as 64KiB can greatly reduce the amount of ** 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 */ #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ #define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ #define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */ |
︙ | ︙ | |||
1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 | #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ #define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ #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 */ /* ** CAPI3REF: Database Connection Configuration Options ** ** These constants are the available integer configuration options that ** can be passed as the second argument to the [sqlite3_db_config()] interface. ** | > | 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 | #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ #define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ #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 ** ** These constants are the available integer configuration options that ** can be passed as the second argument to the [sqlite3_db_config()] interface. ** |
︙ | ︙ | |||
8832 8833 8834 8835 8836 8837 8838 | */ #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 | | | 8856 8857 8858 8859 8860 8861 8862 8863 8864 8865 8866 8867 8868 8869 8870 | */ #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. ** |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
633 634 635 636 637 638 639 640 641 642 643 644 645 646 | ** The default value of "20" was choosen to minimize the run-time of the ** speedtest1 test program with options: --shrink-memory --reprepare */ #ifndef SQLITE_DEFAULT_PCACHE_INITSZ # define SQLITE_DEFAULT_PCACHE_INITSZ 20 #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 | > > > > > > > | 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 | ** The default value of "20" was choosen to minimize the run-time of the ** speedtest1 test program with options: --shrink-memory --reprepare */ #ifndef SQLITE_DEFAULT_PCACHE_INITSZ # define SQLITE_DEFAULT_PCACHE_INITSZ 20 #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 |
︙ | ︙ | |||
957 958 959 960 961 962 963 | ** The sqlite.busyHandler member of the sqlite struct contains the busy ** callback for the database handle. Each pager opened via the sqlite ** handle is passed a pointer to sqlite.busyHandler. The busy-handler ** callback is currently invoked only from within pager.c. */ typedef struct BusyHandler BusyHandler; struct BusyHandler { | | | | > | 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 | ** The sqlite.busyHandler member of the sqlite struct contains the busy ** callback for the database handle. Each pager opened via the sqlite ** handle is passed a pointer to sqlite.busyHandler. The busy-handler ** callback is currently invoked only from within pager.c. */ typedef struct BusyHandler BusyHandler; struct BusyHandler { 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 */ }; /* ** Name of the master database table. The master database table ** is a special table that holds the names and attributes of all ** user tables and indices. */ |
︙ | ︙ | |||
1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 | typedef struct TableLock TableLock; typedef struct Token Token; typedef struct TreeView TreeView; typedef struct Trigger Trigger; typedef struct TriggerPrg TriggerPrg; typedef struct TriggerStep TriggerStep; typedef struct UnpackedRecord UnpackedRecord; typedef struct VTable VTable; typedef struct VtabCtx VtabCtx; typedef struct Walker Walker; typedef struct WhereInfo WhereInfo; typedef struct With With; /* A VList object records a mapping between parameters/variables/wildcards | > | 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 | typedef struct TableLock TableLock; typedef struct Token Token; typedef struct TreeView TreeView; typedef struct Trigger Trigger; 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 With With; /* A VList object records a mapping between parameters/variables/wildcards |
︙ | ︙ | |||
1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 | #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 */ /* TH3 expects the Stat34 ^^^^^^ value to be 0x0800. Don't change it */ #define SQLITE_PushDown 0x1000 /* The push-down optimization */ #define SQLITE_AllOpts 0xffff /* All optimizations */ /* ** Macros for testing whether or not optimizations are enabled or disabled. */ #define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0) #define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0) | > | 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 | #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 */ /* 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_AllOpts 0xffff /* All optimizations */ /* ** Macros for testing whether or not optimizations are enabled or disabled. */ #define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0) #define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0) |
︙ | ︙ | |||
1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 | /* Allowed values for Column.colFlags: */ #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" */ /* ** A "Collating Sequence" is defined by an instance of the following ** structure. Conceptually, a collating sequence consists of a name and ** a comparison routine that defines the order of that sequence. ** ** If CollSeq.xCmp is NULL, it means that the | > | 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 | /* Allowed values for Column.colFlags: */ #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 ** structure. Conceptually, a collating sequence consists of a name and ** a comparison routine that defines the order of that sequence. ** ** If CollSeq.xCmp is NULL, it means that the |
︙ | ︙ | |||
2041 2042 2043 2044 2045 2046 2047 | */ #define OE_None 0 /* There is no constraint to check */ #define OE_Rollback 1 /* Fail the operation and rollback the transaction */ #define OE_Abort 2 /* Back out changes but do no rollback transaction */ #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 */ | | | | | | < | | 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 | */ #define OE_None 0 /* There is no constraint to check */ #define OE_Rollback 1 /* Fail the operation and rollback the transaction */ #define OE_Abort 2 /* Back out changes but do no rollback transaction */ #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 */ /* ** An instance of the following structure is passed as the first ** argument to sqlite3VdbeKeyCompare and is used to control the ** comparison of the two index keys. ** |
︙ | ︙ | |||
2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 | Expr *pExpr; /* The parse tree for this expression */ char *zName; /* Token associated with this expression */ char *zSpan; /* Original text of the expression */ u8 sortOrder; /* 1 for DESC or 0 for ASC */ 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 */ union { struct { u16 iOrderByCol; /* For ORDER BY, column number in result set */ u16 iAlias; /* Index into Parse.aAlias[] for zName */ } x; int iConstExprReg; /* Register in which Expr value is cached */ } u; | > | 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 | Expr *pExpr; /* The parse tree for this expression */ char *zName; /* Token associated with this expression */ char *zSpan; /* Original text of the expression */ u8 sortOrder; /* 1 for DESC or 0 for ASC */ 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 */ u16 iAlias; /* Index into Parse.aAlias[] for zName */ } x; int iConstExprReg; /* Register in which Expr value is cached */ } u; |
︙ | ︙ | |||
2677 2678 2679 2680 2681 2682 2683 | ** NameContext in the parent query. Thus the process of scanning the ** NameContext list corresponds to searching through successively outer ** subqueries looking for a match. */ struct NameContext { Parse *pParse; /* The parser */ SrcList *pSrcList; /* One or more tables used to resolve names */ | > | | > > | 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 | ** NameContext in the parent query. Thus the process of scanning the ** NameContext list corresponds to searching through successively outer ** subqueries looking for a match. */ struct NameContext { Parse *pParse; /* The parser */ SrcList *pSrcList; /* One or more tables used to resolve names */ 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 */ }; /* |
︙ | ︙ | |||
2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 | #define NC_AllowAgg 0x0001 /* Aggregate functions are allowed here */ #define NC_PartIdx 0x0002 /* True if resolving a partial index WHERE */ #define NC_IsCheck 0x0004 /* True if resolving names in a CHECK constraint */ #define NC_InAggFunc 0x0008 /* True if analyzing arguments to an agg func */ #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_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */ #define NC_Complex 0x2000 /* True if a function or subquery seen */ /* ** 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 | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 | #define NC_AllowAgg 0x0001 /* Aggregate functions are allowed here */ #define NC_PartIdx 0x0002 /* True if resolving a partial index WHERE */ #define NC_IsCheck 0x0004 /* True if resolving names in a CHECK constraint */ #define NC_InAggFunc 0x0008 /* True if analyzing arguments to an agg func */ #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 */ /* ** 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 |
︙ | ︙ | |||
2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 | ExprList *pEList; /* The fields of the result */ u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */ 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 int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */ SrcList *pSrc; /* The FROM clause */ Expr *pWhere; /* The WHERE clause */ ExprList *pGroupBy; /* The GROUP BY clause */ Expr *pHaving; /* The HAVING clause */ ExprList *pOrderBy; /* The ORDER BY clause */ | > | 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 | ExprList *pEList; /* The fields of the result */ u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */ 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 */ u32 iSelectId; /* EXPLAIN QUERY PLAN select ID */ #endif int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */ SrcList *pSrc; /* The FROM clause */ Expr *pWhere; /* The WHERE clause */ ExprList *pGroupBy; /* The GROUP BY clause */ Expr *pHaving; /* The HAVING clause */ ExprList *pOrderBy; /* The ORDER BY clause */ |
︙ | ︙ | |||
3202 3203 3204 3205 3206 3207 3208 | struct TriggerStep { u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */ u8 orconf; /* OE_Rollback etc. */ Trigger *pTrig; /* The trigger that this step is a part of */ 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 */ | | > | 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 | struct TriggerStep { u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */ u8 orconf; /* OE_Rollback etc. */ Trigger *pTrig; /* The trigger that this step is a part of */ 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 */ 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 */ }; /* ** The following structure contains information used by the sqliteFix... |
︙ | ︙ | |||
3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 | void *pVdbeBranchArg; /* 1st argument */ #endif #ifndef SQLITE_UNTESTABLE int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */ #endif int bLocaltimeFault; /* True to fail localtime() calls */ int iOnceResetThreshold; /* When to reset OP_Once counters */ }; /* ** This macro is used inside of assert() statements to indicate that ** the assert is only valid on a well-formed database. Instead of: ** ** assert( X ); | > | 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 | void *pVdbeBranchArg; /* 1st argument */ #endif #ifndef SQLITE_UNTESTABLE int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */ #endif int bLocaltimeFault; /* True to fail localtime() calls */ int iOnceResetThreshold; /* When to reset OP_Once counters */ u32 szSorterRef; /* Min size in bytes to use sorter-refs */ }; /* ** This macro is used inside of assert() statements to indicate that ** the assert is only valid on a well-formed database. Instead of: ** ** assert( X ); |
︙ | ︙ | |||
3354 3355 3356 3357 3358 3359 3360 | int n; /* A counter */ int iCur; /* A cursor number */ SrcList *pSrcList; /* FROM clause */ struct SrcCount *pSrcCount; /* Counting column references */ struct CCurHint *pCCurHint; /* Used by codeCursorHint() */ int *aiCol; /* array of column indexes */ struct IdxCover *pIdxCover; /* Check for index coverage */ | | | | 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 | int n; /* A counter */ int iCur; /* A cursor number */ SrcList *pSrcList; /* FROM clause */ struct SrcCount *pSrcCount; /* Counting column references */ struct CCurHint *pCCurHint; /* Used by codeCursorHint() */ int *aiCol; /* array of column indexes */ struct IdxCover *pIdxCover; /* Check for index coverage */ struct IdxExprTrans *pIdxTrans; /* Convert idxed expr to column */ ExprList *pGroupBy; /* GROUP BY clause */ Select *pSelect; /* HAVING to WHERE clause ctx */ } u; }; /* Forward declarations */ int sqlite3WalkExpr(Walker*, Expr*); int sqlite3WalkExprList(Walker*, ExprList*); int sqlite3WalkSelect(Walker*, Select*); |
︙ | ︙ | |||
3735 3736 3737 3738 3739 3740 3741 | #ifndef SQLITE_OMIT_AUTOINCREMENT void sqlite3AutoincrementBegin(Parse *pParse); void sqlite3AutoincrementEnd(Parse *pParse); #else # define sqlite3AutoincrementBegin(X) # define sqlite3AutoincrementEnd(X) #endif | | | 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 | #ifndef SQLITE_OMIT_AUTOINCREMENT void sqlite3AutoincrementBegin(Parse *pParse); void sqlite3AutoincrementEnd(Parse *pParse); #else # define sqlite3AutoincrementBegin(X) # define sqlite3AutoincrementEnd(X) #endif void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int, Upsert*); void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*); IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*); int sqlite3IdListIndex(IdList*,const char*); SrcList *sqlite3SrcListEnlarge(sqlite3*, SrcList*, int, int); SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*); SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*, Token*, Select*, Expr*, IdList*); |
︙ | ︙ | |||
3765 3766 3767 3768 3769 3770 3771 | Table *sqlite3SrcListLookup(Parse*, SrcList*); int sqlite3IsReadOnly(Parse*, Table*, int); void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*); #endif void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*); | | > | 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 | Table *sqlite3SrcListLookup(Parse*, SrcList*); int sqlite3IsReadOnly(Parse*, Table*, int); void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*); #endif void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*); void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*, Upsert*); WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int); void sqlite3WhereEnd(WhereInfo*); LogEst sqlite3WhereOutputRowCount(WhereInfo*); int sqlite3WhereIsDistinct(WhereInfo*); int sqlite3WhereIsOrdered(WhereInfo*); int sqlite3WhereOrderedInnerLoop(WhereInfo*); int sqlite3WhereIsSorted(WhereInfo*); |
︙ | ︙ | |||
3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 | void sqlite3Vacuum(Parse*,Token*); int sqlite3RunVacuum(char**, sqlite3*, int); char *sqlite3NameFromToken(sqlite3*, Token*); int sqlite3ExprCompare(Parse*,Expr*, Expr*, int); int sqlite3ExprCompareSkip(Expr*, Expr*, int); int sqlite3ExprListCompare(ExprList*, ExprList*, int); int sqlite3ExprImpliesExpr(Parse*,Expr*, Expr*, int); void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx); int sqlite3FunctionUsesThisSrc(Expr*, SrcList*); Vdbe *sqlite3GetVdbe(Parse*); #ifndef SQLITE_UNTESTABLE void sqlite3PrngSaveState(void); | > | 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 | void sqlite3Vacuum(Parse*,Token*); int sqlite3RunVacuum(char**, sqlite3*, int); char *sqlite3NameFromToken(sqlite3*, Token*); int sqlite3ExprCompare(Parse*,Expr*, Expr*, int); int sqlite3ExprCompareSkip(Expr*, Expr*, int); int sqlite3ExprListCompare(ExprList*, ExprList*, int); int sqlite3ExprImpliesExpr(Parse*,Expr*, Expr*, int); int sqlite3ExprImpliesNonNullRow(Expr*,int); void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx); int sqlite3FunctionUsesThisSrc(Expr*, SrcList*); Vdbe *sqlite3GetVdbe(Parse*); #ifndef SQLITE_UNTESTABLE void sqlite3PrngSaveState(void); |
︙ | ︙ | |||
3857 3858 3859 3860 3861 3862 3863 | int sqlite3IsRowid(const char*); void sqlite3GenerateRowDelete( Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int); void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int); int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int); void sqlite3ResolvePartIdxLabel(Parse*,int); void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int, | | | 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 | int sqlite3IsRowid(const char*); void sqlite3GenerateRowDelete( Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int); void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int); int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int); void sqlite3ResolvePartIdxLabel(Parse*,int); void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int, u8,u8,int,int*,int*,Upsert*); #ifdef SQLITE_ENABLE_NULL_TRIM void sqlite3SetMakeRecordP5(Vdbe*,Table*); #else # define sqlite3SetMakeRecordP5(A,B) #endif void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int); int sqlite3OpenTableAndIndices(Parse*, Table*, int, u8, int, u8*, int*, int*); |
︙ | ︙ | |||
3910 3911 3912 3913 3914 3915 3916 | int, int, int); void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, int, int, int); void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*); void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*); TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*, const char*,const char*); TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*, | > | | 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 | int, int, int); void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, int, int, int); void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*); void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*); TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*, const char*,const char*); TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*, Select*,u8,Upsert*, const char*,const char*); TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8, const char*,const char*); TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*, const char*,const char*); void sqlite3DeleteTrigger(sqlite3*, Trigger*); void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int); |
︙ | ︙ | |||
4096 4097 4098 4099 4100 4101 4102 | void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*); void sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*); int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); void sqlite3ColumnDefault(Vdbe *, Table *, int, int); void sqlite3AlterFinishAddColumn(Parse *, Token *); void sqlite3AlterBeginAddColumn(Parse *, SrcList *); CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*); | | | | 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 | void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*); void sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*); int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); void sqlite3ColumnDefault(Vdbe *, Table *, int, int); void sqlite3AlterFinishAddColumn(Parse *, Token *); void sqlite3AlterBeginAddColumn(Parse *, SrcList *); CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*); char sqlite3AffinityType(const char*, Column*); void sqlite3Analyze(Parse*, Token*, Token*); int sqlite3InvokeBusyHandler(BusyHandler*, sqlite3_file*); int sqlite3FindDb(sqlite3*, Token*); int sqlite3FindDbName(sqlite3 *, const char *); int sqlite3AnalysisLoad(sqlite3*,int iDB); void sqlite3DeleteIndexSamples(sqlite3*,Index*); void sqlite3DefaultRowEst(Index*); void sqlite3RegisterLikeFunctions(sqlite3*, int); int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*); |
︙ | ︙ | |||
4158 4159 4160 4161 4162 4163 4164 | char sqlite3IndexColumnAffinity(sqlite3*, Index*, int); #endif /* ** The interface to the LEMON-generated parser */ #ifndef SQLITE_AMALGAMATION | | | | 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 | char sqlite3IndexColumnAffinity(sqlite3*, Index*, int); #endif /* ** The interface to the LEMON-generated parser */ #ifndef SQLITE_AMALGAMATION void *sqlite3ParserAlloc(void*(*)(u64), Parse*); void sqlite3ParserFree(void*, void(*)(void*)); #endif void sqlite3Parser(void*, int, Token); #ifdef YYTRACKMAXSTACKDEPTH int sqlite3ParserStackPeak(void*); #endif void sqlite3AutoLoadExtensions(sqlite3*); #ifndef SQLITE_OMIT_LOAD_EXTENSION void sqlite3CloseExtensions(sqlite3*); |
︙ | ︙ | |||
4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 | With *sqlite3WithAdd(Parse*,With*,Token*,ExprList*,Select*); void sqlite3WithDelete(sqlite3*,With*); void sqlite3WithPush(Parse*, With*, u8); #else #define sqlite3WithPush(x,y,z) #define sqlite3WithDelete(x,y) #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 ** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In ** this case foreign keys are parsed, but no other functionality is ** provided (enforcement of FK constraints requires the triggers sub-system). | > > > > > > > > > > > > | 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 | With *sqlite3WithAdd(Parse*,With*,Token*,ExprList*,Select*); void sqlite3WithDelete(sqlite3*,With*); void sqlite3WithPush(Parse*, With*, u8); #else #define sqlite3WithPush(x,y,z) #define sqlite3WithDelete(x,y) #endif #ifndef SQLITE_OMIT_UPSERT Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*); void sqlite3UpsertDelete(sqlite3*,Upsert*); Upsert *sqlite3UpsertDup(sqlite3*,Upsert*); int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*); 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 ** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In ** this case foreign keys are parsed, but no other functionality is ** provided (enforcement of FK constraints requires the triggers sub-system). |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 | Tcl_WrongNumArgs(interp, 1, objv, ""); return TCL_ERROR; } sqlite3_config(SQLITE_CONFIG_SQLLOG, 0, 0); return TCL_OK; } #endif /* ** Usage: vfs_current_time_int64 ** ** Return the value returned by the default VFS's xCurrentTimeInt64 method. */ static int SQLITE_TCLAPI vfsCurrentTimeInt64( | > > > > > > > > > > > > > > > > > > > > > | 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 | Tcl_WrongNumArgs(interp, 1, objv, ""); return TCL_ERROR; } sqlite3_config(SQLITE_CONFIG_SQLLOG, 0, 0); return TCL_OK; } #endif /* ** Usage: sqlite3_config_sorterref ** ** Set the SQLITE_CONFIG_SORTERREF_SIZE configuration option */ static int SQLITE_TCLAPI test_config_sorterref( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ int iVal; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "NBYTE"); return TCL_ERROR; } if( Tcl_GetIntFromObj(interp, objv[1], &iVal) ) return TCL_ERROR; sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, iVal); return TCL_OK; } /* ** Usage: vfs_current_time_int64 ** ** Return the value returned by the default VFS's xCurrentTimeInt64 method. */ static int SQLITE_TCLAPI vfsCurrentTimeInt64( |
︙ | ︙ | |||
7783 7784 7785 7786 7787 7788 7789 7790 7791 7792 7793 7794 7795 7796 | { "sqlite3_snapshot_open_blob", test_snapshot_open_blob, 0 }, { "sqlite3_snapshot_cmp_blob", test_snapshot_cmp_blob, 0 }, #endif { "sqlite3_delete_database", test_delete_database, 0 }, { "sqlite3_wal_info", test_wal_info, 0 }, { "atomic_batch_write", test_atomic_batch_write, 0 }, { "sqlite3_mmap_warm", test_mmap_warm, 0 }, }; static int bitmask_size = sizeof(Bitmask)*8; static int longdouble_size = sizeof(LONGDOUBLE_TYPE); int i; extern int sqlite3_sync_count, sqlite3_fullsync_count; extern int sqlite3_opentemp_count; extern int sqlite3_like_count; | > | 7804 7805 7806 7807 7808 7809 7810 7811 7812 7813 7814 7815 7816 7817 7818 | { "sqlite3_snapshot_open_blob", test_snapshot_open_blob, 0 }, { "sqlite3_snapshot_cmp_blob", test_snapshot_cmp_blob, 0 }, #endif { "sqlite3_delete_database", test_delete_database, 0 }, { "sqlite3_wal_info", test_wal_info, 0 }, { "atomic_batch_write", test_atomic_batch_write, 0 }, { "sqlite3_mmap_warm", test_mmap_warm, 0 }, { "sqlite3_config_sorterref", test_config_sorterref, 0 }, }; static int bitmask_size = sizeof(Bitmask)*8; static int longdouble_size = sizeof(LONGDOUBLE_TYPE); int i; extern int sqlite3_sync_count, sqlite3_fullsync_count; extern int sqlite3_opentemp_count; extern int sqlite3_like_count; |
︙ | ︙ |
Changes to src/tokenize.c.
︙ | ︙ | |||
492 493 494 495 496 497 498 | } pParse->rc = SQLITE_OK; pParse->zTail = zSql; assert( pzErrMsg!=0 ); /* sqlite3ParserTrace(stdout, "parser: "); */ #ifdef sqlite3Parser_ENGINEALWAYSONSTACK pEngine = &sEngine; | | | | 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 | } pParse->rc = SQLITE_OK; pParse->zTail = zSql; assert( pzErrMsg!=0 ); /* sqlite3ParserTrace(stdout, "parser: "); */ #ifdef sqlite3Parser_ENGINEALWAYSONSTACK pEngine = &sEngine; sqlite3ParserInit(pEngine, pParse); #else pEngine = sqlite3ParserAlloc(sqlite3Malloc, pParse); if( pEngine==0 ){ sqlite3OomFault(db); return SQLITE_NOMEM_BKPT; } #endif assert( pParse->pNewTable==0 ); assert( pParse->pNewTrigger==0 ); |
︙ | ︙ | |||
538 539 540 541 542 543 544 | sqlite3ErrorMsg(pParse, "unrecognized token: \"%.*s\"", n, zSql); break; } zSql += n; }else{ pParse->sLastToken.z = zSql; pParse->sLastToken.n = n; | | | 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 | sqlite3ErrorMsg(pParse, "unrecognized token: \"%.*s\"", n, zSql); break; } zSql += n; }else{ 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; |
︙ | ︙ |
Changes to src/treeview.c.
︙ | ︙ | |||
58 59 60 61 62 63 64 | 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); } sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4); } | > | | | | | > | 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | 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); } sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4); } if( zFormat!=0 ){ va_start(ap, zFormat); sqlite3VXPrintf(&acc, zFormat, ap); va_end(ap); assert( acc.nChar>0 ); sqlite3StrAccumAppend(&acc, "\n", 1); } sqlite3StrAccumFinish(&acc); fprintf(stdout,"%s", zBuf); fflush(stdout); } /* ** Shorthand for starting a new tree item that consists of a single label |
︙ | ︙ | |||
135 136 137 138 139 140 141 | sqlite3TreeViewWith(pView, p->pWith, 1); cnt = 1; sqlite3TreeViewPush(pView, 1); } do{ #if SELECTTRACE_ENABLED sqlite3TreeViewLine(pView, | | | | 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | sqlite3TreeViewWith(pView, p->pWith, 1); cnt = 1; sqlite3TreeViewPush(pView, 1); } do{ #if SELECTTRACE_ENABLED sqlite3TreeViewLine(pView, "SELECT%s%s (%s/%d/%p) selFlags=0x%x nSelectRow=%d", ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""), ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p->zSelName, p->iSelectId, 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 |
︙ | ︙ | |||
532 533 534 535 536 537 538 539 | sqlite3TreeViewLine(pView, "%s (empty)", zLabel); }else{ int i; sqlite3TreeViewLine(pView, "%s", zLabel); for(i=0; i<pList->nExpr; i++){ int j = pList->a[i].u.x.iOrderByCol; char *zName = pList->a[i].zName; if( j || zName ){ | > | < > > | | | | | | > > > | | 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 | sqlite3TreeViewLine(pView, "%s (empty)", zLabel); }else{ int i; sqlite3TreeViewLine(pView, "%s", zLabel); 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, 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, moreToFollow); if( j || zName ){ sqlite3TreeViewPop(pView); } } } } void sqlite3TreeViewExprList( |
︙ | ︙ |
Changes to src/trigger.c.
︙ | ︙ | |||
21 22 23 24 25 26 27 28 29 30 31 32 33 34 | TriggerStep * pTmp = pTriggerStep; pTriggerStep = pTriggerStep->pNext; sqlite3ExprDelete(db, pTmp->pWhere); sqlite3ExprListDelete(db, pTmp->pExprList); sqlite3SelectDelete(db, pTmp->pSelect); sqlite3IdListDelete(db, pTmp->pIdList); sqlite3DbFree(db, pTmp->zSpan); sqlite3DbFree(db, pTmp); } } /* | > | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | TriggerStep * pTmp = pTriggerStep; pTriggerStep = pTriggerStep->pNext; sqlite3ExprDelete(db, pTmp->pWhere); sqlite3ExprListDelete(db, pTmp->pExprList); sqlite3SelectDelete(db, pTmp->pSelect); sqlite3IdListDelete(db, pTmp->pIdList); sqlite3UpsertDelete(db, pTmp->pUpsert); sqlite3DbFree(db, pTmp->zSpan); sqlite3DbFree(db, pTmp); } } /* |
︙ | ︙ | |||
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 | */ TriggerStep *sqlite3TriggerInsertStep( sqlite3 *db, /* The database connection */ 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.) */ const char *zStart, /* Start of SQL text */ const char *zEnd /* End of SQL text */ ){ TriggerStep *pTriggerStep; assert(pSelect != 0 || db->mallocFailed); pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName, zStart, zEnd); if( pTriggerStep ){ pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); pTriggerStep->pIdList = pColumn; pTriggerStep->orconf = orconf; }else{ sqlite3IdListDelete(db, pColumn); } sqlite3SelectDelete(db, pSelect); return pTriggerStep; } /* | > > > > > | 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 | */ TriggerStep *sqlite3TriggerInsertStep( sqlite3 *db, /* The database connection */ 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 */ ){ TriggerStep *pTriggerStep; assert(pSelect != 0 || db->mallocFailed); pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName, zStart, zEnd); if( pTriggerStep ){ 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); return pTriggerStep; } /* |
︙ | ︙ | |||
742 743 744 745 746 747 748 | switch( pStep->op ){ case TK_UPDATE: { sqlite3Update(pParse, targetSrcList(pParse, pStep), sqlite3ExprListDup(db, pStep->pExprList, 0), sqlite3ExprDup(db, pStep->pWhere, 0), | | | > | 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 | switch( pStep->op ){ case TK_UPDATE: { sqlite3Update(pParse, targetSrcList(pParse, pStep), sqlite3ExprListDup(db, pStep->pExprList, 0), sqlite3ExprDup(db, pStep->pWhere, 0), pParse->eOrconf, 0, 0, 0 ); break; } case TK_INSERT: { sqlite3Insert(pParse, targetSrcList(pParse, pStep), sqlite3SelectDup(db, pStep->pSelect, 0), sqlite3IdListDup(db, pStep->pIdList), pParse->eOrconf, sqlite3UpsertDup(db, pStep->pUpsert) ); break; } case TK_DELETE: { sqlite3DeleteFrom(pParse, targetSrcList(pParse, pStep), sqlite3ExprDup(db, pStep->pWhere, 0), 0, 0 |
︙ | ︙ |
Changes to src/update.c.
︙ | ︙ | |||
89 90 91 92 93 94 95 | void sqlite3Update( Parse *pParse, /* The parser context */ 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 */ ExprList *pOrderBy, /* ORDER BY clause. May be null */ | | > | 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | void sqlite3Update( Parse *pParse, /* The parser context */ 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 */ 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 */ int addrTop = 0; /* VDBE instruction address of the start of the loop */ WhereInfo *pWInfo; /* Information about the WHERE clause */ Vdbe *v; /* The virtual database engine */ Index *pIdx; /* For looping over indices */ |
︙ | ︙ | |||
196 197 198 199 200 201 202 | } /* Allocate a cursors for the main database table and for all indices. ** The index cursors might not be used, but if they are used they ** need to occur right after the database cursor. So go ahead and ** allocate enough space, just in case. */ | | > | < > > > > > > > > > | 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | } /* Allocate a cursors for the main database table and for all indices. ** The index cursors might not be used, but if they are used they ** need to occur right after the database cursor. So go ahead and ** allocate enough space, just in case. */ 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( pPk==pIdx ){ iDataCur = pParse->nTab; } 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. */ aXRef = sqlite3DbMallocRawNN(db, sizeof(int) * (pTab->nCol+nIdx) + nIdx+2 ); if( aXRef==0 ) goto update_cleanup; aRegIdx = aXRef+pTab->nCol; aToOpen = (u8*)(aRegIdx+nIdx); memset(aToOpen, 1, nIdx+1); aToOpen[nIdx+1] = 0; for(i=0; i<pTab->nCol; i++) aXRef[i] = -1; /* Initialize the name-context */ 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 ** for each column to be updated in the pChanges array. For each ** column to be updated, make sure we have authorization to change ** that column. */ |
︙ | ︙ | |||
325 326 327 328 329 330 331 | memset(aToOpen, 1, nIdx+1); } /* Begin generating code. */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto update_cleanup; if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); | | | 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 | memset(aToOpen, 1, nIdx+1); } /* Begin generating code. */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto update_cleanup; if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); sqlite3BeginWriteOperation(pParse, pTrigger || hasFK, iDb); /* Allocate required registers. */ if( !IsVirtual(pTab) ){ regRowSet = ++pParse->nMem; regOldRowid = regNewRowid = ++pParse->nMem; if( chngPk || pTrigger || hasFK ){ regOld = pParse->nMem + 1; |
︙ | ︙ | |||
376 377 378 379 380 381 382 | if( IsVirtual(pTab) ){ updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef, pWhere, onError); goto update_cleanup; } #endif | > > > > | > | > > > > | < | | | | | > > > > > > > > > > > | | | | | | | | | | | | | | | | | | | | | | | | | > > | | | | | | | | > > | > | | | | < | | | | | | | | | | | | | | | | | | | | | | | | | < < | | | | | | | | | | | | | | | | | | | > | | | 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 | if( IsVirtual(pTab) ){ updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef, pWhere, onError); goto update_cleanup; } #endif /* 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); } if( HasRowid(pTab) ){ sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid); }else{ assert( pPk!=0 ); nPk = pPk->nKeyCol; iPk = pParse->nMem+1; pParse->nMem += nPk; regKey = ++pParse->nMem; 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); } } 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) ); } } } 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, ** leave it in register regOldRowid. */ sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid); if( eOnePass==ONEPASS_OFF ){ sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid); } }else{ /* Read the PK of the current row into an array of registers. In ** ONEPASS_OFF mode, serialize the array into a record and store it in ** the ephemeral table. Or, in ONEPASS_SINGLE or MULTI mode, change ** the OP_OpenEphemeral instruction to a Noop (the ephemeral table ** is not required) and leave the PK fields in the array of registers. */ for(i=0; i<nPk; i++){ assert( pPk->aiColumn[i]>=0 ); sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur,pPk->aiColumn[i],iPk+i); } if( eOnePass ){ if( addrOpen ) sqlite3VdbeChangeToNoop(v, addrOpen); nKey = nPk; regKey = iPk; }else{ sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey, sqlite3IndexAffinityStr(db, pPk), nPk); sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEph, regKey, iPk, nPk); } } if( pUpsert==0 ){ if( eOnePass!=ONEPASS_MULTI ){ sqlite3WhereEnd(pWInfo); } 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); } /* 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 = 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 = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet,labelBreak, regOldRowid); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid); VdbeCoverage(v); } } /* 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 ); if( chngRowid ){ sqlite3ExprCode(pParse, pRowidExpr, regNewRowid); sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid); VdbeCoverage(v); } |
︙ | ︙ | |||
622 623 624 625 626 627 628 | if( !isView ){ int addr1 = 0; /* Address of jump instruction */ /* Do constraint checks. */ assert( regOldRowid>0 ); sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace, | | | 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 | if( !isView ){ int addr1 = 0; /* Address of jump instruction */ /* Do constraint checks. */ assert( regOldRowid>0 ); sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace, aXRef, 0); /* Do FK constraint checks. */ if( hasFK ){ sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngKey); } /* Delete the index entries associated with the current record. */ |
︙ | ︙ | |||
692 693 694 695 696 697 698 | if( hasFK ){ sqlite3FkActions(pParse, pTab, pChanges, regOldRowid, aXRef, chngKey); } } /* Increment the row counter */ | | | 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 | if( hasFK ){ sqlite3FkActions(pParse, pTab, pChanges, regOldRowid, aXRef, chngKey); } } /* Increment the row counter */ if( regRowCount ){ sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); } sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, TRIGGER_AFTER, pTab, regOldRowid, onError, labelContinue); /* Repeat the above with the next record to be updated, until |
︙ | ︙ | |||
719 720 721 722 723 724 725 | } sqlite3VdbeResolveLabel(v, labelBreak); /* Update the sqlite_sequence table by storing the content of the ** maximum rowid counter values recorded while inserting into ** autoincrement tables. */ | | | < | | | 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 | } sqlite3VdbeResolveLabel(v, labelBreak); /* Update the sqlite_sequence table by storing the content of the ** maximum rowid counter values recorded while inserting into ** autoincrement tables. */ if( pParse->nested==0 && pParse->pTriggerTab==0 && pUpsert==0 ){ sqlite3AutoincrementEnd(pParse); } /* ** Return the number of rows that were changed, if we are tracking ** that information. */ if( regRowCount ){ sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", SQLITE_STATIC); } update_cleanup: sqlite3AuthContextPop(&sContext); |
︙ | ︙ | |||
849 850 851 852 853 854 855 | sqlite3VdbeAddOp2(v, OP_SCopy, regArg+2+iPk, regArg+1); } bOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy); if( bOnePass ){ /* If using the onepass strategy, no-op out the OP_OpenEphemeral coded | | < < < < > | 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 | sqlite3VdbeAddOp2(v, OP_SCopy, regArg+2+iPk, regArg+1); } bOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy); if( bOnePass ){ /* If using the onepass strategy, no-op out the OP_OpenEphemeral coded ** above. */ sqlite3VdbeChangeToNoop(v, addr); }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); |
︙ | ︙ |
Added src/upsert.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | /* ** 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 */ 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. */ 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. */ 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. */ 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. */ 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 = pUpsert->iDataCur; assert( v!=0 ); VdbeNoopComment((v, "Begin DO UPDATE of UPSERT")); 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)); } 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 */ |
Changes to src/vdbe.h.
︙ | ︙ | |||
216 217 218 219 220 221 222 223 224 225 226 227 228 229 | void sqlite3VdbeRunOnlyOnce(Vdbe*); void sqlite3VdbeReusable(Vdbe*); void sqlite3VdbeDelete(Vdbe*); void sqlite3VdbeClearObject(sqlite3*,Vdbe*); void sqlite3VdbeMakeReady(Vdbe*,Parse*); int sqlite3VdbeFinalize(Vdbe*); void sqlite3VdbeResolveLabel(Vdbe*, int); int sqlite3VdbeCurrentAddr(Vdbe*); #ifdef SQLITE_DEBUG int sqlite3VdbeAssertMayAbort(Vdbe *, int); #endif void sqlite3VdbeResetStepResult(Vdbe*); void sqlite3VdbeRewind(Vdbe*); int sqlite3VdbeReset(Vdbe*); | > > > | 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | void sqlite3VdbeRunOnlyOnce(Vdbe*); void sqlite3VdbeReusable(Vdbe*); void sqlite3VdbeDelete(Vdbe*); void sqlite3VdbeClearObject(sqlite3*,Vdbe*); void sqlite3VdbeMakeReady(Vdbe*,Parse*); int sqlite3VdbeFinalize(Vdbe*); void sqlite3VdbeResolveLabel(Vdbe*, int); #ifdef SQLITE_COVERAGE_TEST int sqlite3VdbeLabelHasBeenResolved(Vdbe*,int); #endif int sqlite3VdbeCurrentAddr(Vdbe*); #ifdef SQLITE_DEBUG int sqlite3VdbeAssertMayAbort(Vdbe *, int); #endif void sqlite3VdbeResetStepResult(Vdbe*); void sqlite3VdbeRewind(Vdbe*); int sqlite3VdbeReset(Vdbe*); |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 | void sqlite3VdbeResolveLabel(Vdbe *v, int x){ Parse *p = v->pParse; int j = ADDR(x); assert( v->magic==VDBE_MAGIC_INIT ); assert( j<p->nLabel ); assert( j>=0 ); if( p->aLabel ){ p->aLabel[j] = v->nOp; } } /* ** Mark the VDBE as one that can only be run one time. */ void sqlite3VdbeRunOnlyOnce(Vdbe *p){ p->runOnlyOnce = 1; } | > > > > > > > > > > > > > > > > > > > | 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 | void sqlite3VdbeResolveLabel(Vdbe *v, int x){ Parse *p = v->pParse; int j = ADDR(x); assert( v->magic==VDBE_MAGIC_INIT ); 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; } } #ifdef SQLITE_COVERAGE_TEST /* ** Return TRUE if and only if the label x has already been resolved. ** Return FALSE (zero) if label x is still unresolved. ** ** This routine is only used inside of testcase() macros, and so it ** only exists when measuring test coverage. */ int sqlite3VdbeLabelHasBeenResolved(Vdbe *v, int x){ return v->pParse->aLabel && v->pParse->aLabel[ADDR(x)]>=0; } #endif /* SQLITE_COVERAGE_TEST */ /* ** Mark the VDBE as one that can only be run one time. */ void sqlite3VdbeRunOnlyOnce(Vdbe *p){ p->runOnlyOnce = 1; } |
︙ | ︙ | |||
1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 | ** running the code, it invokes the callback once for each instruction. ** This feature is used to implement "EXPLAIN". ** ** When p->explain==1, each instruction is listed. When ** 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. ** ** When p->explain==1, first the main program is listed, then each of ** the trigger subprograms are listed one by one. */ int sqlite3VdbeList( Vdbe *p /* The VDBE */ ){ | > > > | 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 | ** running the code, it invokes the callback once for each instruction. ** This feature is used to implement "EXPLAIN". ** ** When p->explain==1, each instruction is listed. When ** 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. */ int sqlite3VdbeList( Vdbe *p /* The VDBE */ ){ |
︙ | ︙ | |||
1684 1685 1686 1687 1688 1689 1690 | apSub = (SubProgram **)pSub->z; } for(i=0; i<nSub; i++){ nRow += apSub[i]->nOp; } } | | | 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 | apSub = (SubProgram **)pSub->z; } for(i=0; i<nSub; i++){ nRow += apSub[i]->nOp; } } while(1){ /* Loop exits via break */ i = p->pc++; if( i>=nRow ){ p->rc = SQLITE_OK; rc = SQLITE_DONE; break; } if( i<p->nOp ){ |
︙ | ︙ | |||
1730 1731 1732 1733 1734 1735 1736 | apSub = (SubProgram **)pSub->z; apSub[nSub++] = pOp->p4.pProgram; pSub->flags |= MEM_Blob; pSub->n = nSub*sizeof(SubProgram*); nRow += pOp->p4.pProgram->nOp; } } | | > > > | 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 | 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; } if( rc==SQLITE_OK ){ if( db->u1.isInterrupted ){ p->rc = SQLITE_INTERRUPT; rc = SQLITE_ERROR; sqlite3VdbeError(p, sqlite3ErrStr(p->rc)); }else{ |
︙ | ︙ |
Changes to src/vdbemem.c.
︙ | ︙ | |||
1474 1475 1476 1477 1478 1479 1480 | zVal = &pExpr->u.zToken[2]; nVal = sqlite3Strlen30(zVal)-1; assert( zVal[nVal]=='\'' ); sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2, 0, SQLITE_DYNAMIC); } #endif | < > > > > > | 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 | zVal = &pExpr->u.zToken[2]; nVal = sqlite3Strlen30(zVal)-1; assert( zVal[nVal]=='\'' ); sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2, 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: #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 if( pCtx==0 || pCtx->pParse->nErr==0 ) |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
2369 2370 2371 2372 2373 2374 2375 | int rc = SQLITE_OK; /* Return code */ LogEst rSize; /* Number of rows in the table */ LogEst rLogSize; /* Logarithm of table size */ WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */ pNew = pBuilder->pNew; if( db->mallocFailed ) return SQLITE_NOMEM_BKPT; | | | | 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 | int rc = SQLITE_OK; /* Return code */ LogEst rSize; /* Number of rows in the table */ LogEst rLogSize; /* Logarithm of table size */ WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */ pNew = pBuilder->pNew; if( db->mallocFailed ) return SQLITE_NOMEM_BKPT; 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 ); if( pNew->wsFlags & WHERE_BTM_LIMIT ){ opMask = WO_LT|WO_LE; }else{ assert( pNew->u.btree.nBtm==0 ); |
︙ | ︙ | |||
2416 2417 2418 2419 2420 2421 2422 | } if( pTerm->prereqRight & pNew->maskSelf ) continue; /* Do not allow the upper bound of a LIKE optimization range constraint ** to mix with a lower range bound from some other source */ if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue; | | < < < | 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 | } if( pTerm->prereqRight & pNew->maskSelf ) continue; /* Do not allow the upper bound of a LIKE optimization range constraint ** to mix with a lower range bound from some other source */ if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue; /* 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) ){ continue; } if( IsUniqueIndex(pProbe) && saved_nEq==pProbe->nKeyCol-1 ){ pBuilder->bldFlags |= SQLITE_BLDF_UNIQUE; }else{ pBuilder->bldFlags |= SQLITE_BLDF_INDEXED; |
︙ | ︙ | |||
2656 2657 2658 2659 2660 2661 2662 | whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nIter + nInMul); pNew->nOut = saved_nOut; pNew->u.btree.nEq = saved_nEq; pNew->nSkip = saved_nSkip; pNew->wsFlags = saved_wsFlags; } | | | | 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 | whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nIter + nInMul); pNew->nOut = saved_nOut; pNew->u.btree.nEq = saved_nEq; pNew->nSkip = saved_nSkip; pNew->wsFlags = saved_wsFlags; } WHERETRACE(0x800, ("END %s.addBtreeIdx(%s), nEq=%d, rc=%d\n", pProbe->pTable->zName, pProbe->zName, saved_nEq, rc)); return rc; } /* ** Return True if it is possible that pIndex might be useful in ** implementing the ORDER BY clause in pBuilder. ** |
︙ | ︙ | |||
3095 3096 3097 3098 3099 3100 3101 | int j = pIdxCons->iTermOffset; if( iTerm>=nConstraint || j<0 || j>=pWC->nTerm || pNew->aLTerm[iTerm]!=0 || pIdxCons->usable==0 ){ | < > | | 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 | int j = pIdxCons->iTermOffset; if( iTerm>=nConstraint || j<0 || j>=pWC->nTerm || pNew->aLTerm[iTerm]!=0 || pIdxCons->usable==0 ){ sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName); testcase( pIdxInfo->needToFreeIdxStr ); return SQLITE_ERROR; } testcase( iTerm==nConstraint-1 ); testcase( j==0 ); testcase( j==pWC->nTerm-1 ); pTerm = &pWC->a[j]; pNew->prereq |= pTerm->prereqRight; assert( iTerm<pNew->nLSlot ); |
︙ | ︙ | |||
3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 | *pbIn = 1; assert( (mExclude & WO_IN)==0 ); } } } pNew->u.vtab.omitMask &= ~mNoOmit; pNew->nLTerm = mxTerm+1; assert( pNew->nLTerm<=pNew->nLSlot ); pNew->u.vtab.idxNum = pIdxInfo->idxNum; pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr; pIdxInfo->needToFreeIdxStr = 0; pNew->u.vtab.idxStr = pIdxInfo->idxStr; pNew->u.vtab.isOrdered = (i8)(pIdxInfo->orderByConsumed ? pIdxInfo->nOrderBy : 0); | > > > > > > > > > | 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 | *pbIn = 1; assert( (mExclude & WO_IN)==0 ); } } } 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; pIdxInfo->needToFreeIdxStr = 0; pNew->u.vtab.idxStr = pIdxInfo->idxStr; pNew->u.vtab.isOrdered = (i8)(pIdxInfo->orderByConsumed ? pIdxInfo->nOrderBy : 0); |
︙ | ︙ | |||
3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 | nConstraint = p->nConstraint; if( whereLoopResize(pParse->db, pNew, nConstraint) ){ sqlite3DbFree(pParse->db, p); return SQLITE_NOMEM_BKPT; } /* First call xBestIndex() with all constraints usable. */ WHERETRACE(0x40, (" VirtualOne: all usable\n")); rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn); /* If the call to xBestIndex() with all terms enabled produced a plan ** that does not require any source tables (IOW: a plan with mBest==0), ** then there is no point in making any further calls to xBestIndex() ** since they will all return the same result (if the xBestIndex() | > | 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 | nConstraint = p->nConstraint; if( whereLoopResize(pParse->db, pNew, nConstraint) ){ sqlite3DbFree(pParse->db, p); return SQLITE_NOMEM_BKPT; } /* 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); /* If the call to xBestIndex() with all terms enabled produced a plan ** that does not require any source tables (IOW: a plan with mBest==0), ** then there is no point in making any further calls to xBestIndex() ** since they will all return the same result (if the xBestIndex() |
︙ | ︙ | |||
3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 | rc = whereLoopAddVirtualOne( pBuilder, mPrereq, mPrereq, WO_IN, p, mNoOmit, &bIn); } } if( p->needToFreeIdxStr ) sqlite3_free(p->idxStr); sqlite3DbFreeNN(pParse->db, p); return rc; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ /* ** Add WhereLoop entries to handle OR terms. This works for either ** btrees or virtual tables. | > | 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 | rc = whereLoopAddVirtualOne( pBuilder, mPrereq, mPrereq, WO_IN, p, mNoOmit, &bIn); } } 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 */ /* ** Add WhereLoop entries to handle OR terms. This works for either ** btrees or virtual tables. |
︙ | ︙ |
Changes to src/whereInt.h.
︙ | ︙ | |||
15 16 17 18 19 20 21 | ** a separate source file for easier editing. */ /* ** Trace output macros */ #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) | | | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | ** a separate source file for easier editing. */ /* ** Trace output macros */ #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) /***/ extern int sqlite3WhereTrace; #endif #if defined(SQLITE_DEBUG) \ && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE)) # define WHERETRACE(K,X) if(sqlite3WhereTrace&(K)) sqlite3DebugPrintf X # define WHERETRACE_ENABLED 1 #else # define WHERETRACE(K,X) |
︙ | ︙ |
Changes to src/wherecode.c.
︙ | ︙ | |||
1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 | addrBrk = pLevel->addrBrk = pLevel->addrNxt = sqlite3VdbeMakeLabel(v); addrCont = pLevel->addrCont = sqlite3VdbeMakeLabel(v); /* If this is the right table of a LEFT OUTER JOIN, allocate and ** initialize a memory cell that records if this table matches any ** row of the left table of the join. */ if( pLevel->iFrom>0 && (pTabItem[0].fg.jointype & JT_LEFT)!=0 ){ pLevel->iLeftJoin = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin); VdbeComment((v, "init LEFT JOIN no-match flag")); } /* Compute a safe address to jump to if we discover that the table for | > > > | 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 | addrBrk = pLevel->addrBrk = pLevel->addrNxt = sqlite3VdbeMakeLabel(v); addrCont = pLevel->addrCont = sqlite3VdbeMakeLabel(v); /* If this is the right table of a LEFT OUTER JOIN, allocate and ** 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); VdbeComment((v, "init LEFT JOIN no-match flag")); } /* Compute a safe address to jump to if we discover that the table for |
︙ | ︙ | |||
1744 1745 1746 1747 1748 1749 1750 1751 | sqlite3VdbeAddOp4Int(v, OP_NotFound, iCur, addrCont, iRowidReg, pPk->nKeyCol); VdbeCoverage(v); } /* 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. */ | > > > > > > > | | | 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 | sqlite3VdbeAddOp4Int(v, OP_NotFound, iCur, addrCont, iRowidReg, pPk->nKeyCol); VdbeCoverage(v); } /* 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 */ 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; }else if( bRev ){ pLevel->op = OP_Prev; }else{ |
︙ | ︙ | |||
1902 1903 1904 1905 1906 1907 1908 | ** See ticket http://www.sqlite.org/src/info/f2369304e4 */ if( pWC->nTerm>1 ){ int iTerm; for(iTerm=0; iTerm<pWC->nTerm; iTerm++){ Expr *pExpr = pWC->a[iTerm].pExpr; if( &pWC->a[iTerm] == pTerm ) continue; | < | 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 | ** See ticket http://www.sqlite.org/src/info/f2369304e4 */ if( pWC->nTerm>1 ){ int iTerm; for(iTerm=0; iTerm<pWC->nTerm; iTerm++){ Expr *pExpr = pWC->a[iTerm].pExpr; if( &pWC->a[iTerm] == pTerm ) 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; if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO ); pExpr = sqlite3ExprDup(db, pExpr, 0); pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr); |
︙ | ︙ | |||
1927 1928 1929 1930 1931 1932 1933 | wctrlFlags = WHERE_OR_SUBCLAUSE | (pWInfo->wctrlFlags & WHERE_SEEK_TABLE); for(ii=0; ii<pOrWc->nTerm; ii++){ WhereTerm *pOrTerm = &pOrWc->a[ii]; if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){ WhereInfo *pSubWInfo; /* Info for single OR-term scan */ Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */ int jmp1 = 0; /* Address of jump operation */ | > | > > | 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 | wctrlFlags = WHERE_OR_SUBCLAUSE | (pWInfo->wctrlFlags & WHERE_SEEK_TABLE); for(ii=0; ii<pOrWc->nTerm; ii++){ WhereTerm *pOrTerm = &pOrWc->a[ii]; if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){ WhereInfo *pSubWInfo; /* Info for single OR-term scan */ Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */ int jmp1 = 0; /* Address of jump operation */ assert( (pTabItem[0].fg.jointype & JT_LEFT)==0 || ExprHasProperty(pOrExpr, EP_FromJoin) ); if( pAndExpr ){ pAndExpr->pLeft = pOrExpr; pOrExpr = pAndExpr; } /* Loop through table entries that match term pOrTerm. */ WHERETRACE(0xffff, ("Subplan for OR-clause:\n")); pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0, wctrlFlags, iCovCur); |
︙ | ︙ | |||
2110 2111 2112 2113 2114 2115 2116 | testcase( pWInfo->untestedTerms==0 && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 ); pWInfo->untestedTerms = 1; continue; } pE = pTerm->pExpr; assert( pE!=0 ); | | | | | > | 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 | testcase( pWInfo->untestedTerms==0 && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 ); pWInfo->untestedTerms = 1; continue; } pE = pTerm->pExpr; assert( pE!=0 ); if( (pTabItem->fg.jointype&JT_LEFT) && !ExprHasProperty(pE,EP_FromJoin) ){ continue; } if( iLoop==1 && !sqlite3ExprCoveredByIndex(pE, pLevel->iTabCur, pIdx) ){ iNext = 2; continue; } if( iLoop<3 && (pTerm->wtFlags & TERM_VARSELECT) ){ if( iNext==0 ) iNext = 3; continue; } 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 ** for strings. So do not skip the call to the function on the pass ** that compares BLOBs. */ #ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS continue; #else u32 x = pLevel->iLikeRepCntr; if( x>0 ){ skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)?OP_IfNot:OP_If,(int)(x>>1)); } VdbeCoverage(v); #endif } #ifdef WHERETRACE_ENABLED /* 0xffff */ if( sqlite3WhereTrace ){ VdbeNoopComment((v, "WhereTerm[%d] (%p) priority=%d", pWC->nTerm-j, pTerm, iLoop)); |
︙ | ︙ |
Changes to src/whereexpr.c.
︙ | ︙ | |||
814 815 816 817 818 819 820 | testcase( idxNew==0 ); exprAnalyze(pSrc, pWC, idxNew); pTerm = &pWC->a[idxTerm]; markTermAsChild(pWC, idxNew, idxTerm); }else{ sqlite3ExprListDelete(db, pList); } | < | 814 815 816 817 818 819 820 821 822 823 824 825 826 827 | testcase( idxNew==0 ); exprAnalyze(pSrc, pWC, idxNew); pTerm = &pWC->a[idxTerm]; markTermAsChild(pWC, idxNew, idxTerm); }else{ sqlite3ExprListDelete(db, pList); } } } } #endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */ /* ** We already know that pExpr is a binary operator where both operands are |
︙ | ︙ |
Changes to test/analyze.test.
︙ | ︙ | |||
345 346 347 348 349 350 351 | " } {t4i1 t4i2 t4} } # This test corrupts the database file so it must be the last test # in the series. # | | > > > > > > > > > > > > > > > > | 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 | " } {t4i1 t4i2 t4} } # This test corrupts the database file so it must be the last test # in the series. # do_test analyze-5.99 { execsql { PRAGMA writable_schema=on; UPDATE sqlite_master SET sql='nonsense' WHERE name='sqlite_stat1'; } db close catch { sqlite3 db test.db } catchsql { ANALYZE } } {1 {malformed database schema (sqlite_stat1)}} # Verify that tables whose names begin with "sqlite" but not # "sqlite_" are analyzed. # db close sqlite3 db :memory: do_execsql_test analyze-6.1 { CREATE TABLE sqliteDemo(a); INSERT INTO sqliteDemo(a) VALUES(1),(2),(3),(4),(5); CREATE TABLE SQLiteDemo2(a INTEGER PRIMARY KEY AUTOINCREMENT); INSERT INTO SQLiteDemo2 SELECT * FROM sqliteDemo; CREATE TABLE t1(b); INSERT INTO t1(b) SELECT a FROM sqliteDemo; ANALYZE; SELECT tbl FROM sqlite_stat1 WHERE idx IS NULL ORDER BY tbl; } {SQLiteDemo2 sqliteDemo t1} finish_test |
Changes to test/autoinc.test.
︙ | ︙ | |||
671 672 673 674 675 676 677 | CREATE TABLE t10a(a INTEGER PRIMARY KEY AUTOINCREMENT, b UNIQUE); INSERT INTO t10a VALUES(888,9999); CREATE TABLE t10b(x INTEGER PRIMARY KEY AUTOINCREMENT, y UNIQUE); INSERT INTO t10b SELECT * FROM t10a; SELECT * FROM sqlite_sequence; } {t10a 888 t10b 888} | > | > > > > > > | 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 | CREATE TABLE t10a(a INTEGER PRIMARY KEY AUTOINCREMENT, b UNIQUE); INSERT INTO t10a VALUES(888,9999); CREATE TABLE t10b(x INTEGER PRIMARY KEY AUTOINCREMENT, y UNIQUE); INSERT INTO t10b SELECT * FROM t10a; SELECT * FROM sqlite_sequence; } {t10a 888 t10b 888} # 2018-04-21 autoincrement does not cause problems for upsert # do_execsql_test autoinc-11.1 { CREATE TABLE t11(a INTEGER PRIMARY KEY AUTOINCREMENT,b UNIQUE); INSERT INTO t11(a,b) VALUES(2,3),(5,6),(4,3),(1,2) ON CONFLICT(b) DO UPDATE SET a=a+1000; SELECT seq FROM sqlite_sequence WHERE name='t11'; } {5} finish_test |
Changes to test/avtrans.test.
︙ | ︙ | |||
18 19 20 21 22 23 24 | set testdir [file dirname $argv0] source $testdir/tester.tcl # Create several tables to work with. # do_test avtrans-1.0 { | | > | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | set testdir [file dirname $argv0] source $testdir/tester.tcl # Create several tables to work with. # do_test avtrans-1.0 { execsql { PRAGMA auto_vacuum=full } wal_set_journal_mode execsql { CREATE TABLE one(a int PRIMARY KEY, b text); INSERT INTO one VALUES(1,'one'); INSERT INTO one VALUES(2,'two'); INSERT INTO one VALUES(3,'three'); SELECT b FROM one ORDER BY a; } } {one two three} do_test avtrans-1.0.1 { execsql { PRAGMA auto_vacuum } } 1 do_test avtrans-1.1 { execsql { CREATE TABLE two(a int PRIMARY KEY, b text); INSERT INTO two VALUES(1,'I'); INSERT INTO two VALUES(5,'V'); INSERT INTO two VALUES(10,'X'); SELECT b FROM two ORDER BY a; |
︙ | ︙ |
Changes to test/bestindex1.test.
︙ | ︙ | |||
55 56 57 58 59 60 61 | 0 0 0 {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!} } do_eqp_test 1.2 { SELECT * FROM x1 WHERE a IN ('abc', 'def'); } { 0 0 0 {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!} | < | 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | 0 0 0 {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!} } do_eqp_test 1.2 { SELECT * FROM x1 WHERE a IN ('abc', 'def'); } { 0 0 0 {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!} } #------------------------------------------------------------------------- # reset_db register_tcl_module db |
︙ | ︙ | |||
142 143 144 145 146 147 148 | do_execsql_test 2.2.$mode.5 { SELECT rowid FROM t1 WHERE a IN ('one', 'four') ORDER BY +rowid } {1 4} set plan(use) { 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'} | < < < | 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | do_execsql_test 2.2.$mode.5 { SELECT rowid FROM t1 WHERE a IN ('one', 'four') ORDER BY +rowid } {1 4} set plan(use) { 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'} 0 0 0 {USE TEMP B-TREE FOR ORDER BY} } set plan(omit) { 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'} 0 0 0 {USE TEMP B-TREE FOR ORDER BY} } set plan(use2) { 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x} 0 0 0 {USE TEMP B-TREE FOR ORDER BY} } do_eqp_test 2.2.$mode.6 { SELECT rowid FROM t1 WHERE a IN ('one', 'four') ORDER BY +rowid } $plan($mode) } |
︙ | ︙ |
Changes to test/csv01.test.
︙ | ︙ | |||
136 137 138 139 140 141 142 143 144 | columns=4, schema= 'CREATE TABLE t3(a,b,c,d) WITHOUT ROWID', testflags=1 ); } {1 {vtable constructor failed: t5}} finish_test | > > > > > > > | 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | columns=4, schema= 'CREATE TABLE t3(a,b,c,d) WITHOUT ROWID', testflags=1 ); } {1 {vtable constructor failed: t5}} # 2018-04-24 # Memory leak reported on the sqlite-users mailing list by Ralf Junker. # do_catchsql_test 4.3 { CREATE VIRTUAL TABLE IF NOT EXISTS temp.t1 USING csv(filename='FileDoesNotExist.csv'); } {1 {cannot open 'FileDoesNotExist.csv' for reading}} finish_test |
Changes to test/cursorhint2.test.
︙ | ︙ | |||
132 133 134 135 136 137 138 | do_extract_hints_test 2.5 { SELECT * FROM x1 LEFT JOIN x2 ON (a=x) WHERE 1 = coalesce(b, 1) } { x2 {EQ(c0,r[2])} } | > > > | | | | | | | | | | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | > | 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | do_extract_hints_test 2.5 { SELECT * FROM x1 LEFT JOIN x2 ON (a=x) WHERE 1 = coalesce(b, 1) } { x2 {EQ(c0,r[2])} } if {0} { # These tests no longer work due to the LEFT-JOIN strength reduction # optimization do_extract_hints_test 2.6 { SELECT * FROM x1 CROSS JOIN x2 ON (a=x) WHERE 0 = (b IS NOT NULL) } { x2 {EQ(c0,r[2])} } do_extract_hints_test 2.7 { SELECT * FROM x1 LEFT JOIN x2 ON (a=x) WHERE 0 = (b IS NOT +NULL) } { x2 {EQ(c0,r[2])} } do_extract_hints_test 2.8 { SELECT * FROM x1 LEFT JOIN x2 ON (a=x) WHERE b IS NOT +NULL } { x2 {EQ(c0,r[2])} } do_extract_hints_test 2.9 { SELECT * FROM x1 LEFT JOIN x2 ON (a=x) WHERE CASE b WHEN 0 THEN 0 ELSE 1 END; } { x2 {EQ(c0,r[2])} } do_extract_hints_test 2.10 { SELECT * FROM x1 LEFT JOIN x2 ON (a=x) WHERE x2.b = 32+32 } { x2 {AND(EQ(c1,ADD(32,32)),EQ(c0,r[2]))} } ifcapable !icu { # This test only works using the built-in LIKE, not the ICU LIKE extension. do_extract_hints_test 2.11 { SELECT * FROM x1 LEFT JOIN x2 ON (a=x) WHERE x2.b LIKE 'abc%' } { x2 {AND(expr,EQ(c0,r[2]))} } } } do_extract_hints_test 2.12 { SELECT * FROM x1 LEFT JOIN x2 ON (a=x) WHERE coalesce(x2.b, 1) } { x2 {EQ(c0,r[2])} } finish_test |
Changes to test/dbstatus2.test.
︙ | ︙ | |||
106 107 108 109 110 111 112 | do_test 3.0 { db_spill db 1 } {0 0 0} do_test 3.1 { db_spill db 0 } {0 0 0} do_execsql_test 3.2 { PRAGMA journal_mode=DELETE; PRAGMA cache_size=3; UPDATE t1 SET b=randomblob(1000); } {delete} | | | 106 107 108 109 110 111 112 113 114 115 | do_test 3.0 { db_spill db 1 } {0 0 0} do_test 3.1 { db_spill db 0 } {0 0 0} do_execsql_test 3.2 { PRAGMA journal_mode=DELETE; PRAGMA cache_size=3; UPDATE t1 SET b=randomblob(1000); } {delete} do_test 3.3 { db_spill db 0 } {0 8 0} finish_test |
Changes to test/delete.test.
︙ | ︙ | |||
398 399 400 401 402 403 404 405 406 407 | do_execsql_test delete-10.1 { DELETE FROM t1 WHERE a='1' AND b='2'; } do_execsql_test delete-10.2 { SELECT * FROM t1 WHERE a='1' AND b='2'; } finish_test | > > > > > > > > > > > > | 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 | do_execsql_test delete-10.1 { DELETE FROM t1 WHERE a='1' AND b='2'; } do_execsql_test delete-10.2 { SELECT * FROM t1 WHERE a='1' AND b='2'; } do_execsql_test delete-11.0 { CREATE TABLE t11(a INTEGER PRIMARY KEY, b INT); WITH RECURSIVE cnt(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM cnt WHERE x<20) INSERT INTO t11(a,b) SELECT x, (x*17)%100 FROM cnt; SELECT * FROM t11; } {1 17 2 34 3 51 4 68 5 85 6 2 7 19 8 36 9 53 10 70 11 87 12 4 13 21 14 38 15 55 16 72 17 89 18 6 19 23 20 40} do_execsql_test delete-11.1 { DELETE FROM t11 AS xyz WHERE EXISTS(SELECT 1 FROM t11 WHERE t11.a>xyz.a AND t11.b<=xyz.b); SELECT * FROM t11; } {6 2 12 4 18 6 19 23 20 40} finish_test |
Changes to test/e_select.test.
︙ | ︙ | |||
744 745 746 747 748 749 750 | do_execsql_test e_select-3.1.5 { SELECT k FROM x1 WHERE x IS NULL } {4 5} do_execsql_test e_select-3.1.6 { SELECT k FROM x1 WHERE z - 78.43 } {2 4 6} do_execsql_test e_select-3.2.1a { SELECT k FROM x1 LEFT JOIN x2 USING(k) } {1 2 3 4 5 6} do_execsql_test e_select-3.2.1b { | | | 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 | do_execsql_test e_select-3.1.5 { SELECT k FROM x1 WHERE x IS NULL } {4 5} do_execsql_test e_select-3.1.6 { SELECT k FROM x1 WHERE z - 78.43 } {2 4 6} do_execsql_test e_select-3.2.1a { SELECT k FROM x1 LEFT JOIN x2 USING(k) } {1 2 3 4 5 6} do_execsql_test e_select-3.2.1b { SELECT k FROM x1 LEFT JOIN x2 USING(k) WHERE x2.k ORDER BY +k } {1 3 5} do_execsql_test e_select-3.2.2 { SELECT k FROM x1 LEFT JOIN x2 USING(k) WHERE x2.k IS NULL } {2 4 6} do_execsql_test e_select-3.2.3 { SELECT k FROM x1 NATURAL JOIN x2 WHERE x2.k |
︙ | ︙ |
Changes to test/istrue.test.
︙ | ︙ | |||
118 119 120 121 122 123 124 125 126 | } {1 {CHECK constraint failed: t2}} do_catchsql_test istrue-523 { INSERT INTO t2 VALUES(2,true,false,true,null); } {1 {CHECK constraint failed: t2}} do_catchsql_test istrue-524 { INSERT INTO t2 VALUES(2,true,false,null,false); } {1 {CHECK constraint failed: t2}} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | } {1 {CHECK constraint failed: t2}} do_catchsql_test istrue-523 { INSERT INTO t2 VALUES(2,true,false,true,null); } {1 {CHECK constraint failed: t2}} do_catchsql_test istrue-524 { INSERT INTO t2 VALUES(2,true,false,null,false); } {1 {CHECK constraint failed: t2}} foreach {tn val} [list 1 NaN 2 -NaN 3 NaN0 4 -NaN0 5 Inf 6 -Inf] { do_execsql_test istrue-600.$tn.1 { DROP TABLE IF EXISTS t1; CREATE TABLE t1(x); } do_test istrue-600.$tn.2 { set ::STMT [sqlite3_prepare db "INSERT INTO t1 VALUES(?)" -1 TAIL] sqlite3_bind_double $::STMT 1 $val sqlite3_step $::STMT sqlite3_reset $::STMT sqlite3_finalize $::STMT } {SQLITE_OK} do_execsql_test istrue-600.$tn.3 { SELECT x IS TRUE FROM t1; } [expr {$tn in [list 5 6] ? {1} : {0}}] do_execsql_test istrue-600.$tn.4 { SELECT x IS FALSE FROM t1; } {0} } do_execsql_test istrue-700 { CREATE TABLE t7( a INTEGER PRIMARY KEY, b BOOLEAN DEFAULT false, c BOOLEAN DEFAULT true ); INSERT INTO t7(a) VALUES(1); INSERT INTO t7(a,b,c) VALUES(2,true,false); ALTER TABLE t7 ADD COLUMN d BOOLEAN DEFAULT false; ALTER TABLE t7 ADD COLUMN e BOOLEAN DEFAULT true; INSERT INTO t7(a,b,c) VALUES(3,true,false); INSERT INTO t7 VALUES(4,false,true,true,false); SELECT *,'x' FROM t7 ORDER BY a; } {1 0 1 0 1 x 2 1 0 0 1 x 3 1 0 0 1 x 4 0 1 1 0 x} finish_test |
Changes to test/join.test.
︙ | ︙ | |||
776 777 778 779 780 781 782 783 | INSERT INTO t3(id) VALUES(1),(2); SELECT t1.id, x2.id, x3.id FROM t1 LEFT JOIN (SELECT * FROM t2) AS x2 ON t1.id=x2.c2 LEFT JOIN t3 AS x3 ON x2.id=x3.c3; } {456 {} {}} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 | INSERT INTO t3(id) VALUES(1),(2); SELECT t1.id, x2.id, x3.id FROM t1 LEFT JOIN (SELECT * FROM t2) AS x2 ON t1.id=x2.c2 LEFT JOIN t3 AS x3 ON x2.id=x3.c3; } {456 {} {}} # 2018-03-24. # E.Pasma discovered that the LEFT JOIN strength reduction optimization # was misbehaving. The problem turned out to be that the # sqlite3ExprImpliesNotNull() routine was saying that CASE expressions # like # # CASE WHEN true THEN true ELSE x=0 END # # could never be true if x is NULL. The following test cases verify # that this error has been resolved. # db close sqlite3 db :memory: do_execsql_test join-15.100 { CREATE TABLE t1(a INT, b INT); INSERT INTO t1 VALUES(1,2),(3,4); CREATE TABLE t2(x INT, y INT); SELECT *, 'x' FROM t1 LEFT JOIN t2 WHERE CASE WHEN FALSE THEN a=x ELSE 1 END; } {1 2 {} {} x 3 4 {} {} x} do_execsql_test join-15.105 { SELECT *, 'x' FROM t1 LEFT JOIN t2 WHERE a IN (1,3,x,y); } {1 2 {} {} x 3 4 {} {} x} do_execsql_test join-15.106 { SELECT *, 'x' FROM t1 LEFT JOIN t2 WHERE NOT ( 'x'='y' AND t2.y=1 ); } {1 2 {} {} x 3 4 {} {} x} do_execsql_test join-15.107 { SELECT *, 'x' FROM t1 LEFT JOIN t2 WHERE t2.y IS NOT 'abc' } {1 2 {} {} x 3 4 {} {} x} do_execsql_test join-15.110 { DROP TABLE t1; DROP TABLE t2; CREATE TABLE t1(a INTEGER PRIMARY KEY, b INTEGER); INSERT INTO t1(a,b) VALUES(1,0),(11,1),(12,1),(13,1),(121,12); CREATE INDEX t1b ON t1(b); CREATE TABLE t2(x INTEGER PRIMARY KEY); INSERT INTO t2(x) VALUES(0),(1); SELECT a1, a2, a3, a4, a5 FROM (SELECT a AS a1 FROM t1 WHERE b=0) JOIN (SELECT x AS x1 FROM t2) LEFT JOIN (SELECT a AS a2, b AS b2 FROM t1) ON x1 IS TRUE AND b2=a1 JOIN (SELECT x AS x2 FROM t2) ON x2<=CASE WHEN x1 THEN CASE WHEN a2 THEN 1 ELSE -1 END ELSE 0 END LEFT JOIN (SELECT a AS a3, b AS b3 FROM t1) ON x2 IS TRUE AND b3=a2 JOIN (SELECT x AS x3 FROM t2) ON x3<=CASE WHEN x2 THEN CASE WHEN a3 THEN 1 ELSE -1 END ELSE 0 END LEFT JOIN (SELECT a AS a4, b AS b4 FROM t1) ON x3 IS TRUE AND b4=a3 JOIN (SELECT x AS x4 FROM t2) ON x4<=CASE WHEN x3 THEN CASE WHEN a4 THEN 1 ELSE -1 END ELSE 0 END LEFT JOIN (SELECT a AS a5, b AS b5 FROM t1) ON x4 IS TRUE AND b5=a4 ORDER BY a1, a2, a3, a4, a5; } {1 {} {} {} {} 1 11 {} {} {} 1 12 {} {} {} 1 12 121 {} {} 1 13 {} {} {}} finish_test |
Changes to test/join2.test.
︙ | ︙ | |||
82 83 84 85 86 87 88 | CREATE TABLE cc(c); INSERT INTO aa VALUES('one'); INSERT INTO bb VALUES('one'); INSERT INTO cc VALUES('one'); } do_catchsql_test 2.1 { | | | 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | CREATE TABLE cc(c); INSERT INTO aa VALUES('one'); INSERT INTO bb VALUES('one'); INSERT INTO cc VALUES('one'); } do_catchsql_test 2.1 { SELECT * FROM aa LEFT JOIN cc ON (a=b) JOIN bb ON (b=coalesce(c,1)); } {1 {ON clause references tables to its right}} do_catchsql_test 2.2 { SELECT * FROM aa JOIN cc ON (a=b) JOIN bb ON (b=c); } {0 {one one one}} #------------------------------------------------------------------------- # Test that a problem causing where.c to overlook opportunities to |
︙ | ︙ | |||
260 261 262 263 264 265 266 267 268 | CREATE INDEX u1ab ON u1(b, c); } do_eqp_test 6.1 { SELECT u2.* FROM u2 LEFT JOIN u1 ON( u1.a=u2.a AND u1.b=u2.b AND u1.c=u2.c ); } { 0 0 0 {SCAN TABLE u2} } finish_test | > > > > > > > > > > > > > > | 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 | CREATE INDEX u1ab ON u1(b, c); } do_eqp_test 6.1 { SELECT u2.* FROM u2 LEFT JOIN u1 ON( u1.a=u2.a AND u1.b=u2.b AND u1.c=u2.c ); } { 0 0 0 {SCAN TABLE u2} } db close sqlite3 db :memory: do_execsql_test 7.0 { CREATE TABLE t1(a,b); INSERT INTO t1 VALUES(1,2),(3,4),(5,6); CREATE TABLE t2(c,d); INSERT INTO t2 VALUES(2,4),(3,6); CREATE TABLE t3(x); INSERT INTO t3 VALUES(9); CREATE VIEW test AS SELECT *, 'x' FROM t1 LEFT JOIN (SELECT * FROM t2, t3) ON (c=b AND x=9) WHERE c IS NULL; SELECT * FROM test; } {3 4 {} {} {} x 5 6 {} {} {} x} finish_test |
Changes to test/join5.test.
︙ | ︙ | |||
160 161 162 163 164 165 166 | INSERT INTO x3 VALUES('c', NULL); SELECT * FROM x1 LEFT JOIN x2 JOIN x3 WHERE x3.d = x2.b; } {} # Ticket https://www.sqlite.org/src/tktview/c2a19d81652f40568c770c43 on # 2015-08-20. LEFT JOIN and the push-down optimization. # | | | | 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | INSERT INTO x3 VALUES('c', NULL); SELECT * FROM x1 LEFT JOIN x2 JOIN x3 WHERE x3.d = x2.b; } {} # Ticket https://www.sqlite.org/src/tktview/c2a19d81652f40568c770c43 on # 2015-08-20. LEFT JOIN and the push-down optimization. # do_execsql_test join5-4.1 { SELECT * FROM ( SELECT 'apple' fruit UNION ALL SELECT 'banana' ) a JOIN ( SELECT 'apple' fruit UNION ALL SELECT 'banana' ) b ON a.fruit=b.fruit LEFT JOIN ( SELECT 1 isyellow ) c ON b.fruit='banana'; } {apple apple {} banana banana 1} do_execsql_test join5-4.2 { SELECT * FROM (SELECT 'apple' fruit UNION ALL SELECT 'banana') LEFT JOIN (SELECT 1) ON fruit='banana'; } {apple {} banana 1} #------------------------------------------------------------------------- do_execsql_test 5.0 { |
︙ | ︙ | |||
207 208 209 210 211 212 213 214 215 | do_execsql_test 5.4 { SELECT count(z) FROM ( SELECT * FROM y1 ) LEFT JOIN y2 ON x } 1 do_execsql_test 5.5 { SELECT * FROM ( SELECT * FROM y1 ) LEFT JOIN y2 ON x } {0 0 1 {}} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 | do_execsql_test 5.4 { SELECT count(z) FROM ( SELECT * FROM y1 ) LEFT JOIN y2 ON x } 1 do_execsql_test 5.5 { SELECT * FROM ( SELECT * FROM y1 ) LEFT JOIN y2 ON x } {0 0 1 {}} #------------------------------------------------------------------------- # reset_db do_execsql_test 6.1 { CREATE TABLE t1(x); INSERT INTO t1 VALUES(1); CREATE TABLE t2(y INTEGER PRIMARY KEY,a,b); INSERT INTO t2 VALUES(1,2,3); CREATE INDEX t2a ON t2(a); CREATE INDEX t2b ON t2(b); } do_execsql_test 6.2 { SELECT * FROM t1 LEFT JOIN t2 ON a=2 OR b=3 WHERE y IS NULL; } {} do_execsql_test 6.3.1 { CREATE TABLE t3(x); INSERT INTO t3 VALUES(1); CREATE TABLE t4(y, z); SELECT ifnull(z, '!!!') FROM t3 LEFT JOIN t4 ON (x=y); } {!!!} do_execsql_test 6.3.2 { CREATE INDEX t4i ON t4(y, ifnull(z, '!!!')); SELECT ifnull(z, '!!!') FROM t3 LEFT JOIN t4 ON (x=y); } {!!!} #------------------------------------------------------------------------- # reset_db do_execsql_test 7.0 { CREATE TABLE t1(x); INSERT INTO t1 VALUES(1); } do_execsql_test 7.1 { CREATE TABLE t2(x, y, z); CREATE INDEX t2xy ON t2(x, y); WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50000 ) INSERT INTO t2 SELECT i/10, i, NULL FROM s; ANALYZE; } do_eqp_test 7.2 { SELECT * FROM t1 LEFT JOIN t2 ON ( t2.x = t1.x AND (t2.y=? OR (t2.y=? AND t2.z IS NOT NULL)) ); } { 0 0 0 {SCAN TABLE t1} 0 1 1 {SEARCH TABLE t2 USING INDEX t2xy (x=? AND y=?)} 0 1 1 {SEARCH TABLE t2 USING INDEX t2xy (x=? AND y=?)} } do_execsql_test 7.3 { CREATE TABLE t3(x); CREATE TABLE t4(x, y, z); CREATE INDEX t4xy ON t4(x, y); CREATE INDEX t4xz ON t4(x, z); WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50000) INSERT INTO t4 SELECT i/10, i, i FROM s; ANALYZE; } do_eqp_test 7.4 { SELECT * FROM t3 LEFT JOIN t4 ON (t4.x = t3.x) WHERE (t4.y = ? OR t4.z = ?); } { 0 0 0 {SCAN TABLE t3} 0 1 1 {SEARCH TABLE t4 USING INDEX t4xz (x=?)} } finish_test |
Changes to test/kvtest.c.
︙ | ︙ | |||
558 559 560 561 562 563 564 | sqlite3_snprintf(20, zTail, "%02d/%02d/%02d", iKey/10000, (iKey/100)%100, iKey%100); } out = fopen(zFN, "wb"); nWrote = fwrite(pData, 1, (size_t)nData, out); fclose(out); printf("\r%s ", zTail); fflush(stdout); | | | 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 | sqlite3_snprintf(20, zTail, "%02d/%02d/%02d", iKey/10000, (iKey/100)%100, iKey%100); } out = fopen(zFN, "wb"); nWrote = fwrite(pData, 1, (size_t)nData, out); fclose(out); printf("\r%s ", zTail); fflush(stdout); if( nWrote!=(size_t)nData ){ fatalError("Wrote only %d of %d bytes to %s\n", (int)nWrote, nData, zFN); } } sqlite3_finalize(pStmt); sqlite3_close(db); sqlite3_free(zFN); |
︙ | ︙ |
Changes to test/memdb1.test.
︙ | ︙ | |||
53 54 55 56 57 58 59 60 61 62 63 64 65 66 | do_execsql_test 110 { SELECT * FROM t1; } {1 2} # What happens when we try to VACUUM a MEMDB database? # do_execsql_test 120 { VACUUM; } {} do_execsql_test 130 { CREATE TABLE t2(x, y); WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100) INSERT INTO t2(x, y) SELECT x, randomblob(1000) FROM c; DROP TABLE t2; | > | 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | do_execsql_test 110 { SELECT * FROM t1; } {1 2} # What happens when we try to VACUUM a MEMDB database? # do_execsql_test 120 { PRAGMA auto_vacuum = off; VACUUM; } {} do_execsql_test 130 { CREATE TABLE t2(x, y); WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100) INSERT INTO t2(x, y) SELECT x, randomblob(1000) FROM c; DROP TABLE t2; |
︙ | ︙ |
Changes to test/misc8.test.
︙ | ︙ | |||
53 54 55 56 57 58 59 60 61 62 63 64 65 66 | BEGIN; CREATE TABLE t2(x); SELECT a, coalesce(b, eval('ROLLBACK; SELECT ''bam''')), c FROM t1 ORDER BY rowid; } {1 {abort due to ROLLBACK}} reset_db proc dbeval {sql} { db eval $sql } db func eval dbeval do_execsql_test misc8-2.1 { | > > > > | 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | BEGIN; CREATE TABLE t2(x); SELECT a, coalesce(b, eval('ROLLBACK; SELECT ''bam''')), c FROM t1 ORDER BY rowid; } {1 {abort due to ROLLBACK}} do_catchsql_test misc8-1.8 { PRAGMA empty_result_callbacks = 1; SELECT eval('SELECT * FROM t1 WHERE 1 = 0;'); } {0 {{}}} reset_db proc dbeval {sql} { db eval $sql } db func eval dbeval do_execsql_test misc8-2.1 { |
︙ | ︙ |
Added test/optfuzz-db01.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 | /* content of file testdb01.db */ unsigned char data001[] = { 83, 81, 76,105,116,101, 32,102,111,114,109, 97,116, 32, 51, 0, 2, 0, 1, 1, 0, 64, 32, 32, 0, 0, 0, 2, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 4, 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, 2, 0, 46, 32,152, 5, 0, 0, 0, 7, 1,221, 0, 0, 0, 0, 35, 1,251, 1,246, 1,241, 1,236, 1,231, 1,226, 1,221, 84, 4, 7, 23, 17, 17, 1, 129, 19,116, 97, 98,108,101,116, 52,116, 52, 5, 67, 82, 69, 65, 84, 69, 32, 84, 65, 66, 76, 69, 32,116, 52, 40, 97, 32, 73, 78, 84, 32, 85, 78, 73, 81, 85, 69, 32, 78, 79, 84, 32, 78, 85, 76, 76, 44, 32, 98, 32, 73, 78, 84, 32, 85, 78, 73, 81, 85, 69, 32, 78, 79, 84, 32, 78, 85, 76, 76, 44, 99, 44,100, 44,101, 41, 35, 6, 6, 23, 55, 17, 1, 0,105,110,100,101,120,115,113,108, 105,116,101, 95, 97,117,116,111,105,110,100,101,120, 95,116, 52, 95, 50,116, 52, 7, 35, 5, 6, 23, 55, 17, 1, 0,105,110,100,101,120,115,113,108,105, 116,101, 95, 97,117,116,111,105,110,100,101,120, 95,116, 52, 95, 49,116, 52, 6, 42, 3, 6, 23, 17, 17, 1, 65,116, 97, 98,108,101,116, 51,116, 51, 4, 67, 82, 69, 65, 84, 69, 32, 84, 65, 66, 76, 69, 32,116, 51, 40, 97, 44, 98, 44, 99, 44,100, 44,101, 41, 95, 2, 7, 23, 17, 17, 1,129, 41,116, 97, 98, 108,101,116, 50,116, 50, 3, 67, 82, 69, 65, 84, 69, 32, 84, 65, 66, 76, 69, 32,116, 50, 40, 97, 32, 73, 78, 84, 44, 32, 98, 32, 73, 78, 84, 44, 32, 99, 32, 73, 78, 84, 44,100, 32, 73, 78, 84, 44,101, 32, 73, 78, 84, 44, 80, 82, 73, 77, 65, 82, 89, 32, 75, 69, 89, 40, 98, 44, 97, 41, 41, 87, 73, 84, 72, 79, 85, 84, 32, 82, 79, 87, 73, 68, 83, 1, 7, 23, 17, 17, 1,129, 17,116, 97, 98,108,101,116, 49,116, 49, 2, 67, 82, 69, 65, 84, 69, 32, 84, 65, 66, 76, 69, 32,116, 49, 40, 97, 32, 73, 78, 84, 69, 71, 69, 82, 32, 80, 82, 73, 77, 65, 0, 0, 0, 34, 32, 0, 0, 0, 33, 29, 0, 0, 0, 32, 26, 0, 0, 0, 31, 23, 0, 0, 0, 30, 19, 0, 0, 0, 11, 14, 0, 0, 0, 9, 7, 5, 0, 0, 0, 1, 1,251, 0, 0, 0, 0, 16, 1,251, 1,195, 1,180, 1,166, 1,151, 1,136, 1,121, 1,105, 1, 91, 1, 76, 1, 61, 1, 46, 1, 29, 1, 14, 0,252, 0,238, 0,224, 0,209, 0,194, 0,177, 0,157, 0,143, 0,128, 0,110, 0, 94, 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 28, 6, 0, 1, 1, 1, 23, 17, 67, 31,119,111,114,107,115, 14, 27, 6, 0, 1, 1, 1, 23, 22, 71, 3, 97,110,103,101,108, 16, 26, 6, 0, 1, 1, 1, 27, 40, 98, 17,109,111,114,110,105,110,103, 13, 25, 6, 0, 1, 1, 1, 21, 10, 7, 19,103,111,110,101, 12, 24, 6, 0, 1, 1, 9, 21, 43, 46, 119, 97,121,115, 18, 23, 6, 0, 1, 1, 1, 31, 6, 37, 31,115, 97, 99,114, 105,102,105, 99,101, 15, 22, 6, 0, 1, 1, 1, 25, 45, 71, 28,116,104,111, 117,103,104, 13, 21, 6, 0, 1, 1, 1, 21, 22, 92, 18,115,111,109,101, 13, 20, 6, 0, 9, 1, 1, 23, 2, 45, 97, 98,111,118,101, 12, 19, 6, 0, 1, 1, 8, 21, 4, 58,119, 97,121,115, 12, 18, 6, 0, 1, 1, 1, 19, 44, 19, 43,119, 97,114, 16, 17, 6, 0, 1, 1, 1, 27, 29, 74, 36, 98,101,116,119, 101,101,110, 13, 16, 6, 0, 1, 1, 1, 21, 44, 52, 19,112,111,111,114, 15, 15, 6, 0, 1, 1, 1, 25, 6, 3, 11,116,101,109,112,108,101, 13, 14, 6, 0, 1, 1, 1, 21, 35, 48, 27,100,105,101,100, 13, 13, 6, 0, 1, 1, 1, 21, 4, 21, 39,100,111,116,104, 13, 12, 6, 0, 1, 1, 1, 21, 4, 38, 36, 115,101,110,100, 12, 11, 6, 0, 1, 1, 1, 19, 13, 48, 22,115,105,120, 14, 10, 6, 0, 1, 1, 1, 23, 41, 89, 14,115,101,114,118,101, 13, 9, 6, 0, 8, 1, 1, 23, 16, 50, 98,101,103, 97,116, 13, 8, 6, 0, 1, 1, 1, 21, 42, 49, 34,115,101,110,100, 13, 7, 6, 0, 1, 1, 1, 21, 21, 91, 38,110, 101, 97,114, 12, 6, 6, 0, 1, 1, 1, 19, 2, 37, 11, 99, 97,110, 13, 5, 6, 0, 1, 1, 1, 21, 25, 27, 28,103,111,110,101, 13, 4, 6, 0, 1, 1, 1, 21, 41, 32, 35,110,101, 97,114, 14, 3, 6, 0, 1, 1, 1, 23, 32, 24, 26,115,101,114,118,101, 13, 2, 6, 0, 1, 1, 1, 21, 45, 14, 39,115, 97, 118,101, 13, 1, 6, 0, 1, 1, 1, 21, 40, 68, 0, 0, 0, 15, 28, 2, 0, 0, 0, 1, 1,238, 0, 0, 0, 0, 22, 1,238, 1,197, 1,181, 1,166, 1, 151, 1,137, 1,121, 1,104, 1, 84, 1, 73, 1, 59, 1, 41, 1, 26, 1, 11, 0,253, 0,238, 0,223, 0,207, 0,191, 0,175, 0,159, 0,144, 0,129, 0, 113, 0, 97, 0, 82, 0, 68, 0, 0, 13, 6, 1, 1, 1, 1, 19, 26, 34, 15, 20, 97,114,107, 14, 6, 1, 1, 1, 1, 21, 25, 5, 27, 28,103,111,110,101, 15, 6, 1, 1, 1, 1, 23, 22, 47, 16, 40, 97,110,103,101,114, 15, 6, 1, 1, 1, 1, 23, 22, 27, 71, 3, 97,110,103,101,108, 14, 6, 1, 1, 1, 1, 21, 22, 21, 92, 18,115,111,109,101, 14, 6, 1, 1, 1, 1, 21, 21, 7, 91, 38,110,101, 97,114, 15, 6, 1, 1, 1, 1, 23, 20, 42, 18, 5, 98,101,103, 97,116, 15, 6, 1, 1, 1, 1, 23, 17, 37, 66, 18,100,119,101,108,116, 15, 6, 1, 1, 1, 1, 23, 17, 28, 67, 31,119,111,114,107,115, 15, 6, 1, 1, 1, 8, 25, 16, 32, 7,112,108, 97, 99,101,115, 14, 6, 1, 1, 1, 1, 21, 16, 30, 81, 25,119, 97,108,107, 14, 6, 1, 1, 1, 1, 21, 14, 40, 30, 26, 115,101,110,100, 13, 6, 1, 1, 1, 1, 19, 13, 11, 48, 22,115,105,120, 14, 6, 1, 1, 1, 1, 21, 10, 38, 97, 34,115,104,101,119, 14, 6, 1, 1, 1, 1, 21, 10, 25, 7, 19,103,111,110,101, 17, 6, 1, 1, 1, 1, 27, 9, 50, 92, 29,116,104,101,114,101,105,110, 13, 6, 1, 1, 1, 1, 19, 9, 49, 51, 38,111,105,108, 10, 6, 1, 1, 1, 1, 0, 7, 33, 72, 31, 19, 6, 1, 1, 1, 1, 31, 6, 23, 37, 31,115, 97, 99,114,105,102,105, 99,101, 16, 6, 1, 1, 1, 1, 25, 6, 15, 3, 11,116,101,109,112,108,101, 15, 6, 1, 1, 1, 1, 23, 5, 43, 23, 41, 98,101,103, 97,116, 13, 6, 1, 1, 1, 8, 21, 4, 19, 58,119, 97,121,115, 14, 6, 1, 1, 1, 1, 21, 4, 13, 21, 39,100,111, 116,104, 14, 6, 1, 1, 1, 1, 21, 4, 12, 38, 36,115,101,110,100, 15, 6, 1, 1, 1, 1, 23, 3, 39, 21, 45, 98,101,103, 97,116, 13, 6, 1, 1, 1, 1, 19, 2, 6, 37, 11, 99, 97,110, 14, 6, 9, 1, 1, 1, 23, 20, 2, 45, 97, 98,111,118,101, 14, 6, 8, 1, 1, 1, 23, 36, 52, 17, 99,104, 0, 0, 0, 21, 13, 6, 1, 1, 1, 1, 19, 26, 34, 15, 20, 97,114,107, 13, 0, 0, 0, 35, 0, 92, 0, 1,244, 1,232, 1,216, 1,204, 1,186, 1,171, 1,160, 1,149, 1,138, 1,128, 1,117, 1,106, 1, 92, 1, 76, 1, 65, 1, 49, 1, 32, 1, 21, 1, 10, 0,255, 0,241, 0,225, 0,214, 0,203, 0,192, 0,180, 0,168, 0,156, 0,144, 0,132, 0,124, 0,116, 0,108, 0,100, 0, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 35, 6, 0, 0, 0, 0, 0, 6, 34, 6, 0, 0, 0, 0, 0, 6, 33, 6, 0, 0, 0, 0, 0, 6, 32, 6, 0, 0, 0, 0, 0, 6, 31, 6, 0, 0, 0, 0, 0, 10, 30, 6, 1, 1, 1, 1, 0, 48, 37, 93, 7, 10, 29, 6, 1, 1, 1, 1, 0, 28, 17, 67, 31, 10, 28, 6, 1, 1, 1, 1, 0, 22, 45, 71, 28, 10, 27, 6, 1, 1, 1, 1, 0, 12, 4, 38, 36, 10, 26, 6, 1, 1, 1, 1, 0, 49, 9, 51, 38, 9, 25, 6, 1, 1, 1, 0, 0, 17, 29, 74, 9, 24, 6, 1, 1, 1, 0, 0, 47, 22, 16, 9, 23, 6, 1, 1, 1, 0, 0, 32, 16, 7, 14, 22, 6, 1, 1, 1, 0, 23, 42, 20, 18, 98,101,103, 97,116, 12, 21, 6, 1, 1, 1, 0, 19, 34, 26, 15, 97,114,107, 9, 20, 6, 1, 1, 0, 1, 0, 49, 9, 38, 9, 19, 6, 1, 1, 0, 1, 0, 44, 48, 9, 9, 18, 6, 1, 1, 0, 1, 0, 21, 22, 18, 15, 17, 6, 1, 1, 0, 1, 25, 35, 38, 22, 99,117, 98,105,116,115, 14, 16, 6, 1, 1, 0, 1, 23, 37, 17, 18,100,119,101,108,116, 9, 15, 6, 1, 0, 1, 1, 0, 49, 51, 38, 14, 14, 6, 1, 0, 1, 1, 23, 10, 89, 14,115,101, 114,118,101, 12, 13, 6, 9, 0, 1, 1, 21, 68, 32,100,111,116,104, 9, 12, 6, 1, 0, 1, 1, 0, 47, 16, 40, 9, 11, 6, 1, 0, 1, 1, 0, 25, 7, 19, 8, 10, 6, 0, 1, 1, 8, 0, 16, 7, 9, 9, 6, 0, 1, 1, 1, 0, 16, 81, 25, 9, 8, 6, 0, 1, 1, 1, 0, 7, 72, 31, 9, 7, 6, 0, 1, 1, 1, 0, 6, 37, 31, 13, 6, 6, 0, 1, 1, 1, 21, 21, 91, 38,110,101, 97,114, 16, 5, 6, 1, 1, 1, 1, 25, 15, 6, 3, 11,116,101,109,112,108, 101, 10, 4, 6, 1, 1, 1, 1, 0, 21, 22, 92, 18, 14, 3, 6, 1, 1, 1, 1, 21, 4, 41, 32, 35,110,101, 97,114, 10, 2, 6, 1, 1, 1, 1, 0, 46, 28, 88, 22, 10, 1, 6, 1, 1, 1, 1, 0, 17, 29, 74, 36, 13, 0, 0, 0, 15, 1, 71, 0, 1,243, 1,230, 1,217, 1,204, 1,191, 1,179, 1,167, 1, 155, 1,143, 1,131, 1,119, 1,107, 1, 95, 1, 83, 1, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 15, 6, 1, 1, 1, 1, 0, 48, 37, 93, 7, 10, 14, 6, 1, 1, 1, 1, 0, 22, 45, 71, 28, 10, 13, 6, 1, 1, 1, 1, 0, 12, 4, 38, 36, 10, 12, 6, 1, 1, 1, 0, 1, 32, 16, 7, 79, 10, 11, 6, 1, 1, 1, 0, 1, 42, 20, 18, 19, 10, 10, 6, 1, 1, 1, 0, 1, 34, 26, 15, 13, 10, 9, 6, 1, 1, 0, 1, 1, 49, 9, 38, 97, 10, 8, 6, 1, 1, 0, 1, 1, 44, 48, 9, 90, 10, 7, 6, 1, 1, 0, 1, 1, 35, 38, 22, 33, 10, 6, 6, 1, 1, 0, 1, 1, 37, 17, 18, 18, 11, 5, 6, 1, 1, 1, 1, 1, 15, 6, 3, 11, 43, 11, 4, 6, 1, 1, 1, 1, 1, 21, 22, 92, 18, 62, 11, 3, 6, 1, 1, 1, 1, 1, 4, 41, 32, 35, 36, 11, 2, 6, 1, 1, 1, 1, 1, 46, 28, 88, 22, 77, 11, 1, 6, 1, 1, 1, 1, 1, 17, 29, 74, 36, 61, 10, 0, 0, 0, 15, 1,167, 0, 1,250, 1,244, 1,238, 1,233, 1,227, 1,221, 1,215, 1,209, 1,203, 1,197, 1,191, 1,185, 1,179, 1,173, 1,167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 3, 1, 1, 49, 9, 5, 3, 1, 1, 48, 15, 5, 3, 1, 1, 46, 2, 5, 3, 1, 1, 44, 8, 5, 3, 1, 1, 42, 11, 5, 3, 1, 1, 37, 6, 5, 3, 1, 1, 35, 7, 5, 3, 1, 1, 34, 10, 5, 3, 1, 1, 32, 12, 5, 3, 1, 1, 22, 14, 5, 3, 1, 1, 21, 4, 4, 3, 1, 9, 17, 5, 3, 1, 1, 15, 5, 5, 3, 1, 1, 12, 13, 5, 3, 1, 1, 4, 3, 10, 0, 0, 0, 15, 1, 167, 0, 1,250, 1,244, 1,238, 1,232, 1,226, 1,220, 1,214, 1,208, 1, 202, 1,197, 1,191, 1,185, 1,179, 1,173, 1,167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 3, 1, 1, 48, 8, 5, 3, 1, 1, 45, 14, 5, 3, 1, 1, 41, 3, 5, 3, 1, 1, 38, 7, 5, 3, 1, 1, 37, 15, 4, 3, 1, 9, 29, 5, 3, 1, 1, 28, 2, 5, 3, 1, 1, 26, 10, 5, 3, 1, 1, 22, 4, 5, 3, 1, 1, 20, 11, 5, 3, 1, 1, 17, 6, 5, 3, 1, 1, 16, 12, 5, 3, 1, 1, 9, 9, 5, 3, 1, 1, 6, 5, 5, 3, 1, 1, 4, 13, 5, 0, 0, 0, 2, 1,246, 0, 0, 0, 0, 27, 1,251, 1,246, 1,168, 1,148, 1,130, 1,107, 1, 86, 1, 65, 1, 44, 1, 27, 1, 14, 0,250, 0,224, 0,205, 0,184, 0,165, 0, 145, 0,123, 0,106, 0, 86, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 23, 6, 0, 23, 1, 1, 21,107,110,111,119,110, 52, 19,112, 111,111,114, 18, 22, 6, 0, 23, 1, 1, 23, 97, 98,111,118,101, 24, 26,115, 101,114,118,101, 15, 21, 6, 0, 19, 1, 1, 21,119, 97,114, 52, 19,112,111, 111,114, 20, 20, 6, 0, 27, 1, 8, 25,110,111,116,104,105,110,103, 7,112, 108, 97, 99,101,115, 18, 19, 6, 0, 23, 1, 1, 23, 98,101,103, 97,116, 90, 27,116,114,117,116,104, 17, 18, 6, 0, 23, 1, 1, 21,100,119,101,108,116, 21, 39,100,111,116,104, 19, 17, 6, 0, 27, 1, 1, 21,109,111,114,110,105, 110,103, 52, 19,112,111,111,114, 17, 16, 6, 0, 21, 1, 1, 23,115,104,101, 119, 90, 27,116,114,117,116,104, 24, 15, 6, 0, 27, 1, 1, 31,116,104,101, 114,101,105,110, 37, 31,115, 97, 99,114,105,102,105, 99,101, 18, 14, 6, 0, 23, 1, 8, 25,115,109,111,116,101, 7,112,108, 97, 99,101,115, 11, 13, 6, 0, 19, 1, 1, 0, 97,114,107, 72, 31, 15, 12, 6, 0, 21, 1, 8, 21,119, 105,110,101, 58,119, 97,121,115, 19, 11, 6, 0, 21, 1, 1, 27,115,111,109, 101, 98, 17,109,111,114,110,105,110,103, 19, 10, 6, 0, 27, 1, 1, 21, 98, 101,116,119,101,101,110, 92, 18,115,111,109,101, 19, 9, 6, 0, 21, 1, 1, 27,115, 97,118,101, 74, 36, 98,101,116,119,101,101,110, 21, 8, 6, 0, 25, 1, 1, 27,116,104,111,117,103,104, 98, 17,109,111,114,110,105,110,103, 16, 7, 6, 0, 21, 1, 1, 21,115,101,110,100, 49, 34,115,101,110,100, 18, 6, 6, 0, 25, 1, 1, 21,119,105,115,100,111,109, 38, 36,115,101,110,100, 16, 5, 6, 0, 23, 1, 9, 21, 97,110,103,101,114, 46,119, 97,121,115, 14, 4, 6, 0, 19, 1, 1, 19, 99, 97,110, 19, 43,119, 97,114, 16, 3, 6, 0, 23, 1, 1, 19,111,102,102,101,114, 48, 22,115,105,120, 16, 2, 6, 0, 23, 1, 8, 21,119,111,114,107,115, 58,119, 97,121,115, 16, 1, 6, 0, 23, 1, 1, 19, 0, 0, 0, 26, 45, 0, 0, 0, 25, 23, 13, 0, 0, 0, 7, 0, 48, 0, 1,171, 1, 74, 1, 30, 0,126, 0,249, 0,212, 0, 48, 0, 81, 0, 0, 84, 4, 7, 23, 17, 17, 1,129, 19,116, 97, 98,108,101,116, 52,116, 52, 5, 67, 82, 69, 76, 7, 7, 23, 17, 17, 1,129, 3,116, 97, 98,108,101,116, 53,116, 53, 8, 67, 82, 69, 65, 84, 69, 32, 84, 65, 66, 76, 69, 32,116, 53, 40, 97, 32, 73, 78, 84, 69, 71, 69, 82, 32, 80, 82, 73, 77, 65, 82, 89, 32, 75, 69, 89, 44, 32, 98, 32, 84, 69, 88, 84, 32, 85, 78, 73, 81, 85, 69, 44, 99, 44, 100, 44,101, 41, 84, 4, 7, 23, 17, 17, 1,129, 19,116, 97, 98,108,101,116, 52,116, 52, 5, 67, 82, 69, 65, 84, 69, 32, 84, 65, 66, 76, 69, 32,116, 52, 40, 97, 32, 73, 78, 84, 32, 85, 78, 73, 81, 85, 69, 32, 78, 79, 84, 32, 78, 85, 76, 76, 44, 32, 98, 32, 73, 78, 84, 32, 85, 78, 73, 81, 85, 69, 32, 78, 79, 84, 32, 78, 85, 76, 76, 44, 99, 44,100, 44,101, 41, 35, 6, 6, 23, 55, 17, 1, 0,105,110,100,101,120,115,113,108,105,116,101, 95, 97,117,116,111, 105,110,100,101,120, 95,116, 52, 95, 50,116, 52, 7, 35, 5, 6, 23, 55, 17, 1, 0,105,110,100,101,120,115,113,108,105,116,101, 95, 97,117,116,111,105, 110,100,101,120, 95,116, 52, 95, 49,116, 52, 6, 42, 3, 6, 23, 17, 17, 1, 65,116, 97, 98,108,101,116, 51,116, 51, 4, 67, 82, 69, 65, 84, 69, 32, 84, 65, 66, 76, 69, 32,116, 51, 40, 97, 44, 98, 44, 99, 44,100, 44,101, 41, 95, 2, 7, 23, 17, 17, 1,129, 41,116, 97, 98,108,101,116, 50,116, 50, 3, 67, 82, 69, 65, 84, 69, 32, 84, 65, 66, 76, 69, 32,116, 50, 40, 97, 32, 73, 78, 84, 44, 32, 98, 32, 73, 78, 84, 44, 32, 99, 32, 73, 78, 84, 44,100, 32, 73, 78, 84, 44,101, 32, 73, 78, 84, 44, 80, 82, 73, 77, 65, 82, 89, 32, 75, 69, 89, 40, 98, 44, 97, 41, 41, 87, 73, 84, 72, 79, 85, 84, 32, 82, 79, 87, 73, 68, 83, 1, 7, 23, 17, 17, 1,129, 17,116, 97, 98,108,101,116, 49,116, 49, 2, 67, 82, 69, 65, 84, 69, 32, 84, 65, 66, 76, 69, 32,116, 49, 40, 97, 32, 73, 78, 84, 69, 71, 69, 82, 32, 80, 82, 73, 77, 65, 82, 89, 32, 75, 69, 89, 44, 32, 98, 32, 73, 78, 84, 44, 32, 99, 32, 73, 78, 84, 44, 32,100, 32, 73, 78, 84, 44, 32,101, 32, 73, 78, 84, 41, 2, 0, 0, 0, 1, 1,243, 0, 0, 0, 0, 29, 1,243, 1,218, 1,209, 1,199, 1,187, 1,179, 1,169, 1,158, 1,145, 1,136, 1,127, 1,117, 1,107, 1, 98, 1, 82, 1, 72, 1, 63, 1, 51, 1, 42, 1, 30, 1, 20, 1, 12, 1, 3, 0,248, 0,239, 0,225, 0,216, 0,207, 0,197, 0,188, 0,180, 0,170, 0,161, 0,152, 0,141, 0,129, 0, 118, 0,106, 0, 97, 0, 0, 0, 0, 0, 0, 0, 8, 3, 21, 1,116,114,101, 101, 49, 11, 3, 27, 1,116,104,121,115,101,108,102, 27, 10, 3, 25, 1,116, 104,111,117,103,104, 8, 11, 3, 27, 1,116,104,101,114,101,105,110, 15, 10, 3, 25, 1,116,101,109,112,108,101, 43, 8, 3, 21, 1,116,101,108,108, 25, 8, 3, 21, 1,115,111,109,101, 11, 9, 3, 23, 1,115,109,111,116,101, 14, 7, 3, 19, 1,115,105,120, 48, 8, 3, 21, 1,115,104,101,119, 16, 9, 3, 23, 1,115,101,114,118,101, 37, 8, 3, 21, 1,115,101,110,100, 7, 8, 3, 21, 1,115, 97,118,101, 9, 13, 3, 31, 1,115, 97, 99,114,105,102,105, 99, 101, 24, 8, 3, 21, 1,112,111,111,114, 40, 10, 3, 25, 1,112,108, 97, 99, 101,115, 28, 8, 3, 21, 1,112, 97,114,116, 30, 7, 3, 19, 1,111,105,108, 46, 9, 3, 23, 1,111,102,102,101,114, 3, 11, 3, 27, 1,110,111,116,104, 105,110,103, 20, 8, 3, 21, 1,110,101, 97,114, 36, 11, 3, 27, 1,109,111, 114,110,105,110,103, 17, 8, 3, 21, 1,108,111,110,103, 35, 9, 3, 23, 1, 107,110,111,119,110, 23, 15, 3, 35, 1,105,110,104, 97, 98,105,116, 97,110, 116,115, 45, 8, 3, 21, 1,103,111,110,101, 32, 9, 3, 23, 1,102,114,117, 105,116, 38, 9, 3, 23, 1,100,119,101,108,116, 18, 8, 3, 21, 1,100,111, 116,104, 39, 8, 3, 21, 1,100,105,101,100, 47, 12, 3, 29, 1,100,101,112, 97,114,116,101,100, 26, 10, 3, 25, 1, 99,117, 98,105,116,115, 33, 9, 3, 23, 1, 99,104,105,108,100, 42, 7, 3, 19, 1, 99, 97,110, 4, 11, 3, 27, 1, 98,101,116,119,101,101,110, 10, 9, 3, 23, 1, 98,101,103, 97,116, 19, 8, 3, 21, 1, 98,101, 97,114, 29, 7, 3, 19, 1, 97,114,107, 13, 9, 3, 23, 1, 97,110,103,101,114, 5, 9, 3, 23, 1, 97,110,103, 0, 0, 0, 28, 8, 3, 21, 1,116,114,101,101, 49, 13, 1,104, 0, 7, 0, 24, 0, 1, 67, 1, 13, 0,225, 0,177, 0,109, 1,171, 0, 24, 0, 0, 83, 14, 7, 21, 19, 19, 8,129, 17,118,105,101,119,118, 50, 48,118, 50, 48, 67, 82, 69, 65, 84, 69, 32, 86, 73, 69, 87, 32,118, 50, 48, 40, 97, 44, 98, 44, 99, 44,100, 44, 101, 41, 32, 65, 83, 32, 83, 69, 76, 69, 67, 84, 32, 97, 44, 98, 44, 99, 44, 100, 44,101, 32, 70, 82, 79, 77, 32,116, 50, 32, 87, 72, 69, 82, 69, 32, 97, 60, 62, 50, 53, 66, 12, 6, 21, 19, 19, 8,113,118,105,101,119,118, 48, 48, 118, 48, 48, 67, 82, 69, 65, 84, 69, 32, 86, 73, 69, 87, 32,118, 48, 48, 40, 97, 44, 98, 44, 99, 44,100, 44,101, 41, 32, 65, 83, 32, 83, 69, 76, 69, 67, 84, 32, 49, 44, 49, 44, 49, 44, 49, 44, 39,111,110,101, 39, 46, 11, 6, 23, 21, 17, 1, 69,105,110,100,101,120,116, 50,101,100,116, 50, 14, 67, 82, 69, 65, 84, 69, 32, 73, 78, 68, 69, 88, 32,116, 50,101,100, 32, 79, 78, 32,116, 50, 40,101, 44,100, 41, 42, 10, 6, 23, 19, 17, 1, 63,105,110,100,101,120, 116, 49,101,116, 49, 13, 67, 82, 69, 65, 84, 69, 32, 73, 78, 68, 69, 88, 32, 116, 49,101, 32, 79, 78, 32,116, 49, 40,101, 41, 52, 9, 6, 23, 21, 17, 1, 81,105,110,100,101,120,116, 51,120, 49,116, 51, 12, 67, 82, 69, 65, 84, 69, 32, 73, 78, 68, 69, 88, 32,116, 51,120, 49, 32, 79, 78, 32,116, 51, 40, 97, 44, 98, 44, 99, 44,100, 44,101, 41, 35, 8, 6, 23, 55, 17, 1, 0,105,110, 100,101,120,115,113,108,105,116,101, 95, 97,117,116,111,105,110,100,101,120, 95,116, 53, 95, 49,116, 53, 10, 0, 0, 0, 67, 17, 17, 1,129, 3,116, 97, 98,108,101,116, 53,116, 53, 8, 67, 82, 69, 65, 84, 69, 32, 84, 65, 66, 76, 69, 32,116, 53, 40, 97, 32, 73, 78, 84, 69, 71, 69, 82, 32, 80, 82, 73, 77, 65, 82, 89, 32, 75, 69, 89, 44, 32, 98, 32, 84, 69, 88, 84, 32, 85, 78, 83, 13, 7, 21, 19, 19, 8,129, 17,118,105,101,119,118, 49, 48,118, 49, 48, 67, 82, 69, 65, 84, 69, 32, 86, 73, 69, 87, 32,118, 49, 48, 40, 97, 44, 98, 44, 99, 44,100, 44,101, 41, 32, 65, 83, 32, 83, 69, 76, 69, 67, 84, 32, 97, 44, 98, 44, 99, 44,100, 44,101, 32, 70, 82, 79, 77, 32,116, 49, 32, 87, 72, 69, 82, 69, 32, 97, 60, 62, 50, 53, 2, 0, 0, 0, 1, 1,240, 0, 0, 0, 0, 24, 1,240, 1,220, 1,211, 1,199, 1,187, 1,176, 1,164, 1,148, 1,133, 1,116, 1, 99, 1, 86, 1, 67, 1, 55, 1, 43, 1, 31, 1, 18, 1, 5, 0, 249, 0,236, 0,224, 0,209, 0,191, 0,174, 0,157, 0,145, 0,132, 0,120, 0,108, 0, 95, 0, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 7, 1, 0, 1, 1, 0, 1, 49, 51, 38, 15, 12, 7, 1, 1, 1, 1, 0, 1, 48, 37, 93, 7, 30, 11, 7, 1, 1, 1, 0, 0, 1, 47, 22, 16, 24, 11, 7, 1, 0, 1, 1, 0, 1, 47, 16, 40, 12, 12, 7, 1, 1, 1, 1, 0, 1, 46, 28, 88, 22, 2, 11, 7, 1, 1, 0, 1, 0, 1, 44, 48, 9, 19, 16, 7, 1, 1, 1, 0, 23, 1, 42, 20, 18, 98,101,103, 97,116, 22, 16, 7, 1, 1, 0, 1, 23, 1, 37, 17, 18,100,119,101,108,116, 16, 17, 7, 1, 1, 0, 1, 25, 1, 35, 38, 22, 99,117, 98,105,116,115, 17, 14, 7, 1, 1, 1, 0, 19, 1, 34, 26, 15, 97,114,107, 21, 11, 7, 1, 1, 1, 0, 0, 1, 32, 16, 7, 23, 12, 7, 1, 1, 1, 1, 0, 1, 28, 17, 67, 31, 29, 11, 7, 1, 0, 1, 1, 0, 1, 25, 7, 19, 11, 12, 7, 1, 1, 1, 1, 0, 1, 22, 45, 71, 28, 28, 12, 7, 1, 1, 1, 1, 0, 1, 21, 22, 92, 18, 4, 11, 7, 1, 1, 0, 1, 0, 1, 21, 22, 18, 18, 11, 7, 1, 1, 1, 1, 0, 9, 17, 29, 74, 36, 11, 7, 1, 1, 1, 0, 0, 1, 17, 29, 74, 25, 18, 7, 1, 1, 1, 1, 25, 1, 15, 6, 3, 11,116,101,109,112,108,101, 5, 12, 7, 1, 1, 1, 1, 0, 1, 12, 4, 38, 36, 27, 16, 7, 1, 0, 1, 1, 23, 1, 10, 89, 14,115,101,114,118,101, 14, 16, 7, 1, 1, 1, 1, 21, 1, 4, 41, 32, 35,110,101, 97,114, 3, 14, 7, 9, 0, 1, 1, 21, 1, 68, 32,100,111,116,104, 13, 15, 7, 0, 1, 1, 1, 21, 1, 21, 91, 38,110,101, 97,114, 6, 11, 7, 0, 1, 1, 1, 0, 1, 16, 81, 25, 9, 10, 7, 0, 1, 1, 8, 0, 1, 16, 7, 10, 11, 7, 0, 1, 1, 1, 0, 1, 7, 72, 31, 8, 11, 7, 0, 1, 1, 1, 0, 1, 6, 37, 31, 7, 8, 7, 0, 0, 0, 0, 0, 1, 35, 8, 7, 0, 0, 0, 0, 0, 1, 34, 8, 7, 0, 0, 0, 0, 0, 1, 33, 8, 7, 0, 0, 0, 23, 11, 7, 1, 0, 1, 1, 0, 1, 49, 51, 38, 15, 2, 0, 0, 0, 1, 1,241, 0, 0, 0, 0, 18, 1,241, 1,221, 1,211, 1,203, 1,193, 1,183, 1,173, 1,163, 1,151, 1, 143, 1,133, 1,122, 1,109, 1,100, 1, 92, 1, 83, 1, 74, 1, 64, 1, 55, 1, 46, 1, 34, 1, 22, 1, 13, 1, 4, 0,252, 0,241, 0,232, 0,218, 0, 209, 0,200, 0,191, 0,182, 0,173, 0,163, 0,153, 0,144, 0,136, 0,127, 0,116, 0,105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 3, 25, 1,116,101,109,112,108,101, 48, 10, 3, 25, 1,116,101,109,112,108,101, 15, 8, 3, 21, 1,115,111,109,101, 21, 7, 3, 19, 1,115,105,120, 11, 8, 3, 21, 1,115,104,101,119, 38, 9, 3, 23, 1,115,101,114,118,101, 10, 9, 3, 23, 1,115,101,114,118,101, 3, 8, 3, 21, 1,115,101,110,100, 40, 8, 3, 21, 1,115,101,110,100, 29, 8, 3, 21, 1,115,101,110,100, 12, 8, 3, 21, 1,115,101,110,100, 8, 8, 3, 21, 1,115, 97,118,101, 2, 13, 3, 31, 1,115, 97, 99,114,105,102,105, 99,101, 23, 8, 3, 21, 1,112,111,111,114, 16, 10, 3, 25, 1,112,108, 97, 99,101,115, 32, 7, 3, 19, 1,111,105,108, 49, 8, 3, 21, 1,110,101, 97,114, 7, 8, 3, 21, 1,110,101, 97,114, 4, 11, 3, 27, 1,109,111,114,110,105,110,103, 41, 11, 3, 27, 1,109,111,114, 110,105,110,103, 26, 8, 3, 21, 1,103,111,110,101, 25, 8, 3, 21, 1,103, 111,110,101, 5, 9, 3, 23, 1,100,119,101,108,116, 37, 8, 3, 21, 1,100, 111,116,104, 44, 8, 3, 21, 1,100,111,116,104, 13, 7, 3, 21, 9,100,111, 116,104, 8, 3, 21, 1,100,105,101,100, 14, 12, 3, 29, 1,100,101,112, 97, 114,116,101,100, 46, 10, 3, 25, 1, 99,117, 98,105,116,115, 35, 9, 3, 23, 1, 99,104,105,108,100, 36, 7, 3, 19, 1, 99, 97,110, 6, 11, 3, 27, 1, 98,101,116,119,101,101,110, 17, 9, 3, 23, 1, 98,101,103, 97,116, 43, 9, 3, 23, 1, 98,101,103, 97,116, 42, 9, 3, 23, 1, 98,101,103, 97,116, 39, 9, 3, 23, 1, 98,101,103, 97,116, 9, 7, 3, 19, 1, 97,114,107, 34, 9, 3, 23, 1, 97,110,103,101,114, 47, 9, 3, 23, 1, 97,110,103,101,108, 27, 9, 3, 23, 1, 97, 98,111,118,101, 45, 0, 0, 0, 17, 10, 3, 25, 1,116, 101,109,112,108,101, 48, 2, 0, 0, 0, 1, 1,239, 0, 0, 0, 0, 20, 1, 239, 1,206, 1,192, 1,180, 1,166, 1,152, 1,138, 1,125, 1,109, 1, 97, 1, 84, 1, 69, 1, 52, 1, 39, 1, 26, 1, 14, 1, 1, 0,243, 0,230, 0, 217, 0,201, 0,185, 0,172, 0,159, 0,147, 0,133, 0,120, 0,102, 0, 89, 0, 76, 0, 0, 0, 0, 12, 5, 21, 1, 1, 1,115,101,110,100, 26, 14, 40, 12, 5, 21, 1, 1, 1,115, 97,118,101, 39, 45, 2, 17, 5, 31, 1, 1, 1, 115, 97, 99,114,105,102,105, 99,101, 31, 6, 23, 12, 5, 21, 1, 1, 1,112, 111,111,114, 19, 44, 16, 13, 5, 25, 8, 1, 1,112,108, 97, 99,101,115, 16, 32, 11, 5, 19, 1, 1, 1,111,105,108, 38, 9, 49, 12, 5, 21, 1, 1, 1, 110,101, 97,114, 38, 21, 7, 12, 5, 21, 1, 1, 1,110,101, 97,114, 35, 41, 4, 15, 5, 27, 1, 1, 1,109,111,114,110,105,110,103, 17, 40, 26, 15, 5, 27, 1, 1, 1,109,111,114,110,105,110,103, 13, 46, 41, 12, 5, 21, 1, 1, 1,103,111,110,101, 28, 25, 5, 12, 5, 21, 1, 1, 1,103,111,110,101, 19, 10, 25, 13, 5, 23, 1, 1, 1,100,119,101,108,116, 18, 17, 37, 12, 5, 21, 1, 1, 1,100,111,116,104, 39, 4, 13, 11, 5, 21, 1, 1, 9,100,111,116, 104, 32, 40, 12, 5, 21, 1, 1, 1,100,111,116,104, 9, 48, 44, 12, 5, 21, 1, 1, 1,100,105,101,100, 27, 35, 14, 16, 5, 29, 1, 1, 1,100,101,112, 97,114,116,101,100, 22, 28, 46, 14, 5, 25, 1, 1, 1, 99,117, 98,105,116, 115, 22, 38, 35, 12, 5, 23, 1, 8, 1, 99,104,105,108,100, 17, 36, 11, 5, 19, 1, 1, 1, 99, 97,110, 11, 2, 6, 15, 5, 27, 1, 1, 1, 98,101,116, 119,101,101,110, 36, 29, 17, 12, 5, 23, 1, 8, 1, 98,101,103, 97,116, 50, 9, 13, 5, 23, 1, 1, 1, 98,101,103, 97,116, 45, 3, 39, 13, 5, 23, 1, 1, 1, 98,101,103, 97,116, 41, 5, 43, 13, 5, 23, 1, 1, 1, 98,101,103, 97,116, 5, 20, 42, 11, 5, 19, 1, 1, 1, 97,114,107, 20, 26, 34, 13, 5, 23, 1, 1, 1, 97,110,103,101,114, 40, 22, 47, 13, 5, 23, 1, 1, 1, 97, 110,103,101,108, 3, 22, 27, 12, 5, 23, 1, 9, 1, 97, 98,111,118,101, 45, 20, 13, 5, 23, 1, 1, 1, 0, 0, 0, 19, 12, 5, 21, 1, 1, 1,115,101, 110,100, 26, 14, 40, 13, 0, 0, 0, 28, 0, 78, 0, 1,241, 1,226, 1,210, 1,195, 1,180, 1,166, 1,151, 1,136, 1,121, 1,105, 1, 91, 1, 76, 1, 61, 1, 46, 1, 29, 1, 14, 0,252, 0,238, 0,224, 0,209, 0,194, 0,177, 0,157, 0,143, 0,128, 0,110, 0, 94, 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 28, 6, 0, 1, 1, 1, 23, 17, 67, 31,119, 111,114,107,115, 14, 27, 6, 0, 1, 1, 1, 23, 22, 71, 3, 97,110,103,101, 108, 16, 26, 6, 0, 1, 1, 1, 27, 40, 98, 17,109,111,114,110,105,110,103, 13, 25, 6, 0, 1, 1, 1, 21, 10, 7, 19,103,111,110,101, 12, 24, 6, 0, 1, 1, 9, 21, 43, 46,119, 97,121,115, 18, 23, 6, 0, 1, 1, 1, 31, 6, 37, 31,115, 97, 99,114,105,102,105, 99,101, 15, 22, 6, 0, 1, 1, 1, 25, 45, 71, 28,116,104,111,117,103,104, 13, 21, 6, 0, 1, 1, 1, 21, 22, 92, 18,115,111,109,101, 13, 20, 6, 0, 9, 1, 1, 23, 2, 45, 97, 98,111,118, 101, 12, 19, 6, 0, 1, 1, 8, 21, 4, 58,119, 97,121,115, 12, 18, 6, 0, 1, 1, 1, 19, 44, 19, 43,119, 97,114, 16, 17, 6, 0, 1, 1, 1, 27, 29, 74, 36, 98,101,116,119,101,101,110, 13, 16, 6, 0, 1, 1, 1, 21, 44, 52, 19,112,111,111,114, 15, 15, 6, 0, 1, 1, 1, 25, 6, 3, 11,116,101,109, 112,108,101, 13, 14, 6, 0, 1, 1, 1, 21, 35, 48, 27,100,105,101,100, 13, 13, 6, 0, 1, 1, 1, 21, 4, 21, 39,100,111,116,104, 13, 12, 6, 0, 1, 1, 1, 21, 4, 38, 36,115,101,110,100, 12, 11, 6, 0, 1, 1, 1, 19, 13, 48, 22,115,105,120, 14, 10, 6, 0, 1, 1, 1, 23, 41, 89, 14,115,101,114, 118,101, 13, 9, 6, 0, 8, 1, 1, 23, 16, 50, 98,101,103, 97,116, 13, 8, 6, 0, 1, 1, 1, 21, 42, 49, 34,115,101,110,100, 13, 7, 6, 0, 1, 1, 1, 21, 21, 91, 38,110,101, 97,114, 12, 6, 6, 0, 1, 1, 1, 19, 2, 37, 11, 99, 97,110, 13, 5, 6, 0, 1, 1, 1, 21, 25, 27, 28,103,111,110,101, 13, 4, 6, 0, 1, 1, 1, 21, 41, 32, 35,110,101, 97,114, 14, 3, 6, 0, 1, 1, 1, 23, 32, 24, 26,115,101,114,118,101, 13, 2, 6, 0, 1, 1, 1, 21, 45, 14, 39,115, 97,118,101, 13, 1, 6, 0, 1, 1, 1, 21, 40, 68, 32, 100,111,116,104, 13, 0, 0, 0, 22, 0,166, 0, 1,241, 1,226, 1,210, 1, 194, 1,183, 1,169, 1,152, 1,137, 1,121, 1,106, 1, 90, 1, 75, 1, 57, 1, 41, 1, 25, 1, 10, 0,250, 0,231, 0,215, 0,198, 0,184, 0,166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 50, 6, 0, 1, 1, 1, 27, 9, 92, 29,116,104,101,114,101,105,110, 12, 49, 6, 0, 1, 1, 1, 19, 9, 51, 38,111,105,108, 15, 48, 6, 0, 1, 1, 1, 25, 37, 93, 7,116,101,109,112,108,101, 14, 47, 6, 0, 1, 1, 1, 23, 22, 16, 40, 97,110,103,101,114, 17, 46, 6, 0, 1, 1, 1, 29, 28, 88, 22,100, 101,112, 97,114,116,101,100, 14, 45, 6, 0, 1, 1, 1, 23, 47, 54, 12, 97, 98,111,118,101, 13, 44, 6, 0, 1, 1, 1, 21, 48, 15, 9,100,111,116,104, 14, 43, 6, 0, 1, 1, 1, 23, 5, 23, 41, 98,101,103, 97,116, 14, 42, 6, 0, 1, 1, 1, 23, 20, 18, 5, 98,101,103, 97,116, 16, 41, 6, 0, 1, 1, 1, 27, 46, 92, 13,109,111,114,110,105,110,103, 13, 40, 6, 0, 1, 1, 1, 21, 14, 30, 26,115,101,110,100, 14, 39, 6, 0, 1, 1, 1, 23, 3, 21, 45, 98,101,103, 97,116, 13, 38, 6, 0, 1, 1, 1, 21, 10, 97, 34,115,104,101, 119, 14, 37, 6, 0, 1, 1, 1, 23, 17, 66, 18,100,119,101,108,116, 13, 36, 6, 0, 8, 1, 1, 23, 52, 17, 99,104,105,108,100, 15, 35, 6, 0, 1, 1, 1, 25, 38, 34, 22, 99,117, 98,105,116,115, 12, 34, 6, 0, 1, 1, 1, 19, 26, 15, 20, 97,114,107, 9, 33, 6, 0, 1, 1, 1, 0, 7, 72, 31, 14, 32, 6, 0, 1, 1, 8, 25, 16, 7,112,108, 97, 99,101,115, 14, 31, 6, 0, 1, 1, 1, 23, 39, 90, 27,116,114,117,116,104, 13, 30, 6, 0, 1, 1, 1, 21, 16, 81, 25,119, 97,108,107, 13, 29, 6, 0, 1, 1, 1, 21, 34, 62, 27,115, 101,110,100, 10, 0, 0, 0, 41, 0,116, 0, 1,251, 1,241, 1,231, 1,221, 1,211, 1,203, 1,193, 1,183, 1,173, 1,163, 1,151, 1,143, 1,133, 1, 122, 1,109, 1,100, 1, 92, 1, 83, 1, 74, 1, 64, 1, 55, 1, 46, 1, 34, 1, 22, 1, 13, 1, 4, 0,252, 0,241, 0,232, 0,218, 0,209, 0,200, 0, 191, 0,182, 0,173, 0,163, 0,153, 0,144, 0,136, 0,127, 0,116, 0,105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11,116,101, 109,112,108,101, 48, 10, 3, 25, 1,116,101,109,112,108,101, 15, 8, 3, 21, 1,115,111,109,101, 21, 7, 3, 19, 1,115,105,120, 11, 8, 3, 21, 1,115, 104,101,119, 38, 9, 3, 23, 1,115,101,114,118,101, 10, 9, 3, 23, 1,115, 101,114,118,101, 3, 8, 3, 21, 1,115,101,110,100, 40, 8, 3, 21, 1,115, 101,110,100, 29, 8, 3, 21, 1,115,101,110,100, 12, 8, 3, 21, 1,115,101, 110,100, 8, 8, 3, 21, 1,115, 97,118,101, 2, 13, 3, 31, 1,115, 97, 99, 114,105,102,105, 99,101, 23, 8, 3, 21, 1,112,111,111,114, 16, 10, 3, 25, 1,112,108, 97, 99,101,115, 32, 7, 3, 19, 1,111,105,108, 49, 8, 3, 21, 1,110,101, 97,114, 7, 8, 3, 21, 1,110,101, 97,114, 4, 11, 3, 27, 1, 109,111,114,110,105,110,103, 41, 11, 3, 27, 1,109,111,114,110,105,110,103, 26, 8, 3, 21, 1,103,111,110,101, 25, 8, 3, 21, 1,103,111,110,101, 5, 9, 3, 23, 1,100,119,101,108,116, 37, 8, 3, 21, 1,100,111,116,104, 44, 8, 3, 21, 1,100,111,116,104, 13, 7, 3, 21, 9,100,111,116,104, 8, 3, 21, 1,100,105,101,100, 14, 12, 3, 29, 1,100,101,112, 97,114,116,101,100, 46, 10, 3, 25, 1, 99,117, 98,105,116,115, 35, 9, 3, 23, 1, 99,104,105, 108,100, 36, 7, 3, 19, 1, 99, 97,110, 6, 11, 3, 27, 1, 98,101,116,119, 101,101,110, 17, 9, 3, 23, 1, 98,101,103, 97,116, 43, 9, 3, 23, 1, 98, 101,103, 97,116, 42, 9, 3, 23, 1, 98,101,103, 97,116, 39, 9, 3, 23, 1, 98,101,103, 97,116, 9, 7, 3, 19, 1, 97,114,107, 34, 9, 3, 23, 1, 97, 110,103,101,114, 47, 9, 3, 23, 1, 97,110,103,101,108, 27, 9, 3, 23, 1, 97, 98,111,118,101, 45, 9, 3, 23, 1, 97, 98,111,118,101, 20, 4, 3, 0, 1, 33, 10, 0, 0, 0, 8, 1,178, 0, 1,244, 1,233, 1,223, 1,214, 1, 206, 1,197, 1,188, 1,178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 3, 23, 1,119,111,114,107,115, 28, 8, 3, 21, 1,119, 97,121,115, 24, 8, 3, 21, 1,119, 97,121,115, 19, 7, 3, 19, 1,119, 97,114, 18, 8, 3, 21, 1,119, 97,108,107, 30, 9, 3, 23, 1,116,114,117,116,104, 31, 10, 3, 25, 1,116,104,111,117,103,104, 22, 11, 3, 27, 1,116,104,101,114,101,105,110, 50, 10, 0, 0, 0, 31, 0, 89, 0, 1,247, 1,233, 1,220, 1,206, 1,192, 1,180, 1,166, 1,152, 1,138, 1,125, 1,109, 1, 97, 1, 84, 1, 69, 1, 52, 1, 39, 1, 26, 1, 14, 1, 1, 0,243, 0,230, 0,217, 0,201, 0,185, 0,172, 0,159, 0,147, 0,133, 0,120, 0,102, 0, 89, 0, 76, 0, 0, 0, 0, 0, 0, 0, 13, 1, 1,115,101,110,100, 26, 14, 40, 12, 5, 21, 1, 1, 1,115, 97,118,101, 39, 45, 2, 17, 5, 31, 1, 1, 1,115, 97, 99,114,105, 102,105, 99,101, 31, 6, 23, 12, 5, 21, 1, 1, 1,112,111,111,114, 19, 44, 16, 13, 5, 25, 8, 1, 1,112,108, 97, 99,101,115, 16, 32, 11, 5, 19, 1, 1, 1,111,105,108, 38, 9, 49, 12, 5, 21, 1, 1, 1,110,101, 97,114, 38, 21, 7, 12, 5, 21, 1, 1, 1,110,101, 97,114, 35, 41, 4, 15, 5, 27, 1, 1, 1,109,111,114,110,105,110,103, 17, 40, 26, 15, 5, 27, 1, 1, 1,109, 111,114,110,105,110,103, 13, 46, 41, 12, 5, 21, 1, 1, 1,103,111,110,101, 28, 25, 5, 12, 5, 21, 1, 1, 1,103,111,110,101, 19, 10, 25, 13, 5, 23, 1, 1, 1,100,119,101,108,116, 18, 17, 37, 12, 5, 21, 1, 1, 1,100,111, 116,104, 39, 4, 13, 11, 5, 21, 1, 1, 9,100,111,116,104, 32, 40, 12, 5, 21, 1, 1, 1,100,111,116,104, 9, 48, 44, 12, 5, 21, 1, 1, 1,100,105, 101,100, 27, 35, 14, 16, 5, 29, 1, 1, 1,100,101,112, 97,114,116,101,100, 22, 28, 46, 14, 5, 25, 1, 1, 1, 99,117, 98,105,116,115, 22, 38, 35, 12, 5, 23, 1, 8, 1, 99,104,105,108,100, 17, 36, 11, 5, 19, 1, 1, 1, 99, 97,110, 11, 2, 6, 15, 5, 27, 1, 1, 1, 98,101,116,119,101,101,110, 36, 29, 17, 12, 5, 23, 1, 8, 1, 98,101,103, 97,116, 50, 9, 13, 5, 23, 1, 1, 1, 98,101,103, 97,116, 45, 3, 39, 13, 5, 23, 1, 1, 1, 98,101,103, 97,116, 41, 5, 43, 13, 5, 23, 1, 1, 1, 98,101,103, 97,116, 5, 20, 42, 11, 5, 19, 1, 1, 1, 97,114,107, 20, 26, 34, 13, 5, 23, 1, 1, 1, 97, 110,103,101,114, 40, 22, 47, 13, 5, 23, 1, 1, 1, 97,110,103,101,108, 3, 22, 27, 12, 5, 23, 1, 9, 1, 97, 98,111,118,101, 45, 20, 13, 5, 23, 1, 1, 1, 97, 98,111,118,101, 12, 47, 45, 8, 5, 0, 1, 1, 1, 31, 7, 33, 10, 0, 0, 0, 18, 1, 13, 0, 1,243, 1,230, 1,217, 1,203, 1,189, 1, 176, 1,164, 1,151, 1,136, 1,121, 1,105, 1, 90, 1, 76, 1, 63, 1, 51, 1, 39, 1, 27, 1, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 5, 23, 1, 1, 1,119,111,114,107,115, 31, 17, 28, 11, 5, 21, 9, 1, 1,119, 97,121,115, 43, 24, 11, 5, 21, 8, 1, 1,119, 97,121, 115, 4, 19, 11, 5, 19, 1, 1, 1,119, 97,114, 43, 44, 18, 12, 5, 21, 1, 1, 1,119, 97,108,107, 25, 16, 30, 13, 5, 23, 1, 1, 1,116,114,117,116, 104, 27, 39, 31, 14, 5, 25, 1, 1, 1,116,104,111,117,103,104, 28, 45, 22, 15, 5, 27, 1, 1, 1,116,104,101,114,101,105,110, 29, 9, 50, 14, 5, 25, 1, 1, 1,116,101,109,112,108,101, 11, 6, 15, 14, 5, 25, 1, 1, 1,116, 101,109,112,108,101, 7, 37, 48, 12, 5, 21, 1, 1, 1,115,111,109,101, 18, 22, 21, 11, 5, 19, 1, 1, 1,115,105,120, 22, 13, 11, 12, 5, 21, 1, 1, 1,115,104,101,119, 34, 10, 38, 13, 5, 23, 1, 1, 1,115,101,114,118,101, 26, 32, 3, 13, 5, 23, 1, 1, 1,115,101,114,118,101, 14, 41, 10, 12, 5, 21, 1, 1, 1,115,101,110,100, 36, 4, 12, 12, 5, 21, 1, 1, 1,115,101, 110,100, 34, 42, 8, 12, 5, 21, 1, 1, 1,115,101,110,100, 27, 34, 29, 10, 0, 0, 0, 28, 0, 82, 0, 1,241, 1,226, 1,211, 1,197, 1,181, 1,166, 1,151, 1,137, 1,121, 1,104, 1, 84, 1, 73, 1, 59, 1, 41, 1, 26, 1, 11, 0,253, 0,238, 0,223, 0,207, 0,191, 0,175, 0,159, 0,144, 0,129, 0,113, 0, 97, 0, 82, 0, 68, 0, 0, 0, 0, 0, 14, 1, 1, 19, 26, 34, 15, 20, 97,114,107, 14, 6, 1, 1, 1, 1, 21, 25, 5, 27, 28,103,111,110, 101, 15, 6, 1, 1, 1, 1, 23, 22, 47, 16, 40, 97,110,103,101,114, 15, 6, 1, 1, 1, 1, 23, 22, 27, 71, 3, 97,110,103,101,108, 14, 6, 1, 1, 1, 1, 21, 22, 21, 92, 18,115,111,109,101, 14, 6, 1, 1, 1, 1, 21, 21, 7, 91, 38,110,101, 97,114, 15, 6, 1, 1, 1, 1, 23, 20, 42, 18, 5, 98,101, 103, 97,116, 15, 6, 1, 1, 1, 1, 23, 17, 37, 66, 18,100,119,101,108,116, 15, 6, 1, 1, 1, 1, 23, 17, 28, 67, 31,119,111,114,107,115, 15, 6, 1, 1, 1, 8, 25, 16, 32, 7,112,108, 97, 99,101,115, 14, 6, 1, 1, 1, 1, 21, 16, 30, 81, 25,119, 97,108,107, 14, 6, 1, 1, 1, 1, 21, 14, 40, 30, 26,115,101,110,100, 13, 6, 1, 1, 1, 1, 19, 13, 11, 48, 22,115,105,120, 14, 6, 1, 1, 1, 1, 21, 10, 38, 97, 34,115,104,101,119, 14, 6, 1, 1, 1, 1, 21, 10, 25, 7, 19,103,111,110,101, 17, 6, 1, 1, 1, 1, 27, 9, 50, 92, 29,116,104,101,114,101,105,110, 13, 6, 1, 1, 1, 1, 19, 9, 49, 51, 38,111,105,108, 10, 6, 1, 1, 1, 1, 0, 7, 33, 72, 31, 19, 6, 1, 1, 1, 1, 31, 6, 23, 37, 31,115, 97, 99,114,105,102,105, 99,101, 16, 6, 1, 1, 1, 1, 25, 6, 15, 3, 11,116,101,109,112,108,101, 15, 6, 1, 1, 1, 1, 23, 5, 43, 23, 41, 98,101,103, 97,116, 13, 6, 1, 1, 1, 8, 21, 4, 19, 58,119, 97,121,115, 14, 6, 1, 1, 1, 1, 21, 4, 13, 21, 39,100, 111,116,104, 14, 6, 1, 1, 1, 1, 21, 4, 12, 38, 36,115,101,110,100, 15, 6, 1, 1, 1, 1, 23, 3, 39, 21, 45, 98,101,103, 97,116, 13, 6, 1, 1, 1, 1, 19, 2, 6, 37, 11, 99, 97,110, 14, 6, 9, 1, 1, 1, 23, 20, 2, 45, 97, 98,111,118,101, 14, 6, 8, 1, 1, 1, 23, 36, 52, 17, 99,104,105, 108,100, 14, 6, 8, 1, 1, 1, 23, 9, 16, 50, 98,101,103, 97,116, 10, 0, 0, 0, 21, 0,177, 0, 1,237, 1,219, 1,203, 1,188, 1,173, 1,156, 1, 139, 1,123, 1,109, 1, 91, 1, 76, 1, 60, 1, 45, 1, 31, 1, 16, 1, 2, 0,243, 0,226, 0,208, 0,192, 0,177, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 6, 1, 1, 1, 1, 21, 48, 44, 15, 9,100,111,116,104, 15, 6, 1, 1, 1, 1, 23, 47, 45, 54, 12, 97, 98,111,118,101, 17, 6, 1, 1, 1, 1, 27, 46, 41, 92, 13,109,111,114,110,105,110,103, 16, 6, 1, 1, 1, 1, 25, 45, 22, 71, 28,116,104,111,117,103,104, 14, 6, 1, 1, 1, 1, 21, 45, 2, 14, 39,115, 97,118,101, 13, 6, 1, 1, 1, 1, 19, 44, 18, 19, 43,119, 97,114, 14, 6, 1, 1, 1, 1, 21, 44, 16, 52, 19,112,111,111,114, 13, 6, 1, 1, 1, 9, 21, 43, 24, 46,119, 97,121,115, 14, 6, 1, 1, 1, 1, 21, 42, 8, 49, 34,115,101,110,100, 15, 6, 1, 1, 1, 1, 23, 41, 10, 89, 14,115,101,114,118,101, 14, 6, 1, 1, 1, 1, 21, 41, 4, 32, 35,110, 101, 97,114, 17, 6, 1, 1, 1, 1, 27, 40, 26, 98, 17,109,111,114,110,105, 110,103, 13, 6, 1, 9, 1, 1, 21, 40, 68, 32,100,111,116,104, 15, 6, 1, 1, 1, 1, 23, 39, 31, 90, 27,116,114,117,116,104, 16, 6, 1, 1, 1, 1, 25, 38, 35, 34, 22, 99,117, 98,105,116,115, 16, 6, 1, 1, 1, 1, 25, 37, 48, 93, 7,116,101,109,112,108,101, 14, 6, 1, 1, 1, 1, 21, 35, 14, 48, 27,100,105,101,100, 14, 6, 1, 1, 1, 1, 21, 34, 29, 62, 27,115,101,110, 100, 15, 6, 1, 1, 1, 1, 23, 32, 3, 24, 26,115,101,114,118,101, 17, 6, 1, 1, 1, 1, 27, 29, 17, 74, 36, 98,101,116,119,101,101,110, 18, 6, 1, 1, 1, 1, 29, 28, 46, 88, 22,100,101,112, 97,114,116,101,100, 10, 0, 0, 0, 32, 0, 95, 0, 1,247, 1,238, 1,229, 1,220, 1,211, 1,199, 1,187, 1,176, 1,164, 1,148, 1,133, 1,116, 1, 99, 1, 86, 1, 67, 1, 55, 1, 43, 1, 31, 1, 18, 1, 5, 0,249, 0,236, 0,224, 0,209, 0,191, 0,174, 0,157, 0,145, 0,132, 0,120, 0,108, 0, 95, 0, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 1, 1, 0, 1, 49, 51, 38, 15, 12, 7, 1, 1, 1, 1, 0, 1, 48, 37, 93, 7, 30, 11, 7, 1, 1, 1, 0, 0, 1, 47, 22, 16, 24, 11, 7, 1, 0, 1, 1, 0, 1, 47, 16, 40, 12, 12, 7, 1, 1, 1, 1, 0, 1, 46, 28, 88, 22, 2, 11, 7, 1, 1, 0, 1, 0, 1, 44, 48, 9, 19, 16, 7, 1, 1, 1, 0, 23, 1, 42, 20, 18, 98,101,103, 97,116, 22, 16, 7, 1, 1, 0, 1, 23, 1, 37, 17, 18,100,119,101,108,116, 16, 17, 7, 1, 1, 0, 1, 25, 1, 35, 38, 22, 99,117, 98,105,116,115, 17, 14, 7, 1, 1, 1, 0, 19, 1, 34, 26, 15, 97,114,107, 21, 11, 7, 1, 1, 1, 0, 0, 1, 32, 16, 7, 23, 12, 7, 1, 1, 1, 1, 0, 1, 28, 17, 67, 31, 29, 11, 7, 1, 0, 1, 1, 0, 1, 25, 7, 19, 11, 12, 7, 1, 1, 1, 1, 0, 1, 22, 45, 71, 28, 28, 12, 7, 1, 1, 1, 1, 0, 1, 21, 22, 92, 18, 4, 11, 7, 1, 1, 0, 1, 0, 1, 21, 22, 18, 18, 11, 7, 1, 1, 1, 1, 0, 9, 17, 29, 74, 36, 11, 7, 1, 1, 1, 0, 0, 1, 17, 29, 74, 25, 18, 7, 1, 1, 1, 1, 25, 1, 15, 6, 3, 11,116,101,109,112,108,101, 5, 12, 7, 1, 1, 1, 1, 0, 1, 12, 4, 38, 36, 27, 16, 7, 1, 0, 1, 1, 23, 1, 10, 89, 14,115,101,114,118,101, 14, 16, 7, 1, 1, 1, 1, 21, 1, 4, 41, 32, 35,110,101, 97,114, 3, 14, 7, 9, 0, 1, 1, 21, 1, 68, 32,100,111,116, 104, 13, 15, 7, 0, 1, 1, 1, 21, 1, 21, 91, 38,110,101, 97,114, 6, 11, 7, 0, 1, 1, 1, 0, 1, 16, 81, 25, 9, 10, 7, 0, 1, 1, 8, 0, 1, 16, 7, 10, 11, 7, 0, 1, 1, 1, 0, 1, 7, 72, 31, 8, 11, 7, 0, 1, 1, 1, 0, 1, 6, 37, 31, 7, 8, 7, 0, 0, 0, 0, 0, 1, 35, 8, 7, 0, 0, 0, 0, 0, 1, 34, 8, 7, 0, 0, 0, 0, 0, 1, 33, 8, 7, 0, 0, 0, 0, 0, 1, 32, 8, 7, 0, 0, 0, 0, 0, 1, 31, 10, 0, 0, 0, 2, 1,231, 0, 1,244, 1,231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 7, 1, 1, 1, 1, 0, 1, 49, 9, 51, 38, 26, 11, 7, 1, 1, 0, 1, 0, 1, 49, 9, 38, 20, 13, 0, 0, 0, 23, 0, 67, 0, 1,238, 1,220, 1,202, 1,186, 1,168, 1,148, 1,130, 1,107, 1, 86, 1, 65, 1, 44, 1, 27, 1, 14, 0,250, 0,224, 0,205, 0,184, 0, 165, 0,145, 0,123, 0,106, 0, 86, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 23, 6, 0, 23, 1, 1, 21,107,110,111,119,110, 52, 19,112,111,111,114, 18, 22, 6, 0, 23, 1, 1, 23, 97, 98,111,118,101, 24, 26,115,101,114,118,101, 15, 21, 6, 0, 19, 1, 1, 21,119, 97,114, 52, 19, 112,111,111,114, 20, 20, 6, 0, 27, 1, 8, 25,110,111,116,104,105,110,103, 7,112,108, 97, 99,101,115, 18, 19, 6, 0, 23, 1, 1, 23, 98,101,103, 97, 116, 90, 27,116,114,117,116,104, 17, 18, 6, 0, 23, 1, 1, 21,100,119,101, 108,116, 21, 39,100,111,116,104, 19, 17, 6, 0, 27, 1, 1, 21,109,111,114, 110,105,110,103, 52, 19,112,111,111,114, 17, 16, 6, 0, 21, 1, 1, 23,115, 104,101,119, 90, 27,116,114,117,116,104, 24, 15, 6, 0, 27, 1, 1, 31,116, 104,101,114,101,105,110, 37, 31,115, 97, 99,114,105,102,105, 99,101, 18, 14, 6, 0, 23, 1, 8, 25,115,109,111,116,101, 7,112,108, 97, 99,101,115, 11, 13, 6, 0, 19, 1, 1, 0, 97,114,107, 72, 31, 15, 12, 6, 0, 21, 1, 8, 21,119,105,110,101, 58,119, 97,121,115, 19, 11, 6, 0, 21, 1, 1, 27,115, 111,109,101, 98, 17,109,111,114,110,105,110,103, 19, 10, 6, 0, 27, 1, 1, 21, 98,101,116,119,101,101,110, 92, 18,115,111,109,101, 19, 9, 6, 0, 21, 1, 1, 27,115, 97,118,101, 74, 36, 98,101,116,119,101,101,110, 21, 8, 6, 0, 25, 1, 1, 27,116,104,111,117,103,104, 98, 17,109,111,114,110,105,110, 103, 16, 7, 6, 0, 21, 1, 1, 21,115,101,110,100, 49, 34,115,101,110,100, 18, 6, 6, 0, 25, 1, 1, 21,119,105,115,100,111,109, 38, 36,115,101,110, 100, 16, 5, 6, 0, 23, 1, 9, 21, 97,110,103,101,114, 46,119, 97,121,115, 14, 4, 6, 0, 19, 1, 1, 19, 99, 97,110, 19, 43,119, 97,114, 16, 3, 6, 0, 23, 1, 1, 19,111,102,102,101,114, 48, 22,115,105,120, 16, 2, 6, 0, 23, 1, 8, 21,119,111,114,107,115, 58,119, 97,121,115, 16, 1, 6, 0, 23, 1, 1, 19,116,114,117,116,104, 37, 11, 99, 97,110, 13, 0, 0, 0, 22, 0, 64, 0, 1,230, 1,213, 1,191, 1,169, 1,148, 1,130, 1,108, 1, 89, 1, 70, 1, 51, 1, 34, 1, 16, 0,253, 0,233, 0,214, 0,194, 0,174, 0,151, 0,132, 0,109, 0, 90, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 45, 6, 0, 35, 1, 1, 23,105,110,104, 97, 98,105,116, 97,110,116, 115, 23, 41, 98,101,103, 97,116, 17, 44, 6, 0, 23, 1, 1, 21, 97,110,103, 101,108, 48, 27,100,105,101,100, 21, 43, 6, 0, 25, 1, 1, 27,116,101,109, 112,108,101, 74, 36, 98,101,116,119,101,101,110, 17, 42, 6, 0, 23, 1, 1, 21, 99,104,105,108,100, 81, 25,119, 97,108,107, 21, 41, 6, 0, 21, 1, 1, 31,119, 97,121,115, 37, 31,115, 97, 99,114,105,102,105, 99,101, 18, 40, 6, 0, 21, 1, 1, 25,112,111,111,114, 93, 7,116,101,109,112,108,101, 18, 39, 6, 0, 21, 1, 1, 25,100,111,116,104, 3, 11,116,101,109,112,108,101, 17, 38, 6, 0, 23, 1, 1, 21,102,114,117,105,116, 62, 27,115,101,110,100, 18, 37, 6, 0, 23, 1, 1, 23,115,101,114,118,101, 90, 27,116,114,117,116,104, 17, 36, 6, 0, 21, 1, 1, 23,110,101, 97,114, 90, 27,116,114,117,116,104, 16, 35, 6, 0, 21, 1, 1, 21,108,111,110,103, 14, 39,115, 97,118,101, 15, 34, 6, 0, 21, 1, 1, 19,119, 97,108,107, 15, 20, 97,114,107, 17, 33, 6, 0, 25, 1, 9, 21, 99,117, 98,105,116,115, 46,119, 97,121,115, 17, 32, 6, 0, 21, 1, 1, 23,103,111,110,101, 23, 41, 98,101,103, 97,116, 17, 31, 6, 0, 23, 1, 1, 21,119,104,105,108,101, 49, 34,115,101,110,100, 20, 30, 6, 0, 21, 1, 1, 29,112, 97,114,116, 88, 22,100,101,112, 97,114,116,101,100, 16, 29, 6, 0, 21, 1, 1, 21, 98,101, 97,114, 92, 18,115,111,109,101, 19, 28, 6, 0, 25, 1, 1, 23,112,108, 97, 99,101,115, 23, 41, 98,101,103, 97, 116, 20, 27, 6, 0, 27, 1, 1, 23,116,104,121,115,101,108,102, 54, 12, 97, 98,111,118,101, 20, 26, 6, 0, 29, 1, 1, 21,100,101,112, 97,114,116,101, 100, 92, 18,115,111,109,101, 15, 25, 6, 0, 21, 1, 1, 19,116,101,108,108, 19, 43,119, 97,114, 24, 24, 6, 0, 31, 1, 1, 27,115, 97, 99,114,105,102, 105, 99,101, 92, 13,109,111,114,110,105,110,103, 13, 0, 0, 0, 5, 1,162, 0, 1,239, 1,221, 1,203, 1,182, 1,162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 50, 6, 0, 23, 1, 1, 23,119,114, 97,116,104, 21, 45, 98,101,103, 97,116, 19, 49, 6, 0, 21, 1, 1, 27,116,114,101,101, 98, 17,109,111,114,110,105,110,103, 16, 48, 6, 0, 19, 1, 1, 23,115,105,120, 71, 3, 97,110,103,101,108, 16, 47, 6, 0, 21, 1, 1, 21,100,105,101,100, 7, 19,103,111,110,101, 15, 46, 6, 0, 19, 1, 1, 21,111,105,108, 81, 25,119, 97,108,107, 10, 0, 0, 0, 40, 0,106, 0, 1,246, 1,236, 1,226, 1,218, 1,209, 1,199, 1,187, 1,179, 1,169, 1, 158, 1,145, 1,136, 1,127, 1,117, 1,107, 1, 98, 1, 82, 1, 72, 1, 63, 1, 51, 1, 42, 1, 30, 1, 20, 1, 12, 1, 3, 0,248, 0,239, 0,225, 0, 216, 0,207, 0,197, 0,188, 0,180, 0,170, 0,161, 0,152, 0,141, 0,129, 0,118, 0,106, 0, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,116,114, 101,101, 49, 11, 3, 27, 1,116,104,121,115,101,108,102, 27, 10, 3, 25, 1, 116,104,111,117,103,104, 8, 11, 3, 27, 1,116,104,101,114,101,105,110, 15, 10, 3, 25, 1,116,101,109,112,108,101, 43, 8, 3, 21, 1,116,101,108,108, 25, 8, 3, 21, 1,115,111,109,101, 11, 9, 3, 23, 1,115,109,111,116,101, 14, 7, 3, 19, 1,115,105,120, 48, 8, 3, 21, 1,115,104,101,119, 16, 9, 3, 23, 1,115,101,114,118,101, 37, 8, 3, 21, 1,115,101,110,100, 7, 8, 3, 21, 1,115, 97,118,101, 9, 13, 3, 31, 1,115, 97, 99,114,105,102,105, 99,101, 24, 8, 3, 21, 1,112,111,111,114, 40, 10, 3, 25, 1,112,108, 97, 99,101,115, 28, 8, 3, 21, 1,112, 97,114,116, 30, 7, 3, 19, 1,111,105, 108, 46, 9, 3, 23, 1,111,102,102,101,114, 3, 11, 3, 27, 1,110,111,116, 104,105,110,103, 20, 8, 3, 21, 1,110,101, 97,114, 36, 11, 3, 27, 1,109, 111,114,110,105,110,103, 17, 8, 3, 21, 1,108,111,110,103, 35, 9, 3, 23, 1,107,110,111,119,110, 23, 15, 3, 35, 1,105,110,104, 97, 98,105,116, 97, 110,116,115, 45, 8, 3, 21, 1,103,111,110,101, 32, 9, 3, 23, 1,102,114, 117,105,116, 38, 9, 3, 23, 1,100,119,101,108,116, 18, 8, 3, 21, 1,100, 111,116,104, 39, 8, 3, 21, 1,100,105,101,100, 47, 12, 3, 29, 1,100,101, 112, 97,114,116,101,100, 26, 10, 3, 25, 1, 99,117, 98,105,116,115, 33, 9, 3, 23, 1, 99,104,105,108,100, 42, 7, 3, 19, 1, 99, 97,110, 4, 11, 3, 27, 1, 98,101,116,119,101,101,110, 10, 9, 3, 23, 1, 98,101,103, 97,116, 19, 8, 3, 21, 1, 98,101, 97,114, 29, 7, 3, 19, 1, 97,114,107, 13, 9, 3, 23, 1, 97,110,103,101,114, 5, 9, 3, 23, 1, 97,110,103,101,108, 44, 9, 3, 23, 1, 97, 98,111,118,101, 22, 10, 0, 0, 0, 9, 1,171, 0, 1, 247, 1,238, 1,230, 1,221, 1,211, 1,202, 1,191, 1,181, 1,171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 3, 23, 1,119,114, 97,116,104, 50, 9, 3, 23, 1,119,111,114,107,115, 2, 10, 3, 25, 1,119,105,115,100,111,109, 6, 8, 3, 21, 1,119,105,110, 101, 12, 9, 3, 23, 1,119,104,105,108,101, 31, 8, 3, 21, 1,119, 97,121, 115, 41, 7, 3, 19, 1,119, 97,114, 21, 8, 3, 21, 1,119, 97,108,107, 34, 8, 3, 23, 9,116,114,117,116,104, 13, 0, 0, 0, 5, 0, 84, 0, 1, 78, 0,249, 0,177, 1,163, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 19, 7, 21, 19, 19, 8,129, 33,118,105,101,119,118, 50, 49,118, 50, 49, 67, 82, 69, 65, 84, 69, 32, 86, 73, 69, 87, 32,118, 50, 49, 40, 97, 44, 98, 44, 99, 44,100, 44,101, 41, 32, 65, 83, 32, 83, 69, 76, 69, 67, 84, 32, 97, 44, 98, 44, 99, 44,100, 44,101, 32, 70, 82, 79, 77, 32,116, 50, 32, 79, 82, 68, 69, 82, 32, 66, 89, 32, 98, 32, 76, 73, 77, 73, 84, 32, 49, 48, 70, 17, 6, 21, 19, 19, 8,121,118,105,101,119,118, 53, 48,118, 53, 48, 67, 82, 69, 65, 84, 69, 32, 86, 73, 69, 87, 32,118, 53, 48, 40, 97, 44, 98, 41, 32, 65, 83, 32, 83, 69, 76, 69, 67, 84, 32, 97, 44, 98, 32, 70, 82, 79, 77, 32,116, 53, 32, 87, 72, 69, 82, 69, 32, 97, 60, 62, 50, 53, 83, 16, 7, 21, 19, 19, 8,129, 17,118,105,101,119,118, 52, 48,118, 52, 48, 67, 82, 69, 65, 84, 69, 32, 86, 73, 69, 87, 32,118, 52, 48, 40, 97, 44, 98, 44, 99, 44,100, 44,101, 41, 32, 65, 83, 32, 83, 69, 76, 69, 67, 84, 32, 97, 44, 98, 44, 99, 44,100, 44,101, 32, 70, 82, 79, 77, 32,116, 52, 32, 87, 72, 69, 82, 69, 32, 97, 60, 62, 50, 53, 83, 15, 7, 21, 19, 19, 8,129, 17,118,105,101,119,118, 51, 48,118, 51, 48, 67, 82, 69, 65, 84, 69, 32, 86, 73, 69, 87, 32,118, 51, 48, 40, 97, 44, 98, 44, 99, 44,100, 44,101, 41, 32, 65, 83, 32, 83, 69, 76, 69, 67, 84, 32, 97, 44, 98, 44, 99, 44,100, 44,101, 32, 70, 82, 79, 77, 32,116, 51, 32, 87, 72, 69, 82, 69, 32, 97, 60, 62, 50, 53, 91, 18, 7, 21, 19, 19, 8,129, 33, 118,105,101,119,118, 49, 49,118, 49, 49, 67, 82, 69, 65, 84, 69, 32, 86, 73, 69, 87, 32,118, 49, 49, 40, 97, 44, 98, 44, 99, 44,100, 44,101, 41, 32, 65, 83, 32, 83, 69, 76, 69, 67, 84, 32, 97, 44, 98, 44, 99, 44,100, 44,101, 32, 70, 82, 79, 77, 32,116, 49, 32, 79, 82, 68, 69, 82, 32, 66, 89, 32, 98, 32, 76, 73, 77, 73, 84, 32, 49, 48, 13, 1,163, 0, 4, 0, 40, 0, 1, 70, 0, 233, 0,152, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,110, 23, 7, 21, 19, 19, 8,129, 71, 118,105,101,119,118, 49, 50,118, 49, 50, 67, 82, 69, 65, 84, 69, 32, 86, 73, 69, 87, 32,118, 49, 50, 40, 97, 44, 98, 44, 99, 44,100, 44,101, 41, 32, 65, 83, 10, 32, 32, 83, 69, 76, 69, 67, 84, 32,115,117,109, 40, 97, 41, 44, 32, 97,118,103, 40, 98, 41, 44, 32, 99,111,117,110,116, 40, 42, 41, 44, 32,109, 105,110, 40,100, 41, 44, 32,101, 32, 70, 82, 79, 77, 32,116, 49, 32, 71, 82, 79, 85, 80, 32, 66, 89, 32, 53, 79, 22, 7, 21, 19, 19, 8,129, 9,118,105, 101,119,118, 53, 49,118, 53, 49, 67, 82, 69, 65, 84, 69, 32, 86, 73, 69, 87, 32,118, 53, 49, 40, 97, 44, 98, 41, 32, 65, 83, 32, 83, 69, 76, 69, 67, 84, 32, 97, 44, 98, 32, 70, 82, 79, 77, 32,116, 53, 32, 79, 82, 68, 69, 82, 32, 66, 89, 32, 98, 32, 76, 73, 77, 73, 84, 32, 49, 48, 91, 21, 7, 21, 19, 19, 8,129, 33,118,105,101,119,118, 52, 49,118, 52, 49, 67, 82, 69, 65, 84, 69, 32, 86, 73, 69, 87, 32,118, 52, 49, 40, 97, 44, 98, 44, 99, 44,100, 44,101, 41, 32, 65, 83, 32, 83, 69, 76, 69, 67, 84, 32, 97, 44, 98, 44, 99, 44,100, 44,101, 32, 70, 82, 79, 77, 32,116, 52, 32, 79, 82, 68, 69, 82, 32, 66, 89, 32, 98, 32, 76, 73, 77, 73, 84, 32, 49, 48, 91, 20, 7, 21, 19, 19, 8,129, 33,118,105,101,119,118, 51, 49,118, 51, 49, 67, 82, 69, 65, 84, 69, 32, 86, 73, 69, 87, 32,118, 51, 49, 40, 97, 44, 98, 44, 99, 44,100, 44,101, 41, 32, 65, 83, 32, 83, 69, 76, 69, 67, 84, 32, 97, 44, 98, 44, 99, 44,100, 44,101, 32, 70, 82, 79, 77, 32,116, 51, 32, 79, 82, 68, 69, 82, 32, 66, 89, 32, 98, 32, 76, 73, 77, 73, 84, 32, 49, 48, 0, 0, 0, 93, 19, 19, 8,129, 33,118, 105,101,119,118, 50, 49,118, 50, 49, 67, 82, 69, 65, 84, 69, 32, 86, 73, 69, 87, 32,118, 50, 49, 40, 97, 44, 98, 44, 99, 44,100, 44,101, 41, 32, 65, 83, 32, 83, 69, 76, 69, 67, 84, 32, 97, 44, 98, 44, 99, 44,100, 44,101, 32, 70, 82, 79, 77, 32,116, 50, 32, 79, 82, 68, 69, 82, 32, 66, 89, 32, 98, 32, 76, 73, 77, 73, 84, 32, 49, 48, 13, 0, 0, 0, 3, 0, 66, 0, 1,107, 0,214, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,129, 17, 26, 7, 21, 19, 19, 8,130, 13,118,105,101,119,118, 52, 50,118, 52, 50, 67, 82, 69, 65, 84, 69, 32, 86, 73, 69, 87, 32,118, 52, 50, 40, 97, 44, 98, 44, 99, 44,100, 44,101, 41, 32, 65, 83, 10, 32, 32, 83, 69, 76, 69, 67, 84, 32,115, 117,109, 40, 97, 41, 44, 32, 97,118,103, 40, 98, 41, 44, 32, 99,111,117,110, 116, 40, 42, 41, 44, 32,109,105,110, 40,100, 41, 44, 32,101, 32, 70, 82, 79, 77, 32,116, 52, 32, 71, 82, 79, 85, 80, 32, 66, 89, 32, 53, 10, 32, 32, 32, 32, 72, 65, 86, 73, 78, 71, 32,109,105,110, 40,100, 41, 60, 51, 48, 32, 79, 82, 68, 69, 82, 32, 66, 89, 32, 51, 44, 32, 49,129, 18, 25, 7, 21, 19, 19, 8,130, 15,118,105,101,119,118, 51, 50,118, 51, 50, 67, 82, 69, 65, 84, 69, 32, 86, 73, 69, 87, 32,118, 51, 50, 40, 97, 44, 98, 44, 99, 44,100, 44,101, 41, 32, 65, 83, 10, 32, 32, 83, 69, 76, 69, 67, 84, 32,115,117,109, 40, 97, 41, 44, 32, 97,118,103, 40, 98, 41, 44, 32, 99,111,117,110,116, 40, 42, 41, 44, 32,109,105,110, 40,100, 41, 44, 32,101, 32, 70, 82, 79, 77, 32,116, 51, 32, 71, 82, 79, 85, 80, 32, 66, 89, 32, 53, 10, 32, 32, 32, 32, 72, 65, 86, 73, 78, 71, 32, 99,111,117,110,116, 40, 42, 41, 62, 49, 32, 79, 82, 68, 69, 82, 32, 66, 89, 32, 51, 44, 32, 49,129, 18, 24, 7, 21, 19, 19, 8,130, 15, 118,105,101,119,118, 50, 50,118, 50, 50, 67, 82, 69, 65, 84, 69, 32, 86, 73, 69, 87, 32,118, 50, 50, 40, 97, 44, 98, 44, 99, 44,100, 44,101, 41, 32, 65, 83, 10, 32, 32, 83, 69, 76, 69, 67, 84, 32,115,117,109, 40, 97, 41, 44, 32, 97,118,103, 40, 98, 41, 44, 32, 99,111,117,110,116, 40, 42, 41, 44, 32,109, 105,110, 40,100, 41, 44, 32,101, 32, 70, 82, 79, 77, 32,116, 50, 32, 71, 82, 79, 85, 80, 32, 66, 89, 32, 53, 10, 32, 32, 32, 32, 72, 65, 86, 73, 78, 71, 32, 99,111,117,110,116, 40, 42, 41, 62, 49, 32, 79, 82, 68, 69, 82, 32, 66, 89, 32, 51, 44, 32, 49, 13, 1,108, 0, 3, 0, 83, 0, 0,225, 0, 83, 1, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,129, 11, 28, 7, 21, 19, 19, 8,130, 1,118,105,101,119,118, 49, 51,118, 49, 51, 67, 82, 69, 65, 84, 69, 32, 86, 73, 69, 87, 32,118, 49, 51, 40, 97, 44, 98, 44, 99, 44,100, 44, 101, 41, 32, 65, 83, 10, 32, 32, 83, 69, 76, 69, 67, 84, 32, 97, 44, 98, 44, 99, 44,100, 44,101, 32, 70, 82, 79, 77, 32,116, 49, 10, 32, 32, 85, 78, 73, 79, 78, 32, 83, 69, 76, 69, 67, 84, 32, 97, 44, 98, 44, 99, 44,100, 44,101, 32, 70, 82, 79, 77, 32,116, 50, 10, 32, 32, 85, 78, 73, 79, 78, 32, 83, 69, 76, 69, 67, 84, 32, 97, 44, 98, 44, 99, 44,100, 44,101, 32, 70, 82, 79, 77, 32,116, 51,129, 8, 27, 7, 21, 19, 19, 8,129,123,118,105,101,119,118, 53, 50,118, 53, 50, 67, 82, 69, 65, 84, 69, 32, 86, 73, 69, 87, 32,118, 53, 50, 40, 97, 44, 98, 44, 99, 44,100, 44,101, 41, 32, 65, 83, 10, 32, 32, 83, 69, 76, 69, 67, 84, 32, 99,111,117,110,116, 40, 42, 41, 44, 32,109,105,110, 40, 98, 41, 44, 32,115,117, 98,115,116,114, 40, 98, 44, 49, 44, 49, 41, 44, 32, 109,105,110, 40, 97, 41, 44, 32,109, 97,120, 40, 97, 41, 32, 70, 82, 79, 77, 32,116, 53, 10, 32, 32, 32, 71, 82, 79, 85, 80, 32, 66, 89, 32, 51, 32, 79, 82, 68, 69, 82, 32, 66, 89, 32, 49, 0, 0, 0, 28, 21, 19, 19, 8,130, 13, 118,105,101,119,118, 52, 50,118, 52, 50, 67, 82, 69, 65, 84, 69, 32, 86,118, 29, 7, 21, 19, 19, 8,129, 87,118,105,101,119,118, 50, 51,118, 50, 51, 67, 82, 69, 65, 84, 69, 32, 86, 73, 69, 87, 32,118, 50, 51, 40, 97, 44, 98, 44, 99, 44,100, 44,101, 41, 32, 65, 83, 10, 32, 32, 83, 69, 76, 69, 67, 84, 32, 97, 44, 98, 44, 99, 44,100, 44,101, 32, 70, 82, 79, 77, 32,116, 49, 10, 32, 32, 69, 88, 67, 69, 80, 84, 32, 83, 69, 76, 69, 67, 84, 32, 97, 44, 98, 44, 99, 44,100, 44,101, 32, 70, 82, 79, 77, 32,116, 49, 32, 87, 72, 69, 82, 69, 32, 98, 60, 50, 53, 13, 0, 0, 0, 3, 0, 40, 0, 1,134, 1, 12, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,129, 97, 32, 7, 21, 19, 19, 8,131, 45,118,105, 101,119,118, 54, 50,118, 54, 50, 67, 82, 69, 65, 84, 69, 32, 86, 73, 69, 87, 32,118, 54, 50, 40, 97, 44, 98, 44, 99, 44,100, 44,101, 41, 32, 65, 83, 10, 32, 32, 83, 69, 76, 69, 67, 84, 32,116, 49, 46, 97, 44,116, 50, 46, 98, 44, 116, 51, 46, 99, 44,116, 52, 46,100, 44,116, 53, 46, 98, 10, 32, 32, 32, 32, 70, 82, 79, 77, 32,116, 49, 32, 74, 79, 73, 78, 32,116, 50, 32, 79, 78, 32, 40,116, 49, 46, 97, 61,116, 50, 46, 98, 41, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 74, 79, 73, 78, 32,116, 51, 32, 79, 78, 32, 40,116, 49, 46, 97, 61,116, 51, 46, 97, 41, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 74, 79, 73, 78, 32,116, 52, 32, 79, 78, 32, 40,116, 52, 46, 98, 61, 116, 51, 46, 98, 41, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 76, 69, 70, 84, 32, 74, 79, 73, 78, 32,116, 53, 32, 79, 78, 32, 40,116, 53, 46, 97, 61,116, 49, 46, 99, 41,120, 31, 7, 21, 19, 19, 8,129, 91,118,105,101, 119,118, 54, 49,118, 54, 49, 67, 82, 69, 65, 84, 69, 32, 86, 73, 69, 87, 32, 118, 54, 49, 40, 97, 44, 98, 44, 99, 44,100, 44,101, 41, 32, 65, 83, 10, 32, 32, 83, 69, 76, 69, 67, 84, 32,116, 50, 46, 97, 44,116, 51, 46, 98, 44,116, 50, 46, 99, 44,116, 51, 46,100, 44,116, 50, 46,101, 10, 32, 32, 32, 32, 70, 82, 79, 77, 32,116, 50, 32, 76, 69, 70, 84, 32, 74, 79, 73, 78, 32,116, 51, 32, 79, 78, 32, 40,116, 50, 46, 97, 61,116, 51, 46, 97, 41,120, 30, 7, 21, 19, 19, 8,129, 91,118,105,101,119,118, 54, 48,118, 54, 48, 67, 82, 69, 65, 84, 69, 32, 86, 73, 69, 87, 32,118, 54, 48, 40, 97, 44, 98, 44, 99, 44,100, 44,101, 41, 32, 65, 83, 10, 32, 32, 83, 69, 76, 69, 67, 84, 32,116, 49, 46, 97, 44,116, 50, 46, 98, 44,116, 49, 46, 99, 44,116, 50, 46,100, 44,116, 49, 46,101, 10, 32, 32, 32, 32, 70, 82, 79, 77, 32,116, 49, 32, 76, 69, 70, 84, 32, 74, 79, 73, 78, 32,116, 50, 32, 79, 78, 32, 40,116, 49, 46, 97, 61,116, 50, 46, 98, 41, 13, 0, 0, 0, 1, 1, 73, 0, 1, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,129, 52, 33, 7, 21, 19, 19, 8,130, 83,118,105,101,119,118, 55, 48,118, 55, 48, 67, 82, 69, 65, 84, 69, 32, 86, 73, 69, 87, 32,118, 55, 48, 40, 97, 44, 98, 44, 99, 44,100, 44,101, 41, 32, 65, 83, 10, 32, 32, 87, 73, 84, 72, 32, 82, 69, 67, 85, 82, 83, 73, 86, 69, 32, 99, 48, 40,120, 41, 32, 65, 83, 32, 40, 86, 65, 76, 85, 69, 83, 40, 49, 41, 32, 85, 78, 73, 79, 78, 32, 65, 76, 76, 32, 83, 69, 76, 69, 67, 84, 32, 120, 43, 49, 32, 70, 82, 79, 77, 32, 99, 48, 32, 87, 72, 69, 82, 69, 32,120, 60, 57, 41, 10, 32, 32, 83, 69, 76, 69, 67, 84, 32,120, 44, 32, 98, 44, 32, 99, 44, 32,100, 44, 32,101, 32, 70, 82, 79, 77, 32, 99, 48, 32, 74, 79, 73, 78, 32,116, 49, 32, 79, 78, 32, 40,116, 49, 46, 97, 61, 53, 48, 45, 99, 48, 46,120, 41, }; |
Added test/optfuzz-db01.txt.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | -- Run this script through the sqlite3 command-line shell in order to generate -- a database file containing lots of data for testing purposes. -- -- This script assumes that the "bin2c" program is available on ones $PATH. -- The "bin2c" program reads a binary file and outputs C-code that creates -- an array of bytes holding the content of that file. -- -- This script is designed to create many tables and views all having -- 5 columns, "a" through "e", and with a variety of integers, short strings, -- and NULL values. -- .open -new testdb01.db PRAGMA page_size=512; BEGIN; CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT, c INT, d INT, e INT); WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<50) INSERT INTO t1(a,b,c,d,e) SELECT x,abs(random()%51), abs(random()%100), abs(random()%51), abs(random()%100) FROM c; CREATE TABLE t2(a INT, b INT, c INT,d INT,e INT,PRIMARY KEY(b,a))WITHOUT ROWID; INSERT INTO t2 SELECT * FROM t1; CREATE TABLE t3(a,b,c,d,e); INSERT INTO t3 SELECT a,b,c,d,e FROM t1 ORDER BY random() LIMIT 5; INSERT INTO t3 SELECT null,b,c,d,e FROM t1 ORDER BY random() LIMIT 5; INSERT INTO t3 SELECT a,null,c,d,e FROM t1 ORDER BY random() LIMIT 5; INSERT INTO t3 SELECT a,b,null,d,e FROM t1 ORDER BY random() LIMIT 5; INSERT INTO t3 SELECT a,b,c,null,e FROM t1 ORDER BY random() LIMIT 5; INSERT INTO t3 SELECT a,b,c,d,null FROM t1 ORDER BY random() LIMIT 5; INSERT INTO t3 SELECT null,null,null,null,null FROM t1 LIMIT 5; CREATE INDEX t3x1 ON t3(a,b,c,d,e); CREATE TABLE t4(a INT UNIQUE NOT NULL, b INT UNIQUE NOT NULL,c,d,e); INSERT OR IGNORE INTO t4 SELECT a,b,c,d,e FROM t3; CREATE TABLE t5(a INTEGER PRIMARY KEY, b TEXT UNIQUE,c,d,e); INSERT INTO t5(b) VALUES ('truth'), ('works'), ('offer'), ('can'), ('anger'), ('wisdom'), ('send'), ('though'), ('save'), ('between'), ('some'), ('wine'), ('ark'), ('smote'), ('therein'), ('shew'), ('morning'), ('dwelt'), ('begat'), ('nothing'), ('war'), ('above'), ('known'), ('sacrifice'), ('tell'), ('departed'), ('thyself'), ('places'), ('bear'), ('part'), ('while'), ('gone'), ('cubits'), ('walk'), ('long'), ('near'), ('serve'), ('fruit'), ('doth'), ('poor'), ('ways'), ('child'), ('temple'), ('angel'), ('inhabitants'), ('oil'), ('died'), ('six'), ('tree'), ('wrath'); UPDATE t1 SET e=(SELECT b FROM t5 WHERE t5.a=(t1.e%51)); UPDATE t5 SET (c,d,e) = (SELECT c,d,e FROM t1 WHERE t1.a=abs(t5.a+random()/100)%50+1); UPDATE t2 SET e=(SELECT b FROM t5 WHERE t5.a=(t2.e%51)); UPDATE t3 SET e=(SELECT b FROM t5 WHERE t5.a=t3.e); CREATE INDEX t1e ON t1(e); CREATE INDEX t2ed ON t2(e,d); CREATE VIEW v00(a,b,c,d,e) AS SELECT 1,1,1,1,'one'; CREATE VIEW v10(a,b,c,d,e) AS SELECT a,b,c,d,e FROM t1 WHERE a<>25; CREATE VIEW v20(a,b,c,d,e) AS SELECT a,b,c,d,e FROM t2 WHERE a<>25; CREATE VIEW v30(a,b,c,d,e) AS SELECT a,b,c,d,e FROM t3 WHERE a<>25; CREATE VIEW v40(a,b,c,d,e) AS SELECT a,b,c,d,e FROM t4 WHERE a<>25; CREATE VIEW v50(a,b) AS SELECT a,b FROM t5 WHERE a<>25; CREATE VIEW v11(a,b,c,d,e) AS SELECT a,b,c,d,e FROM t1 ORDER BY b LIMIT 10; CREATE VIEW v21(a,b,c,d,e) AS SELECT a,b,c,d,e FROM t2 ORDER BY b LIMIT 10; CREATE VIEW v31(a,b,c,d,e) AS SELECT a,b,c,d,e FROM t3 ORDER BY b LIMIT 10; CREATE VIEW v41(a,b,c,d,e) AS SELECT a,b,c,d,e FROM t4 ORDER BY b LIMIT 10; CREATE VIEW v51(a,b) AS SELECT a,b FROM t5 ORDER BY b LIMIT 10; CREATE VIEW v12(a,b,c,d,e) AS SELECT sum(a), avg(b), count(*), min(d), e FROM t1 GROUP BY 5; CREATE VIEW v22(a,b,c,d,e) AS SELECT sum(a), avg(b), count(*), min(d), e FROM t2 GROUP BY 5 HAVING count(*)>1 ORDER BY 3, 1; CREATE VIEW v32(a,b,c,d,e) AS SELECT sum(a), avg(b), count(*), min(d), e FROM t3 GROUP BY 5 HAVING count(*)>1 ORDER BY 3, 1; CREATE VIEW v42(a,b,c,d,e) AS SELECT sum(a), avg(b), count(*), min(d), e FROM t4 GROUP BY 5 HAVING min(d)<30 ORDER BY 3, 1; CREATE VIEW v52(a,b,c,d,e) AS SELECT count(*), min(b), substr(b,1,1), min(a), max(a) FROM t5 GROUP BY 3 ORDER BY 1; CREATE VIEW v13(a,b,c,d,e) AS SELECT a,b,c,d,e FROM t1 UNION SELECT a,b,c,d,e FROM t2 UNION SELECT a,b,c,d,e FROM t3; CREATE VIEW v23(a,b,c,d,e) AS SELECT a,b,c,d,e FROM t1 EXCEPT SELECT a,b,c,d,e FROM t1 WHERE b<25; CREATE VIEW v60(a,b,c,d,e) AS SELECT t1.a,t2.b,t1.c,t2.d,t1.e FROM t1 LEFT JOIN t2 ON (t1.a=t2.b); CREATE VIEW v61(a,b,c,d,e) AS SELECT t2.a,t3.b,t2.c,t3.d,t2.e FROM t2 LEFT JOIN t3 ON (t2.a=t3.a); CREATE VIEW v62(a,b,c,d,e) AS SELECT t1.a,t2.b,t3.c,t4.d,t5.b FROM t1 JOIN t2 ON (t1.a=t2.b) JOIN t3 ON (t1.a=t3.a) JOIN t4 ON (t4.b=t3.b) LEFT JOIN t5 ON (t5.a=t1.c); CREATE VIEW v70(a,b,c,d,e) AS WITH RECURSIVE c0(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c0 WHERE x<9) SELECT x, b, c, d, e FROM c0 JOIN t1 ON (t1.a=50-c0.x); COMMIT; VACUUM; .shell bin2c testdb01.db |
Added test/optfuzz.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 | /* ** 2018-03-21 ** ** 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 program attempts to verify the correctness of the SQLite query ** optimizer by fuzzing. ** ** The input is an SQL script, presumably generated by a fuzzer. The ** argument is the name of the input. If no files are named, standard ** input is read. ** ** The SQL script is run twice, once with optimization enabled, and again ** with optimization disabled. If the output is not equivalent, an error ** is printed and the program returns non-zero. */ /* Include the SQLite amalgamation, after making appropriate #defines. */ #define SQLITE_THREADSAFE 0 #define SQLITE_OMIT_LOAD_EXTENSION 1 #define SQLITE_ENABLE_DESERIALIZE 1 #include "sqlite3.c" /* Content of the read-only test database */ #include "optfuzz-db01.c" /* ** Prepare a single SQL statement. Panic if anything goes wrong */ static sqlite3_stmt *prepare_sql(sqlite3 *db, const char *zFormat, ...){ char *zSql; int rc; sqlite3_stmt *pStmt = 0; va_list ap; va_start(ap, zFormat); zSql = sqlite3_vmprintf(zFormat, ap); va_end(ap); rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); if( rc ){ printf("Error: %s\nSQL: %s\n", sqlite3_errmsg(db), zSql); exit(1); } sqlite3_free(zSql); return pStmt; } /* ** Run SQL. Panic if anything goes wrong */ static void run_sql(sqlite3 *db, const char *zFormat, ...){ char *zSql; int rc; char *zErr = 0; va_list ap; va_start(ap, zFormat); zSql = sqlite3_vmprintf(zFormat, ap); va_end(ap); rc = sqlite3_exec(db, zSql, 0, 0, &zErr); if( rc || zErr ){ printf("Error: %s\nsqlite3_errmsg: %s\nSQL: %s\n", zErr, sqlite3_errmsg(db), zSql); exit(1); } sqlite3_free(zSql); } /* ** Run one or more SQL statements contained in zSql against database dbRun. ** Store the input in database dbOut. */ static int optfuzz_exec( sqlite3 *dbRun, /* The database on which the SQL executes */ const char *zSql, /* The SQL to be executed */ sqlite3 *dbOut, /* Store results in this database */ const char *zOutTab, /* Store results in this table of dbOut */ int *pnStmt, /* Write the number of statements here */ int *pnRow, /* Write the number of rows here */ int bTrace /* Print query results if true */ ){ int rc = SQLITE_OK; /* Return code */ const char *zLeftover; /* Tail of unprocessed SQL */ sqlite3_stmt *pStmt = 0; /* The current SQL statement */ sqlite3_stmt *pIns = 0; /* Statement to insert into dbOut */ const char *zCol; /* Single column value */ int nCol; /* Number of output columns */ char zLine[4000]; /* Complete row value */ run_sql(dbOut, "BEGIN"); run_sql(dbOut, "CREATE TABLE IF NOT EXISTS staging(x TEXT)"); run_sql(dbOut, "CREATE TABLE IF NOT EXISTS \"%w\"(x TEXT)", zOutTab); pIns = prepare_sql(dbOut, "INSERT INTO staging(x) VALUES(?1)"); *pnRow = *pnStmt = 0; while( rc==SQLITE_OK && zSql && zSql[0] ){ zLeftover = 0; rc = sqlite3_prepare_v2(dbRun, zSql, -1, &pStmt, &zLeftover); zSql = zLeftover; assert( rc==SQLITE_OK || pStmt==0 ); if( rc!=SQLITE_OK ){ printf("Error with [%s]\n%s\n", zSql, sqlite3_errmsg(dbRun)); break; } if( !pStmt ) continue; (*pnStmt)++; nCol = sqlite3_column_count(pStmt); run_sql(dbOut, "DELETE FROM staging;"); while( sqlite3_step(pStmt)==SQLITE_ROW ){ int i, j; for(i=j=0; i<nCol && j<sizeof(zLine)-50; i++){ int eType = sqlite3_column_type(pStmt, i); if( eType==SQLITE_NULL ){ zCol = "NULL"; }else{ zCol = (const char*)sqlite3_column_text(pStmt, i); } if( i ) zLine[j++] = ','; if( eType==SQLITE_TEXT ){ sqlite3_snprintf(sizeof(zLine)-j, zLine+j, "'%q'", zCol); }else{ sqlite3_snprintf(sizeof(zLine)-j, zLine+j, "%s", zCol); } j += (int)strlen(zLine+j); } /* Detect if any row is too large and throw an error, because we will ** want to go back and look more closely at that case */ if( j>=sizeof(zLine)-100 ){ printf("Excessively long output line: %d bytes\n" ,j); exit(1); } if( bTrace ){ printf("%s\n", zLine); } (*pnRow)++; sqlite3_bind_text(pIns, 1, zLine, j, SQLITE_TRANSIENT); rc = sqlite3_step(pIns); assert( rc==SQLITE_DONE ); rc = sqlite3_reset(pIns); } run_sql(dbOut, "INSERT INTO \"%w\"(x) VALUES('### %q ###')", zOutTab, sqlite3_sql(pStmt) ); run_sql(dbOut, "INSERT INTO \"%w\"(x) SELECT group_concat(x,char(10))" " FROM (SELECT x FROM staging ORDER BY x)", zOutTab ); run_sql(dbOut, "COMMIT"); sqlite3_finalize(pStmt); pStmt = 0; } sqlite3_finalize(pStmt); sqlite3_finalize(pIns); return rc; } /* ** Read the content of file zName into memory obtained from sqlite3_malloc64() ** and return a pointer to the buffer. The caller is responsible for freeing ** the memory. ** ** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes ** read. ** ** For convenience, a nul-terminator byte is always appended to the data read ** from the file before the buffer is returned. This byte is not included in ** the final value of (*pnByte), if applicable. ** ** NULL is returned if any error is encountered. The final value of *pnByte ** is undefined in this case. */ static char *readFile(const char *zName, int *pnByte){ FILE *in = fopen(zName, "rb"); long nIn; size_t nRead; char *pBuf; if( in==0 ) return 0; fseek(in, 0, SEEK_END); nIn = ftell(in); rewind(in); pBuf = sqlite3_malloc64( nIn+1 ); if( pBuf==0 ) return 0; nRead = fread(pBuf, nIn, 1, in); fclose(in); if( nRead!=1 ){ sqlite3_free(pBuf); return 0; } pBuf[nIn] = 0; if( pnByte ) *pnByte = nIn; return pBuf; } int main(int argc, char **argv){ int nIn = 0; /* Number of input files */ char **azIn = 0; /* Names of input files */ sqlite3 *dbOut = 0; /* Database to hold results */ sqlite3 *dbRun = 0; /* Database used for tests */ int bTrace = 0; /* Show query results */ int bShowValid = 0; /* Just list inputs that are valid SQL */ int nRow, nStmt; /* Number of rows and statements */ int i, rc; for(i=1; i<argc; i++){ const char *z = argv[i]; if( z[0]=='-' && z[1]=='-' ) z++; if( strcmp(z,"-help")==0 ){ printf("Usage: %s [OPTIONS] FILENAME ...\n", argv[0]); printf("Options:\n"); printf(" --help Show his message\n"); printf(" --output-trace Show each line of SQL output\n"); printf(" --valid-sql List FILEs that are valid SQL\n"); return 0; } else if( strcmp(z,"-output-trace")==0 ){ bTrace = 1; } else if( strcmp(z,"-valid-sql")==0 ){ bShowValid = 1; } else if( z[0]=='-' ){ printf("unknown option \"%s\". Use --help for details\n", argv[i]); return 1; } else { nIn++; azIn = realloc(azIn, sizeof(azIn[0])*nIn); if( azIn==0 ){ printf("out of memory\n"); exit(1); } azIn[nIn-1] = argv[i]; } } sqlite3_open(":memory:", &dbOut); sqlite3_open(":memory:", &dbRun); sqlite3_deserialize(dbRun, "main", data001, sizeof(data001), sizeof(data001), SQLITE_DESERIALIZE_READONLY); for(i=0; i<nIn; i++){ char *zSql = readFile(azIn[i], 0); sqlite3_stmt *pCk; sqlite3_exec(dbRun, "ROLLBACK", 0, 0, 0); if( bShowValid ){ rc = sqlite3_exec(dbRun, zSql, 0, 0, 0); if( rc==SQLITE_OK ) printf("%s\n", azIn[i]); sqlite3_free(zSql); continue; } sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, dbRun, 0); if( bTrace ) printf("%s: Optimized\n", azIn[i]); rc = optfuzz_exec(dbRun, zSql, dbOut, "opt", &nStmt, &nRow, bTrace); if( rc ){ printf("%s: optimized run failed: %s\n", azIn[i], sqlite3_errmsg(dbRun)); }else{ sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, dbRun, 0xffff); if( bTrace ) printf("%s: Non-optimized\n", azIn[i]); rc = optfuzz_exec(dbRun, zSql, dbOut, "noopt", &nStmt, &nRow, bTrace); if( rc ){ printf("%s: non-optimized run failed: %s\n", azIn[i], sqlite3_errmsg(dbRun)); exit(1); } pCk = prepare_sql(dbOut, "SELECT (SELECT group_concat(x,char(10)) FROM opt)==" " (SELECT group_concat(x,char(10)) FROM noopt)"); rc = sqlite3_step(pCk); if( rc!=SQLITE_ROW ){ printf("%s: comparison failed\n", sqlite3_errmsg(dbOut)); exit(1); } if( !sqlite3_column_int(pCk, 0) ){ printf("%s: opt/no-opt outputs differ\n", azIn[i]); pCk = prepare_sql(dbOut, "SELECT group_concat(x,char(10)) FROM opt " "UNION ALL " "SELECT group_concat(x,char(10)) FROM noopt"); sqlite3_step(pCk); printf("opt:\n%s\n", sqlite3_column_text(pCk,0)); sqlite3_step(pCk); printf("noopt:\n%s\n", sqlite3_column_text(pCk,0)); exit(1); }else{ printf("%s: %d stmts %d rows ok\n", azIn[i], nStmt, nRow); } sqlite3_finalize(pCk); } sqlite3_free(zSql); } sqlite3_close(dbRun); sqlite3_close(dbOut); free(azIn); if( sqlite3_memory_used() ){ printf("Memory leak of %lld bytes\n", sqlite3_memory_used()); exit(1); } return 0; } |
Changes to test/permutations.test.
︙ | ︙ | |||
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 | } -dbconfig { $::dbhandle version -use-legacy-prepare 1 #$::dbhandle cache size 0 } -files [ test_set $allquicktests -exclude *malloc* *ioerr* *fault* \ stmtvtab1.test index9.test ] # End of tests ############################################################################# # run_tests NAME OPTIONS # # where available options are: | > > > > > > > > > > > > > > > > > > > > | 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 | } -dbconfig { $::dbhandle version -use-legacy-prepare 1 #$::dbhandle cache size 0 } -files [ test_set $allquicktests -exclude *malloc* *ioerr* *fault* \ stmtvtab1.test index9.test ] test_suite "sorterref" -prefix "" -description { Run the "veryquick" test suite with SQLITE_CONFIG_SORTERREF_SIZE set to 0 so that sorter-references are used whenever possible. } -files [ test_set $allquicktests -exclude *malloc* *ioerr* *fault* *bigfile* *_err* \ *fts5corrupt* *fts5big* *fts5aj* ] -initialize { catch {db close} sqlite3_shutdown sqlite3_config_sorterref 0 sqlite3_initialize autoinstall_test_functions } -shutdown { catch {db close} sqlite3_shutdown sqlite3_config_sorterref -1 sqlite3_initialize autoinstall_test_functions } # End of tests ############################################################################# # run_tests NAME OPTIONS # # where available options are: |
︙ | ︙ |
Changes to test/releasetest.tcl.
︙ | ︙ | |||
169 170 171 172 173 174 175 176 177 178 179 180 181 182 | -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_MAX_COMPOUND_SELECT=50 -DSQLITE_MAX_PAGE_SIZE=32768 -DSQLITE_OMIT_TRACE=1 -DSQLITE_TEMP_STORE=3 -DSQLITE_THREADSAFE=2 --enable-json1 --enable-fts5 --enable-session } "Locking-Style" { -O2 -DSQLITE_ENABLE_LOCKING_STYLE=1 } "Apple" { | > | 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_MAX_COMPOUND_SELECT=50 -DSQLITE_MAX_PAGE_SIZE=32768 -DSQLITE_OMIT_TRACE=1 -DSQLITE_TEMP_STORE=3 -DSQLITE_THREADSAFE=2 -DSQLITE_ENABLE_DESERIALIZE=1 --enable-json1 --enable-fts5 --enable-session } "Locking-Style" { -O2 -DSQLITE_ENABLE_LOCKING_STYLE=1 } "Apple" { |
︙ | ︙ |
Changes to test/shell1.test.
︙ | ︙ | |||
1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 | error "failed with error: $res" } if {$res ne "CREATE TABLE ${test}(x);"} { error "failed with mismatch: $res" } forcedelete test3.db } {} } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 | error "failed with error: $res" } if {$res ne "CREATE TABLE ${test}(x);"} { error "failed with mismatch: $res" } forcedelete test3.db } {} } db close forcedelete test.db test.db-journal test.db-wal sqlite3 db test.db # The shell tool ".schema" command uses virtual table "pragma_database_list" # ifcapable vtab { do_test shell1-7.1.1 { db eval { CREATE TABLE Z (x TEXT PRIMARY KEY); CREATE TABLE _ (x TEXT PRIMARY KEY); CREATE TABLE YY (x TEXT PRIMARY KEY); CREATE TABLE __ (x TEXT PRIMARY KEY); CREATE TABLE WWW (x TEXT PRIMARY KEY); CREATE TABLE ___ (x TEXT PRIMARY KEY); } } {} do_test shell1-7.1.2 { catchcmd "test.db" ".schema _" } {0 {CREATE TABLE Z (x TEXT PRIMARY KEY); CREATE TABLE _ (x TEXT PRIMARY KEY);}} do_test shell1-7.1.3 { catchcmd "test.db" ".schema \\\\_" } {0 {CREATE TABLE _ (x TEXT PRIMARY KEY);}} do_test shell1-7.1.4 { catchcmd "test.db" ".schema __" } {0 {CREATE TABLE YY (x TEXT PRIMARY KEY); CREATE TABLE __ (x TEXT PRIMARY KEY);}} do_test shell1-7.1.5 { catchcmd "test.db" ".schema \\\\_\\\\_" } {0 {CREATE TABLE __ (x TEXT PRIMARY KEY);}} do_test shell1-7.1.6 { catchcmd "test.db" ".schema ___" } {0 {CREATE TABLE WWW (x TEXT PRIMARY KEY); CREATE TABLE ___ (x TEXT PRIMARY KEY);}} do_test shell1-7.1.7 { catchcmd "test.db" ".schema \\\\_\\\\_\\\\_" } {0 {CREATE TABLE ___ (x TEXT PRIMARY KEY);}} } finish_test |
Changes to test/sort5.test.
︙ | ︙ | |||
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | } } catch { db close } forcedelete test.db sqlite3 db test.db -vfs tvfs execsql { CREATE TABLE t1(x) } # Each iteration of the following loop attempts to sort 10001 records # each a bit over 100 bytes in size. In total a little more than 1MiB # of data. # foreach {tn pgsz cachesz bTemp} { 1 4096 1000 0 2 1024 1000 1 3 4096 -1000 1 4 1024 -1000 1 5 4096 -9000 0 6 1024 -9000 0 } { do_execsql_test 2.$tn.0 " PRAGMA page_size = $pgsz; VACUUM; PRAGMA cache_size = $cachesz; " if {[db one {PRAGMA page_size}]!=$pgsz} { | > > > > | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | } } catch { db close } forcedelete test.db sqlite3 db test.db -vfs tvfs execsql { CREATE TABLE t1(x) } execsql { PRAGMA temp_store = 1 } # Each iteration of the following loop attempts to sort 10001 records # each a bit over 100 bytes in size. In total a little more than 1MiB # of data. # foreach {tn pgsz cachesz bTemp} { 1 4096 1000 0 2 1024 1000 1 3 4096 -1000 1 4 1024 -1000 1 5 4096 -9000 0 6 1024 -9000 0 } { if {$::TEMP_STORE>2} { set bTemp 0 } do_execsql_test 2.$tn.0 " PRAGMA page_size = $pgsz; VACUUM; PRAGMA cache_size = $cachesz; " if {[db one {PRAGMA page_size}]!=$pgsz} { |
︙ | ︙ |
Added test/sorterref.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | # 2018 April 14. # # 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. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix sorterref do_execsql_test 1.0 { CREATE TABLE t1(a, b, c); INSERT INTO t1 VALUES(1, 2, 3); INSERT INTO t1 VALUES(4, 5, 6); ALTER TABLE t1 ADD COLUMN d DEFAULT 'string'; INSERT INTO t1 VALUES(7, 8, 9, 'text'); } do_execsql_test 1.1 { SELECT * FROM t1 ORDER BY b; } { 1 2 3 string 4 5 6 string 7 8 9 text } do_execsql_test 2.0 { DROP TABLE IF EXISTS t1; CREATE TABLE t1(a, b); CREATE TABLE t2(c, d, PRIMARY KEY(c)) WITHOUT ROWID; INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(2, 3); INSERT INTO t1 VALUES(3, 4); INSERT INTO t2 VALUES(1, 'one'); INSERT INTO t2 VALUES(3, 'three'); } do_execsql_test 2.1 { SELECT * FROM t1 LEFT JOIN t2 ON (a=c) ORDER BY b; } {1 2 1 one 2 3 {} {} 3 4 3 three} finish_test |
Changes to test/speedtest1.c.
︙ | ︙ | |||
1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 | for(i=0; i<n; i++){ x1 = speedtest1_random()%nRow; sqlite3_bind_int(g.pStmt, 1, x1); speedtest1_run(); } speedtest1_end_test(); } /* ** A testset used for debugging speedtest1 itself. */ void testset_debug1(void){ unsigned i, n; unsigned x1, x2; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 | for(i=0; i<n; i++){ x1 = speedtest1_random()%nRow; sqlite3_bind_int(g.pStmt, 1, x1); speedtest1_run(); } speedtest1_end_test(); } /* */ void testset_trigger(void){ int jj, ii; char zNum[2000]; /* A number name */ const int NROW = 500*g.szTest; const int NROW2 = 100*g.szTest; speedtest1_exec( "BEGIN;" "CREATE TABLE t1(rowid INTEGER PRIMARY KEY, i INTEGER, t TEXT);" "CREATE TABLE t2(rowid INTEGER PRIMARY KEY, i INTEGER, t TEXT);" "CREATE TABLE t3(rowid INTEGER PRIMARY KEY, i INTEGER, t TEXT);" "CREATE VIEW v1 AS SELECT rowid, i, t FROM t1;" "CREATE VIEW v2 AS SELECT rowid, i, t FROM t2;" "CREATE VIEW v3 AS SELECT rowid, i, t FROM t3;" ); for(jj=1; jj<=3; jj++){ speedtest1_prepare("INSERT INTO t%d VALUES(NULL,?1,?2)", jj); for(ii=0; ii<NROW; ii++){ int x1 = speedtest1_random() % NROW; speedtest1_numbername(x1, zNum, sizeof(zNum)); sqlite3_bind_int(g.pStmt, 1, x1); sqlite3_bind_text(g.pStmt, 2, zNum, -1, SQLITE_STATIC); speedtest1_run(); } } speedtest1_exec( "CREATE INDEX i1 ON t1(t);" "CREATE INDEX i2 ON t2(t);" "CREATE INDEX i3 ON t3(t);" "COMMIT;" ); speedtest1_begin_test(100, "speed4p-join1"); speedtest1_prepare( "SELECT * FROM t1, t2, t3 WHERE t1.oid = t2.oid AND t2.oid = t3.oid" ); speedtest1_run(); speedtest1_end_test(); speedtest1_begin_test(110, "speed4p-join2"); speedtest1_prepare( "SELECT * FROM t1, t2, t3 WHERE t1.t = t2.t AND t2.t = t3.t" ); speedtest1_run(); speedtest1_end_test(); speedtest1_begin_test(120, "speed4p-view1"); for(jj=1; jj<=3; jj++){ speedtest1_prepare("SELECT * FROM v%d WHERE rowid = ?", jj); for(ii=0; ii<NROW2; ii+=3){ sqlite3_bind_int(g.pStmt, 1, ii*3); speedtest1_run(); } } speedtest1_end_test(); speedtest1_begin_test(130, "speed4p-table1"); for(jj=1; jj<=3; jj++){ speedtest1_prepare("SELECT * FROM t%d WHERE rowid = ?", jj); for(ii=0; ii<NROW2; ii+=3){ sqlite3_bind_int(g.pStmt, 1, ii*3); speedtest1_run(); } } speedtest1_end_test(); speedtest1_begin_test(140, "speed4p-table1"); for(jj=1; jj<=3; jj++){ speedtest1_prepare("SELECT * FROM t%d WHERE rowid = ?", jj); for(ii=0; ii<NROW2; ii+=3){ sqlite3_bind_int(g.pStmt, 1, ii*3); speedtest1_run(); } } speedtest1_end_test(); speedtest1_begin_test(150, "speed4p-subselect1"); speedtest1_prepare("SELECT " "(SELECT t FROM t1 WHERE rowid = ?1)," "(SELECT t FROM t2 WHERE rowid = ?1)," "(SELECT t FROM t3 WHERE rowid = ?1)" ); for(jj=0; jj<NROW2; jj++){ sqlite3_bind_int(g.pStmt, 1, jj*3); speedtest1_run(); } speedtest1_end_test(); speedtest1_begin_test(160, "speed4p-rowid-update"); speedtest1_exec("BEGIN"); speedtest1_prepare("UPDATE t1 SET i=i+1 WHERE rowid=?1"); for(jj=0; jj<NROW2; jj++){ sqlite3_bind_int(g.pStmt, 1, jj); speedtest1_run(); } speedtest1_exec("COMMIT"); speedtest1_end_test(); speedtest1_exec("CREATE TABLE t5(t TEXT PRIMARY KEY, i INTEGER);"); speedtest1_begin_test(170, "speed4p-insert-ignore"); speedtest1_exec("INSERT OR IGNORE INTO t5 SELECT t, i FROM t1"); speedtest1_end_test(); speedtest1_exec( "CREATE TABLE log(op TEXT, r INTEGER, i INTEGER, t TEXT);" "CREATE TABLE t4(rowid INTEGER PRIMARY KEY, i INTEGER, t TEXT);" "CREATE TRIGGER t4_trigger1 AFTER INSERT ON t4 BEGIN" " INSERT INTO log VALUES('INSERT INTO t4', new.rowid, new.i, new.t);" "END;" "CREATE TRIGGER t4_trigger2 AFTER UPDATE ON t4 BEGIN" " INSERT INTO log VALUES('UPDATE OF t4', new.rowid, new.i, new.t);" "END;" "CREATE TRIGGER t4_trigger3 AFTER DELETE ON t4 BEGIN" " INSERT INTO log VALUES('DELETE OF t4', old.rowid, old.i, old.t);" "END;" "BEGIN;" ); speedtest1_begin_test(180, "speed4p-trigger1"); speedtest1_prepare("INSERT INTO t4 VALUES(NULL, ?1, ?2)"); for(jj=0; jj<NROW2; jj++){ speedtest1_numbername(jj, zNum, sizeof(zNum)); sqlite3_bind_int(g.pStmt, 1, jj); sqlite3_bind_text(g.pStmt, 2, zNum, -1, SQLITE_STATIC); speedtest1_run(); } speedtest1_end_test(); /* ** Note: Of the queries, only half actually update a row. This property ** was copied over from speed4p.test, where it was probably introduced ** inadvertantly. */ speedtest1_begin_test(190, "speed4p-trigger2"); speedtest1_prepare("UPDATE t4 SET i = ?1, t = ?2 WHERE rowid = ?3"); for(jj=1; jj<=NROW2*2; jj+=2){ speedtest1_numbername(jj*2, zNum, sizeof(zNum)); sqlite3_bind_int(g.pStmt, 1, jj*2); sqlite3_bind_text(g.pStmt, 2, zNum, -1, SQLITE_STATIC); sqlite3_bind_int(g.pStmt, 3, jj); speedtest1_run(); } speedtest1_end_test(); /* ** Note: Same again. */ speedtest1_begin_test(200, "speed4p-trigger3"); speedtest1_prepare("DELETE FROM t4 WHERE rowid = ?1"); for(jj=1; jj<=NROW2*2; jj+=2){ sqlite3_bind_int(g.pStmt, 1, jj*2); speedtest1_run(); } speedtest1_end_test(); speedtest1_exec("COMMIT"); /* ** The following block contains the same tests as the above block that ** tests triggers, with one crucial difference: no triggers are defined. ** So the difference in speed between these tests and the preceding ones ** is the amount of time taken to compile and execute the trigger programs. */ speedtest1_exec( "DROP TABLE t4;" "DROP TABLE log;" "VACUUM;" "CREATE TABLE t4(rowid INTEGER PRIMARY KEY, i INTEGER, t TEXT);" "BEGIN;" ); speedtest1_begin_test(210, "speed4p-notrigger1"); speedtest1_prepare("INSERT INTO t4 VALUES(NULL, ?1, ?2)"); for(jj=0; jj<NROW2; jj++){ speedtest1_numbername(jj, zNum, sizeof(zNum)); sqlite3_bind_int(g.pStmt, 1, jj); sqlite3_bind_text(g.pStmt, 2, zNum, -1, SQLITE_STATIC); speedtest1_run(); } speedtest1_end_test(); speedtest1_begin_test(210, "speed4p-notrigger2"); speedtest1_prepare("UPDATE t4 SET i = ?1, t = ?2 WHERE rowid = ?3"); for(jj=1; jj<=NROW2*2; jj+=2){ speedtest1_numbername(jj*2, zNum, sizeof(zNum)); sqlite3_bind_int(g.pStmt, 1, jj*2); sqlite3_bind_text(g.pStmt, 2, zNum, -1, SQLITE_STATIC); sqlite3_bind_int(g.pStmt, 3, jj); speedtest1_run(); } speedtest1_end_test(); speedtest1_begin_test(220, "speed4p-notrigger3"); speedtest1_prepare("DELETE FROM t4 WHERE rowid = ?1"); for(jj=1; jj<=NROW2*2; jj+=2){ sqlite3_bind_int(g.pStmt, 1, jj*2); speedtest1_run(); } speedtest1_end_test(); speedtest1_exec("COMMIT"); } /* ** A testset used for debugging speedtest1 itself. */ void testset_debug1(void){ unsigned i, n; unsigned x1, x2; |
︙ | ︙ | |||
1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 | testset_debug1(); }else if( strcmp(zTSet,"orm")==0 ){ testset_orm(); }else if( strcmp(zTSet,"cte")==0 ){ testset_cte(); }else if( strcmp(zTSet,"fp")==0 ){ testset_fp(); }else if( strcmp(zTSet,"rtree")==0 ){ #ifdef SQLITE_ENABLE_RTREE testset_rtree(6, 147); #else fatal_error("compile with -DSQLITE_ENABLE_RTREE to enable " "the R-Tree tests\n"); #endif }else{ | > > | > | 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 | testset_debug1(); }else if( strcmp(zTSet,"orm")==0 ){ testset_orm(); }else if( strcmp(zTSet,"cte")==0 ){ testset_cte(); }else if( strcmp(zTSet,"fp")==0 ){ testset_fp(); }else if( strcmp(zTSet,"trigger")==0 ){ testset_trigger(); }else if( strcmp(zTSet,"rtree")==0 ){ #ifdef SQLITE_ENABLE_RTREE testset_rtree(6, 147); #else fatal_error("compile with -DSQLITE_ENABLE_RTREE to enable " "the R-Tree tests\n"); #endif }else{ fatal_error("unknown testset: \"%s\"\n" "Choices: cte debug1 fp main orm rtree trigger\n", zTSet); } speedtest1_final(); if( showStats ){ sqlite3_exec(g.db, "PRAGMA compile_options", xCompileOptions, 0, 0); } |
︙ | ︙ |
Changes to test/subquery2.test.
︙ | ︙ | |||
143 144 145 146 147 148 149 150 151 152 | SELECT data, id FROM ( SELECT id, data FROM ( SELECT * FROM t3 UNION ALL SELECT * FROM t4 ) ORDER BY data ); } {a 4 b 3 c 2 d 1} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | SELECT data, id FROM ( SELECT id, data FROM ( SELECT * FROM t3 UNION ALL SELECT * FROM t4 ) ORDER BY data ); } {a 4 b 3 c 2 d 1} #------------------------------------------------------------------------- do_execsql_test 4.0 { CREATE TABLE t6(x); } foreach {tn sql} { 1 { SELECT 'abc' FROM ( SELECT x FROM t6 ORDER BY 1 UNION ALL SELECT x FROM t6 ) } 2 { SELECT 'abc' FROM ( SELECT x FROM t6 UNION ALL SELECT x FROM t6 ORDER BY 1 UNION ALL SELECT x FROM t6 ) } 3 { SELECT 'abc' FROM ( SELECT x FROM t6 ORDER BY 1 UNION ALL SELECT x FROM t6 ORDER BY 1 UNION ALL SELECT x FROM t6 ) } 4 { SELECT 'abc' FROM ( SELECT x FROM t6 UNION ALL SELECT x FROM t6 ORDER BY 1 UNION ALL SELECT x FROM t6 ORDER BY 1 UNION ALL SELECT x FROM t6 ) } } { do_catchsql_test 4.$tn $sql [list {*}{ 1 {ORDER BY clause should come after UNION ALL not before} }] } finish_test |
Changes to test/tempdb2.test.
︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 21 22 23 24 25 | set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix tempdb2 db close sqlite3 db "" proc int2str {i} { string range [string repeat "$i." 450] 0 899 } db func int2str int2str #------------------------------------------------------------------------- # # 1.1: Write a big transaction to the db. One so large that it forces # the file to be created and the cache flushed to disk on COMMIT. | > > > | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix tempdb2 db close sqlite3 db "" set unlocked unlocked if {$::TEMP_STORE>=2} { set unlocked unknown } proc int2str {i} { string range [string repeat "$i." 450] 0 899 } db func int2str int2str #------------------------------------------------------------------------- # # 1.1: Write a big transaction to the db. One so large that it forces # the file to be created and the cache flushed to disk on COMMIT. |
︙ | ︙ | |||
51 52 53 54 55 56 57 | CREATE TABLE t2(a INTEGER PRIMARY KEY, b); WITH c(x) AS ( VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100 ) INSERT INTO t2 SELECT x, int2str(x) FROM c; COMMIT; PRAGMA lock_status; | | | 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | CREATE TABLE t2(a INTEGER PRIMARY KEY, b); WITH c(x) AS ( VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100 ) INSERT INTO t2 SELECT x, int2str(x) FROM c; COMMIT; PRAGMA lock_status; } [list main $unlocked temp closed] do_execsql_test 1.2 { UPDATE t1 SET b=int2str(2); SELECT b=int2str(2) FROM t1 } {1 1 1} do_execsql_test 1.3 { |
︙ | ︙ |
Changes to test/temptable2.test.
︙ | ︙ | |||
340 341 342 343 344 345 346 | WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<500 ) INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x; COMMIT; INSERT INTO t2 VALUES(3, 4); } ifcapable mmap { | | | 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 | WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<500 ) INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM x; COMMIT; INSERT INTO t2 VALUES(3, 4); } ifcapable mmap { if {[permutation]!="journaltest" && $::TEMP_STORE<2} { # The journaltest permutation does not support mmap, so this part of # the test is omitted. do_execsql_test 10.2 { PRAGMA mmap_size = 512000 } 512000 } } do_execsql_test 10.3 { SELECT * FROM t2 } {1 2 3 4} |
︙ | ︙ |
Changes to test/trace3.test.
︙ | ︙ | |||
125 126 127 128 129 130 131 | set ::stmtlist(record) {} db trace_v2 trace_v2_record profile execsql { SELECT a, b FROM t1 ORDER BY a; } set stmt [lindex [lindex $::stmtlist(record) 0] 0] set ns [lindex [lindex $::stmtlist(record) 0] 1] | | | | 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | set ::stmtlist(record) {} db trace_v2 trace_v2_record profile execsql { SELECT a, b FROM t1 ORDER BY a; } set stmt [lindex [lindex $::stmtlist(record) 0] 0] set ns [lindex [lindex $::stmtlist(record) 0] 1] list $stmt [expr {$ns >= 0 && $ns <= 9999999}]; # less than 0.010 seconds } {/^-?\d+ 1$/} do_test trace3-4.4 { set ::stmtlist(record) {} db trace_v2 trace_v2_record 2 execsql { SELECT a, b FROM t1 ORDER BY a; } set stmt [lindex [lindex $::stmtlist(record) 0] 0] set ns [lindex [lindex $::stmtlist(record) 0] 1] list $stmt [expr {$ns >= 0 && $ns <= 9999999}]; # less than 0.010 seconds } {/^-?\d+ 1$/} do_test trace3-5.1 { set ::stmtlist(record) {} db trace_v2 trace_v2_record row execsql { SELECT a, b FROM t1 ORDER BY a; |
︙ | ︙ |
Changes to test/triggerE.test.
︙ | ︙ | |||
53 54 55 56 57 58 59 60 61 62 63 64 65 66 | 2 { BEFORE DELETE ON t1 BEGIN SELECT ?; END; } 3 { BEFORE DELETE ON t1 BEGIN SELECT * FROM (SELECT * FROM (SELECT ?)); END; } 5 { BEFORE DELETE ON t1 BEGIN SELECT * FROM t2 GROUP BY ?; END; } 6 { BEFORE DELETE ON t1 BEGIN SELECT * FROM t2 LIMIT ?; END; } 7 { BEFORE DELETE ON t1 BEGIN SELECT * FROM t2 ORDER BY ?; END; } 8 { BEFORE UPDATE ON t1 BEGIN UPDATE t2 SET c = ?; END; } 9 { BEFORE UPDATE ON t1 BEGIN UPDATE t2 SET c = 1 WHERE d = ?; END; } } { catchsql {drop trigger tr1} do_catchsql_test 1.1.$tn "CREATE TRIGGER tr1 $defn" [list 1 $errmsg] do_catchsql_test 1.2.$tn "CREATE TEMP TRIGGER tr1 $defn" [list 1 $errmsg] } #------------------------------------------------------------------------- | > | 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | 2 { BEFORE DELETE ON t1 BEGIN SELECT ?; END; } 3 { BEFORE DELETE ON t1 BEGIN SELECT * FROM (SELECT * FROM (SELECT ?)); END; } 5 { BEFORE DELETE ON t1 BEGIN SELECT * FROM t2 GROUP BY ?; END; } 6 { BEFORE DELETE ON t1 BEGIN SELECT * FROM t2 LIMIT ?; END; } 7 { BEFORE DELETE ON t1 BEGIN SELECT * FROM t2 ORDER BY ?; END; } 8 { BEFORE UPDATE ON t1 BEGIN UPDATE t2 SET c = ?; END; } 9 { BEFORE UPDATE ON t1 BEGIN UPDATE t2 SET c = 1 WHERE d = ?; END; } 10 { AFTER INSERT ON t1 BEGIN SELECT * FROM pragma_stats(?); END; } } { catchsql {drop trigger tr1} do_catchsql_test 1.1.$tn "CREATE TRIGGER tr1 $defn" [list 1 $errmsg] do_catchsql_test 1.2.$tn "CREATE TEMP TRIGGER tr1 $defn" [list 1 $errmsg] } #------------------------------------------------------------------------- |
︙ | ︙ |
Changes to test/update.test.
︙ | ︙ | |||
504 505 506 507 508 509 510 511 512 513 514 515 516 517 | } {2 14 3 7} do_test update-11.2 { execsql { UPDATE t1 SET e=e+1 WHERE a IN (SELECT a FROM t1); SELECT a,e FROM t1; } } {1 15 2 8} } integrity_check update-12.1 # Ticket 602. Updates should occur in the same order as the records # were discovered in the WHERE clause. # | > > > > > > > > > > > > | 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 | } {2 14 3 7} do_test update-11.2 { execsql { UPDATE t1 SET e=e+1 WHERE a IN (SELECT a FROM t1); SELECT a,e FROM t1; } } {1 15 2 8} do_test update-11.3 { execsql { UPDATE t1 AS xyz SET e=e+1 WHERE xyz.a IN (SELECT a FROM t1); SELECT a,e FROM t1; } } {1 16 2 9} do_test update-11.4 { execsql { UPDATE t1 AS xyz SET e=e+1 WHERE EXISTS(SELECT 1 FROM t1 WHERE t1.a<xyz.a); SELECT a,e FROM t1; } } {1 16 2 10} } integrity_check update-12.1 # Ticket 602. Updates should occur in the same order as the records # were discovered in the WHERE clause. # |
︙ | ︙ | |||
614 615 616 617 618 619 620 | CREATE INDEX t15c ON t15(c); INSERT INTO t15(a,b) VALUES(5,'zyx'),(15,'wvu'),(25,'tsr'),(35,'qpo'); UPDATE t15 SET c=printf("y%d",a) WHERE c IS NULL; SELECT a,b,c,'|' FROM t15 ORDER BY a; } {5 zyx y5 | 10 abc y10 | 15 wvu y15 | 20 def y20 | 25 tsr y25 | 30 ghi y30 | 35 qpo y35 |} | > > > | > > > > > > > | 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 | CREATE INDEX t15c ON t15(c); INSERT INTO t15(a,b) VALUES(5,'zyx'),(15,'wvu'),(25,'tsr'),(35,'qpo'); UPDATE t15 SET c=printf("y%d",a) WHERE c IS NULL; SELECT a,b,c,'|' FROM t15 ORDER BY a; } {5 zyx y5 | 10 abc y10 | 15 wvu y15 | 20 def y20 | 25 tsr y25 | 30 ghi y30 | 35 qpo y35 |} # Unreleased bug in UPDATE caused by the UPSERT changes. # Found by OSSFuzz as soon as the UPSERT changes landed on trunk. # Never released into the wild. 2018-04-19. # do_execsql_test update-16.1 { CREATE TABLE t16(a INTEGER PRIMARY KEY ON CONFLICT REPLACE, b UNIQUE); INSERT INTO t16(a,b) VALUES(1,2),(3,4),(5,6); UPDATE t16 SET a=a; SELECT * FROM t16 ORDER BY +a; } {1 2 3 4 5 6} finish_test |
Added test/upsert1.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | # 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. # #*********************************************************************** # # Test cases for UPSERT set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix zipfile do_execsql_test upsert1-100 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c DEFAULT 0); CREATE UNIQUE INDEX t1x1 ON t1(b); INSERT INTO t1(a,b) VALUES(1,2) ON CONFLICT DO NOTHING; INSERT INTO t1(a,b) VALUES(1,99),(99,2) ON CONFLICT DO NOTHING; SELECT * FROM t1; } {1 2 0} do_execsql_test upsert1-101 { DELETE FROM t1; INSERT INTO t1(a,b) VALUES(2,3) ON CONFLICT(a) DO NOTHING; INSERT INTO t1(a,b) VALUES(2,99) ON CONFLICT(a) DO NOTHING; SELECT * FROM t1; } {2 3 0} do_execsql_test upsert1-102 { DELETE FROM t1; INSERT INTO t1(a,b) VALUES(3,4) ON CONFLICT(b) DO NOTHING; INSERT INTO t1(a,b) VALUES(99,4) ON CONFLICT(b) DO NOTHING; SELECT * FROM t1; } {3 4 0} do_catchsql_test upsert1-110 { INSERT INTO t1(a,b) VALUES(5,6) ON CONFLICT(x) DO NOTHING; SELECT * FROM t1; } {1 {no such column: x}} do_catchsql_test upsert1-120 { INSERT INTO t1(a,b) VALUES(5,6) ON CONFLICT(c) DO NOTHING; SELECT * FROM t1; } {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}} breakpoint do_catchsql_test upsert1-130 { INSERT INTO t1(a,b) VALUES(5,6) ON CONFLICT(b COLLATE nocase) DO NOTHING; SELECT * FROM t1; } {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}} do_execsql_test upsert1-140 { DELETE FROM t1; INSERT INTO t1(a,b) VALUES(5,6) ON CONFLICT(b COLLATE binary) DO NOTHING; SELECT * FROM t1; } {5 6 0} do_catchsql_test upsert1-200 { DROP TABLE t1; CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT, c DEFAULT 0); CREATE UNIQUE INDEX t1x1 ON t1(a+b); INSERT INTO t1(a,b) VALUES(7,8) ON CONFLICT(a+b) DO NOTHING; INSERT INTO t1(a,b) VALUES(8,7),(9,6) ON CONFLICT(a+b) DO NOTHING; SELECT * FROM t1; } {0 {7 8 0}} do_catchsql_test upsert1-201 { INSERT INTO t1(a,b) VALUES(8,7),(9,6) ON CONFLICT(a) DO NOTHING; } {1 {UNIQUE constraint failed: index 't1x1'}} do_catchsql_test upsert1-210 { DELETE FROM t1; INSERT INTO t1(a,b) VALUES(9,10) ON CONFLICT(a+(+b)) DO NOTHING; SELECT * FROM t1; } {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}} do_catchsql_test upsert1-300 { DROP INDEX t1x1; DELETE FROM t1; CREATE UNIQUE INDEX t1x1 ON t1(b) WHERE b>10; INSERT INTO t1(a,b) VALUES(1,2),(3,2) ON CONFLICT(b) DO NOTHING; SELECT * FROM t1; } {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}} do_catchsql_test upsert1-310 { DELETE FROM t1; INSERT INTO t1(a,b) VALUES(1,2),(3,2) ON CONFLICT(b) WHERE b!=10 DO NOTHING; SELECT * FROM t1; } {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}} do_execsql_test upsert1-320 { DELETE FROM t1; INSERT INTO t1(a,b) VALUES(1,2),(3,2),(4,20),(5,20) ON CONFLICT(b) WHERE b>10 DO NOTHING; SELECT *, 'x' FROM t1 ORDER BY b, a; } {1 2 0 x 3 2 0 x 4 20 0 x} # Upsert works with count_changes=on; do_execsql_test upsert1-400 { DROP TABLE IF EXISTS t2; CREATE TABLE t2(a TEXT UNIQUE, b INT DEFAULT 1); INSERT INTO t2(a) VALUES('one'),('two'),('three'); PRAGMA count_changes=ON; INSERT INTO t2(a) VALUES('one'),('one'),('three'),('four') ON CONFLICT(a) DO UPDATE SET b=b+1; } {1} do_execsql_test upsert1-410 { PRAGMA count_changes=OFF; SELECT a, b FROM t2 ORDER BY a; } {four 1 one 3 three 2 two 1} # Problem found by AFL prior to any release do_execsql_test upsert1-500 { DROP TABLE t1; CREATE TABLE t1(x INTEGER PRIMARY KEY, y INT UNIQUE); INSERT INTO t1(x,y) SELECT 1,2 WHERE true ON CONFLICT(x) DO UPDATE SET y=max(t1.y,excluded.y) AND true; SELECT * FROM t1; } {1 2} finish_test |
Added test/upsert2.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | # 2018-04-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. # #*********************************************************************** # # Test cases for UPSERT set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix zipfile do_execsql_test upsert2-100 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b int, c DEFAULT 0); INSERT INTO t1(a,b) VALUES(1,2),(3,4); INSERT INTO t1(a,b) VALUES(1,8),(2,11),(3,1) ON CONFLICT(a) DO UPDATE SET b=excluded.b, c=c+1 WHERE t1.b<excluded.b; SELECT *, 'x' FROM t1 ORDER BY a; } {1 8 1 x 2 11 0 x 3 4 0 x} do_execsql_test upsert2-110 { DROP TABLE t1; CREATE TABLE t1(a INT PRIMARY KEY, b int, c DEFAULT 0) WITHOUT ROWID; INSERT INTO t1(a,b) VALUES(1,2),(3,4); INSERT INTO t1(a,b) VALUES(1,8),(2,11),(3,1) ON CONFLICT(a) DO UPDATE SET b=excluded.b, c=c+1 WHERE t1.b<excluded.b; SELECT *, 'x' FROM t1 ORDER BY a; } {1 8 1 x 2 11 0 x 3 4 0 x} do_execsql_test upsert2-200 { DROP TABLE t1; CREATE TABLE t1(a INTEGER PRIMARY KEY, b int, c DEFAULT 0); INSERT INTO t1(a,b) VALUES(1,2),(3,4); WITH nx(a,b) AS (VALUES(1,8),(2,11),(3,1),(2,15),(1,4),(1,99)) INSERT INTO t1(a,b) SELECT a, b FROM nx WHERE true ON CONFLICT(a) DO UPDATE SET b=excluded.b, c=c+1 WHERE t1.b<excluded.b; SELECT *, 'x' FROM t1 ORDER BY a; } {1 99 2 x 2 15 1 x 3 4 0 x} do_execsql_test upsert2-201 { DELETE FROM t1; INSERT INTO t1(a,b) VALUES(1,2),(3,4); WITH nx(a,b) AS (VALUES(1,8),(2,11),(3,1),(2,15),(1,4),(1,99)) INSERT INTO main.t1 AS t2(a,b) SELECT a, b FROM nx WHERE true ON CONFLICT(a) DO UPDATE SET b=excluded.b, c=t2.c+1 WHERE t2.b<excluded.b; SELECT *, 'x' FROM t1 ORDER BY a; } {1 99 2 x 2 15 1 x 3 4 0 x} do_catchsql_test upsert2-202 { WITH nx(a,b) AS (VALUES(1,8),(2,11),(3,1),(2,15),(1,4),(1,99)) INSERT INTO t1 AS t2(a,b) SELECT a, b FROM nx WHERE true ON CONFLICT(a) DO UPDATE SET b=excluded.b, c=t1.c+1 WHERE t1.b<excluded.b; } {1 {no such column: t1.c}} do_execsql_test upsert2-210 { DROP TABLE t1; CREATE TABLE t1(a INT PRIMARY KEY, b int, c DEFAULT 0) WITHOUT ROWID; INSERT INTO t1(a,b) VALUES(1,2),(3,4); WITH nx(a,b) AS (VALUES(1,8),(2,11),(3,1),(2,15),(1,4),(1,99)) INSERT INTO t1(a,b) SELECT a, b FROM nx WHERE true ON CONFLICT(a) DO UPDATE SET b=excluded.b, c=c+1 WHERE t1.b<excluded.b; SELECT *, 'x' FROM t1 ORDER BY a; } {1 99 2 x 2 15 1 x 3 4 0 x} # On an ON CONFLICT DO UPDATE, the before-insert, before-update, and # after-update triggers fire. # do_execsql_test upsert2-300 { DROP TABLE t1; CREATE TABLE t1(a INTEGER PRIMARY KEY, b int, c DEFAULT 0); CREATE TABLE record(x TEXT, y TEXT); CREATE TRIGGER r1 BEFORE INSERT ON t1 BEGIN INSERT INTO record(x,y) VALUES('before-insert',printf('%d,%d,%d',new.a,new.b,new.c)); END; CREATE TRIGGER r2 AFTER INSERT ON t1 BEGIN INSERT INTO record(x,y) VALUES('after-insert',printf('%d,%d,%d',new.a,new.b,new.c)); END; CREATE TRIGGER r3 BEFORE UPDATE ON t1 BEGIN INSERT INTO record(x,y) VALUES('before-update',printf('%d,%d,%d/%d,%d,%d', old.a,old.b,old.c,new.a,new.b,new.c)); END; CREATE TRIGGER r4 AFTER UPDATE ON t1 BEGIN INSERT INTO record(x,y) VALUES('after-update',printf('%d,%d,%d/%d,%d,%d', old.a,old.b,old.c,new.a,new.b,new.c)); END; INSERT INTO t1(a,b) VALUES(1,2); DELETE FROM record; INSERT INTO t1(a,b) VALUES(1,2) ON CONFLICT(a) DO UPDATE SET c=t1.c+1; SELECT * FROM record } {before-insert 1,2,0 before-update 1,2,0/1,2,1 after-update 1,2,0/1,2,1} # On an ON CONFLICT DO NOTHING, only the before-insert trigger fires. # do_execsql_test upsert2-310 { DELETE FROM record; INSERT INTO t1(a,b) VALUES(1,2) ON CONFLICT DO NOTHING; SELECT * FROM record; } {before-insert 1,2,0} # With ON CONFLICT DO UPDATE and a failed WHERE, only the before-insert # trigger fires. # do_execsql_test upsert2-320 { DELETE FROM record; INSERT INTO t1(a,b) VALUES(1,2) ON CONFLICT(a) DO UPDATE SET c=c+1 WHERE c<0; SELECT * FROM record; } {before-insert 1,2,0} do_execsql_test upsert2-321 { SELECT * FROM t1; } {1 2 1} # Trigger tests repeated for a WITHOUT ROWID table. # do_execsql_test upsert2-400 { DROP TABLE t1; CREATE TABLE t1(a INT PRIMARY KEY, b int, c DEFAULT 0) WITHOUT ROWID; CREATE TRIGGER r1 BEFORE INSERT ON t1 BEGIN INSERT INTO record(x,y) VALUES('before-insert',printf('%d,%d,%d',new.a,new.b,new.c)); END; CREATE TRIGGER r2 AFTER INSERT ON t1 BEGIN INSERT INTO record(x,y) VALUES('after-insert',printf('%d,%d,%d',new.a,new.b,new.c)); END; CREATE TRIGGER r3 BEFORE UPDATE ON t1 BEGIN INSERT INTO record(x,y) VALUES('before-update',printf('%d,%d,%d/%d,%d,%d', old.a,old.b,old.c,new.a,new.b,new.c)); END; CREATE TRIGGER r4 AFTER UPDATE ON t1 BEGIN INSERT INTO record(x,y) VALUES('after-update',printf('%d,%d,%d/%d,%d,%d', old.a,old.b,old.c,new.a,new.b,new.c)); END; INSERT INTO t1(a,b) VALUES(1,2); DELETE FROM record; INSERT INTO t1(a,b) VALUES(1,2) ON CONFLICT(a) DO UPDATE SET c=t1.c+1; SELECT * FROM record } {before-insert 1,2,0 before-update 1,2,0/1,2,1 after-update 1,2,0/1,2,1} # On an ON CONFLICT DO NOTHING, only the before-insert trigger fires. # do_execsql_test upsert2-410 { DELETE FROM record; INSERT INTO t1(a,b) VALUES(1,2) ON CONFLICT DO NOTHING; SELECT * FROM record; } {before-insert 1,2,0} # With ON CONFLICT DO UPDATE and a failed WHERE, only the before-insert # trigger fires. # do_execsql_test upsert2-420 { DELETE FROM record; INSERT INTO t1(a,b) VALUES(1,2) ON CONFLICT(a) DO UPDATE SET c=c+1 WHERE c<0; SELECT * FROM record; } {before-insert 1,2,0} do_execsql_test upsert2-421 { SELECT * FROM t1; } {1 2 1} finish_test |
Added test/upsert3.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | # 2018-04-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. # #*********************************************************************** # # Test cases for UPSERT # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix zipfile do_execsql_test upsert3-100 { CREATE TABLE t1(k int, v text); CREATE UNIQUE INDEX x1 ON t1(k, v); } {} do_catchsql_test upsert3-110 { INSERT INTO t1 VALUES(0,'abcdefghij') ON CONFLICT(k) DO NOTHING; } {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}} do_catchsql_test upsert3-120 { INSERT INTO t1 VALUES(0,'abcdefghij') ON CONFLICT(v) DO NOTHING; } {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}} do_execsql_test upsert3-130 { INSERT INTO t1 VALUES(0, 'abcdefghij') ON CONFLICT(k,v) DO NOTHING; SELECT * FROM t1; } {0 abcdefghij} do_execsql_test upsert3-140 { INSERT INTO t1 VALUES(0, 'abcdefghij') ON CONFLICT(v,k) DO NOTHING; SELECT * FROM t1; } {0 abcdefghij} do_execsql_test upsert3-200 { CREATE TABLE excluded(a INT, b INT, c INT DEFAULT 0); CREATE UNIQUE INDEX excludedab ON excluded(a,b); INSERT INTO excluded(a,b) VALUES(1,2),(1,2),(3,4),(1,2),(5,6),(3,4) ON CONFLICT(b,a) DO UPDATE SET c=excluded.c+1; SELECT *, 'x' FROM excluded ORDER BY a; } {1 2 2 x 3 4 1 x 5 6 0 x} do_execsql_test upsert3-210 { INSERT INTO excluded AS base(a,b,c) VALUES(1,2,8),(1,2,3) ON CONFLICT(b,a) DO UPDATE SET c=excluded.c+1 WHERE base.c<excluded.c; SELECT *, 'x' FROM excluded ORDER BY a; } {1 2 9 x 3 4 1 x 5 6 0 x} finish_test |
Added test/upsert4.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 | # 2018-04-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. # #*********************************************************************** # # Test cases for UPSERT set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix upsert4 foreach {tn sql} { 1 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c UNIQUE) } 2 { CREATE TABLE t1(a INT PRIMARY KEY, b, c UNIQUE) } 3 { CREATE TABLE t1(a INT PRIMARY KEY, b, c UNIQUE) WITHOUT ROWID} } { reset_db execsql $sql do_execsql_test 1.$tn.0 { INSERT INTO t1 VALUES(1, NULL, 'one'); INSERT INTO t1 VALUES(2, NULL, 'two'); INSERT INTO t1 VALUES(3, NULL, 'three'); } do_execsql_test 1.$tn.1 { INSERT INTO t1 VALUES(1, NULL, 'xyz') ON CONFLICT DO NOTHING; SELECT * FROM t1; } { 1 {} one 2 {} two 3 {} three } do_execsql_test 1.$tn.2 { INSERT INTO t1 VALUES(4, NULL, 'two') ON CONFLICT DO NOTHING; SELECT * FROM t1; } { 1 {} one 2 {} two 3 {} three } do_execsql_test 1.$tn.3 { INSERT INTO t1 VALUES(4, NULL, 'two') ON CONFLICT (c) DO UPDATE SET b = 1; SELECT * FROM t1; } { 1 {} one 2 1 two 3 {} three } do_execsql_test 1.$tn.4 { INSERT INTO t1 VALUES(2, NULL, 'zero') ON CONFLICT (a) DO UPDATE SET b=2; SELECT * FROM t1; } {1 {} one 2 2 two 3 {} three} do_catchsql_test 1.$tn.5 { INSERT INTO t1 VALUES(2, NULL, 'zero') ON CONFLICT (a) DO UPDATE SET c = 'one'; } {1 {UNIQUE constraint failed: t1.c}} do_execsql_test 1.$tn.6 { SELECT * FROM t1; } {1 {} one 2 2 two 3 {} three} do_execsql_test 1.$tn.7 { INSERT INTO t1 VALUES(2, NULL, 'zero') ON CONFLICT (a) DO UPDATE SET (b, c) = (SELECT 'x', 'y'); SELECT * FROM t1; } {1 {} one 2 x y 3 {} three} do_execsql_test 1.$tn.8 { INSERT INTO t1 VALUES(1, NULL, NULL) ON CONFLICT (a) DO UPDATE SET (c, a) = ('four', 4); SELECT * FROM t1 ORDER BY 1; } {2 x y 3 {} three 4 {} four} } #------------------------------------------------------------------------- # Test target analysis. # set rtbl(0) {0 {}} set rtbl(1) {/1 .*failed.*/} set rtbl(2) {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}} foreach {tn sql} { 1 { CREATE TABLE xyz(a INTEGER PRIMARY KEY, b, c, d); CREATE UNIQUE INDEX xyz1 ON xyz(d, c, b COLLATE nocase); } 2 { CREATE TABLE xyz(a INT PRIMARY KEY, b, c, d); CREATE UNIQUE INDEX xyz1 ON xyz(d, c, b COLLATE nocase); } 3 { CREATE TABLE xyz(a INT PRIMARY KEY, b, c, d) WITHOUT ROWID; CREATE UNIQUE INDEX xyz1 ON xyz(d, c, b COLLATE nocase); } } { reset_db execsql $sql do_execsql_test 2.$tn.1 { INSERT INTO xyz VALUES(10, 1, 1, 'one'); } foreach {tn2 oc res} { 1 "ON CONFLICT (b COLLATE nocase, c, d) DO NOTHING" 0 2 "ON CONFLICT (b, c, d) DO NOTHING" 0 3 "ON CONFLICT (b, c COLLATE nocase, d) DO NOTHING" 2 4 "ON CONFLICT (a) DO NOTHING" 1 5 "ON CONFLICT DO NOTHING" 0 6 "ON CONFLICT (b, c, d) WHERE a!=0 DO NOTHING" 0 7 "ON CONFLICT (d, c, c) WHERE a!=0 DO NOTHING" 2 8 "ON CONFLICT (b COLLATE nocase, c COLLATE nocase, d) DO NOTHING" 2 9 "ON CONFLICT (b, c, d) WHERE b==45 DO NOTHING" 0 } { do_catchsql_test 2.$tn.2.$tn2 " INSERT INTO xyz VALUES(11, 1, 1, 'one') $oc " $rtbl($res) } do_execsql_test 2.$tn.3 { SELECT * FROM xyz; } {10 1 1 one} } foreach {tn sql} { 1 { CREATE TABLE abc(a INTEGER PRIMARY KEY, x, y); CREATE UNIQUE INDEX abc1 ON abc(('x' || x) COLLATE nocase); } 2 { CREATE TABLE abc(a INT PRIMARY KEY, x, y); CREATE UNIQUE INDEX abc1 ON abc(('x' || x) COLLATE nocase); } 3 { CREATE TABLE abc(a INT PRIMARY KEY, x, y) WITHOUT ROWID; CREATE UNIQUE INDEX abc1 ON abc(('x' || x) COLLATE nocase); } } { reset_db execsql $sql do_execsql_test 3.$tn.1 { INSERT INTO abc VALUES(1, 'one', 'two'); } foreach {tn2 oc res} { 1 "ON CONFLICT DO NOTHING" 0 2 "ON CONFLICT ('x' || x) DO NOTHING" 0 3 "ON CONFLICT (('x' || x) COLLATE nocase) DO NOTHING" 0 4 "ON CONFLICT (('x' || x) COLLATE binary) DO NOTHING" 2 5 "ON CONFLICT (x || 'x') DO NOTHING" 2 6 "ON CONFLICT ((('x' || x))) DO NOTHING" 0 } { do_catchsql_test 3.$tn.2.$tn2 " INSERT INTO abc VALUES(2, 'one', NULL) $oc; " $rtbl($res) } do_execsql_test 3.$tn.3 { SELECT * FROM abc } {1 one two} } foreach {tn sql} { 1 { CREATE TABLE abc(a INTEGER PRIMARY KEY, x, y); CREATE UNIQUE INDEX abc1 ON abc(x) WHERE y>0; CREATE UNIQUE INDEX abc2 ON abc(y) WHERE x='xyz' COLLATE nocase; } } { reset_db execsql $sql do_execsql_test 4.$tn.1 { INSERT INTO abc VALUES(1, 'one', 1); INSERT INTO abc VALUES(2, 'two', 2); INSERT INTO abc VALUES(3, 'xyz', 3); INSERT INTO abc VALUES(4, 'XYZ', 4); } foreach {tn2 oc res} { 1 "ON CONFLICT DO NOTHING" 0 2 "ON CONFLICT(x) WHERE y>0 DO NOTHING" 0 3 "ON CONFLICT(x) DO NOTHING" 2 4 "ON CONFLICT(x) WHERE y>=0 DO NOTHING" 2 5 "ON CONFLICT(y) WHERE x='xyz' COLLATE nocase DO NOTHING" 1 } { do_catchsql_test 4.$tn.2.$tn2 " INSERT INTO abc VALUES(5, 'one', 10) $oc " $rtbl($res) } do_execsql_test 4.$tn.3 { SELECT * FROM abc } {1 one 1 2 two 2 3 xyz 3 4 XYZ 4} foreach {tn2 oc res} { 1 "ON CONFLICT DO NOTHING" 0 2 "ON CONFLICT(y) WHERE x='xyz' COLLATE nocase DO NOTHING" 0 3 "ON CONFLICT(y) WHERE x='xyz' COLLATE binary DO NOTHING" 2 4 "ON CONFLICT(x) WHERE y>0 DO NOTHING" 1 } { do_catchsql_test 4.$tn.2.$tn2 " INSERT INTO abc VALUES(5, 'xYz', 3) $oc " $rtbl($res) } } do_catchsql_test 5.0 { CREATE TABLE w1(a INT PRIMARY KEY, x, y); CREATE UNIQUE INDEX w1expr ON w1(('x' || x)); INSERT INTO w1 VALUES(2, 'one', NULL) ON CONFLICT (('x' || x) COLLATE nocase) DO NOTHING; } {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}} #------------------------------------------------------------------------- # Test that ON CONFLICT constraint processing occurs before any REPLACE # constraint processing. # foreach {tn sql} { 1 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE, c); } 2 { CREATE TABLE t1(a INT PRIMARY KEY, b UNIQUE, c); } 3 { CREATE TABLE t1(a INT PRIMARY KEY, b UNIQUE, c) WITHOUT ROWID; } } { reset_db execsql $sql do_execsql_test 6.1.$tn { INSERT INTO t1 VALUES(1, 1, 'one'); INSERT INTO t1 VALUES(2, 2, 'two'); INSERT OR REPLACE INTO t1 VALUES(1, 2, 'two') ON CONFLICT(b) DO NOTHING; PRAGMA integrity_check; } {ok} } foreach {tn sql} { 1 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE, c UNIQUE); } } { reset_db execsql $sql do_execsql_test 6.2.$tn.1 { INSERT INTO t1 VALUES(1, 1, 1); INSERT INTO t1 VALUES(2, 2, 2); } do_execsql_test 6.2.$tn.2 { INSERT OR REPLACE INTO t1 VALUES(3, 1, 1) ON CONFLICT(b) DO NOTHING; SELECT * FROM t1; PRAGMA integrity_check; } {1 1 1 2 2 2 ok} do_execsql_test 6.2.$tn.3 { INSERT OR REPLACE INTO t1 VALUES(3, 2, 2) ON CONFLICT(c) DO NOTHING; SELECT * FROM t1; PRAGMA integrity_check; } {1 1 1 2 2 2 ok} do_execsql_test 6.2.$tn.2 { INSERT OR REPLACE INTO t1 VALUES(3, 1, 1) ON CONFLICT(b) DO UPDATE SET b=b||'x'; SELECT * FROM t1; PRAGMA integrity_check; } {1 1x 1 2 2 2 ok} do_execsql_test 6.2.$tn.2 { INSERT OR REPLACE INTO t1 VALUES(3, 2, 2) ON CONFLICT(c) DO UPDATE SET c=c||'x'; SELECT * FROM t1; PRAGMA integrity_check; } {1 1x 1 2 2 2x ok} } #------------------------------------------------------------------------- # Test references to "excluded". And using an alias in an INSERT # statement. # foreach {tn sql} { 1 { CREATE TABLE t1(w, x, y, z, PRIMARY KEY(x, y)); CREATE UNIQUE INDEX zz ON t1(z); } 2 { CREATE TABLE t1(w, x, y, z, PRIMARY KEY(x, y)) WITHOUT ROWID; CREATE UNIQUE INDEX zz ON t1(z); } } { reset_db execsql $sql do_execsql_test 7.$tn.0 { INSERT INTO t1 VALUES('a', 1, 1, 1); INSERT INTO t1 VALUES('b', 2, 2, 2); } do_execsql_test 7.$tn.1 { INSERT INTO t1 VALUES('c', 3, 3, 1) ON CONFLICT(z) DO UPDATE SET w = excluded.w; SELECT * FROM t1; } {c 1 1 1 b 2 2 2} do_execsql_test 7.$tn.2 { INSERT INTO t1 VALUES('c', 2, 2, 3) ON CONFLICT(y, x) DO UPDATE SET w = w||w; SELECT * FROM t1; } {c 1 1 1 bb 2 2 2} do_execsql_test 7.$tn.3 { INSERT INTO t1 VALUES('c', 2, 2, 3) ON CONFLICT(y, x) DO UPDATE SET w = w||t1.w; SELECT * FROM t1; } {c 1 1 1 bbbb 2 2 2} do_execsql_test 7.$tn.4 { INSERT INTO t1 AS tbl VALUES('c', 2, 2, 3) ON CONFLICT(y, x) DO UPDATE SET w = w||tbl.w; SELECT * FROM t1; } {c 1 1 1 bbbbbbbb 2 2 2} } foreach {tn sql} { 1 { CREATE TABLE excluded(w, x INTEGER, 'a b', z, PRIMARY KEY(x, 'a b')); CREATE UNIQUE INDEX zz ON excluded(z); CREATE INDEX zz2 ON excluded(z); } 2 { CREATE TABLE excluded(w, x, 'a b', z, PRIMARY KEY(x, 'a b')) WITHOUT ROWID; CREATE UNIQUE INDEX zz ON excluded(z); CREATE INDEX zz2 ON excluded(z); } } { reset_db execsql $sql do_execsql_test 8.$tn.0 { INSERT INTO excluded VALUES('a', 1, 1, 1); INSERT INTO excluded VALUES('b', 2, 2, 2); } # Note: An error in Postgres: "table reference "excluded" is ambiguous". # do_execsql_test 8.$tn.1 { INSERT INTO excluded VALUES('hello', 1, 1, NULL) ON CONFLICT(x, "a b") DO UPDATE SET w=excluded.w; SELECT * FROM excluded; } {a 1 1 1 b 2 2 2} do_execsql_test 8.$tn.2 { INSERT INTO excluded AS x1 VALUES('hello', 1, 1, NULL) ON CONFLICT(x, [a b]) DO UPDATE SET w=excluded.w; SELECT * FROM excluded; } {hello 1 1 1 b 2 2 2} do_execsql_test 8.$tn.3 { INSERT INTO excluded AS x1 VALUES('hello', 1, 1, NULL) ON CONFLICT(x, [a b]) DO UPDATE SET w=w||w WHERE excluded.w!='hello'; SELECT * FROM excluded; } {hello 1 1 1 b 2 2 2} do_execsql_test 8.$tn.4 { INSERT INTO excluded AS x1 VALUES('hello', 1, 1, NULL) ON CONFLICT(x, [a b]) DO UPDATE SET w=w||w WHERE excluded.x=1; SELECT * FROM excluded; } {hellohello 1 1 1 b 2 2 2} do_catchsql_test 8.$tn.5 { INSERT INTO excluded AS x1 VALUES('hello', 1, 1, NULL) ON CONFLICT(x, [a b]) WHERE y=1 DO UPDATE SET w=w||w WHERE excluded.x=1; } {1 {no such column: y}} } #-------------------------------------------------------------------------- # do_execsql_test 9.0 { CREATE TABLE v(x INTEGER); CREATE TABLE hist(x INTEGER PRIMARY KEY, cnt INTEGER); CREATE TRIGGER vt AFTER INSERT ON v BEGIN INSERT INTO hist VALUES(new.x, 1) ON CONFLICT(x) DO UPDATE SET cnt=cnt+1; END; } do_execsql_test 9.1 { INSERT INTO v VALUES(1), (4), (1), (5), (5), (8), (9), (1); SELECT * FROM hist; } { 1 3 4 1 5 2 8 1 9 1 } finish_test |
Added test/upsertfault.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | # 2018-04-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. # #*********************************************************************** # # Test cases for UPSERT set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix upsertfault do_execsql_test 1.0 { CREATE TABLE t1(a PRIMARY KEY, b, c, d, UNIQUE(b, c)); INSERT INTO t1 VALUES(1, 1, 1, 1); INSERT INTO t1 VALUES(2, 2, 2, 2); } faultsim_save_and_close do_faultsim_test 1 -faults oom* -prep { faultsim_restore_and_reopen db eval { SELECT * FROM sqlite_master } } -body { execsql { INSERT INTO t1 VALUES(3, 2, 2, NULL) ON CONFLICT(b, c) DO UPDATE SET d=d+1; } } -test { faultsim_test_result {0 {}} } finish_test |
Changes to test/where.test.
︙ | ︙ | |||
1363 1364 1365 1366 1367 1368 1369 1370 1371 | SELECT DISTINCT a FROM t181 LEFT JOIN t182 ON a=b ORDER BY c IS NULL, +a; } {1 2} do_execsql_test where-18.6 { INSERT INTO t181 VALUES(2); SELECT DISTINCT a FROM t181 LEFT JOIN t182 ON a=b ORDER BY +a, +c IS NULL; } {1 2} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 | SELECT DISTINCT a FROM t181 LEFT JOIN t182 ON a=b ORDER BY c IS NULL, +a; } {1 2} do_execsql_test where-18.6 { INSERT INTO t181 VALUES(2); SELECT DISTINCT a FROM t181 LEFT JOIN t182 ON a=b ORDER BY +a, +c IS NULL; } {1 2} # Make sure the OR optimization works on a JOIN # do_execsql_test where-19.0 { CREATE TABLE t191(a INT UNIQUE NOT NULL, b INT UNIQUE NOT NULL,c,d); CREATE INDEX t191a ON t1(a); CREATE INDEX t191b ON t1(b); CREATE TABLE t192(x INTEGER PRIMARY KEY,y INT, z INT); EXPLAIN QUERY PLAN SELECT t191.rowid FROM t192, t191 WHERE (a=y OR b=y) AND x=?1; } {/.* sqlite_autoindex_t191_1 .* sqlite_autoindex_t191_2 .*/} # 2018-04-24 ticket [https://www.sqlite.org/src/info/4ba5abf65c5b0f9a] # Index on expressions leads to an incorrect answer for a LEFT JOIN # do_execsql_test where-20.0 { CREATE TABLE t201(x); CREATE TABLE t202(y, z); INSERT INTO t201 VALUES('key'); INSERT INTO t202 VALUES('key', -1); CREATE INDEX t202i ON t202(y, ifnull(z, 0)); SELECT count(*) FROM t201 LEFT JOIN t202 ON (x=y) WHERE ifnull(z, 0) >=0; } {0} do_execsql_test where-21.0 { CREATE TABLE t12(a, b, c); CREATE TABLE t13(x); CREATE INDEX t12ab ON t12(b, a); CREATE INDEX t12ac ON t12(c, a); INSERT INTO t12 VALUES(4, 0, 1); INSERT INTO t12 VALUES(4, 1, 0); INSERT INTO t12 VALUES(5, 0, 1); INSERT INTO t12 VALUES(5, 1, 0); INSERT INTO t13 VALUES(1), (2), (3), (4); } do_execsql_test where-21.1 { SELECT * FROM t12 WHERE a = (SELECT * FROM (SELECT count(*) FROM t13 LIMIT 5) ORDER BY 1 LIMIT 10) AND (b=1 OR c=1); } { 4 1 0 4 0 1 } finish_test |
Changes to test/where8.test.
︙ | ︙ | |||
11 12 13 14 15 16 17 18 19 20 21 22 23 24 | # This file implements regression tests for SQLite library. The focus # is testing of where.c. More specifically, the focus is the optimization # of WHERE clauses that feature the OR operator. # set testdir [file dirname $argv0] source $testdir/tester.tcl # Test organization: # # where8-1.*: Tests to demonstrate simple cases work with a single table # in the FROM clause. # # where8-2.*: Tests surrounding virtual tables and the OR optimization. | > > > > > | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | # This file implements regression tests for SQLite library. The focus # is testing of where.c. More specifically, the focus is the optimization # of WHERE clauses that feature the OR operator. # set testdir [file dirname $argv0] source $testdir/tester.tcl if {[permutation]=="sorterref"} { finish_test return } # Test organization: # # where8-1.*: Tests to demonstrate simple cases work with a single table # in the FROM clause. # # where8-2.*: Tests surrounding virtual tables and the OR optimization. |
︙ | ︙ |
Changes to test/without_rowid1.test.
︙ | ︙ | |||
337 338 339 340 341 342 343 344 345 346 | do_execsql_test 8.1 { CREATE TABLE t1(x INTEGER PRIMARY KEY UNIQUE, b) WITHOUT ROWID; CREATE INDEX t1x ON t1(x); INSERT INTO t1(x,b) VALUES('funny','buffalo'); SELECT type, name, '|' FROM sqlite_master; } {table t1 | index t1x |} finish_test | > > > > > > > > > > > > > | 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 | do_execsql_test 8.1 { CREATE TABLE t1(x INTEGER PRIMARY KEY UNIQUE, b) WITHOUT ROWID; CREATE INDEX t1x ON t1(x); INSERT INTO t1(x,b) VALUES('funny','buffalo'); SELECT type, name, '|' FROM sqlite_master; } {table t1 | index t1x |} # 2018-04-05: OSSFuzz found that the following was accessing an # unintialized memory cell. Which was not actually causing a # malfunction, but does cause an assert() to fail. # do_execsql_test 9.0 { CREATE TABLE t2(b, c, PRIMARY KEY(b,c)) WITHOUT ROWID; CREATE UNIQUE INDEX t2b ON t2(b); UPDATE t2 SET b=1 WHERE b=''; } do_execsql_test 10.1 { DELETE FROM t2 WHERE b=1 } finish_test |
Changes to test/wordcount.c.
︙ | ︙ | |||
24 25 26 27 28 29 30 31 32 33 34 35 36 37 | ** (1) INSERT OR IGNORE INTO wordcount VALUES($new,0) ** (2) UPDATE wordcount SET cnt=cnt+1 WHERE word=$new ** ** Replace mode means: ** (1) REPLACE INTO wordcount ** VALUES($new,ifnull((SELECT cnt FROM wordcount WHERE word=$new),0)+1); ** ** Select mode means: ** (1) SELECT 1 FROM wordcount WHERE word=$new ** (2) INSERT INTO wordcount VALUES($new,1) -- if (1) returns nothing ** (3) UPDATE wordcount SET cnt=cnt+1 WHERE word=$new --if (1) return TRUE ** ** Delete mode means: ** (1) DELETE FROM wordcount WHERE word=$new | > > > > | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | ** (1) INSERT OR IGNORE INTO wordcount VALUES($new,0) ** (2) UPDATE wordcount SET cnt=cnt+1 WHERE word=$new ** ** Replace mode means: ** (1) REPLACE INTO wordcount ** VALUES($new,ifnull((SELECT cnt FROM wordcount WHERE word=$new),0)+1); ** ** Upsert mode means: ** (1) INSERT INTO wordcount VALUES($new,1) ** ON CONFLICT(word) DO UPDATE SET cnt=cnt+1 ** ** Select mode means: ** (1) SELECT 1 FROM wordcount WHERE word=$new ** (2) INSERT INTO wordcount VALUES($new,1) -- if (1) returns nothing ** (3) UPDATE wordcount SET cnt=cnt+1 WHERE word=$new --if (1) return TRUE ** ** Delete mode means: ** (1) DELETE FROM wordcount WHERE word=$new |
︙ | ︙ | |||
86 87 88 89 90 91 92 93 94 95 96 97 98 99 | " --select Use SELECT mode\n" " --stats Show sqlite3_status() results at the end.\n" " --summary Show summary information on the collected data.\n" " --tag NAME Tag all output using NAME. Use only stdout.\n" " --timer Time the operation of this program\n" " --trace Enable sqlite3_trace() output.\n" " --update Use UPDATE mode\n" " --without-rowid Use a WITHOUT ROWID table to store the words.\n" ; /* Output tag */ char *zTag = "--"; /* Return the current wall-clock time */ | > | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | " --select Use SELECT mode\n" " --stats Show sqlite3_status() results at the end.\n" " --summary Show summary information on the collected data.\n" " --tag NAME Tag all output using NAME. Use only stdout.\n" " --timer Time the operation of this program\n" " --trace Enable sqlite3_trace() output.\n" " --update Use UPDATE mode\n" " --upsert Use UPSERT mode\n" " --without-rowid Use a WITHOUT ROWID table to store the words.\n" ; /* Output tag */ char *zTag = "--"; /* Return the current wall-clock time */ |
︙ | ︙ | |||
204 205 206 207 208 209 210 | sqlite3_result_text(context, zResult, -1, SQLITE_TRANSIENT); } } /* Define operating modes */ #define MODE_INSERT 0 #define MODE_REPLACE 1 | > | | | | | > | 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 | sqlite3_result_text(context, zResult, -1, SQLITE_TRANSIENT); } } /* Define operating modes */ #define MODE_INSERT 0 #define MODE_REPLACE 1 #define MODE_UPSERT 2 #define MODE_SELECT 3 #define MODE_UPDATE 4 #define MODE_DELETE 5 #define MODE_QUERY 6 #define MODE_COUNT 7 #define MODE_ALL (-1) /* Mode names */ static const char *azMode[] = { "--insert", "--replace", "--upsert", "--select", "--update", "--delete", "--query" }; /* |
︙ | ︙ | |||
288 289 290 291 292 293 294 295 296 297 298 299 300 301 | const char *z = argv[i]; if( z[0]=='-' ){ do{ z++; }while( z[0]=='-' ); if( strcmp(z,"without-rowid")==0 ){ useWithoutRowid = 1; }else if( strcmp(z,"replace")==0 ){ iMode = MODE_REPLACE; }else if( strcmp(z,"select")==0 ){ iMode = MODE_SELECT; }else if( strcmp(z,"insert")==0 ){ iMode = MODE_INSERT; }else if( strcmp(z,"update")==0 ){ iMode = MODE_UPDATE; }else if( strcmp(z,"delete")==0 ){ | > > | 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | const char *z = argv[i]; if( z[0]=='-' ){ do{ z++; }while( z[0]=='-' ); if( strcmp(z,"without-rowid")==0 ){ useWithoutRowid = 1; }else if( strcmp(z,"replace")==0 ){ iMode = MODE_REPLACE; }else if( strcmp(z,"upsert")==0 ){ iMode = MODE_UPSERT; }else if( strcmp(z,"select")==0 ){ iMode = MODE_SELECT; }else if( strcmp(z,"insert")==0 ){ iMode = MODE_INSERT; }else if( strcmp(z,"update")==0 ){ iMode = MODE_UPDATE; }else if( strcmp(z,"delete")==0 ){ |
︙ | ︙ | |||
463 464 465 466 467 468 469 470 471 472 473 474 475 476 | rc = sqlite3_prepare_v2(db, "REPLACE INTO wordcount(word,cnt)" "VALUES(?1,coalesce((SELECT cnt FROM wordcount WHERE word=?1),0)+1)", -1, &pInsert, 0); if( rc ) fatal_error("Could not prepare the REPLACE statement: %s\n", sqlite3_errmsg(db)); } if( iMode2==MODE_DELETE ){ rc = sqlite3_prepare_v2(db, "DELETE FROM wordcount WHERE word=?1", -1, &pDelete, 0); if( rc ) fatal_error("Could not prepare the DELETE statement: %s\n", sqlite3_errmsg(db)); } | > > > > > > > > | 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 | rc = sqlite3_prepare_v2(db, "REPLACE INTO wordcount(word,cnt)" "VALUES(?1,coalesce((SELECT cnt FROM wordcount WHERE word=?1),0)+1)", -1, &pInsert, 0); if( rc ) fatal_error("Could not prepare the REPLACE statement: %s\n", sqlite3_errmsg(db)); } if( iMode2==MODE_UPSERT ){ rc = sqlite3_prepare_v2(db, "INSERT INTO wordcount(word,cnt) VALUES(?1,1) " "ON CONFLICT(word) DO UPDATE SET cnt=cnt+1", -1, &pInsert, 0); if( rc ) fatal_error("Could not prepare the UPSERT statement: %s\n", sqlite3_errmsg(db)); } if( iMode2==MODE_DELETE ){ rc = sqlite3_prepare_v2(db, "DELETE FROM wordcount WHERE word=?1", -1, &pDelete, 0); if( rc ) fatal_error("Could not prepare the DELETE statement: %s\n", sqlite3_errmsg(db)); } |
︙ | ︙ |
Changes to test/zipfile.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | # 2017 December 9 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix zipfile ifcapable !vtab { finish_test; return } if {[catch {load_static_extension db zipfile} error]} { puts "Skipping zipfile tests, hit load error: $error" finish_test; return } proc readfile {f} { set fd [open $f] fconfigure $fd -translation binary -encoding binary set data [read $fd] close $fd set data } | > > > > > > > > | > | | > > > > > > > > > > > > > > > > > > | | > > | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | # 2017 December 9 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # package require Tcl 8.6 set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix zipfile ifcapable !vtab { finish_test; return } if {[catch {load_static_extension db zipfile} error]} { puts "Skipping zipfile tests, hit load error: $error" finish_test; return } if {[catch {load_static_extension db fileio} error]} { puts "Skipping zipfile tests, hit load error: $error" finish_test; return } proc readfile {f} { set fd [open $f] fconfigure $fd -translation binary -encoding binary set data [read $fd] close $fd set data } unset -nocomplain ::UNZIP if {[catch {exec unzip} msg]==0 && \ [regexp -line {^UnZip \d+\.\d+ .*? Info-ZIP\.} $msg]} { set ::UNZIP unzip proc fix_stat_mode {name mode} { if {$::tcl_platform(platform)=="windows"} { # # NOTE: Set or unset the write bits of the file permissions # based on the read-only attribute because the Win32 # version of UnZip does this. # set writebits 0x12; # 0o22 set result $mode if {[file attributes $name -readonly]} { set result [expr {$result | $writebits}] } else { set result [expr {$result & ~$writebits}] } return $result } else { return $mode } } proc do_unzip {file} { forcedelete test_unzip file mkdir test_unzip exec $::UNZIP -d test_unzip $file db func modefix fix_stat_mode set res [db eval { SELECT replace(name,'test_unzip/',''),modefix(name,mode),mtime,data FROM fsdir('test_unzip') WHERE name!='test_unzip' ORDER BY name }] set res } } |
︙ | ︙ | |||
104 105 106 107 108 109 110 | # ( SELECT zipfile(name,mode,mtime,data,method) FROM zipfile($file) ) # ); # # Then tests that unpacking the new archive using [unzip] produces # the same results as in (1). # proc do_unzip_test {tn file} { | < | 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | # ( SELECT zipfile(name,mode,mtime,data,method) FROM zipfile($file) ) # ); # # Then tests that unpacking the new archive using [unzip] produces # the same results as in (1). # proc do_unzip_test {tn file} { db func sss strip_slash db eval { SELECT writefile('test_unzip.zip', ( SELECT zipfile(name,mode,mtime,data,method) FROM zipfile($file) ) ); } |
︙ | ︙ | |||
126 127 128 129 130 131 132 | uplevel [list do_test $tn.1 [list set {} $r2] $r1] uplevel [list do_test $tn.2 [list set {} $r3] $r1] } proc strip_slash {in} { regsub {/$} $in {} } proc do_zip_tests {tn file} { uplevel do_zipfile_blob_test $tn.1 $file | > | > | 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | uplevel [list do_test $tn.1 [list set {} $r2] $r1] uplevel [list do_test $tn.2 [list set {} $r3] $r1] } proc strip_slash {in} { regsub {/$} $in {} } proc do_zip_tests {tn file} { uplevel do_zipfile_blob_test $tn.1 $file if {[info exists ::UNZIP]} { uplevel do_unzip_test $tn.2 $file } } forcedelete test.zip do_execsql_test 1.0 { CREATE VIRTUAL TABLE temp.zz USING zipfile('test.zip'); PRAGMA table_info(zz); } { |
︙ | ︙ | |||
242 243 244 245 246 247 248 249 250 | UPDATE zz SET mtime=4 WHERE name='i.txt'; SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); } { f.txt 33188 1000000000 abcde 0 h.txt 33188 1000000004 aaaaaaaaaabbbbbbbbbb 8 i.txt 33188 4 zxcvb 0 } do_execsql_test 1.6.3 { | > > > > > > > > | | | | | | | | | | | | | | | | | | | | | | | 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 | UPDATE zz SET mtime=4 WHERE name='i.txt'; SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); } { f.txt 33188 1000000000 abcde 0 h.txt 33188 1000000004 aaaaaaaaaabbbbbbbbbb 8 i.txt 33188 4 zxcvb 0 } if {$::tcl_platform(platform)=="unix"} { set modes -rw-r--r-x set perms 33189 } else { set modes -rw-r--r--; # no execute bits on Win32 set perms 33188 } do_execsql_test 1.6.3 { UPDATE zz SET mode=$modes WHERE name='h.txt'; SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); } [string map [list %perms% $perms] { f.txt 33188 1000000000 abcde 0 h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8 i.txt 33188 4 zxcvb 0 }] do_zip_tests 1.6.3a test.zip do_execsql_test 1.6.4 { UPDATE zz SET name = 'blue.txt' WHERE name='f.txt'; SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); } [string map [list %perms% $perms] { blue.txt 33188 1000000000 abcde 0 h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8 i.txt 33188 4 zxcvb 0 }] do_zip_tests 1.6.4a test.zip do_execsql_test 1.6.5 { UPDATE zz SET data = 'edcba' WHERE name='blue.txt'; SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); } [string map [list %perms% $perms] { blue.txt 33188 1000000000 edcba 0 h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8 i.txt 33188 4 zxcvb 0 }] do_execsql_test 1.6.6 { UPDATE zz SET mode=NULL, data = NULL WHERE name='blue.txt'; SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); } [string map [list %perms% $perms] { blue.txt/ 16877 1000000000 {} 0 h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8 i.txt 33188 4 zxcvb 0 }] do_catchsql_test 1.6.7 { UPDATE zz SET data=NULL WHERE name='i.txt' } {1 {zipfile: mode does not match data}} do_execsql_test 1.6.8 { SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); } [string map [list %perms% $perms] { blue.txt/ 16877 1000000000 {} 0 h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8 i.txt 33188 4 zxcvb 0 }] do_execsql_test 1.6.9 { UPDATE zz SET data = '' WHERE name='i.txt'; SELECT name,mode,mtime,data,method from zipfile('test.zip'); } [string map [list %perms% $perms] { blue.txt/ 16877 1000000000 {} 0 h.txt %perms% 1000000004 aaaaaaaaaabbbbbbbbbb 8 i.txt 33188 4 {} 0 }] do_execsql_test 1.6.10 { SELECT a.name, a.data FROM zz AS a, zz AS b WHERE a.name=+b.name AND +a.mode=b.mode } { blue.txt/ {} h.txt aaaaaaaaaabbbbbbbbbb i.txt {} } do_execsql_test 1.6.11 { SELECT name, data FROM zz WHERE name LIKE '%txt' } { h.txt aaaaaaaaaabbbbbbbbbb i.txt {} } do_execsql_test 1.7 { |
︙ | ︙ | |||
356 357 358 359 360 361 362 | } { dirname3/ 16877 {} dirname2/ 16877 {} dirname2/file1.txt 33188 abcdefghijklmnop } do_zip_tests 2.4a test.zip | | | > > > > > | > | 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 | } { dirname3/ 16877 {} dirname2/ 16877 {} dirname2/file1.txt 33188 abcdefghijklmnop } do_zip_tests 2.4a test.zip # Check that the [unzip] utility can unpack our archive. # if {[info exists ::UNZIP]} { do_test 2.5.1 { forcedelete dirname forcedelete dirname2 if {$::tcl_platform(platform)=="unix"} { set null /dev/null } else { set null NUL } set rc [catch { exec $::UNZIP test.zip > $null } msg] list $rc $msg } {0 {}} do_test 2.5.2 { file isdir dirname3 } 1 do_test 2.5.3 { file isdir dirname2 } 1 do_test 2.5.4 { file isdir dirname2/file1.txt } 0 do_test 2.5.5 { set fd [open dirname2/file1.txt] set data [read $fd] close $fd set data } {abcdefghijklmnop} } #------------------------------------------------------------------------- reset_db forcedelete test.zip load_static_extension db zipfile load_static_extension db fileio do_execsql_test 3.0 { CREATE VIRTUAL TABLE temp.x1 USING zipfile('test.zip'); INSERT INTO x1(name, data) VALUES('dir1/', NULL); INSERT INTO x1(name, data) VALUES('file1', '1234'); INSERT INTO x1(name, data) VALUES('dir1/file2', '5678'); } |
︙ | ︙ | |||
449 450 451 452 453 454 455 | WITH c(name,data) AS ( SELECT 'a.txt', 'abc' UNION ALL SELECT NULL, 'def' ) SELECT zipfile(name,data) FROM c } {1 {first argument to zipfile() must be non-NULL}} | | | | 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 | WITH c(name,data) AS ( SELECT 'a.txt', 'abc' UNION ALL SELECT NULL, 'def' ) SELECT zipfile(name,data) FROM c } {1 {first argument to zipfile() must be non-NULL}} do_catchsql_test 4.8 { WITH c(name,data,method) AS ( SELECT 'a.txt', 'abc', 0 UNION SELECT 'b.txt', 'def', 8 UNION SELECT 'c.txt', 'ghi', 16 ) SELECT zipfile(name,NULL,NULL,data,method) FROM c } {1 {illegal method value: 16}} do_catchsql_test 4.9 { WITH c(name,data) AS ( SELECT 'a.txt', 'abc' UNION SELECT 'b.txt', 'def' UNION SELECT 'c.txt/', 'ghi' ) SELECT zipfile(name,NULL,NULL,data) FROM c } {1 {non-directory name must not end with /}} |
︙ | ︙ | |||
481 482 483 484 485 486 487 | SELECT name,mtime,data FROM zipfile( ( SELECT rt( zipfile(name,NULL,mtime,data,NULL) ) FROM c ) ) } { a.txt 946684800 abc } | | < | | 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 | SELECT name,mtime,data FROM zipfile( ( SELECT rt( zipfile(name,NULL,mtime,data,NULL) ) FROM c ) ) } { a.txt 946684800 abc } if {[info exists ::UNZIP]} { ifcapable datetime { forcedelete test1.zip test2.zip do_test 6.0 { execsql { WITH c(name,mtime,data) AS ( SELECT 'a.txt', 946684800, 'abc' UNION ALL SELECT 'b.txt', 1000000000, 'abc' UNION ALL SELECT 'c.txt', 1111111000, 'abc' ) SELECT writefile('test1.zip', rt( zipfile(name, NULL, mtime, data) ) ), writefile('test2.zip', ( zipfile(name, NULL, mtime, data) ) ) FROM c; } forcedelete test_unzip file mkdir test_unzip exec $::UNZIP -d test_unzip test1.zip db eval { SELECT name, strftime('%s', mtime, 'unixepoch', 'localtime') FROM fsdir('test_unzip') WHERE name!='test_unzip' ORDER BY name } } [list {*}{ |
︙ | ︙ | |||
530 531 532 533 534 535 536 | b.txt 1000000000 abc c.txt 1111111000 abc } do_test 6.2 { forcedelete test_unzip file mkdir test_unzip | | | 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 | b.txt 1000000000 abc c.txt 1111111000 abc } do_test 6.2 { forcedelete test_unzip file mkdir test_unzip exec $::UNZIP -d test_unzip test2.zip db eval { SELECT name, mtime FROM fsdir('test_unzip') WHERE name!='test_unzip' ORDER BY name } } [list {*}{ |
︙ | ︙ | |||
600 601 602 603 604 605 606 607 608 609 610 611 612 613 | db eval { SELECT name, data FROM zz } { db eval { DELETE FROM zz WHERE name=$name } } execsql { SELECT name, data FROM zz } } {} execsql COMMIT do_execsql_test 8.1.1 { CREATE VIRTUAL TABLE nogood USING zipfile('test_unzip'); } do_catchsql_test 8.1.2 { INSERT INTO nogood(name, data) VALUES('abc', 'def'); } {1 {zipfile: failed to open file test_unzip for writing}} | > > | 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 | db eval { SELECT name, data FROM zz } { db eval { DELETE FROM zz WHERE name=$name } } execsql { SELECT name, data FROM zz } } {} execsql COMMIT catch { forcedelete test_unzip } catch { file mkdir test_unzip } do_execsql_test 8.1.1 { CREATE VIRTUAL TABLE nogood USING zipfile('test_unzip'); } do_catchsql_test 8.1.2 { INSERT INTO nogood(name, data) VALUES('abc', 'def'); } {1 {zipfile: failed to open file test_unzip for writing}} |
︙ | ︙ | |||
648 649 650 651 652 653 654 655 656 657 658 659 660 661 | #------------------------------------------------------------------------- # INSERT OR REPLACE and INSERT OR IGNORE # catch {db close} forcedelete test.zip test.db sqlite3 db :memory: load_static_extension db zipfile do_execsql_test 10.0 { CREATE VIRTUAL TABLE z USING zipfile('test.zip'); } {} do_catchsql_test 10.1 { INSERT INTO z(name,data) VALUES('a0','one'),('a0','two'); } {1 {duplicate name: "a0"}} do_execsql_test 10.2 { | > > | 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 | #------------------------------------------------------------------------- # INSERT OR REPLACE and INSERT OR IGNORE # catch {db close} forcedelete test.zip test.db sqlite3 db :memory: load_static_extension db zipfile load_static_extension db fileio do_execsql_test 10.0 { CREATE VIRTUAL TABLE z USING zipfile('test.zip'); } {} do_catchsql_test 10.1 { INSERT INTO z(name,data) VALUES('a0','one'),('a0','two'); } {1 {duplicate name: "a0"}} do_execsql_test 10.2 { |
︙ | ︙ | |||
670 671 672 673 674 675 676 677 678 | do_execsql_test 10.5 { INSERT OR IGNORE INTO z(name,data) VALUES('a0','five'),('a0','six'); } {} do_execsql_test 10.6 { SELECT name, data FROM z; } {a0 four} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 | do_execsql_test 10.5 { INSERT OR IGNORE INTO z(name,data) VALUES('a0','five'),('a0','six'); } {} do_execsql_test 10.6 { SELECT name, data FROM z; } {a0 four} do_execsql_test 11.1 { DELETE FROM z; } {} do_execsql_test 11.2 { SELECT name, data FROM z; } {} do_execsql_test 11.3 { INSERT INTO z (name,data) VALUES ('b0','one'); SELECT name, data FROM z; } {b0 one} do_execsql_test 11.4 { UPDATE z SET name = 'b1' WHERE name = 'b0'; SELECT name, data FROM z; } {b1 one} do_execsql_test 11.5 { INSERT INTO z (name,data) VALUES ('b0','one'); SELECT name, data FROM z ORDER BY name; } {b0 one b1 one} do_catchsql_test 11.6 { UPDATE z SET name = 'b1' WHERE name = 'b0'; } {1 {duplicate name: "b1"}} do_execsql_test 11.7 { UPDATE z SET data = 'two' WHERE name = 'b0'; SELECT name, data FROM z ORDER BY name; } {b0 two b1 one} do_catchsql_test 11.8 { UPDATE z SET name = 'b1'; } {1 {duplicate name: "b1"}} do_catchsql_test 11.9 { UPDATE z SET name = 'b2'; } {1 {duplicate name: "b2"}} do_execsql_test 11.10 { UPDATE z SET name = name; SELECT name, data FROM z ORDER BY name; } {b0 two b2 one} do_execsql_test 11.11 { UPDATE z SET name = name || 'suffix'; SELECT name, data FROM z ORDER BY name; } {b0suffix two b2suffix one} finish_test |
Changes to test/zipfile2.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | # 2018 January 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. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix zipfile2 ifcapable !vtab { finish_test; return | > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # 2018 January 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. # #*********************************************************************** # package require Tcl 8.6 set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix zipfile2 ifcapable !vtab { finish_test; return |
︙ | ︙ | |||
50 51 52 53 54 55 56 | CREATE VIRTUAL TABLE fff USING zipfile('test''zip'); } do_test 2.0 { forcedelete testdir file mkdir testdir execsql { CREATE VIRTUAL TABLE hhh USING zipfile('testdir') } | > | > > | | 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | CREATE VIRTUAL TABLE fff USING zipfile('test''zip'); } do_test 2.0 { forcedelete testdir file mkdir testdir execsql { CREATE VIRTUAL TABLE hhh USING zipfile('testdir') } lindex [catchsql { SELECT * FROM hhh; INSERT INTO hhh(name, data) VALUES('1.txt', 'file data'); }] 0 } 1 set archive { 504B0304140000080000D4A52BEC09F3B6E0110000001100000005000900612E 747874555405000140420F00636F6E74656E7473206F6620612E747874504B03 04140000080000D4A52BECD98916A7110000001100000005000900622E747874 555405000140420F00636F6E74656E7473206F6620622E747874504B01021E03 |
︙ | ︙ | |||
199 200 201 202 203 204 205 | set hex [binary encode hex $blob] set hex [string map {6e6f7461646972 6e6f746164692f} $hex] set blob2 [binary decode hex $hex] execsql { SELECT name, data IS NULL FROM zipfile($blob2) } } {notadi/ 1} | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 | set hex [binary encode hex $blob] set hex [string map {6e6f7461646972 6e6f746164692f} $hex] set blob2 [binary decode hex $hex] execsql { SELECT name, data IS NULL FROM zipfile($blob2) } } {notadi/ 1} #------------------------------------------------------------------------- # Test that duplicate entries may not be created using UPDATE # statements. # forcedelete test.zip do_execsql_test 6.0 { CREATE VIRTUAL TABLE temp.zip USING zipfile('test.zip'); INSERT INTO temp.zip (name,data) VALUES ('test1','test'); INSERT INTO temp.zip (name,data) VALUES ('test2','test'); } do_catchsql_test 6.1 { UPDATE temp.zip SET name='test1' WHERE name='test2' } {1 {duplicate name: "test1"}} forcedelete test.zip do_catchsql_test 6.2 { DROP TABLE zip; CREATE VIRTUAL TABLE temp.zip USING zipfile('test.zip'); INSERT INTO temp.zip (name,data) VALUES ('test','test'); UPDATE temp.zip set name=name||'new' where name='test'; INSERT INTO temp.zip (name,data) VALUES ('test','test'); UPDATE temp.zip set name=name||'new' where name='test'; } {1 {duplicate name: "testnew"}} forcedelete test.zip do_execsql_test 6.3 { INSERT INTO temp.zip (name,data) VALUES ('test1','test'); INSERT INTO temp.zip (name,data) VALUES ('test2','test'); UPDATE OR REPLACE zip SET name='test2' WHERE name='test1'; SELECT name FROM zip; } {test2} finish_test |
Changes to tool/lemon.c.
︙ | ︙ | |||
266 267 268 269 270 271 272 273 274 275 276 277 278 279 | int destLineno; /* Line number for start of destructor. Set to ** -1 for duplicate destructors. */ char *datatype; /* The data type of information held by this ** object. Only used if type==NONTERMINAL */ int dtnum; /* The data type number. In the parser, the value ** stack is a union. The .yy%d element of this ** union is the correct data type for this object */ /* The following fields are used by MULTITERMINALs only */ int nsubsym; /* Number of constituent symbols in the MULTI */ struct symbol **subsym; /* Array of constituent symbols */ }; /* Each production rule in the grammar is stored in the following ** structure. */ | > > | 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 | int destLineno; /* Line number for start of destructor. Set to ** -1 for duplicate destructors. */ char *datatype; /* The data type of information held by this ** object. Only used if type==NONTERMINAL */ int dtnum; /* The data type number. In the parser, the value ** stack is a union. The .yy%d element of this ** union is the correct data type for this object */ int bContent; /* True if this symbol ever carries content - if ** it is ever more than just syntax */ /* The following fields are used by MULTITERMINALs only */ int nsubsym; /* Number of constituent symbols in the MULTI */ struct symbol **subsym; /* Array of constituent symbols */ }; /* Each production rule in the grammar is stored in the following ** structure. */ |
︙ | ︙ | |||
392 393 394 395 396 397 398 399 400 401 402 403 404 405 | int maxAction; /* Maximum action value of any kind */ struct symbol **symbols; /* Sorted array of pointers to symbols */ int errorcnt; /* Number of errors */ struct symbol *errsym; /* The error symbol */ struct symbol *wildcard; /* Token that matches anything */ char *name; /* Name of the generated parser */ char *arg; /* Declaration of the 3th argument to parser */ char *tokentype; /* Type of terminal symbols in the parser stack */ char *vartype; /* The default type of non-terminal symbols */ char *start; /* Name of the start symbol for the grammar */ char *stacksize; /* Size of the parser stack */ char *include; /* Code to put at the start of the C file */ char *error; /* Code to execute when an error is seen */ char *overflow; /* Code to execute on a stack overflow */ | > | 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 | int maxAction; /* Maximum action value of any kind */ struct symbol **symbols; /* Sorted array of pointers to symbols */ int errorcnt; /* Number of errors */ struct symbol *errsym; /* The error symbol */ struct symbol *wildcard; /* Token that matches anything */ char *name; /* Name of the generated parser */ char *arg; /* Declaration of the 3th argument to parser */ char *ctx; /* Declaration of 2nd argument to constructor */ char *tokentype; /* Type of terminal symbols in the parser stack */ char *vartype; /* The default type of non-terminal symbols */ char *start; /* Name of the start symbol for the grammar */ char *stacksize; /* Size of the parser stack */ char *include; /* Code to put at the start of the C file */ char *error; /* Code to execute when an error is seen */ char *overflow; /* Code to execute on a stack overflow */ |
︙ | ︙ | |||
1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 | fprintf(stderr,"out of memory\n"); exit(1); } lemon_strcpy(*paz, z); for(z=*paz; *z && *z!='='; z++){} *z = 0; } static char *user_templatename = NULL; static void handle_T_option(char *z){ user_templatename = (char *) malloc( lemonStrlen(z)+1 ); if( user_templatename==0 ){ memory_error(); } | > > > > > > > > > > > > | 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 | fprintf(stderr,"out of memory\n"); exit(1); } lemon_strcpy(*paz, z); for(z=*paz; *z && *z!='='; z++){} *z = 0; } /* Rember the name of the output directory */ static char *outputDir = NULL; static void handle_d_option(char *z){ outputDir = (char *) malloc( lemonStrlen(z)+1 ); if( outputDir==0 ){ fprintf(stderr,"out of memory\n"); exit(1); } lemon_strcpy(outputDir, z); } static char *user_templatename = NULL; static void handle_T_option(char *z){ user_templatename = (char *) malloc( lemonStrlen(z)+1 ); if( user_templatename==0 ){ memory_error(); } |
︙ | ︙ | |||
1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 | static int basisflag = 0; static int compress = 0; static int quiet = 0; static int statistics = 0; static int mhflag = 0; static int nolinenosflag = 0; static int noResort = 0; static struct s_options options[] = { {OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."}, {OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."}, {OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."}, {OPT_FSTR, "f", 0, "Ignored. (Placeholder for -f compiler options.)"}, {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."}, {OPT_FSTR, "I", 0, "Ignored. (Placeholder for '-I' compiler options.)"}, {OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file."}, {OPT_FLAG, "l", (char*)&nolinenosflag, "Do not print #line statements."}, {OPT_FSTR, "O", 0, "Ignored. (Placeholder for '-O' compiler options.)"}, | > > | 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 | static int basisflag = 0; static int compress = 0; static int quiet = 0; static int statistics = 0; static int mhflag = 0; static int nolinenosflag = 0; static int noResort = 0; static struct s_options options[] = { {OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."}, {OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."}, {OPT_FSTR, "d", (char*)&handle_d_option, "Output directory. Default '.'"}, {OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."}, {OPT_FSTR, "f", 0, "Ignored. (Placeholder for -f compiler options.)"}, {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."}, {OPT_FSTR, "I", 0, "Ignored. (Placeholder for '-I' compiler options.)"}, {OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file."}, {OPT_FLAG, "l", (char*)&nolinenosflag, "Do not print #line statements."}, {OPT_FSTR, "O", 0, "Ignored. (Placeholder for '-O' compiler options.)"}, |
︙ | ︙ | |||
1659 1660 1661 1662 1663 1664 1665 | Symbol_init(); State_init(); lem.argv0 = argv[0]; lem.filename = OptArg(0); lem.basisflag = basisflag; lem.nolinenosflag = nolinenosflag; Symbol_new("$"); | < < > | 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 | Symbol_init(); State_init(); lem.argv0 = argv[0]; lem.filename = OptArg(0); lem.basisflag = basisflag; lem.nolinenosflag = nolinenosflag; Symbol_new("$"); /* Parse the input file */ Parse(&lem); if( lem.errorcnt ) exit(lem.errorcnt); if( lem.nrule==0 ){ fprintf(stderr,"Empty grammar.\n"); exit(1); } lem.errsym = Symbol_find("error"); /* Count and index the symbols of the grammar */ Symbol_new("{default}"); lem.nsymbol = Symbol_count(); lem.symbols = Symbol_arrayof(); for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i; qsort(lem.symbols,lem.nsymbol,sizeof(struct symbol*), Symbolcmpp); |
︙ | ︙ | |||
2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 | int i; rp->ruleline = psp->tokenlineno; rp->rhs = (struct symbol**)&rp[1]; rp->rhsalias = (const char**)&(rp->rhs[psp->nrhs]); for(i=0; i<psp->nrhs; i++){ rp->rhs[i] = psp->rhs[i]; rp->rhsalias[i] = psp->alias[i]; } rp->lhs = psp->lhs; rp->lhsalias = psp->lhsalias; rp->nrhs = psp->nrhs; rp->code = 0; rp->noCode = 1; rp->precsym = 0; | > | 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 | int i; rp->ruleline = psp->tokenlineno; rp->rhs = (struct symbol**)&rp[1]; rp->rhsalias = (const char**)&(rp->rhs[psp->nrhs]); for(i=0; i<psp->nrhs; i++){ rp->rhs[i] = psp->rhs[i]; rp->rhsalias[i] = psp->alias[i]; if( rp->rhsalias[i]!=0 ){ rp->rhs[i]->bContent = 1; } } rp->lhs = psp->lhs; rp->lhsalias = psp->lhsalias; rp->nrhs = psp->nrhs; rp->code = 0; rp->noCode = 1; rp->precsym = 0; |
︙ | ︙ | |||
2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 | psp->declargslot = &(psp->gp->accept); }else if( strcmp(x,"parse_failure")==0 ){ psp->declargslot = &(psp->gp->failure); }else if( strcmp(x,"stack_overflow")==0 ){ psp->declargslot = &(psp->gp->overflow); }else if( strcmp(x,"extra_argument")==0 ){ psp->declargslot = &(psp->gp->arg); psp->insertLineMacro = 0; }else if( strcmp(x,"token_type")==0 ){ psp->declargslot = &(psp->gp->tokentype); psp->insertLineMacro = 0; }else if( strcmp(x,"default_type")==0 ){ psp->declargslot = &(psp->gp->vartype); psp->insertLineMacro = 0; | > > > | 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 | psp->declargslot = &(psp->gp->accept); }else if( strcmp(x,"parse_failure")==0 ){ psp->declargslot = &(psp->gp->failure); }else if( strcmp(x,"stack_overflow")==0 ){ psp->declargslot = &(psp->gp->overflow); }else if( strcmp(x,"extra_argument")==0 ){ psp->declargslot = &(psp->gp->arg); psp->insertLineMacro = 0; }else if( strcmp(x,"extra_context")==0 ){ psp->declargslot = &(psp->gp->ctx); psp->insertLineMacro = 0; }else if( strcmp(x,"token_type")==0 ){ psp->declargslot = &(psp->gp->tokentype); psp->insertLineMacro = 0; }else if( strcmp(x,"default_type")==0 ){ psp->declargslot = &(psp->gp->vartype); psp->insertLineMacro = 0; |
︙ | ︙ | |||
3022 3023 3024 3025 3026 3027 3028 3029 | ** name comes from malloc() and must be freed by the calling ** function. */ PRIVATE char *file_makename(struct lemon *lemp, const char *suffix) { char *name; char *cp; | > > > > > > > > > > | > > | > > > | 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 | ** name comes from malloc() and must be freed by the calling ** function. */ PRIVATE char *file_makename(struct lemon *lemp, const char *suffix) { char *name; char *cp; char *filename = lemp->filename; int sz; if( outputDir ){ cp = strrchr(filename, '/'); if( cp ) filename = cp + 1; } sz = lemonStrlen(filename); sz += lemonStrlen(suffix); if( outputDir ) sz += lemonStrlen(outputDir) + 1; sz += 5; name = (char*)malloc( sz ); if( name==0 ){ fprintf(stderr,"Can't allocate space for a filename.\n"); exit(1); } name[0] = 0; if( outputDir ){ lemon_strcpy(name, outputDir); lemon_strcat(name, "/"); } lemon_strcat(name,filename); cp = strrchr(name,'.'); if( cp ) *cp = 0; lemon_strcat(name,suffix); return name; } /* Open a file with a name based on the name of the input file, |
︙ | ︙ | |||
3246 3247 3248 3249 3250 3251 3252 | } return result; } /* Generate the "*.out" log file */ void ReportOutput(struct lemon *lemp) { | | > | 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 | } return result; } /* Generate the "*.out" log file */ void ReportOutput(struct lemon *lemp) { int i, n; struct state *stp; struct config *cfp; struct action *ap; struct rule *rp; FILE *fp; fp = file_open(lemp,".out","wb"); if( fp==0 ) return; for(i=0; i<lemp->nxstate; i++){ stp = lemp->sorted[i]; fprintf(fp,"State %d:\n",stp->statenum); |
︙ | ︙ | |||
3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 | for(ap=stp->ap; ap; ap=ap->next){ if( PrintAction(ap,fp,30) ) fprintf(fp,"\n"); } fprintf(fp,"\n"); } fprintf(fp, "----------------------------------------------------\n"); fprintf(fp, "Symbols:\n"); for(i=0; i<lemp->nsymbol; i++){ int j; struct symbol *sp; sp = lemp->symbols[i]; fprintf(fp, " %3d: %s", i, sp->name); if( sp->type==NONTERMINAL ){ fprintf(fp, ":"); if( sp->lambda ){ fprintf(fp, " <lambda>"); } for(j=0; j<lemp->nterminal; j++){ if( sp->firstset && SetFind(sp->firstset, j) ){ fprintf(fp, " %s", lemp->symbols[j]->name); } } } fprintf(fp, "\n"); } fclose(fp); return; } /* Search for the file "name" which is in the same directory as ** the exacutable */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 | for(ap=stp->ap; ap; ap=ap->next){ if( PrintAction(ap,fp,30) ) fprintf(fp,"\n"); } fprintf(fp,"\n"); } fprintf(fp, "----------------------------------------------------\n"); fprintf(fp, "Symbols:\n"); fprintf(fp, "The first-set of non-terminals is shown after the name.\n\n"); for(i=0; i<lemp->nsymbol; i++){ int j; struct symbol *sp; sp = lemp->symbols[i]; fprintf(fp, " %3d: %s", i, sp->name); if( sp->type==NONTERMINAL ){ fprintf(fp, ":"); if( sp->lambda ){ fprintf(fp, " <lambda>"); } for(j=0; j<lemp->nterminal; j++){ if( sp->firstset && SetFind(sp->firstset, j) ){ fprintf(fp, " %s", lemp->symbols[j]->name); } } } if( sp->prec>=0 ) fprintf(fp," (precedence=%d)", sp->prec); fprintf(fp, "\n"); } fprintf(fp, "----------------------------------------------------\n"); fprintf(fp, "Syntax-only Symbols:\n"); fprintf(fp, "The following symbols never carry semantic content.\n\n"); for(i=n=0; i<lemp->nsymbol; i++){ int w; struct symbol *sp = lemp->symbols[i]; if( sp->bContent ) continue; w = (int)strlen(sp->name); if( n>0 && n+w>75 ){ fprintf(fp,"\n"); n = 0; } if( n>0 ){ fprintf(fp, " "); n++; } fprintf(fp, "%s", sp->name); n += w; } if( n>0 ) fprintf(fp, "\n"); fprintf(fp, "----------------------------------------------------\n"); fprintf(fp, "Rules:\n"); for(rp=lemp->rule; rp; rp=rp->next){ fprintf(fp, "%4d: ", rp->iRule); rule_print(fp, rp); fprintf(fp,"."); if( rp->precsym ){ fprintf(fp," [%s precedence=%d]", rp->precsym->name, rp->precsym->prec); } fprintf(fp,"\n"); } fclose(fp); return; } /* Search for the file "name" which is in the same directory as ** the exacutable */ |
︙ | ︙ | |||
3976 3977 3978 3979 3980 3981 3982 | fprintf(out," int yyinit;\n"); lineno++; fprintf(out," %sTOKENTYPE yy0;\n",name); lineno++; for(i=0; i<arraysize; i++){ if( types[i]==0 ) continue; fprintf(out," %s yy%d;\n",types[i],i+1); lineno++; free(types[i]); } | | | 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 | fprintf(out," int yyinit;\n"); lineno++; fprintf(out," %sTOKENTYPE yy0;\n",name); lineno++; for(i=0; i<arraysize; i++){ if( types[i]==0 ) continue; fprintf(out," %s yy%d;\n",types[i],i+1); lineno++; free(types[i]); } if( lemp->errsym && lemp->errsym->useCnt ){ fprintf(out," int yy%d;\n",lemp->errsym->dtnum); lineno++; } free(stddt); free(types); fprintf(out,"} YYMINORTYPE;\n"); lineno++; *plineno = lineno; } |
︙ | ︙ | |||
4126 4127 4128 4129 4130 4131 4132 | } fprintf(out,"#endif\n"); lineno++; } tplt_xfer(lemp->name,in,out,&lineno); /* Generate the defines */ fprintf(out,"#define YYCODETYPE %s\n", | | | | 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 | } fprintf(out,"#endif\n"); lineno++; } tplt_xfer(lemp->name,in,out,&lineno); /* Generate the defines */ fprintf(out,"#define YYCODETYPE %s\n", minimum_size_type(0, lemp->nsymbol, &szCodeType)); lineno++; fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol); lineno++; fprintf(out,"#define YYACTIONTYPE %s\n", minimum_size_type(0,lemp->maxAction,&szActionType)); lineno++; if( lemp->wildcard ){ fprintf(out,"#define YYWILDCARD %d\n", lemp->wildcard->index); lineno++; } print_stack_union(out,lemp,&lineno,mhflag); |
︙ | ︙ | |||
4152 4153 4154 4155 4156 4157 4158 | name = lemp->name ? lemp->name : "Parse"; if( lemp->arg && lemp->arg[0] ){ i = lemonStrlen(lemp->arg); while( i>=1 && ISSPACE(lemp->arg[i-1]) ) i--; while( i>=1 && (ISALNUM(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--; fprintf(out,"#define %sARG_SDECL %s;\n",name,lemp->arg); lineno++; fprintf(out,"#define %sARG_PDECL ,%s\n",name,lemp->arg); lineno++; | > | | | | > > > > > > > > > > > > > > > > > > > | | 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 | name = lemp->name ? lemp->name : "Parse"; if( lemp->arg && lemp->arg[0] ){ i = lemonStrlen(lemp->arg); while( i>=1 && ISSPACE(lemp->arg[i-1]) ) i--; while( i>=1 && (ISALNUM(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--; fprintf(out,"#define %sARG_SDECL %s;\n",name,lemp->arg); lineno++; fprintf(out,"#define %sARG_PDECL ,%s\n",name,lemp->arg); lineno++; fprintf(out,"#define %sARG_PARAM ,%s\n",name,&lemp->arg[i]); lineno++; fprintf(out,"#define %sARG_FETCH %s=yypParser->%s;\n", name,lemp->arg,&lemp->arg[i]); lineno++; fprintf(out,"#define %sARG_STORE yypParser->%s=%s;\n", name,&lemp->arg[i],&lemp->arg[i]); lineno++; }else{ fprintf(out,"#define %sARG_SDECL\n",name); lineno++; fprintf(out,"#define %sARG_PDECL\n",name); lineno++; fprintf(out,"#define %sARG_PARAM\n",name); lineno++; fprintf(out,"#define %sARG_FETCH\n",name); lineno++; fprintf(out,"#define %sARG_STORE\n",name); lineno++; } if( lemp->ctx && lemp->ctx[0] ){ i = lemonStrlen(lemp->ctx); while( i>=1 && ISSPACE(lemp->ctx[i-1]) ) i--; while( i>=1 && (ISALNUM(lemp->ctx[i-1]) || lemp->ctx[i-1]=='_') ) i--; fprintf(out,"#define %sCTX_SDECL %s;\n",name,lemp->ctx); lineno++; fprintf(out,"#define %sCTX_PDECL ,%s\n",name,lemp->ctx); lineno++; fprintf(out,"#define %sCTX_PARAM ,%s\n",name,&lemp->ctx[i]); lineno++; fprintf(out,"#define %sCTX_FETCH %s=yypParser->%s;\n", name,lemp->ctx,&lemp->ctx[i]); lineno++; fprintf(out,"#define %sCTX_STORE yypParser->%s=%s;\n", name,&lemp->ctx[i],&lemp->ctx[i]); lineno++; }else{ fprintf(out,"#define %sCTX_SDECL\n",name); lineno++; fprintf(out,"#define %sCTX_PDECL\n",name); lineno++; fprintf(out,"#define %sCTX_PARAM\n",name); lineno++; fprintf(out,"#define %sCTX_FETCH\n",name); lineno++; fprintf(out,"#define %sCTX_STORE\n",name); lineno++; } if( mhflag ){ fprintf(out,"#endif\n"); lineno++; } if( lemp->errsym && lemp->errsym->useCnt ){ fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index); lineno++; fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum); lineno++; } if( lemp->has_fallback ){ fprintf(out,"#define YYFALLBACK 1\n"); lineno++; } |
︙ | ︙ |
Changes to tool/lempar.c.
︙ | ︙ | |||
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | ** This is typically a union of many types, one of ** which is ParseTOKENTYPE. The entry in the union ** for terminal symbols is called "yy0". ** YYSTACKDEPTH is the maximum depth of the parser's stack. If ** zero the stack is dynamically sized using realloc() ** ParseARG_SDECL A static variable declaration for the %extra_argument ** ParseARG_PDECL A parameter declaration for the %extra_argument ** ParseARG_STORE Code to store %extra_argument into yypParser ** ParseARG_FETCH Code to extract %extra_argument from yypParser ** 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 | > > | 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | ** This is typically a union of many types, one of ** which is ParseTOKENTYPE. The entry in the union ** for terminal symbols is called "yy0". ** YYSTACKDEPTH is the maximum depth of the parser's stack. If ** zero the stack is dynamically sized using realloc() ** ParseARG_SDECL A static variable declaration for the %extra_argument ** ParseARG_PDECL A parameter declaration for the %extra_argument ** ParseARG_PARAM Code to pass %extra_argument as a subroutine parameter ** ParseARG_STORE Code to store %extra_argument into yypParser ** ParseARG_FETCH Code to extract %extra_argument from yypParser ** ParseCTX_* As ParseARG_ 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 |
︙ | ︙ | |||
207 208 209 210 211 212 213 214 215 216 217 218 219 220 | #ifdef YYTRACKMAXSTACKDEPTH int yyhwm; /* High-water mark of the stack */ #endif #ifndef YYNOERRORRECOVERY int yyerrcnt; /* Shifts left before out of the error */ #endif ParseARG_SDECL /* A place to hold %extra_argument */ #if YYSTACKDEPTH<=0 int yystksz; /* Current side of the stack */ yyStackEntry *yystack; /* The parser's stack */ yyStackEntry yystk0; /* First stack entry */ #else yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */ yyStackEntry *yystackEnd; /* Last entry in the stack */ | > | 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | #ifdef YYTRACKMAXSTACKDEPTH int yyhwm; /* High-water mark of the stack */ #endif #ifndef YYNOERRORRECOVERY int yyerrcnt; /* Shifts left before out of the error */ #endif ParseARG_SDECL /* A place to hold %extra_argument */ ParseCTX_SDECL /* A place to hold %extra_context */ #if YYSTACKDEPTH<=0 int yystksz; /* Current side of the stack */ yyStackEntry *yystack; /* The parser's stack */ yyStackEntry yystk0; /* First stack entry */ #else yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */ yyStackEntry *yystackEnd; /* Last entry in the stack */ |
︙ | ︙ | |||
311 312 313 314 315 316 317 | */ #ifndef YYMALLOCARGTYPE # define YYMALLOCARGTYPE size_t #endif /* Initialize a new parser that has already been allocated. */ | | | > | | | | | | | | | | | | | | | | > > > | | > | 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 | */ #ifndef YYMALLOCARGTYPE # define YYMALLOCARGTYPE size_t #endif /* Initialize a new parser that has already been allocated. */ void ParseInit(void *yypRawParser ParseCTX_PDECL){ yyParser *yypParser = (yyParser*)yypRawParser; ParseCTX_STORE #ifdef YYTRACKMAXSTACKDEPTH yypParser->yyhwm = 0; #endif #if YYSTACKDEPTH<=0 yypParser->yytos = NULL; yypParser->yystack = NULL; yypParser->yystksz = 0; if( yyGrowStack(yypParser) ){ yypParser->yystack = &yypParser->yystk0; yypParser->yystksz = 1; } #endif #ifndef YYNOERRORRECOVERY yypParser->yyerrcnt = -1; #endif yypParser->yytos = yypParser->yystack; yypParser->yystack[0].stateno = 0; yypParser->yystack[0].major = 0; #if YYSTACKDEPTH>0 yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1]; #endif } #ifndef Parse_ENGINEALWAYSONSTACK /* ** This function allocates a new parser. ** The only argument is a pointer to a function which works like ** malloc. ** ** Inputs: ** A pointer to the function used to allocate memory. ** ** Outputs: ** A pointer to a parser. This pointer is used in subsequent calls ** to Parse and ParseFree. */ void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE) ParseCTX_PDECL){ yyParser *yypParser; yypParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); if( yypParser ){ ParseCTX_STORE ParseInit(yypParser ParseCTX_PARAM); } return (void*)yypParser; } #endif /* Parse_ENGINEALWAYSONSTACK */ /* The following function deletes the "minor type" or semantic value ** associated with a symbol. The symbol can be either a terminal ** or nonterminal. "yymajor" is the symbol code, and "yypminor" is ** a pointer to the value to be deleted. The code used to do the ** deletions is derived from the %destructor and/or %token_destructor ** directives of the input grammar. */ static void yy_destructor( yyParser *yypParser, /* The parser */ YYCODETYPE yymajor, /* Type code for object to destroy */ YYMINORTYPE *yypminor /* The object to be destroyed */ ){ ParseARG_FETCH ParseCTX_FETCH switch( yymajor ){ /* Here is inserted the actions which take place when a ** terminal or non-terminal is destroyed. This can happen ** when the symbol is popped from the stack during a ** reduce or during error processing or when a parser is ** being destroyed before it is finished parsing. ** |
︙ | ︙ | |||
493 494 495 496 497 498 499 | } #endif /* ** Find the appropriate action for a parser given the terminal ** look-ahead token iLookAhead. */ | | < | > < | | 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 | } #endif /* ** Find the appropriate action for a parser given the terminal ** look-ahead token iLookAhead. */ static YYACTIONTYPE yy_find_shift_action( YYCODETYPE iLookAhead, /* The look-ahead token */ YYACTIONTYPE stateno /* Current state number */ ){ int i; 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]; |
︙ | ︙ | |||
563 564 565 566 567 568 569 | } /* ** Find the appropriate action for a parser given the non-terminal ** look-ahead token iLookAhead. */ static int yy_find_reduce_action( | | | 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 | } /* ** Find the appropriate action for a parser given the non-terminal ** look-ahead token iLookAhead. */ static int yy_find_reduce_action( YYACTIONTYPE stateno, /* Current state number */ YYCODETYPE iLookAhead /* The look-ahead token */ ){ int i; #ifdef YYERRORSYMBOL if( stateno>YY_REDUCE_COUNT ){ return yy_default[stateno]; } |
︙ | ︙ | |||
592 593 594 595 596 597 598 | return yy_action[i]; } /* ** The following routine is called if the stack overflows. */ static void yyStackOverflow(yyParser *yypParser){ | | > | > | 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 | return yy_action[i]; } /* ** The following routine is called if the stack overflows. */ static void yyStackOverflow(yyParser *yypParser){ ParseARG_FETCH ParseCTX_FETCH #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); } #endif while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will execute if the parser ** stack every overflows */ /******** Begin %stack_overflow code ******************************************/ %% /******** End %stack_overflow code ********************************************/ ParseARG_STORE /* Suppress warning about unused %extra_argument var */ ParseCTX_STORE } /* ** Print tracing information for a SHIFT action */ #ifndef NDEBUG static void yyTraceShift(yyParser *yypParser, int yyNewState, const char *zTag){ |
︙ | ︙ | |||
633 634 635 636 637 638 639 | #endif /* ** Perform a shift action. */ static void yy_shift( yyParser *yypParser, /* The parser to be shifted */ | | | | 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 | #endif /* ** Perform a shift action. */ static void yy_shift( yyParser *yypParser, /* The parser to be shifted */ YYACTIONTYPE yyNewState, /* The new state to shift in */ YYCODETYPE yyMajor, /* The major token to shift in */ ParseTOKENTYPE yyMinor /* The minor token to shift in */ ){ yyStackEntry *yytos; yypParser->yytos++; #ifdef YYTRACKMAXSTACKDEPTH if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){ yypParser->yyhwm++; |
︙ | ︙ | |||
664 665 666 667 668 669 670 | } } #endif if( yyNewState > YY_MAX_SHIFT ){ yyNewState += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; } yytos = yypParser->yytos; | | | | 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 | } } #endif if( yyNewState > YY_MAX_SHIFT ){ yyNewState += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; } yytos = yypParser->yytos; yytos->stateno = yyNewState; yytos->major = yyMajor; yytos->minor.yy0 = yyMinor; yyTraceShift(yypParser, yyNewState, "Shift"); } /* The following table contains information about every rule that ** is used during the reduce. */ |
︙ | ︙ | |||
692 693 694 695 696 697 698 | ** ** 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. */ | | > | | 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 | ** ** 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 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 */ ParseTOKENTYPE yyLookaheadToken /* Value of the lookahead token */ ParseCTX_PDECL /* %extra_context */ ){ int yygoto; /* The next state */ int yyact; /* The next action */ yyStackEntry *yymsp; /* The top of the parser's stack */ int yysize; /* Amount to pop the stack */ ParseARG_FETCH (void)yyLookahead; (void)yyLookaheadToken; yymsp = yypParser->yytos; #ifndef NDEBUG if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ yysize = yyRuleInfo[yyruleno].nrhs; if( yysize ){ |
︙ | ︙ | |||
733 734 735 736 737 738 739 | yypParser->yyhwm++; assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack)); } #endif #if YYSTACKDEPTH>0 if( yypParser->yytos>=yypParser->yystackEnd ){ yyStackOverflow(yypParser); | > > > | > > > | | 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 | yypParser->yyhwm++; assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack)); } #endif #if YYSTACKDEPTH>0 if( yypParser->yytos>=yypParser->yystackEnd ){ yyStackOverflow(yypParser); /* 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); /* 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; } #endif } switch( yyruleno ){ |
︙ | ︙ | |||
776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 | assert( yyact!=YY_ERROR_ACTION ); yymsp += yysize+1; yypParser->yytos = yymsp; yymsp->stateno = (YYACTIONTYPE)yyact; yymsp->major = (YYCODETYPE)yygoto; yyTraceShift(yypParser, yyact, "... then shift"); } /* ** The following code executes when the parse fails */ #ifndef YYNOERRORRECOVERY static void yy_parse_failed( yyParser *yypParser /* The parser */ ){ | > | > | > | > | > | > | > | 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 | assert( yyact!=YY_ERROR_ACTION ); yymsp += yysize+1; yypParser->yytos = yymsp; yymsp->stateno = (YYACTIONTYPE)yyact; yymsp->major = (YYCODETYPE)yygoto; yyTraceShift(yypParser, yyact, "... then shift"); return yyact; } /* ** The following code executes when the parse fails */ #ifndef YYNOERRORRECOVERY static void yy_parse_failed( yyParser *yypParser /* The parser */ ){ ParseARG_FETCH ParseCTX_FETCH #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); } #endif while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will be executed whenever the ** parser fails */ /************ Begin %parse_failure code ***************************************/ %% /************ End %parse_failure code *****************************************/ ParseARG_STORE /* Suppress warning about unused %extra_argument variable */ ParseCTX_STORE } #endif /* YYNOERRORRECOVERY */ /* ** The following code executes when a syntax error first occurs. */ static void yy_syntax_error( yyParser *yypParser, /* The parser */ int yymajor, /* The major type of the error token */ ParseTOKENTYPE yyminor /* The minor type of the error token */ ){ ParseARG_FETCH ParseCTX_FETCH #define TOKEN yyminor /************ Begin %syntax_error code ****************************************/ %% /************ End %syntax_error code ******************************************/ ParseARG_STORE /* Suppress warning about unused %extra_argument variable */ ParseCTX_STORE } /* ** The following is executed when the parser accepts */ static void yy_accept( yyParser *yypParser /* The parser */ ){ ParseARG_FETCH ParseCTX_FETCH #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); } #endif #ifndef YYNOERRORRECOVERY yypParser->yyerrcnt = -1; #endif assert( yypParser->yytos==yypParser->yystack ); /* Here code is inserted which will be executed whenever the ** parser accepts */ /*********** Begin %parse_accept code *****************************************/ %% /*********** End %parse_accept code *******************************************/ ParseARG_STORE /* Suppress warning about unused %extra_argument variable */ ParseCTX_STORE } /* The main parser program. ** The first argument is a pointer to a structure obtained from ** "ParseAlloc" which describes the current state of the parser. ** The second argument is the major token number. The third is ** the minor token. The fourth optional argument is whatever the |
︙ | ︙ | |||
867 868 869 870 871 872 873 | void Parse( void *yyp, /* The parser */ int yymajor, /* The major token code number */ ParseTOKENTYPE yyminor /* The value for the token */ ParseARG_PDECL /* Optional %extra_argument parameter */ ){ YYMINORTYPE yyminorunion; | | | > > < < > < | | | > | | > | | 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 | void Parse( void *yyp, /* The parser */ int yymajor, /* The major token code number */ ParseTOKENTYPE yyminor /* The value for the token */ ParseARG_PDECL /* Optional %extra_argument parameter */ ){ YYMINORTYPE yyminorunion; YYACTIONTYPE yyact; /* The parser action. */ #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) int yyendofinput; /* True if we are at the end of input */ #endif #ifdef YYERRORSYMBOL int yyerrorhit = 0; /* True if yymajor has invoked an error */ #endif yyParser *yypParser = (yyParser*)yyp; /* The parser */ ParseCTX_FETCH ParseARG_STORE assert( yypParser->yytos!=0 ); #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) yyendofinput = (yymajor==0); #endif yyact = yypParser->yytos->stateno; #ifndef NDEBUG if( yyTraceFILE ){ 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{ assert( yyact==yypParser->yytos->stateno ); yyact = yy_find_shift_action(yymajor,yyact); if( yyact >= YY_MIN_REDUCE ){ yyact = yy_reduce(yypParser,yyact-YY_MIN_REDUCE,yymajor, yyminor ParseCTX_PARAM); }else if( yyact <= YY_MAX_SHIFTREDUCE ){ yy_shift(yypParser,yyact,yymajor,yyminor); #ifndef YYNOERRORRECOVERY yypParser->yyerrcnt--; #endif break; }else if( yyact==YY_ACCEPT_ACTION ){ yypParser->yytos--; yy_accept(yypParser); return; }else{ assert( yyact == YY_ERROR_ACTION ); yyminorunion.yy0 = yyminor; |
︙ | ︙ | |||
976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 | yymajor = YYNOCODE; }else if( yymx!=YYERRORSYMBOL ){ yy_shift(yypParser,yyact,YYERRORSYMBOL,yyminor); } } yypParser->yyerrcnt = 3; yyerrorhit = 1; #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 ** error routine and continue going as if nothing had happened. ** ** Applications can set this macro (for example inside %include) if ** they intend to abandon the parse upon the first syntax error seen. */ yy_syntax_error(yypParser,yymajor, yyminor); yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); | > > < | | 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 | yymajor = YYNOCODE; }else if( yymx!=YYERRORSYMBOL ){ yy_shift(yypParser,yyact,YYERRORSYMBOL,yyminor); } } 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 ** error routine and continue going as if nothing had happened. ** ** Applications can set this macro (for example inside %include) if ** they intend to abandon the parse upon the first syntax error seen. */ yy_syntax_error(yypParser,yymajor, yyminor); yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); break; #else /* YYERRORSYMBOL is not defined */ /* This is what we do if the grammar does not define ERROR: ** ** * Report an error message, and throw away the input token. ** ** * If the input token is $, then fail the parse. ** |
︙ | ︙ | |||
1009 1010 1011 1012 1013 1014 1015 | yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); if( yyendofinput ){ yy_parse_failed(yypParser); #ifndef YYNOERRORRECOVERY yypParser->yyerrcnt = -1; #endif } | | | | 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 | yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); if( yyendofinput ){ yy_parse_failed(yypParser); #ifndef YYNOERRORRECOVERY yypParser->yyerrcnt = -1; #endif } break; #endif } }while( yypParser->yytos>yypParser->yystack ); #ifndef NDEBUG if( yyTraceFILE ){ yyStackEntry *i; char cDiv = '['; fprintf(yyTraceFILE,"%sReturn. Stack=",yyTracePrompt); for(i=&yypParser->yystack[1]; i<=yypParser->yytos; i++){ fprintf(yyTraceFILE,"%c%s", cDiv, yyTokenName[i->major]); |
︙ | ︙ |
Changes to tool/mkkeywordhash.c.
︙ | ︙ | |||
139 140 141 142 143 144 145 146 147 148 149 150 151 152 | # define AUTOVACUUM 0x00020000 #endif #ifdef SQLITE_OMIT_CTE # define CTE 0 #else # define CTE 0x00040000 #endif /* ** These are the keywords */ static Keyword aKeywordTable[] = { { "ABORT", "TK_ABORT", CONFLICT|TRIGGER }, { "ACTION", "TK_ACTION", FKEY }, | > > > > > | 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | # define AUTOVACUUM 0x00020000 #endif #ifdef SQLITE_OMIT_CTE # define CTE 0 #else # define CTE 0x00040000 #endif #ifdef SQLITE_OMIT_UPSERT # define UPSERT 0 #else # define UPSERT 0x00080000 #endif /* ** These are the keywords */ static Keyword aKeywordTable[] = { { "ABORT", "TK_ABORT", CONFLICT|TRIGGER }, { "ACTION", "TK_ACTION", FKEY }, |
︙ | ︙ | |||
182 183 184 185 186 187 188 189 190 191 192 193 194 195 | { "DEFAULT", "TK_DEFAULT", ALWAYS }, { "DEFERRED", "TK_DEFERRED", ALWAYS }, { "DEFERRABLE", "TK_DEFERRABLE", FKEY }, { "DELETE", "TK_DELETE", ALWAYS }, { "DESC", "TK_DESC", ALWAYS }, { "DETACH", "TK_DETACH", ATTACH }, { "DISTINCT", "TK_DISTINCT", ALWAYS }, { "DROP", "TK_DROP", ALWAYS }, { "END", "TK_END", ALWAYS }, { "EACH", "TK_EACH", TRIGGER }, { "ELSE", "TK_ELSE", ALWAYS }, { "ESCAPE", "TK_ESCAPE", ALWAYS }, { "EXCEPT", "TK_EXCEPT", COMPOUND }, { "EXISTS", "TK_EXISTS", ALWAYS }, | > | 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | { "DEFAULT", "TK_DEFAULT", ALWAYS }, { "DEFERRED", "TK_DEFERRED", ALWAYS }, { "DEFERRABLE", "TK_DEFERRABLE", FKEY }, { "DELETE", "TK_DELETE", ALWAYS }, { "DESC", "TK_DESC", ALWAYS }, { "DETACH", "TK_DETACH", ATTACH }, { "DISTINCT", "TK_DISTINCT", ALWAYS }, { "DO", "TK_DO", UPSERT }, { "DROP", "TK_DROP", ALWAYS }, { "END", "TK_END", ALWAYS }, { "EACH", "TK_EACH", TRIGGER }, { "ELSE", "TK_ELSE", ALWAYS }, { "ESCAPE", "TK_ESCAPE", ALWAYS }, { "EXCEPT", "TK_EXCEPT", COMPOUND }, { "EXISTS", "TK_EXISTS", ALWAYS }, |
︙ | ︙ | |||
221 222 223 224 225 226 227 228 229 230 231 232 233 234 | { "LEFT", "TK_JOIN_KW", ALWAYS }, { "LIKE", "TK_LIKE_KW", ALWAYS }, { "LIMIT", "TK_LIMIT", ALWAYS }, { "MATCH", "TK_MATCH", ALWAYS }, { "NATURAL", "TK_JOIN_KW", ALWAYS }, { "NO", "TK_NO", FKEY }, { "NOT", "TK_NOT", ALWAYS }, { "NOTNULL", "TK_NOTNULL", ALWAYS }, { "NULL", "TK_NULL", ALWAYS }, { "OF", "TK_OF", ALWAYS }, { "OFFSET", "TK_OFFSET", ALWAYS }, { "ON", "TK_ON", ALWAYS }, { "OR", "TK_OR", ALWAYS }, { "ORDER", "TK_ORDER", ALWAYS }, | > | 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | { "LEFT", "TK_JOIN_KW", ALWAYS }, { "LIKE", "TK_LIKE_KW", ALWAYS }, { "LIMIT", "TK_LIMIT", ALWAYS }, { "MATCH", "TK_MATCH", ALWAYS }, { "NATURAL", "TK_JOIN_KW", ALWAYS }, { "NO", "TK_NO", FKEY }, { "NOT", "TK_NOT", ALWAYS }, { "NOTHING", "TK_NOTHING", UPSERT }, { "NOTNULL", "TK_NOTNULL", ALWAYS }, { "NULL", "TK_NULL", ALWAYS }, { "OF", "TK_OF", ALWAYS }, { "OFFSET", "TK_OFFSET", ALWAYS }, { "ON", "TK_ON", ALWAYS }, { "OR", "TK_OR", ALWAYS }, { "ORDER", "TK_ORDER", ALWAYS }, |
︙ | ︙ |
Changes to tool/mkmsvcmin.tcl.
︙ | ︙ | |||
79 80 81 82 83 84 85 | set blocks(2) [string trimleft [string map [list \\\\ \\] { Replace.exe: $(CSC) /target:exe $(TOP)\Replace.cs sqlite3.def: Replace.exe $(LIBOBJ) echo EXPORTS > sqlite3.def dumpbin /all $(LIBOBJ) \\ | | | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | set blocks(2) [string trimleft [string map [list \\\\ \\] { Replace.exe: $(CSC) /target:exe $(TOP)\Replace.cs sqlite3.def: Replace.exe $(LIBOBJ) echo EXPORTS > sqlite3.def dumpbin /all $(LIBOBJ) \\ | .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup|rebaser)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \\ | sort >> sqlite3.def }]] set data "#### DO NOT EDIT ####\n" append data "# This makefile is automatically " append data "generated from the [file tail $fromFileName] at\n" append data "# the root of the canonical SQLite source tree (not the\n" |
︙ | ︙ |
Changes to tool/mksqlite3c.tcl.
︙ | ︙ | |||
359 360 361 362 363 364 365 366 367 368 369 370 371 372 | loadext.c pragma.c prepare.c select.c table.c trigger.c update.c vacuum.c vtab.c wherecode.c whereexpr.c where.c parse.c | > | 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 | loadext.c pragma.c prepare.c select.c table.c trigger.c update.c upsert.c vacuum.c vtab.c wherecode.c whereexpr.c where.c parse.c |
︙ | ︙ |
Changes to tool/mksqlite3h.tcl.
︙ | ︙ | |||
68 69 70 71 72 73 74 75 76 77 78 79 80 81 | set declpattern3 \ {^ *([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3changeset_[_a-zA-Z0-9]+)(\(.*)$} set declpattern4 \ {^ *([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3changegroup_[_a-zA-Z0-9]+)(\(.*)$} # Force the output to use unix line endings, even on Windows. fconfigure stdout -translation lf set filelist [subst { $TOP/src/sqlite.h.in $TOP/ext/rtree/sqlite3rtree.h $TOP/ext/session/sqlite3session.h | > > > | 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | set declpattern3 \ {^ *([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3changeset_[_a-zA-Z0-9]+)(\(.*)$} set declpattern4 \ {^ *([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3changegroup_[_a-zA-Z0-9]+)(\(.*)$} set declpattern5 \ {^ *([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3rebaser_[_a-zA-Z0-9]+)(\(.*)$} # Force the output to use unix line endings, even on Windows. fconfigure stdout -translation lf set filelist [subst { $TOP/src/sqlite.h.in $TOP/ext/rtree/sqlite3rtree.h $TOP/ext/session/sqlite3session.h |
︙ | ︙ | |||
117 118 119 120 121 122 123 | if {[regexp $varpattern $line] && ![regexp {^ *typedef} $line]} { set line "SQLITE_API $line" } else { if {[regexp $declpattern1 $line all rettype funcname rest] || \ [regexp $declpattern2 $line all rettype funcname rest] || \ [regexp $declpattern3 $line all rettype funcname rest] || \ | | > | 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | if {[regexp $varpattern $line] && ![regexp {^ *typedef} $line]} { set line "SQLITE_API $line" } else { if {[regexp $declpattern1 $line all rettype funcname rest] || \ [regexp $declpattern2 $line all rettype funcname rest] || \ [regexp $declpattern3 $line all rettype funcname rest] || \ [regexp $declpattern4 $line all rettype funcname rest] || \ [regexp $declpattern5 $line all rettype funcname rest]} { set line SQLITE_API append line " " [string trim $rettype] if {[string index $rettype end] ne "*"} { append line " " } if {$useapicall} { if {[lsearch -exact $cdecllist $funcname] >= 0} { |
︙ | ︙ |