Skip to content

Commit 24ffa15

Browse files
committed
[FEATURE][processing] Extract by attribute can extract for null/notnull values
Adds support for filtering where an attribute value is null or not null
1 parent fb8b931 commit 24ffa15

14 files changed

+419
-18
lines changed

python/plugins/processing/algs/qgis/ExtractByAttribute.py

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,17 @@ class ExtractByAttribute(GeoAlgorithm):
5151
'<',
5252
'<=',
5353
'begins with',
54-
'contains'
54+
'contains',
55+
'is null',
56+
'is not null'
5557
]
58+
STRING_OPERATORS = ['begins with',
59+
'contains']
5660

5761
def defineCharacteristics(self):
5862
self.name, self.i18n_name = self.trAlgorithm('Extract by attribute')
5963
self.group, self.i18n_group = self.trAlgorithm('Vector selection tools')
64+
self.tags = self.tr('extract,filter,attribute,value,contains,null,field')
6065

6166
self.i18n_operators = ['=',
6267
'!=',
@@ -65,15 +70,17 @@ def defineCharacteristics(self):
6570
'<',
6671
'<=',
6772
self.tr('begins with'),
68-
self.tr('contains')]
73+
self.tr('contains'),
74+
self.tr('is null'),
75+
self.tr('is not null')]
6976

7077
self.addParameter(ParameterVector(self.INPUT,
7178
self.tr('Input Layer')))
7279
self.addParameter(ParameterTableField(self.FIELD,
7380
self.tr('Selection attribute'), self.INPUT))
7481
self.addParameter(ParameterSelection(self.OPERATOR,
7582
self.tr('Operator'), self.i18n_operators))
76-
self.addParameter(ParameterString(self.VALUE, self.tr('Value')))
83+
self.addParameter(ParameterString(self.VALUE, self.tr('Value'), optional=True))
7784

7885
self.addOutput(OutputVector(self.OUTPUT, self.tr('Extracted (attribute)')))
7986

@@ -90,25 +97,23 @@ def processAlgorithm(self, progress):
9097
idx = layer.fields().lookupField(fieldName)
9198
fieldType = fields[idx].type()
9299

93-
if fieldType != QVariant.String and operator in self.OPERATORS[-2:]:
94-
op = ''.join(['"%s", ' % o for o in self.OPERATORS[-2:]])
100+
if fieldType != QVariant.String and operator in self.STRING_OPERATORS:
101+
op = ''.join(['"%s", ' % o for o in self.STRING_OPERATORS])
95102
raise GeoAlgorithmExecutionException(
96103
self.tr('Operators %s can be used only with string fields.' % op))
97104

98-
if fieldType in [QVariant.Int, QVariant.Double, QVariant.UInt, QVariant.LongLong, QVariant.ULongLong]:
99-
expr = '"%s" %s %s' % (fieldName, operator, value)
100-
elif fieldType == QVariant.String:
101-
if operator not in self.OPERATORS[-2:]:
102-
expr = """"%s" %s '%s'""" % (fieldName, operator, value)
103-
elif operator == 'begins with':
104-
expr = """"%s" LIKE '%s%%'""" % (fieldName, value)
105-
elif operator == 'contains':
106-
expr = """"%s" LIKE '%%%s%%'""" % (fieldName, value)
107-
elif fieldType in [QVariant.Date, QVariant.DateTime]:
108-
expr = """"%s" %s '%s'""" % (fieldName, operator, value)
105+
field_ref = QgsExpression.quotedColumnRef(fieldName)
106+
quoted_val = QgsExpression.quotedValue(value)
107+
if operator == 'is null':
108+
expr = '{} IS NULL'.format(field_ref)
109+
elif operator == 'is not null':
110+
expr = '{} IS NOT NULL'.format(field_ref)
111+
elif operator == 'begins with':
112+
expr = """%s LIKE '%s%%'""" % (field_ref, value)
113+
elif operator == 'contains':
114+
expr = """%s LIKE '%%%s%%'""" % (field_ref, value)
109115
else:
110-
raise GeoAlgorithmExecutionException(
111-
self.tr('Unsupported field type "%s"' % fields[idx].typeName()))
116+
expr = '{} {} {}'.format(field_ref, operator, quoted_val)
112117

113118
expression = QgsExpression(expr)
114119
if not expression.hasParserError():

python/plugins/processing/algs/qgis/ExtractByExpression.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class ExtractByExpression(GeoAlgorithm):
4343
def defineCharacteristics(self):
4444
self.name, self.i18n_name = self.trAlgorithm('Extract by expression')
4545
self.group, self.i18n_group = self.trAlgorithm('Vector selection tools')
46+
self.tags = self.tr('extract,filter,expression,field')
4647

4748
self.addParameter(ParameterVector(self.INPUT,
4849
self.tr('Input Layer')))

python/plugins/processing/algs/qgis/ExtractByLocation.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ class ExtractByLocation(GeoAlgorithm):
4646
def defineCharacteristics(self):
4747
self.name, self.i18n_name = self.trAlgorithm('Extract by location')
4848
self.group, self.i18n_group = self.trAlgorithm('Vector selection tools')
49+
self.tags = self.tr('extract,filter,location,intersects,contains,within')
50+
4951
self.addParameter(ParameterVector(self.INPUT,
5052
self.tr('Layer to select from')))
5153
self.addParameter(ParameterVector(self.INTERSECT,
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<GMLFeatureClassList>
2+
<GMLFeatureClass>
3+
<Name>extract_by_attribute_contains</Name>
4+
<ElementPath>extract_by_attribute_contains</ElementPath>
5+
<!--POLYGON-->
6+
<GeometryType>3</GeometryType>
7+
<SRSName>EPSG:4326</SRSName>
8+
<DatasetSpecificInfo>
9+
<FeatureCount>3</FeatureCount>
10+
<ExtentXMin>-1.00000</ExtentXMin>
11+
<ExtentXMax>6.00000</ExtentXMax>
12+
<ExtentYMin>-1.00000</ExtentYMin>
13+
<ExtentYMax>6.00000</ExtentYMax>
14+
</DatasetSpecificInfo>
15+
<PropertyDefn>
16+
<Name>name</Name>
17+
<ElementPath>name</ElementPath>
18+
<Type>String</Type>
19+
<Width>5</Width>
20+
</PropertyDefn>
21+
<PropertyDefn>
22+
<Name>intval</Name>
23+
<ElementPath>intval</ElementPath>
24+
<Type>Integer</Type>
25+
</PropertyDefn>
26+
<PropertyDefn>
27+
<Name>floatval</Name>
28+
<ElementPath>floatval</ElementPath>
29+
<Type>Real</Type>
30+
</PropertyDefn>
31+
</GMLFeatureClass>
32+
</GMLFeatureClassList>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<ogr:FeatureCollection
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation=""
5+
xmlns:ogr="http://ogr.maptools.org/"
6+
xmlns:gml="http://www.opengis.net/gml">
7+
<gml:boundedBy>
8+
<gml:Box>
9+
<gml:coord><gml:X>-1</gml:X><gml:Y>-1</gml:Y></gml:coord>
10+
<gml:coord><gml:X>6</gml:X><gml:Y>6</gml:Y></gml:coord>
11+
</gml:Box>
12+
</gml:boundedBy>
13+
14+
<gml:featureMember>
15+
<ogr:extract_by_attribute_contains fid="polys.0">
16+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>-1,-1 -1,3 3,3 3,2 2,2 2,-1 -1,-1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
17+
<ogr:name>aaaaa</ogr:name>
18+
<ogr:intval>33</ogr:intval>
19+
<ogr:floatval>44.123456</ogr:floatval>
20+
</ogr:extract_by_attribute_contains>
21+
</gml:featureMember>
22+
<gml:featureMember>
23+
<ogr:extract_by_attribute_contains fid="polys.1">
24+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>5,5 6,4 4,4 5,5</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
25+
<ogr:name>Aaaaa</ogr:name>
26+
<ogr:intval>-33</ogr:intval>
27+
<ogr:floatval>0</ogr:floatval>
28+
</ogr:extract_by_attribute_contains>
29+
</gml:featureMember>
30+
<gml:featureMember>
31+
<ogr:extract_by_attribute_contains fid="polys.2">
32+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2,5 2,6 3,6 3,5 2,5</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
33+
<ogr:name>bbaaa</ogr:name>
34+
<ogr:floatval>0.123</ogr:floatval>
35+
</ogr:extract_by_attribute_contains>
36+
</gml:featureMember>
37+
</ogr:FeatureCollection>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<GMLFeatureClassList>
2+
<GMLFeatureClass>
3+
<Name>extract_by_attribute_greater</Name>
4+
<ElementPath>extract_by_attribute_greater</ElementPath>
5+
<!--POLYGON-->
6+
<GeometryType>3</GeometryType>
7+
<SRSName>EPSG:4326</SRSName>
8+
<DatasetSpecificInfo>
9+
<FeatureCount>2</FeatureCount>
10+
<ExtentXMin>-1.00000</ExtentXMin>
11+
<ExtentXMax>6.00000</ExtentXMax>
12+
<ExtentYMin>-3.00000</ExtentYMin>
13+
<ExtentYMax>3.00000</ExtentYMax>
14+
</DatasetSpecificInfo>
15+
<PropertyDefn>
16+
<Name>name</Name>
17+
<ElementPath>name</ElementPath>
18+
<Type>String</Type>
19+
<Width>5</Width>
20+
</PropertyDefn>
21+
<PropertyDefn>
22+
<Name>intval</Name>
23+
<ElementPath>intval</ElementPath>
24+
<Type>Integer</Type>
25+
</PropertyDefn>
26+
<PropertyDefn>
27+
<Name>floatval</Name>
28+
<ElementPath>floatval</ElementPath>
29+
<Type>Real</Type>
30+
</PropertyDefn>
31+
</GMLFeatureClass>
32+
</GMLFeatureClassList>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<ogr:FeatureCollection
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation=""
5+
xmlns:ogr="http://ogr.maptools.org/"
6+
xmlns:gml="http://www.opengis.net/gml">
7+
<gml:boundedBy>
8+
<gml:Box>
9+
<gml:coord><gml:X>-1</gml:X><gml:Y>-3</gml:Y></gml:coord>
10+
<gml:coord><gml:X>6</gml:X><gml:Y>3</gml:Y></gml:coord>
11+
</gml:Box>
12+
</gml:boundedBy>
13+
14+
<gml:featureMember>
15+
<ogr:extract_by_attribute_greater fid="polys.0">
16+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>-1,-1 -1,3 3,3 3,2 2,2 2,-1 -1,-1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
17+
<ogr:name>aaaaa</ogr:name>
18+
<ogr:intval>33</ogr:intval>
19+
<ogr:floatval>44.123456</ogr:floatval>
20+
</ogr:extract_by_attribute_greater>
21+
</gml:featureMember>
22+
<gml:featureMember>
23+
<ogr:extract_by_attribute_greater fid="polys.5">
24+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>3,2 6,1 6,-3 2,-1 2,2 3,2</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
25+
<ogr:name>elim</ogr:name>
26+
<ogr:intval>2</ogr:intval>
27+
<ogr:floatval>3.33</ogr:floatval>
28+
</ogr:extract_by_attribute_greater>
29+
</gml:featureMember>
30+
</ogr:FeatureCollection>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<GMLFeatureClassList>
2+
<GMLFeatureClass>
3+
<Name>extract_by_expression_not_null</Name>
4+
<ElementPath>extract_by_expression_not_null</ElementPath>
5+
<!--POLYGON-->
6+
<GeometryType>3</GeometryType>
7+
<SRSName>EPSG:4326</SRSName>
8+
<DatasetSpecificInfo>
9+
<FeatureCount>5</FeatureCount>
10+
<ExtentXMin>-1.00000</ExtentXMin>
11+
<ExtentXMax>10.00000</ExtentXMax>
12+
<ExtentYMin>-3.00000</ExtentYMin>
13+
<ExtentYMax>5.00000</ExtentYMax>
14+
</DatasetSpecificInfo>
15+
<PropertyDefn>
16+
<Name>name</Name>
17+
<ElementPath>name</ElementPath>
18+
<Type>String</Type>
19+
<Width>5</Width>
20+
</PropertyDefn>
21+
<PropertyDefn>
22+
<Name>intval</Name>
23+
<ElementPath>intval</ElementPath>
24+
<Type>Integer</Type>
25+
</PropertyDefn>
26+
<PropertyDefn>
27+
<Name>floatval</Name>
28+
<ElementPath>floatval</ElementPath>
29+
<Type>Real</Type>
30+
</PropertyDefn>
31+
</GMLFeatureClass>
32+
</GMLFeatureClassList>
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<ogr:FeatureCollection
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation=""
5+
xmlns:ogr="http://ogr.maptools.org/"
6+
xmlns:gml="http://www.opengis.net/gml">
7+
<gml:boundedBy>
8+
<gml:Box>
9+
<gml:coord><gml:X>-1</gml:X><gml:Y>-3</gml:Y></gml:coord>
10+
<gml:coord><gml:X>10</gml:X><gml:Y>5</gml:Y></gml:coord>
11+
</gml:Box>
12+
</gml:boundedBy>
13+
14+
<gml:featureMember>
15+
<ogr:extract_by_expression_not_null fid="polys.0">
16+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>-1,-1 -1,3 3,3 3,2 2,2 2,-1 -1,-1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
17+
<ogr:name>aaaaa</ogr:name>
18+
<ogr:intval>33</ogr:intval>
19+
<ogr:floatval>44.123456</ogr:floatval>
20+
</ogr:extract_by_expression_not_null>
21+
</gml:featureMember>
22+
<gml:featureMember>
23+
<ogr:extract_by_expression_not_null fid="polys.1">
24+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>5,5 6,4 4,4 5,5</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
25+
<ogr:name>Aaaaa</ogr:name>
26+
<ogr:intval>-33</ogr:intval>
27+
<ogr:floatval>0</ogr:floatval>
28+
</ogr:extract_by_expression_not_null>
29+
</gml:featureMember>
30+
<gml:featureMember>
31+
<ogr:extract_by_expression_not_null fid="polys.3">
32+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>6,1 10,1 10,-3 6,-3 6,1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs><gml:innerBoundaryIs><gml:LinearRing><gml:coordinates>7,0 7,-2 9,-2 9,0 7,0</gml:coordinates></gml:LinearRing></gml:innerBoundaryIs></gml:Polygon></ogr:geometryProperty>
33+
<ogr:name>ASDF</ogr:name>
34+
<ogr:intval>0</ogr:intval>
35+
</ogr:extract_by_expression_not_null>
36+
</gml:featureMember>
37+
<gml:featureMember>
38+
<ogr:extract_by_expression_not_null fid="polys.4">
39+
<ogr:intval>120</ogr:intval>
40+
<ogr:floatval>-100291.43213</ogr:floatval>
41+
</ogr:extract_by_expression_not_null>
42+
</gml:featureMember>
43+
<gml:featureMember>
44+
<ogr:extract_by_expression_not_null fid="polys.5">
45+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>3,2 6,1 6,-3 2,-1 2,2 3,2</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
46+
<ogr:name>elim</ogr:name>
47+
<ogr:intval>2</ogr:intval>
48+
<ogr:floatval>3.33</ogr:floatval>
49+
</ogr:extract_by_expression_not_null>
50+
</gml:featureMember>
51+
</ogr:FeatureCollection>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<GMLFeatureClassList>
2+
<GMLFeatureClass>
3+
<Name>extract_by_expression_null</Name>
4+
<ElementPath>extract_by_expression_null</ElementPath>
5+
<!--POLYGON-->
6+
<GeometryType>3</GeometryType>
7+
<SRSName>EPSG:4326</SRSName>
8+
<DatasetSpecificInfo>
9+
<FeatureCount>1</FeatureCount>
10+
<ExtentXMin>2.00000</ExtentXMin>
11+
<ExtentXMax>3.00000</ExtentXMax>
12+
<ExtentYMin>5.00000</ExtentYMin>
13+
<ExtentYMax>6.00000</ExtentYMax>
14+
</DatasetSpecificInfo>
15+
<PropertyDefn>
16+
<Name>name</Name>
17+
<ElementPath>name</ElementPath>
18+
<Type>String</Type>
19+
<Width>5</Width>
20+
</PropertyDefn>
21+
<PropertyDefn>
22+
<Name>floatval</Name>
23+
<ElementPath>floatval</ElementPath>
24+
<Type>Real</Type>
25+
</PropertyDefn>
26+
</GMLFeatureClass>
27+
</GMLFeatureClassList>

0 commit comments

Comments
 (0)