| OLD | NEW |
| 1 /* | 1 /* |
| 2 ** 2012 Jan 11 | 2 ** 2012 Jan 11 |
| 3 ** | 3 ** |
| 4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
| 5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
| 6 ** | 6 ** |
| 7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
| 8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
| 9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
| 10 */ | 10 */ |
| (...skipping 683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 694 } | 694 } |
| 695 | 695 |
| 696 /* Cursor for iterating interior nodes. Interior page cells contain a | 696 /* Cursor for iterating interior nodes. Interior page cells contain a |
| 697 * child page number and a rowid. The child page contains items left | 697 * child page number and a rowid. The child page contains items left |
| 698 * of the rowid (less than). The rightmost page of the subtree is | 698 * of the rowid (less than). The rightmost page of the subtree is |
| 699 * stored in the page header. | 699 * stored in the page header. |
| 700 * | 700 * |
| 701 * interiorCursorDestroy - release all resources associated with the | 701 * interiorCursorDestroy - release all resources associated with the |
| 702 * cursor and any parent cursors. | 702 * cursor and any parent cursors. |
| 703 * interiorCursorCreate - create a cursor with the given parent and page. | 703 * interiorCursorCreate - create a cursor with the given parent and page. |
| 704 * interiorCursorEOF - returns true if neither the cursor nor the | |
| 705 * parent cursors can return any more data. | |
| 706 * interiorCursorNextPage - fetch the next child page from the cursor. | 704 * interiorCursorNextPage - fetch the next child page from the cursor. |
| 707 * | 705 * |
| 708 * Logically, interiorCursorNextPage() returns the next child page | 706 * Logically, interiorCursorNextPage() returns the next child page |
| 709 * number from the page the cursor is currently reading, calling the | 707 * number from the page the cursor is currently reading, calling the |
| 710 * parent cursor as necessary to get new pages to read, until done. | 708 * parent cursor as necessary to get new pages to read, until done. |
| 711 * SQLITE_ROW if a page is returned, SQLITE_DONE if out of pages, | 709 * SQLITE_ROW if a page is returned, SQLITE_DONE if out of pages, |
| 712 * error otherwise. Unfortunately, if the table is corrupted | 710 * error otherwise. Unfortunately, if the table is corrupted |
| 713 * unexpected pages can be returned. If any unexpected page is found, | 711 * unexpected pages can be returned. If any unexpected page is found, |
| 714 * leaf or otherwise, it is returned to the caller for processing, | 712 * leaf or otherwise, it is returned to the caller for processing, |
| 715 * with the interior cursor left empty. The next call to | 713 * with the interior cursor left empty. The next call to |
| 716 * interiorCursorNextPage() will recurse to the parent cursor until an | 714 * interiorCursorNextPage() will recurse to the parent cursor until an |
| 717 * interior page to iterate is returned. | 715 * interior page to iterate is returned. |
| 718 * | 716 * |
| 719 * Note that while interiorCursorNextPage() will refuse to follow | 717 * Note that while interiorCursorNextPage() will refuse to follow |
| 720 * loops, it does not keep track of pages returned for purposes of | 718 * loops, it does not keep track of pages returned for purposes of |
| 721 * preventing duplication. | 719 * preventing duplication. |
| 722 * | |
| 723 * Note that interiorCursorEOF() could return false (not at EOF), and | |
| 724 * interiorCursorNextPage() could still return SQLITE_DONE. This | |
| 725 * could happen if there are more cells to iterate in an interior | |
| 726 * page, but those cells refer to invalid pages. | |
| 727 */ | 720 */ |
| 728 typedef struct RecoverInteriorCursor RecoverInteriorCursor; | 721 typedef struct RecoverInteriorCursor RecoverInteriorCursor; |
| 729 struct RecoverInteriorCursor { | 722 struct RecoverInteriorCursor { |
| 730 RecoverInteriorCursor *pParent; /* Parent node to this node. */ | 723 RecoverInteriorCursor *pParent; /* Parent node to this node. */ |
| 731 RecoverPage *pPage; /* Reference to leaf page. */ | 724 RecoverPage *pPage; /* Reference to leaf page. */ |
| 732 unsigned nPageSize; /* Size of page. */ | 725 unsigned nPageSize; /* Size of page. */ |
| 733 unsigned nChildren; /* Number of children on the page. */ | 726 unsigned nChildren; /* Number of children on the page. */ |
| 734 unsigned iChild; /* Index of next child to return. */ | 727 unsigned iChild; /* Index of next child to return. */ |
| 735 }; | 728 }; |
| 736 | 729 |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 832 | 825 |
| 833 /* TODO(shess): Check for cell overlaps? Cells require 4 bytes plus | 826 /* TODO(shess): Check for cell overlaps? Cells require 4 bytes plus |
| 834 * a varint. Check could be identical to leaf check (or even a | 827 * a varint. Check could be identical to leaf check (or even a |
| 835 * shared helper testing for "Cells starting in this range"?). | 828 * shared helper testing for "Cells starting in this range"?). |
| 836 */ | 829 */ |
| 837 | 830 |
| 838 /* If the offset is broken, return an invalid page number. */ | 831 /* If the offset is broken, return an invalid page number. */ |
| 839 return 0; | 832 return 0; |
| 840 } | 833 } |
| 841 | 834 |
| 842 static int interiorCursorEOF(RecoverInteriorCursor *pCursor){ | |
| 843 /* Find a parent with remaining children. EOF if none found. */ | |
| 844 while( pCursor && pCursor->iChild>=pCursor->nChildren ){ | |
| 845 pCursor = pCursor->pParent; | |
| 846 } | |
| 847 return pCursor==NULL; | |
| 848 } | |
| 849 | |
| 850 /* Internal helper. Used to detect if iPage would cause a loop. */ | 835 /* Internal helper. Used to detect if iPage would cause a loop. */ |
| 851 static int interiorCursorPageInUse(RecoverInteriorCursor *pCursor, | 836 static int interiorCursorPageInUse(RecoverInteriorCursor *pCursor, |
| 852 unsigned iPage){ | 837 unsigned iPage){ |
| 853 /* Find any parent using the indicated page. */ | 838 /* Find any parent using the indicated page. */ |
| 854 while( pCursor && pCursor->pPage->pgno!=iPage ){ | 839 while( pCursor && pCursor->pPage->pgno!=iPage ){ |
| 855 pCursor = pCursor->pParent; | 840 pCursor = pCursor->pParent; |
| 856 } | 841 } |
| 857 return pCursor!=NULL; | 842 return pCursor!=NULL; |
| 858 } | 843 } |
| 859 | 844 |
| (...skipping 1416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2276 rc = sqlite3_declare_vtab(db, zCreateSql); | 2261 rc = sqlite3_declare_vtab(db, zCreateSql); |
| 2277 sqlite3_free(zCreateSql); | 2262 sqlite3_free(zCreateSql); |
| 2278 if( rc!=SQLITE_OK ){ | 2263 if( rc!=SQLITE_OK ){ |
| 2279 recoverRelease(pRecover); | 2264 recoverRelease(pRecover); |
| 2280 return rc; | 2265 return rc; |
| 2281 } | 2266 } |
| 2282 | 2267 |
| 2283 *ppVtab = (sqlite3_vtab *)pRecover; | 2268 *ppVtab = (sqlite3_vtab *)pRecover; |
| 2284 return SQLITE_OK; | 2269 return SQLITE_OK; |
| 2285 } | 2270 } |
| OLD | NEW |