|
1 | 1 | #include "sqldatasourcequerymodel.h" |
2 | 2 | #include "common/utils_sql.h" |
| 3 | +#include "services/notifymanager.h" |
3 | 4 |
|
4 | 5 | SqlDataSourceQueryModel::SqlDataSourceQueryModel(QObject *parent) : |
5 | 6 | SqlQueryModel(parent) |
@@ -88,6 +89,132 @@ QString SqlDataSourceQueryModel::regExpFilterValueProcessor(const QString& value |
88 | 89 | return pattern.arg(escapeString(value)); |
89 | 90 | } |
90 | 91 |
|
| 92 | +bool SqlDataSourceQueryModel::commitAddedRow(const QList<SqlQueryItem*>& itemsInRow, QList<CommitSuccessfulHandler>& successfulCommitHandlers) |
| 93 | +{ |
| 94 | + if (columns.size() != itemsInRow.size()) |
| 95 | + { |
| 96 | + qCritical() << "Tried to SqlDataSourceQueryModel::commitAddedRow() with number of columns in argument different than model resolved for the table."; |
| 97 | + return false; |
| 98 | + } |
| 99 | + |
| 100 | + // Check that just in case: |
| 101 | + if (columns.size() == 0) |
| 102 | + { |
| 103 | + qCritical() << "Tried to SqlDataSourceQueryModel::commitAddedRow() with number of resolved columns in the table equal to 0!"; |
| 104 | + return false; |
| 105 | + } |
| 106 | + |
| 107 | + // Prepare column placeholders and their values |
| 108 | + QStringList colNameList; |
| 109 | + QStringList bindParams; |
| 110 | + QList<QVariant> args; |
| 111 | + prepareColumnsAndBindParams(itemsInRow, colNameList, bindParams, args); |
| 112 | + |
| 113 | + // Prepare SQL query |
| 114 | + QString sql = getInsertSql(colNameList, bindParams); |
| 115 | + |
| 116 | + // Execute query |
| 117 | + SqlQueryPtr result = db->exec(sql, args); |
| 118 | + |
| 119 | + // Handle error |
| 120 | + if (result->isError()) |
| 121 | + { |
| 122 | + QString errMsg = tr("Error while committing new row: %1").arg(result->getErrorText()); |
| 123 | + for (SqlQueryItem* item : itemsInRow) |
| 124 | + item->setCommittingError(true, errMsg); |
| 125 | + |
| 126 | + notifyError(errMsg); |
| 127 | + return false; |
| 128 | + } |
| 129 | + |
| 130 | + // Take values from RETURNING clause to get actual values (because of DEFAULT, AUTOINCR). |
| 131 | + QList<SqlResultsRowPtr> rows = result->getAll(); |
| 132 | + if (rows.size() != 1) |
| 133 | + { |
| 134 | + qCritical() << "After inserting new row to the table, number of rows returned from the query != 1. This should not happen. Number:" << rows.size(); |
| 135 | + return false; |
| 136 | + } |
| 137 | + |
| 138 | + QList<QVariant> rowValues = rows.first()->valueList(); |
| 139 | + if (columns.size() != rowValues.size()) |
| 140 | + { |
| 141 | + qCritical() << "Tried to SqlDataSourceQueryModel::commitAddedRow() with number of columns in argument different than RETURNING values from the INSERT."; |
| 142 | + return false; |
| 143 | + } |
| 144 | + |
| 145 | + return commitAddedRowPostprocess(itemsInRow, rowValues, result->getInsertRowId(), successfulCommitHandlers); |
| 146 | +} |
| 147 | + |
| 148 | +bool SqlDataSourceQueryModel::commitDeletedRow(const QList<SqlQueryItem*>& itemsInRow, QList<CommitSuccessfulHandler>& successfulCommitHandlers) |
| 149 | +{ |
| 150 | + if (itemsInRow.size() == 0) |
| 151 | + { |
| 152 | + qCritical() << "Tried to SqlDataSourceQueryModel::commitDeletedRow() with number of items equal to 0!"; |
| 153 | + return false; |
| 154 | + } |
| 155 | + |
| 156 | + RowId rowId = getRowIdForRow(itemsInRow); |
| 157 | + if (rowId.isEmpty()) |
| 158 | + return false; |
| 159 | + |
| 160 | + CommitDeleteQueryBuilder queryBuilder; |
| 161 | + queryBuilder.setTableOrView(getTableOrView()); |
| 162 | + queryBuilder.setRowId(rowId); |
| 163 | + |
| 164 | + QString sql = queryBuilder.build(); |
| 165 | + QHash<QString, QVariant> args = queryBuilder.getQueryArgs(); |
| 166 | + |
| 167 | + SqlQueryPtr result = db->exec(sql, args); |
| 168 | + if (result->isError()) |
| 169 | + { |
| 170 | + QString errMsg = tr("Error while deleting row from %1: %2").arg(getTableOrView(), result->getErrorText()); |
| 171 | + for (SqlQueryItem* item : itemsInRow) |
| 172 | + item->setCommittingError(true, errMsg); |
| 173 | + |
| 174 | + notifyError(errMsg); |
| 175 | + return false; |
| 176 | + } |
| 177 | + |
| 178 | + if (!SqlQueryModel::commitDeletedRow(itemsInRow, successfulCommitHandlers)) |
| 179 | + qCritical() << "Could not delete row from SqlQueryView while committing row deletion."; |
| 180 | + |
| 181 | + return commitDeletedRowPostprocess(itemsInRow, result->getAll().size(), successfulCommitHandlers); |
| 182 | +} |
| 183 | + |
| 184 | +QString SqlDataSourceQueryModel::getInsertSql(QStringList& colNameList, QStringList& sqlValues) |
| 185 | +{ |
| 186 | + static_qstring(insertTpl, "INSERT INTO %1 %2 %3 RETURNING *"); |
| 187 | + static_qstring(valuesTpl, "VALUES (%1)"); |
| 188 | + static_qstring(columnsTpl, "(%1)"); |
| 189 | + |
| 190 | + QString wrappedTableName = getDataSource(); |
| 191 | + QString colNames = colNameList.join(", "); |
| 192 | + if (colNameList.isEmpty()) |
| 193 | + return insertTpl.arg(wrappedTableName, "", "DEFAULT VALUES"); |
| 194 | + else |
| 195 | + return insertTpl.arg(wrappedTableName, columnsTpl.arg(colNames), valuesTpl.arg(sqlValues.join(", "))); |
| 196 | +} |
| 197 | + |
| 198 | +void SqlDataSourceQueryModel::prepareColumnsAndBindParams(const QList<SqlQueryItem*>& itemsInRow, QStringList& colNameList, |
| 199 | + QStringList& bindParams, QList<QVariant>& args) |
| 200 | +{ |
| 201 | + SqlQueryItem* item = nullptr; |
| 202 | + int i = 0; |
| 203 | + for (SqlQueryModelColumnPtr& modelColumn : columns) |
| 204 | + { |
| 205 | + item = itemsInRow[i++]; |
| 206 | + if (!modelColumn->canEdit()) |
| 207 | + continue; |
| 208 | + |
| 209 | + if (item->isUntouched() && modelColumn->hasDefaultValueForInsert()) |
| 210 | + continue; |
| 211 | + |
| 212 | + colNameList << wrapObjIfNeeded(modelColumn->column); |
| 213 | + bindParams << ":arg" + QString::number(i); |
| 214 | + args << item->getValue(); |
| 215 | + } |
| 216 | +} |
| 217 | + |
91 | 218 | void SqlDataSourceQueryModel::applySqlFilter(const QString& value) |
92 | 219 | { |
93 | 220 | if (value.isEmpty()) |
@@ -146,7 +273,34 @@ QString SqlDataSourceQueryModel::getDatabasePrefix() |
146 | 273 | return wrapObjIfNeeded(database) + "."; |
147 | 274 | } |
148 | 275 |
|
149 | | -QString SqlDataSourceQueryModel::getDataSource() |
| 276 | +QString SqlDataSourceQueryModel::CommitDeleteQueryBuilder::build() |
| 277 | +{ |
| 278 | + QString dbAndTable; |
| 279 | + if (!database.isNull()) |
| 280 | + dbAndTable += database+"."; |
| 281 | + |
| 282 | + dbAndTable += tableOrView; |
| 283 | + QString conditions = RowIdConditionBuilder::build(); |
| 284 | + |
| 285 | + static_qstring(sql, "DELETE FROM %1 WHERE %2 RETURNING 1;"); |
| 286 | + return sql.arg(dbAndTable, conditions); |
| 287 | +} |
| 288 | + |
| 289 | + |
| 290 | +QString SqlDataSourceQueryModel::SelectColumnsQueryBuilder::build() |
| 291 | +{ |
| 292 | + QString dbAndTable; |
| 293 | + if (!database.isNull()) |
| 294 | + dbAndTable += database+"."; |
| 295 | + |
| 296 | + dbAndTable += tableOrView; |
| 297 | + QString conditions = RowIdConditionBuilder::build(); |
| 298 | + |
| 299 | + static_qstring(sql, "SELECT %1 FROM %2 WHERE %3 LIMIT 1;"); |
| 300 | + return sql.arg(columns.join(", "), dbAndTable, conditions); |
| 301 | +} |
| 302 | + |
| 303 | +void SqlDataSourceQueryModel::SelectColumnsQueryBuilder::addColumn(const QString& col) |
150 | 304 | { |
151 | | - return QString(); |
| 305 | + columns << col; |
152 | 306 | } |
0 commit comments