mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
Rename attributes support for postgres provider
This commit is contained in:
parent
251474a62e
commit
ccc67ef7a5
@ -1123,7 +1123,7 @@ bool QgsPostgresProvider::hasSufficientPermsAndCapabilities()
|
||||
testAccess = connectionRO()->PQexec( sql );
|
||||
if ( testAccess.PQresultStatus() == PGRES_TUPLES_OK && testAccess.PQntuples() == 1 )
|
||||
{
|
||||
mEnabledCapabilities |= QgsVectorDataProvider::AddAttributes | QgsVectorDataProvider::DeleteAttributes;
|
||||
mEnabledCapabilities |= QgsVectorDataProvider::AddAttributes | QgsVectorDataProvider::DeleteAttributes | QgsVectorDataProvider::RenameAttributes;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2251,6 +2251,66 @@ bool QgsPostgresProvider::deleteAttributes( const QgsAttributeIds& ids )
|
||||
return returnvalue;
|
||||
}
|
||||
|
||||
bool QgsPostgresProvider::renameAttributes( const QgsFieldNameMap& renamedAttributes )
|
||||
{
|
||||
if ( mIsQuery )
|
||||
return false;
|
||||
|
||||
|
||||
QString sql = "BEGIN;";
|
||||
|
||||
QgsFieldNameMap::const_iterator renameIt = renamedAttributes.constBegin();
|
||||
bool returnvalue = true;
|
||||
for ( ; renameIt != renamedAttributes.constEnd(); ++renameIt )
|
||||
{
|
||||
int fieldIndex = renameIt.key();
|
||||
if ( fieldIndex < 0 || fieldIndex >= mAttributeFields.count() )
|
||||
{
|
||||
pushError( tr( "Invalid attribute index: %1" ).arg( fieldIndex ) );
|
||||
return false;
|
||||
}
|
||||
if ( mAttributeFields.indexFromName( renameIt.value() ) >= 0 )
|
||||
{
|
||||
//field name already in use
|
||||
pushError( tr( "Error renaming field %1: name '%2' already exists" ).arg( fieldIndex ).arg( renameIt.value() ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
sql += QString( "ALTER TABLE %1 RENAME COLUMN %2 TO %3;" )
|
||||
.arg( mQuery,
|
||||
quotedIdentifier( mAttributeFields.at( fieldIndex ).name() ),
|
||||
quotedIdentifier( renameIt.value() ) );
|
||||
}
|
||||
sql += "COMMIT;";
|
||||
|
||||
QgsPostgresConn* conn = connectionRW();
|
||||
if ( !conn )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
conn->lock();
|
||||
|
||||
try
|
||||
{
|
||||
conn->begin();
|
||||
//send sql statement and do error handling
|
||||
QgsPostgresResult result( conn->PQexec( sql ) );
|
||||
if ( result.PQresultStatus() != PGRES_COMMAND_OK )
|
||||
throw PGException( result );
|
||||
returnvalue = conn->commit();
|
||||
}
|
||||
catch ( PGException &e )
|
||||
{
|
||||
pushError( tr( "PostGIS error while renaming attributes: %1" ).arg( e.errorMessage() ) );
|
||||
conn->rollback();
|
||||
returnvalue = false;
|
||||
}
|
||||
|
||||
loadFields();
|
||||
conn->unlock();
|
||||
return returnvalue;
|
||||
}
|
||||
|
||||
bool QgsPostgresProvider::changeAttributeValues( const QgsChangedAttributesMap &attr_map )
|
||||
{
|
||||
bool returnvalue = true;
|
||||
|
@ -196,15 +196,9 @@ class QgsPostgresProvider : public QgsVectorDataProvider
|
||||
@return true in case of success and false in case of failure*/
|
||||
bool deleteFeatures( const QgsFeatureIds & id ) override;
|
||||
|
||||
/** Adds new attributes
|
||||
@param name map with attribute name as key and type as value
|
||||
@return true in case of success and false in case of failure*/
|
||||
bool addAttributes( const QList<QgsField> &attributes ) override;
|
||||
|
||||
/** Deletes existing attributes
|
||||
@param names of the attributes to delete
|
||||
@return true in case of success and false in case of failure*/
|
||||
bool deleteAttributes( const QgsAttributeIds &name ) override;
|
||||
virtual bool renameAttributes( const QgsFieldNameMap& renamedAttributes ) override;
|
||||
|
||||
/** Changes attribute values of existing features
|
||||
@param attr_map a map containing the new attributes. The integer is the feature id,
|
||||
|
@ -231,6 +231,44 @@ class TestPyQgsPostgresProvider(unittest.TestCase, ProviderTestCase):
|
||||
if 'precision' in e:
|
||||
self.assertEqual(fields.at(fields.indexFromName(f)).precision(), e['precision'])
|
||||
|
||||
def testRenameAttributes(self):
|
||||
''' Test renameAttributes() '''
|
||||
vl = QgsVectorLayer('%s table="qgis_test"."rename_table" sql=' % (self.dbconn), "renames", "postgres")
|
||||
provider = vl.dataProvider()
|
||||
provider.renameAttributes({1: 'field1', 2: 'field2'})
|
||||
|
||||
# bad rename
|
||||
self.assertFalse(provider.renameAttributes({-1: 'not_a_field'}))
|
||||
self.assertFalse(provider.renameAttributes({100: 'not_a_field'}))
|
||||
# already exists
|
||||
self.assertFalse(provider.renameAttributes({1: 'field2'}))
|
||||
|
||||
# rename one field
|
||||
self.assertTrue(provider.renameAttributes({1: 'newname'}))
|
||||
self.assertEqual(provider.fields().at(1).name(), 'newname')
|
||||
vl.updateFields()
|
||||
fet = next(vl.getFeatures())
|
||||
self.assertEqual(fet.fields()[1].name(), 'newname')
|
||||
|
||||
# rename two fields
|
||||
self.assertTrue(provider.renameAttributes({1: 'newname2', 2: 'another'}))
|
||||
self.assertEqual(provider.fields().at(1).name(), 'newname2')
|
||||
self.assertEqual(provider.fields().at(2).name(), 'another')
|
||||
vl.updateFields()
|
||||
fet = next(vl.getFeatures())
|
||||
self.assertEqual(fet.fields()[1].name(), 'newname2')
|
||||
self.assertEqual(fet.fields()[2].name(), 'another')
|
||||
|
||||
# close layer and reopen, then recheck to confirm that changes were saved to db
|
||||
del vl
|
||||
vl = None
|
||||
vl = QgsVectorLayer('%s table="qgis_test"."rename_table" sql=' % (self.dbconn), "renames", "postgres")
|
||||
provider = vl.dataProvider()
|
||||
self.assertEqual(provider.fields().at(1).name(), 'newname2')
|
||||
self.assertEqual(provider.fields().at(2).name(), 'another')
|
||||
fet = next(vl.getFeatures())
|
||||
self.assertEqual(fet.fields()[1].name(), 'newname2')
|
||||
self.assertEqual(fet.fields()[2].name(), 'another')
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
14
tests/testdata/provider/testdata_pg.sql
vendored
14
tests/testdata/provider/testdata_pg.sql
vendored
@ -398,3 +398,17 @@ CREATE TABLE qgis_test.domains
|
||||
fld_text_domain qgis_test.text_domain,
|
||||
fld_numeric_domain qgis_test.numeric_domain
|
||||
);
|
||||
|
||||
|
||||
--------------------------------------
|
||||
-- Temporary table for testing renaming fields
|
||||
--
|
||||
|
||||
CREATE TABLE qgis_test.rename_table
|
||||
(
|
||||
gid serial NOT NULL,
|
||||
field1 text,
|
||||
field2 text
|
||||
);
|
||||
|
||||
INSERT INTO qgis_test.rename_table (field1,field2) VALUES ('a','b');
|
||||
|
Loading…
x
Reference in New Issue
Block a user