diff options
Diffstat (limited to 'src/sql/kernel/qsqlrecord.cpp')
-rw-r--r-- | src/sql/kernel/qsqlrecord.cpp | 605 |
1 files changed, 605 insertions, 0 deletions
diff --git a/src/sql/kernel/qsqlrecord.cpp b/src/sql/kernel/qsqlrecord.cpp new file mode 100644 index 0000000..0162664 --- /dev/null +++ b/src/sql/kernel/qsqlrecord.cpp @@ -0,0 +1,605 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtSql module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsqlrecord.h" + +#include "qdebug.h" +#include "qstringlist.h" +#include "qatomic.h" +#include "qsqlfield.h" +#include "qstring.h" +#include "qvector.h" + +QT_BEGIN_NAMESPACE + +class QSqlRecordPrivate +{ +public: + QSqlRecordPrivate(); + QSqlRecordPrivate(const QSqlRecordPrivate &other); + + inline bool contains(int index) { return index >= 0 && index < fields.count(); } + QString createField(int index, const QString &prefix) const; + + QVector<QSqlField> fields; + QAtomicInt ref; +}; + +QSqlRecordPrivate::QSqlRecordPrivate() +{ + ref = 1; +} + +QSqlRecordPrivate::QSqlRecordPrivate(const QSqlRecordPrivate &other): fields(other.fields) +{ + ref = 1; +} + +/*! \internal + Just for compat +*/ +QString QSqlRecordPrivate::createField(int index, const QString &prefix) const +{ + QString f; + if (!prefix.isEmpty()) + f = prefix + QLatin1Char('.'); + f += fields.at(index).name(); + return f; +} + +/*! + \class QSqlRecord + \brief The QSqlRecord class encapsulates a database record. + + \ingroup database + \ingroup shared + \inmodule QtSql + + The QSqlRecord class encapsulates the functionality and + characteristics of a database record (usually a row in a table or + view within the database). QSqlRecord supports adding and + removing fields as well as setting and retrieving field values. + + The values of a record's fields' can be set by name or position + with setValue(); if you want to set a field to null use + setNull(). To find the position of a field by name use indexOf(), + and to find the name of a field at a particular position use + fieldName(). Use field() to retrieve a QSqlField object for a + given field. Use contains() to see if the record contains a + particular field name. + + When queries are generated to be executed on the database only + those fields for which isGenerated() is true are included in the + generated SQL. + + A record can have fields added with append() or insert(), replaced + with replace(), and removed with remove(). All the fields can be + removed with clear(). The number of fields is given by count(); + all their values can be cleared (to null) using clearValues(). + + \sa QSqlField, QSqlQuery::record() +*/ + + +/*! + Constructs an empty record. + + \sa isEmpty(), append(), insert() +*/ + +QSqlRecord::QSqlRecord() +{ + d = new QSqlRecordPrivate(); +} + +/*! + Constructs a copy of \a other. + + QSqlRecord is \l{implicitly shared}. This means you can make copies + of a record in \l{constant time}. +*/ + +QSqlRecord::QSqlRecord(const QSqlRecord& other) +{ + d = other.d; + d->ref.ref(); +} + +/*! + Sets the record equal to \a other. + + QSqlRecord is \l{implicitly shared}. This means you can make copies + of a record in \l{constant time}. +*/ + +QSqlRecord& QSqlRecord::operator=(const QSqlRecord& other) +{ + qAtomicAssign(d, other.d); + return *this; +} + +/*! + Destroys the object and frees any allocated resources. +*/ + +QSqlRecord::~QSqlRecord() +{ + if (!d->ref.deref()) + delete d; +} + +/*! + \fn bool QSqlRecord::operator!=(const QSqlRecord &other) const + + Returns true if this object is not identical to \a other; + otherwise returns false. + + \sa operator==() +*/ + +/*! + Returns true if this object is identical to \a other (i.e., has + the same fields in the same order); otherwise returns false. + + \sa operator!=() +*/ +bool QSqlRecord::operator==(const QSqlRecord &other) const +{ + return d->fields == other.d->fields; +} + +/*! + Returns the value of the field located at position \a index in + the record. If \a index is out of bounds, an invalid QVariant + is returned. + + \sa fieldName() isNull() +*/ + +QVariant QSqlRecord::value(int index) const +{ + return d->fields.value(index).value(); +} + +/*! + \overload + + Returns the value of the field called \a name in the record. If + field \a name does not exist an invalid variant is returned. + + \sa indexOf() +*/ + +QVariant QSqlRecord::value(const QString& name) const +{ + return value(indexOf(name)); +} + +/*! + Returns the name of the field at position \a index. If the field + does not exist, an empty string is returned. + + \sa indexOf() +*/ + +QString QSqlRecord::fieldName(int index) const +{ + return d->fields.value(index).name(); +} + +/*! + Returns the position of the field called \a name within the + record, or -1 if it cannot be found. Field names are not + case-sensitive. If more than one field matches, the first one is + returned. + + \sa fieldName() +*/ + +int QSqlRecord::indexOf(const QString& name) const +{ + QString nm = name.toUpper(); + for (int i = 0; i < count(); ++i) { + if (d->fields.at(i).name().toUpper() == nm) // TODO: case-insensitive comparison + return i; + } + return -1; +} + +#ifdef QT3_SUPPORT +/*! + \obsolete + Use field() instead +*/ +const QSqlField* QSqlRecord::fieldPtr(int index) const +{ + if (!d->contains(index)) + return 0; + + return &d->fields.at(index); +} + +/*! + \obsolete + Use field() instead +*/ + +const QSqlField* QSqlRecord::fieldPtr(const QString& name) const +{ + int i = indexOf(name); + if (!d->contains(i)) + return 0; + + return &d->fields.at(i); +} +#endif //QT3_SUPPORT + +/*! + Returns the field at position \a index. If the position is out of + range, an empty field is returned. + */ +QSqlField QSqlRecord::field(int index) const +{ + return d->fields.value(index); +} + +/*! \overload + Returns the field called \a name. + */ +QSqlField QSqlRecord::field(const QString &name) const +{ + return field(indexOf(name)); +} + + +/*! + Append a copy of field \a field to the end of the record. + + \sa insert() replace() remove() +*/ + +void QSqlRecord::append(const QSqlField& field) +{ + detach(); + d->fields.append(field); +} + +/*! + Inserts the field \a field at position \a pos in the record. + + \sa append() replace() remove() + */ +void QSqlRecord::insert(int pos, const QSqlField& field) +{ + detach(); + d->fields.insert(pos, field); +} + +/*! + Replaces the field at position \a pos with the given \a field. If + \a pos is out of range, nothing happens. + + \sa append() insert() remove() +*/ + +void QSqlRecord::replace(int pos, const QSqlField& field) +{ + if (!d->contains(pos)) + return; + + detach(); + d->fields[pos] = field; +} + +/*! + Removes the field at position \a pos. If \a pos is out of range, + nothing happens. + + \sa append() insert() replace() +*/ + +void QSqlRecord::remove(int pos) +{ + if (!d->contains(pos)) + return; + + detach(); + d->fields.remove(pos); +} + +/*! + Removes all the record's fields. + + \sa clearValues() isEmpty() +*/ + +void QSqlRecord::clear() +{ + detach(); + d->fields.clear(); +} + +/*! + Returns true if there are no fields in the record; otherwise + returns false. + + \sa append() insert() clear() +*/ + +bool QSqlRecord::isEmpty() const +{ + return d->fields.isEmpty(); +} + + +/*! + Returns true if there is a field in the record called \a name; + otherwise returns false. +*/ + +bool QSqlRecord::contains(const QString& name) const +{ + return indexOf(name) >= 0; +} + +/*! + Clears the value of all fields in the record and sets each field + to null. + + \sa setValue() +*/ + +void QSqlRecord::clearValues() +{ + detach(); + int count = d->fields.count(); + for (int i = 0; i < count; ++i) + d->fields[i].clear(); +} + +/*! + Sets the generated flag for the field called \a name to \a + generated. If the field does not exist, nothing happens. Only + fields that have \a generated set to true are included in the SQL + that is generated by QSqlQueryModel for example. + + \sa isGenerated() +*/ + +void QSqlRecord::setGenerated(const QString& name, bool generated) +{ + setGenerated(indexOf(name), generated); +} + +/*! + \overload + + Sets the generated flag for the field \a index to \a generated. + + \sa isGenerated() +*/ + +void QSqlRecord::setGenerated(int index, bool generated) +{ + if (!d->contains(index)) + return; + detach(); + d->fields[index].setGenerated(generated); +} + +/*! + \overload + + Returns true if the field \a index is null or if there is no field at + position \a index; otherwise returns false. +*/ +bool QSqlRecord::isNull(int index) const +{ + return d->fields.value(index).isNull(); +} + +/*! + Returns true if the field called \a name is null or if there is no + field called \a name; otherwise returns false. + + \sa setNull() +*/ +bool QSqlRecord::isNull(const QString& name) const +{ + return isNull(indexOf(name)); +} + +/*! + Sets the value of field \a index to null. If the field does not exist, + nothing happens. + + \sa setValue() +*/ +void QSqlRecord::setNull(int index) +{ + if (!d->contains(index)) + return; + detach(); + d->fields[index].clear(); +} + +/*! + \overload + + Sets the value of the field called \a name to null. If the field + does not exist, nothing happens. +*/ +void QSqlRecord::setNull(const QString& name) +{ + setNull(indexOf(name)); +} + + +/*! + Returns true if the record has a field called \a name and this + field is to be generated (the default); otherwise returns false. + + \sa setGenerated() +*/ +bool QSqlRecord::isGenerated(const QString& name) const +{ + return isGenerated(indexOf(name)); +} + +/*! \overload + + Returns true if the record has a field at position \a index and this + field is to be generated (the default); otherwise returns false. + + \sa setGenerated() +*/ +bool QSqlRecord::isGenerated(int index) const +{ + return d->fields.value(index).isGenerated(); +} + +#ifdef QT3_SUPPORT +/*! + Returns a list of all the record's field names as a string + separated by \a sep. + + In the unlikely event that you used this function in Qt 3, you + can simulate it using the rest of the QSqlRecord public API. +*/ + +QString QSqlRecord::toString(const QString& prefix, const QString& sep) const +{ + QString pflist; + bool comma = false; + for (int i = 0; i < count(); ++i) { + if (!d->fields.value(i).isGenerated()) { + if (comma) + pflist += sep + QLatin1Char(' '); + pflist += d->createField(i, prefix); + comma = true; + } + } + return pflist; +} + +/*! + Returns a list of all the record's field names, each having the + prefix \a prefix. + + In the unlikely event that you used this function in Qt 3, you + can simulate it using the rest of the QSqlRecord public API. +*/ + +QStringList QSqlRecord::toStringList(const QString& prefix) const +{ + QStringList s; + for (int i = 0; i < count(); ++i) { + if (!d->fields.value(i).isGenerated()) + s += d->createField(i, prefix); + } + return s; +} +#endif // QT3_SUPPORT + +/*! + Returns the number of fields in the record. + + \sa isEmpty() +*/ + +int QSqlRecord::count() const +{ + return d->fields.count(); +} + +/*! + Sets the value of the field at position \a index to \a val. If the + field does not exist, nothing happens. + + \sa setNull() +*/ + +void QSqlRecord::setValue(int index, const QVariant& val) +{ + if (!d->contains(index)) + return; + detach(); + d->fields[index].setValue(val); +} + + +/*! + \overload + + Sets the value of the field called \a name to \a val. If the field + does not exist, nothing happens. +*/ + +void QSqlRecord::setValue(const QString& name, const QVariant& val) +{ + setValue(indexOf(name), val); +} + + +/*! \internal +*/ +void QSqlRecord::detach() +{ + qAtomicDetach(d); +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const QSqlRecord &r) +{ + dbg << "QSqlRecord(" << r.count() << ")"; + for (int i = 0; i < r.count(); ++i) + dbg << '\n' << QString::fromLatin1("%1:").arg(i, 2) << r.field(i) << r.value(i).toString(); + return dbg; +} +#endif + +/*! + \fn int QSqlRecord::position(const QString& name) const + + Use indexOf() instead. +*/ + +QT_END_NAMESPACE |