/****************************************************************************+ −
**+ −
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).+ −
** All rights reserved.+ −
** Contact: Nokia Corporation (qt-info@nokia.com)+ −
**+ −
** This file is part of the Qt3Support 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 Technology Preview License Agreement accompanying+ −
** this package.+ −
**+ −
** 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.1, included in the file LGPL_EXCEPTION.txt in this package.+ −
**+ −
** If you have questions regarding the use of this file, please contact+ −
** Nokia at qt-info@nokia.com.+ −
**+ −
**+ −
**+ −
**+ −
**+ −
**+ −
**+ −
**+ −
** $QT_END_LICENSE$+ −
**+ −
****************************************************************************/+ −
+ −
#include <qplatformdefs.h>+ −
#include "q3sqlcursor.h"+ −
+ −
#ifndef QT_NO_SQL+ −
+ −
#include "qsqldriver.h"+ −
#include "qsqlresult.h"+ −
#include "qdatetime.h"+ −
#include "qsqldatabase.h"+ −
#include "qsql.h"+ −
#include "q3sqlrecordinfo.h"+ −
#include "q3sqlfieldinfo.h"+ −
+ −
QT_BEGIN_NAMESPACE+ −
+ −
class Q3SqlCursorPrivate+ −
{+ −
public:+ −
+ −
Q3SqlCursorPrivate(const QString& name, QSqlDatabase sdb)+ −
: lastAt(QSql::BeforeFirst), nm(name), srt(name), md(0), db(sdb), q(0)+ −
{}+ −
~Q3SqlCursorPrivate()+ −
{+ −
delete q;+ −
}+ −
+ −
QSqlQuery* query()+ −
{+ −
if (!q)+ −
q = new QSqlQuery(QString(), db);+ −
return q;+ −
}+ −
+ −
int lastAt;+ −
QString nm; //name+ −
QSqlIndex srt; //sort+ −
QString ftr; //filter+ −
int md; //mode+ −
QSqlIndex priIndx; //primary index+ −
QSqlRecord editBuffer;+ −
// the primary index as it was before the user changed the values in editBuffer+ −
QString editIndex;+ −
Q3SqlRecordInfo infoBuffer;+ −
QSqlDatabase db;+ −
QSqlQuery *q;+ −
};+ −
+ −
QString qOrderByClause(const QSqlIndex & i, const QString& prefix = QString())+ −
{+ −
QString str;+ −
int k = i.count();+ −
if(k == 0)+ −
return QString();+ −
str = QLatin1String(" order by ") + i.toString(prefix);+ −
return str;+ −
}+ −
+ −
QString qWhereClause(const QString& prefix, QSqlField* field, const QSqlDriver* driver)+ −
{+ −
QString f;+ −
if (field && driver) {+ −
if (!prefix.isEmpty())+ −
f += prefix + QLatin1Char('.');+ −
f += field->name();+ −
if (field->isNull()) {+ −
f += QLatin1String(" IS NULL");+ −
} else {+ −
f += QLatin1String(" = ") + driver->formatValue(field);+ −
}+ −
}+ −
return f;+ −
}+ −
+ −
QString qWhereClause(QSqlRecord* rec, const QString& prefix, const QString& sep,+ −
const QSqlDriver* driver)+ −
{+ −
static QString blank(QLatin1Char(' '));+ −
QString filter;+ −
bool separator = false;+ −
for (int j = 0; j < rec->count(); ++j) {+ −
QSqlField f = rec->field(j);+ −
if (rec->isGenerated(j)) {+ −
if (separator)+ −
filter += sep + blank;+ −
filter += qWhereClause(prefix, &f, driver);+ −
filter += blank;+ −
separator = true;+ −
}+ −
}+ −
return filter;+ −
}+ −
+ −
/*!+ −
\class Q3SqlCursor+ −
\brief The Q3SqlCursor class provides browsing and editing of SQL+ −
tables and views.+ −
+ −
\compat+ −
+ −
A Q3SqlCursor is a database record (see \l QSqlRecord) that+ −
corresponds to a table or view within an SQL database (see \l+ −
QSqlDatabase). There are two buffers in a cursor, one used for+ −
browsing and one used for editing records. Each buffer contains a+ −
list of fields which correspond to the fields in the table or+ −
view.+ −
+ −
When positioned on a valid record, the browse buffer contains the+ −
values of the current record's fields from the database. The edit+ −
buffer is separate, and is used for editing existing records and+ −
inserting new records.+ −
+ −
For browsing data, a cursor must first select() data from the+ −
database. After a successful select() the cursor is active+ −
(isActive() returns true), but is initially not positioned on a+ −
valid record (isValid() returns false). To position the cursor on+ −
a valid record, use one of the navigation functions, next(),+ −
previous(), first(), last(), or seek(). Once positioned on a valid+ −
record, data can be retrieved from the browse buffer using+ −
value(). If a navigation function is not successful, it returns+ −
false, the cursor will no longer be positioned on a valid record+ −
and the values returned by value() are undefined.+ −
+ −
For example:+ −
+ −
\snippet doc/src/snippets/code/src_qt3support_sql_q3sqlcursor.cpp 0+ −
+ −
In the above example, a cursor is created specifying a table or+ −
view name in the database. Then, select() is called, which can be+ −
optionally parameterised to filter and order the records+ −
retrieved. Each record in the cursor is retrieved using next().+ −
When next() returns false, there are no more records to process,+ −
and the loop terminates.+ −
+ −
For editing records (rows of data), a cursor contains a separate+ −
edit buffer which is independent of the fields used when browsing.+ −
The functions insert(), update() and del() operate on the edit+ −
buffer. This allows the cursor to be repositioned to other+ −
records while simultaneously maintaining a separate buffer for+ −
edits. You can get a pointer to the edit buffer using+ −
editBuffer(). The primeInsert(), primeUpdate() and primeDelete()+ −
functions also return a pointer to the edit buffer and prepare it+ −
for insert, update and delete respectively. Edit operations only+ −
affect a single row at a time. Note that update() and del()+ −
require that the table or view contain a primaryIndex() to ensure+ −
that edit operations affect a unique record within the database.+ −
+ −
For example:+ −
+ −
\snippet doc/src/snippets/code/src_qt3support_sql_q3sqlcursor.cpp 1+ −
+ −
To edit an existing database record, first move to the record you+ −
wish to update. Call primeUpdate() to get the pointer to the+ −
cursor's edit buffer. Then use this pointer to modify the values+ −
in the edit buffer. Finally, call update() to save the changes to+ −
the database. The values in the edit buffer will be used to+ −
locate the appropriate record when updating the database (see+ −
primaryIndex()).+ −
+ −
Similarly, when deleting an existing database record, first move+ −
to the record you wish to delete. Then, call primeDelete() to get+ −
the pointer to the edit buffer. Finally, call del() to delete the+ −
record from the database. Again, the values in the edit buffer+ −
will be used to locate and delete the appropriate record.+ −
+ −
To insert a new record, call primeInsert() to get the pointer to+ −
the edit buffer. Use this pointer to populate the edit buffer+ −
with new values and then insert() the record into the database.+ −
+ −
After calling insert(), update() or del(), the cursor is no longer+ −
positioned on a valid record and can no longer be navigated+ −
(isValid() return false). The reason for this is that any changes+ −
made to the database will not be visible until select() is called+ −
to refresh the cursor. You can change this behavior by passing+ −
false to insert(), update() or del() which will prevent the cursor+ −
from becoming invalid. The edits will still not be visible when+ −
navigating the cursor until select() is called.+ −
+ −
Q3SqlCursor contains virtual methods which allow editing behavior+ −
to be customized by subclasses. This allows custom cursors to be+ −
created that encapsulate the editing behavior of a database table+ −
for an entire application. For example, a cursor can be customized+ −
to always auto-number primary index fields, or provide fields with+ −
suitable default values, when inserting new records. Q3SqlCursor+ −
generates SQL statements which are sent to the database engine;+ −
you can control which fields are included in these statements+ −
using setGenerated().+ −
+ −
Note that Q3SqlCursor does not inherit from QObject. This means+ −
that you are responsible for destroying instances of this class+ −
yourself. However if you create a Q3SqlCursor and use it in a+ −
\l Q3DataTable, \l Q3DataBrowser or a \l Q3DataView these classes will+ −
usually take ownership of the cursor and destroy it when they+ −
don't need it anymore. The documentation for Q3DataTable,+ −
Q3DataBrowser and Q3DataView explicitly states which calls take+ −
ownership of the cursor.+ −
*/+ −
+ −
/*!+ −
\enum Q3SqlCursor::Mode+ −
+ −
This enum type describes how Q3SqlCursor operates on records in the+ −
database.+ −
+ −
\value ReadOnly the cursor can only SELECT records from the+ −
database.+ −
+ −
\value Insert the cursor can INSERT records into the database.+ −
+ −
\value Update the cursor can UPDATE records in the database.+ −
+ −
\value Delete the cursor can DELETE records from the database.+ −
+ −
\value Writable the cursor can INSERT, UPDATE and DELETE records+ −
in the database.+ −
*/+ −
+ −
/*!+ −
\fn QVariant Q3SqlCursor::value(const QString &name) const+ −
+ −
\overload+ −
+ −
Returns the value of the field named \a name.+ −
*/+ −
+ −
/*!+ −
\fn void Q3SqlCursor::setValue(const QString &name, const QVariant &val)+ −
+ −
\overload+ −
+ −
Sets the value for the field named \a name to \a val.+ −
*/+ −
+ −
/*!+ −
Constructs a cursor on database \a db using table or view \a name.+ −
+ −
If \a autopopulate is true (the default), the \a name of the+ −
cursor must correspond to an existing table or view name in the+ −
database so that field information can be automatically created.+ −
If the table or view does not exist, the cursor will not be+ −
functional.+ −
+ −
The cursor is created with an initial mode of Q3SqlCursor::Writable+ −
(meaning that records can be inserted, updated or deleted using+ −
the cursor). If the cursor does not have a unique primary index,+ −
update and deletes cannot be performed.+ −
+ −
Note that \a autopopulate refers to populating the cursor with+ −
meta-data, e.g. the names of the table's fields, not with+ −
retrieving data. The select() function is used to populate the+ −
cursor with data.+ −
+ −
\sa setName() setMode()+ −
*/+ −
+ −
Q3SqlCursor::Q3SqlCursor(const QString & name, bool autopopulate, QSqlDatabase db)+ −
: QSqlRecord(), QSqlQuery(QString(), db)+ −
{+ −
d = new Q3SqlCursorPrivate(name, db);+ −
setMode(Writable);+ −
if (!d->nm.isEmpty())+ −
setName(d->nm, autopopulate);+ −
}+ −
+ −
/*!+ −
Constructs a copy of \a other.+ −
*/+ −
+ −
Q3SqlCursor::Q3SqlCursor(const Q3SqlCursor & other)+ −
: QSqlRecord(other), QSqlQuery(other)+ −
{+ −
d = new Q3SqlCursorPrivate(other.d->nm, other.d->db);+ −
d->lastAt = other.d->lastAt;+ −
d->nm = other.d->nm;+ −
d->srt = other.d->srt;+ −
d->ftr = other.d->ftr;+ −
d->priIndx = other.d->priIndx;+ −
d->editBuffer = other.d->editBuffer;+ −
d->infoBuffer = other.d->infoBuffer;+ −
d->q = 0; // do not share queries+ −
setMode(other.mode());+ −
}+ −
+ −
/*!+ −
Destroys the object and frees any allocated resources.+ −
*/+ −
+ −
Q3SqlCursor::~Q3SqlCursor()+ −
{+ −
delete d;+ −
}+ −
+ −
/*!+ −
Sets the cursor equal to \a other.+ −
*/+ −
+ −
Q3SqlCursor& Q3SqlCursor::operator=(const Q3SqlCursor& other)+ −
{+ −
QSqlRecord::operator=(other);+ −
QSqlQuery::operator=(other);+ −
delete d;+ −
d = new Q3SqlCursorPrivate(other.d->nm, other.d->db);+ −
d->lastAt = other.d->lastAt;+ −
d->nm = other.d->nm;+ −
d->srt = other.d->srt;+ −
d->ftr = other.d->ftr;+ −
d->priIndx = other.d->priIndx;+ −
d->editBuffer = other.d->editBuffer;+ −
d->infoBuffer = other.d->infoBuffer;+ −
d->q = 0; // do not share queries+ −
setMode(other.mode());+ −
return *this;+ −
}+ −
+ −
/*!+ −
Sets the current sort to \a sort. Note that no new records are+ −
selected. To select new records, use select(). The \a sort will+ −
apply to any subsequent select() calls that do not explicitly+ −
specify a sort.+ −
*/+ −
+ −
void Q3SqlCursor::setSort(const QSqlIndex& sort)+ −
{+ −
d->srt = sort;+ −
}+ −
+ −
/*!+ −
Returns the current sort, or an empty index if there is no current+ −
sort.+ −
*/+ −
QSqlIndex Q3SqlCursor::sort() const+ −
{+ −
return d->srt;+ −
}+ −
+ −
/*!+ −
Sets the current filter to \a filter. Note that no new records are+ −
selected. To select new records, use select(). The \a filter will+ −
apply to any subsequent select() calls that do not explicitly+ −
specify a filter.+ −
+ −
The filter is a SQL \c WHERE clause without the keyword 'WHERE',+ −
e.g. \c{name='Dave'} which will be processed by the DBMS.+ −
*/+ −
void Q3SqlCursor::setFilter(const QString& filter)+ −
{+ −
d->ftr = filter;+ −
}+ −
+ −
/*!+ −
Returns the current filter, or an empty string if there is no+ −
current filter.+ −
*/+ −
QString Q3SqlCursor::filter() const+ −
{+ −
return d->ftr;+ −
}+ −
+ −
/*!+ −
Sets the name of the cursor to \a name. If \a autopopulate is true+ −
(the default), the \a name must correspond to a valid table or+ −
view name in the database. Also, note that all references to the+ −
cursor edit buffer become invalidated when fields are+ −
auto-populated. See the Q3SqlCursor constructor documentation for+ −
more information.+ −
*/+ −
void Q3SqlCursor::setName(const QString& name, bool autopopulate)+ −
{+ −
d->nm = name;+ −
if (autopopulate) {+ −
if (driver()) {+ −
d->infoBuffer = driver()->record(name);+ −
*this = d->infoBuffer.toRecord();+ −
d->editBuffer = *this;+ −
d->priIndx = driver()->primaryIndex(name);+ −
}+ −
if (isEmpty())+ −
qWarning("Q3SqlCursor::setName: unable to build record, does '%s' exist?", name.latin1());+ −
}+ −
}+ −
+ −
/*!+ −
Returns the name of the cursor.+ −
*/+ −
+ −
QString Q3SqlCursor::name() const+ −
{+ −
return d->nm;+ −
}+ −
+ −
/*! \internal+ −
*/+ −
+ −
QString Q3SqlCursor::toString(const QString& prefix, const QString& sep) const+ −
{+ −
QString pflist;+ −
QString pfix = prefix.isEmpty() ? prefix : prefix + QLatin1Char('.');+ −
bool comma = false;+ −
+ −
for (int i = 0; i < count(); ++i) {+ −
const QString fname = fieldName(i);+ −
if (isGenerated(i)) {+ −
if(comma)+ −
pflist += sep + QLatin1Char(' ');+ −
pflist += pfix + driver()->escapeIdentifier(fname, QSqlDriver::FieldName);+ −
comma = true;+ −
}+ −
}+ −
return pflist;+ −
}+ −
+ −
/*!+ −
\internal+ −
+ −
Assigns the record \a list.+ −
+ −
*/+ −
QSqlRecord & Q3SqlCursor::operator=(const QSqlRecord & list)+ −
{+ −
return QSqlRecord::operator=(list);+ −
}+ −
+ −
/*!+ −
Append a copy of field \a fieldInfo to the end of the cursor. Note+ −
that all references to the cursor edit buffer become invalidated.+ −
*/+ −
+ −
void Q3SqlCursor::append(const Q3SqlFieldInfo& fieldInfo)+ −
{+ −
d->editBuffer.append(fieldInfo.toField());+ −
d->infoBuffer.append(fieldInfo);+ −
QSqlRecord::append(fieldInfo.toField());+ −
}+ −
+ −
/*!+ −
Removes all fields from the cursor. Note that all references to+ −
the cursor edit buffer become invalidated.+ −
*/+ −
void Q3SqlCursor::clear()+ −
{+ −
d->editBuffer.clear();+ −
d->infoBuffer.clear();+ −
QSqlRecord::clear();+ −
}+ −
+ −
+ −
/*!+ −
Insert a copy of \a fieldInfo at position \a pos. If a field+ −
already exists at \a pos, it is removed. Note that all references+ −
to the cursor edit buffer become invalidated.+ −
*/+ −
+ −
void Q3SqlCursor::insert(int pos, const Q3SqlFieldInfo& fieldInfo)+ −
{+ −
d->editBuffer.replace(pos, fieldInfo.toField());+ −
d->infoBuffer[pos] = fieldInfo;+ −
QSqlRecord::replace(pos, fieldInfo.toField());+ −
}+ −
+ −
/*!+ −
Removes the field at \a pos. If \a pos does not exist, nothing+ −
happens. Note that all references to the cursor edit buffer become+ −
invalidated.+ −
*/+ −
+ −
void Q3SqlCursor::remove(int pos)+ −
{+ −
d->editBuffer.remove(pos);+ −
d->infoBuffer[pos] = Q3SqlFieldInfo();+ −
QSqlRecord::remove(pos);+ −
}+ −
+ −
/*!+ −
Sets the generated flag for the field \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 insert(), update() or del().+ −
*/+ −
+ −
void Q3SqlCursor::setGenerated(const QString& name, bool generated)+ −
{+ −
int pos = indexOf(name);+ −
if (pos == -1)+ −
return;+ −
QSqlRecord::setGenerated(name, generated);+ −
d->editBuffer.setGenerated(name, generated);+ −
d->infoBuffer[pos].setGenerated(generated);+ −
}+ −
+ −
/*!+ −
\overload+ −
+ −
Sets the generated flag for the field \a i to \a generated.+ −
*/+ −
void Q3SqlCursor::setGenerated(int i, bool generated)+ −
{+ −
if (i < 0 || i >= (int)d->infoBuffer.count())+ −
return;+ −
QSqlRecord::setGenerated(i, generated);+ −
d->editBuffer.setGenerated(i, generated);+ −
d->infoBuffer[i].setGenerated(generated);+ −
}+ −
+ −
/*!+ −
Returns the primary index associated with the cursor as defined in+ −
the database, or an empty index if there is no primary index. If+ −
\a setFromCursor is true (the default), the index fields are+ −
populated with the corresponding values in the cursor's current+ −
record.+ −
*/+ −
+ −
QSqlIndex Q3SqlCursor::primaryIndex(bool setFromCursor) const+ −
{+ −
if (setFromCursor) {+ −
for (int i = 0; i < d->priIndx.count(); ++i) {+ −
const QString fn = d->priIndx.fieldName(i);+ −
if (contains(fn))+ −
d->priIndx.setValue(i, QSqlRecord::value(fn));+ −
}+ −
}+ −
return d->priIndx;+ −
}+ −
+ −
/*!+ −
Sets the primary index associated with the cursor to the index \a+ −
idx. Note that this index must contain a field or set of fields+ −
which identify a unique record within the underlying database+ −
table or view so that update() and del() will execute as expected.+ −
+ −
\sa update() del()+ −
*/+ −
+ −
void Q3SqlCursor::setPrimaryIndex(const QSqlIndex& idx)+ −
{+ −
d->priIndx = idx;+ −
}+ −
+ −
+ −
/*!+ −
Returns an index composed of \a fieldNames, all in ASCending+ −
order. Note that all field names must exist in the cursor,+ −
otherwise an empty index is returned.+ −
+ −
\sa QSqlIndex+ −
*/+ −
+ −
QSqlIndex Q3SqlCursor::index(const QStringList& fieldNames) const+ −
{+ −
QSqlIndex idx;+ −
for (QStringList::ConstIterator it = fieldNames.begin(); it != fieldNames.end(); ++it) {+ −
QSqlField f = field((*it));+ −
if (!f.isValid()) { /* all fields must exist */+ −
idx.clear();+ −
break;+ −
}+ −
idx.append(f);+ −
}+ −
return idx;+ −
}+ −
+ −
/*!+ −
\overload+ −
+ −
Returns an index based on \a fieldName.+ −
*/+ −
+ −
QSqlIndex Q3SqlCursor::index(const QString& fieldName) const+ −
{+ −
QStringList fl(fieldName);+ −
return index(fl);+ −
}+ −
+ −
/*!+ −
Selects all fields in the cursor from the database matching the+ −
filter criteria \a filter. The data is returned in the order+ −
specified by the index \a sort. Returns true if the data was+ −
successfully selected; otherwise returns false.+ −
+ −
The \a filter is a string containing a SQL \c WHERE clause but+ −
without the 'WHERE' keyword. The cursor is initially positioned at+ −
an invalid row after this function is called. To move to a valid+ −
row, use seek(), first(), last(), previous() or next().+ −
+ −
Example:+ −
\snippet doc/src/snippets/code/src_qt3support_sql_q3sqlcursor.cpp 2+ −
+ −
The filter will apply to any subsequent select() calls that do not+ −
explicitly specify another filter. Similarly the sort will apply+ −
to any subsequent select() calls that do not explicitly specify+ −
another sort.+ −
+ −
\snippet doc/src/snippets/code/src_qt3support_sql_q3sqlcursor.cpp 3+ −
+ −
*/+ −
+ −
bool Q3SqlCursor::select(const QString & filter, const QSqlIndex & sort)+ −
{+ −
QString fieldList(toString(d->nm));+ −
if (fieldList.isEmpty())+ −
return false;+ −
QString str(QLatin1String("select ") + fieldList);+ −
str += QLatin1String(" from ") + d->nm;+ −
if (!filter.isEmpty()) {+ −
d->ftr = filter;+ −
str += QLatin1String(" where ") + filter;+ −
} else+ −
d->ftr.clear();+ −
if (sort.count() > 0)+ −
str += QLatin1String(" order by ") + sort.toString(d->nm);+ −
d->srt = sort;+ −
return exec(str);+ −
}+ −
+ −
/*!+ −
\overload+ −
+ −
Selects all fields in the cursor from the database. The rows are+ −
returned in the order specified by the last call to setSort() or+ −
the last call to select() that specified a sort, whichever is the+ −
most recent. If there is no current sort, the order in which the+ −
rows are returned is undefined. The records are filtered according+ −
to the filter specified by the last call to setFilter() or the+ −
last call to select() that specified a filter, whichever is the+ −
most recent. If there is no current filter, all records are+ −
returned. The cursor is initially positioned at an invalid row. To+ −
move to a valid row, use seek(), first(), last(), previous() or+ −
next().+ −
+ −
\sa setSort() setFilter()+ −
*/+ −
+ −
bool Q3SqlCursor::select()+ −
{+ −
return select(filter(), sort());+ −
}+ −
+ −
/*!+ −
\overload+ −
+ −
Selects all fields in the cursor from the database. The data is+ −
returned in the order specified by the index \a sort. The records+ −
are filtered according to the filter specified by the last call to+ −
setFilter() or the last call to select() that specified a filter,+ −
whichever is the most recent. The cursor is initially positioned+ −
at an invalid row. To move to a valid row, use seek(), first(),+ −
last(), previous() or next().+ −
*/+ −
+ −
bool Q3SqlCursor::select(const QSqlIndex& sort)+ −
{+ −
return select(filter(), sort);+ −
}+ −
+ −
/*!+ −
\overload+ −
+ −
Selects all fields in the cursor matching the filter index \a+ −
filter. The data is returned in the order specified by the index+ −
\a sort. The \a filter index works by constructing a WHERE clause+ −
using the names of the fields from the \a filter and their values+ −
from the current cursor record. The cursor is initially positioned+ −
at an invalid row. To move to a valid row, use seek(), first(),+ −
last(), previous() or next(). This function is useful, for example,+ −
for retrieving data based upon a table's primary index:+ −
+ −
\snippet doc/src/snippets/code/src_qt3support_sql_q3sqlcursor.cpp 4+ −
+ −
In this example the QSqlIndex, pk, is used for two different+ −
purposes. When used as the filter (first) argument, the field+ −
names it contains are used to construct the WHERE clause, each set+ −
to the current cursor value, \c{WHERE id=10}, in this case. When+ −
used as the sort (second) argument the field names it contains are+ −
used for the ORDER BY clause, \c{ORDER BY id} in this example.+ −
*/+ −
+ −
bool Q3SqlCursor::select(const QSqlIndex & filter, const QSqlIndex & sort)+ −
{+ −
return select(toString(filter, this, d->nm, QString(QLatin1Char('=')), QLatin1String("and")), sort);+ −
}+ −
+ −
/*!+ −
Sets the cursor mode to \a mode. This value can be an OR'ed+ −
combination of \l Q3SqlCursor::Mode values. The default mode for a+ −
cursor is Q3SqlCursor::Writable.+ −
+ −
\snippet doc/src/snippets/code/src_qt3support_sql_q3sqlcursor.cpp 5+ −
*/+ −
+ −
void Q3SqlCursor::setMode(int mode)+ −
{+ −
d->md = mode;+ −
}+ −
+ −
/*!+ −
Returns the current cursor mode.+ −
+ −
\sa setMode()+ −
*/+ −
+ −
int Q3SqlCursor::mode() const+ −
{+ −
return d->md;+ −
}+ −
+ −
/*!+ −
Sets field \a name to \a calculated. If the field \a name does not+ −
exist, nothing happens. The value of a calculated field is set by+ −
the calculateField() virtual function which you must reimplement+ −
(or the field value will be an invalid QVariant). Calculated+ −
fields do not appear in generated SQL statements sent to the+ −
database.+ −
+ −
\sa calculateField()+ −
*/+ −
+ −
void Q3SqlCursor::setCalculated(const QString& name, bool calculated)+ −
{+ −
int pos = indexOf(name);+ −
if (pos < 0)+ −
return;+ −
d->infoBuffer[pos].setCalculated(calculated);+ −
if (calculated)+ −
setGenerated(pos, false);+ −
}+ −
+ −
/*!+ −
Returns true if the field \a name exists and is calculated;+ −
otherwise returns false.+ −
+ −
\sa setCalculated()+ −
*/+ −
+ −
bool Q3SqlCursor::isCalculated(const QString& name) const+ −
{+ −
int pos = indexOf(name);+ −
if (pos < 0)+ −
return false;+ −
return d->infoBuffer[pos].isCalculated();+ −
}+ −
+ −
/*!+ −
Sets field \a{name}'s trimmed status to \a trim. If the field \a+ −
name does not exist, nothing happens.+ −
+ −
When a trimmed field of type string is read from the+ −
database any trailing (right-most) spaces are removed.+ −
+ −
\sa isTrimmed() QVariant+ −
*/+ −
+ −
void Q3SqlCursor::setTrimmed(const QString& name, bool trim)+ −
{+ −
int pos = indexOf(name);+ −
if (pos < 0)+ −
return;+ −
d->infoBuffer[pos].setTrim(trim);+ −
}+ −
+ −
/*!+ −
Returns true if the field \a name exists and is trimmed; otherwise+ −
returns false.+ −
+ −
When a trimmed field of type string or cstring is read from the+ −
database any trailing (right-most) spaces are removed.+ −
+ −
\sa setTrimmed()+ −
*/+ −
+ −
bool Q3SqlCursor::isTrimmed(const QString& name) const+ −
{+ −
int pos = indexOf(name);+ −
if (pos < 0)+ −
return false;+ −
return d->infoBuffer[pos].isTrim();+ −
}+ −
+ −
/*!+ −
Returns true if the cursor is read-only; otherwise returns false.+ −
The default is false. Read-only cursors cannot be edited using+ −
insert(), update() or del().+ −
+ −
\sa setMode()+ −
*/+ −
+ −
bool Q3SqlCursor::isReadOnly() const+ −
{+ −
return d->md == 0;+ −
}+ −
+ −
/*!+ −
Returns true if the cursor will perform inserts; otherwise returns+ −
false.+ −
+ −
\sa setMode()+ −
*/+ −
+ −
bool Q3SqlCursor::canInsert() const+ −
{+ −
return ((d->md & Insert) == Insert) ;+ −
}+ −
+ −
+ −
/*!+ −
Returns true if the cursor will perform updates; otherwise returns+ −
false.+ −
+ −
\sa setMode()+ −
*/+ −
+ −
bool Q3SqlCursor::canUpdate() const+ −
{+ −
return ((d->md & Update) == Update) ;+ −
}+ −
+ −
/*!+ −
Returns true if the cursor will perform deletes; otherwise returns+ −
false.+ −
+ −
\sa setMode()+ −
*/+ −
+ −
bool Q3SqlCursor::canDelete() const+ −
{+ −
return ((d->md & Delete) == Delete) ;+ −
}+ −
+ −
/*!+ −
\overload+ −
+ −
Returns a formatted string composed of the \a prefix (e.g. table+ −
or view name), ".", the \a field name, the \a fieldSep and the+ −
field value. If the \a prefix is empty then the string will begin+ −
with the \a field name. This function is useful for generating SQL+ −
statements.+ −
*/+ −
+ −
QString Q3SqlCursor::toString(const QString& prefix, QSqlField* field, const QString& fieldSep) const+ −
{+ −
QString f;+ −
if (field && driver()) {+ −
f = (prefix.length() > 0 ? prefix + QLatin1Char('.') : QString()) + driver()->escapeIdentifier(field->name(), QSqlDriver::FieldName);+ −
f += QLatin1Char(' ') + fieldSep + QLatin1Char(' ');+ −
if (field->isNull()) {+ −
f += QLatin1String("NULL");+ −
} else {+ −
f += driver()->formatValue(field);+ −
}+ −
}+ −
return f;+ −
}+ −
+ −
/*!+ −
Returns a formatted string composed of all the fields in \a rec.+ −
Each field is composed of the \a prefix (e.g. table or view name),+ −
".", the field name, the \a fieldSep and the field value. If the+ −
\a prefix is empty then each field will begin with the field name.+ −
The fields are then joined together separated by \a sep. Fields+ −
where isGenerated() returns false are not included. This function+ −
is useful for generating SQL statements.+ −
*/+ −
+ −
QString Q3SqlCursor::toString(QSqlRecord* rec, const QString& prefix, const QString& fieldSep,+ −
const QString& sep) const+ −
{+ −
static QString blank(QLatin1Char(' '));+ −
QString filter;+ −
bool separator = false;+ −
for (int j = 0; j < count(); ++j) {+ −
QSqlField f = rec->field(j);+ −
if (rec->isGenerated(j)) {+ −
if (separator)+ −
filter += sep + blank;+ −
filter += toString(prefix, &f, fieldSep);+ −
filter += blank;+ −
separator = true;+ −
}+ −
}+ −
return filter;+ −
}+ −
+ −
/*!+ −
\overload+ −
+ −
Returns a formatted string composed of all the fields in the index+ −
\a i. Each field is composed of the \a prefix (e.g. table or view+ −
name), ".", the field name, the \a fieldSep and the field value.+ −
If the \a prefix is empty then each field will begin with the field+ −
name. The field values are taken from \a rec. The fields are then+ −
joined together separated by \a sep. Fields where isGenerated()+ −
returns false are ignored. This function is useful for generating+ −
SQL statements.+ −
*/+ −
+ −
QString Q3SqlCursor::toString(const QSqlIndex& i, QSqlRecord* rec, const QString& prefix,+ −
const QString& fieldSep, const QString& sep) const+ −
{+ −
QString filter;+ −
bool separator = false;+ −
for(int j = 0; j < i.count(); ++j){+ −
if (rec->isGenerated(j)) {+ −
if(separator) {+ −
filter += QLatin1Char(' ') + sep + QLatin1Char(' ') ;+ −
}+ −
QString fn = i.fieldName(j);+ −
QSqlField f = rec->field(fn);+ −
filter += toString(prefix, &f, fieldSep);+ −
separator = true;+ −
}+ −
}+ −
return filter;+ −
}+ −
+ −
/*!+ −
Inserts the current contents of the cursor's edit record buffer+ −
into the database, if the cursor allows inserts. Returns the+ −
number of rows affected by the insert. For error information, use+ −
lastError().+ −
+ −
If \a invalidate is true (the default), the cursor will no longer+ −
be positioned on a valid record and can no longer be navigated. A+ −
new select() call must be made before navigating to a valid+ −
record.+ −
+ −
\snippet doc/src/snippets/code/src_qt3support_sql_q3sqlcursor.cpp 6+ −
+ −
In the above example, a cursor is created on the 'prices' table+ −
and a pointer to the insert buffer is acquired using primeInsert().+ −
Each field's value is set to the desired value and then insert()+ −
is called to insert the data into the database. Remember: all edit+ −
operations (insert(), update() and delete()) operate on the+ −
contents of the cursor edit buffer and not on the contents of the+ −
cursor itself.+ −
+ −
\sa setMode() lastError()+ −
*/+ −
+ −
int Q3SqlCursor::insert(bool invalidate)+ −
{+ −
if ((d->md & Insert) != Insert || !driver())+ −
return false;+ −
int k = d->editBuffer.count();+ −
if (k == 0)+ −
return 0;+ −
+ −
QString fList;+ −
QString vList;+ −
bool comma = false;+ −
// use a prepared query if the driver supports it+ −
if (driver()->hasFeature(QSqlDriver::PreparedQueries)) {+ −
int cnt = 0;+ −
bool oraStyle = driver()->hasFeature(QSqlDriver::NamedPlaceholders);+ −
for(int j = 0; j < k; ++j) {+ −
QSqlField f = d->editBuffer.field(j);+ −
if (d->editBuffer.isGenerated(j)) {+ −
if (comma) {+ −
fList += QLatin1Char(',');+ −
vList += QLatin1Char(',');+ −
}+ −
fList += driver()->escapeIdentifier(f.name(), QSqlDriver::FieldName);+ −
vList += (oraStyle == true) ? QLatin1String(":f") + QString::number(cnt) : QString(QLatin1Char('?'));+ −
cnt++;+ −
comma = true;+ −
}+ −
}+ −
if (!comma) {+ −
return 0;+ −
}+ −
QString str;+ −
str.append(QLatin1String("insert into ")).append(name())+ −
.append(QLatin1String(" (")).append(fList)+ −
.append(QLatin1String(") values (")).append(vList). append(QLatin1Char(')'));+ −
+ −
return applyPrepared(str, invalidate);+ −
} else {+ −
for(int j = 0; j < k; ++j) {+ −
QSqlField f = d->editBuffer.field(j);+ −
if (d->editBuffer.isGenerated(j)) {+ −
if (comma) {+ −
fList += QLatin1Char(',');+ −
vList += QLatin1Char(',');+ −
}+ −
fList += driver()->escapeIdentifier(f.name(), QSqlDriver::FieldName);+ −
vList += driver()->formatValue(&f);+ −
comma = true;+ −
}+ −
}+ −
+ −
if (!comma) {+ −
// no valid fields found+ −
return 0;+ −
}+ −
QString str;+ −
str.append(QLatin1String("insert into ")).append(name()).append(QLatin1String(" ("))+ −
.append(fList).append(QLatin1String(") values (")).append(vList). append (QLatin1String(")"));+ −
return apply(str, invalidate);+ −
}+ −
}+ −
+ −
/*!+ −
Returns the current internal edit buffer. If \a copy is true (the+ −
default is false), the current cursor field values are first+ −
copied into the edit buffer. The edit buffer is valid as long as+ −
the cursor remains valid. The cursor retains ownership of the+ −
returned pointer, so it must not be deleted or modified.+ −
+ −
\sa primeInsert(), primeUpdate() primeDelete()+ −
*/+ −
+ −
QSqlRecord* Q3SqlCursor::editBuffer(bool copy)+ −
{+ −
sync();+ −
if (copy) {+ −
for(int i = 0; i < d->editBuffer.count(); i++) {+ −
if (QSqlRecord::isNull(i)) {+ −
d->editBuffer.setNull(i);+ −
} else {+ −
d->editBuffer.setValue(i, value(i));+ −
}+ −
}+ −
}+ −
return &d->editBuffer;+ −
}+ −
+ −
/*!+ −
This function primes the edit buffer's field values for update and+ −
returns the edit buffer. The default implementation copies the+ −
field values from the current cursor record into the edit buffer+ −
(therefore, this function is equivalent to calling editBuffer(+ −
true)). The cursor retains ownership of the returned pointer, so+ −
it must not be deleted or modified.+ −
+ −
\sa editBuffer() update()+ −
*/+ −
+ −
QSqlRecord* Q3SqlCursor::primeUpdate()+ −
{+ −
// memorize the primary keys as they were before the user changed the values in editBuffer+ −
QSqlRecord* buf = editBuffer(true);+ −
QSqlIndex idx = primaryIndex(false);+ −
if (!idx.isEmpty())+ −
d->editIndex = toString(idx, buf, d->nm, QString(QLatin1Char('=')), QLatin1String("and"));+ −
else+ −
d->editIndex = qWhereClause(buf, d->nm, QLatin1String("and"), driver());+ −
return buf;+ −
}+ −
+ −
/*!+ −
This function primes the edit buffer's field values for delete and+ −
returns the edit buffer. The default implementation copies the+ −
field values from the current cursor record into the edit buffer+ −
(therefore, this function is equivalent to calling editBuffer(+ −
true)). The cursor retains ownership of the returned pointer, so+ −
it must not be deleted or modified.+ −
+ −
\sa editBuffer() del()+ −
*/+ −
+ −
QSqlRecord* Q3SqlCursor::primeDelete()+ −
{+ −
return editBuffer(true);+ −
}+ −
+ −
/*!+ −
This function primes the edit buffer's field values for insert and+ −
returns the edit buffer. The default implementation clears all+ −
field values in the edit buffer. The cursor retains ownership of+ −
the returned pointer, so it must not be deleted or modified.+ −
+ −
\sa editBuffer() insert()+ −
*/+ −
+ −
QSqlRecord* Q3SqlCursor::primeInsert()+ −
{+ −
d->editBuffer.clearValues();+ −
return &d->editBuffer;+ −
}+ −
+ −
+ −
/*!+ −
Updates the database with the current contents of the edit buffer.+ −
Returns the number of records which were updated.+ −
For error information, use lastError().+ −
+ −
Only records which meet the filter criteria specified by the+ −
cursor's primary index are updated. If the cursor does not contain+ −
a primary index, no update is performed and 0 is returned.+ −
+ −
If \a invalidate is true (the default), the current cursor can no+ −
longer be navigated. A new select() call must be made before you+ −
can move to a valid record. For example:+ −
+ −
\snippet doc/src/snippets/code/src_qt3support_sql_q3sqlcursor.cpp 7+ −
+ −
In the above example, a cursor is created on the 'prices' table+ −
and is positioned on the record to be updated. Then a pointer to+ −
the cursor's edit buffer is acquired using primeUpdate(). A new+ −
value is calculated and placed into the edit buffer with the+ −
setValue() call. Finally, an update() call is made on the cursor+ −
which uses the tables's primary index to update the record in the+ −
database with the contents of the cursor's edit buffer. Remember:+ −
all edit operations (insert(), update() and delete()) operate on+ −
the contents of the cursor edit buffer and not on the contents of+ −
the cursor itself.+ −
+ −
Note that if the primary index does not uniquely distinguish+ −
records the database may be changed into an inconsistent state.+ −
+ −
\sa setMode() lastError()+ −
*/+ −
+ −
int Q3SqlCursor::update(bool invalidate)+ −
{+ −
if (d->editIndex.isEmpty())+ −
return 0;+ −
return update(d->editIndex, invalidate);+ −
}+ −
+ −
/*!+ −
\overload+ −
+ −
Updates the database with the current contents of the cursor edit+ −
buffer using the specified \a filter. Returns the number of+ −
records which were updated.+ −
For error information, use lastError().+ −
+ −
Only records which meet the filter criteria are updated, otherwise+ −
all records in the table are updated.+ −
+ −
If \a invalidate is true (the default), the cursor can no longer+ −
be navigated. A new select() call must be made before you can move+ −
to a valid record.+ −
+ −
\sa primeUpdate() setMode() lastError()+ −
*/+ −
+ −
int Q3SqlCursor::update(const QString & filter, bool invalidate)+ −
{+ −
if ((d->md & Update) != Update) {+ −
return false;+ −
}+ −
int k = count();+ −
if (k == 0) {+ −
return 0;+ −
}+ −
+ −
// use a prepared query if the driver supports it+ −
if (driver()->hasFeature(QSqlDriver::PreparedQueries)) {+ −
QString fList;+ −
bool comma = false;+ −
int cnt = 0;+ −
bool oraStyle = driver()->hasFeature(QSqlDriver::NamedPlaceholders);+ −
for(int j = 0; j < k; ++j) {+ −
QSqlField f = d->editBuffer.field(j);+ −
if (d->editBuffer.isGenerated(j)) {+ −
if (comma) {+ −
fList += QLatin1Char(',');+ −
}+ −
fList += f.name() + QLatin1String(" = ") + (oraStyle == true ? QLatin1String(":f") + QString::number(cnt) : QString(QLatin1Char('?')));+ −
cnt++;+ −
comma = true;+ −
}+ −
}+ −
if (!comma) {+ −
return 0;+ −
}+ −
QString str(QLatin1String("update ") + name() + QLatin1String(" set ") + fList);+ −
if (filter.length()) {+ −
str+= QLatin1String(" where ") + filter;+ −
}+ −
return applyPrepared(str, invalidate);+ −
} else {+ −
QString str = QLatin1String("update ") + name();+ −
str += QLatin1String(" set ") + toString(&d->editBuffer, QString(), QString(QLatin1Char('=')), QString(QLatin1Char(',')));+ −
if (filter.length()) {+ −
str+= QLatin1String(" where ") + filter;+ −
}+ −
return apply(str, invalidate);+ −
}+ −
}+ −
+ −
/*!+ −
Deletes a record from the database using the cursor's primary+ −
index and the contents of the cursor edit buffer. Returns the+ −
number of records which were deleted.+ −
For error information, use lastError().+ −
+ −
Only records which meet the filter criteria specified by the+ −
cursor's primary index are deleted. If the cursor does not contain+ −
a primary index, no delete is performed and 0 is returned. If \a+ −
invalidate is true (the default), the current cursor can no longer+ −
be navigated. A new select() call must be made before you can move+ −
to a valid record. For example:+ −
+ −
\snippet doc/src/snippets/code/src_qt3support_sql_q3sqlcursor.cpp 8+ −
+ −
In the above example, a cursor is created on the 'prices' table+ −
and positioned to the record to be deleted. First primeDelete() is+ −
called to populate the edit buffer with the current cursor values,+ −
e.g. with an id of 999, and then del() is called to actually+ −
delete the record from the database. Remember: all edit operations+ −
(insert(), update() and delete()) operate on the contents of the+ −
cursor edit buffer and not on the contents of the cursor itself.+ −
+ −
\sa primeDelete() setMode() lastError()+ −
*/+ −
+ −
int Q3SqlCursor::del(bool invalidate)+ −
{+ −
QSqlIndex idx = primaryIndex(false);+ −
if (idx.isEmpty())+ −
return del(qWhereClause(&d->editBuffer, d->nm, QLatin1String("and"), driver()), invalidate);+ −
return del(toString(primaryIndex(), &d->editBuffer, d->nm, QString(QLatin1Char('=')), QLatin1String("and")), invalidate);+ −
}+ −
+ −
/*!+ −
\overload+ −
+ −
Deletes the current cursor record from the database using the+ −
filter \a filter. Only records which meet the filter criteria are+ −
deleted. Returns the number of records which were deleted. If \a+ −
invalidate is true (the default), the current cursor can no longer+ −
be navigated. A new select() call must be made before you can move+ −
to a valid record. For error information, use lastError().+ −
+ −
The \a filter is an SQL \c WHERE clause, e.g. \c{id=500}.+ −
+ −
\sa setMode() lastError()+ −
*/+ −
+ −
int Q3SqlCursor::del(const QString & filter, bool invalidate)+ −
{+ −
if ((d->md & Delete) != Delete)+ −
return 0;+ −
int k = count();+ −
if(k == 0) return 0;+ −
QString str = QLatin1String("delete from ") + name();+ −
if (filter.length())+ −
str+= QLatin1String(" where ") + filter;+ −
return apply(str, invalidate);+ −
}+ −
+ −
/*+ −
\internal+ −
*/+ −
+ −
int Q3SqlCursor::apply(const QString& q, bool invalidate)+ −
{+ −
int ar = 0;+ −
if (invalidate) {+ −
if (exec(q))+ −
ar = numRowsAffected();+ −
} else if (driver()) {+ −
QSqlQuery* sql = d->query();+ −
if (sql && sql->exec(q))+ −
ar = sql->numRowsAffected();+ −
}+ −
return ar;+ −
}+ −
+ −
/*+ −
\internal+ −
*/+ −
+ −
int Q3SqlCursor::applyPrepared(const QString& q, bool invalidate)+ −
{+ −
int ar = 0;+ −
QSqlQuery* sql = 0;+ −
+ −
if (invalidate) {+ −
sql = (QSqlQuery*)this;+ −
d->lastAt = QSql::BeforeFirst;+ −
} else {+ −
sql = d->query();+ −
}+ −
if (!sql)+ −
return 0;+ −
+ −
if (invalidate || sql->lastQuery() != q) {+ −
if (!sql->prepare(q))+ −
return 0;+ −
}+ −
+ −
int cnt = 0;+ −
int fieldCount = (int)count();+ −
for (int j = 0; j < fieldCount; ++j) {+ −
const QSqlField f = d->editBuffer.field(j);+ −
if (d->editBuffer.isGenerated(j)) {+ −
if (f.type() == QVariant::ByteArray)+ −
sql->bindValue(cnt, f.value(), QSql::In | QSql::Binary);+ −
else+ −
sql->bindValue(cnt, f.value());+ −
cnt++;+ −
}+ −
}+ −
if (sql->exec()) {+ −
ar = sql->numRowsAffected();+ −
}+ −
return ar;+ −
}+ −
+ −
/*!+ −
Executes the SQL query \a sql. Returns true of the cursor is+ −
active, otherwise returns false.+ −
*/+ −
bool Q3SqlCursor::exec(const QString & sql)+ −
{+ −
d->lastAt = QSql::BeforeFirst;+ −
QSqlQuery::exec(sql);+ −
return isActive();+ −
}+ −
+ −
/*!+ −
Protected virtual function which is called whenever a field needs+ −
to be calculated. If calculated fields are being used, derived+ −
classes must reimplement this function and return the appropriate+ −
value for field \a name. The default implementation returns an+ −
invalid QVariant.+ −
+ −
\sa setCalculated()+ −
*/+ −
+ −
QVariant Q3SqlCursor::calculateField(const QString&)+ −
{+ −
return QVariant();+ −
}+ −
+ −
/*! \internal+ −
Ensure fieldlist is synced with query.+ −
+ −
*/+ −
+ −
static QString qTrim(const QString& s)+ −
{+ −
QString result = s;+ −
int end = result.length() - 1;+ −
while (end >= 0 && result[end].isSpace()) // skip white space from end+ −
end--;+ −
result.truncate(end + 1);+ −
return result;+ −
}+ −
+ −
/*! \internal+ −
*/+ −
+ −
void Q3SqlCursor::sync()+ −
{+ −
if (isActive() && isValid() && d->lastAt != at()) {+ −
d->lastAt = at();+ −
int i = 0;+ −
int j = 0;+ −
bool haveCalculatedFields = false;+ −
for (; i < count(); ++i) {+ −
if (!haveCalculatedFields && d->infoBuffer[i].isCalculated()) {+ −
haveCalculatedFields = true;+ −
}+ −
if (QSqlRecord::isGenerated(i)) {+ −
QVariant v = QSqlQuery::value(j);+ −
if ((v.type() == QVariant::String) &&+ −
d->infoBuffer[i].isTrim()) {+ −
v = qTrim(v.toString());+ −
}+ −
QSqlRecord::setValue(i, v);+ −
if (QSqlQuery::isNull(j))+ −
QSqlRecord::field(i).clear();+ −
j++;+ −
}+ −
}+ −
if (haveCalculatedFields) {+ −
for (i = 0; i < count(); ++i) {+ −
if (d->infoBuffer[i].isCalculated())+ −
QSqlRecord::setValue(i, calculateField(fieldName(i)));+ −
}+ −
}+ −
}+ −
}+ −
+ −
/*!+ −
Returns the value of field number \a i.+ −
*/+ −
+ −
QVariant Q3SqlCursor::value(int i) const+ −
{+ −
const_cast<Q3SqlCursor *>(this)->sync();+ −
return QSqlRecord::value(i);+ −
}+ −
+ −
/*! \internal+ −
cursors should be filled with Q3SqlFieldInfos...+ −
*/+ −
void Q3SqlCursor::append(const QSqlField& field)+ −
{+ −
append(Q3SqlFieldInfo(field));+ −
}+ −
+ −
/*!+ −
Returns true if the field \a i is NULL or if there is no field at+ −
position \a i; otherwise returns false.+ −
+ −
This is the same as calling QSqlRecord::isNull(\a i)+ −
*/+ −
bool Q3SqlCursor::isNull(int i) const+ −
{+ −
const_cast<Q3SqlCursor *>(this)->sync();+ −
return QSqlRecord::isNull(i);+ −
}+ −
/*!+ −
\overload+ −
+ −
Returns true if the field called \a name is NULL or if there is no+ −
field called \a name; otherwise returns false.+ −
+ −
This is the same as calling QSqlRecord::isNull(\a name)+ −
*/+ −
bool Q3SqlCursor::isNull(const QString& name) const+ −
{+ −
const_cast<Q3SqlCursor *>(this)->sync();+ −
return QSqlRecord::isNull(name);+ −
}+ −
+ −
/*! \internal */+ −
void Q3SqlCursor::setValue(int i, const QVariant& val)+ −
{+ −
sync();+ −
#ifdef QT_DEBUG+ −
qDebug("Q3SqlCursor::setValue(): This will not affect actual database values. Use primeInsert(), primeUpdate() or primeDelete().");+ −
#endif+ −
QSqlRecord::setValue(i, val);+ −
}+ −
+ −
/*! \internal */+ −
bool Q3SqlCursor::seek(int i, bool relative)+ −
{+ −
bool res = QSqlQuery::seek(i, relative);+ −
sync();+ −
return res;+ −
}+ −
+ −
/*! \internal */+ −
bool Q3SqlCursor::next()+ −
{+ −
bool res = QSqlQuery::next();+ −
sync();+ −
return res;+ −
}+ −
+ −
/*!+ −
\fn Q3SqlCursor::previous()+ −
+ −
\internal+ −
*/+ −
+ −
/*! \internal */+ −
bool Q3SqlCursor::prev()+ −
{+ −
bool res = QSqlQuery::previous();+ −
sync();+ −
return res;+ −
}+ −
+ −
/*! \internal */+ −
bool Q3SqlCursor::first()+ −
{+ −
bool res = QSqlQuery::first();+ −
sync();+ −
return res;+ −
}+ −
+ −
/*! \internal */+ −
bool Q3SqlCursor::last()+ −
{+ −
bool res = QSqlQuery::last();+ −
sync();+ −
return res;+ −
}+ −
+ −
QT_END_NAMESPACE+ −
+ −
#endif+ −