Skip to content

Commit b85945a

Browse files
committed
WIP
1 parent f854458 commit b85945a

File tree

11 files changed

+1433
-51
lines changed

11 files changed

+1433
-51
lines changed

lib/sql/CMakeLists.txt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
#================= Add Component ==========================
22
qx_add_component("Sql"
33
HEADERS_API
4-
qx-common-sql.h
4+
qx-sqldatabase.h
5+
qx-sqlerror.h
6+
qx-sqlquery.h
7+
qx-sqlstring.h
58
IMPLEMENTATION
6-
qx-common-sql.cpp
9+
qx-sqldatabase.cpp
10+
qx-sqlerror.cpp
11+
qx-sqlquery.cpp
12+
qx-sqlstring.cpp
713
#DOC_ONLY
814
LINKS
915
PUBLIC

lib/sql/include/qx/sql/qx-common-sql.h

Lines changed: 0 additions & 27 deletions
This file was deleted.
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
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+
15+
// Extra-component Includes
16+
17+
using namespace Qt::StringLiterals;
18+
19+
class QThread;
20+
21+
namespace Qx
22+
{
23+
24+
/* Careful use of the thread safe static functions of QSqlDatabase here allow us to avoid
25+
* needing our own lock and connection tracker, AND ensure that a lambda can be used to
26+
* handle connection closures due to thread-termination without having a potential dangling
27+
* reference to the this pointer in the capture, thereby avoiding the overhead of needing
28+
* to make this a QObject in order to disconnect when this is destroyed.
29+
*
30+
* This introduces a small amount of overhead, particularly when it comes to closing all
31+
* connections at destruction, but the added simplicity is worth it..
32+
*/
33+
34+
class QX_SQL_EXPORT SqlDatabase
35+
{
36+
//-Class Variables-----------------------------------------------------------------------------------------------
37+
private:
38+
static inline const QString ID_NAMESPACE = u"Qx::SqlDatabase"_s;
39+
40+
//-Instance Variables-----------------------------------------------------------------------------------------------
41+
private:
42+
// NOTE: These are not const to allow move semantics, but DO NOT write to them after construction, or else this
43+
// isn't thread safe.
44+
QString mDatabaseName; /* TODO: Have opt in ctor var for shared connections in the same thread; that is,
45+
* shared instances don't salt their pointer and reuse the same connection as long
46+
* as they're in the same thread, then non-shared instances (default) will only use
47+
* the same connection through the same instance, as is now. Perhaps specify this by
48+
* an optional connection name input that defaults to empty, which will cause this
49+
* class to use the db name as part of the connection name by default, then if the
50+
* connection name is different, that is used instead of the
51+
*/
52+
QString mDriver;
53+
QString mId;
54+
55+
//-Constructor-------------------------------------------------------------------------------------------------
56+
public:
57+
// TODO: Instead of passing only the driver and db name, allow passing a struct that olds those
58+
// and all of the stuff there are setters for in QSqlDatabase so that we can allow full customization
59+
// before/at construction time, but dont need to allow setting the values after and therefore don't need
60+
// our own mutex.
61+
explicit SqlDatabase(const QString& databaseName, const QString& driver);
62+
SqlDatabase(const SqlDatabase& other);
63+
SqlDatabase(SqlDatabase&& other);
64+
65+
//-Destructor-------------------------------------------------------------------------------------------------
66+
public:
67+
~SqlDatabase();
68+
69+
//-Class Functions------------------------------------------------------------------------------------------------------
70+
private:
71+
static QString connectionName(QStringView id, const QThread* thread);
72+
static void closeConnection(const QString& connectionName);
73+
static void closeConnection(QStringView id, const QThread* thread);
74+
75+
//-Instance Functions------------------------------------------------------------------------------------------------------
76+
private:
77+
void closeAllConnections();
78+
QString connectionName(const QThread* thread) const;
79+
80+
public:
81+
SqlError database(QSqlDatabase& db, bool connect = true);
82+
QString driver() const;
83+
QString databaseName() const;
84+
bool isConnected() const;
85+
86+
// SQL
87+
template<sql_stringable First, sql_stringable ...Rest>
88+
SqlDqlQuery SELECT(First&& fs, Rest&&... s)
89+
{
90+
// static_cast<> coerces the args into Qx::SqlString if they aren't already.
91+
// Not sure if the forwarding here always makes sense
92+
return SqlDqlQuery(
93+
false,
94+
*this,
95+
static_cast<SqlString>(std::forward<First>(fs)),
96+
static_cast<SqlString>(std::forward<Rest>(s))...
97+
);
98+
}
99+
100+
template<QxSql::sql_struct Struct>
101+
SqlDqlQuery SELECT() { return SqlDqlQuery::fromStruct<Struct>(false, *this); }
102+
103+
template<QxSql::sql_struct Struct>
104+
SqlDqlQuery SELECT_DISTINCT() { return SqlDqlQuery::fromStruct<Struct>(true, *this); }
105+
106+
template<sql_stringable First, sql_stringable ...Rest>
107+
SqlDqlQuery SELECT_DISTINCT(First&& fs, Rest&&... s)
108+
{
109+
// static_cast<> coerces the args into Qx::SqlString if they aren't already.
110+
// Not sure if the forwarding here always makes sense
111+
return SqlDqlQuery(
112+
true,
113+
*this,
114+
static_cast<SqlString>(std::forward<First>(fs)),
115+
static_cast<SqlString>(std::forward<Rest>(s))...
116+
);
117+
}
118+
119+
//-Operators------------------------------------------------------------------------------------------------------
120+
public:
121+
SqlDatabase& operator=(const SqlDatabase& other);
122+
SqlDatabase& operator=(SqlDatabase&& other);
123+
};
124+
125+
}
126+
127+
#endif // QX_SQLDATABASE_H
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#ifndef QX_SQLERROR_H
2+
#define QX_SQLERROR_H
3+
4+
// Shared Lib Support
5+
#include "qx/sql/qx_sql_export.h"
6+
7+
// Extra-component Includes
8+
#include "qx/core/qx-abstracterror.h"
9+
10+
class QSqlError;
11+
12+
namespace QxSqlPrivate {template<typename T> struct FieldMatchChecker; }
13+
14+
namespace Qx
15+
{
16+
17+
class SqlQuery;
18+
class SqlDatabase;
19+
20+
class QX_SQL_EXPORT SqlError final : public AbstractError<"Qx::SqlError", 7>
21+
{
22+
template<typename T>
23+
friend struct QxSqlPrivate::FieldMatchChecker;
24+
//-Class Enums-------------------------------------------------------------
25+
public:
26+
enum Form
27+
{
28+
NoError,
29+
EngineError,
30+
TypeMismatch,
31+
MissingField
32+
};
33+
34+
//-Class Variables-------------------------------------------------------------
35+
private:
36+
static inline const QHash<Form, QString> ERR_STRINGS{
37+
{NoError, u"No error occurred."_s},
38+
{EngineError, u"Engine error."_s},
39+
{TypeMismatch, u"A field value did not match the expected type."_s},
40+
{MissingField, u"An expected field is missing."_s},
41+
};
42+
static inline const QString DATABASE_INFO_TEMPLATE =
43+
u"Connected: %1\n"_s
44+
u"Database Name: %2\n"_s
45+
u"Driver: %3"_s;
46+
47+
//-Instance Variables-------------------------------------------------------------
48+
private:
49+
Form mForm;
50+
QString mCause;
51+
QString mQuery;
52+
QString mDatabase;
53+
54+
//-Class Constructor-------------------------------------------------------------
55+
private:
56+
SqlError(const QString& fromType, const QString& toType, const QString& field = {}); // Convenience for TypeMismatch
57+
58+
public:
59+
SqlError();
60+
SqlError(Form f, const QString& c);
61+
SqlError(const QSqlError& engineError);
62+
63+
//-Instance Functions-------------------------------------------------------------
64+
private:
65+
quint32 deriveValue() const override;
66+
QString derivePrimary() const override;
67+
QString deriveSecondary() const override;
68+
QString deriveDetails() const override;
69+
70+
public:
71+
bool isValid() const;
72+
Form form() const;
73+
QString cause() const;
74+
QString query() const;
75+
QString databaseInfo() const;
76+
77+
SqlError& withQuery(const SqlQuery& q); // Auto-adds database
78+
SqlError& withQuery(const QString& q);
79+
SqlError& withDatabase(const SqlDatabase& db);
80+
};
81+
82+
}
83+
84+
#endif // QX_SQLERROR_H

0 commit comments

Comments
 (0)