Skip to content
Permalink
Browse files

QgsAbstractDatabaseProviderConnection::QueryResult proper encapsulation

and rename to execSql
  • Loading branch information
elpaso committed Dec 21, 2020
1 parent 84131e0 commit a277cc63324ae52be86bfbc1f67e74a3e0f0e6ea
@@ -47,13 +47,32 @@ is not supported or cannot be performed without errors.

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

QStringList columns() const;
%Docstring
Returns the column names
%End
QStringList columnns;
QList<QList<QVariant>> rows;

QList<QList<QVariant> > rows() const;
%Docstring
Returns the results rows
%End

void appendColumn( const QString &columnName );
%Docstring
Appends ``columnName`` to the list of column names.
%End

void appendRow( const QList<QVariant> &row );
%Docstring
Appends ``row`` to the results.
%End

};


@@ -445,14 +464,18 @@ Raises a QgsProviderConnectionException if any errors are encountered.
Executes raw ``sql`` and returns the (possibly empty) list of results in a multi-dimensional array, optionally ``feedback`` can be provided.
Raises a QgsProviderConnectionException if any errors are encountered.

.. seealso:: :py:func:`execSql`

:raises :: py:class:`QgsProviderConnectionException`
%End

virtual QueryResult executeSqlWithNames( const QString &sql, QgsFeedback *feedback = 0 ) const throw( QgsProviderConnectionException );
virtual QueryResult execSql( const QString &sql, QgsFeedback *feedback = 0 ) const throw( QgsProviderConnectionException );
%Docstring
Executes raw ``sql`` and returns the (possibly empty) query results, optionally ``feedback`` can be provided.
Raises a QgsProviderConnectionException if any errors are encountered.

.. seealso:: :py:func:`executeSql`

:raises :: py:class:`QgsProviderConnectionException`

.. versionadded:: 3.18
@@ -164,7 +164,7 @@ void QgsGeoPackageProviderConnection::renameVectorTable( const QString &schema,
}
}

QgsAbstractDatabaseProviderConnection::QueryResult QgsGeoPackageProviderConnection::executeSqlWithNames( const QString &sql, QgsFeedback *feedback ) const
QgsAbstractDatabaseProviderConnection::QueryResult QgsGeoPackageProviderConnection::execSql( const QString &sql, QgsFeedback *feedback ) const
{
checkCapability( Capability::ExecuteSql );
return executeGdalSqlPrivate( sql, feedback );
@@ -221,7 +221,7 @@ bool QgsGeoPackageProviderConnection::spatialIndexExists( const QString &schema,
QgsMessageLog::logMessage( QStringLiteral( "Schema is not supported by GPKG, ignoring" ), QStringLiteral( "OGR" ), Qgis::Info );
}
const auto res { executeGdalSqlPrivate( QStringLiteral( "SELECT HasSpatialIndex(%1, %2)" ).arg( QgsSqliteUtils::quotedString( name ),
QgsSqliteUtils::quotedString( geometryColumn ) ) ).rows };
QgsSqliteUtils::quotedString( geometryColumn ) ) ).rows() };
return !res.isEmpty() && !res.at( 0 ).isEmpty() && res.at( 0 ).at( 0 ).toBool();
}

@@ -394,7 +394,7 @@ QgsAbstractDatabaseProviderConnection::QueryResult QgsGeoPackageProviderConnecti
fields = QgsOgrUtils::readOgrFields( fet.get(), QTextCodec::codecForName( "UTF-8" ) );
for ( const auto &f : qgis::as_const( fields ) )
{
results.columnns.push_back( f.name() );
results.appendColumn( f.name() );
}
}

@@ -415,7 +415,7 @@ QgsAbstractDatabaseProviderConnection::QueryResult QgsGeoPackageProviderConnecti
}
}

results.rows.push_back( row );
results.appendRow( row );
}
GDALDatasetReleaseResultSet( hDS.get(), ogrLayer );
}
@@ -38,7 +38,7 @@ class QgsGeoPackageProviderConnection : public QgsAbstractDatabaseProviderConnec
void dropVectorTable( const QString &schema, const QString &name ) const override;
void dropRasterTable( const QString &schema, const QString &name ) const override;
void renameVectorTable( const QString &schema, const QString &name, const QString &newName ) const override;
QueryResult executeSqlWithNames( const QString &sql, QgsFeedback *feedback = nullptr ) const override;
QueryResult execSql( const QString &sql, QgsFeedback *feedback = nullptr ) const override;
void vacuum( const QString &schema, const QString &name ) const override;
void createSpatialIndex( const QString &schema, const QString &name, const QgsAbstractDatabaseProviderConnection::SpatialIndexOptions &options = QgsAbstractDatabaseProviderConnection::SpatialIndexOptions() ) const override;
bool spatialIndexExists( const QString &schema, const QString &name, const QString &geometryColumn ) const override;
@@ -135,11 +135,11 @@ void QgsAbstractDatabaseProviderConnection::renameSchema( const QString &, const

QList<QList<QVariant>> QgsAbstractDatabaseProviderConnection::executeSql( const QString &sql, QgsFeedback *feedback ) const
{
return executeSqlWithNames( sql, feedback ).rows;
return execSql( sql, feedback ).rows();
}


QgsAbstractDatabaseProviderConnection::QueryResult QgsAbstractDatabaseProviderConnection::executeSqlWithNames( const QString &, QgsFeedback * ) const
QgsAbstractDatabaseProviderConnection::QueryResult QgsAbstractDatabaseProviderConnection::execSql( const QString &, QgsFeedback * ) const
{
checkCapability( Capability::ExecuteSql );
return QueryResult();
@@ -434,3 +434,23 @@ void QgsAbstractDatabaseProviderConnection::TableProperty::setSchema( const QStr
mSchema = schema;
}


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

QList<QList<QVariant> > QgsAbstractDatabaseProviderConnection::QueryResult::rows() const
{
return mRows;
}

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

void QgsAbstractDatabaseProviderConnection::QueryResult::appendRow( const QList<QVariant> &row )
{
mRows.push_back( row );
}
@@ -68,7 +68,7 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv
Q_FLAG( TableFlags )

/**
* The QueryResult class represents the result of a query executed by executeSqlWithNames()
* The QueryResult class represents the result of a query executed by execSql()
*
* It encapsulates the result rows and a list of the column names.
* The query result may be empty in case the query returns nothing.
@@ -77,14 +77,38 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv
struct CORE_EXPORT QueryResult
{
#ifdef SIP_RUN
SIP_PYOBJECT __repr__();
% MethodCode
QString str = QStringLiteral( "<QgsAbstractDatabaseProviderConnection.QueryResult: %1 rows>" ).arg( sipCpp->rows.size() );
sipRes = PyUnicode_FromString( str.toUtf8().constData() );
% End
SIP_PYOBJECT __repr__();
% MethodCode
QString str = QStringLiteral( "<QgsAbstractDatabaseProviderConnection.QueryResult: %1 rows>" ).arg( sipCpp->rows().size() );
sipRes = PyUnicode_FromString( str.toUtf8().constData() );
% End
#endif
QStringList columnns;
QList<QList<QVariant>> rows;

/**
* Returns the column names
*/
QStringList columns() const;

/**
*Returns the results rows
*/
QList<QList<QVariant> > rows() const;

/**
* Appends \a columnName to the list of column names.
*/
void appendColumn( const QString &columnName );

/**
* Appends \a row to the results.
*/
void appendRow( const QList<QVariant> &row );

private:

QStringList mColumns;
QList<QList<QVariant>> mRows;

};


@@ -477,17 +501,19 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv
/**
* Executes raw \a sql and returns the (possibly empty) list of results in a multi-dimensional array, optionally \a feedback can be provided.
* Raises a QgsProviderConnectionException if any errors are encountered.
* \see execSql()
* \throws QgsProviderConnectionException
*/
virtual QList<QList<QVariant>> executeSql( const QString &sql, QgsFeedback *feedback = nullptr ) const SIP_THROW( QgsProviderConnectionException );

/**
* Executes raw \a sql and returns the (possibly empty) query results, optionally \a feedback can be provided.
* Raises a QgsProviderConnectionException if any errors are encountered.
* \see executeSql()
* \throws QgsProviderConnectionException
* \since QGIS 3.18
*/
virtual QueryResult executeSqlWithNames( const QString &sql, QgsFeedback *feedback = nullptr ) const SIP_THROW( QgsProviderConnectionException );
virtual QueryResult execSql( const QString &sql, QgsFeedback *feedback = nullptr ) const SIP_THROW( QgsProviderConnectionException );

/**
* Vacuum the database table with given \a schema and \a name (schema is ignored if not supported by the backend).
@@ -214,7 +214,7 @@ void QgsMssqlProviderConnection::dropSchema( const QString &schemaName, bool fo
.arg( QgsMssqlProvider::quotedIdentifier( schemaName ) ) );
}

QgsAbstractDatabaseProviderConnection::QueryResult QgsMssqlProviderConnection::executeSqlWithNames( const QString &sql, QgsFeedback *feedback ) const
QgsAbstractDatabaseProviderConnection::QueryResult QgsMssqlProviderConnection::execSql( const QString &sql, QgsFeedback *feedback ) const
{
checkCapability( Capability::ExecuteSql );
return executeSqlPrivate( sql, true, feedback );
@@ -267,7 +267,7 @@ QgsAbstractDatabaseProviderConnection::QueryResult QgsMssqlProviderConnection::e
const int numCols { rec.count() };
for ( int idx = 0; idx < numCols; ++idx )
{
results.columnns.push_back( rec.field( idx ).name() );
results.appendColumn( rec.field( idx ).name() );
}
while ( q.next() && ( ! feedback || ! feedback->isCanceled() ) )
{
@@ -283,7 +283,7 @@ QgsAbstractDatabaseProviderConnection::QueryResult QgsMssqlProviderConnection::e
row.push_back( q.value( col ).toString() );
}
}
results.rows.push_back( row );
results.appendRow( row );
}
}

@@ -365,7 +365,7 @@ QList<QgsMssqlProviderConnection::TableProperty> QgsMssqlProviderConnection::tab
.arg( QgsMssqlProvider::quotedValue( schema ) );
}

const QList<QVariantList> results { executeSqlPrivate( query, false ).rows };
const QList<QVariantList> results { executeSqlPrivate( query, false ).rows() };
for ( const auto &row : results )
{
Q_ASSERT( row.count( ) == 6 );
@@ -399,7 +399,7 @@ QList<QgsMssqlProviderConnection::TableProperty> QgsMssqlProviderConnection::tab
// This may fail for invalid geometries
try
{
const auto geomColResults { executeSqlPrivate( geomColSql ).rows };
const auto geomColResults { executeSqlPrivate( geomColSql ).rows() };
for ( const auto &row : geomColResults )
{
table.addGeometryColumnType( QgsWkbTypes::parseType( row[0].toString() ),
@@ -448,7 +448,7 @@ QStringList QgsMssqlProviderConnection::schemas( ) const
WHERE u.issqluser = 1
AND u.name NOT IN ('sys', 'guest', 'INFORMATION_SCHEMA')
)raw" )};
const QList<QVariantList> result { executeSqlPrivate( sql, false ).rows };
const QList<QVariantList> result { executeSqlPrivate( sql, false ).rows() };
for ( const auto &row : result )
{
if ( row.size() > 0 )
@@ -41,7 +41,7 @@ class QgsMssqlProviderConnection : public QgsAbstractDatabaseProviderConnection
void dropVectorTable( const QString &schema, const QString &name ) const override;
void createSchema( const QString &name ) const override;
void dropSchema( const QString &name, bool force = false ) const override;
QgsAbstractDatabaseProviderConnection::QueryResult executeSqlWithNames( const QString &sql, QgsFeedback *feedback ) const override;
QgsAbstractDatabaseProviderConnection::QueryResult execSql( const QString &sql, QgsFeedback *feedback ) const override;
QList<QgsAbstractDatabaseProviderConnection::TableProperty> tables( const QString &schema,
const TableFlags &flags = TableFlags() ) const override;
QStringList schemas( ) const override;
@@ -192,7 +192,7 @@ void QgsPostgresProviderConnection::renameSchema( const QString &name, const QSt
.arg( QgsPostgresConn::quotedIdentifier( newName ) ) );
}

QgsAbstractDatabaseProviderConnection::QueryResult QgsPostgresProviderConnection::executeSqlWithNames( const QString &sql, QgsFeedback *feedback ) const
QgsAbstractDatabaseProviderConnection::QueryResult QgsPostgresProviderConnection::execSql( const QString &sql, QgsFeedback *feedback ) const
{
checkCapability( Capability::ExecuteSql );
return executeSqlPrivateWithNames( sql, true, feedback );
@@ -201,7 +201,7 @@ QgsAbstractDatabaseProviderConnection::QueryResult QgsPostgresProviderConnection
QList<QVariantList> QgsPostgresProviderConnection::executeSqlPrivate( const QString &sql, bool resolveTypes, QgsFeedback *feedback, std::shared_ptr<QgsPoolPostgresConn> pgconn ) const
{
QStringList columnNames;
return executeSqlPrivateWithNames( sql, resolveTypes, feedback, pgconn ).rows;
return executeSqlPrivateWithNames( sql, resolveTypes, feedback, pgconn ).rows();
}

QgsAbstractDatabaseProviderConnection::QueryResult QgsPostgresProviderConnection::executeSqlPrivateWithNames( const QString &sql, bool resolveTypes, QgsFeedback *feedback, std::shared_ptr<QgsPoolPostgresConn> pgconn ) const
@@ -270,7 +270,7 @@ QgsAbstractDatabaseProviderConnection::QueryResult QgsPostgresProviderConnection
// Get column names
for ( int rowIdx = 0; rowIdx < res.PQnfields(); rowIdx++ )
{
results.columnns.push_back( res.PQfname( rowIdx ) );
results.appendColumn( res.PQfname( rowIdx ) );
}

// Try to convert value types at least for basic simple types that can be directly mapped to Python
@@ -369,7 +369,7 @@ QgsAbstractDatabaseProviderConnection::QueryResult QgsPostgresProviderConnection
row.push_back( res.PQgetvalue( rowIdx, colIdx ) );
}
}
results.rows.push_back( row );
results.appendRow( row );
}
}
if ( ! errCause.isEmpty() )
@@ -46,7 +46,7 @@ class QgsPostgresProviderConnection : public QgsAbstractDatabaseProviderConnecti
void createSchema( const QString &name ) const override;
void dropSchema( const QString &name, bool force = false ) const override;
void renameSchema( const QString &name, const QString &newName ) const override;
QgsAbstractDatabaseProviderConnection::QueryResult executeSqlWithNames( const QString &sql, QgsFeedback *feedback = nullptr ) const override;
QgsAbstractDatabaseProviderConnection::QueryResult execSql( const QString &sql, QgsFeedback *feedback = nullptr ) const override;
void vacuum( const QString &schema, const QString &name ) const override;
void createSpatialIndex( const QString &schema, const QString &name, const QgsAbstractDatabaseProviderConnection::SpatialIndexOptions &options = QgsAbstractDatabaseProviderConnection::SpatialIndexOptions() ) const override;
bool spatialIndexExists( const QString &schema, const QString &name, const QString &geometryColumn ) const override;
@@ -181,7 +181,7 @@ void QgsSpatiaLiteProviderConnection::renameVectorTable( const QString &schema,
}
}

QgsAbstractDatabaseProviderConnection::QueryResult QgsSpatiaLiteProviderConnection::executeSqlWithNames( const QString &sql, QgsFeedback *feedback ) const
QgsAbstractDatabaseProviderConnection::QueryResult QgsSpatiaLiteProviderConnection::execSql( const QString &sql, QgsFeedback *feedback ) const
{
checkCapability( Capability::ExecuteSql );
return executeSqlPrivate( sql, feedback );
@@ -241,7 +241,7 @@ bool QgsSpatiaLiteProviderConnection::spatialIndexExists( const QString &schema,
}
const QList<QVariantList> res = executeSqlPrivate( QStringLiteral( "SELECT spatial_index_enabled FROM geometry_columns WHERE lower(f_table_name) = lower(%1) AND lower(f_geometry_column) = lower(%2)" )
.arg( QgsSqliteUtils::quotedString( name ),
QgsSqliteUtils::quotedString( geometryColumn ) ) ).rows;
QgsSqliteUtils::quotedString( geometryColumn ) ) ).rows();
return !res.isEmpty() && !res.at( 0 ).isEmpty() && res.at( 0 ).at( 0 ).toInt() == 1;
}

@@ -294,15 +294,15 @@ QList<QgsSpatiaLiteProviderConnection::TableProperty> QgsSpatiaLiteProviderConne

// Need to store it here because provider (and underlying gaia library) returns views as spatial table if they have geometries
QStringList viewNames;
for ( const auto &tn : executeSqlPrivate( QStringLiteral( "SELECT name FROM sqlite_master WHERE type = 'view'" ) ).rows )
for ( const auto &tn : executeSqlPrivate( QStringLiteral( "SELECT name FROM sqlite_master WHERE type = 'view'" ) ).rows() )
{
viewNames.push_back( tn.first().toString() );
}

// Another weirdness: table names are converted to lowercase when out of spatialite gaia functions, let's get them back to their real case here,
// may need LAUNDER on open, but let's try to make it consistent with how GPKG works.
QgsStringMap tableNotLowercaseNames;
for ( const auto &tn : executeSqlPrivate( QStringLiteral( "SELECT name FROM sqlite_master WHERE LOWER(name) != name" ) ).rows )
for ( const auto &tn : executeSqlPrivate( QStringLiteral( "SELECT name FROM sqlite_master WHERE LOWER(name) != name" ) ).rows() )
{
const QString tName { tn.first().toString() };
tableNotLowercaseNames.insert( tName.toLower(), tName );
@@ -435,7 +435,7 @@ QgsAbstractDatabaseProviderConnection::QueryResult QgsSpatiaLiteProviderConnecti
fields = QgsOgrUtils::readOgrFields( fet.get(), QTextCodec::codecForName( "UTF-8" ) );
for ( const auto &f : qgis::as_const( fields ) )
{
results.columnns.push_back( f.name() );
results.appendColumn( f.name() );
}
}
if ( ! fields.isEmpty() )
@@ -455,7 +455,7 @@ QgsAbstractDatabaseProviderConnection::QueryResult QgsSpatiaLiteProviderConnecti
}
}

results.rows.push_back( row );
results.appendRow( row );
}
GDALDatasetReleaseResultSet( hDS.get(), ogrLayer );
}
@@ -38,7 +38,7 @@ class QgsSpatiaLiteProviderConnection : public QgsAbstractDatabaseProviderConnec
void createVectorTable( const QString &schema, const QString &name, const QgsFields &fields, QgsWkbTypes::Type wkbType, const QgsCoordinateReferenceSystem &srs, bool overwrite, const QMap<QString, QVariant> *options ) const override;
void dropVectorTable( const QString &schema, const QString &name ) const override;
void renameVectorTable( const QString &schema, const QString &name, const QString &newName ) const override;
QgsAbstractDatabaseProviderConnection::QueryResult executeSqlWithNames( const QString &sql, QgsFeedback *feedback = nullptr ) const override;
QgsAbstractDatabaseProviderConnection::QueryResult execSql( const QString &sql, QgsFeedback *feedback = nullptr ) const override;
void vacuum( const QString &schema, const QString &name ) const override;
void createSpatialIndex( const QString &schema, const QString &name, const QgsAbstractDatabaseProviderConnection::SpatialIndexOptions &options = QgsAbstractDatabaseProviderConnection::SpatialIndexOptions() ) const override;
bool spatialIndexExists( const QString &schema, const QString &name, const QString &geometryColumn ) const override;

0 comments on commit a277cc6

Please sign in to comment.
You can’t perform that action at this time.