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>
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;
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;
103  : m_querySet(0)
104  , m_fetched(-1)
105  , m_offset(0)
106  {
107  }
108 
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 
288 
289  QDjangoQuerySet();
290  QDjangoQuerySet(const QDjangoQuerySet<T> &other);
292 
293  QDjangoQuerySet all() 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 
321 
322 private:
323  QDjangoQuerySetPrivate *d;
324 };
325 
328 template <class T>
330 {
331  d = new QDjangoQuerySetPrivate(T::staticMetaObject.className());
332 }
333 
338 template <class T>
340 {
341  other.d->counter.ref();
342  d = other.d;
343 }
344 
347 template <class T>
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>
383 {
384  return const_iterator(this);
385 }
386 
391 template <class T>
393 {
394  return const_iterator(this);
395 }
396 
402 template <class T>
404 {
406 }
407 
413 template <class T>
415 {
417 }
418 
421 template <class T>
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>
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>
479 {
480  QDjangoQuerySet<T> other = all();
481  other.d->addFilter(!where);
482  return other;
483 }
484 
495 template <class T>
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 {
518  return qs.size() == 1 ? qs.at(0, target) : 0;
519 }
520 
533 template <class T>
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>
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>
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>
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>
660 {
661  return d->resolvedWhere(QDjango::database());
662 }
663 
668 template <class T>
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