Qx v0.7
Qt Extensions Library
Loading...
Searching...
No Matches
qx-sqldatabase.h
1#ifndef QX_SQLDATABASE_H
2#define QX_SQLDATABASE_H
3
4// Shared Lib Support
5#include "qx/sql/qx_sql_export.h"
6
7// Qt Includes
8#include <QSqlDatabase>
9#include <QReadWriteLock>
10#include <QUuid>
11
12// Intra-component Includes
13#include "qx/sql/qx-sqlquery.h"
14#include "qx/sql/qx-sqlschemareport.h"
15
16// Extra-component Includes
17
18using namespace Qt::StringLiterals;
19
20class QThread;
21
22namespace Qx
23{
24
25/* Careful use of the thread safe static functions of QSqlDatabase here allow us to avoid
26 * needing our own lock and connection tracker, AND ensure that a lambda can be used to
27 * handle connection closures due to thread-termination without having a potential dangling
28 * reference to the this pointer in the capture, thereby avoiding the overhead of needing
29 * to make this a QObject in order to disconnect when this is destroyed.
30 *
31 * This introduces a small amount of overhead, particularly when it comes to closing all
32 * connections at destruction, but the added simplicity is worth it..
33 */
34
35class QX_SQL_EXPORT SqlDatabase
36{
37//-Instance Variables-----------------------------------------------------------------------------------------------
38private:
39 // NOTE: These are not const to allow move semantics, but DO NOT write to them after construction, or else this
40 // isn't thread safe.
41 QString mDatabaseName; /* TODO: Have opt in ctor var for shared connections in the same thread; that is,
42 * shared instances don't salt their pointer and reuse the same connection as long
43 * as they're in the same thread, then non-shared instances (default) will only use
44 * the same connection through the same instance, as is now. Perhaps specify this by
45 * an optional connection name input that defaults to empty, which will cause this
46 * class to use the db name as part of the connection name by default, then if the
47 * connection name is different, that is used instead of the
48 */
49 QString mDriver;
50 QString mId;
51 QMetaObject::Connection mThreadCloseConnection; // This is only modified in the destructor.
52
53//-Constructor-------------------------------------------------------------------------------------------------
54public:
55 // TODO: Instead of passing only the driver and db name, allow passing a struct that holds those
56 // and all of the stuff there are setters for in QSqlDatabase so that we can allow full customization
57 // before/at construction time, but dont need to allow setting the values after and therefore don't need
58 // our own mutex.
59 explicit SqlDatabase(const QString& databaseName, const QString& driver);
60 SqlDatabase(const SqlDatabase& other);
62
63//-Destructor-------------------------------------------------------------------------------------------------
64public:
66
67//-Class Functions------------------------------------------------------------------------------------------------------
68private:
69 static QString connectionName(QStringView id, const QThread* thread);
70 static bool closeConnection(const QString& connectionName);
71 static bool closeConnection(QStringView id, const QThread* thread);
72
73//-Instance Functions------------------------------------------------------------------------------------------------------
74private:
75 void closeAllConnections();
76 QString connectionName(const QThread* thread) const;
77
78public:
79 SqlError database(QSqlDatabase& db, bool connect = true);
81 QString driver() const;
82 QString databaseName() const;
83 bool isConnected() const;
84 bool closeConnection();
85
87 SqlError checkSchema(SqlSchemaReport& report, SqlSchemaReport::StrictnessFlags strictness = SqlSchemaReport::Lenient)
88 {
89 QSqlDatabase db;
90 if(auto err = database(db))
91 return err;
92
93 report = SqlSchemaReport::generate<First, Rest...>(db, strictness);
94 return SqlError();
95 }
96
97 /* TODO: See if we can make concepts that basically allow saying that these methods can be called with any type
98 * and combination of arguments that the same keyword in the respective query type allows, and then just always
99 * forward the arguments, so that for the keywords will multiple signatures, we don't need to repeat them
100 * multiple times here.
101 */
102 // SQL - DQL
103 template<sql_stringable First, sql_stringable ...Rest>
104 SqlDqlQuery SELECT(First&& fs, Rest&&... s)
105 {
106 SqlDqlQuery q(*this);
107 q.SELECT(std::forward<First>(fs), std::forward(s)...);
108 return q;
109 }
110
111 template<sql_stringable First, sql_stringable ...Rest>
113 {
114 SqlDqlQuery q(*this);
115 q.SELECT_DISTINCT(std::forward<First>(fs), std::forward(s)...);
116 return q;
117 }
118
119 template<QxSql::sql_struct First, QxSql::sql_struct... Rest>
121 {
122 SqlDqlQuery q(*this);
123 q.SELECT<First, Rest...>();
124 return q;
125 }
126
127 template<QxSql::sql_struct First, QxSql::sql_struct... Rest>
129 {
130 SqlDqlQuery q(*this);
131 q.SELECT<First, Rest...>();
132 return q;
133 }
134
135 // SQL - DML
137 {
138 SqlDmlQuery q(*this);
139 q.DELETE();
140 return q;
141 }
142
143 template<sql_stringable First, sql_stringable ...Rest>
144 SqlDmlQuery INSERT_INTO(const SqlString& table, First&& fs, Rest&&... s)
145 {
146 SqlDmlQuery q(*this);
147 q.INSERT_INTO(table, std::forward<First>(fs), std::forward<Rest>(s)...);
148 return q;
149 }
150
151 template<sql_stringable First>
153 {
154 SqlDmlQuery q(*this);
155 q.MERGE_INTO(std::forward<First>(fs));
156 return q;
157 }
158
159 template<sql_stringable First>
161 {
162 SqlDmlQuery q(*this);
163 q.UPDATE(std::forward<First>(fs));
164 return q;
165 }
166
167 template<QxSql::sql_struct Struct>
169 {
170 SqlDmlQuery q(*this);
171 q.UPDATE<Struct>();
172 return q;
173 }
174
175
176//-Operators------------------------------------------------------------------------------------------------------
177public:
178 SqlDatabase& operator=(const SqlDatabase& other);
180};
181
182}
183
184#endif // QX_SQLDATABASE_H
Derived & SELECT_DISTINCT(First &&fsel, Rest &&... sel)
Definition qx-sqlquery.h:382
Derived & SELECT(First &&fsel, Rest &&... sel)
Definition qx-sqlquery.h:376
The SqlDatabase class provides straightforward access to an SQL database.
Definition qx-sqldatabase.h:36
QString driver() const
Definition qx-sqldatabase.cpp:217
SqlError connect()
Definition qx-sqldatabase.cpp:212
SqlDatabase(const QString &databaseName, const QString &driver)
Definition qx-sqldatabase.cpp:56
SqlDmlQuery UPDATE()
Definition qx-sqldatabase.h:168
SqlDatabase(SqlDatabase &&other)
SqlError checkSchema(SqlSchemaReport &report, SqlSchemaReport::StrictnessFlags strictness=SqlSchemaReport::Lenient)
Definition qx-sqldatabase.h:87
SqlDqlQuery SELECT(First &&fs, Rest &&... s)
Definition qx-sqldatabase.h:104
SqlDatabase & operator=(SqlDatabase &&other)
SqlDmlQuery INSERT_INTO(const SqlString &table, First &&fs, Rest &&... s)
Definition qx-sqldatabase.h:144
SqlDmlQuery MERGE_INTO(First &&fs)
Definition qx-sqldatabase.h:152
SqlDmlQuery UPDATE(First &&fs)
Definition qx-sqldatabase.h:160
SqlDmlQuery DELETE()
Definition qx-sqldatabase.h:136
bool isConnected() const
Definition qx-sqldatabase.cpp:228
SqlError database(QSqlDatabase &db, bool connect=true)
Definition qx-sqldatabase.cpp:159
QString databaseName() const
Definition qx-sqldatabase.cpp:222
SqlDqlQuery SELECT()
Definition qx-sqldatabase.h:120
SqlDqlQuery SELECT_DISTINCT(First &&fs, Rest &&... s)
Definition qx-sqldatabase.h:112
SqlDqlQuery SELECT_DISTINCT()
Definition qx-sqldatabase.h:128
The SqlDmlQuery class represents SQL queries that fit into the data manipulation language sub-languag...
Definition qx-sqlquery.h:531
auto & MERGE_INTO(First &&fs)
auto & INSERT_INTO(const SqlString &table, First &&first, Rest &&... rest)
Definition qx-sqlquery.h:544
auto & UPDATE(First &&fs)
The SqlDqlQuery class represents SQL queries that fit into the data query language sub-language.
Definition qx-sqlquery.h:410
The SqlError class is used to report errors related to database configuration and SQL queries.
Definition qx-sqlerror.h:21
The SqlString class is a convenience class for more easily building SQL statements in a natural manne...
Definition qx-sqlstring.h:36
Specifies that a type is a SQL-tied struct.
Definition qx-sqlconcepts.h:42
Specifies that a type can be converted to SqlString, or used to construct a SqlString.
Definition qx-sqlstring.h:33
The Qx namespace is the main namespace through which all non-global functionality of the Qx library i...
Definition qx-abstracterror.cpp:13
@ First
Definition qx-global.h:19
The qx-sql header file offers a straightforward interface for querying an SQL database.