QDjangoQuerySet.h
/*
* Copyright (C) 2010-2015 Jeremy Lainé
* Copyright (C) 2011 Mathias Hasselmann
* Contact: https://github.com/jlaine/qdjango
*
* This file is part of the QDjango Library.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
#ifndef QDJANGO_QUERYSET_H
#define QDJANGO_QUERYSET_H
#include "QDjango.h"
#include "QDjangoWhere.h"
#include "QDjangoQuerySet_p.h"
template <class T>
class QDjangoQuerySet
{
public:
typedef int size_type;
typedef T value_type;
typedef value_type *pointer;
typedef const value_type *const_pointer;
typedef value_type &reference;
typedef const value_type &const_reference;
typedef qptrdiff difference_type;
class const_iterator
{
friend class QDjangoQuerySet;
public:
typedef std::bidirectional_iterator_tag iterator_category;
typedef qptrdiff difference_type;
typedef T value_type;
typedef T *pointer;
typedef T &reference;
const_iterator()
: m_querySet(0)
, m_fetched(-1)
, m_offset(0)
{
}
const_iterator(const const_iterator &other)
: m_querySet(other.m_querySet)
, m_fetched(-1)
, m_offset(other.m_offset)
{
}
private:
const_iterator(const QDjangoQuerySet<T> *querySet, int offset = 0)
: m_querySet(querySet)
, m_fetched(-1)
, m_offset(offset)
{
}
public:
const T &operator*() const { return *t(); }
const T *operator->() const { return t(); }
bool operator==(const const_iterator &other) const
{
return m_querySet == other.m_querySet && m_offset == other.m_offset;
}
bool operator!=(const const_iterator &other) const
{
return m_querySet != other.m_querySet || m_offset != other.m_offset;
}
bool operator<(const const_iterator& other) const
{
return (m_querySet == other.m_querySet && m_offset < other.m_offset)
|| m_querySet < other.m_querySet;
}
bool operator<=(const const_iterator& other) const
{
return (m_querySet == other.m_querySet && m_offset <= other.m_offset)
|| m_querySet < other.m_querySet;
}
bool operator>(const const_iterator& other) const
{
return (m_querySet == other.m_querySet && m_offset > other.m_offset)
|| m_querySet > other.m_querySet;
}
bool operator>=(const const_iterator& other) const
{
return (m_querySet == other.m_querySet && m_offset >= other.m_offset)
|| m_querySet > other.m_querySet;
}
const_iterator &operator++() { ++m_offset; return *this; }
const_iterator operator++(int) { const_iterator n(*this); ++m_offset; return n; }
const_iterator &operator+=(int i) { m_offset += i; return *this; }
const_iterator operator+(int i) const { return const_iterator(m_querySet, m_offset + i); }
const_iterator &operator-=(int i) { m_offset -= i; return *this; }
const_iterator operator-(int i) const { return const_iterator(m_querySet, m_offset - i); }
const_iterator &operator--() { --m_offset; return *this; }
const_iterator operator--(int) { const_iterator n(*this); --m_offset; return n; }
difference_type operator-(const const_iterator &other) const { return m_offset - other.m_offset; }
private:
const T *t() const
{
if (m_fetched != m_offset && m_querySet) {
if (const_cast<QDjangoQuerySet<T> *>(m_querySet)->at(m_offset, &m_object)) {
m_fetched = m_offset;
}
}
return m_fetched == m_offset ? &m_object : 0;
}
private:
const QDjangoQuerySet<T> *m_querySet;
mutable int m_fetched;
mutable T m_object;
int m_offset;
};
typedef const_iterator ConstIterator;
QDjangoQuerySet();
QDjangoQuerySet(const QDjangoQuerySet<T> &other);
~QDjangoQuerySet();
QDjangoQuerySet all() const;
QDjangoQuerySet exclude(const QDjangoWhere &where) const;
QDjangoQuerySet filter(const QDjangoWhere &where) const;
QDjangoQuerySet limit(int pos, int length = -1) const;
QDjangoQuerySet none() const;
QDjangoQuerySet orderBy(const QStringList &keys) const;
QDjangoQuerySet selectRelated() const;
int count() const;
QDjangoWhere where() const;
bool remove();
int size();
int update(const QVariantMap &fields);
QList<QVariantMap> values(const QStringList &fields = QStringList());
QList<QVariantList> valuesList(const QStringList &fields = QStringList());
T *get(const QDjangoWhere &where, T *target = 0) const;
T *at(int index, T *target = 0);
const_iterator constBegin() const;
const_iterator begin() const;
const_iterator constEnd() const;
const_iterator end() const;
QDjangoQuerySet<T> &operator=(const QDjangoQuerySet<T> &other);
private:
QDjangoQuerySetPrivate *d;
};
template <class T>
QDjangoQuerySet<T>::QDjangoQuerySet()
{
d = new QDjangoQuerySetPrivate(T::staticMetaObject.className());
}
template <class T>
QDjangoQuerySet<T>::QDjangoQuerySet(const QDjangoQuerySet<T> &other)
{
other.d->counter.ref();
d = other.d;
}
template <class T>
QDjangoQuerySet<T>::~QDjangoQuerySet()
{
if (!d->counter.deref())
delete d;
}
template <class T>
T *QDjangoQuerySet<T>::at(int index, T *target)
{
T *entry = target ? target : new T;
if (!d->sqlLoad(entry, index))
{
if (!target)
delete entry;
return 0;
}
return entry;
}
template <class T>
typename QDjangoQuerySet<T>::const_iterator QDjangoQuerySet<T>::constBegin() const
{
return const_iterator(this);
}
template <class T>
typename QDjangoQuerySet<T>::const_iterator QDjangoQuerySet<T>::begin() const
{
return const_iterator(this);
}
template <class T>
typename QDjangoQuerySet<T>::const_iterator QDjangoQuerySet<T>::constEnd() const
{
return const_iterator(this, QDjangoQuerySet<T>::count());
}
template <class T>
typename QDjangoQuerySet<T>::const_iterator QDjangoQuerySet<T>::end() const
{
return const_iterator(this, QDjangoQuerySet<T>::count());
}
template <class T>
QDjangoQuerySet<T> QDjangoQuerySet<T>::all() const
{
QDjangoQuerySet<T> other;
other.d->lowMark = d->lowMark;
other.d->highMark = d->highMark;
other.d->orderBy = d->orderBy;
other.d->selectRelated = d->selectRelated;
other.d->whereClause = d->whereClause;
return other;
}
template <class T>
int QDjangoQuerySet<T>::count() const
{
if (d->hasResults)
return d->properties.size();
// execute COUNT query
QDjangoQuery query(d->countQuery());
if (!query.exec() || !query.next())
return -1;
return query.value(0).toInt();
}
template <class T>
QDjangoQuerySet<T> QDjangoQuerySet<T>::exclude(const QDjangoWhere &where) const
{
QDjangoQuerySet<T> other = all();
other.d->addFilter(!where);
return other;
}
template <class T>
QDjangoQuerySet<T> QDjangoQuerySet<T>::filter(const QDjangoWhere &where) const
{
QDjangoQuerySet<T> other = all();
other.d->addFilter(where);
return other;
}
template <class T>
T *QDjangoQuerySet<T>::get(const QDjangoWhere &where, T *target) const
{
QDjangoQuerySet<T> qs = filter(where);
return qs.size() == 1 ? qs.at(0, target) : 0;
}
template <class T>
QDjangoQuerySet<T> QDjangoQuerySet<T>::limit(int pos, int length) const
{
Q_ASSERT(pos >= 0);
Q_ASSERT(length >= -1);
QDjangoQuerySet<T> other = all();
other.d->lowMark += pos;
if (length > 0)
{
// calculate new high mark
other.d->highMark = other.d->lowMark + length;
// never exceed the current high mark
if (d->highMark > 0 && other.d->highMark > d->highMark)
other.d->highMark = d->highMark;
}
return other;
}
template <class T>
QDjangoQuerySet<T> QDjangoQuerySet<T>::none() const
{
QDjangoQuerySet<T> other;
other.d->whereClause = !QDjangoWhere();
return other;
}
template <class T>
QDjangoQuerySet<T> QDjangoQuerySet<T>::orderBy(const QStringList &keys) const
{
// it is not possible to change ordering once a limit has been set
Q_ASSERT(!d->lowMark && !d->highMark);
QDjangoQuerySet<T> other = all();
other.d->orderBy << keys;
return other;
}
template <class T>
bool QDjangoQuerySet<T>::remove()
{
return d->sqlDelete();
}
template <class T>
QDjangoQuerySet<T> QDjangoQuerySet<T>::selectRelated() const
{
QDjangoQuerySet<T> other = all();
other.d->selectRelated = true;
return other;
}
template <class T>
int QDjangoQuerySet<T>::size()
{
if (!d->sqlFetch())
return -1;
return d->properties.size();
}
template <class T>
int QDjangoQuerySet<T>::update(const QVariantMap &fields)
{
return d->sqlUpdate(fields);
}
template <class T>
QList<QVariantMap> QDjangoQuerySet<T>::values(const QStringList &fields)
{
return d->sqlValues(fields);
}
template <class T>
QList<QVariantList> QDjangoQuerySet<T>::valuesList(const QStringList &fields)
{
return d->sqlValuesList(fields);
}
template <class T>
QDjangoWhere QDjangoQuerySet<T>::where() const
{
return d->resolvedWhere(QDjango::database());
}
template <class T>
QDjangoQuerySet<T> &QDjangoQuerySet<T>::operator=(const QDjangoQuerySet<T> &other)
{
other.d->counter.ref();
if (!d->counter.deref())
delete d;
d = other.d;
return *this;
}
#endif
QDjangoQuerySet::~QDjangoQuerySet
~QDjangoQuerySet()
Definition: QDjangoQuerySet.h:347
QDjangoWhere
The QDjangoWhere class expresses an SQL constraint.
Definition: QDjangoWhere.h:40
QDjangoQuerySet::update
int update(const QVariantMap &fields)
Definition: QDjangoQuerySet.h:607
QDjangoQuerySet::const_iterator::operator--
const_iterator operator--(int)
Definition: QDjangoQuerySet.h:258
QDjangoQuerySet::const_iterator::operator-
difference_type operator-(const const_iterator &other) const
Definition: QDjangoQuerySet.h:264
QDjango::database
static QSqlDatabase database()
Returns the database used by QDjango.
Definition: QDjango.cpp:166
QDjangoQuerySet::remove
bool remove()
Definition: QDjangoQuerySet.h:572
QDjangoQuerySet::selectRelated
QDjangoQuerySet selectRelated() const
Definition: QDjangoQuerySet.h:582
QDjangoQuerySet::where
QDjangoWhere where() const
Definition: QDjangoQuerySet.h:639
QDjangoQuerySet::const_iterator::operator==
bool operator==(const const_iterator &other) const
Definition: QDjangoQuerySet.h:145
QDjangoQuerySet::count
int count() const
Definition: QDjangoQuerySet.h:442
QDjangoQuerySet::const_iterator::const_iterator
const_iterator()
Definition: QDjangoQuerySet.h:102
QDjangoQuerySet::const_iterator::operator++
const_iterator operator++(int)
Definition: QDjangoQuerySet.h:212
QDjangoQuerySet::const_iterator::operator<=
bool operator<=(const const_iterator &other) const
Definition: QDjangoQuerySet.h:172
QDjangoQuerySet::const_iterator
Definition: QDjangoQuerySet.h:78
QDjangoQuerySet::limit
QDjangoQuerySet limit(int pos, int length=-1) const
Definition: QDjangoQuerySet.h:521
QDjangoQuerySet::const_iterator::operator-=
const_iterator & operator-=(int i)
Definition: QDjangoQuerySet.h:233
QDjangoQuerySet::filter
QDjangoQuerySet filter(const QDjangoWhere &where) const
Definition: QDjangoQuerySet.h:483
QDjangoQuerySet::constBegin
const_iterator constBegin() const
Definition: QDjangoQuerySet.h:381
QDjangoQuerySet::exclude
QDjangoQuerySet exclude(const QDjangoWhere &where) const
Definition: QDjangoQuerySet.h:465
QDjangoQuerySet::QDjangoQuerySet
QDjangoQuerySet()
Definition: QDjangoQuerySet.h:328
QDjangoQuerySet::const_iterator::operator+=
const_iterator & operator+=(int i)
Definition: QDjangoQuerySet.h:219
QDjangoQuerySet::operator=
QDjangoQuerySet< T > & operator=(const QDjangoQuerySet< T > &other)
Definition: QDjangoQuerySet.h:649
QDjangoQuerySet::ConstIterator
const_iterator ConstIterator
Definition: QDjangoQuerySet.h:287
QDjangoQuerySet::const_iterator::operator++
const_iterator & operator++()
Definition: QDjangoQuerySet.h:203
QDjangoQuerySet::const_iterator::operator--
const_iterator & operator--()
Definition: QDjangoQuerySet.h:249
QDjangoQuerySet::constEnd
const_iterator constEnd() const
Definition: QDjangoQuerySet.h:402
QDjangoQuerySet::const_iterator::const_iterator
const_iterator(const const_iterator &other)
Definition: QDjangoQuerySet.h:111
QDjangoQuerySet
The QDjangoQuerySet class is a template class for performing database queries.
Definition: QDjangoQuerySet.h:46
QDjangoQuerySet::none
QDjangoQuerySet none() const
Definition: QDjangoQuerySet.h:542
QDjangoQuerySet::at
T * at(int index, T *target=0)
Definition: QDjangoQuerySet.h:364
QDjangoQuerySet::valuesList
QList< QVariantList > valuesList(const QStringList &fields=QStringList())
Definition: QDjangoQuerySet.h:630
QDjangoQuerySet::const_iterator::operator!=
bool operator!=(const const_iterator &other) const
Definition: QDjangoQuerySet.h:155
QDjangoQuerySet::end
const_iterator end() const
Definition: QDjangoQuerySet.h:413
QDjangoQuerySet::const_iterator::operator+
const_iterator operator+(int i) const
Definition: QDjangoQuerySet.h:226
QDjangoQuerySet::orderBy
QDjangoQuerySet orderBy(const QStringList &keys) const
Definition: QDjangoQuerySet.h:557
QDjangoQuerySet::get
T * get(const QDjangoWhere &where, T *target=0) const
Definition: QDjangoQuerySet.h:502
QDjangoQuerySet::const_iterator::operator-
const_iterator operator-(int i) const
Definition: QDjangoQuerySet.h:240
QDjangoQuerySet::size
int size()
Definition: QDjangoQuerySet.h:596
QDjangoQuerySet::all
QDjangoQuerySet all() const
Definition: QDjangoQuerySet.h:421
QDjangoQuerySet::const_iterator::operator*
const T & operator*() const
Definition: QDjangoQuerySet.h:131
QDjangoQuerySet::const_iterator::operator<
bool operator<(const const_iterator &other) const
Definition: QDjangoQuerySet.h:163
QDjangoQuerySet::const_iterator::iterator_category
std::bidirectional_iterator_tag iterator_category
Definition: QDjangoQuerySet.h:86
QDjangoQuerySet::const_iterator::operator->
const T * operator->() const
Definition: QDjangoQuerySet.h:137
QDjangoQuerySet::begin
const_iterator begin() const
Definition: QDjangoQuerySet.h:391
QDjangoQuerySet::values
QList< QVariantMap > values(const QStringList &fields=QStringList())
Definition: QDjangoQuerySet.h:618
QDjangoQuerySet::const_iterator::operator>=
bool operator>=(const const_iterator &other) const
Definition: QDjangoQuerySet.h:190
QDjangoQuerySet::const_iterator::operator>
bool operator>(const const_iterator &other) const
Definition: QDjangoQuerySet.h:181