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

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

Powered by Google App Engine
This is Rietveld 408576698