QGIS API Documentation  3.2.0-Bonn (bc43194)
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  // look for the uid
32  QgsFields fields = layer->dataProvider()->fields();
33  {
35  if ( pk.size() == 1 )
36  {
37  def.setUid( fields.field( pk[0] ).name() );
38  }
39  else
40  {
41  // find an uid name
42  QString uid = QStringLiteral( "uid" );
43  while ( fields.lookupField( uid ) != -1 )
44  uid += QLatin1String( "_" ); // add "_" each time this name already exists
45 
46  // add a column
47  columns << "t.rowid AS " + uid;
48  def.setUid( uid );
49  }
50  }
51  const QgsFields providerFields = layer->dataProvider()->fields();
52  for ( const auto &f : providerFields )
53  {
54  columns << "t." + f.name();
55  }
56 
57  int joinIdx = 0;
58  Q_FOREACH ( const QgsVectorLayerJoinInfo &join, layer->vectorJoins() )
59  {
60  QString joinName = QStringLiteral( "j%1" ).arg( ++joinIdx );
61  QgsVectorLayer *joinedLayer = join.joinLayer();
62  if ( !joinedLayer )
63  continue;
64  QString prefix = join.prefix().isEmpty() ? joinedLayer->name() + "_" : join.prefix();
65 
66  leftJoins << QStringLiteral( "LEFT JOIN %1 AS %2 ON t.\"%5\"=%2.\"%3\"" ).arg( joinedLayer->id(), joinName, join.joinFieldName(), join.targetFieldName() );
67  if ( join.joinFieldNamesSubset() )
68  {
69  Q_FOREACH ( const QString &f, *join.joinFieldNamesSubset() )
70  {
71  columns << joinName + "." + f + " AS " + prefix + f;
72  }
73  }
74  else
75  {
76  const QgsFields joinFields = joinedLayer->fields();
77  for ( const QgsField &f : joinFields )
78  {
79  if ( f.name() == join.joinFieldName() )
80  continue;
81  columns << joinName + "." + f.name() + " AS " + prefix + f.name();
82  }
83  }
84  }
85 
86  QString query = "SELECT " + columns.join( QStringLiteral( ", " ) ) + " FROM " + layer->id() + " AS t " + leftJoins.join( QStringLiteral( " " ) );
87  def.setQuery( query );
88 
89  return def;
90 }
int lookupField(const QString &fieldName) const
Look up field&#39;s index from the field name.
Definition: qgsfields.cpp:299
QString targetFieldName() const
Returns name of the field of our layer that will be used for join.
QString name
Definition: qgsfield.h:57
virtual QgsAttributeList pkAttributeIndexes() const
Returns list of indexes of fields that make up the primary key.
Container of fields for a vector layer.
Definition: qgsfields.h:42
const QList< QgsVectorLayerJoinInfo > vectorJoins() const
QString id() const
Returns the layer&#39;s unique ID, which is used to access this layer from QgsProject.
QgsVectorLayer * joinLayer() const
Returns joined layer (may be null if the reference was set by layer ID and not resolved yet) ...
QgsFields fields() const override
Returns the list of fields of this layer.
void setQuery(const QString &query)
Sets the SQL query.
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.
static QgsVirtualLayerDefinition fromJoinedLayer(QgsVectorLayer *joinedLayer)
Gets a virtual layer definition from a vector layer where vector joins are replaced by SQL LEFT JOINs...
static QStringList joinFieldNamesSubset(const QgsVectorLayerJoinInfo &info, bool blacklisted=true)
Returns the list of field names to use for joining considering blacklisted fields and subset...
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:48
void setUid(const QString &uid)
Sets the name of the field with unique identifiers.
QgsVectorDataProvider * dataProvider() override
Returns the layer&#39;s data provider.
QString name
Definition: qgsmaplayer.h:65
QList< int > QgsAttributeList
Definition: qgsfield.h:27
Represents a vector layer which manages a vector based data sets.
QString joinFieldName() const
Returns name of the field of joined layer that will be used for join.
QgsField field(int fieldIdx) const
Gets field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:150
Class to manipulate the definition of a virtual layer.
QString prefix() const
Returns prefix of fields from the joined layer. If null, joined layer&#39;s name will be used...