QGIS API Documentation  3.21.0-Master (5b68dc587e)
qgsvirtuallayerdefinitionutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvirtuallayerdefinitionutils.cpp
3 begin : Jan 2016
4 copyright : (C) 2016 Hugo Mercier, Oslandia
5 email : hugo dot mercier at oslandia dot com
6  ***************************************************************************/
7 
8 /***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 
18 #include "qgsvectorlayer.h"
19 #include "qgsvectorlayerjoininfo.h"
20 #include "qgsvectordataprovider.h"
21 #include "qgsproject.h"
23 
25 {
27 
28  QStringList leftJoins;
29  QStringList columns;
30 
31  // add the geometry column if the layer is spatial
32  if ( layer->isSpatial() )
33  columns << "t.geometry";
34 
35  // look for the uid
36  const QgsFields fields = layer->dataProvider()->fields();
37  {
39  if ( pk.size() == 1 )
40  {
41  def.setUid( fields.field( pk[0] ).name() );
42  }
43  else
44  {
45  // find an uid name
46  QString uid = QStringLiteral( "uid" );
47  while ( fields.lookupField( uid ) != -1 )
48  uid += QLatin1Char( '_' ); // add "_" each time this name already exists
49 
50  // add a column
51  columns << "t.rowid AS " + uid;
52  def.setUid( uid );
53  }
54  }
55  const QgsFields providerFields = layer->dataProvider()->fields();
56  for ( const auto &f : providerFields )
57  {
58  columns << "t.\"" + f.name() + "\"";
59  }
60 
61  int joinIdx = 0;
62  const auto constVectorJoins = layer->vectorJoins();
63  for ( const QgsVectorLayerJoinInfo &join : constVectorJoins )
64  {
65  const QString joinName = QStringLiteral( "j%1" ).arg( ++joinIdx );
66  QgsVectorLayer *joinedLayer = join.joinLayer();
67  if ( !joinedLayer )
68  continue;
69  const QString prefix = join.prefix().isEmpty() ? joinedLayer->name() + "_" : join.prefix();
70 
71  leftJoins << QStringLiteral( "LEFT JOIN \"%1\" AS %2 ON t.\"%5\"=%2.\"%3\"" ).arg( joinedLayer->id(), joinName, join.joinFieldName(), join.targetFieldName() );
72  if ( auto *lJoinFieldNamesSubset = join.joinFieldNamesSubset() )
73  {
74  const QStringList joinFieldNamesSubset { *lJoinFieldNamesSubset };
75  for ( const QString &f : joinFieldNamesSubset )
76  {
77  columns << joinName + ".\"" + f + "\" AS \"" + prefix + f + "\"";
78  }
79  }
80  else
81  {
82  const QgsFields joinFields = joinedLayer->fields();
83  for ( const QgsField &f : joinFields )
84  {
85  if ( f.name() == join.joinFieldName() )
86  continue;
87  columns << joinName + ".\"" + f.name() + "\" AS \"" + prefix + f.name() + "\"";
88  }
89  }
90  }
91 
92  const QString query = "SELECT " + columns.join( QLatin1String( ", " ) ) + " FROM \"" + layer->id() + "\" AS t " + leftJoins.join( QLatin1Char( ' ' ) );
93  def.setQuery( query );
94 
95  return def;
96 }
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:51
QString name
Definition: qgsfield.h:60
Container of fields for a vector layer.
Definition: qgsfields.h:45
QgsField field(int fieldIdx) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:168
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:344
QString name
Definition: qgsmaplayer.h:76
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
virtual QgsAttributeList pkAttributeIndexes() const
Returns list of indexes of fields that make up the primary key.
QgsFields fields() const override=0
Returns the fields associated with this data provider.
Defines left outer join from our vector layer to some other vector layer.
Represents a vector layer which manages a vector based data sets.
bool isSpatial() const FINAL
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
QgsFields fields() const FINAL
Returns the list of fields of this layer.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
const QList< QgsVectorLayerJoinInfo > vectorJoins() const
static QgsVirtualLayerDefinition fromJoinedLayer(QgsVectorLayer *joinedLayer)
Gets a virtual layer definition from a vector layer where vector joins are replaced by SQL LEFT JOINs...
Class to manipulate the definition of a virtual layer.
void setUid(const QString &uid)
Sets the name of the field with unique identifiers.
void setQuery(const QString &query)
Sets the SQL query.
QList< int > QgsAttributeList
Definition: qgsfield.h:26