QDjango
 All Classes Functions Typedefs Enumerations Enumerator Properties Groups Pages
QDjangoQuerySet.h
1 /*
2  * Copyright (C) 2010-2012 Jeremy LainĂ©
3  * Copyright (C) 2011 Mathias Hasselmann
4  * Contact: http://code.google.com/p/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;
300 
301  int count() const;
302  QDjangoWhere where() const;
303 
304  bool remove();
305  int size();
306  int update(const QVariantMap &fields);
307  QList<QVariantMap> values(const QStringList &fields = QStringList());
308  QList<QVariantList> valuesList(const QStringList &fields = QStringList());
309 
310  T *get(const QDjangoWhere &where, T *target = 0) const;
311  T *at(int index, T *target = 0);
312 
313  const_iterator constBegin() const;
314  const_iterator begin() const;
315 
316  const_iterator constEnd() const;
317  const_iterator end() const;
318 
320 
321 private:
322  QDjangoQuerySetPrivate *d;
323 };
324 
327 template <class T>
329 {
330  d = new QDjangoQuerySetPrivate(T::staticMetaObject.className());
331 }
332 
337 template <class T>
339 {
340  other.d->counter.ref();
341  d = other.d;
342 }
343 
346 template <class T>
348 {
349  if (!d->counter.deref())
350  delete d;
351 }
352 
363 template <class T>
364 T *QDjangoQuerySet<T>::at(int index, T *target)
365 {
366  T *entry = target ? target : new T;
367  if (!d->sqlLoad(entry, index))
368  {
369  if (!target)
370  delete entry;
371  return 0;
372  }
373  return entry;
374 }
375 
380 template <class T>
382 {
383  return const_iterator(this);
384 }
385 
390 template <class T>
392 {
393  return const_iterator(this);
394 }
395 
401 template <class T>
403 {
405 }
406 
412 template <class T>
414 {
416 }
417 
420 template <class T>
422 {
423  QDjangoQuerySet<T> other;
424  other.d->lowMark = d->lowMark;
425  other.d->highMark = d->highMark;
426  other.d->orderBy = d->orderBy;
427  other.d->selectRelated = d->selectRelated;
428  other.d->whereClause = d->whereClause;
429  return other;
430 }
431 
441 template <class T>
443 {
444  if (d->hasResults)
445  return d->properties.size();
446  return d->sqlCount();
447 }
448 
459 template <class T>
461 {
462  QDjangoQuerySet<T> other = all();
463  other.d->addFilter(!where);
464  return other;
465 }
466 
477 template <class T>
479 {
480  QDjangoQuerySet<T> other = all();
481  other.d->addFilter(where);
482  return other;
483 }
484 
496 template <class T>
497 T *QDjangoQuerySet<T>::get(const QDjangoWhere &where, T *target) const
498 {
499  QDjangoQuerySet<T> qs = filter(where);
500  return qs.size() == 1 ? qs.at(0, target) : 0;
501 }
502 
515 template <class T>
517 {
518  Q_ASSERT(pos >= 0);
519  Q_ASSERT(length >= -1);
520 
521  QDjangoQuerySet<T> other = all();
522  other.d->lowMark += pos;
523  if (length > 0)
524  {
525  // calculate new high mark
526  other.d->highMark = other.d->lowMark + length;
527  // never exceed the current high mark
528  if (d->highMark > 0 && other.d->highMark > d->highMark)
529  other.d->highMark = d->highMark;
530  }
531  return other;
532 }
533 
536 template <class T>
538 {
539  QDjangoQuerySet<T> other;
540  other.d->whereClause = !QDjangoWhere();
541  return other;
542 }
543 
551 template <class T>
552 QDjangoQuerySet<T> QDjangoQuerySet<T>::orderBy(const QStringList &keys) const
553 {
554  // it is not possible to change ordering once a limit has been set
555  Q_ASSERT(!d->lowMark && !d->highMark);
556 
557  QDjangoQuerySet<T> other = all();
558  other.d->orderBy << keys;
559  return other;
560 }
561 
566 template <class T>
568 {
569  return d->sqlDelete();
570 }
571 
576 template <class T>
578 {
579  QDjangoQuerySet<T> other = all();
580  other.d->selectRelated = true;
581  return other;
582 }
583 
590 template <class T>
592 {
593  if (!d->sqlFetch())
594  return -1;
595  return d->properties.size();
596 }
597 
601 template <class T>
602 int QDjangoQuerySet<T>::update(const QVariantMap &fields)
603 {
604  return d->sqlUpdate(fields);
605 }
606 
612 template <class T>
613 QList<QVariantMap> QDjangoQuerySet<T>::values(const QStringList &fields)
614 {
615  return d->sqlValues(fields);
616 }
617 
624 template <class T>
625 QList<QVariantList> QDjangoQuerySet<T>::valuesList(const QStringList &fields)
626 {
627  return d->sqlValuesList(fields);
628 }
629 
633 template <class T>
635 {
636  return d->resolvedWhere(QDjango::database());
637 }
638 
643 template <class T>
645 {
646  other.d->counter.ref();
647  if (!d->counter.deref())
648  delete d;
649  d = other.d;
650  return *this;
651 }
652 
653 #endif