34using namespace Qt::StringLiterals;
47 mFilterExpression = parameters.
filter;
70 context = context ? context : &defaultContext;
72 std::unique_ptr<QgsExpression> expression;
80 expression = std::make_unique<QgsExpression>( fieldOrExpression );
82 if ( expression->hasParserError() || !expression->prepare( context ) )
84 mLastError = !expression->parserErrorString().isEmpty() ? expression->parserErrorString() : expression->evalErrorString();
91 lst.insert( mLayer->fields().at( attrNum ).name() );
93 lst = expression->referencedColumns();
95 bool expressionNeedsGeometry { expression && expression->needsGeometry() };
97 if ( !mOrderBy.empty() )
102 if ( orderBy.expression().needsGeometry() )
104 expressionNeedsGeometry =
true;
115 if ( !mFilterExpression.isEmpty() )
123 QMetaType::Type resultType = QMetaType::Type::Double;
129 resultType = QMetaType::Type::User;
134 bool foundFeatures =
false;
136 if ( !foundFeatures )
140 return defaultValue( aggregate );
143 resultType = std::get<0>( returnType );
144 if ( resultType == QMetaType::Type::UnknownType )
188 resultType =
static_cast<QMetaType::Type
>( v.userType() );
193 resultType = mLayer->fields().at( attrNum ).type();
196 return calculate( aggregate, fit, resultType, attrNum, expression.get(), mDelimiter, context, ok, &mLastError );
201 const QString normalized =
string.trimmed().toLower();
206 if ( normalized ==
"count"_L1 )
208 else if ( normalized ==
"count_distinct"_L1 )
210 else if ( normalized ==
"count_missing"_L1 )
212 else if ( normalized ==
"min"_L1 || normalized ==
"minimum"_L1 )
214 else if ( normalized ==
"max"_L1 || normalized ==
"maximum"_L1 )
216 else if ( normalized ==
"sum"_L1 )
218 else if ( normalized ==
"mean"_L1 )
220 else if ( normalized ==
"median"_L1 )
222 else if ( normalized ==
"stdev"_L1 )
224 else if ( normalized ==
"stdevsample"_L1 )
226 else if ( normalized ==
"range"_L1 )
228 else if ( normalized ==
"minority"_L1 )
230 else if ( normalized ==
"majority"_L1 )
232 else if ( normalized ==
"q1"_L1 )
234 else if ( normalized ==
"q3"_L1 )
236 else if ( normalized ==
"iqr"_L1 )
238 else if ( normalized ==
"min_length"_L1 )
240 else if ( normalized ==
"max_length"_L1 )
242 else if ( normalized ==
"concatenate"_L1 )
244 else if ( normalized ==
"concatenate_unique"_L1 )
246 else if ( normalized ==
"collect"_L1 )
248 else if ( normalized ==
"array_agg"_L1 )
262 return QObject::tr(
"count" );
264 return QObject::tr(
"count distinct" );
266 return QObject::tr(
"count missing" );
268 return QObject::tr(
"minimum" );
270 return QObject::tr(
"maximum" );
272 return QObject::tr(
"sum" );
274 return QObject::tr(
"mean" );
276 return QObject::tr(
"median" );
278 return QObject::tr(
"standard deviation" );
280 return QObject::tr(
"standard deviation (sample)" );
282 return QObject::tr(
"range" );
284 return QObject::tr(
"minority" );
286 return QObject::tr(
"majority" );
288 return QObject::tr(
"first quartile" );
290 return QObject::tr(
"third quartile" );
292 return QObject::tr(
"inter quartile range" );
294 return QObject::tr(
"minimum length" );
296 return QObject::tr(
"maximum length" );
298 return QObject::tr(
"concatenate" );
300 return QObject::tr(
"collection" );
302 return QObject::tr(
"array aggregate" );
304 return QObject::tr(
"concatenate (unique)" );
313 <<
AggregateInfo { u
"count"_s, QCoreApplication::tr(
"Count" ), QSet<QMetaType::Type>() << QMetaType::Type::QDateTime << QMetaType::Type::QDate << QMetaType::Type::Int << QMetaType::Type::UInt << QMetaType::Type::LongLong << QMetaType::Type::ULongLong << QMetaType::Type::QString }
314 <<
AggregateInfo { u
"count_distinct"_s, QCoreApplication::tr(
"Count Distinct" ), QSet<QMetaType::Type>() << QMetaType::Type::QDateTime << QMetaType::Type::QDate << QMetaType::Type::UInt << QMetaType::Type::Int << QMetaType::Type::LongLong << QMetaType::Type::ULongLong << QMetaType::Type::QString }
315 <<
AggregateInfo { u
"count_missing"_s, QCoreApplication::tr(
"Count Missing" ), QSet<QMetaType::Type>() << QMetaType::Type::QDateTime << QMetaType::Type::QDate << QMetaType::Type::Int << QMetaType::Type::UInt << QMetaType::Type::LongLong << QMetaType::Type::QString }
316 <<
AggregateInfo { u
"min"_s, QCoreApplication::tr(
"Min" ), QSet<QMetaType::Type>() << QMetaType::Type::QDateTime << QMetaType::Type::QDate << QMetaType::Type::Int << QMetaType::Type::UInt << QMetaType::Type::LongLong << QMetaType::Type::ULongLong << QMetaType::Type::Double << QMetaType::Type::QString }
317 <<
AggregateInfo { u
"max"_s, QCoreApplication::tr(
"Max" ), QSet<QMetaType::Type>() << QMetaType::Type::QDateTime << QMetaType::Type::QDate << QMetaType::Type::Int << QMetaType::Type::UInt << QMetaType::Type::LongLong << QMetaType::Type::ULongLong << QMetaType::Type::Double << QMetaType::Type::QString }
318 <<
AggregateInfo { u
"sum"_s, QCoreApplication::tr(
"Sum" ), QSet<QMetaType::Type>() << QMetaType::Type::Int << QMetaType::Type::UInt << QMetaType::Type::LongLong << QMetaType::Type::ULongLong << QMetaType::Type::Double }
319 <<
AggregateInfo { u
"mean"_s, QCoreApplication::tr(
"Mean" ), QSet<QMetaType::Type>() << QMetaType::Type::Int << QMetaType::Type::UInt << QMetaType::Type::LongLong << QMetaType::Type::ULongLong << QMetaType::Type::Double }
320 <<
AggregateInfo { u
"median"_s, QCoreApplication::tr(
"Median" ), QSet<QMetaType::Type>() << QMetaType::Type::Int << QMetaType::Type::UInt << QMetaType::Type::Double }
321 <<
AggregateInfo { u
"stdev"_s, QCoreApplication::tr(
"Stdev" ), QSet<QMetaType::Type>() << QMetaType::Type::Int << QMetaType::Type::UInt << QMetaType::Type::LongLong << QMetaType::Type::ULongLong << QMetaType::Type::Double }
322 <<
AggregateInfo { u
"stdevsample"_s, QCoreApplication::tr(
"Stdev Sample" ), QSet<QMetaType::Type>() << QMetaType::Type::Int << QMetaType::Type::UInt << QMetaType::Type::LongLong << QMetaType::Type::ULongLong << QMetaType::Type::Double }
323 <<
AggregateInfo { u
"range"_s, QCoreApplication::tr(
"Range" ), QSet<QMetaType::Type>() << QMetaType::Type::QDate << QMetaType::Type::QDateTime << QMetaType::Type::Int << QMetaType::Type::UInt << QMetaType::Type::LongLong << QMetaType::Type::ULongLong << QMetaType::Type::Double }
324 <<
AggregateInfo { u
"minority"_s, QCoreApplication::tr(
"Minority" ), QSet<QMetaType::Type>() << QMetaType::Type::Int << QMetaType::Type::UInt << QMetaType::Type::LongLong << QMetaType::Type::ULongLong << QMetaType::Type::Double << QMetaType::Type::QString }
325 <<
AggregateInfo { u
"majority"_s, QCoreApplication::tr(
"Majority" ), QSet<QMetaType::Type>() << QMetaType::Type::Int << QMetaType::Type::UInt << QMetaType::Type::LongLong << QMetaType::Type::ULongLong << QMetaType::Type::Double << QMetaType::Type::QString }
326 <<
AggregateInfo { u
"q1"_s, QCoreApplication::tr(
"Q1" ), QSet<QMetaType::Type>() << QMetaType::Type::Int << QMetaType::Type::UInt << QMetaType::Type::LongLong << QMetaType::Type::ULongLong << QMetaType::Type::Double }
327 <<
AggregateInfo { u
"q3"_s, QCoreApplication::tr(
"Q3" ), QSet<QMetaType::Type>() << QMetaType::Type::Int << QMetaType::Type::UInt << QMetaType::Type::LongLong << QMetaType::Type::ULongLong << QMetaType::Type::Double }
328 <<
AggregateInfo { u
"iqr"_s, QCoreApplication::tr(
"InterQuartileRange" ), QSet<QMetaType::Type>() << QMetaType::Type::Int << QMetaType::Type::UInt << QMetaType::Type::LongLong << QMetaType::Type::ULongLong << QMetaType::Type::Double }
329 <<
AggregateInfo { u
"min_length"_s, QCoreApplication::tr(
"Min Length" ), QSet<QMetaType::Type>() << QMetaType::Type::QString }
330 <<
AggregateInfo { u
"max_length"_s, QCoreApplication::tr(
"Max Length" ), QSet<QMetaType::Type>() << QMetaType::Type::QString }
331 <<
AggregateInfo { u
"concatenate"_s, QCoreApplication::tr(
"Concatenate" ), QSet<QMetaType::Type>() << QMetaType::Type::QString }
332 <<
AggregateInfo { u
"collect"_s, QCoreApplication::tr(
"Collect" ), QSet<QMetaType::Type>() }
333 <<
AggregateInfo { u
"array_agg"_s, QCoreApplication::tr(
"Array Aggregate" ), QSet<QMetaType::Type>() };
349 return calculateArrayAggregate( fit, attr, expression, context );
352 switch ( resultType )
354 case QMetaType::Type::Int:
355 case QMetaType::Type::UInt:
356 case QMetaType::Type::LongLong:
357 case QMetaType::Type::ULongLong:
358 case QMetaType::Type::Double:
361 const Qgis::Statistic stat = numericStatFromAggregate( aggregate, &statOk );
365 *error = expression ? QObject::tr(
"Cannot calculate %1 on numeric values" ).arg(
displayName( aggregate ) )
366 : QObject::tr(
"Cannot calculate %1 on numeric fields" ).arg(
displayName( aggregate ) );
372 return calculateNumericAggregate( fit, attr, expression, context, stat );
375 case QMetaType::Type::QDate:
376 case QMetaType::Type::QDateTime:
383 *error = ( expression ? QObject::tr(
"Cannot calculate %1 on %2 values" ).arg(
displayName( aggregate ) ) : QObject::tr(
"Cannot calculate %1 on %2 fields" ).arg(
displayName( aggregate ) ) )
384 .arg( resultType == QMetaType::Type::QDate ? QObject::tr(
"date" ) : QObject::tr(
"datetime" ) );
390 return calculateDateTimeAggregate( fit, attr, expression, context, stat );
393 case QMetaType::Type::User:
399 return calculateGeometryAggregate( fit, expression, context );
415 return concatenateStrings( fit, attr, expression, context,
delimiter );
422 return concatenateStrings( fit, attr, expression, context,
delimiter,
true );
430 if ( resultType == QMetaType::Type::UnknownType )
431 typeString = QObject::tr(
"null" );
433 typeString = resultType == QMetaType::Type::QString ? QObject::tr(
"string" ) : QVariant::typeToName( resultType );
436 *error = expression ? QObject::tr(
"Cannot calculate %1 on %3 values" ).arg(
displayName( aggregate ), typeString )
437 : QObject::tr(
"Cannot calculate %1 on %3 fields" ).arg(
displayName( aggregate ), typeString );
443 return calculateStringAggregate( fit, attr, expression, context, stat );
610 Q_ASSERT( expression || attr >= 0 );
612 QgsStatisticalSummary s( stat );
621 const QVariant v = expression->
evaluate( context );
630 const double val = s.statistic( stat );
631 return std::isnan( val ) ? QVariant() : val;
636 Q_ASSERT( expression || attr >= 0 );
638 QgsStringStatisticalSummary s( stat );
647 const QVariant v = expression->
evaluate( context );
656 return s.statistic( stat );
661 Q_ASSERT( expression );
664 QVector< QgsGeometry > geometries;
669 const QVariant v = expression->
evaluate( context );
670 if ( v.userType() == qMetaTypeId< QgsGeometry>() )
672 geometries << v.value<QgsGeometry>();
681 Q_ASSERT( expression || attr >= 0 );
692 const QVariant v = expression->
evaluate( context );
693 result = v.toString();
700 if ( !unique || !results.contains( result ) )
707QVariant QgsAggregateCalculator::defaultValue(
Qgis::Aggregate aggregate )
const
723 return QVariantList();
749 Q_ASSERT( expression || attr >= 0 );
751 QgsDateTimeStatisticalSummary s( stat );
760 const QVariant v = expression->
evaluate( context );
769 return s.statistic( stat );
774 Q_ASSERT( expression || attr >= 0 );
786 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.