Rewrite and simplify import SQL code

Rewrite the import SQL code using a similar method to the one used in
executeQuery(). This makes the code much easier to read and removes the
last remnants of that C code stolen from some demo application.
This commit is contained in:
Martin Kleusberg
2013-03-20 22:17:36 +01:00
parent 0282533092
commit 0868f299af
6 changed files with 58 additions and 189 deletions

View File

@@ -933,11 +933,19 @@ void MainWindow::importDatabaseFromSQL()
if(!fileName.isNull())
db.create(newDBfile);
}
int lineErr;
if (!db.reload(fileName, &lineErr))
QMessageBox::information(this, QApplication::applicationName(), tr("Error importing data at line %1").arg(lineErr) );
// Open, read, execute and close file
QApplication::setOverrideCursor(Qt::WaitCursor);
QFile f(fileName);
f.open(QIODevice::ReadOnly);
if(!db.executeMultiSQL(f.readAll()))
QMessageBox::warning(this, QApplication::applicationName(), tr("Error importing data: %1").arg(db.lastErrorMessage));
else
QMessageBox::information(this, QApplication::applicationName(), tr("Import completed"));
QMessageBox::information(this, QApplication::applicationName(), tr("Import completed."));
f.close();
QApplication::restoreOverrideCursor();
// Resfresh window
populateStructure();
resetBrowser();
}

View File

@@ -1,150 +0,0 @@
#include "sqlbrowser_util.h"
#include <sqlite3.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/*following routines extracted from shell.c for dump support*/
/*
** Return TRUE if the last non-whitespace character in z[] is a semicolon.
** z[] is N characters long.
*/
static int _ends_with_semicolon(const char *z, int N){
while( N>0 && isspace(z[N-1]) ){ N--; }
return N>0 && z[N-1]==';';
}
/*
** Test to see if a line consists entirely of whitespace.
*/
static int _all_whitespace(const char *z){
for(; *z; z++){
if( isspace(*z) ) continue;
if( *z=='/' && z[1]=='*' ){
z += 2;
while( *z && (*z!='*' || z[1]!='/') ){ z++; }
if( *z==0 ) return 0;
z++;
continue;
}
if( *z=='-' && z[1]=='-' ){
z += 2;
while( *z && *z!='\n' ){ z++; }
if( *z==0 ) return 1;
continue;
}
return 0;
}
return 1;
}
static char *sqlbrowser_getline(FILE *in){
char *zLine;
int nLine;
int n;
int eol;
nLine = 100;
zLine = malloc( nLine );
if( zLine==0 ) return 0;
n = 0;
eol = 0;
while( !eol ){
if( n+100>nLine ){
nLine = nLine*2 + 100;
zLine = realloc(zLine, nLine);
if( zLine==0 )
return 0;
}
if( fgets(&zLine[n], nLine - n, in)==0 ){
if( n==0 ){
free(zLine);
return 0;
}
zLine[n] = 0;
eol = 1;
break;
}
while( zLine[n] ){ n++; }
if( n>0 && zLine[n-1]=='\n' ){
n--;
zLine[n] = 0;
eol = 1;
}
}
zLine = realloc( zLine, n+1 );
return zLine;
}
static void process_input(sqlite3 * db, FILE *in, int * lineErr){
char *zLine;
char *zSql = 0;
char * zErrMsg = 0;
int nSql = 0;
int rc;
while((zLine = sqlbrowser_getline(in))!=0 ){
if( (zSql==0 || zSql[0]==0) && _all_whitespace(zLine) ) continue;
(*lineErr)++;
if( zSql==0 ){
int i;
for(i=0; zLine[i] && isspace(zLine[i]); i++){}
if( zLine[i]!=0 ){
nSql = strlen(zLine);
zSql = malloc( nSql+1 );
strcpy(zSql, zLine);
}
}else{
int len = strlen(zLine);
zSql = realloc( zSql, nSql + len + 2 );
/*if( zSql==0 ){
fprintf(stderr,"%s: out of memory!\n", Argv0);
exit(1);
}*/
strcpy(&zSql[nSql++], "\n");
strcpy(&zSql[nSql], zLine);
nSql += len;
}
free(zLine);
if( zSql && _ends_with_semicolon(zSql, nSql) && sqlite3_complete(zSql) ){
rc = sqlite3_exec(db, zSql, NULL, NULL, &zErrMsg);//&zErrMsg
if( rc || zErrMsg ){
//if( in!=0 && !p->echoOn ) printf("%s\n",zSql);
if( zErrMsg!=0 ){
/*printf("SQL error: %s\n", zErrMsg);*/
free(zErrMsg);
zErrMsg = 0;
if( zSql ){
free(zSql);
}
return;
}/*else{
printf("SQL error: %s\n", sqlite3_error_string(rc));
}*/
}
free(zSql);
zSql = 0;
nSql = 0;
}
}
if( zSql ){
/*if( !_all_whitespace(zSql) ) printf("Incomplete SQL: %s\n", zSql);*/
free(zSql);
}
/*normal exit, clear err*/
*lineErr = 0;
}
/*
/Dump database to a file
*/
int load_database(sqlite3 * db, FILE * infile, int * lineErr){
int rc = 0;
process_input(db, infile, lineErr);
return rc;
}
/* end of shell.c routines*/

View File

@@ -1,17 +0,0 @@
#ifndef _H_SQLBROWSERUTIL
#define _H_SQLBROWSERUTIL
#ifdef __cplusplus
extern "C" {
#endif
#include <sqlite3.h>
#include <stdio.h>
int load_database(sqlite3 * db, FILE * infile, int * lineErr);
#ifdef __cplusplus
} /* End of the 'extern "C"' block */
#endif
#endif

View File

@@ -1,5 +1,4 @@
#include "sqlitedb.h"
#include "sqlbrowser_util.h"
#include "MainWindow.h"
#include <QFile>
@@ -220,21 +219,6 @@ bool DBBrowserDB::compact ( )
}
}
bool DBBrowserDB::reload( const QString & filename, int * lineErr)
{
/*to avoid a nested transaction error*/
sqlite3_exec(_db,"COMMIT;", NULL,NULL,NULL);
FILE * cfile = fopen(filename.toUtf8(), (const char *) "r");
load_database(_db, cfile, lineErr);
fclose(cfile);
setDirty(false);
if ((*lineErr)!=0)
{
return false;
}
return true;
}
bool DBBrowserDB::dump(const QString& filename)
{
// Open file
@@ -347,6 +331,51 @@ bool DBBrowserDB::executeSQL ( const QString & statement, bool dirtyDB, bool log
return true;
}
bool DBBrowserDB::executeMultiSQL(const QString& statement, bool dirty, bool log)
{
// First check if a DB is opened
if(!isOpen())
return false;
// Log the statement if needed
if(log)
logSQL(statement, kLogMsg_App);
// Execute the statement by looping until SQLite stops giving back a tail string
sqlite3_stmt* vm;
QByteArray utf8Query = statement.toUtf8();
const char *tail = utf8Query.data();
int res = 0;
unsigned int line = 0;
do
{
line++;
res = sqlite3_prepare_v2(_db, tail, strlen(tail), &vm, &tail);
if(res == SQLITE_OK)
{
if(sqlite3_step(vm) == SQLITE_ERROR)
{
sqlite3_finalize(vm);
lastErrorMessage = QObject::tr("Error in statement #%1: %2.\nAborting execution.").arg(line).arg(sqlite3_errmsg(_db));
qDebug(lastErrorMessage.toStdString().c_str());
return false;
} else {
sqlite3_finalize(vm);
}
} else {
lastErrorMessage = QObject::tr("Error in statement #%1: %2.\nAborting execution.").arg(line).arg(sqlite3_errmsg(_db));
qDebug(lastErrorMessage.toStdString().c_str());
return false;
}
} while(tail && *tail != 0 && (res == SQLITE_OK || res == SQLITE_DONE));
// Set dirty flag
if(dirty)
setDirty(true);
// Exit
return true;
}
bool DBBrowserDB::addRecord ( )
{

View File

@@ -86,6 +86,7 @@ public:
bool dump( const QString & filename);
bool reload( const QString & filename, int * lineErr);
bool executeSQL ( const QString & statement, bool dirtyDB=true, bool logsql=true);
bool executeMultiSQL(const QString& statement, bool dirty = true, bool log = false);
/**
* @brief getTableSQL Returns the create table statement for the given table.

View File

@@ -10,7 +10,6 @@ CONFIG += qt \
HEADERS += \
sqlitedb.h \
sqlbrowser_util.h \
MainWindow.h \
SQLiteSyntaxHighlighter.h \
CreateIndexDialog.h \
@@ -30,7 +29,6 @@ HEADERS += \
SOURCES += \
sqlitedb.cpp \
sqlbrowser_util.c \
MainWindow.cpp \
SQLiteSyntaxHighlighter.cpp \
CreateIndexDialog.cpp \