Nut  0.1
query.h
1 /**************************************************************************
2 **
3 ** This file is part of Nut project.
4 ** https://github.com/HamedMasafi/Nut
5 **
6 ** Nut is free software: you can redistribute it and/or modify
7 ** it under the terms of the GNU Lesser General Public License as published by
8 ** the Free Software Foundation, either version 3 of the License, or
9 ** (at your option) any later version.
10 **
11 ** Nut is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU Lesser General Public License for more details.
15 **
16 ** You should have received a copy of the GNU Lesser General Public License
17 ** along with Nut. If not, see <http://www.gnu.org/licenses/>.
18 **
19 **************************************************************************/
20 
21 #ifndef QUERY_H
22 #define QUERY_H
23 
24 #include <QtCore/QVariant>
25 #include <QtCore/QDebug>
26 #include <QtCore/QScopedPointer>
27 #include <QtCore/QRegularExpression>
28 
29 #include "query_p.h"
30 #include "database.h"
31 #include "databasemodel.h"
32 #include "tablesetbase_p.h"
33 #include "sqlgeneratorbase_p.h"
34 #include "querybase_p.h"
35 #include "wherephrase.h"
36 
37 QT_BEGIN_NAMESPACE
38 
39 template<class T>
40 class NUT_EXPORT Query : public QueryBase
41 {
42  QueryPrivate *d_ptr;
43  Q_DECLARE_PRIVATE(Query)
44 
45 public:
46  Query(Database *database, TableSetBase *tableSet);
47  ~Query();
48 
49  QList<T *> toList(int count = -1);
50  int remove();
51  T *first();
52 
53  int count();
54 
55  QVariant max(FieldPhrase &f);
56  QVariant min(FieldPhrase &f);
57  QVariant average(FieldPhrase &f){
58  //TODO: ...
59  return QVariant();
60  }
61 
62  Query<T> *join(const QString &tableName);
63  Query<T> *setWhere(WherePhrase where);
64 
65  Query<T> *join(Table *c){
66  join(c->metaObject()->className());
67  return this;
68  }
69 
70 // Query<T> *setWhere(const QString &where);
71  Query<T> *orderBy(QString fieldName, QString type);
72  Query<T> *orderBy(WherePhrase phrase);
73 };
74 
75 template<class T>
76 Q_OUTOFLINE_TEMPLATE Query<T>::Query(Database *database, TableSetBase *tableSet) : QueryBase(database),
77  d_ptr(new QueryPrivate(this))
78 {
79  Q_D(Query);
80 
81  d->database = database;
82  d->tableSet = tableSet;
83  d->tableName = d->database->tableName(T::staticMetaObject.className());
84 }
85 
86 template<class T>
87 Q_OUTOFLINE_TEMPLATE Query<T>::~Query()
88 {
89  qDebug() << "Query::~Query()";
90  Q_D(Query);
91  delete d;
92 }
93 
94 template<class T>
95 Q_OUTOFLINE_TEMPLATE QList<T *> Query<T>::toList(int count)
96 {
97  Q_D(Query);
98  QList<T*> result;
99  d->select = "*";
100 
101 // QSqlQuery q = d->database->exec(d->database->sqlGenertor()->selectCommand(d->wheres, d->orders, d->tableName, d->joinClassName));
102  QSqlQuery q = d->database->exec(d->database->sqlGenertor()->selectCommand(
103  SqlGeneratorBase::SelectALl,
104  "",
105  d->wheres,
106  d->orderPhrases,
107  d->tableName,
108  d->joinClassName));
109 
110  QString pk =d->database->model().model(d->tableName)->primaryKey();
111  QVariant lastPkValue = QVariant();
112  int childTypeId = 0;
113  T *lastRow = 0;
114  TableSetBase *childTableSet;
115  QStringList masterFields = d->database->model().model(d->tableName)->fieldsNames();
116  QStringList childFields;
117  if(!d->joinClassName.isNull())
118  if(d->database->model().modelByClass(d->joinClassName)){
119  childFields = d->database->model().modelByClass(d->joinClassName)->fieldsNames();
120  QString joinTableName = d->database->tableName(d->joinClassName);
121  childTypeId = d->database->model().model(joinTableName)->typeId();
122  }
123 
124  while (q.next()) {
125  if(lastPkValue != q.value(pk)){
126  T *t = new T();
127 
128  foreach (QString field, masterFields)
129  t->setProperty(field.toLatin1().data(), q.value(field));
130 
131  t->setTableSet(d->tableSet);
132  t->setStatus(Table::FeatchedFromDB);
133  t->setParent(this);
134 
135  result.append(t);
136  lastRow = t;
137 
138  if(childTypeId){
139  QSet<TableSetBase*> tableSets = t->tableSets;
140  foreach (TableSetBase *ts, tableSets)
141  if(ts->childClassName() == d->joinClassName)
142  childTableSet = ts;
143  }
144  }
145 
146  if(childTypeId){
147  const QMetaObject *childMetaObject = QMetaType::metaObjectForType(childTypeId);
148  Table *childTable = qobject_cast<Table*>(childMetaObject->newInstance());
149 
150  foreach (QString field, childFields)
151  childTable->setProperty(field.toLatin1().data(), q.value(field));
152 
153  childTable->setParent(this);
154  childTable->setParentTable(lastRow);
155  childTable->setStatus(Table::FeatchedFromDB);
156  childTable->setTableSet(childTableSet);
157  childTableSet->add(childTable);
158  }
159  lastPkValue = q.value(pk);
160 
161  if(!--count)
162  break;
163  }
164 
165  deleteLater();
166  return result;
167 }
168 
169 template<class T>
170 Q_OUTOFLINE_TEMPLATE T *Query<T>::first()
171 {
172  QList<T *> list = toList(1);
173 
174  if(list.count())
175  return list.first();
176  else
177  return 0;
178 }
179 
180 template<class T>
181 Q_OUTOFLINE_TEMPLATE int Query<T>::count()
182 {
183  Q_D(Query);
184 
185  d->select = "COUNT(*)";
186  QSqlQuery q = d->database->exec(d->database->sqlGenertor()->selectCommand("COUNT(*)", d->wheres, d->orders, d->tableName, d->joinClassName));
187 
188  if(q.next())
189  return q.value(0).toInt();
190  return 0;
191 }
192 
193 template<class T>
194 Q_OUTOFLINE_TEMPLATE QVariant Query<T>::max(FieldPhrase &f){
195  Q_D(Query);
196 
197  QSqlQuery q = d->database->exec(d->database->sqlGenertor()->selectCommand("MAX(" + f.data()->text + ")", d->wheres, d->orders, d->tableName, d->joinClassName));
198 
199  if(q.next())
200  return q.value(0).toInt();
201  return 0;
202 }
203 
204 template<class T>
205 Q_OUTOFLINE_TEMPLATE QVariant Query<T>::min(FieldPhrase &f){
206  Q_D(Query);
207 
208  QSqlQuery q = d->database->exec(d->database->sqlGenertor()->selectCommand("MIN(" + f.data()->text + ")", d->wheres, d->orders, d->tableName, d->joinClassName));
209 
210  if(q.next())
211  return q.value(0).toInt();
212  return 0;
213 }
214 
215 template<class T>
216 Q_OUTOFLINE_TEMPLATE int Query<T>::remove()
217 {
218  Q_D(Query);
219 
220  QString sql = d->database->sqlGenertor()->deleteCommand(d->wheres, d->tableName);
221 // d->_database->sqlGenertor()->deleteRecords(_tableName, queryText());
222 // sql = compileCommand(sql);
223  QSqlQuery q = d->database->exec(sql);
224  return q.numRowsAffected();
225 }
226 
227 template<class T>
228 Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::join(const QString &tableName)
229 {
230  Q_D(Query);
231  d->joinClassName = tableName;
232  return this;
233 }
234 
235 template<class T>
236 Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::setWhere(WherePhrase where)
237 {
238  Q_D(Query);
239  d->wheres.append(where);
240  return this;
241 }
242 
243 template<class T>
244 Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::orderBy(QString fieldName, QString type)
245 {
246  Q_D(Query);
247  d->orders.insert(fieldName, type);
248  return this;
249 }
250 
251 template<class T>
252 Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::orderBy(WherePhrase phrase)
253 {
254  Q_D(Query);
255  d->orderPhrases.append(phrase);
256  return this;
257 }
258 
259 QT_END_NAMESPACE
260 
261 #endif // QUERY_H