mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-05 04:30:38 +03:00
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) FossilOrigin-Name: d3f3acb77f4e9f597af5afac565916b9c5e1c5d6
This commit is contained in:
90
src/shell.c
90
src/shell.c
@@ -12,7 +12,7 @@
|
||||
** This file contains code to implement the "sqlite" command line
|
||||
** utility for accessing SQLite databases.
|
||||
**
|
||||
** $Id: shell.c,v 1.111 2004/08/14 18:18:44 drh Exp $
|
||||
** $Id: shell.c,v 1.112 2004/08/30 01:54:05 drh Exp $
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -556,6 +556,27 @@ static char * appendText(char *zIn, char const *zAppend, char quote){
|
||||
return zIn;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Execute a query statement that has a single result column. Print
|
||||
** that result column on a line by itself with a semicolon terminator.
|
||||
*/
|
||||
static int run_table_dump_query(FILE *out, sqlite3 *db, const char *zSelect){
|
||||
sqlite3_stmt *pSelect;
|
||||
int rc;
|
||||
rc = sqlite3_prepare(db, zSelect, -1, &pSelect, 0);
|
||||
if( rc!=SQLITE_OK || !pSelect ){
|
||||
return rc;
|
||||
}
|
||||
rc = sqlite3_step(pSelect);
|
||||
while( rc==SQLITE_ROW ){
|
||||
fprintf(out, "%s;\n", sqlite3_column_text(pSelect, 0));
|
||||
rc = sqlite3_step(pSelect);
|
||||
}
|
||||
return sqlite3_finalize(pSelect);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** This is a different callback routine used for dumping the database.
|
||||
** Each row received by this callback consists of a table name,
|
||||
@@ -578,7 +599,6 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
|
||||
|
||||
if( strcmp(zType, "table")==0 ){
|
||||
sqlite3_stmt *pTableInfo = 0;
|
||||
sqlite3_stmt *pSelect = 0;
|
||||
char *zSelect = 0;
|
||||
char *zTableInfo = 0;
|
||||
char *zTmp = 0;
|
||||
@@ -618,26 +638,44 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
|
||||
zSelect = appendText(zSelect, "|| ')' FROM ", 0);
|
||||
zSelect = appendText(zSelect, zTable, '"');
|
||||
|
||||
rc = sqlite3_prepare(p->db, zSelect, -1, &pSelect, 0);
|
||||
rc = run_table_dump_query(p->out, p->db, zSelect);
|
||||
if( rc==SQLITE_CORRUPT ){
|
||||
zSelect = appendText(zSelect, " ORDER BY rowid DESC", 0);
|
||||
rc = run_table_dump_query(p->out, p->db, zSelect);
|
||||
}
|
||||
if( zSelect ) free(zSelect);
|
||||
if( rc!=SQLITE_OK || !pSelect ){
|
||||
return 1;
|
||||
}
|
||||
|
||||
rc = sqlite3_step(pSelect);
|
||||
while( rc==SQLITE_ROW ){
|
||||
fprintf(p->out, "%s;\n", sqlite3_column_text(pSelect, 0));
|
||||
rc = sqlite3_step(pSelect);
|
||||
}
|
||||
rc = sqlite3_finalize(pSelect);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Run zQuery. Update dump_callback() as the callback routine.
|
||||
** If we get a SQLITE_CORRUPT error, rerun the query after appending
|
||||
** "ORDER BY rowid DESC" to the end.
|
||||
*/
|
||||
static int run_schema_dump_query(
|
||||
struct callback_data *p,
|
||||
const char *zQuery,
|
||||
char **pzErrMsg
|
||||
){
|
||||
int rc;
|
||||
rc = sqlite3_exec(p->db, zQuery, dump_callback, p, pzErrMsg);
|
||||
if( rc==SQLITE_CORRUPT ){
|
||||
char *zQ2;
|
||||
int len = strlen(zQuery);
|
||||
if( pzErrMsg ) sqlite3_free(*pzErrMsg);
|
||||
zQ2 = malloc( len+100 );
|
||||
if( zQ2==0 ) return rc;
|
||||
sprintf(zQ2, "%s ORDER BY rowid DESC", zQuery);
|
||||
rc = sqlite3_exec(p->db, zQ2, dump_callback, p, pzErrMsg);
|
||||
free(zQ2);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Text of a help message
|
||||
*/
|
||||
@@ -799,22 +837,26 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
||||
open_db(p);
|
||||
fprintf(p->out, "BEGIN TRANSACTION;\n");
|
||||
if( nArg==1 ){
|
||||
sqlite3_exec(p->db,
|
||||
run_schema_dump_query(p,
|
||||
"SELECT name, type, sql FROM sqlite_master "
|
||||
"WHERE type!='meta' AND sql NOT NULL "
|
||||
"ORDER BY substr(type,2,1), name",
|
||||
dump_callback, p, &zErrMsg
|
||||
"WHERE sql NOT NULL AND type=='table'", 0
|
||||
);
|
||||
run_schema_dump_query(p,
|
||||
"SELECT name, type, sql FROM sqlite_master "
|
||||
"WHERE sql NOT NULL AND type!='table' AND type!='meta'", 0
|
||||
);
|
||||
}else{
|
||||
int i;
|
||||
for(i=1; i<nArg && zErrMsg==0; i++){
|
||||
for(i=1; i<nArg; i++){
|
||||
zShellStatic = azArg[i];
|
||||
sqlite3_exec(p->db,
|
||||
run_schema_dump_query(p,
|
||||
"SELECT name, type, sql FROM sqlite_master "
|
||||
"WHERE tbl_name LIKE shellstatic() AND type!='meta' AND sql NOT NULL "
|
||||
"ORDER BY substr(type,2,1), name",
|
||||
dump_callback, p, &zErrMsg
|
||||
);
|
||||
"WHERE tbl_name LIKE shellstatic() AND type=='table'"
|
||||
" AND sql NOT NULL", 0);
|
||||
run_schema_dump_query(p,
|
||||
"SELECT name, type, sql FROM sqlite_master "
|
||||
"WHERE tbl_name LIKE shellstatic() AND type!='table'"
|
||||
" AND type!='meta' AND sql NOT NULL", 0);
|
||||
zShellStatic = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user