cutelyst  4.4.0
A C++ Web Framework built on top of Qt, using the simple approach of Catalyst (Perl) framework.
sql.cpp
1 /*
2  * SPDX-FileCopyrightText: (C) 2015-2022 Daniel Nicoletti <dantti12@gmail.com>
3  * SPDX-License-Identifier: BSD-3-Clause
4  */
5 #include "sql.h"
6 
7 #include <QJsonArray>
8 #include <QJsonObject>
9 #include <QJsonValue>
10 #include <QLoggingCategory>
11 #include <QThread>
12 #include <QtSql/QSqlError>
13 #include <QtSql/QSqlQuery>
14 #include <QtSql/QSqlRecord>
15 
16 Q_LOGGING_CATEGORY(C_SQL, "cutelyst.utils.sql", QtWarningMsg)
17 
18 using namespace Cutelyst;
19 
20 QVariantHash Sql::queryToHashObject(QSqlQuery &query)
21 {
22  QVariantHash ret;
23  if (query.next()) {
24  const QSqlRecord record = query.record();
25  const int columns = record.count();
26  for (int i = 0; i < columns; ++i) {
27  ret.insert(record.fieldName(i), query.value(i));
28  }
29  }
30  return ret;
31 }
32 
33 QVariantList Sql::queryToHashList(QSqlQuery &query)
34 {
35  QVariantList ret;
36  const QSqlRecord record = query.record();
37  const int columns = record.count();
38  QStringList cols;
39  for (int i = 0; i < columns; ++i) {
40  cols.append(record.fieldName(i));
41  }
42 
43  while (query.next()) {
44  QVariantHash line;
45  for (int i = 0; i < columns; ++i) {
46  line.insert(cols.at(i), query.value(i));
47  }
48  ret.append(line);
49  }
50  return ret;
51 }
52 
53 QVariantMap Sql::queryToMapObject(QSqlQuery &query)
54 {
55  QVariantMap ret;
56  if (query.next()) {
57  const QSqlRecord record = query.record();
58  const int columns = record.count();
59  for (int i = 0; i < columns; ++i) {
60  ret.insert(record.fieldName(i), query.value(i));
61  }
62  }
63  return ret;
64 }
65 
67 {
68  QJsonObject ret;
69  if (query.next()) {
70  const QSqlRecord record = query.record();
71  const int columns = record.count();
72  for (int i = 0; i < columns; ++i) {
73  ret.insert(record.fieldName(i), QJsonValue::fromVariant(query.value(i)));
74  }
75  }
76  return ret;
77 }
78 
79 QVariantList Sql::queryToMapList(QSqlQuery &query)
80 {
81  QVariantList ret;
82  const QSqlRecord record = query.record();
83  const int columns = record.count();
84  QStringList cols;
85  for (int i = 0; i < columns; ++i) {
86  cols.append(record.fieldName(i));
87  }
88 
89  while (query.next()) {
90  QVariantMap line;
91  for (int i = 0; i < columns; ++i) {
92  line.insert(cols.at(i), query.value(i));
93  }
94  ret.append(line);
95  }
96  return ret;
97 }
98 
100 {
101  QJsonArray ret;
102  const QSqlRecord record = query.record();
103  const int columns = record.count();
104  QStringList cols;
105  for (int i = 0; i < columns; ++i) {
106  cols.append(record.fieldName(i));
107  }
108 
109  while (query.next()) {
110  QJsonObject line;
111  for (int i = 0; i < columns; ++i) {
112  line.insert(cols.at(i), QJsonValue::fromVariant(query.value(i)));
113  }
114  ret.append(line);
115  }
116  return ret;
117 }
118 
119 QVariantList Sql::queryToList(QSqlQuery &query)
120 {
121  QVariantList ret;
122 
123  const int columns = query.record().count();
124  while (query.next()) {
125  QVariantList line;
126  for (int i = 0; i < columns; ++i) {
127  line.append(query.value(i));
128  }
129  ret.append(QVariant::fromValue(line));
130  }
131 
132  return ret;
133 }
134 
136 {
137  QJsonArray ret;
138 
139  const int columns = query.record().count();
140  while (query.next()) {
141  QJsonArray array;
142  for (int i = 0; i < columns; ++i) {
143  array.append(QJsonValue::fromVariant(query.value(i)));
144  }
145  ret.append(array);
146  }
147 
148  return ret;
149 }
150 
151 QVariantHash Sql::queryToIndexedHash(QSqlQuery &query, const QString &key)
152 {
153  QVariantHash ret;
154 
155  const QSqlRecord record = query.record();
156  int index = record.indexOf(key);
157  if (index == -1) {
158  qCCritical(C_SQL) << "Field Name " << key << " not found in result set";
159  return ret;
160  }
161 
162  const int columns = record.count();
163  QStringList cols;
164 
165  for (int i = 0; i < columns; ++i) {
166  cols.append(record.fieldName(i));
167  }
168 
169  while (query.next()) {
170  QVariantHash line;
171  for (int i = 0; i < columns; ++i) {
172  if (i != index) {
173  line.insert(cols.at(i), query.value(i));
174  }
175  }
176 
177  ret.insert(query.value(index).toString(), line);
178  }
179 
180  return ret;
181 }
182 
184 {
185  QJsonObject ret;
186 
187  const QSqlRecord record = query.record();
188  int index = record.indexOf(key);
189  if (index == -1) {
190  qCCritical(C_SQL) << "Field Name " << key << " not found in result set";
191  return ret;
192  }
193 
194  const int columns = record.count();
195  QStringList cols;
196 
197  for (int i = 0; i < columns; ++i) {
198  cols.append(record.fieldName(i));
199  }
200 
201  while (query.next()) {
202  QJsonObject obj;
203  for (int i = 0; i < columns; ++i) {
204  if (i != index) {
205  obj.insert(cols.at(i), QJsonValue::fromVariant(query.value(i)));
206  }
207  }
208 
209  ret.insert(query.value(index).toString(), obj);
210  }
211 
212  return ret;
213 }
214 
216  const Cutelyst::ParamsMultiMap &params,
217  bool htmlEscaped)
218 {
219  auto it = params.constBegin();
220  if (htmlEscaped) {
221  while (it != params.constEnd()) {
222  if (it.value().isNull()) {
223  query.bindValue(u':' + it.key(), QVariant());
224  } else {
225  query.bindValue(u':' + it.key(), it.value().toHtmlEscaped());
226  }
227  ++it;
228  }
229  } else {
230  while (it != params.constEnd()) {
231  if (it.value().isNull()) {
232  query.bindValue(u':' + it.key(), QVariant());
233  } else {
234  query.bindValue(u':' + it.key(), it.value());
235  }
236  ++it;
237  }
238  }
239 }
240 
241 QSqlQuery Sql::preparedQuery(const QString &query, QSqlDatabase db, bool forwardOnly)
242 {
243  QSqlQuery sqlQuery(db);
244  sqlQuery.setForwardOnly(forwardOnly);
245  if (!sqlQuery.prepare(query)) {
246  qCCritical(C_SQL) << "Failed to prepare query:" << query
247  << sqlQuery.lastError().databaseText();
248  }
249  return sqlQuery;
250 }
251 
252 QSqlQuery Sql::preparedQueryThread(const QString &query, const QString &dbName, bool forwardOnly)
253 {
255  sqlQuery.setForwardOnly(forwardOnly);
256  if (!sqlQuery.prepare(query)) {
257  qCCritical(C_SQL) << "Failed to prepare query:" << query
258  << sqlQuery.lastError().databaseText();
259  }
260  return sqlQuery;
261 }
262 
264 {
265  return dbName + u'-' + QThread::currentThread()->objectName();
266 }
267 
269 {
271 }
272 
274  : m_db(databaseThread(databaseName))
275 {
276  m_transactionRunning = m_db.transaction();
277 }
278 
280  : m_db(database)
281 {
282  m_transactionRunning = m_db.transaction();
283 }
284 
286 {
287  if (m_transactionRunning) {
288  m_db.rollback();
289  }
290 }
291 
293 {
294  return m_transactionRunning;
295 }
296 
298 {
299  // In case we fail to commit we will still call rollback, not sure it's really needed
300  m_transactionRunning = !m_db.commit();
301  return !m_transactionRunning;
302 }
303 
305 {
306  m_transactionRunning = false;
307  return m_db.rollback();
308 }
bool transaction() const
Definition: sql.cpp:292
Transaction(const QString &databaseName=QString())
Definition: sql.cpp:273
CUTELYST_PLUGIN_UTILS_SQL_EXPORT QVariantList queryToHashList(QSqlQuery &query)
Definition: sql.cpp:33
CUTELYST_PLUGIN_UTILS_SQL_EXPORT QVariantMap queryToMapObject(QSqlQuery &query)
Definition: sql.cpp:53
CUTELYST_PLUGIN_UTILS_SQL_EXPORT QVariantHash queryToHashObject(QSqlQuery &query)
Definition: sql.cpp:20
CUTELYST_PLUGIN_UTILS_SQL_EXPORT void bindParamsToQuery(QSqlQuery &query, const Cutelyst::ParamsMultiMap &params, bool htmlEscaped=true)
Definition: sql.cpp:215
CUTELYST_PLUGIN_UTILS_SQL_EXPORT QJsonArray queryToJsonObjectArray(QSqlQuery &query)
Definition: sql.cpp:99
CUTELYST_PLUGIN_UTILS_SQL_EXPORT QString databaseNameThread(const QString &dbName=QString())
Definition: sql.cpp:263
CUTELYST_PLUGIN_UTILS_SQL_EXPORT QSqlQuery preparedQuery(const QString &query, QSqlDatabase db=QSqlDatabase(), bool forwardOnly=false)
Definition: sql.cpp:241
CUTELYST_PLUGIN_UTILS_SQL_EXPORT QVariantList queryToList(QSqlQuery &query)
Definition: sql.cpp:119
CUTELYST_PLUGIN_UTILS_SQL_EXPORT QJsonObject queryToIndexedJsonObject(QSqlQuery &query, const QString &key)
Definition: sql.cpp:183
CUTELYST_PLUGIN_UTILS_SQL_EXPORT QVariantList queryToMapList(QSqlQuery &query)
Definition: sql.cpp:79
CUTELYST_PLUGIN_UTILS_SQL_EXPORT QSqlDatabase databaseThread(const QString &dbName=QString())
Definition: sql.cpp:268
CUTELYST_PLUGIN_UTILS_SQL_EXPORT QVariantHash queryToIndexedHash(QSqlQuery &query, const QString &key)
Definition: sql.cpp:151
CUTELYST_PLUGIN_UTILS_SQL_EXPORT QJsonArray queryToJsonArray(QSqlQuery &query)
Definition: sql.cpp:135
CUTELYST_PLUGIN_UTILS_SQL_EXPORT QSqlQuery preparedQueryThread(const QString &query, const QString &dbName=QString(), bool forwardOnly=false)
Definition: sql.cpp:252
CUTELYST_PLUGIN_UTILS_SQL_EXPORT QJsonObject queryToJsonObject(QSqlQuery &query)
Definition: sql.cpp:66
The Cutelyst namespace holds all public Cutelyst API.
void append(const QJsonValue &value)
QJsonObject::iterator insert(QLatin1StringView key, const QJsonValue &value)
QJsonValue fromVariant(const QVariant &variant)
void append(QList::parameter_type value)
QList::const_reference at(qsizetype i) const const
QMultiMap::const_iterator constBegin() const const
QMultiMap::const_iterator constEnd() const const
QSqlDatabase database(const QString &connectionName, bool open)
bool transaction()
QString databaseText() const const
void bindValue(const QString &placeholder, const QVariant &val, QSql::ParamType paramType)
QSqlError lastError() const const
bool next()
bool prepare(const QString &query)
QSqlRecord record() const const
void setForwardOnly(bool forward)
QVariant value(const QString &name) const const
int count() const const
QString fieldName(int index) const const
int indexOf(const QString &name) const const
QThread * currentThread()
QVariant fromValue(T &&value)
QString toString() const const