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

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

Issue 2366013002: [sqlite] Bring patches up-to-date with trunk. (Closed)
Patch Set: Created 4 years, 2 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 From 31dd2fd1cdeba87223f6a46cc19bcea9eb8b2f38 Mon Sep 17 00:00:00 2001 1 From d176c774ba1a8b431400f38ca71459bf148f0c3a Mon Sep 17 00:00:00 2001
2 From: Scott Hess <shess@chromium.org> 2 From: Scott Hess <shess@chromium.org>
3 Date: Sat, 20 Jul 2013 11:42:21 -0700 3 Date: Sat, 20 Jul 2013 11:42:21 -0700
4 Subject: [PATCH 05/13] Virtual table supporting recovery of corrupted 4 Subject: [PATCH 05/13] Virtual table supporting recovery of corrupted
5 databases. 5 databases.
6 6
7 "recover" implements a virtual table which uses the SQLite pager layer 7 "recover" implements a virtual table which uses the SQLite pager layer
8 to read table pages and pull out the data which is structurally sound 8 to read table pages and pull out the data which is structurally sound
9 (at least at the storage layer). 9 (at least at the storage layer).
10 10
11 BUG=109482 11 BUG=109482
12 12
13 Since this implements a new feature for SQLite, the review URLs aren't 13 Since this implements a new feature for SQLite, the review URLs aren't
14 listed. This patch and the top of recover.c should be considered 14 listed. This patch and the top of recover.c should be considered
15 authoritative. The history is mostly under 15 authoritative. The history is mostly under
16 third_party/sqlite/src/src/{recover,recover-alt}.c . 16 third_party/sqlite/src/src/{recover,recover-alt}.c .
17 --- 17 ---
18 third_party/sqlite/src/Makefile.in | 1 + 18 third_party/sqlite/src/main.mk | 6 +-
19 third_party/sqlite/src/Makefile.linux-gcc | 4 + 19 third_party/sqlite/src/src/main.c | 8 +
20 third_party/sqlite/src/main.mk | 5 +- 20 third_party/sqlite/src/src/recover.c | 2270 +++++++++++++++++++++++++++
21 third_party/sqlite/src/src/main.c | 8 + 21 third_party/sqlite/src/src/recover.h | 23 +
22 third_party/sqlite/src/src/recover.c | 2281 ++++++++++++++++++++++++++++ 22 third_party/sqlite/src/src/recover_varint.c | 201 +++
23 third_party/sqlite/src/src/sqlite.h.in | 16 + 23 third_party/sqlite/src/test/recover.test | 164 ++
24 third_party/sqlite/src/test/recover.test | 164 ++ 24 third_party/sqlite/src/test/recover0.test | 532 +++++++
25 third_party/sqlite/src/test/recover0.test | 532 +++++++ 25 third_party/sqlite/src/test/recover1.test | 429 +++++
26 third_party/sqlite/src/test/recover1.test | 429 ++++++ 26 third_party/sqlite/src/test/recover2.test | 157 ++
27 third_party/sqlite/src/test/recover2.test | 157 ++ 27 9 files changed, 3789 insertions(+), 1 deletion(-)
28 third_party/sqlite/src/tool/mksqlite3c.tcl | 2 +
29 11 files changed, 3598 insertions(+), 1 deletion(-)
30 create mode 100644 third_party/sqlite/src/src/recover.c 28 create mode 100644 third_party/sqlite/src/src/recover.c
29 create mode 100644 third_party/sqlite/src/src/recover.h
30 create mode 100644 third_party/sqlite/src/src/recover_varint.c
31 create mode 100644 third_party/sqlite/src/test/recover.test 31 create mode 100644 third_party/sqlite/src/test/recover.test
32 create mode 100644 third_party/sqlite/src/test/recover0.test 32 create mode 100644 third_party/sqlite/src/test/recover0.test
33 create mode 100644 third_party/sqlite/src/test/recover1.test 33 create mode 100644 third_party/sqlite/src/test/recover1.test
34 create mode 100644 third_party/sqlite/src/test/recover2.test 34 create mode 100644 third_party/sqlite/src/test/recover2.test
35 35
36 diff --git a/third_party/sqlite/src/Makefile.in b/third_party/sqlite/src/Makefil e.in
37 index 1fe49d6..8b965c7 100644
38 --- a/third_party/sqlite/src/Makefile.in
39 +++ b/third_party/sqlite/src/Makefile.in
40 @@ -260,6 +260,7 @@ SRC = \
41 $(TOP)/src/prepare.c \
42 $(TOP)/src/printf.c \
43 $(TOP)/src/random.c \
44 + $(TOP)/src/recover.c \
45 $(TOP)/src/resolve.c \
46 $(TOP)/src/rowset.c \
47 $(TOP)/src/select.c \
48 diff --git a/third_party/sqlite/src/Makefile.linux-gcc b/third_party/sqlite/src/ Makefile.linux-gcc
49 index 952e8d1..f6291c0 100644
50 --- a/third_party/sqlite/src/Makefile.linux-gcc
51 +++ b/third_party/sqlite/src/Makefile.linux-gcc
52 @@ -81,6 +81,10 @@ OPTS += -DSQLITE_MEMDEBUG=1
53 # TODO(shess) I can't see why I need this setting.
54 OPTS += -DOS_UNIX=1
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 36 diff --git a/third_party/sqlite/src/main.mk b/third_party/sqlite/src/main.mk
64 index 6ff3bd4..a8629aa 100644 37 index 6ff3bd4..26f9f15 100644
65 --- a/third_party/sqlite/src/main.mk 38 --- a/third_party/sqlite/src/main.mk
66 +++ b/third_party/sqlite/src/main.mk 39 +++ b/third_party/sqlite/src/main.mk
67 @@ -67,7 +67,8 @@ LIBOBJ+= vdbe.o parse.o \ 40 @@ -67,7 +67,8 @@ LIBOBJ+= vdbe.o parse.o \
68 mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \ 41 mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \
69 notify.o opcodes.o os.o os_unix.o os_win.o \ 42 notify.o opcodes.o os.o os_unix.o os_win.o \
70 pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \ 43 pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \
71 - random.o resolve.o rowset.o rtree.o select.o sqlite3rbu.o status.o \ 44 - random.o resolve.o rowset.o rtree.o select.o sqlite3rbu.o status.o \
72 + random.o recover.o resolve.o rowset.o rtree.o \ 45 + random.o recover.o recover_varint.o resolve.o rowset.o rtree.o \
73 + select.o sqlite3rbu.o status.o \ 46 + select.o sqlite3rbu.o status.o \
74 table.o threads.o tokenize.o treeview.o trigger.o \ 47 table.o threads.o tokenize.o treeview.o trigger.o \
75 update.o userauth.o util.o vacuum.o \ 48 update.o userauth.o util.o vacuum.o \
76 vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \ 49 vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \
77 @@ -140,6 +141,7 @@ SRC = \ 50 @@ -360,6 +361,8 @@ TESTSRC2 = \
78 $(TOP)/src/prepare.c \ 51 $(TOP)/src/prepare.c \
79 $(TOP)/src/printf.c \ 52 $(TOP)/src/printf.c \
80 $(TOP)/src/random.c \ 53 $(TOP)/src/random.c \
81 + $(TOP)/src/recover.c \ 54 + $(TOP)/src/recover.c \
82 $(TOP)/src/resolve.c \ 55 + $(TOP)/src/recover_varint.c \
83 $(TOP)/src/rowset.c \
84 $(TOP)/src/select.c \
85 @@ -360,6 +362,7 @@ TESTSRC2 = \
86 $(TOP)/src/prepare.c \
87 $(TOP)/src/printf.c \
88 $(TOP)/src/random.c \
89 + $(TOP)/src/recover.c \
90 $(TOP)/src/pcache.c \ 56 $(TOP)/src/pcache.c \
91 $(TOP)/src/pcache1.c \ 57 $(TOP)/src/pcache1.c \
92 $(TOP)/src/select.c \ 58 $(TOP)/src/select.c \
59 @@ -720,6 +723,7 @@ sqlite3_analyzer$(EXE): sqlite3_analyzer.c
60 #
61 TESTFIXTURE_FLAGS = -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
62 TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE
63 +TESTFIXTURE_FLAGS += -DDEFAULT_ENABLE_RECOVER=1
64
65 testfixture$(EXE): $(TESTSRC2) libsqlite3.a $(TESTSRC) $(TOP)/src/tclsqlite.c
66 $(TCCX) $(TCL_FLAGS) -DTCLSH=1 $(TESTFIXTURE_FLAGS) \
93 diff --git a/third_party/sqlite/src/src/main.c b/third_party/sqlite/src/src/main .c 67 diff --git a/third_party/sqlite/src/src/main.c b/third_party/sqlite/src/src/main .c
94 index 3be7c77..301808c 100644 68 index 3be7c77..301808c 100644
95 --- a/third_party/sqlite/src/src/main.c 69 --- a/third_party/sqlite/src/src/main.c
96 +++ b/third_party/sqlite/src/src/main.c 70 +++ b/third_party/sqlite/src/src/main.c
97 @@ -2927,6 +2927,14 @@ static int openDatabase( 71 @@ -2927,6 +2927,14 @@ static int openDatabase(
98 } 72 }
99 #endif 73 #endif
100 74
101 +#ifdef DEFAULT_ENABLE_RECOVER 75 +#ifdef DEFAULT_ENABLE_RECOVER
102 + /* Initialize recover virtual table for testing. */ 76 + /* Initialize recover virtual table for testing. */
103 + extern int recoverVtableInit(sqlite3 *db); 77 + extern int recoverVtableInit(sqlite3 *db);
104 + if( !db->mallocFailed && rc==SQLITE_OK ){ 78 + if( !db->mallocFailed && rc==SQLITE_OK ){
105 + rc = recoverVtableInit(db); 79 + rc = recoverVtableInit(db);
106 + } 80 + }
107 +#endif 81 +#endif
108 + 82 +
109 #ifdef SQLITE_ENABLE_ICU 83 #ifdef SQLITE_ENABLE_ICU
110 if( !db->mallocFailed && rc==SQLITE_OK ){ 84 if( !db->mallocFailed && rc==SQLITE_OK ){
111 rc = sqlite3IcuInit(db); 85 rc = sqlite3IcuInit(db);
112 diff --git a/third_party/sqlite/src/src/recover.c b/third_party/sqlite/src/src/r ecover.c 86 diff --git a/third_party/sqlite/src/src/recover.c b/third_party/sqlite/src/src/r ecover.c
113 new file mode 100644 87 new file mode 100644
114 index 0000000..5ff6f78 88 index 0000000..c22fd4d
115 --- /dev/null 89 --- /dev/null
116 +++ b/third_party/sqlite/src/src/recover.c 90 +++ b/third_party/sqlite/src/src/recover.c
117 @@ -0,0 +1,2281 @@ 91 @@ -0,0 +1,2270 @@
118 +/* 92 +/*
119 +** 2012 Jan 11 93 +** 2012 Jan 11
120 +** 94 +**
121 +** The author disclaims copyright to this source code. In place of 95 +** The author disclaims copyright to this source code. In place of
122 +** a legal notice, here is a blessing: 96 +** a legal notice, here is a blessing:
123 +** 97 +**
124 +** May you do good and not evil. 98 +** May you do good and not evil.
125 +** May you find forgiveness for yourself and forgive others. 99 +** May you find forgiveness for yourself and forgive others.
126 +** May you share freely, never taking more than you give. 100 +** May you share freely, never taking more than you give.
127 +*/ 101 +*/
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 + */ 294 + */
321 +/* TODO(shess): It might be useful to allow DEFAULT in types to 295 +/* TODO(shess): It might be useful to allow DEFAULT in types to
322 + * specify what to do for NULL when an ALTER TABLE case comes up. 296 + * specify what to do for NULL when an ALTER TABLE case comes up.
323 + * Unfortunately, simply adding it to the exposed schema and using 297 + * Unfortunately, simply adding it to the exposed schema and using
324 + * sqlite3_result_null() does not cause the default to be generate. 298 + * sqlite3_result_null() does not cause the default to be generate.
325 + * Handling it ourselves seems hard, unfortunately. 299 + * Handling it ourselves seems hard, unfortunately.
326 + */ 300 + */
327 + 301 +
328 +#include <assert.h> 302 +#include <assert.h>
329 +#include <ctype.h> 303 +#include <ctype.h>
304 +#include <stdint.h>
330 +#include <stdio.h> 305 +#include <stdio.h>
331 +#include <string.h> 306 +#include <string.h>
332 + 307 +
333 +/* Internal SQLite things that are used: 308 +#include "sqlite3.h"
334 + * u32, u64, i64 types. 309 +
335 + * Btree, Pager, and DbPage structs. 310 +/* Some SQLite internals use, cribbed from fts5int.h. */
336 + * DbPage.pData, .pPager, and .pgno 311 +#ifndef SQLITE_AMALGAMATION
337 + * sqlite3 struct. 312 +typedef uint8_t u8;
338 + * sqlite3BtreePager() and sqlite3BtreeGetPageSize() 313 +typedef uint32_t u32;
339 + * sqlite3BtreeGetOptimalReserve() 314 +typedef sqlite3_int64 i64;
340 + * sqlite3PagerGet() and sqlite3PagerUnref() 315 +typedef sqlite3_uint64 u64;
341 + * getVarint(). 316 +
342 + */ 317 +#define ArraySize(x) (sizeof(x) / sizeof(x[0]))
343 +#include "sqliteInt.h" 318 +#endif
319 +
320 +/* From recover_varint.c. */
321 +u8 recoverGetVarint(const unsigned char *p, u64 *v);
344 + 322 +
345 +/* For debugging. */ 323 +/* For debugging. */
346 +#if 0 324 +#if 0
347 +#define FNENTRY() fprintf(stderr, "In %s\n", __FUNCTION__) 325 +#define FNENTRY() fprintf(stderr, "In %s\n", __FUNCTION__)
348 +#else 326 +#else
349 +#define FNENTRY() 327 +#define FNENTRY()
350 +#endif 328 +#endif
351 + 329 +
352 +/* Generic constants and helper functions. */ 330 +/* Generic constants and helper functions. */
353 + 331 +
354 +static const unsigned char kTableLeafPage = 0x0D; 332 +static const unsigned char kTableLeafPage = 0x0D;
355 +static const unsigned char kTableInteriorPage = 0x05; 333 +static const unsigned char kTableInteriorPage = 0x05;
356 + 334 +
357 +/* From section 1.2. */ 335 +/* From section 1.2. */
358 +static const unsigned kiHeaderPageSizeOffset = 16; 336 +static const unsigned kiHeaderPageSizeOffset = 16;
359 +static const unsigned kiHeaderReservedSizeOffset = 20; 337 +static const unsigned kiHeaderReservedSizeOffset = 20;
360 +static const unsigned kiHeaderEncodingOffset = 56; 338 +static const unsigned kiHeaderEncodingOffset = 56;
361 +/* TODO(shess) |static const unsigned| fails creating the header in GetPager() 339 +/* TODO(shess) |static const unsigned| fails creating the header in GetPager()
362 +** because |knHeaderSize| isn't |constexpr|. But this isn't C++, either. 340 +** because |knHeaderSize| isn't |constexpr|. But this isn't C++, either.
363 +*/ 341 +*/
364 +enum { knHeaderSize = 100}; 342 +enum { knHeaderSize = 100};
365 + 343 +
366 +/* From section 1.5. */ 344 +/* From section 1.5. */
367 +static const unsigned kiPageTypeOffset = 0; 345 +static const unsigned kiPageTypeOffset = 0;
368 +static const unsigned kiPageFreeBlockOffset = 1; 346 +/* static const unsigned kiPageFreeBlockOffset = 1; */
369 +static const unsigned kiPageCellCountOffset = 3; 347 +static const unsigned kiPageCellCountOffset = 3;
370 +static const unsigned kiPageCellContentOffset = 5; 348 +/* static const unsigned kiPageCellContentOffset = 5; */
371 +static const unsigned kiPageFragmentedBytesOffset = 7; 349 +/* static const unsigned kiPageFragmentedBytesOffset = 7; */
372 +static const unsigned knPageLeafHeaderBytes = 8; 350 +static const unsigned knPageLeafHeaderBytes = 8;
373 +/* Interior pages contain an additional field. */ 351 +/* Interior pages contain an additional field. */
374 +static const unsigned kiPageRightChildOffset = 8; 352 +static const unsigned kiPageRightChildOffset = 8;
375 +static const unsigned kiPageInteriorHeaderBytes = 12; 353 +static const unsigned kiPageInteriorHeaderBytes = 12;
376 + 354 +
377 +/* Accepted types are specified by a mask. */ 355 +/* Accepted types are specified by a mask. */
378 +#define MASK_ROWID (1<<0) 356 +#define MASK_ROWID (1<<0)
379 +#define MASK_INTEGER (1<<1) 357 +#define MASK_INTEGER (1<<1)
380 +#define MASK_FLOAT (1<<2) 358 +#define MASK_FLOAT (1<<2)
381 +#define MASK_TEXT (1<<3) 359 +#define MASK_TEXT (1<<3)
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 +/* TODO(shess): SQLite by default allocates page metadata in a single allocatio n 508 +/* TODO(shess): SQLite by default allocates page metadata in a single allocatio n
531 +** such that the page's data and metadata are contiguous, see pcache1AllocPage 509 +** such that the page's data and metadata are contiguous, see pcache1AllocPage
532 +** in pcache1.c. I believe this was intended to reduce malloc churn. It means 510 +** in pcache1.c. I believe this was intended to reduce malloc churn. It means
533 +** that Chromium's automated tooling would be unlikely to see page-buffer 511 +** that Chromium's automated tooling would be unlikely to see page-buffer
534 +** overruns. I believe that this code is safe, but for now replicate SQLite's 512 +** overruns. I believe that this code is safe, but for now replicate SQLite's
535 +** approach with kExcessSpace. 513 +** approach with kExcessSpace.
536 +*/ 514 +*/
537 +const int kExcessSpace = 128; 515 +const int kExcessSpace = 128;
538 +typedef struct RecoverPage RecoverPage; 516 +typedef struct RecoverPage RecoverPage;
539 +struct RecoverPage { 517 +struct RecoverPage {
540 + Pgno pgno; /* Page number for this page */ 518 + u32 pgno; /* Page number for this page */
541 + void *pData; /* Page data for pgno */ 519 + void *pData; /* Page data for pgno */
542 + RecoverPager *pPager; /* The pager this page is part of */ 520 + RecoverPager *pPager; /* The pager this page is part of */
543 +}; 521 +};
544 + 522 +
545 +static void pageDestroy(RecoverPage *pPage){ 523 +static void pageDestroy(RecoverPage *pPage){
546 + sqlite3_free(pPage->pData); 524 + sqlite3_free(pPage->pData);
547 + memset(pPage, 0xA5, sizeof(*pPage)); 525 + memset(pPage, 0xA5, sizeof(*pPage));
548 + sqlite3_free(pPage); 526 + sqlite3_free(pPage);
549 +} 527 +}
550 + 528 +
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
807 +} 785 +}
808 + 786 +
809 +/* Cursor for iterating interior nodes. Interior page cells contain a 787 +/* Cursor for iterating interior nodes. Interior page cells contain a
810 + * child page number and a rowid. The child page contains items left 788 + * child page number and a rowid. The child page contains items left
811 + * of the rowid (less than). The rightmost page of the subtree is 789 + * of the rowid (less than). The rightmost page of the subtree is
812 + * stored in the page header. 790 + * stored in the page header.
813 + * 791 + *
814 + * interiorCursorDestroy - release all resources associated with the 792 + * interiorCursorDestroy - release all resources associated with the
815 + * cursor and any parent cursors. 793 + * cursor and any parent cursors.
816 + * interiorCursorCreate - create a cursor with the given parent and page. 794 + * interiorCursorCreate - create a cursor with the given parent and page.
817 + * interiorCursorEOF - returns true if neither the cursor nor the
818 + * parent cursors can return any more data.
819 + * interiorCursorNextPage - fetch the next child page from the cursor. 795 + * interiorCursorNextPage - fetch the next child page from the cursor.
820 + * 796 + *
821 + * Logically, interiorCursorNextPage() returns the next child page 797 + * Logically, interiorCursorNextPage() returns the next child page
822 + * number from the page the cursor is currently reading, calling the 798 + * number from the page the cursor is currently reading, calling the
823 + * parent cursor as necessary to get new pages to read, until done. 799 + * parent cursor as necessary to get new pages to read, until done.
824 + * SQLITE_ROW if a page is returned, SQLITE_DONE if out of pages, 800 + * SQLITE_ROW if a page is returned, SQLITE_DONE if out of pages,
825 + * error otherwise. Unfortunately, if the table is corrupted 801 + * error otherwise. Unfortunately, if the table is corrupted
826 + * unexpected pages can be returned. If any unexpected page is found, 802 + * unexpected pages can be returned. If any unexpected page is found,
827 + * leaf or otherwise, it is returned to the caller for processing, 803 + * leaf or otherwise, it is returned to the caller for processing,
828 + * with the interior cursor left empty. The next call to 804 + * with the interior cursor left empty. The next call to
829 + * interiorCursorNextPage() will recurse to the parent cursor until an 805 + * interiorCursorNextPage() will recurse to the parent cursor until an
830 + * interior page to iterate is returned. 806 + * interior page to iterate is returned.
831 + * 807 + *
832 + * Note that while interiorCursorNextPage() will refuse to follow 808 + * Note that while interiorCursorNextPage() will refuse to follow
833 + * loops, it does not keep track of pages returned for purposes of 809 + * loops, it does not keep track of pages returned for purposes of
834 + * preventing duplication. 810 + * preventing duplication.
835 + *
836 + * Note that interiorCursorEOF() could return false (not at EOF), and
837 + * interiorCursorNextPage() could still return SQLITE_DONE. This
838 + * could happen if there are more cells to iterate in an interior
839 + * page, but those cells refer to invalid pages.
840 + */ 811 + */
841 +typedef struct RecoverInteriorCursor RecoverInteriorCursor; 812 +typedef struct RecoverInteriorCursor RecoverInteriorCursor;
842 +struct RecoverInteriorCursor { 813 +struct RecoverInteriorCursor {
843 + RecoverInteriorCursor *pParent; /* Parent node to this node. */ 814 + RecoverInteriorCursor *pParent; /* Parent node to this node. */
844 + RecoverPage *pPage; /* Reference to leaf page. */ 815 + RecoverPage *pPage; /* Reference to leaf page. */
845 + unsigned nPageSize; /* Size of page. */ 816 + unsigned nPageSize; /* Size of page. */
846 + unsigned nChildren; /* Number of children on the page. */ 817 + unsigned nChildren; /* Number of children on the page. */
847 + unsigned iChild; /* Index of next child to return. */ 818 + unsigned iChild; /* Index of next child to return. */
848 +}; 819 +};
849 + 820 +
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
945 + 916 +
946 + /* TODO(shess): Check for cell overlaps? Cells require 4 bytes plus 917 + /* TODO(shess): Check for cell overlaps? Cells require 4 bytes plus
947 + * a varint. Check could be identical to leaf check (or even a 918 + * a varint. Check could be identical to leaf check (or even a
948 + * shared helper testing for "Cells starting in this range"?). 919 + * shared helper testing for "Cells starting in this range"?).
949 + */ 920 + */
950 + 921 +
951 + /* If the offset is broken, return an invalid page number. */ 922 + /* If the offset is broken, return an invalid page number. */
952 + return 0; 923 + return 0;
953 +} 924 +}
954 + 925 +
955 +static int interiorCursorEOF(RecoverInteriorCursor *pCursor){
956 + /* Find a parent with remaining children. EOF if none found. */
957 + while( pCursor && pCursor->iChild>=pCursor->nChildren ){
958 + pCursor = pCursor->pParent;
959 + }
960 + return pCursor==NULL;
961 +}
962 +
963 +/* Internal helper. Used to detect if iPage would cause a loop. */ 926 +/* Internal helper. Used to detect if iPage would cause a loop. */
964 +static int interiorCursorPageInUse(RecoverInteriorCursor *pCursor, 927 +static int interiorCursorPageInUse(RecoverInteriorCursor *pCursor,
965 + unsigned iPage){ 928 + unsigned iPage){
966 + /* Find any parent using the indicated page. */ 929 + /* Find any parent using the indicated page. */
967 + while( pCursor && pCursor->pPage->pgno!=iPage ){ 930 + while( pCursor && pCursor->pPage->pgno!=iPage ){
968 + pCursor = pCursor->pParent; 931 + pCursor = pCursor->pParent;
969 + } 932 + }
970 + return pCursor!=NULL; 933 + return pCursor!=NULL;
971 +} 934 +}
972 + 935 +
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after
1568 + /* B-tree leaf cells lead with varint record size, varint rowid and 1531 + /* B-tree leaf cells lead with varint record size, varint rowid and
1569 + * varint header size. 1532 + * varint header size.
1570 + */ 1533 + */
1571 + /* TODO(shess): The smallest page size is 512 bytes, which has an m 1534 + /* TODO(shess): The smallest page size is 512 bytes, which has an m
1572 + * of 39. Three varints need at most 27 bytes to encode. I think. 1535 + * of 39. Three varints need at most 27 bytes to encode. I think.
1573 + */ 1536 + */
1574 + if( !checkVarints(pCell, nCellMaxBytes, 3) ){ 1537 + if( !checkVarints(pCell, nCellMaxBytes, 3) ){
1575 + return ValidateError(); 1538 + return ValidateError();
1576 + } 1539 + }
1577 + 1540 +
1578 + nRead = getVarint(pCell, &nRecordBytes); 1541 + nRead = recoverGetVarint(pCell, &nRecordBytes);
1579 + assert( iCellOffset+nRead<=pCursor->nPageSize ); 1542 + assert( iCellOffset+nRead<=pCursor->nPageSize );
1580 + pCursor->nRecordBytes = nRecordBytes; 1543 + pCursor->nRecordBytes = nRecordBytes;
1581 + 1544 +
1582 + nRead += getVarint(pCell + nRead, &iRowid); 1545 + nRead += recoverGetVarint(pCell + nRead, &iRowid);
1583 + assert( iCellOffset+nRead<=pCursor->nPageSize ); 1546 + assert( iCellOffset+nRead<=pCursor->nPageSize );
1584 + pCursor->iRowid = (i64)iRowid; 1547 + pCursor->iRowid = (i64)iRowid;
1585 + 1548 +
1586 + pCursor->iRecordOffset = iCellOffset + nRead; 1549 + pCursor->iRecordOffset = iCellOffset + nRead;
1587 + 1550 +
1588 + /* Start overflow setup here because nLocalRecordBytes is needed to 1551 + /* Start overflow setup here because nLocalRecordBytes is needed to
1589 + * check cell overlap. 1552 + * check cell overlap.
1590 + */ 1553 + */
1591 + rc = overflowMaybeCreate(pCursor->pPage, pCursor->nPageSize, 1554 + rc = overflowMaybeCreate(pCursor->pPage, pCursor->nPageSize,
1592 + pCursor->iRecordOffset, pCursor->nRecordBytes, 1555 + pCursor->iRecordOffset, pCursor->nRecordBytes,
1593 + &pCursor->nLocalRecordBytes, 1556 + &pCursor->nLocalRecordBytes,
1594 + &pCursor->pOverflow); 1557 + &pCursor->pOverflow);
1595 + if( rc!=SQLITE_OK ){ 1558 + if( rc!=SQLITE_OK ){
1596 + return ValidateError(); 1559 + return ValidateError();
1597 + } 1560 + }
1598 + 1561 +
1599 + /* Check that no other cell starts within this cell. */ 1562 + /* Check that no other cell starts within this cell. */
1600 + iEndOffset = pCursor->iRecordOffset + pCursor->nLocalRecordBytes; 1563 + iEndOffset = pCursor->iRecordOffset + pCursor->nLocalRecordBytes;
1601 + for( i=0; i<pCursor->nCells && pCellOffsets + i*2 + 2 <= pPageEnd; ++i ){ 1564 + for( i=0; i<pCursor->nCells && pCellOffsets + i*2 + 2 <= pPageEnd; ++i ){
1602 + const unsigned iOtherOffset = decodeUnsigned16(pCellOffsets + i*2); 1565 + const unsigned iOtherOffset = decodeUnsigned16(pCellOffsets + i*2);
1603 + if( iOtherOffset>iCellOffset && iOtherOffset<iEndOffset ){ 1566 + if( iOtherOffset>iCellOffset && iOtherOffset<iEndOffset ){
1604 + return ValidateError(); 1567 + return ValidateError();
1605 + } 1568 + }
1606 + } 1569 + }
1607 + 1570 +
1608 + nRecordHeaderRead = getVarint(pCell + nRead, &nRecordHeaderBytes); 1571 + nRecordHeaderRead = recoverGetVarint(pCell + nRead, &nRecordHeaderBytes);
1609 + assert( nRecordHeaderBytes<=nRecordBytes ); 1572 + assert( nRecordHeaderBytes<=nRecordBytes );
1610 + pCursor->nRecordHeaderBytes = nRecordHeaderBytes; 1573 + pCursor->nRecordHeaderBytes = nRecordHeaderBytes;
1611 + 1574 +
1612 + /* Large headers could overflow if pages are small. */ 1575 + /* Large headers could overflow if pages are small. */
1613 + rc = overflowGetSegment(pCursor->pPage, 1576 + rc = overflowGetSegment(pCursor->pPage,
1614 + pCursor->iRecordOffset, pCursor->nLocalRecordBytes, 1577 + pCursor->iRecordOffset, pCursor->nLocalRecordBytes,
1615 + pCursor->pOverflow, 0, nRecordHeaderBytes, 1578 + pCursor->pOverflow, 0, nRecordHeaderBytes,
1616 + &pCursor->pRecordHeader, &pCursor->bFreeRecordHeader) ; 1579 + &pCursor->pRecordHeader, &pCursor->bFreeRecordHeader) ;
1617 + if( rc!=SQLITE_OK ){ 1580 + if( rc!=SQLITE_OK ){
1618 + return ValidateError(); 1581 + return ValidateError();
1619 + } 1582 + }
1620 + 1583 +
1621 + /* Tally up the column count and size of data. */ 1584 + /* Tally up the column count and size of data. */
1622 + nRecordCols = 0; 1585 + nRecordCols = 0;
1623 + nRecordColBytes = 0; 1586 + nRecordColBytes = 0;
1624 + while( nRecordHeaderRead<nRecordHeaderBytes ){ 1587 + while( nRecordHeaderRead<nRecordHeaderBytes ){
1625 + u64 iSerialType; /* Type descriptor for current column. */ 1588 + u64 iSerialType; /* Type descriptor for current column. */
1626 + if( !checkVarint(pCursor->pRecordHeader + nRecordHeaderRead, 1589 + if( !checkVarint(pCursor->pRecordHeader + nRecordHeaderRead,
1627 + nRecordHeaderBytes - nRecordHeaderRead) ){ 1590 + nRecordHeaderBytes - nRecordHeaderRead) ){
1628 + return ValidateError(); 1591 + return ValidateError();
1629 + } 1592 + }
1630 + nRecordHeaderRead += getVarint(pCursor->pRecordHeader + nRecordHeaderRead, 1593 + nRecordHeaderRead += recoverGetVarint(
1631 + &iSerialType); 1594 + pCursor->pRecordHeader + nRecordHeaderRead, &iSerialType);
1632 + if( iSerialType==10 || iSerialType==11 ){ 1595 + if( iSerialType==10 || iSerialType==11 ){
1633 + return ValidateError(); 1596 + return ValidateError();
1634 + } 1597 + }
1635 + nRecordColBytes += SerialTypeLength(iSerialType); 1598 + nRecordColBytes += SerialTypeLength(iSerialType);
1636 + nRecordCols++; 1599 + nRecordCols++;
1637 + } 1600 + }
1638 + pCursor->nRecordCols = nRecordCols; 1601 + pCursor->nRecordCols = nRecordCols;
1639 + 1602 +
1640 + /* Parsing the header used as many bytes as expected. */ 1603 + /* Parsing the header used as many bytes as expected. */
1641 + if( nRecordHeaderRead!=nRecordHeaderBytes ){ 1604 + if( nRecordHeaderRead!=nRecordHeaderBytes ){
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1687 + 1650 +
1688 + /* Must be able to decode header size. */ 1651 + /* Must be able to decode header size. */
1689 + pRecordHeader = pCursor->pRecordHeader; 1652 + pRecordHeader = pCursor->pRecordHeader;
1690 + if( !checkVarint(pRecordHeader, pCursor->nRecordHeaderBytes) ){ 1653 + if( !checkVarint(pRecordHeader, pCursor->nRecordHeaderBytes) ){
1691 + return SQLITE_CORRUPT; 1654 + return SQLITE_CORRUPT;
1692 + } 1655 + }
1693 + 1656 +
1694 + /* Rather than caching the header size and how many bytes it took, 1657 + /* Rather than caching the header size and how many bytes it took,
1695 + * decode it every time. 1658 + * decode it every time.
1696 + */ 1659 + */
1697 + nRead = getVarint(pRecordHeader, &nRecordHeaderBytes); 1660 + nRead = recoverGetVarint(pRecordHeader, &nRecordHeaderBytes);
1698 + assert( nRecordHeaderBytes==pCursor->nRecordHeaderBytes ); 1661 + assert( nRecordHeaderBytes==pCursor->nRecordHeaderBytes );
1699 + 1662 +
1700 + /* Scan forward to the indicated column. Scans to _after_ column 1663 + /* Scan forward to the indicated column. Scans to _after_ column
1701 + * for later range checking. 1664 + * for later range checking.
1702 + */ 1665 + */
1703 + /* TODO(shess): This could get expensive for very wide tables. An 1666 + /* TODO(shess): This could get expensive for very wide tables. An
1704 + * array of iSerialType could be built in leafCursorCellDecode(), but 1667 + * array of iSerialType could be built in leafCursorCellDecode(), but
1705 + * the number of columns is dynamic per row, so it would add memory 1668 + * the number of columns is dynamic per row, so it would add memory
1706 + * management complexity. Enough info to efficiently forward 1669 + * management complexity. Enough info to efficiently forward
1707 + * iterate could be kept, if all clients forward iterate 1670 + * iterate could be kept, if all clients forward iterate
1708 + * (recoverColumn() may not). 1671 + * (recoverColumn() may not).
1709 + */ 1672 + */
1710 + iColEndOffset = 0; 1673 + iColEndOffset = 0;
1711 + nColsSkipped = 0; 1674 + nColsSkipped = 0;
1712 + while( nColsSkipped<=iCol && nRead<nRecordHeaderBytes ){ 1675 + while( nColsSkipped<=iCol && nRead<nRecordHeaderBytes ){
1713 + if( !checkVarint(pRecordHeader + nRead, nRecordHeaderBytes - nRead) ){ 1676 + if( !checkVarint(pRecordHeader + nRead, nRecordHeaderBytes - nRead) ){
1714 + return SQLITE_CORRUPT; 1677 + return SQLITE_CORRUPT;
1715 + } 1678 + }
1716 + nRead += getVarint(pRecordHeader + nRead, &iSerialType); 1679 + nRead += recoverGetVarint(pRecordHeader + nRead, &iSerialType);
1717 + iColEndOffset += SerialTypeLength(iSerialType); 1680 + iColEndOffset += SerialTypeLength(iSerialType);
1718 + nColsSkipped++; 1681 + nColsSkipped++;
1719 + } 1682 + }
1720 + 1683 +
1721 + /* Column's data extends past record's end. */ 1684 + /* Column's data extends past record's end. */
1722 + if( nRecordHeaderBytes+iColEndOffset>pCursor->nRecordBytes ){ 1685 + if( nRecordHeaderBytes+iColEndOffset>pCursor->nRecordBytes ){
1723 + return SQLITE_CORRUPT; 1686 + return SQLITE_CORRUPT;
1724 + } 1687 + }
1725 + 1688 +
1726 + *piColType = iSerialType; 1689 + *piColType = iSerialType;
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after
2101 + recoverRowid, /* xRowid - read data */ 2064 + recoverRowid, /* xRowid - read data */
2102 + 0, /* xUpdate - write data */ 2065 + 0, /* xUpdate - write data */
2103 + 0, /* xBegin - begin transaction */ 2066 + 0, /* xBegin - begin transaction */
2104 + 0, /* xSync - sync transaction */ 2067 + 0, /* xSync - sync transaction */
2105 + 0, /* xCommit - commit transaction */ 2068 + 0, /* xCommit - commit transaction */
2106 + 0, /* xRollback - rollback transaction */ 2069 + 0, /* xRollback - rollback transaction */
2107 + 0, /* xFindFunction - function overloading */ 2070 + 0, /* xFindFunction - function overloading */
2108 + 0, /* xRename - rename the table */ 2071 + 0, /* xRename - rename the table */
2109 +}; 2072 +};
2110 + 2073 +
2111 +CHROMIUM_SQLITE_API 2074 +SQLITE_API
2112 +int recoverVtableInit(sqlite3 *db){ 2075 +int recoverVtableInit(sqlite3 *db){
2113 + return sqlite3_create_module_v2(db, "recover", &recoverModule, NULL, 0); 2076 + return sqlite3_create_module_v2(db, "recover", &recoverModule, NULL, 0);
2114 +} 2077 +}
2115 + 2078 +
2116 +/* This section of code is for parsing the create input and 2079 +/* This section of code is for parsing the create input and
2117 + * initializing the module. 2080 + * initializing the module.
2118 + */ 2081 + */
2119 + 2082 +
2120 +/* Find the next word in zText and place the endpoints in pzWord*. 2083 +/* Find the next word in zText and place the endpoints in pzWord*.
2121 + * Returns true if the word is non-empty. "Word" is defined as 2084 + * Returns true if the word is non-empty. "Word" is defined as
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
2339 + if( !pRecover ){ 2302 + if( !pRecover ){
2340 + return SQLITE_NOMEM; 2303 + return SQLITE_NOMEM;
2341 + } 2304 + }
2342 + memset(pRecover, 0, sizeof(*pRecover)); 2305 + memset(pRecover, 0, sizeof(*pRecover));
2343 + pRecover->base.pModule = &recoverModule; 2306 + pRecover->base.pModule = &recoverModule;
2344 + pRecover->db = db; 2307 + pRecover->db = db;
2345 + 2308 +
2346 + /* Parse out db.table, assuming main if no dot. */ 2309 + /* Parse out db.table, assuming main if no dot. */
2347 + zDot = strchr(argv[3], '.'); 2310 + zDot = strchr(argv[3], '.');
2348 + if( !zDot ){ 2311 + if( !zDot ){
2349 + pRecover->zDb = sqlite3_strdup(db->aDb[0].zName); 2312 + pRecover->zDb = sqlite3_strdup("main");
2350 + pRecover->zTable = sqlite3_strdup(argv[3]); 2313 + pRecover->zTable = sqlite3_strdup(argv[3]);
2351 + }else if( zDot>argv[3] && zDot[1]!='\0' ){ 2314 + }else if( zDot>argv[3] && zDot[1]!='\0' ){
2352 + pRecover->zDb = sqlite3_strndup(argv[3], zDot - argv[3]); 2315 + pRecover->zDb = sqlite3_strndup(argv[3], zDot - argv[3]);
2353 + pRecover->zTable = sqlite3_strdup(zDot + 1); 2316 + pRecover->zTable = sqlite3_strdup(zDot + 1);
2354 + }else{ 2317 + }else{
2355 + /* ".table" or "db." not allowed. */ 2318 + /* ".table" or "db." not allowed. */
2356 + *pzErr = sqlite3_mprintf("ill-formed table specifier"); 2319 + *pzErr = sqlite3_mprintf("ill-formed table specifier");
2357 + recoverRelease(pRecover); 2320 + recoverRelease(pRecover);
2358 + return SQLITE_ERROR; 2321 + return SQLITE_ERROR;
2359 + } 2322 + }
(...skipping 29 matching lines...) Expand all
2389 + rc = sqlite3_declare_vtab(db, zCreateSql); 2352 + rc = sqlite3_declare_vtab(db, zCreateSql);
2390 + sqlite3_free(zCreateSql); 2353 + sqlite3_free(zCreateSql);
2391 + if( rc!=SQLITE_OK ){ 2354 + if( rc!=SQLITE_OK ){
2392 + recoverRelease(pRecover); 2355 + recoverRelease(pRecover);
2393 + return rc; 2356 + return rc;
2394 + } 2357 + }
2395 + 2358 +
2396 + *ppVtab = (sqlite3_vtab *)pRecover; 2359 + *ppVtab = (sqlite3_vtab *)pRecover;
2397 + return SQLITE_OK; 2360 + return SQLITE_OK;
2398 +} 2361 +}
2399 diff --git a/third_party/sqlite/src/src/sqlite.h.in b/third_party/sqlite/src/src /sqlite.h.in 2362 diff --git a/third_party/sqlite/src/src/recover.h b/third_party/sqlite/src/src/r ecover.h
2400 index e5673fd..6829bcb 100644 2363 new file mode 100644
2401 --- a/third_party/sqlite/src/src/sqlite.h.in 2364 index 0000000..691f2fd
2402 +++ b/third_party/sqlite/src/src/sqlite.h.in 2365 --- /dev/null
2403 @@ -7411,6 +7411,22 @@ int sqlite3_strnicmp(const char *, const char *, int); 2366 +++ b/third_party/sqlite/src/src/recover.h
2404 */ 2367 @@ -0,0 +1,23 @@
2405 int sqlite3_strglob(const char *zGlob, const char *zStr); 2368 +/* TODO(shess): sqliteicu.h is able to make this include without
2406 2369 +** trouble. It doesn't work when used with Chromium's SQLite. For
2407 +/* Begin recover virtual table patch for Chromium */ 2370 +** now the including code must include sqlite3.h first.
2408 +/* Our patches don't conform to SQLite's amalgamation processing. Hack it. */ 2371 +*/
2409 +#ifndef CHROMIUM_SQLITE_API 2372 +/* #include "sqlite3.h" */
2410 +#define CHROMIUM_SQLITE_API SQLITE_API 2373 +
2374 +#ifdef __cplusplus
2375 +extern "C" {
2411 +#endif 2376 +#endif
2377 +
2412 +/* 2378 +/*
2413 +** Call to initialize the recover virtual-table modules (see recover.c). 2379 +** Call to initialize the recover virtual-table modules (see recover.c).
2414 +** 2380 +**
2415 +** This could be loaded by default in main.c, but that would make the 2381 +** This could be loaded by default in main.c, but that would make the
2416 +** virtual table available to Web SQL. Breaking it out allows only 2382 +** virtual table available to Web SQL. Breaking it out allows only
2417 +** selected users to enable it (currently sql/recovery.cc). 2383 +** selected users to enable it (currently sql/recovery.cc).
2418 +*/ 2384 +*/
2419 +CHROMIUM_SQLITE_API 2385 +SQLITE_API
2420 +int recoverVtableInit(sqlite3 *db); 2386 +int recoverVtableInit(sqlite3 *db);
2421 +/* End recover virtual table patch for Chromium */ 2387 +
2422 + 2388 +#ifdef __cplusplus
2423 /* Begin WebDatabase patch for Chromium */ 2389 +} /* End of the 'extern "C"' block */
2424 /* Expose some SQLite internals for the WebDatabase vfs. 2390 +#endif
2425 ** DO NOT EXTEND THE USE OF THIS. 2391 diff --git a/third_party/sqlite/src/src/recover_varint.c b/third_party/sqlite/sr c/src/recover_varint.c
2392 new file mode 100644
2393 index 0000000..c111e2c
2394 --- /dev/null
2395 +++ b/third_party/sqlite/src/src/recover_varint.c
2396 @@ -0,0 +1,201 @@
2397 +/*
2398 +** 2016 Feb 29
2399 +**
2400 +** The author disclaims copyright to this source code. In place of
2401 +** a legal notice, here is a blessing:
2402 +**
2403 +** May you do good and not evil.
2404 +** May you find forgiveness for yourself and forgive others.
2405 +** May you share freely, never taking more than you give.
2406 +**
2407 +******************************************************************************
2408 +**
2409 +** Copy of sqlite3Fts5GetVarint() from fts3_varint.c, which in turn is copied
2410 +** from SQLite core.
2411 +*/
2412 +
2413 +#include <assert.h>
2414 +#include "sqlite3.h"
2415 +
2416 +/* Copied from fts3int.h. */
2417 +#ifndef SQLITE_AMALGAMATION
2418 +typedef unsigned char u8;
2419 +typedef unsigned int u32;
2420 +typedef sqlite3_uint64 u64;
2421 +#endif
2422 +
2423 +/*
2424 +** Bitmasks used by recoverGetVarint(). These precomputed constants
2425 +** are defined here rather than simply putting the constant expressions
2426 +** inline in order to work around bugs in the RVT compiler.
2427 +**
2428 +** SLOT_2_0 A mask for (0x7f<<14) | 0x7f
2429 +**
2430 +** SLOT_4_2_0 A mask for (0x7f<<28) | SLOT_2_0
2431 +*/
2432 +#define SLOT_2_0 0x001fc07f
2433 +#define SLOT_4_2_0 0xf01fc07f
2434 +
2435 +/*
2436 +** Read a 64-bit variable-length integer from memory starting at p[0].
2437 +** Return the number of bytes read. The value is stored in *v.
2438 +*/
2439 +u8 recoverGetVarint(const unsigned char *p, u64 *v){
2440 + u32 a,b,s;
2441 +
2442 + a = *p;
2443 + /* a: p0 (unmasked) */
2444 + if (!(a&0x80))
2445 + {
2446 + *v = a;
2447 + return 1;
2448 + }
2449 +
2450 + p++;
2451 + b = *p;
2452 + /* b: p1 (unmasked) */
2453 + if (!(b&0x80))
2454 + {
2455 + a &= 0x7f;
2456 + a = a<<7;
2457 + a |= b;
2458 + *v = a;
2459 + return 2;
2460 + }
2461 +
2462 + /* Verify that constants are precomputed correctly */
2463 + assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) );
2464 + assert( SLOT_4_2_0 == ((0xfU<<28) | (0x7f<<14) | (0x7f)) );
2465 +
2466 + p++;
2467 + a = a<<14;
2468 + a |= *p;
2469 + /* a: p0<<14 | p2 (unmasked) */
2470 + if (!(a&0x80))
2471 + {
2472 + a &= SLOT_2_0;
2473 + b &= 0x7f;
2474 + b = b<<7;
2475 + a |= b;
2476 + *v = a;
2477 + return 3;
2478 + }
2479 +
2480 + /* CSE1 from below */
2481 + a &= SLOT_2_0;
2482 + p++;
2483 + b = b<<14;
2484 + b |= *p;
2485 + /* b: p1<<14 | p3 (unmasked) */
2486 + if (!(b&0x80))
2487 + {
2488 + b &= SLOT_2_0;
2489 + /* moved CSE1 up */
2490 + /* a &= (0x7f<<14)|(0x7f); */
2491 + a = a<<7;
2492 + a |= b;
2493 + *v = a;
2494 + return 4;
2495 + }
2496 +
2497 + /* a: p0<<14 | p2 (masked) */
2498 + /* b: p1<<14 | p3 (unmasked) */
2499 + /* 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
2500 + /* moved CSE1 up */
2501 + /* a &= (0x7f<<14)|(0x7f); */
2502 + b &= SLOT_2_0;
2503 + s = a;
2504 + /* s: p0<<14 | p2 (masked) */
2505 +
2506 + p++;
2507 + a = a<<14;
2508 + a |= *p;
2509 + /* a: p0<<28 | p2<<14 | p4 (unmasked) */
2510 + if (!(a&0x80))
2511 + {
2512 + /* we can skip these cause they were (effectively) done above in calc'ing s */
2513 + /* a &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
2514 + /* b &= (0x7f<<14)|(0x7f); */
2515 + b = b<<7;
2516 + a |= b;
2517 + s = s>>18;
2518 + *v = ((u64)s)<<32 | a;
2519 + return 5;
2520 + }
2521 +
2522 + /* 2:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
2523 + s = s<<7;
2524 + s |= b;
2525 + /* s: p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
2526 +
2527 + p++;
2528 + b = b<<14;
2529 + b |= *p;
2530 + /* b: p1<<28 | p3<<14 | p5 (unmasked) */
2531 + if (!(b&0x80))
2532 + {
2533 + /* we can skip this cause it was (effectively) done above in calc'ing s */
2534 + /* b &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
2535 + a &= SLOT_2_0;
2536 + a = a<<7;
2537 + a |= b;
2538 + s = s>>18;
2539 + *v = ((u64)s)<<32 | a;
2540 + return 6;
2541 + }
2542 +
2543 + p++;
2544 + a = a<<14;
2545 + a |= *p;
2546 + /* a: p2<<28 | p4<<14 | p6 (unmasked) */
2547 + if (!(a&0x80))
2548 + {
2549 + a &= SLOT_4_2_0;
2550 + b &= SLOT_2_0;
2551 + b = b<<7;
2552 + a |= b;
2553 + s = s>>11;
2554 + *v = ((u64)s)<<32 | a;
2555 + return 7;
2556 + }
2557 +
2558 + /* CSE2 from below */
2559 + a &= SLOT_2_0;
2560 + p++;
2561 + b = b<<14;
2562 + b |= *p;
2563 + /* b: p3<<28 | p5<<14 | p7 (unmasked) */
2564 + if (!(b&0x80))
2565 + {
2566 + b &= SLOT_4_2_0;
2567 + /* moved CSE2 up */
2568 + /* a &= (0x7f<<14)|(0x7f); */
2569 + a = a<<7;
2570 + a |= b;
2571 + s = s>>4;
2572 + *v = ((u64)s)<<32 | a;
2573 + return 8;
2574 + }
2575 +
2576 + p++;
2577 + a = a<<15;
2578 + a |= *p;
2579 + /* a: p4<<29 | p6<<15 | p8 (unmasked) */
2580 +
2581 + /* moved CSE2 up */
2582 + /* a &= (0x7f<<29)|(0x7f<<15)|(0xff); */
2583 + b &= SLOT_2_0;
2584 + b = b<<8;
2585 + a |= b;
2586 +
2587 + s = s<<4;
2588 + b = p[-4];
2589 + b &= 0x7f;
2590 + b = b>>3;
2591 + s |= b;
2592 +
2593 + *v = ((u64)s)<<32 | a;
2594 +
2595 + return 9;
2596 +}
2597 +
2426 diff --git a/third_party/sqlite/src/test/recover.test b/third_party/sqlite/src/t est/recover.test 2598 diff --git a/third_party/sqlite/src/test/recover.test b/third_party/sqlite/src/t est/recover.test
2427 new file mode 100644 2599 new file mode 100644
2428 index 0000000..bfb7888 2600 index 0000000..bfb7888
2429 --- /dev/null 2601 --- /dev/null
2430 +++ b/third_party/sqlite/src/test/recover.test 2602 +++ b/third_party/sqlite/src/test/recover.test
2431 @@ -0,0 +1,164 @@ 2603 @@ -0,0 +1,164 @@
2432 +# 2012 January 11 {} 2604 +# 2012 January 11 {}
2433 +# 2605 +#
2434 +# The author disclaims copyright to this source code. In place of 2606 +# The author disclaims copyright to this source code. In place of
2435 +# a legal notice, here is a blessing: 2607 +# a legal notice, here is a blessing:
(...skipping 1286 matching lines...) Expand 10 before | Expand all | Expand 10 after
3722 + db eval {VACUUM} 3894 + db eval {VACUUM}
3723 + 3895 +
3724 + execsql { 3896 + execsql {
3725 + PRAGMA page_count; 3897 + PRAGMA page_count;
3726 + PRAGMA page_size; 3898 + PRAGMA page_size;
3727 + SELECT rowid, TYPEOF(value), length(value), value FROM overflow_recover; 3899 + SELECT rowid, TYPEOF(value), length(value), value FROM overflow_recover;
3728 + } 3900 + }
3729 +} [list 4 1024 1 text [string length $substr] $substr] 3901 +} [list 4 1024 1 text [string length $substr] $substr]
3730 + 3902 +
3731 +finish_test 3903 +finish_test
3732 diff --git a/third_party/sqlite/src/tool/mksqlite3c.tcl b/third_party/sqlite/src /tool/mksqlite3c.tcl
3733 index 23241e2..1113758 100644
3734 --- a/third_party/sqlite/src/tool/mksqlite3c.tcl
3735 +++ b/third_party/sqlite/src/tool/mksqlite3c.tcl
3736 @@ -361,6 +361,8 @@ foreach file {
3737 main.c
3738 notify.c
3739
3740 + recover.c
3741 +
3742 fts3.c
3743 fts3_aux.c
3744 fts3_expr.c
3745 -- 3904 --
3746 2.7.0 3905 2.5.0
3747 3906
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698