Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge all recent trunk changes, and especially the new sqlite3_snapshot_recover() interface. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | apple-osx |
Files: | files | file ages | folders |
SHA1: |
41a3af5443d8c97ba75cac7f082f06b5 |
User & Date: | drh 2016-11-26 20:44:52.669 |
Context
2016-12-12
| ||
16:15 | Merge all the latest performance enhancements from trunk. (check-in: a24f805b5e user: drh tags: apple-osx) | |
2016-11-26
| ||
20:44 | Merge all recent trunk changes, and especially the new sqlite3_snapshot_recover() interface. (check-in: 41a3af5443 user: drh tags: apple-osx) | |
20:12 | Update test case for opening SHM files read/write on a read-only connection so that they are only attempted on Darwin with SQLITE_ENABLE_PRESIST_WAL. (check-in: d6a7bf80cf user: drh tags: apple-osx) | |
19:44 | Add the sqlite3_snapshot_recover() interface and related functionality. (check-in: b70c85ce6d user: drh tags: trunk) | |
Changes
Changes to Makefile.in.
︙ | ︙ | |||
560 561 562 563 564 565 566 | # Databases containing fuzzer test cases # FUZZDATA = \ $(TOP)/test/fuzzdata1.db \ $(TOP)/test/fuzzdata2.db \ $(TOP)/test/fuzzdata3.db \ | | > | > | 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 | # Databases containing fuzzer test cases # FUZZDATA = \ $(TOP)/test/fuzzdata1.db \ $(TOP)/test/fuzzdata2.db \ $(TOP)/test/fuzzdata3.db \ $(TOP)/test/fuzzdata4.db \ $(TOP)/test/fuzzdata5.db # Standard options to testfixture # TESTOPTS = --verbose=file --output=test-out.txt # Extra compiler options for various shell tools # SHELL_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 # SHELL_OPT += -DSQLITE_ENABLE_FTS5 SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1 FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ FUZZCHECK_SRC = $(TOP)/test/fuzzcheck.c $(TOP)/test/ossfuzz.c # This is the default Makefile target. The objects listed here # are what get build when you type just "make" with no arguments. # all: sqlite3.h libsqlite3.la sqlite3$(TEXE) $(HAVE_TCL:1=libtclsqlite3.la) Makefile: $(TOP)/Makefile.in |
︙ | ︙ | |||
621 622 623 624 625 626 627 | sourcetest: srcck1$(BEXE) sqlite3.c ./srcck1 sqlite3.c fuzzershell$(TEXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h $(LTLINK) -o $@ $(FUZZERSHELL_OPT) \ $(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS) | | > > > | | 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 | sourcetest: srcck1$(BEXE) sqlite3.c ./srcck1 sqlite3.c fuzzershell$(TEXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h $(LTLINK) -o $@ $(FUZZERSHELL_OPT) \ $(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS) fuzzcheck$(TEXE): $(FUZZCHECK_SRC) sqlite3.c sqlite3.h $(LTLINK) -o $@ $(FUZZCHECK_OPT) $(FUZZCHECK_SRC) sqlite3.c $(TLIBS) ossshell$(TEXE): $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.h $(LTLINK) -o $@ $(FUZZCHECK_OPT) $(TOP)/test/ossshell.c sqlite3.c sqlite3.h $(TLIBS) mptester$(TEXE): sqlite3.lo $(TOP)/mptest/mptest.c $(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.lo \ $(TLIBS) -rpath "$(libdir)" MPTEST1=./mptester$(TEXE) mptest.db $(TOP)/mptest/crash01.test --repeat 20 MPTEST2=./mptester$(TEXE) mptest.db $(TOP)/mptest/multiwrite01.test --repeat 20 |
︙ | ︙ | |||
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 | ./fuzzcheck$(TEXE) $(FUZZDATA) fastfuzztest: fuzzcheck$(TEXE) $(FUZZDATA) ./fuzzcheck$(TEXE) --limit-mem 100M $(FUZZDATA) valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA) valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA) # Minimal testing that runs in less than 3 minutes # quicktest: ./testfixture$(TEXE) ./testfixture$(TEXE) $(TOP)/test/extraquick.test $(TESTOPTS) # This is the common case. Run many tests that do not take too long, | > | 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 | ./fuzzcheck$(TEXE) $(FUZZDATA) fastfuzztest: fuzzcheck$(TEXE) $(FUZZDATA) ./fuzzcheck$(TEXE) --limit-mem 100M $(FUZZDATA) valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA) valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA) # Minimal testing that runs in less than 3 minutes # quicktest: ./testfixture$(TEXE) ./testfixture$(TEXE) $(TOP)/test/extraquick.test $(TESTOPTS) # This is the common case. Run many tests that do not take too long, |
︙ | ︙ |
Changes to Makefile.msc.
︙ | ︙ | |||
1475 1476 1477 1478 1479 1480 1481 | # Databases containing fuzzer test cases # FUZZDATA = \ $(TOP)\test\fuzzdata1.db \ $(TOP)\test\fuzzdata2.db \ $(TOP)\test\fuzzdata3.db \ | | > | > > | 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 | # Databases containing fuzzer test cases # FUZZDATA = \ $(TOP)\test\fuzzdata1.db \ $(TOP)\test\fuzzdata2.db \ $(TOP)\test\fuzzdata3.db \ $(TOP)\test\fuzzdata4.db \ $(TOP)\test\fuzzdata5.db # <</mark>> # Additional compiler options for the shell. These are only effective # when the shell is not being dynamically linked. # !IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 # SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS5 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION !ENDIF # <<mark>> # Extra compiler options for various test tools. # MPTESTER_COMPILE_OPTS = -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS5 FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ FUZZCHECK_SRC = $(TOP)\test\fuzzcheck.c $(TOP)\test\ossfuzz.c OSSSHELL_SRC = $(TOP)\test\ossshell.c $(TOP)\test\ossfuzz.c # Standard options to testfixture. # TESTOPTS = --verbose=file --output=test-out.txt # Extra targets for the "all" target that require Tcl. # |
︙ | ︙ | |||
1563 1564 1565 1566 1567 1568 1569 | sourcetest: srcck1.exe sqlite3.c srcck1.exe sqlite3.c fuzzershell.exe: $(TOP)\tool\fuzzershell.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) $(FUZZERSHELL_COMPILE_OPTS) $(TOP)\tool\fuzzershell.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) | | | > > > | 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 | sourcetest: srcck1.exe sqlite3.c srcck1.exe sqlite3.c fuzzershell.exe: $(TOP)\tool\fuzzershell.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) $(FUZZERSHELL_COMPILE_OPTS) $(TOP)\tool\fuzzershell.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) fuzzcheck.exe: $(FUZZCHECK_SRC) $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(FUZZCHECK_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) ossshell.exe: $(OSSSHELL_SRC) $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(OSSSHELL_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) mptester.exe: $(TOP)\mptest\mptest.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) $(MPTESTER_COMPILE_OPTS) $(TOP)\mptest\mptest.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) MPTEST1 = mptester mptest.db $(TOP)\mptest\crash01.test --repeat 20 MPTEST2 = mptester mptest.db $(TOP)\mptest\multiwrite01.test --repeat 20 |
︙ | ︙ |
Changes to configure.
︙ | ︙ | |||
11248 11249 11250 11251 11252 11253 11254 | if test "${enable_debug+set}" = set; then : enableval=$enable_debug; use_debug=$enableval else use_debug=no fi if test "${use_debug}" = "yes" ; then | | | 11248 11249 11250 11251 11252 11253 11254 11255 11256 11257 11258 11259 11260 11261 11262 | if test "${enable_debug+set}" = set; then : enableval=$enable_debug; use_debug=$enableval else use_debug=no fi if test "${use_debug}" = "yes" ; then TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE" else TARGET_DEBUG="-DNDEBUG" fi ######### # See whether we should use the amalgamation to build |
︙ | ︙ | |||
13825 13826 13827 13828 13829 13830 13831 | # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi | < | 13825 13826 13827 13828 13829 13830 13831 | # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi |
Changes to configure.ac.
︙ | ︙ | |||
556 557 558 559 560 561 562 | AC_SEARCH_LIBS(fdatasync, [rt]) ######### # check for debug enabled AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug],[enable debugging & verbose explain]), [use_debug=$enableval],[use_debug=no]) if test "${use_debug}" = "yes" ; then | | | 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 | AC_SEARCH_LIBS(fdatasync, [rt]) ######### # check for debug enabled AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug],[enable debugging & verbose explain]), [use_debug=$enableval],[use_debug=no]) if test "${use_debug}" = "yes" ; then TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE" else TARGET_DEBUG="-DNDEBUG" fi AC_SUBST(TARGET_DEBUG) ######### # See whether we should use the amalgamation to build |
︙ | ︙ |
Changes to ext/fts5/fts5_expr.c.
︙ | ︙ | |||
916 917 918 919 920 921 922 | if( fts5ExprSynonymAdvanceto(pTerm, bDesc, &iLast, &rc) ){ pNode->bNomatch = 0; pNode->bEof = 1; return rc; } }else{ Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter; | | | 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 | if( fts5ExprSynonymAdvanceto(pTerm, bDesc, &iLast, &rc) ){ pNode->bNomatch = 0; pNode->bEof = 1; return rc; } }else{ Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter; if( pIter->iRowid==iLast || pIter->bEof ) continue; bMatch = 0; if( fts5ExprAdvanceto(pIter, bDesc, &iLast, &rc, &pNode->bEof) ){ return rc; } } } } |
︙ | ︙ |
Changes to ext/fts5/fts5_index.c.
︙ | ︙ | |||
2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 | static void fts5MultiIterNext( Fts5Index *p, Fts5Iter *pIter, int bFrom, /* True if argument iFrom is valid */ i64 iFrom /* Advance at least as far as this */ ){ int bUseFrom = bFrom; while( p->rc==SQLITE_OK ){ int iFirst = pIter->aFirst[1].iFirst; int bNewTerm = 0; Fts5SegIter *pSeg = &pIter->aSeg[iFirst]; assert( p->rc==SQLITE_OK ); if( bUseFrom && pSeg->pDlidx ){ fts5SegIterNextFrom(p, pSeg, iFrom); | > | 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 | static void fts5MultiIterNext( Fts5Index *p, Fts5Iter *pIter, int bFrom, /* True if argument iFrom is valid */ i64 iFrom /* Advance at least as far as this */ ){ int bUseFrom = bFrom; assert( pIter->base.bEof==0 ); while( p->rc==SQLITE_OK ){ int iFirst = pIter->aFirst[1].iFirst; int bNewTerm = 0; Fts5SegIter *pSeg = &pIter->aSeg[iFirst]; assert( p->rc==SQLITE_OK ); if( bUseFrom && pSeg->pDlidx ){ fts5SegIterNextFrom(p, pSeg, iFrom); |
︙ | ︙ |
Changes to ext/fts5/test/fts5simple3.test.
︙ | ︙ | |||
75 76 77 78 79 80 81 82 83 84 85 | do_execsql_test 3.0 { CREATE VIRTUAL TABLE x3 USING fts5(one); INSERT INTO x3 VALUES('a b c'); INSERT INTO x3 VALUES('c b a'); INSERT INTO x3 VALUES('o t t'); SELECT * FROM x3('x OR y OR z'); } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | do_execsql_test 3.0 { CREATE VIRTUAL TABLE x3 USING fts5(one); INSERT INTO x3 VALUES('a b c'); INSERT INTO x3 VALUES('c b a'); INSERT INTO x3 VALUES('o t t'); SELECT * FROM x3('x OR y OR z'); } #------------------------------------------------------------------------- # Test that a crash occuring when the second or subsequent tokens in a # phrase matched zero rows has been fixed. # do_execsql_test 4.0 { CREATE VIRTUAL TABLE t1 USING fts5(x); INSERT INTO t1 VALUES('ab'); INSERT INTO t1 VALUES('cd'); INSERT INTO t1 VALUES('ab cd'); INSERT INTO t1 VALUES('ab cdXXX'); INSERT INTO t1 VALUES('abXXX cd'); } do_execsql_test 4.1 { SELECT * FROM t1('"ab cd" OR "ab cd" *'); } {{ab cd} {ab cdXXX}} do_execsql_test 4.2 { SELECT * FROM t1('"xy zz" OR "ab cd" *'); } {{ab cd} {ab cdXXX}} do_execsql_test 4.3 { SELECT * FROM t1('"xy zz" OR "xy zz" *'); } do_execsql_test 4.4 { SELECT * FROM t1('"ab cd" OR "xy zz" *'); } {{ab cd}} do_execsql_test 4.5 { CREATE VIRTUAL TABLE t2 USING fts5(x); INSERT INTO t2 VALUES('ab'); INSERT INTO t2 VALUES('cd'); INSERT INTO t2 VALUES('ef'); } do_execsql_test 4.6 { SELECT * FROM t2('ab + xyz'); } finish_test |
Changes to ext/misc/csv.c.
︙ | ︙ | |||
398 399 400 401 402 403 404 | /* Return 0 if the argument is false and 1 if it is true. Return -1 if ** we cannot really tell. */ static int csv_boolean(const char *z){ if( sqlite3_stricmp("yes",z)==0 || sqlite3_stricmp("on",z)==0 || sqlite3_stricmp("true",z)==0 | | | 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 | /* Return 0 if the argument is false and 1 if it is true. Return -1 if ** we cannot really tell. */ static int csv_boolean(const char *z){ if( sqlite3_stricmp("yes",z)==0 || sqlite3_stricmp("on",z)==0 || sqlite3_stricmp("true",z)==0 || (z[0]=='1' && z[1]==0) ){ return 1; } if( sqlite3_stricmp("no",z)==0 || sqlite3_stricmp("off",z)==0 || sqlite3_stricmp("false",z)==0 || (z[0]=='0' && z[1]==0) |
︙ | ︙ |
Changes to ext/misc/json1.c.
︙ | ︙ | |||
45 46 47 48 49 50 51 | /* ** Versions of isspace(), isalnum() and isdigit() to which it is safe ** to pass signed char values. */ #ifdef sqlite3Isdigit /* Use the SQLite core versions if this routine is part of the ** SQLite amalgamation */ | | | > | | > | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | /* ** Versions of isspace(), isalnum() and isdigit() to which it is safe ** to pass signed char values. */ #ifdef sqlite3Isdigit /* Use the SQLite core versions if this routine is part of the ** SQLite amalgamation */ # define safe_isdigit(x) sqlite3Isdigit(x) # define safe_isalnum(x) sqlite3Isalnum(x) # define safe_isxdigit(x) sqlite3Isxdigit(x) #else /* Use the standard library for separate compilation */ #include <ctype.h> /* amalgamator: keep */ # define safe_isdigit(x) isdigit((unsigned char)(x)) # define safe_isalnum(x) isalnum((unsigned char)(x)) # define safe_isxdigit(x) isxdigit((unsigned char)(x)) #endif /* ** Growing our own isspace() routine this way is twice as fast as ** the library isspace() function, resulting in a 7% overall performance ** increase for the parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os). */ |
︙ | ︙ | |||
589 590 591 592 593 594 595 | char c = z[i]; if( c!='\\' ){ zOut[j++] = c; }else{ c = z[++i]; if( c=='u' ){ u32 v = 0, k; | | > > | | | < | 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 | char c = z[i]; if( c!='\\' ){ zOut[j++] = c; }else{ c = z[++i]; if( c=='u' ){ u32 v = 0, k; for(k=0; k<4; i++, k++){ assert( i<n-2 ); c = z[i+1]; assert( safe_isxdigit(c) ); if( c<='9' ) v = v*16 + c - '0'; else if( c<='F' ) v = v*16 + c - 'A' + 10; else v = v*16 + c - 'a' + 10; } if( v==0 ) break; if( v<=0x7f ){ zOut[j++] = (char)v; }else if( v<=0x7ff ){ zOut[j++] = (char)(0xc0 | (v>>6)); zOut[j++] = 0x80 | (v&0x3f); |
︙ | ︙ | |||
697 698 699 700 701 702 703 704 705 706 707 708 709 710 | p->eType = (u8)eType; p->jnFlags = 0; p->iVal = 0; p->n = n; p->u.zJContent = zContent; return pParse->nNode++; } /* ** Parse a single JSON value which begins at pParse->zJson[i]. Return the ** index of the first character past the end of the value parsed. ** ** Return negative for a syntax error. Special cases: return -2 if the ** first non-whitespace character is '}' and return -3 if the first | > > > > > > > > > | 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 | p->eType = (u8)eType; p->jnFlags = 0; p->iVal = 0; p->n = n; p->u.zJContent = zContent; return pParse->nNode++; } /* ** Return true if z[] begins with 4 (or more) hexadecimal digits */ static int jsonIs4Hex(const char *z){ int i; for(i=0; i<4; i++) if( !safe_isxdigit(z[i]) ) return 0; return 1; } /* ** Parse a single JSON value which begins at pParse->zJson[i]. Return the ** index of the first character past the end of the value parsed. ** ** Return negative for a syntax error. Special cases: return -2 if the ** first non-whitespace character is '}' and return -3 if the first |
︙ | ︙ | |||
772 773 774 775 776 777 778 | u8 jnFlags = 0; j = i+1; for(;;){ c = pParse->zJson[j]; if( c==0 ) return -1; if( c=='\\' ){ c = pParse->zJson[++j]; | | > > | > > > | 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 | u8 jnFlags = 0; j = i+1; for(;;){ c = pParse->zJson[j]; if( c==0 ) return -1; if( c=='\\' ){ c = pParse->zJson[++j]; if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f' || c=='n' || c=='r' || c=='t' || (c=='u' && jsonIs4Hex(pParse->zJson+j+1)) ){ jnFlags = JNODE_ESCAPE; }else{ return -1; } }else if( c=='"' ){ break; } j++; } jsonParseAddNode(pParse, JSON_STRING, j+1-i, &pParse->zJson[i]); if( !pParse->oom ) pParse->aNode[pParse->nNode-1].jnFlags = jnFlags; |
︙ | ︙ | |||
1641 1642 1643 1644 1645 1646 1647 | } static void jsonObjectFinal(sqlite3_context *ctx){ JsonString *pStr; pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); if( pStr ){ jsonAppendChar(pStr, '}'); if( pStr->bErr ){ | | | 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 | } static void jsonObjectFinal(sqlite3_context *ctx){ JsonString *pStr; pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); if( pStr ){ jsonAppendChar(pStr, '}'); if( pStr->bErr ){ if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); assert( pStr->bStatic ); }else{ sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed, pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); pStr->bStatic = 1; } }else{ |
︙ | ︙ | |||
1919 1920 1921 1922 1923 1924 1925 | jsonEachComputePath(p, &x, p->sParse.aUp[p->i]); jsonResult(&x); break; } /* For json_each() path and root are the same so fall through ** into the root case */ } | | | | 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 | jsonEachComputePath(p, &x, p->sParse.aUp[p->i]); jsonResult(&x); break; } /* For json_each() path and root are the same so fall through ** into the root case */ } default: { const char *zRoot = p->zRoot; if( zRoot==0 ) zRoot = "$"; sqlite3_result_text(ctx, zRoot, -1, SQLITE_STATIC); break; } case JEACH_JSON: { assert( i==JEACH_JSON ); sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_STATIC); break; |
︙ | ︙ |
Changes to ext/rtree/rtreeD.test.
︙ | ︙ | |||
15 16 17 18 19 20 21 | if {![info exists testdir]} { set testdir [file join [file dirname [info script]] .. .. test] } source [file join [file dirname [info script]] rtree_util.tcl] source $testdir/tester.tcl source $testdir/lock_common.tcl | | | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | if {![info exists testdir]} { set testdir [file join [file dirname [info script]] .. .. test] } source [file join [file dirname [info script]] rtree_util.tcl] source $testdir/tester.tcl source $testdir/lock_common.tcl ifcapable !rtree||!builtin_test { finish_test return } set testprefix rtreeD #------------------------------------------------------------------------- # Test that if an SQLITE_BUSY is encountered within the vtable |
︙ | ︙ |
Changes to main.mk.
︙ | ︙ | |||
446 447 448 449 450 451 452 | # Databases containing fuzzer test cases # FUZZDATA = \ $(TOP)/test/fuzzdata1.db \ $(TOP)/test/fuzzdata2.db \ $(TOP)/test/fuzzdata3.db \ | | > | 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 | # Databases containing fuzzer test cases # FUZZDATA = \ $(TOP)/test/fuzzdata1.db \ $(TOP)/test/fuzzdata2.db \ $(TOP)/test/fuzzdata3.db \ $(TOP)/test/fuzzdata4.db \ $(TOP)/test/fuzzdata5.db # Standard options to testfixture # TESTOPTS = --verbose=file --output=test-out.txt # Extra compiler options for various shell tools # |
︙ | ︙ | |||
495 496 497 498 499 500 501 | ./srcck1 sqlite3.c fuzzershell$(EXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h $(TCCX) -o fuzzershell$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ $(FUZZERSHELL_OPT) $(TOP)/tool/fuzzershell.c sqlite3.c \ $(TLIBS) $(THREADLIB) | | > > > > > | | 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 | ./srcck1 sqlite3.c fuzzershell$(EXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h $(TCCX) -o fuzzershell$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ $(FUZZERSHELL_OPT) $(TOP)/tool/fuzzershell.c sqlite3.c \ $(TLIBS) $(THREADLIB) fuzzcheck$(EXE): $(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h $(TOP)/test/ossfuzz.c $(TCCX) -o fuzzcheck$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ -DSQLITE_ENABLE_MEMSYS5 $(FUZZCHECK_OPT) -DSQLITE_OSS_FUZZ \ $(TOP)/test/fuzzcheck.c $(TOP)/test/ossfuzz.c sqlite3.c $(TLIBS) $(THREADLIB) ossshell$(EXE): $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.h $(TCCX) -o ossshell$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ -DSQLITE_ENABLE_MEMSYS5 $(FUZZCHECK_OPT) \ $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c $(TLIBS) $(THREADLIB) mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c $(TCCX) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \ $(TLIBS) $(THREADLIB) MPTEST1=./mptester$(EXE) mptest1.db $(TOP)/mptest/crash01.test --repeat 20 MPTEST2=./mptester$(EXE) mptest2.db $(TOP)/mptest/multiwrite01.test --repeat 20 |
︙ | ︙ |
Changes to src/attach.c.
︙ | ︙ | |||
321 322 323 324 325 326 327 328 329 330 331 332 333 334 | ){ int rc; NameContext sName; Vdbe *v; sqlite3* db = pParse->db; int regArgs; memset(&sName, 0, sizeof(NameContext)); sName.pParse = pParse; if( SQLITE_OK!=(rc = resolveAttachExpr(&sName, pFilename)) || SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) || SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey)) | > | 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 | ){ int rc; NameContext sName; Vdbe *v; sqlite3* db = pParse->db; int regArgs; if( pParse->nErr ) goto attach_end; memset(&sName, 0, sizeof(NameContext)); sName.pParse = pParse; if( SQLITE_OK!=(rc = resolveAttachExpr(&sName, pFilename)) || SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) || SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey)) |
︙ | ︙ |
Changes to src/btree.c.
︙ | ︙ | |||
634 635 636 637 638 639 640 | pCur->nKey = sqlite3BtreeIntegerKey(pCur); }else{ /* For an index btree, save the complete key content */ void *pKey; pCur->nKey = sqlite3BtreePayloadSize(pCur); pKey = sqlite3Malloc( pCur->nKey ); if( pKey ){ | | | 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 | pCur->nKey = sqlite3BtreeIntegerKey(pCur); }else{ /* For an index btree, save the complete key content */ void *pKey; pCur->nKey = sqlite3BtreePayloadSize(pCur); pKey = sqlite3Malloc( pCur->nKey ); if( pKey ){ rc = sqlite3BtreePayload(pCur, 0, (int)pCur->nKey, pKey); if( rc==SQLITE_OK ){ pCur->pKey = pKey; }else{ sqlite3_free(pKey); } }else{ rc = SQLITE_NOMEM_BKPT; |
︙ | ︙ | |||
4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 | ** that is currently pointing to a row in a (non-empty) table. ** This is a verification routine is used only within assert() statements. */ int sqlite3BtreeCursorIsValid(BtCursor *pCur){ return pCur && pCur->eState==CURSOR_VALID; } #endif /* NDEBUG */ /* ** Return the value of the integer key or "rowid" for a table btree. ** This routine is only valid for a cursor that is pointing into a ** ordinary table btree. If the cursor points to an index btree or ** is invalid, the result of this routine is undefined. */ | > > > > | 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 | ** that is currently pointing to a row in a (non-empty) table. ** This is a verification routine is used only within assert() statements. */ int sqlite3BtreeCursorIsValid(BtCursor *pCur){ return pCur && pCur->eState==CURSOR_VALID; } #endif /* NDEBUG */ int sqlite3BtreeCursorIsValidNN(BtCursor *pCur){ assert( pCur!=0 ); return pCur->eState==CURSOR_VALID; } /* ** Return the value of the integer key or "rowid" for a table btree. ** This routine is only valid for a cursor that is pointing into a ** ordinary table btree. If the cursor points to an index btree or ** is invalid, the result of this routine is undefined. */ |
︙ | ︙ | |||
4649 4650 4651 4652 4653 4654 4655 | if( rc==SQLITE_OK && amt>0 ){ return SQLITE_CORRUPT_BKPT; } return rc; } /* | | | > > > > | | > | | < < < < < < < < < | < < < < > | 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 | if( rc==SQLITE_OK && amt>0 ){ return SQLITE_CORRUPT_BKPT; } return rc; } /* ** Read part of the payload for the row at which that cursor pCur is currently ** pointing. "amt" bytes will be transferred into pBuf[]. The transfer ** begins at "offset". ** ** pCur can be pointing to either a table or an index b-tree. ** If pointing to a table btree, then the content section is read. If ** pCur is pointing to an index b-tree then the key section is read. ** ** For sqlite3BtreePayload(), the caller must ensure that pCur is pointing ** to a valid row in the table. For sqlite3BtreePayloadChecked(), the ** cursor might be invalid or might need to be restored before being read. ** ** Return SQLITE_OK on success or an error code if anything goes ** wrong. An error is returned if "offset+amt" is larger than ** the available payload. */ int sqlite3BtreePayload(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] ); assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell ); return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0); } #ifndef SQLITE_OMIT_INCRBLOB int sqlite3BtreePayloadChecked(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ int rc; if ( pCur->eState==CURSOR_INVALID ){ return SQLITE_ABORT; } assert( cursorOwnsBtShared(pCur) ); rc = restoreCursorPosition(pCur); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_VALID ); assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] ); assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell ); rc = accessPayload(pCur, offset, amt, pBuf, 0); } return rc; } #endif /* SQLITE_OMIT_INCRBLOB */ /* ** Return a pointer to payload information from the entry that the ** pCur cursor is pointing to. The pointer is to the beginning of ** the key if index btrees (pPage->intKey==0) and is the data for ** table btrees (pPage->intKey==1). The number of bytes of available ** key/data is written into *pAmt. If *pAmt==0, then the value |
︙ | ︙ | |||
5167 5168 5169 5170 5171 5172 5173 | lwr = idx+1; if( lwr>upr ){ c = -1; break; } }else if( nCellKey>intKey ){ upr = idx-1; if( lwr>upr ){ c = +1; break; } }else{ assert( nCellKey==intKey ); | < < > > > | < | 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 | lwr = idx+1; if( lwr>upr ){ c = -1; break; } }else if( nCellKey>intKey ){ upr = idx-1; if( lwr>upr ){ c = +1; break; } }else{ assert( nCellKey==intKey ); pCur->aiIdx[pCur->iPage] = (u16)idx; if( !pPage->leaf ){ lwr = idx; goto moveto_next_layer; }else{ pCur->curFlags |= BTCF_ValidNKey; pCur->info.nKey = nCellKey; pCur->info.nSize = 0; *pRes = 0; return SQLITE_OK; } } assert( lwr+upr>=0 ); idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2; */ } }else{ for(;;){ |
︙ | ︙ | |||
5287 5288 5289 5290 5291 5292 5293 | } pCur->aiIdx[pCur->iPage] = (u16)lwr; rc = moveToChild(pCur, chldPg); if( rc ) break; } moveto_finish: pCur->info.nSize = 0; | | | 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 | } pCur->aiIdx[pCur->iPage] = (u16)lwr; rc = moveToChild(pCur, chldPg); if( rc ) break; } moveto_finish: pCur->info.nSize = 0; assert( (pCur->curFlags & BTCF_ValidOvfl)==0 ); return rc; } /* ** Return TRUE if the cursor is not pointing at an entry of the table. ** |
︙ | ︙ | |||
5485 5486 5487 5488 5489 5490 5491 | pCur->eState = CURSOR_INVALID; *pRes = 1; return SQLITE_OK; } moveToParent(pCur); } assert( pCur->info.nSize==0 ); | | | 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 | pCur->eState = CURSOR_INVALID; *pRes = 1; return SQLITE_OK; } moveToParent(pCur); } assert( pCur->info.nSize==0 ); assert( (pCur->curFlags & (BTCF_ValidOvfl))==0 ); pCur->aiIdx[pCur->iPage]--; pPage = pCur->apPage[pCur->iPage]; if( pPage->intKey && !pPage->leaf ){ rc = sqlite3BtreePrevious(pCur, pRes); }else{ rc = SQLITE_OK; |
︙ | ︙ | |||
7942 7943 7944 7945 7946 7947 7948 | ** hold the content of the row. ** ** For an index btree (used for indexes and WITHOUT ROWID tables), the ** key is an arbitrary byte sequence stored in pX.pKey,nKey. The ** pX.pData,nData,nZero fields must be zero. ** ** If the seekResult parameter is non-zero, then a successful call to | | | > | > | < < | | | > | > | 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 | ** hold the content of the row. ** ** For an index btree (used for indexes and WITHOUT ROWID tables), the ** key is an arbitrary byte sequence stored in pX.pKey,nKey. The ** pX.pData,nData,nZero fields must be zero. ** ** If the seekResult parameter is non-zero, then a successful call to ** MovetoUnpacked() to seek cursor pCur to (pKey,nKey) has already ** been performed. In other words, if seekResult!=0 then the cursor ** is currently pointing to a cell that will be adjacent to the cell ** to be inserted. If seekResult<0 then pCur points to a cell that is ** smaller then (pKey,nKey). If seekResult>0 then pCur points to a cell ** that is larger than (pKey,nKey). ** ** If seekResult==0, that means pCur is pointing at some unknown location. ** In that case, this routine must seek the cursor to the correct insertion ** point for (pKey,nKey) before doing the insertion. For index btrees, ** if pX->nMem is non-zero, then pX->aMem contains pointers to the unpacked ** key values and pX->aMem can be used instead of pX->pKey to avoid having ** to decode the key. */ int sqlite3BtreeInsert( BtCursor *pCur, /* Insert data into the table of this cursor */ const BtreePayload *pX, /* Content of the row to be inserted */ int appendBias, /* True if this is likely an append */ int seekResult /* Result of prior MovetoUnpacked() call */ ){ |
︙ | ︙ | |||
8013 8014 8015 8016 8017 8018 8019 | /* If this is an insert into a table b-tree, invalidate any incrblob ** cursors open on the row being replaced */ invalidateIncrblobCursors(p, pX->nKey, 0); /* If the cursor is currently on the last row and we are appending a ** new row onto the end, set the "loc" to avoid an unnecessary ** btreeMoveto() call */ | | > > | | > > > > > > > > | > | 8012 8013 8014 8015 8016 8017 8018 8019 8020 8021 8022 8023 8024 8025 8026 8027 8028 8029 8030 8031 8032 8033 8034 8035 8036 8037 8038 8039 8040 8041 8042 8043 8044 8045 | /* If this is an insert into a table b-tree, invalidate any incrblob ** cursors open on the row being replaced */ invalidateIncrblobCursors(p, pX->nKey, 0); /* If the cursor is currently on the last row and we are appending a ** new row onto the end, set the "loc" to avoid an unnecessary ** btreeMoveto() call */ if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey ){ loc = 0; }else if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey>0 && pCur->info.nKey==pX->nKey-1 ){ loc = -1; }else if( loc==0 ){ rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, appendBias, &loc); if( rc ) return rc; } }else if( loc==0 ){ if( pX->nMem ){ UnpackedRecord r; memset(&r, 0, sizeof(r)); r.pKeyInfo = pCur->pKeyInfo; r.aMem = pX->aMem; r.nField = pX->nMem; rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, appendBias, &loc); }else{ rc = btreeMoveto(pCur, pX->pKey, pX->nKey, appendBias, &loc); } if( rc ) return rc; } assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) ); pPage = pCur->apPage[pCur->iPage]; assert( pPage->intKey || pX->nKey>=0 ); assert( pPage->leaf || !pPage->intKey ); |
︙ | ︙ | |||
8563 8564 8565 8566 8567 8568 8569 | static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){ int rc; MemPage *pPage = 0; BtShared *pBt = p->pBt; assert( sqlite3BtreeHoldsMutex(p) ); assert( p->inTrans==TRANS_WRITE ); | | < < < < < < < < < < < < < < < < < < < < | 8573 8574 8575 8576 8577 8578 8579 8580 8581 8582 8583 8584 8585 8586 8587 | static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){ int rc; MemPage *pPage = 0; BtShared *pBt = p->pBt; assert( sqlite3BtreeHoldsMutex(p) ); assert( p->inTrans==TRANS_WRITE ); assert( iTable>=2 ); rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0); if( rc ) return rc; rc = sqlite3BtreeClearTable(p, iTable, 0); if( rc ){ releasePage(pPage); return rc; |
︙ | ︙ |
Changes to src/btree.h.
︙ | ︙ | |||
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 | ** organized and understandable, and it also helps the resulting code to ** run a little faster by using fewer registers for parameter passing. */ struct BtreePayload { const void *pKey; /* Key content for indexes. NULL for tables */ sqlite3_int64 nKey; /* Size of pKey for indexes. PRIMARY KEY for tabs */ const void *pData; /* Data for tables. NULL for indexes */ int nData; /* Size of pData. 0 if none. */ int nZero; /* Extra zero data appended after pData,nData */ }; int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload, int bias, int seekResult); int sqlite3BtreeFirst(BtCursor*, int *pRes); int sqlite3BtreeLast(BtCursor*, int *pRes); int sqlite3BtreeNext(BtCursor*, int *pRes); int sqlite3BtreeEof(BtCursor*); int sqlite3BtreePrevious(BtCursor*, int *pRes); i64 sqlite3BtreeIntegerKey(BtCursor*); | > > | < > > | 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 | ** organized and understandable, and it also helps the resulting code to ** run a little faster by using fewer registers for parameter passing. */ struct BtreePayload { const void *pKey; /* Key content for indexes. NULL for tables */ sqlite3_int64 nKey; /* Size of pKey for indexes. PRIMARY KEY for tabs */ const void *pData; /* Data for tables. NULL for indexes */ struct Mem *aMem; /* First of nMem value in the unpacked pKey */ u16 nMem; /* Number of aMem[] value. Might be zero */ int nData; /* Size of pData. 0 if none. */ int nZero; /* Extra zero data appended after pData,nData */ }; int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload, int bias, int seekResult); int sqlite3BtreeFirst(BtCursor*, int *pRes); int sqlite3BtreeLast(BtCursor*, int *pRes); int sqlite3BtreeNext(BtCursor*, int *pRes); int sqlite3BtreeEof(BtCursor*); int sqlite3BtreePrevious(BtCursor*, int *pRes); i64 sqlite3BtreeIntegerKey(BtCursor*); int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*); const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt); u32 sqlite3BtreePayloadSize(BtCursor*); char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*); struct Pager *sqlite3BtreePager(Btree*); #ifndef SQLITE_OMIT_INCRBLOB int sqlite3BtreePayloadChecked(BtCursor*, u32 offset, u32 amt, void*); int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); void sqlite3BtreeIncrblobCursor(BtCursor *); #endif void sqlite3BtreeClearCursor(BtCursor *); int sqlite3BtreeSetVersion(Btree *pBt, int iVersion); int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask); int sqlite3BtreeIsReadonly(Btree *pBt); int sqlite3HeaderSizeBtree(void); #ifndef NDEBUG int sqlite3BtreeCursorIsValid(BtCursor*); #endif int sqlite3BtreeCursorIsValidNN(BtCursor*); #ifndef SQLITE_OMIT_BTREECOUNT int sqlite3BtreeCount(BtCursor *, i64 *); #endif #ifdef SQLITE_TEST int sqlite3BtreeCursorInfo(BtCursor*, int*, int); |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
55 56 57 58 59 60 61 62 63 64 65 66 67 68 | ){ Parse *pToplevel = sqlite3ParseToplevel(pParse); int i; int nBytes; TableLock *p; assert( iDb>=0 ); for(i=0; i<pToplevel->nTableLock; i++){ p = &pToplevel->aTableLock[i]; if( p->iDb==iDb && p->iTab==iTab ){ p->isWriteLock = (p->isWriteLock || isWriteLock); return; } } | > > | 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | ){ Parse *pToplevel = sqlite3ParseToplevel(pParse); int i; int nBytes; TableLock *p; assert( iDb>=0 ); if( iDb==1 ) return; if( !sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return; for(i=0; i<pToplevel->nTableLock; i++){ p = &pToplevel->aTableLock[i]; if( p->iDb==iDb && p->iTab==iTab ){ p->isWriteLock = (p->isWriteLock || isWriteLock); return; } } |
︙ | ︙ | |||
2812 2813 2814 2815 2816 2817 2818 | pIndex->nKeyCol); VdbeCoverage(v); sqlite3UniqueConstraint(pParse, OE_Abort, pIndex); }else{ addr2 = sqlite3VdbeCurrentAddr(v); } sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx); sqlite3VdbeAddOp3(v, OP_Last, iIdx, 0, -1); | | | 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 | pIndex->nKeyCol); VdbeCoverage(v); sqlite3UniqueConstraint(pParse, OE_Abort, pIndex); }else{ addr2 = sqlite3VdbeCurrentAddr(v); } sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx); sqlite3VdbeAddOp3(v, OP_Last, iIdx, 0, -1); sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); sqlite3ReleaseTempReg(pParse, regRecord); sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp1(v, OP_Close, iTab); sqlite3VdbeAddOp1(v, OP_Close, iIdx); |
︙ | ︙ |
Changes to src/delete.c.
︙ | ︙ | |||
445 446 447 448 449 450 451 | }else{ if( pPk ){ /* Add the PK key for this row to the temporary table */ iKey = ++pParse->nMem; nKey = 0; /* Zero tells OP_Found to use a composite key */ sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey, sqlite3IndexAffinityStr(pParse->db, pPk), nPk); | | | 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 | }else{ if( pPk ){ /* Add the PK key for this row to the temporary table */ iKey = ++pParse->nMem; nKey = 0; /* Zero tells OP_Found to use a composite key */ sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey, sqlite3IndexAffinityStr(pParse->db, pPk), nPk); sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEphCur, iKey, iPk, nPk); }else{ /* Add the rowid of the row to be deleted to the RowSet */ nKey = 1; /* OP_Seek always uses a single rowid */ sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey); } } |
︙ | ︙ | |||
491 492 493 494 495 496 497 | if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){ assert( pPk!=0 || pTab->pSelect!=0 ); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey); VdbeCoverage(v); } }else if( pPk ){ addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v); | | | 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 | if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){ assert( pPk!=0 || pTab->pSelect!=0 ); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey); VdbeCoverage(v); } }else if( pPk ){ addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_RowData, iEphCur, iKey); assert( nKey==0 ); /* OP_Found will use a composite key */ }else{ addrLoop = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, 0, iKey); VdbeCoverage(v); assert( nKey==1 ); } |
︙ | ︙ | |||
534 535 536 537 538 539 540 | }else if( pPk ){ sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addrLoop); }else{ sqlite3VdbeGoto(v, addrLoop); sqlite3VdbeJumpHere(v, addrLoop); } | < < < < < < < < | 534 535 536 537 538 539 540 541 542 543 544 545 546 547 | }else if( pPk ){ sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addrLoop); }else{ sqlite3VdbeGoto(v, addrLoop); sqlite3VdbeJumpHere(v, addrLoop); } } /* End non-truncate path */ /* Update the sqlite_sequence table by storing the content of the ** maximum rowid counter values recorded while inserting into ** autoincrement tables. */ if( pParse->nested==0 && pParse->pTriggerTab==0 ){ |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
2534 2535 2536 2537 2538 2539 2540 | sqlite3VdbeAddOp2(v, OP_MustBeInt, r3, sqlite3VdbeCurrentAddr(v)+2); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3); }else{ sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); sqlite3ExprCacheAffinityChange(pParse, r3, 1); | | | 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 | sqlite3VdbeAddOp2(v, OP_MustBeInt, r3, sqlite3VdbeCurrentAddr(v)+2); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3); }else{ sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); sqlite3ExprCacheAffinityChange(pParse, r3, 1); sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pExpr->iTable, r2, r3, 1); } } } sqlite3ReleaseTempReg(pParse, r1); sqlite3ReleaseTempReg(pParse, r2); } if( pKeyInfo ){ |
︙ | ︙ | |||
3292 3293 3294 3295 3296 3297 3298 | if( p->op==TK_SELECT ){ iResult = sqlite3CodeSubselect(pParse, p, 0, 0); }else{ int i; iResult = pParse->nMem+1; pParse->nMem += nResult; for(i=0; i<nResult; i++){ | | | 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 | if( p->op==TK_SELECT ){ iResult = sqlite3CodeSubselect(pParse, p, 0, 0); }else{ int i; iResult = pParse->nMem+1; pParse->nMem += nResult; for(i=0; i<nResult; i++){ sqlite3ExprCodeFactorable(pParse, p->x.pList->a[i].pExpr, i+iResult); } } } return iResult; } |
︙ | ︙ | |||
4082 4083 4084 4085 4086 4087 4088 | assert( pList!=0 ); assert( target>0 ); assert( pParse->pVdbe!=0 ); /* Never gets this far otherwise */ n = pList->nExpr; if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR; for(pItem=pList->a, i=0; i<n; i++, pItem++){ Expr *pExpr = pItem->pExpr; | | > > > > | > | 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 | assert( pList!=0 ); assert( target>0 ); assert( pParse->pVdbe!=0 ); /* Never gets this far otherwise */ n = pList->nExpr; if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR; for(pItem=pList->a, i=0; i<n; i++, pItem++){ Expr *pExpr = pItem->pExpr; if( (flags & SQLITE_ECEL_REF)!=0 && (j = pItem->u.x.iOrderByCol)>0 ){ if( flags & SQLITE_ECEL_OMITREF ){ i--; n--; }else{ sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i); } }else if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){ sqlite3ExprCodeAtInit(pParse, pExpr, target+i, 0); }else{ int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i); if( inReg!=target+i ){ VdbeOp *pOp; if( copyOp==OP_Copy |
︙ | ︙ | |||
4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 | compRight.op = TK_LE; compRight.pLeft = &exprX; compRight.pRight = pExpr->x.pList->a[1].pExpr; exprToRegister(&exprX, exprCodeVector(pParse, &exprX, ®Free1)); if( xJump ){ xJump(pParse, &exprAnd, dest, jumpIfNull); }else{ exprX.flags |= EP_FromJoin; sqlite3ExprCodeTarget(pParse, &exprAnd, dest); } sqlite3ReleaseTempReg(pParse, regFree1); /* Ensure adequate test coverage */ testcase( xJump==sqlite3ExprIfTrue && jumpIfNull==0 && regFree1==0 ); | > > > > > | 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 | compRight.op = TK_LE; compRight.pLeft = &exprX; compRight.pRight = pExpr->x.pList->a[1].pExpr; exprToRegister(&exprX, exprCodeVector(pParse, &exprX, ®Free1)); if( xJump ){ xJump(pParse, &exprAnd, dest, jumpIfNull); }else{ /* Mark the expression is being from the ON or USING clause of a join ** so that the sqlite3ExprCodeTarget() routine will not attempt to move ** it into the Parse.pConstExpr list. We should use a new bit for this, ** for clarity, but we are out of bits in the Expr.flags field so we ** have to reuse the EP_FromJoin bit. Bummer. */ exprX.flags |= EP_FromJoin; sqlite3ExprCodeTarget(pParse, &exprAnd, dest); } sqlite3ReleaseTempReg(pParse, regFree1); /* Ensure adequate test coverage */ testcase( xJump==sqlite3ExprIfTrue && jumpIfNull==0 && regFree1==0 ); |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
481 482 483 484 485 486 487 | Select *pSelect, /* A SELECT statement to use as the data source */ IdList *pColumn, /* Column names corresponding to IDLIST. */ int onError /* How to handle constraint errors */ ){ sqlite3 *db; /* The main database structure */ Table *pTab; /* The table to insert into. aka TABLE */ char *zTab; /* Name of the table into which we are inserting */ | | | 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 | Select *pSelect, /* A SELECT statement to use as the data source */ IdList *pColumn, /* Column names corresponding to IDLIST. */ int onError /* How to handle constraint errors */ ){ sqlite3 *db; /* The main database structure */ Table *pTab; /* The table to insert into. aka TABLE */ char *zTab; /* Name of the table into which we are inserting */ int i, j; /* Loop counters */ Vdbe *v; /* Generate code into this virtual machine */ Index *pIdx; /* For looping over indices of the table */ int nColumn; /* Number of columns in the data */ int nHidden = 0; /* Number of hidden columns if TABLE is virtual */ int iDataCur = 0; /* VDBE cursor that is the main data repository */ int iIdxCur = 0; /* First index cursor */ int ipkColumn = -1; /* Column that is the INTEGER PRIMARY KEY */ |
︙ | ︙ | |||
788 789 790 791 792 793 794 | int nIdx; nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, -1, 0, &iDataCur, &iIdxCur); aRegIdx = sqlite3DbMallocRawNN(db, sizeof(int)*(nIdx+1)); if( aRegIdx==0 ){ goto insert_cleanup; } | | > > | 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 | int nIdx; nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, -1, 0, &iDataCur, &iIdxCur); aRegIdx = sqlite3DbMallocRawNN(db, sizeof(int)*(nIdx+1)); if( aRegIdx==0 ){ goto insert_cleanup; } for(i=0, pIdx=pTab->pIndex; i<nIdx; pIdx=pIdx->pNext, i++){ assert( pIdx ); aRegIdx[i] = ++pParse->nMem; pParse->nMem += pIdx->nColumn; } } /* This is the top of the main insertion loop */ if( useTempTable ){ /* This block codes the top of loop only. The complete loop is the ** following pseudocode (template 4): |
︙ | ︙ | |||
991 992 993 994 995 996 997 998 999 1000 1001 1002 | sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, pVTab, P4_VTAB); sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError); sqlite3MayAbort(pParse); }else #endif { int isReplace; /* Set to true if constraints may cause a replace */ sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0 ); sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0); sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur, | > > > > > > > > > > > > > | > | 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 | sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, pVTab, P4_VTAB); sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError); sqlite3MayAbort(pParse); }else #endif { int isReplace; /* Set to true if constraints may cause a replace */ int bUseSeek; /* True to use OPFLAG_SEEKRESULT */ sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0 ); sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0); /* Set the OPFLAG_USESEEKRESULT flag if either (a) there are no REPLACE ** constraints or (b) there are no triggers and this table is not a ** parent table in a foreign key constraint. It is safe to set the ** flag in the second case as if any REPLACE constraint is hit, an ** OP_Delete or OP_IdxDelete instruction will be executed on each ** cursor that is disturbed. And these instructions both clear the ** VdbeCursor.seekResult variable, disabling the OPFLAG_USESEEKRESULT ** functionality. */ bUseSeek = (isReplace==0 || (pTrigger==0 && ((db->flags & SQLITE_ForeignKeys)==0 || sqlite3FkReferences(pTab)==0) )); sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur, regIns, aRegIdx, 0, appendFlag, bUseSeek ); } } /* Update the count of rows that are inserted */ if( (db->flags & SQLITE_CountRows)!=0 ){ sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); |
︙ | ︙ | |||
1025 1026 1027 1028 1029 1030 1031 | sqlite3VdbeJumpHere(v, addrInsTop); sqlite3VdbeAddOp1(v, OP_Close, srcTab); }else if( pSelect ){ sqlite3VdbeGoto(v, addrCont); sqlite3VdbeJumpHere(v, addrInsTop); } | < < < < < < < < | 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 | sqlite3VdbeJumpHere(v, addrInsTop); sqlite3VdbeAddOp1(v, OP_Close, srcTab); }else if( pSelect ){ sqlite3VdbeGoto(v, addrCont); sqlite3VdbeJumpHere(v, addrInsTop); } insert_end: /* Update the sqlite_sequence table by storing the content of the ** maximum rowid counter values recorded while inserting into ** autoincrement tables. */ if( pParse->nested==0 && pParse->pTriggerTab==0 ){ sqlite3AutoincrementEnd(pParse); |
︙ | ︙ | |||
1239 1240 1241 1242 1243 1244 1245 | int addr1; /* Address of jump instruction */ int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */ int nPkField; /* Number of fields in PRIMARY KEY. 1 for ROWID tables */ int ipkTop = 0; /* Top of the rowid change constraint check */ int ipkBottom = 0; /* Bottom of the rowid change constraint check */ u8 isUpdate; /* True if this is an UPDATE operation */ u8 bAffinityDone = 0; /* True if the OP_Affinity operation has been run */ | < | 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 | int addr1; /* Address of jump instruction */ int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */ int nPkField; /* Number of fields in PRIMARY KEY. 1 for ROWID tables */ int ipkTop = 0; /* Top of the rowid change constraint check */ int ipkBottom = 0; /* Bottom of the rowid change constraint check */ u8 isUpdate; /* True if this is an UPDATE operation */ u8 bAffinityDone = 0; /* True if the OP_Affinity operation has been run */ isUpdate = regOldData!=0; db = pParse->db; v = sqlite3GetVdbe(pParse); assert( v!=0 ); assert( pTab->pSelect==0 ); /* This table is not a VIEW */ nCol = pTab->nCol; |
︙ | ︙ | |||
1359 1360 1361 1362 1363 1364 1365 | if( overrideError!=OE_Default ){ onError = overrideError; }else if( onError==OE_Default ){ onError = OE_Abort; } if( isUpdate ){ | | | 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 | if( overrideError!=OE_Default ){ onError = overrideError; }else if( onError==OE_Default ){ onError = OE_Abort; } if( isUpdate ){ /* pkChng!=0 does not mean that the rowid has changed, only that ** it might have changed. Skip the conflict logic below if the rowid ** is unchanged. */ sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRowidOk, regOldData); sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); VdbeCoverage(v); } |
︙ | ︙ | |||
1494 1495 1496 1497 1498 1499 1500 | SQLITE_JUMPIFNULL); pParse->ckBase = 0; } /* Create a record for this index entry as it should appear after ** the insert or update. Store that record in the aRegIdx[ix] register */ | | < < < < > > > > > > | 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 | SQLITE_JUMPIFNULL); pParse->ckBase = 0; } /* Create a record for this index entry as it should appear after ** the insert or update. Store that record in the aRegIdx[ix] register */ regIdx = aRegIdx[ix]+1; for(i=0; i<pIdx->nColumn; i++){ int iField = pIdx->aiColumn[i]; int x; if( iField==XN_EXPR ){ pParse->ckBase = regNewData+1; sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i); pParse->ckBase = 0; VdbeComment((v, "%s column %d", pIdx->zName, i)); }else{ if( iField==XN_ROWID || iField==pTab->iPKey ){ x = regNewData; }else{ x = iField + regNewData + 1; } sqlite3VdbeAddOp2(v, iField<0 ? OP_IntCopy : OP_SCopy, x, regIdx+i); VdbeComment((v, "%s", iField<0 ? "rowid" : pTab->aCol[iField].zName)); } } sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]); VdbeComment((v, "for %s", pIdx->zName)); /* In an UPDATE operation, if this index is the PRIMARY KEY index ** of a WITHOUT ROWID table and there has been no change the ** primary key, then no collision is possible. The collision detection ** logic below can all be skipped. */ if( isUpdate && pPk==pIdx && pkChng==0 ){ sqlite3VdbeResolveLabel(v, addrUniqueOk); continue; } /* Find out what action to take in case there is a uniqueness conflict */ onError = pIdx->onError; if( onError==OE_None ){ sqlite3VdbeResolveLabel(v, addrUniqueOk); continue; /* pIdx is not a UNIQUE index */ } if( overrideError!=OE_Default ){ onError = overrideError; }else if( onError==OE_Default ){ onError = OE_Abort; } if( ix==0 && pPk==pIdx && onError==OE_Replace && pPk->pNext==0 ){ sqlite3VdbeResolveLabel(v, addrUniqueOk); continue; } /* Check to see if the new index entry will be unique */ sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk, regIdx, pIdx->nKeyCol); VdbeCoverage(v); /* Generate code to handle collisions */ regR = (pIdx==pPk) ? regIdx : sqlite3GetTempRange(pParse, nPkField); |
︙ | ︙ | |||
1630 1631 1632 1633 1634 1635 1636 | regR, nPkField, 0, OE_Replace, (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), -1); seenReplace = 1; break; } } sqlite3VdbeResolveLabel(v, addrUniqueOk); | < | 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 | regR, nPkField, 0, OE_Replace, (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), -1); seenReplace = 1; break; } } sqlite3VdbeResolveLabel(v, addrUniqueOk); if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField); } if( ipkTop ){ sqlite3VdbeGoto(v, ipkTop+1); sqlite3VdbeJumpHere(v, ipkBottom); } |
︙ | ︙ | |||
1680 1681 1682 1683 1684 1685 1686 | for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ if( aRegIdx[i]==0 ) continue; bAffinityDone = 1; if( pIdx->pPartIdxWhere ){ sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2); VdbeCoverage(v); } | | > > | > | > | 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 | for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ if( aRegIdx[i]==0 ) continue; bAffinityDone = 1; if( pIdx->pPartIdxWhere ){ sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2); VdbeCoverage(v); } sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i], aRegIdx[i]+1, pIdx->uniqNotNull ? pIdx->nKeyCol: pIdx->nColumn); pik_flags = 0; if( useSeekResult ) pik_flags = OPFLAG_USESEEKRESULT; if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ assert( pParse->nested==0 ); pik_flags |= OPFLAG_NCHANGE; } sqlite3VdbeChangeP5(v, pik_flags); } if( !HasRowid(pTab) ) return; regData = regNewData + 1; regRec = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec); if( !bAffinityDone ){ sqlite3TableAffinity(v, pTab, 0); sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol); } if( pParse->nested ){ pik_flags = 0; }else{ pik_flags = OPFLAG_NCHANGE; pik_flags |= (isUpdate?OPFLAG_ISUPDATE:OPFLAG_LASTROWID); } if( appendBias ){ |
︙ | ︙ | |||
2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 | ** (3) onError is something other than OE_Abort and OE_Rollback. */ addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0); VdbeCoverage(v); emptyDestTest = sqlite3VdbeAddOp0(v, OP_Goto); sqlite3VdbeJumpHere(v, addr1); } if( HasRowid(pSrc) ){ sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead); emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); if( pDest->iPKey>=0 ){ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid); VdbeCoverage(v); sqlite3RowidConstraint(pParse, onError, pDest); sqlite3VdbeJumpHere(v, addr2); autoIncStep(pParse, regAutoinc, regRowid); }else if( pDest->pIndex==0 ){ addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid); }else{ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); assert( (pDest->tabFlags & TF_Autoincrement)==0 ); } sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData); sqlite3VdbeAddOp4(v, OP_Insert, iDest, regData, regRowid, (char*)pDest, P4_TABLE); | > > > > > > > > | | 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 | ** (3) onError is something other than OE_Abort and OE_Rollback. */ addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0); VdbeCoverage(v); emptyDestTest = sqlite3VdbeAddOp0(v, OP_Goto); sqlite3VdbeJumpHere(v, addr1); } if( HasRowid(pSrc) ){ u8 insFlags; sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead); emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); if( pDest->iPKey>=0 ){ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid); VdbeCoverage(v); sqlite3RowidConstraint(pParse, onError, pDest); sqlite3VdbeJumpHere(v, addr2); autoIncStep(pParse, regAutoinc, regRowid); }else if( pDest->pIndex==0 ){ addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid); }else{ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); assert( (pDest->tabFlags & TF_Autoincrement)==0 ); } sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData); if( db->flags & SQLITE_Vacuum ){ sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1); insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID| OPFLAG_APPEND|OPFLAG_USESEEKRESULT; }else{ insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND; } sqlite3VdbeAddOp4(v, OP_Insert, iDest, regData, regRowid, (char*)pDest, P4_TABLE); sqlite3VdbeChangeP5(v, insFlags); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); }else{ sqlite3TableLock(pParse, iDbDest, pDest->tnum, 1, pDest->zName); sqlite3TableLock(pParse, iDbSrc, pSrc->tnum, 0, pSrc->zName); } |
︙ | ︙ | |||
2132 2133 2134 2135 2136 2137 2138 | sqlite3VdbeSetP4KeyInfo(pParse, pSrcIdx); VdbeComment((v, "%s", pSrcIdx->zName)); sqlite3VdbeAddOp3(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest); sqlite3VdbeSetP4KeyInfo(pParse, pDestIdx); sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR); VdbeComment((v, "%s", pDestIdx->zName)); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); | | | 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 | sqlite3VdbeSetP4KeyInfo(pParse, pSrcIdx); VdbeComment((v, "%s", pSrcIdx->zName)); sqlite3VdbeAddOp3(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest); sqlite3VdbeSetP4KeyInfo(pParse, pDestIdx); sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR); VdbeComment((v, "%s", pDestIdx->zName)); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData); if( db->flags & SQLITE_Vacuum ){ /* This INSERT command is part of a VACUUM operation, which guarantees ** that the destination table is empty. If all indexed columns use ** collation sequence BINARY, then it can also be assumed that the ** index will be populated by inserting keys in strictly sorted ** order. In this case, instead of seeking within the b-tree as part ** of every OP_IdxInsert opcode, an OP_Last is added before the |
︙ | ︙ | |||
2162 2163 2164 2165 2166 2167 2168 | idxInsFlags = OPFLAG_USESEEKRESULT; sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1); } } if( !HasRowid(pSrc) && pDestIdx->idxType==2 ){ idxInsFlags |= OPFLAG_NCHANGE; } | | | | 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 | idxInsFlags = OPFLAG_USESEEKRESULT; sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1); } } if( !HasRowid(pSrc) && pDestIdx->idxType==2 ){ idxInsFlags |= OPFLAG_NCHANGE; } sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData); sqlite3VdbeChangeP5(v, idxInsFlags|OPFLAG_APPEND); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); } if( emptySrcTest ) sqlite3VdbeJumpHere(v, emptySrcTest); sqlite3ReleaseTempReg(pParse, regRowid); |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
4131 4132 4133 4134 4135 4136 4137 | int sqlite3_snapshot_get( sqlite3 *db, const char *zDb, sqlite3_snapshot **ppSnapshot ){ int rc = SQLITE_ERROR; #ifndef SQLITE_OMIT_WAL | < > | | | | | | | > | 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 | int sqlite3_snapshot_get( sqlite3 *db, const char *zDb, sqlite3_snapshot **ppSnapshot ){ int rc = SQLITE_ERROR; #ifndef SQLITE_OMIT_WAL #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ return SQLITE_MISUSE_BKPT; } #endif sqlite3_mutex_enter(db->mutex); if( db->autoCommit==0 ){ int iDb = sqlite3FindDbName(db, zDb); if( iDb==0 || iDb>1 ){ Btree *pBt = db->aDb[iDb].pBt; if( 0==sqlite3BtreeIsInTrans(pBt) ){ rc = sqlite3BtreeBeginTrans(pBt, 0); if( rc==SQLITE_OK ){ rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot); } } } } sqlite3_mutex_leave(db->mutex); #endif /* SQLITE_OMIT_WAL */ return rc; |
︙ | ︙ | |||
4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 | rc = sqlite3BtreeBeginTrans(pBt, 0); sqlite3PagerSnapshotOpen(sqlite3BtreePager(pBt), 0); } } } } sqlite3_mutex_leave(db->mutex); #endif /* SQLITE_OMIT_WAL */ return rc; } /* ** Free a snapshot handle obtained from sqlite3_snapshot_get(). */ void sqlite3_snapshot_free(sqlite3_snapshot *pSnapshot){ sqlite3_free(pSnapshot); } #endif /* SQLITE_ENABLE_SNAPSHOT */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 | rc = sqlite3BtreeBeginTrans(pBt, 0); sqlite3PagerSnapshotOpen(sqlite3BtreePager(pBt), 0); } } } } sqlite3_mutex_leave(db->mutex); #endif /* SQLITE_OMIT_WAL */ return rc; } /* ** Recover as many snapshots as possible from the wal file associated with ** schema zDb of database db. */ int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb){ int rc = SQLITE_ERROR; int iDb; #ifndef SQLITE_OMIT_WAL #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ return SQLITE_MISUSE_BKPT; } #endif sqlite3_mutex_enter(db->mutex); iDb = sqlite3FindDbName(db, zDb); if( iDb==0 || iDb>1 ){ Btree *pBt = db->aDb[iDb].pBt; if( 0==sqlite3BtreeIsInReadTrans(pBt) ){ rc = sqlite3BtreeBeginTrans(pBt, 0); if( rc==SQLITE_OK ){ rc = sqlite3PagerSnapshotRecover(sqlite3BtreePager(pBt)); sqlite3BtreeCommit(pBt); } } } sqlite3_mutex_leave(db->mutex); #endif /* SQLITE_OMIT_WAL */ return rc; } /* ** Free a snapshot handle obtained from sqlite3_snapshot_get(). */ void sqlite3_snapshot_free(sqlite3_snapshot *pSnapshot){ sqlite3_free(pSnapshot); } #endif /* SQLITE_ENABLE_SNAPSHOT */ |
Changes to src/pager.c.
︙ | ︙ | |||
4041 4042 4043 4044 4045 4046 4047 | assert( assert_pager_state(pPager) ); disable_simulated_io_errors(); sqlite3BeginBenignMalloc(); pagerFreeMapHdrs(pPager); /* pPager->errCode = 0; */ pPager->exclusiveMode = 0; #ifndef SQLITE_OMIT_WAL | > | > > | 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 | assert( assert_pager_state(pPager) ); disable_simulated_io_errors(); sqlite3BeginBenignMalloc(); pagerFreeMapHdrs(pPager); /* pPager->errCode = 0; */ pPager->exclusiveMode = 0; #ifndef SQLITE_OMIT_WAL assert( db || pPager->pWal==0 ); sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags, pPager->pageSize, (db && (db->flags & SQLITE_NoCkptOnClose) ? 0 : pTmp) ); pPager->pWal = 0; #endif pager_reset(pPager); if( MEMDB ){ pager_unlock(pPager); }else{ /* If it is open, sync the journal file before calling UnlockAndRollback. |
︙ | ︙ | |||
7447 7448 7449 7450 7451 7452 7453 7454 7455 7456 7457 7458 7459 7460 | if( pPager->pWal ){ sqlite3WalSnapshotOpen(pPager->pWal, pSnapshot); }else{ rc = SQLITE_ERROR; } return rc; } #endif /* SQLITE_ENABLE_SNAPSHOT */ #endif /* !SQLITE_OMIT_WAL */ #ifdef SQLITE_ENABLE_ZIPVFS /* ** A read-lock must be held on the pager when this function is called. If ** the pager is in WAL mode and the WAL file currently contains one or more | > > > > > > > > > > > > > > | 7450 7451 7452 7453 7454 7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474 7475 7476 7477 | if( pPager->pWal ){ sqlite3WalSnapshotOpen(pPager->pWal, pSnapshot); }else{ rc = SQLITE_ERROR; } return rc; } /* ** If this is a WAL database, call sqlite3WalSnapshotRecover(). If this ** is not a WAL database, return an error. */ int sqlite3PagerSnapshotRecover(Pager *pPager){ int rc; if( pPager->pWal ){ rc = sqlite3WalSnapshotRecover(pPager->pWal); }else{ rc = SQLITE_ERROR; } return rc; } #endif /* SQLITE_ENABLE_SNAPSHOT */ #endif /* !SQLITE_OMIT_WAL */ #ifdef SQLITE_ENABLE_ZIPVFS /* ** A read-lock must be held on the pager when this function is called. If ** the pager is in WAL mode and the WAL file currently contains one or more |
︙ | ︙ |
Changes to src/pager.h.
︙ | ︙ | |||
178 179 180 181 182 183 184 185 186 187 188 189 190 191 | int sqlite3PagerWalCallback(Pager *pPager); int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); int sqlite3PagerCloseWal(Pager *pPager, sqlite3*); int sqlite3PagerUseWal(Pager *pPager); # ifdef SQLITE_ENABLE_SNAPSHOT int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot); int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot); # endif #else # define sqlite3PagerUseWal(x) 0 #endif #ifdef SQLITE_ENABLE_ZIPVFS int sqlite3PagerWalFramesize(Pager *pPager); | > | 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 | int sqlite3PagerWalCallback(Pager *pPager); int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); int sqlite3PagerCloseWal(Pager *pPager, sqlite3*); int sqlite3PagerUseWal(Pager *pPager); # ifdef SQLITE_ENABLE_SNAPSHOT int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot); int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot); int sqlite3PagerSnapshotRecover(Pager *pPager); # endif #else # define sqlite3PagerUseWal(x) 0 #endif #ifdef SQLITE_ENABLE_ZIPVFS int sqlite3PagerWalFramesize(Pager *pPager); |
︙ | ︙ |
Changes to src/printf.c.
︙ | ︙ | |||
857 858 859 860 861 862 863 864 865 866 867 868 | /* ** Finish off a string by making sure it is zero-terminated. ** Return a pointer to the resulting string. Return a NULL ** pointer if any kind of error was encountered. */ char *sqlite3StrAccumFinish(StrAccum *p){ if( p->zText ){ assert( (p->zText==p->zBase)==!isMalloced(p) ); p->zText[p->nChar] = 0; if( p->mxAlloc>0 && !isMalloced(p) ){ | > > > > > > > > > > > < < < < < | < | 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 | /* ** Finish off a string by making sure it is zero-terminated. ** Return a pointer to the resulting string. Return a NULL ** pointer if any kind of error was encountered. */ static SQLITE_NOINLINE char *strAccumFinishRealloc(StrAccum *p){ assert( p->mxAlloc>0 && !isMalloced(p) ); p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); if( p->zText ){ memcpy(p->zText, p->zBase, p->nChar+1); p->printfFlags |= SQLITE_PRINTF_MALLOCED; }else{ setStrAccumError(p, STRACCUM_NOMEM); } return p->zText; } char *sqlite3StrAccumFinish(StrAccum *p){ if( p->zText ){ assert( (p->zText==p->zBase)==!isMalloced(p) ); p->zText[p->nChar] = 0; if( p->mxAlloc>0 && !isMalloced(p) ){ return strAccumFinishRealloc(p); } } return p->zText; } /* ** Reset an StrAccum string. Reclaim all malloced memory. |
︙ | ︙ | |||
1008 1009 1010 1011 1012 1013 1014 | (void)SQLITE_MISUSE_BKPT; if( zBuf ) zBuf[0] = 0; return zBuf; } #endif sqlite3StrAccumInit(&acc, 0, zBuf, n, 0); sqlite3VXPrintf(&acc, zFormat, ap); | > | | 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 | (void)SQLITE_MISUSE_BKPT; if( zBuf ) zBuf[0] = 0; return zBuf; } #endif sqlite3StrAccumInit(&acc, 0, zBuf, n, 0); sqlite3VXPrintf(&acc, zFormat, ap); zBuf[acc.nChar] = 0; return zBuf; } char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ char *z; va_list ap; va_start(ap,zFormat); z = sqlite3_vsnprintf(n, zBuf, zFormat, ap); va_end(ap); |
︙ | ︙ |
Changes to src/resolve.c.
︙ | ︙ | |||
395 396 397 398 399 400 401 402 403 404 405 406 407 408 | assert( pExpr->pLeft==0 && pExpr->pRight==0 ); assert( pExpr->x.pList==0 ); assert( pExpr->x.pSelect==0 ); pOrig = pEList->a[j].pExpr; if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){ sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs); return WRC_Abort; } resolveAlias(pParse, pEList, j, pExpr, "", nSubquery); cnt = 1; pMatch = 0; assert( zTab==0 && zDb==0 ); goto lookupname_end; } | > > > > | 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 | assert( pExpr->pLeft==0 && pExpr->pRight==0 ); assert( pExpr->x.pList==0 ); assert( pExpr->x.pSelect==0 ); pOrig = pEList->a[j].pExpr; if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){ sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs); return WRC_Abort; } if( sqlite3ExprVectorSize(pOrig)!=1 ){ sqlite3ErrorMsg(pParse, "row value misused"); return WRC_Abort; } resolveAlias(pParse, pEList, j, pExpr, "", nSubquery); cnt = 1; pMatch = 0; assert( zTab==0 && zDb==0 ); goto lookupname_end; } |
︙ | ︙ | |||
772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 | } break; } case TK_VARIABLE: { notValid(pParse, pNC, "parameters", NC_IsCheck|NC_PartIdx|NC_IdxExpr); break; } case TK_EQ: case TK_NE: case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_IS: case TK_ISNOT: { int nLeft, nRight; if( pParse->db->mallocFailed ) break; | > < > > > > > > > | > > | 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 | } break; } case TK_VARIABLE: { notValid(pParse, pNC, "parameters", NC_IsCheck|NC_PartIdx|NC_IdxExpr); break; } case TK_BETWEEN: case TK_EQ: case TK_NE: case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_IS: case TK_ISNOT: { int nLeft, nRight; if( pParse->db->mallocFailed ) break; assert( pExpr->pLeft!=0 ); nLeft = sqlite3ExprVectorSize(pExpr->pLeft); if( pExpr->op==TK_BETWEEN ){ nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[0].pExpr); if( nRight==nLeft ){ nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[1].pExpr); } }else{ assert( pExpr->pRight!=0 ); nRight = sqlite3ExprVectorSize(pExpr->pRight); } if( nLeft!=nRight ){ testcase( pExpr->op==TK_EQ ); testcase( pExpr->op==TK_NE ); testcase( pExpr->op==TK_LT ); testcase( pExpr->op==TK_LE ); testcase( pExpr->op==TK_GT ); testcase( pExpr->op==TK_GE ); testcase( pExpr->op==TK_IS ); testcase( pExpr->op==TK_ISNOT ); testcase( pExpr->op==TK_BETWEEN ); sqlite3ErrorMsg(pParse, "row value misused"); } break; } } return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue; } |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
517 518 519 520 521 522 523 | int regBase; /* Regs for sorter record */ int regRecord = ++pParse->nMem; /* Assembled sorter record */ int nOBSat = pSort->nOBSat; /* ORDER BY terms to skip */ int op; /* Opcode to add sorter record to sorter */ int iLimit; /* LIMIT counter */ assert( bSeq==0 || bSeq==1 ); | | | | | 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 | int regBase; /* Regs for sorter record */ int regRecord = ++pParse->nMem; /* Assembled sorter record */ int nOBSat = pSort->nOBSat; /* ORDER BY terms to skip */ int op; /* Opcode to add sorter record to sorter */ int iLimit; /* LIMIT counter */ assert( bSeq==0 || bSeq==1 ); assert( nData==1 || regData==regOrigData || regOrigData==0 ); if( nPrefixReg ){ assert( nPrefixReg==nExpr+bSeq ); regBase = regData - nExpr - bSeq; }else{ regBase = pParse->nMem + 1; pParse->nMem += nBase; } assert( pSelect->iOffset==0 || pSelect->iLimit!=0 ); iLimit = pSelect->iOffset ? pSelect->iOffset+1 : pSelect->iLimit; pSort->labelDone = sqlite3VdbeMakeLabel(v); sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, regOrigData, SQLITE_ECEL_DUP | (regOrigData? SQLITE_ECEL_REF : 0)); if( bSeq ){ sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr); } if( nPrefixReg==0 && nData>0 ){ sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData); } sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regRecord); if( nOBSat>0 ){ int regPrevKey; /* The first nOBSat columns of the previous row */ int addrFirst; /* Address of the OP_IfNot opcode */ int addrJmp; /* Address of the OP_Jump opcode */ |
︙ | ︙ | |||
583 584 585 586 587 588 589 | sqlite3VdbeJumpHere(v, addrJmp); } if( pSort->sortFlags & SORTFLAG_UseSorter ){ op = OP_SorterInsert; }else{ op = OP_IdxInsert; } | | > | 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 | sqlite3VdbeJumpHere(v, addrJmp); } if( pSort->sortFlags & SORTFLAG_UseSorter ){ op = OP_SorterInsert; }else{ op = OP_IdxInsert; } sqlite3VdbeAddOp4Int(v, op, pSort->iECursor, regRecord, regBase+nOBSat, nBase-nOBSat); if( iLimit ){ int addr; int r1 = 0; /* Fill the sorter until it contains LIMIT+OFFSET entries. (The iLimit ** register is initialized with value of LIMIT+OFFSET.) After the sorter ** fills up, delete the least entry in the sorter after each insert. ** Thus we never hold more than the LIMIT+OFFSET rows in memory at once */ |
︙ | ︙ | |||
651 652 653 654 655 656 657 | Vdbe *v; int r1; v = pParse->pVdbe; r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1); | | | | < > > > > > > > > | 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 | Vdbe *v; int r1; v = pParse->pVdbe; r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1); sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r1, iMem, N); sqlite3ReleaseTempReg(pParse, r1); } /* ** This routine generates the code for the inside of the inner loop ** of a SELECT. ** ** If srcTab is negative, then the pEList expressions ** are evaluated in order to get the data for this row. If srcTab is ** zero or more, then data is pulled from srcTab and pEList is used only ** to get the number of columns and the collation sequence for each column. */ static void selectInnerLoop( Parse *pParse, /* The parser context */ Select *p, /* The complete select statement being coded */ ExprList *pEList, /* List of values being extracted */ int srcTab, /* Pull data from this table */ SortCtx *pSort, /* If not NULL, info on how to process ORDER BY */ DistinctCtx *pDistinct, /* If not NULL, info on how to process DISTINCT */ SelectDest *pDest, /* How to dispose of the results */ int iContinue, /* Jump here to continue with next row */ int iBreak /* Jump here to break out of the inner loop */ ){ Vdbe *v = pParse->pVdbe; int i; int hasDistinct; /* True if the DISTINCT keyword is present */ int eDest = pDest->eDest; /* How to dispose of results */ int iParm = pDest->iSDParm; /* First argument to disposal method */ int nResultCol; /* Number of result columns */ int nPrefixReg = 0; /* Number of extra registers before regResult */ /* Usually, regResult is the first cell in an array of memory cells ** containing the current result row. In this case regOrig is set to the ** same value. However, if the results are being sent to the sorter, the ** values for any expressions that are also part of the sort-key are omitted ** from this array. In this case regOrig is set to zero. */ int regResult; /* Start of memory holding current results */ int regOrig; /* Start of memory holding full result (or 0) */ assert( v ); assert( pEList!=0 ); hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP; if( pSort && pSort->pOrderBy==0 ) pSort = 0; if( pSort==0 && !hasDistinct ){ assert( iContinue!=0 ); codeOffset(v, p->iOffset, iContinue); |
︙ | ︙ | |||
714 715 716 717 718 719 720 | ** on the right-hand side of an INSERT contains more result columns than ** there are columns in the table on the left. The error will be caught ** and reported later. But we need to make sure enough memory is allocated ** to avoid other spurious errors in the meantime. */ pParse->nMem += nResultCol; } pDest->nSdst = nResultCol; | | > > > > > > > > > > > > > > > > > > > | | 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 | ** on the right-hand side of an INSERT contains more result columns than ** there are columns in the table on the left. The error will be caught ** and reported later. But we need to make sure enough memory is allocated ** to avoid other spurious errors in the meantime. */ pParse->nMem += nResultCol; } pDest->nSdst = nResultCol; regOrig = regResult = pDest->iSdst; if( srcTab>=0 ){ for(i=0; i<nResultCol; i++){ sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i); VdbeComment((v, "%s", pEList->a[i].zName)); } }else if( eDest!=SRT_Exists ){ /* If the destination is an EXISTS(...) expression, the actual ** values returned by the SELECT are not required. */ u8 ecelFlags; if( eDest==SRT_Mem || eDest==SRT_Output || eDest==SRT_Coroutine ){ ecelFlags = SQLITE_ECEL_DUP; }else{ ecelFlags = 0; } assert( eDest!=SRT_Table || pSort==0 ); if( pSort && hasDistinct==0 && eDest!=SRT_EphemTab ){ /* For each expression in pEList that is a copy of an expression in ** the ORDER BY clause (pSort->pOrderBy), set the associated ** iOrderByCol value to one more than the index of the ORDER BY ** expression within the sort-key that pushOntoSorter() will generate. ** This allows the pEList field to be omitted from the sorted record, ** saving space and CPU cycles. */ ecelFlags |= (SQLITE_ECEL_OMITREF|SQLITE_ECEL_REF); for(i=pSort->nOBSat; i<pSort->pOrderBy->nExpr; i++){ int j; if( (j = pSort->pOrderBy->a[i].u.x.iOrderByCol)>0 ){ pEList->a[j-1].u.x.iOrderByCol = i+1-pSort->nOBSat; } } regOrig = 0; assert( eDest==SRT_Set || eDest==SRT_Mem || eDest==SRT_Coroutine || eDest==SRT_Output ); } nResultCol = sqlite3ExprCodeExprList(pParse,pEList,regResult,0,ecelFlags); } /* If the DISTINCT keyword was present on the SELECT statement ** and this row has been seen before, then do not make this row ** part of the result. */ if( hasDistinct ){ |
︙ | ︙ | |||
804 805 806 807 808 809 810 | ** table iParm. */ #ifndef SQLITE_OMIT_COMPOUND_SELECT case SRT_Union: { int r1; r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1); | | | 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 | ** table iParm. */ #ifndef SQLITE_OMIT_COMPOUND_SELECT case SRT_Union: { int r1; r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1); sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol); sqlite3ReleaseTempReg(pParse, r1); break; } /* Construct a record from the query result, but instead of ** saving that record, use it as a key to delete elements from ** the temporary table iParm. |
︙ | ︙ | |||
841 842 843 844 845 846 847 | ** on an ephemeral index. If the current row is already present ** in the index, do not write it to the output. If not, add the ** current row to the index and proceed with writing it to the ** output table as well. */ int addr = sqlite3VdbeCurrentAddr(v) + 4; sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0); VdbeCoverage(v); | | | 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 | ** on an ephemeral index. If the current row is already present ** in the index, do not write it to the output. If not, add the ** current row to the index and proceed with writing it to the ** output table as well. */ int addr = sqlite3VdbeCurrentAddr(v) + 4; sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0); VdbeCoverage(v); sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm+1, r1,regResult,nResultCol); assert( pSort==0 ); } #endif if( pSort ){ pushOntoSorter(pParse, pSort, p, r1+nPrefixReg,regResult,1,nPrefixReg); }else{ int r2 = sqlite3GetTempReg(pParse); |
︙ | ︙ | |||
870 871 872 873 874 875 876 | case SRT_Set: { if( pSort ){ /* At first glance you would think we could optimize out the ** ORDER BY in this case since the order of entries in the set ** does not matter. But there might be a LIMIT clause, in which ** case the order does matter */ pushOntoSorter( | | | < > | > | | 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 | case SRT_Set: { if( pSort ){ /* At first glance you would think we could optimize out the ** ORDER BY in this case since the order of entries in the set ** does not matter. But there might be a LIMIT clause, in which ** case the order does matter */ pushOntoSorter( pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg); }else{ int r1 = sqlite3GetTempReg(pParse); assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol ); sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol, r1, pDest->zAffSdst, nResultCol); sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol); sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol); sqlite3ReleaseTempReg(pParse, r1); } break; } /* If any row exist in the result set, record that fact and abort. */ case SRT_Exists: { sqlite3VdbeAddOp2(v, OP_Integer, 1, iParm); /* The LIMIT clause will terminate the loop for us */ break; } /* If this is a scalar select that is part of an expression, then ** store the results in the appropriate memory cell or array of ** memory cells and break out of the scan loop. */ case SRT_Mem: { if( pSort ){ assert( nResultCol<=pDest->nSdst ); pushOntoSorter( pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg); }else{ assert( nResultCol==pDest->nSdst ); assert( regResult==iParm ); /* The LIMIT clause will jump out of the loop for us */ } break; } #endif /* #ifndef SQLITE_OMIT_SUBQUERY */ case SRT_Coroutine: /* Send data to a co-routine */ case SRT_Output: { /* Return the results */ testcase( eDest==SRT_Coroutine ); testcase( eDest==SRT_Output ); if( pSort ){ pushOntoSorter(pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg); }else if( eDest==SRT_Coroutine ){ sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); }else{ sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nResultCol); sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol); } |
︙ | ︙ | |||
963 964 965 966 967 968 969 | for(i=0; i<nKey; i++){ sqlite3VdbeAddOp2(v, OP_SCopy, regResult + pSO->a[i].u.x.iOrderByCol - 1, r2+i); } sqlite3VdbeAddOp2(v, OP_Sequence, iParm, r2+nKey); sqlite3VdbeAddOp3(v, OP_MakeRecord, r2, nKey+2, r1); | | | 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 | for(i=0; i<nKey; i++){ sqlite3VdbeAddOp2(v, OP_SCopy, regResult + pSO->a[i].u.x.iOrderByCol - 1, r2+i); } sqlite3VdbeAddOp2(v, OP_Sequence, iParm, r2+nKey); sqlite3VdbeAddOp3(v, OP_MakeRecord, r2, nKey+2, r1); sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, r2, nKey+2); if( addrTest ) sqlite3VdbeJumpHere(v, addrTest); sqlite3ReleaseTempReg(pParse, r1); sqlite3ReleaseTempRange(pParse, r2, nKey+2); break; } #endif /* SQLITE_OMIT_CTE */ |
︙ | ︙ | |||
1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 | int addrOnce = 0; int iTab; ExprList *pOrderBy = pSort->pOrderBy; int eDest = pDest->eDest; int iParm = pDest->iSDParm; int regRow; int regRowid; int nKey; int iSortTab; /* Sorter cursor to read from */ int nSortData; /* Trailing values to read from sorter */ int i; int bSeq; /* True if sorter record includes seq. no. */ | > < < | 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 | int addrOnce = 0; int iTab; ExprList *pOrderBy = pSort->pOrderBy; int eDest = pDest->eDest; int iParm = pDest->iSDParm; int regRow; int regRowid; int iCol; int nKey; int iSortTab; /* Sorter cursor to read from */ int nSortData; /* Trailing values to read from sorter */ int i; int bSeq; /* True if sorter record includes seq. no. */ struct ExprList_item *aOutEx = p->pEList->a; assert( addrBreak<0 ); if( pSort->labelBkOut ){ sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut); sqlite3VdbeGoto(v, addrBreak); sqlite3VdbeResolveLabel(v, pSort->labelBkOut); } |
︙ | ︙ | |||
1243 1244 1245 1246 1247 1248 1249 | bSeq = 0; }else{ addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v); codeOffset(v, p->iOffset, addrContinue); iSortTab = iTab; bSeq = 1; } | | > > > > > > | | | 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 | bSeq = 0; }else{ addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v); codeOffset(v, p->iOffset, addrContinue); iSortTab = iTab; bSeq = 1; } for(i=0, iCol=nKey+bSeq; i<nSortData; i++){ int iRead; if( aOutEx[i].u.x.iOrderByCol ){ iRead = aOutEx[i].u.x.iOrderByCol-1; }else{ iRead = iCol++; } sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i); VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan)); } switch( eDest ){ case SRT_EphemTab: { sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); break; } #ifndef SQLITE_OMIT_SUBQUERY case SRT_Set: { assert( nColumn==sqlite3Strlen30(pDest->zAffSdst) ); sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, nColumn, regRowid, pDest->zAffSdst, nColumn); sqlite3ExprCacheAffinityChange(pParse, regRow, nColumn); sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, regRowid, regRow, nColumn); break; } case SRT_Mem: { /* The LIMIT clause will terminate the loop for us */ break; } #endif |
︙ | ︙ | |||
2469 2470 2471 2472 2473 2474 2475 | generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList); } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); computeLimitRegisters(pParse, p, iBreak); sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v); r1 = sqlite3GetTempReg(pParse); | | | 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 | generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList); } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); computeLimitRegisters(pParse, p, iBreak); sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v); r1 = sqlite3GetTempReg(pParse); iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1); sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); VdbeCoverage(v); sqlite3ReleaseTempReg(pParse, r1); selectInnerLoop(pParse, p, p->pEList, tab1, 0, 0, &dest, iCont, iBreak); sqlite3VdbeResolveLabel(v, iCont); sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v); sqlite3VdbeResolveLabel(v, iBreak); |
︙ | ︙ | |||
2636 2637 2638 2639 2640 2641 2642 | case SRT_Set: { int r1; testcase( pIn->nSdst>1 ); r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1, pDest->zAffSdst, pIn->nSdst); sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst); | | > | 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 | case SRT_Set: { int r1; testcase( pIn->nSdst>1 ); r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1, pDest->zAffSdst, pIn->nSdst); sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst); sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1, pIn->iSdst, pIn->nSdst); sqlite3ReleaseTempReg(pParse, r1); break; } /* If this is a scalar select that is part of an expression, then ** store the results in the appropriate memory cell and break out ** of the scan loop. |
︙ | ︙ |
Changes to src/shell.c.
︙ | ︙ | |||
1212 1213 1214 1215 1216 1217 1218 | utf8_printf(p->out, "%s%s", zSep, azCol[i]); } raw_printf(p->out,")"); } raw_printf(p->out," VALUES("); }else if( p->cnt==0 && p->showHeader ){ for(i=0; i<nArg; i++){ | | | | 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 | utf8_printf(p->out, "%s%s", zSep, azCol[i]); } raw_printf(p->out,")"); } raw_printf(p->out," VALUES("); }else if( p->cnt==0 && p->showHeader ){ for(i=0; i<nArg; i++){ if( i>0 ) raw_printf(p->out, ","); output_quoted_string(p->out, azCol[i]); } raw_printf(p->out,"\n"); } p->cnt++; for(i=0; i<nArg; i++){ char *zSep = i>0 ? ",": ""; if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ utf8_printf(p->out,"%sNULL",zSep); }else if( aiType && aiType[i]==SQLITE_TEXT ){ |
︙ | ︙ | |||
2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 | if( f==0 ){ utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile); } } return f; } /* ** A routine for handling output from sqlite3_trace(). */ static int sql_trace_callback( unsigned mType, void *pArg, void *pP, void *pX ){ FILE *f = (FILE*)pArg; UNUSED_PARAMETER(mType); UNUSED_PARAMETER(pP); if( f ){ const char *z = (const char*)pX; int i = (int)strlen(z); while( i>0 && z[i-1]==';' ){ i--; } utf8_printf(f, "%.*s;\n", i, z); } return 0; } /* ** A no-op routine that runs with the ".breakpoint" doc-command. This is ** a useful spot to set a debugger breakpoint. */ static void test_breakpoint(void){ static int nCall = 0; | > > > > | 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 | if( f==0 ){ utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile); } } return f; } #if !defined(SQLITE_OMIT_BUILTIN_TEST) #if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) /* ** A routine for handling output from sqlite3_trace(). */ static int sql_trace_callback( unsigned mType, void *pArg, void *pP, void *pX ){ FILE *f = (FILE*)pArg; UNUSED_PARAMETER(mType); UNUSED_PARAMETER(pP); if( f ){ const char *z = (const char*)pX; int i = (int)strlen(z); while( i>0 && z[i-1]==';' ){ i--; } utf8_printf(f, "%.*s;\n", i, z); } return 0; } #endif #endif /* ** A no-op routine that runs with the ".breakpoint" doc-command. This is ** a useful spot to set a debugger breakpoint. */ static void test_breakpoint(void){ static int nCall = 0; |
︙ | ︙ | |||
3912 3913 3914 3915 3916 3917 3918 | if( rc==SQLITE_OK ){ rc = sqlite3_exec(p->db, zSql, 0, 0, 0); sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0); if( rc ){ utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db)); }else{ utf8_printf(stdout, "%s;\n", zSql); | | | | 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 | if( rc==SQLITE_OK ){ rc = sqlite3_exec(p->db, zSql, 0, 0, 0); sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0); if( rc ){ utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db)); }else{ utf8_printf(stdout, "%s;\n", zSql); raw_printf(stdout, "WARNING: writing to an imposter table will corrupt the index!\n" ); } }else{ raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc); rc = 1; } sqlite3_free(zSql); }else #endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */ #ifdef SQLITE_ENABLE_IOTRACE |
︙ | ︙ | |||
4071 4072 4073 4074 4075 4076 4077 | p->mode = MODE_Quote; }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){ p->mode = MODE_Ascii; sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit); sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record); }else { raw_printf(stderr, "Error: mode should be one of: " | | | 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 | p->mode = MODE_Quote; }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){ p->mode = MODE_Ascii; sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit); sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record); }else { raw_printf(stderr, "Error: mode should be one of: " "ascii column csv html insert line list quote tabs tcl\n"); rc = 1; } p->cMode = p->mode; }else if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){ if( nArg==2 ){ |
︙ | ︙ | |||
4778 4779 4780 4781 4782 4783 4784 | }else /* Begin redirecting output to the file "testcase-out.txt" */ if( c=='t' && strcmp(azArg[0],"testcase")==0 ){ output_reset(p); p->out = output_file_open("testcase-out.txt"); if( p->out==0 ){ | | | 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 | }else /* Begin redirecting output to the file "testcase-out.txt" */ if( c=='t' && strcmp(azArg[0],"testcase")==0 ){ output_reset(p); p->out = output_file_open("testcase-out.txt"); if( p->out==0 ){ raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n"); } if( nArg>=2 ){ sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]); }else{ sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?"); } }else |
︙ | ︙ | |||
5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 | if( zSql==0 ) return 1; zSql[nSql] = ';'; zSql[nSql+1] = 0; rc = sqlite3_complete(zSql); zSql[nSql] = 0; return rc; } /* ** Read input from *in and process it. If *in==0 then input ** is interactive - the user is typing it it. Otherwise, input ** is coming from a file or device. A prompt is issued and history ** is saved only if input is interactive. An interrupt signal will ** cause this routine to exit immediately, unless input is interactive. ** ** Return the number of errors. */ static int process_input(ShellState *p, FILE *in){ char *zLine = 0; /* A single input line */ char *zSql = 0; /* Accumulated SQL text */ int nLine; /* Length of current line */ int nSql = 0; /* Bytes of zSql[] used */ int nAlloc = 0; /* Allocated zSql[] space */ int nSqlPrior = 0; /* Bytes of zSql[] used by prior line */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < | 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 | if( zSql==0 ) return 1; zSql[nSql] = ';'; zSql[nSql+1] = 0; rc = sqlite3_complete(zSql); zSql[nSql] = 0; return rc; } /* ** Run a single line of SQL */ static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){ int rc; char *zErrMsg = 0; open_db(p, 0); if( p->backslashOn ) resolve_backslashes(zSql); BEGIN_TIMER; rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg); END_TIMER; if( rc || zErrMsg ){ char zPrefix[100]; if( in!=0 || !stdin_is_interactive ){ sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error: near line %d:", startline); }else{ sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:"); } if( zErrMsg!=0 ){ utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg); sqlite3_free(zErrMsg); zErrMsg = 0; }else{ utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db)); } return 1; }else if( p->countChanges ){ raw_printf(p->out, "changes: %3d total_changes: %d\n", sqlite3_changes(p->db), sqlite3_total_changes(p->db)); } return 0; } /* ** Read input from *in and process it. If *in==0 then input ** is interactive - the user is typing it it. Otherwise, input ** is coming from a file or device. A prompt is issued and history ** is saved only if input is interactive. An interrupt signal will ** cause this routine to exit immediately, unless input is interactive. ** ** Return the number of errors. */ static int process_input(ShellState *p, FILE *in){ char *zLine = 0; /* A single input line */ char *zSql = 0; /* Accumulated SQL text */ int nLine; /* Length of current line */ int nSql = 0; /* Bytes of zSql[] used */ int nAlloc = 0; /* Allocated zSql[] space */ int nSqlPrior = 0; /* Bytes of zSql[] used by prior line */ int rc; /* Error code */ int errCnt = 0; /* Number of errors seen */ int lineno = 0; /* Current line number */ int startline = 0; /* Line number for start of current input */ while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){ fflush(p->out); |
︙ | ︙ | |||
5248 5249 5250 5251 5252 5253 5254 | }else{ zSql[nSql++] = '\n'; memcpy(zSql+nSql, zLine, nLine+1); nSql += nLine; } if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior) && sqlite3_complete(zSql) ){ | < < < < < < < < < < < < < < < < < < < < < | < < < < < | | < < | 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 | }else{ zSql[nSql++] = '\n'; memcpy(zSql+nSql, zLine, nLine+1); nSql += nLine; } if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior) && sqlite3_complete(zSql) ){ errCnt += runOneSqlLine(p, zSql, in, startline); nSql = 0; if( p->outCount ){ output_reset(p); p->outCount = 0; } }else if( nSql && _all_whitespace(zSql) ){ if( p->echoOn ) printf("%s\n", zSql); nSql = 0; } } if( nSql && !_all_whitespace(zSql) ){ runOneSqlLine(p, zSql, in, startline); } free(zSql); free(zLine); return errCnt>0; } /* |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
123 124 125 126 127 128 129 | */ #define SQLITE_VERSION "--VERS--" #define SQLITE_VERSION_NUMBER --VERSION-NUMBER-- #define SQLITE_SOURCE_ID "--SOURCE-ID--" /* ** CAPI3REF: Run-Time Library Version Numbers | | | 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | */ #define SQLITE_VERSION "--VERS--" #define SQLITE_VERSION_NUMBER --VERSION-NUMBER-- #define SQLITE_SOURCE_ID "--SOURCE-ID--" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros ** but are associated with the library instead of the header file. ^(Cautious ** programmers might include assert() statements in their application to ** verify that values returned by these interfaces match the macros in ** the header, and thus ensure that the application is |
︙ | ︙ | |||
3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 | ** [SAVEPOINT], and [RELEASE] cause sqlite3_stmt_readonly() to return true, ** since the statements themselves do not actually modify the database but ** rather they control the timing of when other statements modify the ** database. ^The [ATTACH] and [DETACH] statements also cause ** sqlite3_stmt_readonly() to return true since, while those statements ** change the configuration of a database connection, they do not make ** changes to the content of the database files on disk. */ int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If A Prepared Statement Has Been Reset ** METHOD: sqlite3_stmt ** | > > > > | 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 | ** [SAVEPOINT], and [RELEASE] cause sqlite3_stmt_readonly() to return true, ** since the statements themselves do not actually modify the database but ** rather they control the timing of when other statements modify the ** database. ^The [ATTACH] and [DETACH] statements also cause ** sqlite3_stmt_readonly() to return true since, while those statements ** change the configuration of a database connection, they do not make ** changes to the content of the database files on disk. ** ^The sqlite3_stmt_readonly() interface returns true for [BEGIN] since ** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and ** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so ** sqlite3_stmt_readonly() returns false for those commands. */ int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If A Prepared Statement Has Been Reset ** METHOD: sqlite3_stmt ** |
︙ | ︙ | |||
8222 8223 8224 8225 8226 8227 8228 | ** callback was invoked as a result of a direct insert, update, or delete ** operation; or 1 for inserts, updates, or deletes invoked by top-level ** triggers; or 2 for changes resulting from triggers called by top-level ** triggers; and so forth. ** ** See also: [sqlite3_update_hook()] */ | > | | | | | > | 8226 8227 8228 8229 8230 8231 8232 8233 8234 8235 8236 8237 8238 8239 8240 8241 8242 8243 8244 8245 8246 8247 8248 8249 8250 8251 8252 8253 8254 8255 8256 8257 8258 | ** callback was invoked as a result of a direct insert, update, or delete ** operation; or 1 for inserts, updates, or deletes invoked by top-level ** triggers; or 2 for changes resulting from triggers called by top-level ** triggers; and so forth. ** ** See also: [sqlite3_update_hook()] */ #if defined(SQLITE_ENABLE_PREUPDATE_HOOK) void *sqlite3_preupdate_hook( sqlite3 *db, void(*xPreUpdate)( void *pCtx, /* Copy of third arg to preupdate_hook() */ sqlite3 *db, /* Database handle */ int op, /* SQLITE_UPDATE, DELETE or INSERT */ char const *zDb, /* Database name */ char const *zName, /* Table name */ sqlite3_int64 iKey1, /* Rowid of row about to be deleted/updated */ sqlite3_int64 iKey2 /* New rowid value (for a rowid UPDATE) */ ), void* ); int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **); int sqlite3_preupdate_count(sqlite3 *); int sqlite3_preupdate_depth(sqlite3 *); int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); #endif /* ** CAPI3REF: Low-level system error code ** ** ^Attempt to return the underlying operating system error code or error ** number that caused the most recent I/O error or failure to open a file. ** The return value is OS-dependent. For example, on unix systems, after |
︙ | ︙ | |||
8278 8279 8280 8281 8282 8283 8284 | ** the most recent version. ** ** The constructor for this object is [sqlite3_snapshot_get()]. The ** [sqlite3_snapshot_open()] method causes a fresh read transaction to refer ** to an historical snapshot (if possible). The destructor for ** sqlite3_snapshot objects is [sqlite3_snapshot_free()]. */ | | > > > > > > > > > > > > > | > > > > > > > > > > > > > | < | 8284 8285 8286 8287 8288 8289 8290 8291 8292 8293 8294 8295 8296 8297 8298 8299 8300 8301 8302 8303 8304 8305 8306 8307 8308 8309 8310 8311 8312 8313 8314 8315 8316 8317 8318 8319 8320 8321 8322 8323 8324 8325 8326 8327 8328 8329 8330 8331 8332 8333 8334 8335 8336 | ** the most recent version. ** ** The constructor for this object is [sqlite3_snapshot_get()]. The ** [sqlite3_snapshot_open()] method causes a fresh read transaction to refer ** to an historical snapshot (if possible). The destructor for ** sqlite3_snapshot objects is [sqlite3_snapshot_free()]. */ typedef struct sqlite3_snapshot { unsigned char hidden[48]; } sqlite3_snapshot; /* ** CAPI3REF: Record A Database Snapshot ** EXPERIMENTAL ** ** ^The [sqlite3_snapshot_get(D,S,P)] interface attempts to make a ** new [sqlite3_snapshot] object that records the current state of ** schema S in database connection D. ^On success, the ** [sqlite3_snapshot_get(D,S,P)] interface writes a pointer to the newly ** created [sqlite3_snapshot] object into *P and returns SQLITE_OK. ** If there is not already a read-transaction open on schema S when ** this function is called, one is opened automatically. ** ** The following must be true for this function to succeed. If any of ** the following statements are false when sqlite3_snapshot_get() is ** called, SQLITE_ERROR is returned. The final value of *P is undefined ** in this case. ** ** <ul> ** <li> The database handle must be in [autocommit mode]. ** ** <li> Schema S of [database connection] D must be a [WAL mode] database. ** ** <li> There must not be a write transaction open on schema S of database ** connection D. ** ** <li> One or more transactions must have been written to the current wal ** file since it was created on disk (by any connection). This means ** that a snapshot cannot be taken on a wal mode database with no wal ** file immediately after it is first opened. At least one transaction ** must be written to it first. ** </ul> ** ** This function may also return SQLITE_NOMEM. If it is called with the ** database handle in autocommit mode but fails for some other reason, ** whether or not a read transaction is opened on schema S is undefined. ** ** The [sqlite3_snapshot] object returned from a successful call to ** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()] ** to avoid a memory leak. ** ** The [sqlite3_snapshot_get()] interface is only available when the ** SQLITE_ENABLE_SNAPSHOT compile-time option is used. |
︙ | ︙ | |||
8384 8385 8386 8387 8388 8389 8390 8391 8392 8393 8394 8395 8396 8397 8398 8399 8400 8401 8402 | ** snapshot, and a positive value if P1 is a newer snapshot than P2. */ SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( sqlite3_snapshot *p1, sqlite3_snapshot *p2 ); /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ #ifdef SQLITE_OMIT_FLOATING_POINT # undef double #endif #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif #endif /* SQLITE3_H */ | > > > > > > > > > > > > > > > > > > > > > > | 8415 8416 8417 8418 8419 8420 8421 8422 8423 8424 8425 8426 8427 8428 8429 8430 8431 8432 8433 8434 8435 8436 8437 8438 8439 8440 8441 8442 8443 8444 8445 8446 8447 8448 8449 8450 8451 8452 8453 8454 8455 | ** snapshot, and a positive value if P1 is a newer snapshot than P2. */ SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( sqlite3_snapshot *p1, sqlite3_snapshot *p2 ); /* ** CAPI3REF: Recover snapshots from a wal file ** EXPERIMENTAL ** ** If all connections disconnect from a database file but do not perform ** a checkpoint, the existing wal file is opened along with the database ** file the next time the database is opened. At this point it is only ** possible to successfully call sqlite3_snapshot_open() to open the most ** recent snapshot of the database (the one at the head of the wal file), ** even though the wal file may contain other valid snapshots for which ** clients have sqlite3_snapshot handles. ** ** This function attempts to scan the wal file associated with database zDb ** of database handle db and make all valid snapshots available to ** sqlite3_snapshot_open(). It is an error if there is already a read ** transaction open on the database, or if the database is not a wal mode ** database. ** ** SQLITE_OK is returned if successful, or an SQLite error code otherwise. */ SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ #ifdef SQLITE_OMIT_FLOATING_POINT # undef double #endif #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif #endif /* SQLITE3_H */ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
2943 2944 2945 2946 2947 2948 2949 | u8 tempReg; /* iReg is a temp register that needs to be freed */ int iLevel; /* Nesting level */ int iReg; /* Reg with value of this column. 0 means none. */ int lru; /* Least recently used entry has the smallest value */ } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */ int aTempReg[8]; /* Holding area for temporary registers */ Token sNameToken; /* Token with unqualified schema object name */ | < | | > | 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 | u8 tempReg; /* iReg is a temp register that needs to be freed */ int iLevel; /* Nesting level */ int iReg; /* Reg with value of this column. 0 means none. */ int lru; /* Least recently used entry has the smallest value */ } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */ int aTempReg[8]; /* Holding area for temporary registers */ Token sNameToken; /* Token with unqualified schema object name */ /************************************************************************ ** Above is constant between recursions. Below is reset before and after ** each recursion. The boundary between these two regions is determined ** using offsetof(Parse,sLastToken) so the sLastToken field must be the ** first field in the recursive region. ************************************************************************/ Token sLastToken; /* The last token parsed */ ynVar nVar; /* Number of '?' variables seen in the SQL so far */ int nzVar; /* Number of available slots in azVar[] */ u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */ u8 explain; /* True if the EXPLAIN flag is found on the query */ #ifndef SQLITE_OMIT_VIRTUALTABLE u8 declareVtab; /* True if inside sqlite3_declare_vtab() */ int nVtabLock; /* Number of virtual tables to lock */ |
︙ | ︙ | |||
2985 2986 2987 2988 2989 2990 2991 | With *pWithToFree; /* Free this WITH object at the end of the parse */ }; /* ** Sizes and pointers of various parts of the Parse object. */ #define PARSE_HDR_SZ offsetof(Parse,aColCache) /* Recursive part w/o aColCache*/ | | | 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 | With *pWithToFree; /* Free this WITH object at the end of the parse */ }; /* ** Sizes and pointers of various parts of the Parse object. */ #define PARSE_HDR_SZ offsetof(Parse,aColCache) /* Recursive part w/o aColCache*/ #define PARSE_RECURSE_SZ offsetof(Parse,sLastToken) /* Recursive part */ #define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */ #define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */ /* ** Return true if currently inside an sqlite3_declare_vtab() call. */ #ifdef SQLITE_OMIT_VIRTUALTABLE |
︙ | ︙ | |||
3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 | int sqlite3ExprCodeTemp(Parse*, Expr*, int*); int sqlite3ExprCodeTarget(Parse*, Expr*, int); void sqlite3ExprCodeAndCache(Parse*, Expr*, int); int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int, u8); #define SQLITE_ECEL_DUP 0x01 /* Deep, not shallow copies */ #define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */ #define SQLITE_ECEL_REF 0x04 /* Use ExprList.u.x.iOrderByCol */ void sqlite3ExprIfTrue(Parse*, Expr*, int, int); void sqlite3ExprIfFalse(Parse*, Expr*, int, int); void sqlite3ExprIfFalseDup(Parse*, Expr*, int, int); Table *sqlite3FindTable(sqlite3*,const char*, const char*); #define LOCATE_VIEW 0x01 #define LOCATE_NOERR 0x02 Table *sqlite3LocateTable(Parse*,u32 flags,const char*, const char*); | > | 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 | int sqlite3ExprCodeTemp(Parse*, Expr*, int*); int sqlite3ExprCodeTarget(Parse*, Expr*, int); void sqlite3ExprCodeAndCache(Parse*, Expr*, int); int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int, u8); #define SQLITE_ECEL_DUP 0x01 /* Deep, not shallow copies */ #define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */ #define SQLITE_ECEL_REF 0x04 /* Use ExprList.u.x.iOrderByCol */ #define SQLITE_ECEL_OMITREF 0x08 /* Omit if ExprList.u.x.iOrderByCol */ void sqlite3ExprIfTrue(Parse*, Expr*, int, int); void sqlite3ExprIfFalse(Parse*, Expr*, int, int); void sqlite3ExprIfFalseDup(Parse*, Expr*, int, int); Table *sqlite3FindTable(sqlite3*,const char*, const char*); #define LOCATE_VIEW 0x01 #define LOCATE_NOERR 0x02 Table *sqlite3LocateTable(Parse*,u32 flags,const char*, const char*); |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 | if( sqlite3TestMakePointerStr(interp, zBuf, pSnapshot) ) return TCL_ERROR; Tcl_SetObjResult(interp, Tcl_NewStringObj(zBuf, -1)); } return TCL_OK; } #endif /* SQLITE_ENABLE_SNAPSHOT */ #ifdef SQLITE_ENABLE_SNAPSHOT /* ** Usage: sqlite3_snapshot_open DB DBNAME SNAPSHOT */ static int SQLITE_TCLAPI test_snapshot_open( void * clientData, Tcl_Interp *interp, | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 | if( sqlite3TestMakePointerStr(interp, zBuf, pSnapshot) ) return TCL_ERROR; Tcl_SetObjResult(interp, Tcl_NewStringObj(zBuf, -1)); } return TCL_OK; } #endif /* SQLITE_ENABLE_SNAPSHOT */ #ifdef SQLITE_ENABLE_SNAPSHOT /* ** Usage: sqlite3_snapshot_recover DB DBNAME */ static int SQLITE_TCLAPI test_snapshot_recover( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ int rc; sqlite3 *db; char *zName; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME"); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; zName = Tcl_GetString(objv[2]); rc = sqlite3_snapshot_recover(db, zName); if( rc!=SQLITE_OK ){ Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); return TCL_ERROR; }else{ Tcl_ResetResult(interp); } return TCL_OK; } #endif /* SQLITE_ENABLE_SNAPSHOT */ #ifdef SQLITE_ENABLE_SNAPSHOT /* ** Usage: sqlite3_snapshot_open DB DBNAME SNAPSHOT */ static int SQLITE_TCLAPI test_snapshot_open( void * clientData, Tcl_Interp *interp, |
︙ | ︙ | |||
2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 | return TCL_ERROR; } p1 = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[1])); p2 = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[2])); res = sqlite3_snapshot_cmp(p1, p2); Tcl_SetObjResult(interp, Tcl_NewIntObj(res)); return TCL_OK; } #endif /* SQLITE_ENABLE_SNAPSHOT */ /* ** Usage: sqlite3_delete_database FILENAME */ int sqlite3_delete_database(const char*); /* in test_delete.c */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 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 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 | return TCL_ERROR; } p1 = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[1])); p2 = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[2])); res = sqlite3_snapshot_cmp(p1, p2); Tcl_SetObjResult(interp, Tcl_NewIntObj(res)); return TCL_OK; } #endif /* SQLITE_ENABLE_SNAPSHOT */ #ifdef SQLITE_ENABLE_SNAPSHOT /* ** Usage: sqlite3_snapshot_get_blob DB DBNAME */ static int SQLITE_TCLAPI test_snapshot_get_blob( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ int rc; sqlite3 *db; char *zName; sqlite3_snapshot *pSnapshot = 0; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME"); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; zName = Tcl_GetString(objv[2]); rc = sqlite3_snapshot_get(db, zName, &pSnapshot); if( rc!=SQLITE_OK ){ Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); return TCL_ERROR; }else{ Tcl_SetObjResult(interp, Tcl_NewByteArrayObj((unsigned char*)pSnapshot, sizeof(sqlite3_snapshot)) ); sqlite3_snapshot_free(pSnapshot); } return TCL_OK; } #endif /* SQLITE_ENABLE_SNAPSHOT */ #ifdef SQLITE_ENABLE_SNAPSHOT /* ** Usage: sqlite3_snapshot_open_blob DB DBNAME SNAPSHOT */ static int SQLITE_TCLAPI test_snapshot_open_blob( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ int rc; sqlite3 *db; char *zName; unsigned char *pBlob; int nBlob; if( objc!=4 ){ Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SNAPSHOT"); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; zName = Tcl_GetString(objv[2]); pBlob = Tcl_GetByteArrayFromObj(objv[3], &nBlob); if( nBlob!=sizeof(sqlite3_snapshot) ){ Tcl_AppendResult(interp, "bad SNAPSHOT", 0); return TCL_ERROR; } rc = sqlite3_snapshot_open(db, zName, (sqlite3_snapshot*)pBlob); if( rc!=SQLITE_OK ){ Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); return TCL_ERROR; } return TCL_OK; } #endif /* SQLITE_ENABLE_SNAPSHOT */ #ifdef SQLITE_ENABLE_SNAPSHOT /* ** Usage: sqlite3_snapshot_cmp_blob SNAPSHOT1 SNAPSHOT2 */ static int SQLITE_TCLAPI test_snapshot_cmp_blob( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ int res; unsigned char *p1; unsigned char *p2; int n1; int n2; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 1, objv, "SNAPSHOT1 SNAPSHOT2"); return TCL_ERROR; } p1 = Tcl_GetByteArrayFromObj(objv[1], &n1); p2 = Tcl_GetByteArrayFromObj(objv[2], &n2); if( n1!=sizeof(sqlite3_snapshot) || n1!=n2 ){ Tcl_AppendResult(interp, "bad SNAPSHOT", 0); return TCL_ERROR; } res = sqlite3_snapshot_cmp((sqlite3_snapshot*)p1, (sqlite3_snapshot*)p2); Tcl_SetObjResult(interp, Tcl_NewIntObj(res)); return TCL_OK; } #endif /* SQLITE_ENABLE_SNAPSHOT */ /* ** Usage: sqlite3_delete_database FILENAME */ int sqlite3_delete_database(const char*); /* in test_delete.c */ |
︙ | ︙ | |||
7733 7734 7735 7736 7737 7738 7739 7740 7741 7742 7743 7744 7745 7746 | #endif { "vfs_current_time_int64", vfsCurrentTimeInt64, 0 }, #ifdef SQLITE_ENABLE_SNAPSHOT { "sqlite3_snapshot_get", test_snapshot_get, 0 }, { "sqlite3_snapshot_open", test_snapshot_open, 0 }, { "sqlite3_snapshot_free", test_snapshot_free, 0 }, { "sqlite3_snapshot_cmp", test_snapshot_cmp, 0 }, #endif { "sqlite3_delete_database", test_delete_database, 0 }, }; static int bitmask_size = sizeof(Bitmask)*8; static int longdouble_size = sizeof(LONGDOUBLE_TYPE); int i; extern int sqlite3_sync_count, sqlite3_fullsync_count; | > > > > | 7872 7873 7874 7875 7876 7877 7878 7879 7880 7881 7882 7883 7884 7885 7886 7887 7888 7889 | #endif { "vfs_current_time_int64", vfsCurrentTimeInt64, 0 }, #ifdef SQLITE_ENABLE_SNAPSHOT { "sqlite3_snapshot_get", test_snapshot_get, 0 }, { "sqlite3_snapshot_open", test_snapshot_open, 0 }, { "sqlite3_snapshot_free", test_snapshot_free, 0 }, { "sqlite3_snapshot_cmp", test_snapshot_cmp, 0 }, { "sqlite3_snapshot_recover", test_snapshot_recover, 0 }, { "sqlite3_snapshot_get_blob", test_snapshot_get_blob, 0 }, { "sqlite3_snapshot_open_blob", test_snapshot_open_blob, 0 }, { "sqlite3_snapshot_cmp_blob", test_snapshot_cmp_blob, 0 }, #endif { "sqlite3_delete_database", test_delete_database, 0 }, }; static int bitmask_size = sizeof(Bitmask)*8; static int longdouble_size = sizeof(LONGDOUBLE_TYPE); int i; extern int sqlite3_sync_count, sqlite3_fullsync_count; |
︙ | ︙ |
Changes to src/test_blob.c.
︙ | ︙ | |||
110 111 112 113 114 115 116 | const char *zTable; const char *zColumn; Tcl_WideInt iRowid; int flags; const char *zVarname; int nVarname; | | | 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | const char *zTable; const char *zColumn; Tcl_WideInt iRowid; int flags; const char *zVarname; int nVarname; sqlite3_blob *pBlob = (sqlite3_blob*)&flags; /* Non-zero initialization */ int rc; if( objc!=8 ){ const char *zUsage = "DB DATABASE TABLE COLUMN ROWID FLAGS VARNAME"; Tcl_WrongNumArgs(interp, 1, objv, zUsage); return TCL_ERROR; } |
︙ | ︙ |
Changes to src/test_delete.c.
︙ | ︙ | |||
43 44 45 46 47 48 49 | /* ** This routine is a copy of (most of) the code from SQLite function ** sqlite3FileSuffix3(). It modifies the filename in buffer z in the ** same way as SQLite does when in 8.3 filenames mode. */ static void sqlite3Delete83Name(char *z){ int i, sz; | | | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | /* ** This routine is a copy of (most of) the code from SQLite function ** sqlite3FileSuffix3(). It modifies the filename in buffer z in the ** same way as SQLite does when in 8.3 filenames mode. */ static void sqlite3Delete83Name(char *z){ int i, sz; sz = (int)strlen(z); for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){} if( z[i]=='.' && (sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4); } /* ** zFile is a filename. Assuming no error occurs, if this file exists, ** set *pbExists to true and unlink it. Or, if the file does not exist, |
︙ | ︙ | |||
101 102 103 104 105 106 107 | { "%s%03d", 0, 1 }, { "%s-journal%03d", SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET, 1 }, { "%s-wal%03d", SQLITE_MULTIPLEX_WAL_8_3_OFFSET, 1 }, }; /* Allocate a buffer large enough for any of the files that need to be ** deleted. */ | | | 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | { "%s%03d", 0, 1 }, { "%s-journal%03d", SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET, 1 }, { "%s-wal%03d", SQLITE_MULTIPLEX_WAL_8_3_OFFSET, 1 }, }; /* Allocate a buffer large enough for any of the files that need to be ** deleted. */ nBuf = (int)strlen(zFile) + 100; zBuf = (char*)sqlite3_malloc(nBuf); if( zBuf==0 ) return SQLITE_NOMEM; /* Delete both the regular and 8.3 filenames versions of the database, ** journal, wal and shm files. */ for(i=0; rc==0 && i<sizeof(azFmt)/sizeof(azFmt[0]); i++){ sqlite3_snprintf(nBuf, zBuf, azFmt[i], zFile); |
︙ | ︙ |
Changes to src/update.c.
︙ | ︙ | |||
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 | ** ** FIXME: Be smarter about omitting indexes that use expressions. */ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ int reg; if( chngKey || hasFK || pIdx->pPartIdxWhere || pIdx==pPk ){ reg = ++pParse->nMem; }else{ reg = 0; for(i=0; i<pIdx->nKeyCol; i++){ i16 iIdxCol = pIdx->aiColumn[i]; if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){ reg = ++pParse->nMem; break; } } } if( reg==0 ) aToOpen[j+1] = 0; aRegIdx[j] = reg; } | > > | 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 | ** ** FIXME: Be smarter about omitting indexes that use expressions. */ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ int reg; if( chngKey || hasFK || pIdx->pPartIdxWhere || pIdx==pPk ){ reg = ++pParse->nMem; pParse->nMem += pIdx->nColumn; }else{ reg = 0; for(i=0; i<pIdx->nKeyCol; i++){ i16 iIdxCol = pIdx->aiColumn[i]; if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){ reg = ++pParse->nMem; pParse->nMem += pIdx->nColumn; break; } } } if( reg==0 ) aToOpen[j+1] = 0; aRegIdx[j] = reg; } |
︙ | ︙ | |||
394 395 396 397 398 399 400 | if( okOnePass ){ sqlite3VdbeChangeToNoop(v, addrOpen); nKey = nPk; regKey = iPk; }else{ sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey, sqlite3IndexAffinityStr(db, pPk), nPk); | | | 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 | if( okOnePass ){ sqlite3VdbeChangeToNoop(v, addrOpen); nKey = nPk; regKey = iPk; }else{ sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey, sqlite3IndexAffinityStr(db, pPk), nPk); sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEph, regKey, iPk, nPk); } sqlite3WhereEnd(pWInfo); } /* Initialize the count of updated rows */ if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab ){ |
︙ | ︙ | |||
446 447 448 449 450 451 452 | labelContinue = labelBreak; sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak); VdbeCoverageIf(v, pPk==0); VdbeCoverageIf(v, pPk!=0); }else if( pPk ){ labelContinue = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v); | | | 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 | labelContinue = labelBreak; sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak); VdbeCoverageIf(v, pPk==0); VdbeCoverageIf(v, pPk!=0); }else if( pPk ){ labelContinue = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v); addrTop = sqlite3VdbeAddOp2(v, OP_RowData, iEph, regKey); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0); VdbeCoverage(v); }else{ labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, labelBreak, regOldRowid); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid); |
︙ | ︙ | |||
653 654 655 656 657 658 659 | sqlite3VdbeResolveLabel(v, labelContinue); sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); VdbeCoverage(v); }else{ sqlite3VdbeGoto(v, labelContinue); } sqlite3VdbeResolveLabel(v, labelBreak); | < < < < < < < < < | 655 656 657 658 659 660 661 662 663 664 665 666 667 668 | sqlite3VdbeResolveLabel(v, labelContinue); sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); VdbeCoverage(v); }else{ sqlite3VdbeGoto(v, labelContinue); } sqlite3VdbeResolveLabel(v, labelBreak); /* Update the sqlite_sequence table by storing the content of the ** maximum rowid counter values recorded while inserting into ** autoincrement tables. */ if( pParse->nested==0 && pParse->pTriggerTab==0 ){ sqlite3AutoincrementEnd(pParse); } |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
2467 2468 2469 2470 2471 2472 2473 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); assert( pC!=0 ); assert( p2<pC->nField ); aOffset = pC->aOffset; assert( pC->eCurType!=CURTYPE_VTAB ); assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow ); assert( pC->eCurType!=CURTYPE_SORTER ); | < > | 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 | assert( pOp->p1>=0 && pOp->p1<p->nCursor ); assert( pC!=0 ); assert( p2<pC->nField ); aOffset = pC->aOffset; assert( pC->eCurType!=CURTYPE_VTAB ); assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow ); assert( pC->eCurType!=CURTYPE_SORTER ); if( pC->cacheStatus!=p->cacheCtr ){ /*OPTIMIZATION-IF-FALSE*/ if( pC->nullRow ){ if( pC->eCurType==CURTYPE_PSEUDO ){ assert( pC->uc.pseudoTableReg>0 ); pReg = &aMem[pC->uc.pseudoTableReg]; assert( pReg->flags & MEM_Blob ); assert( memIsValid(pReg) ); pC->payloadSize = pC->szRow = avail = pReg->n; pC->aRow = (u8*)pReg->z; }else{ sqlite3VdbeMemSetNull(pDest); goto op_column_out; } }else{ pCrsr = pC->uc.pCursor; assert( pC->eCurType==CURTYPE_BTREE ); assert( pCrsr ); assert( sqlite3BtreeCursorIsValid(pCrsr) ); pC->payloadSize = sqlite3BtreePayloadSize(pCrsr); pC->aRow = sqlite3BtreePayloadFetch(pCrsr, &avail); assert( avail<=65536 ); /* Maximum page size is 64KiB */ if( pC->payloadSize <= (u32)avail ){ |
︙ | ︙ | |||
2546 2547 2548 2549 2550 2551 2552 | /* If there is more header available for parsing in the record, try ** to extract additional fields up through the p2+1-th field */ if( pC->iHdrOffset<aOffset[0] ){ /* Make sure zData points to enough of the record to cover the header. */ if( pC->aRow==0 ){ memset(&sMem, 0, sizeof(sMem)); | | | 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 | /* If there is more header available for parsing in the record, try ** to extract additional fields up through the p2+1-th field */ if( pC->iHdrOffset<aOffset[0] ){ /* Make sure zData points to enough of the record to cover the header. */ if( pC->aRow==0 ){ memset(&sMem, 0, sizeof(sMem)); rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, 0, aOffset[0], &sMem); if( rc!=SQLITE_OK ) goto abort_due_to_error; zData = (u8*)sMem.z; }else{ zData = pC->aRow; } /* Fill in pC->aType[i] and aOffset[i] values through the p2-th field. */ |
︙ | ︙ | |||
2659 2660 2661 2662 2663 2664 2665 | ** 2. the length(X) function if X is a blob, and ** 3. if the content length is zero. ** So we might as well use bogus content rather than reading ** content from disk. */ static u8 aZero[8]; /* This is the bogus content */ sqlite3VdbeSerialGet(aZero, t, pDest); }else{ | | < | 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 | ** 2. the length(X) function if X is a blob, and ** 3. if the content length is zero. ** So we might as well use bogus content rather than reading ** content from disk. */ static u8 aZero[8]; /* This is the bogus content */ sqlite3VdbeSerialGet(aZero, t, pDest); }else{ rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, aOffset[p2], len, pDest); if( rc!=SQLITE_OK ) goto abort_due_to_error; sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest); pDest->flags &= ~MEM_Ephem; } } op_column_out: |
︙ | ︙ | |||
4319 4320 4321 4322 4323 4324 4325 | ** be a MEM_Int. ** ** If the OPFLAG_NCHANGE flag of P5 is set, then the row change count is ** incremented (otherwise not). If the OPFLAG_LASTROWID flag of P5 is set, ** then rowid is stored for subsequent return by the ** sqlite3_last_insert_rowid() function (otherwise it is unmodified). ** | | | | < | < < < < | 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 | ** be a MEM_Int. ** ** If the OPFLAG_NCHANGE flag of P5 is set, then the row change count is ** incremented (otherwise not). If the OPFLAG_LASTROWID flag of P5 is set, ** then rowid is stored for subsequent return by the ** sqlite3_last_insert_rowid() function (otherwise it is unmodified). ** ** If the OPFLAG_USESEEKRESULT flag of P5 is set, the implementation might ** run faster by avoiding an unnecessary seek on cursor P1. However, ** the OPFLAG_USESEEKRESULT flag must only be set if there have been no prior ** seeks on the cursor or if the most recent seek used a key equal to P3. ** ** If the OPFLAG_ISUPDATE flag is set, then this opcode is part of an ** UPDATE operation. Otherwise (if the flag is clear) then this opcode ** is part of an INSERT operation. The difference is only important to ** the update hook. ** ** Parameter P4 may point to a Table structure, or may be NULL. If it is |
︙ | ︙ | |||
4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 | nExtraDelete--; } } #endif rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5); pC->cacheStatus = CACHE_STALE; if( rc ) goto abort_due_to_error; /* Invoke the update-hook if required. */ if( opflags & OPFLAG_NCHANGE ){ p->nChange++; if( db->xUpdateCallback && HasRowid(pTab) ){ db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, pTab->zName, | > | 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 | nExtraDelete--; } } #endif rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5); pC->cacheStatus = CACHE_STALE; pC->seekResult = 0; if( rc ) goto abort_due_to_error; /* Invoke the update-hook if required. */ if( opflags & OPFLAG_NCHANGE ){ p->nChange++; if( db->xUpdateCallback && HasRowid(pTab) ){ db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, pTab->zName, |
︙ | ︙ | |||
4640 4641 4642 4643 4644 4645 4646 | p->apCsr[pOp->p3]->cacheStatus = CACHE_STALE; break; } /* Opcode: RowData P1 P2 * * * ** Synopsis: r[P2]=data ** | | > < < < < < < | < < | < < < < | | 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 | p->apCsr[pOp->p3]->cacheStatus = CACHE_STALE; break; } /* Opcode: RowData P1 P2 * * * ** Synopsis: r[P2]=data ** ** Write into register P2 the complete row content for the row at ** which cursor P1 is currently pointing. ** There is no interpretation of the data. ** It is just copied onto the P2 register exactly as ** it is found in the database file. ** ** If cursor P1 is an index, then the content is the key of the row. ** If cursor P2 is a table, then the content extracted is the data. ** ** If the P1 cursor must be pointing to a valid row (not a NULL row) ** of a real table, not a pseudo-table. */ case OP_RowData: { VdbeCursor *pC; BtCursor *pCrsr; u32 n; pOut = &aMem[pOp->p2]; memAboutToChange(p, pOut); assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->eCurType==CURTYPE_BTREE ); assert( isSorter(pC)==0 ); assert( pC->nullRow==0 ); assert( pC->uc.pCursor!=0 ); pCrsr = pC->uc.pCursor; /* The OP_RowData opcodes always follow OP_NotExists or ** OP_SeekRowid or OP_Rewind/Op_Next with no intervening instructions ** that might invalidate the cursor. ** If this where not the case, on of the following assert()s ** would fail. Should this ever change (because of changes in the code ** generator) then the fix would be to insert a call to ** sqlite3VdbeCursorMoveto(). */ |
︙ | ︙ | |||
4705 4706 4707 4708 4709 4710 4711 | } testcase( n==0 ); if( sqlite3VdbeMemClearAndResize(pOut, MAX(n,32)) ){ goto no_mem; } pOut->n = n; MemSetTypeFlag(pOut, MEM_Blob); | < | < < < | 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 | } testcase( n==0 ); if( sqlite3VdbeMemClearAndResize(pOut, MAX(n,32)) ){ goto no_mem; } pOut->n = n; MemSetTypeFlag(pOut, MEM_Blob); rc = sqlite3BtreePayload(pCrsr, 0, n, pOut->z); if( rc ) goto abort_due_to_error; pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */ UPDATE_MAX_BLOBSIZE(pOut); REGISTER_TRACE(pOp->p2, pOut); break; } |
︙ | ︙ | |||
4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 | ** If the table or index is empty and P2>0, then jump immediately to P2. ** If P2 is 0 or if the table or index is not empty, fall through ** 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_Last: { /* jump */ VdbeCursor *pC; BtCursor *pCrsr; int res; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->eCurType==CURTYPE_BTREE ); pCrsr = pC->uc.pCursor; res = 0; assert( pCrsr!=0 ); | > > > > > > > < < < < > > > > > | | | | > > > | 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 | ** If the table or index is empty and P2>0, then jump immediately to P2. ** If P2 is 0 or if the table or index is not empty, fall through ** 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. ** ** If P3 is -1, then the cursor is positioned at the end of the btree ** for the purpose of appending a new entry onto the btree. In that ** case P2 must be 0. It is assumed that the cursor is used only for ** appending and so if the cursor is valid, then the cursor must already ** be pointing at the end of the btree and so no changes are made to ** the cursor. */ case OP_Last: { /* jump */ VdbeCursor *pC; BtCursor *pCrsr; int res; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->eCurType==CURTYPE_BTREE ); pCrsr = pC->uc.pCursor; res = 0; assert( pCrsr!=0 ); pC->seekResult = pOp->p3; #ifdef SQLITE_DEBUG pC->seekOp = OP_Last; #endif if( pOp->p3==0 || !sqlite3BtreeCursorIsValidNN(pCrsr) ){ rc = sqlite3BtreeLast(pCrsr, &res); pC->nullRow = (u8)res; pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; if( rc ) goto abort_due_to_error; if( pOp->p2>0 ){ VdbeBranchTaken(res!=0,2); if( res ) goto jump_to_p2; } }else{ assert( pOp->p2==0 ); } break; } /* Opcode: Sort P1 P2 * * * ** |
︙ | ︙ | |||
5013 5014 5015 5016 5017 5018 5019 | goto jump_to_p2_and_check_for_interrupt; }else{ pC->nullRow = 1; } goto check_for_interrupt; } | | > > > > > | | | | > > | | 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 | goto jump_to_p2_and_check_for_interrupt; }else{ pC->nullRow = 1; } goto check_for_interrupt; } /* Opcode: IdxInsert P1 P2 P3 P4 P5 ** Synopsis: key=r[P2] ** ** Register P2 holds an SQL index key made using the ** MakeRecord instructions. This opcode writes that key ** into the index P1. Data for the entry is nil. ** ** If P4 is not zero, then it is the number of values in the unpacked ** key of reg(P2). In that case, P3 is the index of the first register ** for the unpacked key. The availability of the unpacked key can sometimes ** be an optimization. ** ** If P5 has the OPFLAG_APPEND bit set, that is a hint to the b-tree layer ** that this insert is likely to be an append. ** ** If P5 has the OPFLAG_NCHANGE bit set, then the change counter is ** incremented by this instruction. If the OPFLAG_NCHANGE bit is clear, ** then the change counter is unchanged. ** ** If the OPFLAG_USESEEKRESULT flag of P5 is set, the implementation might ** run faster by avoiding an unnecessary seek on cursor P1. However, ** the OPFLAG_USESEEKRESULT flag must only be set if there have been no prior ** seeks on the cursor or if the most recent seek used a key equivalent ** to P2. ** ** This instruction only works for indices. The equivalent instruction ** for tables is OP_Insert. */ /* Opcode: SorterInsert P1 P2 * * * ** Synopsis: key=r[P2] ** |
︙ | ︙ | |||
5062 5063 5064 5065 5066 5067 5068 | rc = ExpandBlob(pIn2); if( rc ) goto abort_due_to_error; if( pOp->opcode==OP_SorterInsert ){ rc = sqlite3VdbeSorterWrite(pC, pIn2); }else{ x.nKey = pIn2->n; x.pKey = pIn2->z; | > > | > | 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 | rc = ExpandBlob(pIn2); if( rc ) goto abort_due_to_error; if( pOp->opcode==OP_SorterInsert ){ rc = sqlite3VdbeSorterWrite(pC, pIn2); }else{ x.nKey = pIn2->n; x.pKey = pIn2->z; x.aMem = aMem + pOp->p3; x.nMem = (u16)pOp->p4.i; rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, (pOp->p5 & OPFLAG_APPEND)!=0, ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0) ); assert( pC->deferredMoveto==0 ); pC->cacheStatus = CACHE_STALE; } if( rc) goto abort_due_to_error; break; |
︙ | ︙ | |||
5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 | if( rc ) goto abort_due_to_error; if( res==0 ){ rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE); if( rc ) goto abort_due_to_error; } assert( pC->deferredMoveto==0 ); pC->cacheStatus = CACHE_STALE; break; } /* Opcode: Seek P1 * P3 P4 * ** Synopsis: Move P3 to P1.rowid ** ** P1 is an open index cursor and P3 is a cursor on the corresponding | > | 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 | if( rc ) goto abort_due_to_error; if( res==0 ){ rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE); if( rc ) goto abort_due_to_error; } assert( pC->deferredMoveto==0 ); pC->cacheStatus = CACHE_STALE; pC->seekResult = 0; break; } /* Opcode: Seek P1 * P3 P4 * ** Synopsis: Move P3 to P1.rowid ** ** P1 is an open index cursor and P3 is a cursor on the corresponding |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
92 93 94 95 96 97 98 | BtCursor *pCursor; /* CURTYPE_BTREE. Btree cursor */ sqlite3_vtab_cursor *pVCur; /* CURTYPE_VTAB. Vtab cursor */ int pseudoTableReg; /* CURTYPE_PSEUDO. Reg holding content. */ VdbeSorter *pSorter; /* CURTYPE_SORTER. Sorter object */ } uc; Btree *pBt; /* Separate file holding temporary table */ KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */ | | > > > | 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | BtCursor *pCursor; /* CURTYPE_BTREE. Btree cursor */ sqlite3_vtab_cursor *pVCur; /* CURTYPE_VTAB. Vtab cursor */ int pseudoTableReg; /* CURTYPE_PSEUDO. Reg holding content. */ VdbeSorter *pSorter; /* CURTYPE_SORTER. Sorter object */ } uc; Btree *pBt; /* Separate file holding temporary table */ KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */ int seekResult; /* Result of previous sqlite3BtreeMoveto() or 0 ** if there have been no prior seeks on the cursor. */ /* NB: seekResult does not distinguish between "no seeks have ever occurred ** on this cursor" and "the most recent seek was an exact match". */ i64 seqCount; /* Sequence counter */ i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ VdbeCursor *pAltCursor; /* Associated index cursor from which to read */ int *aAltMap; /* Mapping from table to index column numbers */ #ifdef SQLITE_ENABLE_COLUMN_USED_MASK u64 maskUsed; /* Mask of columns used by this cursor */ #endif |
︙ | ︙ | |||
480 481 482 483 484 485 486 | i64 sqlite3VdbeIntValue(Mem*); int sqlite3VdbeMemIntegerify(Mem*); double sqlite3VdbeRealValue(Mem*); void sqlite3VdbeIntegerAffinity(Mem*); int sqlite3VdbeMemRealify(Mem*); int sqlite3VdbeMemNumerify(Mem*); void sqlite3VdbeMemCast(Mem*,u8,u8); | | | 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 | i64 sqlite3VdbeIntValue(Mem*); int sqlite3VdbeMemIntegerify(Mem*); double sqlite3VdbeRealValue(Mem*); void sqlite3VdbeIntegerAffinity(Mem*); int sqlite3VdbeMemRealify(Mem*); int sqlite3VdbeMemNumerify(Mem*); void sqlite3VdbeMemCast(Mem*,u8,u8); int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*); void sqlite3VdbeMemRelease(Mem *p); int sqlite3VdbeMemFinalize(Mem*, FuncDef*); const char *sqlite3OpcodeName(int); int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); int sqlite3VdbeMemClearAndResize(Mem *pMem, int n); int sqlite3VdbeCloseStatement(Vdbe *, int); void sqlite3VdbeFrameDelete(VdbeFrame*); |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
1734 1735 1736 1737 1738 1739 1740 | if( p->pUnpacked==0 ){ u32 nRec; u8 *aRec; nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor); aRec = sqlite3DbMallocRaw(db, nRec); if( !aRec ) goto preupdate_old_out; | | | 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 | if( p->pUnpacked==0 ){ u32 nRec; u8 *aRec; nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor); aRec = sqlite3DbMallocRaw(db, nRec); if( !aRec ) goto preupdate_old_out; rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec); if( rc==SQLITE_OK ){ p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec); if( !p->pUnpacked ) rc = SQLITE_NOMEM; } if( rc!=SQLITE_OK ){ sqlite3DbFree(db, aRec); goto preupdate_old_out; |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
1267 1268 1269 1270 1271 1272 1273 | break; } case P4_FUNCDEF: { FuncDef *pDef = pOp->p4.pFunc; sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg); break; } | | | 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 | break; } case P4_FUNCDEF: { FuncDef *pDef = pOp->p4.pFunc; sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg); break; } #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) case P4_FUNCCTX: { FuncDef *pDef = pOp->p4.pCtx->pFunc; sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg); break; } #endif case P4_INT64: { |
︙ | ︙ | |||
4361 4362 4363 4364 4365 4366 4367 | */ assert( sqlite3BtreeCursorIsValid(pCur) ); nCellKey = sqlite3BtreePayloadSize(pCur); assert( (nCellKey & SQLITE_MAX_U32)==(u64)nCellKey ); /* Read in the complete content of the index entry */ sqlite3VdbeMemInit(&m, db, 0); | | | 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 | */ assert( sqlite3BtreeCursorIsValid(pCur) ); nCellKey = sqlite3BtreePayloadSize(pCur); assert( (nCellKey & SQLITE_MAX_U32)==(u64)nCellKey ); /* Read in the complete content of the index entry */ sqlite3VdbeMemInit(&m, db, 0); rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, &m); if( rc ){ return rc; } /* The index entry must begin with a header size */ (void)getVarint32((u8*)m.z, szHdr); testcase( szHdr==3 ); |
︙ | ︙ | |||
4441 4442 4443 4444 4445 4446 4447 | /* nCellKey will always be between 0 and 0xffffffff because of the way ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */ if( nCellKey<=0 || nCellKey>0x7fffffff ){ *res = 0; return SQLITE_CORRUPT_BKPT; } sqlite3VdbeMemInit(&m, db, 0); | | | 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 | /* nCellKey will always be between 0 and 0xffffffff because of the way ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */ if( nCellKey<=0 || nCellKey>0x7fffffff ){ *res = 0; return SQLITE_CORRUPT_BKPT; } sqlite3VdbeMemInit(&m, db, 0); rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, &m); if( rc ){ return rc; } *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked); sqlite3VdbeMemRelease(&m); return SQLITE_OK; } |
︙ | ︙ |
Changes to src/vdbeblob.c.
︙ | ︙ | |||
258 259 260 261 262 263 264 | {OP_TableLock, 0, 0, 0}, /* 0: Acquire a read or write lock */ {OP_OpenRead, 0, 0, 0}, /* 1: Open a cursor */ {OP_Variable, 1, 1, 0}, /* 2: Move ?1 into reg[1] */ {OP_NotExists, 0, 7, 1}, /* 3: Seek the cursor */ {OP_Column, 0, 0, 1}, /* 4 */ {OP_ResultRow, 1, 0, 0}, /* 5 */ {OP_Goto, 0, 2, 0}, /* 6 */ | < | | 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 | {OP_TableLock, 0, 0, 0}, /* 0: Acquire a read or write lock */ {OP_OpenRead, 0, 0, 0}, /* 1: Open a cursor */ {OP_Variable, 1, 1, 0}, /* 2: Move ?1 into reg[1] */ {OP_NotExists, 0, 7, 1}, /* 3: Seek the cursor */ {OP_Column, 0, 0, 1}, /* 4 */ {OP_ResultRow, 1, 0, 0}, /* 5 */ {OP_Goto, 0, 2, 0}, /* 6 */ {OP_Halt, 0, 0, 0}, /* 7 */ }; Vdbe *v = (Vdbe *)pBlob->pStmt; int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); VdbeOp *aOp; sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, flags, pTab->pSchema->schema_cookie, |
︙ | ︙ | |||
437 438 439 440 441 442 443 | return rc; } /* ** Read data from a blob handle. */ int sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){ | | | 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 | return rc; } /* ** Read data from a blob handle. */ int sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){ return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreePayloadChecked); } /* ** Write data to a blob handle. */ int sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){ return blobReadWrite(pBlob, (void *)z, n, iOffset, sqlite3BtreePutData); |
︙ | ︙ |
Changes to src/vdbemem.c.
︙ | ︙ | |||
930 931 932 933 934 935 936 | } return SQLITE_OK; } /* ** Move data out of a btree key or data field and into a Mem structure. | | < | < < | < < < < | | 930 931 932 933 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 960 961 962 963 964 965 966 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 | } return SQLITE_OK; } /* ** Move data out of a btree key or data field and into a Mem structure. ** The data is payload from the entry that pCur is currently pointing ** to. offset and amt determine what portion of the data or key to retrieve. ** The result is written into the pMem element. ** ** The pMem object must have been initialized. This routine will use ** pMem->zMalloc to hold the content from the btree, if possible. New ** pMem->zMalloc space will be allocated if necessary. The calling routine ** is responsible for making sure that the pMem object is eventually ** destroyed. ** ** If this routine fails for any reason (malloc returns NULL or unable ** to read from the disk) then the pMem is left in an inconsistent state. */ static SQLITE_NOINLINE int vdbeMemFromBtreeResize( BtCursor *pCur, /* Cursor pointing at record to retrieve. */ u32 offset, /* Offset from the start of data to return bytes from. */ u32 amt, /* Number of bytes to return. */ Mem *pMem /* OUT: Return data in this Mem structure. */ ){ int rc; pMem->flags = MEM_Null; if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+2)) ){ rc = sqlite3BtreePayload(pCur, offset, amt, pMem->z); if( rc==SQLITE_OK ){ pMem->z[amt] = 0; pMem->z[amt+1] = 0; pMem->flags = MEM_Blob|MEM_Term; pMem->n = (int)amt; }else{ sqlite3VdbeMemRelease(pMem); } } return rc; } int sqlite3VdbeMemFromBtree( BtCursor *pCur, /* Cursor pointing at record to retrieve. */ u32 offset, /* Offset from the start of data to return bytes from. */ u32 amt, /* Number of bytes to return. */ Mem *pMem /* OUT: Return data in this Mem structure. */ ){ char *zData; /* Data from the btree layer */ u32 available = 0; /* Number of bytes available on the local btree page */ int rc = SQLITE_OK; /* Return code */ assert( sqlite3BtreeCursorIsValid(pCur) ); assert( !VdbeMemDynamic(pMem) ); /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert() ** that both the BtShared and database handle mutexes are held. */ assert( (pMem->flags & MEM_RowSet)==0 ); zData = (char *)sqlite3BtreePayloadFetch(pCur, &available); assert( zData!=0 ); if( offset+amt<=available ){ pMem->z = &zData[offset]; pMem->flags = MEM_Blob|MEM_Ephem; pMem->n = (int)amt; }else{ rc = vdbeMemFromBtreeResize(pCur, offset, amt, pMem); } return rc; } /* ** The pVal argument is known to be a value other than NULL. |
︙ | ︙ |
Changes to src/wal.c.
︙ | ︙ | |||
1944 1945 1946 1947 1948 1949 1950 | ** ordinary, rollback-mode locking methods, this guarantees that the ** connection associated with this log file is the only connection to ** the database. In this case checkpoint the database and unlink both ** the wal and wal-index files. ** ** The EXCLUSIVE lock is not released before returning. */ | | | 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 | ** ordinary, rollback-mode locking methods, this guarantees that the ** connection associated with this log file is the only connection to ** the database. In this case checkpoint the database and unlink both ** the wal and wal-index files. ** ** The EXCLUSIVE lock is not released before returning. */ if( zBuf!=0 && SQLITE_OK==(rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE)) ){ if( pWal->exclusiveMode==WAL_NORMAL_MODE ){ pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; } rc = sqlite3WalCheckpoint(pWal, db, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0 |
︙ | ︙ | |||
2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 | }else{ assert( mxReadMark<=pWal->hdr.mxFrame ); pWal->readLock = (i16)mxI; } return rc; } /* ** Begin a read transaction on the database. ** ** This routine used to be called sqlite3OpenSnapshot() and with good reason: ** it takes a snapshot of the state of the WAL and wal-index for the current ** instant in time. The current thread will continue to use this snapshot. ** Other threads might append new content to the WAL and wal-index but | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 | }else{ assert( mxReadMark<=pWal->hdr.mxFrame ); pWal->readLock = (i16)mxI; } return rc; } #ifdef SQLITE_ENABLE_SNAPSHOT /* ** Attempt to reduce the value of the WalCkptInfo.nBackfillAttempted ** variable so that older snapshots can be accessed. To do this, loop ** through all wal frames from nBackfillAttempted to (nBackfill+1), ** comparing their content to the corresponding page with the database ** file, if any. Set nBackfillAttempted to the frame number of the ** first frame for which the wal file content matches the db file. ** ** This is only really safe if the file-system is such that any page ** writes made by earlier checkpointers were atomic operations, which ** is not always true. It is also possible that nBackfillAttempted ** may be left set to a value larger than expected, if a wal frame ** contains content that duplicate of an earlier version of the same ** page. ** ** SQLITE_OK is returned if successful, or an SQLite error code if an ** error occurs. It is not an error if nBackfillAttempted cannot be ** decreased at all. */ int sqlite3WalSnapshotRecover(Wal *pWal){ int rc; assert( pWal->readLock>=0 ); rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); if( rc==SQLITE_OK ){ volatile WalCkptInfo *pInfo = walCkptInfo(pWal); int szPage = (int)pWal->szPage; i64 szDb; /* Size of db file in bytes */ rc = sqlite3OsFileSize(pWal->pDbFd, &szDb); if( rc==SQLITE_OK ){ void *pBuf1 = sqlite3_malloc(szPage); void *pBuf2 = sqlite3_malloc(szPage); if( pBuf1==0 || pBuf2==0 ){ rc = SQLITE_NOMEM; }else{ u32 i = pInfo->nBackfillAttempted; for(i=pInfo->nBackfillAttempted; i>pInfo->nBackfill; i--){ volatile ht_slot *dummy; volatile u32 *aPgno; /* Array of page numbers */ u32 iZero; /* Frame corresponding to aPgno[0] */ u32 pgno; /* Page number in db file */ i64 iDbOff; /* Offset of db file entry */ i64 iWalOff; /* Offset of wal file entry */ rc = walHashGet(pWal, walFramePage(i), &dummy, &aPgno, &iZero); if( rc!=SQLITE_OK ) break; pgno = aPgno[i-iZero]; iDbOff = (i64)(pgno-1) * szPage; if( iDbOff+szPage<=szDb ){ iWalOff = walFrameOffset(i, szPage) + WAL_FRAME_HDRSIZE; rc = sqlite3OsRead(pWal->pWalFd, pBuf1, szPage, iWalOff); if( rc==SQLITE_OK ){ rc = sqlite3OsRead(pWal->pDbFd, pBuf2, szPage, iDbOff); } if( rc!=SQLITE_OK || 0==memcmp(pBuf1, pBuf2, szPage) ){ break; } } pInfo->nBackfillAttempted = i-1; } } sqlite3_free(pBuf1); sqlite3_free(pBuf2); } walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); } return rc; } #endif /* SQLITE_ENABLE_SNAPSHOT */ /* ** Begin a read transaction on the database. ** ** This routine used to be called sqlite3OpenSnapshot() and with good reason: ** it takes a snapshot of the state of the WAL and wal-index for the current ** instant in time. The current thread will continue to use this snapshot. ** Other threads might append new content to the WAL and wal-index but |
︙ | ︙ | |||
2445 2446 2447 2448 2449 2450 2451 | /* It is possible that there is a checkpointer thread running ** concurrent with this code. If this is the case, it may be that the ** checkpointer has already determined that it will checkpoint ** snapshot X, where X is later in the wal file than pSnapshot, but ** has not yet set the pInfo->nBackfillAttempted variable to indicate ** its intent. To avoid the race condition this leads to, ensure that ** there is no checkpointer process by taking a shared CKPT lock | | > > > > | 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 | /* It is possible that there is a checkpointer thread running ** concurrent with this code. If this is the case, it may be that the ** checkpointer has already determined that it will checkpoint ** snapshot X, where X is later in the wal file than pSnapshot, but ** has not yet set the pInfo->nBackfillAttempted variable to indicate ** its intent. To avoid the race condition this leads to, ensure that ** there is no checkpointer process by taking a shared CKPT lock ** before checking pInfo->nBackfillAttempted. ** ** TODO: Does the aReadMark[] lock prevent a checkpointer from doing ** this already? */ rc = walLockShared(pWal, WAL_CKPT_LOCK); if( rc==SQLITE_OK ){ /* Check that the wal file has not been wrapped. Assuming that it has ** not, also check that no checkpointer has attempted to checkpoint any ** frames beyond pSnapshot->mxFrame. If either of these conditions are ** true, return SQLITE_BUSY_SNAPSHOT. Otherwise, overwrite pWal->hdr |
︙ | ︙ | |||
3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 | /* Create a snapshot object. The content of a snapshot is opaque to ** every other subsystem, so the WAL module can put whatever it needs ** in the object. */ int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot){ int rc = SQLITE_OK; WalIndexHdr *pRet; assert( pWal->readLock>=0 && pWal->writeLock==0 ); pRet = (WalIndexHdr*)sqlite3_malloc(sizeof(WalIndexHdr)); if( pRet==0 ){ rc = SQLITE_NOMEM_BKPT; }else{ memcpy(pRet, &pWal->hdr, sizeof(WalIndexHdr)); *ppSnapshot = (sqlite3_snapshot*)pRet; } | > > > > > | 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 | /* Create a snapshot object. The content of a snapshot is opaque to ** every other subsystem, so the WAL module can put whatever it needs ** in the object. */ int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot){ int rc = SQLITE_OK; WalIndexHdr *pRet; static const u32 aZero[4] = { 0, 0, 0, 0 }; assert( pWal->readLock>=0 && pWal->writeLock==0 ); if( memcmp(&pWal->hdr.aFrameCksum[0],aZero,16)==0 ){ *ppSnapshot = 0; return SQLITE_ERROR; } pRet = (WalIndexHdr*)sqlite3_malloc(sizeof(WalIndexHdr)); if( pRet==0 ){ rc = SQLITE_NOMEM_BKPT; }else{ memcpy(pRet, &pWal->hdr, sizeof(WalIndexHdr)); *ppSnapshot = (sqlite3_snapshot*)pRet; } |
︙ | ︙ |
Changes to src/wal.h.
︙ | ︙ | |||
130 131 132 133 134 135 136 137 138 139 140 141 142 143 | ** WAL module is using shared-memory, return false. */ int sqlite3WalHeapMemory(Wal *pWal); #ifdef SQLITE_ENABLE_SNAPSHOT int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot); void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot); #endif #ifdef SQLITE_ENABLE_ZIPVFS /* If the WAL file is not empty, return the number of bytes of content ** stored in each frame (i.e. the db page-size when the WAL was created). */ int sqlite3WalFramesize(Wal *pWal); | > | 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | ** WAL module is using shared-memory, return false. */ int sqlite3WalHeapMemory(Wal *pWal); #ifdef SQLITE_ENABLE_SNAPSHOT int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot); void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot); int sqlite3WalSnapshotRecover(Wal *pWal); #endif #ifdef SQLITE_ENABLE_ZIPVFS /* If the WAL file is not empty, return the number of bytes of content ** stored in each frame (i.e. the db page-size when the WAL was created). */ int sqlite3WalFramesize(Wal *pWal); |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
4907 4908 4909 4910 4911 4912 4913 | */ if( pTabItem->fg.viaCoroutine && !db->mallocFailed ){ translateColumnToCopy(v, pLevel->addrBody, pLevel->iTabCur, pTabItem->regResult, 0); continue; } | < < < < < < < < < < < < < < < < < < < < < | 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 | */ if( pTabItem->fg.viaCoroutine && !db->mallocFailed ){ translateColumnToCopy(v, 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 ** this optimization prevents the table from ever being read, which can ** yield a significant performance boost. ** ** Calls to the code generator in between sqlite3WhereBegin and ** sqlite3WhereEnd will have created code that references the table |
︙ | ︙ |
Changes to src/wherecode.c.
︙ | ︙ | |||
442 443 444 445 446 447 448 449 450 451 452 453 454 455 | } if( (pX->flags & EP_xIsSelect)==0 || pX->x.pSelect->pEList->nExpr==1 ){ eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0); }else{ Select *pSelect = pX->x.pSelect; sqlite3 *db = pParse->db; ExprList *pOrigRhs = pSelect->pEList; ExprList *pOrigLhs = pX->pLeft->x.pList; ExprList *pRhs = 0; /* New Select.pEList for RHS */ ExprList *pLhs = 0; /* New pX->pLeft vector */ for(i=iEq;i<pLoop->nLTerm; i++){ if( pLoop->aLTerm[i]->pExpr==pX ){ | > | 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 | } if( (pX->flags & EP_xIsSelect)==0 || pX->x.pSelect->pEList->nExpr==1 ){ eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0); }else{ Select *pSelect = pX->x.pSelect; sqlite3 *db = pParse->db; u16 savedDbOptFlags = db->dbOptFlags; ExprList *pOrigRhs = pSelect->pEList; ExprList *pOrigLhs = pX->pLeft->x.pList; ExprList *pRhs = 0; /* New Select.pEList for RHS */ ExprList *pLhs = 0; /* New pX->pLeft vector */ for(i=iEq;i<pLoop->nLTerm; i++){ if( pLoop->aLTerm[i]->pExpr==pX ){ |
︙ | ︙ | |||
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 | pX->pLeft = pLhs->a[0].pExpr; }else{ pLeft->x.pList = pLhs; aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int) * nEq); testcase( aiMap==0 ); } pSelect->pEList = pRhs; eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap); testcase( aiMap!=0 && aiMap[0]!=0 ); pSelect->pEList = pOrigRhs; pLeft->x.pList = pOrigLhs; pX->pLeft = pLeft; } sqlite3ExprListDelete(pParse->db, pLhs); sqlite3ExprListDelete(pParse->db, pRhs); | > > | 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 | pX->pLeft = pLhs->a[0].pExpr; }else{ pLeft->x.pList = pLhs; aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int) * nEq); testcase( aiMap==0 ); } pSelect->pEList = pRhs; db->dbOptFlags |= SQLITE_QueryFlattener; eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap); db->dbOptFlags = savedDbOptFlags; testcase( aiMap!=0 && aiMap[0]!=0 ); pSelect->pEList = pOrigRhs; pLeft->x.pList = pOrigLhs; pX->pLeft = pLeft; } sqlite3ExprListDelete(pParse->db, pLhs); sqlite3ExprListDelete(pParse->db, pRhs); |
︙ | ︙ | |||
1840 1841 1842 1843 1844 1845 1846 | ** be tested for. */ if( iSet ){ jmp1 = sqlite3VdbeAddOp4Int(v, OP_Found, regRowset, 0, r, nPk); VdbeCoverage(v); } if( iSet>=0 ){ sqlite3VdbeAddOp3(v, OP_MakeRecord, r, nPk, regRowid); | | > | 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 | ** be tested for. */ if( iSet ){ jmp1 = sqlite3VdbeAddOp4Int(v, OP_Found, regRowset, 0, r, nPk); VdbeCoverage(v); } if( iSet>=0 ){ sqlite3VdbeAddOp3(v, OP_MakeRecord, r, nPk, regRowid); sqlite3VdbeAddOp4Int(v, OP_IdxInsert, regRowset, regRowid, r, nPk); if( iSet ) sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); } /* Release the array of temp registers */ sqlite3ReleaseTempRange(pParse, r, nPk); } } |
︙ | ︙ |
Changes to src/whereexpr.c.
︙ | ︙ | |||
1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 | } } #endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ /* Prevent ON clause terms of a LEFT JOIN from being used to drive ** an index for tables to the left of the join. */ pTerm->prereqRight |= extraRight; } /*************************************************************************** ** Routines with file scope above. Interface to the rest of the where.c ** subsystem follows. ***************************************************************************/ | > > | 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 | } } #endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ /* Prevent ON clause terms of a LEFT JOIN from being used to drive ** an index for tables to the left of the join. */ testcase( pTerm!=&pWC->a[idxTerm] ); pTerm = &pWC->a[idxTerm]; pTerm->prereqRight |= extraRight; } /*************************************************************************** ** Routines with file scope above. Interface to the rest of the where.c ** subsystem follows. ***************************************************************************/ |
︙ | ︙ |
Added test/bestindex4.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | # 2016 November 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. # #*********************************************************************** # Test the virtual table interface. In particular the xBestIndex # method. # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix bestindex4 ifcapable !vtab { finish_test return } #------------------------------------------------------------------------- # Virtual table callback for a virtual table named $tbl. # # The table created is: # # "CREATE TABLE t1 (id, host, class)" # # The virtual table supports == operators on a subset of its columns. The # exact subset depends on the value of bitmask paramater $param. # # 0x01 - == on "id" supported # 0x02 - == on "host" supported # 0x04 - == on "class" supported # # $param also supports the following bits: # # 0x08 - ignore the "usable" flag (malfunction) # # # proc vtab_cmd {param method args} { switch -- $method { xConnect { return "CREATE TABLE t1(id TEXT, host TEXT, class TEXT)" } xBestIndex { foreach {clist orderby mask} $args {} set ret [list] set use use for {set i 0} {$i < [llength $clist]} {incr i} { array unset C array set C [lindex $clist $i] if { ($C(usable) || ($param & 0x08)) && $C(op)=="eq" && ($param & 1<<$C(column)) } { lappend ret $use $i break } } set score 1000000 if {$ret!=""} { set score [expr $score / [llength $ret]] } lappend ret cost $score rows $score return $ret } xFilter { } } return "" } register_tcl_module db for {set param1 0} {$param1<16} {incr param1} { for {set param2 0} {$param2<16} {incr param2} { reset_db register_tcl_module db do_execsql_test 1.$param1.$param2.1 " CREATE VIRTUAL TABLE t1 USING tcl('vtab_cmd $param1'); CREATE VIRTUAL TABLE t2 USING tcl('vtab_cmd $param2'); " foreach {tn sql} { 2 "select t1.id as ID from t1, t2 where t1.id=t2.host and t2.class='xx'" 3 { select t1.id as ID from t1, t2 where t2.class ='xx' and t2.id = t1.host } 4 { select t1.id as ID from t1, t2 where t1.host = t2.id and t2. class ='xx' } } { if {($param1 & 0x08)==0 && ($param2 & 0x08)==0} { do_execsql_test 1.$param1.$param2.$tn.a $sql {} } else { do_test 1.$param1.$param2.$tn.b { catchsql $sql set {} {} } {} } } } } finish_test |
Changes to test/e_expr.test.
︙ | ︙ | |||
1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 | # result of the CAST expression is also NULL. # do_expr_test e_expr-27.2.1 { CAST(NULL AS integer) } null {} do_expr_test e_expr-27.2.2 { CAST(NULL AS text) } null {} do_expr_test e_expr-27.2.3 { CAST(NULL AS blob) } null {} do_expr_test e_expr-27.2.4 { CAST(NULL AS number) } null {} # EVIDENCE-OF: R-43522-35548 Casting a value to a type-name with no # affinity causes the value to be converted into a BLOB. # do_expr_test e_expr-27.3.1 { CAST('abc' AS blob) } blob abc do_expr_test e_expr-27.3.2 { CAST('def' AS shobblob_x) } blob def do_expr_test e_expr-27.3.3 { CAST('ghi' AS abbLOb10) } blob ghi | > > > > > > > | 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 | # result of the CAST expression is also NULL. # do_expr_test e_expr-27.2.1 { CAST(NULL AS integer) } null {} do_expr_test e_expr-27.2.2 { CAST(NULL AS text) } null {} do_expr_test e_expr-27.2.3 { CAST(NULL AS blob) } null {} do_expr_test e_expr-27.2.4 { CAST(NULL AS number) } null {} # EVIDENCE-OF: R-29283-15561 Otherwise, the storage class of the result # is determined by applying the rules for determining column affinity to # the type-name. # # The R-29283-15561 requirement above is demonstrated by all of the # subsequent e_expr-26 tests. # # EVIDENCE-OF: R-43522-35548 Casting a value to a type-name with no # affinity causes the value to be converted into a BLOB. # do_expr_test e_expr-27.3.1 { CAST('abc' AS blob) } blob abc do_expr_test e_expr-27.3.2 { CAST('def' AS shobblob_x) } blob def do_expr_test e_expr-27.3.3 { CAST('ghi' AS abbLOb10) } blob ghi |
︙ | ︙ | |||
1782 1783 1784 1785 1786 1787 1788 | CREATE TABLE t2(a, b); INSERT INTO t2 VALUES('one', 'two'); INSERT INTO t2 VALUES('three', NULL); INSERT INTO t2 VALUES(4, 5.0); } } {} | | | | | > | | | | | 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 | CREATE TABLE t2(a, b); INSERT INTO t2 VALUES('one', 'two'); INSERT INTO t2 VALUES('three', NULL); INSERT INTO t2 VALUES(4, 5.0); } } {} # EVIDENCE-OF: R-43573-23448 A SELECT statement enclosed in parentheses # is a subquery. # # EVIDENCE-OF: R-56294-03966 All types of SELECT statement, including # aggregate and compound SELECT queries (queries with keywords like # UNION or EXCEPT) are allowed as scalar subqueries. # do_expr_test e_expr-35.1.1 { (SELECT 35) } integer 35 do_expr_test e_expr-35.1.2 { (SELECT NULL) } null {} do_expr_test e_expr-35.1.3 { (SELECT count(*) FROM t2) } integer 3 do_expr_test e_expr-35.1.4 { (SELECT 4 FROM t2) } integer 4 do_expr_test e_expr-35.1.5 { (SELECT b FROM t2 UNION SELECT a+1 FROM t2) } null {} do_expr_test e_expr-35.1.6 { (SELECT a FROM t2 UNION SELECT COALESCE(b, 55) FROM t2 ORDER BY 1) } integer 4 # EVIDENCE-OF: R-22239-33740 A subquery that returns two or more columns # is a row value subquery and can only be used as the operand of a # comparison operator. # # The following block tests that errors are returned in a bunch of cases # where a subquery returns more than one column. # set M {/1 {sub-select returns [23] columns - expected 1}/} foreach {tn sql} { 1 { SELECT (SELECT * FROM t2 UNION SELECT a+1, b+1 FROM t2) } 2 { SELECT (SELECT * FROM t2 UNION SELECT a+1, b+1 FROM t2 ORDER BY 1) } 3 { SELECT (SELECT 1, 2) } 4 { SELECT (SELECT NULL, NULL, NULL) } 5 { SELECT (SELECT * FROM t2) } 6 { SELECT (SELECT * FROM (SELECT 1, 2, 3)) } } { do_catchsql_test e_expr-35.2.$tn $sql $M } # EVIDENCE-OF: R-18318-14995 The value of a subquery expression is the # first row of the result from the enclosed SELECT statement. # # EVIDENCE-OF: R-15900-52156 In other words, an implied "LIMIT 1" is # added to the subquery, overriding an explicitly coded LIMIT. # do_execsql_test e_expr-36.3.1 { CREATE TABLE t4(x, y); INSERT INTO t4 VALUES(1, 'one'); INSERT INTO t4 VALUES(2, 'two'); INSERT INTO t4 VALUES(3, 'three'); } {} |
︙ | ︙ | |||
1848 1849 1850 1851 1852 1853 1854 | 8 { ( SELECT group_concat(y,'') FROM t4 ) } text onetwothree 9 { ( SELECT max(x) FROM t4 WHERE y LIKE '___') } integer 2 } { do_expr_test e_expr-36.3.$tn $expr $restype $resval } | | | | 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 | 8 { ( SELECT group_concat(y,'') FROM t4 ) } text onetwothree 9 { ( SELECT max(x) FROM t4 WHERE y LIKE '___') } integer 2 } { do_expr_test e_expr-36.3.$tn $expr $restype $resval } # EVIDENCE-OF: R-52325-25449 The value of a subquery expression is NULL # if the enclosed SELECT statement returns no rows. # foreach {tn expr} { 1 { ( SELECT x FROM t4 WHERE x>3 ORDER BY x ) } 2 { ( SELECT x FROM t4 WHERE y<'one' ORDER BY y ) } } { do_expr_test e_expr-36.4.$tn $expr null {} } |
︙ | ︙ |
Changes to test/e_select.test.
︙ | ︙ | |||
1248 1249 1250 1251 1252 1253 1254 | # EVIDENCE-OF: R-02054-15343 For the purposes of detecting duplicate # rows, two NULL values are considered to be equal. # do_select_tests e_select-5.5 { 1 "SELECT DISTINCT d FROM h3" {{} 2 2,3 2,4 3} } | | | | 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 | # EVIDENCE-OF: R-02054-15343 For the purposes of detecting duplicate # rows, two NULL values are considered to be equal. # do_select_tests e_select-5.5 { 1 "SELECT DISTINCT d FROM h3" {{} 2 2,3 2,4 3} } # EVIDENCE-OF: R-47709-27231 The usual rules apply for selecting a # collation sequence to compare text values. # do_select_tests e_select-5.6 { 1 "SELECT DISTINCT b FROM h1" {one I i four IV iv} 2 "SELECT DISTINCT b COLLATE nocase FROM h1" {one I four IV} 3 "SELECT DISTINCT x FROM h2" {One Two Three Four} 4 "SELECT DISTINCT x COLLATE binary FROM h2" { One Two Three Four one two three four |
︙ | ︙ |
Changes to test/fuzz-oss1.test.
︙ | ︙ | |||
1993 1994 1995 1996 1997 1998 1999 2000 2001 | "nao:Property14"."ID" AND "9_u" IS NOT NULL AND "10_u" IS NOT NULL AND ("9_u" COLLATE NOCASE = ? COLLATE NOCASE))) FROM (SELECT "nco:PersonContact1"."ID" AS "1_u" FROM "nco:PersonContact" AS "nco:PersonContact1") ORDER BY "1_u"; } } {/.* Goto .*/} finish_test | > > > > | 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 | "nao:Property14"."ID" AND "9_u" IS NOT NULL AND "10_u" IS NOT NULL AND ("9_u" COLLATE NOCASE = ? COLLATE NOCASE))) FROM (SELECT "nco:PersonContact1"."ID" AS "1_u" FROM "nco:PersonContact" AS "nco:PersonContact1") ORDER BY "1_u"; } } {/.* Goto .*/} # Crash reported by OSS-FUZZ on 2016-11-10 do_catchsql_test fuzz-oss1-detach { DETACH x IS #1; } {1 {near "#1": syntax error}} finish_test |
Changes to test/fuzzcheck.c.
︙ | ︙ | |||
76 77 78 79 80 81 82 83 84 85 86 87 88 89 | #ifdef __unix__ # include <signal.h> # include <unistd.h> #endif /* ** Files in the virtual file system. */ typedef struct VFile VFile; struct VFile { char *zFilename; /* Filename. NULL for delete-on-close. From malloc() */ int sz; /* Size of the file in bytes */ | > > > > > | 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | #ifdef __unix__ # include <signal.h> # include <unistd.h> #endif #ifdef SQLITE_OSS_FUZZ # include <stddef.h> # include <stdint.h> #endif /* ** Files in the virtual file system. */ typedef struct VFile VFile; struct VFile { char *zFilename; /* Filename. NULL for delete-on-close. From malloc() */ int sz; /* Size of the file in bytes */ |
︙ | ︙ | |||
790 791 792 793 794 795 796 797 798 799 800 801 802 803 | " -q|--quiet Reduced output\n" " --limit-mem N Limit memory used by test SQLite instance to N bytes\n" " --limit-vdbe Panic if any test runs for more than 100,000 cycles\n" " --load-sql ARGS... Load SQL scripts fro files into SOURCE-DB\n" " --load-db ARGS... Load template databases from files into SOURCE_DB\n" " -m TEXT Add a description to the database\n" " --native-vfs Use the native VFS for initially empty database files\n" " --rebuild Rebuild and vacuum the database file\n" " --result-trace Show the results of each SQL command\n" " --sqlid N Use only SQL where sqlid=N\n" " --timeout N Abort if any single test needs more than N seconds\n" " -v|--verbose Increased output. Repeat for more output.\n" ); } | > | 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 | " -q|--quiet Reduced output\n" " --limit-mem N Limit memory used by test SQLite instance to N bytes\n" " --limit-vdbe Panic if any test runs for more than 100,000 cycles\n" " --load-sql ARGS... Load SQL scripts fro files into SOURCE-DB\n" " --load-db ARGS... Load template databases from files into SOURCE_DB\n" " -m TEXT Add a description to the database\n" " --native-vfs Use the native VFS for initially empty database files\n" " --oss-fuzz Enable OSS-FUZZ testing\n" " --rebuild Rebuild and vacuum the database file\n" " --result-trace Show the results of each SQL command\n" " --sqlid N Use only SQL where sqlid=N\n" " --timeout N Abort if any single test needs more than N seconds\n" " -v|--verbose Increased output. Repeat for more output.\n" ); } |
︙ | ︙ | |||
828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 | int nTest = 0; /* Total number of tests performed */ char *zDbName = ""; /* Appreviated name of a source database */ const char *zFailCode = 0; /* Value of the TEST_FAILURE environment variable */ int cellSzCkFlag = 0; /* --cell-size-check */ int sqlFuzz = 0; /* True for SQL fuzz testing. False for DB fuzz */ int iTimeout = 120; /* Default 120-second timeout */ int nMem = 0; /* Memory limit */ char *zExpDb = 0; /* Write Databases to files in this directory */ char *zExpSql = 0; /* Write SQL to files in this directory */ void *pHeap = 0; /* Heap for use by SQLite */ iBegin = timeOfDay(); #ifdef __unix__ signal(SIGALRM, timeoutHandler); #endif g.zArgv0 = argv[0]; zFailCode = getenv("TEST_FAILURE"); | > > > | 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 | int nTest = 0; /* Total number of tests performed */ char *zDbName = ""; /* Appreviated name of a source database */ const char *zFailCode = 0; /* Value of the TEST_FAILURE environment variable */ int cellSzCkFlag = 0; /* --cell-size-check */ int sqlFuzz = 0; /* True for SQL fuzz testing. False for DB fuzz */ int iTimeout = 120; /* Default 120-second timeout */ int nMem = 0; /* Memory limit */ int nMemThisDb = 0; /* Memory limit set by the CONFIG table */ char *zExpDb = 0; /* Write Databases to files in this directory */ char *zExpSql = 0; /* Write SQL to files in this directory */ void *pHeap = 0; /* Heap for use by SQLite */ int ossFuzz = 0; /* enable OSS-FUZZ testing */ int ossFuzzThisDb = 0; /* ossFuzz value for this particular database */ iBegin = timeOfDay(); #ifdef __unix__ signal(SIGALRM, timeoutHandler); #endif g.zArgv0 = argv[0]; zFailCode = getenv("TEST_FAILURE"); |
︙ | ︙ | |||
890 891 892 893 894 895 896 897 898 899 900 901 902 903 | }else if( strcmp(z,"m")==0 ){ if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]); zMsg = argv[++i]; }else if( strcmp(z,"native-vfs")==0 ){ nativeFlag = 1; }else if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){ quietFlag = 1; verboseFlag = 0; }else if( strcmp(z,"rebuild")==0 ){ rebuildFlag = 1; | > > > | 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 | }else if( strcmp(z,"m")==0 ){ if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]); zMsg = argv[++i]; }else if( strcmp(z,"native-vfs")==0 ){ nativeFlag = 1; }else if( strcmp(z,"oss-fuzz")==0 ){ ossFuzz = 1; }else if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){ quietFlag = 1; verboseFlag = 0; }else if( strcmp(z,"rebuild")==0 ){ rebuildFlag = 1; |
︙ | ︙ | |||
967 968 969 970 971 972 973 974 975 976 977 978 979 980 | char *zSql; zSql = sqlite3_mprintf( "DELETE FROM readme; INSERT INTO readme(msg) VALUES(%Q)", zMsg); rc = sqlite3_exec(db, zSql, 0, 0, 0); sqlite3_free(zSql); if( rc ) fatalError("cannot change description: %s", sqlite3_errmsg(db)); } if( zInsSql ){ sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0, readfileFunc, 0, 0); rc = sqlite3_prepare_v2(db, zInsSql, -1, &pStmt, 0); if( rc ) fatalError("cannot prepare statement [%s]: %s", zInsSql, sqlite3_errmsg(db)); rc = sqlite3_exec(db, "BEGIN", 0, 0, 0); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 | char *zSql; zSql = sqlite3_mprintf( "DELETE FROM readme; INSERT INTO readme(msg) VALUES(%Q)", zMsg); rc = sqlite3_exec(db, zSql, 0, 0, 0); sqlite3_free(zSql); if( rc ) fatalError("cannot change description: %s", sqlite3_errmsg(db)); } ossFuzzThisDb = ossFuzz; /* If the CONFIG(name,value) table exists, read db-specific settings ** from that table */ if( sqlite3_table_column_metadata(db,0,"config",0,0,0,0,0,0)==SQLITE_OK ){ rc = sqlite3_prepare_v2(db, "SELECT name, value FROM config", -1, &pStmt, 0); if( rc ) fatalError("cannot prepare query of CONFIG table: %s", sqlite3_errmsg(db)); while( SQLITE_ROW==sqlite3_step(pStmt) ){ const char *zName = (const char *)sqlite3_column_text(pStmt,0); if( zName==0 ) continue; if( strcmp(zName, "oss-fuzz")==0 ){ ossFuzzThisDb = sqlite3_column_int(pStmt,1); if( verboseFlag ) printf("Config: oss-fuzz=%d\n", ossFuzzThisDb); } if( strcmp(zName, "limit-mem")==0 ){ #if !defined(SQLITE_ENABLE_MEMSYS3) && !defined(SQLITE_ENABLE_MEMSYS5) fatalError("the limit-mem option requires -DSQLITE_ENABLE_MEMSYS5" " or _MEMSYS3"); #else nMemThisDb = sqlite3_column_int(pStmt,1); if( verboseFlag ) printf("Config: limit-mem=%d\n", nMemThisDb); #endif } } sqlite3_finalize(pStmt); } if( zInsSql ){ sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0, readfileFunc, 0, 0); rc = sqlite3_prepare_v2(db, zInsSql, -1, &pStmt, 0); if( rc ) fatalError("cannot prepare statement [%s]: %s", zInsSql, sqlite3_errmsg(db)); rc = sqlite3_exec(db, "BEGIN", 0, 0, 0); |
︙ | ︙ | |||
1082 1083 1084 1085 1086 1087 1088 | */ sqlite3_close(db); if( sqlite3_memory_used()>0 ){ fatalError("SQLite has memory in use before the start of testing"); } /* Limit available memory, if requested */ | | | | | 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 | */ sqlite3_close(db); if( sqlite3_memory_used()>0 ){ fatalError("SQLite has memory in use before the start of testing"); } /* Limit available memory, if requested */ if( nMemThisDb>0 ){ sqlite3_shutdown(); pHeap = realloc(pHeap, nMemThisDb); if( pHeap==0 ){ fatalError("failed to allocate %d bytes of heap memory", nMem); } sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nMemThisDb, 128); } /* Register the in-memory virtual filesystem */ formatVfs(); inmemVfsRegister(); |
︙ | ︙ | |||
1119 1120 1121 1122 1123 1124 1125 | if( amt!=prevAmt ){ printf(" %d%%", amt*10); fflush(stdout); prevAmt = amt; } } createVFile("main.db", pDb->sz, pDb->a); | > > > > > > > > | | | | | | | | | | | | | | | | | > | 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 | if( amt!=prevAmt ){ printf(" %d%%", amt*10); fflush(stdout); prevAmt = amt; } } createVFile("main.db", pDb->sz, pDb->a); if( ossFuzzThisDb ){ #ifndef SQLITE_OSS_FUZZ fatalError("--oss-fuzz not supported: recompile with -DSQLITE_OSS_FUZZ"); #else extern int LLVMFuzzerTestOneInput(const uint8_t*, size_t); LLVMFuzzerTestOneInput((const uint8_t*)pSql->a, (size_t)pSql->sz); #endif }else{ openFlags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE; if( nativeFlag && pDb->sz==0 ){ openFlags |= SQLITE_OPEN_MEMORY; zVfs = 0; } rc = sqlite3_open_v2("main.db", &db, openFlags, zVfs); if( rc ) fatalError("cannot open inmem database"); if( cellSzCkFlag ) runSql(db, "PRAGMA cell_size_check=ON", runFlags); setAlarm(iTimeout); #ifndef SQLITE_OMIT_PROGRESS_CALLBACK if( sqlFuzz || vdbeLimitFlag ){ sqlite3_progress_handler(db, 100000, progressHandler, &vdbeLimitFlag); } #endif do{ runSql(db, (char*)pSql->a, runFlags); }while( timeoutTest ); setAlarm(0); sqlite3_close(db); } if( sqlite3_memory_used()>0 ) fatalError("memory leak"); reformatVfs(); nTest++; g.zTestName[0] = 0; /* Simulate an error if the TEST_FAILURE environment variable is "5". ** This is used to verify that automated test script really do spot |
︙ | ︙ |
Added test/fuzzdata5.db.
cannot compute difference between binary files
Changes to test/json101.test.
︙ | ︙ | |||
378 379 380 381 382 383 384 | do_catchsql_test json-9.6 { SELECT json_quote(123,456) } {1 {wrong number of arguments to function json_quote()}} do_catchsql_test json-9.7 { SELECT json_quote() } {1 {wrong number of arguments to function json_quote()}} | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 | do_catchsql_test json-9.6 { SELECT json_quote(123,456) } {1 {wrong number of arguments to function json_quote()}} do_catchsql_test json-9.7 { SELECT json_quote() } {1 {wrong number of arguments to function json_quote()}} # Make sure only valid backslash-escapes are accepted. # do_execsql_test json-10.1 { SELECT json_valid('" \ "'); } {0} do_execsql_test json-10.2 { SELECT json_valid('" \! "'); } {0} do_execsql_test json-10.3 { SELECT json_valid('" \" "'); } {1} do_execsql_test json-10.4 { SELECT json_valid('" \# "'); } {0} do_execsql_test json-10.5 { SELECT json_valid('" \$ "'); } {0} do_execsql_test json-10.6 { SELECT json_valid('" \% "'); } {0} do_execsql_test json-10.7 { SELECT json_valid('" \& "'); } {0} do_execsql_test json-10.8 { SELECT json_valid('" \'' "'); } {0} do_execsql_test json-10.9 { SELECT json_valid('" \( "'); } {0} do_execsql_test json-10.10 { SELECT json_valid('" \) "'); } {0} do_execsql_test json-10.11 { SELECT json_valid('" \* "'); } {0} do_execsql_test json-10.12 { SELECT json_valid('" \+ "'); } {0} do_execsql_test json-10.13 { SELECT json_valid('" \, "'); } {0} do_execsql_test json-10.14 { SELECT json_valid('" \- "'); } {0} do_execsql_test json-10.15 { SELECT json_valid('" \. "'); } {0} do_execsql_test json-10.16 { SELECT json_valid('" \/ "'); } {1} do_execsql_test json-10.17 { SELECT json_valid('" \0 "'); } {0} do_execsql_test json-10.18 { SELECT json_valid('" \1 "'); } {0} do_execsql_test json-10.19 { SELECT json_valid('" \2 "'); } {0} do_execsql_test json-10.20 { SELECT json_valid('" \3 "'); } {0} do_execsql_test json-10.21 { SELECT json_valid('" \4 "'); } {0} do_execsql_test json-10.22 { SELECT json_valid('" \5 "'); } {0} do_execsql_test json-10.23 { SELECT json_valid('" \6 "'); } {0} do_execsql_test json-10.24 { SELECT json_valid('" \7 "'); } {0} do_execsql_test json-10.25 { SELECT json_valid('" \8 "'); } {0} do_execsql_test json-10.26 { SELECT json_valid('" \9 "'); } {0} do_execsql_test json-10.27 { SELECT json_valid('" \: "'); } {0} do_execsql_test json-10.28 { SELECT json_valid('" \; "'); } {0} do_execsql_test json-10.29 { SELECT json_valid('" \< "'); } {0} do_execsql_test json-10.30 { SELECT json_valid('" \= "'); } {0} do_execsql_test json-10.31 { SELECT json_valid('" \> "'); } {0} do_execsql_test json-10.32 { SELECT json_valid('" \? "'); } {0} do_execsql_test json-10.33 { SELECT json_valid('" \@ "'); } {0} do_execsql_test json-10.34 { SELECT json_valid('" \A "'); } {0} do_execsql_test json-10.35 { SELECT json_valid('" \B "'); } {0} do_execsql_test json-10.36 { SELECT json_valid('" \C "'); } {0} do_execsql_test json-10.37 { SELECT json_valid('" \D "'); } {0} do_execsql_test json-10.38 { SELECT json_valid('" \E "'); } {0} do_execsql_test json-10.39 { SELECT json_valid('" \F "'); } {0} do_execsql_test json-10.40 { SELECT json_valid('" \G "'); } {0} do_execsql_test json-10.41 { SELECT json_valid('" \H "'); } {0} do_execsql_test json-10.42 { SELECT json_valid('" \I "'); } {0} do_execsql_test json-10.43 { SELECT json_valid('" \J "'); } {0} do_execsql_test json-10.44 { SELECT json_valid('" \K "'); } {0} do_execsql_test json-10.45 { SELECT json_valid('" \L "'); } {0} do_execsql_test json-10.46 { SELECT json_valid('" \M "'); } {0} do_execsql_test json-10.47 { SELECT json_valid('" \N "'); } {0} do_execsql_test json-10.48 { SELECT json_valid('" \O "'); } {0} do_execsql_test json-10.49 { SELECT json_valid('" \P "'); } {0} do_execsql_test json-10.50 { SELECT json_valid('" \Q "'); } {0} do_execsql_test json-10.51 { SELECT json_valid('" \R "'); } {0} do_execsql_test json-10.52 { SELECT json_valid('" \S "'); } {0} do_execsql_test json-10.53 { SELECT json_valid('" \T "'); } {0} do_execsql_test json-10.54 { SELECT json_valid('" \U "'); } {0} do_execsql_test json-10.55 { SELECT json_valid('" \V "'); } {0} do_execsql_test json-10.56 { SELECT json_valid('" \W "'); } {0} do_execsql_test json-10.57 { SELECT json_valid('" \X "'); } {0} do_execsql_test json-10.58 { SELECT json_valid('" \Y "'); } {0} do_execsql_test json-10.59 { SELECT json_valid('" \Z "'); } {0} do_execsql_test json-10.60 { SELECT json_valid('" \[ "'); } {0} do_execsql_test json-10.61 { SELECT json_valid('" \\ "'); } {1} do_execsql_test json-10.62 { SELECT json_valid('" \] "'); } {0} do_execsql_test json-10.63 { SELECT json_valid('" \^ "'); } {0} do_execsql_test json-10.64 { SELECT json_valid('" \_ "'); } {0} do_execsql_test json-10.65 { SELECT json_valid('" \` "'); } {0} do_execsql_test json-10.66 { SELECT json_valid('" \a "'); } {0} do_execsql_test json-10.67 { SELECT json_valid('" \b "'); } {1} do_execsql_test json-10.68 { SELECT json_valid('" \c "'); } {0} do_execsql_test json-10.69 { SELECT json_valid('" \d "'); } {0} do_execsql_test json-10.70 { SELECT json_valid('" \e "'); } {0} do_execsql_test json-10.71 { SELECT json_valid('" \f "'); } {1} do_execsql_test json-10.72 { SELECT json_valid('" \g "'); } {0} do_execsql_test json-10.73 { SELECT json_valid('" \h "'); } {0} do_execsql_test json-10.74 { SELECT json_valid('" \i "'); } {0} do_execsql_test json-10.75 { SELECT json_valid('" \j "'); } {0} do_execsql_test json-10.76 { SELECT json_valid('" \k "'); } {0} do_execsql_test json-10.77 { SELECT json_valid('" \l "'); } {0} do_execsql_test json-10.78 { SELECT json_valid('" \m "'); } {0} do_execsql_test json-10.79 { SELECT json_valid('" \n "'); } {1} do_execsql_test json-10.80 { SELECT json_valid('" \o "'); } {0} do_execsql_test json-10.81 { SELECT json_valid('" \p "'); } {0} do_execsql_test json-10.82 { SELECT json_valid('" \q "'); } {0} do_execsql_test json-10.83 { SELECT json_valid('" \r "'); } {1} do_execsql_test json-10.84 { SELECT json_valid('" \s "'); } {0} do_execsql_test json-10.85 { SELECT json_valid('" \t "'); } {1} do_execsql_test json-10.86.0 { SELECT json_valid('" \u "'); } {0} do_execsql_test json-10.86.1 { SELECT json_valid('" \ua "'); } {0} do_execsql_test json-10.86.2 { SELECT json_valid('" \uab "'); } {0} do_execsql_test json-10.86.3 { SELECT json_valid('" \uabc "'); } {0} do_execsql_test json-10.86.4 { SELECT json_valid('" \uabcd "'); } {1} do_execsql_test json-10.86.5 { SELECT json_valid('" \uFEDC "'); } {1} do_execsql_test json-10.86.6 { SELECT json_valid('" \u1234 "'); } {1} do_execsql_test json-10.87 { SELECT json_valid('" \v "'); } {0} do_execsql_test json-10.88 { SELECT json_valid('" \w "'); } {0} do_execsql_test json-10.89 { SELECT json_valid('" \x "'); } {0} do_execsql_test json-10.90 { SELECT json_valid('" \y "'); } {0} do_execsql_test json-10.91 { SELECT json_valid('" \z "'); } {0} do_execsql_test json-10.92 { SELECT json_valid('" \{ "'); } {0} do_execsql_test json-10.93 { SELECT json_valid('" \| "'); } {0} do_execsql_test json-10.94 { SELECT json_valid('" \} "'); } {0} do_execsql_test json-10.95 { SELECT json_valid('" \~ "'); } {0} finish_test |
Changes to test/nockpt.test.
︙ | ︙ | |||
46 47 48 49 50 51 52 53 54 55 | do_test 1.10 { file exists test.db-wal } 1 do_test 1.11 { file size test.db-wal } [wal_file_size 2 1024] sqlite3 db test.db do_execsql_test 1.12 { SELECT * FROM c1 } {1 2 3 4 5 6 7 8 9} finish_test | > > > > > > | 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | do_test 1.10 { file exists test.db-wal } 1 do_test 1.11 { file size test.db-wal } [wal_file_size 2 1024] sqlite3 db test.db do_execsql_test 1.12 { SELECT * FROM c1 } {1 2 3 4 5 6 7 8 9} do_execsql_test 1.13 { PRAGMA main.journal_mode } {wal} do_test 1.14 { sqlite3_db_config db NO_CKPT_ON_CLOSE 1 } {1} do_execsql_test 1.14 { PRAGMA main.journal_mode = delete } {delete} do_test 1.15 { file exists test.db-wal } {0} finish_test |
Added test/ossfuzz.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | /* ** This module interfaces SQLite to the Google OSS-Fuzz, fuzzer as a service. ** (https://github.com/google/oss-fuzz) */ #include <stddef.h> #include <stdint.h> #include "sqlite3.h" /* ** Progress handler callback */ static int progress_handler(void *pReturn) { return *(int*)pReturn; } /* ** Callback for sqlite3_exec(). */ static int exec_handler(void *pCnt, int argc, char **argv, char **namev){ int i; if( argv ){ for(i=0; i<argc; i++) sqlite3_free(sqlite3_mprintf("%s", argv[i])); } return ((*(int*)pCnt)--)<=0; } /* ** Main entry point. The fuzzer invokes this function with each ** fuzzed input. */ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { int progressArg = 0; /* 1 causes progress handler abort */ int execCnt = 0; /* Abort row callback when count reaches zero */ char *zErrMsg = 0; /* Error message returned by sqlite_exec() */ sqlite3 *db; /* The database connection */ uint8_t uSelector; /* First byte of input data[] */ int rc; /* Return code from various interfaces */ char *zSql; /* Zero-terminated copy of data[] */ if( size<3 ) return 0; /* Early out if unsufficient data */ /* Extract the selector byte from the beginning of the input. But only ** do this if the second byte is a \n. If the second byte is not \n, ** then use a default selector */ if( data[1]=='\n' ){ uSelector = data[0]; data += 2; size -= 2; }else{ uSelector = 0xfd; } /* Open the database connection. Only use an in-memory database. */ rc = sqlite3_open_v2("fuzz.db", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY, 0); if( rc ) return 0; /* Bit 0 of the selector enables progress callbacks. Bit 1 is the ** return code from progress callbacks */ if( uSelector & 1 ){ sqlite3_progress_handler(db, 4, progress_handler, (void*)&progressArg); } uSelector >>= 1; progressArg = uSelector & 1; uSelector >>= 1; /* Bit 2 of the selector enables foreign key constraints */ sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, uSelector&1, &rc); uSelector >>= 1; /* Remaining bits of the selector determine a limit on the number of ** output rows */ execCnt = uSelector + 1; /* Run the SQL. The sqlite_exec() interface expects a zero-terminated ** string, so make a copy. */ zSql = sqlite3_mprintf("%.*s", (int)size, data); sqlite3_exec(db, zSql, exec_handler, (void*)&execCnt, &zErrMsg); /* Cleanup and return */ sqlite3_free(zErrMsg); sqlite3_free(zSql); sqlite3_close(db); return 0; } |
Added test/ossshell.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | /* ** This is a test interface for the ossfuzz.c module. The ossfuzz.c module ** is an adaptor for OSS-FUZZ. (https://github.com/google/oss-fuzz) ** ** This program links against ossfuzz.c. It reads files named on the ** command line and passes them one by one into ossfuzz.c. */ #include <stddef.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include "sqlite3.h" /* ** The entry point in ossfuzz.c that this routine will be calling */ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); /* ** Read files named on the command-line and invoke the fuzzer for ** each one. */ int main(int argc, char **argv){ FILE *in; int i; int nErr = 0; uint8_t *zBuf = 0; size_t sz; for(i=1; i<argc; i++){ const char *zFilename = argv[i]; in = fopen(zFilename, "rb"); if( in==0 ){ fprintf(stderr, "cannot open \"%s\"\n", zFilename); nErr++; continue; } fseek(in, 0, SEEK_END); sz = ftell(in); rewind(in); zBuf = realloc(zBuf, sz); if( zBuf==0 ){ fprintf(stderr, "cannot malloc() for %d bytes\n", (int)sz); exit(1); } if( fread(zBuf, sz, 1, in)!=1 ){ fprintf(stderr, "cannot read %d bytes from \"%s\"\n", (int)sz, zFilename); nErr++; }else{ printf("%s... ", zFilename); fflush(stdout); (void)LLVMFuzzerTestOneInput(zBuf, sz); printf("ok\n"); } fclose(in); } free(zBuf); return nErr; } |
Changes to test/rowvalue.test.
︙ | ︙ | |||
262 263 264 265 266 267 268 269 | DROP TABLE IF EXISTS t1; CREATE TABLE t1(a,b); INSERT INTO t1 VALUES(1,2); DROP TABLE IF EXISTS t2; CREATE TABLE t2(x,y); INSERT INTO t2 VALUES(3,4); SELECT *,'x' FROM t1 LEFT JOIN t2 ON (a,b)=(x,y); } {1 2 {} {} x} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | DROP TABLE IF EXISTS t1; CREATE TABLE t1(a,b); INSERT INTO t1 VALUES(1,2); DROP TABLE IF EXISTS t2; CREATE TABLE t2(x,y); INSERT INTO t2 VALUES(3,4); SELECT *,'x' FROM t1 LEFT JOIN t2 ON (a,b)=(x,y); } {1 2 {} {} x} foreach {tn sql} { 0 "SELECT (1,2) AS x WHERE x=3" 1 "SELECT (1,2) BETWEEN 1 AND 2" 2 "SELECT 1 BETWEEN (1,2) AND 2" 3 "SELECT 2 BETWEEN 1 AND (1,2)" 4 "SELECT (1,2) FROM (SELECT 1) ORDER BY 1" 5 "SELECT (1,2) FROM (SELECT 1) GROUP BY 1" } { do_catchsql_test 13.$tn $sql {1 {row value misused}} } do_execsql_test 14.0 { CREATE TABLE t12(x); INSERT INTO t12 VALUES(2), (4); } do_execsql_test 14.1 "SELECT 1 WHERE (2,2) BETWEEN (1,1) AND (3,3)" 1 do_execsql_test 14.2 "SELECT CASE (2,2) WHEN (1, 1) THEN 2 ELSE 1 END" 1 do_execsql_test 14.3 "SELECT CASE (SELECT 2,2) WHEN (1, 1) THEN 2 ELSE 1 END" 1 do_execsql_test 14.4 "SELECT 1 WHERE (SELECT 2,2) BETWEEN (1,1) AND (3,3)" 1 do_execsql_test 14.5 "SELECT 1 FROM t12 WHERE (x,1) BETWEEN (1,1) AND (3,3)" 1 do_execsql_test 14.6 { SELECT 1 FROM t12 WHERE (1,x) BETWEEN (1,1) AND (3,3) } {1 1} finish_test |
Changes to test/rowvalue3.test.
︙ | ︙ | |||
197 198 199 200 201 202 203 204 205 206 | do_execsql_test 4.$tn.$tn2 " SELECT c FROM hh WHERE (a, b) in (SELECT x, y FROM k1) ORDER BY $orderby " $res } } #------------------------------------------------------------------------- finish_test | > > > > > > > > > > > > > > | 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | do_execsql_test 4.$tn.$tn2 " SELECT c FROM hh WHERE (a, b) in (SELECT x, y FROM k1) ORDER BY $orderby " $res } } #------------------------------------------------------------------------- # 2016-11-17. Query flattening in a vector SELECT on the RHS of an IN # operator. Ticket https://www.sqlite.org/src/info/da7841375186386c # do_execsql_test 5.0 { DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t2; CREATE TABLE T1(a TEXT); INSERT INTO T1(a) VALUES ('aaa'); CREATE TABLE T2(a TEXT PRIMARY KEY,n INT); INSERT INTO T2(a, n) VALUES('aaa',0); SELECT * FROM T2 WHERE (a,n) IN (SELECT T1.a, V.n FROM T1, (SELECT * FROM (SELECT 0 n)) V); } {aaa 0} finish_test |
Changes to test/shell1.test.
︙ | ︙ | |||
195 196 197 198 199 200 201 | catchcmd "test.db" ".explain \"OFF" } {0 {}} do_test shell1-2.2.4 { catchcmd "test.db" ".explain \'OFF" } {0 {}} do_test shell1-2.2.5 { catchcmd "test.db" ".mode \"insert FOO" | | | | 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | catchcmd "test.db" ".explain \"OFF" } {0 {}} do_test shell1-2.2.4 { catchcmd "test.db" ".explain \'OFF" } {0 {}} do_test shell1-2.2.5 { catchcmd "test.db" ".mode \"insert FOO" } {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}} do_test shell1-2.2.6 { catchcmd "test.db" ".mode \'insert FOO" } {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}} # check multiple tokens, and quoted tokens do_test shell1-2.3.1 { catchcmd "test.db" ".explain 1" } {0 {}} do_test shell1-2.3.2 { catchcmd "test.db" ".explain on" |
︙ | ︙ | |||
226 227 228 229 230 231 232 | do_test shell1-2.3.7 { catchcmd "test.db" ".\'explain\' \'OFF\'" } {0 {}} # check quoted args are unquoted do_test shell1-2.4.1 { catchcmd "test.db" ".mode FOO" | | | 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 | do_test shell1-2.3.7 { catchcmd "test.db" ".\'explain\' \'OFF\'" } {0 {}} # check quoted args are unquoted do_test shell1-2.4.1 { catchcmd "test.db" ".mode FOO" } {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}} do_test shell1-2.4.2 { catchcmd "test.db" ".mode csv" } {0 {}} do_test shell1-2.4.2 { catchcmd "test.db" ".mode \"csv\"" } {0 {}} |
︙ | ︙ | |||
423 424 425 426 427 428 429 | # insert SQL insert statements for TABLE # line One value per line # list Values delimited by .separator strings # tabs Tab-separated values # tcl TCL list elements do_test shell1-3.13.1 { catchcmd "test.db" ".mode" | | | | 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 | # insert SQL insert statements for TABLE # line One value per line # list Values delimited by .separator strings # tabs Tab-separated values # tcl TCL list elements do_test shell1-3.13.1 { catchcmd "test.db" ".mode" } {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}} do_test shell1-3.13.2 { catchcmd "test.db" ".mode FOO" } {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}} do_test shell1-3.13.3 { catchcmd "test.db" ".mode csv" } {0 {}} do_test shell1-3.13.4 { catchcmd "test.db" ".mode column" } {0 {}} do_test shell1-3.13.5 { |
︙ | ︙ | |||
459 460 461 462 463 464 465 | # extra arguments ignored catchcmd "test.db" ".mode tcl BAD" } {0 {}} # don't allow partial mode type matches do_test shell1-3.13.12 { catchcmd "test.db" ".mode l" | | | | 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 | # extra arguments ignored catchcmd "test.db" ".mode tcl BAD" } {0 {}} # don't allow partial mode type matches do_test shell1-3.13.12 { catchcmd "test.db" ".mode l" } {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}} do_test shell1-3.13.13 { catchcmd "test.db" ".mode li" } {1 {Error: mode should be one of: ascii column csv html insert line list quote tabs tcl}} do_test shell1-3.13.14 { catchcmd "test.db" ".mode lin" } {0 {}} # .nullvalue STRING Print STRING in place of NULL values do_test shell1-3.14.1 { catchcmd "test.db" ".nullvalue" |
︙ | ︙ |
Changes to test/shell3.test.
︙ | ︙ | |||
92 93 94 95 96 97 98 | catchcmd "foo.db" "CREATE TABLE t1(a); DROP TABLE t1;" } {0 {}} do_test shell3-2.6 { catchcmd "foo.db" ".tables" } {0 {}} do_test shell3-2.7 { catchcmd "foo.db" "CREATE TABLE" | | | 92 93 94 95 96 97 98 99 100 101 | catchcmd "foo.db" "CREATE TABLE t1(a); DROP TABLE t1;" } {0 {}} do_test shell3-2.6 { catchcmd "foo.db" ".tables" } {0 {}} do_test shell3-2.7 { catchcmd "foo.db" "CREATE TABLE" } {1 {Error: near line 1: near "TABLE": syntax error}} finish_test |
Changes to test/snapshot.test.
︙ | ︙ | |||
22 23 24 25 26 27 28 | # "PRAGMA journal_mode=memory", which fails if the database is in wal mode # and there are one or more existing connections. if {[permutation]=="inmemory_journal"} { finish_test return } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | > | | | | | | | | | | | | | | | | | | | | | > > > > > > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 | # "PRAGMA journal_mode=memory", which fails if the database is in wal mode # and there are one or more existing connections. if {[permutation]=="inmemory_journal"} { finish_test return } foreach {tn tcl} { 1 { proc snapshot_get {DB DBNAME} { uplevel [list sqlite3_snapshot_get $DB $DBNAME] } proc snapshot_open {DB DBNAME SNAPSHOT} { uplevel [list sqlite3_snapshot_open $DB $DBNAME $SNAPSHOT] } proc snapshot_free {SNAPSHOT} { uplevel [list sqlite3_snapshot_free $SNAPSHOT] } proc snapshot_cmp {SNAPSHOT1 SNAPSHOT2} { uplevel [list sqlite3_snapshot_cmp $SNAPSHOT1 $SNAPSHOT2] } } 2 { proc snapshot_get {DB DBNAME} { uplevel [list sqlite3_snapshot_get_blob $DB $DBNAME] } proc snapshot_open {DB DBNAME SNAPSHOT} { uplevel [list sqlite3_snapshot_open_blob $DB $DBNAME $SNAPSHOT] } proc snapshot_free {SNAPSHOT} { } proc snapshot_cmp {SNAPSHOT1 SNAPSHOT2} { uplevel [list sqlite3_snapshot_cmp_blob $SNAPSHOT1 $SNAPSHOT2] } } } { reset_db eval $tcl #------------------------------------------------------------------------- # Check some error conditions in snapshot_get(). It is an error if: # # 1) snapshot_get() is called on a non-WAL database, or # 2) there is an open write transaction on the database. # 3) the database handle is in auto-commit mode # do_execsql_test $tn.1.0 { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); } do_test $tn.1.1.1 { execsql { BEGIN; SELECT * FROM t1; } list [catch { snapshot_get db main } msg] $msg } {1 SQLITE_ERROR} do_execsql_test $tn.1.1.2 COMMIT do_test $tn.1.2.1 { execsql { PRAGMA journal_mode = WAL; BEGIN; INSERT INTO t1 VALUES(5, 6); INSERT INTO t1 VALUES(7, 8); } list [catch { snapshot_get db main } msg] $msg } {1 SQLITE_ERROR} do_execsql_test $tn.1.2.2 COMMIT do_test $tn.1.3.1 { list [catch { snapshot_get db main } msg] $msg } {1 SQLITE_ERROR} do_test $tn.1.3.2 { db trans { set snap [snapshot_get db main] } snapshot_free $snap } {} #------------------------------------------------------------------------- # Check that a simple case works. Reuse the database created by the # block of tests above. # do_execsql_test $tn.2.1.0 { BEGIN; SELECT * FROM t1; } {1 2 3 4 5 6 7 8} do_test $tn.2.1.1 { set snapshot [snapshot_get db main] execsql { COMMIT; INSERT INTO t1 VALUES(9, 10); SELECT * FROM t1; } } {1 2 3 4 5 6 7 8 9 10} do_test $tn.2.1.2 { execsql BEGIN snapshot_open db main $snapshot execsql { SELECT * FROM t1; } } {1 2 3 4 5 6 7 8} do_test $tn.2.1.3 { snapshot_free $snapshot execsql COMMIT } {} do_test $tn.2.2.0 { sqlite3 db2 test.db execsql { BEGIN; SELECT * FROM t1; } db2 } {1 2 3 4 5 6 7 8 9 10} do_test $tn.2.2.1 { set snapshot [snapshot_get db2 main] execsql { INSERT INTO t1 VALUES(11, 12); SELECT * FROM t1; } } {1 2 3 4 5 6 7 8 9 10 11 12} do_test $tn.2.2.2 { execsql BEGIN snapshot_open db main $snapshot execsql { SELECT * FROM t1; } } {1 2 3 4 5 6 7 8 9 10} do_test $tn.2.2.3 { snapshot_free $snapshot execsql COMMIT execsql COMMIT db2 db2 close } {} do_test $tn.2.3.1 { execsql { DELETE FROM t1 WHERE a>6 } db trans { set snapshot [snapshot_get db main] } execsql { INSERT INTO t1 VALUES('a', 'b'); INSERT INTO t1 VALUES('c', 'd'); SELECT * FROM t1; } } {1 2 3 4 5 6 a b c d} do_test $tn.2.3.2 { execsql BEGIN snapshot_open db main $snapshot execsql { SELECT * FROM t1 } } {1 2 3 4 5 6} do_test $tn.2.3.3 { catchsql { INSERT INTO t1 VALUES('x','y') } } {1 {database is locked}} do_test $tn.2.3.4 { execsql COMMIT snapshot_free $snapshot } {} #------------------------------------------------------------------------- # Check some errors in snapshot_open(). It is an error if: # # 1) the db is in auto-commit mode, # 2) the db has an open (read or write) transaction, # 3) the db is not a wal database, # # Reuse the database created by earlier tests. # do_execsql_test $tn.3.0.0 { CREATE TABLE t2(x, y); INSERT INTO t2 VALUES('a', 'b'); INSERT INTO t2 VALUES('c', 'd'); BEGIN; SELECT * FROM t2; } {a b c d} do_test $tn.3.0.1 { set snapshot [snapshot_get db main] execsql { COMMIT } execsql { INSERT INTO t2 VALUES('e', 'f'); } } {} do_test $tn.3.1 { list [catch {snapshot_open db main $snapshot } msg] $msg } {1 SQLITE_ERROR} do_test $tn.3.2.1 { execsql { BEGIN; SELECT * FROM t2; } } {a b c d e f} do_test $tn.3.2.2 { list [catch {snapshot_open db main $snapshot } msg] $msg } {1 SQLITE_ERROR} do_test $tn.3.2.3 { execsql { COMMIT; BEGIN; INSERT INTO t2 VALUES('g', 'h'); } list [catch {snapshot_open db main $snapshot } msg] $msg } {1 SQLITE_ERROR} do_execsql_test $tn.3.2.4 COMMIT do_test $tn.3.3.1 { execsql { PRAGMA journal_mode = DELETE } execsql { BEGIN } list [catch {snapshot_open db main $snapshot } msg] $msg } {1 SQLITE_ERROR} do_test $tn.$tn.3.3.2 { snapshot_free $snapshot execsql COMMIT } {} #------------------------------------------------------------------------- # Check that SQLITE_BUSY_SNAPSHOT is returned if the specified snapshot # no longer exists because the wal file has been checkpointed. # # 1. Reading a snapshot from the middle of a wal file is not possible # after the wal file has been checkpointed. # # 2. That a snapshot from the end of a wal file can not be read once # the wal file has been wrapped. # do_execsql_test $tn.4.1.0 { PRAGMA journal_mode = wal; CREATE TABLE t3(i, j); INSERT INTO t3 VALUES('o', 't'); INSERT INTO t3 VALUES('t', 'f'); BEGIN; SELECT * FROM t3; } {wal o t t f} do_test $tn.4.1.1 { set snapshot [snapshot_get db main] execsql COMMIT } {} do_test $tn.4.1.2 { execsql { INSERT INTO t3 VALUES('f', 's'); BEGIN; } snapshot_open db main $snapshot execsql { SELECT * FROM t3 } } {o t t f} do_test $tn.4.1.3 { execsql { COMMIT; PRAGMA wal_checkpoint; BEGIN; } list [catch {snapshot_open db main $snapshot} msg] $msg } {1 SQLITE_BUSY_SNAPSHOT} do_test $tn.4.1.4 { snapshot_free $snapshot execsql COMMIT } {} do_test $tn.4.2.1 { execsql { INSERT INTO t3 VALUES('s', 'e'); INSERT INTO t3 VALUES('n', 't'); BEGIN; SELECT * FROM t3; } } {o t t f f s s e n t} do_test $tn.4.2.2 { set snapshot [snapshot_get db main] execsql { COMMIT; PRAGMA wal_checkpoint; BEGIN; } snapshot_open db main $snapshot execsql { SELECT * FROM t3 } } {o t t f f s s e n t} do_test $tn.4.2.3 { execsql { COMMIT; INSERT INTO t3 VALUES('e', 't'); BEGIN; } list [catch {snapshot_open db main $snapshot} msg] $msg } {1 SQLITE_BUSY_SNAPSHOT} do_test $tn.4.2.4 { snapshot_free $snapshot } {} #------------------------------------------------------------------------- # Check that SQLITE_BUSY is returned if a checkpoint is running when # sqlite3_snapshot_open() is called. # reset_db db close testvfs tvfs sqlite3 db test.db -vfs tvfs do_execsql_test $tn.5.1 { PRAGMA journal_mode = wal; CREATE TABLE x1(x, xx, xxx); INSERT INTO x1 VALUES('z', 'zz', 'zzz'); BEGIN; SELECT * FROM x1; } {wal z zz zzz} do_test $tn.5.2 { set ::snapshot [snapshot_get db main] sqlite3 db2 test.db -vfs tvfs execsql { INSERT INTO x1 VALUES('a', 'aa', 'aaa'); COMMIT; } } {} set t53 0 proc write_callback {args} { do_test $tn.5.3.[incr ::t53] { execsql BEGIN list [catch { snapshot_open db main $::snapshot } msg] $msg } {1 SQLITE_BUSY} catchsql COMMIT } tvfs filter xWrite tvfs script write_callback db2 eval { PRAGMA wal_checkpoint } db close db2 close tvfs delete snapshot_free $snapshot #------------------------------------------------------------------------- # Test that sqlite3_snapshot_get() may be called immediately after # "BEGIN; PRAGMA user_version;". And that sqlite3_snapshot_open() may # be called after opening the db handle and running the script # "PRAGMA user_version; BEGIN". reset_db do_execsql_test $tn.6.1 { PRAGMA journal_mode = wal; CREATE TABLE x1(x, xx, xxx); INSERT INTO x1 VALUES('z', 'zz', 'zzz'); BEGIN; PRAGMA user_version; } {wal 0} do_test $tn.6.2 { set ::snapshot [snapshot_get db main] execsql { INSERT INTO x1 VALUES('a', 'aa', 'aaa'); COMMIT; } } {} do_test $tn.6.3 { sqlite3 db2 test.db db2 eval "PRAGMA user_version ; BEGIN" snapshot_open db2 main $::snapshot db2 eval { SELECT * FROM x1 } } {z zz zzz} do_test $tn.6.4 { db2 close sqlite3 db2 test.db db2 eval "PRAGMA application_id" db2 eval "BEGIN" snapshot_open db2 main $::snapshot db2 eval { SELECT * FROM x1 } } {z zz zzz} do_test $tn.6.5 { db2 close sqlite3 db2 test.db db2 eval "BEGIN" list [catch {snapshot_open db2 main $::snapshot} msg] $msg } {1 SQLITE_ERROR} snapshot_free $snapshot #------------------------------------------------------------------------- # The following tests investigate the sqlite3_snapshot_cmp() API. # # Compare snapshots $p1 and $p2, checking that the result is $r. # proc do_snapshot_cmp_test {tn p1 p2 r} { uplevel [list do_test $tn.1 [list snapshot_cmp $p1 $p2] $r] uplevel [list do_test $tn.2 [list snapshot_cmp $p2 $p1] [expr $r*-1]] uplevel [list do_test $tn.3 [list snapshot_cmp $p1 $p1] 0] uplevel [list do_test $tn.4 [list snapshot_cmp $p2 $p2] 0] } catch { db2 close } reset_db do_execsql_test $tn.7.1 { PRAGMA journal_mode = wal; CREATE TABLE t1(x); } wal do_test $tn.7.1.2 { execsql { BEGIN ; PRAGMA application_id } set p1 [snapshot_get db main] execsql { INSERT INTO t1 VALUES(10); COMMIT; } execsql { BEGIN ; PRAGMA application_id } set p2 [snapshot_get db main] execsql COMMIT } {} do_snapshot_cmp_test $tn.7.1.3 $p1 $p2 -1 snapshot_free $p1 snapshot_free $p2 do_execsql_test $tn.7.2.1 { INSERT INTO t1 VALUES(11); INSERT INTO t1 VALUES(12); INSERT INTO t1 VALUES(13); BEGIN; PRAGMA application_id; } {0} do_test $tn.7.2.2 { set p1 [snapshot_get db main] execsql { COMMIT; INSERT INTO t1 VALUES(14); PRAGMA wal_checkpoint; BEGIN; PRAGMA application_id; } set p2 [snapshot_get db main] execsql COMMIT } {} do_snapshot_cmp_test $tn.7.2.3 $p1 $p2 -1 snapshot_free $p2 do_test $tn.7.3.1 { execsql { INSERT INTO t1 VALUES(14); BEGIN; PRAGMA application_id; } set p2 [snapshot_get db main] execsql COMMIT } {} do_snapshot_cmp_test $tn.7.3.2 $p1 $p2 -1 snapshot_free $p1 snapshot_free $p2 } finish_test |
Added test/snapshot2.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | # 2016 November 18 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The focus # of this file is the sqlite3_snapshot_xxx() APIs. # set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !snapshot {finish_test; return} set testprefix snapshot2 # This test does not work with the inmemory_journal permutation. The reason # is that each connection opened as part of this permutation executes # "PRAGMA journal_mode=memory", which fails if the database is in wal mode # and there are one or more existing connections. if {[permutation]=="inmemory_journal"} { finish_test return } #------------------------------------------------------------------------- # Check that it is not possible to obtain a snapshot immediately after # a wal mode database with an empty wal file is opened. But it is after # the file has been written, even by some other connection. # do_execsql_test 1.0 { PRAGMA journal_mode = wal; CREATE TABLE t1(a, b, c); INSERT INTO t1 VALUES(1, 2, 3); INSERT INTO t1 VALUES(4, 5, 6); } {wal} db close do_test 1.1.1 { list [file exists test.db] [file exists test.db-wal] } {1 0} sqlite3 db test.db do_execsql_test 1.1.2 { SELECT * FROM t1 } {1 2 3 4 5 6} do_test 1.1.3 { execsql BEGIN list [catch { sqlite3_snapshot_get_blob db main } msg] $msg } {1 SQLITE_ERROR} execsql COMMIT do_test 1.1.4 { execsql { INSERT INTO t1 VALUES(7, 8, 9) } execsql BEGIN string length [sqlite3_snapshot_get_blob db main] } 48 execsql COMMIT db close do_test 1.2.1 { list [file exists test.db] [file exists test.db-wal] } {1 0} sqlite3 db test.db do_execsql_test 1.2.2 { SELECT * FROM t1 } {1 2 3 4 5 6 7 8 9} do_test 1.2.3 { execsql BEGIN list [catch { sqlite3_snapshot_get_blob db main } msg] $msg } {1 SQLITE_ERROR} execsql COMMIT do_test 1.2.4 { sqlite3 db2 test.db execsql { INSERT INTO t1 VALUES(10, 11, 12) } db2 execsql BEGIN string length [sqlite3_snapshot_get_blob db main] } 48 execsql COMMIT db2 close #------------------------------------------------------------------------- # Simple tests for sqlite3_snapshot_recover(). # reset_db do_execsql_test 2.0 { CREATE TABLE t1(x); PRAGMA journal_mode = wal; INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(2); } {wal} do_test 2.1 { db trans { set snap [sqlite3_snapshot_get_blob db main] } sqlite3_db_config db NO_CKPT_ON_CLOSE 1 db close sqlite3 db test.db execsql {SELECT * FROM sqlite_master} execsql BEGIN sqlite3_snapshot_open_blob db main $snap execsql COMMIT; execsql { INSERT INTO t1 VALUES(3); } } {} do_test 2.2 { sqlite3_db_config db NO_CKPT_ON_CLOSE 1 db close sqlite3 db test.db execsql {SELECT * FROM sqlite_master} execsql BEGIN list [catch { sqlite3_snapshot_open_blob db main $snap } msg] $msg } {1 SQLITE_BUSY_SNAPSHOT} do_test 2.3 { execsql COMMIT sqlite3_snapshot_recover db main execsql BEGIN sqlite3_snapshot_open_blob db main $snap execsql { SELECT * FROM t1 } } {1 2} do_test 2.4 { execsql COMMIT execsql { SELECT * FROM t1 } } {1 2 3} do_test 2.5 { execsql { PRAGMA wal_checkpoint } sqlite3_db_config db NO_CKPT_ON_CLOSE 1 db close sqlite3 db test.db sqlite3_snapshot_recover db main execsql BEGIN list [catch { sqlite3_snapshot_open_blob db main $snap } msg] $msg } {1 SQLITE_BUSY_SNAPSHOT} #------------------------------------------------------------------------- # Check that calling sqlite3_snapshot_recover() does not confuse the # pager cache. reset_db do_execsql_test 3.0 { PRAGMA journal_mode = wal; CREATE TABLE t1(x, y); INSERT INTO t1 VALUES('a', 'b'); INSERT INTO t1 VALUES('c', 'd'); } {wal} do_test 3.1 { sqlite3 db2 test.db execsql { INSERT INTO t1 VALUES('e', 'f') } db2 db2 close sqlite3_snapshot_recover db main } {} do_execsql_test 3.2 { SELECT * FROM t1; } {a b c d e f} #------------------------------------------------------------------------- # Check that sqlite3_snapshot_recover() returns an error if it is called # with an open read-transaction. Or on a database that does not exist. Or # on the temp database. Or on a db that is not in wal mode. # do_test 4.1 { sqlite3_snapshot_recover db main } {} do_test 4.2 { execsql { BEGIN; SELECT * FROM sqlite_master; } list [catch { sqlite3_snapshot_recover db main } msg] $msg } {1 SQLITE_ERROR} do_test 4.3 { execsql COMMIT sqlite3_snapshot_recover db main } {} do_test 4.4 { list [catch { sqlite3_snapshot_recover db aux } msg] $msg } {1 SQLITE_ERROR} do_test 4.5 { forcedelete test.db2 execsql { ATTACH 'test.db2' AS aux; PRAGMA aux.journal_mode = wal; CREATE TABLE aux.t2(x, y); } list [catch { sqlite3_snapshot_recover db aux } msg] $msg } {0 {}} do_test 4.6 { list [catch { sqlite3_snapshot_recover db temp } msg] $msg } {1 SQLITE_ERROR} do_test 4.7 { execsql { PRAGMA aux.journal_mode = delete; } list [catch { sqlite3_snapshot_recover db aux } msg] $msg } {1 SQLITE_ERROR} finish_test |
Changes to test/snapshot_fault.test.
︙ | ︙ | |||
154 155 156 157 158 159 160 161 162 163 164 | PRAGMA integrity_check; }] if {$res != "1 2 3 ok"} { error "res is $res" } } sqlite3_snapshot_free $::snapshot } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | PRAGMA integrity_check; }] if {$res != "1 2 3 ok"} { error "res is $res" } } sqlite3_snapshot_free $::snapshot } #------------------------------------------------------------------------- # Test the handling of faults that occur within sqlite3_snapshot_recover(). # reset_db do_execsql_test 4.0 { PRAGMA journal_mode = wal; CREATE TABLE t1(zzz); INSERT INTO t1 VALUES('abc'); INSERT INTO t1 VALUES('def'); } {wal} faultsim_save_and_close do_test 4.0.1 { faultsim_restore_and_reopen db eval { SELECT * FROM sqlite_master } sqlite3_snapshot_recover db main } {} db close do_faultsim_test 4.0 -faults oom* -prep { faultsim_restore_and_reopen db eval { SELECT * FROM sqlite_master } } -body { sqlite3_snapshot_recover db main } -test { faultsim_test_result {0 {}} {1 SQLITE_NOMEM} {1 SQLITE_IOERR_NOMEM} } # The following test cases contrive to call sqlite3_snapshot_recover() # before all pages of the *-shm file have been mapped. This tests an # extra branch of error handling logic in snapshot_recover(). # reset_db do_execsql_test 4.1.0 { PRAGMA page_size = 512; PRAGMA journal_mode = wal; PRAGMA wal_autocheckpoint = 0; CREATE TABLE t1(zzz); INSERT INTO t1 VALUES(randomblob( 500 * 9500 )); PRAGMA user_version = 211; } {wal 0} do_test 4.1.1 { list [file size test.db-shm] [file size test.db] } {98304 512} faultsim_save_and_close do_faultsim_test 4.1 -faults shm* -prep { catch { db2 close } catch { db close } faultsim_restore_and_reopen sqlite3 db2 test.db db2 eval { SELECT * FROM sqlite_master } db eval BEGIN sqlite3_snapshot_get_blob db main db eval COMMIT } -body { sqlite3_snapshot_recover db main } -test { faultsim_test_result {0 {}} {1 SQLITE_IOERR} } finish_test |
Changes to test/speedtest1.c.
︙ | ︙ | |||
45 46 47 48 49 50 51 52 53 54 55 56 57 58 | #include "sqlite3.h" #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <ctype.h> #define ISSPACE(X) isspace((unsigned char)(X)) #define ISDIGIT(X) isdigit((unsigned char)(X)) #if SQLITE_VERSION_NUMBER<3005000 # define sqlite3_int64 sqlite_int64 #endif #ifdef SQLITE_ENABLE_RBU | > | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | #include "sqlite3.h" #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <ctype.h> #include <unistd.h> #define ISSPACE(X) isspace((unsigned char)(X)) #define ISDIGIT(X) isdigit((unsigned char)(X)) #if SQLITE_VERSION_NUMBER<3005000 # define sqlite3_int64 sqlite_int64 #endif #ifdef SQLITE_ENABLE_RBU |
︙ | ︙ | |||
451 452 453 454 455 456 457 458 459 460 461 462 463 464 | y1 = (y0 + x/y0)/2; if( y1==y0 ) break; y0 = y1; } return y0; } /* ** The main and default testset */ void testset_main(void){ int i; /* Loop counter */ int n; /* iteration count */ int sz; /* Size of the tables */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | y1 = (y0 + x/y0)/2; if( y1==y0 ) break; y0 = y1; } return y0; } #if SQLITE_VERSION_NUMBER<3005004 /* ** An implementation of group_concat(). Used only when testing older ** versions of SQLite that lack the built-in group_concat(). */ struct groupConcat { char *z; int nAlloc; int nUsed; }; static void groupAppend(struct groupConcat *p, const char *z, int n){ if( p->nUsed+n >= p->nAlloc ){ int n2 = (p->nAlloc+n+1)*2; char *z2 = sqlite3_realloc(p->z, n2); if( z2==0 ) return; p->z = z2; p->nAlloc = n2; } memcpy(p->z+p->nUsed, z, n); p->nUsed += n; } static void groupStep( sqlite3_context *context, int argc, sqlite3_value **argv ){ const char *zVal; struct groupConcat *p; const char *zSep; int nVal, nSep; assert( argc==1 || argc==2 ); if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; p= (struct groupConcat*)sqlite3_aggregate_context(context, sizeof(*p)); if( p ){ int firstTerm = p->nUsed==0; if( !firstTerm ){ if( argc==2 ){ zSep = (char*)sqlite3_value_text(argv[1]); nSep = sqlite3_value_bytes(argv[1]); }else{ zSep = ","; nSep = 1; } if( nSep ) groupAppend(p, zSep, nSep); } zVal = (char*)sqlite3_value_text(argv[0]); nVal = sqlite3_value_bytes(argv[0]); if( zVal ) groupAppend(p, zVal, nVal); } } static void groupFinal(sqlite3_context *context){ struct groupConcat *p; p = sqlite3_aggregate_context(context, 0); if( p && p->z ){ p->z[p->nUsed] = 0; sqlite3_result_text(context, p->z, p->nUsed, sqlite3_free); } } #endif /* ** The main and default testset */ void testset_main(void){ int i; /* Loop counter */ int n; /* iteration count */ int sz; /* Size of the tables */ |
︙ | ︙ | |||
520 521 522 523 524 525 526 527 528 529 530 531 | sqlite3_bind_int64(g.pStmt, 1, (sqlite3_int64)x1); sqlite3_bind_text(g.pStmt, 3, zNum, -1, SQLITE_STATIC); speedtest1_run(); } speedtest1_exec("COMMIT"); speedtest1_end_test(); n = 25; speedtest1_begin_test(130, "%d SELECTS, numeric BETWEEN, unindexed", n); speedtest1_exec("BEGIN"); speedtest1_prepare( | > > > > | | | | 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 | sqlite3_bind_int64(g.pStmt, 1, (sqlite3_int64)x1); sqlite3_bind_text(g.pStmt, 3, zNum, -1, SQLITE_STATIC); speedtest1_run(); } speedtest1_exec("COMMIT"); speedtest1_end_test(); #if SQLITE_VERSION_NUMBER<3005004 sqlite3_create_function(g.db, "group_concat", 1, SQLITE_UTF8, 0, 0, groupStep, groupFinal); #endif n = 25; speedtest1_begin_test(130, "%d SELECTS, numeric BETWEEN, unindexed", n); speedtest1_exec("BEGIN"); speedtest1_prepare( "SELECT count(*), avg(b), sum(length(c)), group_concat(c) FROM t1\n" " WHERE b BETWEEN ?1 AND ?2; -- %d times", n ); for(i=1; i<=n; i++){ if( (i-1)%g.nRepeat==0 ){ x1 = speedtest1_random()%maxb; x2 = speedtest1_random()%10 + sz/5000 + x1; } sqlite3_bind_int(g.pStmt, 1, x1); sqlite3_bind_int(g.pStmt, 2, x2); speedtest1_run(); } speedtest1_exec("COMMIT"); speedtest1_end_test(); n = 10; speedtest1_begin_test(140, "%d SELECTS, LIKE, unindexed", n); speedtest1_exec("BEGIN"); speedtest1_prepare( "SELECT count(*), avg(b), sum(length(c)), group_concat(c) FROM t1\n" " WHERE c LIKE ?1; -- %d times", n ); for(i=1; i<=n; i++){ if( (i-1)%g.nRepeat==0 ){ x1 = speedtest1_random()%maxb; zNum[0] = '%'; len = speedtest1_numbername(i, zNum+1, sizeof(zNum)-2); zNum[len] = '%'; zNum[len+1] = 0; } sqlite3_bind_text(g.pStmt, 1, zNum, len+1, SQLITE_STATIC); speedtest1_run(); } speedtest1_exec("COMMIT"); speedtest1_end_test(); n = 10; |
︙ | ︙ | |||
578 579 580 581 582 583 584 | if( (i-1)%g.nRepeat==0 ){ x1 = speedtest1_random()%maxb; zNum[0] = '%'; len = speedtest1_numbername(i, zNum+1, sizeof(zNum)-2); zNum[len] = '%'; zNum[len+1] = 0; } | | | | 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 | if( (i-1)%g.nRepeat==0 ){ x1 = speedtest1_random()%maxb; zNum[0] = '%'; len = speedtest1_numbername(i, zNum+1, sizeof(zNum)-2); zNum[len] = '%'; zNum[len+1] = 0; } sqlite3_bind_text(g.pStmt, 1, zNum, len+1, SQLITE_STATIC); speedtest1_run(); } speedtest1_exec("COMMIT"); speedtest1_end_test(); n = 10; /* g.szTest/5; */ speedtest1_begin_test(145, "%d SELECTS w/ORDER BY and LIMIT, unindexed", n); speedtest1_exec("BEGIN"); speedtest1_prepare( "SELECT a, b, c FROM t1 WHERE c LIKE ?1\n" " ORDER BY a LIMIT 10; -- %d times", n ); for(i=1; i<=n; i++){ if( (i-1)%g.nRepeat==0 ){ x1 = speedtest1_random()%maxb; zNum[0] = '%'; len = speedtest1_numbername(i, zNum+1, sizeof(zNum)-2); zNum[len] = '%'; zNum[len+1] = 0; } sqlite3_bind_text(g.pStmt, 1, zNum, len+1, SQLITE_STATIC); speedtest1_run(); } speedtest1_exec("COMMIT"); speedtest1_end_test(); speedtest1_begin_test(150, "CREATE INDEX five times"); |
︙ | ︙ | |||
621 622 623 624 625 626 627 | speedtest1_end_test(); n = sz/5; speedtest1_begin_test(160, "%d SELECTS, numeric BETWEEN, indexed", n); speedtest1_exec("BEGIN"); speedtest1_prepare( | | | | | 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 | speedtest1_end_test(); n = sz/5; speedtest1_begin_test(160, "%d SELECTS, numeric BETWEEN, indexed", n); speedtest1_exec("BEGIN"); speedtest1_prepare( "SELECT count(*), avg(b), sum(length(c)), group_concat(a) FROM t1\n" " WHERE b BETWEEN ?1 AND ?2; -- %d times", n ); for(i=1; i<=n; i++){ if( (i-1)%g.nRepeat==0 ){ x1 = speedtest1_random()%maxb; x2 = speedtest1_random()%10 + sz/5000 + x1; } sqlite3_bind_int(g.pStmt, 1, x1); sqlite3_bind_int(g.pStmt, 2, x2); speedtest1_run(); } speedtest1_exec("COMMIT"); speedtest1_end_test(); n = sz/5; speedtest1_begin_test(161, "%d SELECTS, numeric BETWEEN, PK", n); speedtest1_exec("BEGIN"); speedtest1_prepare( "SELECT count(*), avg(b), sum(length(c)), group_concat(a) FROM t2\n" " WHERE a BETWEEN ?1 AND ?2; -- %d times", n ); for(i=1; i<=n; i++){ if( (i-1)%g.nRepeat==0 ){ x1 = speedtest1_random()%maxb; x2 = speedtest1_random()%10 + sz/5000 + x1; } sqlite3_bind_int(g.pStmt, 1, x1); sqlite3_bind_int(g.pStmt, 2, x2); speedtest1_run(); } speedtest1_exec("COMMIT"); speedtest1_end_test(); n = sz/5; speedtest1_begin_test(170, "%d SELECTS, text BETWEEN, indexed", n); speedtest1_exec("BEGIN"); speedtest1_prepare( "SELECT count(*), avg(b), sum(length(c)), group_concat(a) FROM t1\n" " WHERE c BETWEEN ?1 AND (?1||'~'); -- %d times", n ); for(i=1; i<=n; i++){ if( (i-1)%g.nRepeat==0 ){ x1 = swizzle(i, maxb); len = speedtest1_numbername(x1, zNum, sizeof(zNum)-1); } |
︙ | ︙ | |||
826 827 828 829 830 831 832 833 834 835 836 837 838 839 | "SELECT sum(a), max(c),\n" " avg((SELECT a FROM t2 WHERE 5+t2.b=t1.b) AND rowid<?1), max(c)\n" " FROM t1 WHERE rowid<?1;" ); sqlite3_bind_int(g.pStmt, 1, est_square_root(g.szTest)*50); speedtest1_run(); speedtest1_end_test(); speedtest1_begin_test(980, "PRAGMA integrity_check"); speedtest1_exec("PRAGMA integrity_check"); speedtest1_end_test(); speedtest1_begin_test(990, "ANALYZE"); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 | "SELECT sum(a), max(c),\n" " avg((SELECT a FROM t2 WHERE 5+t2.b=t1.b) AND rowid<?1), max(c)\n" " FROM t1 WHERE rowid<?1;" ); sqlite3_bind_int(g.pStmt, 1, est_square_root(g.szTest)*50); speedtest1_run(); speedtest1_end_test(); sz = n = g.szTest*700; zNum[0] = 0; maxb = roundup_allones(sz/3); speedtest1_begin_test(400, "%d REPLACE ops on an IPK", n); speedtest1_exec("BEGIN"); speedtest1_exec("CREATE%s TABLE t5(a INTEGER PRIMARY KEY, b %s);", isTemp(9), g.zNN); speedtest1_prepare("REPLACE INTO t5 VALUES(?1,?2); -- %d times",n); for(i=1; i<=n; i++){ x1 = swizzle(i,maxb); speedtest1_numbername(i, zNum, sizeof(zNum)); sqlite3_bind_int(g.pStmt, 1, (sqlite3_int64)x1); sqlite3_bind_text(g.pStmt, 2, zNum, -1, SQLITE_STATIC); speedtest1_run(); } speedtest1_exec("COMMIT"); speedtest1_end_test(); speedtest1_begin_test(410, "%d SELECTS on an IPK", n); speedtest1_prepare("SELECT b FROM t5 WHERE a=?1; -- %d times",n); for(i=1; i<=n; i++){ x1 = swizzle(i,maxb); sqlite3_bind_int(g.pStmt, 1, (sqlite3_int64)x1); speedtest1_run(); } speedtest1_end_test(); sz = n = g.szTest*700; zNum[0] = 0; maxb = roundup_allones(sz/3); speedtest1_begin_test(500, "%d REPLACE on TEXT PK", n); speedtest1_exec("BEGIN"); speedtest1_exec("CREATE%s TABLE t6(a TEXT PRIMARY KEY, b %s)%s;", isTemp(9), g.zNN, sqlite3_libversion_number()>=3008002 ? "WITHOUT ROWID" : ""); speedtest1_prepare("REPLACE INTO t6 VALUES(?1,?2); -- %d times",n); for(i=1; i<=n; i++){ x1 = swizzle(i,maxb); speedtest1_numbername(x1, zNum, sizeof(zNum)); sqlite3_bind_int(g.pStmt, 2, i); sqlite3_bind_text(g.pStmt, 1, zNum, -1, SQLITE_STATIC); speedtest1_run(); } speedtest1_exec("COMMIT"); speedtest1_end_test(); speedtest1_begin_test(510, "%d SELECTS on a TEXT PK", n); speedtest1_prepare("SELECT b FROM t6 WHERE a=?1; -- %d times",n); for(i=1; i<=n; i++){ x1 = swizzle(i,maxb); speedtest1_numbername(x1, zNum, sizeof(zNum)); sqlite3_bind_text(g.pStmt, 1, zNum, -1, SQLITE_STATIC); speedtest1_run(); } speedtest1_end_test(); speedtest1_begin_test(520, "%d SELECT DISTINCT", n); speedtest1_exec("SELECT DISTINCT b FROM t5;"); speedtest1_exec("SELECT DISTINCT b FROM t6;"); speedtest1_end_test(); speedtest1_begin_test(980, "PRAGMA integrity_check"); speedtest1_exec("PRAGMA integrity_check"); speedtest1_end_test(); speedtest1_begin_test(990, "ANALYZE"); |
︙ | ︙ | |||
1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 | if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]); zKey = argv[++i]; }else if( strcmp(z,"lookaside")==0 ){ if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]); nLook = integerValue(argv[i+1]); szLook = integerValue(argv[i+2]); i += 2; }else if( strcmp(z,"multithread")==0 ){ sqlite3_config(SQLITE_CONFIG_MULTITHREAD); }else if( strcmp(z,"nomemstat")==0 ){ sqlite3_config(SQLITE_CONFIG_MEMSTATUS, 0); }else if( strcmp(z,"nosync")==0 ){ noSync = 1; }else if( strcmp(z,"notnull")==0 ){ g.zNN = "NOT NULL"; #ifdef SQLITE_ENABLE_RBU }else if( strcmp(z,"rbu")==0 ){ sqlite3ota_create_vfs("rbu", 0); | > > | 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 | if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]); zKey = argv[++i]; }else if( strcmp(z,"lookaside")==0 ){ if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]); nLook = integerValue(argv[i+1]); szLook = integerValue(argv[i+2]); i += 2; #if SQLITE_VERSION_NUMBER>=3006000 }else if( strcmp(z,"multithread")==0 ){ sqlite3_config(SQLITE_CONFIG_MULTITHREAD); }else if( strcmp(z,"nomemstat")==0 ){ sqlite3_config(SQLITE_CONFIG_MEMSTATUS, 0); #endif }else if( strcmp(z,"nosync")==0 ){ noSync = 1; }else if( strcmp(z,"notnull")==0 ){ g.zNN = "NOT NULL"; #ifdef SQLITE_ENABLE_RBU }else if( strcmp(z,"rbu")==0 ){ sqlite3ota_create_vfs("rbu", 0); |
︙ | ︙ | |||
1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 | }else if( strcmp(z,"reprepare")==0 ){ g.bReprepare = 1; }else if( strcmp(z,"scratch")==0 ){ if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]); nScratch = integerValue(argv[i+1]); szScratch = integerValue(argv[i+2]); i += 2; }else if( strcmp(z,"serialized")==0 ){ sqlite3_config(SQLITE_CONFIG_SERIALIZED); }else if( strcmp(z,"singlethread")==0 ){ sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); }else if( strcmp(z,"sqlonly")==0 ){ g.bSqlOnly = 1; }else if( strcmp(z,"shrink-memory")==0 ){ g.bMemShrink = 1; }else if( strcmp(z,"size")==0 ){ if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]); g.szTest = integerValue(argv[++i]); | > > | 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 | }else if( strcmp(z,"reprepare")==0 ){ g.bReprepare = 1; }else if( strcmp(z,"scratch")==0 ){ if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]); nScratch = integerValue(argv[i+1]); szScratch = integerValue(argv[i+2]); i += 2; #if SQLITE_VERSION_NUMBER>=3006000 }else if( strcmp(z,"serialized")==0 ){ sqlite3_config(SQLITE_CONFIG_SERIALIZED); }else if( strcmp(z,"singlethread")==0 ){ sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); #endif }else if( strcmp(z,"sqlonly")==0 ){ g.bSqlOnly = 1; }else if( strcmp(z,"shrink-memory")==0 ){ g.bMemShrink = 1; }else if( strcmp(z,"size")==0 ){ if( i>=argc-1 ) fatal_error("missing argument on %s\n", argv[i]); g.szTest = integerValue(argv[++i]); |
︙ | ︙ |
Changes to test/tkt-80e031a00f.test.
︙ | ︙ | |||
16 17 18 19 20 21 22 | # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/malloc_common.tcl | < < < < | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/malloc_common.tcl # EVIDENCE-OF: R-52275-55503 When the right operand is an empty set, the # result of IN is false and the result of NOT IN is true, regardless of # the left operand and even if the left operand is NULL. # # EVIDENCE-OF: R-13595-45863 Note that SQLite allows the parenthesized # list of scalar values on the right-hand side of an IN or NOT IN # operator to be an empty list but most other SQL database database |
︙ | ︙ |
Changes to tool/fuzzershell.c.
︙ | ︙ | |||
191 192 193 194 195 196 197 | /* ** This callback is invoked by sqlite3_exec() to return query results. */ static int execCallback(void *NotUsed, int argc, char **argv, char **colv){ int i; static unsigned cnt = 0; printf("ROW #%u:\n", ++cnt); | > | | | | | | > | 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | /* ** This callback is invoked by sqlite3_exec() to return query results. */ static int execCallback(void *NotUsed, int argc, char **argv, char **colv){ int i; static unsigned cnt = 0; printf("ROW #%u:\n", ++cnt); if( argv ){ for(i=0; i<argc; i++){ printf(" %s=", colv[i]); if( argv[i] ){ printf("[%s]\n", argv[i]); }else{ printf("NULL\n"); } } } fflush(stdout); return 0; } static int execNoop(void *NotUsed, int argc, char **argv, char **colv){ return 0; |
︙ | ︙ |