Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch branch-3.42 Excluding Merge-Ins
This is equivalent to a diff from 831d0fb283 to f5913e7632
2023-10-12
| ||
20:03 | Fix a problem with an fts5 secure-delete on a rowid/term pair that follows a legacy delete of the same pair. (Leaf check-in: f5913e7632 user: dan tags: branch-3.42) | |
19:46 | Fix a problem with an fts5 secure-delete on a rowid/term pair that follows a legacy delete of the same pair. (check-in: 579aea0c28 user: dan tags: trunk) | |
2023-09-08
| ||
19:32 | Fix a problem with fts5 secure-delete mode causing fts5 to corrupt its records. (check-in: cc0f82a480 user: dan tags: branch-3.42) | |
2023-05-17
| ||
00:29 | Fix two assert() statements that failed to take into account the likely() built-in function. This does not impact production code. (check-in: 634fe4c238 user: drh tags: branch-3.42) | |
2023-05-16
| ||
20:37 | Further extend use of CLI resmanage. (40% of dot commands) (check-in: 0cdab9f17a user: larrybr tags: cli_extension) | |
14:18 | Resolve the JS-side corner case reported in forum post 7774b773937cbe0a by not caching oo1.Stmt.columnCount. (check-in: 37d44e8c44 user: stephan tags: trunk) | |
13:11 | Merge all 3.42.0 release enhancements into the reuse-schema branch. (check-in: d67b6c393f user: drh tags: reuse-schema) | |
13:00 | Merge all 3.42.0 release changes into the wal2 branch. (check-in: 137057f957 user: drh tags: wal2) | |
12:56 | Merge all 3.42.0 release changes into the begin-concurrent branch. (check-in: 804bb138f5 user: drh tags: begin-concurrent) | |
12:36 | Version 3.42.0 (check-in: 831d0fb283 user: drh tags: trunk, release, version-3.42.0) | |
12:34 | Update the tool/mkmsvcmin.tcl script so that it prints a one-line message to explain what it has done. (check-in: 4254f08641 user: drh tags: trunk) | |
Changes to VERSION.
|
| | | 1 | 3.42.1 |
Changes to configure.
1 2 | #! /bin/sh # Guess values for system-dependent variables and create Makefiles. | | | 1 2 3 4 5 6 7 8 9 10 | #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for sqlite 3.42.1. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. |
︙ | ︙ | |||
722 723 724 725 726 727 728 | subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' | | | | 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 | subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' PACKAGE_VERSION='3.42.1' PACKAGE_STRING='sqlite 3.42.1' PACKAGE_BUGREPORT='' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include <stdio.h> #ifdef HAVE_SYS_TYPES_H |
︙ | ︙ | |||
1466 1467 1468 1469 1470 1471 1472 | # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF | | | 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 | # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures sqlite 3.42.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. |
︙ | ︙ | |||
1531 1532 1533 1534 1535 1536 1537 | --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in | | | 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 | --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of sqlite 3.42.1:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] |
︙ | ︙ | |||
1661 1662 1663 1664 1665 1666 1667 | cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF | | | 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 | cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF sqlite configure 3.42.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit |
︙ | ︙ | |||
2080 2081 2082 2083 2084 2085 2086 | eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. | | | 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 | eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by sqlite $as_me 3.42.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { |
︙ | ︙ | |||
12453 12454 12455 12456 12457 12458 12459 | test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" | | | 12453 12454 12455 12456 12457 12458 12459 12460 12461 12462 12463 12464 12465 12466 12467 | test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by sqlite $as_me 3.42.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ |
︙ | ︙ | |||
12519 12520 12521 12522 12523 12524 12525 | Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ | | | 12519 12520 12521 12522 12523 12524 12525 12526 12527 12528 12529 12530 12531 12532 12533 | Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ sqlite config.status 3.42.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." |
︙ | ︙ |
Changes to ext/fts5/fts5_index.c.
︙ | ︙ | |||
2687 2688 2689 2690 2691 2692 2693 | }else{ int res = fts5BufferCompare(&p1->term, &p2->term); if( res==0 ){ assert_nc( i2>i1 ); assert_nc( i2!=0 ); pRes->bTermEq = 1; if( p1->iRowid==p2->iRowid ){ | < | 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 | }else{ int res = fts5BufferCompare(&p1->term, &p2->term); if( res==0 ){ assert_nc( i2>i1 ); assert_nc( i2!=0 ); pRes->bTermEq = 1; if( p1->iRowid==p2->iRowid ){ return i2; } res = ((p1->iRowid > p2->iRowid)==pIter->bRev) ? -1 : +1; } assert( res!=0 ); if( res<0 ){ iRes = i1; |
︙ | ︙ | |||
4707 4708 4709 4710 4711 4712 4713 | int iOff = 0; int nIdx = 0; u8 *aIdx = 0; int bLastInDoclist = 0; int iIdx = 0; int iStart = 0; int iKeyOff = 0; | < | 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 | int iOff = 0; int nIdx = 0; u8 *aIdx = 0; int bLastInDoclist = 0; int iIdx = 0; int iStart = 0; int iKeyOff = 0; int iDelKeyOff = 0; /* Offset of deleted key, if any */ nIdx = nPg-iPgIdx; aIdx = sqlite3Fts5MallocZero(&p->rc, nIdx+16); if( p->rc ) return; memcpy(aIdx, &aPg[iPgIdx], nIdx); |
︙ | ︙ | |||
4771 4772 4773 4774 4775 4776 4777 | } assert_nc( iSOP==pSeg->iLeafOffset ); iNextOff = pSeg->iLeafOffset + pSeg->nPos; } } iOff = iStart; | > | | | | | | | | | | | | | | | | | | | | > > > > | | 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 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 | } assert_nc( iSOP==pSeg->iLeafOffset ); iNextOff = pSeg->iLeafOffset + pSeg->nPos; } } iOff = iStart; if( pSeg->bDel==0 ){ if( iNextOff>=iPgIdx ){ int pgno = pSeg->iLeafPgno+1; fts5SecureDeleteOverflow(p, pSeg->pSeg, pgno, &bLastInDoclist); iNextOff = iPgIdx; }else{ /* Set bLastInDoclist to true if the entry being removed is the last ** in its doclist. */ for(iIdx=0, iKeyOff=0; iIdx<nIdx; /* no-op */){ u32 iVal = 0; iIdx += fts5GetVarint32(&aIdx[iIdx], iVal); iKeyOff += iVal; if( iKeyOff==iNextOff ){ bLastInDoclist = 1; } } } if( fts5GetU16(&aPg[0])==iStart && (bLastInDoclist||iNextOff==iPgIdx) ){ fts5PutU16(&aPg[0], 0); } } if( pSeg->bDel ){ iOff += sqlite3Fts5PutVarint(&aPg[iOff], iDelta); aPg[iOff++] = 0x01; }else if( bLastInDoclist==0 ){ if( iNextOff!=iPgIdx ){ iNextOff += fts5GetVarint(&aPg[iNextOff], &iNextDelta); iOff += sqlite3Fts5PutVarint(&aPg[iOff], iDelta + iNextDelta); } }else if( iStart==pSeg->iTermLeafOffset && pSeg->iLeafPgno==pSeg->iTermLeafPgno ){ |
︙ | ︙ | |||
4836 4837 4838 4839 4840 4841 4842 | if( (iKeyOff+nSuffix)>iPgIdx || (iNextOff+nSuffix2)>iPgIdx ){ p->rc = FTS5_CORRUPT; }else{ if( iKey!=1 ){ iOff += sqlite3Fts5PutVarint(&aPg[iOff], nPrefix); } iOff += sqlite3Fts5PutVarint(&aPg[iOff], nSuffix); | > > | | 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 | if( (iKeyOff+nSuffix)>iPgIdx || (iNextOff+nSuffix2)>iPgIdx ){ p->rc = FTS5_CORRUPT; }else{ if( iKey!=1 ){ iOff += sqlite3Fts5PutVarint(&aPg[iOff], nPrefix); } iOff += sqlite3Fts5PutVarint(&aPg[iOff], nSuffix); if( nPrefix2>pSeg->term.n ){ p->rc = FTS5_CORRUPT; }else if( nPrefix2>nPrefix ){ memcpy(&aPg[iOff], &pSeg->term.p[nPrefix], nPrefix2-nPrefix); iOff += (nPrefix2-nPrefix); } memmove(&aPg[iOff], &aPg[iNextOff], nSuffix2); iOff += nSuffix2; iNextOff += nSuffix2; } |
︙ | ︙ | |||
4889 4890 4891 4892 4893 4894 4895 | } } fts5DataRelease(pTerm); } } if( p->rc==SQLITE_OK ){ | | | > > | < | | | < < | < | | | 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 | } } fts5DataRelease(pTerm); } } if( p->rc==SQLITE_OK ){ const int nMove = nPg - iNextOff; /* Number of bytes to move */ int nShift = iNextOff - iOff; /* Distance to move them */ int iPrevKeyOut = 0; int iKeyIn = 0; memmove(&aPg[iOff], &aPg[iNextOff], nMove); iPgIdx -= nShift; nPg = iPgIdx; fts5PutU16(&aPg[2], iPgIdx); for(iIdx=0; iIdx<nIdx; /* no-op */){ u32 iVal = 0; iIdx += fts5GetVarint32(&aIdx[iIdx], iVal); iKeyIn += iVal; if( iKeyIn!=iDelKeyOff ){ int iKeyOut = (iKeyIn - (iKeyIn>iOff ? nShift : 0)); nPg += sqlite3Fts5PutVarint(&aPg[nPg], iKeyOut - iPrevKeyOut); iPrevKeyOut = iKeyOut; } } if( iPgIdx==nPg && nIdx>0 && pSeg->iLeafPgno!=1 ){ fts5SecureDeleteIdxEntry(p, iSegid, pSeg->iLeafPgno); } |
︙ | ︙ | |||
5087 5088 5089 5090 5091 5092 5093 | iOff++; } } if( (pBuf->n + pPgidx->n)>=pgsz ){ fts5WriteFlushLeaf(p, &writer); } }else{ | | | | > > > > > | > | 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 | iOff++; } } if( (pBuf->n + pPgidx->n)>=pgsz ){ fts5WriteFlushLeaf(p, &writer); } }else{ int bDel = 0; int nPos = 0; int nCopy = fts5GetPoslistSize(&pDoclist[iOff], &nPos, &bDel); if( bDel && bSecureDelete ){ fts5BufferAppendVarint(&p->rc, pBuf, nPos*2); iOff += nCopy; nCopy = nPos; }else{ nCopy += nPos; } if( (pBuf->n + pPgidx->n + nCopy) <= pgsz ){ /* The entire poslist will fit on the current leaf. So copy ** it in one go. */ fts5BufferSafeAppendBlob(pBuf, &pDoclist[iOff], nCopy); }else{ /* The entire poslist will not fit on this leaf. So it needs ** to be broken into sections. The only qualification being |
︙ | ︙ |
Changes to ext/fts5/test/fts5corrupt7.test.
︙ | ︙ | |||
91 92 93 94 95 96 97 98 99 | catchsql { DELETE FROM t1 WHERE rowid=124; } catchsql { DELETE FROM t1 WHERE rowid=123; } set {} {} } {} db close } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | catchsql { DELETE FROM t1 WHERE rowid=124; } catchsql { DELETE FROM t1 WHERE rowid=123; } set {} {} } {} db close } #------------------------------------------------------------------------- reset_db do_execsql_test 2.0 { CREATE VIRTUAL TABLE t1 USING fts5(x); BEGIN; INSERT INTO t1 VALUES('abc'); INSERT INTO t1 VALUES('b d d d'); COMMIT; INSERT INTO t1(t1, rank) VALUES('secure-delete', 1); } execsql_pp { SELECT id, quote(block) FROM t1_data } do_execsql_test 2.1 { SELECT quote(block) FROM t1_data WHERE id > 10; } {X'0000001A04306162630102020101620202020101640206030303040806'} do_execsql_test 2.2 { UPDATE t1_data SET block=X'0000001A04306162630102025501620202020101640206030303040806' WHERE id>10 } do_catchsql_test 2.3 { DELETE FROM t1 WHERE rowid = 1 } {1 {database disk image is malformed}} finish_test |
Changes to ext/fts5/test/fts5secure.test.
︙ | ︙ | |||
268 269 270 271 272 273 274 275 276 277 278 | do_execsql_test 5.3 { INSERT INTO t1(t1) VALUES('integrity-check'); } do_execsql_test 5.4 { SELECT rowid FROM t1('abc'); } 2 do_execsql_test 5.5 { SELECT rowid FROM t1('aa'); } 2 finish_test | > > > > > > > > > > > > > | 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 | do_execsql_test 5.3 { INSERT INTO t1(t1) VALUES('integrity-check'); } do_execsql_test 5.4 { SELECT rowid FROM t1('abc'); } 2 do_execsql_test 5.5 { SELECT rowid FROM t1('aa'); } 2 #------------------------------------------------------------------------- reset_db do_execsql_test 6.0 { CREATE VIRTUAL TABLE fts USING fts5(content); INSERT INTO fts(fts, rank) VALUES ('secure-delete', 1); INSERT INTO fts(rowid, content) VALUES (3407, 'profile profile profile profile profile profile profile profile pull pulling pulling really'); DELETE FROM fts WHERE rowid IS 3407; INSERT INTO fts(fts) VALUES ('integrity-check'); } finish_test |
Changes to ext/fts5/test/fts5secure6.test.
︙ | ︙ | |||
14 15 16 17 18 19 20 | ifcapable !fts5 { finish_test ; return } set ::testprefix fts5secure6 db progress 1 progress_handler set ::PHC 0 proc progress_handler {args} { incr ::PHC | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ifcapable !fts5 { finish_test ; return } set ::testprefix fts5secure6 db progress 1 progress_handler set ::PHC 0 proc progress_handler {args} { incr ::PHC # if {($::PHC % 100000)==0} breakpoint return 0 } proc setup {} { db eval { DROP TABLE IF EXISTS t1; CREATE VIRTUAL TABLE t1 USING fts5(x); |
︙ | ︙ | |||
46 47 48 49 50 51 52 53 54 55 | set phc($tn) $PHC } do_test 1.3 { expr $phc(1)*5 < $phc(2) } {1} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | set phc($tn) $PHC } do_test 1.3 { expr $phc(1)*5 < $phc(2) } {1} #------------------------------------------------------------------------- reset_db do_execsql_test 2.0 { CREATE VIRTUAL TABLE t1 USING fts5(x); INSERT INTO t1(t1, rank) VALUES('secure-delete', $sd) } do_execsql_test 2.1 { BEGIN; INSERT INTO t1(rowid, x) VALUES(-100000, 'abc def ghi'); INSERT INTO t1(rowid, x) VALUES(-99999, 'abc def ghi'); INSERT INTO t1(rowid, x) VALUES(9223372036854775800, 'abc def ghi'); COMMIT; } do_execsql_test 2.2 { SELECT rowid FROM t1('def') } {-100000 -99999 9223372036854775800} #------------------------------------------------------------------------- reset_db do_execsql_test 2.0 { CREATE VIRTUAL TABLE t1 USING fts5(x); INSERT INTO t1(t1, rank) VALUES('secure-delete', $sd) } do_execsql_test 2.1 { BEGIN; INSERT INTO t1(rowid, x) VALUES(51869, 'when whenever where weress what turn'), (51871, 'to were'); COMMIT; } do_execsql_test 3.2 { DELETE FROM t1 WHERE rowid=51871; INSERT INTO t1(t1) VALUES('integrity-check'); } #------------------------------------------------------------------------- reset_db do_execsql_test 2.0 { CREATE VIRTUAL TABLE t1 USING fts5(x); INSERT INTO t1(t1, rank) VALUES('secure-delete', $sd) } do_execsql_test 2.1 { BEGIN; INSERT INTO t1(rowid, x) VALUES(-100000, 'abc def ghi'); INSERT INTO t1(rowid, x) VALUES(-99999, 'abc def ghi'); INSERT INTO t1(rowid, x) VALUES(9223372036854775800, 'abc def ghi'); COMMIT; } do_execsql_test 2.2 { SELECT rowid FROM t1('def') } {-100000 -99999 9223372036854775800} #------------------------------------------------------------------------- reset_db do_execsql_test 3.0 { CREATE VIRTUAL TABLE t1 USING fts5(x); INSERT INTO t1(t1, rank) VALUES('secure-delete', $sd) } do_execsql_test 3.1 { BEGIN; INSERT INTO t1(rowid, x) VALUES(51869, 'when whenever where weress what turn'), (51871, 'to were'); COMMIT; } do_execsql_test 3.2 { DELETE FROM t1 WHERE rowid=51871; INSERT INTO t1(t1) VALUES('integrity-check'); } #------------------------------------------------------------------------- reset_db do_execsql_test 4.0 { CREATE VIRTUAL TABLE t1 USING fts5(x); INSERT INTO t1(rowid, x) VALUES(10, 'one two'); } do_execsql_test 4.1 { UPDATE t1 SET x = 'one three' WHERE rowid=10; INSERT INTO t1(t1, rank) VALUES('secure-delete', 1); } do_execsql_test 4.2 { DELETE FROM t1 WHERE rowid=10; } do_execsql_test 4.3 { INSERT INTO t1(t1) VALUES('integrity-check'); } finish_test |
Changes to ext/recover/recovercorrupt2.test.
︙ | ︙ | |||
281 282 283 284 285 286 287 288 289 | do_test 5.1 { set R [sqlite3_recover_init db main test.db2] catch { $R run } list [catch { $R finish } msg] $msg } {0 {}} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | do_test 5.1 { set R [sqlite3_recover_init db main test.db2] catch { $R run } list [catch { $R finish } msg] $msg } {0 {}} reset_db breakpoint do_test 7.0 { sqlite3 db {} db deserialize [decode_hexdb { | size 4108 pagesize 4096 filename x1.db | page 1 offset 0 | 0: 02 01 00 00 00 00 14 15 40 00 00 00 00 00 00 00 ........@....... | 16: 33 3a 6d 65 6d 6f 72 79 3a 02 02 02 02 02 02 02 3:memory:....... | 32: 02 02 02 02 02 02 12 02 02 02 63 6f 6c 6f 72 20 ..........color | 48: 73 70 61 63 00 f3 a0 81 a1 00 00 a0 02 02 02 02 spac............ | 64: 69 95 73 6f 36 00 ff 0d 00 97 8c 90 3f 0a 70 02 i.so6.......?.p. | 80: 02 02 02 02 02 02 02 02 02 02 02 02 02 01 00 00 ................ | 96: 06 02 02 02 02 5f 02 02 02 2c 02 02 02 02 02 02 ....._...,...... | 112: 02 02 02 02 02 02 02 02 02 12 02 02 02 63 6f 6c .............col | 128: 6f 72 20 73 70 61 63 00 f3 a0 81 a1 00 00 a0 02 or spac......... | 144: 02 02 02 69 95 73 6f 36 00 ff 0d 00 97 8c 90 3f ...i.so6.......? | 160: 0a 70 02 02 02 02 02 02 02 02 02 02 02 02 02 02 .p.............. | 176: 01 00 00 06 02 02 02 02 5f 02 02 02 2c 02 02 00 ........_...,... | 192: 00 01 00 01 00 00 00 01 00 02 fe 00 00 03 00 01 ................ | 208: 00 00 00 01 c5 04 00 00 00 01 00 01 00 00 00 01 ................ | 224: 00 fa 02 00 00 00 03 00 01 00 00 00 81 00 04 00 ................ | 240: 00 00 01 00 01 00 00 00 01 00 02 00 fe 00 03 00 ................ | 256: 01 00 00 00 01 00 04 00 00 00 01 00 01 00 00 00 ................ | 272: 01 00 02 00 00 00 03 00 01 00 00 00 01 00 04 00 ................ | 288: 00 00 01 00 01 00 00 00 01 00 02 00 00 00 03 00 ................ | 304: 01 00 00 00 01 00 04 00 00 00 01 00 01 00 00 00 ................ | 320: 01 00 02 00 00 00 03 00 01 00 00 00 40 00 84 00 ............@... | 336: 84 00 84 00 01 00 00 00 09 00 06 00 f5 00 01 00 ................ | 352: 08 01 03 00 03 00 62 00 62 00 23 00 01 00 62 00 ......b.b.#...b. | 368: 04 00 1e 00 62 00 62 00 62 00 01 00 00 00 0a 00 ....b.b.b....... | 384: 01 00 03 00 01 00 03 00 04 00 02 00 01 00 01 00 ................ | 400: 08 00 01 00 31 c6 00 03 00 0c 00 12 00 18 00 02 ....1........... | 416: 00 05 00 08 00 02 00 06 00 08 00 02 00 07 00 08 ................ | 432: 00 02 00 01 00 01 00 08 00 01 00 0c 00 03 00 16 ................ | 448: 00 1c 00 22 00 01 00 03 00 05 00 06 00 07 00 02 ................ | 464: 00 05 00 09 00 02 00 06 00 09 00 02 00 07 00 09 ................ | 480: 00 00 00 00 01 00 05 00 00 00 01 00 01 00 00 00 ................ | 496: 01 00 02 00 00 00 03 00 01 00 00 00 01 00 04 00 ................ | 512: 00 00 01 00 01 00 00 00 01 00 02 00 00 00 03 00 ................ | 528: 01 00 00 00 01 00 04 00 00 00 01 00 01 00 00 00 ................ | 544: 01 00 02 00 00 f6 03 00 00 02 00 00 01 00 04 00 ................ | 560: 00 00 01 00 01 00 00 00 01 00 02 00 00 00 03 00 ................ | 576: 01 00 00 00 01 00 04 00 00 00 01 00 01 00 00 00 ................ | 592: 01 00 02 00 00 00 03 00 01 00 00 00 01 00 04 00 ................ | 608: 00 00 01 00 01 00 00 00 01 00 02 00 00 00 03 00 ................ | 624: 01 00 00 00 01 00 04 00 00 00 01 00 01 00 00 00 ................ | 640: 01 3d 02 00 00 00 03 00 06 00 00 00 01 00 01 00 .=.............. | 656: 00 00 01 00 01 00 00 00 01 00 02 00 00 00 03 00 ................ | 672: 01 00 00 00 01 00 04 00 00 00 01 00 01 00 00 00 ................ | 688: 01 00 02 00 00 00 55 52 4c 52 65 71 75 65 73 74 ......URLRequest | 704: 43 6f 6e 00 00 00 01 01 0e d4 00 04 00 00 00 01 Con............. | 720: 0e f8 00 04 00 00 00 01 0f 1c 00 04 00 00 00 01 ................ | 736: 0f 00 00 01 00 00 00 01 0f 86 00 01 00 00 00 01 ................ | 752: 0f 84 00 01 00 00 00 01 00 00 01 0f c0 00 01 00 ................ | 768: 00 00 01 0f e8 00 d6 0f 00 01 6f 00 02 0f d6 00 ..........o..... | 784: 02 34 03 03 03 00 01 00 00 00 01 00 05 00 00 00 .4.............. | 800: 01 00 01 00 00 00 01 00 02 00 00 00 03 00 01 00 ................ | 816: 00 00 01 00 04 00 00 00 01 00 01 00 00 00 01 00 ................ | 832: 02 00 00 00 03 00 01 00 10 00 01 00 04 00 00 00 ................ | 848: 01 00 01 00 00 00 01 00 02 00 00 00 03 00 00 02 ................ | 864: 00 00 01 40 04 00 00 03 01 00 01 00 00 00 01 00 ...@............ | 880: 02 00 00 00 03 00 01 00 00 00 00 00 01 0e f8 00 ................ | 896: 04 77 4f 46 32 73 40 23 70 00 00 00 70 00 1f 00 .wOF2s@#p...p... | 912: 00 00 d8 00 00 00 ff ff 00 00 00 00 43 00 00 00 ............C... | 928: 00 00 ff ff ff ff ff 00 00 a8 00 00 0c 00 00 00 ................ | 1024: 00 00 00 00 00 00 00 00 00 00 10 22 00 22 0f 00 ................ | 1040: 00 00 00 00 00 00 10 22 00 00 70 00 1f 00 00 0f ..........p..... | 1056: d8 00 00 00 00 00 00 00 00 00 03 00 00 00 00 00 ................ | 1072: 00 01 00 00 00 3f 23 70 00 00 00 01 0f 1c 00 04 .....?#p........ | 1088: 00 00 00 01 0f 40 00 01 00 00 00 01 0f 86 00 01 .....@.......... | 1104: 00 00 00 01 0f 84 00 01 00 00 00 01 00 00 01 0f ................ | 1120: c0 00 01 00 00 00 01 0f e8 00 01 0f d6 00 6f 00 ..............o. | 1136: 02 0f d6 00 03 02 31 03 2b 03 2a f2 00 0f d4 00 ......1.+.*..... | 1152: 01 00 08 00 01 00 04 03 2b 00 02 02 32 00 01 0f ........+...2... | 1168: c8 01 15 00 02 20 c8 00 02 12 ad 02 00 24 06 c0 ..... .......$.. | 1184: 00 00 00 03 00 00 01 24 00 2a 06 e4 00 00 00 03 .......$.*...... | 1200: 00 00 01 25 00 38 07 0e 00 00 00 03 00 00 01 26 ...%.8.........& | 1216: 00 34 07 46 00 00 00 03 00 00 01 27 00 1c 07 7a .4.F.......'...z | 1232: 00 00 00 03 00 00 01 28 00 2a 07 96 00 00 00 03 .......(.*...... | 1248: 00 e5 01 29 00 34 07 c0 00 00 00 03 00 00 01 2a ...).4.........* | 1264: 67 34 07 f4 00 00 00 03 00 00 01 2b 00 22 08 28 g4.........+...( | 1280: 00 00 00 00 01 00 01 00 00 00 01 00 02 00 00 00 ................ | 1296: 03 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 ................ | 1312: 01 00 00 00 01 00 02 00 00 00 03 00 00 02 00 00 ................ | 1328: 01 00 04 00 00 00 01 00 01 00 00 00 01 00 02 00 ................ | 1344: 00 00 03 00 01 00 00 00 01 00 04 00 00 00 01 00 ................ | 1360: 01 00 00 00 01 00 02 00 00 00 03 00 01 00 00 21 ...............! | 1376: 04 00 01 00 00 00 00 00 01 00 00 00 01 00 02 00 ................ | 1392: 00 00 03 00 01 00 00 00 01 00 04 00 00 00 01 00 ................ | 1408: 01 00 00 00 01 00 02 00 00 00 03 00 01 00 00 00 ................ | 1424: 01 00 05 00 00 00 01 00 01 00 00 01 00 02 02 02 ................ | 1440: 12 02 02 02 63 6f 6c 6f 72 20 73 70 61 63 00 f3 ....color spac.. | 1456: a0 81 a1 00 00 a0 02 02 02 02 69 95 73 6f 36 00 ..........i.so6. | 1472: ff 0d 00 97 8c 90 3f 0a 70 02 02 02 02 02 02 02 ......?.p....... | 1488: 02 02 02 02 02 02 02 01 00 00 06 02 02 02 02 5f ..............._ | 1504: 02 02 02 2c 02 02 00 00 01 00 01 00 00 00 01 00 ...,............ | 1520: 02 fe 00 00 03 00 01 00 00 00 01 c5 04 00 00 00 ................ | 1536: 01 00 01 00 00 00 01 00 02 00 00 00 03 00 01 00 ................ | 1552: 00 00 81 00 04 00 00 00 01 00 01 00 00 00 01 00 ................ | 1568: 02 00 fe 00 03 00 01 00 00 00 01 00 04 00 00 00 ................ | 1584: 01 00 01 00 00 00 01 00 02 00 00 00 03 00 01 00 ................ | 1600: 00 00 01 00 04 00 00 00 01 00 01 00 00 00 01 00 ................ | 1616: 02 00 00 00 03 00 01 00 00 00 01 00 04 00 00 00 ................ | 1632: 01 00 01 00 00 00 01 00 02 00 00 00 03 00 01 00 ................ | 1648: 00 00 40 00 84 00 84 00 84 00 01 00 00 00 09 00 ..@............. | 1664: 06 00 f5 00 01 00 08 01 03 15 15 15 15 15 15 15 ................ | 1680: 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 ................ | 1696: 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 ................ | 1712: 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 ................ | 1728: 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 ................ | 1744: 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 ................ | 1760: 15 15 15 15 15 15 15 15 15 15 15 00 03 00 62 00 ..............b. | 1776: 62 00 23 00 01 00 62 00 04 00 1e 00 62 00 62 00 b.#...b.....b.b. | 1792: 62 00 01 00 00 00 0a 00 01 00 03 00 01 00 03 00 b............... | 1808: 04 00 02 00 01 00 01 00 08 00 01 00 31 c6 00 03 ............1... | 1824: 00 0c 00 12 00 18 00 02 00 05 00 08 00 02 00 06 ................ | 1840: 00 08 00 02 00 07 00 08 00 02 00 01 00 01 00 08 ................ | 1856: 00 01 00 0c 00 03 00 16 00 1c 00 22 00 01 00 03 ................ | 1872: 00 05 00 06 00 07 00 02 00 05 00 09 00 02 00 06 ................ | 1888: 00 09 00 02 00 07 00 09 00 00 00 00 01 00 05 00 ................ | 1904: 00 00 01 00 01 00 00 00 01 00 02 00 00 00 03 00 ................ | 1920: 01 00 00 00 01 00 04 00 00 00 01 00 01 00 00 00 ................ | 1936: 01 00 02 00 00 00 03 00 01 00 00 00 01 00 04 00 ................ | 1952: 00 00 01 0f d6 00 02 34 03 03 03 00 01 00 00 00 .......4........ | 1968: 01 00 05 00 00 00 01 00 01 00 00 00 01 00 02 00 ................ | 1984: 00 00 03 00 01 00 00 00 01 00 04 00 00 00 01 00 ................ | 2000: 01 00 00 00 01 00 02 fc 42 dc 19 5c 74 23 18 cd ........B...t#.. | 2016: b3 a5 a8 7a 90 40 1d 66 12 5d e5 4f 85 00 68 f4 ...z.@.f.].O..h. | 2032: 05 98 86 25 24 dd bc c2 f6 f6 4e a3 e2 61 d2 c6 ...%$.....N..a.. | 2048: aa c1 56 50 d4 80 82 35 f1 e2 59 41 50 a6 da 51 ..VP...5..YAP..Q | 2064: d4 62 9c 19 94 58 aa 31 30 8a 22 c2 5f 33 2b c9 .b...X.10..._3+. | 2080: b6 e6 b4 11 4e 51 82 c4 d8 b6 d8 b4 06 04 fb 68 ....NQ.........h | 2096: f4 d2 6f e7 cb 8a a8 82 d5 74 00 00 00 00 00 00 ..o......t...... | 2368: 00 00 00 00 00 00 00 00 00 08 00 00 00 00 00 00 ................ | 2432: 00 00 00 00 00 03 00 01 00 10 00 01 00 04 00 00 ................ | 2448: 00 01 00 01 00 00 00 01 00 02 00 00 00 03 00 00 ................ | 2464: 02 00 00 01 40 04 00 00 03 01 00 01 00 00 00 01 ....@........... | 2480: 00 02 00 00 00 03 00 01 00 00 00 00 00 01 0e f8 ................ | 2496: 00 04 77 4f 46 32 73 40 23 70 00 00 00 70 00 1f ..wOF2s@#p...p.. | 2512: 00 00 00 d8 00 00 00 ff ff 00 00 00 00 43 00 00 .............C.. | 2528: 00 00 00 ff ff ff ff ff 00 00 a8 00 00 0c 00 00 ................ | 2624: 00 00 00 00 00 00 00 00 00 00 00 10 22 00 22 0f ................ | 2640: 00 00 00 00 00 00 00 10 22 00 00 70 00 1f 00 00 ...........p.... | 2656: 0f d8 00 00 00 00 00 00 00 00 00 03 00 00 00 00 ................ | 2672: 00 00 01 00 00 00 3f 23 70 00 00 00 01 0f 1c 00 ......?#p....... | 2688: 04 00 00 00 01 0f 40 00 01 00 00 00 01 0f 86 00 ......@......... | 2704: 01 00 00 00 01 0f 84 00 01 00 00 00 01 00 00 01 ................ | 2720: 0f c0 00 01 00 00 00 01 0f e8 00 01 0f d6 00 6f ...............o | 2736: 00 02 0f d6 00 03 02 31 03 2b 03 2a f2 00 0f d4 .......1.+.*.... | 2752: 00 01 00 08 00 01 00 04 03 2b 00 02 02 32 00 01 .........+...2.. | 2768: 0f c8 01 15 00 02 20 c8 00 02 12 ad 02 00 24 06 ...... .......$. | 2784: c0 00 00 5a 03 00 00 01 24 00 2a 06 e4 00 00 00 ...Z....$.*..... | 2800: 03 00 00 01 25 00 38 07 0e 00 00 00 03 00 00 01 ....%.8......... | 2816: 26 00 34 07 46 00 00 00 03 00 00 01 27 00 1c 07 &.4.F.......'... | 2832: 7a 00 00 00 03 00 00 01 28 00 2a 07 96 00 00 00 z.......(.*..... | 2848: 03 00 e5 01 29 00 34 07 c0 00 00 00 03 00 00 01 ....).4......... | 2864: 2a 67 34 07 f4 00 00 00 03 00 00 01 2b 00 22 08 *g4.........+... | 2880: 28 00 00 00 00 01 00 01 00 00 00 01 00 02 00 00 (............... | 2896: 00 03 00 01 00 00 00 01 00 00 00 01 00 00 00 01 ................ | 2912: 00 01 00 00 00 01 00 02 00 00 00 03 00 00 02 00 ................ | 2928: 00 01 00 04 00 00 00 01 00 01 00 00 00 00 00 00 ................ | 2992: 00 48 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .H.............. | 3504: 00 00 00 00 00 00 00 00 00 00 00 97 00 00 00 00 ................ | 3904: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 09 ................ | 3920: 03 fe 00 00 01 36 00 3c 0a 38 00 00 00 03 00 00 .....6.<.8...... | 3936: 01 37 00 20 0a 74 00 00 00 fb ff ff 00 38 00 2a .7. .t.......8.* | 3952: 0a 94 00 00 00 03 00 00 01 39 4f 54 54 4f 00 0e .........9OTTO.. | 3968: 00 80 00 03 00 60 43 46 46 20 e3 ae 89 2a 00 00 .....`CFF ...*.. | 3984: 02 b0 00 00 02 76 42 50 4f 53 00 15 00 0a 00 00 .....vBPOS...... | 4000: 05 28 00 00 00 0c 54 53 55 42 c9 70 c3 06 00 00 .(....TSUB.p.... | 4016: 05 34 1f 00 40 00 48 00 00 00 00 00 00 00 00 00 .4..@.H......... | 4064: 00 00 00 00 00 08 00 01 00 01 00 01 00 01 00 06 ................ | 4080: 00 02 00 08 00 01 00 01 00 01 00 01 00 00 00 00 ................ | end x1.db }]} {} do_test 7.1 { set R [sqlite3_recover_init db main test.db2] catch { $R run } list [catch { $R finish } msg] $msg } {1 {file is not a database}} finish_test |
Changes to ext/recover/sqlite3recover.c.
︙ | ︙ | |||
2099 2100 2101 2102 2103 2104 2105 | if( iFree && iFree<=iContent ) return 0; while( iFree ){ int iNext = 0; int nByte = 0; if( iFree>(n-4) ) return 0; iNext = recoverGetU16(&a[iFree]); nByte = recoverGetU16(&a[iFree+2]); | | | 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 | if( iFree && iFree<=iContent ) return 0; while( iFree ){ int iNext = 0; int nByte = 0; if( iFree>(n-4) ) return 0; iNext = recoverGetU16(&a[iFree]); nByte = recoverGetU16(&a[iFree+2]); if( iFree+nByte>n || nByte<4 ) return 0; if( iNext && iNext<iFree+nByte ) return 0; memset(&aUsed[iFree], 0xFF, nByte); iFree = iNext; } /* Run through the cells */ if( eType==0x02 || eType==0x05 ){ |
︙ | ︙ |
Changes to ext/wasm/api/sqlite3-api-oo1.js.
︙ | ︙ | |||
51 52 53 54 55 56 57 58 59 60 61 62 63 64 | }; // Documented in DB.checkRc() const checkSqlite3Rc = function(dbPtr, sqliteResultCode){ if(sqliteResultCode){ if(dbPtr instanceof DB) dbPtr = dbPtr.pointer; toss3( "sqlite3 result code",sqliteResultCode+":", (dbPtr ? capi.sqlite3_errmsg(dbPtr) : capi.sqlite3_errstr(sqliteResultCode)) ); } return arguments[0]; | > | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | }; // Documented in DB.checkRc() const checkSqlite3Rc = function(dbPtr, sqliteResultCode){ if(sqliteResultCode){ if(dbPtr instanceof DB) dbPtr = dbPtr.pointer; toss3( sqliteResultCode, "sqlite3 result code",sqliteResultCode+":", (dbPtr ? capi.sqlite3_errmsg(dbPtr) : capi.sqlite3_errstr(sqliteResultCode)) ); } return arguments[0]; |
︙ | ︙ | |||
326 327 328 329 330 331 332 | functions, its read-only `pointer` property holds its `sqlite3_stmt*` pointer value. Other non-function properties include: - `db`: the DB object which created the statement. | | | > > > > > | < | 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 | functions, its read-only `pointer` property holds its `sqlite3_stmt*` pointer value. Other non-function properties include: - `db`: the DB object which created the statement. - `columnCount`: the number of result columns in the query, or 0 for queries which cannot return results. This property is a proxy for sqlite3_column_count() and its use in loops should be avoided because of the call overhead associated with that. The `columnCount` is not cached when the Stmt is created because a schema change made via a separate db connection between this statement's preparation and when it is stepped may invalidate it. - `parameterCount`: the number of bindable parameters in the query. */ const Stmt = function(){ if(BindTypes!==arguments[2]){ toss3(capi.SQLITE_MISUSE, "Do not call the Stmt constructor directly. Use DB.prepare()."); } this.db = arguments[0]; __ptrMap.set(this, arguments[1]); this.parameterCount = capi.sqlite3_bind_parameter_count(this.pointer); }; /** Throws if the given DB has been closed, else it is returned. */ const affirmDbOpen = function(db){ if(!db.pointer) toss3("DB has been closed."); return db; |
︙ | ︙ | |||
469 470 471 472 473 474 475 | /** Internal impl of the DB.selectValue(), selectArray(), and selectObject() methods. */ const __selectFirstRow = (db, sql, bind, ...getArgs)=>{ const stmt = db.prepare(sql); try { | | > > | 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 | /** Internal impl of the DB.selectValue(), selectArray(), and selectObject() methods. */ const __selectFirstRow = (db, sql, bind, ...getArgs)=>{ const stmt = db.prepare(sql); try { const rc = stmt.bind(bind).step() ? stmt.get(...getArgs) : undefined; stmt.reset(/*for INSERT...RETURNING locking case*/); return rc; }finally{ stmt.finalize(); } }; /** Internal impl of the DB.selectArrays() and selectObjects() |
︙ | ︙ | |||
494 495 496 497 498 499 500 501 502 503 504 505 506 507 | not falsy, this function throws an SQLite3Error with an error message from sqlite3_errmsg(), using db (or, if db is-a DB, db.pointer) as the db handle, or sqlite3_errstr() if db is falsy. Note that if it's passed a non-error code like SQLITE_ROW or SQLITE_DONE, it will still throw but the error string might be "Not an error." The various non-0 non-error codes need to be checked for in client code where they are expected. If it does not throw, it returns its first argument. */ DB.checkRc = (db,resultCode)=>checkSqlite3Rc(db,resultCode); DB.prototype = { /** Returns true if this db handle is open, else false. */ | > > > | 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 | not falsy, this function throws an SQLite3Error with an error message from sqlite3_errmsg(), using db (or, if db is-a DB, db.pointer) as the db handle, or sqlite3_errstr() if db is falsy. Note that if it's passed a non-error code like SQLITE_ROW or SQLITE_DONE, it will still throw but the error string might be "Not an error." The various non-0 non-error codes need to be checked for in client code where they are expected. The thrown exception's `resultCode` property will be the value of the second argument to this function. If it does not throw, it returns its first argument. */ DB.checkRc = (db,resultCode)=>checkSqlite3Rc(db,resultCode); DB.prototype = { /** Returns true if this db handle is open, else false. */ |
︙ | ︙ | |||
542 543 544 545 546 547 548 | if(this.pointer){ if(this.onclose && (this.onclose.before instanceof Function)){ try{this.onclose.before(this)} catch(e){/*ignore*/} } const pDb = this.pointer; Object.keys(__stmtMap.get(this)).forEach((k,s)=>{ | | > > > | 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 | if(this.pointer){ if(this.onclose && (this.onclose.before instanceof Function)){ try{this.onclose.before(this)} catch(e){/*ignore*/} } const pDb = this.pointer; Object.keys(__stmtMap.get(this)).forEach((k,s)=>{ if(s && s.pointer){ try{s.finalize()} catch(e){/*ignore*/} } }); __ptrMap.delete(this); __stmtMap.delete(this); capi.sqlite3_close_v2(pDb); if(this.onclose && (this.onclose.after instanceof Function)){ try{this.onclose.after(this)} catch(e){/*ignore*/} |
︙ | ︙ | |||
697 698 699 700 701 702 703 | result set are stored in this array before the callback (if any) is triggered (regardless of whether the query produces any result rows). If no statement has result columns, this value is unchanged. Achtung: an SQL result may have multiple columns with identical names. - `callback` = a function which gets called for each row of the | | | | | | | | | | | | | | | | | 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 | result set are stored in this array before the callback (if any) is triggered (regardless of whether the query produces any result rows). If no statement has result columns, this value is unchanged. Achtung: an SQL result may have multiple columns with identical names. - `callback` = a function which gets called for each row of the result set, but only if that statement has any result rows. The callback's "this" is the options object, noting that this function synthesizes one if the caller does not pass one to exec(). The second argument passed to the callback is always the current Stmt object, as it's needed if the caller wants to fetch the column names or some such (noting that they could also be fetched via `this.columnNames`, if the client provides the `columnNames` option). If the callback returns a literal `false` (as opposed to any other falsy value, e.g. an implicit `undefined` return), any ongoing statement-`step()` iteration stops without an error. The return value of the callback is otherwise ignored. ACHTUNG: The callback MUST NOT modify the Stmt object. Calling any of the Stmt.get() variants, Stmt.getColumnName(), or similar, is legal, but calling step() or finalize() is not. Member methods which are illegal in this context will trigger an exception, but clients must also refrain from using any lower-level (C-style) APIs which might modify the statement. The first argument passed to the callback defaults to an array of values from the current result row but may be changed with ... - `rowMode` = specifies the type of he callback's first argument. It may be any of... A) A string describing what type of argument should be passed as the first argument to the callback: A.1) `'array'` (the default) causes the results of `stmt.get([])` to be passed to the `callback` and/or appended to `resultRows`. A.2) `'object'` causes the results of `stmt.get(Object.create(null))` to be passed to the `callback` and/or appended to `resultRows`. Achtung: an SQL result may have multiple columns with identical names. In that case, the right-most column will be the one set in this object! A.3) `'stmt'` causes the current Stmt to be passed to the callback, but this mode will trigger an exception if `resultRows` is an array because appending the transient statement to the array would be downright unhelpful. B) An integer, indicating a zero-based column in the result row. Only that one single value will be passed on. C) A string with a minimum length of 2 and leading character of '$' will fetch the row as an object, extract that one field, and pass that field's value to the callback. Note that these |
︙ | ︙ | |||
771 772 773 774 775 776 777 | and can be used over a WebWorker-style message interface. exec() throws if `resultRows` is set and `rowMode` is 'stmt'. - `returnValue`: is a string specifying what this function should return: A) The default value is (usually) `"this"`, meaning that the | | | 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 | and can be used over a WebWorker-style message interface. exec() throws if `resultRows` is set and `rowMode` is 'stmt'. - `returnValue`: is a string specifying what this function should return: A) The default value is (usually) `"this"`, meaning that the DB object itself should be returned. The exception is if the caller passes neither of `callback` nor `returnValue` but does pass an explicit `rowMode` then the default `returnValue` is `"resultRows"`, described below. B) `"resultRows"` means to return the value of the `resultRows` option. If `resultRows` is not set, this function behaves as if it were set to an empty array. |
︙ | ︙ | |||
853 854 855 856 857 858 859 | if(saveSql) saveSql.push(capi.sqlite3_sql(pStmt).trim()); stmt = new Stmt(this, pStmt, BindTypes); if(bind && stmt.parameterCount){ stmt.bind(bind); bind = null; } if(evalFirstResult && stmt.columnCount){ | | > > > > > > > > > < < < | > | | > > > > > > > > | | > | < | 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 | if(saveSql) saveSql.push(capi.sqlite3_sql(pStmt).trim()); stmt = new Stmt(this, pStmt, BindTypes); if(bind && stmt.parameterCount){ stmt.bind(bind); bind = null; } if(evalFirstResult && stmt.columnCount){ /* Only forward SELECT-style results for the FIRST query in the SQL which potentially has them. */ let gotColNames = Array.isArray( opt.columnNames /* As reported in https://sqlite.org/forum/forumpost/7774b773937cbe0a we need to delay fetching of the column names until after the first step() (if we step() at all) because a schema change between the prepare() and step(), via another connection, may invalidate the column count and names. */) ? 0 : 1; evalFirstResult = false; if(arg.cbArg || resultRows){ for(; stmt.step(); stmt._lockedByExec = false){ if(0===gotColNames++) stmt.getColumnNames(opt.columnNames); stmt._lockedByExec = true; const row = arg.cbArg(stmt); if(resultRows) resultRows.push(row); if(callback && false === callback.call(opt, row, stmt)){ break; } } stmt._lockedByExec = false; } if(0===gotColNames){ /* opt.columnNames was provided but we visited no result rows */ stmt.getColumnNames(opt.columnNames); } }else{ stmt.step(); } stmt.reset( /* In order to trigger an exception in the INSERT...RETURNING locking scenario: https://sqlite.org/forum/forumpost/36f7a2e7494897df */).finalize(); stmt = null; }/*prepare() loop*/ }/*catch(e){ sqlite3.config.warn("DB.exec() is propagating exception",opt,e); throw e; }*/finally{ wasm.scopedAllocPop(stack); if(stmt){ delete stmt._lockedByExec; stmt.finalize(); } } return arg.returnVal(); }/*exec()*/, /** Creates a new UDF (User-Defined Function) which is accessible via SQL code. This function may be called in any of the |
︙ | ︙ | |||
1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 | If there are no result rows, an empty array is returned. */ selectValues: function(sql,bind,asType){ const stmt = this.prepare(sql), rc = []; try { stmt.bind(bind); while(stmt.step()) rc.push(stmt.get(0,asType)); }finally{ stmt.finalize(); } return rc; }, /** | > | 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 | If there are no result rows, an empty array is returned. */ selectValues: function(sql,bind,asType){ const stmt = this.prepare(sql), rc = []; try { stmt.bind(bind); while(stmt.step()) rc.push(stmt.get(0,asType)); stmt.reset(/*for INSERT...RETURNING locking case*/); }finally{ stmt.finalize(); } return rc; }, /** |
︙ | ︙ | |||
1237 1238 1239 1240 1241 1242 1243 | }, /** A convenience form of DB.checkRc(this,resultCode). If it does not throw, it returns this object. */ checkRc: function(resultCode){ | | | 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 | }, /** A convenience form of DB.checkRc(this,resultCode). If it does not throw, it returns this object. */ checkRc: function(resultCode){ return checkSqlite3Rc(this, resultCode); } }/*DB.prototype*/; /** Throws if the given Stmt has been finalized, else stmt is returned. */ const affirmStmtOpen = function(stmt){ |
︙ | ︙ | |||
1298 1299 1300 1301 1302 1303 1304 | toss3("Invalid bind() parameter name: "+key); } else if(n<1 || n>stmt.parameterCount) toss3("Bind index",key,"is out of range."); return n; }; /** | | | | | < < < | 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 | toss3("Invalid bind() parameter name: "+key); } else if(n<1 || n>stmt.parameterCount) toss3("Bind index",key,"is out of range."); return n; }; /** If stmt._lockedByExec is truthy, this throws an exception complaining that the 2nd argument (an operation name, e.g. "bind()") is not legal while the statement is "locked". Locking happens before an exec()-like callback is passed a statement, to ensure that the callback does not mutate or finalize the statement. If it does not throw, it returns stmt. */ const affirmNotLockedByExec = function(stmt,currentOpName){ if(stmt._lockedByExec){ toss3("Operation is illegal when statement is locked:",currentOpName); } return stmt; }; /** Binds a single bound parameter value on the given stmt at the given index (numeric or named) using the given bindType (see the BindTypes enum) and value. Throws on error. Returns stmt on success. */ const bindOne = function f(stmt,ndx,bindType,val){ affirmNotLockedByExec(affirmStmtOpen(stmt), 'bind()'); if(!f._){ f._tooBigInt = (v)=>toss3( "BigInt value is too big to store without precision loss:", v ); f._ = { string: function(stmt, ndx, val, asBlob){ const [pStr, n] = wasm.allocCString(val, true); const f = asBlob ? capi.sqlite3_bind_blob : capi.sqlite3_bind_text; return f(stmt.pointer, ndx, pStr, n, capi.SQLITE_WASM_DEALLOC); } }; |
︙ | ︙ | |||
1400 1401 1402 1403 1404 1405 1406 | if(rc) DB.checkRc(stmt.db.pointer, rc); stmt._mayGet = false; return stmt; }; Stmt.prototype = { /** | | > > | > | | > > > | > < < | | > > | | > > > | | | | > > > > > > > > > > | | > | 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 | if(rc) DB.checkRc(stmt.db.pointer, rc); stmt._mayGet = false; return stmt; }; Stmt.prototype = { /** "Finalizes" this statement. This is a no-op if the statement has already been finalized. Returns the result of sqlite3_finalize() (0 on success, non-0 on error), or the undefined value if the statement has already been finalized. Regardless of success or failure, most methods in this class will throw if called after this is. This method always throws if called when it is illegal to do so. Namely, when triggered via a per-row callback handler of a DB.exec() call. */ finalize: function(){ if(this.pointer){ affirmNotLockedByExec(this,'finalize()'); const rc = capi.sqlite3_finalize(this.pointer); delete __stmtMap.get(this.db)[this.pointer]; __ptrMap.delete(this); delete this._mayGet; delete this.parameterCount; delete this._lockedByExec; delete this.db; return rc; } }, /** Clears all bound values. Returns this object. Throws if this statement has been finalized or if modification of the statement is currently illegal (e.g. in the per-row callback of a DB.exec() call). */ clearBindings: function(){ affirmNotLockedByExec(affirmStmtOpen(this), 'clearBindings()') capi.sqlite3_clear_bindings(this.pointer); this._mayGet = false; return this; }, /** Resets this statement so that it may be step()ed again from the beginning. Returns this object. Throws if this statement has been finalized, if it may not legally be reset because it is currently being used from a DB.exec() callback, or if the underlying call to sqlite3_reset() returns non-0. If passed a truthy argument then this.clearBindings() is also called, otherwise any existing bindings, along with any memory allocated for them, are retained. In verions 3.42.0 and earlier, this function did not throw if sqlite3_reset() returns non-0, but it was discovered that throwing (or significant extra client-side code) is necessary in order to avoid certain silent failure scenarios, as discussed at: https://sqlite.org/forum/forumpost/36f7a2e7494897df */ reset: function(alsoClearBinds){ affirmNotLockedByExec(this,'reset()'); if(alsoClearBinds) this.clearBindings(); const rc = capi.sqlite3_reset(affirmStmtOpen(this).pointer); this._mayGet = false; checkSqlite3Rc(this.db, rc); return this; }, /** Binds one or more values to its bindable parameters. It accepts 1 or 2 arguments: If passed a single argument, it must be either an array, an |
︙ | ︙ | |||
1588 1589 1590 1591 1592 1593 1594 | /** Steps the statement one time. If the result indicates that a row of data is available, a truthy value is returned. If no row of data is available, a falsy value is returned. Throws on error. */ step: function(){ | | | 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 | /** Steps the statement one time. If the result indicates that a row of data is available, a truthy value is returned. If no row of data is available, a falsy value is returned. Throws on error. */ step: function(){ affirmNotLockedByExec(this, 'step()'); const rc = capi.sqlite3_step(affirmStmtOpen(this).pointer); switch(rc){ case capi.SQLITE_DONE: return this._mayGet = false; case capi.SQLITE_ROW: return this._mayGet = true; default: this._mayGet = false; sqlite3.config.warn("sqlite3_step() rc=",rc, |
︙ | ︙ | |||
1623 1624 1625 1626 1627 1628 1629 | after the step. */ stepReset: function(){ this.step(); return this.reset(); }, /** | | | | < < > | | | > > > > | 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 | after the step. */ stepReset: function(){ this.step(); return this.reset(); }, /** Functions like step() except that it calls finalize() on this statement immediately after stepping, even if the step() call throws. On success, it returns true if the step indicated that a row of data was available, else it returns false. This is intended to simplify use cases such as: ``` aDb.prepare("insert into foo(a) values(?)").bind(123).stepFinalize(); ``` */ stepFinalize: function(){ try{ const rc = this.step(); this.reset(/*for INSERT...RETURNING locking case*/); return rc; }finally{ try{this.finalize()} catch(e){/*ignored*/} } }, /** Fetches the value from the given 0-based column index of the current data row, throwing if index is out of range. Requires that step() has just returned a truthy value, else an exception is thrown. |
︙ | ︙ | |||
1682 1683 1684 1685 1686 1687 1688 | */ get: function(ndx,asType){ if(!affirmStmtOpen(this)._mayGet){ toss3("Stmt.step() has not (recently) returned true."); } if(Array.isArray(ndx)){ let i = 0; | > | > | | 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 | */ get: function(ndx,asType){ if(!affirmStmtOpen(this)._mayGet){ toss3("Stmt.step() has not (recently) returned true."); } if(Array.isArray(ndx)){ let i = 0; const n = this.columnCount; while(i<n){ ndx[i] = this.get(i++); } return ndx; }else if(ndx && 'object'===typeof ndx){ let i = 0; const n = this.columnCount; while(i<n){ ndx[capi.sqlite3_column_name(this.pointer,i)] = this.get(i++); } return ndx; } affirmColIndex(this, ndx); switch(undefined===asType ? capi.sqlite3_column_type(this.pointer, ndx) |
︙ | ︙ | |||
1786 1787 1788 1789 1790 1791 1792 | */ getColumnName: function(ndx){ return capi.sqlite3_column_name( affirmColIndex(affirmStmtOpen(this),ndx).pointer, ndx ); }, /** | | | | | | | > | | 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 | */ getColumnName: function(ndx){ return capi.sqlite3_column_name( affirmColIndex(affirmStmtOpen(this),ndx).pointer, ndx ); }, /** If this statement potentially has result columns, this function returns an array of all such names. If passed an array, it is used as the target and all names are appended to it. Returns the target array. Throws if this statement cannot have result columns. This object's columnCount property holds the number of columns. */ getColumnNames: function(tgt=[]){ affirmColIndex(affirmStmtOpen(this),0); const n = this.columnCount; for(let i = 0; i < n; ++i){ tgt.push(capi.sqlite3_column_name(this.pointer, i)); } return tgt; }, /** If this statement has named bindable parameters and the given name matches one, its 1-based bind index is |
︙ | ︙ | |||
1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 | enumerable: true, get: function(){return __ptrMap.get(this)}, set: ()=>toss3("The pointer property is read-only.") } Object.defineProperty(Stmt.prototype, 'pointer', prop); Object.defineProperty(DB.prototype, 'pointer', prop); } /** The OO API's public namespace. */ sqlite3.oo1 = { DB, Stmt }/*oo1 object*/; | > > > > > > > > > > > > > > | 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 | enumerable: true, get: function(){return __ptrMap.get(this)}, set: ()=>toss3("The pointer property is read-only.") } Object.defineProperty(Stmt.prototype, 'pointer', prop); Object.defineProperty(DB.prototype, 'pointer', prop); } /** Stmt.columnCount is an interceptor for sqlite3_column_count(). This requires an unfortunate performance hit compared to caching columnCount when the Stmt is created/prepared (as was done in SQLite <=3.42.0), but is necessary in order to handle certain corner cases, as described in https://sqlite.org/forum/forumpost/7774b773937cbe0a. */ Object.defineProperty(Stmt.prototype, 'columnCount', { enumerable: false, get: function(){return capi.sqlite3_column_count(this.pointer)}, set: ()=>toss3("The columnCount property is read-only.") }); /** The OO API's public namespace. */ sqlite3.oo1 = { DB, Stmt }/*oo1 object*/; |
︙ | ︙ |
Changes to ext/wasm/common/SqliteTestUtil.js.
︙ | ︙ | |||
152 153 154 155 156 157 158 | if( ! m ) continue; args[decodeURIComponent(m[1])] = (m[3] ? decodeURIComponent(m[3]) : true); } return args; } }; | < | 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | if( ! m ) continue; args[decodeURIComponent(m[1])] = (m[3] ? decodeURIComponent(m[3]) : true); } return args; } }; /** This is a module object for use with the emscripten-installed sqlite3InitModule() factory function. */ self.sqlite3TestModule = { /** Array of functions to call after Emscripten has initialized the |
︙ | ︙ |
Changes to ext/wasm/common/whwasmutil.js.
︙ | ︙ | |||
170 171 172 173 174 175 176 | More specifically: https://fossil.wanderinghorse.net/r/jaccwabbyt/file/common/whwasmutil.js */ globalThis.WhWasmUtilInstaller = function(target){ 'use strict'; if(undefined===target.bigIntEnabled){ | | | 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | More specifically: https://fossil.wanderinghorse.net/r/jaccwabbyt/file/common/whwasmutil.js */ globalThis.WhWasmUtilInstaller = function(target){ 'use strict'; if(undefined===target.bigIntEnabled){ target.bigIntEnabled = !!globalThis['BigInt64Array']; } /** Throws a new Error, the message of which is the concatenation of all args with a space between each. */ const toss = (...args)=>{throw new Error(args.join(' '))}; if(!target.exports){ |
︙ | ︙ | |||
351 352 353 354 355 356 357 | case 16: return unsigned ? c.HEAP16U : c.HEAP16; case 32: return unsigned ? c.HEAP32U : c.HEAP32; case 64: if(c.HEAP64) return unsigned ? c.HEAP64U : c.HEAP64; break; default: if(target.bigIntEnabled){ | | | | 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 | case 16: return unsigned ? c.HEAP16U : c.HEAP16; case 32: return unsigned ? c.HEAP32U : c.HEAP32; case 64: if(c.HEAP64) return unsigned ? c.HEAP64U : c.HEAP64; break; default: if(target.bigIntEnabled){ if(n===globalThis['BigUint64Array']) return c.HEAP64U; else if(n===globalThis['BigInt64Array']) return c.HEAP64; break; } } toss("Invalid heapForSize() size: expecting 8, 16, 32,", "or (if BigInt is enabled) 64."); }; |
︙ | ︙ |
Changes to ext/wasm/jaccwabyt/jaccwabyt.js.
︙ | ︙ | |||
56 57 58 59 60 61 62 | ? config.heap : (()=>new Uint8Array(config.heap.buffer)), alloc = config.alloc, dealloc = config.dealloc, log = config.log || console.log.bind(console), memberPrefix = (config.memberPrefix || ""), memberSuffix = (config.memberSuffix || ""), bigIntEnabled = (undefined===config.bigIntEnabled | | | | | 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | ? config.heap : (()=>new Uint8Array(config.heap.buffer)), alloc = config.alloc, dealloc = config.dealloc, log = config.log || console.log.bind(console), memberPrefix = (config.memberPrefix || ""), memberSuffix = (config.memberSuffix || ""), bigIntEnabled = (undefined===config.bigIntEnabled ? !!globalThis['BigInt64Array'] : !!config.bigIntEnabled), BigInt = globalThis['BigInt'], BigInt64Array = globalThis['BigInt64Array'], /* Undocumented (on purpose) config options: */ ptrSizeof = config.ptrSizeof || 4, ptrIR = config.ptrIR || 'i32' ; if(!SBF.debugFlags){ SBF.__makeDebugFlags = function(deriveFrom=null){ |
︙ | ︙ |
Changes to ext/wasm/tester1-worker.html.
︙ | ︙ | |||
41 42 43 44 45 46 47 | cbReverse.addEventListener('change',cbReverseIt,true); cbReverseIt(); const urlParams = new URL(self.location.href).searchParams; const workerArgs = []; if(urlParams.has('esm')){ logHtml('warning',"Attempting to run an ES6 Worker Module, "+ "which is not supported by all browsers! "+ | | | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | cbReverse.addEventListener('change',cbReverseIt,true); cbReverseIt(); const urlParams = new URL(self.location.href).searchParams; const workerArgs = []; if(urlParams.has('esm')){ logHtml('warning',"Attempting to run an ES6 Worker Module, "+ "which is not supported by all browsers! "+ "e.g. Firefox (as of 2023-05) cannot do this."); workerArgs.push("tester1.mjs",{type:"module"}); document.querySelectorAll('title,#color-target').forEach((e)=>{ e.innerText = "sqlite3 tester #1: ES6 Worker Module"; }); }else{ workerArgs.push("tester1.js?sqlite3.dir=jswasm"); } |
︙ | ︙ |
Changes to ext/wasm/tester1.c-pp.js.
︙ | ︙ | |||
1162 1163 1164 1165 1166 1167 1168 | .assert(dbFile === db.dbFilename()) .assert(!db.dbFilename('nope')); //Sanity check DB.checkRc()... let ex; try{db.checkRc(rc)} catch(e){ex = e} T.assert(ex instanceof sqlite3.SQLite3Error) | > | | 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 | .assert(dbFile === db.dbFilename()) .assert(!db.dbFilename('nope')); //Sanity check DB.checkRc()... let ex; try{db.checkRc(rc)} catch(e){ex = e} T.assert(ex instanceof sqlite3.SQLite3Error) .assert(capi.SQLITE_MISUSE===ex.resultCode) .assert(0===ex.message.indexOf("SQLITE_MISUSE: sqlite3 result code")) .assert(ex.message.indexOf("Invalid SQL")>0); T.assert(db === db.checkRc(0)) .assert(db === sqlite3.oo1.DB.checkRc(db,0)) .assert(null === sqlite3.oo1.DB.checkRc(null,0)); this.progressHandlerCount = 0; capi.sqlite3_progress_handler(db, 5, (p)=>{ |
︙ | ︙ | |||
1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 | //////////////////////////////////////////////////////////////////// .t('DB.Stmt', function(sqlite3){ let st = this.db.prepare( new TextEncoder('utf-8').encode("select 3 as a") ); //debug("statement =",st); this.progressHandlerCount = 0; try { T.assert(wasm.isPtr(st.pointer)) .mustThrowMatching(()=>st.pointer=1, /read-only/) .assert(1===this.db.openStatementCount()) .assert( capi.sqlite3_stmt_status( st, capi.SQLITE_STMTSTATUS_RUN, 0 ) === 0) .assert(!st._mayGet) .assert('a' === st.getColumnName(0)) .assert(1===st.columnCount) .assert(0===st.parameterCount) .mustThrow(()=>st.bind(1,null)) .assert(true===st.step()) .assert(3 === st.get(0)) .mustThrow(()=>st.get(1)) .mustThrow(()=>st.get(0,~capi.SQLITE_INTEGER)) | > > > | 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 | //////////////////////////////////////////////////////////////////// .t('DB.Stmt', function(sqlite3){ let st = this.db.prepare( new TextEncoder('utf-8').encode("select 3 as a") ); //debug("statement =",st); this.progressHandlerCount = 0; let rc; try { T.assert(wasm.isPtr(st.pointer)) .mustThrowMatching(()=>st.pointer=1, /read-only/) .assert(1===this.db.openStatementCount()) .assert( capi.sqlite3_stmt_status( st, capi.SQLITE_STMTSTATUS_RUN, 0 ) === 0) .assert(!st._mayGet) .assert('a' === st.getColumnName(0)) .mustThrowMatching(()=>st.columnCount=2, /columnCount property is read-only/) .assert(1===st.columnCount) .assert(0===st.parameterCount) .mustThrow(()=>st.bind(1,null)) .assert(true===st.step()) .assert(3 === st.get(0)) .mustThrow(()=>st.get(1)) .mustThrow(()=>st.get(0,~capi.SQLITE_INTEGER)) |
︙ | ︙ | |||
1260 1261 1262 1263 1264 1265 1266 | T.assert(this.progressHandlerCount > 0, "Expecting progress callback."). assert(0===capi.sqlite3_strglob("*.txt", "foo.txt")). assert(0!==capi.sqlite3_strglob("*.txt", "foo.xtx")). assert(0===capi.sqlite3_strlike("%.txt", "foo.txt", 0)). assert(0!==capi.sqlite3_strlike("%.txt", "foo.xtx", 0)); }finally{ | | | > | 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 | T.assert(this.progressHandlerCount > 0, "Expecting progress callback."). assert(0===capi.sqlite3_strglob("*.txt", "foo.txt")). assert(0!==capi.sqlite3_strglob("*.txt", "foo.xtx")). assert(0===capi.sqlite3_strlike("%.txt", "foo.txt", 0)). assert(0!==capi.sqlite3_strlike("%.txt", "foo.xtx", 0)); }finally{ rc = st.finalize(); } T.assert(!st.pointer) .assert(0===this.db.openStatementCount()) .assert(0===rc); T.mustThrowMatching(()=>new sqlite3.oo1.Stmt("hi"), function(err){ return (err instanceof sqlite3.SQLite3Error) && capi.SQLITE_MISUSE === err.resultCode && 0 < err.message.indexOf("Do not call the Stmt constructor directly.") }); }) |
︙ | ︙ | |||
1328 1329 1330 1331 1332 1333 1334 | const db = this.db; let list = []; this.progressHandlerCount = 0; let rc = db.exec({ sql:['CREATE TABLE t(a,b);', // ^^^ using TEMP TABLE breaks the db export test "INSERT INTO t(a,b) VALUES(1,2),(3,4),", | | | | | > > > > > > > > | 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 | const db = this.db; let list = []; this.progressHandlerCount = 0; let rc = db.exec({ sql:['CREATE TABLE t(a,b);', // ^^^ using TEMP TABLE breaks the db export test "INSERT INTO t(a,b) VALUES(1,2),(3,4),", "(?,?)"/*intentionally missing semicolon to test for off-by-one bug in string-to-WASM conversion*/], saveSql: list, bind: [5,6] }); //debug("Exec'd SQL:", list); T.assert(rc === db) .assert(2 === list.length) .assert('string'===typeof list[1]) .assert(3===db.changes()) .assert(this.progressHandlerCount > 0, "Expecting progress callback.") if(wasm.bigIntEnabled){ T.assert(3n===db.changes(false,true)); } rc = db.exec({ sql: "INSERT INTO t(a,b) values('blob',X'6869') RETURNING 13", rowMode: 0 }); T.assert(Array.isArray(rc)) .assert(1===rc.length) .assert(13 === rc[0]) .assert(1===db.changes()); let vals = db.selectValues('select a from t order by a limit 2'); T.assert( 2 === vals.length ) .assert( 1===vals[0] && 3===vals[1] ); vals = db.selectValues('select a from t order by a limit $L', {$L:2}, capi.SQLITE_TEXT); T.assert( 2 === vals.length ) |
︙ | ︙ | |||
1369 1370 1371 1372 1373 1374 1375 1376 1377 | columnNames: colNames, _myState: 3 /* Accessible from the callback */, callback: function(row,stmt){ ++counter; T.assert( 3 === this._myState /* Recall that "this" is the options object. */ ).assert( this.columnNames[0]==='a' && this.columnNames[1]==='b' | > > < < > > > > > > > > | 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 | columnNames: colNames, _myState: 3 /* Accessible from the callback */, callback: function(row,stmt){ ++counter; T.assert( 3 === this._myState /* Recall that "this" is the options object. */ ).assert( this.columnNames===colNames ).assert( this.columnNames[0]==='a' && this.columnNames[1]==='b' ).assert( (row.a%2 && row.a<6) || 'blob'===row.a ); } }); T.assert(2 === colNames.length) .assert('a' === colNames[0]) .assert(4 === counter) .assert(4 === list.length); colNames = []; db.exec({ /* Ensure that columnNames is populated for empty result sets. */ sql: "SELECT a a, b B FROM t WHERE 0", columnNames: colNames }); T.assert(2===colNames.length) .assert('a'===colNames[0] && 'B'===colNames[1]); list.length = 0; db.exec("SELECT a a, b b FROM t",{ rowMode: 'array', callback: function(row,stmt){ ++counter; T.assert(Array.isArray(row)) .assert((0===row[1]%2 && row[1]<7) |
︙ | ︙ | |||
1434 1435 1436 1437 1438 1439 1440 1441 1442 | https://github.com/emscripten-core/emscripten/issues/17391 */ T.mustThrow(()=>db.selectValue("SELECT "+(Number.MAX_SAFE_INTEGER+1))). mustThrow(()=>db.selectValue("SELECT "+(Number.MIN_SAFE_INTEGER-1))); } let st = db.prepare("update t set b=:b where a='blob'"); try { const ndx = st.getParamIndex(':b'); T.assert(1===ndx); | > | > | > | 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 | https://github.com/emscripten-core/emscripten/issues/17391 */ T.mustThrow(()=>db.selectValue("SELECT "+(Number.MAX_SAFE_INTEGER+1))). mustThrow(()=>db.selectValue("SELECT "+(Number.MIN_SAFE_INTEGER-1))); } let st = db.prepare("update t set b=:b where a='blob'"); try { T.assert(0===st.columnCount); const ndx = st.getParamIndex(':b'); T.assert(1===ndx); st.bindAsBlob(ndx, "ima blob") /*step() skipped intentionally*/.reset(true); } finally { T.assert(0===st.finalize()) .assert(undefined===st.finalize()); } try { db.prepare("/*empty SQL*/"); toss("Must not be reached."); }catch(e){ T.assert(e instanceof sqlite3.SQLite3Error) |
︙ | ︙ | |||
1600 1601 1602 1603 1604 1605 1606 | .assert(2===rc.length) .assert('object' === typeof rc[1]) .assert(1===rc[0].a) .assert(2===rc[0].b) .assert(3===rc[1].a) .assert(4===rc[1].b); }) | | > > > > > > > > > > > > | 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 | .assert(2===rc.length) .assert('object' === typeof rc[1]) .assert(1===rc[0].a) .assert(2===rc[0].b) .assert(3===rc[1].a) .assert(4===rc[1].b); }) //////////////////////////////////////////////////////////////////////// .t('selectArray/Object/Values() via INSERT/UPDATE...RETURNING', function(sqlite3){ let rc = this.db.selectObject("INSERT INTO t(a,b) VALUES(83,84) RETURNING a as AA"); T.assert(83===rc.AA); rc = this.db.selectArray("UPDATE T set a=85 WHERE a=83 RETURNING b as BB"); T.assert(Array.isArray(rc)).assert(84===rc[0]); //log("select * from t:",this.db.selectObjects("select * from t order by a")); rc = this.db.selectValues("UPDATE T set a=a*1 RETURNING a"); T.assert(Array.isArray(rc)) .assert(5 === rc.length) .assert('number'===typeof rc[0]) .assert(rc[0]|0 === rc[0] /* is small integer */); }) //////////////////////////////////////////////////////////////////////// .t({ name: 'sqlite3_js_db_export()', predicate: ()=>true, test: function(sqlite3){ const db = this.db; const xp = capi.sqlite3_js_db_export(db.pointer); |
︙ | ︙ |
Changes to src/analyze.c.
︙ | ︙ | |||
1845 1846 1847 1848 1849 1850 1851 | pPrevIdx = pIdx; } pSample = &pIdx->aSample[pIdx->nSample]; decodeIntArray((char*)sqlite3_column_text(pStmt,1),nCol,pSample->anEq,0,0); decodeIntArray((char*)sqlite3_column_text(pStmt,2),nCol,pSample->anLt,0,0); decodeIntArray((char*)sqlite3_column_text(pStmt,3),nCol,pSample->anDLt,0,0); | | > | | | 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 | pPrevIdx = pIdx; } pSample = &pIdx->aSample[pIdx->nSample]; decodeIntArray((char*)sqlite3_column_text(pStmt,1),nCol,pSample->anEq,0,0); decodeIntArray((char*)sqlite3_column_text(pStmt,2),nCol,pSample->anLt,0,0); decodeIntArray((char*)sqlite3_column_text(pStmt,3),nCol,pSample->anDLt,0,0); /* Take a copy of the sample. Add 8 extra 0x00 bytes the end of the buffer. ** This is in case the sample record is corrupted. In that case, the ** sqlite3VdbeRecordCompare() may read up to two varints past the ** end of the allocated buffer before it realizes it is dealing with ** a corrupt record. Or it might try to read a large integer from the ** buffer. In any case, eight 0x00 bytes prevents this from causing ** a buffer overread. */ pSample->n = sqlite3_column_bytes(pStmt, 4); pSample->p = sqlite3DbMallocZero(db, pSample->n + 8); if( pSample->p==0 ){ sqlite3_finalize(pStmt); return SQLITE_NOMEM_BKPT; } if( pSample->n ){ memcpy(pSample->p, sqlite3_column_blob(pStmt, 4), pSample->n); } |
︙ | ︙ |
Changes to src/btree.c.
︙ | ︙ | |||
1630 1631 1632 1633 1634 1635 1636 | } cbrk = usableSize; iCellLast = usableSize - 4; iCellStart = get2byte(&data[hdr+5]); if( nCell>0 ){ temp = sqlite3PagerTempSpace(pPage->pBt->pPager); | | | 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 | } cbrk = usableSize; iCellLast = usableSize - 4; iCellStart = get2byte(&data[hdr+5]); if( nCell>0 ){ temp = sqlite3PagerTempSpace(pPage->pBt->pPager); memcpy(temp, data, usableSize); src = temp; for(i=0; i<nCell; i++){ u8 *pAddr; /* The i-th cell pointer */ pAddr = &data[cellOffset + i*2]; pc = get2byte(pAddr); testcase( pc==iCellFirst ); testcase( pc==iCellLast ); |
︙ | ︙ | |||
3334 3335 3336 3337 3338 3339 3340 | ** between 512 and 65536 inclusive. */ if( ((pageSize-1)&pageSize)!=0 || pageSize>SQLITE_MAX_PAGE_SIZE || pageSize<=256 ){ goto page1_init_failed; } | < > > | 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 | ** between 512 and 65536 inclusive. */ if( ((pageSize-1)&pageSize)!=0 || pageSize>SQLITE_MAX_PAGE_SIZE || pageSize<=256 ){ goto page1_init_failed; } assert( (pageSize & 7)==0 ); /* EVIDENCE-OF: R-59310-51205 The "reserved space" size in the 1-byte ** integer at offset 20 is the number of bytes of space at the end of ** each page to reserve for extensions. ** ** EVIDENCE-OF: R-37497-42412 The size of the reserved region is ** determined by the one-byte unsigned integer found at an offset of 20 ** into the database file header. */ usableSize = pageSize - page1[20]; if( (u32)pageSize!=pBt->pageSize ){ /* After reading the first page of the database assuming a page size ** of BtShared.pageSize, we have discovered that the page-size is ** actually pageSize. Unlock the database, leave pBt->pPage1 at ** zero and return SQLITE_OK. The caller will call this function ** again with the correct page-size. */ releasePageOne(pPage1); pBt->usableSize = usableSize; pBt->pageSize = pageSize; pBt->btsFlags |= BTS_PAGESIZE_FIXED; freeTempSpace(pBt); rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, pageSize-usableSize); return rc; } if( nPage>nPageFile ){ if( sqlite3WritableSchema(pBt->db)==0 ){ rc = SQLITE_CORRUPT_BKPT; goto page1_init_failed; }else{ nPage = nPageFile; } } /* EVIDENCE-OF: R-28312-64704 However, the usable size is not allowed to ** be less than 480. In other words, if the page size is 512, then the ** reserved space size cannot exceed 32. */ if( usableSize<480 ){ goto page1_init_failed; } pBt->btsFlags |= BTS_PAGESIZE_FIXED; pBt->pageSize = pageSize; pBt->usableSize = usableSize; #ifndef SQLITE_OMIT_AUTOVACUUM pBt->autoVacuum = (get4byte(&page1[36 + 4*4])?1:0); pBt->incrVacuum = (get4byte(&page1[36 + 7*4])?1:0); #endif } |
︙ | ︙ | |||
10658 10659 10660 10661 10662 10663 10664 | checkProgress(pCheck); if( pCheck->mxErr==0 ) goto end_of_check; pBt = pCheck->pBt; usableSize = pBt->usableSize; if( iPage==0 ) return 0; if( checkRef(pCheck, iPage) ) return 0; pCheck->zPfx = "Tree %u page %u: "; | | | 10659 10660 10661 10662 10663 10664 10665 10666 10667 10668 10669 10670 10671 10672 10673 | checkProgress(pCheck); if( pCheck->mxErr==0 ) goto end_of_check; pBt = pCheck->pBt; usableSize = pBt->usableSize; if( iPage==0 ) return 0; if( checkRef(pCheck, iPage) ) return 0; pCheck->zPfx = "Tree %u page %u: "; pCheck->v1 = iPage; if( (rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0 ){ checkAppendMsg(pCheck, "unable to get the page. error code=%d", rc); goto end_of_check; } /* Clear MemPage.isInit to make sure the corruption detection code in |
︙ | ︙ | |||
10995 10996 10997 10998 10999 11000 11001 11002 11003 11004 11005 11006 11007 11008 | i64 notUsed; if( aRoot[i]==0 ) continue; #ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->autoVacuum && aRoot[i]>1 && !bPartial ){ checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0); } #endif checkTreePage(&sCheck, aRoot[i], ¬Used, LARGEST_INT64); } pBt->db->flags = savedDbFlags; /* Make sure every page in the file is referenced */ if( !bPartial ){ | > | 10996 10997 10998 10999 11000 11001 11002 11003 11004 11005 11006 11007 11008 11009 11010 | i64 notUsed; if( aRoot[i]==0 ) continue; #ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->autoVacuum && aRoot[i]>1 && !bPartial ){ checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0); } #endif sCheck.v0 = aRoot[i]; checkTreePage(&sCheck, aRoot[i], ¬Used, LARGEST_INT64); } pBt->db->flags = savedDbFlags; /* Make sure every page in the file is referenced */ if( !bPartial ){ |
︙ | ︙ |
Changes to src/delete.c.
︙ | ︙ | |||
31 32 33 34 35 36 37 38 39 40 41 42 43 44 | Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){ SrcItem *pItem = pSrc->a; Table *pTab; assert( pItem && pSrc->nSrc>=1 ); pTab = sqlite3LocateTableItem(pParse, 0, pItem); sqlite3DeleteTable(pParse->db, pItem->pTab); pItem->pTab = pTab; if( pTab ){ pTab->nTabRef++; if( pItem->fg.isIndexedBy && sqlite3IndexedByLookup(pParse, pItem) ){ pTab = 0; } } return pTab; | > | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){ SrcItem *pItem = pSrc->a; Table *pTab; assert( pItem && pSrc->nSrc>=1 ); pTab = sqlite3LocateTableItem(pParse, 0, pItem); sqlite3DeleteTable(pParse->db, pItem->pTab); pItem->pTab = pTab; pItem->fg.notCte = 1; if( pTab ){ pTab->nTabRef++; if( pItem->fg.isIndexedBy && sqlite3IndexedByLookup(pParse, pItem) ){ pTab = 0; } } return pTab; |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
2187 2188 2189 2190 2191 2192 2193 | } /* ** The argument must be a TK_TRUEFALSE Expr node. Return 1 if it is TRUE ** and 0 if it is FALSE. */ int sqlite3ExprTruthValue(const Expr *pExpr){ | | | 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 | } /* ** The argument must be a TK_TRUEFALSE Expr node. Return 1 if it is TRUE ** and 0 if it is FALSE. */ int sqlite3ExprTruthValue(const Expr *pExpr){ pExpr = sqlite3ExprSkipCollateAndLikely((Expr*)pExpr); assert( pExpr->op==TK_TRUEFALSE ); assert( !ExprHasProperty(pExpr, EP_IntValue) ); assert( sqlite3StrICmp(pExpr->u.zToken,"true")==0 || sqlite3StrICmp(pExpr->u.zToken,"false")==0 ); return pExpr->u.zToken[4]==0; } |
︙ | ︙ | |||
6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 | ){ struct AggInfo_col *pCol; int k; assert( pAggInfo->iFirstReg==0 ); pCol = pAggInfo->aCol; for(k=0; k<pAggInfo->nColumn; k++, pCol++){ if( pCol->iTable==pExpr->iTable && pCol->iColumn==pExpr->iColumn && pExpr->op!=TK_IF_NULL_ROW ){ goto fix_up_expr; } } | > | 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 | ){ struct AggInfo_col *pCol; int k; assert( pAggInfo->iFirstReg==0 ); pCol = pAggInfo->aCol; for(k=0; k<pAggInfo->nColumn; k++, pCol++){ if( pCol->pCExpr==pExpr ) return; if( pCol->iTable==pExpr->iTable && pCol->iColumn==pExpr->iColumn && pExpr->op!=TK_IF_NULL_ROW ){ goto fix_up_expr; } } |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
6530 6531 6532 6533 6534 6535 6536 | pAggInfo = pExpr->pAggInfo; if( NEVER(pExpr->iAgg>=pAggInfo->nColumn) ) return WRC_Continue; assert( pExpr->iAgg>=0 ); pCol = &pAggInfo->aCol[pExpr->iAgg]; pExpr->op = TK_AGG_COLUMN; pExpr->iTable = pCol->iTable; pExpr->iColumn = pCol->iColumn; | | | 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 | pAggInfo = pExpr->pAggInfo; if( NEVER(pExpr->iAgg>=pAggInfo->nColumn) ) return WRC_Continue; assert( pExpr->iAgg>=0 ); pCol = &pAggInfo->aCol[pExpr->iAgg]; pExpr->op = TK_AGG_COLUMN; pExpr->iTable = pCol->iTable; pExpr->iColumn = pCol->iColumn; ExprClearProperty(pExpr, EP_Skip|EP_Collate|EP_Unlikely); return WRC_Prune; } /* ** Convert every pAggInfo->aFunc[].pExpr such that any node within ** those expressions that has pAppInfo set is changed into a TK_AGG_COLUMN ** opcode. |
︙ | ︙ |
Changes to src/shell.c.in.
︙ | ︙ | |||
10526 10527 10528 10529 10530 10531 10532 | "ORDER BY 1 collate nocase"; zRevText = sqlite3_mprintf(zRevText, zLike? " AND name LIKE $tspec" : ""); zRevText = sqlite3_mprintf( /* lower-case query is first run, producing upper-case query. */ "with tabcols as materialized(\n" "select tname, cname\n" "from (" | > | | 10526 10527 10528 10529 10530 10531 10532 10533 10534 10535 10536 10537 10538 10539 10540 10541 | "ORDER BY 1 collate nocase"; zRevText = sqlite3_mprintf(zRevText, zLike? " AND name LIKE $tspec" : ""); zRevText = sqlite3_mprintf( /* lower-case query is first run, producing upper-case query. */ "with tabcols as materialized(\n" "select tname, cname\n" "from (" " select printf('\"%%w\"',ss.tname) as tname," " printf('\"%%w\"',ti.name) as cname\n" " from (%z) ss\n inner join pragma_table_info(tname) ti))\n" "select 'SELECT total(bad_text_count) AS bad_text_count\n" "FROM ('||group_concat(query, ' UNION ALL ')||')' as btc_query\n" " from (select 'SELECT COUNT(*) AS bad_text_count\n" "FROM '||tname||' WHERE '\n" "||group_concat('CAST(CAST('||cname||' AS BLOB) AS TEXT)<>'||cname\n" "|| ' AND typeof('||cname||')=''text'' ',\n" |
︙ | ︙ | |||
12173 12174 12175 12176 12177 12178 12179 | void *pOutArg, int makeDefault ); vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1); #endif #ifdef SQLITE_ENABLE_MULTIPLEX }else if( cli_strcmp(z,"-multiplex")==0 ){ | | | 12174 12175 12176 12177 12178 12179 12180 12181 12182 12183 12184 12185 12186 12187 12188 | void *pOutArg, int makeDefault ); vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1); #endif #ifdef SQLITE_ENABLE_MULTIPLEX }else if( cli_strcmp(z,"-multiplex")==0 ){ extern int sqlite3_multiplex_initialize(const char*,int); sqlite3_multiplex_initialize(0, 1); #endif }else if( cli_strcmp(z,"-mmap")==0 ){ sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i)); verify_uninitialized(); sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz); #if defined(SQLITE_ENABLE_SORTER_REFERENCES) |
︙ | ︙ | |||
12216 12217 12218 12219 12220 12221 12222 | #endif }else if( cli_strcmp(z, "-memtrace")==0 ){ sqlite3MemTraceActivate(stderr); }else if( cli_strcmp(z,"-bail")==0 ){ bail_on_error = 1; }else if( cli_strcmp(z,"-nonce")==0 ){ free(data.zNonce); | | | 12217 12218 12219 12220 12221 12222 12223 12224 12225 12226 12227 12228 12229 12230 12231 | #endif }else if( cli_strcmp(z, "-memtrace")==0 ){ sqlite3MemTraceActivate(stderr); }else if( cli_strcmp(z,"-bail")==0 ){ bail_on_error = 1; }else if( cli_strcmp(z,"-nonce")==0 ){ free(data.zNonce); data.zNonce = strdup(cmdline_option_value(argc, argv, ++i)); }else if( cli_strcmp(z,"-unsafe-testing")==0 ){ ShellSetFlag(&data,SHFLG_TestingMode); }else if( cli_strcmp(z,"-safe")==0 ){ /* no-op - catch this on the second pass */ } } #ifndef SQLITE_SHELL_FIDDLE |
︙ | ︙ |
Changes to src/treeview.c.
︙ | ︙ | |||
639 640 641 642 643 644 645 | case TK_TRUTH: { int x; const char *azOp[] = { "IS-FALSE", "IS-TRUE", "IS-NOT-FALSE", "IS-NOT-TRUE" }; assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT ); assert( pExpr->pRight ); | | > | 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 | case TK_TRUTH: { int x; const char *azOp[] = { "IS-FALSE", "IS-TRUE", "IS-NOT-FALSE", "IS-NOT-TRUE" }; assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT ); assert( pExpr->pRight ); assert( sqlite3ExprSkipCollateAndLikely(pExpr->pRight)->op == TK_TRUEFALSE ); x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight); zUniOp = azOp[x]; break; } case TK_SPAN: { assert( !ExprHasProperty(pExpr, EP_IntValue) ); |
︙ | ︙ |
Changes to src/update.c.
︙ | ︙ | |||
220 221 222 223 224 225 226 | #endif pSrc = sqlite3SrcListDup(db, pTabList, 0); pWhere2 = sqlite3ExprDup(db, pWhere, 0); assert( pTabList->nSrc>1 ); if( pSrc ){ | | | 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | #endif pSrc = sqlite3SrcListDup(db, pTabList, 0); pWhere2 = sqlite3ExprDup(db, pWhere, 0); assert( pTabList->nSrc>1 ); if( pSrc ){ assert( pSrc->a[0].fg.notCte ); pSrc->a[0].iCursor = -1; pSrc->a[0].pTab->nTabRef--; pSrc->a[0].pTab = 0; } if( pPk ){ for(i=0; i<pPk->nKeyCol; i++){ Expr *pNew = exprRowColumn(pParse, pPk->aiColumn[i]); |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 | ** always be greater than or equal to the amount of required key space. ** Use that approximation to avoid the more expensive call to ** sqlite3VdbeSerialTypeLen() in the common case. */ if( d1+(u64)serial_type1+2>(u64)nKey1 && d1+(u64)sqlite3VdbeSerialTypeLen(serial_type1)>(u64)nKey1 ){ break; } /* Extract the values to be compared. */ sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1); d1 += sqlite3VdbeSerialTypeLen(serial_type1); | > > > > > > > > > | 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 | ** always be greater than or equal to the amount of required key space. ** Use that approximation to avoid the more expensive call to ** sqlite3VdbeSerialTypeLen() in the common case. */ if( d1+(u64)serial_type1+2>(u64)nKey1 && d1+(u64)sqlite3VdbeSerialTypeLen(serial_type1)>(u64)nKey1 ){ if( serial_type1>=1 && serial_type1<=7 && d1+(u64)sqlite3VdbeSerialTypeLen(serial_type1)<=(u64)nKey1+8 && CORRUPT_DB ){ return 1; /* corrupt record not detected by ** sqlite3VdbeRecordCompareWithSkip(). Return true ** to avoid firing the assert() */ } break; } /* Extract the values to be compared. */ sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1); d1 += sqlite3VdbeSerialTypeLen(serial_type1); |
︙ | ︙ |
Changes to src/vdbemem.c.
︙ | ︙ | |||
1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 | } } if( pRec==0 ) return 0; p->ppRec[0] = pRec; } pRec->nField = p->iVal+1; return &pRec->aMem[p->iVal]; } #else UNUSED_PARAMETER(p); #endif /* defined(SQLITE_ENABLE_STAT4) */ return sqlite3ValueNew(db); } | > | 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 | } } if( pRec==0 ) return 0; p->ppRec[0] = pRec; } pRec->nField = p->iVal+1; sqlite3VdbeMemSetNull(&pRec->aMem[p->iVal]); return &pRec->aMem[p->iVal]; } #else UNUSED_PARAMETER(p); #endif /* defined(SQLITE_ENABLE_STAT4) */ return sqlite3ValueNew(db); } |
︙ | ︙ |
Changes to test/analyze.test.
︙ | ︙ | |||
372 373 374 375 376 377 378 379 380 | CREATE TABLE SQLiteDemo2(a INTEGER PRIMARY KEY AUTOINCREMENT); INSERT INTO SQLiteDemo2 SELECT * FROM sqliteDemo; CREATE TABLE t1(b); INSERT INTO t1(b) SELECT a FROM sqliteDemo; ANALYZE; SELECT tbl FROM sqlite_stat1 WHERE idx IS NULL ORDER BY tbl; } {SQLiteDemo2 sqliteDemo t1} finish_test | > > > > > > > > > > > > > > > > > > > | 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 | CREATE TABLE SQLiteDemo2(a INTEGER PRIMARY KEY AUTOINCREMENT); INSERT INTO SQLiteDemo2 SELECT * FROM sqliteDemo; CREATE TABLE t1(b); INSERT INTO t1(b) SELECT a FROM sqliteDemo; ANALYZE; SELECT tbl FROM sqlite_stat1 WHERE idx IS NULL ORDER BY tbl; } {SQLiteDemo2 sqliteDemo t1} # The following caused a small buffer overread in STAT4 processing prior # to check-in [b99135288b157044]. # ifcapable stat4 { reset_db database_may_be_corrupt do_execsql_test analyze-7.1 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b INTEGER); INSERT INTO t1 VALUES(1, 7223372036854775); INSERT INTO t1 VALUES(2, 7223372036854776); INSERT INTO t1 VALUES(3, 7223372036854777); CREATE INDEX i1 ON t1(b); ANALYZE; UPDATE sqlite_stat4 SET sample = substr(sample, 0, 4); ANALYZE sqlite_schema; SELECT * FROM t1 WHERE b>7223372036854775 } {2 7223372036854776 3 7223372036854777} } finish_test |
Changes to test/corrupt2.test.
︙ | ︙ | |||
244 245 246 247 248 249 250 | db2 eval $::presql db2 eval {SELECT rowid FROM t1} { set result [db2 eval {pragma integrity_check}] break } set result } {{*** in database main *** | | | 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 | db2 eval $::presql db2 eval {SELECT rowid FROM t1} { set result [db2 eval {pragma integrity_check}] break } set result } {{*** in database main *** Tree 2 page 2 cell 0: 2nd reference to page 10 Page 4: never used}} db2 close proc corruption_test {args} { set A(-corrupt) {} set A(-sqlprep) {} |
︙ | ︙ |
Changes to test/shell2.test.
︙ | ︙ | |||
258 259 260 261 262 263 264 265 266 | CREATE TABLE t(line text); .mode ascii .separator "\377" "\n" .import dummy.csv t SELECT count(*) FROM t;}]] } {0 1} finish_test | > > > > > > > > > | 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 | CREATE TABLE t(line text); .mode ascii .separator "\377" "\n" .import dummy.csv t SELECT count(*) FROM t;}]] } {0 1} # Bug from forum post 7cbe081746dd3803 # Keywords as column names were producing an error message. do_test shell2-1.4.12 { set res [catchcmd :memory: [string trim { CREATE TABLE "group"("order" text); INSERT INTO "group" VALUES ('ABC'); .sha3sum}]] } {0 ca08bc02b7e95c7df431a3a4b1cc0f8d8743914793473f55b5558e03} finish_test |
Changes to test/sqldiff1.test.
︙ | ︙ | |||
59 60 61 62 63 64 65 66 | INSERT INTO t2(a,b) VALUES(53.5,'one'||X'0a0d'); INSERT INTO t2(a,b) VALUES(54.5,'one'||X'0a' ||'two'); CREATE TABLE t3(a,b,c); INSERT INTO t3(rowid,a,b,c) VALUES(1,111,222,333); DROP TABLE t4;} finish_test | > > > > > > > > > > > > > > > > > > > > > > | 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 | INSERT INTO t2(a,b) VALUES(53.5,'one'||X'0a0d'); INSERT INTO t2(a,b) VALUES(54.5,'one'||X'0a' ||'two'); CREATE TABLE t3(a,b,c); INSERT INTO t3(rowid,a,b,c) VALUES(1,111,222,333); DROP TABLE t4;} db close forcedelete test.db test2.db sqlite3 db test.db do_test sqldiff-2.0 { db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY); } db close sqlite3 db test2.db db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY, b); } db close set line "exec $PROG test.db test2.db" unset -nocomplain ::MSG catch {eval $line} ::MSG } {0} do_test sqldiff-2.1 { set ::MSG } {ALTER TABLE t1 ADD COLUMN b;} finish_test |
Changes to test/upfrom4.test.
︙ | ︙ | |||
122 123 124 125 126 127 128 129 130 | END; UPDATE t1 SET b=b|100; SELECT * FROM t1 ORDER BY a; } { 1 100 def 4.5 1000 - - - } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | END; UPDATE t1 SET b=b|100; SELECT * FROM t1 ORDER BY a; } { 1 100 def 4.5 1000 - - - } # Forum post https://sqlite.org/forum/forumpost/36ff78b2a3 # ifcapable update_delete_limit { reset_db do_execsql_test 500 { CREATE TABLE t1(abc INT, def INT); INSERT INTO t1 VALUES(0,0); INSERT INTO t1 VALUES(0,0); INSERT INTO t1 VALUES(0,0); CREATE TABLE dual(dummy TEXT); INSERT INTO dual(dummy) VALUES('X'); } {} do_execsql_test 510 { UPDATE t1 SET (abc, def)=(SELECT x, 123) FROM dual LEFT JOIN (SELECT 789 AS 'x' FROM dual) AS d2 LIMIT 2 } do_execsql_test 520 { SELECT * FROM t1 } {789 123 789 123 0 0} } finish_test |
Changes to test/wherelimit2.test.
︙ | ︙ | |||
295 296 297 298 299 300 301 302 303 | do_test 5.5 { set ::log {} execsql { UPDATE "v w" SET "a b" = "a b" || 'x' ORDER BY "a b" LIMIT 5; } set ::log } {ax a bx b cx c dx d ex a} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | do_test 5.5 { set ::log {} execsql { UPDATE "v w" SET "a b" = "a b" || 'x' ORDER BY "a b" LIMIT 5; } set ::log } {ax a bx b cx c dx d ex a} #----------------------------------------------------------------------- reset_db do_execsql_test 6.0 { CREATE TABLE t2(x); INSERT INTO t2(x) VALUES(1),(2),(3),(5),(8),(13); } {} do_execsql_test 6.1 { WITH t2 AS MATERIALIZED (VALUES(5)) DELETE FROM t2 ORDER BY rank()OVER() LIMIT 2; } do_execsql_test 6.2 { SELECT * FROM t2; } {3 5 8 13} #------------------------------------------------------------------------- do_execsql_test 7.0 { CREATE TABLE t1(a INT); INSERT INTO t1(a) VALUES(0); } {} do_execsql_test 7.1 { WITH t1(b) AS (SELECT * FROM (SELECT * FROM (VALUES(2)))) UPDATE t1 SET a=3 LIMIT 1; } do_execsql_test 7.2 { SELECT * FROM t1; } {3} finish_test |
Changes to test/window1.test.
︙ | ︙ | |||
2358 2359 2360 2361 2362 2363 2364 2365 2366 | } {100 {} 400} do_execsql_test 76.4 { SELECT (SELECT y+sum(0) OVER ()) FROM t3 LEFT JOIN t4 ON x=y GROUP BY x; } {100 {} 400} do_execsql_test 76.5 { SELECT (SELECT max(y)+sum(0) OVER ()) FROM t3 LEFT JOIN t4 ON x=y GROUP BY x; } {100 {} 400} finish_test | > > > > > > > > > > > > > | 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 | } {100 {} 400} do_execsql_test 76.4 { SELECT (SELECT y+sum(0) OVER ()) FROM t3 LEFT JOIN t4 ON x=y GROUP BY x; } {100 {} 400} do_execsql_test 76.5 { SELECT (SELECT max(y)+sum(0) OVER ()) FROM t3 LEFT JOIN t4 ON x=y GROUP BY x; } {100 {} 400} # 2023-05-23 https://sqlite.org/forum/forumpost/fbfe330a20 # reset_db do_execsql_test 77.1 { CREATE TABLE t1(x INT); CREATE INDEX t1x ON t1(likely(x)); INSERT INTO t1 VALUES(1),(2),(4),(8); } do_execsql_test 77.2 { SELECT max(~likely(x)) FILTER (WHERE true) FROM t1 INDEXED BY t1x GROUP BY x; } {-2 -3 -5 -9} finish_test |
Changes to tool/sqldiff.c.
︙ | ︙ | |||
601 602 603 604 605 606 607 | nQ = nPk2+1+2*(n2-nPk2); if( n2>nPk2 ){ zSep = "SELECT "; for(i=0; i<nPk; i++){ strPrintf(&sql, "%sB.%s", zSep, az[i]); zSep = ", "; } | | | | | | | | 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 | nQ = nPk2+1+2*(n2-nPk2); if( n2>nPk2 ){ zSep = "SELECT "; for(i=0; i<nPk; i++){ strPrintf(&sql, "%sB.%s", zSep, az[i]); zSep = ", "; } strPrintf(&sql, ", 1 /* changed row */"); while( az[i] ){ strPrintf(&sql, ", A.%s IS NOT B.%s, B.%s", az[i], az2[i], az2[i]); i++; } while( az2[i] ){ strPrintf(&sql, ", B.%s IS NOT NULL, B.%s", az2[i], az2[i]); i++; } strPrintf(&sql, "\n FROM main.%s A, aux.%s B\n", zId, zId); zSep = " WHERE"; for(i=0; i<nPk; i++){ strPrintf(&sql, "%s A.%s=B.%s", zSep, az[i], az[i]); zSep = " AND"; } zSep = "\n AND ("; while( az[i] ){ |
︙ | ︙ | |||
638 639 640 641 642 643 644 | strPrintf(&sql, " UNION ALL\n"); } zSep = "SELECT "; for(i=0; i<nPk; i++){ strPrintf(&sql, "%sA.%s", zSep, az[i]); zSep = ", "; } | | | | | | | | 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 | strPrintf(&sql, " UNION ALL\n"); } zSep = "SELECT "; for(i=0; i<nPk; i++){ strPrintf(&sql, "%sA.%s", zSep, az[i]); zSep = ", "; } strPrintf(&sql, ", 2 /* deleted row */"); while( az2[i] ){ strPrintf(&sql, ", NULL, NULL"); i++; } strPrintf(&sql, "\n FROM main.%s A\n", zId); strPrintf(&sql, " WHERE NOT EXISTS(SELECT 1 FROM aux.%s B\n", zId); zSep = " WHERE"; for(i=0; i<nPk; i++){ strPrintf(&sql, "%s A.%s=B.%s", zSep, az[i], az[i]); zSep = " AND"; } strPrintf(&sql, ")\n"); zSep = " UNION ALL\nSELECT "; for(i=0; i<nPk; i++){ strPrintf(&sql, "%sB.%s", zSep, az[i]); zSep = ", "; } strPrintf(&sql, ", 3 /* inserted row */"); while( az2[i] ){ strPrintf(&sql, ", 1, B.%s", az2[i]); i++; } strPrintf(&sql, "\n FROM aux.%s B\n", zId); strPrintf(&sql, " WHERE NOT EXISTS(SELECT 1 FROM main.%s A\n", zId); zSep = " WHERE"; for(i=0; i<nPk; i++){ strPrintf(&sql, "%s A.%s=B.%s", zSep, az[i], az[i]); zSep = " AND"; } strPrintf(&sql, ")\n ORDER BY"); |
︙ | ︙ |