source: src/orm/ormrecord.h @ a0f3e32

qt5
Last change on this file since a0f3e32 was a0f3e32, checked in by Philipp Spitzer <philipp@…>, 10 years ago

Added some comments, removed and added some debug information.

  • Property mode set to 100644
File size: 5.8 KB
Line 
1/*
2 * Copyright (C) 2010 Ixonos Plc.
3 *
4 * This file is part of fosdem-schedule.
5 *
6 * fosdem-schedule is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation, either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * fosdem-schedule is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * fosdem-schedule.  If not, see <http://www.gnu.org/licenses/>.
18 */
19#ifndef ORMRECORD_H
20#define ORMRECORD_H
21
22#include <QSqlQuery>
23#include <QSqlRecord>
24#include <QSqlField>
25#include <QSqlError>
26#include <QStringList>
27#include <QDateTime>
28#include <QDebug>
29
30class OrmException
31{
32public:
33    OrmException(const QString& text) : mText(text) {}
34    virtual ~OrmException(){}
35    virtual const QString& text() const { return mText; }
36private:
37    QString mText;
38};
39
40class OrmNoObjectException : public OrmException
41{
42public:
43    OrmNoObjectException() : OrmException("No object exception"){}
44    ~OrmNoObjectException(){}
45};
46
47class OrmSqlException : public OrmException
48{
49public:
50    OrmSqlException(const QString& text) : OrmException( QString("Sql error: ") + text ) {}
51    ~OrmSqlException(){}
52};
53
54template <typename T>
55class OrmRecord : protected QSqlRecord
56{
57public:
58    OrmRecord();
59    static T hydrate(const QSqlRecord& record);
60    void update(QString col, QVariant value = QVariant()); // updates specified column 'col'
61
62protected:
63    QVariant value(QString col) const;
64    void setValue(QString col, QVariant value);
65
66    static T loadOne(QSqlQuery query);
67    static QList<T> load(QSqlQuery query);
68
69    // auxiliary methods
70    static QSqlRecord toRecord(const QList<QSqlField> & columnList);
71    // all record items/columns are in one table
72    static QString columnsForSelect(const QString& prefix = QString());
73    static QString selectQuery();
74    static QString updateQuery();
75
76    static QVariant convertToC(QVariant value, QVariant::Type colType);
77    static QVariant convertToDb(QVariant value, QVariant::Type colType);
78};
79
80template <typename T>
81OrmRecord<T>::OrmRecord()
82{
83    QSqlRecord::operator=(T::sColumns);
84}
85
86template <typename T>
87T OrmRecord<T>::hydrate(const QSqlRecord& record)
88{
89    T object;
90    object.QSqlRecord::operator=(record);
91    return object;
92}
93
94// updates specified column 'col'
95// if the value is not specified  as an argument,
96// it's taken from the reford itself
97// see also: setValue() method for more details
98template <typename T>
99void OrmRecord<T>::update(QString col, QVariant value)
100{
101    QSqlQuery query;
102    query.prepare(QString(updateQuery() + "SET %1 = :col WHERE id = :id").arg(col));
103    if(value.isValid()) // take 'col' value from the method's arguments
104        query.bindValue(":col", value);
105    else // take 'col' value from the record; see setValue()
106        query.bindValue(":col", convertToDb(this->value(col), this->value(col).type()));
107    query.bindValue(":id", this->value("id"));
108    //query.bindValue(":id", convertToDb(value("id"), QVariant::Int));
109    query.exec();
110}
111
112template <typename T>
113QVariant OrmRecord<T>::value(QString col) const
114{
115    return convertToC(QSqlRecord::value(col), T::sColumns.field(col).type());
116}
117
118template <typename T>
119void OrmRecord<T>::setValue(QString col, QVariant value)
120{
121    QSqlRecord::setValue(col, convertToDb(value, T::sColumns.field(col).type()));
122}
123
124template <typename T>
125T OrmRecord<T>::loadOne(QSqlQuery query)
126{
127    if (!query.isActive())
128    {
129        if (!query.exec())
130        {
131            throw OrmSqlException(query.lastError().text());
132        }
133    }
134
135    if (!query.next())
136    {
137        throw OrmNoObjectException();
138    }
139
140    return hydrate(query.record());
141}
142
143template <typename T>
144QList<T> OrmRecord<T>::load(QSqlQuery query)
145{
146    if (!query.isActive())
147    {
148        if (!query.exec())
149        {
150            qDebug() << "Error: " << query.lastError().driverText() << "; Type: " << query.lastError().type();
151            throw OrmSqlException(query.lastError().text());
152        }
153        else
154        {
155            /*qDebug() << "SQL OK";*/
156        }
157    }
158
159    QList<T> objects;
160    while (query.next())
161    {
162        objects << hydrate(query.record());
163    }
164    /*qDebug() << "Fetch done";*/
165    return objects;
166}
167
168template <typename T>
169QString OrmRecord<T>::columnsForSelect(const QString& prefix)
170{
171    QStringList prefixedColumns;
172    for (int i=0; i<T::sColumns.count(); i++)
173    {
174        prefixedColumns.append(prefix.isEmpty() ?
175            T::sColumns.field(i).name() :
176            QString("%1.%2").arg(prefix, T::sColumns.field(i).name()));
177    }
178    return prefixedColumns.join(",");
179}
180
181template <typename T>
182QString OrmRecord<T>::selectQuery()
183{
184    return QString("SELECT %1 FROM %2 ").arg(columnsForSelect(), T::sTableName);
185}
186
187template <typename T>
188QString OrmRecord<T>::updateQuery()
189{
190    return QString("UPDATE %1 ").arg(T::sTableName);
191}
192
193template <typename T>
194QSqlRecord OrmRecord<T>::toRecord(const QList<QSqlField> & columnList)
195{
196    QSqlRecord record;
197    for(int i=0; i< columnList.count(); i++)
198    {
199        record.append(columnList[i]);
200    }
201    return record;
202}
203
204template <typename T>
205QVariant OrmRecord<T>::convertToC(QVariant value, QVariant::Type colType)
206{
207    if (colType == QVariant::DateTime && value.canConvert<uint>())
208    {
209        QDateTime date;
210        date.setTimeSpec(Qt::UTC);
211        date.setTime_t(value.toUInt());
212        return date;
213    }
214
215    return value;
216}
217
218template <typename T>
219QVariant OrmRecord<T>::convertToDb(QVariant value, QVariant::Type colType)
220{
221    if (colType == QVariant::DateTime && value.canConvert<QDateTime>())
222    {
223        return value.toDateTime().toTime_t();
224    }
225
226    return value;
227}
228
229#endif // ORMRECORD_H
230
Note: See TracBrowser for help on using the repository browser.