/ Check-in [d3f3acb7]
Login

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

Overview
Comment:Modify the sqlite shell program so that the ".dump" command does not give up if it encounters an SQLITE_CORRUPT error. It tries to keep going in order to extract as much information as it can from the corrupt database. (CVS 1919)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: d3f3acb77f4e9f597af5afac565916b9c5e1c5d6
User & Date: drh 2004-08-30 01:54:05
Context
2004-08-30
14:22
Remove the \001 character that lemon inserts automatically in its output file. The need for this character has expired and it creates confusion for users. Ticket #877 (CVS 1920) check-in: acfc5918 user: drh tags: trunk
01:54
Modify the sqlite shell program so that the ".dump" command does not give up if it encounters an SQLITE_CORRUPT error. It tries to keep going in order to extract as much information as it can from the corrupt database. (CVS 1919) check-in: d3f3acb7 user: drh tags: trunk
2004-08-29
23:42
Change the name of the global variable to sqlite3_temp_directory to avoid a naming conflict with version 2.8. (CVS 1918) check-in: 431f7436 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/shell.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains code to implement the "sqlite" command line
    13     13   ** utility for accessing SQLite databases.
    14     14   **
    15         -** $Id: shell.c,v 1.111 2004/08/14 18:18:44 drh Exp $
           15  +** $Id: shell.c,v 1.112 2004/08/30 01:54:05 drh Exp $
    16     16   */
    17     17   #include <stdlib.h>
    18     18   #include <string.h>
    19     19   #include <stdio.h>
    20     20   #include <assert.h>
    21     21   #include "sqlite3.h"
    22     22   #include <ctype.h>
................................................................................
   551    551     }else{
   552    552       memcpy(&zIn[nIn], zAppend, nAppend);
   553    553       zIn[len-1] = '\0';
   554    554     }
   555    555   
   556    556     return zIn;
   557    557   }
          558  +
          559  +
          560  +/*
          561  +** Execute a query statement that has a single result column.  Print
          562  +** that result column on a line by itself with a semicolon terminator.
          563  +*/
          564  +static int run_table_dump_query(FILE *out, sqlite3 *db, const char *zSelect){
          565  +  sqlite3_stmt *pSelect;
          566  +  int rc;
          567  +  rc = sqlite3_prepare(db, zSelect, -1, &pSelect, 0);
          568  +  if( rc!=SQLITE_OK || !pSelect ){
          569  +    return rc;
          570  +  }
          571  +  rc = sqlite3_step(pSelect);
          572  +  while( rc==SQLITE_ROW ){
          573  +    fprintf(out, "%s;\n", sqlite3_column_text(pSelect, 0));
          574  +    rc = sqlite3_step(pSelect);
          575  +  }
          576  +  return sqlite3_finalize(pSelect);
          577  +}
          578  +
   558    579   
   559    580   /*
   560    581   ** This is a different callback routine used for dumping the database.
   561    582   ** Each row received by this callback consists of a table name,
   562    583   ** the table type ("index" or "table") and SQL to create the table.
   563    584   ** This routine should print text sufficient to recreate the table.
   564    585   */
................................................................................
   574    595     zType = azArg[1];
   575    596     zSql = azArg[2];
   576    597     
   577    598     fprintf(p->out, "%s;\n", zSql);
   578    599   
   579    600     if( strcmp(zType, "table")==0 ){
   580    601       sqlite3_stmt *pTableInfo = 0;
   581         -    sqlite3_stmt *pSelect = 0;
   582    602       char *zSelect = 0;
   583    603       char *zTableInfo = 0;
   584    604       char *zTmp = 0;
   585    605      
   586    606       zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0);
   587    607       zTableInfo = appendText(zTableInfo, zTable, '"');
   588    608       zTableInfo = appendText(zTableInfo, ");", 0);
................................................................................
   614    634       if( rc!=SQLITE_OK ){
   615    635         if( zSelect ) free(zSelect);
   616    636         return 1;
   617    637       }
   618    638       zSelect = appendText(zSelect, "|| ')' FROM  ", 0);
   619    639       zSelect = appendText(zSelect, zTable, '"');
   620    640   
   621         -    rc = sqlite3_prepare(p->db, zSelect, -1, &pSelect, 0);
          641  +    rc = run_table_dump_query(p->out, p->db, zSelect);
          642  +    if( rc==SQLITE_CORRUPT ){
          643  +      zSelect = appendText(zSelect, " ORDER BY rowid DESC", 0);
          644  +      rc = run_table_dump_query(p->out, p->db, zSelect);
          645  +    }
   622    646       if( zSelect ) free(zSelect);
   623         -    if( rc!=SQLITE_OK || !pSelect ){
   624         -      return 1;
   625         -    }
   626         -
   627         -    rc = sqlite3_step(pSelect);
   628         -    while( rc==SQLITE_ROW ){
   629         -      fprintf(p->out, "%s;\n", sqlite3_column_text(pSelect, 0));
   630         -      rc = sqlite3_step(pSelect);
   631         -    }
   632         -    rc = sqlite3_finalize(pSelect);
   633    647       if( rc!=SQLITE_OK ){
   634    648         return 1;
   635    649       }
   636    650     }
   637         -
   638    651     return 0;
   639    652   }
          653  +
          654  +/*
          655  +** Run zQuery.  Update dump_callback() as the callback routine.
          656  +** If we get a SQLITE_CORRUPT error, rerun the query after appending
          657  +** "ORDER BY rowid DESC" to the end.
          658  +*/
          659  +static int run_schema_dump_query(
          660  +  struct callback_data *p, 
          661  +  const char *zQuery,
          662  +  char **pzErrMsg
          663  +){
          664  +  int rc;
          665  +  rc = sqlite3_exec(p->db, zQuery, dump_callback, p, pzErrMsg);
          666  +  if( rc==SQLITE_CORRUPT ){
          667  +    char *zQ2;
          668  +    int len = strlen(zQuery);
          669  +    if( pzErrMsg ) sqlite3_free(*pzErrMsg);
          670  +    zQ2 = malloc( len+100 );
          671  +    if( zQ2==0 ) return rc;
          672  +    sprintf(zQ2, "%s ORDER BY rowid DESC", zQuery);
          673  +    rc = sqlite3_exec(p->db, zQ2, dump_callback, p, pzErrMsg);
          674  +    free(zQ2);
          675  +  }
          676  +  return rc;
          677  +}
   640    678   
   641    679   /*
   642    680   ** Text of a help message
   643    681   */
   644    682   static char zHelp[] =
   645    683     ".databases             List names and files of attached databases\n"
   646    684     ".dump ?TABLE? ...      Dump the database in an SQL text format\n"
................................................................................
   795    833     }else
   796    834   
   797    835     if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
   798    836       char *zErrMsg = 0;
   799    837       open_db(p);
   800    838       fprintf(p->out, "BEGIN TRANSACTION;\n");
   801    839       if( nArg==1 ){
   802         -      sqlite3_exec(p->db,
          840  +      run_schema_dump_query(p, 
          841  +        "SELECT name, type, sql FROM sqlite_master "
          842  +        "WHERE sql NOT NULL AND type=='table'", 0
          843  +      );
          844  +      run_schema_dump_query(p, 
   803    845           "SELECT name, type, sql FROM sqlite_master "
   804         -        "WHERE type!='meta' AND sql NOT NULL "
   805         -        "ORDER BY substr(type,2,1), name",
   806         -        dump_callback, p, &zErrMsg
          846  +        "WHERE sql NOT NULL AND type!='table' AND type!='meta'", 0
   807    847         );
   808    848       }else{
   809    849         int i;
   810         -      for(i=1; i<nArg && zErrMsg==0; i++){
          850  +      for(i=1; i<nArg; i++){
   811    851           zShellStatic = azArg[i];
   812         -        sqlite3_exec(p->db,
          852  +        run_schema_dump_query(p,
          853  +          "SELECT name, type, sql FROM sqlite_master "
          854  +          "WHERE tbl_name LIKE shellstatic() AND type=='table'"
          855  +          "  AND sql NOT NULL", 0);
          856  +        run_schema_dump_query(p,
   813    857             "SELECT name, type, sql FROM sqlite_master "
   814         -          "WHERE tbl_name LIKE shellstatic() AND type!='meta' AND sql NOT NULL "
   815         -          "ORDER BY substr(type,2,1), name",
   816         -          dump_callback, p, &zErrMsg
   817         -        );
          858  +          "WHERE tbl_name LIKE shellstatic() AND type!='table'"
          859  +          "  AND type!='meta' AND sql NOT NULL", 0);
   818    860           zShellStatic = 0;
   819    861         }
   820    862       }
   821    863       if( zErrMsg ){
   822    864         fprintf(stderr,"Error: %s\n", zErrMsg);
   823    865         sqlite3_free(zErrMsg);
   824    866       }else{