34using namespace Qt::StringLiterals;
49 mFilterExpression = parameters.
filter;
73 context = context ? context : &defaultContext;
75 std::unique_ptr<QgsExpression> expression;
83 expression = std::make_unique<QgsExpression>( fieldOrExpression );
85 if ( expression->hasParserError() || !expression->prepare( context ) )
87 mLastError = !expression->parserErrorString().isEmpty() ? expression->parserErrorString() : expression->evalErrorString();
94 lst.insert( mLayer->fields().at( attrNum ).name() );
96 lst = expression->referencedColumns();
98 bool expressionNeedsGeometry { expression &&expression->needsGeometry() };
100 if ( !mOrderBy.empty() )
105 if ( orderBy.expression().needsGeometry() )
107 expressionNeedsGeometry =
true;
113 request.
setFlags( expressionNeedsGeometry ?
121 if ( !mFilterExpression.isEmpty() )
129 QMetaType::Type resultType = QMetaType::Type::Double;
135 resultType = QMetaType::Type::User;
140 bool foundFeatures =
false;
142 if ( !foundFeatures )
146 return defaultValue( aggregate );
149 resultType = std::get<0>( returnType );
150 if ( resultType == QMetaType::Type::UnknownType )
194 resultType =
static_cast<QMetaType::Type
>( v.userType() );
199 resultType = mLayer->fields().at( attrNum ).type();
202 return calculate( aggregate, fit, resultType, attrNum, expression.get(), mDelimiter, context, ok, &mLastError );
207 const QString normalized =
string.trimmed().toLower();
212 if ( normalized ==
"count"_L1 )
214 else if ( normalized ==
"count_distinct"_L1 )
216 else if ( normalized ==
"count_missing"_L1 )
218 else if ( normalized ==
"min"_L1 || normalized ==
"minimum"_L1 )
220 else if ( normalized ==
"max"_L1 || normalized ==
"maximum"_L1 )
222 else if ( normalized ==
"sum"_L1 )
224 else if ( normalized ==
"mean"_L1 )
226 else if ( normalized ==
"median"_L1 )
228 else if ( normalized ==
"stdev"_L1 )
230 else if ( normalized ==
"stdevsample"_L1 )
232 else if ( normalized ==
"range"_L1 )
234 else if ( normalized ==
"minority"_L1 )
236 else if ( normalized ==
"majority"_L1 )
238 else if ( normalized ==
"q1"_L1 )
240 else if ( normalized ==
"q3"_L1 )
242 else if ( normalized ==
"iqr"_L1 )
244 else if ( normalized ==
"min_length"_L1 )
246 else if ( normalized ==
"max_length"_L1 )
248 else if ( normalized ==
"concatenate"_L1 )
250 else if ( normalized ==
"concatenate_unique"_L1 )
252 else if ( normalized ==
"collect"_L1 )
254 else if ( normalized ==
"array_agg"_L1 )
268 return QObject::tr(
"count" );
270 return QObject::tr(
"count distinct" );
272 return QObject::tr(
"count missing" );
274 return QObject::tr(
"minimum" );
276 return QObject::tr(
"maximum" );
278 return QObject::tr(
"sum" );
280 return QObject::tr(
"mean" );
282 return QObject::tr(
"median" );
284 return QObject::tr(
"standard deviation" );
286 return QObject::tr(
"standard deviation (sample)" );
288 return QObject::tr(
"range" );
290 return QObject::tr(
"minority" );
292 return QObject::tr(
"majority" );
294 return QObject::tr(
"first quartile" );
296 return QObject::tr(
"third quartile" );
298 return QObject::tr(
"inter quartile range" );
300 return QObject::tr(
"minimum length" );
302 return QObject::tr(
"maximum length" );
304 return QObject::tr(
"concatenate" );
306 return QObject::tr(
"collection" );
308 return QObject::tr(
"array aggregate" );
310 return QObject::tr(
"concatenate (unique)" );
322 QCoreApplication::tr(
"Count" ),
323 QSet<QMetaType::Type>()
324 << QMetaType::Type::QDateTime
325 << QMetaType::Type::QDate
326 << QMetaType::Type::Int
327 << QMetaType::Type::UInt
328 << QMetaType::Type::LongLong
329 << QMetaType::Type::ULongLong
330 << QMetaType::Type::QString
335 QCoreApplication::tr(
"Count Distinct" ),
336 QSet<QMetaType::Type>()
337 << QMetaType::Type::QDateTime
338 << QMetaType::Type::QDate
339 << QMetaType::Type::UInt
340 << QMetaType::Type::Int
341 << QMetaType::Type::LongLong
342 << QMetaType::Type::ULongLong
343 << QMetaType::Type::QString
348 QCoreApplication::tr(
"Count Missing" ),
349 QSet<QMetaType::Type>()
350 << QMetaType::Type::QDateTime
351 << QMetaType::Type::QDate
352 << QMetaType::Type::Int
353 << QMetaType::Type::UInt
354 << QMetaType::Type::LongLong
355 << QMetaType::Type::QString
360 QCoreApplication::tr(
"Min" ),
361 QSet<QMetaType::Type>()
362 << QMetaType::Type::QDateTime
363 << QMetaType::Type::QDate
364 << QMetaType::Type::Int
365 << QMetaType::Type::UInt
366 << QMetaType::Type::LongLong
367 << QMetaType::Type::ULongLong
368 << QMetaType::Type::Double
369 << QMetaType::Type::QString
374 QCoreApplication::tr(
"Max" ),
375 QSet<QMetaType::Type>()
376 << QMetaType::Type::QDateTime
377 << QMetaType::Type::QDate
378 << QMetaType::Type::Int
379 << QMetaType::Type::UInt
380 << QMetaType::Type::LongLong
381 << QMetaType::Type::ULongLong
382 << QMetaType::Type::Double
383 << QMetaType::Type::QString
388 QCoreApplication::tr(
"Sum" ),
389 QSet<QMetaType::Type>()
390 << QMetaType::Type::Int
391 << QMetaType::Type::UInt
392 << QMetaType::Type::LongLong
393 << QMetaType::Type::ULongLong
394 << QMetaType::Type::Double
399 QCoreApplication::tr(
"Mean" ),
400 QSet<QMetaType::Type>()
401 << QMetaType::Type::Int
402 << QMetaType::Type::UInt
403 << QMetaType::Type::LongLong
404 << QMetaType::Type::ULongLong
405 << QMetaType::Type::Double
410 QCoreApplication::tr(
"Median" ),
411 QSet<QMetaType::Type>()
412 << QMetaType::Type::Int
413 << QMetaType::Type::UInt
414 << QMetaType::Type::Double
419 QCoreApplication::tr(
"Stdev" ),
420 QSet<QMetaType::Type>()
421 << QMetaType::Type::Int
422 << QMetaType::Type::UInt
423 << QMetaType::Type::LongLong
424 << QMetaType::Type::ULongLong
425 << QMetaType::Type::Double
430 QCoreApplication::tr(
"Stdev Sample" ),
431 QSet<QMetaType::Type>()
432 << QMetaType::Type::Int
433 << QMetaType::Type::UInt
434 << QMetaType::Type::LongLong
435 << QMetaType::Type::ULongLong
436 << QMetaType::Type::Double
441 QCoreApplication::tr(
"Range" ),
442 QSet<QMetaType::Type>()
443 << QMetaType::Type::QDate
444 << QMetaType::Type::QDateTime
445 << QMetaType::Type::Int
446 << QMetaType::Type::UInt
447 << QMetaType::Type::LongLong
448 << QMetaType::Type::ULongLong
449 << QMetaType::Type::Double
454 QCoreApplication::tr(
"Minority" ),
455 QSet<QMetaType::Type>()
456 << QMetaType::Type::Int
457 << QMetaType::Type::UInt
458 << QMetaType::Type::LongLong
459 << QMetaType::Type::ULongLong
460 << QMetaType::Type::Double
461 << QMetaType::Type::QString
466 QCoreApplication::tr(
"Majority" ),
467 QSet<QMetaType::Type>()
468 << QMetaType::Type::Int
469 << QMetaType::Type::UInt
470 << QMetaType::Type::LongLong
471 << QMetaType::Type::ULongLong
472 << QMetaType::Type::Double
473 << QMetaType::Type::QString
478 QCoreApplication::tr(
"Q1" ),
479 QSet<QMetaType::Type>()
480 << QMetaType::Type::Int
481 << QMetaType::Type::UInt
482 << QMetaType::Type::LongLong
483 << QMetaType::Type::ULongLong
484 << QMetaType::Type::Double
489 QCoreApplication::tr(
"Q3" ),
490 QSet<QMetaType::Type>()
491 << QMetaType::Type::Int
492 << QMetaType::Type::UInt
493 << QMetaType::Type::LongLong
494 << QMetaType::Type::ULongLong
495 << QMetaType::Type::Double
500 QCoreApplication::tr(
"InterQuartileRange" ),
501 QSet<QMetaType::Type>()
502 << QMetaType::Type::Int
503 << QMetaType::Type::UInt
504 << QMetaType::Type::LongLong
505 << QMetaType::Type::ULongLong
506 << QMetaType::Type::Double
511 QCoreApplication::tr(
"Min Length" ),
512 QSet<QMetaType::Type>()
513 << QMetaType::Type::QString
518 QCoreApplication::tr(
"Max Length" ),
519 QSet<QMetaType::Type>()
520 << QMetaType::Type::QString
525 QCoreApplication::tr(
"Concatenate" ),
526 QSet<QMetaType::Type>()
527 << QMetaType::Type::QString
532 QCoreApplication::tr(
"Collect" ),
533 QSet<QMetaType::Type>()
538 QCoreApplication::tr(
"Array Aggregate" ),
539 QSet<QMetaType::Type>()
555 return calculateArrayAggregate( fit, attr, expression, context );
558 switch ( resultType )
560 case QMetaType::Type::Int:
561 case QMetaType::Type::UInt:
562 case QMetaType::Type::LongLong:
563 case QMetaType::Type::ULongLong:
564 case QMetaType::Type::Double:
567 const Qgis::Statistic stat = numericStatFromAggregate( aggregate, &statOk );
571 *error = expression ? QObject::tr(
"Cannot calculate %1 on numeric values" ).arg(
displayName( aggregate ) )
572 : QObject::tr(
"Cannot calculate %1 on numeric fields" ).arg(
displayName( aggregate ) );
578 return calculateNumericAggregate( fit, attr, expression, context, stat );
581 case QMetaType::Type::QDate:
582 case QMetaType::Type::QDateTime:
589 *error = ( expression ? QObject::tr(
"Cannot calculate %1 on %2 values" ).arg(
displayName( aggregate ) ) :
590 QObject::tr(
"Cannot calculate %1 on %2 fields" ).arg(
displayName( aggregate ) ) ).arg( resultType == QMetaType::Type::QDate ? QObject::tr(
"date" ) : QObject::tr(
"datetime" ) );
596 return calculateDateTimeAggregate( fit, attr, expression, context, stat );
599 case QMetaType::Type::User:
605 return calculateGeometryAggregate( fit, expression, context );
621 return concatenateStrings( fit, attr, expression, context,
delimiter );
628 return concatenateStrings( fit, attr, expression, context,
delimiter,
true );
636 if ( resultType == QMetaType::Type::UnknownType )
637 typeString = QObject::tr(
"null" );
639 typeString = resultType == QMetaType::Type::QString ? QObject::tr(
"string" ) : QVariant::typeToName( resultType );
642 *error = expression ? QObject::tr(
"Cannot calculate %1 on %3 values" ).arg(
displayName( aggregate ), typeString )
643 : QObject::tr(
"Cannot calculate %1 on %3 fields" ).arg(
displayName( aggregate ), typeString );
649 return calculateStringAggregate( fit, attr, expression, context, stat );
817 Q_ASSERT( expression || attr >= 0 );
819 QgsStatisticalSummary s( stat );
828 const QVariant v = expression->
evaluate( context );
837 const double val = s.statistic( stat );
838 return std::isnan( val ) ? QVariant() : val;
844 Q_ASSERT( expression || attr >= 0 );
846 QgsStringStatisticalSummary s( stat );
855 const QVariant v = expression->
evaluate( context );
864 return s.statistic( stat );
869 Q_ASSERT( expression );
872 QVector< QgsGeometry > geometries;
877 const QVariant v = expression->
evaluate( context );
878 if ( v.userType() == qMetaTypeId< QgsGeometry>() )
880 geometries << v.value<QgsGeometry>();
890 Q_ASSERT( expression || attr >= 0 );
901 const QVariant v = expression->
evaluate( context );
902 result = v.toString();
909 if ( !unique || !results.contains( result ) )
916QVariant QgsAggregateCalculator::defaultValue(
Qgis::Aggregate aggregate )
const
932 return QVariantList();
959 Q_ASSERT( expression || attr >= 0 );
961 QgsDateTimeStatisticalSummary s( stat );
970 const QVariant v = expression->
evaluate( context );
979 return s.statistic( stat );
985 Q_ASSERT( expression || attr >= 0 );
997 const QVariant v = expression->
evaluate( context );
Statistic
Available generic statistics.
@ StDev
Standard deviation of values.
@ FirstQuartile
First quartile.
@ Median
Median of values.
@ Range
Range of values (max - min).
@ Minority
Minority of values.
@ CountMissing
Number of missing (null) values.
@ Majority
Majority of values.
@ Variety
Variety (count of distinct) values.
@ StDevSample
Sample standard deviation of values.
@ ThirdQuartile
Third quartile.
@ InterQuartileRange
Inter quartile range (IQR).
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
@ NoFlags
No flags are set.
StringStatistic
Available string statistics.
@ Max
Maximum string value.
@ Min
Minimum string value.
@ MaximumLength
Maximum length of string.
@ Minority
Minority of strings.
@ CountMissing
Number of missing (null) values.
@ Majority
Majority of strings.
@ CountDistinct
Number of distinct string values.
@ MinimumLength
Minimum length of string.
Aggregate
Available aggregates to calculate.
@ StDev
Standard deviation of values (numeric fields only).
@ StringMinimumLength
Minimum length of string (string fields only).
@ FirstQuartile
First quartile (numeric fields only).
@ Mean
Mean of values (numeric fields only).
@ Median
Median of values (numeric fields only).
@ StringMaximumLength
Maximum length of string (string fields only).
@ Range
Range of values (max - min) (numeric and datetime fields only).
@ StringConcatenateUnique
Concatenate unique values with a joining string (string fields only). Specify the delimiter using set...
@ Minority
Minority of values.
@ CountMissing
Number of missing (null) values.
@ ArrayAggregate
Create an array of values.
@ Majority
Majority of values.
@ StDevSample
Sample standard deviation of values (numeric fields only).
@ ThirdQuartile
Third quartile (numeric fields only).
@ CountDistinct
Number of distinct values.
@ StringConcatenate
Concatenate values with a joining string (string fields only). Specify the delimiter using setDelimit...
@ GeometryCollect
Create a multipart geometry from aggregated geometries.
@ InterQuartileRange
Inter quartile range (IQR) (numeric fields only).
DateTimeStatistic
Available date/time statistics.
@ Max
Maximum (latest) datetime value.
@ Min
Minimum (earliest) datetime value.
@ Range
Interval between earliest and latest datetime value.
@ CountMissing
Number of missing (null) values.
@ CountDistinct
Number of distinct datetime values.
const QgsVectorLayer * layer() const
Returns the associated vector layer.
void setParameters(const AggregateParameters ¶meters)
Sets all aggregate parameters from a parameter bundle.
void setFidsFilter(const QgsFeatureIds &fids)
Sets a filter to limit the features used during the aggregate calculation.
static QList< QgsAggregateCalculator::AggregateInfo > aggregates()
Structured information for available aggregates.
QVariant calculate(Qgis::Aggregate aggregate, const QString &fieldOrExpression, QgsExpressionContext *context=nullptr, bool *ok=nullptr, QgsFeedback *feedback=nullptr) const
Calculates the value of an aggregate.
QString delimiter() const
Returns the delimiter used for joining values with the StringConcatenate aggregate.
static QString displayName(Qgis::Aggregate aggregate)
Returns the friendly display name for a aggregate.
static Qgis::Aggregate stringToAggregate(const QString &string, bool *ok=nullptr)
Converts a string to a aggregate type.
QgsAggregateCalculator(const QgsVectorLayer *layer)
Constructor for QgsAggregateCalculator.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly by the expression to check if evaluation sh...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
void setFields(const QgsFields &fields)
Convenience function for setting a fields for the context.
static std::tuple< QMetaType::Type, int > determineResultType(const QString &expression, const QgsVectorLayer *layer, const QgsFeatureRequest &request=QgsFeatureRequest(), const QgsExpressionContext &context=QgsExpressionContext(), bool *foundFeatures=nullptr)
Returns a value type and user type for a given expression.
Handles parsing and evaluation of expressions (formerly called "search strings").
static int expressionToLayerFieldIndex(const QString &expression, const QgsVectorLayer *layer)
Attempts to resolve an expression to a field index from the given layer.
QVariant evaluate()
Evaluate the feature and return the result.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
The OrderByClause class represents an order by clause for a QgsFeatureRequest.
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets the feature IDs that should be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
void setFeedback(QgsFeedback *feedback)
Attach a feedback object that can be queried regularly by the iterator to check if it should be cance...
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
QgsFeatureRequest & setOrderBy(const OrderBy &orderBy)
Set a list of order by clauses.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
A geometry is the spatial representation of a feature.
static QgsGeometry collectGeometry(const QVector< QgsGeometry > &geometries)
Creates a new multipart geometry from a list of QgsGeometry objects.
Represents a vector layer which manages a vector based dataset.
QSet< QgsFeatureId > QgsFeatureIds
Structured information about the available aggregates.
A bundle of parameters controlling aggregate calculation.
QString filter
Optional filter for calculating aggregate over a subset of features, or an empty string to use all fe...
QString delimiter
Delimiter to use for joining values with the StringConcatenate aggregate.
QgsFeatureRequest::OrderBy orderBy
Optional order by clauses.