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