New column page
Shows SQL for columns ALTER TABLE ... [ADD|DROP] COLUMN combines a selection of multiple columns into a single alter table. Show collation in list of columns. (order of columns isn't what is should be but that should maybe be fixed by a generic column selection and ordering mechanism that knows what the default sort should be)
This commit is contained in:
parent
73c4cf4790
commit
57217974f4
19 changed files with 345 additions and 55 deletions
83
pglab/ColumnPage.cpp
Normal file
83
pglab/ColumnPage.cpp
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
#include "ColumnPage.h"
|
||||||
|
#include "ResultTableModelUtil.h"
|
||||||
|
#include "UserConfiguration.h"
|
||||||
|
#include <QTableView>
|
||||||
|
#include "PgClass.h"
|
||||||
|
#include "SqlCodePreview.h"
|
||||||
|
#include "ColumnTableModel.h"
|
||||||
|
#include "CustomFilterSortModel.h"
|
||||||
|
#include "CustomDataRole.h"
|
||||||
|
#include "PgLabItemDelegate.h"
|
||||||
|
#include <QStringBuilder>
|
||||||
|
#include <boost/container/flat_set.hpp>
|
||||||
|
#include "SqlFormattingUtils.h"
|
||||||
|
|
||||||
|
ColumnPage::ColumnPage(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);
|
||||||
|
|
||||||
|
m_columnModel = new ColumnTableModel(this);
|
||||||
|
m_sortFilterProxy = new CustomFilterSortModel(this);
|
||||||
|
m_sortFilterProxy->setSourceModel(m_columnModel);
|
||||||
|
m_tableView->setModel(m_sortFilterProxy);
|
||||||
|
m_tableView->setSortingEnabled(true);
|
||||||
|
m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
|
||||||
|
// With this delegate the coloring of the datatype column doesn't work....
|
||||||
|
// auto item_delegate = new PgLabItemDelegate(this);
|
||||||
|
// m_tableView->setItemDelegate(item_delegate);
|
||||||
|
|
||||||
|
//auto icon_delegate = new IconColumnDelegate(this);
|
||||||
|
|
||||||
|
connect(m_tableView->selectionModel(), &QItemSelectionModel::selectionChanged,
|
||||||
|
this, &ColumnPage::tableView_selectionChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ColumnPage::setData(std::shared_ptr<const PgDatabaseCatalog> cat, const std::optional<PgClass> &cls)
|
||||||
|
{
|
||||||
|
m_catalog = cat;
|
||||||
|
m_definitionView->setCatalog(cat);
|
||||||
|
m_columnModel->setData(cat, cls);
|
||||||
|
m_Class = cls;
|
||||||
|
}
|
||||||
|
|
||||||
|
//void ColumnPage::setFilter(const std::optional<PgClass> &cls)
|
||||||
|
//{
|
||||||
|
// m_sortFilterProxy->setOidFilterTable(cls ? cls->oid() : InvalidOid, FirstHiddenValue);
|
||||||
|
//}
|
||||||
|
|
||||||
|
void ColumnPage::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 addsql;
|
||||||
|
auto iter = rijen.begin();
|
||||||
|
if (iter != rijen.end()) {
|
||||||
|
auto && col = m_columnModel->column(*iter);
|
||||||
|
drops = "ALTER TABLE " % m_Class->fullyQualifiedQuotedObjectName() % "\n DROP COLUMN " % quoteIdent(col.name);
|
||||||
|
addsql = "ALTER TABLE " % m_Class->fullyQualifiedQuotedObjectName() % "\n ADD COLUMN " % col.columnDefinition(*m_catalog);
|
||||||
|
for (++iter; iter != rijen.end(); ++iter) {
|
||||||
|
auto && col = m_columnModel->column(*iter);
|
||||||
|
drops += ",\n DROP COLUMN " % quoteIdent(col.name);
|
||||||
|
addsql += ",\n ADD COLUMN " % col.columnDefinition(*m_catalog);
|
||||||
|
}
|
||||||
|
drops += ";";
|
||||||
|
addsql += ";";
|
||||||
|
m_definitionView->setPlainText(drops % "\n\n" % addsql);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_definitionView->setPlainText("");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
42
pglab/ColumnPage.h
Normal file
42
pglab/ColumnPage.h
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
#ifndef COLUMNPAGE_H
|
||||||
|
#define COLUMNPAGE_H
|
||||||
|
|
||||||
|
#include "PgClass.h"
|
||||||
|
#include <QSplitter>
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
|
||||||
|
class QTableView;
|
||||||
|
class SqlCodePreview;
|
||||||
|
class PgDatabaseCatalog;
|
||||||
|
class ColumnTableModel;
|
||||||
|
class CustomFilterSortModel;
|
||||||
|
class QItemSelection;
|
||||||
|
class QAbstractItemModel;
|
||||||
|
|
||||||
|
class ColumnPage : public QSplitter
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit ColumnPage(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
void setData(std::shared_ptr<const PgDatabaseCatalog> cat, const std::optional<PgClass> &cls);
|
||||||
|
//void setFilter(const std::optional<PgClass> &cls);
|
||||||
|
signals:
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTableView *m_tableView = nullptr;
|
||||||
|
SqlCodePreview *m_definitionView = nullptr;
|
||||||
|
ColumnTableModel *m_columnModel = nullptr;
|
||||||
|
CustomFilterSortModel *m_sortFilterProxy = nullptr;
|
||||||
|
std::shared_ptr<const PgDatabaseCatalog> m_catalog;
|
||||||
|
std::optional<PgClass> m_Class;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void tableView_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COLUMNPAGE_H
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
#include "PgAttributeContainer.h"
|
#include "PgAttributeContainer.h"
|
||||||
#include "PgClassContainer.h"
|
#include "PgClassContainer.h"
|
||||||
#include "PgConstraintContainer.h"
|
#include "PgConstraintContainer.h"
|
||||||
|
#include "PgCollation.h"
|
||||||
|
#include "PgCollationContainer.h"
|
||||||
#include "PgType.h"
|
#include "PgType.h"
|
||||||
#include "PgTypeContainer.h"
|
#include "PgTypeContainer.h"
|
||||||
#include "PgIndexContainer.h"
|
#include "PgIndexContainer.h"
|
||||||
|
|
@ -197,31 +199,34 @@ QVariant ColumnTableModel::getData(const QModelIndex &index) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
QString s;
|
|
||||||
switch (col) {
|
switch (col) {
|
||||||
case AttnumCol:
|
case AttnumCol:
|
||||||
s = QString::asprintf("%d", (int) t.num);
|
//s = QString::asprintf("%d", (int) t.num);
|
||||||
break;
|
//break;
|
||||||
|
return static_cast<int>(t.num);
|
||||||
case NameCol:
|
case NameCol:
|
||||||
s = t.name;
|
v = t.name;
|
||||||
break;
|
break;
|
||||||
case TypeCol:
|
case TypeCol:
|
||||||
s = getTypeDisplayString(*m_catalog, t.typid, t.typmod);
|
v = getTypeDisplayString(*m_catalog, t.typid, t.typmod);
|
||||||
break;
|
break;
|
||||||
case NullCol:
|
case NullCol:
|
||||||
s = QString::fromStdU16String(t.notnull ? u"" : u"N");
|
v = QString::fromStdU16String(t.notnull ? u"" : u"N");
|
||||||
break;
|
break;
|
||||||
case DefaultCol:
|
case DefaultCol:
|
||||||
s = t.defaultValue;
|
v = t.defaultValue;
|
||||||
break;
|
break;
|
||||||
case ForeignKeyCol:
|
case ForeignKeyCol:
|
||||||
s = getFKey(t);
|
v = getFKey(t);
|
||||||
break;
|
break;
|
||||||
case CollationCol:
|
case CollationCol:
|
||||||
s = ""; //t.collation;
|
if (t.collation != InvalidOid) {
|
||||||
|
auto&& col = m_catalog->collations()->getByKey(t.collation);
|
||||||
|
if (col)
|
||||||
|
v = col->objectName();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
v = s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
|
|
@ -290,3 +295,8 @@ QVariant ColumnTableModel::data(const QModelIndex &index, int role) const
|
||||||
}
|
}
|
||||||
return BaseTableModel::data(index, role);
|
return BaseTableModel::data(index, role);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PgAttribute& ColumnTableModel::column(int row) const
|
||||||
|
{
|
||||||
|
return m_columns.at(static_cast<size_t>(row));
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#define COLUMNTABLEMODEL_H
|
#define COLUMNTABLEMODEL_H
|
||||||
|
|
||||||
#include "BaseTableModel.h"
|
#include "BaseTableModel.h"
|
||||||
|
#include "PgAttribute.h"
|
||||||
#include "PgClass.h"
|
#include "PgClass.h"
|
||||||
#include "PgIndex.h"
|
#include "PgIndex.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
@ -36,6 +37,7 @@ public:
|
||||||
int columnCount(const QModelIndex &parent) const override;
|
int columnCount(const QModelIndex &parent) const override;
|
||||||
|
|
||||||
QVariant data(const QModelIndex &index, int role) const override;
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
|
const PgAttribute& column(int row) const;
|
||||||
protected:
|
protected:
|
||||||
virtual Oid getType(int column) const override;
|
virtual Oid getType(int column) const override;
|
||||||
virtual QVariant getData(const QModelIndex &index) const override;
|
virtual QVariant getData(const QModelIndex &index) const override;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "PgAttribute.h"
|
#include "PgAttribute.h"
|
||||||
#include "PgDatabaseCatalog.h"
|
#include "PgDatabaseCatalog.h"
|
||||||
|
#include "ColumnPage.h"
|
||||||
#include "ColumnTableModel.h"
|
#include "ColumnTableModel.h"
|
||||||
#include "ConstraintModel.h"
|
#include "ConstraintModel.h"
|
||||||
#include "IconColumnDelegate.h"
|
#include "IconColumnDelegate.h"
|
||||||
|
|
@ -34,11 +35,6 @@ TablesPage::TablesPage(MainWindow *parent)
|
||||||
ui->tableListTable->sortByColumn(0, Qt::AscendingOrder);
|
ui->tableListTable->sortByColumn(0, Qt::AscendingOrder);
|
||||||
ui->tableListTable->setSelectionBehavior(QAbstractItemView::SelectRows);
|
ui->tableListTable->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
|
||||||
// Columns
|
|
||||||
SetTableViewDefault(ui->columnsTable);
|
|
||||||
m_columnsModel = new ColumnTableModel(this);
|
|
||||||
ui->columnsTable->setModel(m_columnsModel);
|
|
||||||
|
|
||||||
// Constraints
|
// Constraints
|
||||||
SetTableViewDefault(ui->constraintsTable);
|
SetTableViewDefault(ui->constraintsTable);
|
||||||
m_constraintModel = new ConstraintModel(this);
|
m_constraintModel = new ConstraintModel(this);
|
||||||
|
|
@ -82,16 +78,21 @@ TablesPage::TablesPage(MainWindow *parent)
|
||||||
&TablesPage::indexesTable_modelReset);
|
&TablesPage::indexesTable_modelReset);
|
||||||
|
|
||||||
// Non designer based code
|
// Non designer based code
|
||||||
|
// - Columns page
|
||||||
|
m_columnsPage = new ColumnPage(this);
|
||||||
|
ui->twDetails->insertTab(0, m_columnsPage, "");
|
||||||
|
|
||||||
// - Properties page
|
// - Properties page
|
||||||
m_propertiesPage = new PropertiesPage(this);
|
m_propertiesPage = new PropertiesPage(this);
|
||||||
m_propertiesPage->setSourceModel(m_tablesModel);
|
m_propertiesPage->setSourceModel(m_tablesModel);
|
||||||
m_propertiesTab = addDetailTab(m_propertiesPage);
|
ui->twDetails->addTab(m_propertiesPage, "");
|
||||||
|
|
||||||
connect(ui->tableListTable->selectionModel(), &QItemSelectionModel::currentRowChanged,
|
connect(ui->tableListTable->selectionModel(), &QItemSelectionModel::currentRowChanged,
|
||||||
m_propertiesPage, &PropertiesPage::setActiveRow);
|
m_propertiesPage, &PropertiesPage::setActiveRow);
|
||||||
|
|
||||||
// - Trigger page
|
// - Trigger page
|
||||||
m_triggerPage = new TriggerPage(this);
|
m_triggerPage = new TriggerPage(this);
|
||||||
m_triggerTab = addDetailTab(m_triggerPage);
|
ui->twDetails->addTab(m_triggerPage, "");
|
||||||
|
|
||||||
retranslateUi(false);
|
retranslateUi(false);
|
||||||
}
|
}
|
||||||
|
|
@ -102,18 +103,9 @@ void TablesPage::retranslateUi(bool all)
|
||||||
if (all)
|
if (all)
|
||||||
ui->retranslateUi(this);
|
ui->retranslateUi(this);
|
||||||
|
|
||||||
ui->twDetails->setTabText(ui->twDetails->indexOf(m_propertiesTab), QApplication::translate("TablesPage", "Properties", nullptr));
|
ui->twDetails->setTabText(ui->twDetails->indexOf(m_columnsPage), QApplication::translate("TablesPage", "Columns", nullptr));
|
||||||
ui->twDetails->setTabText(ui->twDetails->indexOf(m_triggerTab), QApplication::translate("TablesPage", "Triggers", nullptr));
|
ui->twDetails->setTabText(ui->twDetails->indexOf(m_propertiesPage), QApplication::translate("TablesPage", "Properties", nullptr));
|
||||||
}
|
ui->twDetails->setTabText(ui->twDetails->indexOf(m_triggerPage), QApplication::translate("TablesPage", "Triggers", nullptr));
|
||||||
|
|
||||||
|
|
||||||
QWidget* TablesPage::addDetailTab(QWidget *contents)
|
|
||||||
{
|
|
||||||
auto tab = new QWidget();
|
|
||||||
auto verticalLayout = new QVBoxLayout(tab);
|
|
||||||
verticalLayout->addWidget(contents);
|
|
||||||
ui->twDetails->addTab(tab, "");
|
|
||||||
return tab;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TablesPage::~TablesPage()
|
TablesPage::~TablesPage()
|
||||||
|
|
@ -163,8 +155,8 @@ void TablesPage::tableListTable_layoutChanged(const QList<QPersistentModelIndex>
|
||||||
|
|
||||||
void TablesPage::selectedTableChanged(const std::optional<PgClass> &table)
|
void TablesPage::selectedTableChanged(const std::optional<PgClass> &table)
|
||||||
{
|
{
|
||||||
m_columnsModel->setData(m_catalog, table);
|
m_columnsPage->setData(m_catalog, table);
|
||||||
ui->columnsTable->resizeColumnsToContents();
|
//ui->columnsTable->resizeColumnsToContents();
|
||||||
|
|
||||||
m_constraintModel->setData(m_catalog, table);
|
m_constraintModel->setData(m_catalog, table);
|
||||||
ui->constraintsTable->resizeColumnsToContents();
|
ui->constraintsTable->resizeColumnsToContents();
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ class TablesPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
class TablesTableModel;
|
class TablesTableModel;
|
||||||
|
class ColumnPage;
|
||||||
class ColumnTableModel;
|
class ColumnTableModel;
|
||||||
class ConstraintModel;
|
class ConstraintModel;
|
||||||
class PgDatabaseCatalog;
|
class PgDatabaseCatalog;
|
||||||
|
|
@ -33,9 +34,11 @@ public:
|
||||||
private:
|
private:
|
||||||
Ui::TablesPage *ui;
|
Ui::TablesPage *ui;
|
||||||
MainWindow *m_window;
|
MainWindow *m_window;
|
||||||
QWidget *m_propertiesTab;
|
// QWidget *m_columnsTab;
|
||||||
|
ColumnPage *m_columnsPage;
|
||||||
|
// QWidget *m_propertiesTab;
|
||||||
PropertiesPage *m_propertiesPage;
|
PropertiesPage *m_propertiesPage;
|
||||||
QWidget *m_triggerTab;
|
// QWidget *m_triggerTab;
|
||||||
TriggerPage *m_triggerPage;
|
TriggerPage *m_triggerPage;
|
||||||
std::shared_ptr<PgDatabaseCatalog> m_catalog;
|
std::shared_ptr<PgDatabaseCatalog> m_catalog;
|
||||||
TablesTableModel* m_tablesModel = nullptr;
|
TablesTableModel* m_tablesModel = nullptr;
|
||||||
|
|
@ -45,7 +48,7 @@ private:
|
||||||
//NamespaceFilterWidget* m_namespaceFilterWidget;
|
//NamespaceFilterWidget* m_namespaceFilterWidget;
|
||||||
|
|
||||||
void retranslateUi(bool all = true);
|
void retranslateUi(bool all = true);
|
||||||
QWidget* addDetailTab(QWidget *contents);
|
// QWidget* addDetailTab(QWidget *contents, bool infront = false);
|
||||||
|
|
||||||
void selectedTableChanged(const std::optional<PgClass> &table);
|
void selectedTableChanged(const std::optional<PgClass> &table);
|
||||||
private slots:
|
private slots:
|
||||||
|
|
|
||||||
|
|
@ -38,18 +38,8 @@
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QTabWidget" name="twDetails">
|
<widget class="QTabWidget" name="twDetails">
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>2</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="columnsTab">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Columns</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QTableView" name="columnsTable"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="tabConstraints">
|
<widget class="QWidget" name="tabConstraints">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string>Constraints</string>
|
<string>Constraints</string>
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,8 @@ PropertyProxyModel.cpp \
|
||||||
PropertiesPage.cpp \
|
PropertiesPage.cpp \
|
||||||
PasswordPromptDialog.cpp \
|
PasswordPromptDialog.cpp \
|
||||||
ProcTableModel.cpp \
|
ProcTableModel.cpp \
|
||||||
FunctionsPage.cpp
|
FunctionsPage.cpp \
|
||||||
|
ColumnPage.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
QueryResultModel.h \
|
QueryResultModel.h \
|
||||||
|
|
@ -136,7 +137,8 @@ CustomDataRole.h \
|
||||||
PropertiesPage.h \
|
PropertiesPage.h \
|
||||||
PasswordPromptDialog.h \
|
PasswordPromptDialog.h \
|
||||||
ProcTableModel.h \
|
ProcTableModel.h \
|
||||||
FunctionsPage.h
|
FunctionsPage.h \
|
||||||
|
ColumnPage.h
|
||||||
|
|
||||||
FORMS += mainwindow.ui \
|
FORMS += mainwindow.ui \
|
||||||
ConnectionManagerWindow.ui \
|
ConnectionManagerWindow.ui \
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,56 @@
|
||||||
#include "PgAttribute.h"
|
#include "PgAttribute.h"
|
||||||
|
#include "QStringBuilder"
|
||||||
|
#include "SqlFormattingUtils.h"
|
||||||
|
#include "PgClass.h"
|
||||||
|
#include "PgDatabaseCatalog.h"
|
||||||
|
#include "PgTypeContainer.h"
|
||||||
|
#include "PgCollation.h"
|
||||||
|
#include "PgCollationContainer.h"
|
||||||
|
|
||||||
|
QString PgAttribute::columnDefinition(const PgDatabaseCatalog &cat) const
|
||||||
|
{
|
||||||
|
// create: column_name data_type [ COLLATE collation ] [ column_constraint [ ... ]
|
||||||
|
// alter: column_name data_type [ COLLATE collation ] [ column_constraint [ ... ]
|
||||||
|
// constraints NULL/NOT NULL, DEFAULT, GENERATED other constraints will be ignored here a
|
||||||
|
auto&& type = cat.types()->getByKey(typid);
|
||||||
|
|
||||||
|
QString sql = quoteIdent(name) % " " % type->name;
|
||||||
|
if (collation != InvalidOid) {
|
||||||
|
auto&& col = cat.collations()->getByKey(collation);
|
||||||
|
QString oname = col->objectName();
|
||||||
|
if (oname != "default")
|
||||||
|
sql += " COLLATE " % quoteIdent(oname);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notnull)
|
||||||
|
sql += " NOT NULL";
|
||||||
|
|
||||||
|
if (hasdef)
|
||||||
|
sql += " DEFAULT " % defaultValue;
|
||||||
|
|
||||||
|
if (identity != ' ') {
|
||||||
|
sql += " GENERATED ";
|
||||||
|
if (identity == 'a') sql += "ALWAYS";
|
||||||
|
else if (identity == 'd') sql += "BY DEFAULT";
|
||||||
|
sql += " AS IDENTITY";
|
||||||
|
}
|
||||||
|
// TODO sequence options might be missing
|
||||||
|
|
||||||
|
return sql;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PgAttribute::alterTableAddColumn(const PgDatabaseCatalog &cat, const PgClass &table) const
|
||||||
|
{
|
||||||
|
QString sql = "ALTER TABLE " % table.fullyQualifiedQuotedObjectName()
|
||||||
|
% " ADD COLUMN " % columnDefinition(cat) % ";";
|
||||||
|
return sql;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PgAttribute::alterTableDropColumn(const PgDatabaseCatalog &cat, const PgClass &table) const
|
||||||
|
{
|
||||||
|
QString sql = "ALTER TABLE " % table.fullyQualifiedQuotedObjectName()
|
||||||
|
% " DROP COLUMN " % quoteIdent(name) % ";";
|
||||||
|
return sql;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,13 @@
|
||||||
#include <libpq-fe.h>
|
#include <libpq-fe.h>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
|
class PgClass;
|
||||||
|
class PgDatabaseCatalog;
|
||||||
|
|
||||||
class PgAttribute {
|
class PgAttribute {
|
||||||
public:
|
public:
|
||||||
using Key = std::tuple<Oid, int16_t>;
|
using Key = std::tuple<Oid, int16_t>;
|
||||||
|
|
||||||
// Oid oid = InvalidOid;
|
|
||||||
Oid relid = InvalidOid;
|
Oid relid = InvalidOid;
|
||||||
QString name;
|
QString name;
|
||||||
Oid typid = InvalidOid;
|
Oid typid = InvalidOid;
|
||||||
|
|
@ -20,6 +22,7 @@ public:
|
||||||
int32_t typmod = -1;
|
int32_t typmod = -1;
|
||||||
bool notnull = false;
|
bool notnull = false;
|
||||||
bool hasdef = false;
|
bool hasdef = false;
|
||||||
|
char identity = ' ';
|
||||||
bool isdropped = false;
|
bool isdropped = false;
|
||||||
Oid collation = InvalidOid;
|
Oid collation = InvalidOid;
|
||||||
QString acl;
|
QString acl;
|
||||||
|
|
@ -33,6 +36,10 @@ public:
|
||||||
bool operator<(Key _k) const { return relid < std::get<0>(_k) || (relid == std::get<0>(_k) && num < std::get<1>(_k)); }
|
bool operator<(Key _k) const { return relid < std::get<0>(_k) || (relid == std::get<0>(_k) && num < std::get<1>(_k)); }
|
||||||
bool operator<(const PgAttribute &rhs) const { return relid < rhs.relid || (relid == rhs.relid && num < rhs.num); }
|
bool operator<(const PgAttribute &rhs) const { return relid < rhs.relid || (relid == rhs.relid && num < rhs.num); }
|
||||||
|
|
||||||
|
/// Return the part of the SQL create statement that can be reused for both the CREATE TABLE and ALTER TABLE ADD COLUMN
|
||||||
|
QString columnDefinition(const PgDatabaseCatalog &cat) const;
|
||||||
|
QString alterTableAddColumn(const PgDatabaseCatalog &cat, const PgClass &table) const;
|
||||||
|
QString alterTableDropColumn(const PgDatabaseCatalog &cat, const PgClass &table) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PGATTRIBUTE_H
|
#endif // PGATTRIBUTE_H
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include "PgAttributeContainer.h"
|
#include "PgAttributeContainer.h"
|
||||||
#include "Pgsql_Col.h"
|
#include "Pgsql_Col.h"
|
||||||
|
#include "PgDatabaseCatalog.h"
|
||||||
|
|
||||||
//SELECT attname, pg_get_expr(adbin, adrelid) AS def_value
|
//SELECT attname, pg_get_expr(adbin, adrelid) AS def_value
|
||||||
//FROM pg_attribute
|
//FROM pg_attribute
|
||||||
|
|
@ -8,12 +9,16 @@
|
||||||
|
|
||||||
std::string PgAttributeContainer::getLoadQuery() const
|
std::string PgAttributeContainer::getLoadQuery() const
|
||||||
{
|
{
|
||||||
return R"__(
|
std::string q = R"__(
|
||||||
SELECT attrelid, attname, atttypid, attstattarget,
|
SELECT attrelid, attname, atttypid, attstattarget,
|
||||||
attnum, attndims, atttypmod, attnotnull, atthasdef, attisdropped,
|
attnum, attndims, atttypmod, attnotnull, atthasdef, attisdropped,
|
||||||
attcollation, attacl, attoptions, pg_get_expr(adbin, adrelid) AS def_value
|
attcollation, attacl, attoptions, pg_get_expr(adbin, adrelid) AS def_value)__";
|
||||||
FROM pg_catalog.pg_attribute
|
if (m_catalog.serverVersion() >= 100000)
|
||||||
LEFT JOIN pg_attrdef ON attrelid=adrelid AND attnum=adnum)__";
|
q += ", attidentity";
|
||||||
|
q +=
|
||||||
|
"\n FROM pg_catalog.pg_attribute \n"
|
||||||
|
" LEFT JOIN pg_attrdef ON attrelid=adrelid AND attnum=adnum";
|
||||||
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
PgAttribute PgAttributeContainer::loadElem(const Pgsql::Row &row)
|
PgAttribute PgAttributeContainer::loadElem(const Pgsql::Row &row)
|
||||||
|
|
@ -23,6 +28,9 @@ PgAttribute PgAttributeContainer::loadElem(const Pgsql::Row &row)
|
||||||
col >> v.relid >> v.name >> v.typid >> v.stattarget
|
col >> v.relid >> v.name >> v.typid >> v.stattarget
|
||||||
>> v.num >> v.ndims >> v.typmod >> v.notnull >> v.hasdef >> v.isdropped
|
>> v.num >> v.ndims >> v.typmod >> v.notnull >> v.hasdef >> v.isdropped
|
||||||
>> v.collation >> v.acl >> v.options >> v.defaultValue;
|
>> v.collation >> v.acl >> v.options >> v.defaultValue;
|
||||||
|
if (m_catalog.serverVersion() >= 100000)
|
||||||
|
col >> v.identity;
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
2
pglablib/PgCollation.cpp
Normal file
2
pglablib/PgCollation.cpp
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
#include "PgCollation.h"
|
||||||
|
|
||||||
25
pglablib/PgCollation.h
Normal file
25
pglablib/PgCollation.h
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef PGCOLLATION_H
|
||||||
|
#define PGCOLLATION_H
|
||||||
|
|
||||||
|
#include "PgNamespaceObject.h"
|
||||||
|
#include "PgOwnedObject.h"
|
||||||
|
#include <QString>
|
||||||
|
#include <libpq-fe.h>
|
||||||
|
#include "Pgsql_Value.h"
|
||||||
|
//#include <vector>
|
||||||
|
|
||||||
|
class PgCollation: public PgNamespaceObject, public PgOwnedObject {
|
||||||
|
public:
|
||||||
|
using PgNamespaceObject::PgNamespaceObject;
|
||||||
|
|
||||||
|
// Oid oid; // oid
|
||||||
|
// QString collname; // name
|
||||||
|
// Oid collnamespace; // oid
|
||||||
|
// Oid collowner; // oid
|
||||||
|
int32_t collencoding; // integer
|
||||||
|
QString collcollate; // name
|
||||||
|
QString collctype; // name
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PGCOLLATION_H
|
||||||
28
pglablib/PgCollationContainer.cpp
Normal file
28
pglablib/PgCollationContainer.cpp
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#include "PgCollationContainer.h"
|
||||||
|
#include "Pgsql_Connection.h"
|
||||||
|
#include "Pgsql_Col.h"
|
||||||
|
#include "PgDatabaseCatalog.h"
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
std::string PgCollationContainer::getLoadQuery() const
|
||||||
|
{
|
||||||
|
return "SELECT oid, collname, collnamespace, collowner, collencoding, \n"
|
||||||
|
" collcollate, collctype \n"
|
||||||
|
"FROM pg_collation";
|
||||||
|
}
|
||||||
|
|
||||||
|
PgCollation PgCollationContainer::loadElem(const Pgsql::Row &row)
|
||||||
|
{
|
||||||
|
Pgsql::Col col(row);
|
||||||
|
Oid class_oid = col.nextValue();
|
||||||
|
QString name = col.nextValue();
|
||||||
|
Oid ns_oid = col.nextValue();
|
||||||
|
|
||||||
|
PgCollation v(m_catalog, class_oid, name, ns_oid);
|
||||||
|
Oid owner ;
|
||||||
|
|
||||||
|
col >> owner >> v.collencoding >> v.collcollate >> v.collctype;
|
||||||
|
v.setOwnerOid(m_catalog, owner);
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
25
pglablib/PgCollationContainer.h
Normal file
25
pglablib/PgCollationContainer.h
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef PGCOLLATIONCONTAINER_H
|
||||||
|
#define PGCOLLATIONCONTAINER_H
|
||||||
|
|
||||||
|
#include "PgContainer.h"
|
||||||
|
#include "PgCollation.h"
|
||||||
|
|
||||||
|
namespace Pgsql {
|
||||||
|
|
||||||
|
class Result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class PgCollationContainer: public PgContainer<PgCollation> {
|
||||||
|
public:
|
||||||
|
using PgContainer<PgCollation>::PgContainer;
|
||||||
|
|
||||||
|
virtual std::string getLoadQuery() const override;
|
||||||
|
protected:
|
||||||
|
PgCollation loadElem(const Pgsql::Row &row) override;
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // PGCOLLATIONCONTAINER_H
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
#include "PgTriggerContainer.h"
|
#include "PgTriggerContainer.h"
|
||||||
#include "PgTypeContainer.h"
|
#include "PgTypeContainer.h"
|
||||||
#include "PgProcContainer.h"
|
#include "PgProcContainer.h"
|
||||||
|
#include "PgCollationContainer.h"
|
||||||
#include "Pgsql_Connection.h"
|
#include "Pgsql_Connection.h"
|
||||||
#include "Pgsql_oids.h"
|
#include "Pgsql_oids.h"
|
||||||
|
|
||||||
|
|
@ -160,6 +161,9 @@ void PgDatabaseCatalog::loadAll(Pgsql::Connection &conn,
|
||||||
|
|
||||||
// Load database objects
|
// Load database objects
|
||||||
load2(m_namespaces, conn);
|
load2(m_namespaces, conn);
|
||||||
|
if (progress_callback && !progress_callback(++n, count))
|
||||||
|
return;
|
||||||
|
load2(m_collations, conn);
|
||||||
if (progress_callback && !progress_callback(++n, count))
|
if (progress_callback && !progress_callback(++n, count))
|
||||||
return;
|
return;
|
||||||
load2(m_classes, conn); // needs namespaces
|
load2(m_classes, conn); // needs namespaces
|
||||||
|
|
@ -294,3 +298,8 @@ std::shared_ptr<const PgProcContainer> PgDatabaseCatalog::procs() const
|
||||||
{
|
{
|
||||||
return m_procs;
|
return m_procs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<const PgCollationContainer> PgDatabaseCatalog::collations() const
|
||||||
|
{
|
||||||
|
return m_collations;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ class PgTablespaceContainer;
|
||||||
class PgTriggerContainer;
|
class PgTriggerContainer;
|
||||||
class PgTypeContainer;
|
class PgTypeContainer;
|
||||||
class PgProcContainer;
|
class PgProcContainer;
|
||||||
|
class PgCollationContainer;
|
||||||
|
|
||||||
|
|
||||||
class PgDatabaseCatalog: public QObject, public std::enable_shared_from_this<PgDatabaseCatalog> {
|
class PgDatabaseCatalog: public QObject, public std::enable_shared_from_this<PgDatabaseCatalog> {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
@ -57,6 +59,7 @@ public:
|
||||||
std::shared_ptr<const PgTriggerContainer> triggers() const;
|
std::shared_ptr<const PgTriggerContainer> triggers() const;
|
||||||
std::shared_ptr<const PgTypeContainer> types() const;
|
std::shared_ptr<const PgTypeContainer> types() const;
|
||||||
std::shared_ptr<const PgProcContainer> procs() const;
|
std::shared_ptr<const PgProcContainer> procs() const;
|
||||||
|
std::shared_ptr<const PgCollationContainer> collations() const;
|
||||||
|
|
||||||
enum RefreshFlag {
|
enum RefreshFlag {
|
||||||
Attributes = 1,
|
Attributes = 1,
|
||||||
|
|
@ -94,6 +97,7 @@ private:
|
||||||
std::shared_ptr<PgTriggerContainer> m_triggers;
|
std::shared_ptr<PgTriggerContainer> m_triggers;
|
||||||
std::shared_ptr<PgTypeContainer> m_types;
|
std::shared_ptr<PgTypeContainer> m_types;
|
||||||
std::shared_ptr<PgProcContainer> m_procs;
|
std::shared_ptr<PgProcContainer> m_procs;
|
||||||
|
std::shared_ptr<PgCollationContainer> m_collations;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void load2(std::shared_ptr<T> &ptr, Pgsql::Connection &conn)
|
void load2(std::shared_ptr<T> &ptr, Pgsql::Connection &conn)
|
||||||
|
|
|
||||||
|
|
@ -195,7 +195,7 @@ bool identNeedsQuotes(QString ident)
|
||||||
if (ident[0].isDigit())
|
if (ident[0].isDigit())
|
||||||
return true;
|
return true;
|
||||||
for (auto c : ident)
|
for (auto c : ident)
|
||||||
if ((c < 'a' || c > 'z') && c != '_')
|
if ((c < 'a' || c > 'z') && c != '_' && (c < '0' || c > '9'))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
auto kw = getPgsqlKeyword(ident);
|
auto kw = getPgsqlKeyword(ident);
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,9 @@ codebuilder/StructureTemplate.cpp \
|
||||||
PgDatabaseObject.cpp \
|
PgDatabaseObject.cpp \
|
||||||
PgServerObject.cpp \
|
PgServerObject.cpp \
|
||||||
PgOwnedObject.cpp \
|
PgOwnedObject.cpp \
|
||||||
PgNamespaceObject.cpp
|
PgNamespaceObject.cpp \
|
||||||
|
PgCollation.cpp \
|
||||||
|
PgCollationContainer.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
Pglablib.h \
|
Pglablib.h \
|
||||||
|
|
@ -125,7 +127,9 @@ codebuilder/StructureTemplate.h \
|
||||||
PgDatabaseObject.h \
|
PgDatabaseObject.h \
|
||||||
PgServerObject.h \
|
PgServerObject.h \
|
||||||
PgOwnedObject.h \
|
PgOwnedObject.h \
|
||||||
PgNamespaceObject.h
|
PgNamespaceObject.h \
|
||||||
|
PgCollation.h \
|
||||||
|
PgCollationContainer.h
|
||||||
|
|
||||||
unix {
|
unix {
|
||||||
target.path = /usr/lib
|
target.path = /usr/lib
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue