Skip to content

Commit

Permalink
Doxy and new at() method
Browse files Browse the repository at this point in the history
  • Loading branch information
elpaso committed Jan 13, 2021
1 parent ea72ab9 commit a717bc7
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 7 deletions.
Expand Up @@ -60,7 +60,12 @@ Returns the column names

QList<QList<QVariant> > rows() const;
%Docstring
Returns the results rows
Returns the results rows by calling the iterator internally.

.. note::

results are cached internally and subsequent calls to this method
will return the cached results.
%End

qlonglong rowCount() const;
Expand All @@ -82,6 +87,15 @@ Returns ``True`` if there are more rows to fetch
Returns the next result row or an empty row if there are no rows left
%End

QList<QVariant> at( qlonglong index ) const;
%Docstring
Returns the row data at 0-based index ``index``, if index is not valid, an empty list is returned.

.. note::

this method calls the iterator internally until ``index`` row is retrieved
%End

QueryResult *__iter__();
%MethodCode
sipRes = sipCpp;
Expand Down
3 changes: 3 additions & 0 deletions python/core/auto_generated/qgsqueryresultmodel.sip.in
Expand Up @@ -23,6 +23,9 @@ The QgsQueryResultModel class is a model for QgsAbstractDatabaseProviderConnecti
public:

QgsQueryResultModel( const QgsAbstractDatabaseProviderConnection::QueryResult &queryResult, QObject *parent = 0 );
%Docstring
Constructs a QgsQueryResultModel from a ``queryResult`` with optional ``parent``
%End

public:

Expand Down
26 changes: 26 additions & 0 deletions src/core/qgsabstractdatabaseproviderconnection.cpp
Expand Up @@ -472,6 +472,32 @@ QList<QVariant> QgsAbstractDatabaseProviderConnection::QueryResult::nextRow()
return row;
}

QList<QVariant> QgsAbstractDatabaseProviderConnection::QueryResult::at( qlonglong index ) const
{
if ( index < 0 )
return QList<QVariant>();
// Fetch rows until the index
if ( index > mRows.count( ) )
{
while ( mResultIterator && ( mRowCount < 0 || mRows.count() < mRowCount ) && index < mRows.count() )
{
const QVariantList row { mResultIterator->nextRow() };
if ( row.isEmpty() )
{
break;
}
mRows.push_back( row );
}
}

if ( index >= mRows.count( ) )
{
return QList<QVariant>();
}

return mRows.at( index );
}


qlonglong QgsAbstractDatabaseProviderConnection::QueryResult::rowCount() const
{
Expand Down
16 changes: 15 additions & 1 deletion src/core/qgsabstractdatabaseproviderconnection.h
Expand Up @@ -73,6 +73,12 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv
* It encapsulates the result rows and a list of the column names.
* The query result may be empty in case the query returns nothing.
*
* Rows can be retrieved by iterating over the result with hasNextRow() and nextRow()
* or by calling rows() that will internally iterate over the results and return
* the result list.
*
* The list of results is cached internally and subsequent calls to rows() or at() return the
* cached results.
*
* \since QGIS 3.18
*/
Expand All @@ -92,7 +98,9 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv
QStringList columns() const;

/**
* Returns the results rows
* Returns the results rows by calling the iterator internally.
* \note results are cached internally and subsequent calls to this method
* will return the cached results.
*/
QList<QList<QVariant> > rows() const;

Expand All @@ -112,6 +120,12 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv
*/
QList<QVariant> nextRow();

/**
* Returns the row data at 0-based index \a index, if index is not valid, an empty list is returned.
* \note this method calls the iterator internally until \a index row is retrieved
*/
QList<QVariant> at( qlonglong index ) const;

#ifdef SIP_RUN
QueryResult *__iter__();
% MethodCode
Expand Down
10 changes: 6 additions & 4 deletions src/core/qgsqueryresultmodel.cpp
Expand Up @@ -39,17 +39,19 @@ int QgsQueryResultModel::columnCount( const QModelIndex &parent ) const

QVariant QgsQueryResultModel::data( const QModelIndex &index, int role ) const
{
if ( !index.isValid() )
if ( !index.isValid() || index.row() < 0 || index.column() > mQueryResult.columns().count() - 1 )
return QVariant();

Q_ASSERT( mQueryResult.rows().count( ) == mRowCount );

if ( index.row() >= mRowCount || index.row() < 0 )
return QVariant();

if ( role == Qt::DisplayRole )
{
return mQueryResult.rows().at( index.row() );
const QList<QVariant> result { mQueryResult.at( index.row() ) };
if ( index.column() < result.count( ) )
{
return result.at( index.column() );
}
}
return QVariant();
}
Expand Down
3 changes: 3 additions & 0 deletions src/core/qgsqueryresultmodel.h
Expand Up @@ -34,6 +34,9 @@ class CORE_EXPORT QgsQueryResultModel : public QAbstractListModel
Q_OBJECT
public:

/**
* Constructs a QgsQueryResultModel from a \a queryResult with optional \a parent
*/
QgsQueryResultModel( const QgsAbstractDatabaseProviderConnection::QueryResult &queryResult, QObject *parent = nullptr );

// QAbstractItemModel interface
Expand Down
14 changes: 13 additions & 1 deletion tests/src/python/test_qgsqueryresultmodel.py
Expand Up @@ -20,7 +20,7 @@
QgsAbstractDatabaseProviderConnection,
)
from qgis.testing import unittest, start_app
from qgis.PyQt.QtCore import QCoreApplication
from qgis.PyQt.QtCore import QCoreApplication, QVariant, Qt


class TestPyQgsQgsQueryResultModel(unittest.TestCase):
Expand Down Expand Up @@ -49,10 +49,15 @@ def test_model(self):
self.assertEqual(model.rowCount(model.index(-1)), 0)
self.assertTrue(model.canFetchMore(model.index(-1)))

self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole), QVariant())
self.assertEqual(model.data(model.index(999, 0), Qt.DisplayRole), QVariant())

model.fetchMore(model.index(-1))
self.assertEqual(model.rowCount(model.index(-1)), 200)
self.assertTrue(res.hasNextRow())

self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole), 1)

# Fetch the rest
for batch in range(2, 6):
model.fetchMore(model.index(-1))
Expand All @@ -62,6 +67,13 @@ def test_model(self):
self.assertFalse(res.hasNextRow())
self.assertFalse(model.canFetchMore(model.index(-1)))

# Test data
for i in range(1000):
self.assertEqual(model.data(model.index(i, 0), Qt.DisplayRole), i + 1)

self.assertEqual(model.data(model.index(1000, 0), Qt.DisplayRole), QVariant())
self.assertEqual(model.data(model.index(1, 1), Qt.DisplayRole), QVariant())


if __name__ == '__main__':
unittest.main()

0 comments on commit a717bc7

Please sign in to comment.