1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/*
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)** 2012 Jan 11
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)**
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)** The author disclaims copyright to this source code.  In place of
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)** a legal notice, here is a blessing:
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)**
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)**    May you do good and not evil.
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)**    May you find forgiveness for yourself and forgive others.
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)**    May you share freely, never taking more than you give.
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)*/
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* TODO(shess): THIS MODULE IS STILL EXPERIMENTAL.  DO NOT USE IT. */
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Implements a virtual table "recover" which can be used to recover
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * data from a corrupt table.  The table is walked manually, with
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * corrupt items skipped.  Additionally, any errors while reading will
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * be skipped.
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Given a table with this definition:
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * CREATE TABLE Stuff (
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *   name TEXT PRIMARY KEY,
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *   value TEXT NOT NULL
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * );
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * to recover the data from teh table, you could do something like:
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * -- Attach another database, the original is not trustworthy.
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * ATTACH DATABASE '/tmp/db.db' AS rdb;
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * -- Create a new version of the table.
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * CREATE TABLE rdb.Stuff (
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *   name TEXT PRIMARY KEY,
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *   value TEXT NOT NULL
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * );
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * -- This will read the original table's data.
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * CREATE VIRTUAL TABLE temp.recover_Stuff using recover(
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *   main.Stuff,
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *   name TEXT STRICT NOT NULL,  -- only real TEXT data allowed
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *   value TEXT STRICT NOT NULL
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * );
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * -- Corruption means the UNIQUE constraint may no longer hold for
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * -- Stuff, so either OR REPLACE or OR IGNORE must be used.
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * INSERT OR REPLACE INTO rdb.Stuff (rowid, name, value )
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *   SELECT rowid, name, value FROM temp.recover_Stuff;
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * DROP TABLE temp.recover_Stuff;
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * DETACH DATABASE rdb;
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * -- Move db.db to replace original db in filesystem.
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Usage
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Given the goal of dealing with corruption, it would not be safe to
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * create a recovery table in the database being recovered.  So
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * recovery tables must be created in the temp database.  They are not
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * appropriate to persist, in any case.  [As a bonus, sqlite_master
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * tables can be recovered.  Perhaps more cute than useful, though.]
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * The parameters are a specifier for the table to read, and a column
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * definition for each bit of data stored in that table.  The named
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * table must be convertable to a root page number by reading the
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * sqlite_master table.  Bare table names are assumed to be in
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * database 0 ("main"), other databases can be specified in db.table
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * fashion.
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Column definitions are similar to BUT NOT THE SAME AS those
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * provided to CREATE statements:
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *  column-def: column-name [type-name [STRICT] [NOT NULL]]
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *  type-name: (ANY|ROWID|INTEGER|FLOAT|NUMERIC|TEXT|BLOB)
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Only those exact type names are accepted, there is no type
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * intuition.  The only constraints accepted are STRICT (see below)
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * and NOT NULL.  Anything unexpected will cause the create to fail.
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * ANY is a convenience to indicate that manifest typing is desired.
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * It is equivalent to not specifying a type at all.  The results for
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * such columns will have the type of the data's storage.  The exposed
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * schema will contain no type for that column.
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * ROWID is used for columns representing aliases to the rowid
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * (INTEGER PRIMARY KEY, with or without AUTOINCREMENT), to make the
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * concept explicit.  Such columns are actually stored as NULL, so
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * they cannot be simply ignored.  The exposed schema will be INTEGER
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * for that column.
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * NOT NULL causes rows with a NULL in that column to be skipped.  It
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * also adds NOT NULL to the column in the exposed schema.  If the
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * table has ever had columns added using ALTER TABLE, then those
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * columns implicitly contain NULL for rows which have not been
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * updated.  [Workaround using COALESCE() in your SELECT statement.]
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * The created table is read-only, with no indices.  Any SELECT will
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * be a full-table scan, returning each valid row read from the
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * storage of the backing table.  The rowid will be the rowid of the
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * row from the backing table.  "Valid" means:
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * - The cell metadata for the row is well-formed.  Mainly this means that
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *   the cell header info describes a payload of the size indicated by
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *   the cell's payload size.
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * - The cell does not run off the page.
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * - The cell does not overlap any other cell on the page.
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * - The cell contains doesn't contain too many columns.
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * - The types of the serialized data match the indicated types (see below).
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Type affinity versus type storage.
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * http://www.sqlite.org/datatype3.html describes SQLite's type
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * affinity system.  The system provides for automated coercion of
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * types in certain cases, transparently enough that many developers
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * do not realize that it is happening.  Importantly, it implies that
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * the raw data stored in the database may not have the obvious type.
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Differences between the stored data types and the expected data
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * types may be a signal of corruption.  This module makes some
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * allowances for automatic coercion.  It is important to be concious
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * of the difference between the schema exposed by the module, and the
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * data types read from storage.  The following table describes how
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * the module interprets things:
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * type     schema   data                     STRICT
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * ----     ------   ----                     ------
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * ANY      <none>   any                      any
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * ROWID    INTEGER  n/a                      n/a
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * INTEGER  INTEGER  integer                  integer
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * FLOAT    FLOAT    integer or float         float
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * NUMERIC  NUMERIC  integer, float, or text  integer or float
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * TEXT     TEXT     text or blob             text
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * BLOB     BLOB     blob                     blob
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * type is the type provided to the recover module, schema is the
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * schema exposed by the module, data is the acceptable types of data
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * decoded from storage, and STRICT is a modification of that.
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * A very loose recovery system might use ANY for all columns, then
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * use the appropriate sqlite3_column_*() calls to coerce to expected
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * types.  This doesn't provide much protection if a page from a
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * different table with the same column count is linked into an
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * inappropriate btree.
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * A very tight recovery system might use STRICT to enforce typing on
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * all columns, preferring to skip rows which are valid at the storage
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * level but don't contain the right types.  Note that FLOAT STRICT is
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * almost certainly not appropriate, since integral values are
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * transparently stored as integers, when that is more efficient.
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Another option is to use ANY for all columns and inspect each
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * result manually (using sqlite3_column_*).  This should only be
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * necessary in cases where developers have used manifest typing (test
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * to make sure before you decide that you aren't using manifest
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * typing!).
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Caveats
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Leaf pages not referenced by interior nodes will not be found.
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Leaf pages referenced from interior nodes of other tables will not
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * be resolved.
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Rows referencing invalid overflow pages will be skipped.
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * SQlite rows have a header which describes how to interpret the rest
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * of the payload.  The header can be valid in cases where the rest of
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * the record is actually corrupt (in the sense that the data is not
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * the intended data).  This can especially happen WRT overflow pages,
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * as lack of atomic updates between pages is the primary form of
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * corruption I have seen in the wild.
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* The implementation is via a series of cursors.  The cursor
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * implementations follow the pattern:
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * // Creates the cursor using various initialization info.
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * int cursorCreate(...);
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * // Returns 1 if there is no more data, 0 otherwise.
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * int cursorEOF(Cursor *pCursor);
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * // Various accessors can be used if not at EOF.
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * // Move to the next item.
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * int cursorNext(Cursor *pCursor);
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * // Destroy the memory associated with the cursor.
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * void cursorDestroy(Cursor *pCursor);
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * References in the following are to sections at
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * http://www.sqlite.org/fileformat2.html .
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * RecoverLeafCursor iterates the records in a leaf table node
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * described in section 1.5 "B-tree Pages".  When the node is
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * exhausted, an interior cursor is used to get the next leaf node,
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * and iteration continues there.
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * RecoverInteriorCursor iterates the child pages in an interior table
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * node described in section 1.5 "B-tree Pages".  When the node is
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * exhausted, a parent interior cursor is used to get the next
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * interior node at the same level, and iteration continues there.
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Together these record the path from the leaf level to the root of
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * the tree.  Iteration happens from the leaves rather than the root
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * both for efficiency and putting the special case at the front of
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * the list is easier to implement.
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * RecoverCursor uses a RecoverLeafCursor to iterate the rows of a
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * table, returning results via the SQLite virtual table interface.
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* TODO(shess): It might be useful to allow DEFAULT in types to
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * specify what to do for NULL when an ALTER TABLE case comes up.
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Unfortunately, simply adding it to the exposed schema and using
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * sqlite3_result_null() does not cause the default to be generate.
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Handling it ourselves seems hard, unfortunately.
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <assert.h>
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <ctype.h>
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <stdio.h>
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <string.h>
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Internal SQLite things that are used:
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * u32, u64, i64 types.
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Btree, Pager, and DbPage structs.
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * DbPage.pData, .pPager, and .pgno
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * sqlite3 struct.
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * sqlite3BtreePager() and sqlite3BtreeGetPageSize()
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * sqlite3PagerAcquire() and sqlite3PagerUnref()
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * getVarint().
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "sqliteInt.h"
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* For debugging. */
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if 0
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define FNENTRY() fprintf(stderr, "In %s\n", __FUNCTION__)
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#else
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define FNENTRY()
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Generic constants and helper functions. */
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const unsigned char kTableLeafPage = 0x0D;
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const unsigned char kTableInteriorPage = 0x05;
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* From section 1.5. */
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const unsigned kiPageTypeOffset = 0;
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const unsigned kiPageFreeBlockOffset = 1;
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const unsigned kiPageCellCountOffset = 3;
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const unsigned kiPageCellContentOffset = 5;
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const unsigned kiPageFragmentedBytesOffset = 7;
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const unsigned knPageLeafHeaderBytes = 8;
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Interior pages contain an additional field. */
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const unsigned kiPageRightChildOffset = 8;
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const unsigned kiPageInteriorHeaderBytes = 12;
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Accepted types are specified by a mask. */
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define MASK_ROWID (1<<0)
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define MASK_INTEGER (1<<1)
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define MASK_FLOAT (1<<2)
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define MASK_TEXT (1<<3)
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define MASK_BLOB (1<<4)
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define MASK_NULL (1<<5)
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Helpers to decode fixed-size fields. */
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static u32 decodeUnsigned16(const unsigned char *pData){
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return (pData[0]<<8) + pData[1];
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static u32 decodeUnsigned32(const unsigned char *pData){
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return (decodeUnsigned16(pData)<<16) + decodeUnsigned16(pData+2);
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static i64 decodeSigned(const unsigned char *pData, unsigned nBytes){
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  i64 r = (char)(*pData);
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while( --nBytes ){
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    r <<= 8;
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    r += *(++pData);
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return r;
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Derived from vdbeaux.c, sqlite3VdbeSerialGet(), case 7. */
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* TODO(shess): Determine if swapMixedEndianFloat() applies. */
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static double decodeFloat64(const unsigned char *pData){
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if !defined(NDEBUG)
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  static const u64 t1 = ((u64)0x3ff00000)<<32;
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  static const double r1 = 1.0;
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  u64 t2 = t1;
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  i64 x = decodeSigned(pData, 8);
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  double d;
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  memcpy(&d, &x, sizeof(x));
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return d;
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Return true if a varint can safely be read from pData/nData. */
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* TODO(shess): DbPage points into the middle of a buffer which
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * contains the page data before DbPage.  So code should always be
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * able to read a small number of varints safely.  Consider whether to
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * trust that or not.
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int checkVarint(const unsigned char *pData, unsigned nData){
295ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned i;
296ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* In the worst case the decoder takes all 8 bits of the 9th byte. */
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( nData>=9 ){
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return 1;
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Look for a high-bit-clear byte in what's left. */
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for( i=0; i<nData; ++i ){
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( !(pData[i]&0x80) ){
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return 1;
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Cannot decode in the space given. */
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return 0;
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Return 1 if n varints can be read from pData/nData. */
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int checkVarints(const unsigned char *pData, unsigned nData,
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        unsigned n){
316ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned nCur = 0;   /* Byte offset within current varint. */
317ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned nFound = 0; /* Number of varints found. */
318ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned i;
319ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* In the worst case the decoder takes all 8 bits of the 9th byte. */
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( nData>=9*n ){
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return 1;
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for( i=0; nFound<n && i<nData; ++i ){
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    nCur++;
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( nCur==9 || !(pData[i]&0x80) ){
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      nFound++;
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      nCur = 0;
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return nFound==n;
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* ctype and str[n]casecmp() can be affected by locale (eg, tr_TR).
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * These versions consider only the ASCII space.
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* TODO(shess): It may be reasonable to just remove the need for these
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * entirely.  The module could require "TEXT STRICT NOT NULL", not
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * "Text Strict Not Null" or whatever the developer felt like typing
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * that day.  Handling corrupt data is a PERFECT place to be pedantic.
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int ascii_isspace(char c){
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* From fts3_expr.c */
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f';
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int ascii_isalnum(int x){
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* From fts3_tokenizer1.c */
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return (x>='0' && x<='9') || (x>='A' && x<='Z') || (x>='a' && x<='z');
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int ascii_tolower(int x){
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* From fts3_tokenizer1.c */
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return (x>='A' && x<='Z') ? x-'A'+'a' : x;
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* TODO(shess): Consider sqlite3_strnicmp() */
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int ascii_strncasecmp(const char *s1, const char *s2, size_t n){
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const unsigned char *us1 = (const unsigned char *)s1;
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const unsigned char *us2 = (const unsigned char *)s2;
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while( *us1 && *us2 && n && ascii_tolower(*us1)==ascii_tolower(*us2) ){
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    us1++, us2++, n--;
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return n ? ascii_tolower(*us1)-ascii_tolower(*us2) : 0;
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int ascii_strcasecmp(const char *s1, const char *s2){
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* If s2 is equal through strlen(s1), will exit while() due to s1's
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * trailing NUL, and return NUL-s2[strlen(s1)].
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return ascii_strncasecmp(s1, s2, strlen(s1)+1);
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* For some reason I kept making mistakes with offset calculations. */
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const unsigned char *PageData(DbPage *pPage, unsigned iOffset){
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  assert( iOffset<=pPage->nPageSize );
375ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return (unsigned char *)pPage->pData + iOffset;
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* The first page in the file contains a file header in the first 100
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * bytes.  The page's header information comes after that.  Note that
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * the offsets in the page's header information are relative to the
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * beginning of the page, NOT the end of the page header.
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const unsigned char *PageHeader(DbPage *pPage){
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( pPage->pgno==1 ){
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const unsigned nDatabaseHeader = 100;
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return PageData(pPage, nDatabaseHeader);
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }else{
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return PageData(pPage, 0);
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Helper to fetch the pager and page size for the named database. */
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int GetPager(sqlite3 *db, const char *zName,
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    Pager **pPager, unsigned *pnPageSize){
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Btree *pBt = NULL;
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int i;
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for( i=0; i<db->nDb; ++i ){
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( ascii_strcasecmp(db->aDb[i].zName, zName)==0 ){
399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      pBt = db->aDb[i].pBt;
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( !pBt ){
404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_ERROR;
405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *pPager = sqlite3BtreePager(pBt);
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *pnPageSize = sqlite3BtreeGetPageSize(pBt) - sqlite3BtreeGetReserve(pBt);
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SQLITE_OK;
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* iSerialType is a type read from a record header.  See "2.1 Record Format".
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Storage size of iSerialType in bytes.  My interpretation of SQLite
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * documentation is that text and blob fields can have 32-bit length.
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Values past 2^31-12 will need more than 32 bits to encode, which is
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * why iSerialType is u64.
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static u32 SerialTypeLength(u64 iSerialType){
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch( iSerialType ){
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 0 : return 0;  /* NULL */
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 1 : return 1;  /* Various integers. */
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 2 : return 2;
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 3 : return 3;
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 4 : return 4;
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 5 : return 6;
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 6 : return 8;
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 7 : return 8;  /* 64-bit float. */
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 8 : return 0;  /* Constant 0. */
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 9 : return 0;  /* Constant 1. */
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 10 : case 11 : assert( !"RESERVED TYPE"); return 0;
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return (u32)((iSerialType>>1) - 6);
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* True if iSerialType refers to a blob. */
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int SerialTypeIsBlob(u64 iSerialType){
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  assert( iSerialType>=12 );
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return (iSerialType%2)==0;
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Returns true if the serialized type represented by iSerialType is
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * compatible with the given type mask.
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int SerialTypeIsCompatible(u64 iSerialType, unsigned char mask){
447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch( iSerialType ){
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 0  : return (mask&MASK_NULL)!=0;
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 1  : return (mask&MASK_INTEGER)!=0;
450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 2  : return (mask&MASK_INTEGER)!=0;
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 3  : return (mask&MASK_INTEGER)!=0;
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 4  : return (mask&MASK_INTEGER)!=0;
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 5  : return (mask&MASK_INTEGER)!=0;
454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 6  : return (mask&MASK_INTEGER)!=0;
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 7  : return (mask&MASK_FLOAT)!=0;
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 8  : return (mask&MASK_INTEGER)!=0;
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 9  : return (mask&MASK_INTEGER)!=0;
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 10 : assert( !"RESERVED TYPE"); return 0;
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 11 : assert( !"RESERVED TYPE"); return 0;
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return (mask&(SerialTypeIsBlob(iSerialType) ? MASK_BLOB : MASK_TEXT));
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Versions of strdup() with return values appropriate for
465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * sqlite3_free().  malloc.c has sqlite3DbStrDup()/NDup(), but those
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * need sqlite3DbFree(), which seems intrusive.
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static char *sqlite3_strndup(const char *z, unsigned n){
469ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  char *zNew;
470ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( z==NULL ){
472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return NULL;
473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
475ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  zNew = sqlite3_malloc(n+1);
476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( zNew!=NULL ){
477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    memcpy(zNew, z, n);
478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    zNew[n] = '\0';
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return zNew;
481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static char *sqlite3_strdup(const char *z){
483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( z==NULL ){
484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return NULL;
485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return sqlite3_strndup(z, strlen(z));
487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Fetch the page number of zTable in zDb from sqlite_master in zDb,
490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * and put it in *piRootPage.
491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int getRootPage(sqlite3 *db, const char *zDb, const char *zTable,
493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       u32 *piRootPage){
494ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  char *zSql;  /* SQL selecting root page of named element. */
495ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  sqlite3_stmt *pStmt;
496ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  int rc;
497ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( strcmp(zTable, "sqlite_master")==0 ){
499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *piRootPage = 1;
500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_OK;
501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
503ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  zSql = sqlite3_mprintf("SELECT rootpage FROM %s.sqlite_master "
504ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                         "WHERE type = 'table' AND tbl_name = %Q",
505ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                         zDb, zTable);
506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( !zSql ){
507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_NOMEM;
508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
510ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sqlite3_free(zSql);
512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( rc!=SQLITE_OK ){
513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return rc;
514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Require a result. */
517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rc = sqlite3_step(pStmt);
518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( rc==SQLITE_DONE ){
519c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    rc = SQLITE_CORRUPT;
520c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }else if( rc==SQLITE_ROW ){
521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *piRootPage = sqlite3_column_int(pStmt, 0);
522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* Require only one result. */
524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    rc = sqlite3_step(pStmt);
525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( rc==SQLITE_DONE ){
526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      rc = SQLITE_OK;
527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }else if( rc==SQLITE_ROW ){
528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      rc = SQLITE_CORRUPT;
529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sqlite3_finalize(pStmt);
532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return rc;
533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int getEncoding(sqlite3 *db, const char *zDb, int* piEncoding){
536ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  sqlite3_stmt *pStmt;
537ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  int rc;
538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  char *zSql = sqlite3_mprintf("PRAGMA %s.encoding", zDb);
539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( !zSql ){
540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_NOMEM;
541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
543ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sqlite3_free(zSql);
545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( rc!=SQLITE_OK ){
546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return rc;
547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Require a result. */
550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rc = sqlite3_step(pStmt);
551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( rc==SQLITE_DONE ){
552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* This case should not be possible. */
553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    rc = SQLITE_CORRUPT;
554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }else if( rc==SQLITE_ROW ){
555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( sqlite3_column_type(pStmt, 0)==SQLITE_TEXT ){
556ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      const char* z = (const char *)sqlite3_column_text(pStmt, 0);
557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      /* These strings match the literals in pragma.c. */
558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if( !strcmp(z, "UTF-16le") ){
559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        *piEncoding = SQLITE_UTF16LE;
560c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }else if( !strcmp(z, "UTF-16be") ){
561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        *piEncoding = SQLITE_UTF16BE;
562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }else if( !strcmp(z, "UTF-8") ){
563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        *piEncoding = SQLITE_UTF8;
564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }else{
565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        /* This case should not be possible. */
566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        *piEncoding = SQLITE_UTF8;
567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
568c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }else{
569c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      /* This case should not be possible. */
570c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      *piEncoding = SQLITE_UTF8;
571c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
572c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
573c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* Require only one result. */
574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    rc = sqlite3_step(pStmt);
575c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( rc==SQLITE_DONE ){
576c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      rc = SQLITE_OK;
577c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }else if( rc==SQLITE_ROW ){
578c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      /* This case should not be possible. */
579c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      rc = SQLITE_CORRUPT;
580c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
581c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
582c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sqlite3_finalize(pStmt);
583c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return rc;
584c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
585c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Cursor for iterating interior nodes.  Interior page cells contain a
587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * child page number and a rowid.  The child page contains items left
588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * of the rowid (less than).  The rightmost page of the subtree is
589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * stored in the page header.
590c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
591c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * interiorCursorDestroy - release all resources associated with the
592c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *                         cursor and any parent cursors.
593c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * interiorCursorCreate - create a cursor with the given parent and page.
594c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * interiorCursorEOF - returns true if neither the cursor nor the
595c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *                     parent cursors can return any more data.
596c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * interiorCursorNextPage - fetch the next child page from the cursor.
597c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
598c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Logically, interiorCursorNextPage() returns the next child page
599c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * number from the page the cursor is currently reading, calling the
600c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * parent cursor as necessary to get new pages to read, until done.
601c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * SQLITE_ROW if a page is returned, SQLITE_DONE if out of pages,
602c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * error otherwise.  Unfortunately, if the table is corrupted
603c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * unexpected pages can be returned.  If any unexpected page is found,
604c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * leaf or otherwise, it is returned to the caller for processing,
605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * with the interior cursor left empty.  The next call to
606c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * interiorCursorNextPage() will recurse to the parent cursor until an
607c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * interior page to iterate is returned.
608c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
609c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Note that while interiorCursorNextPage() will refuse to follow
610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * loops, it does not keep track of pages returned for purposes of
611c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * preventing duplication.
612c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Note that interiorCursorEOF() could return false (not at EOF), and
614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * interiorCursorNextPage() could still return SQLITE_DONE.  This
615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * could happen if there are more cells to iterate in an interior
616c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * page, but those cells refer to invalid pages.
617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
618c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)typedef struct RecoverInteriorCursor RecoverInteriorCursor;
619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)struct RecoverInteriorCursor {
620c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RecoverInteriorCursor *pParent; /* Parent node to this node. */
621c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DbPage *pPage;                  /* Reference to leaf page. */
622c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  unsigned nPageSize;             /* Size of page. */
623c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  unsigned nChildren;             /* Number of children on the page. */
624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  unsigned iChild;                /* Index of next child to return. */
625c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static void interiorCursorDestroy(RecoverInteriorCursor *pCursor){
628c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Destroy all the cursors to the root. */
629c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while( pCursor ){
630c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RecoverInteriorCursor *p = pCursor;
631c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pCursor = pCursor->pParent;
632c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
633c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( p->pPage ){
634c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      sqlite3PagerUnref(p->pPage);
635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      p->pPage = NULL;
636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
637c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
638c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    memset(p, 0xA5, sizeof(*p));
639c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    sqlite3_free(p);
640c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
641c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
642c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
643c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Internal helper.  Reset storage in preparation for iterating pPage. */
644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static void interiorCursorSetPage(RecoverInteriorCursor *pCursor,
645c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  DbPage *pPage){
646c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  assert( PageHeader(pPage)[kiPageTypeOffset]==kTableInteriorPage );
647c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( pCursor->pPage ){
649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    sqlite3PagerUnref(pCursor->pPage);
650c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pCursor->pPage = NULL;
651c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
652c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pCursor->pPage = pPage;
653c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pCursor->iChild = 0;
654c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
655c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* A child for each cell, plus one in the header. */
656c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* TODO(shess): Sanity-check the count?  Page header plus per-cell
657c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * cost of 16-bit offset, 32-bit page number, and one varint
658c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * (minimum 1 byte).
659c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pCursor->nChildren = decodeUnsigned16(PageHeader(pPage) +
661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                        kiPageCellCountOffset) + 1;
662c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
663c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
664c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int interiorCursorCreate(RecoverInteriorCursor *pParent,
665c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                DbPage *pPage, int nPageSize,
666c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                RecoverInteriorCursor **ppCursor){
667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RecoverInteriorCursor *pCursor =
668c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    sqlite3_malloc(sizeof(RecoverInteriorCursor));
669c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( !pCursor ){
670c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_NOMEM;
671c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
672c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
673c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  memset(pCursor, 0, sizeof(*pCursor));
674c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pCursor->pParent = pParent;
675c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pCursor->nPageSize = nPageSize;
676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  interiorCursorSetPage(pCursor, pPage);
677c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *ppCursor = pCursor;
678c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SQLITE_OK;
679c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
680c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
681c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Internal helper.  Return the child page number at iChild. */
682c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static unsigned interiorCursorChildPage(RecoverInteriorCursor *pCursor){
683ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const unsigned char *pPageHeader;  /* Header of the current page. */
684ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const unsigned char *pCellOffsets; /* Offset to page's cell offsets. */
685ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned iCellOffset;              /* Offset of target cell. */
686ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
687c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  assert( pCursor->iChild<pCursor->nChildren );
688c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
689c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Rightmost child is in the header. */
690ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  pPageHeader = PageHeader(pCursor->pPage);
691c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( pCursor->iChild==pCursor->nChildren-1 ){
692c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return decodeUnsigned32(pPageHeader + kiPageRightChildOffset);
693c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
694c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
695c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Each cell is a 4-byte integer page number and a varint rowid
696c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * which is greater than the rowid of items in that sub-tree (this
697c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * module ignores ordering). The offset is from the beginning of the
698c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * page, not from the page header.
699c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
700ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  pCellOffsets = pPageHeader + kiPageInteriorHeaderBytes;
701ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  iCellOffset = decodeUnsigned16(pCellOffsets + pCursor->iChild*2);
702c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( iCellOffset<=pCursor->nPageSize-4 ){
703c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return decodeUnsigned32(PageData(pCursor->pPage, iCellOffset));
704c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
705c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
706c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* TODO(shess): Check for cell overlaps?  Cells require 4 bytes plus
707c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * a varint.  Check could be identical to leaf check (or even a
708c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * shared helper testing for "Cells starting in this range"?).
709c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
710c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
711c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* If the offset is broken, return an invalid page number. */
712c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return 0;
713c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
714c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
715c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int interiorCursorEOF(RecoverInteriorCursor *pCursor){
716c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Find a parent with remaining children.  EOF if none found. */
717c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while( pCursor && pCursor->iChild>=pCursor->nChildren ){
718c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pCursor = pCursor->pParent;
719c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
720c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return pCursor==NULL;
721c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
722c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
723c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Internal helper.  Used to detect if iPage would cause a loop. */
724c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int interiorCursorPageInUse(RecoverInteriorCursor *pCursor,
725c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                   unsigned iPage){
726c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Find any parent using the indicated page. */
727c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while( pCursor && pCursor->pPage->pgno!=iPage ){
728c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pCursor = pCursor->pParent;
729c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
730c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return pCursor!=NULL;
731c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
732c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
733c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Get the next page from the interior cursor at *ppCursor.  Returns
734c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * SQLITE_ROW with the page in *ppPage, or SQLITE_DONE if out of
735c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * pages, or the error SQLite returned.
736c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
737c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * If the tree is uneven, then when the cursor attempts to get a new
738c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * interior page from the parent cursor, it may get a non-interior
739c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * page.  In that case, the new page is returned, and *ppCursor is
740c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * updated to point to the parent cursor (this cursor is freed).
741c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
742c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* TODO(shess): I've tried to avoid recursion in most of this code,
743c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * but this case is more challenging because the recursive call is in
744c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * the middle of operation.  One option for converting it without
745c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * adding memory management would be to retain the head pointer and
746c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * use a helper to "back up" as needed.  Another option would be to
747c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * reverse the list during traversal.
748c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
749c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int interiorCursorNextPage(RecoverInteriorCursor **ppCursor,
750c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  DbPage **ppPage){
751c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RecoverInteriorCursor *pCursor = *ppCursor;
752c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while( 1 ){
753ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    int rc;
754ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const unsigned char *pPageHeader;  /* Header of found page. */
755ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
756c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* Find a valid child page which isn't on the stack. */
757c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    while( pCursor->iChild<pCursor->nChildren ){
758c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const unsigned iPage = interiorCursorChildPage(pCursor);
759c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      pCursor->iChild++;
760c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if( interiorCursorPageInUse(pCursor, iPage) ){
761c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        fprintf(stderr, "Loop detected at %d\n", iPage);
762c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }else{
763c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        int rc = sqlite3PagerAcquire(pCursor->pPage->pPager, iPage, ppPage, 0);
764c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if( rc==SQLITE_OK ){
765c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          return SQLITE_ROW;
766c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
767c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
768c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
769c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
770c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* This page has no more children.  Get next page from parent. */
771c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( !pCursor->pParent ){
772c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return SQLITE_DONE;
773c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
774ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    rc = interiorCursorNextPage(&pCursor->pParent, ppPage);
775c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( rc!=SQLITE_ROW ){
776c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return rc;
777c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
778c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
779c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* If a non-interior page is received, that either means that the
780c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * tree is uneven, or that a child was re-used (say as an overflow
781c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * page).  Remove this cursor and let the caller handle the page.
782c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
783ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    pPageHeader = PageHeader(*ppPage);
784c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( pPageHeader[kiPageTypeOffset]!=kTableInteriorPage ){
785c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      *ppCursor = pCursor->pParent;
786c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      pCursor->pParent = NULL;
787c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      interiorCursorDestroy(pCursor);
788c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return SQLITE_ROW;
789c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
790c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
791c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* Iterate the new page. */
792c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    interiorCursorSetPage(pCursor, *ppPage);
793c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *ppPage = NULL;
794c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
795c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
796c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  assert(NULL);  /* NOTREACHED() */
797c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SQLITE_CORRUPT;
798c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
799c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
800c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Large rows are spilled to overflow pages.  The row's main page
801c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * stores the overflow page number after the local payload, with a
802c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * linked list forward from there as necessary.  overflowMaybeCreate()
803c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * and overflowGetSegment() provide an abstraction for accessing such
804c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * data while centralizing the code.
805c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
806c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * overflowDestroy - releases all resources associated with the structure.
807c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * overflowMaybeCreate - create the overflow structure if it is needed
808c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *                       to represent the given record.  See function comment.
809c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * overflowGetSegment - fetch a segment from the record, accounting
810c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *                      for overflow pages.  Segments which are not
811c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *                      entirely contained with a page are constructed
812c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *                      into a buffer which is returned.  See function comment.
813c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
814c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)typedef struct RecoverOverflow RecoverOverflow;
815c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)struct RecoverOverflow {
816c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RecoverOverflow *pNextOverflow;
817c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DbPage *pPage;
818c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  unsigned nPageSize;
819c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
820c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
821c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static void overflowDestroy(RecoverOverflow *pOverflow){
822c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while( pOverflow ){
823c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RecoverOverflow *p = pOverflow;
824c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pOverflow = p->pNextOverflow;
825c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
826c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( p->pPage ){
827c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      sqlite3PagerUnref(p->pPage);
828c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      p->pPage = NULL;
829c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
830c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
831c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    memset(p, 0xA5, sizeof(*p));
832c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    sqlite3_free(p);
833c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
834c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
835c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
836c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Internal helper.  Used to detect if iPage would cause a loop. */
837c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int overflowPageInUse(RecoverOverflow *pOverflow, unsigned iPage){
838c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while( pOverflow && pOverflow->pPage->pgno!=iPage ){
839c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pOverflow = pOverflow->pNextOverflow;
840c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
841c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return pOverflow!=NULL;
842c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
843c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
844c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Setup to access an nRecordBytes record beginning at iRecordOffset
845c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * in pPage.  If nRecordBytes can be satisfied entirely from pPage,
846c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * then no overflow pages are needed an *pnLocalRecordBytes is set to
847c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * nRecordBytes.  Otherwise, *ppOverflow is set to the head of a list
848c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * of overflow pages, and *pnLocalRecordBytes is set to the number of
849c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * bytes local to pPage.
850c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
851c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * overflowGetSegment() will do the right thing regardless of whether
852c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * those values are set to be in-page or not.
853c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
854c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int overflowMaybeCreate(DbPage *pPage, unsigned nPageSize,
855c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               unsigned iRecordOffset, unsigned nRecordBytes,
856c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               unsigned *pnLocalRecordBytes,
857c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               RecoverOverflow **ppOverflow){
858ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned nLocalRecordBytes;  /* Record bytes in the leaf page. */
859ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned iNextPage;          /* Next page number for record data. */
860ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned nBytes;             /* Maximum record bytes as of current page. */
861ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  int rc;
862ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  RecoverOverflow *pFirstOverflow;  /* First in linked list of pages. */
863ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  RecoverOverflow *pLastOverflow;   /* End of linked list. */
864ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
865c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Calculations from the "Table B-Tree Leaf Cell" part of section
866c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * 1.5 of http://www.sqlite.org/fileformat2.html .  maxLocal and
867c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * minLocal to match naming in btree.c.
868c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
869c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const unsigned maxLocal = nPageSize - 35;
870c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const unsigned minLocal = ((nPageSize-12)*32/255)-23;  /* m */
871c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
872c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Always fit anything smaller than maxLocal. */
873c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( nRecordBytes<=maxLocal ){
874c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *pnLocalRecordBytes = nRecordBytes;
875c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *ppOverflow = NULL;
876c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_OK;
877c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
878c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
879c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Calculate the remainder after accounting for minLocal on the leaf
880c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * page and what packs evenly into overflow pages.  If the remainder
881c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * does not fit into maxLocal, then a partially-full overflow page
882c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * will be required in any case, so store as little as possible locally.
883c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
884ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  nLocalRecordBytes = minLocal+((nRecordBytes-minLocal)%(nPageSize-4));
885c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( maxLocal<nLocalRecordBytes ){
886c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    nLocalRecordBytes = minLocal;
887c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
888c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
889c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Don't read off the end of the page. */
890c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( iRecordOffset+nLocalRecordBytes+4>nPageSize ){
891c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_CORRUPT;
892c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
893c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
894c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* First overflow page number is after the local bytes. */
895ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  iNextPage =
896c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      decodeUnsigned32(PageData(pPage, iRecordOffset + nLocalRecordBytes));
897ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  nBytes = nLocalRecordBytes;
898c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
899c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* While there are more pages to read, and more bytes are needed,
900c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * get another page.
901c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
902ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  pFirstOverflow = pLastOverflow = NULL;
903ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  rc = SQLITE_OK;
904c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while( iNextPage && nBytes<nRecordBytes ){
905ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    RecoverOverflow *pOverflow;  /* New overflow page for the list. */
906ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
907c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    rc = sqlite3PagerAcquire(pPage->pPager, iNextPage, &pPage, 0);
908c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( rc!=SQLITE_OK ){
909c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
910c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
911c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
912ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    pOverflow = sqlite3_malloc(sizeof(RecoverOverflow));
913c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( !pOverflow ){
914c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      sqlite3PagerUnref(pPage);
915c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      rc = SQLITE_NOMEM;
916c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
917c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
918c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    memset(pOverflow, 0, sizeof(*pOverflow));
919c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pOverflow->pPage = pPage;
920c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pOverflow->nPageSize = nPageSize;
921c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
922c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( !pFirstOverflow ){
923c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      pFirstOverflow = pOverflow;
924c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }else{
925c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      pLastOverflow->pNextOverflow = pOverflow;
926c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
927c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pLastOverflow = pOverflow;
928c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
929c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    iNextPage = decodeUnsigned32(pPage->pData);
930c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    nBytes += nPageSize-4;
931c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
932c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* Avoid loops. */
933c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( overflowPageInUse(pFirstOverflow, iNextPage) ){
934c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      fprintf(stderr, "Overflow loop detected at %d\n", iNextPage);
935c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      rc = SQLITE_CORRUPT;
936c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
937c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
938c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
939c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
940c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* If there were not enough pages, or too many, things are corrupt.
941c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * Not having enough pages is an obvious problem, all the data
942c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * cannot be read.  Too many pages means that the contents of the
943c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * row between the main page and the overflow page(s) is
944c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * inconsistent (most likely one or more of the overflow pages does
945c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * not really belong to this row).
946c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
947c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( rc==SQLITE_OK && (nBytes<nRecordBytes || iNextPage) ){
948c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    rc = SQLITE_CORRUPT;
949c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
950c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
951c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( rc==SQLITE_OK ){
952c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *ppOverflow = pFirstOverflow;
953c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *pnLocalRecordBytes = nLocalRecordBytes;
954c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }else if( pFirstOverflow ){
955c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    overflowDestroy(pFirstOverflow);
956c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
957c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return rc;
958c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
959c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
960c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Use in concert with overflowMaybeCreate() to efficiently read parts
961c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * of a potentially-overflowing record.  pPage and iRecordOffset are
962c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * the values passed into overflowMaybeCreate(), nLocalRecordBytes and
963c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * pOverflow are the values returned by that call.
964c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
965c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * On SQLITE_OK, *ppBase points to nRequestBytes of data at
966c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * iRequestOffset within the record.  If the data exists contiguously
967c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * in a page, a direct pointer is returned, otherwise a buffer from
968c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * sqlite3_malloc() is returned with the data.  *pbFree is set true if
969c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * sqlite3_free() should be called on *ppBase.
970c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
971c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Operation of this function is subtle.  At any time, pPage is the
972c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * current page, with iRecordOffset and nLocalRecordBytes being record
973c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * data within pPage, and pOverflow being the overflow page after
974c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * pPage.  This allows the code to handle both the initial leaf page
975c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * and overflow pages consistently by adjusting the values
976c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * appropriately.
977c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
978c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int overflowGetSegment(DbPage *pPage, unsigned iRecordOffset,
979c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              unsigned nLocalRecordBytes,
980c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              RecoverOverflow *pOverflow,
981c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              unsigned iRequestOffset, unsigned nRequestBytes,
982c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              unsigned char **ppBase, int *pbFree){
983ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned nBase;         /* Amount of data currently collected. */
984ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned char *pBase;   /* Buffer to collect record data into. */
985ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
986c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Skip to the page containing the start of the data. */
987c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while( iRequestOffset>=nLocalRecordBytes && pOverflow ){
988c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* Factor out current page's contribution. */
989c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    iRequestOffset -= nLocalRecordBytes;
990c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
991c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* Move forward to the next page in the list. */
992c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pPage = pOverflow->pPage;
993c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    iRecordOffset = 4;
994c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    nLocalRecordBytes = pOverflow->nPageSize - iRecordOffset;
995c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pOverflow = pOverflow->pNextOverflow;
996c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
997c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
998c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* If the requested data is entirely within this page, return a
999c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * pointer into the page.
1000c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
1001c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( iRequestOffset+nRequestBytes<=nLocalRecordBytes ){
1002c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* TODO(shess): "assignment discards qualifiers from pointer target type"
1003c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Having ppBase be const makes sense, but sqlite3_free() takes non-const.
1004c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
1005ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    *ppBase = (unsigned char *)PageData(pPage, iRecordOffset + iRequestOffset);
1006c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *pbFree = 0;
1007c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_OK;
1008c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1009c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1010c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* The data range would require additional pages. */
1011c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( !pOverflow ){
1012c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* Should never happen, the range is outside the nRecordBytes
1013c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * passed to overflowMaybeCreate().
1014c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
1015c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    assert(NULL);  /* NOTREACHED */
1016c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_ERROR;
1017c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1018c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1019c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Get a buffer to construct into. */
1020ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  nBase = 0;
1021ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  pBase = sqlite3_malloc(nRequestBytes);
1022c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( !pBase ){
1023c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_NOMEM;
1024c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1025c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while( nBase<nRequestBytes ){
1026c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* Copy over data present on this page. */
1027c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    unsigned nCopyBytes = nRequestBytes - nBase;
1028c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( nLocalRecordBytes-iRequestOffset<nCopyBytes ){
1029c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      nCopyBytes = nLocalRecordBytes - iRequestOffset;
1030c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1031c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    memcpy(pBase + nBase, PageData(pPage, iRecordOffset + iRequestOffset),
1032c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           nCopyBytes);
1033c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    nBase += nCopyBytes;
1034c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1035c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( pOverflow ){
1036c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      /* Copy from start of record data in future pages. */
1037c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      iRequestOffset = 0;
1038c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1039c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      /* Move forward to the next page in the list.  Should match
1040c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       * first while() loop.
1041c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       */
1042c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      pPage = pOverflow->pPage;
1043c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      iRecordOffset = 4;
1044c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      nLocalRecordBytes = pOverflow->nPageSize - iRecordOffset;
1045c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      pOverflow = pOverflow->pNextOverflow;
1046c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }else if( nBase<nRequestBytes ){
1047c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      /* Ran out of overflow pages with data left to deliver.  Not
1048c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       * possible if the requested range fits within nRecordBytes
1049c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       * passed to overflowMaybeCreate() when creating pOverflow.
1050c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       */
1051c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      assert(NULL);  /* NOTREACHED */
1052c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      sqlite3_free(pBase);
1053c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return SQLITE_ERROR;
1054c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1055c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1056c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  assert( nBase==nRequestBytes );
1057c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *ppBase = pBase;
1058c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *pbFree = 1;
1059c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SQLITE_OK;
1060c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1061c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1062c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Primary structure for iterating the contents of a table.
1063c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
1064c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * leafCursorDestroy - release all resources associated with the cursor.
1065c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * leafCursorCreate - create a cursor to iterate items from tree at
1066c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *                    the provided root page.
1067c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * leafCursorNextValidCell - get the cursor ready to access data from
1068c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *                           the next valid cell in the table.
1069c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * leafCursorCellRowid - get the current cell's rowid.
1070c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * leafCursorCellColumns - get current cell's column count.
1071c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * leafCursorCellColInfo - get type and data for a column in current cell.
1072c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
1073c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * leafCursorNextValidCell skips cells which fail simple integrity
1074c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * checks, such as overlapping other cells, or being located at
1075c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * impossible offsets, or where header data doesn't correctly describe
1076c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * payload data.  Returns SQLITE_ROW if a valid cell is found,
1077c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * SQLITE_DONE if all pages in the tree were exhausted.
1078c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
1079c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * leafCursorCellColInfo() accounts for overflow pages in the style of
1080c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * overflowGetSegment().
1081c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
1082c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)typedef struct RecoverLeafCursor RecoverLeafCursor;
1083c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)struct RecoverLeafCursor {
1084c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RecoverInteriorCursor *pParent;  /* Parent node to this node. */
1085c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DbPage *pPage;                   /* Reference to leaf page. */
1086c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  unsigned nPageSize;              /* Size of pPage. */
1087c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  unsigned nCells;                 /* Number of cells in pPage. */
1088c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  unsigned iCell;                  /* Current cell. */
1089c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1090c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Info parsed from data in iCell. */
1091c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  i64 iRowid;                      /* rowid parsed. */
1092c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  unsigned nRecordCols;            /* how many items in the record. */
1093c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  u64 iRecordOffset;               /* offset to record data. */
1094c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* TODO(shess): nRecordBytes and nRecordHeaderBytes are used in
1095c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * leafCursorCellColInfo() to prevent buffer overruns.
1096c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * leafCursorCellDecode() already verified that the cell is valid, so
1097c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * those checks should be redundant.
1098c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
1099c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  u64 nRecordBytes;                /* Size of record data. */
1100ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned nLocalRecordBytes;      /* Amount of record data in-page. */
1101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  unsigned nRecordHeaderBytes;     /* Size of record header data. */
1102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  unsigned char *pRecordHeader;    /* Pointer to record header data. */
1103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int bFreeRecordHeader;           /* True if record header requires free. */
1104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RecoverOverflow *pOverflow;      /* Cell overflow info, if needed. */
1105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
1106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Internal helper shared between next-page and create-cursor.  If
1108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * pPage is a leaf page, it will be stored in the cursor and state
1109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * initialized for reading cells.
1110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
1111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * If pPage is an interior page, a new parent cursor is created and
1112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * injected on the stack.  This is necessary to handle trees with
1113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * uneven depth, but also is used during initial setup.
1114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
1115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * If pPage is not a table page at all, it is discarded.
1116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
1117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * If SQLITE_OK is returned, the caller no longer owns pPage,
1118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * otherwise the caller is responsible for discarding it.
1119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
1120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int leafCursorLoadPage(RecoverLeafCursor *pCursor, DbPage *pPage){
1121ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const unsigned char *pPageHeader;  /* Header of *pPage */
1122ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Release the current page. */
1124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( pCursor->pPage ){
1125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    sqlite3PagerUnref(pCursor->pPage);
1126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pCursor->pPage = NULL;
1127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pCursor->iCell = pCursor->nCells = 0;
1128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* If the page is an unexpected interior node, inject a new stack
1131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * layer and try again from there.
1132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
1133ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  pPageHeader = PageHeader(pPage);
1134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( pPageHeader[kiPageTypeOffset]==kTableInteriorPage ){
1135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RecoverInteriorCursor *pParent;
1136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int rc = interiorCursorCreate(pCursor->pParent, pPage, pCursor->nPageSize,
1137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  &pParent);
1138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( rc!=SQLITE_OK ){
1139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return rc;
1140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pCursor->pParent = pParent;
1142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_OK;
1143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Not a leaf page, skip it. */
1146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( pPageHeader[kiPageTypeOffset]!=kTableLeafPage ){
1147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    sqlite3PagerUnref(pPage);
1148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_OK;
1149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Take ownership of the page and start decoding. */
1152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pCursor->pPage = pPage;
1153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pCursor->iCell = 0;
1154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pCursor->nCells = decodeUnsigned16(pPageHeader + kiPageCellCountOffset);
1155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SQLITE_OK;
1156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Get the next leaf-level page in the tree.  Returns SQLITE_ROW when
1159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * a leaf page is found, SQLITE_DONE when no more leaves exist, or any
1160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * error which occurred.
1161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
1162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int leafCursorNextPage(RecoverLeafCursor *pCursor){
1163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( !pCursor->pParent ){
1164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_DONE;
1165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Repeatedly load the parent's next child page until a leaf is found. */
1168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  do {
1169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DbPage *pNextPage;
1170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int rc = interiorCursorNextPage(&pCursor->pParent, &pNextPage);
1171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( rc!=SQLITE_ROW ){
1172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      assert( rc==SQLITE_DONE );
1173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return rc;
1174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    rc = leafCursorLoadPage(pCursor, pNextPage);
1177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( rc!=SQLITE_OK ){
1178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      sqlite3PagerUnref(pNextPage);
1179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return rc;
1180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } while( !pCursor->pPage );
1182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SQLITE_ROW;
1184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static void leafCursorDestroyCellData(RecoverLeafCursor *pCursor){
1187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( pCursor->bFreeRecordHeader ){
1188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    sqlite3_free(pCursor->pRecordHeader);
1189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pCursor->bFreeRecordHeader = 0;
1191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pCursor->pRecordHeader = NULL;
1192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( pCursor->pOverflow ){
1194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    overflowDestroy(pCursor->pOverflow);
1195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pCursor->pOverflow = NULL;
1196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static void leafCursorDestroy(RecoverLeafCursor *pCursor){
1200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  leafCursorDestroyCellData(pCursor);
1201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( pCursor->pParent ){
1203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    interiorCursorDestroy(pCursor->pParent);
1204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pCursor->pParent = NULL;
1205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( pCursor->pPage ){
1208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    sqlite3PagerUnref(pCursor->pPage);
1209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pCursor->pPage = NULL;
1210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  memset(pCursor, 0xA5, sizeof(*pCursor));
1213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sqlite3_free(pCursor);
1214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Create a cursor to iterate the rows from the leaf pages of a table
1217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * rooted at iRootPage.
1218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
1219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* TODO(shess): recoverOpen() calls this to setup the cursor, and I
1220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * think that recoverFilter() may make a hard assumption that the
1221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * cursor returned will turn up at least one valid cell.
1222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
1223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * The cases I can think of which break this assumption are:
1224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * - pPage is a valid leaf page with no valid cells.
1225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * - pPage is a valid interior page with no valid leaves.
1226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * - pPage is a valid interior page who's leaves contain no valid cells.
1227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * - pPage is not a valid leaf or interior page.
1228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
1229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int leafCursorCreate(Pager *pPager, unsigned nPageSize,
1230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            u32 iRootPage, RecoverLeafCursor **ppCursor){
1231ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DbPage *pPage;               /* Reference to page at iRootPage. */
1232ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  RecoverLeafCursor *pCursor;  /* Leaf cursor being constructed. */
1233ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  int rc;
1234ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Start out with the root page. */
1236ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  rc = sqlite3PagerAcquire(pPager, iRootPage, &pPage, 0);
1237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( rc!=SQLITE_OK ){
1238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return rc;
1239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1241ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  pCursor = sqlite3_malloc(sizeof(RecoverLeafCursor));
1242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( !pCursor ){
1243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    sqlite3PagerUnref(pPage);
1244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_NOMEM;
1245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  memset(pCursor, 0, sizeof(*pCursor));
1247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pCursor->nPageSize = nPageSize;
1249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rc = leafCursorLoadPage(pCursor, pPage);
1251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( rc!=SQLITE_OK ){
1252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    sqlite3PagerUnref(pPage);
1253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    leafCursorDestroy(pCursor);
1254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return rc;
1255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* pPage wasn't a leaf page, find the next leaf page. */
1258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( !pCursor->pPage ){
1259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    rc = leafCursorNextPage(pCursor);
1260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ){
1261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      leafCursorDestroy(pCursor);
1262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return rc;
1263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *ppCursor = pCursor;
1267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SQLITE_OK;
1268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Useful for setting breakpoints. */
1271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int ValidateError(){
1272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SQLITE_ERROR;
1273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Setup the cursor for reading the information from cell iCell. */
1276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int leafCursorCellDecode(RecoverLeafCursor *pCursor){
1277ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const unsigned char *pPageHeader;  /* Header of current page. */
12785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const unsigned char *pPageEnd;     /* Byte after end of current page. */
1279ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const unsigned char *pCellOffsets; /* Pointer to page's cell offsets. */
1280ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned iCellOffset;              /* Offset of current cell (iCell). */
1281ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const unsigned char *pCell;        /* Pointer to data at iCellOffset. */
1282ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned nCellMaxBytes;            /* Maximum local size of iCell. */
1283ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned iEndOffset;               /* End of iCell's in-page data. */
1284ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  u64 nRecordBytes;                  /* Expected size of cell, w/overflow. */
1285ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  u64 iRowid;                        /* iCell's rowid (in table). */
1286ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned nRead;                    /* Amount of cell read. */
1287ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned nRecordHeaderRead;        /* Header data read. */
1288ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  u64 nRecordHeaderBytes;            /* Header size expected. */
1289ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned nRecordCols;              /* Columns read from header. */
1290ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  u64 nRecordColBytes;               /* Bytes in payload for those columns. */
1291ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned i;
1292ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  int rc;
1293ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  assert( pCursor->iCell<pCursor->nCells );
1295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  leafCursorDestroyCellData(pCursor);
1297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Find the offset to the row. */
1299ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  pPageHeader = PageHeader(pCursor->pPage);
1300ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  pCellOffsets = pPageHeader + knPageLeafHeaderBytes;
13015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pPageEnd = PageData(pCursor->pPage, pCursor->nPageSize);
13025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if( pCellOffsets + pCursor->iCell*2 + 2 > pPageEnd ){
13035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return ValidateError();
13045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1305ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  iCellOffset = decodeUnsigned16(pCellOffsets + pCursor->iCell*2);
1306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( iCellOffset>=pCursor->nPageSize ){
1307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ValidateError();
1308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1310ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  pCell = PageData(pCursor->pPage, iCellOffset);
1311ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  nCellMaxBytes = pCursor->nPageSize - iCellOffset;
1312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* B-tree leaf cells lead with varint record size, varint rowid and
1314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * varint header size.
1315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
1316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* TODO(shess): The smallest page size is 512 bytes, which has an m
1317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * of 39.  Three varints need at most 27 bytes to encode.  I think.
1318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
1319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( !checkVarints(pCell, nCellMaxBytes, 3) ){
1320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ValidateError();
1321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1323ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  nRead = getVarint(pCell, &nRecordBytes);
1324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  assert( iCellOffset+nRead<=pCursor->nPageSize );
1325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pCursor->nRecordBytes = nRecordBytes;
1326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  nRead += getVarint(pCell + nRead, &iRowid);
1328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  assert( iCellOffset+nRead<=pCursor->nPageSize );
1329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pCursor->iRowid = (i64)iRowid;
1330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pCursor->iRecordOffset = iCellOffset + nRead;
1332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Start overflow setup here because nLocalRecordBytes is needed to
1334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * check cell overlap.
1335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
1336ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  rc = overflowMaybeCreate(pCursor->pPage, pCursor->nPageSize,
1337ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                           pCursor->iRecordOffset, pCursor->nRecordBytes,
1338ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                           &pCursor->nLocalRecordBytes,
1339ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                           &pCursor->pOverflow);
1340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( rc!=SQLITE_OK ){
1341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ValidateError();
1342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Check that no other cell starts within this cell. */
1345ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  iEndOffset = pCursor->iRecordOffset + pCursor->nLocalRecordBytes;
13465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for( i=0; i<pCursor->nCells && pCellOffsets + i*2 + 2 <= pPageEnd; ++i ){
1347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const unsigned iOtherOffset = decodeUnsigned16(pCellOffsets + i*2);
1348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( iOtherOffset>iCellOffset && iOtherOffset<iEndOffset ){
1349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return ValidateError();
1350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  nRecordHeaderRead = getVarint(pCell + nRead, &nRecordHeaderBytes);
1354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  assert( nRecordHeaderBytes<=nRecordBytes );
1355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pCursor->nRecordHeaderBytes = nRecordHeaderBytes;
1356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Large headers could overflow if pages are small. */
1358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rc = overflowGetSegment(pCursor->pPage,
1359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          pCursor->iRecordOffset, pCursor->nLocalRecordBytes,
1360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          pCursor->pOverflow, 0, nRecordHeaderBytes,
1361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          &pCursor->pRecordHeader, &pCursor->bFreeRecordHeader);
1362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( rc!=SQLITE_OK ){
1363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ValidateError();
1364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Tally up the column count and size of data. */
1367ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  nRecordCols = 0;
1368ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  nRecordColBytes = 0;
1369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while( nRecordHeaderRead<nRecordHeaderBytes ){
1370ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    u64 iSerialType;  /* Type descriptor for current column. */
1371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( !checkVarint(pCursor->pRecordHeader + nRecordHeaderRead,
1372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     nRecordHeaderBytes - nRecordHeaderRead) ){
1373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return ValidateError();
1374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    nRecordHeaderRead += getVarint(pCursor->pRecordHeader + nRecordHeaderRead,
1376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                   &iSerialType);
1377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( iSerialType==10 || iSerialType==11 ){
1378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return ValidateError();
1379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    nRecordColBytes += SerialTypeLength(iSerialType);
1381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    nRecordCols++;
1382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pCursor->nRecordCols = nRecordCols;
1384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Parsing the header used as many bytes as expected. */
1386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( nRecordHeaderRead!=nRecordHeaderBytes ){
1387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ValidateError();
1388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Calculated record is size of expected record. */
1391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( nRecordHeaderBytes+nRecordColBytes!=nRecordBytes ){
1392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ValidateError();
1393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SQLITE_OK;
1396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static i64 leafCursorCellRowid(RecoverLeafCursor *pCursor){
1399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return pCursor->iRowid;
1400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static unsigned leafCursorCellColumns(RecoverLeafCursor *pCursor){
1403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return pCursor->nRecordCols;
1404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Get the column info for the cell.  Pass NULL for ppBase to prevent
1407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * retrieving the data segment.  If *pbFree is true, *ppBase must be
1408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * freed by the caller using sqlite3_free().
1409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
1410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int leafCursorCellColInfo(RecoverLeafCursor *pCursor,
1411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 unsigned iCol, u64 *piColType,
1412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 unsigned char **ppBase, int *pbFree){
1413ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const unsigned char *pRecordHeader;  /* Current cell's header. */
1414ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  u64 nRecordHeaderBytes;              /* Bytes in pRecordHeader. */
1415ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned nRead;                      /* Bytes read from header. */
1416ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  u64 iColEndOffset;                   /* Offset to end of column in cell. */
1417ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned nColsSkipped;               /* Count columns as procesed. */
1418ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  u64 iSerialType;                     /* Type descriptor for current column. */
1419ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Implicit NULL for columns past the end.  This case happens when
1421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * rows have not been updated since an ALTER TABLE added columns.
1422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * It is more convenient to address here than in callers.
1423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
1424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( iCol>=pCursor->nRecordCols ){
1425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *piColType = 0;
1426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( ppBase ){
1427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      *ppBase = 0;
1428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      *pbFree = 0;
1429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_OK;
1431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Must be able to decode header size. */
1434ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  pRecordHeader = pCursor->pRecordHeader;
1435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( !checkVarint(pRecordHeader, pCursor->nRecordHeaderBytes) ){
1436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_CORRUPT;
1437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Rather than caching the header size and how many bytes it took,
1440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * decode it every time.
1441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
1442ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  nRead = getVarint(pRecordHeader, &nRecordHeaderBytes);
1443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  assert( nRecordHeaderBytes==pCursor->nRecordHeaderBytes );
1444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Scan forward to the indicated column.  Scans to _after_ column
1446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * for later range checking.
1447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
1448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* TODO(shess): This could get expensive for very wide tables.  An
1449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * array of iSerialType could be built in leafCursorCellDecode(), but
1450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * the number of columns is dynamic per row, so it would add memory
1451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * management complexity.  Enough info to efficiently forward
1452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * iterate could be kept, if all clients forward iterate
1453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * (recoverColumn() may not).
1454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
1455ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  iColEndOffset = 0;
1456ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  nColsSkipped = 0;
1457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while( nColsSkipped<=iCol && nRead<nRecordHeaderBytes ){
1458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( !checkVarint(pRecordHeader + nRead, nRecordHeaderBytes - nRead) ){
1459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return SQLITE_CORRUPT;
1460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    nRead += getVarint(pRecordHeader + nRead, &iSerialType);
1462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    iColEndOffset += SerialTypeLength(iSerialType);
1463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    nColsSkipped++;
1464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Column's data extends past record's end. */
1467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( nRecordHeaderBytes+iColEndOffset>pCursor->nRecordBytes ){
1468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_CORRUPT;
1469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *piColType = iSerialType;
1472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( ppBase ){
1473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const u32 nColBytes = SerialTypeLength(iSerialType);
1474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* Offset from start of record to beginning of column. */
1476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const unsigned iColOffset = nRecordHeaderBytes+iColEndOffset-nColBytes;
1477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return overflowGetSegment(pCursor->pPage, pCursor->iRecordOffset,
1479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              pCursor->nLocalRecordBytes, pCursor->pOverflow,
1480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              iColOffset, nColBytes, ppBase, pbFree);
1481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SQLITE_OK;
1483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int leafCursorNextValidCell(RecoverLeafCursor *pCursor){
1486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while( 1 ){
1487ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    int rc;
1488ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* Move to the next cell. */
1490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pCursor->iCell++;
1491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* No more cells, get the next leaf. */
1493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( pCursor->iCell>=pCursor->nCells ){
1494ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      rc = leafCursorNextPage(pCursor);
1495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if( rc!=SQLITE_ROW ){
1496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return rc;
1497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
1498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      assert( pCursor->iCell==0 );
1499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* If the cell is valid, indicate that a row is available. */
1502ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    rc = leafCursorCellDecode(pCursor);
1503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( rc==SQLITE_OK ){
1504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return SQLITE_ROW;
1505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* Iterate until done or a valid row is found. */
1508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* TODO(shess): Remove debugging output. */
1509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    fprintf(stderr, "Skipping invalid cell\n");
1510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SQLITE_ERROR;
1512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)typedef struct Recover Recover;
1515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)struct Recover {
1516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sqlite3_vtab base;
1517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sqlite3 *db;                /* Host database connection */
1518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  char *zDb;                  /* Database containing target table */
1519c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  char *zTable;               /* Target table */
1520c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  unsigned nCols;             /* Number of columns in target table */
1521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  unsigned char *pTypes;      /* Types of columns in target table */
1522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
1523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Internal helper for deleting the module. */
1525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static void recoverRelease(Recover *pRecover){
1526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sqlite3_free(pRecover->zDb);
1527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sqlite3_free(pRecover->zTable);
1528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sqlite3_free(pRecover->pTypes);
1529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  memset(pRecover, 0xA5, sizeof(*pRecover));
1530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sqlite3_free(pRecover);
1531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Helper function for initializing the module.  Forward-declared so
1534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * recoverCreate() and recoverConnect() can see it.
1535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
1536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int recoverInit(
1537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sqlite3 *, void *, int, const char *const*, sqlite3_vtab **, char **
1538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles));
1539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int recoverCreate(
1541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sqlite3 *db,
1542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void *pAux,
1543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int argc, const char *const*argv,
1544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sqlite3_vtab **ppVtab,
1545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  char **pzErr
1546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)){
1547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FNENTRY();
1548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return recoverInit(db, pAux, argc, argv, ppVtab, pzErr);
1549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* This should never be called. */
1552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int recoverConnect(
1553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sqlite3 *db,
1554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void *pAux,
1555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int argc, const char *const*argv,
1556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sqlite3_vtab **ppVtab,
1557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  char **pzErr
1558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)){
1559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FNENTRY();
1560c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return recoverInit(db, pAux, argc, argv, ppVtab, pzErr);
1561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* No indices supported. */
1564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int recoverBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
1565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FNENTRY();
1566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SQLITE_OK;
1567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1568c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1569c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Logically, this should never be called. */
1570c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int recoverDisconnect(sqlite3_vtab *pVtab){
1571c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FNENTRY();
1572c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  recoverRelease((Recover*)pVtab);
1573c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SQLITE_OK;
1574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1575c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1576c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int recoverDestroy(sqlite3_vtab *pVtab){
1577c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FNENTRY();
1578c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  recoverRelease((Recover*)pVtab);
1579c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SQLITE_OK;
1580c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1581c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1582c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)typedef struct RecoverCursor RecoverCursor;
1583c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)struct RecoverCursor {
1584c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sqlite3_vtab_cursor base;
1585c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RecoverLeafCursor *pLeafCursor;
1586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int iEncoding;
1587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int bEOF;
1588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
1589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1590c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int recoverOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
1591c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Recover *pRecover = (Recover*)pVTab;
1592ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  u32 iRootPage;                   /* Root page of the backing table. */
1593ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  int iEncoding;                   /* UTF encoding for backing database. */
1594ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned nPageSize;              /* Size of pages in backing database. */
1595ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  Pager *pPager;                   /* Backing database pager. */
1596ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  RecoverLeafCursor *pLeafCursor;  /* Cursor to read table's leaf pages. */
1597ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  RecoverCursor *pCursor;          /* Cursor to read rows from leaves. */
1598ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  int rc;
1599ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1600ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  FNENTRY();
1601c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1602ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  iRootPage = 0;
1603ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  rc = getRootPage(pRecover->db, pRecover->zDb, pRecover->zTable,
1604ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                   &iRootPage);
1605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( rc!=SQLITE_OK ){
1606c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return rc;
1607c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1608c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1609ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  iEncoding = 0;
1610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rc = getEncoding(pRecover->db, pRecover->zDb, &iEncoding);
1611c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( rc!=SQLITE_OK ){
1612c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return rc;
1613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rc = GetPager(pRecover->db, pRecover->zDb, &pPager, &nPageSize);
1616c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( rc!=SQLITE_OK ){
1617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return rc;
1618c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1620c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rc = leafCursorCreate(pPager, nPageSize, iRootPage, &pLeafCursor);
1621c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( rc!=SQLITE_OK ){
1622c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return rc;
1623c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1625ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  pCursor = sqlite3_malloc(sizeof(RecoverCursor));
1626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( !pCursor ){
1627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    leafCursorDestroy(pLeafCursor);
1628c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_NOMEM;
1629c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1630c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  memset(pCursor, 0, sizeof(*pCursor));
1631c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pCursor->base.pVtab = pVTab;
1632c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pCursor->pLeafCursor = pLeafCursor;
1633c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pCursor->iEncoding = iEncoding;
1634c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
16355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  /* If no leaf pages were found, empty result set. */
16365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  /* TODO(shess): leafCursorNextValidCell() would return SQLITE_ROW or
16375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   * SQLITE_DONE to indicate whether there is further data to consider.
16385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   */
16395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pCursor->bEOF = (pLeafCursor->pPage==NULL);
16405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1641c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *ppCursor = (sqlite3_vtab_cursor*)pCursor;
1642c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SQLITE_OK;
1643c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1645c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int recoverClose(sqlite3_vtab_cursor *cur){
1646c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RecoverCursor *pCursor = (RecoverCursor*)cur;
1647ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  FNENTRY();
1648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( pCursor->pLeafCursor ){
1649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    leafCursorDestroy(pCursor->pLeafCursor);
1650c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pCursor->pLeafCursor = NULL;
1651c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1652c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  memset(pCursor, 0xA5, sizeof(*pCursor));
1653c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sqlite3_free(cur);
1654c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SQLITE_OK;
1655c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1656c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1657c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Helpful place to set a breakpoint. */
1658c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int RecoverInvalidCell(){
1659c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SQLITE_ERROR;
1660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1662c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Returns SQLITE_OK if the cell has an appropriate number of columns
1663c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * with the appropriate types of data.
1664c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
1665c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int recoverValidateLeafCell(Recover *pRecover, RecoverCursor *pCursor){
1666ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned i;
1667ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1668c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* If the row's storage has too many columns, skip it. */
1669c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( leafCursorCellColumns(pCursor->pLeafCursor)>pRecover->nCols ){
1670c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return RecoverInvalidCell();
1671c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1672c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1673c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Skip rows with unexpected types. */
1674c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for( i=0; i<pRecover->nCols; ++i ){
1675ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    u64 iType;  /* Storage type of column i. */
1676ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    int rc;
1677ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1678c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* ROWID alias. */
1679c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( (pRecover->pTypes[i]&MASK_ROWID) ){
1680c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      continue;
1681c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1682c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1683ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    rc = leafCursorCellColInfo(pCursor->pLeafCursor, i, &iType, NULL, NULL);
1684c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    assert( rc==SQLITE_OK );
1685c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( rc!=SQLITE_OK || !SerialTypeIsCompatible(iType, pRecover->pTypes[i]) ){
1686c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return RecoverInvalidCell();
1687c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1688c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1689c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1690c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SQLITE_OK;
1691c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1692c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1693c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int recoverNext(sqlite3_vtab_cursor *pVtabCursor){
1694c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RecoverCursor *pCursor = (RecoverCursor*)pVtabCursor;
1695c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Recover *pRecover = (Recover*)pCursor->base.pVtab;
1696c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int rc;
1697c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1698ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  FNENTRY();
1699ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1700c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Scan forward to the next cell with valid storage, then check that
1701c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * the stored data matches the schema.
1702c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
1703c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while( (rc = leafCursorNextValidCell(pCursor->pLeafCursor))==SQLITE_ROW ){
1704c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( recoverValidateLeafCell(pRecover, pCursor)==SQLITE_OK ){
1705c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return SQLITE_OK;
1706c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1707c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1708c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1709c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( rc==SQLITE_DONE ){
1710c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pCursor->bEOF = 1;
1711c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_OK;
1712c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1713c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1714c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  assert( rc!=SQLITE_OK );
1715c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return rc;
1716c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1717c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1718c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int recoverFilter(
1719c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sqlite3_vtab_cursor *pVtabCursor,
1720c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int idxNum, const char *idxStr,
1721c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int argc, sqlite3_value **argv
1722c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)){
1723c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RecoverCursor *pCursor = (RecoverCursor*)pVtabCursor;
1724c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Recover *pRecover = (Recover*)pCursor->base.pVtab;
1725ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  int rc;
1726ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1727ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  FNENTRY();
1728c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
17295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  /* There were no valid leaf pages in the table. */
17305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if( pCursor->bEOF ){
17315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return SQLITE_OK;
17325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
17335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
17345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  /* Load the first cell, and iterate forward if it's not valid.  If no cells at
17355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   * all are valid, recoverNext() sets bEOF and returns appropriately.
17365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   */
1737ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  rc = leafCursorCellDecode(pCursor->pLeafCursor);
1738c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( rc!=SQLITE_OK || recoverValidateLeafCell(pRecover, pCursor)!=SQLITE_OK ){
1739c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return recoverNext(pVtabCursor);
1740c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1741c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1742c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SQLITE_OK;
1743c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1744c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1745c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int recoverEof(sqlite3_vtab_cursor *pVtabCursor){
1746c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RecoverCursor *pCursor = (RecoverCursor*)pVtabCursor;
1747ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  FNENTRY();
1748c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return pCursor->bEOF;
1749c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1750c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1751c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int recoverColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
1752c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RecoverCursor *pCursor = (RecoverCursor*)cur;
1753c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Recover *pRecover = (Recover*)pCursor->base.pVtab;
1754ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  u64 iColType;             /* Storage type of column i. */
1755ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned char *pColData;  /* Column i's data. */
1756ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  int shouldFree;           /* Non-zero if pColData should be freed. */
1757ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  int rc;
1758ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1759ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  FNENTRY();
1760c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1761c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( i>=pRecover->nCols ){
1762c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_ERROR;
1763c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1764c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1765c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* ROWID alias. */
1766c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( (pRecover->pTypes[i]&MASK_ROWID) ){
1767c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    sqlite3_result_int64(ctx, leafCursorCellRowid(pCursor->pLeafCursor));
1768c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_OK;
1769c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1770c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1771ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  pColData = NULL;
1772ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  shouldFree = 0;
1773ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  rc = leafCursorCellColInfo(pCursor->pLeafCursor, i, &iColType,
1774ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                             &pColData, &shouldFree);
1775c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( rc!=SQLITE_OK ){
1776c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return rc;
1777c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1778c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* recoverValidateLeafCell() should guarantee that this will never
1779c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * occur.
1780c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
1781c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( !SerialTypeIsCompatible(iColType, pRecover->pTypes[i]) ){
1782c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( shouldFree ){
1783c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      sqlite3_free(pColData);
1784c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1785c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_ERROR;
1786c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1787c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1788c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch( iColType ){
1789c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 0 : sqlite3_result_null(ctx); break;
1790c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 1 : sqlite3_result_int64(ctx, decodeSigned(pColData, 1)); break;
1791c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 2 : sqlite3_result_int64(ctx, decodeSigned(pColData, 2)); break;
1792c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 3 : sqlite3_result_int64(ctx, decodeSigned(pColData, 3)); break;
1793c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 4 : sqlite3_result_int64(ctx, decodeSigned(pColData, 4)); break;
1794c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 5 : sqlite3_result_int64(ctx, decodeSigned(pColData, 6)); break;
1795c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 6 : sqlite3_result_int64(ctx, decodeSigned(pColData, 8)); break;
1796c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 7 : sqlite3_result_double(ctx, decodeFloat64(pColData)); break;
1797c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 8 : sqlite3_result_int(ctx, 0); break;
1798c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 9 : sqlite3_result_int(ctx, 1); break;
1799c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 10 : assert( iColType!=10 ); break;
1800c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case 11 : assert( iColType!=11 ); break;
1801c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1802c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    default : {
1803ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      u32 l = SerialTypeLength(iColType);
1804ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1805c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      /* If pColData was already allocated, arrange to pass ownership. */
1806c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      sqlite3_destructor_type pFn = SQLITE_TRANSIENT;
1807c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if( shouldFree ){
1808c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        pFn = sqlite3_free;
1809c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        shouldFree = 0;
1810c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
1811c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1812c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if( SerialTypeIsBlob(iColType) ){
1813c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        sqlite3_result_blob(ctx, pColData, l, pFn);
1814c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }else{
1815c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if( pCursor->iEncoding==SQLITE_UTF16LE ){
1816c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          sqlite3_result_text16le(ctx, (const void*)pColData, l, pFn);
1817c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }else if( pCursor->iEncoding==SQLITE_UTF16BE ){
1818c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          sqlite3_result_text16be(ctx, (const void*)pColData, l, pFn);
1819c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }else{
1820c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          sqlite3_result_text(ctx, (const char*)pColData, l, pFn);
1821c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
1822c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
1823c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    } break;
1824c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1825c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( shouldFree ){
1826c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    sqlite3_free(pColData);
1827c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1828c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SQLITE_OK;
1829c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1830c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1831c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int recoverRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){
1832c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RecoverCursor *pCursor = (RecoverCursor*)pVtabCursor;
1833ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  FNENTRY();
1834c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *pRowid = leafCursorCellRowid(pCursor->pLeafCursor);
1835c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SQLITE_OK;
1836c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1837c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1838c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static sqlite3_module recoverModule = {
1839c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  0,                         /* iVersion */
1840c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  recoverCreate,             /* xCreate - create a table */
1841c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  recoverConnect,            /* xConnect - connect to an existing table */
1842c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  recoverBestIndex,          /* xBestIndex - Determine search strategy */
1843c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  recoverDisconnect,         /* xDisconnect - Disconnect from a table */
1844c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  recoverDestroy,            /* xDestroy - Drop a table */
1845c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  recoverOpen,               /* xOpen - open a cursor */
1846c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  recoverClose,              /* xClose - close a cursor */
1847c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  recoverFilter,             /* xFilter - configure scan constraints */
1848c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  recoverNext,               /* xNext - advance a cursor */
1849c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  recoverEof,                /* xEof */
1850c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  recoverColumn,             /* xColumn - read data */
1851c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  recoverRowid,              /* xRowid - read data */
1852c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  0,                         /* xUpdate - write data */
1853c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  0,                         /* xBegin - begin transaction */
1854c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  0,                         /* xSync - sync transaction */
1855c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  0,                         /* xCommit - commit transaction */
1856c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  0,                         /* xRollback - rollback transaction */
1857c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  0,                         /* xFindFunction - function overloading */
1858c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  0,                         /* xRename - rename the table */
1859c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
1860c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1861c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int recoverVtableInit(sqlite3 *db){
1862c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return sqlite3_create_module_v2(db, "recover", &recoverModule, NULL, 0);
1863c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1864c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1865c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* This section of code is for parsing the create input and
1866c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * initializing the module.
1867c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
1868c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1869c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Find the next word in zText and place the endpoints in pzWord*.
1870c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Returns true if the word is non-empty.  "Word" is defined as
1871c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * ASCII alphanumeric plus '_' at this time.
1872c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
1873c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int findWord(const char *zText,
1874c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    const char **pzWordStart, const char **pzWordEnd){
1875ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  int r;
1876c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while( ascii_isspace(*zText) ){
1877c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    zText++;
1878c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1879c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *pzWordStart = zText;
1880c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while( ascii_isalnum(*zText) || *zText=='_' ){
1881c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    zText++;
1882c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1883ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  r = zText>*pzWordStart;  /* In case pzWordStart==pzWordEnd */
1884c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *pzWordEnd = zText;
1885c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return r;
1886c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1887c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1888c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Return true if the next word in zText is zWord, also setting
1889c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * *pzContinue to the character after the word.
1890c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
1891c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int expectWord(const char *zText, const char *zWord,
1892c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      const char **pzContinue){
1893c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const char *zWordStart, *zWordEnd;
1894c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( findWord(zText, &zWordStart, &zWordEnd) &&
1895c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ascii_strncasecmp(zWord, zWordStart, zWordEnd - zWordStart)==0 ){
1896c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *pzContinue = zWordEnd;
1897c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return 1;
1898c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1899c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return 0;
1900c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1901c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1902c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Parse the name and type information out of parameter.  In case of
1903c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * success, *pzNameStart/End contain the name of the column,
1904c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * *pzTypeStart/End contain the top-level type, and *pTypeMask has the
1905c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * type mask to use for the column.
1906c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
1907c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int findNameAndType(const char *parameter,
1908c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           const char **pzNameStart, const char **pzNameEnd,
1909c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           const char **pzTypeStart, const char **pzTypeEnd,
1910c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           unsigned char *pTypeMask){
1911ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned nNameLen;   /* Length of found name. */
1912ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const char *zEnd;    /* Current end of parsed column information. */
1913ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  int bNotNull;        /* Non-zero if NULL is not allowed for name. */
1914ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  int bStrict;         /* Non-zero if column requires exact type match. */
1915ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const char *zDummy;  /* Dummy parameter, result unused. */
1916ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned i;
1917c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1918c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* strictMask is used for STRICT, strictMask|otherMask if STRICT is
1919c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * not supplied.  zReplace provides an alternate type to expose to
1920c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * the caller.
1921c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
1922c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  static struct {
1923c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const char *zName;
1924c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    unsigned char strictMask;
1925c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    unsigned char otherMask;
1926c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const char *zReplace;
1927c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } kTypeInfo[] = {
1928c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "ANY",
1929c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      MASK_INTEGER | MASK_FLOAT | MASK_BLOB | MASK_TEXT | MASK_NULL,
1930c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      0, "",
1931c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    },
1932c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "ROWID",   MASK_INTEGER | MASK_ROWID,             0, "INTEGER", },
1933c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "INTEGER", MASK_INTEGER | MASK_NULL,              0, NULL, },
1934c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "FLOAT",   MASK_FLOAT | MASK_NULL,                MASK_INTEGER, NULL, },
1935c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "NUMERIC", MASK_INTEGER | MASK_FLOAT | MASK_NULL, MASK_TEXT, NULL, },
1936c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "TEXT",    MASK_TEXT | MASK_NULL,                 MASK_BLOB, NULL, },
1937c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "BLOB",    MASK_BLOB | MASK_NULL,                 0, NULL, },
1938c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
1939c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1940ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if( !findWord(parameter, pzNameStart, pzNameEnd) ){
1941ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return SQLITE_MISUSE;
1942ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
1943ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1944ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  /* Manifest typing, accept any storage type. */
1945ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if( !findWord(*pzNameEnd, pzTypeStart, pzTypeEnd) ){
1946ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    *pzTypeEnd = *pzTypeStart = "";
1947ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    *pTypeMask = MASK_INTEGER | MASK_FLOAT | MASK_BLOB | MASK_TEXT | MASK_NULL;
1948ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return SQLITE_OK;
1949ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
1950ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1951ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  nNameLen = *pzTypeEnd - *pzTypeStart;
1952c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for( i=0; i<ArraySize(kTypeInfo); ++i ){
1953c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( ascii_strncasecmp(kTypeInfo[i].zName, *pzTypeStart, nNameLen)==0 ){
1954c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
1955c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1956c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1957c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( i==ArraySize(kTypeInfo) ){
1958c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_MISUSE;
1959c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1960c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1961ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  zEnd = *pzTypeEnd;
1962ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  bStrict = 0;
1963c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( expectWord(zEnd, "STRICT", &zEnd) ){
1964c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* TODO(shess): Ick.  But I don't want another single-purpose
1965c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * flag, either.
1966c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
1967c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( kTypeInfo[i].zReplace && !kTypeInfo[i].zReplace[0] ){
1968c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return SQLITE_MISUSE;
1969c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1970c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bStrict = 1;
1971c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1972c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1973ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  bNotNull = 0;
1974c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( expectWord(zEnd, "NOT", &zEnd) ){
1975c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( expectWord(zEnd, "NULL", &zEnd) ){
1976c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      bNotNull = 1;
1977c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }else{
1978c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      /* Anything other than NULL after NOT is an error. */
1979c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return SQLITE_MISUSE;
1980c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1981c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1982c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1983c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Anything else is an error. */
1984c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( findWord(zEnd, &zDummy, &zDummy) ){
1985c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_MISUSE;
1986c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1987c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1988c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *pTypeMask = kTypeInfo[i].strictMask;
1989c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( !bStrict ){
1990c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *pTypeMask |= kTypeInfo[i].otherMask;
1991c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1992c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( bNotNull ){
1993c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *pTypeMask &= ~MASK_NULL;
1994c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1995c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( kTypeInfo[i].zReplace ){
1996c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *pzTypeStart = kTypeInfo[i].zReplace;
1997c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *pzTypeEnd = *pzTypeStart + strlen(*pzTypeStart);
1998c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1999c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SQLITE_OK;
2000c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
2001c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2002c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Parse the arguments, placing type masks in *pTypes and the exposed
2003c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * schema in *pzCreateSql (for sqlite3_declare_vtab).
2004c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
2005c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int ParseColumnsAndGenerateCreate(unsigned nCols,
2006c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                         const char *const *pCols,
2007c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                         char **pzCreateSql,
2008c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                         unsigned char *pTypes,
2009c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                         char **pzErr){
2010ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  unsigned i;
2011c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  char *zCreateSql = sqlite3_mprintf("CREATE TABLE x(");
2012c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( !zCreateSql ){
2013c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_NOMEM;
2014c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2015c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2016c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for( i=0; i<nCols; i++ ){
2017ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const char *zSep = (i < nCols - 1 ? ", " : ")");
2018ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const char *zNotNull = "";
2019c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const char *zNameStart, *zNameEnd;
2020c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const char *zTypeStart, *zTypeEnd;
2021c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int rc = findNameAndType(pCols[i],
2022c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             &zNameStart, &zNameEnd,
2023c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             &zTypeStart, &zTypeEnd,
2024c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             &pTypes[i]);
2025c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( rc!=SQLITE_OK ){
2026c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      *pzErr = sqlite3_mprintf("unable to parse column %d", i);
2027c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      sqlite3_free(zCreateSql);
2028c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return rc;
2029c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
2030c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2031c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( !(pTypes[i]&MASK_NULL) ){
2032c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      zNotNull = " NOT NULL";
2033c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
2034c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2035c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* Add name and type to the create statement. */
2036c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    zCreateSql = sqlite3_mprintf("%z%.*s %.*s%s%s",
2037c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 zCreateSql,
2038c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 zNameEnd - zNameStart, zNameStart,
2039c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 zTypeEnd - zTypeStart, zTypeStart,
2040c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 zNotNull, zSep);
2041c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if( !zCreateSql ){
2042c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return SQLITE_NOMEM;
2043c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
2044c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2045c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2046c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *pzCreateSql = zCreateSql;
2047c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SQLITE_OK;
2048c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
2049c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2050c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* Helper function for initializing the module. */
2051ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch/* argv[0] module name
2052ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * argv[1] db name for virtual table
2053ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * argv[2] virtual table name
2054ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * argv[3] backing table name
2055ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * argv[4] columns
2056ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch */
2057c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* TODO(shess): Since connect isn't supported, could inline into
2058c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * recoverCreate().
2059c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
2060c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* TODO(shess): Explore cases where it would make sense to set *pzErr. */
2061c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int recoverInit(
2062c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sqlite3 *db,                        /* Database connection */
2063c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void *pAux,                         /* unused */
2064c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int argc, const char *const*argv,   /* Parameters to CREATE TABLE statement */
2065c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sqlite3_vtab **ppVtab,              /* OUT: New virtual table */
2066c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  char **pzErr                        /* OUT: Error message, if any */
2067c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)){
2068ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const unsigned kTypeCol = 4;  /* First argument with column type info. */
2069ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  Recover *pRecover;            /* Virtual table structure being created. */
2070ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  char *zDot;                   /* Any dot found in "db.table" backing. */
2071ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  u32 iRootPage;                /* Root page of backing table. */
2072ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  char *zCreateSql;             /* Schema of created virtual table. */
2073ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  int rc;
2074c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2075c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Require to be in the temp database. */
2076c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( ascii_strcasecmp(argv[1], "temp")!=0 ){
2077c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *pzErr = sqlite3_mprintf("recover table must be in temp database");
2078c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_MISUSE;
2079c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2080c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2081c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Need the backing table and at least one column. */
2082c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( argc<=kTypeCol ){
2083c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *pzErr = sqlite3_mprintf("no columns specified");
2084c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_MISUSE;
2085c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2086c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2087ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  pRecover = sqlite3_malloc(sizeof(Recover));
2088c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( !pRecover ){
2089c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_NOMEM;
2090c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2091c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  memset(pRecover, 0, sizeof(*pRecover));
2092c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pRecover->base.pModule = &recoverModule;
2093c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pRecover->db = db;
2094c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2095c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Parse out db.table, assuming main if no dot. */
2096ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  zDot = strchr(argv[3], '.');
2097c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( !zDot ){
2098c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pRecover->zDb = sqlite3_strdup(db->aDb[0].zName);
2099c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pRecover->zTable = sqlite3_strdup(argv[3]);
2100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }else if( zDot>argv[3] && zDot[1]!='\0' ){
2101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pRecover->zDb = sqlite3_strndup(argv[3], zDot - argv[3]);
2102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pRecover->zTable = sqlite3_strdup(zDot + 1);
2103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }else{
2104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* ".table" or "db." not allowed. */
2105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *pzErr = sqlite3_mprintf("ill-formed table specifier");
2106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    recoverRelease(pRecover);
2107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_ERROR;
2108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pRecover->nCols = argc - kTypeCol;
2111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pRecover->pTypes = sqlite3_malloc(pRecover->nCols);
2112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( !pRecover->zDb || !pRecover->zTable || !pRecover->pTypes ){
2113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    recoverRelease(pRecover);
2114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SQLITE_NOMEM;
2115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Require the backing table to exist. */
2118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* TODO(shess): Be more pedantic about the form of the descriptor
2119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * string.  This already fails for poorly-formed strings, simply
2120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * because there won't be a root page, but it would make more sense
2121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * to be explicit.
2122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
2123ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  rc = getRootPage(pRecover->db, pRecover->zDb, pRecover->zTable, &iRootPage);
2124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( rc!=SQLITE_OK ){
2125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *pzErr = sqlite3_mprintf("unable to find backing table");
2126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    recoverRelease(pRecover);
2127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return rc;
2128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* Parse the column definitions. */
2131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rc = ParseColumnsAndGenerateCreate(pRecover->nCols, argv + kTypeCol,
2132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     &zCreateSql, pRecover->pTypes, pzErr);
2133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( rc!=SQLITE_OK ){
2134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    recoverRelease(pRecover);
2135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return rc;
2136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rc = sqlite3_declare_vtab(db, zCreateSql);
2139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sqlite3_free(zCreateSql);
2140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if( rc!=SQLITE_OK ){
2141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    recoverRelease(pRecover);
2142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return rc;
2143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *ppVtab = (sqlite3_vtab *)pRecover;
2146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SQLITE_OK;
2147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
2148