diff --git a/src/core/qgsvectorlayerutils.cpp b/src/core/qgsvectorlayerutils.cpp index 29653a98bac..0ae2ab27e1c 100644 --- a/src/core/qgsvectorlayerutils.cpp +++ b/src/core/qgsvectorlayerutils.cpp @@ -14,16 +14,31 @@ ***************************************************************************/ #include "qgsvectorlayerutils.h" +#include "qgsvectordataprovider.h" bool QgsVectorLayerUtils::valueExists( const QgsVectorLayer* layer, int fieldIndex, const QVariant& value, const QgsFeatureIds& ignoreIds ) { if ( !layer ) return false; - if ( fieldIndex < 0 || fieldIndex >= layer->fields().count() ) + QgsFields fields = layer->fields(); + + if ( fieldIndex < 0 || fieldIndex >= fields.count() ) return false; - QString fieldName = layer->fields().at( fieldIndex ).name(); + // check - if value is a provider side defaultValueClause then we exclude it from the check + if ( fields.fieldOrigin( fieldIndex ) == QgsFields::OriginProvider ) + { + int providerIdx = fields.fieldOriginIndex( fieldIndex ); + QString providerDefaultClause = layer->dataProvider()->defaultValueClause( providerIdx ); + if ( !providerDefaultClause.isEmpty() && value.toString() == providerDefaultClause ) + { + // exempt from check + return false; + } + } + + QString fieldName = fields.at( fieldIndex ).name(); // build up an optimised feature request QgsFeatureRequest request; diff --git a/tests/src/python/test_provider_postgres.py b/tests/src/python/test_provider_postgres.py index 97ddb8ab3f5..d483da905e1 100644 --- a/tests/src/python/test_provider_postgres.py +++ b/tests/src/python/test_provider_postgres.py @@ -29,7 +29,8 @@ from qgis.core import ( QgsField, QgsFieldConstraints, QgsDataProvider, - NULL + NULL, + QgsVectorLayerUtils ) from qgis.gui import QgsEditorWidgetRegistry from qgis.PyQt.QtCore import QSettings, QDate, QTime, QDateTime, QVariant @@ -516,6 +517,18 @@ class TestPyQgsPostgresProvider(unittest.TestCase, ProviderTestCase): self.assertTrue(vl.fields().at(0).constraints().constraints() & QgsFieldConstraints.ConstraintUnique) self.assertTrue(vl.fieldConstraints(0) & QgsFieldConstraints.ConstraintUnique) + def testVectorLayerUtilsUniqueWithProviderDefault(self): + vl = QgsVectorLayer('%s table="qgis_test"."someData" sql=' % (self.dbconn), "someData", "postgres") + default_clause = 'nextval(\'qgis_test."someData_pk_seq"\'::regclass)' + self.assertEqual(vl.dataProvider().defaultValueClause(0), default_clause) + self.assertTrue(QgsVectorLayerUtils.valueExists(vl, 0, 4)) + + vl.startEditing() + f = QgsFeature(vl.fields()) + f.setAttribute(0, default_clause) + self.assertTrue(vl.addFeatures([f])) + self.assertFalse(QgsVectorLayerUtils.valueExists(vl, 0, default_clause)) + # See http://hub.qgis.org/issues/15188 def testNumericPrecision(self): uri = 'point?field=f1:int'