Generalise CrudModel to mapping-based editing

This commit is contained in:
eelke 2026-10-18 10:17:38 +02:00
parent 35eac713ff
commit bbe52c9db8
2 changed files with 174 additions and 91 deletions

View file

@ -5,8 +5,10 @@
#include "Pgsql_Connection.h"
#include "IntegerRange.h"
#include "ResultSourceMapping.h"
#include "catalog/PgClass.h"
#include "catalog/PgConstraint.h"
#include "catalog/PgAttribute.h"
#include <QAbstractTableModel>
#include <map>
#include <memory>
@ -26,6 +28,8 @@ public:
~CrudModel() override;
void setConfig(std::shared_ptr<OpenDatabase> db, const PgClass &table);
/// Show an arbitrary query result, cells are editable where the result maps them to a table with a primary key
void setResult(std::shared_ptr<OpenDatabase> db, std::shared_ptr<Pgsql::Result> result);
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
@ -50,7 +54,6 @@ public slots:
virtual void revert() override;
private:
using PKeyValues = std::vector<std::string>;
const int PreColumnCount = 1;
@ -76,6 +79,7 @@ private:
res += " NULLS FIRST";
else if (nulls == NullSorting::Last)
res += " NULLS LAST";
return res;
}
};
@ -205,10 +209,11 @@ private:
std::shared_ptr<OpenDatabase> m_database;
std::optional<PgClass> m_table;
std::optional<PgConstraint> m_primaryKey;
std::optional<ResultSourceMapping> m_mapping;
ASyncDBConnection m_dbConn;
bool callLoadData = false;
bool m_wholeTable = false; ///< true when showing a whole table (CRUD), false for an arbitrary query result
std::shared_ptr<Pgsql::Result> m_roData;
@ -218,7 +223,7 @@ private:
// identity allways or generated
};
std::vector<PgAttribute> columnList; // list of columnMeta 1 to 1 with columns in m_roData.
std::vector<std::optional<PgAttribute>> columnList; // attribute per column in m_roData, empty for expression columns
PendingRowList m_pendingRowList;
@ -238,29 +243,30 @@ private:
Oid getType(int column) const;
QString columnName(int col) const;
/// Get the PKey values from when the row was last restored or retrieved.
Pgsql::Params getPKeyParamsForRow(int row) const;
Pgsql::Params getPKeyParamsForRow(const RowMapping &row_mapping, Oid table_oid) const;
bool savePendingChanges();
std::tuple<QString, Pgsql::Params> createUpdateQuery(const Pgsql::Params &pkey_params, const PendingRow &pending_row);
std::tuple<QString, Pgsql::Params> createUpdateQuery(Oid table_oid, const PendingRow &pending_row, const RowMapping &row_mapping);
std::tuple<QString, Pgsql::Params> createInsertQuery(const PendingRow &pending_row);
std::tuple<QString, Pgsql::Params> createDeleteStatement(const PKeyValues &pkey_values);
QString createDeleteStatement() const;
std::tuple<bool, std::vector<Value>> saveRow(const PendingRow &pending_row);
std::tuple<bool, std::vector<Value>> saveRow(const PendingRow &pending_row, const RowMapping &row_mapping);
std::tuple<bool, std::vector<Value>> saveUpdate(const PendingRow &pending_row, const RowMapping &row_mapping);
void appendNewRow();
void appendNewRowInternal();
int lastRowKey = -1;
int allocNewRowKey() { return ++lastRowKey; }
/// Convert an attnum from the database catalog to the corresponding column in the model
///
/// \todo still assumes columns are in order, all being shown and no special column like oid shown.
int attNumToCol(int attnum) const { return attnum - 1; }
/// Name of the table with the given oid, quoted and schema qualified
QString tableName(Oid table_oid) const;
/// Result columns that are user columns (attnum > 0) of the given table, in result order
std::vector<int> resultColumnsOfTable(Oid table_oid) const;
/// Catalog name of the attribute behind a result column, falls back to the result column name
QString attributeName(int col) const;
void RemoveRangesOfRowsFromModel(const std::set<IntegerRange<int>> &row_ranges);
void RemoveRangeOfRowsFromModel(IntegerRange<int> row_range);