Skip to content

Commit a80117b

Browse files
author
Hugo Mercier
authored
Merge pull request #7724 from agiudiceandrea/patch-fix-19636
Fix "Filter on joined fields": add geometry for spatial layer and handle special field/layer names
2 parents 7721694 + 1971f8a commit a80117b

File tree

2 files changed

+32
-14
lines changed

2 files changed

+32
-14
lines changed

src/core/qgsvirtuallayerdefinitionutils.cpp

+9-5
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ QgsVirtualLayerDefinition QgsVirtualLayerDefinitionUtils::fromJoinedLayer( QgsVe
2828
QStringList leftJoins;
2929
QStringList columns;
3030

31+
// add the geometry column if the layer is spatial
32+
if ( layer->isSpatial() )
33+
columns << "t.geometry";
34+
3135
// look for the uid
3236
QgsFields fields = layer->dataProvider()->fields();
3337
{
@@ -51,7 +55,7 @@ QgsVirtualLayerDefinition QgsVirtualLayerDefinitionUtils::fromJoinedLayer( QgsVe
5155
const QgsFields providerFields = layer->dataProvider()->fields();
5256
for ( const auto &f : providerFields )
5357
{
54-
columns << "t." + f.name();
58+
columns << "t.\"" + f.name() + "\"";
5559
}
5660

5761
int joinIdx = 0;
@@ -63,12 +67,12 @@ QgsVirtualLayerDefinition QgsVirtualLayerDefinitionUtils::fromJoinedLayer( QgsVe
6367
continue;
6468
QString prefix = join.prefix().isEmpty() ? joinedLayer->name() + "_" : join.prefix();
6569

66-
leftJoins << QStringLiteral( "LEFT JOIN %1 AS %2 ON t.\"%5\"=%2.\"%3\"" ).arg( joinedLayer->id(), joinName, join.joinFieldName(), join.targetFieldName() );
70+
leftJoins << QStringLiteral( "LEFT JOIN \"%1\" AS %2 ON t.\"%5\"=%2.\"%3\"" ).arg( joinedLayer->id(), joinName, join.joinFieldName(), join.targetFieldName() );
6771
if ( join.joinFieldNamesSubset() )
6872
{
6973
Q_FOREACH ( const QString &f, *join.joinFieldNamesSubset() )
7074
{
71-
columns << joinName + "." + f + " AS " + prefix + f;
75+
columns << joinName + ".\"" + f + "\" AS \"" + prefix + f + "\"";
7276
}
7377
}
7478
else
@@ -78,12 +82,12 @@ QgsVirtualLayerDefinition QgsVirtualLayerDefinitionUtils::fromJoinedLayer( QgsVe
7882
{
7983
if ( f.name() == join.joinFieldName() )
8084
continue;
81-
columns << joinName + "." + f.name() + " AS " + prefix + f.name();
85+
columns << joinName + ".\"" + f.name() + "\" AS \"" + prefix + f.name() + "\"";
8286
}
8387
}
8488
}
8589

86-
QString query = "SELECT " + columns.join( QStringLiteral( ", " ) ) + " FROM " + layer->id() + " AS t " + leftJoins.join( QStringLiteral( " " ) );
90+
QString query = "SELECT " + columns.join( QStringLiteral( ", " ) ) + " FROM \"" + layer->id() + "\" AS t " + leftJoins.join( QStringLiteral( " " ) );
8791
def.setQuery( query );
8892

8993
return def;

tests/src/python/test_provider_virtual.py

+23-9
Original file line numberDiff line numberDiff line change
@@ -822,7 +822,11 @@ def test_joined_layers_conversion(self):
822822
self.assertEqual(v2.isValid(), True)
823823
v3 = QgsVectorLayer("Point?field=id:integer&field=cname:string", "C", "memory")
824824
self.assertEqual(v3.isValid(), True)
825-
QgsProject.instance().addMapLayers([v1, v2, v3])
825+
tl1 = QgsVectorLayer("NoGeometry?field=id:integer&field=e_id:integer&field=0name:string", "D", "memory")
826+
self.assertEqual(tl1.isValid(), True)
827+
tl2 = QgsVectorLayer("NoGeometry?field=id:integer&field=ena me:string", "E", "memory")
828+
self.assertEqual(tl2.isValid(), True)
829+
QgsProject.instance().addMapLayers([v1, v2, v3, tl1, tl2])
826830
joinInfo = QgsVectorLayerJoinInfo()
827831
joinInfo.setTargetFieldName("b_id")
828832
joinInfo.setJoinLayer(v2)
@@ -832,15 +836,15 @@ def test_joined_layers_conversion(self):
832836
self.assertEqual(len(v1.fields()), 6)
833837

834838
df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
835-
self.assertEqual(df.query(), 'SELECT t.rowid AS uid, t.id, t.b_id, t.c_id, t.name, j1.bname AS B_bname, j1.bfield AS B_bfield FROM {} AS t LEFT JOIN {} AS j1 ON t."b_id"=j1."id"'.format(v1.id(), v2.id()))
839+
self.assertEqual(df.query(), 'SELECT t.geometry, t.rowid AS uid, t."id", t."b_id", t."c_id", t."name", j1."bname" AS "B_bname", j1."bfield" AS "B_bfield" FROM "{}" AS t LEFT JOIN "{}" AS j1 ON t."b_id"=j1."id"'.format(v1.id(), v2.id()))
836840

837841
# with a field subset
838842
v1.removeJoin(v2.id())
839843
joinInfo.setJoinFieldNamesSubset(["bname"])
840844
v1.addJoin(joinInfo)
841845
self.assertEqual(len(v1.fields()), 5)
842846
df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
843-
self.assertEqual(df.query(), 'SELECT t.rowid AS uid, t.id, t.b_id, t.c_id, t.name, j1.bname AS B_bname FROM {} AS t LEFT JOIN {} AS j1 ON t."b_id"=j1."id"'.format(v1.id(), v2.id()))
847+
self.assertEqual(df.query(), 'SELECT t.geometry, t.rowid AS uid, t."id", t."b_id", t."c_id", t."name", j1."bname" AS "B_bname" FROM "{}" AS t LEFT JOIN "{}" AS j1 ON t."b_id"=j1."id"'.format(v1.id(), v2.id()))
844848
joinInfo.setJoinFieldNamesSubset(None)
845849

846850
# add a table prefix to the join
@@ -849,7 +853,7 @@ def test_joined_layers_conversion(self):
849853
v1.addJoin(joinInfo)
850854
self.assertEqual(len(v1.fields()), 6)
851855
df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
852-
self.assertEqual(df.query(), 'SELECT t.rowid AS uid, t.id, t.b_id, t.c_id, t.name, j1.bname AS BB_bname, j1.bfield AS BB_bfield FROM {} AS t LEFT JOIN {} AS j1 ON t."b_id"=j1."id"'.format(v1.id(), v2.id()))
856+
self.assertEqual(df.query(), 'SELECT t.geometry, t.rowid AS uid, t."id", t."b_id", t."c_id", t."name", j1."bname" AS "BB_bname", j1."bfield" AS "BB_bfield" FROM "{}" AS t LEFT JOIN "{}" AS j1 ON t."b_id"=j1."id"'.format(v1.id(), v2.id()))
853857
joinInfo.setPrefix("")
854858
v1.removeJoin(v2.id())
855859
v1.addJoin(joinInfo)
@@ -862,11 +866,21 @@ def test_joined_layers_conversion(self):
862866
v1.addJoin(joinInfo2)
863867
self.assertEqual(len(v1.fields()), 7)
864868
df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
865-
self.assertEqual(df.query(), ('SELECT t.rowid AS uid, t.id, t.b_id, t.c_id, t.name, j1.bname AS B_bname, j1.bfield AS B_bfield, j2.cname AS C_cname FROM {} AS t ' +
866-
'LEFT JOIN {} AS j1 ON t."b_id"=j1."id" ' +
867-
'LEFT JOIN {} AS j2 ON t."c_id"=j2."id"').format(v1.id(), v2.id(), v3.id()))
868-
869-
QgsProject.instance().removeMapLayers([v1.id(), v2.id(), v3.id()])
869+
self.assertEqual(df.query(), ('SELECT t.geometry, t.rowid AS uid, t."id", t."b_id", t."c_id", t."name", j1."bname" AS "B_bname", j1."bfield" AS "B_bfield", j2."cname" AS "C_cname" FROM "{}" AS t ' +
870+
'LEFT JOIN "{}" AS j1 ON t."b_id"=j1."id" ' +
871+
'LEFT JOIN "{}" AS j2 ON t."c_id"=j2."id"').format(v1.id(), v2.id(), v3.id()))
872+
873+
# test NoGeometry joined layers with field names starting with a digit or containing white spaces
874+
joinInfo3 = QgsVectorLayerJoinInfo()
875+
joinInfo3.setTargetFieldName("e_id")
876+
joinInfo3.setJoinLayer(tl2)
877+
joinInfo3.setJoinFieldName("id")
878+
tl1.addJoin(joinInfo3)
879+
self.assertEqual(len(tl1.fields()), 4)
880+
df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(tl1)
881+
self.assertEqual(df.query(), 'SELECT t.rowid AS uid, t."id", t."e_id", t."0name", j1."ena me" AS "E_ena me" FROM "{}" AS t LEFT JOIN "{}" AS j1 ON t."e_id"=j1."id"'.format(tl1.id(), tl2.id()))
882+
883+
QgsProject.instance().removeMapLayers([v1.id(), v2.id(), v3.id(), tl1.id(), tl2.id()])
870884

871885
def testFieldsWithSpecialCharacters(self):
872886
ml = QgsVectorLayer("Point?srid=EPSG:4326&field=123:int", "mem_with_nontext_fieldnames", "memory")

0 commit comments

Comments
 (0)