/ Check-in [91df4b8e]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix a problem in the .recover command with recovering WITHOUT ROWID tables where the PK columns are not the leftmost in the CREATE TABLE statement.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | dbdata
Files: files | file ages | folders
SHA3-256: 91df4b8e0386105d01614921e8410994b621404a3d46ec4af8687b8743c52d52
User & Date: dan 2019-04-27 15:35:45
Context
2019-04-27
18:47
Add the "--lost-and-found" option to the ".recover" command. For setting the name of the orphaned rows table. check-in: 67bb88e2 user: dan tags: dbdata
15:35
Fix a problem in the .recover command with recovering WITHOUT ROWID tables where the PK columns are not the leftmost in the CREATE TABLE statement. check-in: 91df4b8e user: dan tags: dbdata
2019-04-26
21:11
Have .recover store all orphaned rows in a single table, with extra columns to indicate the orphaned page and sub-tree they were discovered within. check-in: 7221f6e3 user: dan tags: dbdata
Changes
Hide Diffs Unified Diffs Show Whitespace Changes Patch

Changes to src/shell.c.in.

6286
6287
6288
6289
6290
6291
6292





6293
6294
6295
6296
6297
6298
6299
....
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322


6323
6324
6325
6326
6327
6328
6329
    shellFinalize(&rc, pStmt);

    if( bIntkey==bSqlIntkey ){
      int i;
      const char *zPk = "_rowid_";
      sqlite3_stmt *pPkFinder = 0;






      pTab->iPk = -2;
      if( bIntkey ){
        shellPreparePrintf(dbtmp, &rc, &pPkFinder, 
          "SELECT cid, name FROM pragma_table_info(%Q) "
          "  WHERE pk=1 AND type='integer' COLLATE nocase"
          "  AND NOT EXISTS (SELECT cid FROM pragma_table_info(%Q) WHERE pk=2)"
          , zName, zName
................................................................................
        pTab->azlCol[0] = shellMPrintf(&rc, "%Q", zPk);
      }else{
        pTab->azlCol[0] = shellMPrintf(&rc, "");
      }
      i = 1;
      shellPreparePrintf(dbtmp, &rc, &pStmt, 
          "SELECT %Q || group_concat(name, ', ') "
          "  FILTER (WHERE cid!=%d) OVER (ORDER BY cid) "
          "FROM pragma_table_info(%Q)", 
          bIntkey ? ", " : "", pTab->iPk, zName


      );
      while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
        const char *zText = (const char*)sqlite3_column_text(pStmt, 0);
        pTab->azlCol[i] = shellMPrintf(&rc, "%s%s", pTab->azlCol[0], zText);
        i++;
      }
      shellFinalize(&rc, pStmt);







>
>
>
>
>







 







|

|
>
>







6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
....
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
    shellFinalize(&rc, pStmt);

    if( bIntkey==bSqlIntkey ){
      int i;
      const char *zPk = "_rowid_";
      sqlite3_stmt *pPkFinder = 0;

      /* If this is an intkey table and there is an INTEGER PRIMARY KEY,
      ** set zPk to the name of the PK column, and pTab->iPk to the index
      ** of the column, where columns are 0-numbered from left to right.
      ** Or, if this is a WITHOUT ROWID table or if there is no IPK column,
      ** leave zPk as "_rowid_" and pTab->iPk at -2.  */
      pTab->iPk = -2;
      if( bIntkey ){
        shellPreparePrintf(dbtmp, &rc, &pPkFinder, 
          "SELECT cid, name FROM pragma_table_info(%Q) "
          "  WHERE pk=1 AND type='integer' COLLATE nocase"
          "  AND NOT EXISTS (SELECT cid FROM pragma_table_info(%Q) WHERE pk=2)"
          , zName, zName
................................................................................
        pTab->azlCol[0] = shellMPrintf(&rc, "%Q", zPk);
      }else{
        pTab->azlCol[0] = shellMPrintf(&rc, "");
      }
      i = 1;
      shellPreparePrintf(dbtmp, &rc, &pStmt, 
          "SELECT %Q || group_concat(name, ', ') "
          "  FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) "
          "FROM pragma_table_info(%Q)", 
          bIntkey ? ", " : "", pTab->iPk, 
          bIntkey ? "" : "(CASE WHEN pk=0 THEN 1000000 ELSE pk END), ",
          zName
      );
      while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
        const char *zText = (const char*)sqlite3_column_text(pStmt, 0);
        pTab->azlCol[i] = shellMPrintf(&rc, "%s%s", pTab->azlCol[0], zText);
        i++;
      }
      shellFinalize(&rc, pStmt);

Changes to test/recover.test.

80
81
82
83
84
85
86
87











88
  CREATE TABLE t3(i INTEGER PRIMARY KEY AUTOINCREMENT, b, c);
  INSERT INTO t3 VALUES(NULL, 1, 2);
  INSERT INTO t3 VALUES(NULL, 3, 4);
  INSERT INTO t3 VALUES(NULL, 5, 6);
  DELETE FROM t2;
"
do_recover_test 1.3.2












finish_test








>
>
>
>
>
>
>
>
>
>
>

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  CREATE TABLE t3(i INTEGER PRIMARY KEY AUTOINCREMENT, b, c);
  INSERT INTO t3 VALUES(NULL, 1, 2);
  INSERT INTO t3 VALUES(NULL, 3, 4);
  INSERT INTO t3 VALUES(NULL, 5, 6);
  DELETE FROM t2;
"
do_recover_test 1.3.2

#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.1.0 {
  CREATE TABLE t1(a, b, c, PRIMARY KEY(b, c)) WITHOUT ROWID;
  INSERT INTO t1 VALUES(1, 2, 3);
  INSERT INTO t1 VALUES(4, 5, 6);
  INSERT INTO t1 VALUES(7, 8, 9);
}

do_recover_test 2.1.1

finish_test