Skip to content

Commit

Permalink
[processing] Ensure algorithms which add attributes to features
Browse files Browse the repository at this point in the history
always add a consistent amount of attributes regardless of the
code paths taken

Some algorithms were adding features to data providers with
different number of attributes vs the layer's fields - this is
not supported and depending on the data provider will have
different (bad) results.
  • Loading branch information
nyalldawson committed Feb 15, 2018
1 parent a811036 commit 12fcfac
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 1 deletion.
9 changes: 8 additions & 1 deletion python/plugins/processing/algs/qgis/ExportGeometryInfo.py
Expand Up @@ -30,7 +30,8 @@
from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtCore import QVariant

from qgis.core import (QgsCoordinateTransform,
from qgis.core import (NULL,
QgsCoordinateTransform,
QgsField,
QgsFields,
QgsWkbTypes,
Expand Down Expand Up @@ -148,6 +149,12 @@ def processAlgorithm(self, parameters, context, feedback):
else:
attrs.extend(self.line_attributes(inGeom))

# ensure consistent count of attributes - otherwise null
# geometry features will have incorrect attribute length
# and provider may reject them
if len(attrs) < len(fields):
attrs += [NULL] * (len(fields) - len(attrs))

outFeat.setAttributes(attrs)
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)

Expand Down
14 changes: 14 additions & 0 deletions python/plugins/processing/algs/qgis/SpatialJoinSummary.py
Expand Up @@ -270,6 +270,13 @@ def addField(original, stat, type):

if not f.hasGeometry():
if not discard_nomatch:
# ensure consistent count of attributes - otherwise non matching
# features will have incorrect attribute length
# and provider may reject them
attrs = f.attributes()
if len(attrs) < len(out_fields):
attrs += [NULL] * (len(out_fields) - len(attrs))
f.setAttributes(attrs)
sink.addFeature(f, QgsFeatureSink.FastInsert)
continue

Expand Down Expand Up @@ -302,6 +309,13 @@ def addField(original, stat, type):
if discard_nomatch:
continue
else:
# ensure consistent count of attributes - otherwise non matching
# features will have incorrect attribute length
# and provider may reject them
attrs = f.attributes()
if len(attrs) < len(out_fields):
attrs += [NULL] * (len(out_fields) - len(attrs))
f.setAttributes(attrs)
sink.addFeature(f, QgsFeatureSink.FastInsert)
else:
attrs = f.attributes()
Expand Down
9 changes: 9 additions & 0 deletions src/analysis/processing/qgsalgorithmboundingbox.cpp
Expand Up @@ -86,6 +86,15 @@ QgsFeature QgsBoundingBoxAlgorithm::processFeature( const QgsFeature &feature, Q
<< bounds.perimeter();
f.setAttributes( attrs );
}
else
{
QgsAttributes attrs = f.attributes();
attrs << QVariant()
<< QVariant()
<< QVariant()
<< QVariant();
f.setAttributes( attrs );
}
return f;
}

Expand Down
7 changes: 7 additions & 0 deletions src/analysis/processing/qgsalgorithmconvexhull.cpp
Expand Up @@ -85,6 +85,13 @@ QgsFeature QgsConvexHullAlgorithm::processFeature( const QgsFeature &feature, Qg
<< outputGeometry.constGet()->perimeter();
f.setAttributes( attrs );
}
else
{
QgsAttributes attrs = f.attributes();
attrs << QVariant()
<< QVariant();
f.setAttributes( attrs );
}
}
return f;
}
Expand Down
Expand Up @@ -100,6 +100,13 @@ QgsFeature QgsMinimumEnclosingCircleAlgorithm::processFeature( const QgsFeature
<< M_PI *radius *radius;
f.setAttributes( attrs );
}
else
{
QgsAttributes attrs = f.attributes();
attrs << QVariant()
<< QVariant();
f.setAttributes( attrs );
}
return f;
}

Expand Down
10 changes: 10 additions & 0 deletions src/analysis/processing/qgsalgorithmorientedminimumboundingbox.cpp
Expand Up @@ -96,6 +96,16 @@ QgsFeature QgsOrientedMinimumBoundingBoxAlgorithm::processFeature( const QgsFeat
<< 2 * width + 2 * height;
f.setAttributes( attrs );
}
else
{
QgsAttributes attrs = f.attributes();
attrs << QVariant()
<< QVariant()
<< QVariant()
<< QVariant()
<< QVariant();
f.setAttributes( attrs );
}
return f;
}

Expand Down

0 comments on commit 12fcfac

Please sign in to comment.