Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qsqlquerymodel.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qsqlquerymodel.h"
5#include "qsqlquerymodel_p.h"
6
7#include <qdebug.h>
8#include <qsqldriver.h>
9#include <qsqlfield.h>
10
12
13using namespace Qt::StringLiterals;
14
15#define QSQL_PREFETCH 255
16
18{
19 Q_Q(QSqlQueryModel);
20
21 if (atEnd || limit <= bottom.row() || bottom.column() == -1)
22 return;
23
24 QModelIndex newBottom;
25 const int oldBottomRow = qMax(bottom.row(), 0);
26
27 // try to seek directly
28 if (query.seek(limit)) {
29 newBottom = q->createIndex(limit, bottom.column());
30 } else {
31 // have to seek back to our old position for MS Access
32 int i = oldBottomRow;
33 if (query.seek(i)) {
34 while (query.next())
35 ++i;
36 newBottom = q->createIndex(i, bottom.column());
37 } else {
38 // empty or invalid query
39 newBottom = q->createIndex(-1, bottom.column());
40 }
41 atEnd = true; // this is the end.
42 }
43 if (newBottom.row() >= 0 && newBottom.row() > bottom.row()) {
44 q->beginInsertRows(QModelIndex(), bottom.row() + 1, newBottom.row());
45 bottom = newBottom;
46 q->endInsertRows();
47 } else {
48 bottom = newBottom;
49 }
50}
51
55
57{
59 memset(colOffsets.data(), 0, colOffsets.size() * sizeof(int));
60}
61
62int QSqlQueryModelPrivate::columnInQuery(int modelColumn) const
63{
64 if (modelColumn < 0 || modelColumn >= rec.count() || !rec.isGenerated(modelColumn) || modelColumn >= colOffsets.size())
65 return -1;
66 return modelColumn - colOffsets[modelColumn];
67}
68
124
131
140
155{
156 Q_D(QSqlQueryModel);
157 if (parent.isValid())
158 return;
159 d->prefetch(qMax(d->bottom.row(), 0) + QSQL_PREFETCH);
160}
161
172{
173 Q_D(const QSqlQueryModel);
174 return (!parent.isValid() && !d->atEnd);
175}
176
194QHash<int, QByteArray> QSqlQueryModel::roleNames() const
195{
196 return QHash<int, QByteArray> {
197 { Qt::DisplayRole, QByteArrayLiteral("display") }
198 };
199}
200
203void QSqlQueryModel::beginInsertRows(const QModelIndex &parent, int first, int last)
204{
205 Q_D(QSqlQueryModel);
206 if (!d->nestedResetLevel)
208}
209
213{
214 Q_D(QSqlQueryModel);
215 if (!d->nestedResetLevel)
217}
218
221void QSqlQueryModel::beginRemoveRows(const QModelIndex &parent, int first, int last)
222{
223 Q_D(QSqlQueryModel);
224 if (!d->nestedResetLevel)
226}
227
231{
232 Q_D(QSqlQueryModel);
233 if (!d->nestedResetLevel)
235}
236
239void QSqlQueryModel::beginInsertColumns(const QModelIndex &parent, int first, int last)
240{
241 Q_D(QSqlQueryModel);
242 if (!d->nestedResetLevel)
244}
245
249{
250 Q_D(QSqlQueryModel);
251 if (!d->nestedResetLevel)
253}
254
257void QSqlQueryModel::beginRemoveColumns(const QModelIndex &parent, int first, int last)
258{
259 Q_D(QSqlQueryModel);
260 if (!d->nestedResetLevel)
262}
263
267{
268 Q_D(QSqlQueryModel);
269 if (!d->nestedResetLevel)
271}
272
276{
277 Q_D(QSqlQueryModel);
278 if (!d->nestedResetLevel)
280 ++d->nestedResetLevel;
281}
282
286{
287 Q_D(QSqlQueryModel);
288 --d->nestedResetLevel;
289 if (!d->nestedResetLevel)
291}
292
305{
306 Q_D(const QSqlQueryModel);
307 return index.isValid() ? 0 : d->bottom.row() + 1;
308}
309
313{
314 Q_D(const QSqlQueryModel);
315 return index.isValid() ? 0 : d->rec.count();
316}
317
327{
328 Q_D(const QSqlQueryModel);
329 if (!item.isValid())
330 return QVariant();
331
332 QVariant v;
333 if (role & ~(Qt::DisplayRole | Qt::EditRole))
334 return v;
335
336 if (!d->rec.isGenerated(item.column()))
337 return v;
339 if (dItem.row() > d->bottom.row())
340 const_cast<QSqlQueryModelPrivate *>(d)->prefetch(dItem.row());
341
342 if (!d->query.seek(dItem.row())) {
343 d->error = d->query.lastError();
344 return v;
345 }
346
347 return d->query.value(dItem.column());
348}
349
354QVariant QSqlQueryModel::headerData(int section, Qt::Orientation orientation, int role) const
355{
356 Q_D(const QSqlQueryModel);
357 if (orientation == Qt::Horizontal) {
358 QVariant val = d->headers.value(section).value(role);
359 if (role == Qt::DisplayRole && !val.isValid())
360 val = d->headers.value(section).value(Qt::EditRole);
361 if (val.isValid())
362 return val;
363 if (role == Qt::DisplayRole && d->rec.count() > section && d->columnInQuery(section) != -1)
364 return d->rec.fieldName(section);
365 }
366 return QAbstractItemModel::headerData(section, orientation, role);
367}
368
378{
379 // do nothing
380}
381
382#if QT_DEPRECATED_SINCE(6, 2)
388{
390 setQuery(std::move(copy));
391}
392#endif // QT_DEPRECATED_SINCE(6, 2)
393
409{
410 Q_D(QSqlQueryModel);
412
413 QSqlRecord newRec = query.record();
414 bool columnsChanged = (newRec != d->rec);
415
416 if (d->colOffsets.size() != newRec.count() || columnsChanged)
417 d->initColOffsets(newRec.count());
418
419 d->bottom = QModelIndex();
420 d->error = QSqlError();
421 d->query = std::move(query);
422 d->rec = newRec;
423 d->atEnd = true;
424
425 if (d->query.isForwardOnly()) {
426 d->error = QSqlError("Forward-only queries cannot be used in a data model"_L1,
429 return;
430 }
431
432 if (!d->query.isActive()) {
433 d->error = d->query.lastError();
435 return;
436 }
437
438 if (d->query.driver()->hasFeature(QSqlDriver::QuerySize) && d->query.size() > 0) {
439 d->bottom = createIndex(d->query.size() - 1, d->rec.count() - 1);
440 } else {
441 d->bottom = createIndex(-1, d->rec.count() - 1);
442 d->atEnd = false;
443 }
444
445
446 // fetchMore does the rowsInserted stuff for incremental models
447 fetchMore();
448
450 queryChange();
451}
452
471
476{
477 Q_D(QSqlQueryModel);
479 d->error = QSqlError();
480 d->atEnd = true;
481 d->query.clear();
482 d->rec.clear();
483 d->colOffsets.clear();
484 d->bottom = QModelIndex();
485 d->headers.clear();
487}
488
503bool QSqlQueryModel::setHeaderData(int section, Qt::Orientation orientation,
504 const QVariant &value, int role)
505{
506 Q_D(QSqlQueryModel);
507 if (orientation != Qt::Horizontal || section < 0 || columnCount() <= section)
508 return false;
509
510 if (d->headers.size() <= section)
511 d->headers.resize(qMax(section + 1, 16));
512 d->headers[section][role] = value;
513 emit headerDataChanged(orientation, section, section);
514 return true;
515}
516
523{
524 Q_D(const QSqlQueryModel);
525 return d->query;
526}
527
535{
536 Q_D(const QSqlQueryModel);
537 return d->error;
538}
539
547{
548 Q_D(QSqlQueryModel);
549 d->error = error;
550}
551
563{
564 Q_D(const QSqlQueryModel);
565 if (row < 0)
566 return d->rec;
567
568 QSqlRecord rec = d->rec;
569 for (int i = 0; i < rec.count(); ++i)
571 return rec;
572}
573
585{
586 Q_D(const QSqlQueryModel);
587 return d->rec;
588}
589
605{
606 Q_D(QSqlQueryModel);
607 if (count <= 0 || parent.isValid() || column < 0 || column > d->rec.count())
608 return false;
609
611 for (int c = 0; c < count; ++c) {
612 QSqlField field;
613 field.setReadOnly(true);
614 field.setGenerated(false);
615 d->rec.insert(column, field);
616 if (d->colOffsets.size() < d->rec.count()) {
617 int nVal = d->colOffsets.isEmpty() ? 0 : d->colOffsets[d->colOffsets.size() - 1];
618 d->colOffsets.append(nVal);
619 Q_ASSERT(d->colOffsets.size() >= d->rec.count());
620 }
621 for (int i = column + 1; i < d->colOffsets.size(); ++i)
622 ++d->colOffsets[i];
623 }
625 return true;
626}
627
640{
641 Q_D(QSqlQueryModel);
642 if (count <= 0 || parent.isValid() || column < 0 || column >= d->rec.count())
643 return false;
644
646
647 int i;
648 for (i = 0; i < count; ++i)
649 d->rec.remove(column);
650 for (i = column; i < d->colOffsets.size(); ++i)
651 d->colOffsets[i] -= count;
652
654 return true;
655}
656
670{
671 Q_D(const QSqlQueryModel);
672 int modelColumn = d->columnInQuery(item.column());
673 if (modelColumn < 0)
674 return QModelIndex();
675 return createIndex(item.row(), modelColumn, item.internalPointer());
676}
677
679
680#include "moc_qsqlquerymodel.cpp"
void endResetModel()
Completes a model reset operation.
virtual Q_INVOKABLE QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const
Returns the data for the given role and section in the header with the specified orientation.
void endRemoveRows()
Ends a row removal operation.
void beginRemoveColumns(const QModelIndex &parent, int first, int last)
Begins a column removal operation.
void headerDataChanged(Qt::Orientation orientation, int first, int last)
This signal is emitted whenever a header is changed.
void beginInsertColumns(const QModelIndex &parent, int first, int last)
Begins a column insertion operation.
void endInsertRows()
Ends a row insertion operation.
void beginResetModel()
Begins a model reset operation.
void endRemoveColumns()
Ends a column removal operation.
QModelIndex createIndex(int row, int column, const void *data=nullptr) const
Creates a model index for the given row and column with the internal pointer ptr.
void endInsertColumns()
Ends a column insertion operation.
void beginRemoveRows(const QModelIndex &parent, int first, int last)
Begins a row removal operation.
void beginInsertRows(const QModelIndex &parent, int first, int last)
Begins a row insertion operation.
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
\inmodule QtCore
constexpr int row() const noexcept
Returns the row this model index refers to.
\inmodule QtCore
Definition qobject.h:103
The QSqlDatabase class handles a connection to a database.
The QSqlError class provides SQL database error information.
Definition qsqlerror.h:17
@ ConnectionError
Definition qsqlerror.h:21
The QSqlField class manipulates the fields in SQL database tables and views.
Definition qsqlfield.h:19
void setReadOnly(bool readOnly)
Sets \l readOnly to readOnly.
void setGenerated(bool gen)
Sets \l generated to gen.
QVarLengthArray< int, 56 > colOffsets
void initColOffsets(int size)
int columnInQuery(int modelColumn) const
The QSqlQueryModel class provides a read-only data model for SQL result sets.
void beginInsertRows(const QModelIndex &parent, int first, int last)
virtual QModelIndex indexInQuery(const QModelIndex &item) const
Returns the index of the value in the database result set for the given item in the model.
QVariant data(const QModelIndex &item, int role=Qt::DisplayRole) const override
Returns the value for the specified item and role.
QSqlQueryModel(QObject *parent=nullptr)
Creates an empty QSqlQueryModel with the given parent.
void beginRemoveRows(const QModelIndex &parent, int first, int last)
int rowCount(const QModelIndex &parent=QModelIndex()) const override
If the database supports returning the size of a query (see QSqlDriver::hasFeature()),...
const QSqlQuery & query(QT6_DECL_NEW_OVERLOAD) const
Returns a reference to the const QSqlQuery object associated with this model.
virtual void queryChange()
This virtual function is called whenever the query changes.
void setLastError(const QSqlError &error)
Protected function which allows derived classes to set the value of the last error that occurred on t...
bool canFetchMore(const QModelIndex &parent=QModelIndex()) const override
Returns true if it is possible to read more rows from the database.
void setQuery(QSqlQuery &&query)
Resets the model and sets the data provider to be the given query.
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
Returns the header data for the given role in the section of the header with the specified orientatio...
virtual ~QSqlQueryModel()
Destroys the object and frees any allocated resources.
bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role=Qt::EditRole) override
Sets the caption for a horizontal header for the specified role to value.
void beginRemoveColumns(const QModelIndex &parent, int first, int last)
QHash< int, QByteArray > roleNames() const override
void fetchMore(const QModelIndex &parent=QModelIndex()) override
Fetches more rows from a database.
void beginInsertColumns(const QModelIndex &parent, int first, int last)
QSqlError lastError() const
Returns information about the last error that occurred on the database.
int columnCount(const QModelIndex &parent=QModelIndex()) const override
\reimp
QSqlRecord record() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
virtual void clear()
Clears the model and releases any acquired resource.
bool insertColumns(int column, int count, const QModelIndex &parent=QModelIndex()) override
Inserts count columns into the model at position column.
bool removeColumns(int column, int count, const QModelIndex &parent=QModelIndex()) override
Removes count columns from the model starting from position column.
The QSqlQuery class provides a means of executing and manipulating SQL statements.
Definition qsqlquery.h:24
The QSqlRecord class encapsulates a database record.
Definition qsqlrecord.h:20
int count() const
Returns the number of fields in the record.
void setValue(int i, const QVariant &val)
Sets the value of the field at position index to val.
bool isGenerated(int i) const
Returns true if the record has a field at position index and this field is to be generated (the defau...
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
constexpr size_type size() const noexcept
void resize(qsizetype sz)
T * data() noexcept
\inmodule QtCore
Definition qvariant.h:65
T value() const &
Definition qvariant.h:516
Combined button and popup list for selecting options.
Orientation
Definition qnamespace.h:98
@ Horizontal
Definition qnamespace.h:99
@ EditRole
@ DisplayRole
static jboolean copy(JNIEnv *, jobject)
#define QByteArrayLiteral(str)
Definition qbytearray.h:52
#define QT_IGNORE_DEPRECATIONS(statement)
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLsizei const GLfloat * v
[13]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint GLint bottom
GLint first
GLenum GLenum GLsizei void GLsizei void * column
GLenum query
const GLubyte * c
GLuint GLfloat * val
GLint limit
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLenum GLenum GLsizei void * row
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QSQL_PREFETCH
#define emit
#define QT6_IMPL_NEW_OVERLOAD
QMimeDatabase db
[0]
QGraphicsItem * item