Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Difference From a7fe90c1581e7e4f To 8290646792bc5411
2024-06-12
| ||
21:08 | Fix a potential db corruption case triggered by the OPFS VFS's xCheckReservedLock() implementation. check-in: a7cd07d96e user: stephan tags: branch-3.46 | |
2024-06-09
| ||
17:58 | Disable the omit-noop-join optimization when there are 64 or more terms in the ORDER BY clause. check-in: a7fe90c158 user: drh tags: branch-3.46 | |
17:34 | Disable the omit-noop-join optimization when there are 64 or more terms in the ORDER BY clause. check-in: 40de393979 user: drh tags: trunk | |
2024-06-05
| ||
16:50 | Fix an fts5 problem with secure-delete mode causing integrity-check to erroneously report a corrupt index. check-in: 0a7fa0a434 user: drh tags: branch-3.46 | |
2024-03-05
| ||
18:41 | Remove code that added a P4 parameter to the OP_Variable opcode. This is no longer required. check-in: dd5977c9a8 user: dan tags: trunk | |
18:03 | Merge trunk changes into this branch. check-in: a003fffafd user: dan tags: exp-values-clause | |
17:39 | Reformulate [34439fe3aeea7cbb] slightly to resolve a false-positive OOM reported in [forum:2eadfe94e3|forum post 2eadfe94e3]. check-in: 320ccb5d5f user: stephan tags: branch-3.45 | |
17:33 | Reformulate [34439fe3aeea7cbb] slightly to resolve a false-positive OOM reported in [forum:2eadfe94e3|forum post 2eadfe94e3]. check-in: 8290646792 user: stephan tags: trunk | |
16:47 | The value returned by the json_each.json field needs to survive longer than the json_each virtual table itself, in the event that the value is used in an aggregate expression. dbsqlfuzz 5120bd0b3bb0b73eebbcb79ac37c6b0663fccad6 check-in: 952ed71b9b user: drh tags: trunk | |
Changes to Makefile.in.
︙ | ︙ | |||
813 814 815 816 817 818 819 | rm tsrc/sqlite.h.in tsrc/parse.y $(TCLSH_CMD) $(TOP)/tool/vdbe-compress.tcl $(OPTS) <tsrc/vdbe.c >vdbe.new mv vdbe.new tsrc/vdbe.c cp fts5.c fts5.h tsrc touch .target_source sqlite3.c: .target_source $(TOP)/tool/mksqlite3c.tcl src-verify has_tclsh84 | | > | > | 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 | rm tsrc/sqlite.h.in tsrc/parse.y $(TCLSH_CMD) $(TOP)/tool/vdbe-compress.tcl $(OPTS) <tsrc/vdbe.c >vdbe.new mv vdbe.new tsrc/vdbe.c cp fts5.c fts5.h tsrc touch .target_source sqlite3.c: .target_source $(TOP)/tool/mksqlite3c.tcl src-verify has_tclsh84 $(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl $(AMALGAMATION_LINE_MACROS) \ $(EXTRA_SRC) cp tsrc/sqlite3ext.h . cp $(TOP)/ext/session/sqlite3session.h . sqlite3r.h: sqlite3.h has_tclsh84 $(TCLSH_CMD) $(TOP)/tool/mksqlite3h.tcl $(TOP) --enable-recover >sqlite3r.h sqlite3r.c: sqlite3.c sqlite3r.h has_tclsh84 cp $(TOP)/ext/recover/sqlite3recover.c tsrc/ cp $(TOP)/ext/recover/sqlite3recover.h tsrc/ cp $(TOP)/ext/recover/dbdata.c tsrc/ $(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl --enable-recover \ $(AMALGAMATION_LINE_MACROS) $(EXTRA_SRC) sqlite3ext.h: .target_source cp tsrc/sqlite3ext.h . tclsqlite3.c: sqlite3.c echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c cat sqlite3.c >>tclsqlite3.c |
︙ | ︙ | |||
1308 1309 1310 1311 1312 1313 1314 | TESTFIXTURE_SRC = $(TESTSRC) $(TOP)/src/tclsqlite.c TESTFIXTURE_SRC += $(TESTFIXTURE_SRC$(USE_AMALGAMATION)) testfixture$(TEXE): has_tclsh85 $(TESTFIXTURE_SRC) $(LTLINK) -DSQLITE_NO_SYNC=1 $(TEMP_STORE) $(TESTFIXTURE_FLAGS) \ -o $@ $(TESTFIXTURE_SRC) $(LIBTCL) $(TLIBS) | | | | 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 | TESTFIXTURE_SRC = $(TESTSRC) $(TOP)/src/tclsqlite.c TESTFIXTURE_SRC += $(TESTFIXTURE_SRC$(USE_AMALGAMATION)) testfixture$(TEXE): has_tclsh85 $(TESTFIXTURE_SRC) $(LTLINK) -DSQLITE_NO_SYNC=1 $(TEMP_STORE) $(TESTFIXTURE_FLAGS) \ -o $@ $(TESTFIXTURE_SRC) $(LIBTCL) $(TLIBS) coretestprogs: $(TESTPROGS) testprogs: coretestprogs srcck1$(BEXE) fuzzcheck$(TEXE) sessionfuzz$(TEXE) # A very detailed test running most or all test cases fulltest: alltest fuzztest # Run most or all tcl test cases alltest: $(TESTPROGS) ./testfixture$(TEXE) $(TOP)/test/all.test $(TESTOPTS) |
︙ | ︙ |
Changes to Makefile.msc.
︙ | ︙ | |||
2492 2493 2494 2495 2496 2497 2498 | extensiontest: testfixture.exe testloadext.dll @set PATH=$(LIBTCLPATH);$(PATH) .\testfixture.exe $(TOP)\test\loadext.test $(TESTOPTS) tool-zip: testfixture.exe sqlite3.exe sqldiff.exe sqlite3_analyzer.exe $(TOP)\tool\mktoolzip.tcl .\testfixture.exe $(TOP)\tool\mktoolzip.tcl | | | | 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 | extensiontest: testfixture.exe testloadext.dll @set PATH=$(LIBTCLPATH);$(PATH) .\testfixture.exe $(TOP)\test\loadext.test $(TESTOPTS) tool-zip: testfixture.exe sqlite3.exe sqldiff.exe sqlite3_analyzer.exe $(TOP)\tool\mktoolzip.tcl .\testfixture.exe $(TOP)\tool\mktoolzip.tcl coretestprogs: $(TESTPROGS) testprogs: coretestprogs srcck1.exe fuzzcheck.exe sessionfuzz.exe fulltest: alltest fuzztest alltest: $(TESTPROGS) @set PATH=$(LIBTCLPATH);$(PATH) .\testfixture.exe $(TOP)\test\all.test $(TESTOPTS) |
︙ | ︙ | |||
2549 2550 2551 2552 2553 2554 2555 | devtest: testfixture.exe fuzztest testrunner mdevtest: $(TCLSH_CMD) $(TOP)\test\testrunner.tcl mdevtest # Testing for a release # | | | 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 | devtest: testfixture.exe fuzztest testrunner mdevtest: $(TCLSH_CMD) $(TOP)\test\testrunner.tcl mdevtest # Testing for a release # releasetest: testfixture.exe fuzztest testfixture.exe $(TOP)\test\testrunner.tcl release smoketest: $(TESTPROGS) @set PATH=$(LIBTCLPATH);$(PATH) .\testfixture.exe $(TOP)\test\main.test $(TESTOPTS) |
︙ | ︙ |
Changes to VERSION.
|
| | | 1 | 3.46.0 |
Changes to autoconf/tea/configure.ac.
︙ | ︙ | |||
15 16 17 18 19 20 21 | # This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION # set as provided. These will also be added as -D defs in your Makefile # so you can encode the package version directly into the source files. # This will also define a special symbol for Windows (BUILD_<PACKAGE_NAME> # so that we create the export library with the dll. #----------------------------------------------------------------------- | | | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | # This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION # set as provided. These will also be added as -D defs in your Makefile # so you can encode the package version directly into the source files. # This will also define a special symbol for Windows (BUILD_<PACKAGE_NAME> # so that we create the export library with the dll. #----------------------------------------------------------------------- AC_INIT([sqlite],[3.46.0]) #-------------------------------------------------------------------- # Call TEA_INIT as the first TEA_ macro to set up initial vars. # This will define a ${TEA_PLATFORM} variable == "unix" or "windows" # as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE. #-------------------------------------------------------------------- |
︙ | ︙ |
Changes to configure.
1 2 | #! /bin/sh # Guess values for system-dependent variables and create Makefiles. | | | 1 2 3 4 5 6 7 8 9 10 | #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for sqlite 3.46.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.46.0' PACKAGE_STRING='sqlite 3.46.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include <stdio.h> #ifdef HAVE_SYS_TYPES_H |
︙ | ︙ | |||
1468 1469 1470 1471 1472 1473 1474 | # # 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 | | | 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 | # # 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.46.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. |
︙ | ︙ | |||
1533 1534 1535 1536 1537 1538 1539 | --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 | | | 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 | --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.46.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] |
︙ | ︙ | |||
1664 1665 1666 1667 1668 1669 1670 | cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF | | | 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 | 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.46.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 |
︙ | ︙ | |||
2083 2084 2085 2086 2087 2088 2089 | 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. | | | 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 | 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.46.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { |
︙ | ︙ | |||
12477 12478 12479 12480 12481 12482 12483 | 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=" | | | 12477 12478 12479 12480 12481 12482 12483 12484 12485 12486 12487 12488 12489 12490 12491 | 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.46.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 $@ |
︙ | ︙ | |||
12543 12544 12545 12546 12547 12548 12549 | 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="\\ | | | 12543 12544 12545 12546 12547 12548 12549 12550 12551 12552 12553 12554 12555 12556 12557 | 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.46.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/testrunner.md.
︙ | ︙ | |||
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <li> 3. <a href=#source_code_tests>Source Tests</a> <ul type=none> <li> 3.1. <a href=#commands_to_run_tests>Commands to Run SQLite Tests</a> <li> 3.2. <a href=#zipvfs_tests>Running ZipVFS Tests</a> <li> 3.3. <a href=#source_code_test_failures>Investigating Source Code Test Failures</a> </ul> <li> 4. <a href=#testrunner_options>Extra testrunner.tcl Options</a> <li> 5. <a href=#cpu_cores>Controlling CPU Core Utilization</a> </ul> <a name=overview></a> # 1. Overview testrunner.tcl is a Tcl script used to run multiple SQLite tests using multiple jobs. It supports the following types of tests: * Tcl test scripts. | > | | < < < | < | < < | 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 | <li> 3. <a href=#source_code_tests>Source Tests</a> <ul type=none> <li> 3.1. <a href=#commands_to_run_tests>Commands to Run SQLite Tests</a> <li> 3.2. <a href=#zipvfs_tests>Running ZipVFS Tests</a> <li> 3.3. <a href=#source_code_test_failures>Investigating Source Code Test Failures</a> </ul> <li> 4. <a href=#testrunner_options>Extra testrunner.tcl Options</a> # 4. Extra testrunner.tcl Options <li> 5. <a href=#cpu_cores>Controlling CPU Core Utilization</a> </ul> <a name=overview></a> # 1. Overview testrunner.tcl is a Tcl script used to run multiple SQLite tests using multiple jobs. It supports the following types of tests: * Tcl test scripts. * Tests run with [make] commands. Specifically, at time of writing, [make fuzztest], [make mptest], [make sourcetest] and [make threadtest]. testrunner.tcl pipes the output of all tests and builds run into log file **testrunner.log**, created in the cwd directory. Searching this file for "failed" is a good way to find the output of a failed test. testrunner.tcl also populates SQLite database **testrunner.db**. This database contains details of all tests run, running and to be run. A useful query might be: ``` SELECT * FROM script WHERE state='failed' |
︙ | ︙ | |||
61 62 63 64 65 66 67 | ``` watch ./testfixture $(TESTDIR)/testrunner.tcl status ``` in another terminal is a good way to keep an eye on a long running test. | | | | | 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 | ``` watch ./testfixture $(TESTDIR)/testrunner.tcl status ``` in another terminal is a good way to keep an eye on a long running test. Sometimes testrunner.tcl uses the [testfixture] binary that it is run with to run tests (see "Binary Tests" below). Sometimes it builds testfixture and other binaries in specific configurations to test (see "Source Tests"). <a name=binary_tests></a> # 2. Binary Tests The commands described in this section all run various combinations of the Tcl test scripts using the [testfixture] binary used to run the testrunner.tcl script (i.e. they do not invoke the compiler to build new binaries, or the [make] command to run tests that are not Tcl scripts). The procedure to run these tests is therefore: 1. Build the "testfixture" (or "testfixture.exe" for windows) binary using whatever method seems convenient. 2. Test the binary built in step 1 by running testrunner.tcl with it, perhaps with various options. |
︙ | ︙ | |||
194 195 196 197 198 199 200 | TODO: ./configure + Makefile.msc build systems. <a name=commands_to_run_tests></a> ## 3.1. Commands to Run SQLite Tests The **mdevtest** command is equivalent to running the veryquick tests and | | | 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | TODO: ./configure + Makefile.msc build systems. <a name=commands_to_run_tests></a> ## 3.1. Commands to Run SQLite Tests The **mdevtest** command is equivalent to running the veryquick tests and the [make fuzztest] target once for each of two --enable-all builds - one with debugging enabled and one without: ``` tclsh $TESTDIR/testrunner.tcl mdevtest ``` In other words, it is equivalent to running: |
︙ | ︙ | |||
284 285 286 287 288 289 290 | tclsh $TESTDIR/testrunner.tcl script Device-One > make.sh # Create a script that recreates build configuration "Have-Not" on Windows: tclsh $TESTDIR/testrunner.tcl script Have-Not > make.bat ``` The generated bash or \*.bat file script accepts a single argument - a makefile | | | 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 | tclsh $TESTDIR/testrunner.tcl script Device-One > make.sh # Create a script that recreates build configuration "Have-Not" on Windows: tclsh $TESTDIR/testrunner.tcl script Have-Not > make.bat ``` The generated bash or \*.bat file script accepts a single argument - a makefile target to build. This may be used either to run a [make] command test directly, or else to build a testfixture (or testfixture.exe) binary with which to run a Tcl test script, as <a href=#binary_test_failures>described above</a>. <a name=testrunner_options></a> # 4. Extra testrunner.tcl Options The testrunner.tcl script options in this section may be used with both source |
︙ | ︙ | |||
311 312 313 314 315 316 317 | would normally execute into the testrunner.log file. Example: ``` # Log the shell commmands that make up the mdevtest test. tclsh $TESTDIR/testrunner.tcl --dryrun mdevtest" ``` | < < < < < < < < < < | 306 307 308 309 310 311 312 313 314 315 316 317 318 319 | would normally execute into the testrunner.log file. Example: ``` # Log the shell commmands that make up the mdevtest test. tclsh $TESTDIR/testrunner.tcl --dryrun mdevtest" ``` <a name=cpu_cores></a> # 5. Controlling CPU Core Utilization When running either binary or source code tests, testrunner.tcl reports the number of jobs it intends to use to stdout. e.g. ``` |
︙ | ︙ | |||
350 351 352 353 354 355 356 | The number of jobs may also be changed while an instance of testrunner.tcl is running by exucuting the following command from the directory containing the testrunner.log and testrunner.db files: ``` $ ./testfixture $TESTDIR/testrunner.tcl njob $NEW_NUMBER_OF_JOBS ``` | > > > | 335 336 337 338 339 340 341 342 343 344 | The number of jobs may also be changed while an instance of testrunner.tcl is running by exucuting the following command from the directory containing the testrunner.log and testrunner.db files: ``` $ ./testfixture $TESTDIR/testrunner.tcl njob $NEW_NUMBER_OF_JOBS ``` |
Changes to ext/expert/expert1.test.
1 2 3 4 5 6 7 8 9 10 | # 2009 Nov 11 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** | < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # 2009 Nov 11 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # The focus of this file is testing the CLI shell tool. Specifically, # the ".recommend" command. # # # Test plan: |
︙ | ︙ |
Changes to ext/expert/sqlite3expert.c.
︙ | ︙ | |||
1944 1945 1946 1947 1948 1949 1950 | #endif /* Copy the entire schema of database [db] into [dbm]. */ if( rc==SQLITE_OK ){ sqlite3_stmt *pSql = 0; rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg, "SELECT sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'" | | | 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 | #endif /* Copy the entire schema of database [db] into [dbm]. */ if( rc==SQLITE_OK ){ sqlite3_stmt *pSql = 0; rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg, "SELECT sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'" " AND sql NOT LIKE 'CREATE VIRTUAL %%'" ); while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ const char *zSql = (const char*)sqlite3_column_text(pSql, 0); if( zSql ) rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg); } idxFinalize(&rc, pSql); } |
︙ | ︙ |
Changes to ext/fts3/fts3_snippet.c.
︙ | ︙ | |||
442 443 444 445 446 447 448 | if( (mCover|mCovered)&mPhrase ){ iScore++; }else{ iScore += 1000; } mCover |= mPhrase; | | | 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 | if( (mCover|mCovered)&mPhrase ){ iScore++; }else{ iScore += 1000; } mCover |= mPhrase; for(j=0; j<pPhrase->nToken; j++){ mHighlight |= (mPos>>j); } if( 0==(*pCsr & 0x0FE) ) break; fts3GetDeltaPosition(&pCsr, &iCsr); } } |
︙ | ︙ |
Changes to ext/fts5/fts5.h.
︙ | ︙ | |||
51 52 53 54 55 56 57 | const unsigned char *b; }; /* ** EXTENSION API FUNCTIONS ** ** xUserData(pFts): | | | | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | const unsigned char *b; }; /* ** EXTENSION API FUNCTIONS ** ** xUserData(pFts): ** Return a copy of the context pointer the extension function was ** registered with. ** ** xColumnTotalSize(pFts, iCol, pnToken): ** If parameter iCol is less than zero, set output variable *pnToken ** to the total number of tokens in the FTS5 table. Or, if iCol is ** non-negative but less than the number of columns in the table, return ** the total number of tokens in column iCol, considering all rows in ** the FTS5 table. |
︙ | ︙ |
Changes to ext/fts5/fts5_main.c.
︙ | ︙ | |||
1696 1697 1698 1699 1700 1701 1702 | if( pConfig->bContentlessDelete ){ fts5SetVtabError(pTab, "'delete' may not be used with a contentless_delete=1 table" ); rc = SQLITE_ERROR; }else{ rc = fts5SpecialDelete(pTab, apVal); | < | 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 | if( pConfig->bContentlessDelete ){ fts5SetVtabError(pTab, "'delete' may not be used with a contentless_delete=1 table" ); rc = SQLITE_ERROR; }else{ rc = fts5SpecialDelete(pTab, apVal); } }else{ rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]); } }else{ /* A regular INSERT, UPDATE or DELETE statement. The trick here is that ** any conflict on the rowid value must be detected before any |
︙ | ︙ |
Changes to ext/fts5/test/fts5secure8.test.
︙ | ︙ | |||
38 39 40 41 42 43 44 | DELETE FROM ft WHERE rowid=100; } do_execsql_test 1.2 { PRAGMA integrity_check; } {ok} | < < < < < < < < < < < < < < < < | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | DELETE FROM ft WHERE rowid=100; } do_execsql_test 1.2 { PRAGMA integrity_check; } {ok} finish_test |
Changes to ext/icu/icu.c.
︙ | ︙ | |||
467 468 469 470 471 472 473 | sqlite3 *db = (sqlite3 *)sqlite3_user_data(p); UErrorCode status = U_ZERO_ERROR; const char *zLocale; /* Locale identifier - (eg. "jp_JP") */ const char *zName; /* SQL Collation sequence name (eg. "japanese") */ UCollator *pUCollator; /* ICU library collation object */ int rc; /* Return code from sqlite3_create_collation_x() */ | | < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < | 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 | sqlite3 *db = (sqlite3 *)sqlite3_user_data(p); UErrorCode status = U_ZERO_ERROR; const char *zLocale; /* Locale identifier - (eg. "jp_JP") */ const char *zName; /* SQL Collation sequence name (eg. "japanese") */ UCollator *pUCollator; /* ICU library collation object */ int rc; /* Return code from sqlite3_create_collation_x() */ assert(nArg==2); (void)nArg; /* Unused parameter */ zLocale = (const char *)sqlite3_value_text(apArg[0]); zName = (const char *)sqlite3_value_text(apArg[1]); if( !zLocale || !zName ){ return; } pUCollator = ucol_open(zLocale, &status); if( !U_SUCCESS(status) ){ icuFunctionError(p, "ucol_open", status); return; } assert(p); rc = sqlite3_create_collation_v2(db, zName, SQLITE_UTF16, (void *)pUCollator, icuCollationColl, icuCollationDel ); if( rc!=SQLITE_OK ){ ucol_close(pUCollator); sqlite3_result_error(p, "Error registering collation function", -1); } |
︙ | ︙ | |||
537 538 539 540 541 542 543 | const char *zName; /* Function name */ unsigned char nArg; /* Number of arguments */ unsigned int enc; /* Optimal text encoding */ unsigned char iContext; /* sqlite3_user_data() context */ void (*xFunc)(sqlite3_context*,int,sqlite3_value**); } scalars[] = { {"icu_load_collation",2,SQLITE_UTF8|SQLITE_DIRECTONLY,1, icuLoadCollation}, | < | 505 506 507 508 509 510 511 512 513 514 515 516 517 518 | const char *zName; /* Function name */ unsigned char nArg; /* Number of arguments */ unsigned int enc; /* Optimal text encoding */ unsigned char iContext; /* sqlite3_user_data() context */ void (*xFunc)(sqlite3_context*,int,sqlite3_value**); } scalars[] = { {"icu_load_collation",2,SQLITE_UTF8|SQLITE_DIRECTONLY,1, icuLoadCollation}, #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) {"regexp", 2, SQLITE_ANY|SQLITEICU_EXTRAFLAGS, 0, icuRegexpFunc}, {"lower", 1, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 0, icuCaseFunc16}, {"lower", 2, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 0, icuCaseFunc16}, {"upper", 1, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 1, icuCaseFunc16}, {"upper", 2, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 1, icuCaseFunc16}, {"lower", 1, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS, 0, icuCaseFunc16}, |
︙ | ︙ |
Changes to ext/intck/intck1.test.
︙ | ︙ | |||
11 12 13 14 15 16 17 | # # The focus of this file is testing the incremental integrity check # (intck) extension. # source [file join [file dirname [info script]] intck_common.tcl] set testprefix intck1 | < | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | # # The focus of this file is testing the incremental integrity check # (intck) extension. # source [file join [file dirname [info script]] intck_common.tcl] set testprefix intck1 foreach {tn sql} { 1 "CREATE TABLE t1(a PRIMARY KEY, b)" 2 "CREATE TABLE t2(a PRIMARY KEY, b) WITHOUT ROWID " 3 "CREATE TABLE t3(a PRIMARY KEY, b) WITHOUT rowID;" 4 "CREATE TABLE t4(a PRIMARY KEY, ROWID)" 5 {CREATE TABLE t5(a PRIMARY KEY, ROWID) WITHOUT ROWID |
︙ | ︙ |
Changes to ext/intck/intck2.test.
︙ | ︙ | |||
11 12 13 14 15 16 17 | # # The focus of this file is testing the incremental integrity check # (intck) extension. # source [file join [file dirname [info script]] intck_common.tcl] set testprefix intck2 | < | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | # # The focus of this file is testing the incremental integrity check # (intck) extension. # source [file join [file dirname [info script]] intck_common.tcl] set testprefix intck2 do_execsql_test 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'); |
︙ | ︙ |
Changes to ext/intck/intck_common.tcl.
︙ | ︙ | |||
11 12 13 14 15 16 17 | # if {![info exists testdir]} { set testdir [file join [file dirname [info script]] .. .. test] } source $testdir/tester.tcl | < < < < < < < < < < | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | # if {![info exists testdir]} { set testdir [file join [file dirname [info script]] .. .. test] } source $testdir/tester.tcl proc do_intck {db {bSuspend 0}} { set ic [sqlite3_intck $db main] set ret [list] while {"SQLITE_OK"==[$ic step]} { set msg [$ic message] if {$msg!=""} { |
︙ | ︙ |
Changes to ext/intck/intckbusy.test.
︙ | ︙ | |||
8 9 10 11 12 13 14 | # May you share freely, never taking more than you give. # #*********************************************************************** # source [file join [file dirname [info script]] intck_common.tcl] set testprefix intckbusy | < | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # May you share freely, never taking more than you give. # #*********************************************************************** # source [file join [file dirname [info script]] intck_common.tcl] set testprefix intckbusy do_execsql_test 1.0 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); INSERT INTO t1 VALUES(1, 2, 3); INSERT INTO t1 VALUES(2, 'two', 'three'); |
︙ | ︙ |
Changes to ext/intck/intckcorrupt.test.
︙ | ︙ | |||
11 12 13 14 15 16 17 | # # The focus of this file is testing the intck extensions response # to corruption at the b-tree level. # source [file join [file dirname [info script]] intck_common.tcl] set testprefix intckcorrupt | < | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | # # The focus of this file is testing the intck extensions response # to corruption at the b-tree level. # source [file join [file dirname [info script]] intck_common.tcl] set testprefix intckcorrupt #------------------------------------------------------------------------- reset_db do_test 1.0 { sqlite3 db {} db deserialize [decode_hexdb { | size 356352 pagesize 4096 filename crash-acaae0347204ae.db |
︙ | ︙ |
Changes to ext/intck/intckfault.test.
︙ | ︙ | |||
8 9 10 11 12 13 14 | # May you share freely, never taking more than you give. # #*********************************************************************** # source [file join [file dirname [info script]] intck_common.tcl] set testprefix intckfault | | > | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # May you share freely, never taking more than you give. # #*********************************************************************** # source [file join [file dirname [info script]] intck_common.tcl] set testprefix intckfault do_execsql_test 1.0 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); INSERT INTO t1 VALUES(1, 2, 3); INSERT INTO t1 VALUES(2, 'two', 'three'); INSERT INTO t1 VALUES(3, NULL, NULL); CREATE INDEX i1 ON t1(b, c); |
︙ | ︙ | |||
31 32 33 34 35 36 37 38 39 40 41 42 | if {$nStep==3} { $::ic unlock } } set res [$::ic error] $::ic close set res } -test { catch { $::ic close } faultsim_test_result {0 {SQLITE_OK {}}} {0 {SQLITE_NOMEM {}}} {0 {SQLITE_NOMEM {out of memory}}} } finish_test | > > | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | if {$nStep==3} { $::ic unlock } } set res [$::ic error] $::ic close set res } -test { catch { $::ic close } puts $testresult puts $testnfail faultsim_test_result {0 {SQLITE_OK {}}} {0 {SQLITE_NOMEM {}}} {0 {SQLITE_NOMEM {out of memory}}} } finish_test |
Changes to ext/intck/test_intck.c.
︙ | ︙ | |||
75 76 77 78 79 80 81 | switch( iIdx ){ case 0: assert( 0==strcmp("close", aCmd[iIdx].zName) ); { Tcl_DeleteCommand(interp, Tcl_GetStringFromObj(objv[0], 0)); break; } case 1: assert( 0==strcmp("step", aCmd[iIdx].zName) ); { | | | | | 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 | switch( iIdx ){ case 0: assert( 0==strcmp("close", aCmd[iIdx].zName) ); { Tcl_DeleteCommand(interp, Tcl_GetStringFromObj(objv[0], 0)); break; } case 1: assert( 0==strcmp("step", aCmd[iIdx].zName) ); { int rc = sqlite3_intck_step(p->intck); Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); break; } case 2: assert( 0==strcmp("message", aCmd[iIdx].zName) ); { const char *z = sqlite3_intck_message(p->intck); Tcl_SetObjResult(interp, Tcl_NewStringObj(z ? z : "", -1)); break; } case 3: assert( 0==strcmp("error", aCmd[iIdx].zName) ); { const char *zErr = 0; int rc = sqlite3_intck_error(p->intck, 0); Tcl_Obj *pRes = Tcl_NewObj(); Tcl_ListObjAppendElement( interp, pRes, Tcl_NewStringObj(sqlite3ErrName(rc), -1) ); sqlite3_intck_error(p->intck, &zErr); Tcl_ListObjAppendElement( interp, pRes, Tcl_NewStringObj(zErr ? zErr : 0, -1) ); Tcl_SetObjResult(interp, pRes); break; } case 4: assert( 0==strcmp("unlock", aCmd[iIdx].zName) ); { int rc = sqlite3_intck_unlock(p->intck); Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); break; } case 5: assert( 0==strcmp("test_sql", aCmd[iIdx].zName) ); { const char *zObj = Tcl_GetString(objv[2]); const char *zSql = sqlite3_intck_test_sql(p->intck, zObj[0] ? zObj : 0); |
︙ | ︙ |
Changes to ext/misc/cksumvfs.c.
︙ | ︙ | |||
442 443 444 445 446 447 448 | } /* Verify the checksum if ** (1) the size indicates that we are dealing with a complete ** database page ** (2) checksum verification is enabled ** (3) we are not in the middle of checkpoint */ | | | | | 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 | } /* Verify the checksum if ** (1) the size indicates that we are dealing with a complete ** database page ** (2) checksum verification is enabled ** (3) we are not in the middle of checkpoint */ if( iAmt>=512 /* (1) */ && p->verifyCksm /* (2) */ && !p->inCkpt /* (3) */ ){ u8 cksum[8]; cksmCompute((u8*)zBuf, iAmt-8, cksum); if( memcmp((u8*)zBuf+iAmt-8, cksum, 8)!=0 ){ sqlite3_log(SQLITE_IOERR_DATA, "checksum fault offset %lld of \"%s\"", iOfst, p->zFName); |
︙ | ︙ |
Changes to ext/misc/fileio.c.
︙ | ︙ | |||
368 369 370 371 372 373 374 | mode_t mode, /* MODE parameter passed to writefile() */ sqlite3_int64 mtime /* MTIME parameter (or -1 to not set time) */ ){ if( zFile==0 ) return 1; #if !defined(_WIN32) && !defined(WIN32) if( S_ISLNK(mode) ){ const char *zTo = (const char*)sqlite3_value_text(pData); | < < | | 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 | mode_t mode, /* MODE parameter passed to writefile() */ sqlite3_int64 mtime /* MTIME parameter (or -1 to not set time) */ ){ if( zFile==0 ) return 1; #if !defined(_WIN32) && !defined(WIN32) if( S_ISLNK(mode) ){ const char *zTo = (const char*)sqlite3_value_text(pData); if( zTo==0 || symlink(zTo, zFile)<0 ) return 1; }else #endif { if( S_ISDIR(mode) ){ if( mkdir(zFile, mode) ){ /* The mkdir() call to create the directory failed. This might not ** be an error though - if there is already a directory at the same |
︙ | ︙ | |||
456 457 458 459 460 461 462 | times[0].tv_nsec = times[1].tv_nsec = 0; times[0].tv_sec = time(0); times[1].tv_sec = mtime; if( utimensat(AT_FDCWD, zFile, times, AT_SYMLINK_NOFOLLOW) ){ return 1; } #else | | < < < < < | | | | | | < | 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 | times[0].tv_nsec = times[1].tv_nsec = 0; times[0].tv_sec = time(0); times[1].tv_sec = mtime; if( utimensat(AT_FDCWD, zFile, times, AT_SYMLINK_NOFOLLOW) ){ return 1; } #else /* Legacy unix */ struct timeval times[2]; times[0].tv_usec = times[1].tv_usec = 0; times[0].tv_sec = time(0); times[1].tv_sec = mtime; if( utimes(zFile, times) ){ return 1; } #endif } return 0; } |
︙ | ︙ |
Changes to ext/misc/series.c.
︙ | ︙ | |||
372 373 374 375 376 377 378 | ** once prior to any call to seriesColumn() or seriesRowid() or ** seriesEof(). ** ** The query plan selected by seriesBestIndex is passed in the idxNum ** parameter. (idxStr is not used in this implementation.) idxNum ** is a bitmask showing which constraints are available: ** | | | | > > | | < < | | | | < < < < < < < < < < < < < < < < < < | | | | | < < < < < | | < < < < < < < < < < < < < < < < < < | < < | < < < < < | | < | | | < < < | 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 | ** once prior to any call to seriesColumn() or seriesRowid() or ** seriesEof(). ** ** The query plan selected by seriesBestIndex is passed in the idxNum ** parameter. (idxStr is not used in this implementation.) idxNum ** is a bitmask showing which constraints are available: ** ** 1: start=VALUE ** 2: stop=VALUE ** 4: step=VALUE ** ** Also, if bit 8 is set, that means that the series should be output ** in descending order rather than in ascending order. If bit 16 is ** set, then output must appear in ascending order. ** ** This routine should initialize the cursor and position it so that it ** is pointing at the first row, or pointing off the end of the table ** (so that seriesEof() will return true) if the table is empty. */ static int seriesFilter( sqlite3_vtab_cursor *pVtabCursor, int idxNum, const char *idxStrUnused, int argc, sqlite3_value **argv ){ series_cursor *pCur = (series_cursor *)pVtabCursor; int i = 0; (void)idxStrUnused; if( idxNum & 1 ){ pCur->ss.iBase = sqlite3_value_int64(argv[i++]); }else{ pCur->ss.iBase = 0; } if( idxNum & 2 ){ pCur->ss.iTerm = sqlite3_value_int64(argv[i++]); }else{ pCur->ss.iTerm = 0xffffffff; } if( idxNum & 4 ){ pCur->ss.iStep = sqlite3_value_int64(argv[i++]); if( pCur->ss.iStep==0 ){ pCur->ss.iStep = 1; }else if( pCur->ss.iStep<0 ){ if( (idxNum & 16)==0 ) idxNum |= 8; } }else{ pCur->ss.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->ss.iBase = 1; pCur->ss.iTerm = 0; pCur->ss.iStep = 1; break; } } if( idxNum & 8 ){ pCur->ss.isReversing = pCur->ss.iStep > 0; }else{ pCur->ss.isReversing = pCur->ss.iStep < 0; } setupSequence( &pCur->ss ); return SQLITE_OK; } /* ** SQLite will invoke this method one or more times while planning a query ** that uses the generate_series virtual table. This routine needs to create ** a query plan for each invocation and compute an estimated cost for that ** plan. ** ** In this implementation idxNum is used to represent the ** query plan. idxStr is unused. ** ** The query plan is represented by bits in idxNum: ** ** (1) start = $value -- constraint exists ** (2) stop = $value -- constraint exists ** (4) step = $value -- constraint exists ** (8) output in descending order */ static int seriesBestIndex( sqlite3_vtab *pVTab, sqlite3_index_info *pIdxInfo ){ int i, j; /* Loop over constraints */ int idxNum = 0; /* The query plan bitmask */ int bStartSeen = 0; /* EQ constraint seen on the START column */ int unusableMask = 0; /* Mask of unusable constraints */ int nArg = 0; /* Number of arguments that seriesFilter() expects */ int aIdx[3]; /* Constraints on start, stop, and step */ const struct sqlite3_index_constraint *pConstraint; /* This implementation assumes that the start, stop, and step columns ** are the last three columns in the virtual table. */ assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 ); assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 ); aIdx[0] = aIdx[1] = aIdx[2] = -1; pConstraint = pIdxInfo->aConstraint; for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ int iCol; /* 0 for start, 1 for stop, 2 for step */ int iMask; /* bitmask for those column */ if( pConstraint->iColumn<SERIES_COLUMN_START ) continue; iCol = pConstraint->iColumn - SERIES_COLUMN_START; assert( iCol>=0 && iCol<=2 ); iMask = 1 << iCol; if( iCol==0 ) bStartSeen = 1; if( pConstraint->usable==0 ){ unusableMask |= iMask; continue; }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ idxNum |= iMask; aIdx[iCol] = i; } } for(i=0; i<3; i++){ if( (j = aIdx[i])>=0 ){ pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg; pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY; } } /* The current generate_column() implementation requires at least one ** argument (the START value). Legacy versions assumed START=0 if the ** first argument was omitted. Compile with -DZERO_ARGUMENT_GENERATE_SERIES ** to obtain the legacy behavior */ #ifndef ZERO_ARGUMENT_GENERATE_SERIES if( !bStartSeen ){ sqlite3_free(pVTab->zErrMsg); pVTab->zErrMsg = sqlite3_mprintf( "first argument to \"generate_series()\" missing or unusable"); return SQLITE_ERROR; } #endif if( (unusableMask & ~idxNum)!=0 ){ /* The start, stop, and step columns are inputs. Therefore if there ** are unusable constraints on any of start, stop, or step then ** this plan is unusable */ return SQLITE_CONSTRAINT; } if( (idxNum & 3)==3 ){ /* Both start= and stop= boundaries are available. This is the ** the preferred case */ pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0)); pIdxInfo->estimatedRows = 1000; if( pIdxInfo->nOrderBy>=1 && pIdxInfo->aOrderBy[0].iColumn==0 ){ if( pIdxInfo->aOrderBy[0].desc ){ idxNum |= 8; }else{ idxNum |= 16; } pIdxInfo->orderByConsumed = 1; } }else{ /* If either boundary is missing, we have to generate a huge span ** of numbers. Make this case very expensive so that the query ** planner will work hard to avoid it. */ pIdxInfo->estimatedRows = 2147483647; } pIdxInfo->idxNum = idxNum; |
︙ | ︙ |
Changes to ext/misc/sqlar.c.
︙ | ︙ | |||
77 78 79 80 81 82 83 | */ static void sqlarUncompressFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ uLong nData; | | < | | | 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 | */ static void sqlarUncompressFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ uLong nData; uLongf sz; assert( argc==2 ); sz = sqlite3_value_int(argv[1]); if( sz<=0 || sz==(nData = sqlite3_value_bytes(argv[0])) ){ sqlite3_result_value(context, argv[0]); }else{ const Bytef *pData= sqlite3_value_blob(argv[0]); Bytef *pOut = sqlite3_malloc(sz); if( pOut==0 ){ sqlite3_result_error_nomem(context); }else if( Z_OK!=uncompress(pOut, &sz, pData, nData) ){ sqlite3_result_error(context, "error in uncompress()", -1); }else{ sqlite3_result_blob(context, pOut, sz, SQLITE_TRANSIENT); } sqlite3_free(pOut); } } #ifdef _WIN32 __declspec(dllexport) |
︙ | ︙ |
Changes to ext/misc/vtablog.c.
︙ | ︙ | |||
34 35 36 37 38 39 40 | /* vtablog_vtab is a subclass of sqlite3_vtab which will ** serve as the underlying representation of a vtablog virtual table */ typedef struct vtablog_vtab vtablog_vtab; struct vtablog_vtab { sqlite3_vtab base; /* Base class - must be first */ | < < > | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | /* vtablog_vtab is a subclass of sqlite3_vtab which will ** serve as the underlying representation of a vtablog virtual table */ typedef struct vtablog_vtab vtablog_vtab; struct vtablog_vtab { sqlite3_vtab base; /* Base class - must be first */ int nRow; /* Number of rows in the table */ int iInst; /* Instance number for this vtablog table */ int nCursor; /* Number of cursors created */ }; /* vtablog_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 */ |
︙ | ︙ | |||
164 165 166 167 168 169 170 171 172 173 174 175 176 | sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVtab, char **pzErr, int isCreate ){ vtablog_vtab *pNew; int i; int rc; char *zSchema = 0; char *zNRow = 0; | > > < | | < | < > | > < | < < < < < < | 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 | sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVtab, char **pzErr, int isCreate ){ static int nInst = 0; vtablog_vtab *pNew; int i; int rc; int iInst = ++nInst; char *zSchema = 0; char *zNRow = 0; printf("vtablog%s(tab=%d):\n", isCreate ? "Create" : "Connect", iInst); printf(" argc=%d\n", argc); for(i=0; i<argc; i++){ printf(" argv[%d] = ", i); if( argv[i] ){ printf("[%s]\n", argv[i]); }else{ printf("NULL\n"); } } for(i=3; i<argc; i++){ const char *z = argv[i]; if( vtablog_string_parameter(pzErr, "schema", z, &zSchema) ){ return SQLITE_ERROR; } if( vtablog_string_parameter(pzErr, "rows", z, &zNRow) ){ return SQLITE_ERROR; } } if( zSchema==0 ){ *pzErr = sqlite3_mprintf("no schema defined"); return SQLITE_ERROR; } rc = sqlite3_declare_vtab(db, zSchema); if( rc==SQLITE_OK ){ pNew = sqlite3_malloc( sizeof(*pNew) ); *ppVtab = (sqlite3_vtab*)pNew; if( pNew==0 ) return SQLITE_NOMEM; memset(pNew, 0, sizeof(*pNew)); pNew->nRow = 10; if( zNRow ) pNew->nRow = atoi(zNRow); pNew->iInst = iInst; } return rc; } static int vtablogCreate( sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVtab, |
︙ | ︙ | |||
240 241 242 243 244 245 246 | /* ** This method is the destructor for vtablog_cursor objects. */ static int vtablogDisconnect(sqlite3_vtab *pVtab){ vtablog_vtab *pTab = (vtablog_vtab*)pVtab; | | < < | < < < | | | < | | 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 | /* ** This method is the destructor for vtablog_cursor objects. */ static int vtablogDisconnect(sqlite3_vtab *pVtab){ vtablog_vtab *pTab = (vtablog_vtab*)pVtab; printf("vtablogDisconnect(%d)\n", pTab->iInst); sqlite3_free(pVtab); return SQLITE_OK; } /* ** This method is the destructor for vtablog_cursor objects. */ static int vtablogDestroy(sqlite3_vtab *pVtab){ vtablog_vtab *pTab = (vtablog_vtab*)pVtab; printf("vtablogDestroy(%d)\n", pTab->iInst); sqlite3_free(pVtab); return SQLITE_OK; } /* ** Constructor for a new vtablog_cursor object. */ static int vtablogOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ vtablog_vtab *pTab = (vtablog_vtab*)p; vtablog_cursor *pCur; printf("vtablogOpen(tab=%d, cursor=%d)\n", pTab->iInst, ++pTab->nCursor); pCur = sqlite3_malloc( sizeof(*pCur) ); if( pCur==0 ) return SQLITE_NOMEM; memset(pCur, 0, sizeof(*pCur)); pCur->iCursor = pTab->nCursor; *ppCursor = &pCur->base; return SQLITE_OK; } /* ** Destructor for a vtablog_cursor. */ static int vtablogClose(sqlite3_vtab_cursor *cur){ vtablog_cursor *pCur = (vtablog_cursor*)cur; vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab; printf("vtablogClose(tab=%d, cursor=%d)\n", pTab->iInst, pCur->iCursor); sqlite3_free(cur); return SQLITE_OK; } /* ** Advance a vtablog_cursor to its next row of output. */ static int vtablogNext(sqlite3_vtab_cursor *cur){ vtablog_cursor *pCur = (vtablog_cursor*)cur; vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab; printf("vtablogNext(tab=%d, cursor=%d) rowid %d -> %d\n", pTab->iInst, pCur->iCursor, (int)pCur->iRowid, (int)pCur->iRowid+1); pCur->iRowid++; return SQLITE_OK; } /* ** Return values of columns for the row at which the vtablog_cursor ** is currently pointing. |
︙ | ︙ | |||
319 320 321 322 323 324 325 | if( i<26 ){ sqlite3_snprintf(sizeof(zVal),zVal,"%c%d", "abcdefghijklmnopqrstuvwyz"[i], pCur->iRowid); }else{ sqlite3_snprintf(sizeof(zVal),zVal,"{%d}%d", i, pCur->iRowid); } | | | | | | | | 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 | if( i<26 ){ sqlite3_snprintf(sizeof(zVal),zVal,"%c%d", "abcdefghijklmnopqrstuvwyz"[i], pCur->iRowid); }else{ sqlite3_snprintf(sizeof(zVal),zVal,"{%d}%d", i, pCur->iRowid); } printf("vtablogColumn(tab=%d, cursor=%d, i=%d): [%s]\n", pTab->iInst, pCur->iCursor, i, zVal); sqlite3_result_text(ctx, zVal, -1, SQLITE_TRANSIENT); return SQLITE_OK; } /* ** Return the rowid for the current row. In this implementation, the ** rowid is the same as the output value. */ static int vtablogRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ vtablog_cursor *pCur = (vtablog_cursor*)cur; vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab; printf("vtablogRowid(tab=%d, cursor=%d): %d\n", pTab->iInst, pCur->iCursor, (int)pCur->iRowid); *pRowid = pCur->iRowid; return SQLITE_OK; } /* ** Return TRUE if the cursor has been moved off of the last ** row of output. */ static int vtablogEof(sqlite3_vtab_cursor *cur){ vtablog_cursor *pCur = (vtablog_cursor*)cur; vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab; int rc = pCur->iRowid >= pTab->nRow; printf("vtablogEof(tab=%d, cursor=%d): %d\n", pTab->iInst, pCur->iCursor, rc); return rc; } /* ** Output an sqlite3_value object's value as an SQL literal. */ static void vtablogQuote(sqlite3_value *p){ |
︙ | ︙ | |||
426 427 428 429 430 431 432 | static int vtablogFilter( sqlite3_vtab_cursor *cur, int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ vtablog_cursor *pCur = (vtablog_cursor *)cur; vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab; | | | < < < < < | < < < < < < < < < < < < < < < | | < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | | | | | | | | | | 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 | static int vtablogFilter( sqlite3_vtab_cursor *cur, int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ vtablog_cursor *pCur = (vtablog_cursor *)cur; vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab; printf("vtablogFilter(tab=%d, cursor=%d):\n", pTab->iInst, pCur->iCursor); pCur->iRowid = 0; return SQLITE_OK; } /* ** SQLite will invoke this method one or more times while planning a query ** that uses the vtablog virtual table. This routine needs to create ** a query plan for each invocation and compute an estimated cost for that ** plan. */ static int vtablogBestIndex( sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo ){ vtablog_vtab *pTab = (vtablog_vtab*)tab; printf("vtablogBestIndex(tab=%d):\n", pTab->iInst); pIdxInfo->estimatedCost = (double)500; pIdxInfo->estimatedRows = 500; return SQLITE_OK; } /* ** SQLite invokes this method to INSERT, UPDATE, or DELETE content from ** the table. ** ** This implementation does not actually make any changes to the table ** content. It merely logs the fact that the method was invoked */ static int vtablogUpdate( sqlite3_vtab *tab, int argc, sqlite3_value **argv, sqlite_int64 *pRowid ){ vtablog_vtab *pTab = (vtablog_vtab*)tab; int i; printf("vtablogUpdate(tab=%d):\n", pTab->iInst); printf(" argc=%d\n", argc); for(i=0; i<argc; i++){ printf(" argv[%d]=", i); vtablogQuote(argv[i]); printf("\n"); } return SQLITE_OK; } /* ** This following structure defines all the methods for the ** vtablog virtual table. */ static sqlite3_module vtablogModule = { 0, /* iVersion */ vtablogCreate, /* xCreate */ vtablogConnect, /* xConnect */ vtablogBestIndex, /* xBestIndex */ vtablogDisconnect, /* xDisconnect */ vtablogDestroy, /* xDestroy */ vtablogOpen, /* xOpen - open a cursor */ vtablogClose, /* xClose - close a cursor */ vtablogFilter, /* xFilter - configure scan constraints */ vtablogNext, /* xNext - advance a cursor */ vtablogEof, /* xEof - check for end of scan */ vtablogColumn, /* xColumn - read data */ vtablogRowid, /* xRowid - read data */ vtablogUpdate, /* xUpdate */ 0, /* xBegin */ 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0, /* xShadowName */ 0 /* xIntegrity */ }; #ifdef _WIN32 __declspec(dllexport) #endif int sqlite3_vtablog_init( sqlite3 *db, |
︙ | ︙ |
Changes to ext/rbu/sqlite3rbu.c.
︙ | ︙ | |||
195 196 197 198 199 200 201 | typedef struct RbuUpdateStmt RbuUpdateStmt; #if !defined(SQLITE_AMALGAMATION) typedef unsigned int u32; typedef unsigned short u16; typedef unsigned char u8; typedef sqlite3_int64 i64; | < | 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | typedef struct RbuUpdateStmt RbuUpdateStmt; #if !defined(SQLITE_AMALGAMATION) typedef unsigned int u32; typedef unsigned short u16; typedef unsigned char u8; typedef sqlite3_int64 i64; #endif /* ** These values must match the values defined in wal.c for the equivalent ** locks. These are not magic numbers as they are part of the SQLite file ** format. */ |
︙ | ︙ | |||
882 883 884 885 886 887 888 | if( pIter->bCleanup ){ rbuObjIterFreeCols(pIter); pIter->bCleanup = 0; rc = sqlite3_step(pIter->pTblIter); if( rc!=SQLITE_ROW ){ rc = resetAndCollectError(pIter->pTblIter, &p->zErrmsg); pIter->zTbl = 0; | < | 881 882 883 884 885 886 887 888 889 890 891 892 893 894 | if( pIter->bCleanup ){ rbuObjIterFreeCols(pIter); pIter->bCleanup = 0; rc = sqlite3_step(pIter->pTblIter); if( rc!=SQLITE_ROW ){ rc = resetAndCollectError(pIter->pTblIter, &p->zErrmsg); pIter->zTbl = 0; }else{ pIter->zTbl = (const char*)sqlite3_column_text(pIter->pTblIter, 0); pIter->zDataTbl = (const char*)sqlite3_column_text(pIter->pTblIter,1); rc = (pIter->zDataTbl && pIter->zTbl) ? SQLITE_OK : SQLITE_NOMEM; } }else{ if( pIter->zIdx==0 ){ |
︙ | ︙ | |||
2977 2978 2979 2980 2981 2982 2983 | static i64 rbuShmChecksum(sqlite3rbu *p){ i64 iRet = 0; if( p->rc==SQLITE_OK ){ sqlite3_file *pDb = p->pTargetFd->pReal; u32 volatile *ptr; p->rc = pDb->pMethods->xShmMap(pDb, 0, 32*1024, 0, (void volatile**)&ptr); if( p->rc==SQLITE_OK ){ | | | 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 | static i64 rbuShmChecksum(sqlite3rbu *p){ i64 iRet = 0; if( p->rc==SQLITE_OK ){ sqlite3_file *pDb = p->pTargetFd->pReal; u32 volatile *ptr; p->rc = pDb->pMethods->xShmMap(pDb, 0, 32*1024, 0, (void volatile**)&ptr); if( p->rc==SQLITE_OK ){ iRet = ((i64)ptr[10] << 32) + ptr[11]; } } return iRet; } /* ** This function is called as part of initializing or reinitializing an |
︙ | ︙ |
Changes to ext/recover/dbdata.c.
︙ | ︙ | |||
84 85 86 87 88 89 90 | #ifndef SQLITE_OMIT_VIRTUALTABLE #define DBDATA_PADDING_BYTES 100 typedef struct DbdataTable DbdataTable; typedef struct DbdataCursor DbdataCursor; | < < < < < < < < < | | 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 | #ifndef SQLITE_OMIT_VIRTUALTABLE #define DBDATA_PADDING_BYTES 100 typedef struct DbdataTable DbdataTable; typedef struct DbdataCursor DbdataCursor; /* Cursor object */ struct DbdataCursor { sqlite3_vtab_cursor base; /* Base class. Must be first */ sqlite3_stmt *pStmt; /* For fetching database pages */ int iPgno; /* Current page number */ u8 *aPage; /* Buffer containing page */ int nPage; /* Size of aPage[] in bytes */ int nCell; /* Number of cells on aPage[] */ int iCell; /* Current cell number */ int bOnePage; /* True to stop after one page */ int szDb; sqlite3_int64 iRowid; /* Only for the sqlite_dbdata table */ u8 *pRec; /* Buffer containing current record */ sqlite3_int64 nRec; /* Size of pRec[] in bytes */ sqlite3_int64 nHdr; /* Size of header in bytes */ int iField; /* Current field number */ u8 *pHdrPtr; u8 *pPtr; u32 enc; /* Text encoding */ |
︙ | ︙ | |||
154 155 156 157 158 159 160 | #define DBPTR_SCHEMA \ "CREATE TABLE x(" \ " pgno INTEGER," \ " child INTEGER," \ " schema TEXT HIDDEN" \ ")" | < < < < < < < < < < < < < < < < < < < < < < < < < | 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | #define DBPTR_SCHEMA \ "CREATE TABLE x(" \ " pgno INTEGER," \ " child INTEGER," \ " schema TEXT HIDDEN" \ ")" /* ** Connect to an sqlite_dbdata (pAux==0) or sqlite_dbptr (pAux!=0) virtual ** table. */ static int dbdataConnect( sqlite3 *db, void *pAux, |
︙ | ︙ | |||
319 320 321 322 323 324 325 | } pCsr->pStmt = 0; pCsr->iPgno = 1; pCsr->iCell = 0; pCsr->iField = 0; pCsr->bOnePage = 0; sqlite3_free(pCsr->aPage); | > | < | 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 | } pCsr->pStmt = 0; pCsr->iPgno = 1; pCsr->iCell = 0; pCsr->iField = 0; pCsr->bOnePage = 0; sqlite3_free(pCsr->aPage); sqlite3_free(pCsr->pRec); pCsr->pRec = 0; pCsr->aPage = 0; } /* ** Close an sqlite_dbdata or sqlite_dbptr cursor. */ static int dbdataClose(sqlite3_vtab_cursor *pCursor){ DbdataCursor *pCsr = (DbdataCursor*)pCursor; |
︙ | ︙ | |||
463 464 465 466 467 468 469 | static void dbdataValue( sqlite3_context *pCtx, u32 enc, int eType, u8 *pData, sqlite3_int64 nData ){ | < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < < < < < < < < | | < < < < < < < < < < < | 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 | static void dbdataValue( sqlite3_context *pCtx, u32 enc, int eType, u8 *pData, sqlite3_int64 nData ){ if( eType>=0 && dbdataValueBytes(eType)<=nData ){ switch( eType ){ case 0: case 10: case 11: sqlite3_result_null(pCtx); break; case 8: sqlite3_result_int(pCtx, 0); break; case 9: sqlite3_result_int(pCtx, 1); break; case 1: case 2: case 3: case 4: case 5: case 6: case 7: { sqlite3_uint64 v = (signed char)pData[0]; pData++; switch( eType ){ case 7: case 6: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2; case 5: v = (v<<16) + (pData[0]<<8) + pData[1]; pData += 2; case 4: v = (v<<8) + pData[0]; pData++; case 3: v = (v<<8) + pData[0]; pData++; case 2: v = (v<<8) + pData[0]; pData++; } if( eType==7 ){ double r; memcpy(&r, &v, sizeof(r)); sqlite3_result_double(pCtx, r); }else{ sqlite3_result_int64(pCtx, (sqlite3_int64)v); } break; } default: { int n = ((eType-12) / 2); if( eType % 2 ){ switch( enc ){ #ifndef SQLITE_OMIT_UTF16 case SQLITE_UTF16BE: sqlite3_result_text16be(pCtx, (void*)pData, n, SQLITE_TRANSIENT); break; case SQLITE_UTF16LE: sqlite3_result_text16le(pCtx, (void*)pData, n, SQLITE_TRANSIENT); break; #endif default: sqlite3_result_text(pCtx, (char*)pData, n, SQLITE_TRANSIENT); break; } }else{ sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT); } } } } } /* ** Move an sqlite_dbdata or sqlite_dbptr cursor to the next entry. */ static int dbdataNext(sqlite3_vtab_cursor *pCursor){ DbdataCursor *pCsr = (DbdataCursor*)pCursor; DbdataTable *pTab = (DbdataTable*)pCursor->pVtab; |
︙ | ︙ | |||
573 574 575 576 577 578 579 | if( pCsr->bOnePage ) return SQLITE_OK; pCsr->iPgno++; } assert( iOff+3+2<=pCsr->nPage ); pCsr->iCell = pTab->bPtr ? -2 : 0; pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]); | < < < < | | 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 | if( pCsr->bOnePage ) return SQLITE_OK; pCsr->iPgno++; } assert( iOff+3+2<=pCsr->nPage ); pCsr->iCell = pTab->bPtr ? -2 : 0; pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]); } if( pTab->bPtr ){ if( pCsr->aPage[iOff]!=0x02 && pCsr->aPage[iOff]!=0x05 ){ pCsr->iCell = pCsr->nCell; } pCsr->iCell++; if( pCsr->iCell>=pCsr->nCell ){ sqlite3_free(pCsr->aPage); pCsr->aPage = 0; if( pCsr->bOnePage ) return SQLITE_OK; pCsr->iPgno++; }else{ return SQLITE_OK; } }else{ /* If there is no record loaded, load it now. */ if( pCsr->pRec==0 ){ int bHasRowid = 0; int nPointer = 0; sqlite3_int64 nPayload = 0; sqlite3_int64 nHdr = 0; int iHdr; int U, X; int nLocal; |
︙ | ︙ | |||
621 622 623 624 625 626 627 | pCsr->iCell = pCsr->nCell; break; } if( pCsr->iCell>=pCsr->nCell ){ bNextPage = 1; }else{ | < > | | | < | 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 | pCsr->iCell = pCsr->nCell; break; } if( pCsr->iCell>=pCsr->nCell ){ bNextPage = 1; }else{ iOff += 8 + nPointer + pCsr->iCell*2; if( iOff>pCsr->nPage ){ bNextPage = 1; }else{ iOff = get_uint16(&pCsr->aPage[iOff]); } /* For an interior node cell, skip past the child-page number */ iOff += nPointer; /* Load the "byte of payload including overflow" field */ if( bNextPage || iOff>pCsr->nPage ){ bNextPage = 1; }else{ iOff += dbdataGetVarintU32(&pCsr->aPage[iOff], &nPayload); if( nPayload>0x7fffff00 ) nPayload &= 0x3fff; } /* If this is a leaf intkey cell, load the rowid */ if( bHasRowid && !bNextPage && iOff<pCsr->nPage ){ iOff += dbdataGetVarint(&pCsr->aPage[iOff], &pCsr->iIntkey); } |
︙ | ︙ | |||
673 674 675 676 677 678 679 | if( bNextPage || nLocal+iOff>pCsr->nPage ){ bNextPage = 1; }else{ /* Allocate space for payload. And a bit more to catch small buffer ** overruns caused by attempting to read a varint or similar from ** near the end of a corrupt record. */ | | | > | | | < < < | | | | < < | | > | | > | | 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 | if( bNextPage || nLocal+iOff>pCsr->nPage ){ bNextPage = 1; }else{ /* Allocate space for payload. And a bit more to catch small buffer ** overruns caused by attempting to read a varint or similar from ** near the end of a corrupt record. */ pCsr->pRec = (u8*)sqlite3_malloc64(nPayload+DBDATA_PADDING_BYTES); if( pCsr->pRec==0 ) return SQLITE_NOMEM; memset(pCsr->pRec, 0, nPayload+DBDATA_PADDING_BYTES); pCsr->nRec = nPayload; /* Load the nLocal bytes of payload */ memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal); iOff += nLocal; /* Load content from overflow pages */ if( nPayload>nLocal ){ sqlite3_int64 nRem = nPayload - nLocal; u32 pgnoOvfl = get_uint32(&pCsr->aPage[iOff]); while( nRem>0 ){ u8 *aOvfl = 0; int nOvfl = 0; int nCopy; rc = dbdataLoadPage(pCsr, pgnoOvfl, &aOvfl, &nOvfl); assert( rc!=SQLITE_OK || aOvfl==0 || nOvfl==pCsr->nPage ); if( rc!=SQLITE_OK ) return rc; if( aOvfl==0 ) break; nCopy = U-4; if( nCopy>nRem ) nCopy = nRem; memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy); nRem -= nCopy; pgnoOvfl = get_uint32(aOvfl); sqlite3_free(aOvfl); } } iHdr = dbdataGetVarintU32(pCsr->pRec, &nHdr); if( nHdr>nPayload ) nHdr = 0; pCsr->nHdr = nHdr; pCsr->pHdrPtr = &pCsr->pRec[iHdr]; pCsr->pPtr = &pCsr->pRec[pCsr->nHdr]; pCsr->iField = (bHasRowid ? -1 : 0); } } }else{ pCsr->iField++; if( pCsr->iField>0 ){ sqlite3_int64 iType; if( pCsr->pHdrPtr>&pCsr->pRec[pCsr->nRec] ){ bNextPage = 1; }else{ int szField = 0; pCsr->pHdrPtr += dbdataGetVarintU32(pCsr->pHdrPtr, &iType); szField = dbdataValueBytes(iType); if( (pCsr->nRec - (pCsr->pPtr - pCsr->pRec))<szField ){ pCsr->pPtr = &pCsr->pRec[pCsr->nRec]; }else{ pCsr->pPtr += szField; } } } } if( bNextPage ){ sqlite3_free(pCsr->aPage); sqlite3_free(pCsr->pRec); pCsr->aPage = 0; pCsr->pRec = 0; if( pCsr->bOnePage ) return SQLITE_OK; pCsr->iPgno++; }else{ if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->pRec[pCsr->nHdr] ){ return SQLITE_OK; } /* Advance to the next cell. The next iteration of the loop will load ** the record and so on. */ sqlite3_free(pCsr->pRec); pCsr->pRec = 0; pCsr->iCell++; } } } assert( !"can't get here" ); return SQLITE_OK; |
︙ | ︙ | |||
939 940 941 942 943 944 945 | break; case DBDATA_COLUMN_FIELD: sqlite3_result_int(ctx, pCsr->iField); break; case DBDATA_COLUMN_VALUE: { if( pCsr->iField<0 ){ sqlite3_result_int64(ctx, pCsr->iIntkey); | | | | 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 | break; case DBDATA_COLUMN_FIELD: sqlite3_result_int(ctx, pCsr->iField); break; case DBDATA_COLUMN_VALUE: { if( pCsr->iField<0 ){ sqlite3_result_int64(ctx, pCsr->iIntkey); }else if( &pCsr->pRec[pCsr->nRec] >= pCsr->pPtr ){ sqlite3_int64 iType; dbdataGetVarintU32(pCsr->pHdrPtr, &iType); dbdataValue( ctx, pCsr->enc, iType, pCsr->pPtr, &pCsr->pRec[pCsr->nRec] - pCsr->pPtr ); } break; } } } return SQLITE_OK; |
︙ | ︙ |
Changes to ext/recover/recover1.test.
︙ | ︙ | |||
338 339 340 341 342 343 344 | CREATE TABLE t1(a, b); CREATE TABLE t2(a, b); INSERT INTO t1 VALUES('abc', 'def'); PRAGMA writable_schema = 1; DELETE FROM sqlite_schema WHERE name='t1'; } | | | < < < < < < < < < < < | 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 | CREATE TABLE t1(a, b); CREATE TABLE t2(a, b); INSERT INTO t1 VALUES('abc', 'def'); PRAGMA writable_schema = 1; DELETE FROM sqlite_schema WHERE name='t1'; } proc my_sql_hook {sql} { if {[string match "INSERT INTO lostandfound*" $sql]} { lappend ::script $sql } return 0 } do_test 18.$enc.2 { set ::script [list] set R [sqlite3_recover_init_sql db main my_sql_hook] $R config lostandfound lostandfound $R run $R finish set ::script } {{INSERT INTO lostandfound VALUES(2, 2, 2, 1, 'abc', 'def')}} } finish_test |
Changes to ext/recover/recovercorrupt2.test.
︙ | ︙ | |||
520 521 522 523 524 525 526 | }]} {} do_test 7.1 { set R [sqlite3_recover_init db main test.db2] catch { $R run } list [catch { $R finish } msg] $msg } {1 {file is not a database}} | < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 520 521 522 523 524 525 526 527 528 | }]} {} do_test 7.1 { set R [sqlite3_recover_init db main test.db2] catch { $R run } list [catch { $R finish } msg] $msg } {1 {file is not a database}} finish_test |
Deleted ext/recover/recovercorrupt3.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted ext/recover/recovercorrupt4.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to ext/recover/sqlite3recover.c.
︙ | ︙ | |||
1185 1186 1187 1188 1189 1190 1191 | } rc = sqlite3_exec(p->dbOut, zSql, 0, 0, 0); if( rc==SQLITE_OK ){ recoverSqlCallback(p, zSql); if( bTable && !bVirtual ){ if( SQLITE_ROW==sqlite3_step(pTblname) ){ const char *zTbl = (const char*)sqlite3_column_text(pTblname, 0); | | | 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 | } rc = sqlite3_exec(p->dbOut, zSql, 0, 0, 0); if( rc==SQLITE_OK ){ recoverSqlCallback(p, zSql); if( bTable && !bVirtual ){ if( SQLITE_ROW==sqlite3_step(pTblname) ){ const char *zTbl = (const char*)sqlite3_column_text(pTblname, 0); recoverAddTable(p, zTbl, iRoot); } recoverReset(p, pTblname); } }else if( rc!=SQLITE_ERROR ){ recoverDbError(p, p->dbOut); } sqlite3_free(zFree); |
︙ | ︙ |
Changes to ext/rtree/rtree.c.
︙ | ︙ | |||
1837 1838 1839 1840 1841 1842 1843 | pCons->op = RTREE_QUERY; pCons->u.xQueryFunc = pBlob->cb.xQueryFunc; } pCons->pInfo = pInfo; return SQLITE_OK; } | < < | 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 | pCons->op = RTREE_QUERY; pCons->u.xQueryFunc = pBlob->cb.xQueryFunc; } pCons->pInfo = pInfo; return SQLITE_OK; } /* ** Rtree virtual table module xFilter method. */ static int rtreeFilter( sqlite3_vtab_cursor *pVtabCursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv |
︙ | ︙ | |||
1868 1869 1870 1871 1872 1873 1874 | /* Special case - lookup by rowid. */ RtreeNode *pLeaf; /* Leaf on which the required cell resides */ RtreeSearchPoint *p; /* Search point for the leaf */ i64 iRowid = sqlite3_value_int64(argv[0]); i64 iNode = 0; int eType = sqlite3_value_numeric_type(argv[0]); if( eType==SQLITE_INTEGER | | < | 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 | /* Special case - lookup by rowid. */ RtreeNode *pLeaf; /* Leaf on which the required cell resides */ RtreeSearchPoint *p; /* Search point for the leaf */ i64 iRowid = sqlite3_value_int64(argv[0]); i64 iNode = 0; int eType = sqlite3_value_numeric_type(argv[0]); if( eType==SQLITE_INTEGER || (eType==SQLITE_FLOAT && sqlite3_value_double(argv[0])==iRowid) ){ rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode); }else{ rc = SQLITE_OK; pLeaf = 0; } if( rc==SQLITE_OK && pLeaf!=0 ){ |
︙ | ︙ |
Changes to ext/rtree/rtree1.test.
︙ | ︙ | |||
793 794 795 796 797 798 799 | reset_db do_test 23.0 { db eval {CREATE TABLE t1(a,b,c);} catch {db eval {CREATE TABLE t2 AS SELECT rtreecheck('t1') AS y;}} db eval {PRAGMA integrity_check;} } {ok} | < < < < < < < < < < < < < < < < < < | 793 794 795 796 797 798 799 800 | reset_db do_test 23.0 { db eval {CREATE TABLE t1(a,b,c);} catch {db eval {CREATE TABLE t2 AS SELECT rtreecheck('t1') AS y;}} db eval {PRAGMA integrity_check;} } {ok} finish_test |
Deleted ext/session/sessionchange.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted ext/session/sessionconflict.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to ext/session/sqlite3session.c.
︙ | ︙ | |||
3681 3682 3683 3684 3685 3686 3687 | /* Make sure the buffer contains at least 10 bytes of input data, or all ** remaining data if there are less than 10 bytes available. This is ** sufficient either for the 'T' or 'P' byte and the varint that follows ** it, or for the two single byte values otherwise. */ p->rc = sessionInputBuffer(&p->in, 2); if( p->rc!=SQLITE_OK ) return p->rc; | < < < > > > | 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 | /* Make sure the buffer contains at least 10 bytes of input data, or all ** remaining data if there are less than 10 bytes available. This is ** sufficient either for the 'T' or 'P' byte and the varint that follows ** it, or for the two single byte values otherwise. */ p->rc = sessionInputBuffer(&p->in, 2); if( p->rc!=SQLITE_OK ) return p->rc; /* If the iterator is already at the end of the changeset, return DONE. */ if( p->in.iNext>=p->in.nData ){ return SQLITE_DONE; } 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; |
︙ | ︙ | |||
5423 5424 5425 5426 5427 5428 5429 | /* ** sqlite3_changegroup handle. */ struct sqlite3_changegroup { int rc; /* Error code */ int bPatch; /* True to accumulate patchsets */ SessionTable *pList; /* List of tables in current patch */ | < | 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 | /* ** sqlite3_changegroup handle. */ struct sqlite3_changegroup { int rc; /* Error code */ int bPatch; /* True to accumulate patchsets */ SessionTable *pList; /* List of tables in current patch */ sqlite3 *db; /* Configured by changegroup_schema() */ char *zDb; /* Configured by changegroup_schema() */ }; /* ** This function is called to merge two changes to the same row together as |
︙ | ︙ | |||
5722 5723 5724 5725 5726 5727 5728 | sessionAppendBlob(pOut, aRec, nRec, &rc); } return rc; } /* | | | < < < | < < | < < < < < < < | < < | < < < < < < < < < < < < < < < < < < < < < < < | < < < < < | < < < < < < < | < < | < < | | | | < < | < < < < < < < | | | | | | | < < < | | | | | | | > | > | > > > | | > > > > | | > > > > | > | | > > > | > | > | | > > | | | > > > > > > > > > | > | | > > > > | > > > | < > > > > > > > > | < < < > | | | | | | < < | | < < < < < < < < < < < < < < < < < < | 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 | sessionAppendBlob(pOut, aRec, nRec, &rc); } 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; SessionBuffer rec = {0, 0, 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; SessionChange **pp; /* Ensure that only changesets, or only patchsets, but not a mixture ** of both, are being combined. It is an error to try to combine a ** changeset and a patchset. */ if( pGrp->pList==0 ){ pGrp->bPatch = pIter->bPatchset; }else if( pIter->bPatchset!=pGrp->bPatch ){ rc = SQLITE_ERROR; break; } sqlite3changeset_op(pIter, &zNew, &nCol, &op, &bIndirect); if( !pTab || sqlite3_stricmp(zNew, pTab->zName) ){ /* Search the list for a matching table */ int nNew = (int)strlen(zNew); u8 *abPK; sqlite3changeset_pk(pIter, &abPK, 0); for(pTab = pGrp->pList; pTab; pTab=pTab->pNext){ if( 0==sqlite3_strnicmp(pTab->zName, zNew, nNew+1) ) break; } if( !pTab ){ SessionTable **ppTab; pTab = sqlite3_malloc64(sizeof(SessionTable) + nCol + nNew+1); if( !pTab ){ rc = SQLITE_NOMEM; break; } memset(pTab, 0, sizeof(SessionTable)); pTab->nCol = nCol; pTab->abPK = (u8*)&pTab[1]; memcpy(pTab->abPK, abPK, nCol); pTab->zName = (char*)&pTab->abPK[nCol]; memcpy(pTab->zName, zNew, nNew+1); if( pGrp->db ){ pTab->nCol = 0; rc = sessionInitTable(0, pTab, pGrp->db, pGrp->zDb); if( rc ){ assert( pTab->azCol==0 ); sqlite3_free(pTab); break; } } /* The new object must be linked on to the end of the list, not ** simply added to the start of it. This is to ensure that the ** tables within the output of sqlite3changegroup_output() are in ** the right order. */ for(ppTab=&pGrp->pList; *ppTab; ppTab=&(*ppTab)->pNext); *ppTab = pTab; } if( !sessionChangesetCheckCompat(pTab, nCol, abPK) ){ rc = SQLITE_SCHEMA; break; } } if( nCol<pTab->nCol ){ assert( pGrp->db ); rc = sessionChangesetExtendRecord(pGrp, pTab, nCol, op, aRec, nRec, &rec); if( rc ) break; aRec = rec.aBuf; nRec = rec.nBuf; } if( sessionGrowHash(0, pIter->bPatchset, pTab) ){ rc = SQLITE_NOMEM; break; } iHash = sessionChangeHash( pTab, (pIter->bPatchset && op==SQLITE_DELETE), aRec, pTab->nChange ); /* Search for existing entry. If found, remove it from the hash table. ** Code below may link it back in. */ for(pp=&pTab->apChange[iHash]; *pp; pp=&(*pp)->pNext){ int bPkOnly1 = 0; int bPkOnly2 = 0; if( pIter->bPatchset ){ bPkOnly1 = (*pp)->op==SQLITE_DELETE; bPkOnly2 = op==SQLITE_DELETE; } if( sessionChangeEqual(pTab, bPkOnly1, (*pp)->aRecord, bPkOnly2, aRec) ){ 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++; } } sqlite3_free(rec.aBuf); if( rc==SQLITE_OK ) rc = pIter->rc; return rc; } /* ** Serialize a changeset (or patchset) based on all changesets (or patchsets) ** added to the changegroup object passed as the first argument. |
︙ | ︙ | |||
6020 6021 6022 6023 6024 6025 6026 | if( rc==SQLITE_OK ){ rc = sessionChangesetToHash(pIter, pGrp, 0); } sqlite3changeset_finalize(pIter); return rc; } | < < < < < < < < < < < < < < < < < | 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 | if( rc==SQLITE_OK ){ rc = sessionChangesetToHash(pIter, pGrp, 0); } sqlite3changeset_finalize(pIter); return rc; } /* ** Obtain a buffer containing a changeset representing the concatenation ** of all changesets added to the group so far. */ int sqlite3changegroup_output( sqlite3_changegroup *pGrp, int *pnData, |
︙ | ︙ | |||
6086 6087 6088 6089 6090 6091 6092 | /* ** Delete a changegroup object. */ void sqlite3changegroup_delete(sqlite3_changegroup *pGrp){ if( pGrp ){ sqlite3_free(pGrp->zDb); sessionDeleteTable(0, pGrp->pList); | < | 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 | /* ** Delete a changegroup object. */ void sqlite3changegroup_delete(sqlite3_changegroup *pGrp){ if( pGrp ){ sqlite3_free(pGrp->zDb); sessionDeleteTable(0, pGrp->pList); sqlite3_free(pGrp); } } /* ** Combine two changesets together. */ |
︙ | ︙ | |||
6488 6489 6490 6491 6492 6493 6494 | /* ** Destroy a rebaser object */ void sqlite3rebaser_delete(sqlite3_rebaser *p){ if( p ){ sessionDeleteTable(0, p->grp.pList); | < | 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 | /* ** Destroy a rebaser object */ void sqlite3rebaser_delete(sqlite3_rebaser *p){ if( p ){ sessionDeleteTable(0, p->grp.pList); sqlite3_free(p); } } /* ** Global configuration */ |
︙ | ︙ |
Changes to ext/session/sqlite3session.h.
︙ | ︙ | |||
1052 1053 1054 1055 1056 1057 1058 | ** detected, SQLITE_CORRUPT is returned. Or, if an out-of-memory condition ** occurs during processing, this function returns SQLITE_NOMEM. ** ** In all cases, if an error occurs the state of the final contents of the ** changegroup is undefined. If no error occurs, SQLITE_OK is returned. */ int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData); | < < < < < < < < < < < < < < < < < < < < < < < < | 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 | ** detected, SQLITE_CORRUPT is returned. Or, if an out-of-memory condition ** occurs during processing, this function returns SQLITE_NOMEM. ** ** In all cases, if an error occurs the state of the final contents of the ** changegroup is undefined. If no error occurs, SQLITE_OK is returned. */ int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData); /* ** CAPI3REF: Obtain A Composite Changeset From A Changegroup ** METHOD: sqlite3_changegroup ** ** Obtain a buffer containing a changeset (or patchset) representing the ** current contents of the changegroup. If the inputs to the changegroup |
︙ | ︙ |
Changes to ext/session/test_session.c.
︙ | ︙ | |||
1034 1035 1036 1037 1038 1039 1040 | assert_changeset_is_ok(sOut.n, sOut.p); Tcl_SetObjResult(interp,Tcl_NewByteArrayObj((unsigned char*)sOut.p,sOut.n)); } sqlite3_free(sOut.p); return rc; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 | assert_changeset_is_ok(sOut.n, sOut.p); Tcl_SetObjResult(interp,Tcl_NewByteArrayObj((unsigned char*)sOut.p,sOut.n)); } sqlite3_free(sOut.p); return rc; } /* ** sqlite3session_foreach VARNAME CHANGESET SCRIPT */ static int SQLITE_TCLAPI test_sqlite3session_foreach( void * clientData, Tcl_Interp *interp, int objc, |
︙ | ︙ | |||
1165 1166 1167 1168 1169 1170 1171 | } } if( rc!=SQLITE_OK ){ return test_session_error(interp, rc, 0); } while( SQLITE_ROW==sqlite3changeset_next(pIter) ){ | > > > > | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 | } } if( rc!=SQLITE_OK ){ return test_session_error(interp, rc, 0); } while( SQLITE_ROW==sqlite3changeset_next(pIter) ){ int nCol; /* Number of columns in table */ int nCol2; /* Number of columns in table */ int op; /* SQLITE_INSERT, UPDATE or DELETE */ const char *zTab; /* Name of table change applies to */ Tcl_Obj *pVar; /* Tcl value to set $VARNAME to */ Tcl_Obj *pOld; /* Vector of old.* values */ Tcl_Obj *pNew; /* Vector of new.* values */ int bIndirect; char *zPK; unsigned char *abPK; int i; /* Test that _fk_conflicts() returns SQLITE_MISUSE if called on this ** iterator. */ int nDummy; if( SQLITE_MISUSE!=sqlite3changeset_fk_conflicts(pIter, &nDummy) ){ sqlite3changeset_finalize(pIter); return TCL_ERROR; } sqlite3changeset_op(pIter, &zTab, &nCol, &op, &bIndirect); pVar = Tcl_NewObj(); Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj( op==SQLITE_INSERT ? "INSERT" : op==SQLITE_UPDATE ? "UPDATE" : "DELETE", -1 )); Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(zTab, -1)); Tcl_ListObjAppendElement(0, pVar, Tcl_NewBooleanObj(bIndirect)); zPK = ckalloc(nCol+1); memset(zPK, 0, nCol+1); sqlite3changeset_pk(pIter, &abPK, &nCol2); assert( nCol==nCol2 ); for(i=0; i<nCol; i++){ zPK[i] = (abPK[i] ? 'X' : '.'); } Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(zPK, -1)); ckfree(zPK); pOld = Tcl_NewObj(); if( op!=SQLITE_INSERT ){ for(i=0; i<nCol; i++){ sqlite3_value *pVal; sqlite3changeset_old(pIter, i, &pVal); test_append_value(pOld, pVal); } } pNew = Tcl_NewObj(); if( op!=SQLITE_DELETE ){ for(i=0; i<nCol; i++){ sqlite3_value *pVal; sqlite3changeset_new(pIter, i, &pVal); test_append_value(pNew, pVal); } } Tcl_ListObjAppendElement(0, pVar, pOld); Tcl_ListObjAppendElement(0, pVar, pNew); Tcl_ObjSetVar2(interp, pVarname, 0, pVar, 0); rc = Tcl_EvalObjEx(interp, pScript, 0); if( rc!=TCL_OK && rc!=TCL_CONTINUE ){ sqlite3changeset_finalize(pIter); return rc==TCL_BREAK ? TCL_OK : rc; } } |
︙ | ︙ | |||
1453 1454 1455 1456 1457 1458 1459 | return TCL_OK; } typedef struct TestChangegroup TestChangegroup; struct TestChangegroup { sqlite3_changegroup *pGrp; }; | < < < < < < | 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 | return TCL_OK; } typedef struct TestChangegroup TestChangegroup; struct TestChangegroup { sqlite3_changegroup *pGrp; }; /* ** Destructor for Tcl changegroup command object. */ static void test_changegroup_del(void *clientData){ TestChangegroup *pGrp = (TestChangegroup*)clientData; sqlite3changegroup_delete(pGrp->pGrp); |
︙ | ︙ | |||
1492 1493 1494 1495 1496 1497 1498 | const char *zMsg; int iSub; } aSub[] = { { "schema", 2, "DB DBNAME", }, /* 0 */ { "add", 1, "CHANGESET", }, /* 1 */ { "output", 0, "", }, /* 2 */ { "delete", 0, "", }, /* 3 */ | < | 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 | const char *zMsg; int iSub; } aSub[] = { { "schema", 2, "DB DBNAME", }, /* 0 */ { "add", 1, "CHANGESET", }, /* 1 */ { "output", 0, "", }, /* 2 */ { "delete", 0, "", }, /* 3 */ { 0 } }; int rc = TCL_OK; int iSub = 0; if( objc<2 ){ Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ..."); |
︙ | ︙ | |||
1544 1545 1546 1547 1548 1549 1550 | }else{ Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(aByte, nByte)); } sqlite3_free(aByte); break; }; | < < < < < < < < < < < < < < < < < < | 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 | }else{ Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(aByte, nByte)); } sqlite3_free(aByte); break; }; default: { /* delete */ assert( iSub==3 ); Tcl_DeleteCommand(interp, Tcl_GetString(objv[0])); break; } } |
︙ | ︙ | |||
1605 1606 1607 1608 1609 1610 1611 | interp, Tcl_GetString(objv[1]), test_changegroup_cmd, (ClientData)p, test_changegroup_del ); Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 | interp, Tcl_GetString(objv[1]), test_changegroup_cmd, (ClientData)p, test_changegroup_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 }, { "sqlite3changegroup", test_sqlite3changegroup }, { "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 }, |
︙ | ︙ |
Changes to ext/wasm/GNUmakefile.
︙ | ︙ | |||
285 286 287 288 289 290 291 | endif ######################################################################### # bin.version-info = binary to output various sqlite3 version info for # embedding in the JS files and in building the distribution zip file. # It must NOT be in $(dir.tmp) because we need it to survive the # cleanup process for the dist build to work properly. | < < < < < < | < | | 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 | endif ######################################################################### # bin.version-info = binary to output various sqlite3 version info for # embedding in the JS files and in building the distribution zip file. # It must NOT be in $(dir.tmp) because we need it to survive the # cleanup process for the dist build to work properly. bin.version-info := $(dir.top)/version-info .NOTPARALLEL: $(bin.version-info) $(bin.version-info): $(dir.tool)/version-info.c $(sqlite3.h) $(dir.top)/Makefile $(MAKE) -C $(dir.top) version-info ######################################################################### # bin.stripcomments is used for stripping C/C++-style comments from JS # files. The JS files contain large chunks of documentation which we # don't need for all builds. That app's -k flag is of particular # importance here, as it allows us to retain the opening comment # block(s), which contain the license header and version info. bin.stripccomments := $(dir.tool)/stripccomments $(bin.stripccomments): $(bin.stripccomments).c $(MAKEFILE) $(CC) -o $@ $< DISTCLEAN_FILES += $(bin.stripccomments) ######################################################################## # C-PP.FILTER: a $(call)able to transform $(1) to $(2) via ./c-pp -f # $(1) ... # # Historical notes: # # - We first attempted to use gcc and/or clang to preprocess JS files # in the same way we would normally do C files, but C-specific quirks # of each makes that untennable. # |
︙ | ︙ | |||
337 338 339 340 341 342 343 | # # c-pp.c was written specifically for the sqlite project's JavaScript # builds but is maintained as a standalone project: # https://fossil.wanderinghorse.net/r/c-pp # # Note that the SQLITE_... build flags used here have NO EFFECT on the # JS/WASM build. They are solely for use with $(bin.c-pp) itself. | < < < < < < < | | 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 | # # c-pp.c was written specifically for the sqlite project's JavaScript # builds but is maintained as a standalone project: # https://fossil.wanderinghorse.net/r/c-pp # # Note that the SQLITE_... build flags used here have NO EFFECT on the # JS/WASM build. They are solely for use with $(bin.c-pp) itself. bin.c-pp := ./c-pp $(bin.c-pp): c-pp.c $(sqlite3.c) $(MAKEFILE) $(CC) -O0 -o $@ c-pp.c $(sqlite3.c) '-DCMPP_DEFAULT_DELIM="//#"' -I$(dir.top) \ -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_UTF16 \ -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_WAL -DSQLITE_THREADSAFE=0 \ -DSQLITE_TEMP_STORE=3 define C-PP.FILTER # Create $2 from $1 using $(bin.c-pp) # $1 = Input file: c-pp -f $(1).js # $2 = Output file: c-pp -o $(2).js # $3 = optional c-pp -D... flags $(2): $(1) $$(MAKEFILE) $$(bin.c-pp) $$(bin.c-pp) -f $(1) -o $$@ $(3) CLEAN_FILES += $(2) endef # /end C-PP.FILTER ######################################################################## # cflags.common = C compiler flags for all builds cflags.common := -I. -I$(dir $(sqlite3.c)) |
︙ | ︙ | |||
462 463 464 465 466 467 468 | ######################################################################## # SOAP.js is an external API file which is part of our distribution # but not part of the sqlite3-api.js amalgamation. It's a component of # the first OPFS VFS and necessarily an external file. SOAP.js := $(dir.api)/sqlite3-opfs-async-proxy.js SOAP.js.bld := $(dir.dout)/$(notdir $(SOAP.js)) | < < < < | > > > | 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 | ######################################################################## # SOAP.js is an external API file which is part of our distribution # but not part of the sqlite3-api.js amalgamation. It's a component of # the first OPFS VFS and necessarily an external file. SOAP.js := $(dir.api)/sqlite3-opfs-async-proxy.js SOAP.js.bld := $(dir.dout)/$(notdir $(SOAP.js)) sqlite3-api.ext.jses += $(SOAP.js.bld) $(SOAP.js.bld): $(SOAP.js) cp $< $@ all quick: $(sqlite3-api.ext.jses) q: quick ######################################################################## # $(sqlite3-api*.*js) contain the core library code but not the # Emscripten-related glue which deals with loading sqlite3.wasm. In # theory they can be used by arbitrary build environments and WASM # loaders, but in practice that breaks down because the WASM loader # has to be able to provide all of the necessary "imports" to |
︙ | ︙ | |||
836 837 838 839 840 841 842 | # # $1 = one of: $(JS_BUILD_NAMES) # $2 = build mode name: one of $(JS_BUILD_MODES) # $3 = 1 for ESM build mode, else 0 # $4 = resulting sqlite-api JS/MJS file # $5 = resulting JS/MJS file # $6 = -D... flags for $(bin.c-pp) | | | | | 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 | # # $1 = one of: $(JS_BUILD_NAMES) # $2 = build mode name: one of $(JS_BUILD_MODES) # $3 = 1 for ESM build mode, else 0 # $4 = resulting sqlite-api JS/MJS file # $5 = resulting JS/MJS file # $6 = -D... flags for $(bin.c-pp) # $7 = emcc -sXYZ flags (CURRENTLY UNUSED - was factored out) # # Maintenance reminder: be careful not to introduce spaces around args # ($1, $2), otherwise string concatenation will malfunction. # # emcc.environment.$(2) must be set to a value for emcc's # -sENVIRONMENT flag. # # $(cflags.$(1)) and $(cflags.$(1).$(2)) may be defined to append # CFLAGS to a given build mode. # # $(emcc.flags.$(1)) and $(emcc.flags.$(1).$(2)) may be defined to # append emcc-specific flags to a given build mode. define SETUP_LIB_BUILD_MODE |
︙ | ︙ | |||
949 950 951 952 953 954 955 | # themselves use importScripts() or Workers or URL() constructors # which refer to other in-tree (m)JS files quire a bundler-friendly # copy. sqlite3-worker1.js.in := $(dir.api)/sqlite3-worker1.c-pp.js sqlite3-worker1-promiser.js.in := $(dir.api)/sqlite3-worker1-promiser.c-pp.js sqlite3-worker1.js := $(dir.dout)/sqlite3-worker1.js sqlite3-worker1-promiser.js := $(dir.dout)/sqlite3-worker1-promiser.js | < | | < < | < < < < < < < < < < < < < < | < < < < | 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 | # themselves use importScripts() or Workers or URL() constructors # which refer to other in-tree (m)JS files quire a bundler-friendly # copy. sqlite3-worker1.js.in := $(dir.api)/sqlite3-worker1.c-pp.js sqlite3-worker1-promiser.js.in := $(dir.api)/sqlite3-worker1-promiser.c-pp.js sqlite3-worker1.js := $(dir.dout)/sqlite3-worker1.js sqlite3-worker1-promiser.js := $(dir.dout)/sqlite3-worker1-promiser.js sqlite3-worker1-bundler-friendly.js := $(dir.dout)/sqlite3-worker1-bundler-friendly.mjs sqlite3-worker1-promiser-bundler-friendly.js := $(dir.dout)/sqlite3-worker1-promiser-bundler-friendly.js $(eval $(call C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1.js))) $(eval $(call C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1-bundler-friendly.js),\ $(c-pp.D.sqlite3-bundler-friendly))) $(eval $(call C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),$(sqlite3-worker1-promiser.js))) $(eval $(call C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),\ $(sqlite3-worker1-promiser-bundler-friendly.js),\ $(c-pp.D.sqlite3-bundler-friendly))) $(sqlite3-bundler-friendly.mjs): $(sqlite3-worker1-bundler-friendly.js) \ $(sqlite3-worker1-promiser-bundler-friendly.js) $(sqlite3.js) $(sqlite3.mjs): $(sqlite3-worker1.js) $(sqlite3-worker1-promiser.js) ######################################################################## # batch-runner.js is part of one of the test apps which reads in SQL # dumps generated by $(speedtest1) and executes them. dir.sql := sql speedtest1 := ../../speedtest1 speedtest1.c := ../../test/speedtest1.c |
︙ | ︙ |
Changes to ext/wasm/api/sqlite3-api-glue.js.
︙ | ︙ | |||
325 326 327 328 329 330 331 | if(false && wasm.compileOptionUsed('SQLITE_ENABLE_NORMALIZE')){ /* ^^^ "the problem" is that this is an option feature and the build-time function-export list does not currently take optional features into account. */ wasm.bindingSignatures.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]); } | < | < < | 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 | if(false && wasm.compileOptionUsed('SQLITE_ENABLE_NORMALIZE')){ /* ^^^ "the problem" is that this is an option feature and the build-time function-export list does not currently take optional features into account. */ wasm.bindingSignatures.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]); } if(wasm.exports.sqlite3_activate_see instanceof Function){ /** This code is capable of using an SEE build but note that an SEE WASM build is generally incompatible with SEE's license conditions. It is permitted for use internally in organizations which have licensed SEE, but not for public sites because exposing an SEE build of sqlite3.wasm effectively provides all clients with a working copy of the commercial SEE code. */ wasm.bindingSignatures.push( ["sqlite3_key", "int", "sqlite3*", "string", "int"], ["sqlite3_key_v2","int","sqlite3*","string","*","int"], ["sqlite3_rekey", "int", "sqlite3*", "string", "int"], ["sqlite3_rekey_v2", "int", "sqlite3*", "string", "*", "int"], ["sqlite3_activate_see", undefined, "string"] ); } /** Functions which require BigInt (int64) support are separated from the others because we need to conditionally bind them or apply dummy impls, depending on the capabilities of the environment. (That said: we never actually build without BigInt support, and such builds are untested.) |
︙ | ︙ | |||
623 624 625 626 627 628 629 | prefix, to ensure that clients do not accidentally depend on them. They have always been documented as internal-use-only, so no clients "should" be depending on the old names. */ wasm.bindingSignatures.wasmInternal = [ ["sqlite3__wasm_db_reset", "int", "sqlite3*"], ["sqlite3__wasm_db_vfs", "sqlite3_vfs*", "sqlite3*","string"], | < < < | | | < | 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 | prefix, to ensure that clients do not accidentally depend on them. They have always been documented as internal-use-only, so no clients "should" be depending on the old names. */ wasm.bindingSignatures.wasmInternal = [ ["sqlite3__wasm_db_reset", "int", "sqlite3*"], ["sqlite3__wasm_db_vfs", "sqlite3_vfs*", "sqlite3*","string"], ["sqlite3__wasm_vfs_create_file", "int", "sqlite3_vfs*","string","*", "int"], ["sqlite3__wasm_posix_create_file", "int", "string","*", "int"], ["sqlite3__wasm_vfs_unlink", "int", "sqlite3_vfs*","string"] ]; /** Install JS<->C struct bindings for the non-opaque struct types we need... */ sqlite3.StructBinder = globalThis.Jaccwabyt({ heap: 0 ? wasm.memory : wasm.heap8u, |
︙ | ︙ | |||
1550 1551 1552 1553 1554 1555 1556 | case capi.SQLITE_CONFIG_PCACHE_HDRSZ: // 24 /* int *psz */ case capi.SQLITE_CONFIG_PMASZ: // 25 /* unsigned int szPma */ case capi.SQLITE_CONFIG_SERIALIZED: // 3 /* nil */ case capi.SQLITE_CONFIG_SINGLETHREAD: // 1 /* nil */: case capi.SQLITE_CONFIG_SQLLOG: // 21 /* xSqllog, void* */ case capi.SQLITE_CONFIG_WIN32_HEAPSIZE: // 23 /* int nByte */ default: | < < < < | 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 | case capi.SQLITE_CONFIG_PCACHE_HDRSZ: // 24 /* int *psz */ case capi.SQLITE_CONFIG_PMASZ: // 25 /* unsigned int szPma */ case capi.SQLITE_CONFIG_SERIALIZED: // 3 /* nil */ case capi.SQLITE_CONFIG_SINGLETHREAD: // 1 /* nil */: case capi.SQLITE_CONFIG_SQLLOG: // 21 /* xSqllog, void* */ case capi.SQLITE_CONFIG_WIN32_HEAPSIZE: // 23 /* int nByte */ default: return capi.SQLITE_NOTFOUND; } }; }/* sqlite3_config() */ {/*auto-extension bindings.*/ const __autoExtFptr = new Set; |
︙ | ︙ |
Changes to ext/wasm/api/sqlite3-api-oo1.js.
︙ | ︙ | |||
83 84 85 86 87 88 89 | A map of sqlite3_vfs pointers to SQL code or a callback function to run when the DB constructor opens a database with the given VFS. In the latter case, the call signature is (theDbObject,sqlite3Namespace) and the callback is expected to throw on error. */ const __vfsPostOpenSql = Object.create(null); | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | A map of sqlite3_vfs pointers to SQL code or a callback function to run when the DB constructor opens a database with the given VFS. In the latter case, the call signature is (theDbObject,sqlite3Namespace) and the callback is expected to throw on error. */ const __vfsPostOpenSql = Object.create(null); /** A proxy for DB class constructors. It must be called with the being-construct DB object as its "this". See the DB constructor for the argument docs. This is split into a separate function in order to enable simple creation of special-case DB constructors, e.g. JsStorageDb and OpfsDb. |
︙ | ︙ | |||
269 270 271 272 273 274 275 | }finally{ wasm.pstack.restore(stack); } this.filename = fnJs; __ptrMap.set(this, pDb); __stmtMap.set(this, Object.create(null)); try{ | < < < | | < < < < < < < < | | | | | | < | 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | }finally{ wasm.pstack.restore(stack); } this.filename = fnJs; __ptrMap.set(this, pDb); __stmtMap.set(this, Object.create(null)); try{ // Check for per-VFS post-open SQL/callback... const pVfs = capi.sqlite3_js_db_vfs(pDb); if(!pVfs) toss3("Internal error: cannot get VFS for new db handle."); const postInitSql = __vfsPostOpenSql[pVfs]; if(postInitSql instanceof Function){ postInitSql(this, sqlite3); }else if(postInitSql){ checkSqlite3Rc( pDb, capi.sqlite3_exec(pDb, postInitSql, 0, 0, 0) ); } }catch(e){ this.close(); throw e; } }; |
︙ | ︙ | |||
386 387 388 389 390 391 392 | in the form of a single configuration object with the following properties: - `filename`: database file name - `flags`: open-mode flags - `vfs`: the VFS fname | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < | 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 | in the form of a single configuration object with the following properties: - `filename`: database file name - `flags`: open-mode flags - `vfs`: the VFS fname The `filename` and `vfs` arguments may be either JS strings or C-strings allocated via WASM. `flags` is required to be a JS string (because it's specific to this API, which is specific to JS). For purposes of passing a DB instance to C-style sqlite3 functions, the DB object's read-only `pointer` property holds its `sqlite3*` pointer value. That property can also be used to check whether this DB instance is still open. In the main window thread, the filenames `":localStorage:"` and `":sessionStorage:"` are special: they cause the db to use either localStorage or sessionStorage for storing the database using the kvvfs. If one of these names are used, they trump any vfs name set in the arguments. */ |
︙ | ︙ | |||
570 571 572 573 574 575 576 | toss3("Invalid returnValue value:",opt.returnValue); } if(!opt.callback && !opt.returnValue && undefined!==opt.rowMode){ if(!opt.resultRows) opt.resultRows = []; out.returnVal = ()=>opt.resultRows; } if(opt.callback || opt.resultRows){ | | < < < < < < < < < < < < | | < < < < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 | toss3("Invalid returnValue value:",opt.returnValue); } if(!opt.callback && !opt.returnValue && undefined!==opt.rowMode){ if(!opt.resultRows) opt.resultRows = []; out.returnVal = ()=>opt.resultRows; } if(opt.callback || opt.resultRows){ switch((undefined===opt.rowMode) ? 'array' : opt.rowMode) { case 'object': out.cbArg = (stmt)=>stmt.get(Object.create(null)); break; case 'array': out.cbArg = (stmt)=>stmt.get([]); break; case 'stmt': if(Array.isArray(opt.resultRows)){ toss3("exec(): invalid rowMode for a resultRows array: must", "be one of 'array', 'object',", "a result column number, or column name reference."); } out.cbArg = (stmt)=>stmt; break; default: if(util.isInt32(opt.rowMode)){ out.cbArg = (stmt)=>stmt.get(opt.rowMode); break; }else if('string'===typeof opt.rowMode && opt.rowMode.length>1 && '$'===opt.rowMode[0]){ /* "$X": fetch column named "X" (case-sensitive!). Prior to 2022-12-14 ":X" and "@X" were also permitted, but having so many options is unnecessary and likely to cause confusion. */ const $colName = opt.rowMode.substr(1); out.cbArg = (stmt)=>{ const rc = stmt.get(Object.create(null))[$colName]; return (undefined===rc) ? toss3(capi.SQLITE_NOTFOUND, "exec(): unknown result column:",$colName) : rc; }; break; } toss3("Invalid rowMode:",opt.rowMode); } } return out; }; /** Internal impl of the DB.selectValue(), selectArray(), and |
︙ | ︙ | |||
1037 1038 1039 1040 1041 1042 1043 | we need to delay fetching of the column names until after the first step() (if we step() at all) because a schema change between the prepare() and step(), via another connection, may invalidate the column count and names. */) ? 0 : 1; evalFirstResult = false; if(arg.cbArg || resultRows){ | < < < | < < | | 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 | we need to delay fetching of the column names until after the first step() (if we step() at all) because a schema change between the prepare() and step(), via another connection, may invalidate the column count and names. */) ? 0 : 1; evalFirstResult = false; if(arg.cbArg || resultRows){ for(; stmt.step(); stmt._lockedByExec = false){ if(0===gotColNames++) stmt.getColumnNames(opt.columnNames); stmt._lockedByExec = true; const row = arg.cbArg(stmt); if(resultRows) resultRows.push(row); if(callback && false === callback.call(opt, row, stmt)){ break; } } stmt._lockedByExec = false; } |
︙ | ︙ | |||
1680 1681 1682 1683 1684 1685 1686 | property when binding an array/object (see below) is treated the same as null. - Numbers are bound as either doubles or integers: doubles if they are larger than 32 bits, else double or int32, depending on whether they have a fractional part. Booleans are bound as integer 0 or 1. It is not expected the distinction of binding | | | 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 | property when binding an array/object (see below) is treated the same as null. - Numbers are bound as either doubles or integers: doubles if they are larger than 32 bits, else double or int32, depending on whether they have a fractional part. Booleans are bound as integer 0 or 1. It is not expected the distinction of binding doubles which have no fractional parts is integers is significant for the majority of clients due to sqlite3's data typing model. If [BigInt] support is enabled then this routine will bind BigInt values as 64-bit integers if they'll fit in 64 bits. If that support disabled, it will store the BigInt as an int32 or a double if it can do so without loss of precision. If the BigInt is _too BigInt_ then it will throw. |
︙ | ︙ | |||
1864 1865 1866 1867 1868 1869 1870 | Fetches the value from the given 0-based column index of the current data row, throwing if index is out of range. Requires that step() has just returned a truthy value, else an exception is thrown. By default it will determine the data type of the result | | | 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 | Fetches the value from the given 0-based column index of the current data row, throwing if index is out of range. Requires that step() has just returned a truthy value, else an exception is thrown. By default it will determine the data type of the result automatically. If passed a second arugment, it must be one of the enumeration values for sqlite3 types, which are defined as members of the sqlite3 module: SQLITE_INTEGER, SQLITE_FLOAT, SQLITE_TEXT, SQLITE_BLOB. Any other value, except for undefined, will trigger an exception. Passing undefined is the same as not passing a value. It is legal to, e.g., fetch an integer value as a string, in which case sqlite3 will convert the value to a string. |
︙ | ︙ | |||
2064 2065 2066 2067 2068 2069 2070 | }/*oo1 object*/; if(util.isUIThread()){ /** Functionally equivalent to DB(storageName,'c','kvvfs') except that it throws if the given storage name is not one of 'local' or 'session'. | < < < < < < < < < < < < < < | > > > > | 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 | }/*oo1 object*/; if(util.isUIThread()){ /** Functionally equivalent to DB(storageName,'c','kvvfs') except that it throws if the given storage name is not one of 'local' or 'session'. */ sqlite3.oo1.JsStorageDb = function(storageName='session'){ if('session'!==storageName && 'local'!==storageName){ toss3("JsStorageDb db name must be one of 'session' or 'local'."); } dbCtorHelper.call(this, { filename: storageName, flags: 'c', vfs: "kvvfs" }); }; const jdb = sqlite3.oo1.JsStorageDb; jdb.prototype = Object.create(DB.prototype); /** Equivalent to sqlite3_js_kvvfs_clear(). */ jdb.clearStorage = capi.sqlite3_js_kvvfs_clear; /** Clears this database instance's storage or throws if this |
︙ | ︙ |
Changes to ext/wasm/api/sqlite3-api-prologue.js.
︙ | ︙ | |||
241 242 243 244 245 246 247 | If called with exactly 2 arguments and the 2nd is an object, that object is treated as the 2nd argument to the parent constructor. The exception's message is created by concatenating its arguments with a space between each, except for the | | | 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 | If called with exactly 2 arguments and the 2nd is an object, that object is treated as the 2nd argument to the parent constructor. The exception's message is created by concatenating its arguments with a space between each, except for the two-args-with-an-objec form and that the first argument will get coerced to a string, as described above, if it's an integer. If passed an integer first argument, the error object's `resultCode` member will be set to the given integer value, else it will be set to capi.SQLITE_ERROR. */ |
︙ | ︙ | |||
1834 1835 1836 1837 1838 1839 1840 | } return tgt; }; /** Calls either sqlite3_result_error_nomem(), if e is-a WasmAllocError, or sqlite3_result_error(). In the latter case, | | | 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 | } return tgt; }; /** Calls either sqlite3_result_error_nomem(), if e is-a WasmAllocError, or sqlite3_result_error(). In the latter case, the second arugment is coerced to a string to create the error message. The first argument is a (sqlite3_context*). Returns void. Does not throw. */ capi.sqlite3_result_error_js = function(pCtx,e){ if(e instanceof WasmAllocError){ |
︙ | ︙ |
Changes to ext/wasm/api/sqlite3-api-worker1.js.
︙ | ︙ | |||
454 455 456 457 458 459 460 461 462 463 464 465 466 467 | const db = wState.getDb(msgData.dbId,false) || wState.dbList[0]; return affirmExists ? affirmDbOpen(db) : db; }; const getDefaultDbId = function(){ return wState.dbList[0] && getDbId(wState.dbList[0]); }; const isSpecialDbFilename = (n)=>{ return ""===n || ':'===n[0]; }; /** A level of "organizational abstraction" for the Worker1 | > > > > > | 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 | const db = wState.getDb(msgData.dbId,false) || wState.dbList[0]; return affirmExists ? affirmDbOpen(db) : db; }; const getDefaultDbId = function(){ return wState.dbList[0] && getDbId(wState.dbList[0]); }; const guessVfs = function(filename){ const m = /^file:.+(vfs=(\w+))/.exec(filename); return sqlite3.capi.sqlite3_vfs_find(m ? m[2] : 0); }; const isSpecialDbFilename = (n)=>{ return ""===n || ':'===n[0]; }; /** A level of "organizational abstraction" for the Worker1 |
︙ | ︙ | |||
476 477 478 479 480 481 482 483 | const wMsgHandler = { open: function(ev){ const oargs = Object.create(null), args = (ev.args || Object.create(null)); if(args.simulateError){ // undocumented internal testing option toss("Throwing because of simulateError flag."); } const rc = Object.create(null); oargs.vfs = args.vfs; | > > | > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | const wMsgHandler = { open: function(ev){ const oargs = Object.create(null), args = (ev.args || Object.create(null)); if(args.simulateError){ // undocumented internal testing option toss("Throwing because of simulateError flag."); } const rc = Object.create(null); let byteArray, pVfs; oargs.vfs = args.vfs; if(isSpecialDbFilename(args.filename)){ oargs.filename = args.filename || ""; }else{ oargs.filename = args.filename; byteArray = args.byteArray; if(byteArray) pVfs = guessVfs(args.filename); } if(pVfs){ /* 2022-11-02: this feature is as-yet untested except that sqlite3__wasm_vfs_create_file() has been tested from the browser dev console. */ let pMem; try{ pMem = sqlite3.wasm.allocFromTypedArray(byteArray); const rc = util.sqlite3__wasm_vfs_create_file( pVfs, oargs.filename, pMem, byteArray.byteLength ); if(rc) sqlite3.SQLite3Error.toss(rc); }catch(e){ throw new sqlite3.SQLite3Error( e.name+' creating '+args.filename+": "+e.message, { cause: e } ); }finally{ if(pMem) sqlite3.wasm.dealloc(pMem); } } const db = wState.open(oargs); rc.filename = db.filename; rc.persistent = !!sqlite3.capi.sqlite3_js_db_uses_vfs(db.pointer, "opfs"); rc.dbId = getDbId(db); rc.vfs = db.dbVfsName(); return rc; }, |
︙ | ︙ |
Changes to ext/wasm/api/sqlite3-opfs-async-proxy.js.
︙ | ︙ | |||
47 48 49 50 51 52 53 | synchronous, but we do do not use those APIs that way. i.e. we don't _need_ to change anything for this, but at some point (after Chrome versions (approximately) 104-107 are extinct) should change our usage of those methods to remove the "await". */ "use strict"; const wPost = (type,...args)=>postMessage({type, payload:args}); | | | 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | synchronous, but we do do not use those APIs that way. i.e. we don't _need_ to change anything for this, but at some point (after Chrome versions (approximately) 104-107 are extinct) should change our usage of those methods to remove the "await". */ "use strict"; const wPost = (type,...args)=>postMessage({type, payload:args}); const installAsyncProxy = function(self){ const toss = function(...args){throw new Error(args.join(' '))}; if(globalThis.window === globalThis){ toss("This code cannot run from the main thread.", "Load it as a Worker from a separate Worker."); }else if(!navigator?.storage?.getDirectory){ toss("This API requires navigator.storage.getDirectory."); } |
︙ | ︙ | |||
558 559 560 561 562 563 564 | }catch(e){ state.s11n.storeException(1,e); storeAndNotify(opName, state.sq3Codes.SQLITE_NOTFOUND); mTimeEnd(); wTimeEnd(); return; } | < < < < < < < < | 558 559 560 561 562 563 564 565 566 567 568 569 570 571 | }catch(e){ state.s11n.storeException(1,e); storeAndNotify(opName, state.sq3Codes.SQLITE_NOTFOUND); mTimeEnd(); wTimeEnd(); return; } const hFile = await hDir.getFileHandle(filenamePart, {create}); wTimeEnd(); const fh = Object.assign(Object.create(null),{ fid: fid, filenameAbs: filename, filenamePart: filenamePart, dirHandle: hDir, |
︙ | ︙ | |||
915 916 917 918 919 920 921 | }else if(!globalThis.FileSystemHandle || !globalThis.FileSystemDirectoryHandle || !globalThis.FileSystemFileHandle || !globalThis.FileSystemFileHandle.prototype.createSyncAccessHandle || !navigator?.storage?.getDirectory){ wPost('opfs-unavailable',"Missing required OPFS APIs."); }else{ | | | 907 908 909 910 911 912 913 914 915 | }else if(!globalThis.FileSystemHandle || !globalThis.FileSystemDirectoryHandle || !globalThis.FileSystemFileHandle || !globalThis.FileSystemFileHandle.prototype.createSyncAccessHandle || !navigator?.storage?.getDirectory){ wPost('opfs-unavailable',"Missing required OPFS APIs."); }else{ installAsyncProxy(self); } |
Changes to ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js.
︙ | ︙ | |||
1268 1269 1270 1271 1272 1273 1274 | } ); }/*extend sqlite3.oo1*/ thePool.log("VFS initialized."); return poolUtil; }).catch(async (e)=>{ await thePool.removeVfs().catch(()=>{}); | | | 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 | } ); }/*extend sqlite3.oo1*/ thePool.log("VFS initialized."); return poolUtil; }).catch(async (e)=>{ await thePool.removeVfs().catch(()=>{}); return e; }); }).catch((err)=>{ //error("rejecting promise:",err); return initPromises[vfsName] = Promise.reject(err); }); }/*installOpfsSAHPoolVfs()*/; }/*sqlite3ApiBootstrap.initializers*/); |
︙ | ︙ |
Changes to ext/wasm/api/sqlite3-vfs-opfs.c-pp.js.
︙ | ︙ | |||
419 420 421 422 423 424 425 | ].forEach((k)=>{ if(undefined === (state.sq3Codes[k] = capi[k])){ toss("Maintenance required: not found:",k); } }); state.opfsFlags = Object.assign(Object.create(null),{ /** | | | < < < < < < < < < < < < < < < | 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 | ].forEach((k)=>{ if(undefined === (state.sq3Codes[k] = capi[k])){ toss("Maintenance required: not found:",k); } }); state.opfsFlags = Object.assign(Object.create(null),{ /** Flag for use with xOpen(). "opfs-unlock-asap=1" enables this. See defaultUnlockAsap, below. */ OPFS_UNLOCK_ASAP: 0x01, /** If true, any async routine which implicitly acquires a sync access handle (i.e. an OPFS lock) will release that locks at the end of the call which acquires it. If false, such "autolocks" are not released until the VFS is idle for some brief amount of time. The benefit of enabling this is much higher concurrency. The |
︙ | ︙ | |||
886 887 888 889 890 891 892 | }, //xSleep is optionally defined below xOpen: function f(pVfs, zName, pFile, flags, pOutFlags){ mTimeStart('xOpen'); let opfsFlags = 0; if(0===zName){ zName = randomFilename(); | | < < < < | 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 | }, //xSleep is optionally defined below xOpen: function f(pVfs, zName, pFile, flags, pOutFlags){ mTimeStart('xOpen'); let opfsFlags = 0; if(0===zName){ zName = randomFilename(); }else if('number'===typeof zName){ if(capi.sqlite3_uri_boolean(zName, "opfs-unlock-asap", 0)){ /* -----------------------^^^^^ MUST pass the untranslated C-string here. */ opfsFlags |= state.opfsFlags.OPFS_UNLOCK_ASAP; } zName = wasm.cstrToJs(zName); } const fh = Object.create(null); fh.fid = pFile; fh.filename = zName; fh.sab = new SharedArrayBuffer(state.fileBufferSize); fh.flags = flags; const rc = opRun('xOpen', pFile, zName, flags, opfsFlags); |
︙ | ︙ |
Changes to ext/wasm/api/sqlite3-wasm.c.
︙ | ︙ | |||
541 542 543 544 545 546 547 | DefInt(SQLITE_CONFIG_WIN32_HEAPSIZE); DefInt(SQLITE_CONFIG_PCACHE_HDRSZ); DefInt(SQLITE_CONFIG_PMASZ); DefInt(SQLITE_CONFIG_STMTJRNL_SPILL); DefInt(SQLITE_CONFIG_SMALL_MALLOC); DefInt(SQLITE_CONFIG_SORTERREF_SIZE); DefInt(SQLITE_CONFIG_MEMDB_MAXSIZE); | < < < < | 541 542 543 544 545 546 547 548 549 550 551 552 553 554 | DefInt(SQLITE_CONFIG_WIN32_HEAPSIZE); DefInt(SQLITE_CONFIG_PCACHE_HDRSZ); DefInt(SQLITE_CONFIG_PMASZ); DefInt(SQLITE_CONFIG_STMTJRNL_SPILL); DefInt(SQLITE_CONFIG_SMALL_MALLOC); DefInt(SQLITE_CONFIG_SORTERREF_SIZE); DefInt(SQLITE_CONFIG_MEMDB_MAXSIZE); } _DefGroup; DefGroup(dataTypes) { DefInt(SQLITE_INTEGER); DefInt(SQLITE_FLOAT); DefInt(SQLITE_TEXT); DefInt(SQLITE_BLOB); |
︙ | ︙ | |||
1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 | ** a single i64 argument. */ SQLITE_WASM_EXPORT int sqlite3__wasm_config_j(int op, sqlite3_int64 arg){ return sqlite3_config(op, arg); } /* ** This function is NOT part of the sqlite3 public API. It is strictly ** for use by the sqlite project's own JS/WASM bindings. ** | > > > | > > > > > > | > > | | > > > > > | < < < < < < | > | 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 | ** a single i64 argument. */ SQLITE_WASM_EXPORT int sqlite3__wasm_config_j(int op, sqlite3_int64 arg){ return sqlite3_config(op, arg); } #if 0 // Pending removal after verification of a workaround discussed in the // forum post linked to below. /* ** This function is NOT part of the sqlite3 public API. It is strictly ** for use by the sqlite project's own JS/WASM bindings. ** ** Returns a pointer to sqlite3_free(). In compliant browsers the ** return value, when passed to sqlite3.wasm.exports.functionEntry(), ** must resolve to the same function as ** sqlite3.wasm.exports.sqlite3_free. i.e. from a dev console where ** sqlite3 is exported globally, the following must be true: ** ** ``` ** sqlite3.wasm.functionEntry( ** sqlite3.wasm.exports.sqlite3__wasm_ptr_to_sqlite3_free() ** ) === sqlite3.wasm.exports.sqlite3_free ** ``` ** ** Using a function to return this pointer, as opposed to exporting it ** via sqlite3__wasm_enum_json(), is an attempt to work around a ** Safari-specific quirk covered at ** https://sqlite.org/forum/info/e5b20e1feb37a19a. **/ SQLITE_WASM_EXPORT void * sqlite3__wasm_ptr_to_sqlite3_free(void){ return (void*)sqlite3_free; } #endif #if defined(__EMSCRIPTEN__) && defined(SQLITE_ENABLE_WASMFS) #include <emscripten/wasmfs.h> /* ** This function is NOT part of the sqlite3 public API. It is strictly ** for use by the sqlite project's own JS/WASM bindings, specifically |
︙ | ︙ |
Changes to ext/wasm/api/sqlite3-worker1-promiser.c-pp.js.
︙ | ︙ | |||
38 39 40 41 42 43 44 | config option may alternately be a function, in which case this function re-assigns this property with the result of calling that function, enabling delayed instantiation of a Worker. - `onready` (optional, but...): this callback is called with no arguments when the worker fires its initial 'sqlite3-api'/'worker1-ready' message, which it does when | | | | < < < < | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | config option may alternately be a function, in which case this function re-assigns this property with the result of calling that function, enabling delayed instantiation of a Worker. - `onready` (optional, but...): this callback is called with no arguments when the worker fires its initial 'sqlite3-api'/'worker1-ready' message, which it does when sqlite3.initWorker1API() completes its initialization. This is the simplest way to tell the worker to kick off work at the earliest opportunity. - `onunhandled` (optional): a callback which gets passed the message event object for any worker.onmessage() events which are not handled by this proxy. Ideally that "should" never happen, as this proxy aims to handle all known message types. - `generateMessageId` (optional): a function which, when passed an |
︙ | ︙ | |||
203 204 205 206 207 208 209 | msg = arguments[0]; }else if(2===arguments.length){ msg = Object.create(null); msg.type = arguments[0]; msg.args = arguments[1]; msg.dbId = msg.args.dbId; }else{ | | | 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | msg = arguments[0]; }else if(2===arguments.length){ msg = Object.create(null); msg.type = arguments[0]; msg.args = arguments[1]; msg.dbId = msg.args.dbId; }else{ toss("Invalid arugments for sqlite3Worker1Promiser()-created factory."); } if(!msg.dbId && msg.type!=='open') msg.dbId = dbId; msg.messageId = genMsgId(msg); msg.departureTime = performance.now(); const proxy = Object.create(null); proxy.message = msg; let rowCallbackId /* message handler ID for exec on-row callback proxy */; |
︙ | ︙ | |||
247 248 249 250 251 252 253 | debug("Posting",msg.type,"message to Worker dbId="+(dbId||'default')+':',msg); config.worker.postMessage(msg); }); if(rowCallbackId) p = p.finally(()=>delete handlerMap[rowCallbackId]); return p; }; }/*sqlite3Worker1Promiser()*/; | < | | < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 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 | debug("Posting",msg.type,"message to Worker dbId="+(dbId||'default')+':',msg); config.worker.postMessage(msg); }); if(rowCallbackId) p = p.finally(()=>delete handlerMap[rowCallbackId]); return p; }; }/*sqlite3Worker1Promiser()*/; globalThis.sqlite3Worker1Promiser.defaultConfig = { worker: function(){ //#if target=es6-bundler-friendly return new Worker(new URL("sqlite3-worker1-bundler-friendly.mjs", import.meta.url),{ type: 'module' }); //#else let theJs = "sqlite3-worker1.js"; if(this.currentScript){ const src = this.currentScript.src.split('/'); src.pop(); theJs = src.join('/')+'/' + theJs; //sqlite3.config.warn("promiser currentScript, theJs =",this.currentScript,theJs); }else if(globalThis.location){ //sqlite3.config.warn("promiser globalThis.location =",globalThis.location); const urlParams = new URL(globalThis.location.href).searchParams; if(urlParams.has('sqlite3.dir')){ theJs = urlParams.get('sqlite3.dir') + '/' + theJs; } } return new Worker(theJs + globalThis.location.search); //#endif } //#ifnot target=es6-bundler-friendly .bind({ currentScript: globalThis?.document?.currentScript }) //#endif , onerror: (...args)=>console.error('worker1 promiser error',...args) }; //#else /* Built with the omit-oo1 flag. */ //#endif ifnot omit-oo1 |
Changes to ext/wasm/common/whwasmutil.js.
︙ | ︙ | |||
1378 1379 1380 1381 1382 1383 1384 | Looks up a WASM-exported function named fname from target.exports. If found, it is called, passed all remaining arguments, and its return value is returned to xCall's caller. If not found, an exception is thrown. This function does no conversion of argument or return types, but see xWrap() and xCallWrapped() for variants which do. | < < < < | | | 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 | Looks up a WASM-exported function named fname from target.exports. If found, it is called, passed all remaining arguments, and its return value is returned to xCall's caller. If not found, an exception is thrown. This function does no conversion of argument or return types, but see xWrap() and xCallWrapped() for variants which do. As a special case, if passed only 1 argument after the name and that argument in an Array, that array's entries become the function arguments. (This is not an ambiguous case because it's not legal to pass an Array object to a WASM function.) */ target.xCall = function(fname, ...args){ const f = target.xGet(fname); if(!(f instanceof Function)) toss("Exported symbol",fname,"is not a function."); if(f.length!==args.length) __argcMismatch(fname,f.length) /* This is arguably over-pedantic but we want to help clients keep from shooting themselves in the foot when calling C APIs. */; return (2===arguments.length && Array.isArray(arguments[1])) ? f.apply(null, arguments[1]) : f.apply(null, args); }; |
︙ | ︙ | |||
1537 1538 1539 1540 1541 1542 1543 | is solely for debugging and error-reporting purposes. If not provided, an empty string is assumed. - signature: a function signature string compatible with jsFuncToWasm(). - bindScope (string): one of ('transient', 'context', | | | 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 | is solely for debugging and error-reporting purposes. If not provided, an empty string is assumed. - signature: a function signature string compatible with jsFuncToWasm(). - bindScope (string): one of ('transient', 'context', 'singleton'). Bind scopes are: - 'transient': it will convert JS functions to WASM only for the duration of the xWrap()'d function call, using scopedInstallFunction(). Before that call returns, the WASM-side binding will be uninstalled. - 'singleton': holds one function-pointer binding for this |
︙ | ︙ | |||
1787 1788 1789 1790 1791 1792 1793 | const __xArgAdapterCheck = (t)=>xArg.get(t) || toss("Argument adapter not found:",t); const __xResultAdapterCheck = (t)=>xResult.get(t) || toss("Result adapter not found:",t); | < < < < < < < < < < < < < < < < < < | 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 | const __xArgAdapterCheck = (t)=>xArg.get(t) || toss("Argument adapter not found:",t); const __xResultAdapterCheck = (t)=>xResult.get(t) || toss("Result adapter not found:",t); cache.xWrap.convertArg = (t,...args)=>__xArgAdapterCheck(t)(...args); cache.xWrap.convertArgNoCheck = (t,...args)=>xArg.get(t)(...args); cache.xWrap.convertResult = (t,v)=>(null===t ? v : (t ? __xResultAdapterCheck(t)(v) : undefined)); cache.xWrap.convertResultNoCheck = (t,v)=>(null===t ? v : (t ? xResult.get(t)(v) : undefined)); /** Creates a wrapper for another function which converts the arguments of the wrapper to argument types accepted by the wrapped function, then converts the wrapped function's result to another form |
︙ | ︙ | |||
1921 1922 1923 1924 1925 1926 1927 | client has already allocated and it's passed on as a WASM pointer. - `string` or `utf8` (results): treats the result value as a const C-string, encoded as UTF-8, copies it to a JS string, and returns that JS string. | | | | | | | | | | | 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 | client has already allocated and it's passed on as a WASM pointer. - `string` or `utf8` (results): treats the result value as a const C-string, encoded as UTF-8, copies it to a JS string, and returns that JS string. - `string:dealloc` or `utf8:dealloc) (results): treats the result value as a non-const UTF-8 C-string, ownership of which has just been transfered to the caller. It copies the C-string to a JS string, frees the C-string, and returns the JS string. If such a result value is NULL, the JS result is `null`. Achtung: when using an API which returns results from a specific allocator, e.g. `my_malloc()`, this conversion _is not legal_. Instead, an equivalent conversion which uses the appropriate deallocator is required. For example: ```js target.xWrap.resultAdapter('string:my_free',(i)=>{ try { return i ? target.cstrToJs(i) : null } finally{ target.exports.my_free(i) } }; ``` |
︙ | ︙ | |||
2030 2031 2032 2033 2034 2035 2036 | AbstractArgAdapter.convertArgs() gets its 2nd+ arguments, and how FuncPtrAdapter.contextKey() gets its args, is also an implementation detail and subject to change. i.e. the public interface of 1 argument is stable. The fact that any arguments may be passed in after that one, and what those arguments are, is _not_ part of the public interface and is _not_ stable. | < < < < | | 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 | AbstractArgAdapter.convertArgs() gets its 2nd+ arguments, and how FuncPtrAdapter.contextKey() gets its args, is also an implementation detail and subject to change. i.e. the public interface of 1 argument is stable. The fact that any arguments may be passed in after that one, and what those arguments are, is _not_ part of the public interface and is _not_ stable. */ for(const i in args) args[i] = cxw.convertArgNoCheck( argTypes[i], args[i], args, i ); return cxw.convertResultNoCheck(resultType, xf.apply(null,args)); }finally{ target.scopedAllocPop(scope); } }; |
︙ | ︙ |
Deleted ext/wasm/demo-worker1-promiser.c-pp.html.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted ext/wasm/demo-worker1-promiser.c-pp.js.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Added ext/wasm/demo-worker1-promiser.html.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | <!doctype html> <html lang="en-us"> <head> <meta charset="utf-8"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon"> <link rel="stylesheet" href="common/emscripten.css"/> <link rel="stylesheet" href="common/testing.css"/> <title>worker-promise tests</title> </head> <body> <header id='titlebar'><span>worker-promise tests</span></header> <!-- emscripten bits --> <figure id="module-spinner"> <div class="spinner"></div> <div class='center'><strong>Initializing app...</strong></div> <div class='center'> On a slow internet connection this may take a moment. If this message displays for "a long time", intialization may have failed and the JavaScript console may contain clues as to why. </div> </figure> <div class="emscripten" id="module-status">Downloading...</div> <div class="emscripten"> <progress value="0" max="100" id="module-progress" hidden='1'></progress> </div><!-- /emscripten bits --> <div>Most stuff on this page happens in the dev console.</div> <hr> <div id='test-output'></div> <script src="common/SqliteTestUtil.js"></script> <script src="jswasm/sqlite3-worker1-promiser.js"></script> <script src="demo-worker1-promiser.js"></script> </body> </html> |
Added ext/wasm/demo-worker1-promiser.js.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | /* 2022-08-23 The author disclaims copyright to this source code. In place of a legal notice, here is a blessing: * May you do good and not evil. * May you find forgiveness for yourself and forgive others. * May you share freely, never taking more than you give. *********************************************************************** Demonstration of the sqlite3 Worker API #1 Promiser: a Promise-based proxy for for the sqlite3 Worker #1 API. */ 'use strict'; (function(){ const T = self.SqliteTestUtil; const eOutput = document.querySelector('#test-output'); const warn = console.warn.bind(console); const error = console.error.bind(console); const log = console.log.bind(console); const logHtml = async function(cssClass,...args){ log.apply(this, args); const ln = document.createElement('div'); if(cssClass) ln.classList.add(cssClass); ln.append(document.createTextNode(args.join(' '))); eOutput.append(ln); }; let startTime; const testCount = async ()=>{ logHtml("","Total test count:",T.counter+". Total time =",(performance.now() - startTime),"ms"); }; //why is this triggered even when we catch() a Promise? //window.addEventListener('unhandledrejection', function(event) { // warn('unhandledrejection',event); //}); const promiserConfig = { worker: ()=>{ const w = new Worker("jswasm/sqlite3-worker1.js"); w.onerror = (event)=>error("worker.onerror",event); return w; }, debug: 1 ? undefined : (...args)=>console.debug('worker debug',...args), onunhandled: function(ev){ error("Unhandled worker message:",ev.data); }, onready: function(){ T.affirm(arguments[0] === workerPromise /* as of version 3.46. Prior to that this callback had no arguments */); self.sqlite3TestModule.setStatus(null)/*hide the HTML-side is-loading spinner*/; runTests(); }, onerror: function(ev){ error("worker1 error:",ev); } }; const workerPromise = self.sqlite3Worker1Promiser(promiserConfig); delete self.sqlite3Worker1Promiser; const wtest = async function(msgType, msgArgs, callback){ if(2===arguments.length && 'function'===typeof msgArgs){ callback = msgArgs; msgArgs = undefined; } const p = 1 ? workerPromise({type: msgType, args:msgArgs}) : workerPromise(msgType, msgArgs); return callback ? p.then(callback).finally(testCount) : p; }; let sqConfig; const runTests = async function(){ const dbFilename = '/testing2.sqlite3'; startTime = performance.now(); await wtest('config-get', (ev)=>{ const r = ev.result; log('sqlite3.config subset:', r); T.assert('boolean' === typeof r.bigIntEnabled); sqConfig = r; }); logHtml('', "Sending 'open' message and waiting for its response before continuing..."); await wtest('open', { filename: dbFilename, simulateError: 0 /* if true, fail the 'open' */, }, function(ev){ const r = ev.result; log("then open result",r); T.assert(ev.dbId === r.dbId) .assert(ev.messageId) .assert('string' === typeof r.vfs); promiserConfig.dbId = ev.dbId; }).then(runTests2); }; const runTests2 = async function(){ const mustNotReach = ()=>toss("This is not supposed to be reached."); await wtest('exec',{ sql: ["create table t(a,b)", "insert into t(a,b) values(1,2),(3,4),(5,6)" ].join(';'), resultRows: [], columnNames: [], countChanges: sqConfig.bigIntEnabled ? 64 : true }, function(ev){ ev = ev.result; T.assert(0===ev.resultRows.length) .assert(0===ev.columnNames.length) .assert(sqConfig.bigIntEnabled ? (3n===ev.changeCount) : (3===ev.changeCount)); }); await wtest('exec',{ sql: 'select a a, b b from t order by a', resultRows: [], columnNames: [], }, function(ev){ ev = ev.result; T.assert(3===ev.resultRows.length) .assert(1===ev.resultRows[0][0]) .assert(6===ev.resultRows[2][1]) .assert(2===ev.columnNames.length) .assert('b'===ev.columnNames[1]); }); await wtest('exec',{ sql: 'select a a, b b from t order by a', resultRows: [], columnNames: [], rowMode: 'object', countChanges: true }, function(ev){ ev = ev.result; T.assert(3===ev.resultRows.length) .assert(1===ev.resultRows[0].a) .assert(6===ev.resultRows[2].b) .assert(0===ev.changeCount); }); await wtest( 'exec', {sql:'intentional_error'}, mustNotReach ).catch((e)=>{ warn("Intentional error:",e); }); await wtest('exec',{ sql:'select 1 union all select 3', resultRows: [] }, function(ev){ ev = ev.result; T.assert(2 === ev.resultRows.length) .assert(1 === ev.resultRows[0][0]) .assert(3 === ev.resultRows[1][0]) .assert(undefined === ev.changeCount); }); const resultRowTest1 = function f(ev){ if(undefined === f.counter) f.counter = 0; if(null === ev.rowNumber){ /* End of result set. */ T.assert(undefined === ev.row) .assert(2===ev.columnNames.length) .assert('a'===ev.columnNames[0]) .assert('B'===ev.columnNames[1]); }else{ T.assert(ev.rowNumber > 0); ++f.counter; } log("exec() result row:",ev); T.assert(null === ev.rowNumber || 'number' === typeof ev.row.B); }; await wtest('exec',{ sql: 'select a a, b B from t order by a limit 3', callback: resultRowTest1, rowMode: 'object' }, function(ev){ T.assert(3===resultRowTest1.counter); resultRowTest1.counter = 0; }); const resultRowTest2 = function f(ev){ if(null === ev.rowNumber){ /* End of result set. */ T.assert(undefined === ev.row) .assert(1===ev.columnNames.length) .assert('a'===ev.columnNames[0]) }else{ T.assert(ev.rowNumber > 0); f.counter = ev.rowNumber; } log("exec() result row:",ev); T.assert(null === ev.rowNumber || 'number' === typeof ev.row); }; await wtest('exec',{ sql: 'select a a from t limit 3', callback: resultRowTest2, rowMode: 0 }, function(ev){ T.assert(3===resultRowTest2.counter); }); const resultRowTest3 = function f(ev){ if(null === ev.rowNumber){ T.assert(3===ev.columnNames.length) .assert('foo'===ev.columnNames[0]) .assert('bar'===ev.columnNames[1]) .assert('baz'===ev.columnNames[2]); }else{ f.counter = ev.rowNumber; T.assert('number' === typeof ev.row); } }; await wtest('exec',{ sql: "select 'foo' foo, a bar, 'baz' baz from t limit 2", callback: resultRowTest3, columnNames: [], rowMode: '$bar' }, function(ev){ log("exec() result row:",ev); T.assert(2===resultRowTest3.counter); }); await wtest('exec',{ sql:[ 'pragma foreign_keys=0;', // ^^^ arbitrary query with no result columns 'select a, b from t order by a desc; select a from t;' // exec() only honors SELECT results from the first // statement with result columns (regardless of whether // it has any rows). ], rowMode: 1, resultRows: [] },function(ev){ const rows = ev.result.resultRows; T.assert(3===rows.length). assert(6===rows[0]); }); await wtest('exec',{sql: 'delete from t where a>3'}); await wtest('exec',{ sql: 'select count(a) from t', resultRows: [] },function(ev){ ev = ev.result; T.assert(1===ev.resultRows.length) .assert(2===ev.resultRows[0][0]); }); await wtest('export', function(ev){ ev = ev.result; T.assert('string' === typeof ev.filename) .assert(ev.byteArray instanceof Uint8Array) .assert(ev.byteArray.length > 1024) .assert('application/x-sqlite3' === ev.mimetype); }); /***** close() tests must come last. *****/ await wtest('close',{},function(ev){ T.assert('string' === typeof ev.result.filename); }); await wtest('close', (ev)=>{ T.assert(undefined === ev.result.filename); }).finally(()=>logHtml('',"That's all, folks!")); }/*runTests2()*/; log("Init complete, but async init bits may still be running."); })(); |
Changes to ext/wasm/dist.make.
︙ | ︙ | |||
15 16 17 18 19 20 21 | ######################################################################## # Chicken/egg situation: we need $(bin.version-info) to get the # version info for the archive name, but that binary may not yet be # built, and won't be built until we expand the dependencies. Thus we # have to use a temporary name for the archive until we can get # that binary built. | < < < < < | | | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | ######################################################################## # Chicken/egg situation: we need $(bin.version-info) to get the # version info for the archive name, but that binary may not yet be # built, and won't be built until we expand the dependencies. Thus we # have to use a temporary name for the archive until we can get # that binary built. ifeq (,$(filter snapshot,$(MAKECMDGOALS))) dist-name-prefix := sqlite-wasm else dist-name-prefix := sqlite-wasm-snapshot-$(shell /usr/bin/date +%Y%m%d) endif dist-name := $(dist-name-prefix)-TEMP ######################################################################## # dist.build must be the name of a target which triggers the build of # the files to be packed into the dist archive. The intention is that # it be one of (o0, o1, o2, o3, os, oz), each of which uses like-named |
︙ | ︙ | |||
50 51 52 53 54 55 56 | dist-dir.common := $(dist-dir.top)/common dist.top.extras := \ demo-123.html demo-123-worker.html demo-123.js \ tester1.html tester1-worker.html tester1-esm.html \ tester1.js tester1.mjs \ demo-jsstorage.html demo-jsstorage.js \ demo-worker1.html demo-worker1.js \ | | < | < < < < < | < < | 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 | dist-dir.common := $(dist-dir.top)/common dist.top.extras := \ demo-123.html demo-123-worker.html demo-123.js \ tester1.html tester1-worker.html tester1-esm.html \ tester1.js tester1.mjs \ demo-jsstorage.html demo-jsstorage.js \ demo-worker1.html demo-worker1.js \ demo-worker1-promiser.html demo-worker1-promiser.js dist.jswasm.extras := $(sqlite3-api.ext.jses) $(sqlite3.wasm) dist.common.extras := \ $(wildcard $(dir.common)/*.css) \ $(dir.common)/SqliteTestUtil.js .PHONY: dist snapshot # DIST_STRIP_COMMENTS $(call)able to be used in stripping C-style # from the dist copies of certain files. # # $1 = source js file # $2 = flags for $(bin.stripcomments) define DIST_STRIP_COMMENTS $(bin.stripccomments) $(2) < $(1) > $(dist-dir.jswasm)/$(notdir $(1)) || exit; endef # STRIP_K1.js = list of JS files which need to be passed through # $(bin.stripcomments) with a single -k flag. STRIP_K1.js := $(sqlite3-worker1.js) $(sqlite3-worker1-promiser.js) \ $(sqlite3-worker1-bundler-friendly.js) $(sqlite3-worker1-promiser-bundler-friendly.js) # STRIP_K2.js = list of JS files which need to be passed through # $(bin.stripcomments) with two -k flags. STRIP_K2.js := $(sqlite3.js) $(sqlite3.mjs) \ $(sqlite3-bundler-friendly.mjs) $(sqlite3-node.mjs) ######################################################################## # dist: create the end-user deliverable archive. # # Maintenance reminder: because dist depends on $(dist.build), and # $(dist.build) will depend on clean, having any deps on # $(dist-archive) which themselves may be cleaned up by the clean # target will lead to grief in parallel builds (-j #). Thus # dist's deps must be trimmed to non-generated files or # files which are _not_ cleaned up by the clean target. # # Note that we require $(bin.version-info) in order to figure out the # dist file's name, so cannot (without a recursive make) have the # target name equal to the archive name. dist: \ $(bin.stripccomments) $(bin.version-info) \ $(dist.build) $(STRIP_K1.js) $(STRIP_K2.js) \ $(MAKEFILE) $(MAKEFILE.dist) @echo "Making end-user deliverables..." @rm -fr $(dist-dir.top) @mkdir -p $(dist-dir.jswasm) $(dist-dir.common) @cp -p $(dist.top.extras) $(dist-dir.top) @cp -p README-dist.txt $(dist-dir.top)/README.txt @cp -p index-dist.html $(dist-dir.top)/index.html |
︙ | ︙ |
Changes to ext/wasm/fiddle/fiddle.js.
︙ | ︙ | |||
757 758 759 760 761 762 763 | " SELECT max(iter), cx, cy FROM m GROUP BY cx, cy\n", " ),\n", " a(t) AS (\n", " SELECT group_concat( substr(' .+*#', 1+min(iter/7,4), 1), '') \n", " FROM m2 GROUP BY cy\n", " )\n", "SELECT group_concat(rtrim(t),x'0a') as Mandelbrot FROM a;\n", | | < < < < < < | 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 | " SELECT max(iter), cx, cy FROM m GROUP BY cx, cy\n", " ),\n", " a(t) AS (\n", " SELECT group_concat( substr(' .+*#', 1+min(iter/7,4), 1), '') \n", " FROM m2 GROUP BY cy\n", " )\n", "SELECT group_concat(rtrim(t),x'0a') as Mandelbrot FROM a;\n", ]} ]; const newOpt = function(lbl,val){ const o = document.createElement('option'); if(Array.isArray(val)) val = val.join(''); o.value = val; if(!val) o.setAttribute('disabled',true); o.appendChild(document.createTextNode(lbl)); |
︙ | ︙ |
Changes to ext/wasm/index-dist.html.
︙ | ︙ | |||
93 94 95 96 97 98 99 | demo of using the key-value VFS for storing a persistent db in JS <code>localStorage</code> or <code>sessionStorage</code>.</li> <li><a href='demo-worker1.html'>demo-worker1</a>: Worker-based wrapper of the OO API #1. Its Promise-based wrapper is significantly easier to use, however.</li> <li><a href='demo-worker1-promiser.html'>demo-worker1-promiser</a>: a demo of the Promise-based wrapper of the Worker1 API.</li> | < < | 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | demo of using the key-value VFS for storing a persistent db in JS <code>localStorage</code> or <code>sessionStorage</code>.</li> <li><a href='demo-worker1.html'>demo-worker1</a>: Worker-based wrapper of the OO API #1. Its Promise-based wrapper is significantly easier to use, however.</li> <li><a href='demo-worker1-promiser.html'>demo-worker1-promiser</a>: a demo of the Promise-based wrapper of the Worker1 API.</li> </ul> </li> </ul> </div> <style> #test-list { font-size: 120%; } </style> |
︙ | ︙ |
Changes to ext/wasm/index.html.
︙ | ︙ | |||
80 81 82 83 84 85 86 | demo of using the key-value VFS for storing a persistent db in JS <code>localStorage</code> or <code>sessionStorage</code>.</li> <li><a href='demo-worker1.html'>demo-worker1</a>: Worker-based wrapper of the OO API #1. Its Promise-based wrapper is significantly easier to use, however.</li> <li><a href='demo-worker1-promiser.html'>demo-worker1-promiser</a>: a demo of the Promise-based wrapper of the Worker1 API.</li> | < < | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | demo of using the key-value VFS for storing a persistent db in JS <code>localStorage</code> or <code>sessionStorage</code>.</li> <li><a href='demo-worker1.html'>demo-worker1</a>: Worker-based wrapper of the OO API #1. Its Promise-based wrapper is significantly easier to use, however.</li> <li><a href='demo-worker1-promiser.html'>demo-worker1-promiser</a>: a demo of the Promise-based wrapper of the Worker1 API.</li> </ul> </li> <li>speedtest1 ports (sqlite3's primary benchmarking tool)... <ul> <li><a href='speedtest1.html'>speedtest1</a>: a main-thread WASM build of speedtest1.</li> <li><a href='speedtest1.html?vfs=kvvfs'>speedtest1?vfs=kvvfs</a>: speedtest1 with the kvvfs.</li> <li><a href='speedtest1-worker.html?size=15'>speedtest1-worker</a>: an interactive Worker-thread variant of speedtest1.</li> |
︙ | ︙ |
Changes to ext/wasm/tester1.c-pp.js.
︙ | ︙ | |||
1478 1479 1480 1481 1482 1483 1484 | T.assert(0===st.columnCount); const ndx = st.getParamIndex(':b'); T.assert(1===ndx); st.bindAsBlob(ndx, "ima blob") /*step() skipped intentionally*/.reset(true); } finally { T.assert(0===st.finalize()) | | | 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 | T.assert(0===st.columnCount); const ndx = st.getParamIndex(':b'); T.assert(1===ndx); st.bindAsBlob(ndx, "ima blob") /*step() skipped intentionally*/.reset(true); } finally { T.assert(0===st.finalize()) .assert(undefined===st.finalize()); } try { db.prepare("/*empty SQL*/"); toss("Must not be reached."); }catch(e){ T.assert(e instanceof sqlite3.SQLite3Error) |
︙ | ︙ | |||
2583 2584 2585 2586 2587 2588 2589 | predicate: ()=>(isUIThread() || "local/sessionStorage are unavailable in a Worker"), test: function(sqlite3){ const filename = this.kvvfsDbFile = 'session'; const pVfs = capi.sqlite3_vfs_find('kvvfs'); T.assert(pVfs); const JDb = this.JDb = sqlite3.oo1.JsStorageDb; | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 | predicate: ()=>(isUIThread() || "local/sessionStorage are unavailable in a Worker"), test: function(sqlite3){ const filename = this.kvvfsDbFile = 'session'; const pVfs = capi.sqlite3_vfs_find('kvvfs'); T.assert(pVfs); const JDb = this.JDb = sqlite3.oo1.JsStorageDb; const unlink = this.kvvfsUnlink = ()=>{JDb.clearStorage(filename)}; unlink(); let db = new JDb(filename); try { db.exec([ 'create table kvvfs(a);', 'insert into kvvfs(a) values(1),(2),(3)' ]); T.assert(3 === db.selectValue('select count(*) from kvvfs')); db.close(); db = new JDb(filename); db.exec('insert into kvvfs(a) values(4),(5),(6)'); T.assert(6 === db.selectValue('select count(*) from kvvfs')); }finally{ db.close(); } } }/*kvvfs sanity checks*/) ;/* end kvvfs tests */ //////////////////////////////////////////////////////////////////////// T.g('Hook APIs') .t({ name: "sqlite3_commit/rollback/update_hook()", predicate: ()=>wasm.bigIntEnabled || "Update hook requires int64", |
︙ | ︙ | |||
2938 2939 2940 2941 2942 2943 2944 | //////////////////////////////////////////////////////////////////////// T.g('OPFS: Origin-Private File System', (sqlite3)=>(sqlite3.capi.sqlite3_vfs_find("opfs") || 'requires "opfs" VFS')) .t({ name: 'OPFS db sanity checks', test: async function(sqlite3){ | < < | > | > | < < | | > > > < < < < < < | < < > < < | 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 | //////////////////////////////////////////////////////////////////////// T.g('OPFS: Origin-Private File System', (sqlite3)=>(sqlite3.capi.sqlite3_vfs_find("opfs") || 'requires "opfs" VFS')) .t({ name: 'OPFS db sanity checks', test: async function(sqlite3){ const filename = this.opfsDbFile = '/dir/sqlite3-tester1.db'; const pVfs = this.opfsVfs = capi.sqlite3_vfs_find('opfs'); T.assert(pVfs); const unlink = this.opfsUnlink = (fn=filename)=>{sqlite3.util.sqlite3__wasm_vfs_unlink(pVfs,fn)}; unlink(); let db = new sqlite3.oo1.OpfsDb(filename); try { db.exec([ 'create table p(a);', 'insert into p(a) values(1),(2),(3)' ]); T.assert(3 === db.selectValue('select count(*) from p')); db.close(); db = new sqlite3.oo1.OpfsDb(filename); db.exec('insert into p(a) values(4),(5),(6)'); T.assert(6 === db.selectValue('select count(*) from p')); this.opfsDbExport = capi.sqlite3_js_db_export(db); T.assert(this.opfsDbExport instanceof Uint8Array) .assert(this.opfsDbExport.byteLength>0 && 0===this.opfsDbExport.byteLength % 512); }finally{ db.close(); unlink(); } } }/*OPFS db sanity checks*/) .t({ name: 'OPFS import', test: async function(sqlite3){ let db; try { const exp = this.opfsDbExport; const filename = this.opfsDbFile; delete this.opfsDbExport; this.opfsImportSize = await sqlite3.oo1.OpfsDb.importDb(filename, exp); db = new sqlite3.oo1.OpfsDb(this.opfsDbFile); T.assert(6 === db.selectValue('select count(*) from p')). assert( this.opfsImportSize == exp.byteLength ); db.close(); this.opfsUnlink(filename); T.assert(!(await sqlite3.opfs.entryExists(filename))); // Try again with a function as an input source: let cursor = 0; const blockSize = 512, end = exp.byteLength; const reader = async function(){ if(cursor >= exp.byteLength){ |
︙ | ︙ | |||
3012 3013 3014 3015 3016 3017 3018 3019 | } } }/*OPFS export/import*/) .t({ name: '(Internal-use) OPFS utility APIs', test: async function(sqlite3){ const filename = this.opfsDbFile; const unlink = this.opfsUnlink; | > | > | 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 | } } }/*OPFS export/import*/) .t({ name: '(Internal-use) OPFS utility APIs', test: async function(sqlite3){ const filename = this.opfsDbFile; const pVfs = this.opfsVfs; const unlink = this.opfsUnlink; T.assert(filename && pVfs && !!unlink); delete this.opfsDbFile; delete this.opfsVfs; delete this.opfsUnlink; /************************************************************** ATTENTION CLIENT-SIDE USERS: sqlite3.opfs is NOT intended for client-side use. It is only for this project's own internal use. Its APIs are subject to change or removal at any time. ***************************************************************/ |
︙ | ︙ |
Changes to src/alter.c.
︙ | ︙ | |||
2258 2259 2260 2261 2262 2263 2264 | regOut = reg+1+iPos-(iPos>iColPos); }else{ regOut = reg+1+nField; } if( i==pTab->iPKey ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regOut); }else{ | < < < < < | 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 | regOut = reg+1+iPos-(iPos>iColPos); }else{ regOut = reg+1+nField; } if( i==pTab->iPKey ){ sqlite3VdbeAddOp2(v, OP_Null, 0, regOut); }else{ sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut); } nField++; } } if( nField==0 ){ /* dbsqlfuzz 5f09e7bcc78b4954d06bf9f2400d7715f48d1fef */ pParse->nMem++; |
︙ | ︙ |
Changes to src/btree.c.
︙ | ︙ | |||
5139 5140 5141 5142 5143 5144 5145 | }else{ pCur->aOverflow = aNew; } } memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno)); pCur->curFlags |= BTCF_ValidOvfl; }else{ | < < < < < < | 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 | }else{ pCur->aOverflow = aNew; } } memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno)); pCur->curFlags |= BTCF_ValidOvfl; }else{ /* If the overflow page-list cache has been allocated and the ** entry for the first required overflow page is valid, skip ** directly to it. */ if( pCur->aOverflow[offset/ovflSize] ){ iIdx = (offset/ovflSize); nextPage = pCur->aOverflow[iIdx]; |
︙ | ︙ | |||
5626 5627 5628 5629 5630 5631 5632 | assert( pCur->pgnoRoot==0 || (pCur->pPage!=0 && pCur->pPage->nCell==0) ); *pRes = 1; rc = SQLITE_OK; } return rc; } | < < < < < < < < < < < < < < < < < | 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 | assert( pCur->pgnoRoot==0 || (pCur->pPage!=0 && pCur->pPage->nCell==0) ); *pRes = 1; rc = SQLITE_OK; } return rc; } /* Move the cursor to the last entry in the table. Return SQLITE_OK ** on success. Set *pRes to 0 if the cursor actually points to something ** or set *pRes to 1 if the table is empty. */ static SQLITE_NOINLINE int btreeLast(BtCursor *pCur, int *pRes){ int rc = moveToRoot(pCur); if( rc==SQLITE_OK ){ |
︙ | ︙ | |||
5671 5672 5673 5674 5675 5676 5677 | } int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ assert( cursorOwnsBtShared(pCur) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); /* If the cursor already points to the last entry, this is a no-op. */ if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){ | > > > > > > > | > > > > | 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 | } int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ assert( cursorOwnsBtShared(pCur) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); /* If the cursor already points to the last entry, this is a no-op. */ if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){ #ifdef SQLITE_DEBUG /* This block serves to assert() that the cursor really does point ** to the last entry in the b-tree. */ int ii; for(ii=0; ii<pCur->iPage; ii++){ assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell ); } assert( pCur->ix==pCur->pPage->nCell-1 || CORRUPT_DB ); testcase( pCur->ix!=pCur->pPage->nCell-1 ); /* ^-- dbsqlfuzz b92b72e4de80b5140c30ab71372ca719b8feb618 */ assert( pCur->pPage->leaf ); #endif *pRes = 0; return SQLITE_OK; } return btreeLast(pCur, pRes); } /* Move the cursor so that it points to an entry in a table (a.k.a INTKEY) |
︙ | ︙ | |||
5724 5725 5726 5727 5728 5729 5730 | if( pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0 ){ if( pCur->info.nKey==intKey ){ *pRes = 0; return SQLITE_OK; } if( pCur->info.nKey<intKey ){ if( (pCur->curFlags & BTCF_AtLast)!=0 ){ | < | 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 | if( pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0 ){ if( pCur->info.nKey==intKey ){ *pRes = 0; return SQLITE_OK; } if( pCur->info.nKey<intKey ){ if( (pCur->curFlags & BTCF_AtLast)!=0 ){ *pRes = -1; return SQLITE_OK; } /* If the requested key is one more than the previous key, then ** try to get there using sqlite3BtreeNext() rather than a full ** binary search. This is an optimization only. The correct answer ** is still obtained without this case, only a little more slowly. */ |
︙ | ︙ | |||
9530 9531 9532 9533 9534 9535 9536 | return SQLITE_OK; } dropCell(pPage, idx, info.nSize, &rc); if( rc ) goto end_insert; }else if( loc<0 && pPage->nCell>0 ){ assert( pPage->leaf ); idx = ++pCur->ix; | | | 9517 9518 9519 9520 9521 9522 9523 9524 9525 9526 9527 9528 9529 9530 9531 | return SQLITE_OK; } dropCell(pPage, idx, info.nSize, &rc); if( rc ) goto end_insert; }else if( loc<0 && pPage->nCell>0 ){ assert( pPage->leaf ); idx = ++pCur->ix; pCur->curFlags &= ~BTCF_ValidNKey; }else{ assert( pPage->leaf ); } rc = insertCellFast(pPage, idx, newCell, szNew); assert( pPage->nOverflow==0 || rc==SQLITE_OK ); assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 ); |
︙ | ︙ | |||
9560 9561 9562 9563 9564 9565 9566 | ** the b-tree if possible. If the cursor is left pointing to the last ** entry in the table, and the next row inserted has an integer key ** larger than the largest existing key, it is possible to insert the ** row without seeking the cursor. This can be a big performance boost. */ if( pPage->nOverflow ){ assert( rc==SQLITE_OK ); | | | 9547 9548 9549 9550 9551 9552 9553 9554 9555 9556 9557 9558 9559 9560 9561 | ** the b-tree if possible. If the cursor is left pointing to the last ** entry in the table, and the next row inserted has an integer key ** larger than the largest existing key, it is possible to insert the ** row without seeking the cursor. This can be a big performance boost. */ if( pPage->nOverflow ){ assert( rc==SQLITE_OK ); pCur->curFlags &= ~(BTCF_ValidNKey); rc = balance(pCur); /* Must make sure nOverflow is reset to zero even if the balance() ** fails. Internal data structure corruption will result otherwise. ** Also, set the cursor state to invalid. This stops saveCursorPosition() ** from trying to save the current position of the cursor. */ pCur->pPage->nOverflow = 0; |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
2824 2825 2826 2827 2828 2829 2830 | SelectDest dest; /* Where the SELECT should store results */ int regYield; /* Register holding co-routine entry-point */ int addrTop; /* Top of the co-routine */ int regRec; /* A record to be insert into the new table */ int regRowid; /* Rowid of the next row to insert */ int addrInsLoop; /* Top of the loop for inserting rows */ Table *pSelTab; /* A table that describes the SELECT results */ | < < > | > | | | | 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 | SelectDest dest; /* Where the SELECT should store results */ int regYield; /* Register holding co-routine entry-point */ int addrTop; /* Top of the co-routine */ int regRec; /* A record to be insert into the new table */ int regRowid; /* Rowid of the next row to insert */ int addrInsLoop; /* Top of the loop for inserting rows */ Table *pSelTab; /* A table that describes the SELECT results */ if( IN_SPECIAL_PARSE ){ pParse->rc = SQLITE_ERROR; pParse->nErr++; return; } regYield = ++pParse->nMem; regRec = ++pParse->nMem; regRowid = ++pParse->nMem; assert(pParse->nTab==1); sqlite3MayAbort(pParse); sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb); sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG); pParse->nTab = 2; addrTop = sqlite3VdbeCurrentAddr(v) + 1; sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); if( pParse->nErr ) return; pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect, SQLITE_AFF_BLOB); if( pSelTab==0 ) return; assert( p->aCol==0 ); p->nCol = p->nNVCol = pSelTab->nCol; p->aCol = pSelTab->aCol; pSelTab->nCol = 0; pSelTab->aCol = 0; sqlite3DeleteTable(db, pSelTab); sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); sqlite3Select(pParse, pSelect, &dest); if( pParse->nErr ) return; sqlite3VdbeEndCoroutine(v, regYield); sqlite3VdbeJumpHere(v, addrTop - 1); addrInsLoop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_MakeRecord, dest.iSdst, dest.nSdst, regRec); sqlite3TableAffinity(v, p, 0); sqlite3VdbeAddOp2(v, OP_NewRowid, 1, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, 1, regRec, regRowid); sqlite3VdbeGoto(v, addrInsLoop); sqlite3VdbeJumpHere(v, addrInsLoop); sqlite3VdbeAddOp1(v, OP_Close, 1); } /* Compute the complete text of the CREATE statement */ if( pSelect ){ zStmt = createTableStmt(db, p); }else{ Token *pEnd2 = tabOpts ? &pParse->sLastToken : pEnd; |
︙ | ︙ | |||
2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 | /* Test for cycles in generated columns and illegal expressions ** in CHECK constraints and in DEFAULT clauses. */ if( p->tabFlags & TF_HasGenerated ){ sqlite3VdbeAddOp4(v, OP_SqlExec, 0x0001, 0, 0, sqlite3MPrintf(db, "SELECT*FROM\"%w\".\"%w\"", db->aDb[iDb].zDbSName, p->zName), P4_DYNAMIC); } } /* Add the table to the in-memory representation of the database. */ if( db->init.busy ){ Table *pOld; Schema *pSchema = p->pSchema; | > > > | 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 | /* Test for cycles in generated columns and illegal expressions ** in CHECK constraints and in DEFAULT clauses. */ if( p->tabFlags & TF_HasGenerated ){ sqlite3VdbeAddOp4(v, OP_SqlExec, 0x0001, 0, 0, sqlite3MPrintf(db, "SELECT*FROM\"%w\".\"%w\"", db->aDb[iDb].zDbSName, p->zName), P4_DYNAMIC); } sqlite3VdbeAddOp4(v, OP_SqlExec, 0x0001, 0, 0, sqlite3MPrintf(db, "PRAGMA \"%w\".integrity_check(%Q)", db->aDb[iDb].zDbSName, p->zName), P4_DYNAMIC); } /* Add the table to the in-memory representation of the database. */ if( db->init.busy ){ Table *pOld; Schema *pSchema = p->pSchema; |
︙ | ︙ | |||
2999 3000 3001 3002 3003 3004 3005 | p = pParse->pNewTable; if( p==0 || pParse->nErr ) goto create_view_fail; /* Legacy versions of SQLite allowed the use of the magic "rowid" column ** on a view, even though views do not have rowids. The following flag ** setting fixes this problem. But the fix can be disabled by compiling ** with -DSQLITE_ALLOW_ROWID_IN_VIEW in case there are legacy apps that | | < | < < | | 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 | p = pParse->pNewTable; if( p==0 || pParse->nErr ) goto create_view_fail; /* Legacy versions of SQLite allowed the use of the magic "rowid" column ** on a view, even though views do not have rowids. The following flag ** setting fixes this problem. But the fix can be disabled by compiling ** with -DSQLITE_ALLOW_ROWID_IN_VIEW in case there are legacy apps that ** depend upon the old buggy behavior. */ #ifndef SQLITE_ALLOW_ROWID_IN_VIEW p->tabFlags |= TF_NoVisibleRowid; #endif sqlite3TwoPartName(pParse, pName1, pName2, &pName); iDb = sqlite3SchemaToIndex(db, p->pSchema); sqlite3FixInit(&sFix, pParse, iDb, "view", pName); if( sqlite3FixSelect(&sFix, pSelect) ) goto create_view_fail; |
︙ | ︙ | |||
3060 3061 3062 3063 3064 3065 3066 | return; } #endif /* SQLITE_OMIT_VIEW */ #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) /* ** The Table structure pTable is really a VIEW. Fill in the names of | | | < | 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 | return; } #endif /* SQLITE_OMIT_VIEW */ #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) /* ** The Table structure pTable is really a VIEW. Fill in the names of ** the columns of the view in the pTable structure. Return the number ** of errors. If an error is seen leave an error message in pParse->zErrMsg. */ static SQLITE_NOINLINE int viewGetColumnNames(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 */ sqlite3 *db = pParse->db; /* Database connection for malloc errors */ #ifndef SQLITE_OMIT_VIRTUALTABLE |
︙ | ︙ | |||
3185 3186 3187 3188 3189 3190 3191 | nErr++; } pTable->pSchema->schemaFlags |= DB_UnresetViews; if( db->mallocFailed ){ sqlite3DeleteColumnNames(db, pTable); } #endif /* SQLITE_OMIT_VIEW */ | | | 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 | nErr++; } pTable->pSchema->schemaFlags |= DB_UnresetViews; if( db->mallocFailed ){ sqlite3DeleteColumnNames(db, pTable); } #endif /* SQLITE_OMIT_VIEW */ return nErr; } int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ assert( pTable!=0 ); if( !IsVirtual(pTable) && pTable->nCol>0 ) return 0; return viewGetColumnNames(pParse, pTable); } #endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */ |
︙ | ︙ |
Changes to src/ctime.c.
︙ | ︙ | |||
61 62 63 64 65 66 67 | "4_BYTE_ALIGNED_MALLOC", #endif #ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN # if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1 "ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN), # endif #endif | < < < | 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | "4_BYTE_ALIGNED_MALLOC", #endif #ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN # if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1 "ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN), # endif #endif #ifdef SQLITE_ALLOW_URI_AUTHORITY "ALLOW_URI_AUTHORITY", #endif #ifdef SQLITE_ATOMIC_INTRINSICS "ATOMIC_INTRINSICS=" CTIMEOPT_VAL(SQLITE_ATOMIC_INTRINSICS), #endif #ifdef SQLITE_BITMASK_TYPE |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
214 215 216 217 218 219 220 | Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){ while( pExpr && ExprHasProperty(pExpr, EP_Skip|EP_Unlikely) ){ if( ExprHasProperty(pExpr, EP_Unlikely) ){ assert( ExprUseXList(pExpr) ); assert( pExpr->x.pList->nExpr>0 ); assert( pExpr->op==TK_FUNCTION ); pExpr = pExpr->x.pList->a[0].pExpr; | > | < < | 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){ while( pExpr && ExprHasProperty(pExpr, EP_Skip|EP_Unlikely) ){ if( ExprHasProperty(pExpr, EP_Unlikely) ){ assert( ExprUseXList(pExpr) ); assert( pExpr->x.pList->nExpr>0 ); assert( pExpr->op==TK_FUNCTION ); pExpr = pExpr->x.pList->a[0].pExpr; }else{ assert( pExpr->op==TK_COLLATE ); pExpr = pExpr->pLeft; } } return pExpr; } /* ** Return the collation sequence for the expression pExpr. If |
︙ | ︙ | |||
1364 1365 1366 1367 1368 1369 1370 | /* ** Recursively delete an expression tree. */ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){ assert( p!=0 ); assert( db!=0 ); | < > < < < < < < < < < < < < < | 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 | /* ** Recursively delete an expression tree. */ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){ assert( p!=0 ); assert( db!=0 ); assert( !ExprUseUValue(p) || p->u.iValue>=0 ); assert( !ExprUseYWin(p) || !ExprUseYSub(p) ); assert( !ExprUseYWin(p) || p->y.pWin!=0 || db->mallocFailed ); assert( p->op!=TK_FUNCTION || !ExprUseYSub(p) ); #ifdef SQLITE_DEBUG if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){ assert( p->pLeft==0 ); assert( p->pRight==0 ); assert( !ExprUseXSelect(p) || p->x.pSelect==0 ); assert( !ExprUseXList(p) || p->x.pList==0 ); } #endif if( !ExprHasProperty(p, (EP_TokenOnly|EP_Leaf)) ){ /* The Expr.x union is never used at the same time as Expr.pRight */ assert( (ExprUseXList(p) && p->x.pList==0) || p->pRight==0 ); if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft); if( p->pRight ){ assert( !ExprHasProperty(p, EP_WinFunc) ); sqlite3ExprDeleteNN(db, p->pRight); }else if( ExprUseXSelect(p) ){ assert( !ExprHasProperty(p, EP_WinFunc) ); sqlite3SelectDelete(db, p->x.pSelect); }else{ sqlite3ExprListDelete(db, p->x.pList); #ifndef SQLITE_OMIT_WINDOWFUNC if( ExprHasProperty(p, EP_WinFunc) ){ sqlite3WindowDelete(db, p->y.pWin); } #endif } } if( !ExprHasProperty(p, EP_Static) ){ sqlite3DbNNFreeNN(db, p); } } void sqlite3ExprDelete(sqlite3 *db, Expr *p){ if( p ) sqlite3ExprDeleteNN(db, p); |
︙ | ︙ | |||
1439 1440 1441 1442 1443 1444 1445 | /* ** Arrange to cause pExpr to be deleted when the pParse is deleted. ** This is similar to sqlite3ExprDelete() except that the delete is ** deferred until the pParse is deleted. ** ** The pExpr might be deleted immediately on an OOM error. ** | | | | | | 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 | /* ** Arrange to cause pExpr to be deleted when the pParse is deleted. ** This is similar to sqlite3ExprDelete() except that the delete is ** deferred until the pParse is deleted. ** ** The pExpr might be deleted immediately on an OOM error. ** ** The deferred delete is (currently) implemented by adding the ** pExpr to the pParse->pConstExpr list with a register number of 0. */ void sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){ sqlite3ParserAddCleanup(pParse, sqlite3ExprDeleteGeneric, pExpr); } /* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the ** expression. */ void sqlite3ExprUnmapAndDelete(Parse *pParse, Expr *p){ if( p ){ |
︙ | ︙ | |||
1879 1880 1881 1882 1883 1884 1885 | pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase); pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias); pNewItem->fg = pOldItem->fg; pNewItem->iCursor = pOldItem->iCursor; pNewItem->addrFillSub = pOldItem->addrFillSub; pNewItem->regReturn = pOldItem->regReturn; | < < < < < < > > > > | 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 | pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase); pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias); pNewItem->fg = pOldItem->fg; pNewItem->iCursor = pOldItem->iCursor; pNewItem->addrFillSub = pOldItem->addrFillSub; pNewItem->regReturn = pOldItem->regReturn; if( pNewItem->fg.isIndexedBy ){ pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy); } pNewItem->u2 = pOldItem->u2; if( pNewItem->fg.isCte ){ pNewItem->u2.pCteUse->nUse++; } if( pNewItem->fg.isTabFunc ){ pNewItem->u1.pFuncArg = sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags); } pTab = pNewItem->pTab = pOldItem->pTab; if( pTab ){ pTab->nTabRef++; } pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect, flags); if( pOldItem->fg.isUsing ){ assert( pNewItem->fg.isUsing ); |
︙ | ︙ | |||
2357 2358 2359 2360 2361 2362 2363 | }else if( ExprAlwaysTrue(pRight) || ExprAlwaysFalse(pLeft) ){ pExpr = pExpr->op==TK_AND ? pLeft : pRight; } } return pExpr; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 | }else if( ExprAlwaysTrue(pRight) || ExprAlwaysFalse(pLeft) ){ pExpr = pExpr->op==TK_AND ? pLeft : pRight; } } return pExpr; } /* ** These routines are Walker callbacks used to check expressions to ** see if they are "constant" for some definition of constant. The ** Walker.eCode value determines the type of "constant" we are looking ** for. ** |
︙ | ︙ | |||
2433 2434 2435 2436 2437 2438 2439 | ** an error for new statements, but is silently converted ** to NULL for existing schemas. This allows sqlite_schema tables that ** contain a bound parameter because they were generated by older versions ** of SQLite to be parsed by newer versions of SQLite without raising a ** malformed schema error. */ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ | < < < | 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 | ** an error for new statements, but is silently converted ** to NULL for existing schemas. This allows sqlite_schema tables that ** contain a bound parameter because they were generated by older versions ** of SQLite to be parsed by newer versions of SQLite without raising a ** malformed schema error. */ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ /* If pWalker->eCode is 2 then any term of the expression that comes from ** the ON or USING clauses of an outer join disqualifies the expression ** from being considered constant. */ if( pWalker->eCode==2 && ExprHasProperty(pExpr, EP_OuterON) ){ pWalker->eCode = 0; return WRC_Abort; } switch( pExpr->op ){ /* Consider functions to be constant if all their arguments are constant ** and either pWalker->eCode==4 or 5 or the function has the ** SQLITE_FUNC_CONST flag. */ case TK_FUNCTION: if( (pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_ConstFunc)) && !ExprHasProperty(pExpr, EP_WinFunc) ){ if( pWalker->eCode==5 ) ExprSetProperty(pExpr, EP_FromDDL); return WRC_Continue; }else{ pWalker->eCode = 0; return WRC_Abort; } case TK_ID: /* Convert "true" or "false" in a DEFAULT clause into the ** appropriate TK_TRUEFALSE operator */ |
︙ | ︙ | |||
2483 2484 2485 2486 2487 2488 2489 | if( pWalker->eCode==3 && pExpr->iTable==pWalker->u.iCur ){ return WRC_Continue; } /* no break */ deliberate_fall_through case TK_IF_NULL_ROW: case TK_REGISTER: case TK_DOT: | < < | 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 | if( pWalker->eCode==3 && pExpr->iTable==pWalker->u.iCur ){ return WRC_Continue; } /* no break */ deliberate_fall_through case TK_IF_NULL_ROW: case TK_REGISTER: case TK_DOT: testcase( pExpr->op==TK_REGISTER ); testcase( pExpr->op==TK_IF_NULL_ROW ); testcase( pExpr->op==TK_DOT ); 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_schema table */ |
︙ | ︙ | |||
2509 2510 2511 2512 2513 2514 2515 | /* no break */ deliberate_fall_through default: testcase( pExpr->op==TK_SELECT ); /* sqlite3SelectWalkFail() disallows */ testcase( pExpr->op==TK_EXISTS ); /* sqlite3SelectWalkFail() disallows */ return WRC_Continue; } } | | < > < < < < < < | | | | < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < | < < < | | 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 | /* no break */ deliberate_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; w.xSelectCallback = sqlite3SelectWalkFail; #ifdef SQLITE_DEBUG w.xSelectCallback2 = sqlite3SelectWalkAssert2; #endif w.u.iCur = iCur; sqlite3WalkExpr(&w, p); return w.eCode; } /* ** Walk an expression tree. Return non-zero if the expression is constant ** and 0 if it involves variables or function calls. ** ** For the purposes of this function, a double-quoted string (ex: "abc") ** is considered a variable but a single-quoted string (ex: 'abc') is ** a constant. */ int sqlite3ExprIsConstant(Expr *p){ return exprIsConst(p, 1, 0); } /* ** Walk an expression tree. Return non-zero if ** ** (1) the expression is constant, and ** (2) the expression does originate in the ON or USING clause ** of a LEFT JOIN, and ** (3) the expression does not contain any EP_FixedCol TK_COLUMN ** operands created by the constant propagation optimization. ** ** When this routine returns true, it indicates that the expression ** can be added to the pParse->pConstExpr list and evaluated once when ** the prepared statement starts up. See sqlite3ExprCodeRunJustOnce(). */ int sqlite3ExprIsConstantNotJoin(Expr *p){ return exprIsConst(p, 2, 0); } /* ** Walk an expression tree. Return non-zero if the expression is constant ** for any single row of the table with cursor iCur. In other words, the ** expression must not refer to any non-deterministic function nor any ** table other than iCur. */ int sqlite3ExprIsTableConstant(Expr *p, int iCur){ return exprIsConst(p, 3, iCur); } /* ** Check pExpr to see if it is an constraint on the single data source ** pSrc = &pSrcList->a[iSrc]. In other words, check to see if pExpr ** constrains pSrc but does not depend on any other tables or data ** sources anywhere else in the query. Return true (non-zero) if pExpr ** is a constraint on pSrc only. ** ** This is an optimization. False negatives will perhaps cause slower ** queries, but false positives will yield incorrect answers. So when in ** doubt, return 0. ** ** To be an single-source constraint, the following must be true: ** ** (1) pExpr cannot refer to any table other than pSrc->iCursor. ** ** (2) pExpr cannot use subqueries or non-deterministic functions. ** ** (3) pSrc cannot be part of the left operand for a RIGHT JOIN. ** (Is there some way to relax this constraint?) ** ** (4) If pSrc is the right operand of a LEFT JOIN, then... ** (4a) pExpr must come from an ON clause.. ** (4b) and specifically the ON clause associated with the LEFT JOIN. |
︙ | ︙ | |||
2647 2648 2649 2650 2651 2652 2653 | ** from the left side of a RIGHT JOIN over to the right side, ** which leads to incorrect answers. See also restriction (9) ** on push-down. */ int sqlite3ExprIsSingleTableConstraint( Expr *pExpr, /* The constraint */ const SrcList *pSrcList, /* Complete FROM clause */ | | < | 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 | ** from the left side of a RIGHT JOIN over to the right side, ** which leads to incorrect answers. See also restriction (9) ** on push-down. */ int sqlite3ExprIsSingleTableConstraint( Expr *pExpr, /* The constraint */ const SrcList *pSrcList, /* Complete FROM clause */ int iSrc /* Which element of pSrcList to use */ ){ const SrcItem *pSrc = &pSrcList->a[iSrc]; if( pSrc->fg.jointype & JT_LTORJ ){ return 0; /* rule (3) */ } if( pSrc->fg.jointype & JT_LEFT ){ if( !ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* rule (4a) */ |
︙ | ︙ | |||
2673 2674 2675 2676 2677 2678 2679 | if( (pSrcList->a[jj].fg.jointype & JT_LTORJ)!=0 ){ return 0; /* restriction (6) */ } break; } } } | < | | 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 | if( (pSrcList->a[jj].fg.jointype & JT_LTORJ)!=0 ){ return 0; /* restriction (6) */ } break; } } } return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor); /* rules (1), (2) */ } /* ** sqlite3WalkExpr() callback used by sqlite3ExprIsConstantOrGroupBy(). */ static int exprNodeIsConstantOrGroupBy(Walker *pWalker, Expr *pExpr){ |
︙ | ︙ | |||
2759 2760 2761 2762 2763 2764 2765 | ** ** For the purposes of this function, a double-quoted string (ex: "abc") ** is considered a variable but a single-quoted string (ex: 'abc') is ** a constant. */ int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){ assert( isInit==0 || isInit==1 ); | | | 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 | ** ** For the purposes of this function, a double-quoted string (ex: "abc") ** is considered a variable but a single-quoted string (ex: 'abc') is ** a constant. */ int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){ assert( isInit==0 || isInit==1 ); return exprIsConst(p, 4+isInit, 0); } #ifdef SQLITE_ENABLE_CURSOR_HINTS /* ** Walk an expression tree. Return 1 if the expression contains a ** subquery of some kind. Return 0 if there are no subqueries. */ |
︙ | ︙ | |||
2849 2850 2851 2852 2853 2854 2855 | case TK_INTEGER: case TK_STRING: case TK_FLOAT: case TK_BLOB: return 0; case TK_COLUMN: assert( ExprUseYTab(p) ); | | | < < < | | 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 | case TK_INTEGER: case TK_STRING: case TK_FLOAT: case TK_BLOB: return 0; case TK_COLUMN: assert( ExprUseYTab(p) ); return ExprHasProperty(p, EP_CanBeNull) || NEVER(p->y.pTab==0) || /* Reference to column of index on expr */ (p->iColumn>=0 && p->y.pTab->aCol!=0 /* Possible due to prior error */ && ALWAYS(p->iColumn<p->y.pTab->nCol) && p->y.pTab->aCol[p->iColumn].notNull==0); default: return 1; } } |
︙ | ︙ | |||
3007 3008 3009 3010 3011 3012 3013 | #ifndef SQLITE_OMIT_SUBQUERY /* ** The argument is an IN operator with a list (not a subquery) on the ** right-hand side. Return TRUE if that list is constant. */ | | | | 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 | #ifndef SQLITE_OMIT_SUBQUERY /* ** The argument is an IN operator with a list (not a subquery) on the ** right-hand side. Return TRUE if that list is constant. */ static int sqlite3InRhsIsConstant(Expr *pIn){ Expr *pLHS; int res; assert( !ExprHasProperty(pIn, EP_xIsSelect) ); pLHS = pIn->pLeft; pIn->pLeft = 0; res = sqlite3ExprIsConstant(pIn); pIn->pLeft = pLHS; return res; } #endif /* ** This function is used by the implementation of the IN (...) operator. |
︙ | ︙ | |||
3282 3283 3284 3285 3286 3287 3288 | ** and the RHS is not constant or has two or fewer terms, ** then it is not worth creating an ephemeral table to evaluate ** the IN operator so return IN_INDEX_NOOP. */ if( eType==0 && (inFlags & IN_INDEX_NOOP_OK) && ExprUseXList(pX) | | | 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 | ** and the RHS is not constant or has two or fewer terms, ** then it is not worth creating an ephemeral table to evaluate ** the IN operator so return IN_INDEX_NOOP. */ if( eType==0 && (inFlags & IN_INDEX_NOOP_OK) && ExprUseXList(pX) && (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2) ){ pParse->nTab--; /* Back out the allocation of the unused cursor */ iTab = -1; /* Cursor is not allocated */ eType = IN_INDEX_NOOP; } if( eType==0 ){ |
︙ | ︙ | |||
3565 3566 3567 3568 3569 3570 3571 | Expr *pE2 = pItem->pExpr; /* If the expression is not constant then we will need to ** disable the test that was generated above that makes sure ** this code only executes once. Because for a non-constant ** expression we need to rerun this code each time. */ | | | 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 | Expr *pE2 = pItem->pExpr; /* If the expression is not constant then we will need to ** disable the test that was generated above that makes sure ** this code only executes once. Because for a non-constant ** expression we need to rerun this code each time. */ if( addrOnce && !sqlite3ExprIsConstant(pE2) ){ sqlite3VdbeChangeToNoop(v, addrOnce-1); sqlite3VdbeChangeToNoop(v, addrOnce); ExprClearProperty(pExpr, EP_Subrtn); addrOnce = 0; } /* Evaluate the expression and insert it into the temp table */ |
︙ | ︙ | |||
4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 | } #endif case TK_VARIABLE: { assert( !ExprHasProperty(pExpr, EP_IntValue) ); assert( pExpr->u.zToken!=0 ); assert( pExpr->u.zToken[0]!=0 ); sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target); return target; } case TK_REGISTER: { return pExpr->iTable; } #ifndef SQLITE_OMIT_CAST case TK_CAST: { | > > > > > > | 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 | } #endif case TK_VARIABLE: { assert( !ExprHasProperty(pExpr, EP_IntValue) ); assert( pExpr->u.zToken!=0 ); assert( pExpr->u.zToken[0]!=0 ); sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target); if( pExpr->u.zToken[1]!=0 ){ const char *z = sqlite3VListNumToName(pParse->pVList, pExpr->iColumn); assert( pExpr->u.zToken[0]=='?' || (z && !strcmp(pExpr->u.zToken, z)) ); pParse->pVList[0] = 0; /* Indicate VList may no longer be enlarged */ sqlite3VdbeAppendP4(v, (char*)z, P4_STATIC); } return target; } case TK_REGISTER: { return pExpr->iTable; } #ifndef SQLITE_OMIT_CAST case TK_CAST: { |
︙ | ︙ | |||
4902 4903 4904 4905 4906 4907 4908 | #ifndef SQLITE_OMIT_WINDOWFUNC if( ExprHasProperty(pExpr, EP_WinFunc) ){ return pExpr->y.pWin->regResult; } #endif | | < < | 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 | #ifndef SQLITE_OMIT_WINDOWFUNC if( ExprHasProperty(pExpr, EP_WinFunc) ){ return pExpr->y.pWin->regResult; } #endif if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){ /* SQL functions can be expensive. So try to avoid running them ** multiple times if we know they always give the same result */ return sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1); } assert( !ExprHasProperty(pExpr, EP_TokenOnly) ); assert( ExprUseXList(pExpr) ); pFarg = pExpr->x.pList; |
︙ | ︙ | |||
4935 4936 4937 4938 4939 4940 4941 | return exprCodeInlineFunction(pParse, pFarg, SQLITE_PTR_TO_INT(pDef->pUserData), target); }else if( pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE) ){ sqlite3ExprFunctionUsable(pParse, pExpr, pDef); } for(i=0; i<nFarg; i++){ | | | 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 | return exprCodeInlineFunction(pParse, pFarg, SQLITE_PTR_TO_INT(pDef->pUserData), target); }else if( pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE) ){ sqlite3ExprFunctionUsable(pParse, pExpr, pDef); } for(i=0; i<nFarg; i++){ if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){ testcase( i==31 ); constMask |= MASKBIT32(i); } if( (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){ pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr); } } |
︙ | ︙ | |||
5077 5078 5079 5080 5081 5082 5083 | exprCodeBetween(pParse, pExpr, target, 0, 0); return target; } case TK_COLLATE: { if( !ExprHasProperty(pExpr, EP_Collate) ){ /* A TK_COLLATE Expr node without the EP_Collate tag is a so-called ** "SOFT-COLLATE" that is added to constraints that are pushed down | | | < | 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 | exprCodeBetween(pParse, pExpr, target, 0, 0); return target; } case TK_COLLATE: { if( !ExprHasProperty(pExpr, EP_Collate) ){ /* A TK_COLLATE Expr node without the EP_Collate tag is a so-called ** "SOFT-COLLATE" that is added to constraints that are pushed down ** from outer queries into sub-queries by the push-down optimization. ** Clear subtypes as subtypes may not cross a subquery boundary. */ assert( pExpr->pLeft ); sqlite3ExprCode(pParse, pExpr->pLeft, target); sqlite3VdbeAddOp1(v, OP_ClrSubtype, target); return target; }else{ pExpr = pExpr->pLeft; |
︙ | ︙ | |||
5403 5404 5405 5406 5407 5408 5409 | */ int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){ int r2; pExpr = sqlite3ExprSkipCollateAndLikely(pExpr); if( ConstFactorOk(pParse) && ALWAYS(pExpr!=0) && pExpr->op!=TK_REGISTER | | | 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 | */ int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){ int r2; pExpr = sqlite3ExprSkipCollateAndLikely(pExpr); if( ConstFactorOk(pParse) && ALWAYS(pExpr!=0) && pExpr->op!=TK_REGISTER && sqlite3ExprIsConstantNotJoin(pExpr) ){ *pReg = 0; r2 = sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1); }else{ int r1 = sqlite3GetTempReg(pParse); r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); if( r2==r1 ){ |
︙ | ︙ | |||
5467 5468 5469 5470 5471 5472 5473 | /* ** Generate code that will evaluate expression pExpr and store the ** results in register target. The results are guaranteed to appear ** in register target. If the expression is constant, then this routine ** might choose to code the expression at initialization time. */ void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){ | | | 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 | /* ** Generate code that will evaluate expression pExpr and store the ** results in register target. The results are guaranteed to appear ** in register target. If the expression is constant, then this routine ** might choose to code the expression at initialization time. */ void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){ if( pParse->okConstFactor && sqlite3ExprIsConstantNotJoin(pExpr) ){ sqlite3ExprCodeRunJustOnce(pParse, pExpr, target); }else{ sqlite3ExprCodeCopy(pParse, pExpr, target); } } /* |
︙ | ︙ | |||
5526 5527 5528 5529 5530 5531 5532 | if( flags & SQLITE_ECEL_OMITREF ){ i--; n--; }else{ sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i); } }else if( (flags & SQLITE_ECEL_FACTOR)!=0 | | | 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 | if( flags & SQLITE_ECEL_OMITREF ){ i--; n--; }else{ sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i); } }else if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstantNotJoin(pExpr) ){ sqlite3ExprCodeRunJustOnce(pParse, pExpr, target+i); }else{ int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i); if( inReg!=target+i ){ VdbeOp *pOp; if( copyOp==OP_Copy |
︙ | ︙ | |||
6677 6678 6679 6680 6681 6682 6683 | sqlite3 *db = pParse->db; assert( iAgg>=0 ); if( pExpr->op!=TK_AGG_FUNCTION ){ if( iAgg<pAggInfo->nColumn && pAggInfo->aCol[iAgg].pCExpr==pExpr ){ pExpr = sqlite3ExprDup(db, pExpr, 0); | | > | > | 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 | sqlite3 *db = pParse->db; assert( iAgg>=0 ); if( pExpr->op!=TK_AGG_FUNCTION ){ if( iAgg<pAggInfo->nColumn && pAggInfo->aCol[iAgg].pCExpr==pExpr ){ pExpr = sqlite3ExprDup(db, pExpr, 0); if( pExpr ){ pAggInfo->aCol[iAgg].pCExpr = pExpr; sqlite3ExprDeferredDelete(pParse, pExpr); } } }else{ assert( pExpr->op==TK_AGG_FUNCTION ); if( ALWAYS(iAgg<pAggInfo->nFunc) && pAggInfo->aFunc[iAgg].pFExpr==pExpr ){ pExpr = sqlite3ExprDup(db, pExpr, 0); if( pExpr ){ pAggInfo->aFunc[iAgg].pFExpr = pExpr; sqlite3ExprDeferredDelete(pParse, pExpr); } } } } return WRC_Continue; } |
︙ | ︙ |
Changes to src/func.c.
︙ | ︙ | |||
1888 1889 1890 1891 1892 1893 1894 | static void sumFinalize(sqlite3_context *context){ SumCtx *p; p = sqlite3_aggregate_context(context, 0); if( p && p->cnt>0 ){ if( p->approx ){ if( p->ovrfl ){ sqlite3_result_error(context,"integer overflow",-1); | | | | | 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 | static void sumFinalize(sqlite3_context *context){ SumCtx *p; p = sqlite3_aggregate_context(context, 0); if( p && p->cnt>0 ){ if( p->approx ){ if( p->ovrfl ){ sqlite3_result_error(context,"integer overflow",-1); }else if( !sqlite3IsNaN(p->rErr) ){ sqlite3_result_double(context, p->rSum+p->rErr); }else{ sqlite3_result_double(context, p->rSum); } }else{ sqlite3_result_int64(context, p->iSum); } } } static void avgFinalize(sqlite3_context *context){ SumCtx *p; p = sqlite3_aggregate_context(context, 0); if( p && p->cnt>0 ){ double r; if( p->approx ){ r = p->rSum; if( !sqlite3IsNaN(p->rErr) ) r += p->rErr; }else{ r = (double)(p->iSum); } sqlite3_result_double(context, r/(double)p->cnt); } } static void totalFinalize(sqlite3_context *context){ SumCtx *p; double r = 0.0; p = sqlite3_aggregate_context(context, 0); if( p ){ if( p->approx ){ r = p->rSum; if( !sqlite3IsNaN(p->rErr) ) r += p->rErr; }else{ r = (double)(p->iSum); } } sqlite3_result_double(context, r); } |
︙ | ︙ | |||
2202 2203 2204 2205 2206 2207 2208 | = (GroupConcatCtx*)sqlite3_aggregate_context(context, 0); if( pGCC ){ StrAccum *pAccum = &pGCC->str; if( pAccum->accError==SQLITE_TOOBIG ){ sqlite3_result_error_toobig(context); }else if( pAccum->accError==SQLITE_NOMEM ){ sqlite3_result_error_nomem(context); | < < | 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 | = (GroupConcatCtx*)sqlite3_aggregate_context(context, 0); if( pGCC ){ StrAccum *pAccum = &pGCC->str; if( pAccum->accError==SQLITE_TOOBIG ){ sqlite3_result_error_toobig(context); }else if( pAccum->accError==SQLITE_NOMEM ){ sqlite3_result_error_nomem(context); }else{ const char *zText = sqlite3_str_value(pAccum); sqlite3_result_text(context, zText, pAccum->nChar, SQLITE_TRANSIENT); } } } #else |
︙ | ︙ |
Changes to src/global.c.
︙ | ︙ | |||
285 286 287 288 289 290 291 | #endif #ifndef SQLITE_OMIT_DESERIALIZE SQLITE_MEMDB_DEFAULT_MAXSIZE, /* mxMemdbSize */ #endif #ifndef SQLITE_UNTESTABLE 0, /* xTestCallback */ #endif | < < < | 285 286 287 288 289 290 291 292 293 294 295 296 297 298 | #endif #ifndef SQLITE_OMIT_DESERIALIZE SQLITE_MEMDB_DEFAULT_MAXSIZE, /* mxMemdbSize */ #endif #ifndef SQLITE_UNTESTABLE 0, /* xTestCallback */ #endif 0, /* bLocaltimeFault */ 0, /* xAltLocaltime */ 0x7ffffffe, /* iOnceResetThreshold */ SQLITE_DEFAULT_SORTERREF_SIZE, /* szSorterRef */ 0, /* iPrngSeed */ #ifdef SQLITE_DEBUG {0,0,0,0,0,0}, /* aTune */ |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
573 574 575 576 577 578 579 | ** If SQLITE_OMIT_AUTOINCREMENT is defined, then the three routines ** above are all no-ops */ # define autoIncBegin(A,B,C) (0) # define autoIncStep(A,B,C) #endif /* SQLITE_OMIT_AUTOINCREMENT */ | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 573 574 575 576 577 578 579 580 581 582 583 584 585 586 | ** If SQLITE_OMIT_AUTOINCREMENT is defined, then the three routines ** above are all no-ops */ # define autoIncBegin(A,B,C) (0) # define autoIncStep(A,B,C) #endif /* SQLITE_OMIT_AUTOINCREMENT */ /* Forward declaration */ static int xferOptimization( Parse *pParse, /* Parser context */ Table *pDest, /* The table we are inserting into */ Select *pSelect, /* A SELECT statement to use as the data source */ int onError, /* How to handle constraint errors */ |
︙ | ︙ | |||
1098 1099 1100 1101 1102 1103 1104 1105 1106 | ** is coming from a SELECT statement, then generate a co-routine that ** produces a single row of the SELECT on each invocation. The ** co-routine is the common header to the 3rd and 4th templates. */ if( pSelect ){ /* Data is coming from a SELECT or from a multi-row VALUES clause. ** Generate a co-routine to run the SELECT. */ int rc; /* Result code */ | > > < < < < < < < < < < < < < < < < | | | | | | | | | | | | | | | < | 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 | ** is coming from a SELECT statement, then generate a co-routine that ** produces a single row of the SELECT on each invocation. The ** co-routine is the common header to the 3rd and 4th templates. */ if( pSelect ){ /* Data is coming from a SELECT or from a multi-row VALUES clause. ** Generate a co-routine to run the SELECT. */ int regYield; /* Register holding co-routine entry-point */ int addrTop; /* Top of the co-routine */ int rc; /* Result code */ regYield = ++pParse->nMem; addrTop = sqlite3VdbeCurrentAddr(v) + 1; sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); dest.iSdst = bIdListInOrder ? regData : 0; dest.nSdst = pTab->nCol; rc = sqlite3Select(pParse, pSelect, &dest); regFromSelect = dest.iSdst; assert( db->pParse==pParse ); if( rc || pParse->nErr ) goto insert_cleanup; assert( db->mallocFailed==0 ); sqlite3VdbeEndCoroutine(v, regYield); sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */ assert( pSelect->pEList ); nColumn = pSelect->pEList->nExpr; /* Set useTempTable to TRUE if the result of the SELECT statement ** should be written into a temporary table (template 4). Set to ** FALSE if each output row of the SELECT can be written directly into ** the destination table (template 3). ** ** A temp table must be used if the table being updated is also one |
︙ | ︙ | |||
1286 1287 1288 1289 1290 1291 1292 | pNx = pUpsert; do{ pNx->pUpsertSrc = pTabList; pNx->regData = regData; pNx->iDataCur = iDataCur; pNx->iIdxCur = iIdxCur; if( pNx->pUpsertTarget ){ | | | 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 | pNx = pUpsert; do{ pNx->pUpsertSrc = pTabList; pNx->regData = regData; pNx->iDataCur = iDataCur; pNx->iIdxCur = iIdxCur; if( pNx->pUpsertTarget ){ if( sqlite3UpsertAnalyzeTarget(pParse, pTabList, pNx) ){ goto insert_cleanup; } } pNx = pNx->pNextUpsert; }while( pNx!=0 ); } #endif |
︙ | ︙ | |||
3178 3179 3180 3181 3182 3183 3184 | /* The sqlite3FaultSim() call allows this corruption test to be ** bypassed during testing, in order to exercise other corruption tests ** further downstream. */ return 0; /* Corrupt schema - two indexes on the same btree */ } } #ifndef SQLITE_OMIT_CHECK | < < | < | 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 | /* The sqlite3FaultSim() call allows this corruption test to be ** bypassed during testing, in order to exercise other corruption tests ** further downstream. */ return 0; /* Corrupt schema - two indexes on the same btree */ } } #ifndef SQLITE_OMIT_CHECK if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){ return 0; /* Tables have different CHECK constraints. Ticket #2252 */ } #endif #ifndef SQLITE_OMIT_FOREIGN_KEY /* Disallow the transfer optimization if the destination table contains ** any foreign key constraints. This is more restrictive than necessary. ** But the main beneficiary of the transfer optimization is the VACUUM |
︙ | ︙ |
Changes to src/json.c.
︙ | ︙ | |||
558 559 560 561 562 563 564 565 566 567 568 569 570 571 | if( N+p->nUsed >= p->nAlloc ){ jsonStringExpandAndAppend(p,zIn,N); }else{ memcpy(p->zBuf+p->nUsed, zIn, N); p->nUsed += N; } } /* Append formatted text (not to exceed N bytes) to the JsonString. */ static void jsonPrintf(int N, JsonString *p, const char *zFormat, ...){ va_list ap; if( (p->nUsed + N >= p->nAlloc) && jsonStringGrow(p, N) ) return; va_start(ap, zFormat); | > | 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 | if( N+p->nUsed >= p->nAlloc ){ jsonStringExpandAndAppend(p,zIn,N); }else{ memcpy(p->zBuf+p->nUsed, zIn, N); p->nUsed += N; } } /* Append formatted text (not to exceed N bytes) to the JsonString. */ static void jsonPrintf(int N, JsonString *p, const char *zFormat, ...){ va_list ap; if( (p->nUsed + N >= p->nAlloc) && jsonStringGrow(p, N) ) return; va_start(ap, zFormat); |
︙ | ︙ | |||
2330 2331 2332 2333 2334 2335 2336 | malformed_jsonb: pOut->eErr |= JSTRING_MALFORMED; break; } } return i+n+sz; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 | malformed_jsonb: pOut->eErr |= JSTRING_MALFORMED; break; } } return i+n+sz; } /* Return true if the input pJson ** ** For performance reasons, this routine does not do a detailed check of the ** input BLOB to ensure that it is well-formed. Hence, false positives are ** possible. False negatives should never occur, however. */ |
︙ | ︙ | |||
3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 | } if( (p->aBlob[i] & 0x0f)==JSONB_ARRAY ){ cnt = jsonbArrayCount(p, i); } if( !eErr ) sqlite3_result_int64(ctx, cnt); jsonParseFree(p); } /* True if the string is all alphanumerics and underscores */ static int jsonAllAlphanum(const char *z, int n){ int i; for(i=0; i<n && (sqlite3Isalnum(z[i]) || z[i]=='_'); i++){} return i==n; } | > > > > > > > | 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 | } if( (p->aBlob[i] & 0x0f)==JSONB_ARRAY ){ cnt = jsonbArrayCount(p, i); } if( !eErr ) sqlite3_result_int64(ctx, cnt); jsonParseFree(p); } /* True if the string is all digits */ static int jsonAllDigits(const char *z, int n){ int i; for(i=0; i<n && sqlite3Isdigit(z[i]); i++){} return i==n; } /* True if the string is all alphanumerics and underscores */ static int jsonAllAlphanum(const char *z, int n){ int i; for(i=0; i<n && (sqlite3Isalnum(z[i]) || z[i]=='_'); i++){} return i==n; } |
︙ | ︙ | |||
3855 3856 3857 3858 3859 3860 3861 | ** convenience. ** ** NUMBER ==> $[NUMBER] // PG compatible ** LABEL ==> $.LABEL // PG compatible ** [NUMBER] ==> $[NUMBER] // Not PG. Purely for convenience */ jsonStringInit(&jx, ctx); | | | 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 | ** convenience. ** ** NUMBER ==> $[NUMBER] // PG compatible ** LABEL ==> $.LABEL // PG compatible ** [NUMBER] ==> $[NUMBER] // Not PG. Purely for convenience */ jsonStringInit(&jx, ctx); if( jsonAllDigits(zPath, nPath) ){ jsonAppendRawNZ(&jx, "[", 1); jsonAppendRaw(&jx, zPath, nPath); jsonAppendRawNZ(&jx, "]", 2); }else if( jsonAllAlphanum(zPath, nPath) ){ jsonAppendRawNZ(&jx, ".", 1); jsonAppendRaw(&jx, zPath, nPath); }else if( zPath[0]=='[' && nPath>=3 && zPath[nPath-1]==']' ){ |
︙ | ︙ | |||
4349 4350 4351 4352 4353 4354 4355 | i = 0; } sqlite3_result_text(ctx, jsonbType[p->aBlob[i]&0x0f], -1, SQLITE_STATIC); json_type_done: jsonParseFree(p); } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 | i = 0; } sqlite3_result_text(ctx, jsonbType[p->aBlob[i]&0x0f], -1, SQLITE_STATIC); json_type_done: jsonParseFree(p); } /* ** json_valid(JSON) ** json_valid(JSON, FLAGS) ** ** Check the JSON argument to see if it is well-formed. The FLAGS argument ** encodes the various constraints on what is meant by "well-formed": ** |
︙ | ︙ | |||
5397 5398 5399 5400 5401 5402 5403 | JFUNCTION(->>, 2,1,0, 0,0,JSON_SQL, jsonExtractFunc), JFUNCTION(json_insert, -1,1,1, 1,0,0, jsonSetFunc), JFUNCTION(jsonb_insert, -1,1,0, 1,1,0, jsonSetFunc), JFUNCTION(json_object, -1,0,1, 1,0,0, jsonObjectFunc), JFUNCTION(jsonb_object, -1,0,1, 1,1,0, jsonObjectFunc), JFUNCTION(json_patch, 2,1,1, 0,0,0, jsonPatchFunc), JFUNCTION(jsonb_patch, 2,1,0, 0,1,0, jsonPatchFunc), | < < | 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 | JFUNCTION(->>, 2,1,0, 0,0,JSON_SQL, jsonExtractFunc), JFUNCTION(json_insert, -1,1,1, 1,0,0, jsonSetFunc), JFUNCTION(jsonb_insert, -1,1,0, 1,1,0, jsonSetFunc), JFUNCTION(json_object, -1,0,1, 1,0,0, jsonObjectFunc), JFUNCTION(jsonb_object, -1,0,1, 1,1,0, jsonObjectFunc), JFUNCTION(json_patch, 2,1,1, 0,0,0, jsonPatchFunc), JFUNCTION(jsonb_patch, 2,1,0, 0,1,0, jsonPatchFunc), JFUNCTION(json_quote, 1,0,1, 1,0,0, jsonQuoteFunc), JFUNCTION(json_remove, -1,1,1, 0,0,0, jsonRemoveFunc), JFUNCTION(jsonb_remove, -1,1,0, 0,1,0, jsonRemoveFunc), JFUNCTION(json_replace, -1,1,1, 1,0,0, jsonReplaceFunc), JFUNCTION(jsonb_replace, -1,1,0, 1,1,0, jsonReplaceFunc), JFUNCTION(json_set, -1,1,1, 1,0,JSON_ISSET, jsonSetFunc), JFUNCTION(jsonb_set, -1,1,0, 1,1,JSON_ISSET, jsonSetFunc), |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
761 762 763 764 765 766 767 | #ifndef SQLITE_OMIT_DESERIALIZE case SQLITE_CONFIG_MEMDB_MAXSIZE: { sqlite3GlobalConfig.mxMemdbSize = va_arg(ap, sqlite3_int64); break; } #endif /* SQLITE_OMIT_DESERIALIZE */ | < < < < < < < < < < < < | 761 762 763 764 765 766 767 768 769 770 771 772 773 774 | #ifndef SQLITE_OMIT_DESERIALIZE case SQLITE_CONFIG_MEMDB_MAXSIZE: { sqlite3GlobalConfig.mxMemdbSize = va_arg(ap, sqlite3_int64); break; } #endif /* SQLITE_OMIT_DESERIALIZE */ default: { rc = SQLITE_ERROR; break; } } va_end(ap); return rc; |
︙ | ︙ |
Changes to src/os_unix.c.
︙ | ︙ | |||
6394 6395 6396 6397 6398 6399 6400 | if( fd<0 ){ if( isNewJrnl && errno==EACCES && osAccess(zName, F_OK) ){ /* If unable to create a journal because the directory is not ** writable, change the error code to indicate that. */ rc = SQLITE_READONLY_DIRECTORY; }else if( errno!=EISDIR && isReadWrite ){ /* Failed to open the file for read/write access. Try read-only. */ | < < < < < < | < | 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 | if( fd<0 ){ if( isNewJrnl && errno==EACCES && osAccess(zName, F_OK) ){ /* If unable to create a journal because the directory is not ** writable, change the error code to indicate that. */ rc = SQLITE_READONLY_DIRECTORY; }else if( errno!=EISDIR && isReadWrite ){ /* Failed to open the file for read/write access. Try read-only. */ flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); openFlags &= ~(O_RDWR|O_CREAT); flags |= SQLITE_OPEN_READONLY; openFlags |= O_RDONLY; isReadonly = 1; fd = robust_open(zName, openFlags, openMode); } } if( fd<0 ){ int rc2 = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName); if( rc==SQLITE_OK ) rc = rc2; goto open_finished; } |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
7083 7084 7085 7086 7087 7088 7089 | } /* ** 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){ | | | 7083 7084 7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 | } /* ** 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; #else return pPager->pWal ? sqlite3WalFile(pPager->pWal) : pPager->jfd; #endif } /* |
︙ | ︙ |
Changes to src/parse.y.
︙ | ︙ | |||
561 562 563 564 565 566 567 | } } %ifndef SQLITE_OMIT_CTE select(A) ::= WITH wqlist(W) selectnowith(X). {A = attachWithToSelect(pParse,X,W);} select(A) ::= WITH RECURSIVE wqlist(W) selectnowith(X). {A = attachWithToSelect(pParse,X,W);} | < | 561 562 563 564 565 566 567 568 569 570 571 572 573 574 | } } %ifndef SQLITE_OMIT_CTE select(A) ::= WITH wqlist(W) selectnowith(X). {A = attachWithToSelect(pParse,X,W);} select(A) ::= WITH RECURSIVE wqlist(W) selectnowith(X). {A = attachWithToSelect(pParse,X,W);} %endif /* SQLITE_OMIT_CTE */ select(A) ::= selectnowith(A). { Select *p = A; if( p ){ parserDoubleLinkSelect(pParse, p); } } |
︙ | ︙ | |||
619 620 621 622 623 624 625 | }else{ sqlite3WindowListDelete(pParse->db, R); } } %endif | | | < | < < | < > | > > > > | < < | | < < | 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 | }else{ sqlite3WindowListDelete(pParse->db, R); } } %endif oneselect(A) ::= values(A). %type values {Select*} %destructor values {sqlite3SelectDelete(pParse->db, $$);} values(A) ::= VALUES LP nexprlist(X) RP. { A = sqlite3SelectNew(pParse,X,0,0,0,0,0,SF_Values,0); } values(A) ::= values(A) COMMA LP nexprlist(Y) RP. { Select *pRight, *pLeft = A; pRight = sqlite3SelectNew(pParse,Y,0,0,0,0,0,SF_Values|SF_MultiValue,0); if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue; if( pRight ){ pRight->op = TK_ALL; pRight->pPrior = pLeft; A = pRight; }else{ A = pLeft; } } // The "distinct" nonterminal is true (1) if the DISTINCT keyword is // present and false (0) if it is not. // %type distinct {int} distinct(A) ::= DISTINCT. {A = SF_Distinct;} |
︙ | ︙ | |||
1278 1279 1280 1281 1282 1283 1284 | } expr(A) ::= NOT(B) expr(X). {A = sqlite3PExpr(pParse, @B, X, 0);/*A-overwrites-B*/} expr(A) ::= BITNOT(B) expr(X). {A = sqlite3PExpr(pParse, @B, X, 0);/*A-overwrites-B*/} expr(A) ::= PLUS|MINUS(B) expr(X). [BITNOT] { | < < < < < < < < | | < | 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 | } expr(A) ::= NOT(B) expr(X). {A = sqlite3PExpr(pParse, @B, X, 0);/*A-overwrites-B*/} expr(A) ::= BITNOT(B) expr(X). {A = sqlite3PExpr(pParse, @B, X, 0);/*A-overwrites-B*/} expr(A) ::= PLUS|MINUS(B) expr(X). [BITNOT] { A = sqlite3PExpr(pParse, @B==TK_PLUS ? TK_UPLUS : TK_UMINUS, X, 0); /*A-overwrites-B*/ } expr(A) ::= expr(B) PTR(C) expr(D). { ExprList *pList = sqlite3ExprListAppend(pParse, 0, B); pList = sqlite3ExprListAppend(pParse, pList, D); A = sqlite3ExprFunction(pParse, pList, &C, 0); } |
︙ | ︙ | |||
1330 1331 1332 1333 1334 1335 1336 | ** regardless of the value of expr1. */ sqlite3ExprUnmapAndDelete(pParse, A); A = sqlite3Expr(pParse->db, TK_STRING, N ? "true" : "false"); if( A ) sqlite3ExprIdToTrueFalse(A); }else{ Expr *pRHS = Y->a[0].pExpr; | | | 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 | ** regardless of the value of expr1. */ sqlite3ExprUnmapAndDelete(pParse, A); A = sqlite3Expr(pParse->db, TK_STRING, N ? "true" : "false"); if( A ) sqlite3ExprIdToTrueFalse(A); }else{ Expr *pRHS = Y->a[0].pExpr; if( Y->nExpr==1 && sqlite3ExprIsConstant(pRHS) && A->op!=TK_VECTOR ){ Y->a[0].pExpr = 0; sqlite3ExprListDelete(pParse->db, Y); pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0); A = sqlite3PExpr(pParse, TK_EQ, A, pRHS); }else if( Y->nExpr==1 && pRHS->op==TK_SELECT ){ A = sqlite3PExpr(pParse, TK_IN, A, 0); sqlite3PExprAddSelect(pParse, A, pRHS->x.pSelect); |
︙ | ︙ | |||
1770 1771 1772 1773 1774 1775 1776 | with ::= WITH wqlist(W). { sqlite3WithPush(pParse, W, 1); } with ::= WITH RECURSIVE wqlist(W). { sqlite3WithPush(pParse, W, 1); } %type wqas {u8} wqas(A) ::= AS. {A = M10d_Any;} wqas(A) ::= AS MATERIALIZED. {A = M10d_Yes;} wqas(A) ::= AS NOT MATERIALIZED. {A = M10d_No;} | | < | 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 | with ::= WITH wqlist(W). { sqlite3WithPush(pParse, W, 1); } with ::= WITH RECURSIVE wqlist(W). { sqlite3WithPush(pParse, W, 1); } %type wqas {u8} wqas(A) ::= AS. {A = M10d_Any;} wqas(A) ::= AS MATERIALIZED. {A = M10d_Yes;} wqas(A) ::= AS NOT MATERIALIZED. {A = M10d_No;} wqitem(A) ::= nm(X) eidlist_opt(Y) wqas(M) LP select(Z) RP. { A = sqlite3CteNew(pParse, &X, Y, Z, M); /*A-overwrites-X*/ } wqlist(A) ::= wqitem(X). { A = sqlite3WithAdd(pParse, 0, X); /*A-overwrites-X*/ } wqlist(A) ::= wqlist(A) COMMA wqitem(X). { A = sqlite3WithAdd(pParse, A, X); } %endif SQLITE_OMIT_CTE |
︙ | ︙ | |||
1934 1935 1936 1937 1938 1939 1940 | %token COLUMN /* Reference to a table column */ AGG_FUNCTION /* An aggregate function */ AGG_COLUMN /* An aggregated column */ TRUEFALSE /* True or false keyword */ ISNOT /* Combination of IS and NOT */ FUNCTION /* A function invocation */ | < > | 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 | %token COLUMN /* Reference to a table column */ AGG_FUNCTION /* An aggregate function */ AGG_COLUMN /* An aggregated column */ TRUEFALSE /* True or false keyword */ ISNOT /* Combination of IS and NOT */ FUNCTION /* A function invocation */ UMINUS /* Unary minus */ UPLUS /* Unary plus */ TRUTH /* IS TRUE or IS FALSE or IS NOT TRUE or IS NOT FALSE */ REGISTER /* Reference to a VDBE register */ VECTOR /* Vector */ SELECT_COLUMN /* Choose a single column from a multi-column SELECT */ IF_NULL_ROW /* the if-null-row operator */ ASTERISK /* The "*" in count(*) and similar */ SPAN /* The span operator */ |
︙ | ︙ |
Changes to src/pragma.c.
︙ | ︙ | |||
1699 1700 1701 1702 1703 1704 1705 | /* Initialize the VDBE program */ pParse->nMem = 6; /* Set the maximum error count */ mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; if( zRight ){ | | | 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 | /* Initialize the VDBE program */ pParse->nMem = 6; /* Set the maximum error count */ mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; if( zRight ){ if( sqlite3GetInt32(zRight, &mxErr) ){ if( mxErr<=0 ){ mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; } }else{ pObjTab = sqlite3LocateTable(pParse, 0, zRight, iDb>=0 ? db->aDb[iDb].zDbSName : 0); } |
︙ | ︙ | |||
2866 2867 2868 2869 2870 2871 2872 | pIdxInfo->estimatedCost = (double)1; if( pTab->nHidden==0 ){ return SQLITE_OK; } pConstraint = pIdxInfo->aConstraint; seen[0] = 0; seen[1] = 0; for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ | | | > < | | | < < | 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 | pIdxInfo->estimatedCost = (double)1; if( pTab->nHidden==0 ){ return SQLITE_OK; } pConstraint = pIdxInfo->aConstraint; seen[0] = 0; seen[1] = 0; for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ if( pConstraint->usable==0 ) continue; if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; if( pConstraint->iColumn < pTab->iHidden ) continue; j = pConstraint->iColumn - pTab->iHidden; assert( j < 2 ); seen[j] = i+1; } if( seen[0]==0 ){ pIdxInfo->estimatedCost = (double)2147483647; pIdxInfo->estimatedRows = 2147483647; return SQLITE_OK; } j = seen[0]-1; pIdxInfo->aConstraintUsage[j].argvIndex = 1; pIdxInfo->aConstraintUsage[j].omit = 1; if( seen[1]==0 ) return SQLITE_OK; pIdxInfo->estimatedCost = (double)20; pIdxInfo->estimatedRows = 20; j = seen[1]-1; pIdxInfo->aConstraintUsage[j].argvIndex = 2; pIdxInfo->aConstraintUsage[j].omit = 1; return SQLITE_OK; } /* Create a new cursor for the pragma virtual table */ static int pragmaVtabOpen(sqlite3_vtab *pVtab, sqlite3_vtab_cursor **ppCursor){ PragmaVtabCursor *pCsr; pCsr = (PragmaVtabCursor*)sqlite3_malloc(sizeof(*pCsr)); if( pCsr==0 ) return SQLITE_NOMEM; memset(pCsr, 0, sizeof(PragmaVtabCursor)); pCsr->base.pVtab = pVtab; *ppCursor = &pCsr->base; return SQLITE_OK; } /* Clear all content from pragma virtual table cursor. */ static void pragmaVtabCursorClear(PragmaVtabCursor *pCsr){ int i; sqlite3_finalize(pCsr->pPragma); pCsr->pPragma = 0; for(i=0; i<ArraySize(pCsr->azArg); i++){ sqlite3_free(pCsr->azArg[i]); pCsr->azArg[i] = 0; } } /* Close a pragma virtual table cursor */ |
︙ | ︙ |
Changes to src/prepare.c.
︙ | ︙ | |||
629 630 631 632 633 634 635 | ** pObj = sqlite3ParserAddCleanup(pParse, destructor, pObj); */ void *sqlite3ParserAddCleanup( Parse *pParse, /* Destroy when this Parser finishes */ void (*xCleanup)(sqlite3*,void*), /* The cleanup routine */ void *pPtr /* Pointer to object to be cleaned up */ ){ | < < < < < | < | 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 | ** pObj = sqlite3ParserAddCleanup(pParse, destructor, pObj); */ void *sqlite3ParserAddCleanup( Parse *pParse, /* Destroy when this Parser finishes */ void (*xCleanup)(sqlite3*,void*), /* The cleanup routine */ void *pPtr /* Pointer to object to be cleaned up */ ){ ParseCleanup *pCleanup = sqlite3DbMallocRaw(pParse->db, sizeof(*pCleanup)); if( pCleanup ){ pCleanup->pNext = pParse->pCleanup; pParse->pCleanup = pCleanup; pCleanup->pPtr = pPtr; pCleanup->xCleanup = xCleanup; }else{ xCleanup(pParse->db, pPtr); |
︙ | ︙ |
Changes to src/printf.c.
︙ | ︙ | |||
853 854 855 856 857 858 859 | sqlite3_str_append(pAccum, ".", 1); } sqlite3_str_appendall(pAccum, pItem->zName); }else if( pItem->zAlias ){ sqlite3_str_appendall(pAccum, pItem->zAlias); }else{ Select *pSel = pItem->pSelect; | | < < < < | 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 | sqlite3_str_append(pAccum, ".", 1); } sqlite3_str_appendall(pAccum, pItem->zName); }else if( pItem->zAlias ){ sqlite3_str_appendall(pAccum, pItem->zAlias); }else{ Select *pSel = pItem->pSelect; assert( pSel!=0 ); if( pSel->selFlags & SF_NestedFrom ){ sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId); }else{ sqlite3_str_appendf(pAccum, "(subquery-%u)", pSel->selId); } } length = width = 0; break; } |
︙ | ︙ |
Changes to src/resolve.c.
︙ | ︙ | |||
465 466 467 468 469 470 471 | if( pItem->fg.isNestedFrom ){ sqlite3SrcItemColumnUsed(pItem, j); } break; } } if( 0==cnt && VisibleRowid(pTab) ){ | < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < | 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 | if( pItem->fg.isNestedFrom ){ sqlite3SrcItemColumnUsed(pItem, j); } break; } } if( 0==cnt && VisibleRowid(pTab) ){ cntTab++; pMatch = pItem; } } if( pMatch ){ pExpr->iTable = pMatch->iCursor; assert( ExprUseYTab(pExpr) ); pExpr->y.pTab = pMatch->pTab; if( (pMatch->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 ){ |
︙ | ︙ | |||
524 525 526 527 528 529 530 | #ifndef SQLITE_OMIT_TRIGGER if( pParse->pTriggerTab!=0 ){ int op = pParse->eTriggerOp; assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT ); if( pParse->bReturning ){ if( (pNC->ncFlags & NC_UBaseReg)!=0 && ALWAYS(zTab==0 | | < | 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 | #ifndef SQLITE_OMIT_TRIGGER if( pParse->pTriggerTab!=0 ){ int op = pParse->eTriggerOp; assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT ); if( pParse->bReturning ){ if( (pNC->ncFlags & NC_UBaseReg)!=0 && ALWAYS(zTab==0 || sqlite3StrICmp(zTab,pParse->pTriggerTab->zName)==0) ){ pExpr->iTable = op!=TK_DELETE; pTab = pParse->pTriggerTab; } }else if( op!=TK_DELETE && zTab && sqlite3StrICmp("new",zTab) == 0 ){ pExpr->iTable = 1; pTab = pParse->pTriggerTab; |
︙ | ︙ | |||
622 623 624 625 626 627 628 | } #endif /* !defined(SQLITE_OMIT_TRIGGER) || !defined(SQLITE_OMIT_UPSERT) */ /* ** Perhaps the name is a reference to the ROWID */ if( cnt==0 | | | < < < < < | 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 | } #endif /* !defined(SQLITE_OMIT_TRIGGER) || !defined(SQLITE_OMIT_UPSERT) */ /* ** Perhaps the name is a reference to the ROWID */ if( cnt==0 && cntTab==1 && pMatch && (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0 && sqlite3IsRowid(zCol) && ALWAYS(VisibleRowid(pMatch->pTab) || pMatch->fg.isNestedFrom) ){ cnt = 1; if( pMatch->fg.isNestedFrom==0 ) pExpr->iColumn = -1; pExpr->affExpr = SQLITE_AFF_INTEGER; } /* ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z ** might refer to an result-set alias. This happens, for example, when |
︙ | ︙ | |||
824 825 826 827 828 829 830 | ** if the mask contains extra set bits. However, it is important to ** avoid setting bits beyond the maximum column number of the table. ** (See ticket [b92e5e8ec2cdbaa1]). ** ** If a generated column is referenced, set bits for every column ** of the table. */ | < | | < < < | 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 | ** if the mask contains extra set bits. However, it is important to ** avoid setting bits beyond the maximum column number of the table. ** (See ticket [b92e5e8ec2cdbaa1]). ** ** If a generated column is referenced, set bits for every column ** of the table. */ if( pExpr->iColumn>=0 && cnt==1 && pMatch!=0 ){ pMatch->colUsed |= sqlite3ExprColUsed(pExpr); } pExpr->op = eNewExprOp; lookupname_end: if( cnt==1 ){ assert( pNC!=0 ); #ifndef SQLITE_OMIT_AUTHORIZATION |
︙ | ︙ | |||
1006 1007 1008 1009 1010 1011 1012 | ** "NOT NULL strength reduction optimization". ** ** If this optimization occurs, also restore the NameContext ref-counts ** to the state they where in before the "column" LHS expression was ** resolved. This prevents "column" from being counted as having been ** referenced, which might prevent a SELECT from being erroneously ** marked as correlated. | < < < < < < < < < < < < < < | < < < < < < < < < | | < < < < < < < < < | | | > | | | | | > | 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 | ** "NOT NULL strength reduction optimization". ** ** If this optimization occurs, also restore the NameContext ref-counts ** to the state they where in before the "column" LHS expression was ** resolved. This prevents "column" from being counted as having been ** referenced, which might prevent a SELECT from being erroneously ** marked as correlated. */ case TK_NOTNULL: case TK_ISNULL: { int anRef[8]; NameContext *p; int i; for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){ anRef[i] = p->nRef; } sqlite3WalkExpr(pWalker, pExpr->pLeft); if( 0==sqlite3ExprCanBeNull(pExpr->pLeft) && !IN_RENAME_OBJECT ){ testcase( ExprHasProperty(pExpr, EP_OuterON) ); assert( !ExprHasProperty(pExpr, EP_IntValue) ); pExpr->u.iValue = (pExpr->op==TK_NOTNULL); pExpr->flags |= EP_IntValue; pExpr->op = TK_INTEGER; for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){ p->nRef = anRef[i]; } sqlite3ExprDelete(pParse->db, pExpr->pLeft); pExpr->pLeft = 0; } return WRC_Prune; } /* A column name: ID ** Or table name and column name: ID.ID ** Or a database, table and column: ID.ID.ID ** |
︙ | ︙ | |||
1281 1282 1283 1284 1285 1286 1287 | #ifndef SQLITE_OMIT_WINDOWFUNC pNC->ncFlags &= ~(NC_AllowWin | (!pWin ? NC_AllowAgg : 0)); #else pNC->ncFlags &= ~NC_AllowAgg; #endif } } | > | > | 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 | #ifndef SQLITE_OMIT_WINDOWFUNC pNC->ncFlags &= ~(NC_AllowWin | (!pWin ? NC_AllowAgg : 0)); #else pNC->ncFlags &= ~NC_AllowAgg; #endif } } #ifndef SQLITE_OMIT_WINDOWFUNC else if( ExprHasProperty(pExpr, EP_WinFunc) ){ is_agg = 1; } #endif sqlite3WalkExprList(pWalker, pList); if( is_agg ){ if( pExpr->pLeft ){ assert( pExpr->pLeft->op==TK_ORDER ); assert( ExprUseXList(pExpr->pLeft) ); sqlite3WalkExprList(pWalker, pExpr->pLeft->x.pList); } |
︙ | ︙ | |||
1353 1354 1355 1356 1357 1358 1359 | testcase( pExpr->op==TK_IN ); if( ExprUseXSelect(pExpr) ){ int nRef = pNC->nRef; testcase( pNC->ncFlags & NC_IsCheck ); testcase( pNC->ncFlags & NC_PartIdx ); testcase( pNC->ncFlags & NC_IdxExpr ); testcase( pNC->ncFlags & NC_GenCol ); | < < | 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 | testcase( pExpr->op==TK_IN ); if( ExprUseXSelect(pExpr) ){ int nRef = pNC->nRef; testcase( pNC->ncFlags & NC_IsCheck ); testcase( pNC->ncFlags & NC_PartIdx ); testcase( pNC->ncFlags & NC_IdxExpr ); testcase( pNC->ncFlags & NC_GenCol ); if( pNC->ncFlags & NC_SelfRef ){ notValidImpl(pParse, pNC, "subqueries", pExpr, pExpr); }else{ sqlite3WalkSelect(pWalker, pExpr->x.pSelect); } assert( pNC->nRef>=nRef ); if( nRef!=pNC->nRef ){ ExprSetProperty(pExpr, EP_VarSelect); } pNC->ncFlags |= NC_Subquery; } break; } case TK_VARIABLE: { testcase( pNC->ncFlags & NC_IsCheck ); |
︙ | ︙ | |||
1888 1889 1890 1891 1892 1893 1894 | } /* Recursively resolve names in all subqueries in the FROM clause */ if( pOuterNC ) pOuterNC->nNestedSelect++; for(i=0; i<p->pSrc->nSrc; i++){ SrcItem *pItem = &p->pSrc->a[i]; | < | 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 | } /* Recursively resolve names in all subqueries in the FROM clause */ if( pOuterNC ) pOuterNC->nNestedSelect++; for(i=0; i<p->pSrc->nSrc; i++){ SrcItem *pItem = &p->pSrc->a[i]; if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){ int nRef = pOuterNC ? pOuterNC->nRef : 0; const char *zSavedContext = pParse->zAuthContext; if( pItem->zName ) pParse->zAuthContext = pItem->zName; sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC); pParse->zAuthContext = zSavedContext; |
︙ | ︙ | |||
1957 1958 1959 1960 1961 1962 1963 | if( p->pHaving ){ if( (p->selFlags & SF_Aggregate)==0 ){ sqlite3ErrorMsg(pParse, "HAVING clause on a non-aggregate query"); return WRC_Abort; } if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort; } | < < | 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 | if( p->pHaving ){ if( (p->selFlags & SF_Aggregate)==0 ){ sqlite3ErrorMsg(pParse, "HAVING clause on a non-aggregate query"); return WRC_Abort; } 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++){ SrcItem *pItem = &p->pSrc->a[i]; if( pItem->fg.isTabFunc && sqlite3ResolveExprListNames(&sNC, pItem->u1.pFuncArg) ){ |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
1669 1670 1671 1672 1673 1674 1675 | int bSeq; /* True if sorter record includes seq. no. */ int nRefKey = 0; struct ExprList_item *aOutEx = p->pEList->a; #ifdef SQLITE_ENABLE_STMT_SCANSTATUS int addrExplain; /* Address of OP_Explain instruction */ #endif | < < | | | < < < < < | 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 | int bSeq; /* True if sorter record includes seq. no. */ int nRefKey = 0; struct ExprList_item *aOutEx = p->pEList->a; #ifdef SQLITE_ENABLE_STMT_SCANSTATUS int addrExplain; /* Address of OP_Explain instruction */ #endif ExplainQueryPlan2(addrExplain, (pParse, 0, "USE TEMP B-TREE FOR %sORDER BY", pSort->nOBSat>0?"RIGHT PART OF ":"") ); sqlite3VdbeScanStatusRange(v, addrExplain,pSort->addrPush,pSort->addrPushEnd); sqlite3VdbeScanStatusCounters(v, addrExplain, addrExplain, pSort->addrPush); assert( addrBreak<0 ); if( pSort->labelBkOut ){ sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut); |
︙ | ︙ | |||
1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 | if( eDest==SRT_EphemTab || eDest==SRT_Table ){ regRow = sqlite3GetTempReg(pParse); nColumn = 0; }else{ regRow = sqlite3GetTempRange(pParse, nColumn); } } 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, | > | 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 | if( eDest==SRT_EphemTab || eDest==SRT_Table ){ regRow = sqlite3GetTempReg(pParse); nColumn = 0; }else{ 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, |
︙ | ︙ | |||
1955 1956 1957 1958 1959 1960 1961 | assert( pTab && ExprUseYTab(pExpr) && pExpr->y.pTab==pTab ); if( pS ){ /* The "table" is actually a sub-select or a view in the FROM clause ** of the SELECT statement. Return the declaration type and origin ** data for the result-set column of the sub-select. */ if( iCol<pS->pEList->nExpr | > | > > > | 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 | assert( pTab && ExprUseYTab(pExpr) && pExpr->y.pTab==pTab ); if( pS ){ /* The "table" is actually a sub-select or a view in the FROM clause ** of the SELECT statement. Return the declaration type and origin ** data for the result-set column of the sub-select. */ if( iCol<pS->pEList->nExpr #ifdef SQLITE_ALLOW_ROWID_IN_VIEW && iCol>=0 #else && ALWAYS(iCol>=0) #endif ){ /* If iCol is less than zero, then the expression requests the ** rowid of the sub-select or view. This expression is legal (see ** test case misc2.2.2) - it always evaluates to NULL. */ NameContext sNC; Expr *p = pS->pEList->a[iCol].pExpr; |
︙ | ︙ | |||
2320 2321 2322 2323 2324 2325 2326 | CollSeq *pColl; int i,j; Expr *p; struct ExprList_item *a; NameContext sNC; assert( pSelect!=0 ); | > | < < < < < < < | > > | | 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 | CollSeq *pColl; int i,j; Expr *p; struct ExprList_item *a; NameContext sNC; assert( pSelect!=0 ); testcase( (pSelect->selFlags & SF_Resolved)==0 ); assert( (pSelect->selFlags & SF_Resolved)!=0 || IN_RENAME_OBJECT ); assert( pTab->nCol==pSelect->pEList->nExpr || pParse->nErr>0 ); assert( aff==SQLITE_AFF_NONE || aff==SQLITE_AFF_BLOB ); if( db->mallocFailed || IN_RENAME_OBJECT ) return; while( pSelect->pPrior ) pSelect = pSelect->pPrior; a = pSelect->pEList->a; memset(&sNC, 0, sizeof(sNC)); sNC.pSrcList = pSelect->pSrc; for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){ const char *zType; i64 n; pTab->tabFlags |= (pCol->colFlags & COLFLAG_NOINSERT); p = a[i].pExpr; /* pCol->szEst = ... // Column size est for SELECT tables never used */ pCol->affinity = sqlite3ExprAffinity(p); if( pCol->affinity<=SQLITE_AFF_NONE ){ pCol->affinity = aff; } if( pCol->affinity>=SQLITE_AFF_TEXT && pSelect->pNext ){ int m = 0; Select *pS2; for(m=0, pS2=pSelect->pNext; pS2; pS2=pS2->pNext){ m |= sqlite3ExprDataType(pS2->pEList->a[i].pExpr); } if( pCol->affinity==SQLITE_AFF_TEXT && (m&0x01)!=0 ){ pCol->affinity = SQLITE_AFF_BLOB; }else if( pCol->affinity>=SQLITE_AFF_NUMERIC && (m&0x02)!=0 ){ pCol->affinity = SQLITE_AFF_BLOB; |
︙ | ︙ | |||
2376 2377 2378 2379 2380 2381 2382 | zType = sqlite3StdType[j]; break; } } } } if( zType ){ | | | | | 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 | zType = sqlite3StdType[j]; break; } } } } if( zType ){ i64 m = sqlite3Strlen30(zType); n = sqlite3Strlen30(pCol->zCnName); pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+m+2); pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL); if( pCol->zCnName ){ memcpy(&pCol->zCnName[n+1], zType, m+1); pCol->colFlags |= COLFLAG_HASTYPE; } } pColl = sqlite3ExprCollSeq(pParse, p); if( pColl ){ assert( pTab->pIndex==0 ); sqlite3ColumnSetColl(db, pCol, pColl->zName); |
︙ | ︙ | |||
4778 4779 4780 4781 4782 4783 4784 | WhereConst *pConst, /* The WhereConst into which we are inserting */ Expr *pColumn, /* The COLUMN part of the constraint */ Expr *pValue, /* The VALUE part of the constraint */ Expr *pExpr /* Overall expression: COLUMN=VALUE or VALUE=COLUMN */ ){ int i; assert( pColumn->op==TK_COLUMN ); | | | 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 | WhereConst *pConst, /* The WhereConst into which we are inserting */ Expr *pColumn, /* The COLUMN part of the constraint */ Expr *pValue, /* The VALUE part of the constraint */ Expr *pExpr /* Overall expression: COLUMN=VALUE or VALUE=COLUMN */ ){ int i; assert( pColumn->op==TK_COLUMN ); assert( sqlite3ExprIsConstant(pValue) ); if( ExprHasProperty(pColumn, EP_FixedCol) ) return; if( sqlite3ExprAffinity(pValue)!=0 ) return; if( !sqlite3IsBinary(sqlite3ExprCompareCollSeq(pConst->pParse,pExpr)) ){ return; } |
︙ | ︙ | |||
4836 4837 4838 4839 4840 4841 4842 | return; } if( pExpr->op!=TK_EQ ) return; pRight = pExpr->pRight; pLeft = pExpr->pLeft; assert( pRight!=0 ); assert( pLeft!=0 ); | | | | 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 | return; } if( pExpr->op!=TK_EQ ) return; pRight = pExpr->pRight; pLeft = pExpr->pLeft; assert( pRight!=0 ); assert( pLeft!=0 ); if( pRight->op==TK_COLUMN && sqlite3ExprIsConstant(pLeft) ){ constInsert(pConst,pRight,pLeft,pExpr); } if( pLeft->op==TK_COLUMN && sqlite3ExprIsConstant(pRight) ){ constInsert(pConst,pLeft,pRight,pExpr); } } /* ** This is a helper function for Walker callback propagateConstantExprRewrite(). ** |
︙ | ︙ | |||
5060 5061 5062 5063 5064 5065 5066 | ** ** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1 WHERE a=5 AND c-d=10) ** WHERE x=5 AND y=10; ** ** The hope is that the terms added to the inner query will make it more ** efficient. ** | < < < < < < < < < < < < | 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 | ** ** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1 WHERE a=5 AND c-d=10) ** WHERE x=5 AND y=10; ** ** The hope is that the terms added to the inner query will make it more ** efficient. ** ** Do not attempt this optimization if: ** ** (1) (** This restriction was removed on 2017-09-29. We used to ** disallow this optimization for aggregate subqueries, but now ** it is allowed by putting the extra terms on the HAVING clause. ** The added HAVING clause is pointless if the subquery lacks ** a GROUP BY clause. But such a HAVING clause is also harmless |
︙ | ︙ | |||
5137 5138 5139 5140 5141 5142 5143 | ** of a join (either an INNER or an OUTER join), and ** ** (9b) The subquery is to the right of the ON/USING clause ** ** (9c) There is a RIGHT JOIN (or FULL JOIN) in between the ON/USING ** clause and the subquery. ** | | | | | < < < < | 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 | ** of a join (either an INNER or an OUTER join), and ** ** (9b) The subquery is to the right of the ON/USING clause ** ** (9c) There is a RIGHT JOIN (or FULL JOIN) in between the ON/USING ** clause and the subquery. ** ** Without this restriction, the push-down optimization might move ** the ON/USING filter expression from the left side of a RIGHT JOIN ** over to the right side, which leads to incorrect answers. See ** also restriction (6) in sqlite3ExprIsSingleTableConstraint(). ** ** (10) The inner query is not the right-hand table of a RIGHT JOIN. ** ** (11) The subquery is not a VALUES clause ** ** 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 */ |
︙ | ︙ | |||
5260 5261 5262 5263 5264 5265 5266 | if( ExprHasProperty(pWhere,EP_OuterON) && pWhere->w.iJoin!=iCursor ){ return 0; /* restriction (5) */ } #endif | < < < < < < < < < < < < | | 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 | if( ExprHasProperty(pWhere,EP_OuterON) && pWhere->w.iJoin!=iCursor ){ return 0; /* restriction (5) */ } #endif if( sqlite3ExprIsSingleTableConstraint(pWhere, pSrcList, iSrc) ){ nChng++; pSubq->selFlags |= SF_PushDown; while( pSubq ){ SubstContext x; pNew = sqlite3ExprDup(pParse->db, pWhere, 0); unsetJoinExpr(pNew, -1, 1); x.pParse = pParse; |
︙ | ︙ | |||
5899 5900 5901 5902 5903 5904 5905 | pTab->zName = sqlite3DbStrDup(pParse->db, pFrom->zAlias); }else{ pTab->zName = sqlite3MPrintf(pParse->db, "%!S", pFrom); } while( pSel->pPrior ){ pSel = pSel->pPrior; } sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol); pTab->iPKey = -1; | < | < | 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 | pTab->zName = sqlite3DbStrDup(pParse->db, pFrom->zAlias); }else{ pTab->zName = sqlite3MPrintf(pParse->db, "%!S", pFrom); } while( pSel->pPrior ){ pSel = pSel->pPrior; } sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol); pTab->iPKey = -1; pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); #ifndef SQLITE_ALLOW_ROWID_IN_VIEW /* The usual case - do not allow ROWID on a subquery */ pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid; #else pTab->tabFlags |= TF_Ephemeral; /* Legacy compatibility mode */ #endif return pParse->nErr ? SQLITE_ERROR : SQLITE_OK; } /* ** Check the N SrcItem objects to the right of pBase. (N might be zero!) |
︙ | ︙ | |||
6174 6175 6176 6177 6178 6179 6180 | if( db->mallocFailed ) break; assert( (int)pFrom->fg.isNestedFrom == IsNestedFrom(pFrom->pSelect) ); if( pFrom->fg.isNestedFrom ){ assert( pFrom->pSelect!=0 ); pNestedFrom = pFrom->pSelect->pEList; assert( pNestedFrom!=0 ); assert( pNestedFrom->nExpr==pTab->nCol ); | | | 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 | if( db->mallocFailed ) break; assert( (int)pFrom->fg.isNestedFrom == IsNestedFrom(pFrom->pSelect) ); if( pFrom->fg.isNestedFrom ){ assert( pFrom->pSelect!=0 ); pNestedFrom = pFrom->pSelect->pEList; assert( pNestedFrom!=0 ); assert( pNestedFrom->nExpr==pTab->nCol ); assert( VisibleRowid(pTab)==0 ); }else{ if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ continue; } pNestedFrom = 0; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); zSchemaName = iDb>=0 ? db->aDb[iDb].zDbSName : "*"; |
︙ | ︙ | |||
6206 6207 6208 6209 6210 6211 6212 | pX->fg.bUsingTerm = 1; } } }else{ pUsing = 0; } | | < | 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 | pX->fg.bUsingTerm = 1; } } }else{ pUsing = 0; } nAdd = pTab->nCol + (VisibleRowid(pTab) && (selFlags&SF_NestedFrom)); for(j=0; j<nAdd; j++){ const char *zName; struct ExprList_item *pX; /* Newly added ExprList term */ if( j==pTab->nCol ){ zName = sqlite3RowidAlias(pTab); if( zName==0 ) continue; |
︙ | ︙ | |||
6289 6290 6291 6292 6293 6294 6295 | pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); if( pNew==0 ){ break; /* OOM */ } pX = &pNew->a[pNew->nExpr-1]; assert( pX->zEName==0 ); if( (selFlags & SF_NestedFrom)!=0 && !IN_RENAME_OBJECT ){ | | < | 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 | pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); if( pNew==0 ){ break; /* OOM */ } pX = &pNew->a[pNew->nExpr-1]; assert( pX->zEName==0 ); if( (selFlags & SF_NestedFrom)!=0 && !IN_RENAME_OBJECT ){ if( pNestedFrom ){ pX->zEName = sqlite3DbStrDup(db, pNestedFrom->a[j].zEName); testcase( pX->zEName==0 ); }else{ pX->zEName = sqlite3MPrintf(db, "%s.%s.%s", zSchemaName, zTabName, zName); testcase( pX->zEName==0 ); } |
︙ | ︙ | |||
6407 6408 6409 6410 6411 6412 6413 | int i; SrcList *pTabList; SrcItem *pFrom; if( p->selFlags & SF_HasTypeInfo ) return; p->selFlags |= SF_HasTypeInfo; pParse = pWalker->pParse; | > | | 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 | int i; SrcList *pTabList; SrcItem *pFrom; if( p->selFlags & SF_HasTypeInfo ) return; p->selFlags |= SF_HasTypeInfo; pParse = pWalker->pParse; testcase( (p->selFlags & SF_Resolved)==0 ); assert( (p->selFlags & SF_Resolved) || IN_RENAME_OBJECT ); pTabList = p->pSrc; for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ Table *pTab = pFrom->pTab; assert( pTab!=0 ); if( (pTab->tabFlags & TF_Ephemeral)!=0 ){ /* A sub-query in the FROM clause of a SELECT */ Select *pSel = pFrom->pSelect; |
︙ | ︙ | |||
7669 7670 7671 7672 7673 7674 7675 | sqlite3AuthCheck(pParse, SQLITE_READ, pItem->zName, "", pItem->zDatabase); } #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) /* Generate code for all sub-queries in the FROM clause */ pSub = pItem->pSelect; | | | 7632 7633 7634 7635 7636 7637 7638 7639 7640 7641 7642 7643 7644 7645 7646 | sqlite3AuthCheck(pParse, SQLITE_READ, pItem->zName, "", pItem->zDatabase); } #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) /* Generate code for all sub-queries in the FROM clause */ pSub = pItem->pSelect; if( pSub==0 ) continue; /* The code for a subquery should only be generated once. */ assert( pItem->addrFillSub==0 ); /* Increment Parse.nHeight by the height of the largest expression ** tree referred to by this, the parent select. The child select ** may contain expression trees of at most |
︙ | ︙ | |||
7700 7701 7702 7703 7704 7705 7706 | TREETRACE(0x4000,pParse,p, ("After WHERE-clause push-down into subquery %d:\n", pSub->selId)); sqlite3TreeViewSelect(0, p, 0); } #endif assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 ); }else{ | | | 7663 7664 7665 7666 7667 7668 7669 7670 7671 7672 7673 7674 7675 7676 7677 | TREETRACE(0x4000,pParse,p, ("After WHERE-clause push-down into subquery %d:\n", pSub->selId)); sqlite3TreeViewSelect(0, p, 0); } #endif assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 ); }else{ TREETRACE(0x4000,pParse,p,("Push-down not possible\n")); } /* Convert unused result columns of the subquery into simple NULL ** expressions, to avoid unneeded searching and computation. */ if( OptimizationEnabled(db, SQLITE_NullUnusedCols) && disableUnusedSubqueryResultColumns(pItem) |
︙ | ︙ |
Changes to src/shell.c.in.
︙ | ︙ | |||
7936 7937 7938 7939 7940 7941 7942 | */ static struct { int iId; /* ID that triggers a simulated fault. -1 means "any" */ int iErr; /* The error code to return on a fault */ int iCnt; /* Trigger the fault only if iCnt is already zero */ int iInterval; /* Reset iCnt to this value after each fault */ int eVerbose; /* When to print output */ | < < < | | | < < < < | 7936 7937 7938 7939 7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956 7957 7958 7959 7960 7961 7962 7963 7964 7965 7966 7967 7968 7969 | */ static struct { int iId; /* ID that triggers a simulated fault. -1 means "any" */ int iErr; /* The error code to return on a fault */ int iCnt; /* Trigger the fault only if iCnt is already zero */ int iInterval; /* Reset iCnt to this value after each fault */ int eVerbose; /* When to print output */ } faultsim_state = {-1, 0, 0, 0, 0}; /* ** This is the fault-sim callback */ static int faultsim_callback(int iArg){ if( faultsim_state.iId>0 && faultsim_state.iId!=iArg ){ return SQLITE_OK; } if( faultsim_state.iCnt>0 ){ faultsim_state.iCnt--; if( faultsim_state.eVerbose>=2 ){ oputf("FAULT-SIM id=%d no-fault (cnt=%d)\n", iArg, faultsim_state.iCnt); } return SQLITE_OK; } if( faultsim_state.eVerbose>=1 ){ oputf("FAULT-SIM id=%d returns %d\n", iArg, faultsim_state.iErr); } faultsim_state.iCnt = faultsim_state.iInterval; return faultsim_state.iErr; } /* ** If an input line begins with "." then invoke this routine to ** process that line. ** |
︙ | ︙ | |||
8781 8782 8783 8784 8785 8786 8787 | showHelp(p->out, 0); } }else #ifndef SQLITE_SHELL_FIDDLE if( c=='i' && cli_strncmp(azArg[0], "import", n)==0 ){ char *zTable = 0; /* Insert data into this table */ | | | | > | 8774 8775 8776 8777 8778 8779 8780 8781 8782 8783 8784 8785 8786 8787 8788 8789 8790 8791 8792 8793 8794 8795 8796 8797 | showHelp(p->out, 0); } }else #ifndef SQLITE_SHELL_FIDDLE if( c=='i' && cli_strncmp(azArg[0], "import", n)==0 ){ char *zTable = 0; /* Insert data into this table */ char *zSchema = 0; /* within this schema (may default to "main") */ char *zFile = 0; /* Name of file to extra content from */ sqlite3_stmt *pStmt = NULL; /* A statement */ int nCol; /* Number of columns in the table */ int nByte; /* Number of bytes in an SQL string */ int i, j; /* Loop counters */ int needCommit; /* True to COMMIT or ROLLBACK at end */ int nSep; /* Number of bytes in p->colSeparator[] */ char *zSql; /* An SQL statement */ char *zFullTabName; /* Table name with schema if applicable */ ImportCtx sCtx; /* Reader context */ char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */ int eVerbose = 0; /* Larger for more console output */ int nSkip = 0; /* Initial lines to skip */ int useOutputMode = 1; /* Use output mode to determine separators */ char *zCreate = 0; /* CREATE TABLE statement text */ |
︙ | ︙ | |||
8923 8924 8925 8926 8927 8928 8929 8930 | import_cleanup(&sCtx); shell_out_of_memory(); } /* Below, resources must be freed before exit. */ while( (nSkip--)>0 ){ while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){} } import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */ | > > > > > > > > > > > > | < | < > > > > < < < < < < | < < < < < < < < < < | | > > | < < | | < < < < < < < < | < | < < < < < < < | < < > > | 8917 8918 8919 8920 8921 8922 8923 8924 8925 8926 8927 8928 8929 8930 8931 8932 8933 8934 8935 8936 8937 8938 8939 8940 8941 8942 8943 8944 8945 8946 8947 8948 8949 8950 8951 8952 8953 8954 8955 8956 8957 8958 8959 8960 8961 8962 8963 8964 8965 8966 8967 8968 8969 8970 8971 8972 8973 8974 8975 8976 8977 8978 8979 8980 8981 8982 8983 8984 8985 8986 8987 8988 8989 8990 8991 8992 8993 8994 8995 8996 8997 8998 8999 9000 9001 9002 9003 9004 9005 9006 9007 9008 9009 9010 9011 9012 9013 9014 9015 9016 9017 | import_cleanup(&sCtx); shell_out_of_memory(); } /* Below, resources must be freed before exit. */ while( (nSkip--)>0 ){ while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){} } if( zSchema!=0 ){ zFullTabName = sqlite3_mprintf("\"%w\".\"%w\"", zSchema, zTable); }else{ zFullTabName = sqlite3_mprintf("\"%w\"", zTable); } zSql = sqlite3_mprintf("SELECT * FROM %s", zFullTabName); if( zSql==0 || zFullTabName==0 ){ import_cleanup(&sCtx); 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 ){ sqlite3 *dbCols = 0; char *zRenames = 0; char *zColDefs; zCreate = sqlite3_mprintf("CREATE TABLE %s", zFullTabName); while( xRead(&sCtx) ){ zAutoColumn(sCtx.z, &dbCols, 0); if( sCtx.cTerm!=sCtx.cColSep ) break; } zColDefs = zAutoColumn(0, &dbCols, &zRenames); if( zRenames!=0 ){ sputf((stdin_is_interactive && p->in==stdin)? p->out : stderr, "Columns renamed during .import %s due to duplicates:\n" "%s\n", sCtx.zFile, zRenames); sqlite3_free(zRenames); } assert(dbCols==0); if( zColDefs==0 ){ eputf("%s: empty file\n", sCtx.zFile); import_fail: sqlite3_free(zCreate); sqlite3_free(zSql); sqlite3_free(zFullTabName); import_cleanup(&sCtx); rc = 1; goto meta_command_exit; } zCreate = sqlite3_mprintf("%z%z\n", zCreate, zColDefs); if( eVerbose>=1 ){ oputf("%s\n", zCreate); } rc = sqlite3_exec(p->db, zCreate, 0, 0, 0); if( rc ){ eputf("%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db)); goto import_fail; } sqlite3_free(zCreate); zCreate = 0; rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); } if( rc ){ if (pStmt) sqlite3_finalize(pStmt); eputf("Error: %s\n", sqlite3_errmsg(p->db)); goto import_fail; } sqlite3_free(zSql); 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 ){ import_cleanup(&sCtx); shell_out_of_memory(); } sqlite3_snprintf(nByte+20, zSql, "INSERT INTO %s VALUES(?", zFullTabName); j = strlen30(zSql); for(i=1; i<nCol; i++){ zSql[j++] = ','; zSql[j++] = '?'; } zSql[j++] = ')'; zSql[j] = 0; if( eVerbose>=2 ){ oputf("Insert using: %s\n", zSql); } rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); if( rc ){ eputf("Error: %s\n", sqlite3_errmsg(p->db)); if (pStmt) sqlite3_finalize(pStmt); goto import_fail; } sqlite3_free(zSql); sqlite3_free(zFullTabName); needCommit = sqlite3_get_autocommit(p->db); if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0); do{ int startLine = sCtx.nLine; for(i=0; i<nCol; i++){ char *z = xRead(&sCtx); /* |
︙ | ︙ | |||
11129 11130 11131 11132 11133 11134 11135 | isOk = 3; for(kk=2; kk<nArg; kk++){ const char *z = azArg[kk]; if( z[0]=='-' && z[1]=='-' ) z++; if( cli_strcmp(z,"off")==0 ){ sqlite3_test_control(testctrl, 0); }else if( cli_strcmp(z,"on")==0 ){ | | < | < < < < < < < < < | 11105 11106 11107 11108 11109 11110 11111 11112 11113 11114 11115 11116 11117 11118 11119 11120 11121 11122 11123 11124 11125 11126 11127 11128 11129 11130 11131 11132 11133 11134 11135 11136 11137 11138 11139 | isOk = 3; for(kk=2; kk<nArg; kk++){ const char *z = azArg[kk]; if( z[0]=='-' && z[1]=='-' ) z++; if( cli_strcmp(z,"off")==0 ){ sqlite3_test_control(testctrl, 0); }else if( cli_strcmp(z,"on")==0 ){ faultsim_state.iCnt = faultsim_state.iInterval; if( faultsim_state.iErr==0 ) faultsim_state.iErr = 1; sqlite3_test_control(testctrl, faultsim_callback); }else if( cli_strcmp(z,"reset")==0 ){ faultsim_state.iCnt = faultsim_state.iInterval; }else if( cli_strcmp(z,"status")==0 ){ oputf("faultsim.iId: %d\n", faultsim_state.iId); oputf("faultsim.iErr: %d\n", faultsim_state.iErr); oputf("faultsim.iCnt: %d\n", faultsim_state.iCnt); oputf("faultsim.iInterval: %d\n", faultsim_state.iInterval); oputf("faultsim.eVerbose: %d\n", faultsim_state.eVerbose); }else if( cli_strcmp(z,"-v")==0 ){ if( faultsim_state.eVerbose<2 ) faultsim_state.eVerbose++; }else if( cli_strcmp(z,"-q")==0 ){ if( faultsim_state.eVerbose>0 ) faultsim_state.eVerbose--; }else if( cli_strcmp(z,"-id")==0 && kk+1<nArg ){ faultsim_state.iId = atoi(azArg[++kk]); }else if( cli_strcmp(z,"-errcode")==0 && kk+1<nArg ){ faultsim_state.iErr = atoi(azArg[++kk]); }else if( cli_strcmp(z,"-interval")==0 && kk+1<nArg ){ faultsim_state.iInterval = atoi(azArg[++kk]); }else if( cli_strcmp(z,"-?")==0 || sqlite3_strglob("*help*",z)==0){ bShowHelp = 1; }else{ eputf("Unrecognized fault_install argument: \"%s\"\n", azArg[kk]); rc = 1; bShowHelp = 1; |
︙ | ︙ | |||
11183 11184 11185 11186 11187 11188 11189 | " reset Reset the trigger counter\n" " status Show current status\n" " -v Increase verbosity\n" " -q Decrease verbosity\n" " --errcode N When triggered, return N as error code\n" " --id ID Trigger only for the ID specified\n" " --interval N Trigger only after every N-th call\n" | < < | 11149 11150 11151 11152 11153 11154 11155 11156 11157 11158 11159 11160 11161 11162 | " reset Reset the trigger counter\n" " status Show current status\n" " -v Increase verbosity\n" " -q Decrease verbosity\n" " --errcode N When triggered, return N as error code\n" " --id ID Trigger only for the ID specified\n" " --interval N Trigger only after every N-th call\n" ); } break; } } } if( isOk==0 && iCtrl>=0 ){ |
︙ | ︙ | |||
12078 12079 12080 12081 12082 12083 12084 | " -mmap N default mmap size set to N\n" #ifdef SQLITE_ENABLE_MULTIPLEX " -multiplex enable the multiplexor VFS\n" #endif " -newline SEP set output row separator. Default: '\\n'\n" " -nofollow refuse to open symbolic links to database files\n" " -nonce STRING set the safe-mode escape nonce\n" | < | 12042 12043 12044 12045 12046 12047 12048 12049 12050 12051 12052 12053 12054 12055 | " -mmap N default mmap size set to N\n" #ifdef SQLITE_ENABLE_MULTIPLEX " -multiplex enable the multiplexor VFS\n" #endif " -newline SEP set output row separator. Default: '\\n'\n" " -nofollow refuse to open symbolic links to database files\n" " -nonce STRING set the safe-mode escape nonce\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" " -pcachetrace trace all page cache operations\n" " -quote set output mode to 'quote'\n" " -readonly open the database read-only\n" " -safe enable safe-mode\n" " -separator SEP set output column separator. Default: '|'\n" |
︙ | ︙ | |||
12369 12370 12371 12372 12373 12374 12375 | /* Need to check for batch mode here to so we can avoid printing ** informational messages (like from process_sqliterc) before ** we do the actual processing of arguments later in a second pass. */ stdin_is_interactive = 0; }else if( cli_strcmp(z,"-utf8")==0 ){ }else if( cli_strcmp(z,"-no-utf8")==0 ){ | < < < < | 12332 12333 12334 12335 12336 12337 12338 12339 12340 12341 12342 12343 12344 12345 | /* Need to check for batch mode here to so we can avoid printing ** informational messages (like from process_sqliterc) before ** we do the actual processing of arguments later in a second pass. */ stdin_is_interactive = 0; }else if( cli_strcmp(z,"-utf8")==0 ){ }else if( cli_strcmp(z,"-no-utf8")==0 ){ }else if( cli_strcmp(z,"-heap")==0 ){ #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) const char *zSize; sqlite3_int64 szHeap; zSize = cmdline_option_value(argc, argv, ++i); szHeap = integerValue(zSize); |
︙ | ︙ | |||
12648 12649 12650 12651 12652 12653 12654 | stdin_is_interactive = 1; }else if( cli_strcmp(z,"-batch")==0 ){ /* already handled */ }else if( cli_strcmp(z,"-utf8")==0 ){ /* already handled */ }else if( cli_strcmp(z,"-no-utf8")==0 ){ /* already handled */ | < < | 12607 12608 12609 12610 12611 12612 12613 12614 12615 12616 12617 12618 12619 12620 | stdin_is_interactive = 1; }else if( cli_strcmp(z,"-batch")==0 ){ /* already handled */ }else if( cli_strcmp(z,"-utf8")==0 ){ /* already handled */ }else if( cli_strcmp(z,"-no-utf8")==0 ){ /* already handled */ }else if( cli_strcmp(z,"-heap")==0 ){ i++; }else if( cli_strcmp(z,"-pagecache")==0 ){ i+=2; }else if( cli_strcmp(z,"-lookaside")==0 ){ i+=2; }else if( cli_strcmp(z,"-threadsafe")==0 ){ |
︙ | ︙ | |||
12811 12812 12813 12814 12815 12816 12817 | data.in = stdin; rc = process_input(&data); } } #ifndef SQLITE_SHELL_FIDDLE /* In WASM mode we have to leave the db state in place so that ** client code can "push" SQL into it after this call returns. */ | < < < < < | 12768 12769 12770 12771 12772 12773 12774 12775 12776 12777 12778 12779 12780 12781 | data.in = stdin; rc = process_input(&data); } } #ifndef SQLITE_SHELL_FIDDLE /* In WASM mode we have to leave the db state in place so that ** client code can "push" SQL into it after this call returns. */ free(azCmd); set_table_name(&data, 0); if( data.db ){ session_close_all(&data, -1); close_db(data.db); } for(i=0; i<ArraySize(data.aAuxDb); i++){ |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
2139 2140 2141 2142 2143 2144 2145 | ** [sqlite3_int64] parameter which is the default maximum size for an in-memory ** database created using [sqlite3_deserialize()]. This default maximum ** size can be adjusted up or down for individual databases using the ** [SQLITE_FCNTL_SIZE_LIMIT] [sqlite3_file_control|file-control]. If this ** configuration setting is never used, then the default maximum is determined ** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that ** compile-time option is not set, then the default maximum is 1073741824. | < < < < < < < < < < < < < < < < | 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 | ** [sqlite3_int64] parameter which is the default maximum size for an in-memory ** database created using [sqlite3_deserialize()]. This default maximum ** size can be adjusted up or down for individual databases using the ** [SQLITE_FCNTL_SIZE_LIMIT] [sqlite3_file_control|file-control]. If this ** configuration setting is never used, then the default maximum is determined ** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that ** compile-time option is not set, then the default maximum is 1073741824. ** </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* */ |
︙ | ︙ | |||
2186 2187 2188 2189 2190 2191 2192 | #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 */ #define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */ | < | 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 | #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 */ #define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */ /* ** 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. ** |
︙ | ︙ | |||
3301 3302 3303 3304 3305 3306 3307 | #define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ #define SQLITE_FUNCTION 31 /* NULL Function Name */ #define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */ #define SQLITE_COPY 0 /* No longer used */ #define SQLITE_RECURSIVE 33 /* NULL NULL */ /* | | | | 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 | #define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ #define SQLITE_FUNCTION 31 /* NULL Function Name */ #define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */ #define SQLITE_COPY 0 /* No longer used */ #define SQLITE_RECURSIVE 33 /* NULL NULL */ /* ** CAPI3REF: Tracing And Profiling Functions ** METHOD: sqlite3 ** ** These routines are deprecated. Use the [sqlite3_trace_v2()] interface ** instead of the routines described here. ** ** These routines register callback functions that can be used for ** tracing and profiling the execution of SQL statements. ** |
︙ | ︙ | |||
6883 6884 6885 6886 6887 6888 6889 | ** ^In the current implementation, the update hook ** is not invoked when conflicting rows are deleted because of an ** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook ** invoked when rows are deleted using the [truncate optimization]. ** The exceptions defined in this paragraph might change in a future ** release of SQLite. ** | < < < < < < | 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879 | ** ^In the current implementation, the update hook ** is not invoked when conflicting rows are deleted because of an ** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook ** invoked when rows are deleted using the [truncate optimization]. ** The exceptions defined in this paragraph might change in a future ** release of SQLite. ** ** The update hook implementation must not do anything that will modify ** the database connection that invoked the update hook. Any actions ** to modify the database connection must be deferred until after the ** completion of the [sqlite3_step()] call that triggered the update hook. ** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their ** database connections for the meaning of "modify" in this paragraph. ** |
︙ | ︙ | |||
8359 8360 8361 8362 8363 8364 8365 | ** recognized by SQLite. Applications can uses these routines to determine ** whether or not a specific identifier needs to be escaped (for example, ** by enclosing in double-quotes) so as not to confuse the parser. ** ** The sqlite3_keyword_count() interface returns the number of distinct ** keywords understood by SQLite. ** | | | 8336 8337 8338 8339 8340 8341 8342 8343 8344 8345 8346 8347 8348 8349 8350 | ** recognized by SQLite. Applications can uses these routines to determine ** whether or not a specific identifier needs to be escaped (for example, ** by enclosing in double-quotes) so as not to confuse the parser. ** ** The sqlite3_keyword_count() interface returns the number of distinct ** keywords understood by SQLite. ** ** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and ** makes *Z point to that keyword expressed as UTF8 and writes the number ** of bytes in the keyword into *L. The string that *Z points to is not ** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns ** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z ** or L are NULL or invalid pointers then calls to ** sqlite3_keyword_name(N,Z,L) result in undefined behavior. ** |
︙ | ︙ | |||
9938 9939 9940 9941 9942 9943 9944 | ** that the query planner does not need the rows to be returned in sorted order ** as long as all rows with the same values in all columns identified by the ** "aOrderBy" field are adjacent.)^ This mode is used when the query planner ** is doing a GROUP BY. ** <li value="2"><p> ** ^(If the sqlite3_vtab_distinct() interface returns 2, that means ** that the query planner does not need the rows returned in any particular | | | | | > | | < > | < | < < | | < < | < < < < < < < < < < < < < < < < < | 9915 9916 9917 9918 9919 9920 9921 9922 9923 9924 9925 9926 9927 9928 9929 9930 9931 9932 9933 9934 9935 9936 9937 9938 9939 9940 9941 9942 9943 9944 9945 9946 | ** that the query planner does not need the rows to be returned in sorted order ** as long as all rows with the same values in all columns identified by the ** "aOrderBy" field are adjacent.)^ This mode is used when the query planner ** is doing a GROUP BY. ** <li value="2"><p> ** ^(If the sqlite3_vtab_distinct() interface returns 2, that means ** that the query planner does not need the rows returned in any particular ** order, as long as rows with the same values in all "aOrderBy" columns ** are adjacent.)^ ^(Furthermore, only a single row for each particular ** combination of values in the columns identified by the "aOrderBy" field ** needs to be returned.)^ ^It is always ok for two or more rows with the same ** values in all "aOrderBy" columns to be returned, as long as all such rows ** are adjacent. ^The virtual table may, if it chooses, omit extra rows ** that have the same value for all columns identified by "aOrderBy". ** ^However omitting the extra rows is optional. ** This mode is used for a DISTINCT query. ** <li value="3"><p> ** ^(If the sqlite3_vtab_distinct() interface returns 3, that means ** that the query planner needs only distinct rows but it does need the ** rows to be sorted.)^ ^The virtual table implementation is free to omit ** rows that are identical in all aOrderBy columns, if it wants to, but ** it is not required to omit any rows. This mode is used for queries ** that have both DISTINCT and ORDER BY clauses. ** </ol> ** ** ^For the purposes of comparing virtual table output values to see if the ** values are same value for sorting purposes, two NULL values are considered ** to be the same. In other words, the comparison operator is "IS" ** (or "IS NOT DISTINCT FROM") and not "==". ** ** If a virtual table implementation is unable to meet the requirements ** specified above, then it must not set the "orderByConsumed" flag in the |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
1121 1122 1123 1124 1125 1126 1127 | ** 0x00001000 LEFT JOIN simplifies to JOIN ** 0x00002000 Constant propagation ** 0x00004000 Push-down optimization ** 0x00008000 After all FROM-clause analysis ** 0x00010000 Beginning of DELETE/INSERT/UPDATE processing ** 0x00020000 Transform DISTINCT into GROUP BY ** 0x00040000 SELECT tree dump after all code has been generated | < | 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 | ** 0x00001000 LEFT JOIN simplifies to JOIN ** 0x00002000 Constant propagation ** 0x00004000 Push-down optimization ** 0x00008000 After all FROM-clause analysis ** 0x00010000 Beginning of DELETE/INSERT/UPDATE processing ** 0x00020000 Transform DISTINCT into GROUP BY ** 0x00040000 SELECT tree dump after all code has been generated */ /* ** Macros for "wheretrace" */ extern u32 sqlite3WhereTrace; #if defined(SQLITE_DEBUG) \ |
︙ | ︙ | |||
1152 1153 1154 1155 1156 1157 1158 | ** 0x00000002 Solver ** 0x00000004 Solver costs ** 0x00000008 WhereLoop inserts ** ** 0x00000010 Display sqlite3_index_info xBestIndex calls ** 0x00000020 Range an equality scan metrics ** 0x00000040 IN operator decisions | | | 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 | ** 0x00000002 Solver ** 0x00000004 Solver costs ** 0x00000008 WhereLoop inserts ** ** 0x00000010 Display sqlite3_index_info xBestIndex calls ** 0x00000020 Range an equality scan metrics ** 0x00000040 IN operator decisions ** 0x00000080 WhereLoop cost adjustements ** 0x00000100 ** 0x00000200 Covering index decisions ** 0x00000400 OR optimization ** 0x00000800 Index scanner ** 0x00001000 More details associated with code generation ** 0x00002000 ** 0x00004000 Show all WHERE terms at key points |
︙ | ︙ | |||
1902 1903 1904 1905 1906 1907 1908 | #define SQLITE_OrderByIdxJoin 0x00000040 /* ORDER BY of joins via index */ #define SQLITE_Transitive 0x00000080 /* Transitive constraints */ #define SQLITE_OmitNoopJoin 0x00000100 /* Omit unused tables in joins */ #define SQLITE_CountOfView 0x00000200 /* The count-of-view optimization */ #define SQLITE_CursorHints 0x00000400 /* Add OP_CursorHint opcodes */ #define SQLITE_Stat4 0x00000800 /* Use STAT4 data */ /* TH3 expects this value ^^^^^^^^^^ to be 0x0000800. Don't change it */ | | | 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 | #define SQLITE_OrderByIdxJoin 0x00000040 /* ORDER BY of joins via index */ #define SQLITE_Transitive 0x00000080 /* Transitive constraints */ #define SQLITE_OmitNoopJoin 0x00000100 /* Omit unused tables in joins */ #define SQLITE_CountOfView 0x00000200 /* The count-of-view optimization */ #define SQLITE_CursorHints 0x00000400 /* Add OP_CursorHint opcodes */ #define SQLITE_Stat4 0x00000800 /* Use STAT4 data */ /* TH3 expects this value ^^^^^^^^^^ to be 0x0000800. Don't change it */ #define SQLITE_PushDown 0x00001000 /* The push-down optimization */ #define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */ #define SQLITE_SkipScan 0x00004000 /* Skip-scans */ #define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */ #define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */ #define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */ #define SQLITE_OmitOrderBy 0x00040000 /* Omit pointless ORDER BY */ /* TH3 expects this value ^^^^^^^^^^ to be 0x40000. Coordinate any change */ |
︙ | ︙ | |||
2531 2532 2533 2534 2535 2536 2537 | #endif /* Does the table have a rowid */ #define HasRowid(X) (((X)->tabFlags & TF_WithoutRowid)==0) #define VisibleRowid(X) (((X)->tabFlags & TF_NoVisibleRowid)==0) | < < < < < < < < < | 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 | #endif /* Does the table have a rowid */ #define HasRowid(X) (((X)->tabFlags & TF_WithoutRowid)==0) #define VisibleRowid(X) (((X)->tabFlags & TF_NoVisibleRowid)==0) /* ** Each foreign key constraint is an instance of the following structure. ** ** A foreign key is associated with two tables. The "from" table is ** the table that contains the REFERENCES clause that creates the foreign ** key. The "to" table is the table that is named in the REFERENCES clause. ** Consider this example: |
︙ | ︙ | |||
3275 3276 3277 3278 3279 3280 3281 | ** jointype expresses the join between the table and the previous table. ** ** In the colUsed field, the high-order bit (bit 63) is set if the table ** contains more than 63 columns and the 64-th or later column is used. ** ** Union member validity: ** | | | < < | | | 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 | ** jointype expresses the join between the table and the previous table. ** ** In the colUsed field, the high-order bit (bit 63) is set if the table ** contains more than 63 columns and the 64-th or later column is used. ** ** Union member validity: ** ** u1.zIndexedBy fg.isIndexedBy && !fg.isTabFunc ** u1.pFuncArg fg.isTabFunc && !fg.isIndexedBy ** u2.pIBIndex fg.isIndexedBy && !fg.isCte ** u2.pCteUse fg.isCte && !fg.isIndexedBy */ struct SrcItem { Schema *pSchema; /* Schema to which this item is fixed */ char *zDatabase; /* Name of database holding this table */ char *zName; /* Name of the table */ char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */ Table *pTab; /* An SQL table corresponding to zName */ |
︙ | ︙ | |||
3308 3309 3310 3311 3312 3313 3314 | unsigned fromDDL :1; /* Comes from sqlite_schema */ unsigned isCte :1; /* This is a CTE */ unsigned notCte :1; /* This item may not match a CTE */ unsigned isUsing :1; /* u3.pUsing is valid */ unsigned isOn :1; /* u3.pOn was once valid and non-NULL */ unsigned isSynthUsing :1; /* u3.pUsing is synthesized from NATURAL */ unsigned isNestedFrom :1; /* pSelect is a SF_NestedFrom subquery */ | < < | 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 | unsigned fromDDL :1; /* Comes from sqlite_schema */ unsigned isCte :1; /* This is a CTE */ unsigned notCte :1; /* This item may not match a CTE */ unsigned isUsing :1; /* u3.pUsing is valid */ unsigned isOn :1; /* u3.pOn was once valid and non-NULL */ unsigned isSynthUsing :1; /* u3.pUsing is synthesized from NATURAL */ unsigned isNestedFrom :1; /* pSelect is a SF_NestedFrom subquery */ } fg; int iCursor; /* The VDBE cursor number used to access this table */ union { Expr *pOn; /* fg.isUsing==0 => The ON clause of a join */ IdList *pUsing; /* fg.isUsing==1 => The USING clause of a join */ } u3; Bitmask colUsed; /* Bit N set if column N used. Details above for N>62 */ union { char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */ ExprList *pFuncArg; /* Arguments to table-valued-function */ } u1; union { Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */ CteUse *pCteUse; /* CTE Usage info when fg.isCte is true */ } u2; }; |
︙ | ︙ | |||
3384 3385 3386 3387 3388 3389 3390 | #define WHERE_GROUPBY 0x0040 /* pOrderBy is really a GROUP BY */ #define WHERE_DISTINCTBY 0x0080 /* pOrderby is really a DISTINCT clause */ #define WHERE_WANT_DISTINCT 0x0100 /* All output needs to be distinct */ #define WHERE_SORTBYGROUP 0x0200 /* Support sqlite3WhereIsSorted() */ #define WHERE_AGG_DISTINCT 0x0400 /* Query is "SELECT agg(DISTINCT ...)" */ #define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */ #define WHERE_RIGHT_JOIN 0x1000 /* Processing a RIGHT JOIN */ | | | 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 | #define WHERE_GROUPBY 0x0040 /* pOrderBy is really a GROUP BY */ #define WHERE_DISTINCTBY 0x0080 /* pOrderby is really a DISTINCT clause */ #define WHERE_WANT_DISTINCT 0x0100 /* All output needs to be distinct */ #define WHERE_SORTBYGROUP 0x0200 /* Support sqlite3WhereIsSorted() */ #define WHERE_AGG_DISTINCT 0x0400 /* Query is "SELECT agg(DISTINCT ...)" */ #define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */ #define WHERE_RIGHT_JOIN 0x1000 /* Processing a RIGHT JOIN */ /* 0x2000 not currently used */ #define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */ /* 0x8000 not currently used */ /* Allowed return values from sqlite3WhereIsDistinct() */ #define WHERE_DISTINCT_NOOP 0 /* DISTINCT keyword not used */ #define WHERE_DISTINCT_UNIQUE 1 /* No duplicates */ |
︙ | ︙ | |||
3463 3464 3465 3466 3467 3468 3469 | #define NC_Complex 0x002000 /* True if a function or subquery seen */ #define NC_AllowWin 0x004000 /* Window functions are allowed here */ #define NC_HasWin 0x008000 /* One or more window functions seen */ #define NC_IsDDL 0x010000 /* Resolving names in a CREATE statement */ #define NC_InAggFunc 0x020000 /* True if analyzing arguments to an agg func */ #define NC_FromDDL 0x040000 /* SQL text comes from sqlite_schema */ #define NC_NoSelect 0x080000 /* Do not descend into sub-selects */ | < | 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 | #define NC_Complex 0x002000 /* True if a function or subquery seen */ #define NC_AllowWin 0x004000 /* Window functions are allowed here */ #define NC_HasWin 0x008000 /* One or more window functions seen */ #define NC_IsDDL 0x010000 /* Resolving names in a CREATE statement */ #define NC_InAggFunc 0x020000 /* True if analyzing arguments to an agg func */ #define NC_FromDDL 0x040000 /* SQL text comes from sqlite_schema */ #define NC_NoSelect 0x080000 /* Do not descend into sub-selects */ #define NC_OrderAgg 0x8000000 /* Has an aggregate other than count/min/max */ /* ** 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 |
︙ | ︙ | |||
3487 3488 3489 3490 3491 3492 3493 | struct Upsert { ExprList *pUpsertTarget; /* Optional description of conflict target */ 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 */ Upsert *pNextUpsert; /* Next ON CONFLICT clause in the list */ u8 isDoUpdate; /* True for DO UPDATE. False for DO NOTHING */ | < | 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 | struct Upsert { ExprList *pUpsertTarget; /* Optional description of conflict target */ 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 */ Upsert *pNextUpsert; /* Next ON CONFLICT clause in the list */ u8 isDoUpdate; /* True for DO UPDATE. False for DO NOTHING */ /* Above this point is the parse tree for the ON CONFLICT clauses. ** The next group of fields stores intermediate data. */ void *pToFree; /* Free memory when deleting the Upsert object */ /* All fields above are owned by the Upsert object and must be freed ** when the Upsert is destroyed. The fields below are used to transfer ** information from the INSERT processing down into the UPDATE processing ** while generating code. The fields below are owned by the INSERT |
︙ | ︙ | |||
3577 3578 3579 3580 3581 3582 3583 | #define SF_IncludeHidden 0x0020000 /* Include hidden columns in output */ #define SF_ComplexResult 0x0040000 /* Result contains subquery or function */ #define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */ #define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */ #define SF_View 0x0200000 /* SELECT statement is a view */ #define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */ #define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */ | | < | 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 | #define SF_IncludeHidden 0x0020000 /* Include hidden columns in output */ #define SF_ComplexResult 0x0040000 /* Result contains subquery or function */ #define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */ #define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */ #define SF_View 0x0200000 /* SELECT statement is a view */ #define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */ #define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */ #define SF_PushDown 0x1000000 /* SELECT has be modified by push-down opt */ #define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */ #define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */ #define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */ #define SF_UpdateFrom 0x10000000 /* Query originates with UPDATE FROM */ /* True if S exists and has SF_NestedFrom */ #define IsNestedFrom(S) ((S)!=0 && ((S)->selFlags&SF_NestedFrom)!=0) /* ** The results of a SELECT can be distributed in several ways, as defined ** by one of the following macros. The "SRT" prefix means "SELECT Result |
︙ | ︙ | |||
3822 3823 3824 3825 3826 3827 3828 | u8 isMultiWrite; /* True if statement may modify/insert multiple rows */ u8 mayAbort; /* True if statement may throw an ABORT exception */ u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ u8 okConstFactor; /* OK to factor out constants */ u8 disableLookaside; /* Number of times lookaside has been disabled */ u8 prepFlags; /* SQLITE_PREPARE_* flags */ u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */ | < | 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 | u8 isMultiWrite; /* True if statement may modify/insert multiple rows */ u8 mayAbort; /* True if statement may throw an ABORT exception */ u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ u8 okConstFactor; /* OK to factor out constants */ u8 disableLookaside; /* Number of times lookaside has been disabled */ u8 prepFlags; /* SQLITE_PREPARE_* flags */ u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */ #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */ #endif #ifdef SQLITE_DEBUG u8 ifNotExists; /* Might be true if IF NOT EXISTS. Assert()s only */ #endif int nRangeReg; /* Size of the temporary register block */ |
︙ | ︙ | |||
4261 4262 4263 4264 4265 4266 4267 | #endif #ifndef SQLITE_OMIT_DESERIALIZE sqlite3_int64 mxMemdbSize; /* Default max memdb size */ #endif #ifndef SQLITE_UNTESTABLE int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */ #endif | < < < < < | 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 | #endif #ifndef SQLITE_OMIT_DESERIALIZE sqlite3_int64 mxMemdbSize; /* Default max memdb size */ #endif #ifndef SQLITE_UNTESTABLE int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */ #endif int bLocaltimeFault; /* True to fail localtime() calls */ int (*xAltLocaltime)(const void*,void*); /* Alternative localtime() routine */ int iOnceResetThreshold; /* When to reset OP_Once counters */ u32 szSorterRef; /* Min size in bytes to use sorter-refs */ unsigned int iPrngSeed; /* Alternative fixed seed for the PRNG */ /* vvvv--- must be last ---vvv */ #ifdef SQLITE_DEBUG |
︙ | ︙ | |||
4502 4503 4504 4505 4506 4507 4508 | int regOne; /* Register containing constant value 1 */ int regStartRowid; int regEndRowid; u8 bExprArgs; /* Defer evaluation of window function arguments ** due to the SQLITE_SUBTYPE flag */ }; | < < < | 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 | int regOne; /* Register containing constant value 1 */ int regStartRowid; int regEndRowid; u8 bExprArgs; /* Defer evaluation of window function arguments ** due to the SQLITE_SUBTYPE flag */ }; #ifndef SQLITE_OMIT_WINDOWFUNC void sqlite3WindowDelete(sqlite3*, Window*); void sqlite3WindowUnlinkFromSelect(Window*); void sqlite3WindowListDelete(sqlite3 *db, Window *p); Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*, u8); void sqlite3WindowAttach(Parse*, Expr*, Window*); void sqlite3WindowLink(Select *pSel, Window *pWin); |
︙ | ︙ | |||
4724 4725 4726 4727 4728 4729 4730 | # define sqlite3MutexWarnOnContention(x) #endif #ifndef SQLITE_OMIT_FLOATING_POINT # define EXP754 (((u64)0x7ff)<<52) # define MAN754 ((((u64)1)<<52)-1) # define IsNaN(X) (((X)&EXP754)==EXP754 && ((X)&MAN754)!=0) | < < | | < | 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 | # define sqlite3MutexWarnOnContention(x) #endif #ifndef SQLITE_OMIT_FLOATING_POINT # define EXP754 (((u64)0x7ff)<<52) # define MAN754 ((((u64)1)<<52)-1) # define IsNaN(X) (((X)&EXP754)==EXP754 && ((X)&MAN754)!=0) int sqlite3IsNaN(double); #else # define IsNaN(X) 0 # define sqlite3IsNaN(X) 0 #endif /* ** An instance of the following structure holds information about SQL ** functions arguments that are the parameters to the printf() function. */ struct PrintfArguments { |
︙ | ︙ | |||
4853 4854 4855 4856 4857 4858 4859 | Expr *sqlite3ExprFunction(Parse*,ExprList*, const Token*, int); void sqlite3ExprAddFunctionOrderBy(Parse*,Expr*,ExprList*); void sqlite3ExprOrderByAggregateError(Parse*,Expr*); void sqlite3ExprFunctionUsable(Parse*,const Expr*,const FuncDef*); void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32); void sqlite3ExprDelete(sqlite3*, Expr*); void sqlite3ExprDeleteGeneric(sqlite3*,void*); | | | 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 | Expr *sqlite3ExprFunction(Parse*,ExprList*, const Token*, int); void sqlite3ExprAddFunctionOrderBy(Parse*,Expr*,ExprList*); void sqlite3ExprOrderByAggregateError(Parse*,Expr*); void sqlite3ExprFunctionUsable(Parse*,const Expr*,const FuncDef*); void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32); void sqlite3ExprDelete(sqlite3*, Expr*); void sqlite3ExprDeleteGeneric(sqlite3*,void*); void sqlite3ExprDeferredDelete(Parse*, Expr*); void sqlite3ExprUnmapAndDelete(Parse*, Expr*); ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*); Select *sqlite3ExprListToValues(Parse*, int, ExprList*); void sqlite3ExprListSetSortOrder(ExprList*,int,int); void sqlite3ExprListSetName(Parse*,ExprList*,const Token*,int); void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*); |
︙ | ︙ | |||
5076 5077 5078 5079 5080 5081 5082 | void sqlite3EndTransaction(Parse*,int); void sqlite3Savepoint(Parse*, int, Token*); void sqlite3CloseSavepoints(sqlite3 *); void sqlite3LeaveMutexAndCloseZombie(sqlite3*); u32 sqlite3IsTrueOrFalse(const char*); int sqlite3ExprIdToTrueFalse(Expr*); int sqlite3ExprTruthValue(const Expr*); | | > > | | 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 | void sqlite3EndTransaction(Parse*,int); void sqlite3Savepoint(Parse*, int, Token*); void sqlite3CloseSavepoints(sqlite3 *); void sqlite3LeaveMutexAndCloseZombie(sqlite3*); u32 sqlite3IsTrueOrFalse(const char*); int sqlite3ExprIdToTrueFalse(Expr*); int sqlite3ExprTruthValue(const Expr*); int sqlite3ExprIsConstant(Expr*); int sqlite3ExprIsConstantNotJoin(Expr*); int sqlite3ExprIsConstantOrFunction(Expr*, u8); int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*); int sqlite3ExprIsTableConstant(Expr*,int); int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int); #ifdef SQLITE_ENABLE_CURSOR_HINTS int sqlite3ExprContainsSubquery(Expr*); #endif int sqlite3ExprIsInteger(const Expr*, int*); int sqlite3ExprCanBeNull(const Expr*); int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); int sqlite3IsRowid(const char*); |
︙ | ︙ | |||
5264 5265 5266 5267 5268 5269 5270 | int sqlite3ExprDataType(const Expr *pExpr); int sqlite3Atoi64(const char*, i64*, int, u8); int sqlite3DecOrHexToI64(const char*, i64*); void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...); void sqlite3Error(sqlite3*,int); void sqlite3ErrorClear(sqlite3*); void sqlite3SystemError(sqlite3*,int); | < < | 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 | int sqlite3ExprDataType(const Expr *pExpr); int sqlite3Atoi64(const char*, i64*, int, u8); int sqlite3DecOrHexToI64(const char*, i64*); void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...); void sqlite3Error(sqlite3*,int); void sqlite3ErrorClear(sqlite3*); void sqlite3SystemError(sqlite3*,int); void *sqlite3HexToBlob(sqlite3*, const char *z, int n); u8 sqlite3HexToInt(int h); int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); #if defined(SQLITE_NEED_ERR_NAME) const char *sqlite3ErrName(int); #endif |
︙ | ︙ | |||
5577 5578 5579 5580 5581 5582 5583 | # define sqlite3WithDelete(x,y) # define sqlite3WithPush(x,y,z) ((void*)0) #endif #ifndef SQLITE_OMIT_UPSERT Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*,Upsert*); void sqlite3UpsertDelete(sqlite3*,Upsert*); Upsert *sqlite3UpsertDup(sqlite3*,Upsert*); | | | 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 | # define sqlite3WithDelete(x,y) # define sqlite3WithPush(x,y,z) ((void*)0) #endif #ifndef SQLITE_OMIT_UPSERT Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*,Upsert*); void sqlite3UpsertDelete(sqlite3*,Upsert*); Upsert *sqlite3UpsertDup(sqlite3*,Upsert*); int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*); void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int); Upsert *sqlite3UpsertOfIndex(Upsert*,Index*); int sqlite3UpsertNextIsIPK(Upsert*); #else #define sqlite3UpsertNew(u,v,w,x,y,z) ((Upsert*)0) #define sqlite3UpsertDelete(x,y) #define sqlite3UpsertDup(x,y) ((Upsert*)0) |
︙ | ︙ |
Changes to src/test_bestindex.c.
︙ | ︙ | |||
211 212 213 214 215 216 217 | rc = Tcl_EvalObjEx(interp, pScript, TCL_EVAL_GLOBAL); if( rc!=TCL_OK ){ *pzErr = sqlite3_mprintf("%s", Tcl_GetStringResult(interp)); rc = SQLITE_ERROR; }else{ rc = sqlite3_declare_vtab(db, Tcl_GetStringResult(interp)); | < < < | | 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 | rc = Tcl_EvalObjEx(interp, pScript, TCL_EVAL_GLOBAL); if( rc!=TCL_OK ){ *pzErr = sqlite3_mprintf("%s", Tcl_GetStringResult(interp)); rc = SQLITE_ERROR; }else{ rc = sqlite3_declare_vtab(db, Tcl_GetStringResult(interp)); } if( rc!=SQLITE_OK ){ sqlite3_free(pTab); pTab = 0; } }else{ rc = SQLITE_NOMEM; } sqlite3_free(zCmd); *ppVtab = &pTab->base; return rc; } /* The xDisconnect and xDestroy methods are also the same */ static int tclDisconnect(sqlite3_vtab *pVtab){ tcl_vtab *pTab = (tcl_vtab*)pVtab; while( pTab->pFindFunctionList ){ |
︙ | ︙ |
Changes to src/test_config.c.
︙ | ︙ | |||
55 56 57 58 59 60 61 | #ifdef SQLITE_32BIT_ROWID Tcl_SetVar2(interp, "sqlite_options", "rowid32", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "rowid32", "0", TCL_GLOBAL_ONLY); #endif | < < < < < < < < | 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | #ifdef SQLITE_32BIT_ROWID Tcl_SetVar2(interp, "sqlite_options", "rowid32", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "rowid32", "0", TCL_GLOBAL_ONLY); #endif #ifdef SQLITE_CASE_SENSITIVE_LIKE Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","1",TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","0",TCL_GLOBAL_ONLY); #endif #ifdef CONFIG_SLOWDOWN_FACTOR |
︙ | ︙ |
Changes to src/treeview.c.
︙ | ︙ | |||
190 191 192 193 194 195 196 | StrAccum x; int n = 0; char zLine[1000]; sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); x.printfFlags |= SQLITE_PRINTF_INTERNAL; sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem); if( pItem->pTab ){ | | | < < | 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | StrAccum x; int n = 0; char zLine[1000]; sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); x.printfFlags |= SQLITE_PRINTF_INTERNAL; sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem); if( pItem->pTab ){ sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx", pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed); } if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==(JT_LEFT|JT_RIGHT) ){ sqlite3_str_appendf(&x, " FULL-OUTER-JOIN"); }else if( pItem->fg.jointype & JT_LEFT ){ sqlite3_str_appendf(&x, " LEFT-JOIN"); }else if( pItem->fg.jointype & JT_RIGHT ){ sqlite3_str_appendf(&x, " RIGHT-JOIN"); |
︙ | ︙ | |||
233 234 235 236 237 238 239 | if( pItem->pSelect ) n++; if( pItem->fg.isTabFunc ) n++; if( pItem->fg.isUsing ) n++; if( pItem->fg.isUsing ){ sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING"); } if( pItem->pSelect ){ | < < | 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 | if( pItem->pSelect ) n++; if( pItem->fg.isTabFunc ) n++; if( pItem->fg.isUsing ) n++; if( pItem->fg.isUsing ){ sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING"); } if( pItem->pSelect ){ if( pItem->pTab ){ Table *pTab = pItem->pTab; sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1); } assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) ); sqlite3TreeViewSelect(pView, pItem->pSelect, (--n)>0); } if( pItem->fg.isTabFunc ){ sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:"); } sqlite3TreeViewPop(&pView); } } |
︙ | ︙ | |||
344 345 346 347 348 349 350 | if( p->pOrderBy ){ sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY"); } if( p->pLimit ){ sqlite3TreeViewItem(pView, "LIMIT", (n--)>0); sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0); if( p->pLimit->pRight ){ | | | 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 | if( p->pOrderBy ){ sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY"); } if( p->pLimit ){ sqlite3TreeViewItem(pView, "LIMIT", (n--)>0); sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0); if( p->pLimit->pRight ){ sqlite3TreeViewItem(pView, "OFFSET", (n--)>0); sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0); sqlite3TreeViewPop(&pView); } sqlite3TreeViewPop(&pView); } if( p->pPrior ){ const char *zOp = "UNION"; |
︙ | ︙ |
Changes to src/trigger.c.
︙ | ︙ | |||
947 948 949 950 951 952 953 | pItem->fg.eEName = pList->a[i].fg.eEName; } } } return pNew; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 947 948 949 950 951 952 953 954 955 956 957 958 959 960 | pItem->fg.eEName = pList->a[i].fg.eEName; } } } return pNew; } /* ** Generate code for the RETURNING trigger. Unlike other triggers ** that invoke a subprogram in the bytecode, the code for RETURNING ** is generated in-line. */ static void codeReturningTrigger( Parse *pParse, /* Parse context */ |
︙ | ︙ | |||
1049 1050 1051 1052 1053 1054 1055 | } memset(&sSelect, 0, sizeof(sSelect)); memset(&sFrom, 0, sizeof(sFrom)); sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0); sSelect.pSrc = &sFrom; sFrom.nSrc = 1; sFrom.a[0].pTab = pTab; | < | 983 984 985 986 987 988 989 990 991 992 993 994 995 996 | } memset(&sSelect, 0, sizeof(sSelect)); memset(&sFrom, 0, sizeof(sFrom)); sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0); sSelect.pSrc = &sFrom; sFrom.nSrc = 1; sFrom.a[0].pTab = pTab; sFrom.a[0].iCursor = -1; sqlite3SelectPrep(pParse, &sSelect, 0); if( pParse->nErr==0 ){ assert( db->mallocFailed==0 ); sqlite3GenerateColumnNames(pParse, &sSelect); } sqlite3ExprListDelete(db, sSelect.pEList); |
︙ | ︙ | |||
1076 1077 1078 1079 1080 1081 1082 | pParse->pTriggerTab = pTab; if( sqlite3ResolveExprListNames(&sNC, pNew)==SQLITE_OK && ALWAYS(!db->mallocFailed) ){ int i; int nCol = pNew->nExpr; int reg = pParse->nMem+1; | < | 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 | pParse->pTriggerTab = pTab; if( sqlite3ResolveExprListNames(&sNC, pNew)==SQLITE_OK && ALWAYS(!db->mallocFailed) ){ int i; int nCol = pNew->nExpr; int reg = pParse->nMem+1; pParse->nMem += nCol+2; pReturning->iRetReg = reg; for(i=0; i<nCol; i++){ Expr *pCol = pNew->a[i].pExpr; assert( pCol!=0 ); /* Due to !db->mallocFailed ~9 lines above */ sqlite3ExprCodeFactorable(pParse, pCol, reg+i); if( sqlite3ExprAffinity(pCol)==SQLITE_AFF_REAL ){ |
︙ | ︙ |
Changes to src/update.c.
︙ | ︙ | |||
917 918 919 920 921 922 923 | testcase( oldmask!=0xffffffff && i==31 ); sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, k); } } if( chngRowid==0 && pPk==0 ){ | < < < | 917 918 919 920 921 922 923 924 925 926 927 928 929 930 | testcase( oldmask!=0xffffffff && i==31 ); sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, k); } } if( chngRowid==0 && pPk==0 ){ sqlite3VdbeAddOp2(v, OP_Copy, regOldRowid, regNewRowid); } } /* Populate the array of registers beginning at regNew with the new ** row data. This array is used to check constants, create the new ** table and index records, and as the values for any new.* references |
︙ | ︙ |
Changes to src/upsert.c.
︙ | ︙ | |||
86 87 88 89 90 91 92 | ** ** 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 */ | | < | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | ** ** 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 */ |
︙ | ︙ | |||
190 191 192 193 194 195 196 | } 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; | < < < < < < < < | 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | } 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; break; } if( pUpsert->pUpsertIdx==0 ){ char zWhich[16]; if( nClause==0 && pUpsert->pNextUpsert==0 ){ zWhich[0] = 0; }else{ |
︙ | ︙ | |||
224 225 226 227 228 229 230 | ** conflict target, or if pUpsert is followed by another ON CONFLICT ** clause that targets the INTEGER PRIMARY KEY. */ int sqlite3UpsertNextIsIPK(Upsert *pUpsert){ Upsert *pNext; if( NEVER(pUpsert==0) ) return 0; pNext = pUpsert->pNextUpsert; | < | | | < < < | 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 | ** conflict target, or if pUpsert is followed by another ON CONFLICT ** clause that targets the INTEGER PRIMARY KEY. */ int sqlite3UpsertNextIsIPK(Upsert *pUpsert){ Upsert *pNext; if( NEVER(pUpsert==0) ) return 0; pNext = pUpsert->pNextUpsert; if( pNext==0 ) return 1; if( pNext->pUpsertTarget==0 ) return 1; if( pNext->pUpsertIdx==0 ) return 1; return 0; } /* ** Given the list of ON CONFLICT clauses described by pUpsert, and ** a particular index pIdx, return a pointer to the particular ON CONFLICT ** clause that applies to the index. Or, if the index is not subject to |
︙ | ︙ |
Changes to src/util.c.
︙ | ︙ | |||
64 65 66 67 68 69 70 | rc = isnan(x); #endif /* HAVE_ISNAN */ testcase( rc ); return rc; } #endif /* SQLITE_OMIT_FLOATING_POINT */ | < < < < < < < < < < < < < | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | rc = isnan(x); #endif /* HAVE_ISNAN */ testcase( rc ); return rc; } #endif /* SQLITE_OMIT_FLOATING_POINT */ /* ** Compute a string length that is limited to what can be stored in ** lower 30 bits of a 32-bit signed integer. ** ** The value returned will never be negative. Nor will it ever be greater ** than the actual length of the string. For very long strings (greater ** than 1GiB) the value returned might be less than the true string length. |
︙ | ︙ | |||
674 675 676 677 678 679 680 | *pResult = (double)r; } }else{ double rr[2]; u64 s2; rr[0] = (double)s; s2 = (u64)rr[0]; | < < < | 661 662 663 664 665 666 667 668 669 670 671 672 673 674 | *pResult = (double)r; } }else{ double rr[2]; u64 s2; rr[0] = (double)s; s2 = (u64)rr[0]; rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s); if( e>0 ){ while( e>=100 ){ e -= 100; dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83); } while( e>=10 ){ |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
1125 1126 1127 1128 1129 1130 1131 | ** ** If P2!=0 then the coroutine implementation immediately follows ** this opcode. So jump over the coroutine implementation to ** address P2. ** ** See also: EndCoroutine */ | | | 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 | ** ** If P2!=0 then the coroutine implementation immediately follows ** this opcode. So jump over the coroutine implementation to ** address P2. ** ** See also: EndCoroutine */ case OP_InitCoroutine: { /* jump */ assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); assert( pOp->p2>=0 && pOp->p2<p->nOp ); assert( pOp->p3>=0 && pOp->p3<p->nOp ); pOut = &aMem[pOp->p1]; assert( !VdbeMemDynamic(pOut) ); pOut->u.i = pOp->p3 - 1; pOut->flags = MEM_Int; |
︙ | ︙ | |||
1148 1149 1150 1151 1152 1153 1154 | break; } /* Opcode: EndCoroutine P1 * * * * ** ** The instruction at the address in register P1 is a Yield. ** Jump to the P2 parameter of that Yield. | | < < < > | | 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 | break; } /* Opcode: EndCoroutine P1 * * * * ** ** The instruction at the address in register P1 is a Yield. ** Jump to the P2 parameter of that Yield. ** After the jump, register P1 becomes undefined. ** ** See also: InitCoroutine */ case OP_EndCoroutine: { /* in1 */ VdbeOp *pCaller; pIn1 = &aMem[pOp->p1]; assert( pIn1->flags==MEM_Int ); assert( pIn1->u.i>=0 && pIn1->u.i<p->nOp ); pCaller = &aOp[pIn1->u.i]; assert( pCaller->opcode==OP_Yield ); assert( pCaller->p2>=0 && pCaller->p2<p->nOp ); pOp = &aOp[pCaller->p2 - 1]; pIn1->flags = MEM_Undefined; break; } /* Opcode: Yield P1 P2 * * * ** ** Swap the program counter with the value in register P1. This ** has the effect of yielding to a coroutine. ** ** If the coroutine that is launched by this instruction ends with ** Yield or Return then continue to the next instruction. But if ** the coroutine launched by this instruction ends with ** EndCoroutine, then jump to P2 rather than continuing with the ** next instruction. ** ** See also: InitCoroutine */ case OP_Yield: { /* in1, jump */ int pcDest; pIn1 = &aMem[pOp->p1]; assert( VdbeMemDynamic(pIn1)==0 ); pIn1->flags = MEM_Int; pcDest = (int)pIn1->u.i; pIn1->u.i = (int)(pOp - aOp); REGISTER_TRACE(pOp->p1, pIn1); |
︙ | ︙ | |||
1510 1511 1512 1513 1514 1515 1516 | sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0); } pOut->enc = encoding; UPDATE_MAX_BLOBSIZE(pOut); break; } | | | > > > > | 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 | sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0); } pOut->enc = encoding; UPDATE_MAX_BLOBSIZE(pOut); break; } /* Opcode: Variable P1 P2 * P4 * ** Synopsis: r[P2]=parameter(P1,P4) ** ** Transfer the values of bound parameter P1 into register P2 ** ** If the parameter is named, then its name appears in P4. ** The P4 value is used by sqlite3_bind_parameter_name(). */ case OP_Variable: { /* out2 */ Mem *pVar; /* Value being transferred */ assert( pOp->p1>0 && pOp->p1<=p->nVar ); assert( pOp->p4.z==0 || pOp->p4.z==sqlite3VListNumToName(p->pVList,pOp->p1) ); pVar = &p->aVar[pOp->p1 - 1]; if( sqlite3VdbeMemTooBig(pVar) ){ goto too_big; } pOut = &aMem[pOp->p2]; if( VdbeMemDynamic(pOut) ) sqlite3VdbeMemSetNull(pOut); memcpy(pOut, pVar, MEMCELLSIZE); |
︙ | ︙ | |||
2039 2040 2041 2042 2043 2044 2045 | /* Opcode: MustBeInt P1 P2 * * * ** ** Force the value in register P1 to be an integer. If the value ** in P1 is not an integer and cannot be converted into an integer ** without data loss, then jump immediately to P2, or if P2==0 ** raise an SQLITE_MISMATCH exception. */ | | | 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 | /* Opcode: MustBeInt P1 P2 * * * ** ** Force the value in register P1 to be an integer. If the value ** in P1 is not an integer and cannot be converted into an integer ** without data loss, then jump immediately to P2, or if P2==0 ** raise an SQLITE_MISMATCH exception. */ case OP_MustBeInt: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; if( (pIn1->flags & MEM_Int)==0 ){ applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding); if( (pIn1->flags & MEM_Int)==0 ){ VdbeBranchTaken(1, 2); if( pOp->p2==0 ){ rc = SQLITE_MISMATCH; |
︙ | ︙ | |||
4580 4581 4582 4583 4584 4585 4586 | ** ** A pseudo-table created by this opcode is used to hold a single ** row output from the sorter so that the row can be decomposed into ** individual columns using the OP_Column opcode. The OP_Column opcode ** is the only cursor opcode that works with a pseudo-table. ** ** P3 is the number of fields in the records that will be stored by | | < | 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 | ** ** A pseudo-table created by this opcode is used to hold a single ** row output from the sorter so that the row can be decomposed into ** individual columns using the OP_Column opcode. The OP_Column opcode ** is the only cursor opcode that works with a pseudo-table. ** ** P3 is the number of fields in the records that will be stored by ** the pseudo-table. */ case OP_OpenPseudo: { VdbeCursor *pCx; assert( pOp->p1>=0 ); assert( pOp->p3>=0 ); pCx = allocateCursor(p, pOp->p1, pOp->p3, CURTYPE_PSEUDO); |
︙ | ︙ | |||
4724 4725 4726 4727 4728 4729 4730 | ** The IdxGE opcode will be skipped if this opcode succeeds, but the ** IdxGE opcode will be used on subsequent loop iterations. The ** OPFLAG_SEEKEQ flags is a hint to the btree layer to say that this ** is an equality search. ** ** See also: Found, NotFound, SeekGt, SeekGe, SeekLt */ | | | | | | 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 | ** The IdxGE opcode will be skipped if this opcode succeeds, but the ** IdxGE opcode will be used on subsequent loop iterations. The ** OPFLAG_SEEKEQ flags is a hint to the btree layer to say that this ** is an equality search. ** ** See also: Found, NotFound, SeekGt, SeekGe, SeekLt */ case OP_SeekLT: /* jump, in3, group, ncycle */ case OP_SeekLE: /* jump, in3, group, ncycle */ case OP_SeekGE: /* jump, in3, group, ncycle */ case OP_SeekGT: { /* jump, in3, group, ncycle */ int res; /* Comparison result */ int oc; /* Opcode */ VdbeCursor *pC; /* The cursor to seek */ UnpackedRecord r; /* The key to seek for */ int nField; /* Number of columns or fields in the key */ i64 iKey; /* The rowid we are to seek to */ int eqOnly; /* Only interested in == results */ |
︙ | ︙ | |||
5394 5395 5396 5397 5398 5399 5400 | ** ** This opcode leaves the cursor in a state where it cannot be advanced ** in either direction. In other words, the Next and Prev opcodes will ** not work following this opcode. ** ** See also: Found, NotFound, NoConflict, SeekRowid */ | | | 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 | ** ** This opcode leaves the cursor in a state where it cannot be advanced ** in either direction. In other words, the Next and Prev opcodes will ** not work following this opcode. ** ** See also: Found, NotFound, NoConflict, SeekRowid */ case OP_SeekRowid: { /* jump, in3, ncycle */ VdbeCursor *pC; BtCursor *pCrsr; int res; u64 iKey; pIn3 = &aMem[pOp->p3]; testcase( pIn3->flags & MEM_Int ); |
︙ | ︙ | |||
6153 6154 6155 6156 6157 6158 6159 | ** to the following instruction. ** ** This opcode leaves the cursor configured to move in reverse order, ** from the end toward the beginning. In other words, the cursor is ** configured to use Prev, not Next. */ case OP_SeekEnd: /* ncycle */ | | | 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 | ** to the following instruction. ** ** This opcode leaves the cursor configured to move in reverse order, ** from the end toward the beginning. In other words, the cursor is ** configured to use Prev, not Next. */ case OP_SeekEnd: /* ncycle */ case OP_Last: { /* jump, ncycle */ VdbeCursor *pC; BtCursor *pCrsr; int res; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); |
︙ | ︙ | |||
6191 6192 6193 6194 6195 6196 6197 | break; } /* Opcode: IfSizeBetween P1 P2 P3 P4 * ** ** Let N be the approximate number of rows in the table or index ** with cursor P1 and let X be 10*log2(N) if N is positive or -1 | | < | | | 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 | break; } /* Opcode: IfSizeBetween P1 P2 P3 P4 * ** ** Let N be the approximate number of rows in the table or index ** with cursor P1 and let X be 10*log2(N) if N is positive or -1 ** if N is zero. Thus X will be within the range of -1 to 640, inclusive ** Jump to P2 if X is in between P3 and P4, inclusive. */ case OP_IfSizeBetween: { /* jump */ VdbeCursor *pC; BtCursor *pCrsr; int res; i64 sz; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); assert( pOp->p4type==P4_INT32 ); assert( pOp->p3>=-1 && pOp->p3<=640 ); assert( pOp->p4.i>=-1 && pOp->p4.i<=640 ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); pCrsr = pC->uc.pCursor; assert( pCrsr ); rc = sqlite3BtreeFirst(pCrsr, &res); if( rc ) goto abort_due_to_error; if( res!=0 ){ |
︙ | ︙ | |||
6271 6272 6273 6274 6275 6276 6277 | ** If P2 is zero, that is an assertion that the P1 table is never ** empty and hence the jump will never be taken. ** ** This opcode leaves the cursor configured to move in forward order, ** from the beginning toward the end. In other words, the cursor is ** configured to use Next, not Prev. */ | | | 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 | ** If P2 is zero, that is an assertion that the P1 table is never ** empty and hence the jump will never be taken. ** ** This opcode leaves the cursor configured to move in forward order, ** from the beginning toward the end. In other words, the cursor is ** configured to use Next, not Prev. */ case OP_Rewind: { /* jump, ncycle */ VdbeCursor *pC; BtCursor *pCrsr; int res; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); assert( pOp->p5==0 ); assert( pOp->p2>=0 && pOp->p2<p->nOp ); |
︙ | ︙ | |||
7279 7280 7281 7282 7283 7284 7285 | /* Opcode: Program P1 P2 P3 P4 P5 ** ** Execute the trigger program passed as P4 (type P4_SUBPROGRAM). ** ** P1 contains the address of the memory cell that contains the first memory ** cell in an array of values used as arguments to the sub-program. P2 ** contains the address to jump to if the sub-program throws an IGNORE | | < < | | 7279 7280 7281 7282 7283 7284 7285 7286 7287 7288 7289 7290 7291 7292 7293 7294 7295 7296 7297 7298 7299 7300 7301 | /* Opcode: Program P1 P2 P3 P4 P5 ** ** Execute the trigger program passed as P4 (type P4_SUBPROGRAM). ** ** P1 contains the address of the memory cell that contains the first memory ** cell in an array of values used as arguments to the sub-program. P2 ** contains the address to jump to if the sub-program throws an IGNORE ** exception using the RAISE() function. Register P3 contains the address ** of a memory cell in this (the parent) VM that is used to allocate the ** memory required by the sub-vdbe at runtime. ** ** P4 is a pointer to the VM containing the trigger program. ** ** If P5 is non-zero, then recursive program invocation is enabled. */ case OP_Program: { /* jump */ int nMem; /* Number of memory registers for sub-program */ int nByte; /* Bytes of runtime space required for sub-program */ Mem *pRt; /* Register to allocate runtime space */ Mem *pMem; /* Used to iterate through memory cells */ Mem *pEnd; /* Last memory cell in new array */ VdbeFrame *pFrame; /* New vdbe frame to execute in */ SubProgram *pProgram; /* Sub-program to execute */ |
︙ | ︙ | |||
8838 8839 8840 8841 8842 8843 8844 | ** Increment the value of P1 so that OP_Once opcodes will jump the ** first time they are evaluated for this run. ** ** If P3 is not zero, then it is an address to jump to if an SQLITE_CORRUPT ** error is encountered. */ case OP_Trace: | | | 8836 8837 8838 8839 8840 8841 8842 8843 8844 8845 8846 8847 8848 8849 8850 | ** Increment the value of P1 so that OP_Once opcodes will jump the ** first time they are evaluated for this run. ** ** If P3 is not zero, then it is an address to jump to if an SQLITE_CORRUPT ** error is encountered. */ case OP_Trace: case OP_Init: { /* jump */ int i; #ifndef SQLITE_OMIT_TRACE char *zTrace; #endif /* If the P4 argument is not NULL, then it must be an SQL comment string. ** The "--" string is broken up to prevent false-positives with srcck1.c. |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 | *(i64*)pOut = res; return 0; } return 1; } if( flags & SQLITE_SCANSTAT_COMPLEX ){ idx = iScan; }else{ /* If the COMPLEX flag is clear, then this function must ignore any ** ScanStatus structures with ScanStatus.addrLoop set to 0. */ for(idx=0; idx<p->nScan; idx++){ pScan = &p->aScan[idx]; if( pScan->zName ){ iScan--; if( iScan<0 ) break; } } } if( idx>=p->nScan ) return 1; | > < < | 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 | *(i64*)pOut = res; return 0; } return 1; } if( flags & SQLITE_SCANSTAT_COMPLEX ){ idx = iScan; pScan = &p->aScan[idx]; }else{ /* If the COMPLEX flag is clear, then this function must ignore any ** ScanStatus structures with ScanStatus.addrLoop set to 0. */ for(idx=0; idx<p->nScan; idx++){ pScan = &p->aScan[idx]; if( pScan->zName ){ iScan--; if( iScan<0 ) break; } } } if( idx>=p->nScan ) return 1; switch( iScanStatusOp ){ case SQLITE_SCANSTAT_NLOOP: { if( pScan->addrLoop>0 ){ *(sqlite3_int64*)pOut = aOp[pScan->addrLoop].nExec; }else{ *(sqlite3_int64*)pOut = -1; |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
935 936 937 938 939 940 941 | ** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to ** have non-negative values for P2. */ assert( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 ); assert( ADDR(pOp->p2)<-pParse->nLabel ); assert( aLabel!=0 ); /* True because of tag-20230419-1 */ pOp->p2 = aLabel[ADDR(pOp->p2)]; } | < < < < < < < < < | 935 936 937 938 939 940 941 942 943 944 945 946 947 948 | ** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to ** have non-negative values for P2. */ assert( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 ); assert( ADDR(pOp->p2)<-pParse->nLabel ); assert( aLabel!=0 ); /* True because of tag-20230419-1 */ pOp->p2 = aLabel[ADDR(pOp->p2)]; } break; } } /* The mkopcodeh.tcl script has so arranged things that the only ** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to ** have non-negative values for P2. */ assert( (sqlite3OpcodeProperty[pOp->opcode]&OPFLG_JUMP)==0 || pOp->p2>=0); |
︙ | ︙ | |||
3351 3352 3353 3354 3355 3356 3357 | p->nChange = 0; } } } /* Check for immediate foreign key violations. */ if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){ | | | | 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 | p->nChange = 0; } } } /* Check for immediate foreign key violations. */ if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){ sqlite3VdbeCheckFk(p, 0); } /* If the auto-commit flag is set and this is the only active writer ** VM, then we do either a commit or rollback of the current transaction. ** ** Note: This block also runs if one of the special errors handled ** above has occurred. */ if( !sqlite3VtabInSync(db) |
︙ | ︙ |
Changes to src/vdbemem.c.
︙ | ︙ | |||
1945 1946 1947 1948 1949 1950 1951 | sqlite3 *db, /* Database handle */ const void *pRec, /* Pointer to buffer containing record */ int nRec, /* Size of buffer pRec in bytes */ int iCol, /* Column to extract */ sqlite3_value **ppVal /* OUT: Extracted value */ ){ u32 t = 0; /* a column type code */ | | | | | | | 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 | sqlite3 *db, /* Database handle */ const void *pRec, /* Pointer to buffer containing record */ int nRec, /* Size of buffer pRec in bytes */ int iCol, /* Column to extract */ sqlite3_value **ppVal /* OUT: Extracted value */ ){ u32 t = 0; /* a column type code */ int nHdr; /* Size of the header in the record */ int iHdr; /* Next unread header byte */ int iField; /* Next unread data byte */ int szField = 0; /* Size of the current data field */ int i; /* Column index */ u8 *a = (u8*)pRec; /* Typecast byte array */ Mem *pMem = *ppVal; /* Write result into this Mem object */ assert( iCol>0 ); iHdr = getVarint32(a, nHdr); if( nHdr>nRec || iHdr>=nHdr ) return SQLITE_CORRUPT_BKPT; iField = nHdr; for(i=0; i<=iCol; i++){ iHdr += getVarint32(&a[iHdr], t); testcase( iHdr==nHdr ); testcase( iHdr==nHdr+1 ); if( iHdr>nHdr ) return SQLITE_CORRUPT_BKPT; szField = sqlite3VdbeSerialTypeLen(t); |
︙ | ︙ |
Changes to src/vdbevtab.c.
︙ | ︙ | |||
282 283 284 285 286 287 288 | sqlite3_result_text(ctx, "(FK)", 4, SQLITE_STATIC); } break; } #ifdef SQLITE_ENABLE_STMT_SCANSTATUS case 9: /* nexec */ | | | | 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 | sqlite3_result_text(ctx, "(FK)", 4, SQLITE_STATIC); } break; } #ifdef SQLITE_ENABLE_STMT_SCANSTATUS case 9: /* nexec */ sqlite3_result_int(ctx, pOp->nExec); break; case 10: /* ncycle */ sqlite3_result_int(ctx, pOp->nCycle); break; #else case 9: /* nexec */ case 10: /* ncycle */ sqlite3_result_int(ctx, 0); break; #endif |
︙ | ︙ |
Changes to src/vtab.c.
︙ | ︙ | |||
809 810 811 812 813 814 815 | */ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ VtabCtx *pCtx; int rc = SQLITE_OK; Table *pTab; Parse sParse; int initBusy; | < < < < < < < < < < < < < < < < < < < | | | | > | 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 | */ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ VtabCtx *pCtx; int rc = SQLITE_OK; Table *pTab; Parse sParse; int initBusy; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) || zCreateTable==0 ){ return SQLITE_MISUSE_BKPT; } #endif sqlite3_mutex_enter(db->mutex); pCtx = db->pVtabCtx; if( !pCtx || pCtx->bDeclared ){ sqlite3Error(db, SQLITE_MISUSE_BKPT); sqlite3_mutex_leave(db->mutex); return SQLITE_MISUSE_BKPT; } pTab = pCtx->pTab; assert( IsVirtual(pTab) ); sqlite3ParseObjectInit(&sParse, db); sParse.eParseMode = PARSE_MODE_DECLARE_VTAB; sParse.disableTriggers = 1; /* We should never be able to reach this point while loading the ** schema. Nevertheless, defend against that (turn off db->init.busy) ** in case a bug arises. */ assert( db->init.busy==0 ); initBusy = db->init.busy; db->init.busy = 0; sParse.nQueryLoop = 1; if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable) && ALWAYS(sParse.pNewTable!=0) && ALWAYS(!db->mallocFailed) && IsOrdinaryTable(sParse.pNewTable) ){ assert( sParse.zErrMsg==0 ); if( !pTab->aCol ){ Table *pNew = sParse.pNewTable; Index *pIdx; pTab->aCol = pNew->aCol; sqlite3ExprListDelete(db, pNew->u.tab.pDfltList); pTab->nNVCol = pTab->nCol = pNew->nCol; |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
298 299 300 301 302 303 304 | p = sqlite3ExprSkipCollateAndLikely(p->pRight); if( ALWAYS(p!=0) && p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){ return p; } return 0; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 298 299 300 301 302 303 304 305 306 307 308 309 310 311 | p = sqlite3ExprSkipCollateAndLikely(p->pRight); if( ALWAYS(p!=0) && p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){ return p; } return 0; } /* ** Advance to the next WhereTerm that matches according to the criteria ** established when the pScan object was initialized by whereScanInit(). ** Return NULL if there are no more matching WhereTerms. */ static WhereTerm *whereScanNext(WhereScan *pScan){ int iCur; /* The cursor on the LHS of the term */ |
︙ | ︙ | |||
384 385 386 387 388 389 390 | pScan->aiColumn[j] = pX->iColumn; pScan->nEquiv++; } } if( (pTerm->eOperator & pScan->opMask)!=0 ){ /* Verify the affinity and collating sequence match */ if( pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0 ){ | | < < < < < < | | | | | < < | | | 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 | pScan->aiColumn[j] = pX->iColumn; pScan->nEquiv++; } } if( (pTerm->eOperator & pScan->opMask)!=0 ){ /* Verify the affinity and collating sequence match */ if( pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0 ){ CollSeq *pColl; Parse *pParse = pWC->pWInfo->pParse; pX = pTerm->pExpr; if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){ continue; } assert(pX->pLeft); pColl = sqlite3ExprCompareCollSeq(pParse, pX); if( pColl==0 ) pColl = pParse->db->pDfltColl; if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){ continue; } } if( (pTerm->eOperator & (WO_EQ|WO_IS))!=0 && (pX = pTerm->pExpr->pRight, ALWAYS(pX!=0)) && pX->op==TK_COLUMN && pX->iTable==pScan->aiCur[0] |
︙ | ︙ | |||
753 754 755 756 757 758 759 | /* ** Two routines for printing the content of an sqlite3_index_info ** structure. Used for testing and debugging only. If neither ** SQLITE_TEST or SQLITE_DEBUG are defined, then these routines ** are no-ops. */ #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(WHERETRACE_ENABLED) | | < < < < | < < < < | | | 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 | /* ** Two routines for printing the content of an sqlite3_index_info ** structure. Used for testing and debugging only. If neither ** SQLITE_TEST or SQLITE_DEBUG are defined, then these routines ** are no-ops. */ #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(WHERETRACE_ENABLED) static void whereTraceIndexInfoInputs(sqlite3_index_info *p){ int i; if( (sqlite3WhereTrace & 0x10)==0 ) return; for(i=0; i<p->nConstraint; i++){ sqlite3DebugPrintf( " constraint[%d]: col=%d termid=%d op=%d usabled=%d collseq=%s\n", i, p->aConstraint[i].iColumn, p->aConstraint[i].iTermOffset, p->aConstraint[i].op, p->aConstraint[i].usable, sqlite3_vtab_collation(p,i)); } for(i=0; i<p->nOrderBy; i++){ sqlite3DebugPrintf(" orderby[%d]: col=%d desc=%d\n", i, p->aOrderBy[i].iColumn, p->aOrderBy[i].desc); } } static void whereTraceIndexInfoOutputs(sqlite3_index_info *p){ int i; if( (sqlite3WhereTrace & 0x10)==0 ) return; for(i=0; i<p->nConstraint; i++){ sqlite3DebugPrintf(" usage[%d]: argvIdx=%d omit=%d\n", i, p->aConstraintUsage[i].argvIndex, p->aConstraintUsage[i].omit); } sqlite3DebugPrintf(" idxNum=%d\n", p->idxNum); sqlite3DebugPrintf(" idxStr=%s\n", p->idxStr); sqlite3DebugPrintf(" orderByConsumed=%d\n", p->orderByConsumed); sqlite3DebugPrintf(" estimatedCost=%g\n", p->estimatedCost); sqlite3DebugPrintf(" estimatedRows=%lld\n", p->estimatedRows); } #else #define whereTraceIndexInfoInputs(A) #define whereTraceIndexInfoOutputs(A) #endif /* ** We know that pSrc is an operand of an outer join. Return true if ** pTerm is a constraint that is compatible with that join. ** ** pTerm must be EP_OuterON if pSrc is the right operand of an |
︙ | ︙ | |||
982 983 984 985 986 987 988 | idxCols = 0; for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){ Expr *pExpr = pTerm->pExpr; /* Make the automatic index a partial index if there are terms in the ** WHERE clause (or the ON clause of a LEFT join) that constrain which ** rows of the target table (pSrc) that can be used. */ if( (pTerm->wtFlags & TERM_VIRTUAL)==0 | | | 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 | idxCols = 0; for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){ Expr *pExpr = pTerm->pExpr; /* Make the automatic index a partial index if there are terms in the ** WHERE clause (or the ON clause of a LEFT join) that constrain which ** rows of the target table (pSrc) that can be used. */ if( (pTerm->wtFlags & TERM_VIRTUAL)==0 && sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, pLevel->iFrom) ){ pPartial = sqlite3ExprAnd(pParse, pPartial, sqlite3ExprDup(pParse->db, pExpr, 0)); } if( termCanDriveIndex(pTerm, pSrc, notReady) ){ int iCol; Bitmask cMask; |
︙ | ︙ | |||
1024 1025 1026 1027 1028 1029 1030 | ** columns that are needed by the query. With a covering index, the ** original table never needs to be accessed. Automatic indices must ** be a covering index because the index will not be updated if the ** original table changes and the index and table cannot both be used ** if they go out of sync. */ if( IsView(pTable) ){ | | | 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 | ** columns that are needed by the query. With a covering index, the ** original table never needs to be accessed. Automatic indices must ** be a covering index because the index will not be updated if the ** original table changes and the index and table cannot both be used ** if they go out of sync. */ if( IsView(pTable) ){ extraCols = ALLBITS; }else{ extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1)); } mxBitCol = MIN(BMS-1,pTable->nCol); testcase( pTable->nCol==BMS-1 ); testcase( pTable->nCol==BMS-2 ); for(i=0; i<mxBitCol; i++){ |
︙ | ︙ | |||
1251 1252 1253 1254 1255 1256 1257 | sqlite3VdbeAddOp2(v, OP_Blob, (int)sz, pLevel->regFilter); addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v); pWCEnd = &pWInfo->sWC.a[pWInfo->sWC.nTerm]; for(pTerm=pWInfo->sWC.a; pTerm<pWCEnd; pTerm++){ Expr *pExpr = pTerm->pExpr; if( (pTerm->wtFlags & TERM_VIRTUAL)==0 | | | 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 | sqlite3VdbeAddOp2(v, OP_Blob, (int)sz, pLevel->regFilter); addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v); pWCEnd = &pWInfo->sWC.a[pWInfo->sWC.nTerm]; for(pTerm=pWInfo->sWC.a; pTerm<pWCEnd; pTerm++){ Expr *pExpr = pTerm->pExpr; if( (pTerm->wtFlags & TERM_VIRTUAL)==0 && sqlite3ExprIsSingleTableConstraint(pExpr, pTabList, iSrc) ){ sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL); } } if( pLoop->wsFlags & WHERE_IPK ){ int r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_Rowid, iCur, r1); |
︙ | ︙ | |||
1377 1378 1379 1380 1381 1382 1383 | if( pOrderBy ){ int n = pOrderBy->nExpr; for(i=0; i<n; i++){ Expr *pExpr = pOrderBy->a[i].pExpr; Expr *pE2; /* Skip over constant terms in the ORDER BY clause */ | | | 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 | if( pOrderBy ){ int n = pOrderBy->nExpr; for(i=0; i<n; i++){ Expr *pExpr = pOrderBy->a[i].pExpr; Expr *pE2; /* Skip over constant terms in the ORDER BY clause */ if( sqlite3ExprIsConstant(pExpr) ){ continue; } /* Virtual tables are unable to deal with NULLS FIRST */ if( pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_BIGNULL ) break; /* First case - a direct column references without a COLLATE operator */ |
︙ | ︙ | |||
1412 1413 1414 1415 1416 1417 1418 | } /* No matches cause a break out of the loop */ break; } if( i==n ){ nOrderBy = n; | | | 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 | } /* No matches cause a break out of the loop */ break; } if( i==n ){ nOrderBy = n; if( (pWInfo->wctrlFlags & WHERE_DISTINCTBY) ){ eDistinct = 2 + ((pWInfo->wctrlFlags & WHERE_SORTBYGROUP)!=0); }else if( pWInfo->wctrlFlags & WHERE_GROUPBY ){ eDistinct = 1; } } } |
︙ | ︙ | |||
1489 1490 1491 1492 1493 1494 1495 | j++; } assert( j==nTerm ); pIdxInfo->nConstraint = j; for(i=j=0; i<nOrderBy; i++){ Expr *pExpr = pOrderBy->a[i].pExpr; | | | 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 | j++; } assert( j==nTerm ); pIdxInfo->nConstraint = j; for(i=j=0; i<nOrderBy; i++){ Expr *pExpr = pOrderBy->a[i].pExpr; if( sqlite3ExprIsConstant(pExpr) ) continue; assert( pExpr->op==TK_COLUMN || (pExpr->op==TK_COLLATE && pExpr->pLeft->op==TK_COLUMN && pExpr->iColumn==pExpr->pLeft->iColumn) ); pIdxOrderBy[j].iColumn = pExpr->iColumn; pIdxOrderBy[j].desc = pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_DESC; j++; } |
︙ | ︙ | |||
1541 1542 1543 1544 1545 1546 1547 | ** caller to eventually free p->idxStr if p->needToFreeIdxStr indicates ** that this is required. */ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab; int rc; | | | | 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 | ** caller to eventually free p->idxStr if p->needToFreeIdxStr indicates ** that this is required. */ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab; int rc; whereTraceIndexInfoInputs(p); pParse->db->nSchemaLock++; rc = pVtab->pModule->xBestIndex(pVtab, p); pParse->db->nSchemaLock--; whereTraceIndexInfoOutputs(p); if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT ){ if( rc==SQLITE_NOMEM ){ sqlite3OomFault(pParse->db); }else if( !pVtab->zErrMsg ){ sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc)); }else{ |
︙ | ︙ | |||
3292 3293 3294 3295 3296 3297 3298 | ** as (col=?). */ pNew->nOut += 10; } } } } | | | | | < < < | < < < < < < < < | 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 | ** as (col=?). */ pNew->nOut += 10; } } } } /* Set rCostIdx to the cost of visiting selected rows in index. Add ** it to pNew->rRun, which is currently set to the cost of the index ** seek only. Then, if this is a non-covering index, add the cost of ** visiting the rows in the main table. */ assert( pSrc->pTab->szTabRow>0 ); if( pProbe->idxType==SQLITE_IDXTYPE_IPK ){ /* The pProbe->szIdxRow is low for an IPK table since the interior ** pages are small. Thus szIdxRow gives a good estimate of seek cost. ** But the leaf pages are full-size, so pProbe->szIdxRow would badly ** under-estimate the scanning cost. */ rCostIdx = pNew->nOut + 16; }else{ rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow; } pNew->rRun = sqlite3LogEstAdd(rLogSize, rCostIdx); if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK|WHERE_EXPRIDX))==0 ){ pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut + 16); } ApplyCostMultiplier(pNew->rRun, pProbe->pTable->costMult); nOutUnadjusted = pNew->nOut; pNew->rRun += nInMul + nIn; |
︙ | ︙ | |||
3682 3683 3684 3685 3686 3687 3688 | if( (pPart->op==TK_EQ || pPart->op==TK_IS) ){ Expr *pLeft = pPart->pLeft; Expr *pRight = pPart->pRight; u8 aff; if( pLeft->op!=TK_COLUMN ) return; | | | 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 | if( (pPart->op==TK_EQ || pPart->op==TK_IS) ){ Expr *pLeft = pPart->pLeft; Expr *pRight = pPart->pRight; u8 aff; if( pLeft->op!=TK_COLUMN ) return; if( !sqlite3ExprIsConstant(pRight) ) return; if( !sqlite3IsBinary(sqlite3ExprCompareCollSeq(pParse, pPart)) ) return; if( pLeft->iColumn<0 ) return; aff = pIdx->pTable->aCol[pLeft->iColumn].affinity; if( aff>=SQLITE_AFF_TEXT ){ if( pItem ){ sqlite3 *db = pParse->db; IndexedExpr *p = (IndexedExpr*)sqlite3DbMallocRaw(db, sizeof(*p)); |
︙ | ︙ | |||
4053 4054 4055 4056 4057 4058 4059 | */ static int isLimitTerm(WhereTerm *pTerm){ assert( pTerm->eOperator==WO_AUX || pTerm->eMatchOp==0 ); return pTerm->eMatchOp>=SQLITE_INDEX_CONSTRAINT_LIMIT && pTerm->eMatchOp<=SQLITE_INDEX_CONSTRAINT_OFFSET; } | < < < < < < < < < < < < < < < | 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 | */ static int isLimitTerm(WhereTerm *pTerm){ assert( pTerm->eOperator==WO_AUX || pTerm->eMatchOp==0 ); return pTerm->eMatchOp>=SQLITE_INDEX_CONSTRAINT_LIMIT && pTerm->eMatchOp<=SQLITE_INDEX_CONSTRAINT_OFFSET; } /* ** Argument pIdxInfo is already populated with all constraints that may ** be used by the virtual table identified by pBuilder->pNew->iTab. This ** function marks a subset of those constraints usable, invokes the ** xBestIndex method and adds the returned plan to pBuilder. ** ** A constraint is marked usable if: |
︙ | ︙ | |||
4208 4209 4210 4211 4212 4213 4214 | ** (2) Multiple outputs from a single IN value will not merge ** together. */ pIdxInfo->orderByConsumed = 0; pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE; *pbIn = 1; assert( (mExclude & WO_IN)==0 ); } | < < < < < | | < < | | | 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 | ** (2) Multiple outputs from a single IN value will not merge ** together. */ pIdxInfo->orderByConsumed = 0; pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE; *pbIn = 1; assert( (mExclude & WO_IN)==0 ); } assert( pbRetryLimit || !isLimitTerm(pTerm) ); if( isLimitTerm(pTerm) && *pbIn ){ /* If there is an IN(...) term handled as an == (separate call to ** xFilter for each value on the RHS of the IN) and a LIMIT or ** OFFSET term handled as well, the plan is unusable. Set output ** variable *pbRetryLimit to true to tell the caller to retry with ** LIMIT and OFFSET disabled. */ if( pIdxInfo->needToFreeIdxStr ){ sqlite3_free(pIdxInfo->idxStr); pIdxInfo->idxStr = 0; pIdxInfo->needToFreeIdxStr = 0; } *pbRetryLimit = 1; return SQLITE_OK; |
︙ | ︙ | |||
5078 5079 5080 5081 5082 5083 5084 | orderDistinctMask |= pLoop->maskSelf; for(i=0; i<nOrderBy; i++){ Expr *p; Bitmask mTerm; if( MASKBIT(i) & obSat ) continue; p = pOrderBy->a[i].pExpr; mTerm = sqlite3WhereExprUsage(&pWInfo->sMaskSet,p); | | | 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 | orderDistinctMask |= pLoop->maskSelf; for(i=0; i<nOrderBy; i++){ Expr *p; Bitmask mTerm; if( MASKBIT(i) & obSat ) continue; p = pOrderBy->a[i].pExpr; mTerm = sqlite3WhereExprUsage(&pWInfo->sMaskSet,p); if( mTerm==0 && !sqlite3ExprIsConstant(p) ) continue; if( (mTerm&~orderDistinctMask)==0 ){ obSat |= MASKBIT(i); } } } } /* End the loop over all WhereLoops from outer-most down to inner-most */ if( obSat==obDone ) return (i8)nOrderBy; |
︙ | ︙ | |||
5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 | assert( pWInfo->sorted==0 ); if( nOrder==pWInfo->pOrderBy->nExpr ){ pWInfo->sorted = 1; pWInfo->revMask = revMask; } } } pWInfo->nRowOut = pFrom->nRow; /* Free temporary memory and return success */ sqlite3StackFreeNN(pParse->db, pSpace); return SQLITE_OK; } | > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 | assert( pWInfo->sorted==0 ); if( nOrder==pWInfo->pOrderBy->nExpr ){ pWInfo->sorted = 1; pWInfo->revMask = revMask; } } } pWInfo->nRowOut = pFrom->nRow; /* Free temporary memory and return success */ sqlite3StackFreeNN(pParse->db, pSpace); return SQLITE_OK; } /* ** Most queries use only a single table (they are not joins) and have ** simple == constraints against indexed fields. This routine attempts ** to plan those simple cases using much less ceremony than the ** general-purpose query planner, and thereby yield faster sqlite3_prepare() ** times for the common case. ** |
︙ | ︙ | |||
5844 5845 5846 5847 5848 5849 5850 | ** 5) The table must not have an inner-join ON or USING clause if there is ** a RIGHT JOIN anywhere in the query. Otherwise the ON/USING clause ** might move from the right side to the left side of the RIGHT JOIN. ** Note: Due to (2), this condition can only arise if the table is ** the right-most table of a subquery that was flattened into the ** main query and that subquery was the right-hand operand of an ** inner join that held an ON or USING clause. | < < < < | 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 | ** 5) The table must not have an inner-join ON or USING clause if there is ** a RIGHT JOIN anywhere in the query. Otherwise the ON/USING clause ** might move from the right side to the left side of the RIGHT JOIN. ** Note: Due to (2), this condition can only arise if the table is ** the right-most table of a subquery that was flattened into the ** main query and that subquery was the right-hand operand of an ** inner join that held an ON or USING clause. ** ** For example, given: ** ** CREATE TABLE t1(ipk INTEGER PRIMARY KEY, v1); ** CREATE TABLE t2(ipk INTEGER PRIMARY KEY, v2); ** CREATE TABLE t3(ipk INTEGER PRIMARY KEY, v3); ** |
︙ | ︙ | |||
5989 5990 5991 5992 5993 5994 5995 | (double)sqlite3LogEstToInt(pTab->nRowLogEst))); } } nSearch += pLoop->nOut; } } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 | (double)sqlite3LogEstToInt(pTab->nRowLogEst))); } } nSearch += pLoop->nOut; } } /* ** The index pIdx is used by a query and contains one or more expressions. ** In other words pIdx is an index on an expression. iIdxCur is the cursor ** number for the index and iDataCur is the cursor number for the corresponding ** table. ** ** This routine adds IndexedExpr entries to the Parse->pIdxEpr field for |
︙ | ︙ | |||
6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 | IndexedExpr *p; Table *pTab; assert( pIdx->bHasExpr ); pTab = pIdx->pTable; for(i=0; i<pIdx->nColumn; i++){ Expr *pExpr; int j = pIdx->aiColumn[i]; if( j==XN_EXPR ){ pExpr = pIdx->aColExpr->a[i].pExpr; }else if( j>=0 && (pTab->aCol[j].colFlags & COLFLAG_VIRTUAL)!=0 ){ pExpr = sqlite3ColumnExpr(pTab, &pTab->aCol[j]); }else{ continue; } | > > > > > > | | > > > > > > > | > | | 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 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 5896 5897 5898 5899 5900 5901 5902 5903 5904 | IndexedExpr *p; Table *pTab; assert( pIdx->bHasExpr ); pTab = pIdx->pTable; for(i=0; i<pIdx->nColumn; i++){ Expr *pExpr; int j = pIdx->aiColumn[i]; int bMaybeNullRow; if( j==XN_EXPR ){ pExpr = pIdx->aColExpr->a[i].pExpr; testcase( pTabItem->fg.jointype & JT_LEFT ); testcase( pTabItem->fg.jointype & JT_RIGHT ); testcase( pTabItem->fg.jointype & JT_LTORJ ); bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0; }else if( j>=0 && (pTab->aCol[j].colFlags & COLFLAG_VIRTUAL)!=0 ){ pExpr = sqlite3ColumnExpr(pTab, &pTab->aCol[j]); bMaybeNullRow = 0; }else{ continue; } if( sqlite3ExprIsConstant(pExpr) ) continue; if( pExpr->op==TK_FUNCTION ){ /* Functions that might set a subtype should not be replaced by the ** value taken from an expression index since the index omits the ** subtype. https://sqlite.org/forum/forumpost/68d284c86b082c3e */ int n; FuncDef *pDef; sqlite3 *db = pParse->db; assert( ExprUseXList(pExpr) ); n = pExpr->x.pList ? pExpr->x.pList->nExpr : 0; pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0); if( pDef==0 || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){ continue; } } p = sqlite3DbMallocRaw(pParse->db, sizeof(IndexedExpr)); if( p==0 ) break; p->pIENext = pParse->pIdxEpr; #ifdef WHERETRACE_ENABLED if( sqlite3WhereTrace & 0x200 ){ sqlite3DebugPrintf("New pParse->pIdxEpr term {%d,%d}\n", iIdxCur, i); if( sqlite3WhereTrace & 0x5000 ) sqlite3ShowExpr(pExpr); } #endif p->pExpr = sqlite3ExprDup(pParse->db, pExpr, 0); p->iDataCur = pTabItem->iCursor; p->iIdxCur = iIdxCur; p->iIdxCol = i; p->bMaybeNullRow = bMaybeNullRow; if( sqlite3IndexAffinityStr(pParse->db, pIdx) ){ p->aff = pIdx->zColAff[i]; } #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS p->zIdxName = pIdx->zName; #endif pParse->pIdxEpr = p; |
︙ | ︙ | |||
6261 6262 6263 6264 6265 6266 6267 | memset(&sWLB, 0, sizeof(sWLB)); /* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */ testcase( pOrderBy && pOrderBy->nExpr==BMS-1 ); if( pOrderBy && pOrderBy->nExpr>=BMS ){ pOrderBy = 0; wctrlFlags &= ~WHERE_WANT_DISTINCT; | < | 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 | memset(&sWLB, 0, sizeof(sWLB)); /* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */ testcase( pOrderBy && pOrderBy->nExpr==BMS-1 ); if( pOrderBy && pOrderBy->nExpr>=BMS ){ pOrderBy = 0; wctrlFlags &= ~WHERE_WANT_DISTINCT; } /* The number of tables in the FROM clause is limited by the number of ** bits in a Bitmask */ testcase( pTabList->nSrc==BMS ); if( pTabList->nSrc>BMS ){ |
︙ | ︙ | |||
6344 6345 6346 6347 6348 6349 6350 | if( nTabList==0 ){ if( pOrderBy ) pWInfo->nOBSat = pOrderBy->nExpr; if( (wctrlFlags & WHERE_WANT_DISTINCT)!=0 && OptimizationEnabled(db, SQLITE_DistinctOpt) ){ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; } | < < < | < | 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 | if( nTabList==0 ){ if( pOrderBy ) pWInfo->nOBSat = pOrderBy->nExpr; if( (wctrlFlags & WHERE_WANT_DISTINCT)!=0 && OptimizationEnabled(db, SQLITE_DistinctOpt) ){ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; } ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW")); }else{ /* Assign a bit from the bitmask to every term in the FROM clause. ** ** The N-th term of the FROM clause is assigned a bitmask of 1<<N. ** ** The rule of the previous sentence ensures that if X is the bitmask for ** a table T, then X-1 is the bitmask for all other tables to the left of T. |
︙ | ︙ | |||
6501 6502 6503 6504 6505 6506 6507 | } #endif WHERETRACE_ALL_LOOPS(pWInfo, sWLB.pWC); wherePathSolver(pWInfo, 0); if( db->mallocFailed ) goto whereBeginError; if( pWInfo->pOrderBy ){ | < | 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 | } #endif WHERETRACE_ALL_LOOPS(pWInfo, sWLB.pWC); wherePathSolver(pWInfo, 0); if( db->mallocFailed ) goto whereBeginError; if( pWInfo->pOrderBy ){ wherePathSolver(pWInfo, pWInfo->nRowOut+1); if( db->mallocFailed ) goto whereBeginError; } /* TUNING: Assume that a DISTINCT clause on a subquery reduces ** the output size by a factor of 8 (LogEst -30). */ |
︙ | ︙ | |||
6562 6563 6564 6565 6566 6567 6568 | ** procedure to keep the sqlite3WhereBegin() procedure from becoming ** too large. If sqlite3WhereBegin() becomes too large, that prevents ** some C-compiler optimizers from in-lining the ** sqlite3WhereCodeOneLoopStart() procedure, and it is important to ** in-line sqlite3WhereCodeOneLoopStart() for performance reasons. */ notReady = ~(Bitmask)0; | | | | | | 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 | ** procedure to keep the sqlite3WhereBegin() procedure from becoming ** too large. If sqlite3WhereBegin() becomes too large, that prevents ** some C-compiler optimizers from in-lining the ** sqlite3WhereCodeOneLoopStart() procedure, and it is important to ** in-line sqlite3WhereCodeOneLoopStart() for performance reasons. */ notReady = ~(Bitmask)0; if( pWInfo->nLevel>=2 && pResultSet!=0 /* these two combine to guarantee */ && 0==(wctrlFlags & WHERE_AGG_DISTINCT) /* condition (1) above */ && OptimizationEnabled(db, SQLITE_OmitNoopJoin) ){ notReady = whereOmitNoopJoin(pWInfo, notReady); nTabList = pWInfo->nLevel; assert( nTabList>0 ); } /* Check to see if there are any SEARCH loops that might benefit from |
︙ | ︙ | |||
7051 7052 7053 7054 7055 7056 7057 | } #endif if( pLevel->iLeftJoin ){ int ws = pLoop->wsFlags; addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v); assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 ); if( (ws & WHERE_IDX_ONLY)==0 ){ | < | < < < < < < < | 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 | } #endif if( pLevel->iLeftJoin ){ int ws = pLoop->wsFlags; addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v); assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 ); if( (ws & WHERE_IDX_ONLY)==0 ){ assert( pLevel->iTabCur==pTabList->a[pLevel->iFrom].iCursor ); sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur); } if( (ws & WHERE_INDEXED) || ((ws & WHERE_MULTI_OR) && pLevel->u.pCoveringIdx) ){ if( ws & WHERE_MULTI_OR ){ Index *pIx = pLevel->u.pCoveringIdx; |
︙ | ︙ | |||
7109 7110 7111 7112 7113 7114 7115 | /* For a co-routine, change all OP_Column references to the table of ** the co-routine into OP_Copy of result contained in a register. ** OP_Rowid becomes OP_Null. */ if( pTabItem->fg.viaCoroutine ){ testcase( pParse->db->mallocFailed ); | < | 6892 6893 6894 6895 6896 6897 6898 6899 6900 6901 6902 6903 6904 6905 | /* For a co-routine, change all OP_Column references to the table of ** the co-routine into OP_Copy of result contained in a register. ** OP_Rowid becomes OP_Null. */ if( pTabItem->fg.viaCoroutine ){ testcase( pParse->db->mallocFailed ); translateColumnToCopy(pParse, pLevel->addrBody, pLevel->iTabCur, pTabItem->regResult, 0); continue; } /* If this scan uses an index, make VDBE code substitutions to read data ** from the index instead of from the table where possible. In some cases |
︙ | ︙ |
Changes to src/wherecode.c.
︙ | ︙ | |||
1333 1334 1335 1336 1337 1338 1339 | VdbeCoverage(pParse->pVdbe); } pLevel->regFilter = 0; pLevel->addrBrk = 0; } } | < < < < < < < < < < < < < < < < < < < < < | 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 | VdbeCoverage(pParse->pVdbe); } pLevel->regFilter = 0; pLevel->addrBrk = 0; } } /* ** Generate code for the start of the iLevel-th loop in the WHERE clause ** implementation described by pWInfo. */ Bitmask sqlite3WhereCodeOneLoopStart( Parse *pParse, /* Parsing context */ Vdbe *v, /* Prepared statement under construction */ |
︙ | ︙ | |||
1432 1433 1434 1435 1436 1437 1438 | */ assert( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN)) || 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); | | | 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 | */ assert( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN)) || 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 ** this loop is empty and can never contribute content. */ for(j=iLevel; j>0; j--){ if( pWInfo->a[j].iLeftJoin ) break; if( pWInfo->a[j].pRJ ) break; |
︙ | ︙ | |||
2101 2102 2103 2104 2105 2106 2107 | /* The following assert() is not a requirement, merely an observation: ** The OR-optimization doesn't work for the right hand table of ** a LEFT JOIN: */ assert( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0 ); } /* Record the instruction used to terminate the loop. */ | | < < | 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 | /* The following assert() is not a requirement, merely an observation: ** The OR-optimization doesn't work for the right hand table of ** a LEFT JOIN: */ assert( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0 ); } /* 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{ pLevel->op = OP_Next; } pLevel->p1 = iIdxCur; |
︙ | ︙ | |||
2493 2494 2495 2496 2497 2498 2499 | ** ** iLoop==1: Code only expressions that are entirely covered by pIdx. ** iLoop==2: Code remaining expressions that do not contain correlated ** sub-queries. ** iLoop==3: Code all remaining expressions. ** ** An effort is made to skip unnecessary iterations of the loop. | < < < < < < | 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 | ** ** iLoop==1: Code only expressions that are entirely covered by pIdx. ** iLoop==2: Code remaining expressions that do not contain correlated ** sub-queries. ** iLoop==3: Code all remaining expressions. ** ** An effort is made to skip unnecessary iterations of the loop. */ iLoop = (pIdx ? 1 : 2); do{ int iNext = 0; /* Next value for iLoop */ for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ Expr *pE; int skipLikeAddr = 0; |
︙ | ︙ | |||
2749 2750 2751 2752 2753 2754 2755 | int k; ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pTab->zName)); sqlite3VdbeNoJumpsOutsideSubrtn(v, pRJ->addrSubrtn, pRJ->endSubrtn, pRJ->regReturn); for(k=0; k<iLevel; k++){ int iIdxCur; | < < < < < < < < < | 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 | int k; ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pTab->zName)); sqlite3VdbeNoJumpsOutsideSubrtn(v, pRJ->addrSubrtn, pRJ->endSubrtn, pRJ->regReturn); for(k=0; k<iLevel; k++){ int iIdxCur; mAll |= pWInfo->a[k].pWLoop->maskSelf; sqlite3VdbeAddOp1(v, OP_NullRow, pWInfo->a[k].iTabCur); iIdxCur = pWInfo->a[k].iIdxCur; if( iIdxCur ){ sqlite3VdbeAddOp1(v, OP_NullRow, iIdxCur); } } if( (pTabItem->fg.jointype & JT_LTORJ)==0 ){ |
︙ | ︙ |
Changes to src/whereexpr.c.
︙ | ︙ | |||
985 986 987 988 989 990 991 | iCur = pFrom->a[j].iCursor; for(pIdx=pFrom->a[j].pTab->pIndex; pIdx; pIdx=pIdx->pNext){ if( pIdx->aColExpr==0 ) continue; for(i=0; i<pIdx->nKeyCol; i++){ if( pIdx->aiColumn[i]!=XN_EXPR ) continue; assert( pIdx->bHasExpr ); if( sqlite3ExprCompareSkip(pExpr,pIdx->aColExpr->a[i].pExpr,iCur)==0 | | | 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 | iCur = pFrom->a[j].iCursor; for(pIdx=pFrom->a[j].pTab->pIndex; pIdx; pIdx=pIdx->pNext){ if( pIdx->aColExpr==0 ) continue; for(i=0; i<pIdx->nKeyCol; i++){ if( pIdx->aiColumn[i]!=XN_EXPR ) continue; assert( pIdx->bHasExpr ); if( sqlite3ExprCompareSkip(pExpr,pIdx->aColExpr->a[i].pExpr,iCur)==0 && pExpr->op!=TK_STRING ){ aiCurCol[0] = iCur; aiCurCol[1] = XN_EXPR; return 1; } } } |
︙ | ︙ | |||
1634 1635 1636 1637 1638 1639 1640 | /* If this term has child terms, then they are also part of the ** pWC->a[] array. So this term can be ignored, as a LIMIT clause ** will only be added if each of the child terms passes the ** (leftCursor==iCsr) test below. */ continue; } if( pWC->a[ii].leftCursor!=iCsr ) return; | < > > | < < < < | 1634 1635 1636 1637 1638 1639 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 | /* If this term has child terms, then they are also part of the ** pWC->a[] array. So this term can be ignored, as a LIMIT clause ** will only be added if each of the child terms passes the ** (leftCursor==iCsr) test below. */ continue; } if( pWC->a[ii].leftCursor!=iCsr ) return; } /* Check condition (5). Return early if it is not met. */ if( pOrderBy ){ for(ii=0; ii<pOrderBy->nExpr; ii++){ Expr *pExpr = pOrderBy->a[ii].pExpr; if( pExpr->op!=TK_COLUMN ) return; if( pExpr->iTable!=iCsr ) return; if( pOrderBy->a[ii].fg.sortFlags & KEYINFO_ORDER_BIGNULL ) return; } } /* All conditions are met. Add the terms to the where-clause object. */ assert( p->pLimit->op==TK_LIMIT ); whereAddLimitExpr(pWC, p->iLimit, p->pLimit->pLeft, iCsr, SQLITE_INDEX_CONSTRAINT_LIMIT); if( p->iOffset>0 ){ whereAddLimitExpr(pWC, p->iOffset, p->pLimit->pRight, iCsr, SQLITE_INDEX_CONSTRAINT_OFFSET); } } } /* ** Initialize a preallocated WhereClause structure. */ void sqlite3WhereClauseInit( |
︙ | ︙ |
Changes to src/window.c.
︙ | ︙ | |||
1160 1161 1162 1163 1164 1165 1166 | ** The argument expression is an PRECEDING or FOLLOWING offset. The ** value should be a non-negative integer. If the value is not a ** constant, change it to NULL. The fact that it is then a non-negative ** integer will be caught later. But it is important not to leave ** variable values in the expression tree. */ static Expr *sqlite3WindowOffsetExpr(Parse *pParse, Expr *pExpr){ | | | 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 | ** The argument expression is an PRECEDING or FOLLOWING offset. The ** value should be a non-negative integer. If the value is not a ** constant, change it to NULL. The fact that it is then a non-negative ** integer will be caught later. But it is important not to leave ** variable values in the expression tree. */ static Expr *sqlite3WindowOffsetExpr(Parse *pParse, Expr *pExpr){ if( 0==sqlite3ExprIsConstant(pExpr) ){ if( IN_RENAME_OBJECT ) sqlite3RenameExprUnmap(pParse, pExpr); sqlite3ExprDelete(pParse->db, pExpr); pExpr = sqlite3ExprAlloc(pParse->db, TK_NULL, 0, 0); } return pExpr; } |
︙ | ︙ |
Changes to test/altertab2.test.
︙ | ︙ | |||
356 357 358 359 360 361 362 | do_catchsql_test 8.6 { CREATE TABLE t0(c0); CREATE INDEX i0 ON t0(likelihood(1,2) AND 0); ALTER TABLE t0 RENAME TO t1; SELECT sql FROM sqlite_master WHERE name='i0'; } {1 {error in index i0: second argument to likelihood() must be a constant between 0.0 and 1.0}} | < < < < < < < < < < < < < < < < < < < < < < | 356 357 358 359 360 361 362 363 | do_catchsql_test 8.6 { CREATE TABLE t0(c0); CREATE INDEX i0 ON t0(likelihood(1,2) AND 0); ALTER TABLE t0 RENAME TO t1; SELECT sql FROM sqlite_master WHERE name='i0'; } {1 {error in index i0: second argument to likelihood() must be a constant between 0.0 and 1.0}} finish_test |
Changes to test/altertab3.test.
︙ | ︙ | |||
732 733 734 735 736 737 738 | {CREATE TRIGGER tr2 AFTER DELETE ON "t3" BEGIN SELECT z, y FROM ( SELECT "t3".* FROM "t3" ); END} } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 732 733 734 735 736 737 738 739 | {CREATE TRIGGER tr2 AFTER DELETE ON "t3" BEGIN SELECT z, y FROM ( SELECT "t3".* FROM "t3" ); END} } finish_test |
Changes to test/avfs.test.
1 2 3 4 5 6 7 8 9 10 | # 2021-03-06 # # 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 | # 2021-03-06 # # 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 tests for the appendvfs extension. # # Tests performed: # avfs-1.0. Test that an appendvfs DB can be added to an empty (ZLF) file. # avfs-1.1. Test that the DB can be read with correct content upon reopen. # avfs-1.2. Test that an appendvfs DB can be added to a simple text file. |
︙ | ︙ |
Changes to test/bestindex8.test.
︙ | ︙ | |||
154 155 156 157 158 159 160 | set ::lFilterArgs } {10} do_test 2.2 { set ::lFilterArgs [list] execsql { SELECT * FROM vt1 LIMIT 5 OFFSET 50 } set ::lFilterArgs | | | 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | set ::lFilterArgs } {10} do_test 2.2 { set ::lFilterArgs [list] execsql { SELECT * FROM vt1 LIMIT 5 OFFSET 50 } set ::lFilterArgs } {{5 50}} do_test 2.3 { set ::lFilterArgs [list] execsql { SELECT * FROM vt1 ORDER BY a, b LIMIT 1 OFFSET 1 } set ::lFilterArgs } {{1 1}} |
︙ | ︙ |
Deleted test/bestindexC.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to test/capi3.test.
︙ | ︙ | |||
177 178 179 180 181 182 183 | } {SQLITE_CANTOPEN 1} do_test capi3-3.4 { sqlite3_errmsg $db2 } {unable to open database file} do_test capi3-3.5 { list [sqlite3_system_errno $db2] [sqlite3_close $db2] } [list $::capi3_errno SQLITE_OK] | | | 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | } {SQLITE_CANTOPEN 1} do_test capi3-3.4 { sqlite3_errmsg $db2 } {unable to open database file} do_test capi3-3.5 { list [sqlite3_system_errno $db2] [sqlite3_close $db2] } [list $::capi3_errno SQLITE_OK] if {[clang_sanitize_address]==0} { do_test capi3-3.6.1-misuse { sqlite3_close $db2 } {SQLITE_MISUSE} do_test capi3-3.6.2-misuse { sqlite3_errmsg $db2 } {bad parameter or other API misuse} ifcapable {utf16} { |
︙ | ︙ |
Deleted test/cksumvfs.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to test/corruptL.test.
︙ | ︙ | |||
1501 1502 1503 1504 1505 1506 1507 | } db close sqlite3 db test.db do_catchsql_test 19.4 { PRAGMA integrity_check; } {1 {database disk image is malformed}} | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1501 1502 1503 1504 1505 1506 1507 1508 | } db close sqlite3 db test.db do_catchsql_test 19.4 { PRAGMA integrity_check; } {1 {database disk image is malformed}} finish_test |
Changes to test/cost.test.
︙ | ︙ | |||
99 100 101 102 103 104 105 | } do_eqp_test 5.2 { SELECT * FROM t2 ORDER BY x, y; } { QUERY PLAN |--SCAN t2 USING INDEX t2i1 | | | 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | } do_eqp_test 5.2 { SELECT * FROM t2 ORDER BY x, y; } { QUERY PLAN |--SCAN t2 USING INDEX t2i1 `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY } do_eqp_test 5.3 { SELECT * FROM t2 WHERE x BETWEEN ? AND ? ORDER BY rowid; } { QUERY PLAN |--SEARCH t2 USING INDEX t2i1 (x>? AND x<?) |
︙ | ︙ |
Changes to test/default.test.
︙ | ︙ | |||
131 132 133 134 135 136 137 | # 2020-03-09 out-of-bounds memory access discovered by "Eternal Sakura" # and reported to chromium. # reset_db do_catchsql_test default-5.1 { CREATE TABLE t1 (a,b DEFAULT(random() NOTNULL IN (RAISE(IGNORE),2,3))); INSERT INTO t1(a) VALUES(1); | | < < < < | 131 132 133 134 135 136 137 138 139 140 | # 2020-03-09 out-of-bounds memory access discovered by "Eternal Sakura" # and reported to chromium. # reset_db do_catchsql_test default-5.1 { CREATE TABLE t1 (a,b DEFAULT(random() NOTNULL IN (RAISE(IGNORE),2,3))); INSERT INTO t1(a) VALUES(1); } {1 {RAISE() may only be used within a trigger-program}} finish_test |
Changes to test/eqp.test.
︙ | ︙ | |||
409 410 411 412 413 414 415 | QUERY PLAN `--MERGE (UNION) |--LEFT | |--SCAN t1 | `--USE TEMP B-TREE FOR ORDER BY `--RIGHT |--SCAN t2 USING INDEX t2i1 | | | | | 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 | QUERY PLAN `--MERGE (UNION) |--LEFT | |--SCAN t1 | `--USE TEMP B-TREE FOR ORDER BY `--RIGHT |--SCAN t2 USING INDEX t2i1 `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY } do_eqp_test 4.2.4 { SELECT * FROM t1 INTERSECT SELECT * FROM t2 ORDER BY 1 } { QUERY PLAN `--MERGE (INTERSECT) |--LEFT | |--SCAN t1 | `--USE TEMP B-TREE FOR ORDER BY `--RIGHT |--SCAN t2 USING INDEX t2i1 `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY } do_eqp_test 4.2.5 { SELECT * FROM t1 EXCEPT SELECT * FROM t2 ORDER BY 1 } { QUERY PLAN `--MERGE (EXCEPT) |--LEFT | |--SCAN t1 | `--USE TEMP B-TREE FOR ORDER BY `--RIGHT |--SCAN t2 USING INDEX t2i1 `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY } do_eqp_test 4.3.1 { SELECT x FROM t1 UNION SELECT x FROM t2 } { QUERY PLAN `--COMPOUND QUERY |
︙ | ︙ |
Deleted test/eqp2.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted test/exprfault2.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to test/fts3snippet2.test.
︙ | ︙ | |||
51 52 53 54 55 56 57 | INSERT INTO t0 VALUES ('one', '1234','aaaa','bbbb'); } do_execsql_test 2.2 { SELECT snippet(t0) FROM t0 WHERE t0 MATCH '(def AND (one NEAR abc)) OR one' } {<b>one</b>} | < < < < < < < < < < < | 51 52 53 54 55 56 57 58 59 | INSERT INTO t0 VALUES ('one', '1234','aaaa','bbbb'); } do_execsql_test 2.2 { SELECT snippet(t0) FROM t0 WHERE t0 MATCH '(def AND (one NEAR abc)) OR one' } {<b>one</b>} set sqlite_fts3_enable_parentheses 0 finish_test |
Changes to test/func.test.
︙ | ︙ | |||
1557 1558 1559 1560 1561 1562 1563 | # Incorrect handling of infinity by SUM(). # do_execsql_test func-38.100 { WITH t1(x) AS (VALUES(9e+999)) SELECT sum(x), avg(x), total(x) FROM t1; WITH t1(x) AS (VALUES(-9e+999)) SELECT sum(x), avg(x), total(x) FROM t1; } {Inf Inf Inf -Inf -Inf -Inf} | < < < < < < < < < < < < < < < < < < < < < | 1557 1558 1559 1560 1561 1562 1563 1564 | # Incorrect handling of infinity by SUM(). # do_execsql_test func-38.100 { WITH t1(x) AS (VALUES(9e+999)) SELECT sum(x), avg(x), total(x) FROM t1; WITH t1(x) AS (VALUES(-9e+999)) SELECT sum(x), avg(x), total(x) FROM t1; } {Inf Inf Inf -Inf -Inf -Inf} finish_test |
Changes to test/func2.test.
︙ | ︙ | |||
504 505 506 507 508 509 510 | bin_to_hex [lindex $blob 0] } "12" do_test func2-3.9.2 { set blob [execsql "SELECT SUBSTR(x'1234', 2, -2)"] bin_to_hex [lindex $blob 0] } "12" | < < < < < < < < < < < < < < < < < < < < < < < | 504 505 506 507 508 509 510 511 | bin_to_hex [lindex $blob 0] } "12" do_test func2-3.9.2 { set blob [execsql "SELECT SUBSTR(x'1234', 2, -2)"] bin_to_hex [lindex $blob 0] } "12" finish_test |
Changes to test/func4.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 | # 2013 March 10 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The focus of # this file is testing the tointeger() and toreal() functions. # # Several of the toreal() tests are disabled on platforms where floating # point precision is not high enough to represent their constant integer # expression arguments as double precision floating point values. # set testdir [file dirname $argv0] source $testdir/tester.tcl set saved_tcl_precision $tcl_precision set tcl_precision 0 load_static_extension db totype set highPrecision(1) [expr \ {[db eval {SELECT tointeger(9223372036854775807 + 1);}] eq {{}}}] do_execsql_test func4-1.1 { SELECT tointeger(NULL); } {{}} do_execsql_test func4-1.2 { SELECT tointeger(''); } {{}} |
︙ | ︙ | |||
208 209 210 211 212 213 214 215 216 217 218 219 220 221 | SELECT tointeger(18446744073709551616); } {{}} do_execsql_test func4-1.55 { SELECT tointeger(18446744073709551616 + 1); } {{}} ifcapable floatingpoint { do_execsql_test func4-2.1 { SELECT toreal(NULL); } {{}} do_execsql_test func4-2.2 { SELECT toreal(''); } {{}} | > > | 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | SELECT tointeger(18446744073709551616); } {{}} do_execsql_test func4-1.55 { SELECT tointeger(18446744073709551616 + 1); } {{}} ifcapable floatingpoint { set highPrecision(2) [expr \ {[db eval {SELECT toreal(-9223372036854775808 + 1);}] eq {{}}}] do_execsql_test func4-2.1 { SELECT toreal(NULL); } {{}} do_execsql_test func4-2.2 { SELECT toreal(''); } {{}} |
︙ | ︙ | |||
352 353 354 355 356 357 358 | } {4503599627370497.0} do_execsql_test func4-2.44 { SELECT toreal(9007199254740992 - 1); } {9007199254740991.0} do_execsql_test func4-2.45 { SELECT toreal(9007199254740992); } {9007199254740992.0} | | < < < < | 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 | } {4503599627370497.0} do_execsql_test func4-2.44 { SELECT toreal(9007199254740992 - 1); } {9007199254740991.0} do_execsql_test func4-2.45 { SELECT toreal(9007199254740992); } {9007199254740992.0} if {$highPrecision(2)} { do_execsql_test func4-2.46 { SELECT toreal(9007199254740992 + 1); } {{}} } do_execsql_test func4-2.47 { SELECT toreal(9007199254740992 + 2); } {9007199254740994.0} do_execsql_test func4-2.48 { SELECT toreal(tointeger(9223372036854775808) - 1); } {{}} |
︙ | ︙ | |||
641 642 643 644 645 646 647 | } {4503599627370497} do_execsql_test func4-5.21 { SELECT tointeger(toreal(9007199254740992 - 1)); } {9007199254740991} do_execsql_test func4-5.22 { SELECT tointeger(toreal(9007199254740992)); } {9007199254740992} | | < < < < | 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 | } {4503599627370497} do_execsql_test func4-5.21 { SELECT tointeger(toreal(9007199254740992 - 1)); } {9007199254740991} do_execsql_test func4-5.22 { SELECT tointeger(toreal(9007199254740992)); } {9007199254740992} if {$highPrecision(2)} { do_execsql_test func4-5.23 { SELECT tointeger(toreal(9007199254740992 + 1)); } {{}} } do_execsql_test func4-5.24 { SELECT tointeger(toreal(9007199254740992 + 2)); } {9007199254740994} if {$highPrecision(1)} { do_execsql_test func4-5.25 { SELECT tointeger(toreal(9223372036854775808 - 1)); |
︙ | ︙ |
Changes to test/fuzzcheck.c.
︙ | ︙ | |||
975 976 977 978 979 980 981 | extern int fuzz_invariant( sqlite3 *db, /* The database connection */ sqlite3_stmt *pStmt, /* Test statement stopped on an SQLITE_ROW */ int iCnt, /* Invariant sequence number, starting at 0 */ int iRow, /* The row number for pStmt */ int nRow, /* Total number of output rows */ int *pbCorrupt, /* IN/OUT: Flag indicating a corrupt database file */ | | < | 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 | extern int fuzz_invariant( sqlite3 *db, /* The database connection */ sqlite3_stmt *pStmt, /* Test statement stopped on an SQLITE_ROW */ int iCnt, /* Invariant sequence number, starting at 0 */ int iRow, /* The row number for pStmt */ int nRow, /* Total number of output rows */ int *pbCorrupt, /* IN/OUT: Flag indicating a corrupt database file */ int eVerbosity /* How much debugging output */ ); /* Implementation of sqlite_dbdata and sqlite_dbptr */ extern int sqlite3_dbdata_init(sqlite3*,const char**,void*); /* |
︙ | ︙ | |||
1028 1029 1030 1031 1032 1033 1034 | } return rc; } /* ** Run the SQL text */ | | < < < < < | 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 | } return rc; } /* ** Run the SQL text */ static int runDbSql(sqlite3 *db, const char *zSql, unsigned int *pBtsFlags){ int rc; sqlite3_stmt *pStmt; int bCorrupt = 0; while( isspace(zSql[0]&0x7f) ) zSql++; if( zSql[0]==0 ) return SQLITE_OK; if( eVerbosity>=4 ){ printf("RUNNING-SQL: [%s]\n", zSql); |
︙ | ︙ | |||
1109 1110 1111 1112 1113 1114 1115 | int iRow = 0; sqlite3_reset(pStmt); while( sqlite3_step(pStmt)==SQLITE_ROW ){ int iCnt = 0; iRow++; for(iCnt=0; iCnt<99999; iCnt++){ rc = fuzz_invariant(db, pStmt, iCnt, iRow, nRow, | | | 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 | int iRow = 0; sqlite3_reset(pStmt); while( sqlite3_step(pStmt)==SQLITE_ROW ){ int iCnt = 0; iRow++; for(iCnt=0; iCnt<99999; iCnt++){ rc = fuzz_invariant(db, pStmt, iCnt, iRow, nRow, &bCorrupt, eVerbosity); if( rc==SQLITE_DONE ) break; if( rc!=SQLITE_ERROR ) g.nInvariant++; if( eVerbosity>0 ){ if( rc==SQLITE_OK ){ printf("invariant-check: ok\n"); }else if( rc==SQLITE_CORRUPT ){ printf("invariant-check: failed due to database corruption\n"); |
︙ | ︙ | |||
1332 1333 1334 1335 1336 1337 1338 | memcpy(zSql, aData+iSql, nSql); zSql[nSql] = 0; for(i=j=0; zSql[i]; i++){ if( zSql[i]==';' ){ char cSaved = zSql[i+1]; zSql[i+1] = 0; if( sqlite3_complete(zSql+j) ){ | | | | 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 | memcpy(zSql, aData+iSql, nSql); zSql[nSql] = 0; for(i=j=0; zSql[i]; i++){ if( zSql[i]==';' ){ char cSaved = zSql[i+1]; zSql[i+1] = 0; if( sqlite3_complete(zSql+j) ){ rc = runDbSql(cx.db, zSql+j, &btsFlags); j = i+1; } zSql[i+1] = cSaved; if( rc==SQLITE_INTERRUPT || progress_handler(&cx) ){ goto testrun_finished; } } } if( j<i ){ runDbSql(cx.db, zSql+j, &btsFlags); } } testrun_finished: sqlite3_free(zSql); rc = sqlite3_close(cx.db); if( rc!=SQLITE_OK ){ fprintf(stdout, "sqlite3_close() returns %d\n", rc); |
︙ | ︙ |
Changes to test/fuzzinvariants.c.
︙ | ︙ | |||
26 27 28 29 30 31 32 | #include <stdlib.h> #include <string.h> #include <ctype.h> /* Forward references */ static char *fuzz_invariant_sql(sqlite3_stmt*, int); static int sameValue(sqlite3_stmt*,int,sqlite3_stmt*,int,sqlite3_stmt*); | | < < < < < < | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #include <stdlib.h> #include <string.h> #include <ctype.h> /* Forward references */ static char *fuzz_invariant_sql(sqlite3_stmt*, int); static int sameValue(sqlite3_stmt*,int,sqlite3_stmt*,int,sqlite3_stmt*); static void reportInvariantFailed(sqlite3_stmt*,sqlite3_stmt*,int); /* ** Do an invariant check on pStmt. iCnt determines which invariant check to ** perform. The first check is iCnt==0. ** ** *pbCorrupt is a flag that, if true, indicates that the database file ** is known to be corrupt. A value of non-zero means "yes, the database |
︙ | ︙ | |||
70 71 72 73 74 75 76 | int fuzz_invariant( sqlite3 *db, /* The database connection */ sqlite3_stmt *pStmt, /* Test statement stopped on an SQLITE_ROW */ int iCnt, /* Invariant sequence number, starting at 0 */ int iRow, /* Current row number */ int nRow, /* Number of output rows from pStmt */ int *pbCorrupt, /* IN/OUT: Flag indicating a corrupt database file */ | | < < < < < < < < | 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 | int fuzz_invariant( sqlite3 *db, /* The database connection */ sqlite3_stmt *pStmt, /* Test statement stopped on an SQLITE_ROW */ int iCnt, /* Invariant sequence number, starting at 0 */ int iRow, /* Current row number */ int nRow, /* Number of output rows from pStmt */ int *pbCorrupt, /* IN/OUT: Flag indicating a corrupt database file */ int eVerbosity /* How much debugging output */ ){ char *zTest; sqlite3_stmt *pTestStmt = 0; int rc; int i; int nCol; int nParam; if( *pbCorrupt ) return SQLITE_DONE; nParam = sqlite3_bind_parameter_count(pStmt); if( nParam>100 ) return SQLITE_DONE; zTest = fuzz_invariant_sql(pStmt, iCnt); if( zTest==0 ) return SQLITE_DONE; rc = sqlite3_prepare_v2(db, zTest, -1, &pTestStmt, 0); if( rc ){ if( eVerbosity ){ printf("invariant compile failed: %s\n%s\n", sqlite3_errmsg(db), zTest); } sqlite3_free(zTest); sqlite3_finalize(pTestStmt); |
︙ | ︙ | |||
222 223 224 225 226 227 228 | sqlite3_free(zSql); } sqlite3_bind_pointer(pCk, 1, pStmt, "stmt-pointer", 0); rc = sqlite3_step(pCk); } sqlite3_finalize(pCk); if( rc==SQLITE_DONE ){ | | > | 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 | sqlite3_free(zSql); } sqlite3_bind_pointer(pCk, 1, pStmt, "stmt-pointer", 0); rc = sqlite3_step(pCk); } sqlite3_finalize(pCk); if( rc==SQLITE_DONE ){ reportInvariantFailed(pStmt, pTestStmt, iRow); return SQLITE_INTERNAL; }else if( eVerbosity>0 ){ printf("invariant-error ignored due to the use of virtual tables\n"); } } not_a_fault: sqlite3_finalize(pTestStmt); return SQLITE_OK; } /* ** Generate SQL used to test a statement invariant. ** ** Return 0 if the iCnt is out of range. ** ** iCnt meanings: |
︙ | ︙ | |||
498 499 500 501 502 503 504 | /* ** Report a failure of the invariant: The current output row of pOrig ** does not appear in any row of the output from pTest. */ static void reportInvariantFailed( sqlite3_stmt *pOrig, /* The original query */ sqlite3_stmt *pTest, /* The alternative test query with a missing row */ | | < < | < | < | 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 | /* ** Report a failure of the invariant: The current output row of pOrig ** does not appear in any row of the output from pTest. */ static void reportInvariantFailed( sqlite3_stmt *pOrig, /* The original query */ sqlite3_stmt *pTest, /* The alternative test query with a missing row */ int iRow /* Row number in pOrig */ ){ int iTestRow = 0; printf("Invariant check failed on row %d.\n", iRow); printf("Original query --------------------------------------------------\n"); printf("%s\n", sqlite3_expanded_sql(pOrig)); printf("Alternative query -----------------------------------------------\n"); printf("%s\n", sqlite3_expanded_sql(pTest)); printf("Result row that is missing from the alternative -----------------\n"); printRow(pOrig, iRow); printf("Complete results from the alternative query ---------------------\n"); sqlite3_reset(pTest); while( sqlite3_step(pTest)==SQLITE_ROW ){ iTestRow++; printRow(pTest, iTestRow); } sqlite3_finalize(pTest); abort(); } |
Changes to test/icu.test.
︙ | ︙ | |||
145 146 147 148 149 150 151 | SELECT upper(char(0xfb04,0xdf,0xfb04,0xe8,0xfb04)); } } # 2020-03-19 # The ESCAPE clause on LIKE takes precedence over wildcards # | | < < < < < < < < < < < < < < < < | 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | SELECT upper(char(0xfb04,0xdf,0xfb04,0xe8,0xfb04)); } } # 2020-03-19 # The ESCAPE clause on LIKE takes precedence over wildcards # do_execsql_test idu-6.0 { DROP TABLE IF EXISTS t1; CREATE TABLE t1(id INTEGER PRIMARY KEY, x TEXT); INSERT INTO t1 VALUES (1,'abcde'), (2,'abc_'), (3,'abc__'), (4,'abc%'), (5,'abc%%'); SELECT id FROM t1 WHERE x LIKE 'abc%%' ESCAPE '%'; } {4} do_execsql_test icu-6.1 { SELECT id FROM t1 WHERE x LIKE 'abc__' ESCAPE '_'; } {2} finish_test |
Changes to test/in4.test.
︙ | ︙ | |||
454 455 456 457 458 459 460 | ANALYZE sqlite_schema; INSERT INTO sqlite_stat1 VALUES('t1','t1abc','10000 5 00 2003 10'); ANALYZE sqlite_schema; } {} do_execsql_test 11.1 { SELECT * FROM t1 WHERE b IN (345, (SELECT 1 FROM t1 | | | | 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 | ANALYZE sqlite_schema; INSERT INTO sqlite_stat1 VALUES('t1','t1abc','10000 5 00 2003 10'); ANALYZE sqlite_schema; } {} do_execsql_test 11.1 { SELECT * FROM t1 WHERE b IN (345, (SELECT 1 FROM t1 WHERE b IN (345 NOT GLOB 510) AND c GLOB 'abc*xyz')) AND c BETWEEN 'abc' AND 'xyz'; } {xyz 1 abcdefxyz 99} do_execsql_test 11.2 { EXPLAIN SELECT * FROM t1 WHERE b IN (345, (SELECT 1 FROM t1 WHERE b IN (345 NOT GLOB 510) AND c GLOB 'abc*xyz')) AND c BETWEEN 'abc' AND 'xyz'; } {/ SeekScan /} # 2021-06-25 ticket 6dcbfd11cf666e21 # Another problem with OP_SeekScan # |
︙ | ︙ |
Changes to test/in5.test.
︙ | ︙ | |||
262 263 264 265 266 267 268 | SELECT lower('1e500') FROM t0 WHERE rowid NOT IN (0, 0, lower('1e500')); } {1e500} do_execsql_test 9.2 { SELECT lower('1e500') FROM t0 WHERE rowid != lower('1e500'); } {1e500} | < < < < < < < < < < < < < < < < < < < < < < | 262 263 264 265 266 267 268 269 | SELECT lower('1e500') FROM t0 WHERE rowid NOT IN (0, 0, lower('1e500')); } {1e500} do_execsql_test 9.2 { SELECT lower('1e500') FROM t0 WHERE rowid != lower('1e500'); } {1e500} finish_test |
Deleted test/in7.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to test/indexexpr1.test.
︙ | ︙ | |||
611 612 613 614 615 616 617 | JOIN (SELECT t1.tag AS "tag", t2.type AS "type", MAX(t2.value) AS "max_value" FROM t1 JOIN t2 ON t2.t1_id = t1.id GROUP BY t2.type, t1.tag ) v ON v.type = 0 AND v.tag = u.tag; } {7 100 8 101} | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 611 612 613 614 615 616 617 618 619 620 621 622 623 624 | JOIN (SELECT t1.tag AS "tag", t2.type AS "type", MAX(t2.value) AS "max_value" FROM t1 JOIN t2 ON t2.t1_id = t1.id GROUP BY t2.type, t1.tag ) v ON v.type = 0 AND v.tag = u.tag; } {7 100 8 101} # 2023-11-08 Forum post https://sqlite.org/forum/forumpost/68d284c86b082c3e # # Functions that return subtypes and that are indexed cannot be used to # cover function calls from the main table, since the indexed value does # not know the subtype. # |
︙ | ︙ |
Changes to test/join5.test.
︙ | ︙ | |||
366 367 368 369 370 371 372 | do_execsql_test 9.1 { CREATE TABLE t1(a ,b FLOAT); INSERT INTO t1 VALUES(1,1); CREATE INDEX t1x1 ON t1(a,b,a,a,a,a,a,a,a,a,a,b); ANALYZE sqlite_schema; INSERT INTO sqlite_stat1 VALUES('t1','t1x1','648 324 81 81 81 81 81 81 81081 81 81 81'); ANALYZE sqlite_schema; | < < < | < | | 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 | do_execsql_test 9.1 { CREATE TABLE t1(a ,b FLOAT); INSERT INTO t1 VALUES(1,1); CREATE INDEX t1x1 ON t1(a,b,a,a,a,a,a,a,a,a,a,b); ANALYZE sqlite_schema; INSERT INTO sqlite_stat1 VALUES('t1','t1x1','648 324 81 81 81 81 81 81 81081 81 81 81'); ANALYZE sqlite_schema; SELECT a FROM (SELECT a FROM t1 NATURAL LEFT JOIN t1) NATURAL LEFT JOIN t1 WHERE (rowid,1)<=(5,0); } {1} # 2022-03-02 https://sqlite.org/forum/info/50a1bbe08ce4c29c # Bloom-filter pulldown is incompatible with skip-scan. # reset_db do_execsql_test 10.1 { CREATE TABLE t1(x INT); |
︙ | ︙ |
Changes to test/joinH.test.
︙ | ︙ | |||
197 198 199 200 201 202 203 | CREATE TABLE wo1(a PRIMARY KEY, b) WITHOUT ROWID; CREATE TABLE wo2(a PRIMARY KEY, rowid) WITHOUT ROWID; CREATE TABLE wo3(a PRIMARY KEY, b) WITHOUT ROWID; } do_catchsql_test 9.1 { SELECT rowid FROM wo1, x1, x2; | | | | | 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | CREATE TABLE wo1(a PRIMARY KEY, b) WITHOUT ROWID; CREATE TABLE wo2(a PRIMARY KEY, rowid) WITHOUT ROWID; CREATE TABLE wo3(a PRIMARY KEY, b) WITHOUT ROWID; } do_catchsql_test 9.1 { SELECT rowid FROM wo1, x1, x2; } {1 {no such column: rowid}} do_catchsql_test 9.2 { SELECT rowid FROM wo1, (x1, x2); } {1 {no such column: rowid}} do_catchsql_test 9.3 { SELECT rowid FROM wo1 JOIN (x1 JOIN x2); } {1 {no such column: rowid}} do_catchsql_test 9.4 { SELECT a FROM wo1, x1, x2; } {1 {ambiguous column name: a}} # It is not possible to use "rowid" in a USING clause. # |
︙ | ︙ | |||
305 306 307 308 309 310 311 | do_execsql_test 12.2 { SELECT * FROM t1 LEFT JOIN t2 ON true RIGHT JOIN t3 ON d2=e3 WHERE c2 BETWEEN NULL AND a1; } do_execsql_test 12.3 { SELECT * FROM t1 LEFT JOIN t2 ON true RIGHT JOIN t3 ON d2=e3 WHERE c2 BETWEEN NULL AND a1; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 305 306 307 308 309 310 311 312 | do_execsql_test 12.2 { SELECT * FROM t1 LEFT JOIN t2 ON true RIGHT JOIN t3 ON d2=e3 WHERE c2 BETWEEN NULL AND a1; } do_execsql_test 12.3 { SELECT * FROM t1 LEFT JOIN t2 ON true RIGHT JOIN t3 ON d2=e3 WHERE c2 BETWEEN NULL AND a1; } finish_test |
Changes to test/json102.test.
︙ | ︙ | |||
759 760 761 762 763 764 765 | } {ok 2023-08-03 876 5 {{"x":77}}} do_execsql_test json102-1720 { UPDATE t1 SET memo = JSON_SET(memo, '$.y', 6) WHERE a2 IN (876) AND JSON_TYPE(memo, '$.y') IS NULL; PRAGMA integrity_check; SELECT * FROM t1; } {ok 2023-08-03 876 5 {{"x":77,"y":6}}} | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 759 760 761 762 763 764 765 766 767 | } {ok 2023-08-03 876 5 {{"x":77}}} do_execsql_test json102-1720 { UPDATE t1 SET memo = JSON_SET(memo, '$.y', 6) WHERE a2 IN (876) AND JSON_TYPE(memo, '$.y') IS NULL; PRAGMA integrity_check; SELECT * FROM t1; } {ok 2023-08-03 876 5 {{"x":77,"y":6}}} finish_test |
Changes to test/json106.test.
︙ | ︙ | |||
63 64 65 66 67 68 69 | } 0 do_execsql_test $ii.7 { UPDATE t1 SET p=json_patch(j0,j5); SELECT count(*) FROM t1, kv WHERE p->>key IS NOT val } 0 | < < < < < < | 63 64 65 66 67 68 69 70 71 72 73 | } 0 do_execsql_test $ii.7 { UPDATE t1 SET p=json_patch(j0,j5); SELECT count(*) FROM t1, kv WHERE p->>key IS NOT val } 0 } finish_test |
Deleted test/json108.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to test/lemon-test01.y.
1 2 3 4 | // A test case for the LEMON parser generator. Run as follows: // // lemon lemon-test01.y && gcc -g lemon-test01.c && ./a.out // | < < < < < | 1 2 3 4 5 6 7 8 9 10 11 | // A test case for the LEMON parser generator. Run as follows: // // lemon lemon-test01.y && gcc -g lemon-test01.c && ./a.out // %token_prefix TK_ %token_type int %default_type int %include { static int nSyntaxError = 0; static int nAccept = 0; static int nFailure = 0; |
︙ | ︙ | |||
29 30 31 32 33 34 35 | nFailure++; } %code { #include <assert.h> #include "lemon-test01.h" static int nTest = 0; static int nErr = 0; | | | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | nFailure++; } %code { #include <assert.h> #include "lemon-test01.h" static int nTest = 0; static int nErr = 0; static int testCase(int testId, int shouldBe, int actual){ nTest++; if( shouldBe==actual ){ printf("test %d: ok\n", testId); }else{ printf("test %d: got %d, expected %d\n", testId, actual, shouldBe); nErr++; } |
︙ | ︙ |
Changes to test/misc2.test.
︙ | ︙ | |||
50 51 52 53 54 55 56 | CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(1,2,3); CREATE TABLE t2(a,b,c); INSERT INTO t2 VALUES(7,8,9); } } {} ifcapable subquery { | < | | < < < < | < < | | | < < < < < | < < < | 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 | CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(1,2,3); CREATE TABLE t2(a,b,c); INSERT INTO t2 VALUES(7,8,9); } } {} ifcapable subquery { do_catchsql_test misc2-2.2 { SELECT rowid, * FROM (SELECT * FROM t1, t2); } {1 {no such column: rowid}} do_catchsql_test misc2-2.2b { SELECT 'rowid', * FROM (SELECT * FROM t1, t2); } {0 {rowid 1 2 3 7 8 9}} } ifcapable view { do_catchsql_test misc2-2.3 { CREATE VIEW v1 AS SELECT * FROM t1, t2; SELECT rowid, * FROM v1; } {1 {no such column: rowid}} do_catchsql_test misc2-2.3b { SELECT 'rowid', * FROM v1; } {0 {rowid 1 2 3 7 8 9}} } ;# ifcapable view # Ticket #2002 and #1952. ifcapable subquery { |
︙ | ︙ |
Changes to test/misc8.test.
︙ | ︙ | |||
96 97 98 99 100 101 102 | 0 8 {} 10 {} {} 0 9 {} 10 {} {} 0 10 {} 10 {} {} } # 2016-02-26: An assertion fault found by the libFuzzer project # | < < < < < | | 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 | 0 8 {} 10 {} {} 0 9 {} 10 {} {} 0 10 {} 10 {} {} } # 2016-02-26: An assertion fault found by the libFuzzer project # do_catchsql_test misc8-3.0 { SELECT * FROM ( (SELECT 0 AS i) AS x1, (SELECT 1) AS x2 ) AS x3, (SELECT 6 AS j UNION ALL SELECT 7) AS x4 WHERE i<rowid ORDER BY 1; } {1 {no such column: rowid}} # The SQLITE_DBCONFIG_MAINDBNAME interface # db close forcedelete test.db test2.db sqlite3 db test.db do_execsql_test misc8-4.0 { |
︙ | ︙ |
Changes to test/mmapcorrupt.test.
︙ | ︙ | |||
12 13 14 15 16 17 18 | # Test special cases of corrupt database handling in mmap-mode. # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix mmapcorrupt | < < < < | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # Test special cases of corrupt database handling in mmap-mode. # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix mmapcorrupt database_may_be_corrupt db close sqlite3_shutdown sqlite3_config_lookaside 0 0 sqlite3_initialize |
︙ | ︙ |
Changes to test/notnull2.test.
︙ | ︙ | |||
55 56 57 58 59 60 61 | } 100 {} do_vmstep_test 1.4.2 { SELECT * FROM t2 WHERE 0==( c IS NOT NULL ) } +1000 {} do_vmstep_test 1.5.1 { SELECT count(*) FROM t2 WHERE EXISTS( | | | | | | 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | } 100 {} do_vmstep_test 1.4.2 { SELECT * FROM t2 WHERE 0==( c IS NOT NULL ) } +1000 {} do_vmstep_test 1.5.1 { SELECT count(*) FROM t2 WHERE EXISTS( SELECT t2.d IS NULL FROM t1 WHERE t1.a=450 ) } 10000 {1000} do_vmstep_test 1.5.2 { SELECT count(*) FROM t2 WHERE EXISTS( SELECT t2.c IS NULL FROM t1 WHERE t1.a=450 ) } +100000 {1000} #------------------------------------------------------------------------- reset_db do_execsql_test 2.0 { CREATE TABLE T1(a INTEGER PRIMARY KEY, b); CREATE TABLE T3(k, v); } |
︙ | ︙ | |||
107 108 109 110 111 112 113 | do_execsql_test 4.1 { CREATE TABLE t1(a INT); INSERT INTO t1(a) VALUES(1); CREATE TABLE t2(b INT); SELECT * FROM (SELECT 3 AS c FROM t1) AS t3 LEFT JOIN t2 ON c IS NULL; } {3 {}} | < < < < < < < < | 107 108 109 110 111 112 113 114 | do_execsql_test 4.1 { CREATE TABLE t1(a INT); INSERT INTO t1(a) VALUES(1); CREATE TABLE t2(b INT); SELECT * FROM (SELECT 3 AS c FROM t1) AS t3 LEFT JOIN t2 ON c IS NULL; } {3 {}} finish_test |
Changes to test/orderby1.test.
︙ | ︙ | |||
516 517 518 519 520 521 522 | } do_eqp_test 8.1 { SELECT * FROM t1 ORDER BY a, b; } { QUERY PLAN |--SCAN t1 USING INDEX i1 | | | 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 | } do_eqp_test 8.1 { SELECT * FROM t1 ORDER BY a, b; } { QUERY PLAN |--SCAN t1 USING INDEX i1 `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY } do_execsql_test 8.2 { WITH cnt(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM cnt WHERE i<10000 ) INSERT INTO t1 SELECT i%2, randomblob(500) FROM cnt; |
︙ | ︙ |
Changes to test/pragma.test.
︙ | ︙ | |||
383 384 385 386 387 388 389 | } } {{wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2}} do_test pragma-3.5 { execsql { PRAGMA integrity_check=4 } } {{wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}} | < < < | 383 384 385 386 387 388 389 390 391 392 393 394 395 396 | } } {{wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2}} do_test pragma-3.5 { execsql { PRAGMA integrity_check=4 } } {{wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}} do_catchsql_test pragma-3.6 { PRAGMA integrity_check=xyz } {1 {no such table: xyz}} do_catchsql_test pragma-3.6b { PRAGMA integrity_check=t2 } {0 {{wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2}}} do_catchsql_test pragma-3.6c { |
︙ | ︙ |
Changes to test/pragma4.test.
︙ | ︙ | |||
79 80 81 82 83 84 85 | do_pragma_ncol_test 1.$tn.1 $sql 0 } # EXPLAIN on a PRAGMA integrity_check. # Verify that that P4_INTARRAY argument to OP_IntegrityCk is rendered # correctly. # | | | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | do_pragma_ncol_test 1.$tn.1 $sql 0 } # EXPLAIN on a PRAGMA integrity_check. # Verify that that P4_INTARRAY argument to OP_IntegrityCk is rendered # correctly. # db close forcedelete test.db sqlite3 db test.db do_test pragma4-2.100 { db eval { PRAGMA page_size=512; CREATE TABLE t1(x); WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<10000) |
︙ | ︙ | |||
259 260 261 262 263 264 265 266 | CREATE TABLE t4(a DEFAULT 'abc' /* comment */, b DEFAULT -1 -- comment , c DEFAULT +4.0 /* another comment */ ); PRAGMA table_info = t4; } { 0 a {} 0 'abc' 0 1 b {} 0 -1 0 2 c {} 0 +4.0 0 } | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 259 260 261 262 263 264 265 266 267 268 | CREATE TABLE t4(a DEFAULT 'abc' /* comment */, b DEFAULT -1 -- comment , c DEFAULT +4.0 /* another comment */ ); PRAGMA table_info = t4; } { 0 a {} 0 'abc' 0 1 b {} 0 -1 0 2 c {} 0 +4.0 0 } finish_test |
Changes to test/pragma6.test.
︙ | ︙ | |||
47 48 49 50 51 52 53 | | 4048: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 05 ................ | 4064: 03 01 01 05 0a 05 04 03 01 01 04 08 05 03 03 01 ................ | 4080: 01 03 06 05 02 03 00 00 00 00 00 00 00 00 00 00 ................ | end crash-540f4c1eb1e7ac.db }] } {} | | < | | | | | | | > | < < < | 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | | 4048: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 05 ................ | 4064: 03 01 01 05 0a 05 04 03 01 01 04 08 05 03 03 01 ................ | 4080: 01 03 06 05 02 03 00 00 00 00 00 00 00 00 00 00 ................ | end crash-540f4c1eb1e7ac.db }] } {} do_execsql_test 1.1 { CREATE TEMP TABLE t2( a t1 PRIMARY KEY default 27, b default(current_timestamp), d TEXT UNIQUE DEFAULT 'ch`arlie', c TEXT UNIQUE DEFAULT 084, UNIQUE(c,b,b,a,b) ) WITHOUT ROWID; INSERT INTO t1(a) VALUES(zeroblob(40000)); } do_test 1.2 { execsql { PRAGMA integrity_check; } execsql { PRAGMA quick_check; } set {} {} } {} |
︙ | ︙ |
Changes to test/pushdown.test.
|
| | < < < < < < < < < < < < < < < < < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # 2017 April 29 # # 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 pushdown do_execsql_test 1.0 { CREATE TABLE t1(a, b, c); |
︙ | ︙ | |||
103 104 105 106 107 108 109 | SELECT x FROM u2 WHERE x=a AND f('two') ) AND f('three')=123 } set L } {three} # 2022-11-25 dbsqlfuzz crash-3a548de406a50e896c1bf7142692d35d339d697f | | | | 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | SELECT x FROM u2 WHERE x=a AND f('two') ) AND f('three')=123 } set L } {three} # 2022-11-25 dbsqlfuzz crash-3a548de406a50e896c1bf7142692d35d339d697f # Disable the push-down optimization for compound subqueries if any # arm of the compound has an incompatible affinity. # reset_db do_execsql_test 3.1 { CREATE TABLE t0(c0 INT); INSERT INTO t0 VALUES(0); CREATE TABLE t1_a(a INTEGER PRIMARY KEY, b TEXT); INSERT INTO t1_a VALUES(1,'one'); |
︙ | ︙ | |||
201 202 203 204 205 206 207 | `--SCAN t2 } # ^^^^^^^^^^^^^^^^^^^^ # The query should be converted into: # SELECT (SELECT count(*) FROM t1)+(SELECT count(*) FROM t2) # 2023-05-09 https://sqlite.org/forum/forumpost/a7d4be7fb6 | | | 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | `--SCAN t2 } # ^^^^^^^^^^^^^^^^^^^^ # The query should be converted into: # SELECT (SELECT count(*) FROM t1)+(SELECT count(*) FROM t2) # 2023-05-09 https://sqlite.org/forum/forumpost/a7d4be7fb6 # Restriction (9) on the push-down optimization. # reset_db db null - do_execsql_test 4.1 { CREATE TABLE t1(a INT); CREATE TABLE t2(b INT); CREATE TABLE t3(c INT); |
︙ | ︙ | |||
243 244 245 246 247 248 249 | CREATE TABLE t5(e INT); INSERT INTO t5 VALUES(5); SELECT * FROM t1 JOIN t2 ON null RIGHT JOIN t3 ON true LEFT JOIN (t4 JOIN t5 ON d+1=e) ON d=4 WHERE e>0; } {- - 3 4 5} | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 223 224 225 226 227 228 229 230 | CREATE TABLE t5(e INT); INSERT INTO t5 VALUES(5); SELECT * FROM t1 JOIN t2 ON null RIGHT JOIN t3 ON true LEFT JOIN (t4 JOIN t5 ON d+1=e) ON d=4 WHERE e>0; } {- - 3 4 5} finish_test |
Deleted test/readonly.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to test/recover.test.
1 2 3 4 5 6 7 8 9 10 | # 2019 April 23 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** | < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # 2019 April 23 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # Test the shell tool ".ar" command. # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix recover |
︙ | ︙ |
Changes to test/returning1.test.
︙ | ︙ | |||
208 209 210 211 212 213 214 | INSERT INTO log VALUES('insert', new.rowid, new.a, new.b); END; CREATE TRIGGER tr2 INSTEAD OF UPDATE ON t1 BEGIN INSERT INTO log VALUES('update', new.rowid, new.a, new.b); END; } | < | | | | | | | | | | | < < < < < < < < < < < < < < < < < < < < | 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | INSERT INTO log VALUES('insert', new.rowid, new.a, new.b); END; CREATE TRIGGER tr2 INSTEAD OF UPDATE ON t1 BEGIN INSERT INTO log VALUES('update', new.rowid, new.a, new.b); END; } do_catchsql_test 10.3a { INSERT INTO t1(a, b) VALUES(1234, 5678) RETURNING rowid; } {1 {no such column: new.rowid}} do_catchsql_test 10.3b { UPDATE t1 SET a='z' WHERE b='y' RETURNING rowid; } {1 {no such column: new.rowid}} do_execsql_test 10.4 { SELECT * FROM log; } {} # 2021-04-27 dbsqlfuzz 78b9400770ef8cc7d9427dfba26f4fcf46ea7dc2 # Returning clauses on TEMP tables with triggers. # reset_db do_execsql_test 11.1 { CREATE TEMP TABLE t1(a,b); |
︙ | ︙ | |||
456 457 458 459 460 461 462 | do_catchsql_test 19.1 { CREATE TRIGGER IF NOT EXISTS r1 AFTER DELETE ON t1 BEGIN INSERT INTO t1(a) VALUES (1) RETURNING FALSE; INSERT INTO t1(a) VALUES (2) RETURNING TRUE; END; } {0 {}} | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 435 436 437 438 439 440 441 442 | do_catchsql_test 19.1 { CREATE TRIGGER IF NOT EXISTS r1 AFTER DELETE ON t1 BEGIN INSERT INTO t1(a) VALUES (1) RETURNING FALSE; INSERT INTO t1(a) VALUES (2) RETURNING TRUE; END; } {0 {}} finish_test |
Changes to test/rowid.test.
︙ | ︙ | |||
799 800 801 802 803 804 805 | CREATE TABLE t3(z); INSERT INTO t1(rowid, x) VALUES(1, 1); INSERT INTO t2(y) VALUES(2); INSERT INTO t3(rowid, z) VALUES(3, 3); } | < < | < < < < < < < < < < | | | | | | | | > | < < | 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 | CREATE TABLE t3(z); INSERT INTO t1(rowid, x) VALUES(1, 1); INSERT INTO t2(y) VALUES(2); INSERT INTO t3(rowid, z) VALUES(3, 3); } do_execsql_test 16.1 { SELECT rowid FROM t1, t2; } {1} do_execsql_test 16.2 { SELECT rowid FROM t1, v1; } {1} do_execsql_test 16.3 { SELECT rowid FROM t3, v1; } {3} do_execsql_test 16.4 { SELECT rowid FROM t3, (SELECT 123); } {3} do_execsql_test 16.5 { SELECT rowid FROM t2, t1; } {1} do_execsql_test 16.6 { SELECT rowid FROM v1, t1; } {1} do_execsql_test 16.7 { SELECT rowid FROM v1, t3; } {3} do_execsql_test 16.8 { SELECT rowid FROM (SELECT 123), t3; } {3} do_catchsql_test 16.5 { SELECT rowid FROM t1, t3; } {1 {no such column: rowid}} finish_test |
Changes to test/scanstatus2.test.
︙ | ︙ | |||
324 325 326 327 328 329 330 | --MATERIALIZE xy (nCycle=nnn) ----SCAN t1 (nCycle=nnn) ----USE TEMP B-TREE FOR GROUP BY (nCycle=nnn) --SCAN xy (nCycle=nnn) --SCAN xy2 (nCycle=nnn) } | < < < < < < < < < < < | 324 325 326 327 328 329 330 331 332 333 334 | --MATERIALIZE xy (nCycle=nnn) ----SCAN t1 (nCycle=nnn) ----USE TEMP B-TREE FOR GROUP BY (nCycle=nnn) --SCAN xy (nCycle=nnn) --SCAN xy2 (nCycle=nnn) } #explain_i { SELECT (a % 2), group_concat(b) FROM t1 GROUP BY 1 } #puts_debug_info { SELECT (a % 2), group_concat(b) FROM t1 GROUP BY 1 } finish_test |
Changes to test/selectA.test.
︙ | ︙ | |||
1336 1337 1338 1339 1340 1341 1342 | SELECT a, b FROM t4 WHERE f()==f() ORDER BY 1,2 } { QUERY PLAN `--MERGE (UNION ALL) |--LEFT | |--SCAN t5 USING INDEX i2 | | | | 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 | SELECT a, b FROM t4 WHERE f()==f() ORDER BY 1,2 } { QUERY PLAN `--MERGE (UNION ALL) |--LEFT | |--SCAN t5 USING INDEX i2 | `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY `--RIGHT |--SCAN t4 USING INDEX i1 `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY } do_execsql_test 4.1.3 { SELECT c, d FROM t5 UNION ALL SELECT a, b FROM t4 WHERE f()==f() ORDER BY 1,2 |
︙ | ︙ |
Changes to test/sessionfuzz.c.
︙ | ︙ | |||
56 57 58 59 60 61 62 | #ifdef SQLITE_THREADSAFE #undef SQLITE_THREADSAFE #endif #define SQLITE_DEBUG 1 #define SQLITE_THREADSAFE 0 | < | 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | #ifdef SQLITE_THREADSAFE #undef SQLITE_THREADSAFE #endif #define SQLITE_DEBUG 1 #define SQLITE_THREADSAFE 0 #define SQLITE_OMIT_LOAD_EXTENSION 0 #define SQLITE_ENABLE_SESSION 1 #define SQLITE_ENABLE_PREUPDATE_HOOK 1 #define SQLITE_ENABLE_DESERIALIZE 1 #include "sqlite3.c" /* Code to populate the database */ |
︙ | ︙ |
Changes to test/shell1.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2009 Nov 11 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # The focus of this file is testing the CLI shell tool. # | < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # 2009 Nov 11 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # The focus of this file is testing the CLI shell tool. # # # Test plan: # # shell1-1.*: Basic command line option handling. # shell1-2.*: Basic "dot" command token parsing. # shell1-3.*: Basic test that "dot" command can be called. |
︙ | ︙ |
Changes to test/shell2.test.
1 2 3 4 5 6 7 8 9 10 | # 2009 Nov 11 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** | < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # 2009 Nov 11 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # The focus of this file is testing the CLI shell tool. # # $Id: shell2.test,v 1.7 2009/07/17 16:54:48 shaneh Exp $ # # Test plan: |
︙ | ︙ |
Changes to test/shell3.test.
1 2 3 4 5 6 7 8 9 10 | # 2009 Dec 16 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** | < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # 2009 Dec 16 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # The focus of this file is testing the CLI shell tool. # # $Id: shell2.test,v 1.7 2009/07/17 16:54:48 shaneh Exp $ # # Test plan: |
︙ | ︙ |
Changes to test/shell4.test.
1 2 3 4 5 6 7 8 9 10 | # 2010 July 28 # # 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 | # 2010 July 28 # # 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. # #*********************************************************************** # # The focus of this file is testing the CLI shell tool. # These tests are specific to the .stats command. # # 2015-03-19: Added tests for .trace # Test plan: |
︙ | ︙ |
Changes to test/shell5.test.
1 2 3 4 5 6 7 8 9 10 | # 2010 August 4 # # 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 | # 2010 August 4 # # 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. # #*********************************************************************** # # The focus of this file is testing the CLI shell tool. # These tests are specific to the .import command. # # $Id: shell5.test,v 1.7 2009/07/17 16:54:48 shaneh Exp $ # |
︙ | ︙ | |||
567 568 569 570 571 572 573 | forcedelete test.db catchcmd test.db {.import -csv shell5.csv t1 .mode line SELECT * FROM t1;} } {0 { 1 = あい 2 = うえお}} | < < < < < < < < < < < < < < < < < < < < < < < < < < | 566 567 568 569 570 571 572 573 | forcedelete test.db catchcmd test.db {.import -csv shell5.csv t1 .mode line SELECT * FROM t1;} } {0 { 1 = あい 2 = うえお}} finish_test |
Changes to test/shell6.test.
1 2 3 4 5 6 7 8 9 10 | # 2016 December 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** | < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # 2016 December 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # Test the shell tool ".lint fkey-indexes" command. # set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !vtab {finish_test; return} |
︙ | ︙ |
Changes to test/shell7.test.
1 2 3 4 5 6 7 8 9 10 | # 2016 December 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. # #*********************************************************************** | < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # 2016 December 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 the readfile() function built into the shell tool. Specifically, # that it does not truncate the blob read at the first embedded 0x00 # byte. # set testdir [file dirname $argv0] |
︙ | ︙ |
Changes to test/shell8.test.
1 2 3 4 5 6 7 8 9 10 | # 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. # #*********************************************************************** | < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # 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. # #*********************************************************************** # # Test the shell tool ".ar" command. # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix shell8 |
︙ | ︙ | |||
161 162 163 164 165 166 167 | # This is a repeat of test 1.$tn.1, except that there is a 2 second # pause between creating the archive and extracting its contents. # This is to test that timestamps are set correctly. # # Because it is slow, only do this for $tn==1. if {$tn==1} { | | | 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | # This is a repeat of test 1.$tn.1, except that there is a 2 second # pause between creating the archive and extracting its contents. # This is to test that timestamps are set correctly. # # Because it is slow, only do this for $tn==1. if {$tn==1} { do_test 1.$tn.1 { catchcmd test_ar.db $c1 file delete -force ar1 after 2000 catchcmd test_ar.db $x1 dir_to_list ar1 } $expected } |
︙ | ︙ | |||
190 191 192 193 194 195 196 | catchcmd shell8.db {.ar -C ar2 -i .} catchcmd shell8.db {.ar -r ./file2 ./dir1} catchcmd shell8.db {.ar -g -r ./ju*2} catchcmd shell8.db {.ar -C ar4 -x .} regsub -all {ar4} [dir_content ar4] ar2 } {ar2/file1 ar2/file2 ar2/junk1} | < < < < < < < < < < < < < < < < < < < < < < < < < | 189 190 191 192 193 194 195 196 | catchcmd shell8.db {.ar -C ar2 -i .} catchcmd shell8.db {.ar -r ./file2 ./dir1} catchcmd shell8.db {.ar -g -r ./ju*2} catchcmd shell8.db {.ar -C ar4 -x .} regsub -all {ar4} [dir_content ar4] ar2 } {ar2/file1 ar2/file2 ar2/junk1} finish_test |
Changes to test/shell9.test.
1 2 3 4 5 6 7 8 9 10 | # 2024 Jan 8 # # 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 | # 2024 Jan 8 # # 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. # #*********************************************************************** # # The focus of this file is testing the CLI shell tool. Specifically, # testing that it is possible to run a ".dump" script that creates # virtual tables without explicitly disabling defensive mode. # # And, that it can process a ".dump" script that contains strings # delimited using double-quotes in the schema (DQS_DDL setting). |
︙ | ︙ |
Changes to test/sqllimits1.test.
︙ | ︙ | |||
918 919 920 921 922 923 924 | CREATE TABLE b1(x); INSERT INTO b1 VALUES(1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11); } {0 {}} do_catchsql_test sqllimits1-18.2 { INSERT INTO b1 VALUES(1), (2), (3), (4), (5), (6), (7), (8), (9), (10) UNION VALUES(11); | | | 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 | CREATE TABLE b1(x); INSERT INTO b1 VALUES(1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11); } {0 {}} do_catchsql_test sqllimits1-18.2 { INSERT INTO b1 VALUES(1), (2), (3), (4), (5), (6), (7), (8), (9), (10) UNION VALUES(11); } {1 {too many terms in compound SELECT}} #------------------------------------------------------------------------- # reset_db ifcapable utf16 { do_execsql_test 19.0 { PRAGMA encoding = 'utf16'; |
︙ | ︙ |
Changes to test/subquery.test.
︙ | ︙ | |||
647 648 649 650 651 652 653 | # |--CO-ROUTINE v2 # | |--SCAN t2 # | `--USE TEMP B-TREE FOR GROUP BY # |--SCAN v2 # `--SEARCH t1 USING INDEX x12 (aa=?) # | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 647 648 649 650 651 652 653 654 655 | # |--CO-ROUTINE v2 # | |--SCAN t2 # | `--USE TEMP B-TREE FOR GROUP BY # |--SCAN v2 # `--SEARCH t1 USING INDEX x12 (aa=?) # finish_test |
Changes to test/tabfunc01.test.
︙ | ︙ | |||
318 319 320 321 322 323 324 | do_test tabfunc01-930 { catchsql { ALTER TABLE pragma_compile_options DROP COLUMN start; } } {1 {table pragma_compile_options may not be altered}} } | < < < < < < < < < < < < < < < < < < < < < < < < < < | 318 319 320 321 322 323 324 325 326 327 328 329 330 331 | do_test tabfunc01-930 { catchsql { ALTER TABLE pragma_compile_options DROP COLUMN start; } } {1 {table pragma_compile_options may not be altered}} } # Free up memory allocations intarray_addr int64array_addr doublearray_addr textarray_addr |
︙ | ︙ |
Changes to test/testrunner.tcl.
︙ | ︙ | |||
50 51 52 53 54 55 56 | proc usage {} { set a0 [file tail $::argv0] puts stderr [string trim [subst -nocommands { Usage: $a0 ?SWITCHES? ?PERMUTATION? ?PATTERNS? $a0 PERMUTATION FILE | < < | < | < | < < < | | < < < < | < | | < < < < < < < | 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 | proc usage {} { set a0 [file tail $::argv0] puts stderr [string trim [subst -nocommands { Usage: $a0 ?SWITCHES? ?PERMUTATION? ?PATTERNS? $a0 PERMUTATION FILE $a0 njob ?NJOB? $a0 status where SWITCHES are: --buildonly --dryrun --jobs NUMBER-OF-JOBS --zipvfs ZIPVFS-SOURCE-DIR Interesting values for PERMUTATION are: veryquick - a fast subset of the tcl test scripts. This is the default. full - all tcl test scripts. all - all tcl test scripts, plus a subset of test scripts rerun with various permutations. release - full release test with various builds. If no PATTERN arguments are present, all tests specified by the PERMUTATION are run. Otherwise, each pattern is interpreted as a glob pattern. Only those tcl tests for which the final component of the filename matches at least one specified pattern are run. If no PATTERN arguments are present, then various fuzztest, threadtest and other tests are run as part of the "release" permutation. These are omitted if any PATTERN arguments are specified on the command line. If a PERMUTATION is specified and is followed by the path to a Tcl script instead of a list of patterns, then that single Tcl test script is run with the specified permutation. The "status" and "njob" commands are designed to be run from the same directory as a running testrunner.tcl script that is running tests. The "status" command prints a report describing the current state and progress of the tests. The "njob" command may be used to query or modify the number of sub-processes the test script uses to run tests. }]] exit 1 } #------------------------------------------------------------------------- #------------------------------------------------------------------------- |
︙ | ︙ | |||
141 142 143 144 145 146 147 | } } } return $ret } proc default_njob {} { | < < < < | 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | } } } return $ret } proc default_njob {} { set nCore [guess_number_of_cores] if {$nCore<=2} { set nHelper 1 } else { set nHelper [expr int($nCore*0.5)] } return $nHelper |
︙ | ︙ | |||
170 171 172 173 174 175 176 | set TRG(nJob) [default_njob] ;# Default number of helper processes set TRG(patternlist) [list] set TRG(cmdline) $argv set TRG(reporttime) 2000 set TRG(fuzztest) 0 ;# is the fuzztest option present. set TRG(zipvfs) "" ;# -zipvfs option, if any set TRG(buildonly) 0 ;# True if --buildonly option | < < < < < < < | < | 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 | set TRG(nJob) [default_njob] ;# Default number of helper processes set TRG(patternlist) [list] set TRG(cmdline) $argv set TRG(reporttime) 2000 set TRG(fuzztest) 0 ;# is the fuzztest option present. set TRG(zipvfs) "" ;# -zipvfs option, if any set TRG(buildonly) 0 ;# True if --buildonly option set TRG(dryrun) 0 ;# True if --dryrun option switch -nocase -glob -- $tcl_platform(os) { *darwin* { set TRG(platform) osx set TRG(make) make.sh set TRG(makecmd) "bash make.sh" set TRG(testfixture) testfixture set TRG(run) run.sh set TRG(runcmd) "bash run.sh" } *linux* { set TRG(platform) linux set TRG(make) make.sh set TRG(makecmd) "bash make.sh" set TRG(testfixture) testfixture set TRG(run) run.sh set TRG(runcmd) "bash run.sh" } *win* { set TRG(platform) win set TRG(make) make.bat set TRG(makecmd) make.bat set TRG(testfixture) testfixture.exe set TRG(run) run.bat set TRG(runcmd) "run.bat" } default { error "cannot determine platform!" } } |
︙ | ︙ | |||
266 267 268 269 270 271 272 | cmd TEXT NOT NULL, -- shell command to run depid INTEGER, -- identifier of dependency (or '') priority INTEGER NOT NULL, -- higher priority jobs may run earlier /* Fields updated as jobs run */ starttime INTEGER, endtime INTEGER, | | | 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | cmd TEXT NOT NULL, -- shell command to run depid INTEGER, -- identifier of dependency (or '') priority INTEGER NOT NULL, -- higher priority jobs may run earlier /* Fields updated as jobs run */ starttime INTEGER, endtime INTEGER, state TEXT CHECK( state IN ('', 'ready', 'running', 'done', 'failed') ), output TEXT ); CREATE TABLE config( name TEXT COLLATE nocase PRIMARY KEY, value ) WITHOUT ROWID; |
︙ | ︙ | |||
353 354 355 356 357 358 359 | set res [mydb one { SELECT value FROM config WHERE name='njob' }] mydb close puts "$res" exit } #-------------------------------------------------------------------------- | < < < < < < < < | 322 323 324 325 326 327 328 329 330 331 332 333 334 335 | set res [mydb one { SELECT value FROM config WHERE name='njob' }] mydb close puts "$res" exit } #-------------------------------------------------------------------------- #-------------------------------------------------------------------------- # Check if this is the "script" command: # if {[string compare -nocase script [lindex $argv 0]]==0} { if {[llength $argv]!=2 && !([llength $argv]==3&&[lindex $argv 1]=="-msvc")} { usage } |
︙ | ︙ | |||
443 444 445 446 447 448 449 | if {$S(failed)>0} { puts "Failures: " mydb eval { SELECT * FROM jobs WHERE state='failed' ORDER BY starttime } job { display_job [array get job] } | < < < < | 404 405 406 407 408 409 410 411 412 413 414 415 416 417 | if {$S(failed)>0} { puts "Failures: " mydb eval { SELECT * FROM jobs WHERE state='failed' ORDER BY starttime } job { display_job [array get job] } } mydb close exit } #------------------------------------------------------------------------- |
︙ | ︙ | |||
472 473 474 475 476 477 478 | if {$isLast} { usage } } elseif {($n>2 && [string match "$a*" --zipvfs]) || $a=="-z"} { incr ii set TRG(zipvfs) [file normalize [lindex $argv $ii]] if {$isLast} { usage } } elseif {($n>2 && [string match "$a*" --buildonly]) || $a=="-b"} { set TRG(buildonly) 1 | < < < < < < < < < < < < > > | 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 | if {$isLast} { usage } } elseif {($n>2 && [string match "$a*" --zipvfs]) || $a=="-z"} { incr ii set TRG(zipvfs) [file normalize [lindex $argv $ii]] if {$isLast} { usage } } elseif {($n>2 && [string match "$a*" --buildonly]) || $a=="-b"} { set TRG(buildonly) 1 } elseif {($n>2 && [string match "$a*" --dryrun]) || $a=="-d"} { set TRG(dryrun) 1 } else { usage } } else { lappend TRG(patternlist) [string map {% *} $a] } } set argv [list] # This script runs individual tests - tcl scripts or [make xyz] commands - # in directories named "testdir$N", where $N is an integer. This variable # contains a list of integers indicating the directories in use. # # This variable is accessed only via the following commands: # |
︙ | ︙ | |||
666 667 668 669 670 671 672 | $state ) } trdb last_insert_rowid } | < < < < < < < < < | | 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 | $state ) } trdb last_insert_rowid } proc add_tcl_jobs {build config patternlist} { global TRG set topdir [file dirname $::testdir] set testrunner_tcl [file normalize [info script]] if {$build==""} { set testfixture [info nameofexec] |
︙ | ︙ | |||
724 725 726 727 728 729 730 | } set lProp [trd_test_script_properties $f] set priority 0 if {[lsearch $lProp slow]>=0} { set priority 2 } if {[lsearch $lProp superslow]>=0} { set priority 4 } | < < < | > | < < < < < < | < < < < < < < < < < < < < < < < < | 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 | } set lProp [trd_test_script_properties $f] set priority 0 if {[lsearch $lProp slow]>=0} { set priority 2 } if {[lsearch $lProp superslow]>=0} { set priority 4 } add_job \ -displaytype tcl \ -displayname $displayname \ -cmd $cmd \ -depid [lindex $build 0] \ -priority $priority } } proc add_build_job {buildname target} { global TRG set dirname "[string tolower [string map {- _} $buildname]]_$target" set dirname "testrunner_bld_$dirname" set id [add_job \ -displaytype bld \ -displayname "Build $buildname ($target)" \ -dirname $dirname \ -build $buildname \ -cmd "$TRG(makecmd) $target" \ -priority 3 ] list $id [file normalize $dirname] $buildname } proc add_make_job {bld target} { global TRG if {$TRG(platform)=="win"} { set path [string map {/ \\} [lindex $bld 1]] set cmd "xcopy /S $path\\* ." |
︙ | ︙ | |||
850 851 852 853 854 855 856 | # Used to add jobs for "mdevtest" and "sdevtest". # proc add_devtest_jobs {lBld patternlist} { global TRG foreach b $lBld { set bld [add_build_job $b $TRG(testfixture)] | | < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < | < < < < < < < < < < | 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 | # Used to add jobs for "mdevtest" and "sdevtest". # proc add_devtest_jobs {lBld patternlist} { global TRG foreach b $lBld { set bld [add_build_job $b $TRG(testfixture)] add_tcl_jobs $bld veryquick $patternlist if {$patternlist==""} { add_fuzztest_jobs $b } } } proc add_jobs_from_cmdline {patternlist} { global TRG if {$TRG(zipvfs)!=""} { add_zipvfs_jobs if {[llength $patternlist]==0} return } if {[llength $patternlist]==0} { set patternlist [list veryquick] } set first [lindex $patternlist 0] switch -- $first { all { set patternlist [lrange $patternlist 1 end] set clist [trd_all_configs] foreach c $clist { add_tcl_jobs "" $c $patternlist } } mdevtest { add_devtest_jobs {All-O0 All-Debug} [lrange $patternlist 1 end] } sdevtest { add_devtest_jobs {All-Sanitize All-Debug} [lrange $patternlist 1 end] } release { set patternlist [lrange $patternlist 1 end] foreach b [trd_builds $TRG(platform)] { set bld [add_build_job $b $TRG(testfixture)] foreach c [trd_configs $TRG(platform) $b] { add_tcl_jobs $bld $c $patternlist } if {$patternlist==""} { foreach e [trd_extras $TRG(platform) $b] { if {$e=="fuzztest"} { add_fuzztest_jobs $b } else { add_make_job $bld $e } } } } } default { if {[info exists ::testspec($first)]} { add_tcl_jobs "" $first [lrange $patternlist 1 end] } else { add_tcl_jobs "" full $patternlist } } } |
︙ | ︙ | |||
975 976 977 978 979 980 981 | add_jobs_from_cmdline $TRG(patternlist) } } proc mark_job_as_finished {jobid output state endtm} { r_write_db { | < < < < < | | 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 | add_jobs_from_cmdline $TRG(patternlist) } } proc mark_job_as_finished {jobid output state endtm} { r_write_db { trdb eval { UPDATE jobs SET output=$output, state=$state, endtime=$endtm WHERE jobid=$jobid; UPDATE jobs SET state='ready' WHERE depid=$jobid; } } } proc script_input_ready {fd iJob jobid} { global TRG global O |
︙ | ︙ | |||
1015 1016 1017 1018 1019 1020 1021 | set rc [catch { close $fd } msg] if {$rc} { if {[info exists TRG(reportlength)]} { puts -nonewline "[string repeat " " $TRG(reportlength)]\r" } puts "FAILED: $job(displayname) ($iJob)" set state "failed" | < < < < < < < < | 884 885 886 887 888 889 890 891 892 893 894 895 896 897 | set rc [catch { close $fd } msg] if {$rc} { if {[info exists TRG(reportlength)]} { puts -nonewline "[string repeat " " $TRG(reportlength)]\r" } puts "FAILED: $job(displayname) ($iJob)" set state "failed" } set tm [clock_milliseconds] set jobtm [expr {$tm - $job(starttime)}] puts $TRG(log) "### $job(displayname) ${jobtm}ms ($state)" puts $TRG(log) [string trim $O($iJob)] |
︙ | ︙ | |||
1083 1084 1085 1086 1087 1088 1089 | set script [trd_buildscript $job(build) $srcdir $bWin] } set fd [open [file join $dir $TRG(make)] w] puts $fd $script close $fd } | < < < < < < < < < < < | | 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 | set script [trd_buildscript $job(build) $srcdir $bWin] } set fd [open [file join $dir $TRG(make)] w] puts $fd $script close $fd } if { $TRG(dryrun) } { mark_job_as_finished $job(jobid) "" done 0 dirs_freeDir $iJob if {$job(build)!=""} { puts $TRG(log) "(cd $dir ; $job(cmd) )" } else { puts $TRG(log) "$job(cmd)" } } else { set pwd [pwd] cd $dir set fd [open $TRG(run) w] puts $fd $job(cmd) close $fd set fd [open "|$TRG(runcmd) 2>@1" r] cd $pwd fconfigure $fd -blocking false fileevent $fd readable [list script_input_ready $fd $iJob $job(jobid)] } |
︙ | ︙ | |||
1207 1208 1209 1210 1211 1212 1213 | puts "$nErr failures:" trdb eval { SELECT displayname FROM jobs WHERE state='failed' } { puts "FAILED: $displayname" } } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | > | | < > | 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 | puts "$nErr failures:" trdb eval { SELECT displayname FROM jobs WHERE state='failed' } { puts "FAILED: $displayname" } } } puts "\nTest database is $TRG(dbname)" puts "Test log is $TRG(logname)" } # Handle the --buildonly option, if it was specified. # proc handle_buildonly {} { global TRG if {$TRG(buildonly)} { r_write_db { trdb eval { DELETE FROM jobs WHERE displaytype!='bld' } } } } sqlite3 trdb $TRG(dbname) trdb timeout $TRG(timeout) set tm [lindex [time { make_new_testset }] 0] if {$TRG(nJob)>1} { puts "splitting work across $TRG(nJob) jobs" } puts "built testset in [expr $tm/1000]ms.." handle_buildonly run_testset trdb close #puts [pwd] |
Changes to test/testrunner_data.tcl.
︙ | ︙ | |||
19 20 21 22 23 24 25 | set tcltest(linux.User-Auth) veryquick set tcltest(linux.Update-Delete-Limit) veryquick set tcltest(linux.Extra-Robustness) veryquick set tcltest(linux.Device-Two) veryquick set tcltest(linux.No-lookaside) veryquick set tcltest(linux.Devkit) veryquick set tcltest(linux.Apple) veryquick | < | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | set tcltest(linux.User-Auth) veryquick set tcltest(linux.Update-Delete-Limit) veryquick set tcltest(linux.Extra-Robustness) veryquick set tcltest(linux.Device-Two) veryquick set tcltest(linux.No-lookaside) veryquick set tcltest(linux.Devkit) veryquick set tcltest(linux.Apple) veryquick set tcltest(linux.Sanitize) veryquick set tcltest(linux.Device-One) all set tcltest(linux.Default) all_plus_autovacuum_crash set tcltest(linux.Valgrind) valgrind set tcltest(osx.Locking-Style) veryquick set tcltest(osx.Have-Not) veryquick |
︙ | ︙ | |||
50 51 52 53 54 55 56 | set extra(linux.Secure-Delete) {fuzztest sourcetest} set extra(linux.Unlock-Notify) {fuzztest sourcetest} set extra(linux.Update-Delete-Limit) {fuzztest sourcetest} set extra(linux.Extra-Robustness) {fuzztest sourcetest} set extra(linux.Device-Two) {fuzztest sourcetest threadtest} set extra(linux.No-lookaside) {fuzztest sourcetest} set extra(linux.Devkit) {fuzztest sourcetest} | < | 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | set extra(linux.Secure-Delete) {fuzztest sourcetest} set extra(linux.Unlock-Notify) {fuzztest sourcetest} set extra(linux.Update-Delete-Limit) {fuzztest sourcetest} set extra(linux.Extra-Robustness) {fuzztest sourcetest} set extra(linux.Device-Two) {fuzztest sourcetest threadtest} set extra(linux.No-lookaside) {fuzztest sourcetest} set extra(linux.Devkit) {fuzztest sourcetest} set extra(linux.Apple) {fuzztest sourcetest} set extra(linux.Sanitize) {fuzztest sourcetest} set extra(linux.Default) {fuzztest sourcetest threadtest} set extra(osx.Apple) {fuzztest threadtest} set extra(osx.Have-Not) {fuzztest sourcetest} set extra(osx.Locking-Style) {mptest fuzztest sourcetest} |
︙ | ︙ | |||
106 107 108 109 110 111 112 | } set build(Sanitize) { CC=clang -fsanitize=address,undefined -fno-sanitize-recover=undefined -DSQLITE_ENABLE_STAT4 -DSQLITE_OMIT_LOOKASIDE=1 -DCONFIG_SLOWDOWN_FACTOR=5.0 | < | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | } set build(Sanitize) { CC=clang -fsanitize=address,undefined -fno-sanitize-recover=undefined -DSQLITE_ENABLE_STAT4 -DSQLITE_OMIT_LOOKASIDE=1 -DCONFIG_SLOWDOWN_FACTOR=5.0 --enable-debug --enable-all } set build(Stdcall) { -DUSE_STDCALL=1 -O2 } |
︙ | ︙ | |||
244 245 246 247 248 249 250 | -DSQLITE_THREADSAFE=2 --enable-fts5 --enable-session } set build(Locking-Style) { -O2 -DSQLITE_ENABLE_LOCKING_STYLE=1 } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 241 242 243 244 245 246 247 248 249 250 251 252 253 254 | -DSQLITE_THREADSAFE=2 --enable-fts5 --enable-session } set build(Locking-Style) { -O2 -DSQLITE_ENABLE_LOCKING_STYLE=1 } set build(Apple) { -Os -DHAVE_GMTIME_R=1 -DHAVE_ISNAN=1 -DHAVE_LOCALTIME_R=1 -DHAVE_PREAD=1 -DHAVE_PWRITE=1 |
︙ | ︙ | |||
631 632 633 634 635 636 637 | # use the MSVC compiler, false otherwise. # proc trd_buildscript {config srcdir bMsvc} { trd_import # Ensure that the named configuration exists. if {![info exists build($config)]} { | < | < < < < | 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 | # use the MSVC compiler, false otherwise. # proc trd_buildscript {config srcdir bMsvc} { trd_import # Ensure that the named configuration exists. if {![info exists build($config)]} { error "No such build config: $config" } # Generate and return the script. return [make_script $build($config) $srcdir $bMsvc] } # Usage: |
︙ | ︙ | |||
675 676 677 678 679 680 681 | } set trd_test_script_properties_cache($path) $ret close $fd } set trd_test_script_properties_cache($path) } | > | 633 634 635 636 637 638 639 640 | } set trd_test_script_properties_cache($path) $ret close $fd } set trd_test_script_properties_cache($path) } |
Changes to test/trigger9.test.
︙ | ︙ | |||
238 239 240 241 242 243 244 | END; CREATE TRIGGER tr3 INSTEAD OF INSERT ON v1 BEGIN INSERT INTO log VALUES('insert'); END; } | < | | | | | | < < < < < < < < < < < < < < | 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | END; CREATE TRIGGER tr3 INSTEAD OF INSERT ON v1 BEGIN INSERT INTO log VALUES('insert'); END; } do_catchsql_test 4.2 { DELETE FROM v1 WHERE rowid=1; } {1 {no such column: rowid}} do_catchsql_test 4.3 { UPDATE v1 SET a=b WHERE rowid=2; } {1 {no such column: rowid}} finish_test |
Changes to test/unionall.test.
︙ | ︙ | |||
347 348 349 350 351 352 353 | SELECT *, '+' FROM t1 LEFT JOIN t3 ON (a NOT IN(SELECT v FROM t1 LEFT JOIN t2 ON (a=k))=k); } {0 {} {} {} + 1 one {} {} + 2 two {} {} + 5 five {} {} + 3 three {} {} + 6 six {} {} +} ifcapable vtab { do_catchsql_test 5.30 { SELECT * FROM (t1 NATURAL JOIN pragma_table_xinfo('t1_a') NATURAL JOIN t3) t1 NATURAL JOIN t2 NATURAL JOIN t3 WHERE rowid ISNULL>0 AND 0%y; | | | 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 | SELECT *, '+' FROM t1 LEFT JOIN t3 ON (a NOT IN(SELECT v FROM t1 LEFT JOIN t2 ON (a=k))=k); } {0 {} {} {} + 1 one {} {} + 2 two {} {} + 5 five {} {} + 3 three {} {} + 6 six {} {} +} ifcapable vtab { do_catchsql_test 5.30 { SELECT * FROM (t1 NATURAL JOIN pragma_table_xinfo('t1_a') NATURAL JOIN t3) t1 NATURAL JOIN t2 NATURAL JOIN t3 WHERE rowid ISNULL>0 AND 0%y; } {1 {no such column: rowid}} } reset_db do_execsql_test 6.0 { CREATE TABLE t1(a,b); INSERT INTO t1 VALUES(1,2); CREATE TABLE t2(a,b); |
︙ | ︙ |
Changes to test/upsert1.test.
︙ | ︙ | |||
264 265 266 267 268 269 270 | CREATE UNIQUE INDEX t1x ON t1(b+3); } sqlite3_db_config db ENABLE_QPSG 1 do_catchsql_test upsert1-1210 { INSERT INTO t1(a,b) VALUES(1,2) ON CONFLICT(b+?1) DO NOTHING; } {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}} | < < < < < < < < < < < < < < < < < < < < < < < < | 264 265 266 267 268 269 270 271 | CREATE UNIQUE INDEX t1x ON t1(b+3); } sqlite3_db_config db ENABLE_QPSG 1 do_catchsql_test upsert1-1210 { INSERT INTO t1(a,b) VALUES(1,2) ON CONFLICT(b+?1) DO NOTHING; } {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}} finish_test |
Changes to test/upsert5.test.
︙ | ︙ | |||
404 405 406 407 408 409 410 | do_catchsql_test 2.1 { INSERT INTO t2(a,b,c,e,d) VALUES(1,2,3,4,5) ON CONFLICT(c) DO UPDATE SET b='' ON CONFLICT((SELECT t2 FROM nosuchtable)) DO NOTHING; } {1 {no such table: nosuchtable}} | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 404 405 406 407 408 409 410 411 | do_catchsql_test 2.1 { INSERT INTO t2(a,b,c,e,d) VALUES(1,2,3,4,5) ON CONFLICT(c) DO UPDATE SET b='' ON CONFLICT((SELECT t2 FROM nosuchtable)) DO NOTHING; } {1 {no such table: nosuchtable}} finish_test |
Changes to test/vacuum-into.test.
︙ | ︙ | |||
22 23 24 25 26 27 28 | omit_test vacuum.test {Compiled with SQLITE_OMIT_VACUUM} finish_test return } forcedelete out.db do_execsql_test vacuum-into-100 { | | < < < < < < < < < < < < < < < < < < < < < < < | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | omit_test vacuum.test {Compiled with SQLITE_OMIT_VACUUM} finish_test return } forcedelete out.db do_execsql_test vacuum-into-100 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b); WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100) INSERT INTO t1(a,b) SELECT x, randomblob(600) FROM c; CREATE INDEX t1b ON t1(b); DELETE FROM t1 WHERE a%2; SELECT count(*), sum(a), sum(length(b)) FROM t1; } {50 2550 30000} do_execsql_test vacuum-into-110 { VACUUM main INTO 'out.db'; } {} sqlite3 db2 out.db do_test vacuum-into-120 { db2 eval {SELECT count(*), sum(a), sum(length(b)) FROM t1} } {50 2550 30000} |
︙ | ︙ | |||
107 108 109 110 111 112 113 | } 1 do_catchsql_test vacuum-into-420 { VACUUM INTO target2() } {1 {no such function: target2}} # The ability to VACUUM INTO a read-only database db close | < < < < < < < < < < | 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | } 1 do_catchsql_test vacuum-into-420 { VACUUM INTO target2() } {1 {no such function: target2}} # The ability to VACUUM INTO a read-only database db close sqlite3 db test.db -readonly 1 forcedelete test.db2 do_execsql_test vacuum-into-500 { VACUUM INTO 'test.db2'; } sqlite3 db2 test.db2 do_test vacuum-into-510 { db2 eval {SELECT name FROM sqlite_master ORDER BY 1} } {t1 t1b t2} db2 close db close |
︙ | ︙ |
Deleted test/values.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted test/valuesfault.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to test/view.test.
︙ | ︙ | |||
796 797 798 799 800 801 802 | do_execsql_test view-30.1 { PRAGMA table_info = t1; } { 0 a INT 0 {} 0 1 b BLOB 0 {} 0 } do_execsql_test view-30.2 { PRAGMA table_info = t2; } { 0 a INT 0 {} 0 1 b BLOB 0 {} 0 } } | < < < < < < < < < < < < < < < < < < < < < < < | 796 797 798 799 800 801 802 803 804 | do_execsql_test view-30.1 { PRAGMA table_info = t1; } { 0 a INT 0 {} 0 1 b BLOB 0 {} 0 } do_execsql_test view-30.2 { PRAGMA table_info = t2; } { 0 a INT 0 {} 0 1 b BLOB 0 {} 0 } } finish_test |
Deleted test/vtabL.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to test/whereL.test.
︙ | ︙ | |||
45 46 47 48 49 50 51 | ORDER BY t1.a; } { QUERY PLAN |--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (a=?) |--SEARCH t2 USING INDEX sqlite_autoindex_t2_1 (a=?) `--SCAN t3 } | < < < < < < < < < < < < < < < < < < < < < < < < < < < | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | ORDER BY t1.a; } { QUERY PLAN |--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (a=?) |--SEARCH t2 USING INDEX sqlite_autoindex_t2_1 (a=?) `--SCAN t3 } # Constant propagation in the face of collating sequences: # do_execsql_test 200 { CREATE TABLE c3(x COLLATE binary, y COLLATE nocase, z COLLATE binary); CREATE INDEX c3x ON c3(x); INSERT INTO c3 VALUES('ABC', 'ABC', 'abc'); |
︙ | ︙ | |||
232 233 234 235 236 237 238 | do_eqp_test 710 { SELECT v FROM t1 WHERE abs(v)=1 and v=1; } { QUERY PLAN `--SEARCH t1 USING INDEX idx (<expr>=?) } | < < < < < < < < < < < < < < < < < < | 205 206 207 208 209 210 211 212 | do_eqp_test 710 { SELECT v FROM t1 WHERE abs(v)=1 and v=1; } { QUERY PLAN `--SEARCH t1 USING INDEX idx (<expr>=?) } finish_test |
Deleted test/whereN.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to test/window1.test.
︙ | ︙ | |||
2371 2372 2373 2374 2375 2376 2377 | CREATE INDEX t1x ON t1(likely(x)); INSERT INTO t1 VALUES(1),(2),(4),(8); } do_execsql_test 77.2 { SELECT max(~likely(x)) FILTER (WHERE true) FROM t1 INDEXED BY t1x GROUP BY x; } {-2 -3 -5 -9} | < < < < < < < < < < < < < < < < < < | 2371 2372 2373 2374 2375 2376 2377 2378 2379 | CREATE INDEX t1x ON t1(likely(x)); INSERT INTO t1 VALUES(1),(2),(4),(8); } do_execsql_test 77.2 { SELECT max(~likely(x)) FILTER (WHERE true) FROM t1 INDEXED BY t1x GROUP BY x; } {-2 -3 -5 -9} finish_test |
Changes to tool/lemon.c.
︙ | ︙ | |||
55 56 57 58 59 60 61 | /* ** Compilers are getting increasingly pedantic about type conversions ** as C evolves ever closer to Ada.... To work around the latest problems ** we have to define the following variant of strlen(). */ #define lemonStrlen(X) ((int)strlen(X)) | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | /* ** Compilers are getting increasingly pedantic about type conversions ** as C evolves ever closer to Ada.... To work around the latest problems ** we have to define the following variant of strlen(). */ #define lemonStrlen(X) ((int)strlen(X)) /* ** Compilers are starting to complain about the use of sprintf() and strcpy(), ** saying they are unsafe. So we define our own versions of those routines too. ** ** There are three routines here: lemon_sprintf(), lemon_vsprintf(), and ** lemon_addtext(). The first two are replacements for sprintf() and vsprintf(). ** The third is a helper routine for vsnprintf() that adds texts to the end of a |
︙ | ︙ | |||
569 570 571 572 573 574 575 | static struct action *Action_new(void){ static struct action *actionfreelist = 0; struct action *newaction; if( actionfreelist==0 ){ int i; int amt = 100; | | | 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 | static struct action *Action_new(void){ static struct action *actionfreelist = 0; struct action *newaction; if( actionfreelist==0 ){ int i; int amt = 100; actionfreelist = (struct action *)calloc(amt, sizeof(struct action)); if( actionfreelist==0 ){ fprintf(stderr,"Unable to allocate memory for a new parser action."); exit(1); } for(i=0; i<amt-1; i++) actionfreelist[i].next = &actionfreelist[i+1]; actionfreelist[amt-1].next = 0; } |
︙ | ︙ | |||
688 689 690 691 692 693 694 | #define acttab_yyaction(X,N) ((X)->aAction[N].action) /* The value for the N-th entry in yy_lookahead */ #define acttab_yylookahead(X,N) ((X)->aAction[N].lookahead) /* Free all memory associated with the given acttab */ void acttab_free(acttab *p){ | | | | | | | 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 | #define acttab_yyaction(X,N) ((X)->aAction[N].action) /* The value for the N-th entry in yy_lookahead */ #define acttab_yylookahead(X,N) ((X)->aAction[N].lookahead) /* Free all memory associated with the given acttab */ void acttab_free(acttab *p){ free( p->aAction ); free( p->aLookahead ); free( p ); } /* Allocate a new acttab structure */ acttab *acttab_alloc(int nsymbol, int nterminal){ acttab *p = (acttab *) calloc( 1, sizeof(*p) ); if( p==0 ){ fprintf(stderr,"Unable to allocate memory for a new acttab."); exit(1); } memset(p, 0, sizeof(*p)); p->nsymbol = nsymbol; p->nterminal = nterminal; return p; } /* Add a new action to the current transaction set. ** ** This routine is called once for each lookahead for a particular ** state. */ void acttab_action(acttab *p, int lookahead, int action){ if( p->nLookahead>=p->nLookaheadAlloc ){ p->nLookaheadAlloc += 25; p->aLookahead = (struct lookahead_action *) realloc( p->aLookahead, sizeof(p->aLookahead[0])*p->nLookaheadAlloc ); if( p->aLookahead==0 ){ fprintf(stderr,"malloc failed\n"); exit(1); } } if( p->nLookahead==0 ){ |
︙ | ︙ | |||
764 765 766 767 768 769 770 | ** in the worst case. The worst case occurs if the transaction set ** must be appended to the current action table */ n = p->nsymbol + 1; if( p->nAction + n >= p->nActionAlloc ){ int oldAlloc = p->nActionAlloc; p->nActionAlloc = p->nAction + n + p->nActionAlloc + 20; | | | 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 | ** in the worst case. The worst case occurs if the transaction set ** must be appended to the current action table */ n = p->nsymbol + 1; if( p->nAction + n >= p->nActionAlloc ){ int oldAlloc = p->nActionAlloc; p->nActionAlloc = p->nAction + n + p->nActionAlloc + 20; p->aAction = (struct lookahead_action *) realloc( p->aAction, sizeof(p->aAction[0])*p->nActionAlloc); if( p->aAction==0 ){ fprintf(stderr,"malloc failed\n"); exit(1); } for(i=oldAlloc; i<p->nActionAlloc; i++){ p->aAction[i].lookahead = -1; |
︙ | ︙ | |||
1386 1387 1388 1389 1390 1391 1392 | static struct config *current = 0; /* Top of list of configurations */ static struct config **currentend = 0; /* Last on list of configs */ static struct config *basis = 0; /* Top of list of basis configs */ static struct config **basisend = 0; /* End of list of basis configs */ /* Return a pointer to a new configuration */ PRIVATE struct config *newconfig(void){ | | | 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 | static struct config *current = 0; /* Top of list of configurations */ static struct config **currentend = 0; /* Last on list of configs */ static struct config *basis = 0; /* Top of list of basis configs */ static struct config **basisend = 0; /* End of list of basis configs */ /* Return a pointer to a new configuration */ PRIVATE struct config *newconfig(void){ return (struct config*)calloc(1, sizeof(struct config)); } /* The configuration "old" is no longer used */ PRIVATE void deleteconfig(struct config *old) { old->next = freelist; freelist = old; |
︙ | ︙ | |||
1602 1603 1604 1605 1606 1607 1608 | /* This routine is called with the argument to each -D command-line option. ** Add the macro defined to the azDefine array. */ static void handle_D_option(char *z){ char **paz; nDefine++; | | | | | | | 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 | /* This routine is called with the argument to each -D command-line option. ** Add the macro defined to the azDefine array. */ static void handle_D_option(char *z){ char **paz; nDefine++; azDefine = (char **) realloc(azDefine, sizeof(azDefine[0])*nDefine); if( azDefine==0 ){ fprintf(stderr,"out of memory\n"); exit(1); } bDefineUsed = (char*)realloc(bDefineUsed, nDefine); if( bDefineUsed==0 ){ fprintf(stderr,"out of memory\n"); exit(1); } bDefineUsed[nDefine-1] = 0; paz = &azDefine[nDefine-1]; *paz = (char *) malloc( lemonStrlen(z)+1 ); if( *paz==0 ){ 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(); } lemon_strcpy(user_templatename, z); } /* Merge together to lists of rules ordered by rule.iRule */ |
︙ | ︙ | |||
1875 1876 1877 1878 1879 1880 1881 | } if( lem.nconflict > 0 ){ fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict); } /* return 0 on success, 1 on failure. */ exitcode = ((lem.errorcnt > 0) || (lem.nconflict > 0)) ? 1 : 0; | < | 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 | } if( lem.nconflict > 0 ){ fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict); } /* return 0 on success, 1 on failure. */ exitcode = ((lem.errorcnt > 0) || (lem.nconflict > 0)) ? 1 : 0; exit(exitcode); return (exitcode); } /******************** From the file "msort.c" *******************************/ /* ** A generic merge-sort program. ** |
︙ | ︙ | |||
2464 2465 2466 2467 2468 2469 2470 | psp->errorcnt++; psp->state = RESYNC_AFTER_RULE_ERROR; } break; case IN_RHS: if( x[0]=='.' ){ struct rule *rp; | | | 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 | psp->errorcnt++; psp->state = RESYNC_AFTER_RULE_ERROR; } break; case IN_RHS: if( x[0]=='.' ){ struct rule *rp; rp = (struct rule *)calloc( sizeof(struct rule) + sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs, 1); if( rp==0 ){ ErrorMsg(psp->filename,psp->tokenlineno, "Can't allocate enough memory for this rule."); psp->errorcnt++; psp->prevrule = 0; }else{ |
︙ | ︙ | |||
2516 2517 2518 2519 2520 2521 2522 | psp->alias[psp->nrhs] = 0; psp->nrhs++; } }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 && ISUPPER(x[1]) ){ struct symbol *msp = psp->rhs[psp->nrhs-1]; if( msp->type!=MULTITERMINAL ){ struct symbol *origsp = msp; | | | | | 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 | psp->alias[psp->nrhs] = 0; psp->nrhs++; } }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 && ISUPPER(x[1]) ){ struct symbol *msp = psp->rhs[psp->nrhs-1]; if( msp->type!=MULTITERMINAL ){ struct symbol *origsp = msp; msp = (struct symbol *) calloc(1,sizeof(*msp)); memset(msp, 0, sizeof(*msp)); msp->type = MULTITERMINAL; msp->nsubsym = 1; msp->subsym = (struct symbol **) calloc(1,sizeof(struct symbol*)); msp->subsym[0] = origsp; msp->name = origsp->name; psp->rhs[psp->nrhs-1] = msp; } msp->nsubsym++; msp->subsym = (struct symbol **) realloc(msp->subsym, sizeof(struct symbol*)*msp->nsubsym); msp->subsym[msp->nsubsym-1] = Symbol_new(&x[1]); if( ISLOWER(x[1]) || ISLOWER(msp->subsym[0]->name[0]) ){ ErrorMsg(psp->filename,psp->tokenlineno, "Cannot form a compound containing a non-terminal"); psp->errorcnt++; } |
︙ | ︙ | |||
2742 2743 2744 2745 2746 2747 2748 | for(z=psp->filename, nBack=0; *z; z++){ if( *z=='\\' ) nBack++; } lemon_sprintf(zLine, "#line %d ", psp->tokenlineno); nLine = lemonStrlen(zLine); n += nLine + lemonStrlen(psp->filename) + nBack; } | | | 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 | for(z=psp->filename, nBack=0; *z; z++){ if( *z=='\\' ) nBack++; } lemon_sprintf(zLine, "#line %d ", psp->tokenlineno); nLine = lemonStrlen(zLine); n += nLine + lemonStrlen(psp->filename) + nBack; } *psp->declargslot = (char *) realloc(*psp->declargslot, n); zBuf = *psp->declargslot + nOld; if( addLineMacro ){ if( nOld && zBuf[-1]!='\n' ){ *(zBuf++) = '\n'; } memcpy(zBuf, zLine, nLine); zBuf += nLine; |
︙ | ︙ | |||
2856 2857 2858 2859 2860 2861 2862 | break; case WAITING_FOR_CLASS_TOKEN: if( x[0]=='.' ){ psp->state = WAITING_FOR_DECL_OR_RULE; }else if( ISUPPER(x[0]) || ((x[0]=='|' || x[0]=='/') && ISUPPER(x[1])) ){ struct symbol *msp = psp->tkclass; msp->nsubsym++; | | | 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 | break; case WAITING_FOR_CLASS_TOKEN: if( x[0]=='.' ){ psp->state = WAITING_FOR_DECL_OR_RULE; }else if( ISUPPER(x[0]) || ((x[0]=='|' || x[0]=='/') && ISUPPER(x[1])) ){ struct symbol *msp = psp->tkclass; msp->nsubsym++; msp->subsym = (struct symbol **) realloc(msp->subsym, sizeof(struct symbol*)*msp->nsubsym); if( !ISUPPER(x[0]) ) x++; msp->subsym[msp->nsubsym-1] = Symbol_new(x); }else{ ErrorMsg(psp->filename, psp->tokenlineno, "%%token_class argument \"%s\" should be a token", x); psp->errorcnt++; |
︙ | ︙ | |||
3071 3072 3073 3074 3075 3076 3077 | ErrorMsg(ps.filename,0,"Can't open this file for reading."); gp->errorcnt++; return; } fseek(fp,0,2); filesize = ftell(fp); rewind(fp); | | | | | 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 | ErrorMsg(ps.filename,0,"Can't open this file for reading."); gp->errorcnt++; return; } fseek(fp,0,2); filesize = ftell(fp); rewind(fp); filebuf = (char *)malloc( filesize+1 ); if( filesize>100000000 || filebuf==0 ){ ErrorMsg(ps.filename,0,"Input file too large."); free(filebuf); gp->errorcnt++; fclose(fp); return; } if( fread(filebuf,1,filesize,fp)!=filesize ){ ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.", filesize); free(filebuf); gp->errorcnt++; fclose(fp); return; } fclose(fp); filebuf[filesize] = 0; |
︙ | ︙ | |||
3194 3195 3196 3197 3198 3199 3200 | } c = *cp; *cp = 0; /* Null terminate the token */ parseonetoken(&ps); /* Parse the token */ *cp = (char)c; /* Restore the buffer */ cp = nextcp; } | | | | 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 | } c = *cp; *cp = 0; /* Null terminate the token */ parseonetoken(&ps); /* Parse the token */ *cp = (char)c; /* Restore the buffer */ cp = nextcp; } free(filebuf); /* Release the buffer after parsing */ gp->rule = ps.firstrule; gp->errorcnt = ps.errorcnt; } /*************************** From the file "plink.c" *********************/ /* ** Routines processing configuration follow-set propagation links ** in the LEMON parser generator. */ static struct plink *plink_freelist = 0; /* Allocate a new plink */ struct plink *Plink_new(void){ struct plink *newlink; if( plink_freelist==0 ){ int i; int amt = 100; plink_freelist = (struct plink *)calloc( amt, sizeof(struct plink) ); if( plink_freelist==0 ){ fprintf(stderr, "Unable to allocate memory for a new follow-set propagation link.\n"); exit(1); } for(i=0; i<amt-1; i++) plink_freelist[i].next = &plink_freelist[i+1]; plink_freelist[amt-1].next = 0; |
︙ | ︙ | |||
3265 3266 3267 3268 3269 3270 3271 | } } /*********************** From the file "report.c" **************************/ /* ** Procedures for generating reports and tables in the LEMON parser generator. */ | | > > | | 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 | } } /*********************** From the file "report.c" **************************/ /* ** Procedures for generating reports and tables in the LEMON parser generator. */ /* Generate a filename with the given suffix. Space to hold the ** 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); |
︙ | ︙ | |||
3309 3310 3311 3312 3313 3314 3315 | PRIVATE FILE *file_open( struct lemon *lemp, const char *suffix, const char *mode ){ FILE *fp; | | | 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 | PRIVATE FILE *file_open( struct lemon *lemp, const char *suffix, const char *mode ){ FILE *fp; if( lemp->outname ) free(lemp->outname); lemp->outname = file_makename(lemp, suffix); fp = fopen(lemp->outname,mode); if( fp==0 && *mode=='w' ){ fprintf(stderr,"Can't open file \"%s\".\n",lemp->outname); lemp->errorcnt++; return 0; } |
︙ | ︙ | |||
3625 3626 3627 3628 3629 3630 3631 | cp = strrchr(argv0,'\\'); #else cp = strrchr(argv0,'/'); #endif if( cp ){ c = *cp; *cp = 0; | | | | | | 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 | cp = strrchr(argv0,'\\'); #else cp = strrchr(argv0,'/'); #endif if( cp ){ c = *cp; *cp = 0; path = (char *)malloc( lemonStrlen(argv0) + lemonStrlen(name) + 2 ); if( path ) lemon_sprintf(path,"%s/%s",argv0,name); *cp = c; }else{ pathlist = getenv("PATH"); if( pathlist==0 ) pathlist = ".:/bin:/usr/bin"; pathbuf = (char *) malloc( lemonStrlen(pathlist) + 1 ); path = (char *)malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 ); if( (pathbuf != 0) && (path!=0) ){ pathbufptr = pathbuf; lemon_strcpy(pathbuf, pathlist); while( *pathbuf ){ cp = strchr(pathbuf,':'); if( cp==0 ) cp = &pathbuf[lemonStrlen(pathbuf)]; c = *cp; *cp = 0; lemon_sprintf(path,"%s/%s",pathbuf,name); *cp = c; if( c==0 ) pathbuf[0] = 0; else pathbuf = &cp[1]; if( access(path,modemask)==0 ) break; } } free(pathbufptr); } return path; } /* Given an action, compute the integer value for that action ** which is to be put in the action table of the generated machine. ** Return negative if no action should be generated. |
︙ | ︙ | |||
3779 3780 3781 3782 3783 3784 3785 | return 0; } in = fopen(tpltname,"rb"); if( in==0 ){ fprintf(stderr,"Can't open the template file \"%s\".\n",tpltname); lemp->errorcnt++; } | | | 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 | return 0; } in = fopen(tpltname,"rb"); if( in==0 ){ fprintf(stderr,"Can't open the template file \"%s\".\n",tpltname); lemp->errorcnt++; } free(toFree); return in; } /* Print a #line directive line to the output file. */ PRIVATE void tplt_linedir(FILE *out, int lineno, char *filename) { fprintf(out,"#line %d \"",lineno); |
︙ | ︙ | |||
3908 3909 3910 3911 3912 3913 3914 | used += n; assert( used>=0 ); } n = lemonStrlen(zText); } if( (int) (n+sizeof(zInt)*2+used) >= alloced ){ alloced = n + sizeof(zInt)*2 + used + 200; | | | 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 | used += n; assert( used>=0 ); } n = lemonStrlen(zText); } if( (int) (n+sizeof(zInt)*2+used) >= alloced ){ alloced = n + sizeof(zInt)*2 + used + 200; z = (char *) realloc(z, alloced); } if( z==0 ) return empty; while( n-- > 0 ){ c = *(zText++); if( c=='%' && n>0 && zText[0]=='d' ){ lemon_sprintf(zInt, "%d", p1); p1 = p2; |
︙ | ︙ | |||
4198 4199 4200 4201 4202 4203 4204 | char *stddt; /* Standardized name for a datatype */ int i,j; /* Loop counters */ unsigned hash; /* For hashing the name of a type */ const char *name; /* Name of the parser */ /* Allocate and initialize types[] and allocate stddt[] */ arraysize = lemp->nsymbol * 2; | | | | 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 | char *stddt; /* Standardized name for a datatype */ int i,j; /* Loop counters */ unsigned hash; /* For hashing the name of a type */ const char *name; /* Name of the parser */ /* Allocate and initialize types[] and allocate stddt[] */ arraysize = lemp->nsymbol * 2; types = (char**)calloc( arraysize, sizeof(char*) ); if( types==0 ){ fprintf(stderr,"Out of memory.\n"); exit(1); } for(i=0; i<arraysize; i++) types[i] = 0; maxdtlength = 0; if( lemp->vartype ){ maxdtlength = lemonStrlen(lemp->vartype); } for(i=0; i<lemp->nsymbol; i++){ int len; struct symbol *sp = lemp->symbols[i]; if( sp->datatype==0 ) continue; len = lemonStrlen(sp->datatype); if( len>maxdtlength ) maxdtlength = len; } stddt = (char*)malloc( maxdtlength*2 + 1 ); if( stddt==0 ){ fprintf(stderr,"Out of memory.\n"); exit(1); } /* Build a hash table of datatypes. The ".dtnum" field of each symbol ** is filled in with the hash index plus 1. A ".dtnum" value of 0 is |
︙ | ︙ | |||
4264 4265 4266 4267 4268 4269 4270 | break; } hash++; if( hash>=(unsigned)arraysize ) hash = 0; } if( types[hash]==0 ){ sp->dtnum = hash + 1; | | | 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 | break; } hash++; if( hash>=(unsigned)arraysize ) hash = 0; } if( types[hash]==0 ){ sp->dtnum = hash + 1; types[hash] = (char*)malloc( lemonStrlen(stddt)+1 ); if( types[hash]==0 ){ fprintf(stderr,"Out of memory.\n"); exit(1); } lemon_strcpy(types[hash],stddt); } } |
︙ | ︙ | |||
4286 4287 4288 4289 4290 4291 4292 | if( mhflag ){ fprintf(out,"#endif\n"); lineno++; } fprintf(out,"typedef union {\n"); lineno++; 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++; | | | | | 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 | if( mhflag ){ fprintf(out,"#endif\n"); lineno++; } fprintf(out,"typedef union {\n"); lineno++; 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; } /* ** Return the name of a C datatype able to represent values between ** lwr and upr, inclusive. If pnByte!=NULL then also write the sizeof |
︙ | ︙ | |||
4521 4522 4523 4524 4525 4526 4527 | } /* Generate the include code, if any */ tplt_print(out,lemp,lemp->include,&lineno); if( mhflag ){ char *incName = file_makename(lemp, ".h"); fprintf(out,"#include \"%s\"\n", incName); lineno++; | | | 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 | } /* Generate the include code, if any */ tplt_print(out,lemp,lemp->include,&lineno); if( mhflag ){ char *incName = file_makename(lemp, ".h"); fprintf(out,"#include \"%s\"\n", incName); lineno++; free(incName); } tplt_xfer(lemp->name,in,out,&lineno); /* Generate #defines for all tokens */ if( lemp->tokenprefix ) prefix = lemp->tokenprefix; else prefix = ""; if( mhflag ){ |
︙ | ︙ | |||
4628 4629 4630 4631 4632 4633 4634 | fprintf(out,"#define YYFALLBACK 1\n"); lineno++; } /* Compute the action table, but do not output it yet. The action ** table must be computed before generating the YYNSTATE macro because ** we need to know how many states can be eliminated. */ | | | 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 | fprintf(out,"#define YYFALLBACK 1\n"); lineno++; } /* Compute the action table, but do not output it yet. The action ** table must be computed before generating the YYNSTATE macro because ** we need to know how many states can be eliminated. */ ax = (struct axset *) calloc(lemp->nxstate*2, sizeof(ax[0])); if( ax==0 ){ fprintf(stderr,"malloc failed\n"); exit(1); } for(i=0; i<lemp->nxstate; i++){ stp = lemp->sorted[i]; ax[i*2].stp = stp; |
︙ | ︙ | |||
4686 4687 4688 4689 4690 4691 4692 | } printf("%4d: State %3d %s n: %2d size: %5d freespace: %d\n", i, stp->statenum, ax[i].isTkn ? "Token" : "Var ", ax[i].nAction, pActtab->nAction, nn); } #endif } | | | 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 | } printf("%4d: State %3d %s n: %2d size: %5d freespace: %d\n", i, stp->statenum, ax[i].isTkn ? "Token" : "Var ", ax[i].nAction, pActtab->nAction, nn); } #endif } free(ax); /* Mark rules that are actually used for reduce actions after all ** optimizations have been applied */ for(rp=lemp->rule; rp; rp=rp->next) rp->doesReduce = LEMON_FALSE; for(i=0; i<lemp->nxstate; i++){ for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){ |
︙ | ︙ | |||
5312 5313 5314 5315 5316 5317 5318 | { size = n+1; } /* Allocate a new set */ char *SetNew(void){ char *s; | | | | 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 | { size = n+1; } /* Allocate a new set */ char *SetNew(void){ char *s; s = (char*)calloc( size, 1); if( s==0 ){ memory_error(); } return s; } /* Deallocate a set */ void SetFree(char *s) { free(s); } /* Add a new element to the set. Return TRUE if the element was added ** and FALSE if it was already there. */ int SetAdd(char *s, int e) { int rv; |
︙ | ︙ | |||
5381 5382 5383 5384 5385 5386 5387 | const char *Strsafe(const char *y) { const char *z; char *cpy; if( y==0 ) return 0; z = Strsafe_find(y); | | | 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 | const char *Strsafe(const char *y) { const char *z; char *cpy; if( y==0 ) return 0; z = Strsafe_find(y); if( z==0 && (cpy=(char *)malloc( lemonStrlen(y)+1 ))!=0 ){ lemon_strcpy(cpy,y); z = cpy; Strsafe_insert(z); } MemoryCheck(z); return z; } |
︙ | ︙ | |||
5417 5418 5419 5420 5421 5422 5423 | /* There is only one instance of the array, which is the following */ static struct s_x1 *x1a; /* Allocate a new associative array */ void Strsafe_init(void){ if( x1a ) return; | | | | | 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 | /* There is only one instance of the array, which is the following */ static struct s_x1 *x1a; /* Allocate a new associative array */ void Strsafe_init(void){ if( x1a ) return; x1a = (struct s_x1*)malloc( sizeof(struct s_x1) ); if( x1a ){ x1a->size = 1024; x1a->count = 0; x1a->tbl = (x1node*)calloc(1024, sizeof(x1node) + sizeof(x1node*)); if( x1a->tbl==0 ){ free(x1a); x1a = 0; }else{ int i; x1a->ht = (x1node**)&(x1a->tbl[1024]); for(i=0; i<1024; i++) x1a->ht[i] = 0; } } |
︙ | ︙ | |||
5458 5459 5460 5461 5462 5463 5464 | } if( x1a->count>=x1a->size ){ /* Need to make the hash table bigger */ int i,arrSize; struct s_x1 array; array.size = arrSize = x1a->size*2; array.count = x1a->count; | | | | 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 | } if( x1a->count>=x1a->size ){ /* Need to make the hash table bigger */ int i,arrSize; struct s_x1 array; array.size = arrSize = x1a->size*2; array.count = x1a->count; array.tbl = (x1node*)calloc(arrSize, sizeof(x1node) + sizeof(x1node*)); if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ array.ht = (x1node**)&(array.tbl[arrSize]); for(i=0; i<arrSize; i++) array.ht[i] = 0; for(i=0; i<x1a->count; i++){ x1node *oldnp, *newnp; oldnp = &(x1a->tbl[i]); h = strhash(oldnp->data) & (arrSize-1); newnp = &(array.tbl[i]); if( array.ht[h] ) array.ht[h]->from = &(newnp->next); newnp->next = array.ht[h]; newnp->data = oldnp->data; newnp->from = &(array.ht[h]); array.ht[h] = newnp; } /* free(x1a->tbl); // This program was originally for 16-bit machines. ** Don't worry about freeing memory on modern platforms. */ *x1a = array; } /* Insert the new data */ h = ph & (x1a->size-1); np = &(x1a->tbl[x1a->count++]); np->data = data; |
︙ | ︙ | |||
5514 5515 5516 5517 5518 5519 5520 | */ struct symbol *Symbol_new(const char *x) { struct symbol *sp; sp = Symbol_find(x); if( sp==0 ){ | | | 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 | */ struct symbol *Symbol_new(const char *x) { struct symbol *sp; sp = Symbol_find(x); if( sp==0 ){ sp = (struct symbol *)calloc(1, sizeof(struct symbol) ); MemoryCheck(sp); sp->name = Strsafe(x); sp->type = ISUPPER(*x) ? TERMINAL : NONTERMINAL; sp->rule = 0; sp->fallback = 0; sp->prec = -1; sp->assoc = UNK; |
︙ | ︙ | |||
5585 5586 5587 5588 5589 5590 5591 | /* There is only one instance of the array, which is the following */ static struct s_x2 *x2a; /* Allocate a new associative array */ void Symbol_init(void){ if( x2a ) return; | | | | | 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 | /* There is only one instance of the array, which is the following */ static struct s_x2 *x2a; /* Allocate a new associative array */ void Symbol_init(void){ if( x2a ) return; x2a = (struct s_x2*)malloc( sizeof(struct s_x2) ); if( x2a ){ x2a->size = 128; x2a->count = 0; x2a->tbl = (x2node*)calloc(128, sizeof(x2node) + sizeof(x2node*)); if( x2a->tbl==0 ){ free(x2a); x2a = 0; }else{ int i; x2a->ht = (x2node**)&(x2a->tbl[128]); for(i=0; i<128; i++) x2a->ht[i] = 0; } } |
︙ | ︙ | |||
5626 5627 5628 5629 5630 5631 5632 | } if( x2a->count>=x2a->size ){ /* Need to make the hash table bigger */ int i,arrSize; struct s_x2 array; array.size = arrSize = x2a->size*2; array.count = x2a->count; | | | | 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 | } if( x2a->count>=x2a->size ){ /* Need to make the hash table bigger */ int i,arrSize; struct s_x2 array; array.size = arrSize = x2a->size*2; array.count = x2a->count; array.tbl = (x2node*)calloc(arrSize, sizeof(x2node) + sizeof(x2node*)); if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ array.ht = (x2node**)&(array.tbl[arrSize]); for(i=0; i<arrSize; i++) array.ht[i] = 0; for(i=0; i<x2a->count; i++){ x2node *oldnp, *newnp; oldnp = &(x2a->tbl[i]); h = strhash(oldnp->key) & (arrSize-1); newnp = &(array.tbl[i]); if( array.ht[h] ) array.ht[h]->from = &(newnp->next); newnp->next = array.ht[h]; newnp->key = oldnp->key; newnp->data = oldnp->data; newnp->from = &(array.ht[h]); array.ht[h] = newnp; } /* free(x2a->tbl); // This program was originally written for 16-bit ** machines. Don't worry about freeing this trivial amount of memory ** on modern platforms. Just leak it. */ *x2a = array; } /* Insert the new data */ h = ph & (x2a->size-1); np = &(x2a->tbl[x2a->count++]); |
︙ | ︙ | |||
5703 5704 5705 5706 5707 5708 5709 | ** problems, or if the array is empty. */ struct symbol **Symbol_arrayof() { struct symbol **array; int i,arrSize; if( x2a==0 ) return 0; arrSize = x2a->count; | | | 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 | ** problems, or if the array is empty. */ struct symbol **Symbol_arrayof() { struct symbol **array; int i,arrSize; if( x2a==0 ) return 0; arrSize = x2a->count; array = (struct symbol **)calloc(arrSize, sizeof(struct symbol *)); if( array ){ for(i=0; i<arrSize; i++) array[i] = x2a->tbl[i].data; } return array; } /* Compare two configurations */ |
︙ | ︙ | |||
5751 5752 5753 5754 5755 5756 5757 | return h; } /* Allocate a new state structure */ struct state *State_new() { struct state *newstate; | | | 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 | return h; } /* Allocate a new state structure */ struct state *State_new() { struct state *newstate; newstate = (struct state *)calloc(1, sizeof(struct state) ); MemoryCheck(newstate); return newstate; } /* There is one instance of the following structure for each ** associative array of type "x3". */ |
︙ | ︙ | |||
5784 5785 5786 5787 5788 5789 5790 | /* There is only one instance of the array, which is the following */ static struct s_x3 *x3a; /* Allocate a new associative array */ void State_init(void){ if( x3a ) return; | | | | | 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 | /* There is only one instance of the array, which is the following */ static struct s_x3 *x3a; /* Allocate a new associative array */ void State_init(void){ if( x3a ) return; x3a = (struct s_x3*)malloc( sizeof(struct s_x3) ); if( x3a ){ x3a->size = 128; x3a->count = 0; x3a->tbl = (x3node*)calloc(128, sizeof(x3node) + sizeof(x3node*)); if( x3a->tbl==0 ){ free(x3a); x3a = 0; }else{ int i; x3a->ht = (x3node**)&(x3a->tbl[128]); for(i=0; i<128; i++) x3a->ht[i] = 0; } } |
︙ | ︙ | |||
5825 5826 5827 5828 5829 5830 5831 | } if( x3a->count>=x3a->size ){ /* Need to make the hash table bigger */ int i,arrSize; struct s_x3 array; array.size = arrSize = x3a->size*2; array.count = x3a->count; | | | | 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 | } if( x3a->count>=x3a->size ){ /* Need to make the hash table bigger */ int i,arrSize; struct s_x3 array; array.size = arrSize = x3a->size*2; array.count = x3a->count; array.tbl = (x3node*)calloc(arrSize, sizeof(x3node) + sizeof(x3node*)); if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ array.ht = (x3node**)&(array.tbl[arrSize]); for(i=0; i<arrSize; i++) array.ht[i] = 0; for(i=0; i<x3a->count; i++){ x3node *oldnp, *newnp; oldnp = &(x3a->tbl[i]); h = statehash(oldnp->key) & (arrSize-1); newnp = &(array.tbl[i]); if( array.ht[h] ) array.ht[h]->from = &(newnp->next); newnp->next = array.ht[h]; newnp->key = oldnp->key; newnp->data = oldnp->data; newnp->from = &(array.ht[h]); array.ht[h] = newnp; } free(x3a->tbl); *x3a = array; } /* Insert the new data */ h = ph & (x3a->size-1); np = &(x3a->tbl[x3a->count++]); np->key = key; np->data = data; |
︙ | ︙ | |||
5882 5883 5884 5885 5886 5887 5888 | ** problems, or if the array is empty. */ struct state **State_arrayof(void) { struct state **array; int i,arrSize; if( x3a==0 ) return 0; arrSize = x3a->count; | | | 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 | ** problems, or if the array is empty. */ struct state **State_arrayof(void) { struct state **array; int i,arrSize; if( x3a==0 ) return 0; arrSize = x3a->count; array = (struct state **)calloc(arrSize, sizeof(struct state *)); if( array ){ for(i=0; i<arrSize; i++) array[i] = x3a->tbl[i].data; } return array; } /* Hash a configuration */ |
︙ | ︙ | |||
5924 5925 5926 5927 5928 5929 5930 | /* There is only one instance of the array, which is the following */ static struct s_x4 *x4a; /* Allocate a new associative array */ void Configtable_init(void){ if( x4a ) return; | | | | | 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 | /* There is only one instance of the array, which is the following */ static struct s_x4 *x4a; /* Allocate a new associative array */ void Configtable_init(void){ if( x4a ) return; x4a = (struct s_x4*)malloc( sizeof(struct s_x4) ); if( x4a ){ x4a->size = 64; x4a->count = 0; x4a->tbl = (x4node*)calloc(64, sizeof(x4node) + sizeof(x4node*)); if( x4a->tbl==0 ){ free(x4a); x4a = 0; }else{ int i; x4a->ht = (x4node**)&(x4a->tbl[64]); for(i=0; i<64; i++) x4a->ht[i] = 0; } } |
︙ | ︙ | |||
5965 5966 5967 5968 5969 5970 5971 | } if( x4a->count>=x4a->size ){ /* Need to make the hash table bigger */ int i,arrSize; struct s_x4 array; array.size = arrSize = x4a->size*2; array.count = x4a->count; | < | > > > | 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 | } if( x4a->count>=x4a->size ){ /* Need to make the hash table bigger */ int i,arrSize; struct s_x4 array; array.size = arrSize = x4a->size*2; array.count = x4a->count; array.tbl = (x4node*)calloc(arrSize, sizeof(x4node) + sizeof(x4node*)); if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ array.ht = (x4node**)&(array.tbl[arrSize]); for(i=0; i<arrSize; i++) array.ht[i] = 0; for(i=0; i<x4a->count; i++){ x4node *oldnp, *newnp; oldnp = &(x4a->tbl[i]); h = confighash(oldnp->data) & (arrSize-1); newnp = &(array.tbl[i]); if( array.ht[h] ) array.ht[h]->from = &(newnp->next); newnp->next = array.ht[h]; newnp->data = oldnp->data; newnp->from = &(array.ht[h]); array.ht[h] = newnp; } /* free(x4a->tbl); // This code was originall written for 16-bit machines. ** on modern machines, don't worry about freeing this trival amount of ** memory. */ *x4a = array; } /* Insert the new data */ h = ph & (x4a->size-1); np = &(x4a->tbl[x4a->count++]); np->data = data; if( x4a->ht[h] ) x4a->ht[h]->from = &(np->next); |
︙ | ︙ |
Changes to tool/mkctimec.tcl.
︙ | ︙ | |||
101 102 103 104 105 106 107 | } # All Boolean compile time options which default to 0 or empty. # set boolean_defnil_options { SQLITE_32BIT_ROWID SQLITE_4_BYTE_ALIGNED_MALLOC | < | 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | } # All Boolean compile time options which default to 0 or empty. # set boolean_defnil_options { SQLITE_32BIT_ROWID SQLITE_4_BYTE_ALIGNED_MALLOC SQLITE_ALLOW_URI_AUTHORITY SQLITE_BUG_COMPATIBLE_20160819 SQLITE_CASE_SENSITIVE_LIKE SQLITE_CHECK_PAGES SQLITE_COVERAGE_TEST SQLITE_DEBUG SQLITE_DEFAULT_AUTOMATIC_INDEX |
︙ | ︙ |
Changes to tool/mkopcodeh.tcl.
︙ | ︙ | |||
77 78 79 80 81 82 83 | if {[regexp {^case OP_} $line]} { set line [split $line] set name [string trim [lindex $line 1] :] if {$name=="OP_Abortable"} continue; # put OP_Abortable last set op($name) -1 set group($name) 0 set jump($name) 0 | < | 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | if {[regexp {^case OP_} $line]} { set line [split $line] set name [string trim [lindex $line 1] :] if {$name=="OP_Abortable"} continue; # put OP_Abortable last set op($name) -1 set group($name) 0 set jump($name) 0 set in1($name) 0 set in2($name) 0 set in3($name) 0 set out2($name) 0 set out3($name) 0 set ncycle($name) 0 for {set i 3} {$i<[llength $line]-1} {incr i} { |
︙ | ︙ | |||
106 107 108 109 110 111 112 | jump {set jump($name) 1} in1 {set in1($name) 1} in2 {set in2($name) 1} in3 {set in3($name) 1} out2 {set out2($name) 1} out3 {set out3($name) 1} ncycle {set ncycle($name) 1} | < | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | jump {set jump($name) 1} in1 {set in1($name) 1} in2 {set in2($name) 1} in3 {set in3($name) 1} out2 {set out2($name) 1} out3 {set out3($name) 1} ncycle {set ncycle($name) 1} } } if {$group($name)} { set newGroup 0 if {[info exists groups($nGroup)]} { if {$prevName=="" || !$group($prevName)} { set newGroup 1 |
︙ | ︙ | |||
135 136 137 138 139 140 141 | # Assign numbers to all opcodes and output the result. # puts "/* Automatically generated. Do not edit */" puts "/* See the tool/mkopcodeh.tcl script for details */" foreach name {OP_Noop OP_Explain OP_Abortable} { set jump($name) 0 | < | 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | # Assign numbers to all opcodes and output the result. # puts "/* Automatically generated. Do not edit */" puts "/* See the tool/mkopcodeh.tcl script for details */" foreach name {OP_Noop OP_Explain OP_Abortable} { set jump($name) 0 set in1($name) 0 set in2($name) 0 set in3($name) 0 set out2($name) 0 set out3($name) 0 set ncycle($name) 0 set op($name) -1 |
︙ | ︙ | |||
255 256 257 258 259 260 261 | if {![info exists used($i)]} { set def($i) "OP_NotUsed_$i" } if {$i>$max} {set max $i} set name $def($i) puts -nonewline [format {#define %-16s %3d} $name $i] set com {} | < < | | 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 | if {![info exists used($i)]} { set def($i) "OP_NotUsed_$i" } if {$i>$max} {set max $i} set name $def($i) puts -nonewline [format {#define %-16s %3d} $name $i] set com {} if {[info exists jump($name)] && $jump($name)} { lappend com "jump" } if {[info exists sameas($i)]} { lappend com "same as $sameas($i)" } if {[info exists synopsis($name)]} { lappend com "synopsis: $synopsis($name)" |
︙ | ︙ | |||
290 291 292 293 294 295 296 | if {$jump($name)} {incr x 1} if {$in1($name)} {incr x 2} if {$in2($name)} {incr x 4} if {$in3($name)} {incr x 8} if {$out2($name)} {incr x 16} if {$out3($name)} {incr x 32} if {$ncycle($name)} {incr x 64} | < < | 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 | if {$jump($name)} {incr x 1} if {$in1($name)} {incr x 2} if {$in2($name)} {incr x 4} if {$in3($name)} {incr x 8} if {$out2($name)} {incr x 16} if {$out3($name)} {incr x 32} if {$ncycle($name)} {incr x 64} } set bv($i) $x } puts "" puts "/* Properties such as \"out2\" or \"jump\" that are specified in" puts "** comments following the \"case\" for each opcode in the vdbe.c" puts "** are encoded into bitvectors as follows:" puts "*/" puts "#define OPFLG_JUMP 0x01 /* jump: P2 holds jmp target */" puts "#define OPFLG_IN1 0x02 /* in1: P1 is an input */" puts "#define OPFLG_IN2 0x04 /* in2: P2 is an input */" puts "#define OPFLG_IN3 0x08 /* in3: P3 is an input */" puts "#define OPFLG_OUT2 0x10 /* out2: P2 is an output */" puts "#define OPFLG_OUT3 0x20 /* out3: P3 is an output */" puts "#define OPFLG_NCYCLE 0x40 /* ncycle:Cycles count against P1 */" puts "#define OPFLG_INITIALIZER \173\\" for {set i 0} {$i<=$max} {incr i} { if {$i%8==0} { puts -nonewline [format "/* %3d */" $i] } puts -nonewline [format " 0x%02x," $bv($i)] if {$i%8==7} { |
︙ | ︙ |