Navigation Menu

Skip to content

Commit

Permalink
Add rowCount to connections API
Browse files Browse the repository at this point in the history
+ fix memory leak in API fetcher
+ add progress bar to result widget
  • Loading branch information
elpaso committed Jul 6, 2021
1 parent 357fa9c commit 233a809
Show file tree
Hide file tree
Showing 21 changed files with 151 additions and 34 deletions.
Expand Up @@ -89,6 +89,13 @@ Returns the number of fetched rows.
.. seealso:: :py:func:`rowCount`
%End

qlonglong rowCount( ) const;
%Docstring
Returns the number of rows returned by a SELECT query or -1 if unknown

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


// Python iterator
QueryResult *__iter__();
Expand Down
20 changes: 20 additions & 0 deletions src/core/providers/ogr/qgsgeopackageproviderconnection.cpp
Expand Up @@ -29,6 +29,8 @@
#include <QTextCodec>


///@cond PRIVATE

QgsGeoPackageProviderConnection::QgsGeoPackageProviderConnection( const QString &name )
: QgsAbstractDatabaseProviderConnection( name )
{
Expand Down Expand Up @@ -616,6 +618,11 @@ bool QgsGeoPackageProviderResultIterator::hasNextRowPrivate() const
return ! mNextRow.isEmpty();
}

qlonglong QgsGeoPackageProviderResultIterator::rowCountPrivate() const
{
return mRowCount;
}

void QgsGeoPackageProviderResultIterator::setFields( const QgsFields &fields )
{
mFields = fields;
Expand Down Expand Up @@ -1153,10 +1160,23 @@ QMap<QgsAbstractDatabaseProviderConnection::SqlKeywordCategory, QStringList> Qgs
} );
}

QgsGeoPackageProviderResultIterator::QgsGeoPackageProviderResultIterator( gdal::ogr_datasource_unique_ptr hDS, OGRLayerH ogrLayer )
: mHDS( std::move( hDS ) )
, mOgrLayer( ogrLayer )
{
if ( mOgrLayer )
{
// Do not scan the layer!
mRowCount = OGR_L_GetFeatureCount( mOgrLayer, false );
}
}

QgsGeoPackageProviderResultIterator::~QgsGeoPackageProviderResultIterator()
{
if ( mHDS )
{
GDALDatasetReleaseResultSet( mHDS.get(), mOgrLayer );
}
}

///@endcond
9 changes: 4 additions & 5 deletions src/core/providers/ogr/qgsgeopackageproviderconnection.h
Expand Up @@ -28,10 +28,7 @@
struct QgsGeoPackageProviderResultIterator: public QgsAbstractDatabaseProviderConnection::QueryResult::QueryResultIterator
{

QgsGeoPackageProviderResultIterator( gdal::ogr_datasource_unique_ptr hDS, OGRLayerH ogrLayer )
: mHDS( std::move( hDS ) )
, mOgrLayer( ogrLayer )
{}
QgsGeoPackageProviderResultIterator( gdal::ogr_datasource_unique_ptr hDS, OGRLayerH ogrLayer );

~QgsGeoPackageProviderResultIterator();

Expand All @@ -47,10 +44,12 @@ struct QgsGeoPackageProviderResultIterator: public QgsAbstractDatabaseProviderCo
QVariantList mNextRow;
QString mGeometryColumnName;
QString mPrimaryKeyColumnName;
qlonglong mRowCount = -1;

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

};

Expand Down
15 changes: 15 additions & 0 deletions src/core/providers/qgsabstractdatabaseproviderconnection.cpp
Expand Up @@ -1438,6 +1438,15 @@ qlonglong QgsAbstractDatabaseProviderConnection::QueryResult::fetchedRowCount()
return mResultIterator->fetchedRowCount();
}

qlonglong QgsAbstractDatabaseProviderConnection::QueryResult::rowCount() const
{
if ( ! mResultIterator )
{
return -1;
}
return mResultIterator->rowCount();
}


bool QgsAbstractDatabaseProviderConnection::QueryResult::hasNextRow() const
{
Expand Down Expand Up @@ -1482,5 +1491,11 @@ qlonglong QgsAbstractDatabaseProviderConnection::QueryResult::QueryResultIterato
return mFetchedRowCount;
}

qlonglong QgsAbstractDatabaseProviderConnection::QueryResult::QueryResultIterator::rowCount()
{
QMutexLocker lock( &mMutex );
return rowCountPrivate();
}


///@endcond private
18 changes: 18 additions & 0 deletions src/core/providers/qgsabstractdatabaseproviderconnection.h
Expand Up @@ -119,6 +119,13 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv
*/
qlonglong fetchedRowCount( ) const;

/**
* Returns the number of rows returned by a SELECT query or -1 if unknown
*
* \see fetchedRowCount()
*/
qlonglong rowCount( ) const;


#ifdef SIP_RUN
// Python iterator
Expand Down Expand Up @@ -154,15 +161,26 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv
*/
struct CORE_EXPORT QueryResultIterator SIP_SKIP
{
//! Returns the next result row
QVariantList nextRow();

//! Returns TRUE if there is another row to fetch
bool hasNextRow() const;

//! Returns the number of actually fetched rows
qlonglong fetchedRowCount();

//! Returns the total number of rows returned by a SELECT query or -1 if this is not known.
qlonglong rowCount();

virtual ~QueryResultIterator() = default;

private:

virtual QVariantList nextRowPrivate() = 0;
virtual bool hasNextRowPrivate() const = 0;
virtual qlonglong rowCountPrivate() const = 0;

mutable qlonglong mFetchedRowCount = 0;
mutable QMutex mMutex;

Expand Down
11 changes: 5 additions & 6 deletions src/core/qgsqueryresultmodel.cpp
Expand Up @@ -21,12 +21,12 @@ QgsQueryResultModel::QgsQueryResultModel( const QgsAbstractDatabaseProviderConne
, mColumns( queryResult.columns() )
{
qRegisterMetaType< QList<QList<QVariant>>>( "QList<QList<QVariant>>" );
mWorker = new QgsQueryResultFetcher( &mQueryResult );
mWorker = std::make_unique<QgsQueryResultFetcher>( &mQueryResult );
mWorker->moveToThread( &mWorkerThread );
connect( &mWorkerThread, &QThread::started, mWorker, &QgsQueryResultFetcher::fetchRows );
connect( mWorker, &QgsQueryResultFetcher::rowsReady, this, &QgsQueryResultModel::rowsReady );
// Forward signal
connect( mWorker, &QgsQueryResultFetcher::fetchingComplete, this, &QgsQueryResultModel::fetchingComplete );
connect( &mWorkerThread, &QThread::started, mWorker.get(), &QgsQueryResultFetcher::fetchRows );
// Forward signals to the model
connect( mWorker.get(), &QgsQueryResultFetcher::rowsReady, this, &QgsQueryResultModel::rowsReady );
connect( mWorker.get(), &QgsQueryResultFetcher::fetchingComplete, this, &QgsQueryResultModel::fetchingComplete );
mWorkerThread.start();
}

Expand Down Expand Up @@ -57,7 +57,6 @@ QgsQueryResultModel::~QgsQueryResultModel()
mWorker->stopFetching();
mWorkerThread.quit();
mWorkerThread.wait();
mWorker->deleteLater();
}
else
{
Expand Down
2 changes: 1 addition & 1 deletion src/core/qgsqueryresultmodel.h
Expand Up @@ -122,7 +122,7 @@ class CORE_EXPORT QgsQueryResultModel : public QAbstractTableModel
QgsAbstractDatabaseProviderConnection::QueryResult mQueryResult;
QStringList mColumns;
QThread mWorkerThread;
QgsQueryResultFetcher *mWorker = nullptr;
std::unique_ptr<QgsQueryResultFetcher> mWorker;
QList<QVariantList> mRows;

};
Expand Down
15 changes: 14 additions & 1 deletion src/gui/qgsqueryresultwidget.cpp
Expand Up @@ -219,7 +219,6 @@ void QgsQueryResultWidget::cancelApiFetcher()
mApiFetcher->stopFetching();
mApiFetcherWorkerThread.quit();
mApiFetcherWorkerThread.wait();
mApiFetcherWorkerThread.deleteLater();
}
}

Expand Down Expand Up @@ -250,10 +249,19 @@ void QgsQueryResultWidget::startFetching()
mQueryResultsTableView->show();
updateButtons();
updateSqlLayerColumns( );
mActualRowCount = result.rowCount();
if ( mActualRowCount != -1 )
{
mProgressBar->setRange( 0, mActualRowCount );
}
}
mStatusLabel->setText( tr( "Fetched rows: %1 %2" )
.arg( mModel->rowCount( mModel->index( -1, -1 ) ) )
.arg( mWasCanceled ? tr( "(stopped)" ) : QString() ) );
if ( mActualRowCount != -1 )
{
mProgressBar->setValue( mModel->rowCount( mModel->index( -1, -1 ) ) );
}
} );

mQueryResultsTableView->setModel( mModel.get() );
Expand Down Expand Up @@ -356,6 +364,11 @@ void QgsQueryResultWidget::setConnection( QgsAbstractDatabaseProviderConnection
mApiFetcher = nullptr;
} );
connect( mApiFetcher, &QgsConnectionsApiFetcher::tokensReady, this, &QgsQueryResultWidget::tokensReady );
connect( mApiFetcher, &QgsConnectionsApiFetcher::fetchingFinished, &mApiFetcherWorkerThread, [ = ]
{
mApiFetcherWorkerThread.quit();
mApiFetcherWorkerThread.wait();
} );
mApiFetcherWorkerThread.start();
}

Expand Down
7 changes: 4 additions & 3 deletions src/gui/qgsqueryresultwidget.h
Expand Up @@ -40,9 +40,9 @@ class GUI_EXPORT QgsConnectionsApiFetcher: public QObject

public:

//! Constructs a result fetcher from \a queryResult.
QgsConnectionsApiFetcher( const QgsAbstractDatabaseProviderConnection *conn )
: mConnection( conn )
//! Constructs a result fetcher from \a connection.
QgsConnectionsApiFetcher( const QgsAbstractDatabaseProviderConnection *connection )
: mConnection( connection )
{}

//! Start fetching
Expand Down Expand Up @@ -155,6 +155,7 @@ class GUI_EXPORT QgsQueryResultWidget: public QWidget, private Ui::QgsQueryResul
bool mFirstRowFetched = false;
QFutureWatcher<QgsAbstractDatabaseProviderConnection::QueryResult> mQueryResultWatcher;
QString mSqlErrorMessage;
qlonglong mActualRowCount = -1;

/**
* Updates buttons status.
Expand Down
6 changes: 6 additions & 0 deletions src/providers/hana/qgshanaproviderconnection.cpp
Expand Up @@ -52,6 +52,12 @@ bool QgsHanaProviderResultIterator::hasNextRowPrivate() const
return mNextRow;
}

qlonglong QgsHanaProviderResultIterator::rowCountPrivate() const
{
// TODO: hana team, this is for you.
return -1;
}

QgsHanaProviderConnection::QgsHanaProviderConnection( const QString &name )
: QgsAbstractDatabaseProviderConnection( name )
{
Expand Down
10 changes: 6 additions & 4 deletions src/providers/hana/qgshanaproviderconnection.h
Expand Up @@ -25,8 +25,9 @@ struct QgsHanaEmptyProviderResultIterator: public QgsAbstractDatabaseProviderCon
{
// QueryResultIterator interface
private:
QVariantList nextRowPrivate();
bool hasNextRowPrivate() const;
QVariantList nextRowPrivate() override;
bool hasNextRowPrivate() const override;
qlonglong rowCountPrivate() const override { return 0; };
};

struct QgsHanaProviderResultIterator: public QgsAbstractDatabaseProviderConnection::QueryResult::QueryResultIterator
Expand All @@ -40,8 +41,9 @@ struct QgsHanaProviderResultIterator: public QgsAbstractDatabaseProviderConnecti

// QueryResultIterator interface
private:
QVariantList nextRowPrivate();
bool hasNextRowPrivate() const;
QVariantList nextRowPrivate() override;
bool hasNextRowPrivate() const override;
qlonglong rowCountPrivate() const override;
};

class QgsHanaConnectionRef;
Expand Down
5 changes: 5 additions & 0 deletions src/providers/mssql/qgsmssqlproviderconnection.cpp
Expand Up @@ -331,6 +331,11 @@ QVariantList QgssMssqlProviderResultIterator::nextRowInternal()
return row;
}

qlonglong QgssMssqlProviderResultIterator::rowCountPrivate() const
{
return mQuery.size();
}


QList<QgsMssqlProviderConnection::TableProperty> QgsMssqlProviderConnection::tables( const QString &schema, const TableFlags &flags ) const
{
Expand Down
3 changes: 3 additions & 0 deletions src/providers/mssql/qgsmssqlproviderconnection.h
Expand Up @@ -39,6 +39,9 @@ struct QgssMssqlProviderResultIterator: public QgsAbstractDatabaseProviderConnec

QVariantList nextRowInternal();


// QueryResultIterator interface
qlonglong rowCountPrivate() const override;
};

class QgsMssqlProviderConnection : public QgsAbstractDatabaseProviderConnection
Expand Down
5 changes: 5 additions & 0 deletions src/providers/oracle/qgsoracleproviderconnection.cpp
Expand Up @@ -1407,6 +1407,11 @@ QVariantList QgsOracleProviderResultIterator::nextRowInternal()
return row;
}

qlonglong QgsOracleProviderResultIterator::rowCountPrivate() const
{
return mQuery.size();
}

void QgsOracleProviderConnection::createVectorTable( const QString &schema,
const QString &name,
const QgsFields &fields,
Expand Down
2 changes: 1 addition & 1 deletion src/providers/oracle/qgsoracleproviderconnection.h
Expand Up @@ -37,7 +37,7 @@ struct QgsOracleProviderResultIterator: public QgsAbstractDatabaseProviderConnec
QVariantList mNextRow;

QVariantList nextRowInternal();

qlonglong rowCountPrivate() const override;
};

class QgsOracleProviderConnection : public QgsAbstractDatabaseProviderConnection
Expand Down
5 changes: 5 additions & 0 deletions src/providers/postgres/qgspostgresproviderconnection.cpp
Expand Up @@ -427,6 +427,11 @@ bool QgsPostgresProviderResultIterator::hasNextRowPrivate() const
return result && mRowIndex < result->PQntuples();
}

qlonglong QgsPostgresProviderResultIterator::rowCountPrivate() const
{
return result ? result->PQntuples() : -1;
}


void QgsPostgresProviderConnection::vacuum( const QString &schema, const QString &name ) const
{
Expand Down
2 changes: 1 addition & 1 deletion src/providers/postgres/qgspostgresproviderconnection.h
Expand Up @@ -32,11 +32,11 @@ struct QgsPostgresProviderResultIterator: public QgsAbstractDatabaseProviderConn

QVariantList nextRowPrivate() override;
bool hasNextRowPrivate() const override;
qlonglong rowCountPrivate() const override;

bool mResolveTypes = true;
std::shared_ptr<QgsPoolPostgresConn> mConn;
qlonglong mRowIndex = 0;

};

class QgsPostgresProviderConnection : public QgsAbstractDatabaseProviderConnection
Expand Down
16 changes: 16 additions & 0 deletions src/providers/spatialite/qgsspatialiteproviderconnection.cpp
Expand Up @@ -554,6 +554,17 @@ void QgsSpatialiteProviderResultIterator::setFields( const QgsFields &fields )
}


QgsSpatialiteProviderResultIterator::QgsSpatialiteProviderResultIterator( gdal::ogr_datasource_unique_ptr hDS, OGRLayerH ogrLayer )
: mHDS( std::move( hDS ) )
, mOgrLayer( ogrLayer )
{
if ( mOgrLayer )
{
// Do not scan the layer!
mRowCount = OGR_L_GetFeatureCount( mOgrLayer, false );
}
}

QgsSpatialiteProviderResultIterator::~QgsSpatialiteProviderResultIterator()
{
if ( mHDS )
Expand Down Expand Up @@ -611,6 +622,11 @@ QVariantList QgsSpatialiteProviderResultIterator::nextRowInternal()
return row;
}

qlonglong QgsSpatialiteProviderResultIterator::rowCountPrivate() const
{
return mRowCount;
}


void QgsSpatialiteProviderResultIterator::setGeometryColumnName( const QString &geometryColumnName )
{
Expand Down

0 comments on commit 233a809

Please sign in to comment.