QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgsaggregatecalculator.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsaggregatecalculator.cpp
3  --------------------------
4  begin : May 2016
5  copyright : (C) 2016 by Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgsaggregatecalculator.h"
19 #include "qgsexpressionutils.h"
20 #include "qgsfeature.h"
21 #include "qgsfeaturerequest.h"
22 #include "qgsfeatureiterator.h"
23 #include "qgsgeometry.h"
24 #include "qgsvectorlayer.h"
25 
26 
27 
29  : mLayer( layer )
30 {
31 
32 }
33 
35 {
36  return mLayer;
37 }
38 
40 {
41  mFilterExpression = parameters.filter;
42  mDelimiter = parameters.delimiter;
43  mOrderBy = parameters.orderBy;
44 }
45 
47 {
48  mFidsSet = true;
49  mFidsFilter = fids;
50 }
51 
53  const QString &fieldOrExpression, QgsExpressionContext *context, bool *ok, QgsFeedback *feedback ) const
54 {
55  mLastError.clear();
56  if ( ok )
57  *ok = false;
58 
60 
61  if ( !mLayer )
62  return QVariant();
63 
64  QgsExpressionContext defaultContext = mLayer->createExpressionContext();
65  context = context ? context : &defaultContext;
66 
67  std::unique_ptr<QgsExpression> expression;
68 
69  const int attrNum = QgsExpression::expressionToLayerFieldIndex( fieldOrExpression, mLayer );
70  if ( attrNum == -1 )
71  {
72  Q_ASSERT( context );
73  context->setFields( mLayer->fields() );
74  // try to use expression
75  expression.reset( new QgsExpression( fieldOrExpression ) );
76 
77  if ( expression->hasParserError() || !expression->prepare( context ) )
78  {
79  mLastError = !expression->parserErrorString().isEmpty() ? expression->parserErrorString() : expression->evalErrorString();
80  return QVariant();
81  }
82  }
83 
84  QSet<QString> lst;
85  if ( !expression )
86  lst.insert( mLayer->fields().at( attrNum ).name() );
87  else
88  lst = expression->referencedColumns();
89 
90  request.setFlags( ( expression && expression->needsGeometry() ) ?
93  .setSubsetOfAttributes( lst, mLayer->fields() );
94 
95  if ( mFidsSet )
96  request.setFilterFids( mFidsFilter );
97 
98  if ( !mOrderBy.empty() )
99  request.setOrderBy( mOrderBy );
100 
101  if ( !mFilterExpression.isEmpty() )
102  request.setFilterExpression( mFilterExpression );
103  if ( context )
104  request.setExpressionContext( *context );
105 
106  request.setFeedback( feedback ? feedback : ( context ? context->feedback() : nullptr ) );
107 
108  //determine result type
109  QVariant::Type resultType = QVariant::Double;
110  int userType = 0;
111  if ( attrNum == -1 )
112  {
113  if ( aggregate == GeometryCollect )
114  {
115  // in this case we know the result should be a geometry value, so no need to sniff it out...
116  resultType = QVariant::UserType;
117  }
118  else
119  {
120  // check expression result type
121  bool foundFeatures = false;
122  std::tuple<QVariant::Type, int> returnType = QgsExpressionUtils::determineResultType( fieldOrExpression, mLayer, request, *context, &foundFeatures );
123  if ( !foundFeatures )
124  {
125  if ( ok )
126  *ok = true;
127  return defaultValue( aggregate );
128  }
129 
130  resultType = std::get<0>( returnType );
131  userType = std::get<1>( returnType );
132  if ( resultType == QVariant::Invalid )
133  {
134  QVariant v;
135  switch ( aggregate )
136  {
137  // string
138  case StringConcatenate:
140  case StringMinimumLength:
141  case StringMaximumLength:
142  v = QString();
143  break;
144 
145  // numerical
146  case Sum:
147  case Mean:
148  case Median:
149  case StDev:
150  case StDevSample:
151  case Range:
152  case FirstQuartile:
153  case ThirdQuartile:
154  case InterQuartileRange:
155  // mixed type, fallback to numerical
156  case Count:
157  case CountDistinct:
158  case CountMissing:
159  case Minority:
160  case Majority:
161  case Min:
162  case Max:
163  v = 0.0;
164  break;
165 
166  // geometry
167  case GeometryCollect:
168  v = QgsGeometry();
169  break;
170 
171  // list, fallback to string
172  case ArrayAggregate:
173  v = QString();
174  break;
175  }
176  resultType = v.type();
177  userType = v.userType();
178  }
179  }
180  }
181  else
182  resultType = mLayer->fields().at( attrNum ).type();
183 
184  QgsFeatureIterator fit = mLayer->getFeatures( request );
185  return calculate( aggregate, fit, resultType, userType, attrNum, expression.get(), mDelimiter, context, ok, &mLastError );
186 }
187 
189 {
190  const QString normalized = string.trimmed().toLower();
191 
192  if ( ok )
193  *ok = true;
194 
195  if ( normalized == QLatin1String( "count" ) )
196  return Count;
197  else if ( normalized == QLatin1String( "count_distinct" ) )
198  return CountDistinct;
199  else if ( normalized == QLatin1String( "count_missing" ) )
200  return CountMissing;
201  else if ( normalized == QLatin1String( "min" ) )
202  return Min;
203  else if ( normalized == QLatin1String( "max" ) )
204  return Max;
205  else if ( normalized == QLatin1String( "sum" ) )
206  return Sum;
207  else if ( normalized == QLatin1String( "mean" ) )
208  return Mean;
209  else if ( normalized == QLatin1String( "median" ) )
210  return Median;
211  else if ( normalized == QLatin1String( "stdev" ) )
212  return StDev;
213  else if ( normalized == QLatin1String( "stdevsample" ) )
214  return StDevSample;
215  else if ( normalized == QLatin1String( "range" ) )
216  return Range;
217  else if ( normalized == QLatin1String( "minority" ) )
218  return Minority;
219  else if ( normalized == QLatin1String( "majority" ) )
220  return Majority;
221  else if ( normalized == QLatin1String( "q1" ) )
222  return FirstQuartile;
223  else if ( normalized == QLatin1String( "q3" ) )
224  return ThirdQuartile;
225  else if ( normalized == QLatin1String( "iqr" ) )
226  return InterQuartileRange;
227  else if ( normalized == QLatin1String( "min_length" ) )
228  return StringMinimumLength;
229  else if ( normalized == QLatin1String( "max_length" ) )
230  return StringMaximumLength;
231  else if ( normalized == QLatin1String( "concatenate" ) )
232  return StringConcatenate;
233  else if ( normalized == QLatin1String( "concatenate_unique" ) )
235  else if ( normalized == QLatin1String( "collect" ) )
236  return GeometryCollect;
237  else if ( normalized == QLatin1String( "array_agg" ) )
238  return ArrayAggregate;
239 
240  if ( ok )
241  *ok = false;
242 
243  return Count;
244 }
245 
247 {
248  switch ( aggregate )
249  {
251  return QObject::tr( "count" );
253  return QObject::tr( "count distinct" );
255  return QObject::tr( "count missing" );
257  return QObject::tr( "minimum" );
259  return QObject::tr( "maximum" );
261  return QObject::tr( "sum" );
263  return QObject::tr( "mean" );
265  return QObject::tr( "median" );
267  return QObject::tr( "standard deviation" );
269  return QObject::tr( "standard deviation (sample)" );
271  return QObject::tr( "range" );
273  return QObject::tr( "minority" );
275  return QObject::tr( "majority" );
277  return QObject::tr( "first quartile" );
279  return QObject::tr( "third quartile" );
281  return QObject::tr( "inter quartile range" );
283  return QObject::tr( "minimum length" );
285  return QObject::tr( "maximum length" );
287  return QObject::tr( "concatenate" );
289  return QObject::tr( "collection" );
291  return QObject::tr( "array aggregate" );
293  return QObject::tr( "concatenate (unique)" );
294  }
295  return QString();
296 }
297 
298 QList<QgsAggregateCalculator::AggregateInfo> QgsAggregateCalculator::aggregates()
299 {
300  QList< AggregateInfo > aggregates;
301  aggregates
302  << AggregateInfo
303  {
304  QStringLiteral( "count" ),
305  QCoreApplication::tr( "Count" ),
306  QSet<QVariant::Type>()
307  << QVariant::DateTime
308  << QVariant::Date
309  << QVariant::Int
310  << QVariant::UInt
311  << QVariant::LongLong
312  << QVariant::ULongLong
313  << QVariant::String
314  }
315  << AggregateInfo
316  {
317  QStringLiteral( "count_distinct" ),
318  QCoreApplication::tr( "Count Distinct" ),
319  QSet<QVariant::Type>()
320  << QVariant::DateTime
321  << QVariant::Date
322  << QVariant::UInt
323  << QVariant::Int
324  << QVariant::LongLong
325  << QVariant::ULongLong
326  << QVariant::String
327  }
328  << AggregateInfo
329  {
330  QStringLiteral( "count_missing" ),
331  QCoreApplication::tr( "Count Missing" ),
332  QSet<QVariant::Type>()
333  << QVariant::DateTime
334  << QVariant::Date
335  << QVariant::Int
336  << QVariant::UInt
337  << QVariant::LongLong
338  << QVariant::String
339  }
340  << AggregateInfo
341  {
342  QStringLiteral( "min" ),
343  QCoreApplication::tr( "Min" ),
344  QSet<QVariant::Type>()
345  << QVariant::DateTime
346  << QVariant::Date
347  << QVariant::Int
348  << QVariant::UInt
349  << QVariant::LongLong
350  << QVariant::ULongLong
351  << QVariant::Double
352  << QVariant::String
353  }
354  << AggregateInfo
355  {
356  QStringLiteral( "max" ),
357  QCoreApplication::tr( "Max" ),
358  QSet<QVariant::Type>()
359  << QVariant::DateTime
360  << QVariant::Date
361  << QVariant::Int
362  << QVariant::UInt
363  << QVariant::LongLong
364  << QVariant::ULongLong
365  << QVariant::Double
366  << QVariant::String
367  }
368  << AggregateInfo
369  {
370  QStringLiteral( "sum" ),
371  QCoreApplication::tr( "Sum" ),
372  QSet<QVariant::Type>()
373  << QVariant::Int
374  << QVariant::UInt
375  << QVariant::LongLong
376  << QVariant::ULongLong
377  << QVariant::Double
378  }
379  << AggregateInfo
380  {
381  QStringLiteral( "mean" ),
382  QCoreApplication::tr( "Mean" ),
383  QSet<QVariant::Type>()
384  << QVariant::Int
385  << QVariant::UInt
386  << QVariant::LongLong
387  << QVariant::ULongLong
388  << QVariant::Double
389  }
390  << AggregateInfo
391  {
392  QStringLiteral( "median" ),
393  QCoreApplication::tr( "Median" ),
394  QSet<QVariant::Type>()
395  << QVariant::Int
396  << QVariant::UInt
397  << QVariant::Double
398  }
399  << AggregateInfo
400  {
401  QStringLiteral( "stdev" ),
402  QCoreApplication::tr( "Stdev" ),
403  QSet<QVariant::Type>()
404  << QVariant::Int
405  << QVariant::UInt
406  << QVariant::LongLong
407  << QVariant::ULongLong
408  << QVariant::Double
409  }
410  << AggregateInfo
411  {
412  QStringLiteral( "stdevsample" ),
413  QCoreApplication::tr( "Stdev Sample" ),
414  QSet<QVariant::Type>()
415  << QVariant::Int
416  << QVariant::UInt
417  << QVariant::LongLong
418  << QVariant::ULongLong
419  << QVariant::Double
420  }
421  << AggregateInfo
422  {
423  QStringLiteral( "range" ),
424  QCoreApplication::tr( "Range" ),
425  QSet<QVariant::Type>()
426  << QVariant::Date
427  << QVariant::DateTime
428  << QVariant::Int
429  << QVariant::UInt
430  << QVariant::LongLong
431  << QVariant::ULongLong
432  << QVariant::Double
433  }
434  << AggregateInfo
435  {
436  QStringLiteral( "minority" ),
437  QCoreApplication::tr( "Minority" ),
438  QSet<QVariant::Type>()
439  << QVariant::Int
440  << QVariant::UInt
441  << QVariant::LongLong
442  << QVariant::ULongLong
443  << QVariant::Double
444  << QVariant::String
445  }
446  << AggregateInfo
447  {
448  QStringLiteral( "majority" ),
449  QCoreApplication::tr( "Majority" ),
450  QSet<QVariant::Type>()
451  << QVariant::Int
452  << QVariant::UInt
453  << QVariant::LongLong
454  << QVariant::ULongLong
455  << QVariant::Double
456  << QVariant::String
457  }
458  << AggregateInfo
459  {
460  QStringLiteral( "q1" ),
461  QCoreApplication::tr( "Q1" ),
462  QSet<QVariant::Type>()
463  << QVariant::Int
464  << QVariant::UInt
465  << QVariant::LongLong
466  << QVariant::ULongLong
467  << QVariant::Double
468  }
469  << AggregateInfo
470  {
471  QStringLiteral( "q3" ),
472  QCoreApplication::tr( "Q3" ),
473  QSet<QVariant::Type>()
474  << QVariant::Int
475  << QVariant::UInt
476  << QVariant::LongLong
477  << QVariant::ULongLong
478  << QVariant::Double
479  }
480  << AggregateInfo
481  {
482  QStringLiteral( "iqr" ),
483  QCoreApplication::tr( "InterQuartileRange" ),
484  QSet<QVariant::Type>()
485  << QVariant::Int
486  << QVariant::UInt
487  << QVariant::LongLong
488  << QVariant::ULongLong
489  << QVariant::Double
490  }
491  << AggregateInfo
492  {
493  QStringLiteral( "min_length" ),
494  QCoreApplication::tr( "Min Length" ),
495  QSet<QVariant::Type>()
496  << QVariant::String
497  }
498  << AggregateInfo
499  {
500  QStringLiteral( "max_length" ),
501  QCoreApplication::tr( "Max Length" ),
502  QSet<QVariant::Type>()
503  << QVariant::String
504  }
505  << AggregateInfo
506  {
507  QStringLiteral( "concatenate" ),
508  QCoreApplication::tr( "Concatenate" ),
509  QSet<QVariant::Type>()
510  << QVariant::String
511  }
512  << AggregateInfo
513  {
514  QStringLiteral( "collect" ),
515  QCoreApplication::tr( "Collect" ),
516  QSet<QVariant::Type>()
517  }
518  << AggregateInfo
519  {
520  QStringLiteral( "array_agg" ),
521  QCoreApplication::tr( "Array Aggregate" ),
522  QSet<QVariant::Type>()
523  };
524 
525  return aggregates;
526 }
527 
528 QVariant QgsAggregateCalculator::calculate( QgsAggregateCalculator::Aggregate aggregate, QgsFeatureIterator &fit, QVariant::Type resultType, int userType,
529  int attr, QgsExpression *expression, const QString &delimiter, QgsExpressionContext *context, bool *ok, QString *error )
530 {
531  if ( ok )
532  *ok = false;
533 
534  if ( aggregate == QgsAggregateCalculator::ArrayAggregate )
535  {
536  if ( ok )
537  *ok = true;
538  return calculateArrayAggregate( fit, attr, expression, context );
539  }
540 
541  switch ( resultType )
542  {
543  case QVariant::Int:
544  case QVariant::UInt:
545  case QVariant::LongLong:
546  case QVariant::ULongLong:
547  case QVariant::Double:
548  {
549  bool statOk = false;
550  const QgsStatisticalSummary::Statistic stat = numericStatFromAggregate( aggregate, &statOk );
551  if ( !statOk )
552  {
553  if ( error )
554  *error = expression ? QObject::tr( "Cannot calculate %1 on numeric values" ).arg( displayName( aggregate ) )
555  : QObject::tr( "Cannot calculate %1 on numeric fields" ).arg( displayName( aggregate ) );
556  return QVariant();
557  }
558 
559  if ( ok )
560  *ok = true;
561  return calculateNumericAggregate( fit, attr, expression, context, stat );
562  }
563 
564  case QVariant::Date:
565  case QVariant::DateTime:
566  {
567  bool statOk = false;
568  const QgsDateTimeStatisticalSummary::Statistic stat = dateTimeStatFromAggregate( aggregate, &statOk );
569  if ( !statOk )
570  {
571  if ( error )
572  *error = ( expression ? QObject::tr( "Cannot calculate %1 on %2 values" ).arg( displayName( aggregate ) ) :
573  QObject::tr( "Cannot calculate %1 on %2 fields" ).arg( displayName( aggregate ) ) ).arg( resultType == QVariant::Date ? QObject::tr( "date" ) : QObject::tr( "datetime" ) );
574  return QVariant();
575  }
576 
577  if ( ok )
578  *ok = true;
579  return calculateDateTimeAggregate( fit, attr, expression, context, stat );
580  }
581 
582  case QVariant::UserType:
583  {
584  if ( aggregate == GeometryCollect )
585  {
586  if ( ok )
587  *ok = true;
588  return calculateGeometryAggregate( fit, expression, context );
589  }
590  else
591  {
592  return QVariant();
593  }
594  }
595 
596  default:
597  {
598  // treat as string
599  if ( aggregate == StringConcatenate )
600  {
601  //special case
602  if ( ok )
603  *ok = true;
604  return concatenateStrings( fit, attr, expression, context, delimiter );
605  }
606  else if ( aggregate == StringConcatenateUnique )
607  {
608  //special case
609  if ( ok )
610  *ok = true;
611  return concatenateStrings( fit, attr, expression, context, delimiter, true );
612  }
613 
614  bool statOk = false;
615  const QgsStringStatisticalSummary::Statistic stat = stringStatFromAggregate( aggregate, &statOk );
616  if ( !statOk )
617  {
618  QString typeString;
619  if ( resultType == QVariant::Invalid )
620  typeString = QObject::tr( "null" );
621  else if ( resultType == QVariant::UserType )
622  typeString = QMetaType::typeName( userType );
623  else
624  typeString = resultType == QVariant::String ? QObject::tr( "string" ) : QVariant::typeToName( resultType );
625 
626  if ( error )
627  *error = expression ? QObject::tr( "Cannot calculate %1 on %3 values" ).arg( displayName( aggregate ), typeString )
628  : QObject::tr( "Cannot calculate %1 on %3 fields" ).arg( displayName( aggregate ), typeString );
629  return QVariant();
630  }
631 
632  if ( ok )
633  *ok = true;
634  return calculateStringAggregate( fit, attr, expression, context, stat );
635  }
636  }
637 
638 #ifndef _MSC_VER
639  return QVariant();
640 #endif
641 }
642 
643 QgsStatisticalSummary::Statistic QgsAggregateCalculator::numericStatFromAggregate( QgsAggregateCalculator::Aggregate aggregate, bool *ok )
644 {
645  if ( ok )
646  *ok = true;
647 
648  switch ( aggregate )
649  {
650  case Count:
652  case CountDistinct:
654  case CountMissing:
656  case Min:
658  case Max:
660  case Sum:
662  case Mean:
664  case Median:
666  case StDev:
668  case StDevSample:
670  case Range:
672  case Minority:
674  case Majority:
676  case FirstQuartile:
678  case ThirdQuartile:
680  case InterQuartileRange:
682  case StringMinimumLength:
683  case StringMaximumLength:
684  case StringConcatenate:
686  case GeometryCollect:
687  case ArrayAggregate:
688  {
689  if ( ok )
690  *ok = false;
692  }
693  }
694 
695  if ( ok )
696  *ok = false;
698 }
699 
700 QgsStringStatisticalSummary::Statistic QgsAggregateCalculator::stringStatFromAggregate( QgsAggregateCalculator::Aggregate aggregate, bool *ok )
701 {
702  if ( ok )
703  *ok = true;
704 
705  switch ( aggregate )
706  {
707  case Count:
709  case CountDistinct:
711  case CountMissing:
713  case Min:
715  case Max:
717  case StringMinimumLength:
719  case StringMaximumLength:
721  case Minority:
723  case Majority:
725 
726  case Sum:
727  case Mean:
728  case Median:
729  case StDev:
730  case StDevSample:
731  case Range:
732  case FirstQuartile:
733  case ThirdQuartile:
734  case InterQuartileRange:
735  case StringConcatenate:
737  case GeometryCollect:
738  case ArrayAggregate:
739  {
740  if ( ok )
741  *ok = false;
743  }
744  }
745 
746  if ( ok )
747  *ok = false;
749 }
750 
751 QgsDateTimeStatisticalSummary::Statistic QgsAggregateCalculator::dateTimeStatFromAggregate( QgsAggregateCalculator::Aggregate aggregate, bool *ok )
752 {
753  if ( ok )
754  *ok = true;
755 
756  switch ( aggregate )
757  {
758  case Count:
760  case CountDistinct:
762  case CountMissing:
764  case Min:
766  case Max:
768  case Range:
770 
771  case Sum:
772  case Mean:
773  case Median:
774  case StDev:
775  case StDevSample:
776  case Minority:
777  case Majority:
778  case FirstQuartile:
779  case ThirdQuartile:
780  case InterQuartileRange:
781  case StringMinimumLength:
782  case StringMaximumLength:
783  case StringConcatenate:
785  case GeometryCollect:
786  case ArrayAggregate:
787  {
788  if ( ok )
789  *ok = false;
791  }
792  }
793 
794  if ( ok )
795  *ok = false;
797 }
798 
799 QVariant QgsAggregateCalculator::calculateNumericAggregate( QgsFeatureIterator &fit, int attr, QgsExpression *expression,
801 {
802  Q_ASSERT( expression || attr >= 0 );
803 
804  QgsStatisticalSummary s( stat );
805  QgsFeature f;
806 
807  while ( fit.nextFeature( f ) )
808  {
809  if ( expression )
810  {
811  Q_ASSERT( context );
812  context->setFeature( f );
813  const QVariant v = expression->evaluate( context );
814  s.addVariant( v );
815  }
816  else
817  {
818  s.addVariant( f.attribute( attr ) );
819  }
820  }
821  s.finalize();
822  const double val = s.statistic( stat );
823  return std::isnan( val ) ? QVariant() : val;
824 }
825 
826 QVariant QgsAggregateCalculator::calculateStringAggregate( QgsFeatureIterator &fit, int attr, QgsExpression *expression,
828 {
829  Q_ASSERT( expression || attr >= 0 );
830 
831  QgsStringStatisticalSummary s( stat );
832  QgsFeature f;
833 
834  while ( fit.nextFeature( f ) )
835  {
836  if ( expression )
837  {
838  Q_ASSERT( context );
839  context->setFeature( f );
840  const QVariant v = expression->evaluate( context );
841  s.addValue( v );
842  }
843  else
844  {
845  s.addValue( f.attribute( attr ) );
846  }
847  }
848  s.finalize();
849  return s.statistic( stat );
850 }
851 
852 QVariant QgsAggregateCalculator::calculateGeometryAggregate( QgsFeatureIterator &fit, QgsExpression *expression, QgsExpressionContext *context )
853 {
854  Q_ASSERT( expression );
855 
856  QgsFeature f;
857  QVector< QgsGeometry > geometries;
858  while ( fit.nextFeature( f ) )
859  {
860  Q_ASSERT( context );
861  context->setFeature( f );
862  const QVariant v = expression->evaluate( context );
863  if ( v.canConvert<QgsGeometry>() )
864  {
865  geometries << v.value<QgsGeometry>();
866  }
867  }
868 
869  return QVariant::fromValue( QgsGeometry::collectGeometry( geometries ) );
870 }
871 
872 QVariant QgsAggregateCalculator::concatenateStrings( QgsFeatureIterator &fit, int attr, QgsExpression *expression,
873  QgsExpressionContext *context, const QString &delimiter, bool unique )
874 {
875  Q_ASSERT( expression || attr >= 0 );
876 
877  QgsFeature f;
878  QStringList results;
879  while ( fit.nextFeature( f ) )
880  {
881  QString result;
882  if ( expression )
883  {
884  Q_ASSERT( context );
885  context->setFeature( f );
886  const QVariant v = expression->evaluate( context );
887  result = v.toString();
888  }
889  else
890  {
891  result = f.attribute( attr ).toString();
892  }
893 
894  if ( !unique || !results.contains( result ) )
895  results << result;
896  }
897 
898  return results.join( delimiter );
899 }
900 
901 QVariant QgsAggregateCalculator::defaultValue( QgsAggregateCalculator::Aggregate aggregate ) const
902 {
903  // value to return when NO features are aggregated:
904  switch ( aggregate )
905  {
906  // sensible values:
907  case Count:
908  case CountDistinct:
909  case CountMissing:
910  return 0;
911 
912  case StringConcatenate:
914  return ""; // zero length string - not null!
915 
916  case ArrayAggregate:
917  return QVariantList(); // empty list
918 
919  // undefined - nothing makes sense here
920  case Sum:
921  case Min:
922  case Max:
923  case Mean:
924  case Median:
925  case StDev:
926  case StDevSample:
927  case Range:
928  case Minority:
929  case Majority:
930  case FirstQuartile:
931  case ThirdQuartile:
932  case InterQuartileRange:
933  case StringMinimumLength:
934  case StringMaximumLength:
935  case GeometryCollect:
936  return QVariant();
937  }
938  return QVariant();
939 }
940 
941 QVariant QgsAggregateCalculator::calculateDateTimeAggregate( QgsFeatureIterator &fit, int attr, QgsExpression *expression,
943 {
944  Q_ASSERT( expression || attr >= 0 );
945 
947  QgsFeature f;
948 
949  while ( fit.nextFeature( f ) )
950  {
951  if ( expression )
952  {
953  Q_ASSERT( context );
954  context->setFeature( f );
955  const QVariant v = expression->evaluate( context );
956  s.addValue( v );
957  }
958  else
959  {
960  s.addValue( f.attribute( attr ) );
961  }
962  }
963  s.finalize();
964  return s.statistic( stat );
965 }
966 
967 QVariant QgsAggregateCalculator::calculateArrayAggregate( QgsFeatureIterator &fit, int attr, QgsExpression *expression,
968  QgsExpressionContext *context )
969 {
970  Q_ASSERT( expression || attr >= 0 );
971 
972  QgsFeature f;
973 
974  QVariantList array;
975 
976  while ( fit.nextFeature( f ) )
977  {
978  if ( expression )
979  {
980  Q_ASSERT( context );
981  context->setFeature( f );
982  const QVariant v = expression->evaluate( context );
983  array.append( v );
984  }
985  else
986  {
987  array.append( f.attribute( attr ) );
988  }
989  }
990  return array;
991 }
992 
QgsFeatureRequest::NoGeometry
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Definition: qgsfeaturerequest.h:115
QgsVectorLayer::getFeatures
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
Definition: qgsvectorlayer.cpp:1052
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:406
QgsAggregateCalculator::AggregateParameters::delimiter
QString delimiter
Delimiter to use for joining values with the StringConcatenate aggregate.
Definition: qgsaggregatecalculator.h:110
QgsAggregateCalculator::Range
@ Range
Range of values (max - min) (numeric and datetime fields only)
Definition: qgsaggregatecalculator.h:79
QgsDateTimeStatisticalSummary::CountMissing
@ CountMissing
Number of missing (null) values.
Definition: qgsdatetimestatisticalsummary.h:54
QgsStatisticalSummary
Calculator for summary statistics for a list of doubles.
Definition: qgsstatisticalsummary.h:43
qgsfeaturerequest.h
QgsStringStatisticalSummary::Minority
@ Minority
Minority of strings.
Definition: qgsstringstatisticalsummary.h:59
QgsStatisticalSummary::StDev
@ StDev
Standard deviation of values.
Definition: qgsstatisticalsummary.h:55
QgsAggregateCalculator::Minority
@ Minority
Minority of values.
Definition: qgsaggregatecalculator.h:80
QgsAggregateCalculator::AggregateParameters
A bundle of parameters controlling aggregate calculation.
Definition: qgsaggregatecalculator.h:94
QgsAggregateCalculator::CountDistinct
@ CountDistinct
Number of distinct values.
Definition: qgsaggregatecalculator.h:70
QgsAggregateCalculator::Min
@ Min
Min of values.
Definition: qgsaggregatecalculator.h:72
qgsfeatureiterator.h
QgsAggregateCalculator::StringConcatenateUnique
@ StringConcatenateUnique
Concatenate unique values with a joining string (string fields only). Specify the delimiter using set...
Definition: qgsaggregatecalculator.h:90
QgsAggregateCalculator::CountMissing
@ CountMissing
Number of missing (null) values.
Definition: qgsaggregatecalculator.h:71
qgsfeature.h
QgsStatisticalSummary::InterQuartileRange
@ InterQuartileRange
Inter quartile range (IQR)
Definition: qgsstatisticalsummary.h:65
QgsAggregateCalculator::ArrayAggregate
@ ArrayAggregate
Create an array of values.
Definition: qgsaggregatecalculator.h:89
QgsAggregateCalculator::Count
@ Count
Count.
Definition: qgsaggregatecalculator.h:69
QgsExpressionContext::setFields
void setFields(const QgsFields &fields)
Convenience function for setting a fields for the context.
Definition: qgsexpressioncontext.cpp:587
QgsStatisticalSummary::ThirdQuartile
@ ThirdQuartile
Third quartile.
Definition: qgsstatisticalsummary.h:64
QgsFeatureRequest::setSubsetOfAttributes
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
Definition: qgsfeaturerequest.cpp:228
QgsAggregateCalculator::displayName
static QString displayName(Aggregate aggregate)
Returns the friendly display name for a aggregate.
Definition: qgsaggregatecalculator.cpp:246
QgsAggregateCalculator::AggregateParameters::orderBy
QgsFeatureRequest::OrderBy orderBy
Optional order by clauses.
Definition: qgsaggregatecalculator.h:116
QgsField::name
QString name
Definition: qgsfield.h:60
QgsAggregateCalculator::aggregates
static QList< QgsAggregateCalculator::AggregateInfo > aggregates()
Structured information for available aggregates.
Definition: qgsaggregatecalculator.cpp:298
QgsFeatureRequest::setExpressionContext
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
Definition: qgsfeaturerequest.cpp:187
qgsaggregatecalculator.h
QgsFeatureRequest::setFilterExpression
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
Definition: qgsfeaturerequest.cpp:167
QgsStatisticalSummary::Sum
@ Sum
Sum of values.
Definition: qgsstatisticalsummary.h:52
QgsVectorLayer::fields
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Definition: qgsvectorlayer.cpp:3436
QgsAggregateCalculator::InterQuartileRange
@ InterQuartileRange
Inter quartile range (IQR) (numeric fields only)
Definition: qgsaggregatecalculator.h:84
QgsAggregateCalculator::calculate
QVariant calculate(Aggregate aggregate, const QString &fieldOrExpression, QgsExpressionContext *context=nullptr, bool *ok=nullptr, QgsFeedback *feedback=nullptr) const
Calculates the value of an aggregate.
Definition: qgsaggregatecalculator.cpp:52
QgsFeatureRequest
This class wraps a request for features to a vector layer (or directly its vector data provider).
Definition: qgsfeaturerequest.h:83
QgsAggregateCalculator::StDevSample
@ StDevSample
Sample standard deviation of values (numeric fields only)
Definition: qgsaggregatecalculator.h:78
QgsAggregateCalculator::delimiter
QString delimiter() const
Returns the delimiter used for joining values with the StringConcatenate aggregate.
Definition: qgsaggregatecalculator.h:175
QgsFeatureRequest::NoFlags
@ NoFlags
Definition: qgsfeaturerequest.h:114
QgsStatisticalSummary::Minority
@ Minority
Minority of values.
Definition: qgsstatisticalsummary.h:60
QgsAggregateCalculator::StDev
@ StDev
Standard deviation of values (numeric fields only)
Definition: qgsaggregatecalculator.h:77
QgsExpressionContext::feedback
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly by the expression to check if evaluation sh...
Definition: qgsexpressioncontext.cpp:634
QgsStringStatisticalSummary::Max
@ Max
Maximum string value.
Definition: qgsstringstatisticalsummary.h:55
QgsFeedback
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:44
QgsStringStatisticalSummary::Statistic
Statistic
Enumeration of flags that specify statistics to be calculated.
Definition: qgsstringstatisticalsummary.h:49
QgsStatisticalSummary::StDevSample
@ StDevSample
Sample standard deviation of values.
Definition: qgsstatisticalsummary.h:56
QgsAggregateCalculator::StringMinimumLength
@ StringMinimumLength
Minimum length of string (string fields only)
Definition: qgsaggregatecalculator.h:85
QgsStringStatisticalSummary::CountDistinct
@ CountDistinct
Number of distinct string values.
Definition: qgsstringstatisticalsummary.h:52
QgsStringStatisticalSummary::Count
@ Count
Count.
Definition: qgsstringstatisticalsummary.h:51
qgsexpressionutils.h
QgsDateTimeStatisticalSummary::Statistic
Statistic
Enumeration of flags that specify statistics to be calculated.
Definition: qgsdatetimestatisticalsummary.h:50
QgsStatisticalSummary::Range
@ Range
Range of values (max - min)
Definition: qgsstatisticalsummary.h:59
QgsDateTimeStatisticalSummary::Max
@ Max
Maximum (latest) datetime value.
Definition: qgsdatetimestatisticalsummary.h:56
QgsFeature::attribute
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Definition: qgsfeature.cpp:327
QgsStatisticalSummary::Majority
@ Majority
Majority of values.
Definition: qgsstatisticalsummary.h:61
QgsFeatureRequest::setFilterFids
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets the feature IDs that should be fetched.
Definition: qgsfeaturerequest.cpp:148
QgsFeatureRequest::setFeedback
void setFeedback(QgsFeedback *feedback)
Attach a feedback object that can be queried regularly by the iterator to check if it should be cance...
Definition: qgsfeaturerequest.cpp:402
typeName
const QString & typeName
Definition: qgswfsgetfeature.cpp:109
QgsAggregateCalculator::Median
@ Median
Median of values (numeric fields only)
Definition: qgsaggregatecalculator.h:76
QgsAggregateCalculator::Max
@ Max
Max of values.
Definition: qgsaggregatecalculator.h:73
QgsStatisticalSummary::CountMissing
@ CountMissing
Number of missing (null) values.
Definition: qgsstatisticalsummary.h:51
QgsFeatureIds
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
QgsAggregateCalculator::StringConcatenate
@ StringConcatenate
Concatenate values with a joining string (string fields only). Specify the delimiter using setDelimit...
Definition: qgsaggregatecalculator.h:87
QgsExpression::evaluate
QVariant evaluate()
Evaluate the feature and return the result.
Definition: qgsexpression.cpp:350
qgsvectorlayer.h
QgsAggregateCalculator::Mean
@ Mean
Mean of values (numeric fields only)
Definition: qgsaggregatecalculator.h:75
QgsStatisticalSummary::Statistic
Statistic
Enumeration of flags that specify statistics to be calculated.
Definition: qgsstatisticalsummary.h:48
QgsAggregateCalculator::ThirdQuartile
@ ThirdQuartile
Third quartile (numeric fields only)
Definition: qgsaggregatecalculator.h:83
QgsStatisticalSummary::Median
@ Median
Median of values.
Definition: qgsstatisticalsummary.h:54
QgsExpressionUtils::determineResultType
static std::tuple< QVariant::Type, int > determineResultType(const QString &expression, const QgsVectorLayer *layer, QgsFeatureRequest request=QgsFeatureRequest(), QgsExpressionContext context=QgsExpressionContext(), bool *foundFeatures=nullptr)
Returns a value type and user type for a given expression.
Definition: qgsexpressionutils.cpp:75
QgsAggregateCalculator::QgsAggregateCalculator
QgsAggregateCalculator(const QgsVectorLayer *layer)
Constructor for QgsAggregateCalculator.
Definition: qgsaggregatecalculator.cpp:28
qgsgeometry.h
QgsAggregateCalculator::Aggregate
Aggregate
Available aggregates to calculate.
Definition: qgsaggregatecalculator.h:67
QgsFeatureIterator::nextFeature
bool nextFeature(QgsFeature &f)
Definition: qgsfeatureiterator.h:399
QgsGeometry
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsAggregateCalculator::Majority
@ Majority
Majority of values.
Definition: qgsaggregatecalculator.h:81
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:391
QgsStatisticalSummary::Min
@ Min
Min of values.
Definition: qgsstatisticalsummary.h:57
QgsStringStatisticalSummary::MaximumLength
@ MaximumLength
Maximum length of string.
Definition: qgsstringstatisticalsummary.h:57
QgsAggregateCalculator::layer
const QgsVectorLayer * layer() const
Returns the associated vector layer.
Definition: qgsaggregatecalculator.cpp:34
QgsAggregateCalculator::setFidsFilter
void setFidsFilter(const QgsFeatureIds &fids)
Sets a filter to limit the features used during the aggregate calculation.
Definition: qgsaggregatecalculator.cpp:46
QgsDateTimeStatisticalSummary::Count
@ Count
Count.
Definition: qgsdatetimestatisticalsummary.h:52
QgsAggregateCalculator::setParameters
void setParameters(const AggregateParameters &parameters)
Sets all aggregate parameters from a parameter bundle.
Definition: qgsaggregatecalculator.cpp:39
QgsStringStatisticalSummary::CountMissing
@ CountMissing
Number of missing (null) values.
Definition: qgsstringstatisticalsummary.h:53
QgsStatisticalSummary::FirstQuartile
@ FirstQuartile
First quartile.
Definition: qgsstatisticalsummary.h:63
QgsFeatureRequest::setOrderBy
QgsFeatureRequest & setOrderBy(const OrderBy &orderBy)
Set a list of order by clauses.
Definition: qgsfeaturerequest.cpp:210
QgsAggregateCalculator::stringToAggregate
static Aggregate stringToAggregate(const QString &string, bool *ok=nullptr)
Converts a string to a aggregate type.
Definition: qgsaggregatecalculator.cpp:188
QgsDateTimeStatisticalSummary::Min
@ Min
Minimum (earliest) datetime value.
Definition: qgsdatetimestatisticalsummary.h:55
QgsAggregateCalculator::AggregateInfo
Structured information about the available aggregates.
Definition: qgsaggregatecalculator.h:53
QgsStatisticalSummary::Mean
@ Mean
Mean of values.
Definition: qgsstatisticalsummary.h:53
QgsAggregateCalculator::FirstQuartile
@ FirstQuartile
First quartile (numeric fields only)
Definition: qgsaggregatecalculator.h:82
QgsStatisticalSummary::Max
@ Max
Max of values.
Definition: qgsstatisticalsummary.h:58
QgsAggregateCalculator::Sum
@ Sum
Sum of values.
Definition: qgsaggregatecalculator.h:74
QgsAggregateCalculator::AggregateParameters::filter
QString filter
Optional filter for calculating aggregate over a subset of features, or an empty string to use all fe...
Definition: qgsaggregatecalculator.h:103
QgsAggregateCalculator::GeometryCollect
@ GeometryCollect
Create a multipart geometry from aggregated geometries.
Definition: qgsaggregatecalculator.h:88
QgsFeature
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:55
QgsStatisticalSummary::Count
@ Count
Count.
Definition: qgsstatisticalsummary.h:50
QgsExpression::expressionToLayerFieldIndex
static int expressionToLayerFieldIndex(const QString &expression, const QgsVectorLayer *layer)
Attempts to resolve an expression to a field index from the given layer.
Definition: qgsexpression.cpp:1365
QgsVectorLayer::createExpressionContext
QgsExpressionContext createExpressionContext() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
Definition: qgsvectorlayer.cpp:5203
QgsFields::at
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:163
QgsExpression
Class for parsing and evaluation of expressions (formerly called "search strings")....
Definition: qgsexpression.h:102
QgsDateTimeStatisticalSummary::CountDistinct
@ CountDistinct
Number of distinct datetime values.
Definition: qgsdatetimestatisticalsummary.h:53
QgsStringStatisticalSummary::MinimumLength
@ MinimumLength
Minimum length of string.
Definition: qgsstringstatisticalsummary.h:56
QgsDateTimeStatisticalSummary::Range
@ Range
Interval between earliest and latest datetime value.
Definition: qgsdatetimestatisticalsummary.h:57
QgsFeatureIterator
Wrapper for iterator of features from vector data provider or vector layer.
Definition: qgsfeatureiterator.h:289
QgsStringStatisticalSummary::Majority
@ Majority
Majority of strings.
Definition: qgsstringstatisticalsummary.h:60
QgsFeatureRequest::setFlags
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
Definition: qgsfeaturerequest.cpp:222
QgsAggregateCalculator::StringMaximumLength
@ StringMaximumLength
Maximum length of string (string fields only)
Definition: qgsaggregatecalculator.h:86
QgsField::type
QVariant::Type type
Definition: qgsfield.h:58
QgsStringStatisticalSummary
Calculator for summary statistics and aggregates for a list of strings.
Definition: qgsstringstatisticalsummary.h:44
QgsDateTimeStatisticalSummary
Calculator for summary statistics and aggregates for a list of datetimes.
Definition: qgsdatetimestatisticalsummary.h:45
QgsGeometry::collectGeometry
static QgsGeometry collectGeometry(const QVector< QgsGeometry > &geometries)
Creates a new multipart geometry from a list of QgsGeometry objects.
Definition: qgsgeometry.cpp:259
QgsStringStatisticalSummary::Min
@ Min
Minimum string value.
Definition: qgsstringstatisticalsummary.h:54
QgsStatisticalSummary::Variety
@ Variety
Variety (count of distinct) values.
Definition: qgsstatisticalsummary.h:62
QgsExpressionContext::setFeature
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Definition: qgsexpressioncontext.cpp:525