source: src/orm/ormrecord.h @ 5d22816

qt5
Last change on this file since 5d22816 was 5d22816, checked in by pavelpa <pavelpa@…>, 12 years ago

GUI changes for N810 device

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