Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(157)

Side by Side Diff: third_party/sqlite/patches/0008-Virtual-table-supporting-recovery-of-corrupted-datab.patch

Issue 885473002: [sql] Rewrite sqlite patching "system". (Closed) Base URL: http://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed typo in readme. Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 Add new virtual table 'recover' to src/ and the amalgamation. 1 From dc2d5db3e20e8aa8f3f34640b605dfa88576c19c Mon Sep 17 00:00:00 2001
2 From: Scott Hess <shess@chromium.org>
3 Date: Sat, 20 Jul 2013 11:42:21 -0700
4 Subject: [PATCH 08/23] Virtual table supporting recovery of corrupted
5 databases.
2 6
3 Since recover.c is in somewhat active development, it is possible that 7 "recover" implements a virtual table which uses the SQLite pager layer
4 the patch below will not reliably re-create the file. 8 to read table pages and pull out the data which is structurally sound
9 (at least at the storage layer).
5 10
6 shess@chromium.org 11 BUG=109482
7 12
8 Generated with: 13 Since this implements a new feature for SQLite, the review URLs aren't
9 git diff --cached --relative=third_party/sqlite/src --src-prefix='' --dst-prefix ='' > third_party/sqlite/recover.patch 14 listed. This patch and the top of recover.c should be considered
10 [--cached because otherwise the diff adding recover.c wasn't generated.] 15 authoritative. The history is mostly under
16 third_party/sqlite/src/src/{recover,recover-alt}.c .
17 ---
18 third_party/sqlite/src/Makefile.in | 1 +
19 third_party/sqlite/src/Makefile.linux-gcc | 4 +
20 third_party/sqlite/src/main.mk | 4 +-
21 third_party/sqlite/src/src/main.c | 8 +
22 third_party/sqlite/src/src/recover.c | 2164 ++++++++++++++++++++++++++++
23 third_party/sqlite/src/src/sqlite.h.in | 11 +
24 third_party/sqlite/src/test/recover.test | 147 ++
25 third_party/sqlite/src/test/recover0.test | 532 +++++++
26 third_party/sqlite/src/test/recover1.test | 429 ++++++
27 third_party/sqlite/src/test/recover2.test | 157 ++
28 third_party/sqlite/src/tool/mksqlite3c.tcl | 2 +
29 11 files changed, 3458 insertions(+), 1 deletion(-)
30 create mode 100644 third_party/sqlite/src/src/recover.c
31 create mode 100644 third_party/sqlite/src/test/recover.test
32 create mode 100644 third_party/sqlite/src/test/recover0.test
33 create mode 100644 third_party/sqlite/src/test/recover1.test
34 create mode 100644 third_party/sqlite/src/test/recover2.test
11 35
12 diff --git Makefile.in Makefile.in 36 diff --git a/third_party/sqlite/src/Makefile.in b/third_party/sqlite/src/Makefil e.in
13 index f3239f3..216742c 100644 37 index f3239f3..216742c 100644
14 --- Makefile.in 38 --- a/third_party/sqlite/src/Makefile.in
15 +++ Makefile.in 39 +++ b/third_party/sqlite/src/Makefile.in
16 @@ -251,6 +251,7 @@ SRC = \ 40 @@ -251,6 +251,7 @@ SRC = \
17 $(TOP)/src/prepare.c \ 41 $(TOP)/src/prepare.c \
18 $(TOP)/src/printf.c \ 42 $(TOP)/src/printf.c \
19 $(TOP)/src/random.c \ 43 $(TOP)/src/random.c \
20 + $(TOP)/src/recover.c \ 44 + $(TOP)/src/recover.c \
21 $(TOP)/src/resolve.c \ 45 $(TOP)/src/resolve.c \
22 $(TOP)/src/rowset.c \ 46 $(TOP)/src/rowset.c \
23 $(TOP)/src/select.c \ 47 $(TOP)/src/select.c \
24 diff --git src/sqlite.h.in src/sqlite.h.in 48 diff --git a/third_party/sqlite/src/Makefile.linux-gcc b/third_party/sqlite/src/ Makefile.linux-gcc
25 index 62b9326..fb76659 100644 49 index 554bf56..e631816 100644
26 --- src/sqlite.h.in 50 --- a/third_party/sqlite/src/Makefile.linux-gcc
27 +++ src/sqlite.h.in 51 +++ b/third_party/sqlite/src/Makefile.linux-gcc
28 @@ -6403,6 +6403,17 @@ int sqlite3_wal_checkpoint_v2( 52 @@ -82,6 +82,10 @@ OPTS += -DSQLITE_MEMDEBUG=1
29 #define SQLITE_CHECKPOINT_RESTART 2 53 # TODO(shess) I can't see why I need this setting.
54 OPTS += -DOS_UNIX=1
30 55
56 +# The recover virtual table is not generally enabled. Enable it for testing
57 +# purposes.
58 +OPTS += -DDEFAULT_ENABLE_RECOVER=1
59 +
60 #### The suffix to add to executable files. ".exe" for windows.
61 # Nothing for unix.
62 #
63 diff --git a/third_party/sqlite/src/main.mk b/third_party/sqlite/src/main.mk
64 index b0aa4b2..65dd690 100644
65 --- a/third_party/sqlite/src/main.mk
66 +++ b/third_party/sqlite/src/main.mk
67 @@ -62,7 +62,7 @@ LIBOBJ+= alter.o analyze.o attach.o auth.o \
68 mutex.o mutex_noop.o mutex_os2.o mutex_unix.o mutex_w32.o \
69 notify.o opcodes.o os.o os_os2.o os_unix.o os_win.o \
70 pager.o parse.o pcache.o pcache1.o pragma.o prepare.o printf.o \
71 - random.o resolve.o rowset.o rtree.o select.o status.o \
72 + random.o recover.o resolve.o rowset.o rtree.o select.o status.o \
73 table.o tokenize.o trigger.o \
74 update.o util.o vacuum.o \
75 vdbe.o vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbetrace.o \
76 @@ -132,6 +132,7 @@ SRC = \
77 $(TOP)/src/prepare.c \
78 $(TOP)/src/printf.c \
79 $(TOP)/src/random.c \
80 + $(TOP)/src/recover.c \
81 $(TOP)/src/resolve.c \
82 $(TOP)/src/rowset.c \
83 $(TOP)/src/select.c \
84 @@ -284,6 +285,7 @@ TESTSRC2 = \
85 $(TOP)/src/prepare.c \
86 $(TOP)/src/printf.c \
87 $(TOP)/src/random.c \
88 + $(TOP)/src/recover.c \
89 $(TOP)/src/pcache.c \
90 $(TOP)/src/pcache1.c \
91 $(TOP)/src/select.c \
92 diff --git a/third_party/sqlite/src/src/main.c b/third_party/sqlite/src/src/main .c
93 index 4aaa618..696de1c 100644
94 --- a/third_party/sqlite/src/src/main.c
95 +++ b/third_party/sqlite/src/src/main.c
96 @@ -1996,6 +1996,14 @@ static int openDatabase(
97 }
98 #endif
31 99
32 +/* Begin recover.patch for Chromium */ 100 +#ifdef DEFAULT_ENABLE_RECOVER
33 +/* 101 + /* Initialize recover virtual table for testing. */
34 +** Call to initialize the recover virtual-table modules (see recover.c). 102 + extern int recoverVtableInit(sqlite3 *db);
35 +** 103 + if( !db->mallocFailed && rc==SQLITE_OK ){
36 +** This could be loaded by default in main.c, but that would make the 104 + rc = recoverVtableInit(db);
37 +** virtual table available to Web SQL. Breaking it out allows only 105 + }
38 +** selected users to enable it (currently sql/recovery.cc). 106 +#endif
39 +*/
40 +int recoverVtableInit(sqlite3 *db);
41 +/* End recover.patch for Chromium */
42 + 107 +
43 /* 108 #ifdef SQLITE_ENABLE_ICU
44 ** Undo the hack that converts floating point types to integer for 109 if( !db->mallocFailed && rc==SQLITE_OK ){
45 ** builds on processors without floating point support. 110 rc = sqlite3IcuInit(db);
46 diff --git tool/mksqlite3c.tcl tool/mksqlite3c.tcl 111 diff --git a/third_party/sqlite/src/src/recover.c b/third_party/sqlite/src/src/r ecover.c
47 index fa99f2d..df2df07 100644
48 --- tool/mksqlite3c.tcl
49 +++ tool/mksqlite3c.tcl
50 @@ -293,6 +293,8 @@ foreach file {
51 main.c
52 notify.c
53
54 + recover.c
55 +
56 fts3.c
57 fts3_aux.c
58 fts3_expr.c
59 diff --git src/recover.c src/recover.c
60 new file mode 100644 112 new file mode 100644
61 index 0000000..6430c8b 113 index 0000000..c996d53
62 --- /dev/null 114 --- /dev/null
63 +++ src/recover.c 115 +++ b/third_party/sqlite/src/src/recover.c
64 @@ -0,0 +1,2130 @@ 116 @@ -0,0 +1,2164 @@
65 +/* 117 +/*
66 +** 2012 Jan 11 118 +** 2012 Jan 11
67 +** 119 +**
68 +** The author disclaims copyright to this source code. In place of 120 +** The author disclaims copyright to this source code. In place of
69 +** a legal notice, here is a blessing: 121 +** a legal notice, here is a blessing:
70 +** 122 +**
71 +** May you do good and not evil. 123 +** May you do good and not evil.
72 +** May you find forgiveness for yourself and forgive others. 124 +** May you find forgiveness for yourself and forgive others.
73 +** May you share freely, never taking more than you give. 125 +** May you share freely, never taking more than you give.
74 +*/ 126 +*/
(...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after
700 + } 752 + }
701 + 753 +
702 + memset(p, 0xA5, sizeof(*p)); 754 + memset(p, 0xA5, sizeof(*p));
703 + sqlite3_free(p); 755 + sqlite3_free(p);
704 + } 756 + }
705 +} 757 +}
706 + 758 +
707 +/* Internal helper. Reset storage in preparation for iterating pPage. */ 759 +/* Internal helper. Reset storage in preparation for iterating pPage. */
708 +static void interiorCursorSetPage(RecoverInteriorCursor *pCursor, 760 +static void interiorCursorSetPage(RecoverInteriorCursor *pCursor,
709 + DbPage *pPage){ 761 + DbPage *pPage){
762 + const unsigned knMinCellLength = 2 + 4 + 1;
763 + unsigned nMaxChildren;
710 + assert( PageHeader(pPage)[kiPageTypeOffset]==kTableInteriorPage ); 764 + assert( PageHeader(pPage)[kiPageTypeOffset]==kTableInteriorPage );
711 + 765 +
712 + if( pCursor->pPage ){ 766 + if( pCursor->pPage ){
713 + sqlite3PagerUnref(pCursor->pPage); 767 + sqlite3PagerUnref(pCursor->pPage);
714 + pCursor->pPage = NULL; 768 + pCursor->pPage = NULL;
715 + } 769 + }
716 + pCursor->pPage = pPage; 770 + pCursor->pPage = pPage;
717 + pCursor->iChild = 0; 771 + pCursor->iChild = 0;
718 + 772 +
719 + /* A child for each cell, plus one in the header. */ 773 + /* A child for each cell, plus one in the header. */
720 + /* TODO(shess): Sanity-check the count? Page header plus per-cell
721 + * cost of 16-bit offset, 32-bit page number, and one varint
722 + * (minimum 1 byte).
723 + */
724 + pCursor->nChildren = decodeUnsigned16(PageHeader(pPage) + 774 + pCursor->nChildren = decodeUnsigned16(PageHeader(pPage) +
725 + kiPageCellCountOffset) + 1; 775 + kiPageCellCountOffset) + 1;
776 +
777 + /* Each child requires a 16-bit offset from an array after the header,
778 + * and each child contains a 32-bit page number and at least a varint
779 + * (min size of one byte). The final child page is in the header. So
780 + * the maximum value for nChildren is:
781 + * (nPageSize - kiPageInteriorHeaderBytes) /
782 + * (sizeof(uint16) + sizeof(uint32) + 1) + 1
783 + */
784 + /* TODO(shess): This count is very unlikely to be corrupted in
785 + * isolation, so seeing this could signal to skip the page. OTOH, I
786 + * can't offhand think of how to get here unless this or the page-type
787 + * byte is corrupted. Could be an overflow page, but it would require
788 + * a very large database.
789 + */
790 + nMaxChildren =
791 + (pCursor->nPageSize - kiPageInteriorHeaderBytes) / knMinCellLength + 1;
792 + if (pCursor->nChildren > nMaxChildren) {
793 + pCursor->nChildren = nMaxChildren;
794 + }
726 +} 795 +}
727 + 796 +
728 +static int interiorCursorCreate(RecoverInteriorCursor *pParent, 797 +static int interiorCursorCreate(RecoverInteriorCursor *pParent,
729 + DbPage *pPage, int nPageSize, 798 + DbPage *pPage, int nPageSize,
730 + RecoverInteriorCursor **ppCursor){ 799 + RecoverInteriorCursor **ppCursor){
731 + RecoverInteriorCursor *pCursor = 800 + RecoverInteriorCursor *pCursor =
732 + sqlite3_malloc(sizeof(RecoverInteriorCursor)); 801 + sqlite3_malloc(sizeof(RecoverInteriorCursor));
733 + if( !pCursor ){ 802 + if( !pCursor ){
734 + return SQLITE_NOMEM; 803 + return SQLITE_NOMEM;
735 + } 804 + }
(...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after
1332 +} 1401 +}
1333 + 1402 +
1334 +/* Useful for setting breakpoints. */ 1403 +/* Useful for setting breakpoints. */
1335 +static int ValidateError(){ 1404 +static int ValidateError(){
1336 + return SQLITE_ERROR; 1405 + return SQLITE_ERROR;
1337 +} 1406 +}
1338 + 1407 +
1339 +/* Setup the cursor for reading the information from cell iCell. */ 1408 +/* Setup the cursor for reading the information from cell iCell. */
1340 +static int leafCursorCellDecode(RecoverLeafCursor *pCursor){ 1409 +static int leafCursorCellDecode(RecoverLeafCursor *pCursor){
1341 + const unsigned char *pPageHeader; /* Header of current page. */ 1410 + const unsigned char *pPageHeader; /* Header of current page. */
1411 + const unsigned char *pPageEnd; /* Byte after end of current page. */
1342 + const unsigned char *pCellOffsets; /* Pointer to page's cell offsets. */ 1412 + const unsigned char *pCellOffsets; /* Pointer to page's cell offsets. */
1343 + unsigned iCellOffset; /* Offset of current cell (iCell). */ 1413 + unsigned iCellOffset; /* Offset of current cell (iCell). */
1344 + const unsigned char *pCell; /* Pointer to data at iCellOffset. */ 1414 + const unsigned char *pCell; /* Pointer to data at iCellOffset. */
1345 + unsigned nCellMaxBytes; /* Maximum local size of iCell. */ 1415 + unsigned nCellMaxBytes; /* Maximum local size of iCell. */
1346 + unsigned iEndOffset; /* End of iCell's in-page data. */ 1416 + unsigned iEndOffset; /* End of iCell's in-page data. */
1347 + u64 nRecordBytes; /* Expected size of cell, w/overflow. */ 1417 + u64 nRecordBytes; /* Expected size of cell, w/overflow. */
1348 + u64 iRowid; /* iCell's rowid (in table). */ 1418 + u64 iRowid; /* iCell's rowid (in table). */
1349 + unsigned nRead; /* Amount of cell read. */ 1419 + unsigned nRead; /* Amount of cell read. */
1350 + unsigned nRecordHeaderRead; /* Header data read. */ 1420 + unsigned nRecordHeaderRead; /* Header data read. */
1351 + u64 nRecordHeaderBytes; /* Header size expected. */ 1421 + u64 nRecordHeaderBytes; /* Header size expected. */
1352 + unsigned nRecordCols; /* Columns read from header. */ 1422 + unsigned nRecordCols; /* Columns read from header. */
1353 + u64 nRecordColBytes; /* Bytes in payload for those columns. */ 1423 + u64 nRecordColBytes; /* Bytes in payload for those columns. */
1354 + unsigned i; 1424 + unsigned i;
1355 + int rc; 1425 + int rc;
1356 + 1426 +
1357 + assert( pCursor->iCell<pCursor->nCells ); 1427 + assert( pCursor->iCell<pCursor->nCells );
1358 + 1428 +
1359 + leafCursorDestroyCellData(pCursor); 1429 + leafCursorDestroyCellData(pCursor);
1360 + 1430 +
1361 + /* Find the offset to the row. */ 1431 + /* Find the offset to the row. */
1362 + pPageHeader = PageHeader(pCursor->pPage); 1432 + pPageHeader = PageHeader(pCursor->pPage);
1363 + pCellOffsets = pPageHeader + knPageLeafHeaderBytes; 1433 + pCellOffsets = pPageHeader + knPageLeafHeaderBytes;
1434 + pPageEnd = PageData(pCursor->pPage, pCursor->nPageSize);
1435 + if( pCellOffsets + pCursor->iCell*2 + 2 > pPageEnd ){
1436 + return ValidateError();
1437 + }
1364 + iCellOffset = decodeUnsigned16(pCellOffsets + pCursor->iCell*2); 1438 + iCellOffset = decodeUnsigned16(pCellOffsets + pCursor->iCell*2);
1365 + if( iCellOffset>=pCursor->nPageSize ){ 1439 + if( iCellOffset>=pCursor->nPageSize ){
1366 + return ValidateError(); 1440 + return ValidateError();
1367 + } 1441 + }
1368 + 1442 +
1369 + pCell = PageData(pCursor->pPage, iCellOffset); 1443 + pCell = PageData(pCursor->pPage, iCellOffset);
1370 + nCellMaxBytes = pCursor->nPageSize - iCellOffset; 1444 + nCellMaxBytes = pCursor->nPageSize - iCellOffset;
1371 + 1445 +
1372 + /* B-tree leaf cells lead with varint record size, varint rowid and 1446 + /* B-tree leaf cells lead with varint record size, varint rowid and
1373 + * varint header size. 1447 + * varint header size.
(...skipping 21 matching lines...) Expand all
1395 + rc = overflowMaybeCreate(pCursor->pPage, pCursor->nPageSize, 1469 + rc = overflowMaybeCreate(pCursor->pPage, pCursor->nPageSize,
1396 + pCursor->iRecordOffset, pCursor->nRecordBytes, 1470 + pCursor->iRecordOffset, pCursor->nRecordBytes,
1397 + &pCursor->nLocalRecordBytes, 1471 + &pCursor->nLocalRecordBytes,
1398 + &pCursor->pOverflow); 1472 + &pCursor->pOverflow);
1399 + if( rc!=SQLITE_OK ){ 1473 + if( rc!=SQLITE_OK ){
1400 + return ValidateError(); 1474 + return ValidateError();
1401 + } 1475 + }
1402 + 1476 +
1403 + /* Check that no other cell starts within this cell. */ 1477 + /* Check that no other cell starts within this cell. */
1404 + iEndOffset = pCursor->iRecordOffset + pCursor->nLocalRecordBytes; 1478 + iEndOffset = pCursor->iRecordOffset + pCursor->nLocalRecordBytes;
1405 + for( i=0; i<pCursor->nCells; ++i ){ 1479 + for( i=0; i<pCursor->nCells && pCellOffsets + i*2 + 2 <= pPageEnd; ++i ){
1406 + const unsigned iOtherOffset = decodeUnsigned16(pCellOffsets + i*2); 1480 + const unsigned iOtherOffset = decodeUnsigned16(pCellOffsets + i*2);
1407 + if( iOtherOffset>iCellOffset && iOtherOffset<iEndOffset ){ 1481 + if( iOtherOffset>iCellOffset && iOtherOffset<iEndOffset ){
1408 + return ValidateError(); 1482 + return ValidateError();
1409 + } 1483 + }
1410 + } 1484 + }
1411 + 1485 +
1412 + nRecordHeaderRead = getVarint(pCell + nRead, &nRecordHeaderBytes); 1486 + nRecordHeaderRead = getVarint(pCell + nRead, &nRecordHeaderBytes);
1413 + assert( nRecordHeaderBytes<=nRecordBytes ); 1487 + assert( nRecordHeaderBytes<=nRecordBytes );
1414 + pCursor->nRecordHeaderBytes = nRecordHeaderBytes; 1488 + pCursor->nRecordHeaderBytes = nRecordHeaderBytes;
1415 + 1489 +
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
1684 + pCursor = sqlite3_malloc(sizeof(RecoverCursor)); 1758 + pCursor = sqlite3_malloc(sizeof(RecoverCursor));
1685 + if( !pCursor ){ 1759 + if( !pCursor ){
1686 + leafCursorDestroy(pLeafCursor); 1760 + leafCursorDestroy(pLeafCursor);
1687 + return SQLITE_NOMEM; 1761 + return SQLITE_NOMEM;
1688 + } 1762 + }
1689 + memset(pCursor, 0, sizeof(*pCursor)); 1763 + memset(pCursor, 0, sizeof(*pCursor));
1690 + pCursor->base.pVtab = pVTab; 1764 + pCursor->base.pVtab = pVTab;
1691 + pCursor->pLeafCursor = pLeafCursor; 1765 + pCursor->pLeafCursor = pLeafCursor;
1692 + pCursor->iEncoding = iEncoding; 1766 + pCursor->iEncoding = iEncoding;
1693 + 1767 +
1768 + /* If no leaf pages were found, empty result set. */
1769 + /* TODO(shess): leafCursorNextValidCell() would return SQLITE_ROW or
1770 + * SQLITE_DONE to indicate whether there is further data to consider.
1771 + */
1772 + pCursor->bEOF = (pLeafCursor->pPage==NULL);
1773 +
1694 + *ppCursor = (sqlite3_vtab_cursor*)pCursor; 1774 + *ppCursor = (sqlite3_vtab_cursor*)pCursor;
1695 + return SQLITE_OK; 1775 + return SQLITE_OK;
1696 +} 1776 +}
1697 + 1777 +
1698 +static int recoverClose(sqlite3_vtab_cursor *cur){ 1778 +static int recoverClose(sqlite3_vtab_cursor *cur){
1699 + RecoverCursor *pCursor = (RecoverCursor*)cur; 1779 + RecoverCursor *pCursor = (RecoverCursor*)cur;
1700 + FNENTRY(); 1780 + FNENTRY();
1701 + if( pCursor->pLeafCursor ){ 1781 + if( pCursor->pLeafCursor ){
1702 + leafCursorDestroy(pCursor->pLeafCursor); 1782 + leafCursorDestroy(pCursor->pLeafCursor);
1703 + pCursor->pLeafCursor = NULL; 1783 + pCursor->pLeafCursor = NULL;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1772 + sqlite3_vtab_cursor *pVtabCursor, 1852 + sqlite3_vtab_cursor *pVtabCursor,
1773 + int idxNum, const char *idxStr, 1853 + int idxNum, const char *idxStr,
1774 + int argc, sqlite3_value **argv 1854 + int argc, sqlite3_value **argv
1775 +){ 1855 +){
1776 + RecoverCursor *pCursor = (RecoverCursor*)pVtabCursor; 1856 + RecoverCursor *pCursor = (RecoverCursor*)pVtabCursor;
1777 + Recover *pRecover = (Recover*)pCursor->base.pVtab; 1857 + Recover *pRecover = (Recover*)pCursor->base.pVtab;
1778 + int rc; 1858 + int rc;
1779 + 1859 +
1780 + FNENTRY(); 1860 + FNENTRY();
1781 + 1861 +
1782 + /* Load the first cell, and iterate forward if it's not valid. */ 1862 + /* There were no valid leaf pages in the table. */
1783 + /* TODO(shess): What happens if no cells at all are valid? */ 1863 + if( pCursor->bEOF ){
1864 + return SQLITE_OK;
1865 + }
1866 +
1867 + /* Load the first cell, and iterate forward if it's not valid. If no cells a t
1868 + * all are valid, recoverNext() sets bEOF and returns appropriately.
1869 + */
1784 + rc = leafCursorCellDecode(pCursor->pLeafCursor); 1870 + rc = leafCursorCellDecode(pCursor->pLeafCursor);
1785 + if( rc!=SQLITE_OK || recoverValidateLeafCell(pRecover, pCursor)!=SQLITE_OK ){ 1871 + if( rc!=SQLITE_OK || recoverValidateLeafCell(pRecover, pCursor)!=SQLITE_OK ){
1786 + return recoverNext(pVtabCursor); 1872 + return recoverNext(pVtabCursor);
1787 + } 1873 + }
1788 + 1874 +
1789 + return SQLITE_OK; 1875 + return SQLITE_OK;
1790 +} 1876 +}
1791 + 1877 +
1792 +static int recoverEof(sqlite3_vtab_cursor *pVtabCursor){ 1878 +static int recoverEof(sqlite3_vtab_cursor *pVtabCursor){
1793 + RecoverCursor *pCursor = (RecoverCursor*)pVtabCursor; 1879 + RecoverCursor *pCursor = (RecoverCursor*)pVtabCursor;
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
2185 + rc = sqlite3_declare_vtab(db, zCreateSql); 2271 + rc = sqlite3_declare_vtab(db, zCreateSql);
2186 + sqlite3_free(zCreateSql); 2272 + sqlite3_free(zCreateSql);
2187 + if( rc!=SQLITE_OK ){ 2273 + if( rc!=SQLITE_OK ){
2188 + recoverRelease(pRecover); 2274 + recoverRelease(pRecover);
2189 + return rc; 2275 + return rc;
2190 + } 2276 + }
2191 + 2277 +
2192 + *ppVtab = (sqlite3_vtab *)pRecover; 2278 + *ppVtab = (sqlite3_vtab *)pRecover;
2193 + return SQLITE_OK; 2279 + return SQLITE_OK;
2194 +} 2280 +}
2281 diff --git a/third_party/sqlite/src/src/sqlite.h.in b/third_party/sqlite/src/src /sqlite.h.in
2282 index ec7e502..00c8510 100644
2283 --- a/third_party/sqlite/src/src/sqlite.h.in
2284 +++ b/third_party/sqlite/src/src/sqlite.h.in
2285 @@ -6388,6 +6388,17 @@ int sqlite3_wal_checkpoint_v2(
2286 #define SQLITE_CHECKPOINT_RESTART 2
2287
2288
2289 +/* Begin recover.patch for Chromium */
2290 +/*
2291 +** Call to initialize the recover virtual-table modules (see recover.c).
2292 +**
2293 +** This could be loaded by default in main.c, but that would make the
2294 +** virtual table available to Web SQL. Breaking it out allows only
2295 +** selected users to enable it (currently sql/recovery.cc).
2296 +*/
2297 +int recoverVtableInit(sqlite3 *db);
2298 +/* End recover.patch for Chromium */
2299 +
2300 /*
2301 ** Undo the hack that converts floating point types to integer for
2302 ** builds on processors without floating point support.
2303 diff --git a/third_party/sqlite/src/test/recover.test b/third_party/sqlite/src/t est/recover.test
2304 new file mode 100644
2305 index 0000000..b5aa182
2306 --- /dev/null
2307 +++ b/third_party/sqlite/src/test/recover.test
2308 @@ -0,0 +1,147 @@
2309 +# 2012 January 11 {}
2310 +#
2311 +# The author disclaims copyright to this source code. In place of
2312 +# a legal notice, here is a blessing:
2313 +#
2314 +# May you do good and not evil.
2315 +# May you find forgiveness for yourself and forgive others.
2316 +# May you share freely, never taking more than you give.
2317 +#
2318 +#***********************************************************************
2319 +# This file implements regression tests for SQLite library.
2320 +#
2321 +# This file implements tests for the recover module, which can read
2322 +# through corrupt rows and pages.
2323 +#
2324 +# $Id$
2325 +
2326 +# TODO(shess): These all test that the module correctly reads good
2327 +# data. It would be good to implement tests of corrupt data.
2328 +
2329 +set testdir [file dirname $argv0]
2330 +source $testdir/tester.tcl
2331 +
2332 +db eval {
2333 + DROP TABLE IF EXISTS altered;
2334 + CREATE TABLE altered (
2335 + c TEXT
2336 + );
2337 + INSERT INTO altered VALUES ('a');
2338 + INSERT INTO altered VALUES ('b');
2339 + INSERT INTO altered VALUES ('c');
2340 + ALTER TABLE altered ADD COLUMN i INTEGER NOT NULL DEFAULT 10;
2341 + INSERT INTO altered VALUES ('d', 5);
2342 +}
2343 +
2344 +# SQLite will fill the earlier rows with the default.
2345 +do_test recover-alter-1.0 {
2346 + execsql {SELECT c, i FROM altered ORDER BY rowid}
2347 +} {a 10 b 10 c 10 d 5}
2348 +
2349 +# recover sees NULL for those rows.
2350 +do_test recover-alter-1.1 {
2351 + db eval {
2352 + DROP TABLE IF EXISTS temp.altered_recover;
2353 + CREATE VIRTUAL TABLE temp.altered_recover USING recover(
2354 + altered,
2355 + c TEXT,
2356 + i INTEGER
2357 + );
2358 + }
2359 + execsql {SELECT c, i FROM altered_recover ORDER BY rowid}
2360 +} {a {} b {} c {} d 5}
2361 +
2362 +# Can skip those NULL columns like if they contained a real NULL.
2363 +do_test recover-alter-1.2 {
2364 + db eval {
2365 + DROP TABLE IF EXISTS temp.altered_recover;
2366 + CREATE VIRTUAL TABLE temp.altered_recover USING recover(
2367 + altered,
2368 + c TEXT,
2369 + i INTEGER NOT NULL
2370 + );
2371 + }
2372 + execsql {SELECT c, i FROM altered_recover ORDER BY rowid}
2373 +} {d 5}
2374 +
2375 +if {0} {
2376 +# It would be neat if this could work. I tried putting "DEFAULT ..."
2377 +# in the schema exposed by the recover table, but it doesn't do the
2378 +# trick.
2379 +do_test recover-alter-1.2 {
2380 + db eval {
2381 + DROP TABLE IF EXISTS temp.altered_recover;
2382 + CREATE VIRTUAL TABLE temp.altered_recover USING recover(
2383 + altered,
2384 + c TEXT,
2385 + i INTEGER NOT NULL DEFAULT 10
2386 + );
2387 + }
2388 + execsql {SELECT c, i FROM altered_recover ORDER BY rowid}
2389 +} {a 10 b 10 c 10 d 5}
2390 +}
2391 +
2392 +# Helper function to generate an arbitrarily-sized table.
2393 +proc generate {table base count} {
2394 + db eval "DROP TABLE IF EXISTS $table"
2395 + db transaction immediate {
2396 + db eval "CREATE TABLE $table (t TEXT,n INT)"
2397 + for {set i 0} {$i<$count} {incr i} {
2398 + set t [concat $base $i]
2399 + db eval [concat {INSERT INTO} $table {VALUES ($t, $i)}]
2400 + }
2401 + }
2402 +}
2403 +
2404 +# Leaf-only database parses.
2405 +do_test recover-leaf-1.0 {
2406 + db close
2407 + sqlite3 db test.db
2408 + generate "leaf" "Leaf-node-generating line " 10
2409 +
2410 + db eval {
2411 + DROP TABLE IF EXISTS temp.leaf_recover;
2412 + CREATE VIRTUAL TABLE temp.leaf_recover USING recover(
2413 + leaf,
2414 + t TEXT,
2415 + n INTEGER
2416 + );
2417 + }
2418 + execsql {SELECT t, n FROM leaf_recover ORDER BY rowid}
2419 +} {{Leaf-node-generating line 0} 0 {Leaf-node-generating line 1} 1 {Leaf-node-g enerating line 2} 2 {Leaf-node-generating line 3} 3 {Leaf-node-generating line 4 } 4 {Leaf-node-generating line 5} 5 {Leaf-node-generating line 6} 6 {Leaf-node-g enerating line 7} 7 {Leaf-node-generating line 8} 8 {Leaf-node-generating line 9 } 9}
2420 +
2421 +# Single level of interior node.
2422 +do_test recover-interior-1.0 {
2423 + db close
2424 + sqlite3 db test.db
2425 + generate "interior" "Interior-node-generating line " 100
2426 +
2427 + db eval {
2428 + DROP TABLE IF EXISTS temp.interior_recover;
2429 + CREATE VIRTUAL TABLE temp.interior_recover USING recover(
2430 + interior,
2431 + t TEXT,
2432 + n INTEGER
2433 + );
2434 + }
2435 + execsql {SELECT t, n FROM interior_recover WHERE (rowid%10)=0 ORDER BY rowid}
2436 +} {{Interior-node-generating line 9} 9 {Interior-node-generating line 19} 19 {I nterior-node-generating line 29} 29 {Interior-node-generating line 39} 39 {Inter ior-node-generating line 49} 49 {Interior-node-generating line 59} 59 {Interior- node-generating line 69} 69 {Interior-node-generating line 79} 79 {Interior-node -generating line 89} 89 {Interior-node-generating line 99} 99}
2437 +
2438 +# Multiple levels of interior node.
2439 +do_test recover-interior-2.0 {
2440 + db close
2441 + sqlite3 db test.db
2442 + generate "interior2" "Interior-node-generating line " 5000
2443 +
2444 + db eval {
2445 + DROP TABLE IF EXISTS temp.interior2_recover;
2446 + CREATE VIRTUAL TABLE temp.interior2_recover USING recover(
2447 + interior2,
2448 + t TEXT,
2449 + n INTEGER
2450 + );
2451 + }
2452 + execsql {SELECT t, n FROM interior2_recover WHERE (rowid%500)=0 ORDER BY rowi d}
2453 +} {{Interior-node-generating line 499} 499 {Interior-node-generating line 999} 999 {Interior-node-generating line 1499} 1499 {Interior-node-generating line 199 9} 1999 {Interior-node-generating line 2499} 2499 {Interior-node-generating line 2999} 2999 {Interior-node-generating line 3499} 3499 {Interior-node-generating line 3999} 3999 {Interior-node-generating line 4499} 4499 {Interior-node-generat ing line 4999} 4999}
2454 +
2455 +finish_test
2456 diff --git a/third_party/sqlite/src/test/recover0.test b/third_party/sqlite/src/ test/recover0.test
2457 new file mode 100644
2458 index 0000000..aac2ed9
2459 --- /dev/null
2460 +++ b/third_party/sqlite/src/test/recover0.test
2461 @@ -0,0 +1,532 @@
2462 +# 2012 January 4 {}
2463 +#
2464 +# The author disclaims copyright to this source code. In place of
2465 +# a legal notice, here is a blessing:
2466 +#
2467 +# May you do good and not evil.
2468 +# May you find forgiveness for yourself and forgive others.
2469 +# May you share freely, never taking more than you give.
2470 +#
2471 +#***********************************************************************
2472 +# This file implements regression tests for SQLite library.
2473 +#
2474 +# Test recover module syntax.
2475 +#
2476 +# $Id$
2477 +
2478 +# TODO(shess): Test with attached databases.
2479 +
2480 +# TODO(shess): Handle column mismatches? As things stand, the code
2481 +# only needs to pull the root page, so that may not be completely
2482 +# feasible.
2483 +
2484 +set testdir [file dirname $argv0]
2485 +source $testdir/tester.tcl
2486 +
2487 +db eval {
2488 + DROP TABLE IF EXISTS backing;
2489 + CREATE TABLE backing (t TEXT);
2490 +
2491 + DROP TABLE IF EXISTS backing2;
2492 + CREATE TABLE backing2 (id INTEGER PRIMARY KEY, t TEXT);
2493 +}
2494 +
2495 +# Baseline create works.
2496 +do_test recover-syntax-0.0 {
2497 + db eval {DROP TABLE IF EXISTS temp.syntax}
2498 + catchsql {
2499 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2500 + backing,
2501 + t TEXT
2502 + );
2503 + }
2504 +} {0 {}}
2505 +
2506 +# Can specify database.
2507 +do_test recover-syntax-0.1 {
2508 + db eval {DROP TABLE IF EXISTS temp.syntax}
2509 + catchsql {
2510 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2511 + main.backing,
2512 + t TEXT
2513 + );
2514 + }
2515 +} {0 {}}
2516 +
2517 +# Can specify sqlite_master.
2518 +do_test recover-syntax-0.2 {
2519 + db eval {DROP TABLE IF EXISTS temp.syntax}
2520 + catchsql {
2521 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2522 + sqlite_master,
2523 + type TEXT,
2524 + name TEXT,
2525 + tbl_name TEXT,
2526 + rootpage INTEGER,
2527 + sql TEXT
2528 + );
2529 + }
2530 +} {0 {}}
2531 +
2532 +# Fails if virtual table is not in the temp database.
2533 +do_test recover-syntax-1.0 {
2534 + db eval {DROP TABLE IF EXISTS temp.syntax;}
2535 + catchsql {
2536 + CREATE VIRTUAL TABLE syntax USING recover(
2537 + backing,
2538 + t TEXT
2539 + );
2540 + }
2541 +} {1 {recover table must be in temp database}}
2542 +
2543 +# Fails if mentions missing table.
2544 +do_test recover-syntax-2.0 {
2545 + db eval {DROP TABLE IF EXISTS temp.syntax;}
2546 + catchsql {
2547 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2548 + snacking,
2549 + t TEXT
2550 + );
2551 + }
2552 +} {1 {unable to find backing table}}
2553 +
2554 +# Fails if mentions missing database.
2555 +do_test recover-syntax-2.1 {
2556 + db eval {DROP TABLE IF EXISTS temp.syntax;}
2557 + catchsql {
2558 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2559 + db.backing,
2560 + t TEXT
2561 + );
2562 + }
2563 +} {1 {unable to find backing table}}
2564 +
2565 +# Fails if mentions garbage backing.
2566 +do_test recover-syntax-2.2 {
2567 + db eval {DROP TABLE IF EXISTS temp.syntax;}
2568 + catchsql {
2569 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2570 + main.backing excess,
2571 + t TEXT
2572 + );
2573 + }
2574 +} {1 {unable to find backing table}}
2575 +
2576 +# Database only fails.
2577 +do_test recover-syntax-2.3 {
2578 + db eval {DROP TABLE IF EXISTS temp.syntax;}
2579 + catchsql {
2580 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2581 + main.,
2582 + t TEXT
2583 + );
2584 + }
2585 +} {1 {ill-formed table specifier}}
2586 +
2587 +# Table only fails.
2588 +do_test recover-syntax-2.4 {
2589 + db eval {DROP TABLE IF EXISTS temp.syntax;}
2590 + catchsql {
2591 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2592 + .backing,
2593 + t TEXT
2594 + );
2595 + }
2596 +} {1 {ill-formed table specifier}}
2597 +
2598 +# Manifest typing.
2599 +do_test recover-syntax-3.0 {
2600 + db eval {DROP TABLE IF EXISTS temp.syntax}
2601 + execsql {
2602 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2603 + backing,
2604 + t
2605 + );
2606 + PRAGMA table_info(syntax);
2607 + }
2608 +} {0 t {} 0 {} 0}
2609 +
2610 +# ANY as an alternative for manifest typing.
2611 +do_test recover-syntax-3.1 {
2612 + db eval {DROP TABLE IF EXISTS temp.syntax}
2613 + execsql {
2614 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2615 + backing,
2616 + t ANY
2617 + );
2618 + PRAGMA table_info(syntax);
2619 + }
2620 +} {0 t {} 0 {} 0}
2621 +
2622 +# ANY NOT NULL
2623 +do_test recover-syntax-3.2 {
2624 + db eval {DROP TABLE IF EXISTS temp.syntax}
2625 + execsql {
2626 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2627 + backing,
2628 + t ANY NOT NULL
2629 + );
2630 + PRAGMA table_info(syntax);
2631 + }
2632 +} {0 t {} 1 {} 0}
2633 +
2634 +# ANY STRICT is not sensible.
2635 +do_test recover-syntax-3.3 {
2636 + db eval {DROP TABLE IF EXISTS temp.syntax}
2637 + catchsql {
2638 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2639 + backing,
2640 + v ANY STRICT
2641 + );
2642 + PRAGMA table_info(syntax);
2643 + }
2644 +} {1 {unable to parse column 0}}
2645 +
2646 +# TEXT column by type works.
2647 +do_test recover-syntax-4.0 {
2648 + db eval {DROP TABLE IF EXISTS temp.syntax}
2649 + execsql {
2650 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2651 + backing,
2652 + t TEXT
2653 + );
2654 + PRAGMA table_info(syntax);
2655 + }
2656 +} {0 t TEXT 0 {} 0}
2657 +
2658 +# TEXT NOT NULL
2659 +do_test recover-syntax-4.1 {
2660 + db eval {DROP TABLE IF EXISTS temp.syntax}
2661 + execsql {
2662 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2663 + backing,
2664 + t TEXT NOT NULL
2665 + );
2666 + PRAGMA table_info(syntax);
2667 + }
2668 +} {0 t TEXT 1 {} 0}
2669 +
2670 +# TEXT STRICT
2671 +do_test recover-syntax-4.2 {
2672 + db eval {DROP TABLE IF EXISTS temp.syntax}
2673 + execsql {
2674 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2675 + backing,
2676 + t TEXT STRICT
2677 + );
2678 + PRAGMA table_info(syntax);
2679 + }
2680 +} {0 t TEXT 0 {} 0}
2681 +
2682 +# TEXT STRICT NOT NULL
2683 +do_test recover-syntax-4.3 {
2684 + db eval {DROP TABLE IF EXISTS temp.syntax}
2685 + execsql {
2686 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2687 + backing,
2688 + t TEXT STRICT NOT NULL
2689 + );
2690 + PRAGMA table_info(syntax);
2691 + }
2692 +} {0 t TEXT 1 {} 0}
2693 +
2694 +# INTEGER
2695 +do_test recover-syntax-5.0 {
2696 + db eval {DROP TABLE IF EXISTS temp.syntax}
2697 + execsql {
2698 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2699 + backing,
2700 + i INTEGER
2701 + );
2702 + PRAGMA table_info(syntax);
2703 + }
2704 +} {0 i INTEGER 0 {} 0}
2705 +
2706 +# INTEGER NOT NULL
2707 +do_test recover-syntax-5.1 {
2708 + db eval {DROP TABLE IF EXISTS temp.syntax}
2709 + execsql {
2710 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2711 + backing,
2712 + i INTEGER NOT NULL
2713 + );
2714 + PRAGMA table_info(syntax);
2715 + }
2716 +} {0 i INTEGER 1 {} 0}
2717 +
2718 +# INTEGER STRICT
2719 +do_test recover-syntax-5.2 {
2720 + db eval {DROP TABLE IF EXISTS temp.syntax}
2721 + execsql {
2722 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2723 + backing,
2724 + i INTEGER STRICT
2725 + );
2726 + PRAGMA table_info(syntax);
2727 + }
2728 +} {0 i INTEGER 0 {} 0}
2729 +
2730 +# INTEGER STRICT NOT NULL
2731 +do_test recover-syntax-5.3 {
2732 + db eval {DROP TABLE IF EXISTS temp.syntax}
2733 + execsql {
2734 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2735 + backing,
2736 + i INTEGER STRICT NOT NULL
2737 + );
2738 + PRAGMA table_info(syntax);
2739 + }
2740 +} {0 i INTEGER 1 {} 0}
2741 +
2742 +# BLOB
2743 +do_test recover-syntax-6.0 {
2744 + db eval {DROP TABLE IF EXISTS temp.syntax}
2745 + execsql {
2746 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2747 + backing,
2748 + b BLOB
2749 + );
2750 + PRAGMA table_info(syntax);
2751 + }
2752 +} {0 b BLOB 0 {} 0}
2753 +
2754 +# BLOB NOT NULL
2755 +do_test recover-syntax-6.1 {
2756 + db eval {DROP TABLE IF EXISTS temp.syntax}
2757 + execsql {
2758 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2759 + backing,
2760 + b BLOB NOT NULL
2761 + );
2762 + PRAGMA table_info(syntax);
2763 + }
2764 +} {0 b BLOB 1 {} 0}
2765 +
2766 +# BLOB STRICT
2767 +do_test recover-syntax-6.2 {
2768 + db eval {DROP TABLE IF EXISTS temp.syntax}
2769 + execsql {
2770 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2771 + backing,
2772 + b BLOB STRICT
2773 + );
2774 + PRAGMA table_info(syntax);
2775 + }
2776 +} {0 b BLOB 0 {} 0}
2777 +
2778 +# BLOB STRICT NOT NULL
2779 +do_test recover-syntax-6.3 {
2780 + db eval {DROP TABLE IF EXISTS temp.syntax}
2781 + execsql {
2782 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2783 + backing,
2784 + b BLOB STRICT NOT NULL
2785 + );
2786 + PRAGMA table_info(syntax);
2787 + }
2788 +} {0 b BLOB 1 {} 0}
2789 +
2790 +# FLOAT
2791 +do_test recover-syntax-7.0 {
2792 + db eval {DROP TABLE IF EXISTS temp.syntax}
2793 + execsql {
2794 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2795 + backing,
2796 + f FLOAT
2797 + );
2798 + PRAGMA table_info(syntax);
2799 + }
2800 +} {0 f FLOAT 0 {} 0}
2801 +
2802 +# FLOAT NOT NULL
2803 +do_test recover-syntax-7.1 {
2804 + db eval {DROP TABLE IF EXISTS temp.syntax}
2805 + execsql {
2806 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2807 + backing,
2808 + f FLOAT NOT NULL
2809 + );
2810 + PRAGMA table_info(syntax);
2811 + }
2812 +} {0 f FLOAT 1 {} 0}
2813 +
2814 +# FLOAT STRICT
2815 +do_test recover-syntax-7.2 {
2816 + db eval {DROP TABLE IF EXISTS temp.syntax}
2817 + execsql {
2818 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2819 + backing,
2820 + f FLOAT STRICT
2821 + );
2822 + PRAGMA table_info(syntax);
2823 + }
2824 +} {0 f FLOAT 0 {} 0}
2825 +
2826 +# FLOAT STRICT NOT NULL
2827 +do_test recover-syntax-7.3 {
2828 + db eval {DROP TABLE IF EXISTS temp.syntax}
2829 + execsql {
2830 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2831 + backing,
2832 + f FLOAT STRICT NOT NULL
2833 + );
2834 + PRAGMA table_info(syntax);
2835 + }
2836 +} {0 f FLOAT 1 {} 0}
2837 +
2838 +# NUMERIC
2839 +do_test recover-syntax-8.0 {
2840 + db eval {DROP TABLE IF EXISTS temp.syntax}
2841 + execsql {
2842 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2843 + backing,
2844 + f NUMERIC
2845 + );
2846 + PRAGMA table_info(syntax);
2847 + }
2848 +} {0 f NUMERIC 0 {} 0}
2849 +
2850 +# NUMERIC NOT NULL
2851 +do_test recover-syntax-8.1 {
2852 + db eval {DROP TABLE IF EXISTS temp.syntax}
2853 + execsql {
2854 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2855 + backing,
2856 + f NUMERIC NOT NULL
2857 + );
2858 + PRAGMA table_info(syntax);
2859 + }
2860 +} {0 f NUMERIC 1 {} 0}
2861 +
2862 +# NUMERIC STRICT
2863 +do_test recover-syntax-8.2 {
2864 + db eval {DROP TABLE IF EXISTS temp.syntax}
2865 + execsql {
2866 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2867 + backing,
2868 + f NUMERIC STRICT
2869 + );
2870 + PRAGMA table_info(syntax);
2871 + }
2872 +} {0 f NUMERIC 0 {} 0}
2873 +
2874 +# NUMERIC STRICT NOT NULL
2875 +do_test recover-syntax-8.3 {
2876 + db eval {DROP TABLE IF EXISTS temp.syntax}
2877 + execsql {
2878 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2879 + backing,
2880 + f NUMERIC STRICT NOT NULL
2881 + );
2882 + PRAGMA table_info(syntax);
2883 + }
2884 +} {0 f NUMERIC 1 {} 0}
2885 +
2886 +# ROWID
2887 +do_test recover-syntax-9.0 {
2888 + db eval {DROP TABLE IF EXISTS temp.syntax}
2889 + execsql {
2890 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2891 + backing2,
2892 + id ROWID,
2893 + v
2894 + );
2895 + PRAGMA table_info(syntax);
2896 + }
2897 +} {0 id INTEGER 1 {} 0 1 v {} 0 {} 0}
2898 +
2899 +# ROWID NOT NULL (is default)
2900 +do_test recover-syntax-9.1 {
2901 + db eval {DROP TABLE IF EXISTS temp.syntax}
2902 + execsql {
2903 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2904 + backing2,
2905 + id ROWID NOT NULL,
2906 + v
2907 + );
2908 + PRAGMA table_info(syntax);
2909 + }
2910 +} {0 id INTEGER 1 {} 0 1 v {} 0 {} 0}
2911 +
2912 +# ROWID STRICT
2913 +do_test recover-syntax-9.0 {
2914 + db eval {DROP TABLE IF EXISTS temp.syntax}
2915 + execsql {
2916 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2917 + backing2,
2918 + id ROWID STRICT,
2919 + v
2920 + );
2921 + PRAGMA table_info(syntax);
2922 + }
2923 +} {0 id INTEGER 1 {} 0 1 v {} 0 {} 0}
2924 +
2925 +# ROWID STRICT NOT NULL (is default)
2926 +do_test recover-syntax-9.1 {
2927 + db eval {DROP TABLE IF EXISTS temp.syntax}
2928 + execsql {
2929 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2930 + backing2,
2931 + id ROWID STRICT NOT NULL,
2932 + v
2933 + );
2934 + PRAGMA table_info(syntax);
2935 + }
2936 +} {0 id INTEGER 1 {} 0 1 v {} 0 {} 0}
2937 +
2938 +# Invalid type info is not ignored.
2939 +do_test recover-syntax-10.0 {
2940 + db eval {DROP TABLE IF EXISTS temp.syntax}
2941 + catchsql {
2942 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2943 + backing,
2944 + v GARBAGE
2945 + );
2946 + }
2947 +} {1 {unable to parse column 0}}
2948 +
2949 +# Extraneous type info is not ignored.
2950 +do_test recover-syntax-10.1 {
2951 + db eval {DROP TABLE IF EXISTS temp.syntax}
2952 + catchsql {
2953 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2954 + backing,
2955 + v INTEGER GARBAGE
2956 + );
2957 + }
2958 +} {1 {unable to parse column 0}}
2959 +
2960 +# Extraneous type info is not ignored.
2961 +do_test recover-syntax-10.2 {
2962 + db eval {DROP TABLE IF EXISTS temp.syntax}
2963 + catchsql {
2964 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2965 + backing,
2966 + v INTEGER NOT NULL GARBAGE
2967 + );
2968 + }
2969 +} {1 {unable to parse column 0}}
2970 +
2971 +# Multiple types don't work.
2972 +do_test recover-syntax-10.3 {
2973 + db eval {DROP TABLE IF EXISTS temp.syntax}
2974 + catchsql {
2975 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2976 + backing,
2977 + v INTEGER FLOAT BLOB
2978 + );
2979 + }
2980 +} {1 {unable to parse column 0}}
2981 +
2982 +# Multiple types don't work.
2983 +do_test recover-syntax-10.4 {
2984 + db eval {DROP TABLE IF EXISTS temp.syntax}
2985 + catchsql {
2986 + CREATE VIRTUAL TABLE temp.syntax USING recover(
2987 + backing,
2988 + v INTEGER NOT NULL TEXT
2989 + );
2990 + }
2991 +} {1 {unable to parse column 0}}
2992 +
2993 +finish_test
2994 diff --git a/third_party/sqlite/src/test/recover1.test b/third_party/sqlite/src/ test/recover1.test
2995 new file mode 100644
2996 index 0000000..1d90f09
2997 --- /dev/null
2998 +++ b/third_party/sqlite/src/test/recover1.test
2999 @@ -0,0 +1,429 @@
3000 +# 2012 January 4 {}
3001 +#
3002 +# The author disclaims copyright to this source code. In place of
3003 +# a legal notice, here is a blessing:
3004 +#
3005 +# May you do good and not evil.
3006 +# May you find forgiveness for yourself and forgive others.
3007 +# May you share freely, never taking more than you give.
3008 +#
3009 +#***********************************************************************
3010 +# This file implements regression tests for SQLite library.
3011 +#
3012 +# Use tables to test leaf-node reading, and also type checking.
3013 +#
3014 +# $Id$
3015 +
3016 +set testdir [file dirname $argv0]
3017 +source $testdir/tester.tcl
3018 +
3019 +# A really basic table with manifest typing and a row of each type.
3020 +db close
3021 +sqlite3 db test.db
3022 +db eval {
3023 + DROP TABLE IF EXISTS types;
3024 + CREATE TABLE types (rowtype TEXT, value);
3025 + INSERT INTO types VALUES ("NULL", NULL);
3026 + INSERT INTO types VALUES ("INTEGER", 17);
3027 + INSERT INTO types VALUES ("FLOAT", 3.1415927);
3028 + INSERT INTO types VALUES ("TEXT", "This is text");
3029 + INSERT INTO types VALUES ("BLOB", CAST("This is a blob" AS BLOB));
3030 +
3031 + -- Same contents, with an alias for rowid. Testing separately
3032 + -- because it changes the structure of the data (the alias column is
3033 + -- serialized as NULL).
3034 + DROP TABLE IF EXISTS types2;
3035 + CREATE TABLE types2 (id INTEGER PRIMARY KEY, rowtype TEXT, value);
3036 + INSERT INTO types2 (id, rowtype, value)
3037 + SELECT rowid, rowtype, value FROM types;
3038 +}
3039 +
3040 +# Baseline results.
3041 +do_test recover-types-0.0 {
3042 + execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types}
3043 +} {1 NULL {} null 2 INTEGER 17 integer 3 FLOAT 3.1415927 real 4 TEXT {This is t ext} text 5 BLOB {This is a blob} blob}
3044 +
3045 +# With no restrictions, recover table shows identical results.
3046 +do_test recover-types-0.1 {
3047 + db eval {
3048 + DROP TABLE IF EXISTS temp.types_recover;
3049 + CREATE VIRTUAL TABLE temp.types_recover USING recover(
3050 + types,
3051 + rowtype TEXT,
3052 + value
3053 + );
3054 + }
3055 + execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
3056 +} {1 NULL {} null 2 INTEGER 17 integer 3 FLOAT 3.1415927 real 4 TEXT {This is t ext} text 5 BLOB {This is a blob} blob}
3057 +
3058 +# Restrict by INTEGER
3059 +do_test recover-types-1.0 {
3060 + db eval {
3061 + DROP TABLE IF EXISTS temp.types_recover;
3062 + CREATE VIRTUAL TABLE temp.types_recover USING recover(
3063 + types,
3064 + rowtype TEXT,
3065 + value INTEGER
3066 + );
3067 + }
3068 + execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
3069 +} {1 NULL {} null 2 INTEGER 17 integer}
3070 +
3071 +# Restrict by INTEGER NOT NULL
3072 +do_test recover-types-1.1 {
3073 + db eval {
3074 + DROP TABLE IF EXISTS temp.types_recover;
3075 + CREATE VIRTUAL TABLE temp.types_recover USING recover(
3076 + types,
3077 + rowtype TEXT,
3078 + value INTEGER NOT NULL
3079 + );
3080 + }
3081 + execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
3082 +} {2 INTEGER 17 integer}
3083 +
3084 +# Restrict by FLOAT
3085 +do_test recover-types-2.0 {
3086 + db eval {
3087 + DROP TABLE IF EXISTS temp.types_recover;
3088 + CREATE VIRTUAL TABLE temp.types_recover USING recover(
3089 + types,
3090 + rowtype TEXT,
3091 + value FLOAT
3092 + );
3093 + }
3094 + execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
3095 +} {1 NULL {} null 2 INTEGER 17.0 real 3 FLOAT 3.1415927 real}
3096 +
3097 +# Restrict by FLOAT NOT NULL
3098 +do_test recover-types-2.1 {
3099 + db eval {
3100 + DROP TABLE IF EXISTS temp.types_recover;
3101 + CREATE VIRTUAL TABLE temp.types_recover USING recover(
3102 + types,
3103 + rowtype TEXT,
3104 + value FLOAT NOT NULL
3105 + );
3106 + }
3107 + execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
3108 +} {2 INTEGER 17.0 real 3 FLOAT 3.1415927 real}
3109 +
3110 +# Restrict by FLOAT STRICT
3111 +do_test recover-types-2.2 {
3112 + db eval {
3113 + DROP TABLE IF EXISTS temp.types_recover;
3114 + CREATE VIRTUAL TABLE temp.types_recover USING recover(
3115 + types,
3116 + rowtype TEXT,
3117 + value FLOAT STRICT
3118 + );
3119 + }
3120 + execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
3121 +} {1 NULL {} null 3 FLOAT 3.1415927 real}
3122 +
3123 +# Restrict by FLOAT STRICT NOT NULL
3124 +do_test recover-types-2.3 {
3125 + db eval {
3126 + DROP TABLE IF EXISTS temp.types_recover;
3127 + CREATE VIRTUAL TABLE temp.types_recover USING recover(
3128 + types,
3129 + rowtype TEXT,
3130 + value FLOAT STRICT NOT NULL
3131 + );
3132 + }
3133 + execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
3134 +} {3 FLOAT 3.1415927 real}
3135 +
3136 +# Restrict by TEXT
3137 +do_test recover-types-3.0 {
3138 + db eval {
3139 + DROP TABLE IF EXISTS temp.types_recover;
3140 + CREATE VIRTUAL TABLE temp.types_recover USING recover(
3141 + types,
3142 + rowtype TEXT,
3143 + value TEXT
3144 + );
3145 + }
3146 + execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
3147 +} {1 NULL {} null 4 TEXT {This is text} text 5 BLOB {This is a blob} blob}
3148 +
3149 +# Restrict by TEXT NOT NULL
3150 +do_test recover-types-3.1 {
3151 + db eval {
3152 + DROP TABLE IF EXISTS temp.types_recover;
3153 + CREATE VIRTUAL TABLE temp.types_recover USING recover(
3154 + types,
3155 + rowtype TEXT,
3156 + value TEXT NOT NULL
3157 + );
3158 + }
3159 + execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
3160 +} {4 TEXT {This is text} text 5 BLOB {This is a blob} blob}
3161 +
3162 +# Restrict by TEXT STRICT
3163 +do_test recover-types-3.2 {
3164 + db eval {
3165 + DROP TABLE IF EXISTS temp.types_recover;
3166 + CREATE VIRTUAL TABLE temp.types_recover USING recover(
3167 + types,
3168 + rowtype TEXT,
3169 + value TEXT STRICT
3170 + );
3171 + }
3172 + execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
3173 +} {1 NULL {} null 4 TEXT {This is text} text}
3174 +
3175 +# Restrict by TEXT STRICT NOT NULL
3176 +do_test recover-types-3.3 {
3177 + db eval {
3178 + DROP TABLE IF EXISTS temp.types_recover;
3179 + CREATE VIRTUAL TABLE temp.types_recover USING recover(
3180 + types,
3181 + rowtype TEXT,
3182 + value TEXT STRICT NOT NULL
3183 + );
3184 + }
3185 + execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
3186 +} {4 TEXT {This is text} text}
3187 +
3188 +# Restrict by BLOB
3189 +do_test recover-types-4.0 {
3190 + db eval {
3191 + DROP TABLE IF EXISTS temp.types_recover;
3192 + CREATE VIRTUAL TABLE temp.types_recover USING recover(
3193 + types,
3194 + rowtype TEXT,
3195 + value BLOB
3196 + );
3197 + }
3198 + execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
3199 +} {1 NULL {} null 5 BLOB {This is a blob} blob}
3200 +
3201 +# Restrict by BLOB NOT NULL
3202 +do_test recover-types-4.1 {
3203 + db eval {
3204 + DROP TABLE IF EXISTS temp.types_recover;
3205 + CREATE VIRTUAL TABLE temp.types_recover USING recover(
3206 + types,
3207 + rowtype TEXT,
3208 + value BLOB NOT NULL
3209 + );
3210 + }
3211 + execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
3212 +} {5 BLOB {This is a blob} blob}
3213 +
3214 +# Manifest typing.
3215 +do_test recover-types-5.0 {
3216 + db eval {
3217 + DROP TABLE IF EXISTS temp.types_recover;
3218 + CREATE VIRTUAL TABLE temp.types_recover USING recover(
3219 + types,
3220 + rowtype TEXT,
3221 + value
3222 + );
3223 + }
3224 + execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
3225 +} {1 NULL {} null 2 INTEGER 17 integer 3 FLOAT 3.1415927 real 4 TEXT {This is t ext} text 5 BLOB {This is a blob} blob}
3226 +
3227 +# Should get same results specifying manifest typing explicitly.
3228 +do_test recover-types-5.1 {
3229 + db eval {
3230 + DROP TABLE IF EXISTS temp.types_recover;
3231 + CREATE VIRTUAL TABLE temp.types_recover USING recover(
3232 + types,
3233 + rowtype TEXT,
3234 + value ANY
3235 + );
3236 + }
3237 + execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
3238 +} {1 NULL {} null 2 INTEGER 17 integer 3 FLOAT 3.1415927 real 4 TEXT {This is t ext} text 5 BLOB {This is a blob} blob}
3239 +
3240 +# Same results, skipping the NULL row.
3241 +do_test recover-types-5.2 {
3242 + db eval {
3243 + DROP TABLE IF EXISTS temp.types_recover;
3244 + CREATE VIRTUAL TABLE temp.types_recover USING recover(
3245 + types,
3246 + rowtype TEXT,
3247 + value ANY NOT NULL
3248 + );
3249 + }
3250 + execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
3251 +} {2 INTEGER 17 integer 3 FLOAT 3.1415927 real 4 TEXT {This is text} text 5 BLO B {This is a blob} blob}
3252 +
3253 +# Test ROWID values.
3254 +do_test recover-types-6.0 {
3255 + db eval {
3256 + DROP TABLE IF EXISTS temp.types2_recover;
3257 + CREATE VIRTUAL TABLE temp.types2_recover USING recover(
3258 + types2,
3259 + id ROWID,
3260 + rowtype TEXT,
3261 + value
3262 + );
3263 + }
3264 + execsql {SELECT rowid, id, rowtype, value, TYPEOF(value) FROM types2_recover}
3265 +} {1 1 NULL {} null 2 2 INTEGER 17 integer 3 3 FLOAT 3.1415927 real 4 4 TEXT {T his is text} text 5 5 BLOB {This is a blob} blob}
3266 +
3267 +# ROWID NOT NULL is identical.
3268 +do_test recover-types-6.1 {
3269 + db eval {
3270 + DROP TABLE IF EXISTS temp.types2_recover;
3271 + CREATE VIRTUAL TABLE temp.types2_recover USING recover(
3272 + types2,
3273 + id ROWID NOT NULL,
3274 + rowtype TEXT,
3275 + value
3276 + );
3277 + }
3278 + execsql {SELECT rowid, id, rowtype, value, TYPEOF(value) FROM types2_recover}
3279 +} {1 1 NULL {} null 2 2 INTEGER 17 integer 3 3 FLOAT 3.1415927 real 4 4 TEXT {T his is text} text 5 5 BLOB {This is a blob} blob}
3280 +
3281 +# Check that each of the possible integer sizes is being decoded.
3282 +# TODO(shess): It would be neat to ACTUALLY test these things. As-is,
3283 +# this should exercise the code paths, but one needs logging or a
3284 +# debugger to verify that things are stored as expected.
3285 +do_test recover-types-7.0 {
3286 + db eval {
3287 + DROP TABLE IF EXISTS integers;
3288 + CREATE TABLE integers (value);
3289 +
3290 + -- encoded directly in type info.
3291 + INSERT INTO integers VALUES (0);
3292 + INSERT INTO integers VALUES (1);
3293 +
3294 + -- 8-bit signed.
3295 + INSERT INTO integers VALUES (2);
3296 + INSERT INTO integers VALUES (-2);
3297 + INSERT INTO integers VALUES (127);
3298 + INSERT INTO integers VALUES (-128);
3299 +
3300 + -- 16-bit signed.
3301 + INSERT INTO integers VALUES (12345);
3302 + INSERT INTO integers VALUES (-12345);
3303 + INSERT INTO integers VALUES (32767);
3304 + INSERT INTO integers VALUES (-32768);
3305 +
3306 + -- 24-bit signed.
3307 + INSERT INTO integers VALUES (1234567);
3308 + INSERT INTO integers VALUES (-1234567);
3309 + INSERT INTO integers VALUES (8388607);
3310 + INSERT INTO integers VALUES (-8388608);
3311 +
3312 + -- 32-bit signed.
3313 + INSERT INTO integers VALUES (1234567890);
3314 + INSERT INTO integers VALUES (-1234567890);
3315 + INSERT INTO integers VALUES (2147483647);
3316 + INSERT INTO integers VALUES (-2147483648);
3317 +
3318 + -- 48-bit signed.
3319 + INSERT INTO integers VALUES (123456789012345);
3320 + INSERT INTO integers VALUES (-123456789012345);
3321 + INSERT INTO integers VALUES (140737488355327);
3322 + INSERT INTO integers VALUES (-140737488355328);
3323 +
3324 + -- 64-bit signed.
3325 + INSERT INTO integers VALUES (9223372036854775807);
3326 + INSERT INTO integers VALUES (-9223372036854775808);
3327 +
3328 + DROP TABLE IF EXISTS integers_recover;
3329 + CREATE VIRTUAL TABLE temp.integers_recover USING recover(
3330 + integers,
3331 + value INTEGER
3332 + );
3333 + }
3334 + execsql {SELECT rowid, value FROM integers_recover}
3335 +} {1 0 2 1 3 2 4 -2 5 127 6 -128 7 12345 8 -12345 9 32767 10 -32768 11 1234567 12 -1234567 13 8388607 14 -8388608 15 1234567890 16 -1234567890 17 2147483647 18 -2147483648 19 123456789012345 20 -123456789012345 21 140737488355327 22 -14073 7488355328 23 9223372036854775807 24 -9223372036854775808}
3336 +
3337 +# If UTF16 support is disabled, ignore the rest of the tests.
3338 +#
3339 +ifcapable {!utf16} {
3340 + finish_test
3341 + return
3342 +}
3343 +
3344 +# Baseline UTF-8.
3345 +file delete -force test.db
3346 +sqlite3 db test.db;
3347 +db eval {
3348 + PRAGMA encoding = 'UTF-8';
3349 +}
3350 +
3351 +do_test recover-encoding-1.0 {
3352 + execsql {
3353 + DROP TABLE IF EXISTS e;
3354 + CREATE TABLE e (v TEXT);
3355 + INSERT INTO e VALUES('Mjollnir');
3356 + INSERT INTO e VALUES('Mjölnir');
3357 + INSERT INTO e VALUES('Mjǫlnir');
3358 + INSERT INTO e VALUES('Mjölner');
3359 + INSERT INTO e VALUES('Mjølner');
3360 + INSERT INTO e VALUES('ハンマー');
3361 + PRAGMA encoding;
3362 +
3363 + DROP TABLE IF EXISTS e_recover;
3364 + CREATE VIRTUAL TABLE temp.e_recover USING recover(
3365 + e,
3366 + v TEXT
3367 + );
3368 + SELECT rowid, v FROM e_recover ORDER BY rowid;
3369 + }
3370 +} {UTF-8 1 Mjollnir 2 Mjölnir 3 Mjǫlnir 4 Mjölner 5 Mjølner 6 ハンマー}
3371 +
3372 +# Reset the database to UTF-16LE.
3373 +file delete -force test.db
3374 +sqlite3 db test.db;
3375 +db eval {
3376 + PRAGMA encoding = 'UTF-16LE';
3377 +}
3378 +
3379 +do_test recover-encoding-2.0 {
3380 + execsql {
3381 + DROP TABLE IF EXISTS e;
3382 + CREATE TABLE e (v TEXT);
3383 + INSERT INTO e VALUES('Mjollnir');
3384 + INSERT INTO e VALUES('Mjölnir');
3385 + INSERT INTO e VALUES('Mjǫlnir');
3386 + INSERT INTO e VALUES('Mjölner');
3387 + INSERT INTO e VALUES('Mjølner');
3388 + INSERT INTO e VALUES('ハンマー');
3389 + PRAGMA encoding;
3390 +
3391 + DROP TABLE IF EXISTS e_recover;
3392 + CREATE VIRTUAL TABLE temp.e_recover USING recover(
3393 + e,
3394 + v TEXT
3395 + );
3396 + SELECT rowid, v FROM e_recover ORDER BY rowid;
3397 + }
3398 +} {UTF-16le 1 Mjollnir 2 Mjölnir 3 Mjǫlnir 4 Mjölner 5 Mjølner 6 ハンマー}
3399 +
3400 +# Reset the database to UTF-16BE.
3401 +file delete -force test.db
3402 +sqlite3 db test.db;
3403 +db eval {
3404 + PRAGMA encoding = 'UTF-16BE';
3405 +}
3406 +
3407 +do_test recover-encoding-3.0 {
3408 + execsql {
3409 + DROP TABLE IF EXISTS e;
3410 + CREATE TABLE e (v TEXT);
3411 + INSERT INTO e VALUES('Mjollnir');
3412 + INSERT INTO e VALUES('Mjölnir');
3413 + INSERT INTO e VALUES('Mjǫlnir');
3414 + INSERT INTO e VALUES('Mjölner');
3415 + INSERT INTO e VALUES('Mjølner');
3416 + INSERT INTO e VALUES('ハンマー');
3417 + PRAGMA encoding;
3418 +
3419 + DROP TABLE IF EXISTS e_recover;
3420 + CREATE VIRTUAL TABLE temp.e_recover USING recover(
3421 + e,
3422 + v TEXT
3423 + );
3424 + SELECT rowid, v FROM e_recover ORDER BY rowid;
3425 + }
3426 +} {UTF-16be 1 Mjollnir 2 Mjölnir 3 Mjǫlnir 4 Mjölner 5 Mjølner 6 ハンマー}
3427 +
3428 +finish_test
3429 diff --git a/third_party/sqlite/src/test/recover2.test b/third_party/sqlite/src/ test/recover2.test
3430 new file mode 100644
3431 index 0000000..8aa4e04
3432 --- /dev/null
3433 +++ b/third_party/sqlite/src/test/recover2.test
3434 @@ -0,0 +1,157 @@
3435 +# 2012 January 4 {}
3436 +#
3437 +# The author disclaims copyright to this source code. In place of
3438 +# a legal notice, here is a blessing:
3439 +#
3440 +# May you do good and not evil.
3441 +# May you find forgiveness for yourself and forgive others.
3442 +# May you share freely, never taking more than you give.
3443 +#
3444 +#***********************************************************************
3445 +# This file implements regression tests for SQLite library.
3446 +#
3447 +# This file implements tests for how the recover module handles cell
3448 +# overflow.
3449 +#
3450 +# $Id$
3451 +
3452 +set testdir [file dirname $argv0]
3453 +source $testdir/tester.tcl
3454 +
3455 +set lorem "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam sagitti s gravida odio vitae ultrices. Nulla facilisi. Maecenas pulvinar, tellus ut bibe ndum semper, nibh tellus auctor nulla, in dignissim nisi ipsum id arcu. Nullam t incidunt arcu malesuada turpis faucibus in adipiscing enim mattis. Fusce augue m agna, scelerisque sollicitudin egestas in, cursus eu sapien. Pellentesque tempor risus at lectus convallis a convallis orci ornare. Integer tristique aliquam le o vel interdum.
3456 +
3457 +Phasellus quis dictum nisi. Curabitur at enim non felis pharetra imperdiet. Dui s tempus massa eu leo varius porta. Vestibulum sodales nulla at purus tincidunt ultrices. Nam euismod posuere nibh, nec sodales magna luctus ac. Ut commodo hend rerit mauris vitae gravida. In interdum justo ut sem eleifend convallis. Donec c ursus molestie elementum. Suspendisse at nisl tellus, vel consequat mauris. Null am non justo nibh.
3458 +
3459 +Maecenas varius sollicitudin libero, nec feugiat turpis facilisis eget. Quisque et sem risus. Aenean a magna quis purus hendrerit mattis eu vel lorem. Aenean f ringilla diam eget tortor lacinia sed mollis eros feugiat. Quisque ac purus sapi en. Nullam quis tellus vel magna convallis tincidunt. Donec eget ligula at liber o tincidunt congue ut ut lacus. Integer dignissim aliquet congue. Pellentesque s ed risus vitae lorem porta viverra ac eu risus. Vivamus congue suscipit odio pul vinar aliquet. Aliquam porttitor nunc non sapien auctor et vehicula augue molest ie.
3460 +
3461 +Aliquam et dui ac sem tempus dictum. Fusce arcu nulla, viverra sit amet suscipi t quis, malesuada at felis. Fusce ut diam felis. Fusce id ligula non eros fermen tum sodales in nec quam. Donec tempor bibendum arcu ac adipiscing. Praesent nisl lectus, tempor ut vehicula eget, mattis a justo. Mauris condimentum luctus eros a varius. Morbi mollis elit eget velit convallis eu sodales odio egestas. Cum s ociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus interdum, metus sit amet varius varius, lectus eros semper risus, sed s agittis ipsum libero in sapien. Nam lacinia nulla vitae magna facilisis sceleris que. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
3462 +
3463 +Donec gravida dignissim eleifend. Aliquam vel tincidunt tortor. Curabitur massa ante, blandit a auctor at, ullamcorper sed nisl. Class aptent taciti sociosqu a d litora torquent per conubia nostra, per inceptos himenaeos. Suspendisse ut fel is a eros egestas ultricies et quis mi. Vivamus ut risus massa. Donec nec ornare erat. Aliquam ornare, lorem a rhoncus aliquam, tellus diam tincidunt tellus, a mattis nunc ante ac arcu. Curabitur nec metus id risus commodo ullamcorper eu ut tortor."
3464 +
3465 +# Create a database which needs a multiple overflow pages to test the
3466 +# transition from main page to overflow, and then overflow to
3467 +# overflow.
3468 +do_test recover-overflow-1.0 {
3469 + db eval {
3470 + DROP TABLE IF EXISTS overflow;
3471 + CREATE TABLE overflow (value TEXT);
3472 + INSERT INTO overflow VALUES ($lorem);
3473 +
3474 + DROP TABLE IF EXISTS overflow_recover;
3475 + CREATE VIRTUAL TABLE temp.overflow_recover USING recover(
3476 + overflow,
3477 + value TEXT
3478 + );
3479 + }
3480 +
3481 + # Should have root page, leaf page, and 2 overflow pages, because
3482 + # length(value) is more than 2x page_size.
3483 + execsql {
3484 + PRAGMA page_count;
3485 + PRAGMA page_size;
3486 + SELECT rowid, TYPEOF(value), length(value), value FROM overflow_recover;
3487 + }
3488 +} [list 4 1024 1 text [string length $lorem] $lorem]
3489 +
3490 +# No overflow. [1024-35 == 990, overhead of 1-byte rowid, 2-byte
3491 +# record length, 1-byte header length, 2-byte field type.]
3492 +set substr [string range $lorem 0 985]
3493 +do_test recover-overflow-1.1 {
3494 + db eval {
3495 + DROP TABLE IF EXISTS overflow;
3496 + CREATE TABLE overflow (value TEXT);
3497 + INSERT INTO overflow VALUES ($substr);
3498 +
3499 + DROP TABLE IF EXISTS overflow_recover;
3500 + CREATE VIRTUAL TABLE temp.overflow_recover USING recover(
3501 + overflow,
3502 + value TEXT
3503 + );
3504 + }
3505 +
3506 + # Trim to remove excess pages from prior tests.
3507 + db eval {VACUUM}
3508 +
3509 + execsql {
3510 + PRAGMA page_count;
3511 + PRAGMA page_size;
3512 + SELECT rowid, TYPEOF(value), length(value), value FROM overflow_recover;
3513 + }
3514 +} [list 2 1024 1 text [string length $substr] $substr]
3515 +
3516 +# One byte of overflow.
3517 +set substr [string range $lorem 0 986]
3518 +do_test recover-overflow-1.2 {
3519 + db eval {
3520 + DROP TABLE IF EXISTS overflow;
3521 + CREATE TABLE overflow (value TEXT);
3522 + INSERT INTO overflow VALUES ($substr);
3523 +
3524 + DROP TABLE IF EXISTS overflow_recover;
3525 + CREATE VIRTUAL TABLE temp.overflow_recover USING recover(
3526 + overflow,
3527 + value TEXT
3528 + );
3529 + }
3530 +
3531 + # Trim to remove excess pages from prior tests.
3532 + db eval {VACUUM}
3533 +
3534 + execsql {
3535 + PRAGMA page_count;
3536 + PRAGMA page_size;
3537 + SELECT rowid, TYPEOF(value), length(value), value FROM overflow_recover;
3538 + }
3539 +} [list 3 1024 1 text [string length $substr] $substr]
3540 +
3541 +# One full overflow page, plus maxLocal in-leaf. [985+1020]
3542 +set substr [string range $lorem 0 2005]
3543 +do_test recover-overflow-1.3 {
3544 + db eval {
3545 + DROP TABLE IF EXISTS overflow;
3546 + CREATE TABLE overflow (value TEXT);
3547 + INSERT INTO overflow VALUES ($substr);
3548 +
3549 + DROP TABLE IF EXISTS overflow_recover;
3550 + CREATE VIRTUAL TABLE temp.overflow_recover USING recover(
3551 + overflow,
3552 + value TEXT
3553 + );
3554 + }
3555 +
3556 + # Trim to remove excess pages from prior tests.
3557 + db eval {VACUUM}
3558 +
3559 + execsql {
3560 + PRAGMA page_count;
3561 + PRAGMA page_size;
3562 + SELECT rowid, TYPEOF(value), length(value), value FROM overflow_recover;
3563 + }
3564 +} [list 3 1024 1 text [string length $substr] $substr]
3565 +
3566 +# Overflow to a second overflow page.
3567 +set substr [string range $lorem 0 2006]
3568 +do_test recover-overflow-1.4 {
3569 + db eval {
3570 + DROP TABLE IF EXISTS overflow;
3571 + CREATE TABLE overflow (value TEXT);
3572 + INSERT INTO overflow VALUES ($substr);
3573 +
3574 + DROP TABLE IF EXISTS overflow_recover;
3575 + CREATE VIRTUAL TABLE temp.overflow_recover USING recover(
3576 + overflow,
3577 + value TEXT
3578 + );
3579 + }
3580 +
3581 + # Trim to remove excess pages from prior tests.
3582 + db eval {VACUUM}
3583 +
3584 + execsql {
3585 + PRAGMA page_count;
3586 + PRAGMA page_size;
3587 + SELECT rowid, TYPEOF(value), length(value), value FROM overflow_recover;
3588 + }
3589 +} [list 4 1024 1 text [string length $substr] $substr]
3590 +
3591 +finish_test
3592 diff --git a/third_party/sqlite/src/tool/mksqlite3c.tcl b/third_party/sqlite/src /tool/mksqlite3c.tcl
3593 index fa99f2d..df2df07 100644
3594 --- a/third_party/sqlite/src/tool/mksqlite3c.tcl
3595 +++ b/third_party/sqlite/src/tool/mksqlite3c.tcl
3596 @@ -293,6 +293,8 @@ foreach file {
3597 main.c
3598 notify.c
3599
3600 + recover.c
3601 +
3602 fts3.c
3603 fts3_aux.c
3604 fts3_expr.c
3605 --
3606 2.2.1
3607
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698