#include "sqlitedb.h"
#include "sqlitetablemodel.h"
#include "MainWindow.h"
#include
#include
#include
#include
#include
#include
#include
#include
bool DBBrowserDB::isOpen ( ) const
{
return _db!=0;
}
bool DBBrowserDB::getDirty() const
{
return !savepointList.empty();
}
bool DBBrowserDB::open ( const QString & db)
{
bool ok=false;
int err;
if (isOpen()) close();
//try to verify the SQLite version 3 file header
QFile dbfile(db);
if ( dbfile.open( QIODevice::ReadOnly ) ) {
char buffer[16+1];
dbfile.readLine(buffer, 16);
QString contents = QString(buffer);
dbfile.close();
if (!contents.startsWith("SQLite format 3")) {
lastErrorMessage = QObject::tr("File is not a SQLite 3 database");
return false;
}
} else {
lastErrorMessage = QObject::tr("File could not be read");
return false;
}
lastErrorMessage = QObject::tr("no error");
err = sqlite3_open_v2(db.toUtf8(), &_db, SQLITE_OPEN_READWRITE, NULL);
if ( err ) {
lastErrorMessage = QString::fromUtf8((const char*)sqlite3_errmsg(_db));
sqlite3_close(_db);
_db = 0;
return false;
}
if (_db){
// set preference defaults
QSettings settings(QApplication::organizationName(), QApplication::organizationName());
settings.sync();
bool foreignkeys = settings.value( "/db/foreignkeys", false ).toBool();
setPragma("foreign_keys", foreignkeys ? "1" : "0");
if (SQLITE_OK==sqlite3_exec(_db,"PRAGMA empty_result_callbacks = ON;",
NULL,NULL,NULL)){
if (SQLITE_OK==sqlite3_exec(_db,"PRAGMA show_datatypes = ON;",
NULL,NULL,NULL)){
ok=true;
}
curDBFilename = db;
}
// Enable extension loading
sqlite3_enable_load_extension(_db, 1);
}
return ok;
}
bool DBBrowserDB::setRestorePoint(const QString& pointname)
{
if(!isOpen())
return false;
if(savepointList.contains(pointname))
return true;
if(_db)
{
QString query = QString("SAVEPOINT %1;").arg(pointname);
sqlite3_exec(_db, query.toUtf8(), NULL, NULL, NULL);
savepointList.append(pointname);
if(mainWindow) mainWindow->dbState(getDirty());
}
return true;
}
bool DBBrowserDB::save(const QString& pointname)
{
if(!isOpen() || savepointList.contains(pointname) == false)
return false;
if(_db)
{
QString query = QString("RELEASE %1;").arg(pointname);
sqlite3_exec(_db, query.toUtf8(), NULL,NULL,NULL);
savepointList.removeAll(pointname);
if(mainWindow) mainWindow->dbState(getDirty());
}
return true;
}
bool DBBrowserDB::revert(const QString& pointname)
{
if(!isOpen() || savepointList.contains(pointname) == false)
return false;
if(_db)
{
QString query = QString("ROLLBACK TO SAVEPOINT %1;").arg(pointname);
sqlite3_exec(_db, query.toUtf8(), NULL, NULL, NULL);
query = QString("RELEASE %1;").arg(pointname);
sqlite3_exec(_db, query.toUtf8(), NULL, NULL, NULL);
savepointList.removeAll(pointname);
if(mainWindow) mainWindow->dbState(getDirty());
}
return true;
}
bool DBBrowserDB::saveAll()
{
foreach(const QString& point, savepointList)
{
if(!save(point))
return false;
}
return true;
}
bool DBBrowserDB::revertAll()
{
foreach(const QString& point, savepointList)
{
if(!revert(point))
return false;
}
return true;
}
bool DBBrowserDB::create ( const QString & db)
{
bool ok=false;
if (isOpen()) close();
lastErrorMessage = QObject::tr("no error");
// read encoding from settings and open with sqlite3_open for utf8
// and sqlite3_open16 for utf16
QSettings settings(QApplication::organizationName(), QApplication::organizationName());
QString sEncoding = settings.value("/db/defaultencoding", "UTF-8").toString();
int openresult = SQLITE_OK;
if(sEncoding == "UTF-8" || sEncoding == "UTF8" || sEncoding == "Latin1")
openresult = sqlite3_open(db.toUtf8(), &_db);
else
openresult = sqlite3_open16(db.utf16(), &_db);
if( openresult != SQLITE_OK ){
lastErrorMessage = QString::fromUtf8((const char*)sqlite3_errmsg(_db));
sqlite3_close(_db);
_db = 0;
return false;
}
if (_db){
if (SQLITE_OK==sqlite3_exec(_db,"PRAGMA empty_result_callbacks = ON;",
NULL,NULL,NULL)){
if (SQLITE_OK==sqlite3_exec(_db,"PRAGMA show_datatypes = ON;",
NULL,NULL,NULL)){
ok=true;
}
curDBFilename = db;
}
// Enable extension loading
sqlite3_enable_load_extension(_db, 1);
}
return ok;
}
bool DBBrowserDB::close()
{
if(_db)
{
if (getDirty())
{
QMessageBox::StandardButton reply = QMessageBox::question(0,
QApplication::applicationName(),
QObject::tr("Do you want to save the changes "
"made to the database file %1?").arg(curDBFilename),
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
// If the user clicked the cancel button stop here and return false
if(reply == QMessageBox::Cancel)
return false;
// If he didn't it was either yes or no
if(reply == QMessageBox::Yes)
saveAll();
else
revertAll(); //not really necessary, I think... but will not hurt.
}
sqlite3_close(_db);
}
_db = 0;
objMap.clear();
savepointList.clear();
if(mainWindow) mainWindow->dbState(getDirty());
// Return true to tell the calling function that the closing wasn't cancelled by the user
return true;
}
bool DBBrowserDB::dump(const QString& filename)
{
// Open file
QFile file(filename);
if(file.open(QIODevice::WriteOnly))
{
// Create progress dialog. For this count the number of all table rows to be exported first;
// this does neither take the table creation itself nor
// indices, views or triggers into account but compared to the number of rows those should be neglectable
unsigned int numRecordsTotal = 0, numRecordsCurrent = 0;
QList tables = objMap.values("table");
QMutableListIterator it(tables);
while(it.hasNext())
{
it.next();
// Remove the sqlite_stat1 table if there is one
if(it.value().getname() == "sqlite_stat1" || it.value().getname() == "sqlite_sequence")
{
it.remove();
} else {
// Otherwise get the number of records in this table
SqliteTableModel tableModel(0, this);
tableModel.setTable(it.value().getname());
numRecordsTotal += tableModel.totalRowCount();
}
}
QProgressDialog progress(QObject::tr("Exporting database to SQL file..."),
QObject::tr("Cancel"), 0, numRecordsTotal);
progress.setWindowModality(Qt::ApplicationModal);
// Regular expression to check for numeric strings
QRegExp regexpIsNumeric("\\d*");
// Open text stream to the file
QTextStream stream(&file);
// Put the SQL commands in a transaction block
stream