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.
This commit is contained in:
Nyall Dawson 2016-11-08 12:51:47 +10:00
parent 8cd810ed2c
commit e40d64f9d5
2 changed files with 31 additions and 3 deletions

View File

@ -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;

View File

@ -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'