Skip to content
Permalink
Browse files

Make provider default value clauses exempt from unique constraint checks

Otherwise the check fails when the provider has a default value clause
like 'nextval(...)' even though the actual committed value will be
unique.
  • Loading branch information
nyalldawson committed Nov 8, 2016
1 parent 8cd810e commit e40d64f9d5add15202cd9c76ffc1444d9cb65538
Showing with 31 additions and 3 deletions.
  1. +17 −2 src/core/qgsvectorlayerutils.cpp
  2. +14 −1 tests/src/python/test_provider_postgres.py
@@ -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;
@@ -29,7 +29,8 @@
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 @@ def testConstraintOverwrite(self):
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'

0 comments on commit e40d64f

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