Skip to content
Permalink
Browse files

DB Connections API: add fields method -> column info

  • Loading branch information
elpaso committed Jul 6, 2020
1 parent 992b1f2 commit dc67a4edecef0200457b3e1cb7ecd2fd804534da
@@ -234,6 +234,8 @@ This information is calculated from the geometry columns types.
CreateSpatialIndex,
SpatialIndexExists,
DeleteSpatialIndex,
DeleteField,
CreateField,
};

typedef QFlags<QgsAbstractDatabaseProviderConnection::Capability> Capabilities;
@@ -460,6 +462,21 @@ Raises a QgsProviderConnectionException if any errors are encountered.
Returns information about the existing schemas.
Raises a QgsProviderConnectionException if any errors are encountered.

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

virtual QgsFields fields( const QString &schema, const QString &table ) const throw( QgsProviderConnectionException );
%Docstring
Returns the fields of a ``table`` and ``schema``.
Raises a QgsProviderConnectionException if any errors are encountered.

.. note::

the default implementation creates a temporary vector layer, providers may
choose to override this method for a greater efficiency.

.. versionadded:: 3.18

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

@@ -24,6 +24,7 @@
QgsGeoPackageProviderConnection::QgsGeoPackageProviderConnection( const QString &name )
: QgsAbstractDatabaseProviderConnection( name )
{
mProviderKey = QStringLiteral( "ogr" );
setDefaultCapabilities();
QgsSettings settings;
settings.beginGroup( QStringLiteral( "ogr" ), QgsSettings::Section::Providers );
@@ -36,6 +37,7 @@ QgsGeoPackageProviderConnection::QgsGeoPackageProviderConnection( const QString
QgsGeoPackageProviderConnection::QgsGeoPackageProviderConnection( const QString &uri, const QVariantMap &configuration ):
QgsAbstractDatabaseProviderConnection( uri, configuration )
{
mProviderKey = QStringLiteral( "ogr" );
// Cleanup the URI in case it contains other information other than the file path
if ( uri.contains( '|' ) )
{
@@ -14,6 +14,7 @@
* *
***************************************************************************/
#include "qgsabstractdatabaseproviderconnection.h"
#include "qgsvectorlayer.h"
#include "qgsexception.h"
#include <QVariant>
#include <QObject>
@@ -212,6 +213,18 @@ QList<QgsAbstractDatabaseProviderConnection::TableProperty::GeometryColumnType>
return mGeometryColumnTypes;
}

QgsFields QgsAbstractDatabaseProviderConnection::fields( const QString &schema, const QString &tableName ) const
{
QgsVectorLayer vl { tableUri( schema, tableName ), QStringLiteral( "temp_layer" ), mProviderKey };
if ( vl.isValid() )
{
return vl.fields();
}
else
{
throw QgsProviderConnectionException( QObject::tr( "Error retrieving fields information for uri: %1" ).arg( vl.publicSource() ) );
}
}

QString QgsAbstractDatabaseProviderConnection::TableProperty::defaultName() const
{
@@ -293,6 +293,8 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv
CreateSpatialIndex = 1 << 16, //!< The connection can create spatial indices
SpatialIndexExists = 1 << 17, //!< The connection can determine if a spatial index exists
DeleteSpatialIndex = 1 << 18, //!< The connection can delete spatial indices for tables
DeleteField = 1 << 19, //!< Can delete an existing field
CreateField = 1 << 20, //!< Can add a new field
};

Q_ENUM( Capability )
@@ -494,6 +496,16 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv
*/
virtual QStringList schemas() const SIP_THROW( QgsProviderConnectionException );

/**
* Returns the fields of a \a table and \a schema.
* Raises a QgsProviderConnectionException if any errors are encountered.
* \note the default implementation creates a temporary vector layer, providers may
* choose to override this method for a greater efficiency.
* \since QGIS 3.18
* \throws QgsProviderConnectionException
*/
virtual QgsFields fields( const QString &schema, const QString &table ) const SIP_THROW( QgsProviderConnectionException );

protected:

///@cond PRIVATE
@@ -506,6 +518,7 @@ class CORE_EXPORT QgsAbstractDatabaseProviderConnection : public QgsAbstractProv
///@endcond

Capabilities mCapabilities = nullptr SIP_SKIP;
QString mProviderKey;

};

@@ -37,6 +37,7 @@ const QStringList QgsMssqlProviderConnection::EXTRA_CONNECTION_PARAMETERS
QgsMssqlProviderConnection::QgsMssqlProviderConnection( const QString &name )
: QgsAbstractDatabaseProviderConnection( name )
{
mProviderKey = QStringLiteral( "mssql" );
// Remove the sql and table empty parts
setUri( QgsMssqlConnection::connUri( name ).uri() );
setDefaultCapabilities();
@@ -45,6 +46,7 @@ QgsMssqlProviderConnection::QgsMssqlProviderConnection( const QString &name )
QgsMssqlProviderConnection::QgsMssqlProviderConnection( const QString &uri, const QVariantMap &configuration ):
QgsAbstractDatabaseProviderConnection( QString(), configuration )
{
mProviderKey = QStringLiteral( "mssql" );
// Additional connection information
const QgsDataSourceUri inputUri( uri );
QgsDataSourceUri currentUri { QgsDataSourceUri( uri ).connectionInfo( false ) };
@@ -29,6 +29,7 @@ extern "C"
QgsPostgresProviderConnection::QgsPostgresProviderConnection( const QString &name )
: QgsAbstractDatabaseProviderConnection( name )
{
mProviderKey = QStringLiteral( "postgres" );
// Remove the sql and table empty parts
const QRegularExpression removePartsRe { R"raw(\s*sql=\s*|\s*table=""\s*)raw" };
setUri( QgsPostgresConn::connUri( name ).uri().replace( removePartsRe, QString() ) );
@@ -38,6 +39,7 @@ QgsPostgresProviderConnection::QgsPostgresProviderConnection( const QString &nam
QgsPostgresProviderConnection::QgsPostgresProviderConnection( const QString &uri, const QVariantMap &configuration ):
QgsAbstractDatabaseProviderConnection( QgsDataSourceUri( uri ).connectionInfo( false ), configuration )
{
mProviderKey = QStringLiteral( "postgres" );
setDefaultCapabilities();
}

@@ -25,6 +25,7 @@
QgsSpatiaLiteProviderConnection::QgsSpatiaLiteProviderConnection( const QString &name )
: QgsAbstractDatabaseProviderConnection( name )
{
mProviderKey = QStringLiteral( "spatialite" );
setDefaultCapabilities();
// TODO: QGIS 4: move into QgsSettings::Section::Providers group
QgsSettings settings;
@@ -39,6 +40,7 @@ QgsSpatiaLiteProviderConnection::QgsSpatiaLiteProviderConnection( const QString
QgsSpatiaLiteProviderConnection::QgsSpatiaLiteProviderConnection( const QString &uri, const QVariantMap &configuration ):
QgsAbstractDatabaseProviderConnection( uri, configuration )
{
mProviderKey = QStringLiteral( "spatialite" );
const QRegularExpression removePartsRe { R"raw(\s*sql=\s*|\s*table=""\s*|\([^\)]+\))raw" };
// Cleanup the URI in case it contains other information other than the file path
setUri( QString( uri ).replace( removePartsRe, QString() ) );
@@ -118,6 +118,14 @@ def test_gpkg_connections(self):
self.assertFalse('myNewTable' in table_names)
self.assertTrue('myNewAspatialTable' in table_names)

def test_gpkg_fields(self):
"""Test fields"""

md = QgsProviderRegistry.instance().providerMetadata('ogr')
conn = md.createConnection(self.uri, {})
fields = conn.fields('', 'cdb_lines')
self.assertEqual(fields.names(), ['fid', 'id', 'typ', 'name', 'ortsrat', 'id_long'])


if __name__ == '__main__':
unittest.main()
@@ -317,6 +317,14 @@ def test_foreign_table_server(self):
conn.executeSql(foreign_table_definition)
self.assertEquals(conn.tables('foreign_schema', QgsAbstractDatabaseProviderConnection.Foreign)[0].tableName(), 'someData')

def test_fields(self):
"""Test fields"""

md = QgsProviderRegistry.instance().providerMetadata('postgres')
conn = md.createConnection(self.uri, {})
fields = conn.fields('qgis_test', 'someData')
self.assertEqual(fields.names(), ['pk', 'cnt', 'name', 'name2', 'num_char', 'dt', 'date', 'time', 'geom'])


if __name__ == '__main__':
unittest.main()
@@ -110,6 +110,14 @@ def test_spatialite_connections(self):
self.assertFalse('myNewTable' in table_names)
self.assertTrue('myNewAspatialTable' in table_names)

def test_gpkg_fields(self):
"""Test fields"""

md = QgsProviderRegistry.instance().providerMetadata('spatialite')
conn = md.createConnection(self.uri, {})
fields = conn.fields('', 'cdb_lines')
self.assertEqual(fields.names(), ['pk', 'geom', 'fid', 'id', 'typ', 'name', 'ortsrat', 'id_long'])


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

0 comments on commit dc67a4e

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