Skip to content

Commit

Permalink
Merge pull request #452 from minorua/tablejoin
Browse files Browse the repository at this point in the history
Some fixes for table join. Merged for wider testing.
  • Loading branch information
NathanW2 committed Apr 1, 2013
2 parents 9247262 + 30c343c commit 5c028f8
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 25 deletions.
16 changes: 12 additions & 4 deletions src/app/qgsvectorlayerproperties.cpp
Expand Up @@ -451,7 +451,7 @@ void QgsVectorLayerProperties::apply()
{
if ( layer->dataProvider()->capabilities() & QgsVectorDataProvider::SetEncoding )
{
layer->dataProvider()->setEncoding( cboProviderEncoding->currentText() );
layer->setProviderEncoding( cboProviderEncoding->currentText() );
}
}

Expand Down Expand Up @@ -844,15 +844,23 @@ void QgsVectorLayerProperties::addJoinToTreeWidget( const QgsVectorJoinInfo& joi
QTreeWidgetItem* joinItem = new QTreeWidgetItem();

QgsVectorLayer* joinLayer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( join.joinLayerId ) );
if ( !joinLayer )
if ( !layer || !joinLayer )
{
return;
}

joinItem->setText( 0, joinLayer->name() );
joinItem->setData( 0, Qt::UserRole, join.joinLayerId );
joinItem->setText( 1, join.joinFieldName );
joinItem->setText( 2, join.targetFieldName );

if ( join.joinFieldName.isEmpty() && join.joinFieldIndex >= 0 && join.joinFieldIndex < joinLayer->pendingFields().count() )
joinItem->setText( 1, joinLayer->pendingFields().field( join.joinFieldIndex ).name() ); //for compatibility with 1.x
else
joinItem->setText( 1, join.joinFieldName );

if ( join.targetFieldName.isEmpty() && join.targetFieldIndex >= 0 && join.targetFieldIndex < layer->pendingFields().count() )
joinItem->setText( 2, layer->pendingFields().field( join.targetFieldIndex ).name() ); //for compatibility with 1.x
else
joinItem->setText( 2, join.targetFieldName );

mJoinTreeWidget->addTopLevelItem( joinItem );
}
Expand Down
1 change: 1 addition & 0 deletions src/core/qgsproject.cpp
Expand Up @@ -707,6 +707,7 @@ QPair< bool, QList<QDomNode> > QgsProject::_getMapLayers( QDomDocument const &do
for ( ; vIt != vLayerList.end(); ++vIt )
{
vIt->first->createJoinCaches();
vIt->first->updateFields();
//for old symbology, it is necessary to read the symbology again after having the complete field map
if ( !vIt->first->isUsingRendererV2() )
{
Expand Down
3 changes: 2 additions & 1 deletion src/core/qgsvectorlayer.cpp
Expand Up @@ -1320,6 +1320,7 @@ void QgsVectorLayer::setProviderEncoding( const QString& encoding )
if ( mDataProvider )
{
mDataProvider->setEncoding( encoding );
updateFields();
}
}

Expand Down Expand Up @@ -3855,7 +3856,7 @@ void QgsVectorLayer::updateFields()
mEditBuffer->updateFields( mUpdatedFields );

// joined fields
if ( mJoinBuffer->containsJoins() )
if ( mJoinBuffer && mJoinBuffer->containsJoins() )
mJoinBuffer->updateFields( mUpdatedFields );
}

Expand Down
15 changes: 8 additions & 7 deletions src/core/qgsvectorlayer.h
Expand Up @@ -135,9 +135,10 @@ struct CORE_EXPORT QgsVectorJoinInfo
*/
QHash< QString, QgsAttributes> cachedAttributes;

// the following are temporaries, assigned by QgsVectorLayerJoinBuffer::updateFields()
mutable int tmpTargetField;
mutable int tmpJoinField;
/**Join field index in the target layer. For backward compatibility with 1.x (x>=7)*/
int targetFieldIndex;
/**Join field index in the source layer. For backward compatibility with 1.x (x>=7)*/
int joinFieldIndex;
};


Expand Down Expand Up @@ -829,6 +830,10 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
@note public and static from version 1.4 */
static void drawVertexMarker( double x, double y, QPainter& p, QgsVectorLayer::VertexMarkerType type, int vertexSize );

/** Assembles mUpdatedFields considering provider fields, joined fields and added fields
@note added in 1.7 */
void updateFields();

/** Caches joined attributes if required (and not already done)
@note added in 1.7 */
void createJoinCaches();
Expand Down Expand Up @@ -971,10 +976,6 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
/** Stop version 2 renderer and selected renderer (if required) */
void stopRendererV2( QgsRenderContext& rendererContext, QgsSingleSymbolRendererV2* selRenderer );

/** Assembles mUpdatedFields considering provider fields, joined fields and added fields
@note added in 1.7 */
void updateFields();

/**Registers label and diagram layer
@param rendererContext render context
@param attributes attributes needed for labeling and diagrams will be added to the list
Expand Down
25 changes: 21 additions & 4 deletions src/core/qgsvectorlayerfeatureiterator.cpp
Expand Up @@ -310,10 +310,21 @@ void QgsVectorLayerFeatureIterator::prepareJoins()
{
FetchJoinInfo info;
info.joinInfo = joinInfo;
info.indexOffset = *attIt - sourceLayerIndex;
info.joinLayer = joinLayer;
info.targetField = fields.indexFromName( joinInfo->targetFieldName );
info.joinField = joinLayer->pendingFields().indexFromName( joinInfo->joinFieldName );

if ( joinInfo->targetFieldName.isEmpty() )
info.targetField = joinInfo->targetFieldIndex; //for compatibility with 1.x
else
info.targetField = fields.indexFromName( joinInfo->targetFieldName );

if ( joinInfo->joinFieldName.isEmpty() )
info.joinField = joinInfo->joinFieldIndex; //for compatibility with 1.x
else
info.joinField = joinLayer->pendingFields().indexFromName( joinInfo->joinFieldName );

info.indexOffset = *attIt - sourceLayerIndex;
if ( info.joinField < sourceLayerIndex )
info.indexOffset++;

// for joined fields, we always need to request the targetField from the provider too
if ( !fetchAttributes.contains( info.targetField ) )
Expand Down Expand Up @@ -389,7 +400,13 @@ void QgsVectorLayerFeatureIterator::FetchJoinInfo::addJoinedAttributesDirect( Qg
subsetString.append( " AND " );
}

subsetString.append( "\"" + joinInfo->joinFieldName + "\"" + " = " + "\"" + joinValue.toString() + "\"" );
QString joinFieldName;
if ( joinInfo->joinFieldName.isEmpty() && joinInfo->joinFieldIndex >= 0 && joinInfo->joinFieldIndex < joinLayer->pendingFields().count() )
joinFieldName = joinLayer->pendingFields().field( joinInfo->joinFieldIndex ).name(); // for compatibility with 1.x
else
joinFieldName = joinInfo->joinFieldName;

subsetString.append( "\"" + joinFieldName + "\"" + " = " + "\"" + joinValue.toString() + "\"" );
joinLayer->dataProvider()->setSubsetString( subsetString, false );

// select (no geometry)
Expand Down
37 changes: 28 additions & 9 deletions src/core/qgsvectorlayerjoinbuffer.cpp
Expand Up @@ -63,7 +63,11 @@ void QgsVectorLayerJoinBuffer::cacheJoinLayer( QgsVectorJoinInfo& joinInfo )
QgsVectorLayer* cacheLayer = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinInfo.joinLayerId ) );
if ( cacheLayer )
{
int joinFieldIndex = cacheLayer->pendingFields().indexFromName( joinInfo.joinFieldName );
int joinFieldIndex;
if ( joinInfo.joinFieldName.isEmpty() )
joinFieldIndex = joinInfo.joinFieldIndex; //for compatibility with 1.x
else
joinFieldIndex = cacheLayer->pendingFields().indexFromName( joinInfo.joinFieldName );

joinInfo.cachedAttributes.clear();

Expand All @@ -88,15 +92,17 @@ void QgsVectorLayerJoinBuffer::updateFields( QgsFields& fields )
continue;
}

joinIt->tmpTargetField = fields.indexFromName( joinIt->targetFieldName );

const QgsFields& joinFields = joinLayer->pendingFields();
joinIt->tmpJoinField = joinFields.indexFromName( joinIt->joinFieldName );
QString joinFieldName;
if ( joinIt->joinFieldName.isEmpty() && joinIt->joinFieldIndex >= 0 && joinIt->joinFieldIndex < joinFields.count() )
joinFieldName = joinFields.field( joinIt->joinFieldIndex ).name(); //for compatibility with 1.x
else
joinFieldName = joinIt->joinFieldName;

for ( int idx = 0; idx < joinFields.count(); ++idx )
{
//skip the join field to avoid double field names (fields often have the same name)
if ( joinFields[idx].name() != joinIt->joinFieldName )
if ( joinFields[idx].name() != joinFieldName )
{
QgsField f = joinFields[idx];
f.setName( joinLayer->name() + "_" + f.name() );
Expand Down Expand Up @@ -124,9 +130,18 @@ void QgsVectorLayerJoinBuffer::writeXml( QDomNode& layer_node, QDomDocument& doc
for ( ; joinIt != mVectorJoins.constEnd(); ++joinIt )
{
QDomElement joinElem = document.createElement( "join" );
joinElem.setAttribute( "targetFieldName", joinIt->targetFieldName );

if ( joinIt->targetFieldName.isEmpty() )
joinElem.setAttribute( "targetField", joinIt->targetFieldIndex ); //for compatibility with 1.x
else
joinElem.setAttribute( "targetFieldName", joinIt->targetFieldName );

joinElem.setAttribute( "joinLayerId", joinIt->joinLayerId );
joinElem.setAttribute( "joinFieldName", joinIt->joinFieldName );
if ( joinIt->joinFieldName.isEmpty() )
joinElem.setAttribute( "joinField", joinIt->joinFieldIndex ); //for compatibility with 1.x
else
joinElem.setAttribute( "joinFieldName", joinIt->joinFieldName );

joinElem.setAttribute( "memoryCache", !joinIt->cachedAttributes.isEmpty() );
vectorJoinsElem.appendChild( joinElem );
}
Expand All @@ -143,10 +158,14 @@ void QgsVectorLayerJoinBuffer::readXml( const QDomNode& layer_node )
{
QDomElement infoElem = joinList.at( i ).toElement();
QgsVectorJoinInfo info;
info.joinFieldName = infoElem.attribute( "joinFieldName" ); // TODO[MD]: compatibility with 1.x?
info.joinFieldName = infoElem.attribute( "joinFieldName" );
info.joinLayerId = infoElem.attribute( "joinLayerId" );
info.targetFieldName = infoElem.attribute( "targetFieldName" ); // TODO[MD]: compatibility with 1.x?
info.targetFieldName = infoElem.attribute( "targetFieldName" );
info.memoryCache = infoElem.attribute( "memoryCache" ).toInt();

info.joinFieldIndex = infoElem.attribute( "joinField" ).toInt(); //for compatibility with 1.x
info.targetFieldIndex = infoElem.attribute( "targetField" ).toInt(); //for compatibility with 1.x

addJoin( info );
}
}
Expand Down

0 comments on commit 5c028f8

Please sign in to comment.