Skip to content
Permalink
Browse files
Cache only joined attributes without colliding names
Backport of #45170
  • Loading branch information
domi4484 authored and nyalldawson committed Nov 1, 2021
1 parent 60e2460 commit fe4dbff877acab775fa999f0bf0ad82a2ae23e30
Showing with 73 additions and 10 deletions.
  1. +30 −10 src/core/qgsvectorlayerjoinbuffer.cpp
  2. +43 −0 tests/src/core/testqgsvectorlayerjoinbuffer.cpp
@@ -76,12 +76,6 @@ bool QgsVectorLayerJoinBuffer::addJoin( const QgsVectorLayerJoinInfo &joinInfo )
return false;
}

//cache joined layer to virtual memory if specified by user
if ( joinInfo.isUsingMemoryCache() )
{
cacheJoinLayer( mVectorJoins.last() );
}

// Wait for notifications about changed fields in joined layer to propagate them.
// During project load the joined layers possibly do not exist yet so the connection will not be created,
// but then QgsProject makes sure to call createJoinCaches() which will do the connection.
@@ -91,9 +85,16 @@ bool QgsVectorLayerJoinBuffer::addJoin( const QgsVectorLayerJoinInfo &joinInfo )
connectJoinedLayer( vl );
}

mLayer->updateFields();

//cache joined layer to virtual memory if specified by user
if ( joinInfo.isUsingMemoryCache() )
{
cacheJoinLayer( mVectorJoins.last() );
}

locker.unlock();

emit joinedFieldsChanged();
return true;
}

@@ -170,9 +171,28 @@ void QgsVectorLayerJoinBuffer::cacheJoinLayer( QgsVectorLayerJoinInfo &joinInfo
}
else
{
QgsAttributes attrs2 = attrs;
attrs2.remove( joinFieldIndex ); // skip the join field to avoid double field names (fields often have the same name)
joinInfo.cachedAttributes.insert( key, attrs2 );
QgsAttributes attributesCache;
for ( int i = 0; i < attrs.size(); i++ )
{
if ( i == joinFieldIndex )
continue;

QString joinInfoPrefix = joinInfo.prefix();
if ( joinInfoPrefix.isNull() ) // Default prefix 'layerName_' used
joinInfoPrefix = QString( "%1_" ).arg( cacheLayer->name() );

// Joined field name
const QString joinFieldName = joinInfoPrefix + cacheLayer->fields().names().at( i );

// Check for name collisions
int fieldIndex = mLayer->fields().indexFromName( joinFieldName );
if ( fieldIndex >= 0
&& mLayer->fields().fieldOrigin( fieldIndex ) != QgsFields::OriginJoin )
continue;

attributesCache.append( attrs.at( i ) );
}
joinInfo.cachedAttributes.insert( key, attributesCache );
}
}
joinInfo.cacheDirty = false;
@@ -67,6 +67,7 @@ class TestVectorLayerJoinBuffer : public QObject
void testResolveReferences();
void testSignals();
void testChangeAttributeValues();
void testCollidingNameColumnCached();

private:
QgsProject mProject;
@@ -840,6 +841,48 @@ void TestVectorLayerJoinBuffer::testChangeAttributeValues()

}

void TestVectorLayerJoinBuffer::testCollidingNameColumnCached()
{
mProject.clear();
QgsVectorLayer *vlA = new QgsVectorLayer( QStringLiteral( "Point?field=id_a:integer&field=name" ), QStringLiteral( "cacheA" ), QStringLiteral( "memory" ) );
QVERIFY( vlA->isValid() );
QgsVectorLayer *vlB = new QgsVectorLayer( QStringLiteral( "Point?field=id_b:integer&field=name&field=value_b&field=value_c" ), QStringLiteral( "cacheB" ), QStringLiteral( "memory" ) );
QVERIFY( vlB->isValid() );
mProject.addMapLayer( vlA );
mProject.addMapLayer( vlB );

QgsFeature fA1( vlA->dataProvider()->fields(), 1 );
fA1.setAttribute( QStringLiteral( "id_a" ), 1 );
fA1.setAttribute( QStringLiteral( "name" ), QStringLiteral( "name_a" ) );

vlA->dataProvider()->addFeatures( QgsFeatureList() << fA1 );

QgsFeature fB1( vlB->dataProvider()->fields(), 1 );
fB1.setAttribute( QStringLiteral( "id_b" ), 1 );
fB1.setAttribute( QStringLiteral( "name" ), QStringLiteral( "name_b" ) );
fB1.setAttribute( QStringLiteral( "value_b" ), QStringLiteral( "value_b" ) );
fB1.setAttribute( QStringLiteral( "value_c" ), QStringLiteral( "value_c" ) );

vlB->dataProvider()->addFeatures( QgsFeatureList() << fB1 );

QgsVectorLayerJoinInfo joinInfo;
joinInfo.setTargetFieldName( QStringLiteral( "id_a" ) );
joinInfo.setJoinLayer( vlB );
joinInfo.setJoinFieldName( QStringLiteral( "id_b" ) );
joinInfo.setPrefix( QStringLiteral( "" ) );
joinInfo.setEditable( true );
joinInfo.setUpsertOnEdit( false );
joinInfo.setUsingMemoryCache( true );
vlA->addJoin( joinInfo );

QgsFeatureIterator fi1 = vlA->getFeatures();
fi1.nextFeature( fA1 );
QCOMPARE( fA1.fields().names(), QStringList( {"id_a", "name", "value_b", "value_c"} ) );
QCOMPARE( fA1.attribute( "id_a" ).toInt(), 1 );
QCOMPARE( fA1.attribute( "name" ).toString(), QStringLiteral( "name_a" ) );
QCOMPARE( fA1.attribute( "value_b" ).toString(), QStringLiteral( "value_b" ) );
QCOMPARE( fA1.attribute( "value_c" ).toString(), QStringLiteral( "value_c" ) );
}

QGSTEST_MAIN( TestVectorLayerJoinBuffer )
#include "testqgsvectorlayerjoinbuffer.moc"

0 comments on commit fe4dbff

Please sign in to comment.