Added listing of triggers for selected table (not completely finished).
Used slightly different approach. This tab is fully build in source code using subclasses to adjust behaviour of widgets for reuse in the other tabs. Uses custom proxy model for filtering triggers for correct table and supporting out of the box sorting by QTableView. SqlCodePreview: QPlainTextEditor which sql highlighter and in readonly mode but allows copy.
This commit is contained in:
parent
446923ebaf
commit
2a75e86102
23 changed files with 697 additions and 67 deletions
|
|
@ -9,4 +9,4 @@ QMAKE_CXXFLAGS += /std:c++17
|
||||||
# depend on your compiler). Please consult the documentation of the
|
# depend on your compiler). Please consult the documentation of the
|
||||||
# deprecated API in order to know how to port your code away from it.
|
# deprecated API in order to know how to port your code away from it.
|
||||||
DEFINES += QT_DEPRECATED_WARNINGS
|
DEFINES += QT_DEPRECATED_WARNINGS
|
||||||
DEFINES += WIN32_LEAN_AND_MEAN NOMINMAX
|
DEFINES += WIN32_LEAN_AND_MEAN NOMINMAX _WIN32_WINNT=0x0501
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
enum CustomDataRole {
|
enum CustomDataRole {
|
||||||
CustomDataTypeRole = Qt::UserRole,
|
CustomDataTypeRole = Qt::UserRole,
|
||||||
|
// Add other enum before this one is we might want to have multiple hidden values
|
||||||
|
FirstHiddenValue,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CUSTOMDATAROLE_H
|
#endif // CUSTOMDATAROLE_H
|
||||||
|
|
|
||||||
27
pglab/CustomFilterSortModel.cpp
Normal file
27
pglab/CustomFilterSortModel.cpp
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
#include "CustomFilterSortModel.h"
|
||||||
|
|
||||||
|
CustomFilterSortModel::CustomFilterSortModel(QObject *parent)
|
||||||
|
: QSortFilterProxyModel(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CustomFilterSortModel::setOidFilterTable(Oid tbl_oid, int role)
|
||||||
|
{
|
||||||
|
m_filterOid = tbl_oid;
|
||||||
|
m_filterRole = role;
|
||||||
|
invalidateFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CustomFilterSortModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
||||||
|
{
|
||||||
|
bool result = true;
|
||||||
|
if (m_filterOid != InvalidOid) {
|
||||||
|
auto&& source = sourceModel();
|
||||||
|
QModelIndex index0 = source->index(sourceRow, 0, sourceParent);
|
||||||
|
auto&& v = source->data(index0, m_filterRole);
|
||||||
|
result = v.toUInt() == m_filterOid;
|
||||||
|
}
|
||||||
|
return result && QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
|
||||||
|
}
|
||||||
20
pglab/CustomFilterSortModel.h
Normal file
20
pglab/CustomFilterSortModel.h
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef TRIGGERFILTERSORTMODEL_H
|
||||||
|
#define TRIGGERFILTERSORTMODEL_H
|
||||||
|
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
#include "Pgsql_oids.h"
|
||||||
|
|
||||||
|
class CustomFilterSortModel : public QSortFilterProxyModel {
|
||||||
|
public:
|
||||||
|
CustomFilterSortModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
void setOidFilterTable(Oid tbl_oid, int role);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||||
|
private:
|
||||||
|
Oid m_filterOid = InvalidOid;
|
||||||
|
int m_filterRole = Qt::DisplayRole;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TRIGGERFILTERSORTMODEL_H
|
||||||
27
pglab/SqlCodePreview.cpp
Normal file
27
pglab/SqlCodePreview.cpp
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
#include "SqlCodePreview.h"
|
||||||
|
#include "UserConfiguration.h"
|
||||||
|
#include "SqlSyntaxHighlighter.h"
|
||||||
|
|
||||||
|
SqlCodePreview::SqlCodePreview(QWidget *parent)
|
||||||
|
: QPlainTextEdit(parent)
|
||||||
|
{
|
||||||
|
auto&& config = UserConfiguration::instance();
|
||||||
|
setFont(config->codeFont());
|
||||||
|
setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
|
||||||
|
m_highlighter = new SqlSyntaxHighlighter(document());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SqlCodePreview::setCatalog(std::shared_ptr<const PgDatabaseCatalog> catalog)
|
||||||
|
{
|
||||||
|
connect(catalog.get(), &PgDatabaseCatalog::refreshed, this, &SqlCodePreview::catalogRefresh);
|
||||||
|
catalogRefresh(catalog.get(), PgDatabaseCatalog::All);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SqlCodePreview::catalogRefresh(const PgDatabaseCatalog *catalog, PgDatabaseCatalog::RefreshFlags flags)
|
||||||
|
{
|
||||||
|
if (flags & PgDatabaseCatalog::Types) {
|
||||||
|
m_highlighter->setTypes(*catalog->types());
|
||||||
|
}
|
||||||
|
}
|
||||||
30
pglab/SqlCodePreview.h
Normal file
30
pglab/SqlCodePreview.h
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef SQLCODEPREVIEW_H
|
||||||
|
#define SQLCODEPREVIEW_H
|
||||||
|
|
||||||
|
#include "PgDatabaseCatalog.h"
|
||||||
|
#include <QPlainTextEdit>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class SqlSyntaxHighlighter;
|
||||||
|
class PgDatabaseCatalog;
|
||||||
|
|
||||||
|
class SqlCodePreview : public QPlainTextEdit {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
SqlCodePreview(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
/** Sets the database catalog that the syntax highlighter is to use.
|
||||||
|
*/
|
||||||
|
void setCatalog(std::shared_ptr<const PgDatabaseCatalog> catalog);
|
||||||
|
|
||||||
|
|
||||||
|
SqlSyntaxHighlighter *highlighter() { return m_highlighter; }
|
||||||
|
private:
|
||||||
|
SqlSyntaxHighlighter *m_highlighter = nullptr;
|
||||||
|
std::shared_ptr<const PgDatabaseCatalog> m_catalog;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void catalogRefresh(const PgDatabaseCatalog *catalog, PgDatabaseCatalog::RefreshFlags flags);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SQLCODEPREVIEW_H
|
||||||
|
|
@ -31,9 +31,10 @@ SqlSyntaxHighlighter::~SqlSyntaxHighlighter()
|
||||||
void SqlSyntaxHighlighter::setTypes(const PgTypeContainer& types)
|
void SqlSyntaxHighlighter::setTypes(const PgTypeContainer& types)
|
||||||
{
|
{
|
||||||
m_typeNames.clear();
|
m_typeNames.clear();
|
||||||
for (auto &e : types) {
|
for (auto&& e : types) {
|
||||||
m_typeNames.insert(e.name);
|
m_typeNames.insert(e.name);
|
||||||
}
|
}
|
||||||
|
rehighlight();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SqlSyntaxHighlighter::highlightBlock(const QString &text)
|
void SqlSyntaxHighlighter::highlightBlock(const QString &text)
|
||||||
|
|
|
||||||
|
|
@ -3,19 +3,21 @@
|
||||||
|
|
||||||
#include "PgAttribute.h"
|
#include "PgAttribute.h"
|
||||||
#include "PgDatabaseCatalog.h"
|
#include "PgDatabaseCatalog.h"
|
||||||
#include "TablesTableModel.h"
|
|
||||||
#include "ResultTableModelUtil.h"
|
|
||||||
#include "ColumnTableModel.h"
|
#include "ColumnTableModel.h"
|
||||||
#include "ConstraintModel.h"
|
#include "ConstraintModel.h"
|
||||||
#include "PropertyProxyModel.h"
|
|
||||||
#include "IconColumnDelegate.h"
|
#include "IconColumnDelegate.h"
|
||||||
#include "IndexModel.h"
|
#include "IndexModel.h"
|
||||||
#include "SqlFormattingUtils.h"
|
|
||||||
#include "SqlSyntaxHighlighter.h"
|
|
||||||
#include <QStringBuilder>
|
|
||||||
#include <boost/container/flat_set.hpp>
|
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include "PgLabItemDelegate.h"
|
#include "PgLabItemDelegate.h"
|
||||||
|
#include "PropertyProxyModel.h"
|
||||||
|
#include "ResultTableModelUtil.h"
|
||||||
|
#include "SqlFormattingUtils.h"
|
||||||
|
#include "SqlSyntaxHighlighter.h"
|
||||||
|
#include "TablesTableModel.h"
|
||||||
|
#include "TriggerPage.h"
|
||||||
|
#include "UserConfiguration.h"
|
||||||
|
#include <QStringBuilder>
|
||||||
|
#include <boost/container/flat_set.hpp>
|
||||||
|
|
||||||
TablesPage::TablesPage(MainWindow *parent)
|
TablesPage::TablesPage(MainWindow *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
|
|
@ -34,42 +36,43 @@ TablesPage::TablesPage(MainWindow *parent)
|
||||||
ui->tableListTable->setSortingEnabled(true);
|
ui->tableListTable->setSortingEnabled(true);
|
||||||
ui->tableListTable->sortByColumn(0, Qt::AscendingOrder);
|
ui->tableListTable->sortByColumn(0, Qt::AscendingOrder);
|
||||||
|
|
||||||
|
// Columns
|
||||||
SetTableViewDefault(ui->columnsTable);
|
SetTableViewDefault(ui->columnsTable);
|
||||||
m_columnsModel = new ColumnTableModel(this);
|
m_columnsModel = new ColumnTableModel(this);
|
||||||
ui->columnsTable->setModel(m_columnsModel);
|
ui->columnsTable->setModel(m_columnsModel);
|
||||||
|
|
||||||
|
// Constraints
|
||||||
SetTableViewDefault(ui->constraintsTable);
|
SetTableViewDefault(ui->constraintsTable);
|
||||||
m_constraintModel = new ConstraintModel(this);
|
m_constraintModel = new ConstraintModel(this);
|
||||||
ui->constraintsTable->setModel(m_constraintModel);
|
ui->constraintsTable->setModel(m_constraintModel);
|
||||||
ui->constraintsTable->setItemDelegateForColumn(0, icon_delegate);
|
ui->constraintsTable->setItemDelegateForColumn(0, icon_delegate);
|
||||||
|
|
||||||
QFont font;
|
// Indexes
|
||||||
font.setFamily("Source Code Pro");
|
|
||||||
font.setFixedPitch(true);
|
|
||||||
font.setPointSize(10);
|
|
||||||
ui->constraintSqlEdit->setFont(font);
|
|
||||||
ui->indexSqlEdit->setFont(font);
|
|
||||||
|
|
||||||
SetTableViewDefault(ui->indexesTable);
|
SetTableViewDefault(ui->indexesTable);
|
||||||
m_indexModel = new IndexModel(this);
|
m_indexModel = new IndexModel(this);
|
||||||
ui->indexesTable->setModel(m_indexModel);
|
ui->indexesTable->setModel(m_indexModel);
|
||||||
ui->indexesTable->setItemDelegate(pglab_delegate);
|
ui->indexesTable->setItemDelegate(pglab_delegate);
|
||||||
ui->indexesTable->setItemDelegateForColumn(0, icon_delegate);
|
ui->indexesTable->setItemDelegateForColumn(0, icon_delegate);
|
||||||
|
|
||||||
|
// Properties
|
||||||
PropertyProxyModel* property_model = new PropertyProxyModel(this);
|
PropertyProxyModel* property_model = new PropertyProxyModel(this);
|
||||||
property_model->setSourceModel(m_tablesModel);
|
property_model->setSourceModel(m_tablesModel);
|
||||||
SetTableViewDefault(ui->tablePropertiesTable);
|
SetTableViewDefault(ui->tablePropertiesTable);
|
||||||
ui->tablePropertiesTable->setModel(property_model);
|
ui->tablePropertiesTable->setModel(property_model);
|
||||||
ui->tablePropertiesTable->setItemDelegate(pglab_delegate);
|
ui->tablePropertiesTable->setItemDelegate(pglab_delegate);
|
||||||
|
|
||||||
|
|
||||||
|
// Set code editor fonts
|
||||||
|
QFont code_font = UserConfiguration::instance()->codeFont();
|
||||||
|
ui->constraintSqlEdit->setFont(code_font);
|
||||||
|
ui->indexSqlEdit->setFont(code_font);
|
||||||
|
|
||||||
|
|
||||||
|
// Connect signals
|
||||||
|
// ---------------
|
||||||
|
// Table selection
|
||||||
connect(ui->tableListTable->selectionModel(), &QItemSelectionModel::currentRowChanged,
|
connect(ui->tableListTable->selectionModel(), &QItemSelectionModel::currentRowChanged,
|
||||||
property_model, &PropertyProxyModel::setActiveRow);
|
property_model, &PropertyProxyModel::setActiveRow);
|
||||||
|
|
||||||
|
|
||||||
//m_namespaceFilterWidget = new NamespaceFilterWidget(this);
|
|
||||||
//ui->verticalLayoutTableView->addWidget(m_namespaceFilterWidget);
|
|
||||||
|
|
||||||
// Table selection
|
|
||||||
connect(ui->tableListTable->selectionModel(), &QItemSelectionModel::currentRowChanged, this,
|
connect(ui->tableListTable->selectionModel(), &QItemSelectionModel::currentRowChanged, this,
|
||||||
&TablesPage::tableListTable_currentRowChanged);
|
&TablesPage::tableListTable_currentRowChanged);
|
||||||
|
|
||||||
|
|
@ -88,6 +91,29 @@ TablesPage::TablesPage(MainWindow *parent)
|
||||||
connect(ui->indexesTable->model(), &QAbstractItemModel::modelReset, this,
|
connect(ui->indexesTable->model(), &QAbstractItemModel::modelReset, this,
|
||||||
&TablesPage::indexesTable_modelReset);
|
&TablesPage::indexesTable_modelReset);
|
||||||
|
|
||||||
|
// Non designer based code
|
||||||
|
m_triggerPage = new TriggerPage(this);
|
||||||
|
m_triggerTab = addDetailTab(m_triggerPage, tr("Triggers"));
|
||||||
|
retranslateUi(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TablesPage::retranslateUi(bool all)
|
||||||
|
{
|
||||||
|
if (all)
|
||||||
|
ui->retranslateUi(this);
|
||||||
|
|
||||||
|
ui->twDetails->setTabText(ui->twDetails->indexOf(m_triggerTab), QApplication::translate("TablesPage", "Triggers", nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QWidget* TablesPage::addDetailTab(QWidget *contents, QString caption)
|
||||||
|
{
|
||||||
|
auto tab = new QWidget();
|
||||||
|
auto verticalLayout = new QVBoxLayout(tab);
|
||||||
|
verticalLayout->addWidget(contents);
|
||||||
|
ui->twDetails->addTab(tab, caption);
|
||||||
|
return tab;
|
||||||
}
|
}
|
||||||
|
|
||||||
TablesPage::~TablesPage()
|
TablesPage::~TablesPage()
|
||||||
|
|
@ -100,6 +126,8 @@ void TablesPage::setCatalog(std::shared_ptr<PgDatabaseCatalog> cat)
|
||||||
m_catalog = cat;
|
m_catalog = cat;
|
||||||
m_tablesModel->setCatalog(cat);
|
m_tablesModel->setCatalog(cat);
|
||||||
ui->tableListTable->resizeColumnsToContents();
|
ui->tableListTable->resizeColumnsToContents();
|
||||||
|
|
||||||
|
m_triggerPage->setCatalog(cat);
|
||||||
// m_namespaceFilterWidget->init(cat->namespaces());
|
// m_namespaceFilterWidget->init(cat->namespaces());
|
||||||
|
|
||||||
auto highlighter = new SqlSyntaxHighlighter(ui->constraintSqlEdit->document());
|
auto highlighter = new SqlSyntaxHighlighter(ui->constraintSqlEdit->document());
|
||||||
|
|
@ -121,6 +149,8 @@ void TablesPage::tableListTable_currentRowChanged(const QModelIndex ¤t, co
|
||||||
|
|
||||||
m_indexModel->setData(m_catalog, table);
|
m_indexModel->setData(m_catalog, table);
|
||||||
ui->indexesTable->resizeColumnsToContents();
|
ui->indexesTable->resizeColumnsToContents();
|
||||||
|
|
||||||
|
m_triggerPage->setFilter(table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ class PgDatabaseCatalog;
|
||||||
class NamespaceFilterWidget;
|
class NamespaceFilterWidget;
|
||||||
class IndexModel;
|
class IndexModel;
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
|
class TriggerPage;
|
||||||
|
|
||||||
class TablesPage : public QWidget
|
class TablesPage : public QWidget
|
||||||
{
|
{
|
||||||
|
|
@ -29,6 +30,8 @@ public:
|
||||||
private:
|
private:
|
||||||
Ui::TablesPage *ui;
|
Ui::TablesPage *ui;
|
||||||
MainWindow *m_window;
|
MainWindow *m_window;
|
||||||
|
QWidget *m_triggerTab;
|
||||||
|
TriggerPage *m_triggerPage;
|
||||||
std::shared_ptr<PgDatabaseCatalog> m_catalog;
|
std::shared_ptr<PgDatabaseCatalog> m_catalog;
|
||||||
TablesTableModel* m_tablesModel = nullptr;
|
TablesTableModel* m_tablesModel = nullptr;
|
||||||
ColumnTableModel* m_columnsModel = nullptr;
|
ColumnTableModel* m_columnsModel = nullptr;
|
||||||
|
|
@ -36,6 +39,8 @@ private:
|
||||||
IndexModel* m_indexModel = nullptr;
|
IndexModel* m_indexModel = nullptr;
|
||||||
//NamespaceFilterWidget* m_namespaceFilterWidget;
|
//NamespaceFilterWidget* m_namespaceFilterWidget;
|
||||||
|
|
||||||
|
void retranslateUi(bool all = true);
|
||||||
|
QWidget* addDetailTab(QWidget *contents, QString caption);
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void tableListTable_currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
void tableListTable_currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QTabWidget" name="tabWidget">
|
<widget class="QTabWidget" name="twDetails">
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>3</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
|
|
@ -96,21 +96,6 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="statisticsTab">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Statistics</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="dependenciesTab">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Dependencies</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="dependentsTab">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Dependents</string>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
||||||
71
pglab/TriggerPage.cpp
Normal file
71
pglab/TriggerPage.cpp
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
#include "TriggerPage.h"
|
||||||
|
#include "ResultTableModelUtil.h"
|
||||||
|
#include "UserConfiguration.h"
|
||||||
|
#include <QTableView>
|
||||||
|
#include "PgClass.h"
|
||||||
|
#include "SqlCodePreview.h"
|
||||||
|
#include "TriggerTableModel.h"
|
||||||
|
#include "CustomFilterSortModel.h"
|
||||||
|
#include "CustomDataRole.h"
|
||||||
|
#include "PgLabItemDelegate.h"
|
||||||
|
#include <QStringBuilder>
|
||||||
|
#include <boost/container/flat_set.hpp>
|
||||||
|
|
||||||
|
TriggerPage::TriggerPage(QWidget *parent)
|
||||||
|
: QSplitter(Qt::Vertical, parent)
|
||||||
|
{
|
||||||
|
m_tableView = new QTableView(this);
|
||||||
|
m_definitionView = new SqlCodePreview(this);
|
||||||
|
addWidget(m_tableView);
|
||||||
|
addWidget(m_definitionView);
|
||||||
|
|
||||||
|
SetTableViewDefault(m_tableView);
|
||||||
|
|
||||||
|
QFont code_font = UserConfiguration::instance()->codeFont();
|
||||||
|
m_definitionView->setFont(code_font);
|
||||||
|
|
||||||
|
m_model = new TriggerTableModel(this);
|
||||||
|
m_sortFilterProxy = new CustomFilterSortModel(this);
|
||||||
|
m_sortFilterProxy->setSourceModel(m_model);
|
||||||
|
m_tableView->setModel(m_sortFilterProxy);
|
||||||
|
m_tableView->setSortingEnabled(true);
|
||||||
|
|
||||||
|
auto item_delegate = new PgLabItemDelegate(this);
|
||||||
|
m_tableView->setItemDelegate(item_delegate);
|
||||||
|
//auto icon_delegate = new IconColumnDelegate(this);
|
||||||
|
|
||||||
|
connect(m_tableView->selectionModel(), &QItemSelectionModel::selectionChanged,
|
||||||
|
this, &TriggerPage::tableView_selectionChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TriggerPage::setCatalog(std::shared_ptr<const PgDatabaseCatalog> cat)
|
||||||
|
{
|
||||||
|
m_catalog = cat;
|
||||||
|
m_definitionView->setCatalog(cat);
|
||||||
|
m_model->setCatalog(cat);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TriggerPage::setFilter(const PgClass &cls)
|
||||||
|
{
|
||||||
|
m_sortFilterProxy->setOidFilterTable(cls.oid, FirstHiddenValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TriggerPage::tableView_selectionChanged(const QItemSelection &/*selected*/, const QItemSelection &/*deselected*/)
|
||||||
|
{
|
||||||
|
auto&& indexes = m_tableView->selectionModel()->selectedIndexes();
|
||||||
|
boost::container::flat_set<int> rijen;
|
||||||
|
for (const auto &e : indexes)
|
||||||
|
rijen.insert(m_sortFilterProxy->mapToSource(e).row());
|
||||||
|
|
||||||
|
QString drops;
|
||||||
|
QString creates;
|
||||||
|
for (auto rij : rijen) {
|
||||||
|
auto&& t = m_model->trigger(rij);
|
||||||
|
drops += t.dropSql(*m_catalog) % "\n";
|
||||||
|
creates += t.createSql(*m_catalog) % "\n";
|
||||||
|
}
|
||||||
|
m_definitionView->setPlainText(drops % "\n" % creates);
|
||||||
|
}
|
||||||
41
pglab/TriggerPage.h
Normal file
41
pglab/TriggerPage.h
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
#ifndef TRIGGERPAGE_H
|
||||||
|
#define TRIGGERPAGE_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QSplitter>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class QSplitter;
|
||||||
|
class QTableView;
|
||||||
|
class SqlCodePreview;
|
||||||
|
class PgDatabaseCatalog;
|
||||||
|
class PgClass;
|
||||||
|
class TriggerTableModel;
|
||||||
|
class CustomFilterSortModel;
|
||||||
|
class QItemSelection;
|
||||||
|
|
||||||
|
class TriggerPage : public QSplitter
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit TriggerPage(QWidget *parent = nullptr);
|
||||||
|
// TriggerPage(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
void setCatalog(std::shared_ptr<const PgDatabaseCatalog> cat);
|
||||||
|
void setFilter(const PgClass &cls);
|
||||||
|
signals:
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTableView *m_tableView = nullptr;
|
||||||
|
SqlCodePreview *m_definitionView = nullptr;
|
||||||
|
TriggerTableModel *m_model = nullptr;
|
||||||
|
CustomFilterSortModel *m_sortFilterProxy = nullptr;
|
||||||
|
std::shared_ptr<const PgDatabaseCatalog> m_catalog;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void tableView_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TRIGGERPAGE_H
|
||||||
100
pglab/TriggerTableModel.cpp
Normal file
100
pglab/TriggerTableModel.cpp
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
#include "TriggerTableModel.h"
|
||||||
|
#include "PgDatabaseCatalog.h"
|
||||||
|
#include "PgTriggerContainer.h"
|
||||||
|
#include "CustomDataRole.h"
|
||||||
|
|
||||||
|
TriggerTableModel::TriggerTableModel(QObject *parent)
|
||||||
|
: QAbstractTableModel(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant TriggerTableModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
|
{
|
||||||
|
if (orientation == Qt::Horizontal) {
|
||||||
|
if (role == Qt::DisplayRole) {
|
||||||
|
switch (section) {
|
||||||
|
case NameCol: return tr("Name");
|
||||||
|
case EventsCol: return tr("Events");
|
||||||
|
case WhenCol: return tr("When");
|
||||||
|
case DeferrableCol: return tr("Df");
|
||||||
|
case InitiallyCol: return tr("ID");
|
||||||
|
case ForCol: return tr("For");
|
||||||
|
case CondCol: return tr("Cond.");
|
||||||
|
case ReferencingCol: return tr("Referencing");
|
||||||
|
case ProcedureCol: return tr("Function");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TriggerTableModel::setCatalog(std::shared_ptr<const PgDatabaseCatalog> cat)
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
|
||||||
|
m_catalog = cat;
|
||||||
|
m_triggers = cat->triggers();//->getTriggersForRelation(table);
|
||||||
|
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
int TriggerTableModel::rowCount(const QModelIndex &) const
|
||||||
|
{
|
||||||
|
return m_triggers ? static_cast<int>(m_triggers->count()) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int TriggerTableModel::columnCount(const QModelIndex &) const
|
||||||
|
{
|
||||||
|
return colCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QVariant TriggerTableModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (role == Qt::DisplayRole)
|
||||||
|
return getData(index);
|
||||||
|
else if (role == CustomDataTypeRole)
|
||||||
|
return getType(index.column());
|
||||||
|
else if (role == FirstHiddenValue) {
|
||||||
|
auto&& t = m_triggers->getByIdx(index.row());
|
||||||
|
return t.relid; //
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PgTrigger TriggerTableModel::trigger(int row) const
|
||||||
|
{
|
||||||
|
return m_triggers->getByIdx(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Oid TriggerTableModel::getType(int column) const
|
||||||
|
{
|
||||||
|
switch (column) {
|
||||||
|
case DeferrableCol:
|
||||||
|
case InitiallyCol:
|
||||||
|
return Pgsql::bool_oid;
|
||||||
|
}
|
||||||
|
return Pgsql::varchar_oid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QVariant TriggerTableModel::getData(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
auto&& t = m_triggers->getByIdx(index.row());
|
||||||
|
switch (index.column()) {
|
||||||
|
case NameCol: return t.name;
|
||||||
|
case EventsCol: return t.eventAbbr();
|
||||||
|
case WhenCol: return t.typeFireWhen();
|
||||||
|
case DeferrableCol: return t.deferrable;
|
||||||
|
case InitiallyCol: return t.initdeferred;
|
||||||
|
case ForCol: return t.forEach();
|
||||||
|
// case CondCol: return tr("Cond.");
|
||||||
|
// case ReferencingCol: return tr("Referencing");
|
||||||
|
// case ProcedureCol: return tr("Function");
|
||||||
|
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
75
pglab/TriggerTableModel.h
Normal file
75
pglab/TriggerTableModel.h
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
#ifndef TRIGGERTABLEMODEL_H
|
||||||
|
#define TRIGGERTABLEMODEL_H
|
||||||
|
|
||||||
|
#include <QAbstractTableModel>
|
||||||
|
#include "PgClass.h"
|
||||||
|
#include "PgTrigger.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class PgDatabaseCatalog;
|
||||||
|
class PgTriggerContainer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The TriggerTableModel class
|
||||||
|
*
|
||||||
|
* Hidden values:
|
||||||
|
* - FirstHiddenValue: oid of table the trigger belongs to
|
||||||
|
*/
|
||||||
|
class TriggerTableModel: public QAbstractTableModel {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
//using QAbstractTableModel::QAbstractTableModel;
|
||||||
|
|
||||||
|
enum e_Columns : int {
|
||||||
|
NameCol, //
|
||||||
|
EventsCol, // Insert, Update, Delete Truncate
|
||||||
|
WhenCol, // before after instead of
|
||||||
|
DeferrableCol,
|
||||||
|
InitiallyCol,
|
||||||
|
ForCol,
|
||||||
|
CondCol,
|
||||||
|
ReferencingCol,
|
||||||
|
ProcedureCol,
|
||||||
|
colCount
|
||||||
|
};
|
||||||
|
|
||||||
|
TriggerTableModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
// CREATE [ CONSTRAINT ] TRIGGER name { BEFORE | AFTER | INSTEAD OF } { event [ OR ... ] }
|
||||||
|
// ON table_name
|
||||||
|
// [ FROM referenced_table_name ]
|
||||||
|
// [ NOT DEFERRABLE | [ DEFERRABLE ] [ INITIALLY IMMEDIATE | INITIALLY DEFERRED ] ]
|
||||||
|
// [ REFERENCING { { OLD | NEW } TABLE [ AS ] transition_relation_name } [ ... ] ]
|
||||||
|
// [ FOR [ EACH ] { ROW | STATEMENT } ]
|
||||||
|
// [ WHEN ( condition ) ]
|
||||||
|
// EXECUTE PROCEDURE function_name ( arguments )
|
||||||
|
|
||||||
|
// where event can be one of:
|
||||||
|
|
||||||
|
// INSERT
|
||||||
|
// UPDATE [ OF column_name [, ... ] ]
|
||||||
|
// DELETE
|
||||||
|
// TRUNCATE
|
||||||
|
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||||
|
void setCatalog(std::shared_ptr<const PgDatabaseCatalog> cat);
|
||||||
|
|
||||||
|
|
||||||
|
// Basic functionality:
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
|
virtual QVariant data(const QModelIndex &index, int role) const override;
|
||||||
|
|
||||||
|
PgTrigger trigger(int row) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<const PgDatabaseCatalog> m_catalog;
|
||||||
|
std::shared_ptr<const PgTriggerContainer> m_triggers;
|
||||||
|
|
||||||
|
Oid getType(int column) const;
|
||||||
|
QVariant getData(const QModelIndex &index) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // TRIGGERTABLEMODEL_H
|
||||||
|
|
@ -78,7 +78,11 @@ SOURCES += main.cpp\
|
||||||
PlgPage.cpp \
|
PlgPage.cpp \
|
||||||
PropertyProxyModel.cpp \
|
PropertyProxyModel.cpp \
|
||||||
CodeGenerator.cpp \
|
CodeGenerator.cpp \
|
||||||
UserConfiguration.cpp
|
UserConfiguration.cpp \
|
||||||
|
TriggerTableModel.cpp \
|
||||||
|
TriggerPage.cpp \
|
||||||
|
SqlCodePreview.cpp \
|
||||||
|
CustomFilterSortModel.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
QueryResultModel.h \
|
QueryResultModel.h \
|
||||||
|
|
@ -104,7 +108,6 @@ HEADERS += \
|
||||||
ConnectionList.h \
|
ConnectionList.h \
|
||||||
ProcessStdioWidget.h \
|
ProcessStdioWidget.h \
|
||||||
GlobalIoService.h \
|
GlobalIoService.h \
|
||||||
CodeBuilderConfiguration.h \
|
|
||||||
ResultTableModelUtil.h \
|
ResultTableModelUtil.h \
|
||||||
BaseTableModel.h \
|
BaseTableModel.h \
|
||||||
QueryParamListController.h \
|
QueryParamListController.h \
|
||||||
|
|
@ -128,7 +131,11 @@ HEADERS += \
|
||||||
PropertyProxyModel.h \
|
PropertyProxyModel.h \
|
||||||
CustomDataRole.h \
|
CustomDataRole.h \
|
||||||
CodeGenerator.h \
|
CodeGenerator.h \
|
||||||
UserConfiguration.h
|
UserConfiguration.h \
|
||||||
|
TriggerTableModel.h \
|
||||||
|
TriggerPage.h \
|
||||||
|
SqlCodePreview.h \
|
||||||
|
CustomFilterSortModel.h
|
||||||
|
|
||||||
FORMS += mainwindow.ui \
|
FORMS += mainwindow.ui \
|
||||||
ConnectionManagerWindow.ui \
|
ConnectionManagerWindow.ui \
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include "PgIndexContainer.h"
|
#include "PgIndexContainer.h"
|
||||||
#include "PgNamespaceContainer.h"
|
#include "PgNamespaceContainer.h"
|
||||||
#include "PgTablespaceContainer.h"
|
#include "PgTablespaceContainer.h"
|
||||||
|
#include "PgTriggerContainer.h"
|
||||||
#include "PgTypeContainer.h"
|
#include "PgTypeContainer.h"
|
||||||
#include "Pgsql_Connection.h"
|
#include "Pgsql_Connection.h"
|
||||||
#include "Pgsql_oids.h"
|
#include "Pgsql_oids.h"
|
||||||
|
|
@ -134,7 +135,7 @@ void PgDatabaseCatalog::loadAll(Pgsql::Connection &conn,
|
||||||
std::function<bool(int, int)> progress_callback)
|
std::function<bool(int, int)> progress_callback)
|
||||||
{
|
{
|
||||||
loadInfo(conn);
|
loadInfo(conn);
|
||||||
const int count = 11;
|
const int count = 12;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
if (progress_callback && !progress_callback(++n, count))
|
if (progress_callback && !progress_callback(++n, count))
|
||||||
return;
|
return;
|
||||||
|
|
@ -163,10 +164,15 @@ void PgDatabaseCatalog::loadAll(Pgsql::Connection &conn,
|
||||||
if (progress_callback && !progress_callback(++n, count))
|
if (progress_callback && !progress_callback(++n, count))
|
||||||
return;
|
return;
|
||||||
load2(m_ams, conn);
|
load2(m_ams, conn);
|
||||||
|
if (progress_callback && !progress_callback(++n, count))
|
||||||
|
return;
|
||||||
|
load2(m_triggers, conn);
|
||||||
if (progress_callback && !progress_callback(++n, count))
|
if (progress_callback && !progress_callback(++n, count))
|
||||||
return;
|
return;
|
||||||
load2(m_types, conn);
|
load2(m_types, conn);
|
||||||
progress_callback && progress_callback(++n, count);
|
progress_callback && progress_callback(++n, count);
|
||||||
|
|
||||||
|
refreshed(this, All);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PgDatabaseCatalog::loadInfo(Pgsql::Connection &conn)
|
void PgDatabaseCatalog::loadInfo(Pgsql::Connection &conn)
|
||||||
|
|
@ -260,6 +266,11 @@ std::shared_ptr<const PgTablespaceContainer> PgDatabaseCatalog::tablespaces() co
|
||||||
return m_tablespaces;
|
return m_tablespaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<const PgTriggerContainer> PgDatabaseCatalog::triggers() const
|
||||||
|
{
|
||||||
|
return m_triggers;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<const PgTypeContainer> PgDatabaseCatalog::types() const
|
std::shared_ptr<const PgTypeContainer> PgDatabaseCatalog::types() const
|
||||||
{
|
{
|
||||||
return m_types;
|
return m_types;
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,10 @@
|
||||||
#define PGSQLDATABASECATALOGUE_H
|
#define PGSQLDATABASECATALOGUE_H
|
||||||
|
|
||||||
#include <libpq-fe.h>
|
#include <libpq-fe.h>
|
||||||
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <bitset>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
@ -22,9 +24,11 @@ class PgIndexContainer;
|
||||||
class PgNamespaceContainer;
|
class PgNamespaceContainer;
|
||||||
class PgAmContainer;
|
class PgAmContainer;
|
||||||
class PgTablespaceContainer;
|
class PgTablespaceContainer;
|
||||||
|
class PgTriggerContainer;
|
||||||
class PgTypeContainer;
|
class PgTypeContainer;
|
||||||
|
|
||||||
class PgDatabaseCatalog: public std::enable_shared_from_this<PgDatabaseCatalog> {
|
class PgDatabaseCatalog: public QObject, public std::enable_shared_from_this<PgDatabaseCatalog> {
|
||||||
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
PgDatabaseCatalog();
|
PgDatabaseCatalog();
|
||||||
PgDatabaseCatalog(const PgDatabaseCatalog&) = delete;
|
PgDatabaseCatalog(const PgDatabaseCatalog&) = delete;
|
||||||
|
|
@ -49,8 +53,27 @@ public:
|
||||||
std::shared_ptr<const PgAmContainer> ams() const;
|
std::shared_ptr<const PgAmContainer> ams() const;
|
||||||
std::shared_ptr<const PgNamespaceContainer> namespaces() const;
|
std::shared_ptr<const PgNamespaceContainer> namespaces() const;
|
||||||
std::shared_ptr<const PgTablespaceContainer> tablespaces() const;
|
std::shared_ptr<const PgTablespaceContainer> tablespaces() const;
|
||||||
|
std::shared_ptr<const PgTriggerContainer> triggers() const;
|
||||||
std::shared_ptr<const PgTypeContainer> types() const;
|
std::shared_ptr<const PgTypeContainer> types() const;
|
||||||
|
|
||||||
|
enum RefreshFlag {
|
||||||
|
Attributes = 1,
|
||||||
|
AuthIds = (1 << 1),
|
||||||
|
Classes = (1 << 2),
|
||||||
|
Constraints = (1 << 3),
|
||||||
|
Databases = (1 << 4),
|
||||||
|
Indexes = (1 << 5),
|
||||||
|
Ams = (1 << 6),
|
||||||
|
Namespaces = (1 << 7),
|
||||||
|
Tablespaces = (1 << 8),
|
||||||
|
Triggers = (1 << 9),
|
||||||
|
Types = (1 << 10),
|
||||||
|
All = 0xffffffff
|
||||||
|
};
|
||||||
|
using RefreshFlags = int;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void refreshed(const PgDatabaseCatalog *catalog, RefreshFlags flags);
|
||||||
private:
|
private:
|
||||||
QString m_serverVersionString;
|
QString m_serverVersionString;
|
||||||
int m_serverVersion;
|
int m_serverVersion;
|
||||||
|
|
@ -65,6 +88,7 @@ private:
|
||||||
std::shared_ptr<PgAmContainer> m_ams;
|
std::shared_ptr<PgAmContainer> m_ams;
|
||||||
std::shared_ptr<PgNamespaceContainer> m_namespaces;
|
std::shared_ptr<PgNamespaceContainer> m_namespaces;
|
||||||
std::shared_ptr<PgTablespaceContainer> m_tablespaces;
|
std::shared_ptr<PgTablespaceContainer> m_tablespaces;
|
||||||
|
std::shared_ptr<PgTriggerContainer> m_triggers;
|
||||||
std::shared_ptr<PgTypeContainer> m_types;
|
std::shared_ptr<PgTypeContainer> m_types;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,126 @@
|
||||||
#include "PgTrigger.h"
|
#include "PgTrigger.h"
|
||||||
|
#include "PgClassContainer.h"
|
||||||
|
#include "PgDatabaseCatalog.h"
|
||||||
|
#include "SqlFormattingUtils.h"
|
||||||
|
#include <QStringBuilder>
|
||||||
|
|
||||||
PgTrigger::PgTrigger()
|
|
||||||
|
QString PgTrigger::dropSql(const PgDatabaseCatalog &catalog)
|
||||||
{
|
{
|
||||||
|
if (m_dropSql.isEmpty()) {
|
||||||
|
auto&& fqtablename = genFQTableName(catalog, catalog.classes()->getByKey(relid));
|
||||||
|
m_dropSql = "DROP TRIGGER " % quoteIdent(name)
|
||||||
|
% " ON " % fqtablename % ";";
|
||||||
|
}
|
||||||
|
return m_dropSql;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString PgTrigger::createSql(const PgDatabaseCatalog &catalog)
|
||||||
|
{
|
||||||
|
if (m_createSql.isEmpty()) {
|
||||||
|
auto&& fqtablename = genFQTableName(catalog, catalog.classes()->getByKey(relid));
|
||||||
|
// if (GetLanguage() == wxT("edbspl"))
|
||||||
|
// sql += wxT("CREATE OR REPLACE TRIGGER ");
|
||||||
|
// else if (GetConnection()->BackendMinimumVersion(8, 2) && GetIsConstraint())
|
||||||
|
if (constraint != InvalidOid)
|
||||||
|
m_createSql += "CREATE CONSTRAINT TRIGGER ";
|
||||||
|
else
|
||||||
|
m_createSql += "CREATE TRIGGER ";
|
||||||
|
|
||||||
|
m_createSql += quoteIdent(name) + "\n "
|
||||||
|
+ typeFireWhen()
|
||||||
|
+ " " + event();
|
||||||
|
|
||||||
|
m_createSql += "\n ON " + fqtablename;
|
||||||
|
if (deferrable) {
|
||||||
|
m_createSql += "\n DEFERRABLE INITIALLY ";
|
||||||
|
if (initdeferred)
|
||||||
|
m_createSql += "DEFERRED";
|
||||||
|
else
|
||||||
|
m_createSql += "IMMEDIATE";
|
||||||
|
}
|
||||||
|
m_createSql += "\n FOR EACH " + forEach();
|
||||||
|
|
||||||
|
// if (GetConnection()->BackendMinimumVersion(8, 5)
|
||||||
|
// && !GetWhen().IsEmpty())
|
||||||
|
// sql += wxT("\n WHEN (") + GetWhen() + wxT(")");
|
||||||
|
|
||||||
|
// if (GetLanguage() == wxT("edbspl"))
|
||||||
|
// {
|
||||||
|
// sql += wxT("\n") + GetSource();
|
||||||
|
// if (!sql.Trim().EndsWith(wxT(";")))
|
||||||
|
// sql = sql.Trim() + wxT(";");
|
||||||
|
// sql += wxT("\n");
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// sql += wxT("\n EXECUTE PROCEDURE ") + triggerFunction->GetQuotedFullIdentifier()
|
||||||
|
// + wxT("(") + GetArguments() + wxT(")")
|
||||||
|
// + wxT(";\n");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (!GetEnabled())
|
||||||
|
// {
|
||||||
|
// sql += wxT("ALTER TABLE ") + GetQuotedFullTable() + wxT(" ")
|
||||||
|
// + wxT("DISABLE TRIGGER ") + GetQuotedIdentifier() + wxT(";\n");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (!GetComment().IsEmpty())
|
||||||
|
// sql += wxT("COMMENT ON TRIGGER ") + GetQuotedIdentifier() + wxT(" ON ") + GetQuotedFullTable()
|
||||||
|
// + wxT(" IS ") + qtDbString(GetComment()) + wxT(";\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_createSql;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString PgTrigger::typeFireWhen() const
|
||||||
|
{
|
||||||
|
QString when;
|
||||||
|
|
||||||
|
if (type & TriggerTypeBefore)
|
||||||
|
when = "BEFORE";
|
||||||
|
else if (type & TriggerTypeInstead)
|
||||||
|
when = "INSTEAD OF";
|
||||||
|
else
|
||||||
|
when = "AFTER";
|
||||||
|
return when;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString PgTrigger::eventAbbr() const
|
||||||
|
{
|
||||||
|
QString event;
|
||||||
|
if (type & TriggerTypeInsert)
|
||||||
|
event += "I";
|
||||||
|
if (type & TriggerTypeUpdate)
|
||||||
|
event += "U";
|
||||||
|
if (type & TriggerTypeDelete)
|
||||||
|
event += "D";
|
||||||
|
if (type & TriggerTypeTruncate)
|
||||||
|
event += "T";
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PgTrigger::event() const
|
||||||
|
{
|
||||||
|
QString event;
|
||||||
|
if (type & TriggerTypeInsert)
|
||||||
|
event += "INSERT ";
|
||||||
|
if (type & TriggerTypeUpdate)
|
||||||
|
event += "UPDATE ";
|
||||||
|
if (type & TriggerTypeDelete)
|
||||||
|
event += "DELETE ";
|
||||||
|
if (type & TriggerTypeTruncate)
|
||||||
|
event += "TRUNCATE";
|
||||||
|
return event.trimmed();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PgTrigger::forEach() const
|
||||||
|
{
|
||||||
|
if (isRow())
|
||||||
|
return "ROW";
|
||||||
|
else
|
||||||
|
return "STATEMENT";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,24 +5,57 @@
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <libpq-fe.h>
|
#include <libpq-fe.h>
|
||||||
|
|
||||||
|
class PgDatabaseCatalog;
|
||||||
|
|
||||||
class PgTrigger {
|
class PgTrigger {
|
||||||
public:
|
public:
|
||||||
Oid tgrelid;
|
Oid oid = InvalidOid;
|
||||||
QString tgname;
|
Oid relid;
|
||||||
Oid tgfoid;
|
QString name;
|
||||||
int16_t tgtype;
|
Oid foid;
|
||||||
char tgenabled;
|
int16_t type;
|
||||||
bool tgisinternal;
|
char enabled;
|
||||||
Oid tgconstrrelid;
|
bool isinternal;
|
||||||
Oid tgconstrindid;
|
Oid constrrelid;
|
||||||
Oid tgconstraint;
|
Oid constrindid;
|
||||||
bool tgdeferrable;
|
Oid constraint;
|
||||||
bool tginitdeferred;
|
bool deferrable;
|
||||||
int16_t tgnargs;
|
bool initdeferred;
|
||||||
QString tgattr;
|
int16_t nargs;
|
||||||
QString tgargs;
|
QString attr;
|
||||||
QString tgqual;
|
QString args;
|
||||||
|
QString qual;
|
||||||
|
|
||||||
|
bool operator==(Oid _oid) const { return oid == _oid; }
|
||||||
|
bool operator==(const QString &n) const { return name == n; }
|
||||||
|
bool operator<(Oid _oid) const { return oid < _oid; }
|
||||||
|
bool operator<(const PgTrigger &rhs) const { return oid < rhs.oid; }
|
||||||
|
|
||||||
|
static constexpr int TriggerTypeRow = (1 << 0);
|
||||||
|
static constexpr int TriggerTypeBefore = (1 << 1);
|
||||||
|
static constexpr int TriggerTypeInsert = (1 << 2);
|
||||||
|
static constexpr int TriggerTypeDelete = (1 << 3);
|
||||||
|
static constexpr int TriggerTypeUpdate = (1 << 4);
|
||||||
|
static constexpr int TriggerTypeTruncate = (1 << 5);
|
||||||
|
static constexpr int TriggerTypeInstead = (1 << 6);
|
||||||
|
|
||||||
|
QString dropSql(const PgDatabaseCatalog &catalog);
|
||||||
|
QString createSql(const PgDatabaseCatalog &catalog);
|
||||||
|
bool isRow() const { return type & TriggerTypeRow; }
|
||||||
|
bool isBefore() const { return type & TriggerTypeBefore; }
|
||||||
|
QString typeFireWhen() const;
|
||||||
|
QString eventAbbr() const;
|
||||||
|
QString event() const;
|
||||||
|
QString forEach() const;
|
||||||
|
|
||||||
|
//wxString pgTrigger::GetForEach() const
|
||||||
|
//{
|
||||||
|
// return (triggerType & TRIGGER_TYPE_ROW) ? wxT("ROW") : wxT("STATEMENT");
|
||||||
|
//}
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable QString m_dropSql; // cache
|
||||||
|
mutable QString m_createSql; // cache
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PGTRIGGER_H
|
#endif // PGTRIGGER_H
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
#include "PgTriggerContainer.h"
|
#include "PgTriggerContainer.h"
|
||||||
#include "Pgsql_Connection.h"
|
#include "Pgsql_Connection.h"
|
||||||
#include "Pgsql_Col.h"
|
#include "Pgsql_Col.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
std::string PgTriggerContainer::getLoadQuery() const
|
std::string PgTriggerContainer::getLoadQuery() const
|
||||||
{
|
{
|
||||||
return R"(SELECT *
|
return R"(SELECT oid, *
|
||||||
FROM pg_trigger
|
FROM pg_trigger
|
||||||
WHERE NOT tgisinternal)";
|
WHERE NOT tgisinternal)";
|
||||||
}
|
}
|
||||||
|
|
@ -14,8 +15,19 @@ PgTrigger PgTriggerContainer::loadElem(const Pgsql::Row &row)
|
||||||
{
|
{
|
||||||
Pgsql::Col col(row);
|
Pgsql::Col col(row);
|
||||||
PgTrigger v;
|
PgTrigger v;
|
||||||
col >> v.tgrelid >> v.tgname >> v.tgfoid >> v.tgtype >> v.tgenabled >> v.tgisinternal >> v.tgconstrrelid
|
col >> v.oid >> v.relid >> v.name >> v.foid >> v.type >> v.enabled >> v.isinternal >> v.constrrelid
|
||||||
>> v.tgconstrindid >> v.tgconstraint >> v.tgdeferrable >> v.tginitdeferred >> v.tgnargs >> v.tgattr
|
>> v.constrindid >> v.constraint >> v.deferrable >> v.initdeferred >> v.nargs >> v.attr
|
||||||
>> v.tgargs >> v.tgqual;
|
>> v.args >> v.qual;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<PgTrigger> PgTriggerContainer::getTriggersForRelation(Oid cls) const
|
||||||
|
{
|
||||||
|
std::vector<PgTrigger> result;
|
||||||
|
for (auto e : m_container)
|
||||||
|
if (e.relid == cls)
|
||||||
|
result.push_back(e);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "PgContainer.h"
|
#include "PgContainer.h"
|
||||||
#include "PgTrigger.h"
|
#include "PgTrigger.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace Pgsql {
|
namespace Pgsql {
|
||||||
|
|
||||||
|
|
@ -16,6 +17,8 @@ public:
|
||||||
using PgContainer<PgTrigger>::PgContainer;
|
using PgContainer<PgTrigger>::PgContainer;
|
||||||
|
|
||||||
virtual std::string getLoadQuery() const override;
|
virtual std::string getLoadQuery() const override;
|
||||||
|
|
||||||
|
std::vector<PgTrigger> getTriggersForRelation(Oid cls) const;
|
||||||
protected:
|
protected:
|
||||||
PgTrigger loadElem(const Pgsql::Row &row) override;
|
PgTrigger loadElem(const Pgsql::Row &row) override;
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ Value::operator int16_t() const
|
||||||
|
|
||||||
Value::operator int32_t() const
|
Value::operator int32_t() const
|
||||||
{
|
{
|
||||||
const int len = std::strlen(m_val);
|
const size_t len = std::strlen(m_val);
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
char *endptr = nullptr;
|
char *endptr = nullptr;
|
||||||
long result = std::strtol(m_val, &endptr, 10);
|
long result = std::strtol(m_val, &endptr, 10);
|
||||||
|
|
@ -100,6 +100,11 @@ Value::operator double() const
|
||||||
return std::stod(m_val);
|
return std::stod(m_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value::operator char() const
|
||||||
|
{
|
||||||
|
return m_val[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Value::isString() const
|
bool Value::isString() const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ namespace Pgsql {
|
||||||
operator bool() const;
|
operator bool() const;
|
||||||
operator float() const;
|
operator float() const;
|
||||||
operator double() const;
|
operator double() const;
|
||||||
|
operator char() const;
|
||||||
|
|
||||||
bool isString() const;
|
bool isString() const;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue