QDjango
QDjangoQuerySet.h
00001 /*
00002  * Copyright (C) 2010-2012 Jeremy Lainé
00003  * Copyright (C) 2011 Mathias Hasselmann
00004  * Contact: http://code.google.com/p/qdjango/
00005  *
00006  * This file is part of the QDjango Library.
00007  *
00008  * This library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  */
00018 
00019 #ifndef QDJANGO_QUERYSET_H
00020 #define QDJANGO_QUERYSET_H
00021 
00022 #include "QDjango.h"
00023 #include "QDjangoWhere.h"
00024 #include "QDjangoQuerySet_p.h"
00025 
00045 template <class T>
00046     class QDjangoQuerySet
00047 {
00048 public:
00050     typedef int size_type;
00051     typedef T value_type;
00052     typedef value_type *pointer;
00053     typedef const value_type *const_pointer;
00054     typedef value_type &reference;
00055     typedef const value_type &const_reference;
00056     typedef qptrdiff difference_type;
00078     class const_iterator
00079     {
00080         friend class QDjangoQuerySet;
00081 
00082     public:
00086         typedef std::bidirectional_iterator_tag  iterator_category;
00087 
00089         typedef qptrdiff difference_type;
00090         typedef T value_type;
00091         typedef T *pointer;
00092         typedef T &reference;
00102         const_iterator()
00103             : m_querySet(0)
00104             , m_fetched(-1)
00105             , m_offset(0)
00106         {
00107         }
00108 
00111         const_iterator(const const_iterator &other)
00112             : m_querySet(other.m_querySet)
00113             , m_fetched(-1)
00114             , m_offset(other.m_offset)
00115         {
00116         }
00117 
00118     private:
00119         const_iterator(const QDjangoQuerySet<T> *querySet, int offset = 0)
00120             : m_querySet(querySet)
00121             , m_fetched(-1)
00122             , m_offset(offset)
00123         {
00124         }
00125 
00126     public:
00131         const T &operator*() const { return *t(); }
00132 
00137         const T *operator->() const { return t(); }
00138 
00139 
00145         bool operator==(const const_iterator &other) const
00146         {
00147             return m_querySet == other.m_querySet && m_offset == other.m_offset;
00148         }
00149 
00155         bool operator!=(const const_iterator &other) const
00156         {
00157             return m_querySet != other.m_querySet || m_offset != other.m_offset;
00158         }
00159 
00163         bool operator<(const const_iterator& other) const
00164         {
00165             return (m_querySet == other.m_querySet && m_offset < other.m_offset)
00166                     || m_querySet < other.m_querySet;
00167         }
00168 
00172         bool operator<=(const const_iterator& other) const
00173         {
00174             return (m_querySet == other.m_querySet && m_offset <= other.m_offset)
00175                     || m_querySet < other.m_querySet;
00176         }
00177 
00181         bool operator>(const const_iterator& other) const
00182         {
00183             return (m_querySet == other.m_querySet && m_offset > other.m_offset)
00184                     || m_querySet > other.m_querySet;
00185         }
00186 
00190         bool operator>=(const const_iterator& other) const
00191         {
00192             return (m_querySet == other.m_querySet && m_offset >= other.m_offset)
00193                     || m_querySet > other.m_querySet;
00194         }
00195 
00203         const_iterator &operator++() { ++m_offset; return *this; }
00204 
00212         const_iterator operator++(int) { const_iterator n(*this); ++m_offset; return n; }
00213 
00219         const_iterator &operator+=(int i) { m_offset += i; return *this; }
00220 
00226         const_iterator operator+(int i) const { return const_iterator(m_querySet, m_offset + i); }
00227 
00233         const_iterator &operator-=(int i) { m_offset -= i; return *this; }
00234 
00240         const_iterator operator-(int i) const { return const_iterator(m_querySet, m_offset - i); }
00241 
00249         const_iterator &operator--() { --m_offset; return *this; }
00250 
00258         const_iterator operator--(int) { const_iterator n(*this); --m_offset; return n; }
00259 
00260 
00264         difference_type operator-(const const_iterator &other) const { return m_offset - other.m_offset; }
00265 
00266     private:
00267         const T *t() const
00268         {
00269             if (m_fetched != m_offset && m_querySet) {
00270                 if (const_cast<QDjangoQuerySet<T> *>(m_querySet)->at(m_offset, &m_object)) {
00271                     m_fetched = m_offset;
00272                 }
00273             }
00274 
00275             return m_fetched == m_offset ? &m_object : 0;
00276         }
00277 
00278     private:
00279         const QDjangoQuerySet<T> *m_querySet;
00280         mutable int m_fetched;
00281         mutable T m_object;
00282 
00283         int m_offset;
00284     };
00285 
00287     typedef const_iterator ConstIterator;
00288 
00289     QDjangoQuerySet();
00290     QDjangoQuerySet(const QDjangoQuerySet<T> &other);
00291     ~QDjangoQuerySet();
00292 
00293     QDjangoQuerySet all() const;
00294     QDjangoQuerySet exclude(const QDjangoWhere &where) const;
00295     QDjangoQuerySet filter(const QDjangoWhere &where) const;
00296     QDjangoQuerySet limit(int pos, int length = -1) const;
00297     QDjangoQuerySet none() const;
00298     QDjangoQuerySet orderBy(const QStringList &keys) const;
00299     QDjangoQuerySet selectRelated() const;
00300 
00301     int count() const;
00302     QDjangoWhere where() const;
00303 
00304     bool remove();
00305     int size();
00306     int update(const QVariantMap &fields);
00307     QList<QVariantMap> values(const QStringList &fields = QStringList());
00308     QList<QVariantList> valuesList(const QStringList &fields = QStringList());
00309 
00310     T *get(const QDjangoWhere &where, T *target = 0) const;
00311     T *at(int index, T *target = 0);
00312 
00313     const_iterator constBegin() const;
00314     const_iterator begin() const;
00315 
00316     const_iterator constEnd() const;
00317     const_iterator end() const;
00318 
00319     QDjangoQuerySet<T> &operator=(const QDjangoQuerySet<T> &other);
00320 
00321 private:
00322     QDjangoQuerySetPrivate *d;
00323 };
00324 
00327 template <class T>
00328 QDjangoQuerySet<T>::QDjangoQuerySet()
00329 {
00330     d = new QDjangoQuerySetPrivate(T::staticMetaObject.className());
00331 }
00332 
00337 template <class T>
00338 QDjangoQuerySet<T>::QDjangoQuerySet(const QDjangoQuerySet<T> &other)
00339 {
00340     other.d->counter.ref();
00341     d = other.d;
00342 }
00343 
00346 template <class T>
00347 QDjangoQuerySet<T>::~QDjangoQuerySet()
00348 {
00349     if (!d->counter.deref())
00350         delete d;
00351 }
00352 
00363 template <class T>
00364 T *QDjangoQuerySet<T>::at(int index, T *target)
00365 {
00366     T *entry = target ? target : new T;
00367     if (!d->sqlLoad(entry, index))
00368     {
00369         if (!target)
00370             delete entry;
00371         return 0;
00372     }
00373     return entry;
00374 }
00375 
00380 template <class T>
00381 typename QDjangoQuerySet<T>::const_iterator QDjangoQuerySet<T>::constBegin() const
00382 {
00383     return const_iterator(this);
00384 }
00385 
00390 template <class T>
00391 typename QDjangoQuerySet<T>::const_iterator QDjangoQuerySet<T>::begin() const
00392 {
00393     return const_iterator(this);
00394 }
00395 
00401 template <class T>
00402 typename QDjangoQuerySet<T>::const_iterator QDjangoQuerySet<T>::constEnd() const
00403 {
00404     return const_iterator(this, QDjangoQuerySet<T>::count());
00405 }
00406 
00412 template <class T>
00413 typename QDjangoQuerySet<T>::const_iterator QDjangoQuerySet<T>::end() const
00414 {
00415     return const_iterator(this, QDjangoQuerySet<T>::count());
00416 }
00417 
00420 template <class T>
00421 QDjangoQuerySet<T> QDjangoQuerySet<T>::all() const
00422 {
00423     QDjangoQuerySet<T> other;
00424     other.d->lowMark = d->lowMark;
00425     other.d->highMark = d->highMark;
00426     other.d->orderBy = d->orderBy;
00427     other.d->selectRelated = d->selectRelated;
00428     other.d->whereClause = d->whereClause;
00429     return other;
00430 }
00431 
00441 template <class T>
00442 int QDjangoQuerySet<T>::count() const
00443 {
00444     if (d->hasResults)
00445         return d->properties.size();
00446     return d->sqlCount();
00447 }
00448 
00459 template <class T>
00460 QDjangoQuerySet<T> QDjangoQuerySet<T>::exclude(const QDjangoWhere &where) const
00461 {
00462     QDjangoQuerySet<T> other = all();
00463     other.d->addFilter(!where);
00464     return other;
00465 }
00466 
00477 template <class T>
00478 QDjangoQuerySet<T> QDjangoQuerySet<T>::filter(const QDjangoWhere &where) const
00479 {
00480     QDjangoQuerySet<T> other = all();
00481     other.d->addFilter(where);
00482     return other;
00483 }
00484 
00496 template <class T>
00497 T *QDjangoQuerySet<T>::get(const QDjangoWhere &where, T *target) const
00498 {
00499     QDjangoQuerySet<T> qs = filter(where);
00500     return qs.size() == 1 ? qs.at(0, target) : 0;
00501 }
00502 
00515 template <class T>
00516 QDjangoQuerySet<T> QDjangoQuerySet<T>::limit(int pos, int length) const
00517 {
00518     Q_ASSERT(pos >= 0);
00519     Q_ASSERT(length >= -1);
00520 
00521     QDjangoQuerySet<T> other = all();
00522     other.d->lowMark += pos;
00523     if (length > 0)
00524     {
00525         // calculate new high mark
00526         other.d->highMark = other.d->lowMark + length;
00527         // never exceed the current high mark
00528         if (d->highMark > 0 && other.d->highMark > d->highMark)
00529             other.d->highMark = d->highMark;
00530     }
00531     return other;
00532 }
00533 
00536 template <class T>
00537 QDjangoQuerySet<T> QDjangoQuerySet<T>::none() const
00538 {
00539     QDjangoQuerySet<T> other;
00540     other.d->whereClause = !QDjangoWhere();
00541     return other;
00542 }
00543 
00551 template <class T>
00552 QDjangoQuerySet<T> QDjangoQuerySet<T>::orderBy(const QStringList &keys) const
00553 {
00554     // it is not possible to change ordering once a limit has been set
00555     Q_ASSERT(!d->lowMark && !d->highMark);
00556 
00557     QDjangoQuerySet<T> other = all();
00558     other.d->orderBy << keys;
00559     return other;
00560 }
00561 
00566 template <class T>
00567 bool QDjangoQuerySet<T>::remove()
00568 {
00569     return d->sqlDelete();
00570 }
00571 
00576 template <class T>
00577 QDjangoQuerySet<T> QDjangoQuerySet<T>::selectRelated() const
00578 {
00579     QDjangoQuerySet<T> other = all();
00580     other.d->selectRelated = true;
00581     return other;
00582 }
00583 
00590 template <class T>
00591 int QDjangoQuerySet<T>::size()
00592 {
00593     if (!d->sqlFetch())
00594         return -1;
00595     return d->properties.size();
00596 }
00597 
00601 template <class T>
00602 int QDjangoQuerySet<T>::update(const QVariantMap &fields)
00603 {
00604     return d->sqlUpdate(fields);
00605 }
00606 
00612 template <class T>
00613 QList<QVariantMap> QDjangoQuerySet<T>::values(const QStringList &fields)
00614 {
00615     return d->sqlValues(fields);
00616 }
00617 
00624 template <class T>
00625 QList<QVariantList> QDjangoQuerySet<T>::valuesList(const QStringList &fields)
00626 {
00627     return d->sqlValuesList(fields);
00628 }
00629 
00633 template <class T>
00634 QDjangoWhere QDjangoQuerySet<T>::where() const
00635 {
00636     return d->resolvedWhere(QDjango::database());
00637 }
00638 
00643 template <class T>
00644 QDjangoQuerySet<T> &QDjangoQuerySet<T>::operator=(const QDjangoQuerySet<T> &other)
00645 {
00646     other.d->counter.ref();
00647     if (!d->counter.deref())
00648         delete d;
00649     d = other.d;
00650     return *this;
00651 }
00652 
00653 #endif
 All Classes Functions Typedefs Enumerations Enumerator Properties