Skip to content

Commit

Permalink
Implements upsertOnEdit option
Browse files Browse the repository at this point in the history
  • Loading branch information
pblottiere committed Aug 28, 2017
1 parent db11248 commit 1c402ef
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 0 deletions.
60 changes: 60 additions & 0 deletions src/core/qgsvectorlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -947,7 +947,10 @@ bool QgsVectorLayer::addFeature( QgsFeature &feature, Flags )
bool success = mEditBuffer->addFeature( feature );

if ( success )
{
updateExtents();
success = addFeaturesToJoinedLayers( QgsFeatureList() << feature );
}

return success;
}
Expand Down Expand Up @@ -2633,9 +2636,66 @@ bool QgsVectorLayer::addFeatures( QgsFeatureList &features, Flags )
bool res = mEditBuffer->addFeatures( features );
updateExtents();

if ( res )
res = addFeaturesToJoinedLayers( features );

return res;
}

bool QgsVectorLayer::addFeaturesToJoinedLayers( QgsFeatureList &features, Flags )
{
// try to add/update a feature in each joined layer
Q_FOREACH ( const QgsVectorLayerJoinInfo &info, vectorJoins() )
{
QgsVectorLayer *joinLayer = info.joinLayer();

if ( joinLayer && joinLayer->isEditable() && info.isEditable() && info.isUpsertOnEdit() )
{
QgsFeatureList joinFeatures;

Q_FOREACH ( const QgsFeature &feature, features )
{
const QgsFeature joinFeature = info.extractJoinedFeature( feature );

// we don't want to add a new feature in joined layer when the id
// column value yet exist, we just want to update the existing one
const QVariant idFieldValue = feature.attribute( info.targetFieldName() );
const QString filter = QgsExpression::createFieldEqualityExpression( info.joinFieldName(), idFieldValue.toString() );

QgsFeatureRequest request;
request.setFilterExpression( filter );
request.setLimit( 1 );

QgsFeatureIterator it = info.joinLayer()->getFeatures( request );
QgsFeature existingFeature;
it.nextFeature( existingFeature );

if ( existingFeature.isValid() )
{
const QStringList *subsetFields = info.joinFieldNamesSubset();
if ( subsetFields )
{
Q_FOREACH ( const QString &field, *subsetFields )
existingFeature.setAttribute( field, joinFeature.attribute( field ) );
}
else
{
Q_FOREACH ( const QgsField &field, joinFeature.fields() )
existingFeature.setAttribute( field.name(), joinFeature.attribute( field.name() ) );
}

joinLayer->updateFeature( existingFeature );
}
else
joinFeatures << joinFeature;
}

joinLayer->addFeatures( joinFeatures );
}
}

return true;
}

void QgsVectorLayer::setCoordinateSystem()
{
Expand Down
2 changes: 2 additions & 0 deletions src/core/qgsvectorlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -1932,6 +1932,8 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
//! Read simple labeling from layer's custom properties (QGIS 2.x projects)
QgsAbstractVectorLayerLabeling *readLabelingFromCustomProperties();

bool addFeaturesToJoinedLayers( QgsFeatureList &features, Flags flags = 0 );

#ifdef SIP_RUN
QgsVectorLayer( const QgsVectorLayer &rhs );
#endif
Expand Down
23 changes: 23 additions & 0 deletions src/core/qgsvectorlayerjoininfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,26 @@ void QgsVectorLayerJoinInfo::setEditable( bool enabled )
setUpsertOnEdit( false );
}
}

QgsFeature QgsVectorLayerJoinInfo::extractJoinedFeature( const QgsFeature &feature ) const
{
QgsFeature joinFeature;

if ( joinLayer() )
{
const QVariant idFieldValue = feature.attribute( targetFieldName() );
joinFeature.initAttributes( joinLayer()->fields().count() );
joinFeature.setFields( joinLayer()->fields() );
joinFeature.setAttribute( joinFieldName(), idFieldValue );

Q_FOREACH ( const QgsField &field, joinFeature.fields() )
{
const QString prefixedName = prefixedFieldName( field );

if ( feature.fieldNameIndex( prefixedName ) != -1 )
joinFeature.setAttribute( field.name(), feature.attribute( prefixedName ) );
}
}

return joinFeature;
}
8 changes: 8 additions & 0 deletions src/core/qgsvectorlayerjoininfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,14 @@ class CORE_EXPORT QgsVectorLayerJoinInfo
*/
QString prefixedFieldName( const QgsField &field ) const;

/** Extract the join feature from the target feature for the current
* join layer information.
* \param feature A feature from the target layer
* \returns the corresponding joined feature
* \since QGIS 3.0
*/
QgsFeature extractJoinedFeature( const QgsFeature &feature ) const;

bool operator==( const QgsVectorLayerJoinInfo &other ) const
{
return mTargetFieldName == other.mTargetFieldName &&
Expand Down

0 comments on commit 1c402ef

Please sign in to comment.