diff --git a/src/DbStructureModel.cpp b/src/DbStructureModel.cpp index bbe9dc5f..e77921bb 100644 --- a/src/DbStructureModel.cpp +++ b/src/DbStructureModel.cpp @@ -170,40 +170,32 @@ void DbStructureModel::reloadData() typeToParentItem.insert("trigger", itemTriggers); // Get all database objects and sort them by their name - QMultiMap dbobjs; + QMultiMap dbobjs; for(auto it=m_db.objMap.constBegin(); it != m_db.objMap.constEnd(); ++it) - dbobjs.insert((*it).getname(), (*it)); + dbobjs.insert((*it)->name(), (*it)); // Add the actual table objects for(auto it=dbobjs.constBegin();it!=dbobjs.constEnd();++it) { // Object node - QString type; - switch((*it).gettype()) - { - case sqlb::Object::Types::Table: type = "table"; break; - case sqlb::Object::Types::Index: type = "index"; break; - case sqlb::Object::Types::Trigger: type = "trigger"; break; - case sqlb::Object::Types::View: type = "view"; break; - } - QTreeWidgetItem* item = addNode(typeToParentItem.value(type), *it); + QTreeWidgetItem* item = addNode(typeToParentItem.value(sqlb::Object::typeToString((*it)->type())), *it); // If it is a table or view add the field nodes - if((*it).gettype() == sqlb::Object::Types::Table || (*it).gettype() == sqlb::Object::Types::View) + if((*it)->type() == sqlb::Object::Types::Table || (*it)->type() == sqlb::Object::Types::View) { // Add extra node for browsable section addNode(typeToParentItem.value("browsable"), *it); // Add field nodes QStringList pk_columns; - if(it->gettype() == sqlb::Object::Types::Table) + if((*it)->type() == sqlb::Object::Types::Table) { - sqlb::FieldVector pk = it->object.dynamicCast()->primaryKey(); + sqlb::FieldVector pk = (*it).dynamicCast()->primaryKey(); foreach(sqlb::FieldPtr pk_col, pk) pk_columns.push_back(pk_col->name()); } - sqlb::FieldInfoList fieldList = it->object->fieldInformation(); + sqlb::FieldInfoList fieldList = (*it)->fieldInformation(); foreach(const sqlb::FieldInfo& field, fieldList) { QTreeWidgetItem *fldItem = new QTreeWidgetItem(item); @@ -293,22 +285,15 @@ bool DbStructureModel::dropMimeData(const QMimeData* data, Qt::DropAction action } } -QTreeWidgetItem* DbStructureModel::addNode(QTreeWidgetItem* parent, const DBBrowserObject& object) +QTreeWidgetItem* DbStructureModel::addNode(QTreeWidgetItem* parent, const sqlb::ObjectPtr& object) { - QString type; - switch(object.gettype()) - { - case sqlb::Object::Types::Table: type = "table"; break; - case sqlb::Object::Types::Index: type = "index"; break; - case sqlb::Object::Types::Trigger: type = "trigger"; break; - case sqlb::Object::Types::View: type = "view"; break; - } + QString type = sqlb::Object::typeToString(object->type()); QTreeWidgetItem *item = new QTreeWidgetItem(parent); item->setIcon(0, QIcon(QString(":/icons/%1").arg(type))); - item->setText(0, object.getname()); + item->setText(0, object->name()); item->setText(1, type); - item->setText(3, object.getsql()); + item->setText(3, object->originalSql()); return item; } diff --git a/src/DbStructureModel.h b/src/DbStructureModel.h index 45aab828..784ccdb0 100644 --- a/src/DbStructureModel.h +++ b/src/DbStructureModel.h @@ -4,8 +4,8 @@ #include class DBBrowserDB; -class DBBrowserObject; class QTreeWidgetItem; +namespace sqlb { class Object; typedef QSharedPointer ObjectPtr; } class DbStructureModel : public QAbstractItemModel { @@ -33,7 +33,7 @@ private: QTreeWidgetItem* rootItem; DBBrowserDB& m_db; - QTreeWidgetItem* addNode(QTreeWidgetItem* parent, const DBBrowserObject& object); + QTreeWidgetItem* addNode(QTreeWidgetItem* parent, const sqlb::ObjectPtr& object); }; #endif diff --git a/src/EditIndexDialog.cpp b/src/EditIndexDialog.cpp index 96d1e9d4..f63c48e1 100644 --- a/src/EditIndexDialog.cpp +++ b/src/EditIndexDialog.cpp @@ -17,13 +17,13 @@ EditIndexDialog::EditIndexDialog(DBBrowserDB& db, const QString& indexName, bool ui->setupUi(this); // Get list of tables, sort it alphabetically and fill the combobox - QMultiMap dbobjs; - QList tables = pdb.objMap.values("table"); + objectMap dbobjs; + QList tables = pdb.objMap.values("table"); for(auto it=tables.constBegin();it!=tables.constEnd();++it) - dbobjs.insert((*it).getname(), (*it)); + dbobjs.insert((*it)->name(), (*it)); ui->comboTableName->blockSignals(true); for(auto it=dbobjs.constBegin();it!=dbobjs.constEnd();++it) - ui->comboTableName->addItem(QIcon(QString(":icons/table")), (*it).getname()); + ui->comboTableName->addItem(QIcon(QString(":icons/table")), (*it)->name()); ui->comboTableName->blockSignals(false); QHeaderView *tableHeaderView = ui->tableIndexColumns->horizontalHeader(); diff --git a/src/EditTableDialog.cpp b/src/EditTableDialog.cpp index 70a8dd57..f7d725ce 100644 --- a/src/EditTableDialog.cpp +++ b/src/EditTableDialog.cpp @@ -272,9 +272,9 @@ void EditTableDialog::itemChanged(QTreeWidgetItem *item, int column) if(!m_bNewTable) { sqlb::FieldVector pk = m_table.primaryKey(); - foreach(const DBBrowserObject& fkobj, pdb.objMap.values("table")) + foreach(const sqlb::ObjectPtr& fkobj, pdb.objMap.values("table")) { - QList fks = fkobj.object.dynamicCast()->constraints(sqlb::FieldVector(), sqlb::Constraint::ForeignKeyConstraintType); + QList fks = fkobj.dynamicCast()->constraints(sqlb::FieldVector(), sqlb::Constraint::ForeignKeyConstraintType); foreach(sqlb::ConstraintPtr fkptr, fks) { QSharedPointer fk = fkptr.dynamicCast(); @@ -284,7 +284,7 @@ void EditTableDialog::itemChanged(QTreeWidgetItem *item, int column) { QMessageBox::warning(this, qApp->applicationName(), tr("This column is referenced in a foreign key in table %1 and thus " "its name cannot be changed.") - .arg(fkobj.getname())); + .arg(fkobj->name())); // Reset the name to the old value but avoid calling this method again for that automatic change ui->treeWidget->blockSignals(true); item->setText(column, oldFieldName); diff --git a/src/ExportDataDialog.cpp b/src/ExportDataDialog.cpp index fd982165..736df164 100644 --- a/src/ExportDataDialog.cpp +++ b/src/ExportDataDialog.cpp @@ -40,8 +40,8 @@ ExportDataDialog::ExportDataDialog(DBBrowserDB& db, ExportFormats format, QWidge { // Get list of tables to export objectMap objects = pdb.getBrowsableObjects(); - foreach(const DBBrowserObject& obj, objects) - ui->listTables->addItem(new QListWidgetItem(QIcon(QString(":icons/%1").arg(obj.gettype())), obj.getname())); + foreach(const sqlb::ObjectPtr& obj, objects) + ui->listTables->addItem(new QListWidgetItem(QIcon(QString(":icons/%1").arg(sqlb::Object::typeToString(obj->type()))), obj->name())); // Sort list of tables and select the table specified in the selection parameter or alternatively the first one ui->listTables->model()->sort(0); diff --git a/src/ExportSqlDialog.cpp b/src/ExportSqlDialog.cpp index 1de45fc9..f33e2903 100644 --- a/src/ExportSqlDialog.cpp +++ b/src/ExportSqlDialog.cpp @@ -27,7 +27,7 @@ ExportSqlDialog::ExportSqlDialog(DBBrowserDB* db, QWidget* parent, const QString // Get list of tables to export objectMap objects = pdb->getBrowsableObjects(); for(auto it=objects.constBegin();it!=objects.constEnd();++it) { - ui->listTables->addItem(new QListWidgetItem(QIcon(QString(":icons/%1").arg(it.value().gettype())), it.value().getname())); + ui->listTables->addItem(new QListWidgetItem(QIcon(QString(":icons/%1").arg((*it)->type())), (*it)->name())); } // Sort list of tables and select the table specified in the diff --git a/src/ForeignKeyEditorDelegate.cpp b/src/ForeignKeyEditorDelegate.cpp index 805b87c2..973c00d3 100644 --- a/src/ForeignKeyEditorDelegate.cpp +++ b/src/ForeignKeyEditorDelegate.cpp @@ -81,9 +81,9 @@ ForeignKeyEditorDelegate::ForeignKeyEditorDelegate(const DBBrowserDB& db, sqlb:: { const auto objects = m_db.getBrowsableObjects(); for (auto& obj : objects) { - if (obj.gettype() == sqlb::Object::Types::Table) { - QString tableName = obj.object->name(); - m_tablesIds.insert(tableName, obj.object.dynamicCast()->fieldNames()); + if (obj->type() == sqlb::Object::Types::Table) { + QString tableName = obj->name(); + m_tablesIds.insert(tableName, obj.dynamicCast()->fieldNames()); } } } diff --git a/src/ImportCsvDialog.cpp b/src/ImportCsvDialog.cpp index da54c7ac..823b61a9 100644 --- a/src/ImportCsvDialog.cpp +++ b/src/ImportCsvDialog.cpp @@ -186,9 +186,9 @@ void ImportCsvDialog::accept() objectMap objects = pdb->getBrowsableObjects(); for(auto it=objects.constBegin();it!=objects.constEnd();++it) { - if(it.value().gettype() == sqlb::Object::Types::Table && it.value().getname() == ui->editName->text()) + if((*it)->type() == sqlb::Object::Types::Table && (*it)->name() == ui->editName->text()) { - if((size_t)it.value().object.dynamicCast()->fields().size() != csv.columns()) + if((size_t)(*it).dynamicCast()->fields().size() != csv.columns()) { QMessageBox::warning(this, QApplication::applicationName(), tr("There is already a table of that name and an import into an existing table is only possible if the number of columns match.")); diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index c8118468..959a550c 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -365,9 +365,9 @@ void MainWindow::populateStructure() SqlUiLexer::TablesAndColumnsMap tablesToColumnsMap; for(auto it=tab.constBegin();it!=tab.constEnd();++it) { - QString objectname = it.value().getname(); + QString objectname = (*it)->name(); - sqlb::FieldInfoList fi = it->object->fieldInformation(); + sqlb::FieldInfoList fi = (*it)->fieldInformation(); foreach(const sqlb::FieldInfo& f, fi) tablesToColumnsMap[objectname].append(f.name); } diff --git a/src/VacuumDialog.cpp b/src/VacuumDialog.cpp index 766bea3d..9e6e0042 100644 --- a/src/VacuumDialog.cpp +++ b/src/VacuumDialog.cpp @@ -16,13 +16,13 @@ VacuumDialog::VacuumDialog(DBBrowserDB* _db, QWidget* parent) : ui->labelSavepointWarning->setVisible(db->getDirty()); // Populate list of objects to compact - QList objects = db->objMap.values("table"); + QList objects = db->objMap.values("table"); objects.append(db->objMap.values("index")); - for(QList::const_iterator i=objects.constBegin();i!=objects.constEnd();++i) + for(QList::const_iterator i=objects.constBegin();i!=objects.constEnd();++i) { QTreeWidgetItem* item = new QTreeWidgetItem(ui->treeSelectedObjects); - item->setText(0, (*i).getname()); - item->setIcon(0, QIcon(QString(":icons/%1").arg((*i).gettype()))); + item->setText(0, (*i)->name()); + item->setIcon(0, QIcon(QString(":icons/%1").arg(sqlb::Object::typeToString((*i)->type())))); ui->treeSelectedObjects->addTopLevelItem(item); } diff --git a/src/sqlitedb.cpp b/src/sqlitedb.cpp index 2ecfbcd3..6c2dc1b4 100644 --- a/src/sqlitedb.cpp +++ b/src/sqlitedb.cpp @@ -458,20 +458,20 @@ bool DBBrowserDB::dump(const QString& filename, QApplication::setOverrideCursor(Qt::WaitCursor); size_t numRecordsTotal = 0, numRecordsCurrent = 0; - QList tables = objMap.values("table"); - QMutableListIterator it(tables); + 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") + if(it.value()->name() == "sqlite_stat1" || it.value()->name() == "sqlite_sequence") { it.remove(); } else { // Otherwise get the number of records in this table SqliteTableModel tableModel(*this); - tableModel.setTable(it.value().getname()); + tableModel.setTable(it.value()->name()); numRecordsTotal += tableModel.totalRowCount(); } } @@ -491,21 +491,21 @@ bool DBBrowserDB::dump(const QString& filename, // Loop through all tables first as they are required to generate views, indices etc. later for(auto it=tables.constBegin();it!=tables.constEnd();++it) { - if (tablesToDump.indexOf(it->getname()) == -1) + if (tablesToDump.indexOf((*it)->name()) == -1) continue; // Write the SQL string used to create this table to the output file if(exportSchema) - stream << it->getsql() << ";\n"; + stream << (*it)->originalSql() << ";\n"; // If the user doesn't want the data to be exported skip the rest of the loop block here if(!exportData) continue; // get columns - QStringList cols(it->object.dynamicCast()->fieldNames()); + QStringList cols((*it).dynamicCast()->fieldNames()); - QString sQuery = QString("SELECT * FROM %1;").arg(sqlb::escapeIdentifier(it->getname())); + QString sQuery = QString("SELECT * FROM %1;").arg(sqlb::escapeIdentifier((*it)->name())); QByteArray utf8Query = sQuery.toUtf8(); sqlite3_stmt *stmt; QString lineSep(QString(")%1\n").arg(insertNewSyntx?',':';')); @@ -522,7 +522,7 @@ bool DBBrowserDB::dump(const QString& filename, if (!insertNewSyntx || !counter) { - stream << "INSERT INTO " << sqlb::escapeIdentifier(it->getname()); + stream << "INSERT INTO " << sqlb::escapeIdentifier((*it)->name()); if (insertColNames) stream << " (" << cols.join(",") << ")"; stream << " VALUES ("; @@ -594,12 +594,12 @@ bool DBBrowserDB::dump(const QString& filename, for(auto it=objMap.constBegin();it!=objMap.constEnd();++it) { // Make sure it's not a table again - if(it.value().gettype() == sqlb::Object::Types::Table) + if(it.value()->type() == sqlb::Object::Types::Table) continue; // Write the SQL string used to create this object to the output file - if(!it->getsql().isEmpty()) - stream << it->getsql() << ";\n"; + if(!(*it)->originalSql().isEmpty()) + stream << (*it)->originalSql() << ";\n"; } } @@ -1076,13 +1076,13 @@ bool DBBrowserDB::renameColumn(const QString& tablename, const sqlb::Table& tabl for(auto it=objMap.constBegin();it!=objMap.constEnd();++it) { // If this object references the table and it's not the table itself save it's SQL string - if((*it).getTableName() == tablename && (*it).gettype() != sqlb::Object::Types::Table) + if((*it)->baseTable() == tablename && (*it)->type() != sqlb::Object::Types::Table) { // If this is an index, update the fields first. This highly increases the chance that the SQL statement won't throw an // error later on when we try to recreate it. - if((*it).gettype() == sqlb::Object::Types::Index) + if((*it)->type() == sqlb::Object::Types::Index) { - sqlb::IndexPtr idx = (*it).object.dynamicCast(); + sqlb::IndexPtr idx = (*it).dynamicCast(); for(int i=0;icolumns().size();i++) { if(idx->column(i)->name() == name) @@ -1092,7 +1092,7 @@ bool DBBrowserDB::renameColumn(const QString& tablename, const sqlb::Table& tabl } else { // If it's a view or a trigger we don't have any chance to corrections yet. Just store the statement as is and // hope for the best. - otherObjectsSql << (*it).getsql().trimmed() + ";"; + otherObjectsSql << (*it)->originalSql().trimmed() + ";"; } } } @@ -1183,8 +1183,8 @@ const sqlb::ObjectPtr DBBrowserDB::getObjectByName(const QString& name) const { for(auto it=objMap.constBegin();it!=objMap.constEnd();++it) { - if((*it).getname() == name) - return it->object; + if((*it)->name() == name) + return *it; } return sqlb::ObjectPtr(nullptr); } @@ -1252,35 +1252,39 @@ void DBBrowserDB::updateSchema( ) else continue; - DBBrowserObject obj(val_name, val_sql, type, val_tblname); if(!val_sql.isEmpty()) { - obj.object = sqlb::Object::parseSQL(type, val_sql); + sqlb::ObjectPtr object = sqlb::Object::parseSQL(type, val_sql); if(val_temp == "1") - obj.object->setTemporary(true); + object->setTemporary(true); + + // If parsing wasn't successful set the object name manually, so that at least the name is going to be correct + if(!object->fullyParsed()) + object->setName(val_name); // For virtual tables and views query the column list using the SQLite pragma because for both we can't yet rely on our grammar parser - if((type == sqlb::Object::Types::Table && obj.object.dynamicCast()->isVirtual()) || type == sqlb::Object::Types::View) + if((type == sqlb::Object::Types::Table && object.dynamicCast()->isVirtual()) || type == sqlb::Object::Types::View) { auto columns = queryColumnInformation(val_name); if(type == sqlb::Object::Types::Table) { - sqlb::TablePtr tab = obj.object.dynamicCast(); + sqlb::TablePtr tab = object.dynamicCast(); foreach(const auto& column, columns) tab->addField(sqlb::FieldPtr(new sqlb::Field(column.first, column.second))); } else { - sqlb::ViewPtr view = obj.object.dynamicCast(); + sqlb::ViewPtr view = object.dynamicCast(); foreach(const auto& column, columns) view->addField(sqlb::FieldPtr(new sqlb::Field(column.first, column.second))); } } else if(type == sqlb::Object::Types::Trigger) { // For triggers set the name of the table the trigger operates on here because we don't have a parser for trigger statements yet. - sqlb::TriggerPtr trg = obj.object.dynamicCast(); + sqlb::TriggerPtr trg = object.dynamicCast(); trg->setTable(val_tblname); } + + objMap.insert(val_type, object); } - objMap.insert(val_type, obj); } sqlite3_finalize(vm); }else{ diff --git a/src/sqlitedb.h b/src/sqlitedb.h index 4e446252..e68c36f6 100644 --- a/src/sqlitedb.h +++ b/src/sqlitedb.h @@ -16,28 +16,7 @@ enum kLogMsg_App }; -typedef QMultiMap objectMap; - -class DBBrowserObject -{ -public: - DBBrowserObject() : name( "" ) { } - DBBrowserObject(const QString& wname, const QString& wsql, sqlb::Object::Types wtype, const QString& tbl_name) - : name( wname), sql( wsql ), type(wtype), table_name(tbl_name) - { } - - QString getname() const { return name; } - QString getsql() const { return sql; } - sqlb::Object::Types gettype() const { return type; } - QString getTableName() const { return table_name; } - - sqlb::ObjectPtr object; -private: - QString name; - QString sql; - sqlb::Object::Types type; - QString table_name; // The name of the table this object references, interesting for views, triggers and indices -}; +typedef QMultiMap objectMap; class DBBrowserDB : public QObject { diff --git a/src/sqlitetypes.cpp b/src/sqlitetypes.cpp index 27b7f48a..c6a2dd5b 100644 --- a/src/sqlitetypes.cpp +++ b/src/sqlitetypes.cpp @@ -91,6 +91,18 @@ ObjectPtr Object::parseSQL(Object::Types type, const QString& sSQL) return result; } +QString Object::typeToString(Types type) +{ + switch(type) + { + case Types::Table: return "table"; + case Types::Index: return "index"; + case Types::View: return "view"; + case Types::Trigger: return "trigger"; + } + return QString(); +} + bool ForeignKeyClause::isSet() const { return m_override.size() || m_table.size(); diff --git a/src/sqlitetypes.h b/src/sqlitetypes.h index ea0a047f..1b3c659c 100644 --- a/src/sqlitetypes.h +++ b/src/sqlitetypes.h @@ -20,7 +20,7 @@ class Trigger; class Field; class Constraint; class IndexedColumn; -struct FieldInfo; +class FieldInfo; typedef QSharedPointer ObjectPtr; typedef QSharedPointer TablePtr; typedef QSharedPointer IndexPtr; @@ -58,6 +58,7 @@ public: virtual ~Object() {} virtual Types type() const = 0; + static QString typeToString(Types type); void setName(const QString& name) { m_name = name; } const QString& name() const { return m_name; }