mirror of
https://github.com/sqlitebrowser/sqlitebrowser.git
synced 2026-01-20 02:50:46 -06:00
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:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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*/
|
||||
@@ -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
|
||||
@@ -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 ( )
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 \
|
||||
|
||||
Reference in New Issue
Block a user