Resolve "Improve GENERATED support"
This commit is contained in:
parent
54e39ccdb3
commit
9277731c4e
13 changed files with 749 additions and 246 deletions
|
|
@ -12,6 +12,7 @@
|
|||
#include "ScopeGuard.h"
|
||||
#include "SqlFormattingUtils.h"
|
||||
#include <QBrush>
|
||||
#include <QStringBuilder>
|
||||
|
||||
namespace {
|
||||
|
||||
|
|
@ -142,18 +143,6 @@ int ColumnTableModel::columnCount(const QModelIndex &/*parent*/) const
|
|||
Oid ColumnTableModel::getType(int /*column*/) const
|
||||
{
|
||||
Oid oid = Pgsql::varchar_oid;
|
||||
// switch (column) {
|
||||
// case TypeCol:
|
||||
// case NameCol:
|
||||
// case NullCol:
|
||||
// case DefaultCol:
|
||||
// case CollationCol:
|
||||
// oid = VARCHAROID;
|
||||
// break;
|
||||
|
||||
// c = tr("Collation");
|
||||
// break;
|
||||
// }
|
||||
return oid;
|
||||
}
|
||||
|
||||
|
|
@ -191,7 +180,7 @@ QVariant ColumnTableModel::getData(const QModelIndex &index) const
|
|||
v = QString::fromStdU16String(t.notnull ? u"" : u"N");
|
||||
break;
|
||||
case DefaultCol:
|
||||
v = t.defaultValue;
|
||||
v = getDefaultString(t);
|
||||
break;
|
||||
case ForeignKeyCol:
|
||||
v = getFKey(t);
|
||||
|
|
@ -222,7 +211,36 @@ QString ColumnTableModel::getFKey(const PgAttribute &column) const
|
|||
result = getForeignKeyConstraintReferencesShort(*m_catalog, elem);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
QString ColumnTableModel::getDefaultString(const PgAttribute &column) const
|
||||
{
|
||||
if (column.identity != '\0') {
|
||||
QString sql = "GENERATED ";
|
||||
switch (column.identity) {
|
||||
case 'a':
|
||||
sql += "ALWAYS";
|
||||
break;
|
||||
case 'd':
|
||||
sql += "BY DEFAULT";
|
||||
break;
|
||||
}
|
||||
sql += " AS IDENTITY";
|
||||
// TODO sequence options might be missing
|
||||
return sql;
|
||||
}
|
||||
|
||||
if (column.generated != '\0')
|
||||
{
|
||||
return "GENERATED ALWAYS AS " % column.defaultValue % " STORED";
|
||||
}
|
||||
|
||||
|
||||
if (column.hasdef)
|
||||
return column.defaultValue;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void ColumnTableModel::refresh()
|
||||
|
|
|
|||
|
|
@ -55,8 +55,7 @@ protected:
|
|||
QMetaObject::Connection refreshConnection;
|
||||
|
||||
QString getFKey(const PgAttribute &column) const;
|
||||
|
||||
|
||||
QString getDefaultString(const PgAttribute &column) const;
|
||||
|
||||
private slots:
|
||||
/// Retrieves required data from catalog, called everytime it might have changed
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ QVariant CrudModel::data(const QModelIndex &index, int role) const
|
|||
if (index.column() < PreColumnCount)
|
||||
{
|
||||
if (role == Qt::DisplayRole || role == CustomSortRole)
|
||||
return index.row();
|
||||
return index.row() + 1;
|
||||
else if (role == CustomDataTypeRole)
|
||||
return Pgsql::int4_oid;
|
||||
|
||||
|
|
@ -231,6 +231,7 @@ void CrudModel::loadIntoModel(std::shared_ptr<Pgsql::Result> data)
|
|||
beginResetModel();
|
||||
m_pendingRowList.clear();
|
||||
m_roData = data;
|
||||
initializeColumnList();
|
||||
lastRowKey = data->rows() - 1;
|
||||
initRowMapping();
|
||||
appendNewRow();
|
||||
|
|
@ -276,7 +277,7 @@ Qt::ItemFlags CrudModel::flags(const QModelIndex &index) const
|
|||
if (index.column() < PreColumnCount)
|
||||
return flags;
|
||||
|
||||
if (m_primaryKey)
|
||||
if (m_primaryKey && !columnIsReadOnly(index.column()))
|
||||
flags |= Qt::ItemIsEditable;
|
||||
|
||||
return flags;
|
||||
|
|
@ -419,21 +420,16 @@ std::tuple<QString, Pgsql::Params> CrudModel::createInsertQuery(const PendingRow
|
|||
QTextStream q(&buffer);
|
||||
q << "INSERT INTO " << table_name << "(";
|
||||
|
||||
auto columns = m_database->catalog()->attributes()->getColumnsForRelation(m_table->oid());
|
||||
bool first = true;
|
||||
for (const auto& e : data)
|
||||
{
|
||||
int num = e.first + 1;
|
||||
auto find_res = std::find_if(columns.begin(), columns.end(),
|
||||
[num] (const auto &elem) -> bool { return num == elem.num; });
|
||||
if (find_res != columns.end())
|
||||
{
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
q << ",";
|
||||
q << find_res->name;
|
||||
}
|
||||
int num = e.first;
|
||||
auto&& column = columnList[num];
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
q << ",";
|
||||
q << column.name;
|
||||
}
|
||||
q << ") VALUES ($1";
|
||||
for (size_t p = 2; p <= data.size(); ++p)
|
||||
|
|
@ -515,6 +511,30 @@ bool CrudModel::IsLastRow(RowMappingVector::iterator mapping_iter) const
|
|||
return mapping_iter == --m_rowMapping.end();
|
||||
}
|
||||
|
||||
bool CrudModel::columnIsReadOnly(int column_index) const
|
||||
{
|
||||
if (m_roData == nullptr)
|
||||
return true;
|
||||
|
||||
auto&& column = columnList[column_index - PreColumnCount];
|
||||
return column.getIdentity() == PgAttribute::Identity::Always
|
||||
|| column.getGenerated() != PgAttribute::Generated::None;
|
||||
}
|
||||
|
||||
void CrudModel::initializeColumnList()
|
||||
{
|
||||
columnList.clear();
|
||||
columnList.reserve(m_roData->cols());
|
||||
auto columns = m_database->catalog()->attributes()->getColumnsForRelation(m_table->oid());
|
||||
for (int col = 0; col < m_roData->cols(); ++col)
|
||||
{
|
||||
int attnum = m_roData->ftableCol(col);
|
||||
auto find_result = std::find_if(columns.begin(), columns.end(), [attnum](const PgAttribute &att) { return att.num == attnum; });
|
||||
assert(find_result != columns.end());
|
||||
columnList.push_back(*find_result);
|
||||
}
|
||||
}
|
||||
|
||||
bool CrudModel::submit()
|
||||
{
|
||||
return savePendingChanges();
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include <vector>
|
||||
#include <optional>
|
||||
|
||||
class PgAttribute;
|
||||
class PgConstraint;
|
||||
class OpenDatabase;
|
||||
|
||||
|
|
@ -210,6 +211,7 @@ private:
|
|||
bool callLoadData = false;
|
||||
|
||||
std::shared_ptr<Pgsql::Result> m_roData;
|
||||
std::vector<PgAttribute> columnList; // list of columnMeta 1 to 1 with columns in m_roData.
|
||||
|
||||
PendingRowList m_pendingRowList;
|
||||
|
||||
|
|
@ -256,6 +258,8 @@ private:
|
|||
void RemoveRangeOfRowsFromModel(IntegerRange<int> row_range);
|
||||
|
||||
bool IsLastRow(RowMappingVector::iterator mapping_iter) const;
|
||||
bool columnIsReadOnly(int column_index) const;
|
||||
void initializeColumnList();
|
||||
private slots:
|
||||
|
||||
void loadIntoModel(std::shared_ptr<Pgsql::Result> data);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue