Skip to content

Commit

Permalink
Merge pull request #40750 from elpaso/connections-api-queryresult-model
Browse files Browse the repository at this point in the history
QgsQueryResultModel
  • Loading branch information
elpaso committed Jan 14, 2021
2 parents 4b9f82d + dbef0ea commit a0d847f
Show file tree
Hide file tree
Showing 21 changed files with 631 additions and 125 deletions.
Expand Up @@ -47,41 +47,50 @@ is not supported or cannot be performed without errors.

struct QueryResult
{
SIP_PYOBJECT __repr__();
%MethodCode
QString str = QStringLiteral( "<QgsAbstractDatabaseProviderConnection.QueryResult: %1 rows>" ).arg( sipCpp->rowCount() );
sipRes = PyUnicode_FromString( str.toUtf8().constData() );
%End

QStringList columns() const;
%Docstring
Returns the column names
%End

QList<QList<QVariant> > rows() const;
QList<QList<QVariant> > rows( QgsFeedback *feedback = 0 );
%Docstring
Returns the results rows
%End

qlonglong rowCount() const;
%Docstring
Returns the row count
Returns the result rows by calling the iterator internally and fetching
all the rows, an optional ``feedback`` can be used to interrupt the fetching loop.

.. note::

the value may not be exact or it may be -1 if not known
calling this function more than one time is not supported: the second
call will always return an empty list.
%End

bool hasNextRow() const;
%Docstring
Returns ``True`` if there are more rows to fetch

.. seealso:: :py:func:`nextRow`

.. seealso:: :py:func:`rewind`
%End

QList<QVariant> nextRow();
QList<QVariant> nextRow() const;
%Docstring
Returns the next result row or an empty row if there are no rows left

.. seealso:: :py:func:`hasNextRow`

.. seealso:: :py:func:`rewind`
%End

qlonglong fetchedRowCount( ) const;
%Docstring
Returns the number of fetched rows

.. seealso:: :py:func:`rowCount`
%End


// Python iterator
QueryResult *__iter__();
%MethodCode
sipRes = sipCpp;
Expand Down Expand Up @@ -110,7 +119,6 @@ Returns the next result row or an empty row if there are no rows left




};


Expand Down
60 changes: 60 additions & 0 deletions python/core/auto_generated/qgsqueryresultmodel.sip.in
@@ -0,0 +1,60 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsqueryresultmodel.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/








class QgsQueryResultModel : QAbstractListModel
{
%Docstring
The QgsQueryResultModel class is a model for QgsAbstractDatabaseProviderConnection.QueryResult

.. versionadded:: 3.18
%End

%TypeHeaderCode
#include "qgsqueryresultmodel.h"
%End
public:

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

~QgsQueryResultModel();

public:

virtual int rowCount( const QModelIndex &parent ) const;

virtual int columnCount( const QModelIndex &parent ) const;

virtual QVariant data( const QModelIndex &index, int role ) const;


public slots:

void rowsReady( const QList<QList<QVariant> > &rows );
%Docstring
Triggered when ``newRows`` have been fetched and can be added to the model
%End

};

/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsqueryresultmodel.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
1 change: 1 addition & 0 deletions python/core/core_auto.sip
Expand Up @@ -156,6 +156,7 @@
%Include auto_generated/qgsproxyfeaturesink.sip
%Include auto_generated/qgsproxyprogresstask.sip
%Include auto_generated/qgspythonrunner.sip
%Include auto_generated/qgsqueryresultmodel.sip
%Include auto_generated/qgsrange.sip
%Include auto_generated/qgsreadwritecontext.sip
%Include auto_generated/qgsreadwritelocker.sip
Expand Down
2 changes: 2 additions & 0 deletions src/core/CMakeLists.txt
Expand Up @@ -397,6 +397,7 @@ set(QGIS_CORE_SRCS
qgspointxy.cpp
qgspointlocator.cpp
qgspointlocatorinittask.cpp
qgsqueryresultmodel.cpp
qgssnappingconfig.cpp
qgsprojutils.cpp
qgsproperty.cpp
Expand Down Expand Up @@ -1004,6 +1005,7 @@ set(QGIS_CORE_HDRS
qgsproxyfeaturesink.h
qgsproxyprogresstask.h
qgspythonrunner.h
qgsqueryresultmodel.h
qgsrange.h
qgsreadwritecontext.h
qgsreadwritelocker.h
Expand Down
23 changes: 14 additions & 9 deletions src/core/providers/ogr/qgsgeopackageproviderconnection.cpp
Expand Up @@ -380,10 +380,6 @@ QgsAbstractDatabaseProviderConnection::QueryResult QgsGeoPackageProviderConnecti

auto iterator = std::make_shared<QgsGeoPackageProviderResultIterator>( std::move( hDS ), ogrLayer );
QgsAbstractDatabaseProviderConnection::QueryResult results( iterator );
// Note: Returns the number of features in the layer. For dynamic databases the count may not be exact.
// If bForce is FALSE, and it would be expensive to establish the feature count a value of -1 may
// be returned indicating that the count isn’t know.
results.setRowCount( OGR_L_GetFeatureCount( ogrLayer, 0 /* bForce=false: do not scan the whole layer */ ) );

gdal::ogr_feature_unique_ptr fet;
if ( fet.reset( OGR_L_GetNextFeature( ogrLayer ) ), fet )
Expand Down Expand Up @@ -425,14 +421,14 @@ QgsAbstractDatabaseProviderConnection::QueryResult QgsGeoPackageProviderConnecti
return QgsAbstractDatabaseProviderConnection::QueryResult();
}

QVariantList QgsGeoPackageProviderResultIterator::nextRow()
QVariantList QgsGeoPackageProviderResultIterator::nextRowPrivate()
{
const QVariantList currentRow { mNextRow };
mNextRow = nextRowPrivate();
mNextRow = nextRowInternal();
return currentRow;
}

QVariantList QgsGeoPackageProviderResultIterator::nextRowPrivate()
QVariantList QgsGeoPackageProviderResultIterator::nextRowInternal()
{
QVariantList row;
if ( mHDS && mOgrLayer )
Expand All @@ -457,11 +453,17 @@ QVariantList QgsGeoPackageProviderResultIterator::nextRowPrivate()
}
}
}
else
{
// Release the resources
GDALDatasetReleaseResultSet( mHDS.get(), mOgrLayer );
mHDS.release();
}
}
return row;
}

bool QgsGeoPackageProviderResultIterator::hasNextRow() const
bool QgsGeoPackageProviderResultIterator::hasNextRowPrivate() const
{
return ! mNextRow.isEmpty();
}
Expand All @@ -488,5 +490,8 @@ QList<QgsVectorDataProvider::NativeType> QgsGeoPackageProviderConnection::native

QgsGeoPackageProviderResultIterator::~QgsGeoPackageProviderResultIterator()
{
GDALDatasetReleaseResultSet( mHDS.get(), mOgrLayer );
if ( mHDS )
{
GDALDatasetReleaseResultSet( mHDS.get(), mOgrLayer );
}
}
7 changes: 3 additions & 4 deletions src/core/providers/ogr/qgsgeopackageproviderconnection.h
Expand Up @@ -34,9 +34,6 @@ struct QgsGeoPackageProviderResultIterator: public QgsAbstractDatabaseProviderCo

~QgsGeoPackageProviderResultIterator();

QVariantList nextRow() override;
bool hasNextRow() const override;

void setFields( const QgsFields &fields );

private:
Expand All @@ -46,7 +43,9 @@ struct QgsGeoPackageProviderResultIterator: public QgsAbstractDatabaseProviderCo
QgsFields mFields;
QVariantList mNextRow;

QVariantList nextRowPrivate();
QVariantList nextRowPrivate() override;
QVariantList nextRowInternal();
bool hasNextRowPrivate() const override;

};

Expand Down
73 changes: 50 additions & 23 deletions src/core/qgsabstractdatabaseproviderconnection.cpp
Expand Up @@ -17,6 +17,8 @@
#include "qgsvectorlayer.h"
#include "qgsexception.h"
#include "qgslogger.h"
#include "qgsfeedback.h"

#include <QVariant>
#include <QObject>

Expand Down Expand Up @@ -435,49 +437,55 @@ void QgsAbstractDatabaseProviderConnection::TableProperty::setSchema( const QStr
}


///@cond PRIVATE

QStringList QgsAbstractDatabaseProviderConnection::QueryResult::columns() const
{
return mColumns;
}

QList<QList<QVariant> > QgsAbstractDatabaseProviderConnection::QueryResult::rows() const
QList<QList<QVariant> > QgsAbstractDatabaseProviderConnection::QueryResult::rows( QgsFeedback *feedback )
{
// mRowCount might be -1 (unknown)
while ( mResultIterator && ( mRowCount < 0 || mRows.count() < mRowCount ) )

QList<QList<QVariant> > rows;

while ( mResultIterator &&
mResultIterator->hasNextRow() &&
( ! feedback || ! feedback->isCanceled() ) )
{
const QVariantList row( mResultIterator->nextRow() );
if ( row.isEmpty() )
{
break;
}
mRows.push_back( row );
else
{
rows.push_back( row );
}
}
return mRows;
return rows;
}

QList<QVariant> QgsAbstractDatabaseProviderConnection::QueryResult::nextRow()
QList<QVariant> QgsAbstractDatabaseProviderConnection::QueryResult::nextRow() const
{
if ( ! mResultIterator && ! mResultIterator->hasNextRow() )
if ( ! mResultIterator )
{
return QList<QVariant>();
}
return mResultIterator->nextRow();
}

const QList<QVariant> row( mResultIterator->nextRow() );

if ( ! row.isEmpty() )
qlonglong QgsAbstractDatabaseProviderConnection::QueryResult::fetchedRowCount() const
{
if ( ! mResultIterator )
{
mRows.push_back( row );
return 0;
}

return row;
return mResultIterator->fetchedRowCount();
}


qlonglong QgsAbstractDatabaseProviderConnection::QueryResult::rowCount() const
{
return mRowCount;
}

bool QgsAbstractDatabaseProviderConnection::QueryResult::hasNextRow() const
{
if ( ! mResultIterator )
Expand All @@ -487,20 +495,39 @@ bool QgsAbstractDatabaseProviderConnection::QueryResult::hasNextRow() const
return mResultIterator->hasNextRow();
}

///@cond PRIVATE

void QgsAbstractDatabaseProviderConnection::QueryResult::appendColumn( const QString &columnName )
{
mColumns.push_back( columnName );
}

void QgsAbstractDatabaseProviderConnection::QueryResult::setRowCount( const qlonglong &rowCount )
{
mRowCount = rowCount;
}

QgsAbstractDatabaseProviderConnection::QueryResult::QueryResult( std::shared_ptr<QgsAbstractDatabaseProviderConnection::QueryResult::QueryResultIterator> iterator )
: mResultIterator( iterator )
{}


QVariantList QgsAbstractDatabaseProviderConnection::QueryResult::QueryResultIterator::nextRow()
{
QMutexLocker lock( &mMutex );
const QVariantList row { nextRowPrivate() };
if ( ! row.isEmpty() )
{
mFetchedRowCount++;
}
return row;
}

bool QgsAbstractDatabaseProviderConnection::QueryResult::QueryResultIterator::hasNextRow() const
{
QMutexLocker lock( &mMutex );
return hasNextRowPrivate();
}

qlonglong QgsAbstractDatabaseProviderConnection::QueryResult::QueryResultIterator::fetchedRowCount()
{
QMutexLocker lock( &mMutex );
return mFetchedRowCount;
}


///@endcond private

0 comments on commit a0d847f

Please sign in to comment.