cutelyst 5.0.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
16Q_LOGGING_CATEGORY(C_SQL, "cutelyst.utils.sql", QtWarningMsg)
17
18using namespace Cutelyst;
19
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
33QVariantList 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
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
79QVariantList 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
119QVariantList 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
151QVariantHash 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 if (htmlEscaped) {
220 for (const auto &[key, value] : params.asKeyValueRange()) {
221 if (value.isNull()) {
222 query.bindValue(u':' + key, {});
223 } else {
224 query.bindValue(u':' + key, value.toHtmlEscaped());
225 }
226 }
227 } else {
228 for (const auto &[key, value] : params.asKeyValueRange()) {
229 if (value.isNull()) {
230 query.bindValue(u':' + key, {});
231 } else {
232 query.bindValue(u':' + key, value);
233 }
234 }
235 }
236}
237
238QSqlQuery Sql::preparedQuery(const QString &query, QSqlDatabase db, bool forwardOnly)
239{
240 QSqlQuery sqlQuery(db);
241 sqlQuery.setForwardOnly(forwardOnly);
242 if (!sqlQuery.prepare(query)) {
243 qCCritical(C_SQL) << "Failed to prepare query:" << query
244 << sqlQuery.lastError().databaseText();
245 }
246 return sqlQuery;
247}
248
249QSqlQuery Sql::preparedQueryThread(const QString &query, const QString &dbName, bool forwardOnly)
250{
252 sqlQuery.setForwardOnly(forwardOnly);
253 if (!sqlQuery.prepare(query)) {
254 qCCritical(C_SQL) << "Failed to prepare query:" << query
255 << sqlQuery.lastError().databaseText();
256 }
257 return sqlQuery;
258}
259
261{
262 return dbName + u'-' + QThread::currentThread()->objectName();
263}
264
269
271 : m_db(databaseThread(databaseName))
272{
273 m_transactionRunning = m_db.transaction();
274}
275
277 : m_db(database)
278{
279 m_transactionRunning = m_db.transaction();
280}
281
283{
284 if (m_transactionRunning) {
285 std::ignore = m_db.rollback();
286 }
287}
288
290{
291 return m_transactionRunning;
292}
293
295{
296 // In case we fail to commit we will still call rollback, not sure it's really needed
297 m_transactionRunning = !m_db.commit();
298 return !m_transactionRunning;
299}
300
302{
303 m_transactionRunning = false;
304 return m_db.rollback();
305}
bool transaction() const
Definition sql.cpp:289
Transaction(const QString &databaseName={})
Definition sql.cpp:270
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 QSqlQuery preparedQuery(const QString &query, QSqlDatabase db=QSqlDatabase(), bool forwardOnly=false)
Definition sql.cpp:238
CUTELYST_PLUGIN_UTILS_SQL_EXPORT QSqlQuery preparedQueryThread(const QString &query, const QString &dbName={}, bool forwardOnly=false)
Definition sql.cpp:249
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 QVariantHash queryToIndexedHash(QSqlQuery &query, const QString &key)
Definition sql.cpp:151
CUTELYST_PLUGIN_UTILS_SQL_EXPORT QSqlDatabase databaseThread(const QString &dbName={})
Definition sql.cpp:265
CUTELYST_PLUGIN_UTILS_SQL_EXPORT QString databaseNameThread(const QString &dbName={})
Definition sql.cpp:260
CUTELYST_PLUGIN_UTILS_SQL_EXPORT QJsonArray queryToJsonArray(QSqlQuery &query)
Definition sql.cpp:135
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
auto asKeyValueRange() &
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