]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Further fixes to comments in sqlite3recover.h. Also rework some data structures in...
authordan <Dan Kennedy>
Fri, 9 Sep 2022 20:44:56 +0000 (20:44 +0000)
committerdan <Dan Kennedy>
Fri, 9 Sep 2022 20:44:56 +0000 (20:44 +0000)
FossilOrigin-Name: 599d1f8ec2f9e24924a6f9e66c85664360c7b95531b07a4efe1dd8c096b3fc99

ext/recover/sqlite3recover.c
ext/recover/sqlite3recover.h
ext/recover/test_recover.c
manifest
manifest.uuid
test/savepoint.test

index 7d05ec2b3e38e900fc736916db6a882244164ce3..e6975b8771f4962ac6d2ba12ae5d8f71b1d20faf 100644 (file)
 typedef unsigned int u32;
 typedef sqlite3_int64 i64;
 
+typedef struct RecoverTable RecoverTable;
 typedef struct RecoverColumn RecoverColumn;
-struct RecoverColumn {
-  int iField;                     /* Field in record on disk */
-  int iBind;                      /* Binding to use in INSERT */
-  int bIPK;                       /* True for IPK column */
-  char *zCol;
-  int eHidden;
-};
-
-#define RECOVER_EHIDDEN_NONE    0
-#define RECOVER_EHIDDEN_HIDDEN  1
-#define RECOVER_EHIDDEN_VIRTUAL 2
-#define RECOVER_EHIDDEN_STORED  3
 
 /*
-** When running the ".recover" command, each output table, and the special
-** orphaned row table if it is required, is represented by an instance
-** of the following struct.
+** When recovering rows of data that can be associated with table
+** definitions recovered from the sqlite_schema table, each table is
+** represented by an instance of the following object.
+**
+** iRoot:
+**   The root page in the original database. Not necessarily (and usually
+**   not) the same in the recovered database.
+**
+** zTab:
+**   Name of the table.
 **
-** aCol[]:
-**  Array of nCol columns. In the order in which they appear in the table.
+** nCol/aCol[]:
+**   aCol[] is an array of nCol columns. In the order in which they appear 
+**   in the table.
+**
+** bIntkey:
+**   Set to true for intkey tables, false for WITHOUT ROWID.
+**
+** iRowidBind:
+**   Each column in the aCol[] array has associated with it the index of
+**   the bind parameter its values will be bound to in the INSERT statement
+**   used to construct the output database. If the table does has a rowid
+**   but not an INTEGER PRIMARY KEY column, then iRowidBind contains the
+**   index of the bind paramater to which the rowid value should be bound.
+**   Otherwise, it contains -1. If the table does contain an INTEGER PRIMARY 
+**   KEY column, then the rowid value should be bound to the index associated
+**   with the column.
+**
+** pNext:
+**   All RecoverTable objects used by the recovery operation are allocated
+**   and populated as part of creating the recovered database schema in
+**   the output database, before any non-schema data are recovered. They
+**   are then stored in a singly-linked list linked by this variable beginning
+**   at sqlite3_recover.pTblList.
 */
-typedef struct RecoverTable RecoverTable;
 struct RecoverTable {
   u32 iRoot;                      /* Root page in original database */
   char *zTab;                     /* Name of table */
@@ -50,38 +66,94 @@ struct RecoverTable {
   RecoverColumn *aCol;            /* Array of columns */
   int bIntkey;                    /* True for intkey, false for without rowid */
   int iRowidBind;                 /* If >0, bind rowid to INSERT here */
-
   RecoverTable *pNext;
 };
 
+/*
+** Each database column is represented by an instance of the following object
+** stored in the RecoverTable.aCol[] array of the associated table.
+**
+** iField:
+**   The index of the associated field within database records. Or -1 if
+**   there is no associated field (e.g. for virtual generated columns).
+**
+** iBind:
+**   The bind index of the INSERT statement to bind this columns values
+**   to. Or 0 if there is no such index (iff (iField<0)).
+**
+** bIPK:
+**   True if this is the INTEGER PRIMARY KEY column.
+**
+** zCol:
+**   Name of column.
+**
+** eHidden:
+**   A RECOVER_EHIDDEN_* constant value (see below for interpretation of each).
+*/
+struct RecoverColumn {
+  int iField;                     /* Field in record on disk */
+  int iBind;                      /* Binding to use in INSERT */
+  int bIPK;                       /* True for IPK column */
+  char *zCol;
+  int eHidden;
+};
+
+#define RECOVER_EHIDDEN_NONE    0      /* Normal database column */
+#define RECOVER_EHIDDEN_HIDDEN  1      /* Column is __HIDDEN__ */
+#define RECOVER_EHIDDEN_VIRTUAL 2      /* Virtual generated column */
+#define RECOVER_EHIDDEN_STORED  3      /* Stored generated column */
+
+/*
+** Bitmap object used to track pages in the input database. Allocated
+** and manipulated only by the following functions:
+**
+**     recoverBitmapAlloc()
+**     recoverBitmapFree()
+**     recoverBitmapSet()
+**     recoverBitmapQuery()
+**
+** nPg:
+**   Largest page number that may be stored in the bitmap. The range
+**   of valid keys is 1 to nPg, inclusive.
+**
+** aElem[]:
+**   Array large enough to contain a bit for each key. For key value
+**   iKey, the associated bit is the bit (iKey%32) of aElem[iKey/32].
+**   In other words, the following is true if bit iKey is set, or 
+**   false if it is clear:
+**
+**       (aElem[iKey/32] & (1 << (iKey%32))) ? 1 : 0
+*/
 typedef struct RecoverBitmap RecoverBitmap;
 struct RecoverBitmap {
   i64 nPg;                        /* Size of bitmap */
   u32 aElem[0];                   /* Array of 32-bit bitmasks */
 };
 
-
+/*
+**
+*/
 struct sqlite3_recover {
-  sqlite3 *dbIn;
-  sqlite3 *dbOut;
+  sqlite3 *dbIn;                  /* Input database */
+  sqlite3 *dbOut;                 /* Output database */
 
-  sqlite3_stmt *pGetPage;
+  sqlite3_stmt *pGetPage;         /* SELECT against input db sqlite_dbdata */
 
-  char *zDb;
-  char *zUri;
-  RecoverTable *pTblList;
+  char *zDb;                      /* Name of input db ("main" etc.) */
+  char *zUri;                     /* URI for output database */
+  RecoverTable *pTblList;         /* List of tables recovered from schem */
   RecoverBitmap *pUsed;           /* Used by recoverLostAndFound() */
 
   int errCode;                    /* For sqlite3_recover_errcode() */
   char *zErrMsg;                  /* For sqlite3_recover_errmsg() */
 
-  char *zStateDb;
+  char *zStateDb;                 /* State database to use (or NULL) */
   char *zLostAndFound;            /* Name of lost-and-found table (or NULL) */
-  int bFreelistCorrupt;
-  int bRecoverRowid;
+  int bFreelistCorrupt;           /* SQLITE_RECOVER_FREELIST_CORRUPT setting */
+  int bRecoverRowid;              /* SQLITE_RECOVER_ROWIDS setting */
 
-  void *pSqlCtx;
-  int (*xSql)(void*,const char*);
+  void *pSqlCtx;                  /* SQL callback context */
+  int (*xSql)(void*,const char*); /* Pointer to SQL callback function */
 };
 
 /* 
@@ -1340,7 +1412,7 @@ int sqlite3_recover_config(sqlite3_recover *p, int op, void *pArg){
   int rc = SQLITE_OK;
 
   switch( op ){
-    case SQLITE_RECOVER_TESTDB:
+    case 789:
       sqlite3_free(p->zStateDb);
       p->zStateDb = recoverMPrintf(p, "%s", (char*)pArg);
       break;
index ffe016b4f3fdb11616b2912d63d7264965ac2999..30771d8804555e9559f880167da3055ce175f404 100644 (file)
@@ -37,7 +37,6 @@
 **    using sqlite3_recover_finish().
 */
 
-
 #ifndef _SQLITE_RECOVER_H
 #define _SQLITE_RECOVER_H
 
@@ -95,13 +94,18 @@ sqlite3_recover *sqlite3_recover_init_sql(
 );
 
 /*
-**
+** Configure an sqlite3_recover object that has just been created using
+** sqlite3_recover_init() or sqlite3_recover_init_sql(). The second
+** argument passed to this function must be one of the SQLITE_RECOVER_*
+** symbols defined below. Valid values for the third argument depend
+** on the specific SQLITE_RECOVER_* symbol in use.
+**
+** SQLITE_OK is returned if the configuration operation was successful,
+** or an SQLite error code otherwise.
 */
 int sqlite3_recover_config(sqlite3_recover*, int op, void *pArg);
 
 /*
-** SQLITE_RECOVER_TESTDB:
-**
 ** SQLITE_RECOVER_LOST_AND_FOUND:
 **   The pArg argument points to a string buffer containing the name
 **   of a "lost-and-found" table in the output database, or NULL. If
@@ -118,41 +122,79 @@ int sqlite3_recover_config(sqlite3_recover*, int op, void *pArg);
 **   corrupt and an attempt is made to recover records from pages that
 **   appear to be linked into the freelist. Otherwise, pages on the freelist
 **   are ignored. Setting this option can recover more data from the
-**   database, but often ends up "recovering" deleted records.
+**   database, but often ends up "recovering" deleted records. The default 
+**   value is 0 (clear).
 **
 ** SQLITE_RECOVER_ROWIDS:
-**
-** SQLITE_RECOVER_SQLHOOK:
+**   The pArg value must actually be a pointer to a value of type
+**   int containing value 0 or 1 cast as a (void*). If this option is set
+**   (argument is 1), then an attempt is made to recover rowid values
+**   that are not also INTEGER PRIMARY KEY values. If this option is
+**   clear, then new rowids are assigned to all recovered rows. The
+**   default value is 1 (set).
 */
-#define SQLITE_RECOVER_TESTDB           789
-#define SQLITE_RECOVER_LOST_AND_FOUND   790
-#define SQLITE_RECOVER_FREELIST_CORRUPT 791
-#define SQLITE_RECOVER_ROWIDS           792
+#define SQLITE_RECOVER_LOST_AND_FOUND   1
+#define SQLITE_RECOVER_FREELIST_CORRUPT 2
+#define SQLITE_RECOVER_ROWIDS           3
 
 /* 
-** Run the recovery. Return an SQLite error code if an error occurs, or
-** SQLITE_OK otherwise. 
+** Run the recovery operation. This function does not return until the 
+** recovery operation is completed - either the new database has been
+** created and populated (sqlite3_recover_init()) or all SQL statements have
+** been passed to the callback (sqlite3_recover_init_sql()) - or an error
+** occurs. If the recovery is completed without error, SQLITE_OK
+** is returned. It is not considered an error if data cannot be recovered
+** due to database corruption.
+**
+** If an error (for example an out-of-memory or IO error) occurs, then
+** an SQLite error code is returned. The final state of the output database
+** or the results of running any SQL statements already passed to the
+** callback in this case are undefined. An English language error 
+** message corresponding to the error may be available via the 
+** sqlite3_recover_errmsg() API.
+**
+** This function may only be called once on an sqlite3_recover handle.
+** If it is called more than once, the second and subsequent calls
+** return SQLITE_MISUSE. The error code and error message returned
+** by sqlite3_recover_errcode() and sqlite3_recover_errmsg() are not
+** updated in this case.
 */
 int sqlite3_recover_run(sqlite3_recover*);
 
 /*
-** Return a pointer to a buffer containing the English language error
-** message stored in the sqlite3_recover handle. If no error message
-** is available (including in the case where no error has occurred),
-** NULL is returned.
+** If this is called on an sqlite3_recover handle before 
+** sqlite3_recover_run() has been called, or if the call to
+** sqlite3_recover_run() returned SQLITE_OK, then this API always returns
+** a NULL pointer.
+**
+** Otherwise, an attempt is made to return a pointer to a buffer containing 
+** an English language error message related to the error that occurred
+** within the sqlite3_recover_run() call. If no error message is available,
+** or if an out-of-memory error occurs while attempting to allocate a buffer
+** for one, NULL may still be returned.
+**
+** The buffer remains valid until the sqlite3_recover handle is destroyed
+** using sqlite3_recover_finish().
 */
 const char *sqlite3_recover_errmsg(sqlite3_recover*);
 
 /*
-** Return the recover handle error code. SQLITE_OK is returned if no error
-** has occurred.
+** If this function is called on an sqlite3_recover handle before
+** sqlite3_recover_run() has been called, it always returns SQLITE_OK.
+** Otherwise, it returns a copy of the value returned by the first
+** sqlite3_recover_run() call made on the handle.
 */
 int sqlite3_recover_errcode(sqlite3_recover*);
 
 /* 
 ** Clean up a recovery object created by a call to sqlite3_recover_init().
-** This function returns SQLITE_OK if no error occurred, or else a copy
-** of the recover handle error code.
+** The results of using a recovery object with any API after it has been
+** passed to this function are undefined.
+**
+** If this function is called on an sqlite3_recover handle before
+** sqlite3_recover_run() has been called, it always returns SQLITE_OK.
+** Otherwise, it returns a copy of the value returned by the first
+** sqlite3_recover_run() call made on the handle.
 */
 int sqlite3_recover_finish(sqlite3_recover*);
 
index e7fef42fd766ac75fb435722b4aecb01fb7c4b44..a31ddbb94ab9556cb5d277b9d937497a5d4cea45 100644 (file)
@@ -117,7 +117,7 @@ static int testRecoverCmd(
       switch( iOp ){
         case 0:
           res = sqlite3_recover_config(pTest->p, 
-              SQLITE_RECOVER_TESTDB, (void*)Tcl_GetString(objv[3])
+              789, (void*)Tcl_GetString(objv[3]) /* MAGIC NUMBER! */
           );
           break;
         case 1:
index 3da6b77b47efea165d5598474e3dadcb7cbe3d7f..3f230d94672f9b7f78ce4bdf554de3914b1a4353 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Handle\srecovery\sof\svirtual\stables\sby\srecovering\seach\sshadow\stable\sindividually,\sthen\swriting\sthe\sCREATE\sVIRTUAL\sTABLE\sstatement\sdirectly\sinto\sthe\ssqlite_schema\stable.
-D 2022-09-09T16:25:19.064
+C Further\sfixes\sto\scomments\sin\ssqlite3recover.h.\sAlso\srework\ssome\sdata\sstructures\sin\ssqlite3recover.c.
+D 2022-09-09T20:44:56.135
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -392,9 +392,9 @@ F ext/recover/recover_common.tcl 6679af7dffc858e345053a91c9b0a897595b4a13007acef
 F ext/recover/recoverclobber.test e6537ebf99f57bfff6cca59550b5f4278319b57a89865abb98d755a8fd561d84
 F ext/recover/recoverold.test f368a6ae2db12b6017257b332a19ab5df527f4061e43f12f5c85d8e2b236f074
 F ext/recover/recoverrowid.test ec4436cd69e6cdacb48dd2963ff6dd9dbd5fe648376de5e7c0c2f4f6cbacb417
-F ext/recover/sqlite3recover.c 7ed9a573d081435a16982b972c6bb963d273a0a457ec69fa16b0918165991e9d
-F ext/recover/sqlite3recover.h 73648878cea3492427b9a8facebdad0464ed15b161ed1cd70f349a02456e8879
-F ext/recover/test_recover.c b973526785e145e7d9d7920ccde72112025ee5204e22b332db9d86796be73f00
+F ext/recover/sqlite3recover.c e8d0eae7da7ba24e733f6247082c12d7a030ce794eb5c42d64993f55c12882f5
+F ext/recover/sqlite3recover.h 81108efb8c4618d3d9c6da4df785212b0e4501aa0d25edfc463405fe839a6640
+F ext/recover/test_recover.c ed8d0cc8703ab29cf562f793623b045de109b7937f254108ff4132f35abb37fb
 F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
 F ext/repair/checkfreelist.c e21f06995ff4efdc1622dcceaea4dcba2caa83ca2f31a1607b98a8509168a996
 F ext/repair/checkindex.c 4383e4469c21e5b9ae321d0d63cec53e981af9d7a6564be6374f0eeb93dfc890
@@ -1398,7 +1398,7 @@ F test/rowvaluefault.test 963ae9cdaed30a85a29668dd514e639f3556cae903ee9f172ea972
 F test/rowvaluevtab.test cd9747bb3f308086944c07968f547ad6b05022e698d80b9ffbdfe09ce0b8da6f
 F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798
 F test/run-wordcount.sh 891e89c4c2d16e629cd45951d4ed899ad12afc09
-F test/savepoint.test 1f8a6b1aea9a0d05837adc463d4bf47bd9d0f1c842f1c2a9caccd639baf34bf9
+F test/savepoint.test 6e9804a17767f08432c7a5e738b9a8f4b891d243110b63d3a41d270d3d1378ec
 F test/savepoint2.test 9b8543940572a2f01a18298c3135ad0c9f4f67d7
 F test/savepoint4.test c8f8159ade6d2acd9128be61e1230f1c1edc6cc0
 F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd
@@ -2007,8 +2007,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 14164047c43e3ca43aa010c77ea00dfa85400e15645ee0f5b90a677898b6a836
-R e52e610730a5083b962d51491c2e90a5
+P 5f2d5ccd56c06c3468377126acfd4be39b79b05bb6fb09b674b2e185df143aa3
+R d4558eaeefd2a718275b323dc4307f9b
 U dan
-Z 0661ae93944ad96dd9dbcc27159d9d3c
+Z 6e64e7331e56e0c44a533586bb618920
 # Remove this line to create a well-formed Fossil manifest.
index c6ebbcda0e0fcefa8e5b96466b5b3af4f7e3698a..a1b607602a0a095dd2dbbfd7585e71d6f467ff5d 100644 (file)
@@ -1 +1 @@
-5f2d5ccd56c06c3468377126acfd4be39b79b05bb6fb09b674b2e185df143aa3
\ No newline at end of file
+599d1f8ec2f9e24924a6f9e66c85664360c7b95531b07a4efe1dd8c096b3fc99
\ No newline at end of file
index eed8a9e7026603ea799bd32a0f413c1886ea34c3..3952981dabb9eb2eb85a677107a5c778c9e193fb 100644 (file)
@@ -16,6 +16,8 @@ source $testdir/tester.tcl
 source $testdir/lock_common.tcl
 source $testdir/malloc_common.tcl
 
+forcedelete test2.db
+
 #----------------------------------------------------------------------
 # The following tests - savepoint-1.* - test that the SAVEPOINT, RELEASE
 # and ROLLBACK TO comands are correctly parsed, and that the auto-commit