EasyQtSql
Easy SQL data access helper for QtSql
EasyQtSql_Transaction.h
Go to the documentation of this file.
1 #ifndef EASYQTSQL_TRANSACTION_H
2 #define EASYQTSQL_TRANSACTION_H
3 
4 /*
5  * The MIT License (MIT)
6  * Copyright 2018 Alexey Kramin
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining
9  * a copy of this software and associated documentation files (the
10  * "Software"), to deal in the Software without restriction, including
11  * without limitation the rights to use, copy, modify, merge, publish,
12  * distribute, sublicense, and/or sell copies of the Software, and to
13  * permit persons to whom the Software is furnished to do so, subject to
14  * the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be
17  * included in all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26  *
27 */
28 
29 #ifndef EASY_QT_SQL_MAIN
30 
31 #include <QtSql>
32 #include "EasyQtSql_DBException.h"
34 #include "EasyQtSql_InsertQuery.h"
35 #include "EasyQtSql_DeleteQuery.h"
36 #include "EasyQtSql_UpdateQuery.h"
38 
39 #endif
40 
41 #include "EasyQtSql_Util.h"
42 
67 class Database
68 {
69  Q_DISABLE_COPY(Database)
70 
71 public:
72 
80  explicit Database (const QSqlDatabase &db = QSqlDatabase())
81  {
82  m_db = db.isValid() ? db : QSqlDatabase::database();
83 
84  if (!m_db.isOpen())
85  {
86  if (!m_db.open())
87  {
88  #ifdef DB_EXCEPTIONS_ENABLED
89  throw DBException(m_db);
90  #endif
91  }
92  }
93  }
94 
95  Database(Database&& other)
96  {
97  m_db = other.m_db;
98  other.m_db = QSqlDatabase();
99  }
100 
102  {
103  if (this == &other) return *this;
104 
105  m_db = other.m_db;
106  other.m_db = QSqlDatabase();
107 
108  return *this;
109  }
110 
114  QSqlError lastError() const
115  {
116  return m_db.lastError();
117  }
118 
124  NonQueryResult execNonQuery(const QString &sql) const
125  {
126  QSqlQuery q = m_db.exec(sql);
127 
128 #ifdef DB_EXCEPTIONS_ENABLED
129 
130  QSqlError lastError = q.lastError();
131 
132  if (lastError.isValid())
133  throw DBException(q);
134 
135 #endif
136 
137  return NonQueryResult(q);
138  }
139 
145  QueryResult execQuery(const QString &sql) const
146  {
147  QSqlQuery q = m_db.exec(sql);
148 
149 #ifdef DB_EXCEPTIONS_ENABLED
150 
151  QSqlError lastError = q.lastError();
152 
153  if (lastError.isValid())
154  throw DBException(q);
155 
156 #endif
157 
158  return QueryResult(q);
159  }
160 
165  InsertQuery insertInto(const QString &table) const
166  {
167  InsertQuery query(table, m_db);
168 
169  return query;
170  }
171 
176  DeleteQuery deleteFrom(const QString &table) const
177  {
178  DeleteQuery query(table, m_db);
179 
180  return query;
181  }
182 
187  UpdateQuery update(const QString &table) const
188  {
189  UpdateQuery query(table, m_db);
190 
191  return query;
192  }
193 
199  PreparedQuery prepare(const QString &sql, bool forwardOnly = true) const
200  {
201  PreparedQuery query(sql, m_db, forwardOnly);
202 
203  return query;
204  }
205 
209  QSqlDatabase &qSqlDatabase()
210  {
211  return m_db;
212  }
213 
228  template<typename Func>
229  int each (const QString &query, Func&& f) const
230  {
231  QueryResult res = execQuery(query);
232 
233  return Util::each(res, f);
234  }
235 
250  template<typename Func>
251  int first (const QString &query, Func&& f) const
252  {
253  QueryResult res = execQuery(query);
254 
255  return Util::first(res, f);
256  }
257 
274  template<typename Func>
275  int range(const QString &query, int start, int count, Func&& f) const
276  {
277  QueryResult res = execQuery(query);
278 
279  return Util::range(res, start, count, f);
280  }
281 
297  template<typename Func>
298  int top(const QString &query, int topCount, Func&& f) const
299  {
300  QueryResult res = execQuery(query);
301 
302  return Util::top(res, topCount, f);
303  }
304 
310  template<typename T>
311  T scalar(const QString &query) const
312  {
313  QueryResult res = execQuery(query);
314 
315  res.next();
316 
317  return res.scalar<T>();
318  }
319 
325  QVariant scalar(const QString &query) const
326  {
327  QueryResult res = execQuery(query);
328 
329  res.next();
330 
331  return res.scalar();
332  }
333 
334 protected:
335  QSqlDatabase m_db;
336 };
337 
338 
398 class Transaction : public Database
399 {
400  Q_DISABLE_COPY(Transaction)
401 
402 public:
403 
404  explicit Transaction (const QSqlDatabase &db = QSqlDatabase())
405  : Database(db)
406  , m_commited(false)
407  , m_started(false)
408  {
409  m_started = m_db.transaction();
410 
411  #ifdef DB_EXCEPTIONS_ENABLED
412  if (!m_started)
413  {
414  throw DBException(m_db);
415  }
416  #endif
417  }
418 
420  : Database(std::move(other))
421  {
422  m_commited = other.m_commited;
423  m_started = other.m_started;
424 
425  other.m_commited = false;
426  other.m_started = false;
427  }
428 
430  {
431  m_started = other.m_started;
432  m_commited = other.m_commited;
433 
434  other.m_commited = false;
435  other.m_started = false;
436 
437  return static_cast<Transaction&>(Database::operator=(std::move(other)));
438  }
439 
441  {
442  if (m_db.isValid() && !m_commited)
443  {
444  m_db.rollback();
445  }
446  }
447 
455  bool commit()
456  {
457  if (m_db.isValid() && !m_commited)
458  {
459  m_commited = m_db.commit();
460 
461 #ifdef DB_EXCEPTIONS_ENABLED
462 
463  if (!m_commited)
464  throw DBException(m_db);
465 
466 #endif
467 
468  }
469 
470  return m_commited;
471  }
472 
476  bool rollback()
477  {
478  bool res = false;
479 
480  if (m_db.isValid() && !m_commited)
481  {
482  res = m_db.rollback();
483 
484  m_commited = false;
485  }
486 
487  return res;
488  }
489 
493  bool started() const
494  {
495  return m_started;
496  }
497 
501  bool commited() const
502  {
503  return m_commited;
504  }
505 
506 private:
507  bool m_commited = false;
508  bool m_started = false;
509 };
510 
511 #endif // EASYQTSQL_TRANSACTION_H
QVariant scalar(const QString &query) const
Executes query and returns scalar value.
Definition: EasyQtSql_Transaction.h:325
int first(const QString &query, Func &&f) const
Executes query and applies function f to the first result row.
Definition: EasyQtSql_Transaction.h:251
InsertQuery insertInto(const QString &table) const
Creates INSERT query wrapper.
Definition: EasyQtSql_Transaction.h:165
Transaction & operator=(Transaction &&other)
Definition: EasyQtSql_Transaction.h:429
QueryResult execQuery(const QString &sql) const
Executes SELECT query.
Definition: EasyQtSql_Transaction.h:145
bool commited() const
Returns true if the transaction has been commited successfully. Otherwise it returns false...
Definition: EasyQtSql_Transaction.h:501
QSqlDatabase m_db
Definition: EasyQtSql_Transaction.h:335
Class for query preparation and execution.
Definition: EasyQtSql_PreparedQuery.h:63
int range(const QString &query, int start, int count, Func &&f) const
Executes query and applies function f to count result rows starting from index start.
Definition: EasyQtSql_Transaction.h:275
T scalar() const
Returns scalar value converted to type T (the value of the first column of the current row) ...
Definition: EasyQtSql_QueryResult.h:424
bool rollback()
Rolls back transaction.
Definition: EasyQtSql_Transaction.h:476
static int range(QueryResult &res, int start, int count, Func &&f)
Applies function (lambda) f to count rows starting from start index.
Definition: EasyQtSql_Util.h:88
~Transaction()
Definition: EasyQtSql_Transaction.h:440
bool commit()
Commits transaction.
Definition: EasyQtSql_Transaction.h:455
UpdateQuery update(const QString &table) const
Creates UPDATE query wrapper.
Definition: EasyQtSql_Transaction.h:187
QSqlQuery wrapper for non-select query results reading.
Definition: EasyQtSql_NonQueryResult.h:38
bool started() const
Returns true if the transaction has been started successfully. Otherwise it returns false...
Definition: EasyQtSql_Transaction.h:493
static int top(QueryResult &res, int topCount, Func &&f)
Applies function (lambda) f to topCount rows from res.
Definition: EasyQtSql_Util.h:122
QSqlError lastError() const
Returns information about the last error that occurred on the underlying database.
Definition: EasyQtSql_Transaction.h:114
T scalar(const QString &query) const
Executes query and returns scalar value converted to T.
Definition: EasyQtSql_Transaction.h:311
QSqlDatabase wrapper.
Definition: EasyQtSql_Transaction.h:67
Database & operator=(Database &&other)
Definition: EasyQtSql_Transaction.h:101
QSqlDatabase & qSqlDatabase()
Returns a reference to the wrapped QSqlDatabase object.
Definition: EasyQtSql_Transaction.h:209
QSqlQuery wrapper for DELETE FROM ... WHERE .. query execution.
Definition: EasyQtSql_DeleteQuery.h:39
Transaction(Transaction &&other)
Definition: EasyQtSql_Transaction.h:419
Database(Database &&other)
Definition: EasyQtSql_Transaction.h:95
NonQueryResult execNonQuery(const QString &sql) const
Executes non-query SQL statement (DELETE, INSERT, UPDATE, CREATE, ALTER, etc.)
Definition: EasyQtSql_Transaction.h:124
int each(const QString &query, Func &&f) const
Executes query and applies function f to each result row.
Definition: EasyQtSql_Transaction.h:229
DeleteQuery deleteFrom(const QString &table) const
Creates DELETE query wrapper.
Definition: EasyQtSql_Transaction.h:176
QSqlQuery wrapper with handy data fetch methods.
Definition: EasyQtSql_QueryResult.h:39
PreparedQuery prepare(const QString &sql, bool forwardOnly=true) const
Prepares SQL statement.
Definition: EasyQtSql_Transaction.h:199
QSqlDatabase transaction wrapper.
Definition: EasyQtSql_Transaction.h:398
static int first(QueryResult &res, Func &&f)
Applies function (lambda) f to first result row.
Definition: EasyQtSql_Util.h:133
bool next()
Retrieves the next record in the result, if available, and positions the query on the retrieved recor...
Definition: EasyQtSql_QueryResult.h:60
static int each(QueryResult &res, Func &&f)
Applies function (lambda) f to each row in res.
Definition: EasyQtSql_Util.h:64
Transaction(const QSqlDatabase &db=QSqlDatabase())
Definition: EasyQtSql_Transaction.h:404
QSqlQuery wrapper for INSERT INTO table query execution.
Definition: EasyQtSql_InsertQuery.h:39
int top(const QString &query, int topCount, Func &&f) const
Executes query and applies function f to topCount result rows.
Definition: EasyQtSql_Transaction.h:298
Database(const QSqlDatabase &db=QSqlDatabase())
Definition: EasyQtSql_Transaction.h:80
QSqlQuery wrapper for UPDATE ... SET ... WHERE ... query execution.
Definition: EasyQtSql_UpdateQuery.h:39
Exception class for SQL errors handling.
Definition: EasyQtSql_DBException.h:38