diff --git a/pglab/ColumnPage.cpp b/pglab/ColumnPage.cpp index 6fb0f47..a596825 100644 --- a/pglab/ColumnPage.cpp +++ b/pglab/ColumnPage.cpp @@ -30,7 +30,6 @@ ColumnPage::ColumnPage(QWidget *parent) m_tableView->setModel(m_sortFilterProxy); m_tableView->horizontalHeader()->setSortIndicator(ColumnTableModel::AttnumCol, Qt::AscendingOrder); m_tableView->setSortingEnabled(true); -// m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows); m_sortFilterProxy->sort(ColumnTableModel::AttnumCol, Qt::AscendingOrder); connect(m_tableView->selectionModel(), &QItemSelectionModel::selectionChanged, @@ -61,11 +60,13 @@ void ColumnPage::tableView_selectionChanged(const QItemSelection &/*selected*/, QString drops; QString addsql; auto iter = rijen.begin(); - if (iter != rijen.end()) { + if (iter != rijen.end()) + { auto && col = m_columnModel->column(*iter); drops = alterTable % "\n DROP COLUMN " % quoteIdent(col.name); addsql = alterTable % "\n ADD COLUMN " % col.columnDefinition(*m_catalog); - for (++iter; iter != rijen.end(); ++iter) { + 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); @@ -75,16 +76,17 @@ void ColumnPage::tableView_selectionChanged(const QItemSelection &/*selected*/, m_definitionView->setPlainText(drops % "\n\n" % addsql); completeSql += drops % "\n\n" % addsql % "\n\n"; } - for (auto r : rijen) { + for (auto r : rijen) + { auto && col = m_columnModel->column(r); auto cs = col.commentStatement(*m_catalog, m_Class.value()); - if (!cs.isEmpty()) { + if (!cs.isEmpty()) completeSql += cs % "\n"; - } } completeSql += "\n-- SQL to correct just the defaults\n"; - for (auto r : rijen) { + for (auto r : rijen) + { auto && col = m_columnModel->column(r); completeSql += alterTable % " ALTER COLUMN " % quoteIdent(col.name); if (col.hasdef) @@ -93,7 +95,8 @@ void ColumnPage::tableView_selectionChanged(const QItemSelection &/*selected*/, completeSql += " DROP DEFAULT;\n"; } completeSql += "\n-- SQL to correct NULLABLE\n"; - for (auto r : rijen) { + for (auto r : rijen) + { auto && col = m_columnModel->column(r); completeSql += alterTable % " ALTER COLUMN " % quoteIdent(col.name); if (col.notnull) diff --git a/pglab/crud/CrudModel.cpp b/pglab/crud/CrudModel.cpp index 5439e50..007e471 100644 --- a/pglab/crud/CrudModel.cpp +++ b/pglab/crud/CrudModel.cpp @@ -41,7 +41,6 @@ void CrudModel::setConfig(std::shared_ptr db, const PgClass &table m_database = db; m_table = table; m_primaryKey = db->catalog()->constraints()->getPrimaryForRelation(table.oid()); - //cat->attributes()->getColumnsForRelation() callLoadData = true; auto dbconfig = m_database->config(); m_dbConn.setupConnection(dbconfig); @@ -54,16 +53,17 @@ QVariant CrudModel::headerData(int section, Qt::Orientation orientation, int rol int column = section - PreColumnCount; QVariant r; - if (role == Qt::DisplayRole) { - if (orientation == Qt::Horizontal) { + if (role == Qt::DisplayRole) + { + if (orientation == Qt::Horizontal) + { QString s(m_roData->getColName(column)); s += "\n"; s += getTypeDisplayString(*m_database->catalog(), getType(column)); r = s; } - else { + else r = QString::number(column + 1); - } } return r; } @@ -86,25 +86,26 @@ Oid CrudModel::getType(int column) const CrudModel::Value CrudModel::getLatestData(int columnIndex, int rowIndex) const { - if (m_roData) { + if (m_roData) + { auto row_mapping = m_rowMapping[rowIndex]; - std::optional val; - if (row_mapping.pending) { + std::optional val; + if (row_mapping.pending) val = m_pendingRowList.getValue(columnIndex, row_mapping.rowKey); - } + if (!val.has_value()) - { val = getSavedData(row_mapping, columnIndex); - } + return val.value_or(Value()); - } + } return {}; } CrudModel::Value CrudModel::getSavedData(int columnIndex, int rowIndex) const { - if (m_roData) { + if (m_roData) + { auto row_mapping = m_rowMapping[rowIndex]; return getSavedData(row_mapping, columnIndex); } @@ -113,19 +114,14 @@ CrudModel::Value CrudModel::getSavedData(int columnIndex, int rowIndex) const CrudModel::Value CrudModel::getSavedData(const RowMapping &row_mapping, int columnIndex) const { - // First see if we have buffered editted values that still need saving std::optional val; - if (!val.has_value() && row_mapping.isModified()) { + if (!val.has_value() && row_mapping.isModified()) val = row_mapping.modifiedValue(columnIndex); - } - // If we did not have pending or modified data - if (!val.has_value() && row_mapping.rowKey < m_roData->rows()) { - // Then we are going to read the original data. - if (!m_roData->null(columnIndex, row_mapping.rowKey)) { + if (!val.has_value() && row_mapping.rowKey < m_roData->rows()) + if (!m_roData->null(columnIndex, row_mapping.rowKey)) val = std::string(m_roData->val(columnIndex, row_mapping.rowKey)); - } - } + return val.value_or(Value()); } @@ -191,7 +187,7 @@ QVariant CrudModel::data(const QModelIndex &index, int role) const else { if (typ == Pgsql::bool_oid) - return *value == "t"; //s = (s == "t") ? "TRUE" : "FALSE"; + return *value == "t"; else { QString s = QString::fromUtf8(value->c_str()); @@ -215,16 +211,17 @@ QVariant CrudModel::data(const QModelIndex &index, int role) const void CrudModel::loadData() { - QString table_name = m_table->fullyQualifiedQuotedObjectName(); // genFQTableName(*m_database->catalog(), *m_table); + QString table_name = m_table->fullyQualifiedQuotedObjectName(); std::string q = "SELECT * FROM "; q += std::string(table_name.toUtf8().data()); - m_dbConn.send(q, [this] (Expected> res, qint64) { - if (res.valid()) { + m_dbConn.send(q, [this] (Expected> res, qint64) + { + if (res.valid()) + { auto dbres = res.get(); - if (dbres && *dbres) { + if (dbres && *dbres) QMetaObject::invokeMethod(this, "loadIntoModel", Qt::QueuedConnection, Q_ARG(std::shared_ptr, dbres)); - } } }); } @@ -256,7 +253,8 @@ void CrudModel::connectionStateChanged(ASyncDBConnection::State state) case ASyncDBConnection::State::Connecting: break; case ASyncDBConnection::State::Connected: - if (callLoadData) { + if (callLoadData) + { callLoadData = false; loadData(); } @@ -277,9 +275,9 @@ Qt::ItemFlags CrudModel::flags(const QModelIndex &index) const if (index.column() < PreColumnCount) return flags; - if (m_primaryKey) { + if (m_primaryKey) flags |= Qt::ItemIsEditable; - } + return flags; } @@ -288,7 +286,8 @@ bool CrudModel::setData(const QModelIndex &index, const QVariant &value, int rol if (index.column() < PreColumnCount) return false; - if (role == Qt::EditRole) { + if (role == Qt::EditRole) + { int grid_row = index.row(); int col = index.column() - PreColumnCount; @@ -297,7 +296,8 @@ bool CrudModel::setData(const QModelIndex &index, const QVariant &value, int rol Value val; std::string s = value.toString().toUtf8().data(); - if (!s.empty()) { + if (!s.empty()) + { if (s == "''") s.clear(); val = s; @@ -315,13 +315,14 @@ std::tuple> CrudModel::saveRow(const Pending auto data = pending_row.data(); RowMapping& rowmapping = m_rowMapping[pending_row.row()]; - if (!data.empty()) { + if (!data.empty()) + { QString buffer; Pgsql::Params params; - if (rowmapping.isNew()){ + if (rowmapping.isNew()) std::tie(buffer, params) = createInsertQuery(pending_row); - } - else { + else + { Pgsql::Params pkey_params = getPKeyParamsForRow(pending_row.row()); std::tie(buffer, params) = createUpdateQuery(pkey_params, pending_row); } @@ -329,13 +330,15 @@ std::tuple> CrudModel::saveRow(const Pending Pgsql::Connection db_update_conn; auto dbconfig = m_database->config(); db_update_conn.connect(dbconfig.connectionString()); - try { + try + { auto result = db_update_conn.queryParam(buffer, params); - if (result && result.rows() == 1) { - + if (result && result.rows() == 1) + { std::vector values; auto row = *result.begin(); - for (auto v : row) { + for (auto v : row) + { if (v.null()) values.push_back(Value()); else @@ -345,7 +348,8 @@ std::tuple> CrudModel::saveRow(const Pending return { true, values }; } } - catch (const Pgsql::PgResultError &ex) { + catch (const Pgsql::PgResultError &ex) + { QMessageBox msgBox; msgBox.setText(ex.what()); msgBox.exec(); @@ -357,7 +361,8 @@ std::tuple> CrudModel::saveRow(const Pending Pgsql::Params CrudModel::getPKeyParamsForRow(int row) const { Pgsql::Params params; - for (auto attnum : m_primaryKey->key) { + for (auto attnum : m_primaryKey->key) + { const int col = attNumToCol(attnum); Oid t = getType(col); auto s = getSavedData(col, row); @@ -375,23 +380,23 @@ std::tuple CrudModel::createUpdateQuery(const Pgsql::Par { Pgsql::Params params; auto data = pending_row.data(); - QString table_name = m_table->fullyQualifiedQuotedObjectName(); //genFQTableName(*m_database->catalog(), *m_table); + QString table_name = m_table->fullyQualifiedQuotedObjectName(); QString buffer; QTextStream q(&buffer); q << "UPDATE " << table_name << " AS d\n SET "; int param = 0; - for (auto& e : data) { + for (auto& e : data) + { if (param > 0) q << ","; q << quoteIdent(columnName(e.first)) << "=$" << ++param; - - // Add value to paramlist params.add(e.second, getType(e.first)); } q << "\nWHERE "; int i = 0; - for (auto attnum : m_primaryKey->key) { + for (auto attnum : m_primaryKey->key) + { int col = attNumToCol(attnum); if (i > 0) q << " AND "; @@ -408,20 +413,24 @@ std::tuple CrudModel::createInsertQuery(const PendingRow { Pgsql::Params params; auto data = pending_row.data(); - QString table_name = m_table->fullyQualifiedQuotedObjectName(); // genFQTableName(*m_database->catalog(), *m_table); + QString table_name = m_table->fullyQualifiedQuotedObjectName(); QString buffer; 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) { + 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 << ","; + if (find_res != columns.end()) + { + if (first) + first = false; + else + q << ","; q << find_res->name; } } @@ -429,9 +438,9 @@ std::tuple CrudModel::createInsertQuery(const PendingRow for (size_t p = 2; p <= data.size(); ++p) q << ",$" << p; q << ") RETURNING *"; - for (auto& e : data) { + for (auto& e : data) params.add(e.second, getType(e.first)); - } + q.flush(); return { buffer, params }; } @@ -440,7 +449,8 @@ std::tuple CrudModel::createDeleteStatement(const PKeyVa { Pgsql::Params params; size_t i = 0; - for (auto attnum : m_primaryKey->key) { + for (auto attnum : m_primaryKey->key) + { const int col = attNumToCol(attnum); params.add(pkey_values[i].c_str(), getType(col)); ++i; @@ -458,7 +468,8 @@ QString CrudModel::createDeleteStatement() const q << "DELETE FROM " << table_name; q << "\nWHERE "; int i = 0; - for (auto attnum : m_primaryKey->key) { + for (auto attnum : m_primaryKey->key) + { const int col = attNumToCol(attnum); if (i > 0) q << " AND "; @@ -472,27 +483,27 @@ QString CrudModel::createDeleteStatement() const bool CrudModel::savePendingChanges() { - while (!m_pendingRowList.m_rows.empty()) { + while (!m_pendingRowList.m_rows.empty()) + { auto iter = m_pendingRowList.m_rows.begin(); auto [ok, modified_row] = saveRow(iter->second); - if (ok) { + if (ok) + { int rowKey = iter->first; m_pendingRowList.m_rows.erase(iter); auto iter = std::find_if(m_rowMapping.begin(), m_rowMapping.end(), [rowKey](const RowMapping &rhs) -> bool { return rhs.rowKey == rowKey; }); - if (iter != m_rowMapping.end()) { + if (iter != m_rowMapping.end()) + { iter->setModifiedRowData(modified_row); iter->pending = false; if (IsLastRow(iter)) - { appendNewRow(); - } } } - else { + else return false; - } } return true; @@ -523,8 +534,10 @@ void CrudModel::appendNewRow() std::tuple CrudModel::removeRows(const std::set> &row_ranges) { - if (row_ranges.empty()) return { true, "" }; - if (row_ranges.rbegin()->end() > static_cast(m_rowMapping.size())) return { false, "Range error" }; + if (row_ranges.empty()) + return { true, "" }; + if (row_ranges.rbegin()->end() > static_cast(m_rowMapping.size())) + return { false, "Range error" }; // When removing rows there is no direct mapping anymore between the rows in the grid // and the rows in m_roData @@ -534,7 +547,8 @@ std::tuple CrudModel::removeRows(const std::set // 1. Get PKEY and remove that row from table - try { + try + { Pgsql::Connection db_update_conn; auto dbconfig = m_database->config(); db_update_conn.connect(dbconfig.connectionString()); @@ -543,14 +557,14 @@ std::tuple CrudModel::removeRows(const std::set QString delete_statement = createDeleteStatement(); { auto tx = Pgsql::Transaction::startTransaction(db_update_conn); - for (auto range : row_ranges) { - for (int current_row = range.start(); current_row < range.end(); ++current_row) { + for (auto range : row_ranges) + { + for (int current_row = range.start(); current_row < range.end(); ++current_row) + { auto&& mapping = m_rowMapping[static_cast(current_row)]; auto params = getPKeyParamsForRow(mapping.rowKey); - if (!params.empty()) { - // Execute DELETE + if (!params.empty()) db_update_conn.queryParam(delete_statement, params); - } } } tx.commit(); @@ -559,16 +573,19 @@ std::tuple CrudModel::removeRows(const std::set // Then from model RemoveRangesOfRowsFromModel(row_ranges); return { true, "" }; - } catch (const Pgsql::PgResultError &error) { + } + catch (const Pgsql::PgResultError &error) + { return { false, QString::fromUtf8(error.details().messageDetail.c_str()) }; } } bool CrudModel::removeRows(int row, int count, const QModelIndex &) { - if (m_rowMapping.empty()) return false; + if (m_rowMapping.empty()) + return false; - IntegerRange range(row, count); + IntegerRange range(row, count); auto [res, message] = removeRows({ range }); return res; } @@ -576,7 +593,8 @@ bool CrudModel::removeRows(int row, int count, const QModelIndex &) void CrudModel::RemoveRangesOfRowsFromModel(const std::set> &row_ranges) { int rows_deleted = 0; - for (auto range : row_ranges) { + for (auto range : row_ranges) + { range.setStart(range.start() - rows_deleted); RemoveRangeOfRowsFromModel(range); rows_deleted += range.length(); diff --git a/pgsql/Pgsql_Result.cpp b/pgsql/Pgsql_Result.cpp index 32e7cc3..1658026 100644 --- a/pgsql/Pgsql_Result.cpp +++ b/pgsql/Pgsql_Result.cpp @@ -57,26 +57,6 @@ std::string Result::diagSqlState() ErrorDetails Result::diagDetails() { -// ErrorDetails r; -// r.state = PQresultErrorField(result, PG_DIAG_SQLSTATE); ///< PG_DIAG_SQLSTATE Error code as listed in https://www.postgresql.org/docs/9.5/static/errcodes-appendix.html -// r.severity = PQresultErrorField(result, PG_DIAG_SEVERITY); -// r.messagePrimary = PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY); -// r.messageDetail = PQresultErrorField(result, PG_DIAG_MESSAGE_DETAIL); -// r.messageHint = PQresultErrorField(result, PG_DIAG_MESSAGE_HINT); -// r.statementPosition = atoi(PQresultErrorField(result, PG_DIAG_STATEMENT_POSITION)); ///< First character is one, measured in characters not bytes! -// r.internalPosition = atoi(PQresultErrorField(result, PG_DIAG_INTERNAL_POSITION)); -// r.internalQuery = PQresultErrorField(result, PG_DIAG_INTERNAL_QUERY); -// r.context = PQresultErrorField(result, PG_DIAG_CONTEXT); -// r.schemaName = PQresultErrorField(result, PG_DIAG_SCHEMA_NAME); -// r.tableName = PQresultErrorField(result, PG_DIAG_TABLE_NAME); -// r.columnName = PQresultErrorField(result, PG_DIAG_COLUMN_NAME); -// r.datatypeName = PQresultErrorField(result, PG_DIAG_DATATYPE_NAME); -// r.constraintName = PQresultErrorField(result, PG_DIAG_CONSTRAINT_NAME); -// r.sourceFile = PQresultErrorField(result, PG_DIAG_SOURCE_FILE); -// r.sourceLine = PQresultErrorField(result, PG_DIAG_SOURCE_LINE); -// r.sourceFunction = PQresultErrorField(result, PG_DIAG_SOURCE_FUNCTION); - -// return r; return ErrorDetails::createErrorDetailsFromPGresult(result); }