Skip to content

Commit 1c402ef

Browse files
committed
Implements upsertOnEdit option
1 parent db11248 commit 1c402ef

File tree

4 files changed

+93
-0
lines changed

4 files changed

+93
-0
lines changed

src/core/qgsvectorlayer.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -947,7 +947,10 @@ bool QgsVectorLayer::addFeature( QgsFeature &feature, Flags )
947947
bool success = mEditBuffer->addFeature( feature );
948948

949949
if ( success )
950+
{
950951
updateExtents();
952+
success = addFeaturesToJoinedLayers( QgsFeatureList() << feature );
953+
}
951954

952955
return success;
953956
}
@@ -2633,9 +2636,66 @@ bool QgsVectorLayer::addFeatures( QgsFeatureList &features, Flags )
26332636
bool res = mEditBuffer->addFeatures( features );
26342637
updateExtents();
26352638

2639+
if ( res )
2640+
res = addFeaturesToJoinedLayers( features );
2641+
26362642
return res;
26372643
}
26382644

2645+
bool QgsVectorLayer::addFeaturesToJoinedLayers( QgsFeatureList &features, Flags )
2646+
{
2647+
// try to add/update a feature in each joined layer
2648+
Q_FOREACH ( const QgsVectorLayerJoinInfo &info, vectorJoins() )
2649+
{
2650+
QgsVectorLayer *joinLayer = info.joinLayer();
2651+
2652+
if ( joinLayer && joinLayer->isEditable() && info.isEditable() && info.isUpsertOnEdit() )
2653+
{
2654+
QgsFeatureList joinFeatures;
2655+
2656+
Q_FOREACH ( const QgsFeature &feature, features )
2657+
{
2658+
const QgsFeature joinFeature = info.extractJoinedFeature( feature );
2659+
2660+
// we don't want to add a new feature in joined layer when the id
2661+
// column value yet exist, we just want to update the existing one
2662+
const QVariant idFieldValue = feature.attribute( info.targetFieldName() );
2663+
const QString filter = QgsExpression::createFieldEqualityExpression( info.joinFieldName(), idFieldValue.toString() );
2664+
2665+
QgsFeatureRequest request;
2666+
request.setFilterExpression( filter );
2667+
request.setLimit( 1 );
2668+
2669+
QgsFeatureIterator it = info.joinLayer()->getFeatures( request );
2670+
QgsFeature existingFeature;
2671+
it.nextFeature( existingFeature );
2672+
2673+
if ( existingFeature.isValid() )
2674+
{
2675+
const QStringList *subsetFields = info.joinFieldNamesSubset();
2676+
if ( subsetFields )
2677+
{
2678+
Q_FOREACH ( const QString &field, *subsetFields )
2679+
existingFeature.setAttribute( field, joinFeature.attribute( field ) );
2680+
}
2681+
else
2682+
{
2683+
Q_FOREACH ( const QgsField &field, joinFeature.fields() )
2684+
existingFeature.setAttribute( field.name(), joinFeature.attribute( field.name() ) );
2685+
}
2686+
2687+
joinLayer->updateFeature( existingFeature );
2688+
}
2689+
else
2690+
joinFeatures << joinFeature;
2691+
}
2692+
2693+
joinLayer->addFeatures( joinFeatures );
2694+
}
2695+
}
2696+
2697+
return true;
2698+
}
26392699

26402700
void QgsVectorLayer::setCoordinateSystem()
26412701
{

src/core/qgsvectorlayer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1932,6 +1932,8 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
19321932
//! Read simple labeling from layer's custom properties (QGIS 2.x projects)
19331933
QgsAbstractVectorLayerLabeling *readLabelingFromCustomProperties();
19341934

1935+
bool addFeaturesToJoinedLayers( QgsFeatureList &features, Flags flags = 0 );
1936+
19351937
#ifdef SIP_RUN
19361938
QgsVectorLayer( const QgsVectorLayer &rhs );
19371939
#endif

src/core/qgsvectorlayerjoininfo.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,26 @@ void QgsVectorLayerJoinInfo::setEditable( bool enabled )
4444
setUpsertOnEdit( false );
4545
}
4646
}
47+
48+
QgsFeature QgsVectorLayerJoinInfo::extractJoinedFeature( const QgsFeature &feature ) const
49+
{
50+
QgsFeature joinFeature;
51+
52+
if ( joinLayer() )
53+
{
54+
const QVariant idFieldValue = feature.attribute( targetFieldName() );
55+
joinFeature.initAttributes( joinLayer()->fields().count() );
56+
joinFeature.setFields( joinLayer()->fields() );
57+
joinFeature.setAttribute( joinFieldName(), idFieldValue );
58+
59+
Q_FOREACH ( const QgsField &field, joinFeature.fields() )
60+
{
61+
const QString prefixedName = prefixedFieldName( field );
62+
63+
if ( feature.fieldNameIndex( prefixedName ) != -1 )
64+
joinFeature.setAttribute( field.name(), feature.attribute( prefixedName ) );
65+
}
66+
}
67+
68+
return joinFeature;
69+
}

src/core/qgsvectorlayerjoininfo.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,14 @@ class CORE_EXPORT QgsVectorLayerJoinInfo
123123
*/
124124
QString prefixedFieldName( const QgsField &field ) const;
125125

126+
/** Extract the join feature from the target feature for the current
127+
* join layer information.
128+
* \param feature A feature from the target layer
129+
* \returns the corresponding joined feature
130+
* \since QGIS 3.0
131+
*/
132+
QgsFeature extractJoinedFeature( const QgsFeature &feature ) const;
133+
126134
bool operator==( const QgsVectorLayerJoinInfo &other ) const
127135
{
128136
return mTargetFieldName == other.mTargetFieldName &&

0 commit comments

Comments
 (0)