Skip to content

Commit

Permalink
[FEATURE] Not null constraint detection for ogr provider
Browse files Browse the repository at this point in the history
Implements not null constraint detection for the OGR layers, where
supported for the data format by OGR.

(only available for GDAL >= 2.0)
  • Loading branch information
nyalldawson committed Nov 2, 2016
1 parent 210c98b commit bb6fc32
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 10 deletions.
27 changes: 18 additions & 9 deletions src/providers/ogr/qgsogrprovider.cpp
Expand Up @@ -927,18 +927,27 @@ void QgsOgrProvider::loadFields()
if ( prec > 0 )
width -= 1;

mAttributeFields.append(
QgsField(
name,
varType,
QgsField newField = QgsField(
name,
varType,
#ifdef ANDROID
OGR_GetFieldTypeName( ogrType ),
OGR_GetFieldTypeName( ogrType ),
#else
textEncoding()->toUnicode( OGR_GetFieldTypeName( ogrType ) ),
textEncoding()->toUnicode( OGR_GetFieldTypeName( ogrType ) ),
#endif
width, prec
)
);
width, prec
);

#if defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,0,0)
// check if field is nullable
bool nullable = OGR_Fld_IsNullable( fldDef );
if ( !nullable )
{
newField.setConstraint( QgsField::ConstraintNotNull, QgsField::ConstraintOriginProvider );
}
#endif

mAttributeFields.append( newField );
}
}
}
Expand Down
33 changes: 32 additions & 1 deletion tests/src/python/test_provider_ogr_sqlite.py
Expand Up @@ -20,7 +20,7 @@
import glob
from osgeo import gdal, ogr

from qgis.core import QgsVectorLayer, QgsFeature, QgsGeometry, QgsFeatureRequest
from qgis.core import QgsVectorLayer, QgsFeature, QgsGeometry, QgsFeatureRequest, QgsField
from qgis.testing import start_app, unittest
from utilities import unitTestDataPath

Expand Down Expand Up @@ -129,6 +129,37 @@ def testFidSupport(self):
got = [(f.attribute('fid'), f.attribute('intfield')) for f in vl.dataProvider().getFeatures(QgsFeatureRequest().setFilterExpression("fid = 12"))]
self.assertEqual(got, [(12, 123)])

@unittest.expectedFailure(int(gdal.VersionInfo('VERSION_NUM')) < GDAL_COMPUTE_VERSION(2, 0, 0))
def testNotNullConstraint(self):
""" test detection of not null constraint on OGR layer """

tmpfile = os.path.join(self.basetestpath, 'testNotNullConstraint.sqlite')
ds = ogr.GetDriverByName('SQLite').CreateDataSource(tmpfile)
lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint, options=['FID=fid'])
lyr.CreateField(ogr.FieldDefn('field1', ogr.OFTInteger))
fld2 = ogr.FieldDefn('field2', ogr.OFTInteger)
fld2.SetNullable(False)
lyr.CreateField(fld2)
ds = None

vl = QgsVectorLayer('{}'.format(tmpfile), 'test', 'ogr')
self.assertTrue(vl.isValid())

# test some bad indexes
self.assertEqual(vl.dataProvider().fieldConstraints(-1), QgsField.Constraints())
self.assertEqual(vl.dataProvider().fieldConstraints(1001), QgsField.Constraints())

self.assertFalse(vl.dataProvider().fieldConstraints(0) & QgsField.ConstraintNotNull)
self.assertFalse(vl.dataProvider().fieldConstraints(1) & QgsField.ConstraintNotNull)
self.assertTrue(vl.dataProvider().fieldConstraints(2) & QgsField.ConstraintNotNull)

# test that constraints have been saved to fields correctly
fields = vl.fields()
self.assertFalse(fields.at(0).constraints() & QgsField.ConstraintNotNull)
self.assertFalse(fields.at(1).constraints() & QgsField.ConstraintNotNull)
self.assertTrue(fields.at(2).constraints() & QgsField.ConstraintNotNull)
self.assertEqual(fields.at(2).constraintOrigin(QgsField.ConstraintNotNull), QgsField.ConstraintOriginProvider)


if __name__ == '__main__':
unittest.main()

0 comments on commit bb6fc32

Please sign in to comment.