Skip to content

Commit 1f3ee05

Browse files
committed
[processing] Always report errors if features cannot be written
to a destination Before we silently ignored these - now algorithms will automatically push errors to the log if a feature cannot be written to a sink (no changes to algorithms or special handling required)
1 parent 84d2443 commit 1f3ee05

File tree

3 files changed

+87
-3
lines changed

3 files changed

+87
-3
lines changed

python/core/processing/qgsprocessingutils.sip.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ Returns an expression context scope suitable for this source.
283283

284284

285285

286+
286287
/************************************************************************
287288
* This file has been generated automatically from *
288289
* *

src/core/processing/qgsprocessingutils.cpp

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ QgsFeatureSink *QgsProcessingUtils::createFeatureSink( QString &destination, Qgs
388388
destination = layer->id();
389389

390390
// this is a factory, so we need to return a proxy
391-
std::unique_ptr< QgsProxyFeatureSink > sink( new QgsProxyFeatureSink( layer->dataProvider() ) );
391+
std::unique_ptr< QgsProcessingFeatureSink > sink( new QgsProcessingFeatureSink( layer->dataProvider(), destination, context ) );
392392
context.temporaryLayerStore()->addMapLayer( layer.release() );
393393

394394
return sink.release();
@@ -415,7 +415,7 @@ QgsFeatureSink *QgsProcessingUtils::createFeatureSink( QString &destination, Qgs
415415
throw QgsProcessingException( QObject::tr( "Could not create layer %1: %2" ).arg( destination, writer->errorMessage() ) );
416416
}
417417
destination = finalFileName;
418-
return writer.release();
418+
return new QgsProcessingFeatureSink( writer.release(), destination, context, true );
419419
}
420420
else
421421
{
@@ -434,7 +434,7 @@ QgsFeatureSink *QgsProcessingUtils::createFeatureSink( QString &destination, Qgs
434434
destination = layer->id();
435435

436436
context.temporaryLayerStore()->addMapLayer( layer.release() );
437-
return exporter.release();
437+
return new QgsProcessingFeatureSink( exporter.release(), destination, context, true );
438438
}
439439
}
440440
return nullptr;
@@ -750,3 +750,44 @@ QgsExpressionContextScope *QgsProcessingFeatureSource::createExpressionContextSc
750750
}
751751
return expressionContextScope;
752752
}
753+
754+
755+
//
756+
// QgsProcessingFeatureSink
757+
//
758+
QgsProcessingFeatureSink::QgsProcessingFeatureSink( QgsFeatureSink *originalSink, const QString &sinkName, QgsProcessingContext &context, bool ownsOriginalSink )
759+
: QgsProxyFeatureSink( originalSink )
760+
, mContext( context )
761+
, mSinkName( sinkName )
762+
, mOwnsSink( ownsOriginalSink )
763+
{}
764+
765+
QgsProcessingFeatureSink::~QgsProcessingFeatureSink()
766+
{
767+
if ( mOwnsSink )
768+
delete destinationSink();
769+
}
770+
771+
bool QgsProcessingFeatureSink::addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags )
772+
{
773+
bool result = QgsProxyFeatureSink::addFeature( feature, flags );
774+
if ( !result )
775+
mContext.feedback()->reportError( QObject::tr( "Feature could not be written to %1" ).arg( mSinkName ) );
776+
return result;
777+
}
778+
779+
bool QgsProcessingFeatureSink::addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags )
780+
{
781+
bool result = QgsProxyFeatureSink::addFeatures( features, flags );
782+
if ( !result )
783+
mContext.feedback()->reportError( QObject::tr( "%1 feature(s) could not be written to %2" ).arg( features.count() ).arg( mSinkName ) );
784+
return result;
785+
}
786+
787+
bool QgsProcessingFeatureSink::addFeatures( QgsFeatureIterator &iterator, QgsFeatureSink::Flags flags )
788+
{
789+
bool result = !QgsProxyFeatureSink::addFeatures( iterator, flags );
790+
if ( !result )
791+
mContext.feedback()->reportError( QObject::tr( "Features could not be written to %2" ).arg( mSinkName ) );
792+
return result;
793+
}

src/core/processing/qgsprocessingutils.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,48 @@ class CORE_EXPORT QgsProcessingFeatureSource : public QgsFeatureSource
336336

337337
};
338338

339+
#ifndef SIP_RUN
340+
341+
/**
342+
* \class QgsProcessingFeatureSink
343+
* \ingroup core
344+
* QgsProxyFeatureSink subclass which reports feature addition errors to a QgsProcessingContext.
345+
* \since QGIS 3.0
346+
* \note Not available in Python bindings.
347+
*/
348+
class CORE_EXPORT QgsProcessingFeatureSink : public QgsProxyFeatureSink
349+
{
350+
public:
351+
352+
353+
/**
354+
* Constructor for QgsProcessingFeatureSink, accepting an original feature sink \a originalSink
355+
* and processing \a context. Any added features are added to the \a originalSink, with feature
356+
* writing errors being reports to \a context.
357+
*
358+
* The \a context must exist for the lifetime of this object.
359+
*
360+
* The \a sinkName is used to identify the destination sink when reporting errors.
361+
*
362+
* Ownership of \a originalSink is dictated by \a ownsOriginalSource. If \a ownsOriginalSink is false,
363+
* ownership is not transferred, and callers must ensure that \a originalSink exists for the lifetime of this object.
364+
* If \a ownsOriginalSink is true, then this object will take ownership of \a originalSink.
365+
*/
366+
QgsProcessingFeatureSink( QgsFeatureSink *originalSink, const QString &sinkName, QgsProcessingContext &context, bool ownsOriginalSink = false );
367+
~QgsProcessingFeatureSink();
368+
bool addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags = nullptr ) override;
369+
bool addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags = nullptr ) override;
370+
bool addFeatures( QgsFeatureIterator &iterator, QgsFeatureSink::Flags flags = nullptr ) override;
371+
372+
private:
373+
374+
QgsProcessingContext &mContext;
375+
QString mSinkName;
376+
bool mOwnsSink = false;
377+
378+
};
379+
#endif
380+
339381
#endif // QGSPROCESSINGUTILS_H
340382

341383

0 commit comments

Comments
 (0)