QDjango: QDjangoQuerySet.h Source File

QDjango

QDjangoQuerySet.h
1 /*
2 * Copyright (C) 2010-2015 Jeremy Lainé
3 * Copyright (C) 2011 Mathias Hasselmann
4 * Contact: https://github.com/jlaine/qdjango
5 *
6 * This file is part of the QDjango Library.
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 */
18
19 #ifndef QDJANGO_QUERYSET_H
20 #define QDJANGO_QUERYSET_H
21
22 #include "QDjango.h"
23 #include "QDjangoWhere.h"
24 #include "QDjangoQuerySet_p.h"
25
45 template <class T>
46 class QDjangoQuerySet
47 {
48 public:
50 typedef int size_type;
51 typedef T value_type;
52 typedef value_type *pointer;
53 typedef const value_type *const_pointer;
54 typedef value_type &reference;
55 typedef const value_type &const_reference;
56 typedef qptrdiff difference_type;
78 class const_iterator
79 {
80 friend class QDjangoQuerySet;
81
82 public:
86 typedef std::bidirectional_iterator_tag iterator_category;
87
89 typedef qptrdiff difference_type;
90 typedef T value_type;
91 typedef T *pointer;
92 typedef T &reference;
102 const_iterator()
103 : m_querySet(0)
104 , m_fetched(-1)
105 , m_offset(0)
106 {
107 }
108
111 const_iterator(const const_iterator &other)
112 : m_querySet(other.m_querySet)
113 , m_fetched(-1)
114 , m_offset(other.m_offset)
115 {
116 }
117
118 private:
119 const_iterator(const QDjangoQuerySet<T> *querySet, int offset = 0)
120 : m_querySet(querySet)
121 , m_fetched(-1)
122 , m_offset(offset)
123 {
124 }
125
126 public:
131 const T &operator*() const { return *t(); }
132
137 const T *operator->() const { return t(); }
138
139
145 bool operator==(const const_iterator &other) const
146 {
147 return m_querySet == other.m_querySet && m_offset == other.m_offset;
148 }
149
155 bool operator!=(const const_iterator &other) const
156 {
157 return m_querySet != other.m_querySet || m_offset != other.m_offset;
158 }
159
163 bool operator<(const const_iterator& other) const
164 {
165 return (m_querySet == other.m_querySet && m_offset < other.m_offset)
166 || m_querySet < other.m_querySet;
167 }
168
172 bool operator<=(const const_iterator& other) const
173 {
174 return (m_querySet == other.m_querySet && m_offset <= other.m_offset)
175 || m_querySet < other.m_querySet;
176 }
177
181 bool operator>(const const_iterator& other) const
182 {
183 return (m_querySet == other.m_querySet && m_offset > other.m_offset)
184 || m_querySet > other.m_querySet;
185 }
186
190 bool operator>=(const const_iterator& other) const
191 {
192 return (m_querySet == other.m_querySet && m_offset >= other.m_offset)
193 || m_querySet > other.m_querySet;
194 }
195
203 const_iterator &operator++() { ++m_offset; return *this; }
204
212 const_iterator operator++(int) { const_iterator n(*this); ++m_offset; return n; }
213
219 const_iterator &operator+=(int i) { m_offset += i; return *this; }
220
226 const_iterator operator+(int i) const { return const_iterator(m_querySet, m_offset + i); }
227
233 const_iterator &operator-=(int i) { m_offset -= i; return *this; }
234
240 const_iterator operator-(int i) const { return const_iterator(m_querySet, m_offset - i); }
241
249 const_iterator &operator--() { --m_offset; return *this; }
250
258 const_iterator operator--(int) { const_iterator n(*this); --m_offset; return n; }
259
260
264 difference_type operator-(const const_iterator &other) const { return m_offset - other.m_offset; }
265
266 private:
267 const T *t() const
268 {
269 if (m_fetched != m_offset && m_querySet) {
270 if (const_cast<QDjangoQuerySet<T> *>(m_querySet)->at(m_offset, &m_object)) {
271 m_fetched = m_offset;
272 }
273 }
274
275 return m_fetched == m_offset ? &m_object : 0;
276 }
277
278 private:
279 const QDjangoQuerySet<T> *m_querySet;
280 mutable int m_fetched;
281 mutable T m_object;
282
283 int m_offset;
284 };
285
287 typedef const_iterator ConstIterator;
288
289 QDjangoQuerySet();
290 QDjangoQuerySet(const QDjangoQuerySet<T> &other);
291 ~QDjangoQuerySet();
292
293 QDjangoQuerySet all() const;
294 QDjangoQuerySet exclude(const QDjangoWhere &where) const;
295 QDjangoQuerySet filter(const QDjangoWhere &where) const;
296 QDjangoQuerySet limit(int pos, int length = -1) const;
297 QDjangoQuerySet none() const;
298 QDjangoQuerySet orderBy(const QStringList &keys) const;
299 QDjangoQuerySet selectRelated(const QStringList &relatedFields = QStringList()) const;
300
301 int count() const;
302 QVariant aggregate(const QDjangoWhere::AggregateType func, const QString& field) const;
303 QDjangoWhere where() const;
304
305 bool remove();
306 int size();
307 int update(const QVariantMap &fields);
308 QList<QVariantMap> values(const QStringList &fields = QStringList());
309 QList<QVariantList> valuesList(const QStringList &fields = QStringList());
310
311 T *get(const QDjangoWhere &where, T *target = 0) const;
312 T *at(int index, T *target = 0);
313
314 const_iterator constBegin() const;
315 const_iterator begin() const;
316
317 const_iterator constEnd() const;
318 const_iterator end() const;
319
320 QDjangoQuerySet<T> &operator=(const QDjangoQuerySet<T> &other);
321
322 private:
323 QDjangoQuerySetPrivate *d;
324 };
325
328 template <class T>
329 QDjangoQuerySet<T>::QDjangoQuerySet()
330 {
331 d = new QDjangoQuerySetPrivate(T::staticMetaObject.className());
332 }
333
338 template <class T>
339 QDjangoQuerySet<T>::QDjangoQuerySet(const QDjangoQuerySet<T> &other)
340 {
341 other.d->counter.ref();
342 d = other.d;
343 }
344
347 template <class T>
348 QDjangoQuerySet<T>::~QDjangoQuerySet()
349 {
350 if (!d->counter.deref())
351 delete d;
352 }
353
364 template <class T>
365 T *QDjangoQuerySet<T>::at(int index, T *target)
366 {
367 T *entry = target ? target : new T;
368 if (!d->sqlLoad(entry, index))
369 {
370 if (!target)
371 delete entry;
372 return 0;
373 }
374 return entry;
375 }
376
381 template <class T>
382 typename QDjangoQuerySet<T>::const_iterator QDjangoQuerySet<T>::constBegin() const
383 {
384 return const_iterator(this);
385 }
386
391 template <class T>
392 typename QDjangoQuerySet<T>::const_iterator QDjangoQuerySet<T>::begin() const
393 {
394 return const_iterator(this);
395 }
396
402 template <class T>
403 typename QDjangoQuerySet<T>::const_iterator QDjangoQuerySet<T>::constEnd() const
404 {
405 return const_iterator(this, QDjangoQuerySet<T>::count());
406 }
407
413 template <class T>
414 typename QDjangoQuerySet<T>::const_iterator QDjangoQuerySet<T>::end() const
415 {
416 return const_iterator(this, QDjangoQuerySet<T>::count());
417 }
418
421 template <class T>
422 QDjangoQuerySet<T> QDjangoQuerySet<T>::all() const
423 {
424 QDjangoQuerySet<T> other;
425 other.d->lowMark = d->lowMark;
426 other.d->highMark = d->highMark;
427 other.d->orderBy = d->orderBy;
428 other.d->selectRelated = d->selectRelated;
429 other.d->relatedFields = d->relatedFields;
430 other.d->whereClause = d->whereClause;
431 return other;
432 }
433
443 template <class T>
444 int QDjangoQuerySet<T>::count() const
445 {
446 if (d->hasResults)
447 return d->properties.size();
448
449 QVariant count(aggregate(QDjangoWhere::COUNT,"*"));
450 return count.isValid() ? count.toInt() : -1;
451 }
452
457 template <class T>
458 QVariant QDjangoQuerySet<T>::aggregate(const QDjangoWhere::AggregateType func, const QString& field) const
459 {
460 // execute aggregate query
461 QDjangoQuery query(d->aggregateQuery(func, field));
462 if (!query.exec() || !query.next())
463 return QVariant();
464 return query.value(0);
465 }
466
477 template <class T>
478 QDjangoQuerySet<T> QDjangoQuerySet<T>::exclude(const QDjangoWhere &where) const
479 {
480 QDjangoQuerySet<T> other = all();
481 other.d->addFilter(!where);
482 return other;
483 }
484
495 template <class T>
496 QDjangoQuerySet<T> QDjangoQuerySet<T>::filter(const QDjangoWhere &where) const
497 {
498 QDjangoQuerySet<T> other = all();
499 other.d->addFilter(where);
500 return other;
501 }
502
514 template <class T>
515 T *QDjangoQuerySet<T>::get(const QDjangoWhere &where, T *target) const
516 {
517 QDjangoQuerySet<T> qs = filter(where);
518 return qs.size() == 1 ? qs.at(0, target) : 0;
519 }
520
533 template <class T>
534 QDjangoQuerySet<T> QDjangoQuerySet<T>::limit(int pos, int length) const
535 {
536 Q_ASSERT(pos >= 0);
537 Q_ASSERT(length >= -1);
538
539 QDjangoQuerySet<T> other = all();
540 other.d->lowMark += pos;
541 if (length > 0)
542 {
543 // calculate new high mark
544 other.d->highMark = other.d->lowMark + length;
545 // never exceed the current high mark
546 if (d->highMark > 0 && other.d->highMark > d->highMark)
547 other.d->highMark = d->highMark;
548 }
549 return other;
550 }
551
554 template <class T>
555 QDjangoQuerySet<T> QDjangoQuerySet<T>::none() const
556 {
557 QDjangoQuerySet<T> other;
558 other.d->whereClause = !QDjangoWhere();
559 return other;
560 }
561
569 template <class T>
570 QDjangoQuerySet<T> QDjangoQuerySet<T>::orderBy(const QStringList &keys) const
571 {
572 // it is not possible to change ordering once a limit has been set
573 Q_ASSERT(!d->lowMark && !d->highMark);
574
575 QDjangoQuerySet<T> other = all();
576 other.d->orderBy << keys;
577 return other;
578 }
579
584 template <class T>
585 bool QDjangoQuerySet<T>::remove()
586 {
587 return d->sqlDelete();
588 }
589
600 template <class T>
601 QDjangoQuerySet<T> QDjangoQuerySet<T>::selectRelated(const QStringList &relatedFields) const
602 {
603 QDjangoQuerySet<T> other = all();
604 other.d->selectRelated = true;
605 other.d->relatedFields = relatedFields;
606 return other;
607 }
608
615 template <class T>
616 int QDjangoQuerySet<T>::size()
617 {
618 if (!d->sqlFetch())
619 return -1;
620 return d->properties.size();
621 }
622
626 template <class T>
627 int QDjangoQuerySet<T>::update(const QVariantMap &fields)
628 {
629 return d->sqlUpdate(fields);
630 }
631
637 template <class T>
638 QList<QVariantMap> QDjangoQuerySet<T>::values(const QStringList &fields)
639 {
640 return d->sqlValues(fields);
641 }
642
649 template <class T>
650 QList<QVariantList> QDjangoQuerySet<T>::valuesList(const QStringList &fields)
651 {
652 return d->sqlValuesList(fields);
653 }
654
658 template <class T>
659 QDjangoWhere QDjangoQuerySet<T>::where() const
660 {
661 return d->resolvedWhere(QDjango::database());
662 }
663
668 template <class T>
669 QDjangoQuerySet<T> &QDjangoQuerySet<T>::operator=(const QDjangoQuerySet<T> &other)
670 {
671 other.d->counter.ref();
672 if (!d->counter.deref())
673 delete d;
674 d = other.d;
675 return *this;
676 }
677
678 #endif
QDjangoQuerySet::constEnd
const_iterator constEnd() const
Definition: QDjangoQuerySet.h:403
QDjangoQuerySet::const_iterator::iterator_category
std::bidirectional_iterator_tag iterator_category
Definition: QDjangoQuerySet.h:86
QDjangoQuerySet::const_iterator::operator+
const_iterator operator+(int i) const
Definition: QDjangoQuerySet.h:226
QDjangoWhere
The QDjangoWhere class expresses an SQL constraint.
Definition: QDjangoWhere.h:41
QDjangoQuerySet::const_iterator::operator<=
bool operator<=(const const_iterator &other) const
Definition: QDjangoQuerySet.h:172
QDjangoQuerySet::const_iterator
Definition: QDjangoQuerySet.h:79
QDjangoQuerySet::const_iterator::operator++
const_iterator operator++(int)
Definition: QDjangoQuerySet.h:212
QDjangoQuerySet::operator=
QDjangoQuerySet< T > & operator=(const QDjangoQuerySet< T > &other)
Definition: QDjangoQuerySet.h:669
QDjangoQuerySet::ConstIterator
const_iterator ConstIterator
Definition: QDjangoQuerySet.h:287
QDjangoQuerySet::remove
bool remove()
Definition: QDjangoQuerySet.h:585
QDjangoQuerySet::const_iterator::operator!=
bool operator!=(const const_iterator &other) const
Definition: QDjangoQuerySet.h:155
QDjangoQuerySet::const_iterator::operator<
bool operator<(const const_iterator &other) const
Definition: QDjangoQuerySet.h:163
QDjangoQuerySet::where
QDjangoWhere where() const
Definition: QDjangoQuerySet.h:659
QDjangoQuerySet::const_iterator::operator-=
const_iterator & operator-=(int i)
Definition: QDjangoQuerySet.h:233
QDjangoQuerySet::update
int update(const QVariantMap &fields)
Definition: QDjangoQuerySet.h:627
QDjangoQuerySet::const_iterator::operator--
const_iterator operator--(int)
Definition: QDjangoQuerySet.h:258
QDjangoQuerySet::const_iterator::operator>=
bool operator>=(const const_iterator &other) const
Definition: QDjangoQuerySet.h:190
QDjangoQuerySet::const_iterator::operator-
difference_type operator-(const const_iterator &other) const
Definition: QDjangoQuerySet.h:264
QDjangoQuerySet::const_iterator::operator*
const T & operator*() const
Definition: QDjangoQuerySet.h:131
QDjangoQuerySet::const_iterator::const_iterator
const_iterator(const const_iterator &other)
Definition: QDjangoQuerySet.h:111
QDjangoQuerySet::const_iterator::operator--
const_iterator & operator--()
Definition: QDjangoQuerySet.h:249
QDjango::database
static QSqlDatabase database()
Returns the database used by QDjango.
Definition: QDjango.cpp:167
QDjangoQuerySet::selectRelated
QDjangoQuerySet selectRelated(const QStringList &relatedFields=QStringList()) const
Definition: QDjangoQuerySet.h:601
QDjangoQuerySet::exclude
QDjangoQuerySet exclude(const QDjangoWhere &where) const
Definition: QDjangoQuerySet.h:478
QDjangoQuerySet::values
QList< QVariantMap > values(const QStringList &fields=QStringList())
Definition: QDjangoQuerySet.h:638
QDjangoQuerySet::const_iterator::operator>
bool operator>(const const_iterator &other) const
Definition: QDjangoQuerySet.h:181
QDjangoQuerySet::none
QDjangoQuerySet none() const
Definition: QDjangoQuerySet.h:555
QDjangoQuerySet::filter
QDjangoQuerySet filter(const QDjangoWhere &where) const
Definition: QDjangoQuerySet.h:496
QDjangoQuerySet::size
int size()
Definition: QDjangoQuerySet.h:616
QDjangoQuerySet::orderBy
QDjangoQuerySet orderBy(const QStringList &keys) const
Definition: QDjangoQuerySet.h:570
QDjangoQuerySet
The QDjangoQuerySet class is a template class for performing database queries.
Definition: QDjangoQuerySet.h:47
QDjangoQuerySet::const_iterator::operator+=
const_iterator & operator+=(int i)
Definition: QDjangoQuerySet.h:219
QDjangoQuerySet::count
int count() const
Definition: QDjangoQuerySet.h:444
QDjangoQuerySet::end
const_iterator end() const
Definition: QDjangoQuerySet.h:414
QDjangoQuerySet::QDjangoQuerySet
QDjangoQuerySet()
Definition: QDjangoQuerySet.h:329
QDjangoQuerySet::const_iterator::operator-
const_iterator operator-(int i) const
Definition: QDjangoQuerySet.h:240
QDjangoQuerySet::const_iterator::operator==
bool operator==(const const_iterator &other) const
Definition: QDjangoQuerySet.h:145
QDjangoQuerySet::const_iterator::operator++
const_iterator & operator++()
Definition: QDjangoQuerySet.h:203
QDjangoQuerySet::~QDjangoQuerySet
~QDjangoQuerySet()
Definition: QDjangoQuerySet.h:348
QDjangoQuerySet::const_iterator::const_iterator
const_iterator()
Definition: QDjangoQuerySet.h:102
QDjangoQuerySet::const_iterator::operator->
const T * operator->() const
Definition: QDjangoQuerySet.h:137
QDjangoQuerySet::all
QDjangoQuerySet all() const
Definition: QDjangoQuerySet.h:422
QDjangoQuerySet::aggregate
QVariant aggregate(const QDjangoWhere::AggregateType func, const QString &field) const
Definition: QDjangoQuerySet.h:458
QDjangoQuerySet::get
T * get(const QDjangoWhere &where, T *target=0) const
Definition: QDjangoQuerySet.h:515
QDjangoQuerySet::begin
const_iterator begin() const
Definition: QDjangoQuerySet.h:392
QDjangoQuerySet::valuesList
QList< QVariantList > valuesList(const QStringList &fields=QStringList())
Definition: QDjangoQuerySet.h:650
QDjangoQuerySet::constBegin
const_iterator constBegin() const
Definition: QDjangoQuerySet.h:382
QDjangoQuerySet::at
T * at(int index, T *target=0)
Definition: QDjangoQuerySet.h:365
QDjangoQuerySet::limit
QDjangoQuerySet limit(int pos, int length=-1) const
Definition: QDjangoQuerySet.h:534