Skip to content

Commit

Permalink
Add setFieldAlias support for OGR provider connection
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Apr 17, 2023
1 parent 9aac2b8 commit 15c8899
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 0 deletions.
49 changes: 49 additions & 0 deletions src/core/providers/ogr/qgsogrproviderconnection.cpp
Expand Up @@ -446,6 +446,15 @@ void QgsOgrProviderConnection::setDefaultCapabilities()
{
mCapabilities |= RenameField;
}

#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
// only supported on gdal 3.7 and above
if ( CSLFindString( papszTokens, "AlternativeName" ) >= 0 )
{
mCapabilities2 |= Qgis::DatabaseProviderConnectionCapability2::SetFieldAlias;
}
#endif

CSLDestroy( papszTokens );
}
#else
Expand Down Expand Up @@ -1012,6 +1021,46 @@ void QgsOgrProviderConnection::renameField( const QString &schema, const QString
}
}

void QgsOgrProviderConnection::setFieldAlias( const QString &fieldName, const QString &schema, const QString &tableName, const QString &alias ) const
{
#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
if ( ! schema.isEmpty() )
{
QgsMessageLog::logMessage( QStringLiteral( "Schema is not supported by OGR, ignoring" ), QStringLiteral( "OGR" ), Qgis::MessageLevel::Info );
}

QString errCause;
QgsOgrLayerUniquePtr layer = QgsOgrProviderUtils::getLayer( uri(),
true,
QStringList(),
tableName, errCause, true );
if ( !layer )
{
throw QgsProviderConnectionException( QObject::tr( "There was an error opening the dataset: %1" ).arg( errCause ) );
}

//type does not matter, it will not be used
gdal::ogr_field_def_unique_ptr fld( OGR_Fld_Create( fieldName.toUtf8().constData(), OFTReal ) );
OGR_Fld_SetAlternativeName( fld.get(), alias.toUtf8().constData() );

const int fieldIndex = layer->GetLayerDefn().GetFieldIndex( fieldName.toUtf8().constData() );
if ( fieldIndex < 0 )
{
throw QgsProviderConnectionException( QObject::tr( "Could not set alias for %1 - field does not exist" ).arg( fieldName ) );
}
if ( layer->AlterFieldDefn( fieldIndex, fld.get(), ALTER_ALTERNATIVE_NAME_FLAG ) != OGRERR_NONE )
{
throw QgsProviderConnectionException( QObject::tr( "Could not set alias: %1" ).arg( CPLGetLastErrorMsg() ) );
}
#else
( void )fieldName;
( void )schema;
( void )tableName;
( void )alias;
throw QgsProviderConnectionException( QObject::tr( "Setting field aliases for datasets requires GDAL 3.7 or later" ) );
#endif
}

QgsAbstractDatabaseProviderConnection::SqlVectorLayerOptions QgsOgrProviderConnection::sqlOptions( const QString &layerSource )
{
SqlVectorLayerOptions options;
Expand Down
1 change: 1 addition & 0 deletions src/core/providers/ogr/qgsogrproviderconnection.h
Expand Up @@ -89,6 +89,7 @@ class QgsOgrProviderConnection : public QgsAbstractDatabaseProviderConnection
void setFieldDomainName( const QString &fieldName, const QString &schema, const QString &tableName, const QString &domainName ) const override;
void addFieldDomain( const QgsFieldDomain &domain, const QString &schema ) const override;
void renameField( const QString &schema, const QString &tableName, const QString &name, const QString &newName ) const override;
void setFieldAlias( const QString &fieldName, const QString &schema, const QString &tableName, const QString &alias ) const override;
SqlVectorLayerOptions sqlOptions( const QString &layerSource ) override;
QList< Qgis::RelationshipCardinality > supportedRelationshipCardinalities() const override;
QList< Qgis::RelationshipStrength > supportedRelationshipStrengths() const override;
Expand Down
40 changes: 40 additions & 0 deletions tests/src/python/test_provider_ogr.py
Expand Up @@ -3185,6 +3185,46 @@ def testCsvInterleavedUpdate(self):
3: ['3', 'feat 3', 'fid 3']
})

@unittest.skipIf(int(gdal.VersionInfo('VERSION_NUM')) < GDAL_COMPUTE_VERSION(3, 7, 0), "GDAL 3.7 required")
def test_provider_connection_set_field_alias(self):
"""
Test setting field alias via the connections api
"""
metadata = QgsProviderRegistry.instance().providerMetadata('ogr')
with tempfile.TemporaryDirectory() as temp_dir:
tmpfile = os.path.join(temp_dir, 'test_gdb.gdb')

ok, err = metadata.createDatabase(tmpfile)
self.assertTrue(ok)
self.assertFalse(err)

conn = metadata.createConnection(tmpfile, {})
self.assertTrue(conn)

fields = QgsFields()
field = QgsField('my_field', QVariant.String)
fields.append(field)
conn.createVectorTable('', 'test', fields, QgsWkbTypes.Point, QgsCoordinateReferenceSystem('EPSG:4326'), False, {})
layer = QgsVectorLayer(tmpfile + '|layername=test')
self.assertTrue(layer.isValid())

del layer

self.assertTrue(
conn.capabilities2() & Qgis.DatabaseProviderConnectionCapability2.SetFieldAlias)

# field does not exist
with self.assertRaises(QgsProviderConnectionException):
conn.setFieldAlias('not field', '', 'test', 'my alias')

conn.setFieldAlias('my_field', '', 'test', 'my alias')

layer = QgsVectorLayer(tmpfile + '|layername=test')
self.assertTrue(layer.isValid())

fields = layer.fields()
self.assertEqual(fields['my_field'].alias(), 'my alias')

@unittest.skipIf(int(gdal.VersionInfo('VERSION_NUM')) < GDAL_COMPUTE_VERSION(3, 7, 0), "GDAL 3.7 required")
def test_provider_set_field_alias(self):
"""
Expand Down

0 comments on commit 15c8899

Please sign in to comment.