Created IndexModel for displaying the indexes on a table. Constraints can now show the SQL to drop and create them.

The keyword list is now directly based of the official keyword list from postgresql.
This commit is contained in:
eelke 2018-01-06 21:22:22 +01:00
parent b436814eb5
commit 97d4e2a1a4
24 changed files with 754 additions and 228 deletions

View file

@ -69,9 +69,9 @@ QVariant ConstraintModel::headerData(int section, Qt::Orientation orientation, i
case SupportingIndexCol:
c = tr("Supporting index");
break;
case DefinitionCol:
c = tr("Definition");
break;
// case DefinitionCol:
// c = tr("Definition");
// break;
}
v = c;
}
@ -158,11 +158,16 @@ QVariant ConstraintModel::getData(const QModelIndex &index) const
case SupportingIndexCol:
s = getIndexDisplayString(*m_catalog, t.indid);
break;
case DefinitionCol:
s = t.definition;
break;
// case DefinitionCol:
// s = t.definition;
// break;
}
v = s;
return v;
}
const PgConstraint& ConstraintModel::constraint(int row)
{
return m_constraints[row];
}

View file

@ -18,7 +18,7 @@ public:
NameCol, ///
NsCol, ///
SupportingIndexCol,
DefinitionCol,
// DefinitionCol,
colCount };
explicit ConstraintModel(QObject *parent = nullptr);
@ -35,6 +35,7 @@ public:
//QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
const PgConstraint& constraint(int row);
protected:
virtual Oid getType(int column) const override;

85
pglab/IndexModel.cpp Normal file
View file

@ -0,0 +1,85 @@
#include "IndexModel.h"
#include "PgDatabaseCatalog.h"
#include "PgIndexContainer.h"
#include "Pgsql_oids.h"
#include "ScopeGuard.h"
void IndexModel::setData(std::shared_ptr<const PgDatabaseCatalog> cat, const PgClass &table)
{
beginResetModel();
SCOPE_EXIT { endResetModel(); };
m_catalog = cat;
m_table = table;
m_indexes = cat->indexes()->getIndexesForTable(table.oid);
}
int IndexModel::rowCount(const QModelIndex &parent) const
{
return m_indexes.size();
}
int IndexModel::columnCount(const QModelIndex &parent) const
{
return colCount;
}
Oid IndexModel::getType(int column) const
{
return Pgsql::varchar_oid;
}
QVariant IndexModel::headerData(int section, Qt::Orientation orientation, int role) const
{
QVariant v;
if (orientation == Qt::Horizontal) {
if (role == Qt::DisplayRole) {
QString c;
switch (section) {
case TypeCol:
c = tr("Type");
break;
case NameCol:
c = tr("Name");
break;
case ColumnsCol:
c = tr("On");
break;
case ConditionCol:
c = tr("Condition");
break;
// case DefinitionCol:
// c = tr("Definition");
// break;
}
v = c;
}
}
return v;
}
QVariant IndexModel::getData(const QModelIndex &index) const
{
QVariant v;
int rij = index.row();
const auto &dat = m_indexes[rij];
switch (index.column()) {
case TypeCol:
if (dat.isprimary) v = ":/icons/constraints/primarykey.png";
else if (dat.isunique) v = ":/icons/constraints/unique.png";
break;
case NameCol:
v = getIndexDisplayString(*m_catalog, dat.indexrelid);
break;
case ColumnsCol:
break;
case ConditionCol:
break;
}
return v;
}

45
pglab/IndexModel.h Normal file
View file

@ -0,0 +1,45 @@
#ifndef INDEXMODEL_H
#define INDEXMODEL_H
#include "BaseTableModel.h"
#include "PgClass.h"
#include "PgIndex.h"
#include <memory>
#include <vector>
class PgDatabaseCatalog;
class IndexModel: public BaseTableModel {
Q_OBJECT
public:
using BaseTableModel::BaseTableModel;
enum e_Columns : int {
TypeCol, /// primary/unique/normal
NameCol, ///
ColumnsCol, ///
ConditionCol,
colCount };
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
void setData(std::shared_ptr<const PgDatabaseCatalog> cat, const PgClass &table);
// Basic functionality:
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
protected:
virtual Oid getType(int column) const override;
virtual QVariant getData(const QModelIndex &index) const override;
private:
std::shared_ptr<const PgDatabaseCatalog> m_catalog;
PgClass m_table;
using t_Indexes = std::vector<PgIndex>;
t_Indexes m_indexes;
};
#endif // INDEXMODEL_H

View file

@ -3,104 +3,6 @@
#include "PgTypeContainer.h"
#include "SqlLexer.h"
namespace {
t_SymbolSet g_Keywords = {
"a", "abort", "abs", "absent", "absolute", "access", "according", "action", "ada", "add",
"admin", "after", "aggregate", "all", "allocate", "also", "alter", "analyse", "analyze", "and",
"any", "are", "array", "array_agg", "array_max_cardinality", "as", "asc", "asensitive",
"assetion", "assignment", "asymmetric", "at", "atomic", "attribute", "attributes", "authorization", "avg",
"backward", "base64", "before", "begin", "begin_frame", "begin_partition", "bernoulli", "between", "bigint", "binary",
"bit", "bit_length", "blob", "blocked", "bom", "boolean", "both", "breadth", "buffer", "by",
"c", "cache", "call", "called", "cardinality", "cascade", "cascaded", "case", "cast",
"catalog", "catalog_name", "ceil", "ceiling", "chain", "char", "character", "characteristics",
"characters", "character_length", "character_set_catalog", "character_set_name", "character_set_schema",
"char_length", "check", "checkpoint", "class", "class_origin", "clob", "close", "cluster",
"coalesce", "cobol", "collate", "collation", "collation_catalog", "collation_name", "collation_schema",
"collect", "column", "columns", "column_name", "command_function", "command_function_code",
"comment", "comments", "commit", "committed", "concurrently", "condition", "condition_number",
"configuration", "conflict", "connect", "connection", "connection_name", "constraint", "constraints",
"constraint_catalog", "constraint_name", "constraint_schema", "constructor", "contains", "content",
"continue", "control", "conversion", "convert", "copy", "corr", "corresponding", "cost", "count",
"covar_pop", "covar_samp", "create", "cross", "csv", "cube", "cume_dist", "current", "current_catalog",
"current_date", "current_default_transform_group", "current_path", "current_role", "current_row",
"current_schema", "current_time", "current_timestamp", "current_transform_group_for_type",
"current_user", "cursor", "cursor_name", "cycle",
"data", "database", "datalink", "date", "datetime_interval_code", "datetime_interval_precision",
"day", "db", "deallocate", "dec", "decimal", "declare", "default", "defaults", "deferrable", "deferred",
"defined", "definer", "degree", "delete", "delimiter", "delimiters", "dense_rank", "depends", "depth",
"deref", "derived", "desc", "describe", "descriptor", "deterministic", "diagnostics", "dictionary",
"disable", "discard", "disconnect", "dispatch", "distinct", "dlnewcopy", "dlpreviouscopy", "dlurlcomplete",
"dlurlcompleteonly", "dlurlcompletewrite", "dlurlpatch", "dlurlpathonly", "dlurlpathwrite", "dlurlscheme",
"dlurlserver", "dlvalue", "do", "document", "domain", "double", "drop", "dynamic", "dynamic_function",
"dynamic_function_code",
"each", "element", "else", "empty", "enable", "encodign", "encrypted", "end", "end-exec", "end_frame",
"end_partition", "enforced", "enum", "equals", "escape", "event", "every", "except", "exception", "exclude",
"excluding", "exclusive", "exec", "execute", "exists", "exp", "explain", "expression", "extenstion",
"external", "extract", "false", "family", "fetch", "file", "filter", "final", "first", "first_value",
"flag", "float", "floor", "following", "for", "force", "foreign", "fortran", "forward", "found",
"frame_row", "free", "freeze", "from", "fs", "full", "function", "functions", "fusion",
"g", "general", "generated", "get", "global", "go" "goto", "grant", "granted", "greatest", "group",
"grouping", "groups", "handler", "having", "header", "hex", "hierarchy", "hold", "hour", "id", "identity",
"if", "ignore", "ilike", "immediate", "immediatly", "immutable", "implementation", "implicit", "import", "in",
"including", "increment", "indent", "index", "indexes", "indicator", "inherit", "inherits", "initially", "inline",
"inner", "inout", "input", "insensitive", "insert", "instance", "instantiable", "instead", "int", "integer",
"integrity", "intersect", "intersection", "interval", "into", "invoker", "is", "isnull", "isolation",
"join",
"k", "key", "key_member", "key_type",
"label", "lag", "language", "large", "last", "last_value", "lateral", "lead", "leading", "leakproof",
"least", "left", "length", "level", "library", "like", "like_regex", "limit", "link", "listen", "ln", "load", "local",
"localtime", "localtimestamp", "location", "locator", "lock", "locked", "logged", "lower",
"m", "map", "mapping", "match", "matched", "materialized", "max", "maxvalue", "max_cardinality", "member",
"merge", "message_length", "message_octet_length", "message_text", "method", "min", "minute", "minvalue",
"mod", "mode", "modifies", "module", "month", "more", "move", "multiset", "mumps",
"name", "namespace", "national", "natural", "nchar", "nclob", "nesting", "new", "next", "nfc", "nfd", "nfkc", "nkfd",
"nil", "no", "none", "normalize", "normalize", "not", "nothing", "notify", "notnull", "nowait", "nth_value", "ntile",
"null", "nullable", "nullif", "nulls", "number", "numeric",
"object", "occurrences_regex", "octets", "octet_length", "of", "off", "offset", "oids", "old", "on", "only", "open",
"operator", "option", "options", "or", "order", "ordering", "ordinality", "others", "out", "outer", "output", "over",
"overlaps", "overlay", "overriding", "owned", "owner",
"p", "pad", "parallel", "parameter", "parameter_mode", "parameter_name", "parameter_specific_catalog",
"parameter_specific_name", "parameter_specific_schema", "parser",
"partial", "partition", "pascal", "passing", "passthrough", "password", "path", "percent", "percentile_cont",
"percentile_disc", "percent_rank", "period", "permission", "placing", "plans", "pli", "policy", "portion",
"position", "position_regex", "power", "precedes", "preceding", "precision", "prepare", "prepared", "preserve",
"primary", "prior", "privileges", "procedural", "procedure", "program", "public",
"quote", "range", "rank", "read", "reads", "real", "reassign", "recheck", "recovery", "recursive", "ref",
"references", "referencing", "refresh", "regr_avgx", "regr_avgy", "regr_count", "regr_intercept", "regr_r2",
"regr_slope", "regr_sxx", "regr_sxy", "regr_syy", "reindex", "relative", "release", "rename", "repeatable",
"replace", "replica", "requiring", "reset", "respect", "restart", "restore", "restrict", "result", "return",
"returned_cardinality", "returned_length", "returned_octet_length", "returned_sqlstate", "returning", "returns",
"revoke", "right", "role", "rollback", "rollup", "routine", "routine_catalog", "routine_name", "routine_schema",
"row", "rows", "row_count", "row_number", "rule",
"savepoint", "scale", "schema", "schema_name", "scope", "scope_catalog", "scope_name", "scope_schema", "scroll",
"search", "second", "section", "security", "select", "selective", "self", "sensitive", "sequence", "sequences",
"serializable", "server", "server_name", "session", "session_user", "set", "setof", "sets", "share", "show",
"similar", "simple", "size", "skip", "smallint", "snapshot", "some", "source", "space", "specific", "specifictype",
"specific_name", "sql", "sqlcode", "sqlerror", "sqlexception", "sqlstate", "sqlwarning", "sqrt", "stable",
"standalone", "start", "state", "statement", "static", "statistics", "stddev_pop", "stddev_samp", "stdin", "stdout",
"storage", "strict", "strip", "structure", "style", "subclass_origin", "submultiset", "substring", "substring_regex",
"succeeds", "sum", "symmetric", "sysid", "system", "system_time", "system_user",
"t", "table", "tables", "tablesample", "tablespace", "table_name", "temp", "template", "temporary", "text", "then",
"ties", "time", "timestamp", "timezone_hour", "timezone_minute", "to", "token", "top_level_count", "trailing",
"transaction", "transaction_committed", "transaction_rolled_back", "transaction_active", "transform", "transforms",
"translate", "translate_regex", "translation", "treat", "trigger", "trigger_catalog", "trigger_name", "trigger_schema",
"trim", "trim_array", "true", "truncate", "trusted", "type", "types", "uescape", "unbounded", "uncommitted", "under",
"unencrypted", "union", "unique", "unknown", "unlink", "unlisten", "unlogged", "unnamed", "unnest", "until", "untyped",
"update", "upper", "uri", "usage", "user", "user_defined_type_catalog", "user_defined_type_code",
"user_defined_type_name", "user_defined_type_schema", "using",
"vacuum", "valid", "validate", "validator", "value", "values", "value_of", "varbinary", "varchar", "variadic",
"varying", "var_pop", "var_samp", "verbose", "version", "versioning", "view", "views", "volatile",
"when", "whenever", "where", "whitespace", "width_bucket", "window", "with", "within", "without", "work", "wrapper",
"write", "xml", "xmlagg", "xmlattributes", "xmlbinary", "xmlcast", "xmlcomment", "xmlconcat", "xmldeclaration",
"xmldocument", "xmlelement", "xmlexists", "xmlforest", "xmliterate", "xmlnamespaces", "xmlparse", "xmlpi",
"xmlquery", "xmlroot", "xmlschema", "xmlserialize", "xmltable", "xmltext", "xmlvalidate", "year", "yes", "zone"
};
//"bigint",
}
SqlSyntaxHighlighter::SqlSyntaxHighlighter(QTextDocument *parent)
@ -149,12 +51,14 @@ void SqlSyntaxHighlighter::highlightBlock(const QString &text)
case BasicTokenType::End: // End of input
case BasicTokenType::DollarQuote:
break;
case BasicTokenType::Symbol: // can be many things, keyword, object name, operator, ..
if (g_Keywords.count(s.toLower()) > 0) {
setFormat(startpos, length, m_keywordFormat);
}
else if (m_typeNames.count(s.toLower()) > 0) {
setFormat(startpos, length, m_typeFormat);
case BasicTokenType::Symbol: { // can be many things, keyword, object name, operator, ..
auto kw = getPgsqlKeyword(s);
if (kw != nullptr) {
setFormat(startpos, length, m_keywordFormat);
}
else if (m_typeNames.count(s.toLower()) > 0) {
setFormat(startpos, length, m_typeFormat);
}
}
break;
case BasicTokenType::OpenBlockComment:

View file

@ -3,11 +3,9 @@
#include <QSyntaxHighlighter>
#include <QTextFormat>
#include <unordered_set>
#include "PgKeywordList.h"
#include "util.h"
using t_SymbolSet = std::unordered_set<QString>;
class PgTypeContainer;
class SqlSyntaxHighlighter : public QSyntaxHighlighter

View file

@ -9,6 +9,11 @@
#include "ConstraintModel.h"
#include "NamespaceFilterWidget.h"
#include "IconColumnDelegate.h"
#include "IndexModel.h"
#include "SqlFormattingUtils.h"
#include "SqlSyntaxHighlighter.h"
#include <QStringBuilder>
#include <boost/container/flat_set.hpp>
TablesPage::TablesPage(QWidget *parent) :
QWidget(parent),
@ -27,16 +32,32 @@ TablesPage::TablesPage(QWidget *parent) :
SetTableViewDefault(ui->constraintsTable);
m_constraintModel = new ConstraintModel(this);
auto delegate = new IconColumnDelegate(this);
ui->constraintsTable->setModel(m_constraintModel);
ui->constraintsTable->setItemDelegateForColumn(0, delegate);
QFont font;
font.setFamily("Source Code Pro");
font.setFixedPitch(true);
font.setPointSize(10);
ui->constraintSqlEdit->setFont(font);
SetTableViewDefault(ui->indexesTable);
m_indexModel = new IndexModel(this);
ui->indexesTable->setModel(m_indexModel);
ui->indexesTable->setItemDelegateForColumn(0, delegate);
m_namespaceFilterWidget = new NamespaceFilterWidget(this);
ui->verticalLayoutTableView->addWidget(m_namespaceFilterWidget);
connect(ui->tableListTable->selectionModel(), &QItemSelectionModel::currentRowChanged, this,
&TablesPage::on_tableListTable_currentRowChanged);
&TablesPage::on_tableListTable_currentRowChanged);
// connect(ui->constraintsTable->selectionModel(), &QItemSelectionModel::currentRowChanged, this,
// &TablesPage::on_constraintsTable_currentRowChanged);
connect(ui->constraintsTable->selectionModel(), &QItemSelectionModel::selectionChanged, this,
&TablesPage::on_constraintsTable_selectionChanged);
}
@ -51,6 +72,10 @@ void TablesPage::setCatalog(std::shared_ptr<PgDatabaseCatalog> cat)
m_tablesModel->setCatalog(cat);
ui->tableListTable->resizeColumnsToContents();
m_namespaceFilterWidget->init(cat->namespaces());
auto highlighter = new SqlSyntaxHighlighter(ui->constraintSqlEdit->document());
highlighter->setTypes(*cat->types());
}
void TablesPage::on_tableListTable_currentRowChanged(const QModelIndex &current, const QModelIndex &previous)
@ -62,5 +87,37 @@ void TablesPage::on_tableListTable_currentRowChanged(const QModelIndex &current,
m_constraintModel->setData(m_catalog, table);
ui->constraintsTable->resizeColumnsToContents();
ui->constraintsTable->selectionModel()->reset();
m_indexModel->setData(m_catalog, table);
ui->indexesTable->resizeColumnsToContents();
}
}
void TablesPage::on_constraintsTable_currentRowChanged(const QModelIndex &current, const QModelIndex &previous)
{
if (current.row() != previous.row()) {
// QString drop_definition = m_constraintModel->dropDefinition(current.row());
// QString create_definition = m_constraintModel->createDefinition(current.row());
const PgConstraint& constraint = m_constraintModel->constraint(current.row());
QString drop = getDropConstraintDefinition(*m_catalog, constraint);
QString add = getConstraintDefinition(*m_catalog, constraint);
ui->constraintSqlEdit->setPlainText(drop % QString::fromUtf16(u"\n") % add);
}
}
void TablesPage::on_constraintsTable_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
const auto indexes = ui->constraintsTable->selectionModel()->selectedIndexes();
boost::container::flat_set<int> rijen;
for (const auto e : indexes) rijen.insert(e.row());
QString drops;
QString creates;
for (auto rij : rijen) {
const PgConstraint constraint = m_constraintModel->constraint(rij);
drops += getDropConstraintDefinition(*m_catalog, constraint) % "\n";
creates += getConstraintDefinition(*m_catalog, constraint) % "\n";
}
ui->constraintSqlEdit->setPlainText(drops % "\n" % creates);
}

View file

@ -3,6 +3,7 @@
#include <QWidget>
#include <memory>
#include <QItemSelection>
namespace Ui {
class TablesPage;
@ -13,6 +14,7 @@ class ColumnTableModel;
class ConstraintModel;
class PgDatabaseCatalog;
class NamespaceFilterWidget;
class IndexModel;
class TablesPage : public QWidget
{
@ -29,11 +31,14 @@ private:
TablesTableModel* m_tablesModel = nullptr;
ColumnTableModel* m_columnsModel = nullptr;
ConstraintModel* m_constraintModel = nullptr;
IndexModel* m_indexModel = nullptr;
NamespaceFilterWidget* m_namespaceFilterWidget;
private slots:
void on_tableListTable_currentRowChanged(const QModelIndex &current, const QModelIndex &previous);
void on_constraintsTable_currentRowChanged(const QModelIndex &current, const QModelIndex &previous);
void on_constraintsTable_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
};
#endif // TABLESPAGE_H

View file

@ -38,7 +38,7 @@
</widget>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>2</number>
<number>1</number>
</property>
<widget class="QWidget" name="columnsTab">
<attribute name="title">
@ -56,7 +56,17 @@
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QTableView" name="constraintsTable"/>
<widget class="QSplitter" name="splitter_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QTableView" name="constraintsTable">
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
<widget class="QPlainTextEdit" name="constraintSqlEdit"/>
</widget>
</item>
</layout>
</widget>

View file

@ -59,9 +59,9 @@ QVariant TablesTableModel::headerData(int section, Qt::Orientation orientation,
case OptionsCol:
v = tr("Options");
break;
case AclCol:
v = tr("ACL");
break;
// case AclCol:
// v = tr("ACL");
// break;
}
}
}
@ -88,7 +88,7 @@ Oid TablesTableModel::getType(int column) const
case NameCol:
case NamespaceCol:
case OptionsCol:
case AclCol:
// case AclCol:
default:
oid = Pgsql::VARCHAROID;
}
@ -115,9 +115,9 @@ QVariant TablesTableModel::getData(const QModelIndex &index) const
case OptionsCol:
v = t.options;
break;
case AclCol:
v = t.acl;
break;
// case AclCol:
// v = t.acl;
// break;
}
return v;

View file

@ -18,7 +18,7 @@ public:
OwnerCol,
TablespaceCol,
OptionsCol,
AclCol,
//AclCol,
colCount };
TablesTableModel(QObject *parent);

View file

@ -65,7 +65,8 @@ SOURCES += main.cpp\
NamespaceItemModel.cpp \
ApplicationWindow.cpp \
ConstraintModel.cpp \
IconColumnDelegate.cpp
IconColumnDelegate.cpp \
IndexModel.cpp
HEADERS += \
QueryResultModel.h \
@ -102,7 +103,8 @@ HEADERS += \
NamespaceItemModel.h \
ApplicationWindow.h \
ConstraintModel.h \
IconColumnDelegate.h
IconColumnDelegate.h \
IndexModel.h
FORMS += mainwindow.ui \
ConnectionManagerWindow.ui \