QDjango
|
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