Address PR comments - part 2

This commit is contained in:
Alessandro Pasotti 2021-07-07 12:43:14 +02:00
parent 78a42cf7e8
commit 878b2436a5
18 changed files with 141 additions and 70 deletions

View File

@ -315,11 +315,11 @@ Qgis.VectorExportResult.__doc__ = 'Vector layer export result codes.\n\n.. versi
# --
Qgis.VectorExportResult.baseClass = Qgis
# monkey patching scoped based enum
Qgis.SqlLayerDefinitionCapability.Filter.__doc__ = "SQL layer definition supports filter"
Qgis.SqlLayerDefinitionCapability.SubsetStringFilter.__doc__ = "SQL layer definition supports subset string filter"
Qgis.SqlLayerDefinitionCapability.GeometryColumn.__doc__ = "SQL layer definition supports geometry column"
Qgis.SqlLayerDefinitionCapability.PrimaryKeys.__doc__ = "SQL layer definition supports primary keys"
Qgis.SqlLayerDefinitionCapability.SelectAtId.__doc__ = "SQL layer definition supports disabling select at id"
Qgis.SqlLayerDefinitionCapability.__doc__ = 'SqlLayerDefinitionCapability enum lists the arguments supported by the provider when creating SQL query layers.\n\n.. versionadded:: 3.22\n\n' + '* ``Filter``: ' + Qgis.SqlLayerDefinitionCapability.Filter.__doc__ + '\n' + '* ``GeometryColumn``: ' + Qgis.SqlLayerDefinitionCapability.GeometryColumn.__doc__ + '\n' + '* ``PrimaryKeys``: ' + Qgis.SqlLayerDefinitionCapability.PrimaryKeys.__doc__ + '\n' + '* ``SelectAtId``: ' + Qgis.SqlLayerDefinitionCapability.SelectAtId.__doc__
Qgis.SqlLayerDefinitionCapability.UnstableFeatureIds.__doc__ = "SQL layer definition supports disabling select at id"
Qgis.SqlLayerDefinitionCapability.__doc__ = 'SqlLayerDefinitionCapability enum lists the arguments supported by the provider when creating SQL query layers.\n\n.. versionadded:: 3.22\n\n' + '* ``SubsetStringFilter``: ' + Qgis.SqlLayerDefinitionCapability.SubsetStringFilter.__doc__ + '\n' + '* ``GeometryColumn``: ' + Qgis.SqlLayerDefinitionCapability.GeometryColumn.__doc__ + '\n' + '* ``PrimaryKeys``: ' + Qgis.SqlLayerDefinitionCapability.PrimaryKeys.__doc__ + '\n' + '* ``UnstableFeatureIds``: ' + Qgis.SqlLayerDefinitionCapability.UnstableFeatureIds.__doc__
# --
Qgis.SqlLayerDefinitionCapability.baseClass = Qgis
# monkey patching scoped based enum

View File

@ -91,7 +91,7 @@ Returns the number of fetched rows.
long long rowCount( ) const;
%Docstring
Returns the number of rows returned by a SELECT query or -1 if unknown
Returns the number of rows returned by a SELECT query or Qgis.FeatureCountState.UnknownCount if unknown.
.. seealso:: :py:func:`fetchedRowCount`
%End
@ -125,6 +125,16 @@ Returns the number of rows returned by a SELECT query or -1 if unknown
double queryExecutionTime( );
%Docstring
Returns the query execution time in milliseconds.
%End
void setQueryExecutionTime( double queryExecutionTime );
%Docstring
Sets the query execution time to ``queryExecutionTime`` milliseconds.
%End
};
@ -135,7 +145,7 @@ Returns the number of rows returned by a SELECT query or -1 if unknown
QString layerName; //!< Optional name for the new layer
QStringList primaryKeyColumns; //!< List of primary key column names
QString geometryColumn; //!< Name of the geometry column
bool disableSelectAtId; //!< If SelectAtId is disabled (default is false), not all data providers support this feature: check support with SqlLayerDefinitionCapability::SelectAtId capability
bool disableSelectAtId;
};
struct TableProperty
@ -462,7 +472,7 @@ Renames a raster table with given ``schema`` (schema is ignored if not supported
%Docstring
Creates a new schema with the specified ``name``.
:raises QgsProviderConnectionException:
:raises QgsProviderConnectionException: if any errors are encountered.
%End
virtual void dropSchema( const QString &name, bool force = false ) const throw( QgsProviderConnectionException );
@ -523,7 +533,7 @@ Raises a :py:class:`QgsProviderConnectionException` if any errors are encountere
it is responsibility of the caller to handle open layers and registry entries.
:raises QgsProviderConnectionException:
:raises QgsProviderConnectionException: if any errors are encountered.
%End
virtual QList<QList<QVariant>> executeSql( const QString &sql, QgsFeedback *feedback = 0 ) const throw( QgsProviderConnectionException );
@ -538,9 +548,8 @@ Executes raw ``sql`` and returns the (possibly empty) list of results in a multi
virtual QgsVectorLayer *createSqlVectorLayer( const SqlVectorLayerOptions &options ) const throw( QgsProviderConnectionException ) /Factory/;
%Docstring
Creates and returns a (possibly invalid) vector layer based on the ``sql`` statement and optional ``options``.
Raises a :py:class:`QgsProviderConnectionException` if any errors are encountered or if SQL layer creation is not supported.
:raises QgsProviderConnectionException:
:raises QgsProviderConnectionException: if any errors are encountered or if SQL layer creation is not supported.
.. versionadded:: 3.22
%End
@ -638,7 +647,7 @@ Returns the fields of a ``table`` and ``schema``.
behavior when the layer does not expose all fields (GPKG for example hides geometry
and primary key column).
:raises QgsProviderConnectionException:
:raises QgsProviderConnectionException: if any errors are encountered.
.. versionadded:: 3.16
%End
@ -647,7 +656,7 @@ Returns the fields of a ``table`` and ``schema``.
%Docstring
Returns a list of native types supported by the connection.
:raises QgsProviderConnectionException:
:raises QgsProviderConnectionException: if any errors are encountered.
.. versionadded:: 3.16
%End

View File

@ -228,12 +228,11 @@ The development version
enum class SqlLayerDefinitionCapability
{
Filter,
SubsetStringFilter,
GeometryColumn,
PrimaryKeys,
SelectAtId
UnstableFeatureIds
};
typedef QFlags<Qgis::SqlLayerDefinitionCapability> SqlLayerDefinitionCapabilities;
@ -250,7 +249,6 @@ The development version
Identifier
};
enum class DriveType
{
Unknown,
@ -387,6 +385,8 @@ QFlags<Qgis::BrowserItemCapability> operator|(Qgis::BrowserItemCapability f1, QF
QFlags<Qgis::SublayerQueryFlag> operator|(Qgis::SublayerQueryFlag f1, QFlags<Qgis::SublayerQueryFlag> f2);
QFlags<Qgis::SqlLayerDefinitionCapability> operator|(Qgis::SqlLayerDefinitionCapability f1, QFlags<Qgis::SqlLayerDefinitionCapability> f2);

View File

@ -65,7 +65,7 @@ Returns the query result
void rowsReady( const QList<QList<QVariant> > &rows );
%Docstring
Triggered when ``newRows`` have been fetched and can be added to the model
Triggered when ``newRows`` have been fetched and can be added to the model.
%End
void cancel();
@ -78,14 +78,17 @@ Cancels the row fetching.
void fetchingComplete();
%Docstring
Emitted when all rows have been fetched or when the fetching has been stopped (canceled)
Emitted when rows have been fetched (all of them or a batch if `maxRows` was passed to :py:func:`~QgsQueryResultModel.fetchMoreRows` )
or when the fetching has been stopped (canceled).
.. seealso:: :py:func:`fetchMoreRows`
%End
void fetchMoreRows( qlonglong maxRows );
%Docstring
Emitted when more rows are requested
Emitted when more rows are requested.
:param maxRows: the number of rows that will be fetched
:param maxRows: the number of rows that will be fetched.
%End
void fetchingStarted();

View File

@ -1065,7 +1065,7 @@ void QgsDatabaseItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu *
// SQL dialog
if ( std::unique_ptr<QgsAbstractDatabaseProviderConnection> conn( item->databaseConnection() ); conn && conn->capabilities().testFlag( QgsAbstractDatabaseProviderConnection::Capability::ExecuteSql ) )
{
QAction *sqlAction = new QAction( QObject::tr( "Run SQL command" ), menu );
QAction *sqlAction = new QAction( QObject::tr( "Execute SQL " ), menu );
QObject::connect( sqlAction, &QAction::triggered, item, [ item, context ]
{
@ -1082,7 +1082,7 @@ void QgsDatabaseItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu *
QgsDialog dialog;
dialog.setObjectName( QStringLiteral( "SQLCommandsDialog" ) );
dialog.setWindowTitle( tr( "%1 — Run SQL Commands" ).arg( item->name() ) );
dialog.setWindowTitle( tr( "%1 — Execute SQL" ).arg( item->name() ) );
// If this is a layer item (or below the hierarchy) we can pre-set the query to something
// meaningful

View File

@ -22,6 +22,7 @@
#include "qgsogrprovider.h"
#include "qgsmessagelog.h"
#include "qgsproviderregistry.h"
#include "qgsprovidermetadata.h"
#include "qgsapplication.h"
#include "qgsvectorlayer.h"
#include "qgsfeedback.h"
@ -29,6 +30,8 @@
#include <QTextCodec>
#include <QRegularExpression>
#include <chrono>
///@cond PRIVATE
QgsGeoPackageProviderConnection::QgsGeoPackageProviderConnection( const QString &name )
@ -176,7 +179,11 @@ void QgsGeoPackageProviderConnection::renameVectorTable( const QString &schema,
QgsVectorLayer *QgsGeoPackageProviderConnection::createSqlVectorLayer( const QgsAbstractDatabaseProviderConnection::SqlVectorLayerOptions &options ) const
{
return new QgsVectorLayer( QStringLiteral( "%1|subset=%2" ).arg( uri(), options.sql ), options.layerName.isEmpty() ? QStringLiteral( "QueryLayer" ) : options.layerName, providerKey() );
QgsProviderMetadata *providerMetadata { QgsProviderRegistry::instance()->providerMetadata( QStringLiteral( "ogr" ) ) };
Q_ASSERT( providerMetadata );
QMap<QString, QVariant> decoded = providerMetadata->decodeUri( uri() );
decoded[ QStringLiteral( "subset" ) ] = options.sql;
return new QgsVectorLayer( providerMetadata->encodeUri( decoded ), options.layerName.isEmpty() ? QStringLiteral( "QueryLayer" ) : options.layerName, providerKey() );
}
QgsAbstractDatabaseProviderConnection::QueryResult QgsGeoPackageProviderConnection::execSql( const QString &sql, QgsFeedback *feedback ) const
@ -381,7 +388,7 @@ void QgsGeoPackageProviderConnection::setDefaultCapabilities()
};
mSqlLayerDefinitionCapabilities =
{
Qgis::SqlLayerDefinitionCapability::Filter,
Qgis::SqlLayerDefinitionCapability::SubsetStringFilter,
Qgis::SqlLayerDefinitionCapability::PrimaryKeys,
Qgis::SqlLayerDefinitionCapability::GeometryColumn,
};
@ -405,7 +412,9 @@ QgsAbstractDatabaseProviderConnection::QueryResult QgsGeoPackageProviderConnecti
return QgsAbstractDatabaseProviderConnection::QueryResult();
}
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
OGRLayerH ogrLayer( GDALDatasetExecuteSQL( hDS.get(), sql.toUtf8().constData(), nullptr, nullptr ) );
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
// Read fields
if ( ogrLayer )
@ -413,6 +422,7 @@ QgsAbstractDatabaseProviderConnection::QueryResult QgsGeoPackageProviderConnecti
auto iterator = std::make_shared<QgsGeoPackageProviderResultIterator>( std::move( hDS ), ogrLayer );
QgsAbstractDatabaseProviderConnection::QueryResult results( iterator );
results.setQueryExecutionTime( std::chrono::duration_cast<std::chrono::milliseconds>( end - begin ).count() );
gdal::ogr_feature_unique_ptr fet;
if ( fet.reset( OGR_L_GetNextFeature( ogrLayer ) ), fet )

View File

@ -1467,6 +1467,16 @@ QgsAbstractDatabaseProviderConnection::QueryResult::QueryResult( std::shared_ptr
: mResultIterator( iterator )
{}
double QgsAbstractDatabaseProviderConnection::QueryResult::queryExecutionTime()
{
return mQueryExecutionTime;
}
void QgsAbstractDatabaseProviderConnection::QueryResult::setQueryExecutionTime( double queryExecutionTime )
{
mQueryExecutionTime = queryExecutionTime;
}
QVariantList QgsAbstractDatabaseProviderConnection::QueryResult::QueryResultIterator::nextRow()
{

View File

@ -120,7 +120,7 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv
long long fetchedRowCount( ) const;
/**
* Returns the number of rows returned by a SELECT query or -1 if unknown
* Returns the number of rows returned by a SELECT query or Qgis::FeatureCountState::UnknownCount if unknown.
*
* \see fetchedRowCount()
*/
@ -206,12 +206,24 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv
*/
QueryResult( ) = default SIP_SKIP;
/**
* Returns the query execution time in milliseconds.
*/
double queryExecutionTime( );
/**
* Sets the query execution time to \a queryExecutionTime milliseconds.
*/
void setQueryExecutionTime( double queryExecutionTime );
///@endcond private
private:
mutable std::shared_ptr<QueryResultIterator> mResultIterator;
QStringList mColumns;
//! Query execution time in milliseconds
double mQueryExecutionTime = 0;
};
@ -228,7 +240,7 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv
QString layerName; //!< Optional name for the new layer
QStringList primaryKeyColumns; //!< List of primary key column names
QString geometryColumn; //!< Name of the geometry column
bool disableSelectAtId; //!< If SelectAtId is disabled (default is false), not all data providers support this feature: check support with SqlLayerDefinitionCapability::SelectAtId capability
bool disableSelectAtId = false; //!< If SelectAtId is disabled (default is false), not all data providers support this feature: check support with SqlLayerDefinitionCapability::SelectAtId capability
};
/**
@ -596,7 +608,7 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv
/**
* Creates a new schema with the specified \a name.
*
* \throws QgsProviderConnectionException
* \throws QgsProviderConnectionException if any errors are encountered.
*/
virtual void createSchema( const QString &name ) const SIP_THROW( QgsProviderConnectionException );
@ -639,7 +651,7 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv
* Renames a schema with the specified \a name.
* Raises a QgsProviderConnectionException if any errors are encountered.
* \note it is responsibility of the caller to handle open layers and registry entries.
* \throws QgsProviderConnectionException
* \throws QgsProviderConnectionException if any errors are encountered.
*/
virtual void renameSchema( const QString &name, const QString &newName ) const SIP_THROW( QgsProviderConnectionException );
@ -653,8 +665,7 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv
/**
* Creates and returns a (possibly invalid) vector layer based on the \a sql statement and optional \a options.
* Raises a QgsProviderConnectionException if any errors are encountered or if SQL layer creation is not supported.
* \throws QgsProviderConnectionException
* \throws QgsProviderConnectionException if any errors are encountered or if SQL layer creation is not supported.
* \since QGIS 3.22
*/
virtual QgsVectorLayer *createSqlVectorLayer( const SqlVectorLayerOptions &options ) const SIP_THROW( QgsProviderConnectionException ) SIP_FACTORY;
@ -748,7 +759,7 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv
* choose to override this method for a greater efficiency of to overcome provider's
* behavior when the layer does not expose all fields (GPKG for example hides geometry
* and primary key column).
* \throws QgsProviderConnectionException
* \throws QgsProviderConnectionException if any errors are encountered.
* \since QGIS 3.16
*/
virtual QgsFields fields( const QString &schema, const QString &table ) const SIP_THROW( QgsProviderConnectionException );
@ -756,7 +767,7 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv
/**
* Returns a list of native types supported by the connection.
*
* \throws QgsProviderConnectionException
* \throws QgsProviderConnectionException if any errors are encountered.
* \since QGIS 3.16
*/
virtual QList< QgsVectorDataProvider::NativeType > nativeTypes() const SIP_THROW( QgsProviderConnectionException ) = 0;

View File

@ -336,12 +336,11 @@ class CORE_EXPORT Qgis
*/
enum class SqlLayerDefinitionCapability : int
{
Filter = 1 << 1, //!< SQL layer definition supports filter
GeometryColumn = 1 << 2, //!< SQL layer definition supports geometry column
PrimaryKeys = 1 << 3, //!< SQL layer definition supports primary keys
SelectAtId = 1 << 4 //!< SQL layer definition supports disabling select at id
SubsetStringFilter = 1 << 1, //!< SQL layer definition supports subset string filter
GeometryColumn = 1 << 2, //!< SQL layer definition supports geometry column
PrimaryKeys = 1 << 3, //!< SQL layer definition supports primary keys
UnstableFeatureIds = 1 << 4 //!< SQL layer definition supports disabling select at id
};
Q_ENUM( SqlLayerDefinitionCapability )
Q_DECLARE_FLAGS( SqlLayerDefinitionCapabilities, SqlLayerDefinitionCapability )
@ -364,7 +363,6 @@ class CORE_EXPORT Qgis
};
Q_ENUM( SqlKeywordCategory )
/**
* Drive types
* \since QGIS 3.20
@ -583,6 +581,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS( Qgis::SymbolFlags )
Q_DECLARE_OPERATORS_FOR_FLAGS( Qgis::SymbolPreviewFlags )
Q_DECLARE_OPERATORS_FOR_FLAGS( Qgis::BrowserItemCapabilities )
Q_DECLARE_OPERATORS_FOR_FLAGS( Qgis::SublayerQueryFlags )
Q_DECLARE_OPERATORS_FOR_FLAGS( Qgis::SqlLayerDefinitionCapabilities )
// hack to workaround warnings when casting void pointers
// retrieved from QLibrary::resolve to function pointers.

View File

@ -112,7 +112,7 @@ class CORE_EXPORT QgsQueryResultModel : public QAbstractTableModel
public slots:
/**
* Triggered when \a newRows have been fetched and can be added to the model
* Triggered when \a newRows have been fetched and can be added to the model.
*/
void rowsReady( const QList<QList<QVariant> > &rows );
@ -125,13 +125,15 @@ class CORE_EXPORT QgsQueryResultModel : public QAbstractTableModel
signals:
/**
* Emitted when all rows have been fetched or when the fetching has been stopped (canceled)
* Emitted when rows have been fetched (all of them or a batch if `maxRows` was passed to fetchMoreRows() )
* or when the fetching has been stopped (canceled).
* \see fetchMoreRows()
*/
void fetchingComplete();
/**
* Emitted when more rows are requested
* \param maxRows the number of rows that will be fetched
* Emitted when more rows are requested.
* \param maxRows the number of rows that will be fetched.
*/
void fetchMoreRows( qlonglong maxRows );

View File

@ -91,12 +91,12 @@ QgsQueryResultWidget::QgsQueryResultWidget( QWidget *parent, QgsAbstractDatabase
mGeometryColumnCheckBox->setVisible( showGeometryColumnConfig );
mGeometryColumnComboBox->setVisible( showGeometryColumnConfig );
const bool showFilterConfig { connection &&connection->sqlLayerDefinitionCapabilities().testFlag( Qgis::SqlLayerDefinitionCapability::Filter ) };
const bool showFilterConfig { connection &&connection->sqlLayerDefinitionCapabilities().testFlag( Qgis::SqlLayerDefinitionCapability::SubsetStringFilter ) };
mFilterLabel->setVisible( showFilterConfig );
mFilterToolButton->setVisible( showFilterConfig );
mFilterLineEdit->setVisible( showFilterConfig );
const bool showDisableSelectAtId{ connection &&connection->sqlLayerDefinitionCapabilities().testFlag( Qgis::SqlLayerDefinitionCapability::SelectAtId ) };
const bool showDisableSelectAtId{ connection &&connection->sqlLayerDefinitionCapabilities().testFlag( Qgis::SqlLayerDefinitionCapability::UnstableFeatureIds ) };
mAvoidSelectingAsFeatureIdCheckBox->setVisible( showDisableSelectAtId );
}
@ -244,12 +244,15 @@ void QgsQueryResultWidget::startFetching()
{
if ( mQueryResultWatcher.result().rowCount() != static_cast<long long>( Qgis::FeatureCountState::UnknownCount ) )
{
mStatusLabel->setText( QStringLiteral( "Query executed successfully (%1 rows)" ).arg( QLocale().toString( mQueryResultWatcher.result().rowCount() ) ) );
mStatusLabel->setText( QStringLiteral( "Query executed successfully (%1 rows, %2 ms)" )
.arg( QLocale().toString( mQueryResultWatcher.result().rowCount() ),
QLocale().toString( mQueryResultWatcher.result().queryExecutionTime() ) ) );
}
else
{
mStatusLabel->setText( QStringLiteral( "Query executed successfully" ) );
mStatusLabel->setText( QStringLiteral( "Query executed successfully (%1 s)" ).arg( QLocale().toString( mQueryResultWatcher.result().queryExecutionTime() ) ) );
}
mProgressBar->hide();
mModel = std::make_unique<QgsQueryResultModel>( mQueryResultWatcher.result() );
connect( mFeedback.get(), &QgsFeedback::canceled, mModel.get(), [ = ]
{
@ -257,13 +260,14 @@ void QgsQueryResultWidget::startFetching()
mWasCanceled = true;
} );
connect( mModel.get(), &QgsQueryResultModel::fetchingStarted, this, [ = ]
connect( mModel.get(), &QgsQueryResultModel::fetchMoreRows, this, [ = ]( long long maxRows )
{
mFetchedRowsBatchCount = 0;
mProgressBar->setRange( 0, maxRows );
mProgressBar->show();
} );
connect( mModel.get(), &QgsQueryResultModel::rowsInserted, this, [ = ]( const QModelIndex &, int, int )
connect( mModel.get(), &QgsQueryResultModel::rowsInserted, this, [ = ]( const QModelIndex &, int first, int last )
{
if ( ! mFirstRowFetched )
{
@ -273,19 +277,14 @@ void QgsQueryResultWidget::startFetching()
updateButtons();
updateSqlLayerColumns( );
mActualRowCount = mModel->queryResult().rowCount();
if ( mActualRowCount != -1 )
{
mProgressBar->setRange( 0, mActualRowCount );
}
}
mStatusLabel->setText( tr( "Fetched rows: %1/%2 %3" )
mStatusLabel->setText( tr( "Fetched rows: %1/%2 %3 %4 ms" )
.arg( QLocale().toString( mModel->rowCount( mModel->index( -1, -1 ) ) ),
mActualRowCount != -1 ? QLocale().toString( mActualRowCount ) : tr( "unknown" ),
mWasCanceled ? tr( "(stopped)" ) : QString() ) );
if ( mActualRowCount != -1 )
{
mProgressBar->setValue( mModel->rowCount( mModel->index( -1, -1 ) ) );
}
mWasCanceled ? tr( "(stopped)" ) : QString(),
QLocale().toString( mQueryResultWatcher.result().queryExecutionTime() ) ) );
mFetchedRowsBatchCount += last - first + 1;
mProgressBar->setValue( mFetchedRowsBatchCount );
} );
mQueryResultsTableView->setModel( mModel.get() );
@ -293,6 +292,7 @@ void QgsQueryResultWidget::startFetching()
connect( mModel.get(), &QgsQueryResultModel::fetchingComplete, mStopButton, [ = ]
{
mProgressBar->hide();
mStopButton->setEnabled( false );
} );
}
@ -456,7 +456,7 @@ void QgsConnectionsApiFetcher::fetchTokens()
QStringList fieldNames;
try
{
const auto fields( mConnection->fields( schema, table ) );
const QgsFields fields( mConnection->fields( schema, table ) );
if ( mStopFetching ) { return; }
for ( const auto &field : std::as_const( fields ) )
{

View File

@ -178,8 +178,8 @@ class GUI_EXPORT QgsQueryResultWidget: public QWidget, private Ui::QgsQueryResul
bool mFirstRowFetched = false;
QFutureWatcher<QgsAbstractDatabaseProviderConnection::QueryResult> mQueryResultWatcher;
QString mSqlErrorMessage;
qlonglong mActualRowCount = -1;
long long mActualRowCount = -1;
long long mFetchedRowsBatchCount = 0;
/**
* Updates SQL layer columns.

View File

@ -28,6 +28,8 @@
#include "odbc/PreparedStatement.h"
#include <chrono>
QgsHanaProviderResultIterator::QgsHanaProviderResultIterator( QgsHanaResultSetRef &&resultSet )
: mResultSet( std::move( resultSet ) )
, mNumColumns( mResultSet->getMetadata().getColumnCount() )
@ -264,6 +266,7 @@ QgsAbstractDatabaseProviderConnection::QueryResult QgsHanaProviderConnection::ex
try
{
odbc::PreparedStatementRef stmt = conn->prepareStatement( sql );
bool isQuery = stmt->getMetaDataUnicode()->getColumnCount() > 0;
if ( isQuery )
@ -278,9 +281,13 @@ QgsAbstractDatabaseProviderConnection::QueryResult QgsHanaProviderConnection::ex
}
else
{
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
conn->execute( sql );
conn->commit();
return QueryResult( std::make_shared<QgsHanaEmptyProviderResultIterator>() );
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
QueryResult results( std::make_shared<QgsHanaEmptyProviderResultIterator>() );
results.setQueryExecutionTime( std::chrono::duration_cast<std::chrono::milliseconds>( end - begin ).count() );
return results;
}
}
catch ( const QgsHanaException &ex )

View File

@ -27,6 +27,8 @@
#include "qgsfeedback.h"
#include <QIcon>
#include <chrono>
const QStringList QgsMssqlProviderConnection::EXTRA_CONNECTION_PARAMETERS
{
QStringLiteral( "geometryColumnsOnly" ),
@ -101,10 +103,10 @@ void QgsMssqlProviderConnection::setDefaultCapabilities()
};
mSqlLayerDefinitionCapabilities =
{
Qgis::SqlLayerDefinitionCapability::Filter,
Qgis::SqlLayerDefinitionCapability::SubsetStringFilter,
Qgis::SqlLayerDefinitionCapability::PrimaryKeys,
Qgis::SqlLayerDefinitionCapability::GeometryColumn,
Qgis::SqlLayerDefinitionCapability::SelectAtId,
Qgis::SqlLayerDefinitionCapability::UnstableFeatureIds,
};
}
@ -260,6 +262,8 @@ QgsAbstractDatabaseProviderConnection::QueryResult QgsMssqlProviderConnection::e
QSqlQuery q = QSqlQuery( db );
q.setForwardOnly( true );
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
if ( ! q.exec( sql ) )
{
const QString errorMessage { q.lastError().text() };
@ -270,10 +274,12 @@ QgsAbstractDatabaseProviderConnection::QueryResult QgsMssqlProviderConnection::e
if ( q.isActive() )
{
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
const QSqlRecord rec { q.record() };
const int numCols { rec.count() };
auto iterator = std::make_shared<QgssMssqlProviderResultIterator>( resolveTypes, numCols, q );
QgsAbstractDatabaseProviderConnection::QueryResult results( iterator );
results.setQueryExecutionTime( std::chrono::duration_cast<std::chrono::milliseconds>( end - begin ).count() );
for ( int idx = 0; idx < numCols; ++idx )
{
results.appendColumn( rec.field( idx ).name() );

View File

@ -1351,6 +1351,7 @@ QgsAbstractDatabaseProviderConnection::QueryResult QgsOracleProviderConnection::
return QgsAbstractDatabaseProviderConnection::QueryResult();
QSqlQuery qry( *pconn.get() );
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
if ( !qry.exec( sql ) )
{
throw QgsProviderConnectionException( QObject::tr( "SQL error: %1 returned %2" )
@ -1372,6 +1373,8 @@ QgsAbstractDatabaseProviderConnection::QueryResult QgsOracleProviderConnection::
results.appendColumn( rec.field( idx ).name() );
}
iterator->nextRow();
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
results.setQueryExecutionTime( std::chrono::duration_cast<std::chrono::milliseconds>( end - begin ).count() );
return results;
}

View File

@ -25,6 +25,8 @@
#include <QRegularExpression>
#include <QIcon>
#include <chrono>
extern "C"
{
#include <libpq-fe.h>
@ -85,10 +87,10 @@ void QgsPostgresProviderConnection::setDefaultCapabilities()
};
mSqlLayerDefinitionCapabilities =
{
Qgis::SqlLayerDefinitionCapability::Filter,
Qgis::SqlLayerDefinitionCapability::SubsetStringFilter,
Qgis::SqlLayerDefinitionCapability::PrimaryKeys,
Qgis::SqlLayerDefinitionCapability::GeometryColumn,
Qgis::SqlLayerDefinitionCapability::SelectAtId,
Qgis::SqlLayerDefinitionCapability::UnstableFeatureIds,
};
}
@ -254,7 +256,10 @@ QgsAbstractDatabaseProviderConnection::QueryResult QgsPostgresProviderConnection
} );
}
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
std::unique_ptr<QgsPostgresResult> res = std::make_unique<QgsPostgresResult>( conn->PQexec( sql ) );
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
results.setQueryExecutionTime( std::chrono::duration_cast<std::chrono::milliseconds>( end - begin ).count() );
if ( feedback )
{

View File

@ -27,6 +27,8 @@
#include <QRegularExpression>
#include <QTextCodec>
#include <chrono>
QgsSpatiaLiteProviderConnection::QgsSpatiaLiteProviderConnection( const QString &name )
: QgsAbstractDatabaseProviderConnection( name )
{
@ -439,7 +441,7 @@ void QgsSpatiaLiteProviderConnection::setDefaultCapabilities()
};
mSqlLayerDefinitionCapabilities =
{
Qgis::SqlLayerDefinitionCapability::Filter,
Qgis::SqlLayerDefinitionCapability::SubsetStringFilter,
Qgis::SqlLayerDefinitionCapability::GeometryColumn
};
@ -463,7 +465,9 @@ QgsAbstractDatabaseProviderConnection::QueryResult QgsSpatiaLiteProviderConnecti
return QgsAbstractDatabaseProviderConnection::QueryResult();
}
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
OGRLayerH ogrLayer( GDALDatasetExecuteSQL( hDS.get(), sql.toUtf8().constData(), nullptr, nullptr ) );
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
// Read fields
if ( ogrLayer )
@ -471,6 +475,7 @@ QgsAbstractDatabaseProviderConnection::QueryResult QgsSpatiaLiteProviderConnecti
auto iterator = std::make_shared<QgsSpatialiteProviderResultIterator>( std::move( hDS ), ogrLayer );
QgsAbstractDatabaseProviderConnection::QueryResult results( iterator );
results.setQueryExecutionTime( std::chrono::duration_cast<std::chrono::milliseconds>( end - begin ).count() );
gdal::ogr_feature_unique_ptr fet;
if ( fet.reset( OGR_L_GetNextFeature( ogrLayer ) ), fet )

View File

@ -36,6 +36,7 @@ from qgis.core import (
QgsFeedback,
QgsApplication,
QgsTask,
Qgis,
)
from qgis.PyQt import QtCore
from qgis.PyQt.QtTest import QSignalSpy
@ -564,14 +565,14 @@ class TestPyQgsProviderConnectionBase():
self.assertEqual(vl.name(), options.layerName)
# Some providers can also create SQL layer without an explicit PK
if sql_layer_capabilities & QgsAbstractDatabaseProviderConnection.PrimaryKeys:
if sql_layer_capabilities & Qgis.SqlLayerDefinitionCapability.PrimaryKeys:
options.primaryKeyColumns = []
vl = conn.createSqlVectorLayer(options)
self.assertTrue(vl.isValid())
self.assertTrue(vl.isSpatial())
# Some providers can also create SQL layer without an explicit geometry column
if sql_layer_capabilities & QgsAbstractDatabaseProviderConnection.GeometryColumn:
if sql_layer_capabilities & Qgis.SqlLayerDefinitionCapability.GeometryColumn:
options.primaryKeyColumns = table_info.primaryKeyColumns()
options.geometryColumn = ''
vl = conn.createSqlVectorLayer(options)
@ -581,7 +582,7 @@ class TestPyQgsProviderConnectionBase():
self.assertFalse(vl.isSpatial())
# Some providers can also create SQL layer with filters
if sql_layer_capabilities & QgsAbstractDatabaseProviderConnection.Filter:
if sql_layer_capabilities & Qgis.SqlLayerDefinitionCapability.SubsetStringFilter:
options.primaryKeyColumns = table_info.primaryKeyColumns()
options.geometryColumn = table_info.geometryColumn()
options.filter = f'"{options.primaryKeyColumns[0]}" > 0'