Branch data Line data Source code
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 "qgsfeature.h"
20 : : #include "qgsfeaturerequest.h"
21 : : #include "qgsfeatureiterator.h"
22 : : #include "qgsgeometry.h"
23 : : #include "qgsvectorlayer.h"
24 : :
25 : :
26 : :
27 : 0 : QgsAggregateCalculator::QgsAggregateCalculator( const QgsVectorLayer *layer )
28 : 0 : : mLayer( layer )
29 : : {
30 : :
31 : 0 : }
32 : :
33 : 0 : const QgsVectorLayer *QgsAggregateCalculator::layer() const
34 : : {
35 : 0 : return mLayer;
36 : : }
37 : :
38 : 0 : void QgsAggregateCalculator::setParameters( const AggregateParameters ¶meters )
39 : : {
40 : 0 : mFilterExpression = parameters.filter;
41 : 0 : mDelimiter = parameters.delimiter;
42 : 0 : mOrderBy = parameters.orderBy;
43 : 0 : }
44 : :
45 : 0 : void QgsAggregateCalculator::setFidsFilter( const QgsFeatureIds &fids )
46 : : {
47 : 0 : mFidsSet = true;
48 : 0 : mFidsFilter = fids;
49 : 0 : }
50 : :
51 : 0 : QVariant QgsAggregateCalculator::calculate( QgsAggregateCalculator::Aggregate aggregate,
52 : : const QString &fieldOrExpression, QgsExpressionContext *context, bool *ok ) const
53 : : {
54 : 0 : if ( ok )
55 : 0 : *ok = false;
56 : :
57 : 0 : QgsFeatureRequest request = QgsFeatureRequest();
58 : :
59 : 0 : if ( !mLayer )
60 : 0 : return QVariant();
61 : :
62 : 0 : QgsExpressionContext defaultContext = mLayer->createExpressionContext();
63 : 0 : context = context ? context : &defaultContext;
64 : :
65 : 0 : std::unique_ptr<QgsExpression> expression;
66 : :
67 : 0 : int attrNum = mLayer->fields().lookupField( fieldOrExpression );
68 : :
69 : 0 : if ( attrNum == -1 )
70 : : {
71 : : Q_ASSERT( context );
72 : 0 : context->setFields( mLayer->fields() );
73 : : // try to use expression
74 : 0 : expression.reset( new QgsExpression( fieldOrExpression ) );
75 : :
76 : 0 : if ( expression->hasParserError() || !expression->prepare( context ) )
77 : 0 : return QVariant();
78 : 0 : }
79 : :
80 : 0 : QSet<QString> lst;
81 : 0 : if ( !expression )
82 : 0 : lst.insert( fieldOrExpression );
83 : : else
84 : 0 : lst = expression->referencedColumns();
85 : :
86 : 0 : request.setFlags( ( expression && expression->needsGeometry() ) ?
87 : : QgsFeatureRequest::NoFlags :
88 : : QgsFeatureRequest::NoGeometry )
89 : 0 : .setSubsetOfAttributes( lst, mLayer->fields() );
90 : :
91 : 0 : if ( mFidsSet )
92 : 0 : request.setFilterFids( mFidsFilter );
93 : :
94 : 0 : if ( !mOrderBy.empty() )
95 : 0 : request.setOrderBy( mOrderBy );
96 : :
97 : 0 : if ( !mFilterExpression.isEmpty() )
98 : 0 : request.setFilterExpression( mFilterExpression );
99 : 0 : if ( context )
100 : 0 : request.setExpressionContext( *context );
101 : : //determine result type
102 : 0 : QVariant::Type resultType = QVariant::Double;
103 : 0 : if ( attrNum == -1 )
104 : : {
105 : 0 : if ( aggregate == GeometryCollect )
106 : : {
107 : : // in this case we know the result should be a geometry value, so no need to sniff it out...
108 : 0 : resultType = QVariant::UserType;
109 : 0 : }
110 : : else
111 : : {
112 : : // evaluate first feature, check result type
113 : 0 : QgsFeatureRequest testRequest( request );
114 : 0 : testRequest.setLimit( 1 );
115 : 0 : QgsFeature f;
116 : 0 : QgsFeatureIterator fit = mLayer->getFeatures( testRequest );
117 : 0 : if ( !fit.nextFeature( f ) )
118 : : {
119 : : //no matching features
120 : 0 : if ( ok )
121 : 0 : *ok = true;
122 : 0 : return defaultValue( aggregate );
123 : : }
124 : :
125 : 0 : if ( context )
126 : 0 : context->setFeature( f );
127 : 0 : QVariant v = expression->evaluate( context );
128 : 0 : resultType = v.type();
129 : 0 : }
130 : 0 : }
131 : : else
132 : 0 : resultType = mLayer->fields().at( attrNum ).type();
133 : :
134 : 0 : QgsFeatureIterator fit = mLayer->getFeatures( request );
135 : 0 : return calculate( aggregate, fit, resultType, attrNum, expression.get(), mDelimiter, context, ok );
136 : 0 : }
137 : :
138 : 0 : QgsAggregateCalculator::Aggregate QgsAggregateCalculator::stringToAggregate( const QString &string, bool *ok )
139 : : {
140 : 0 : QString normalized = string.trimmed().toLower();
141 : :
142 : 0 : if ( ok )
143 : 0 : *ok = true;
144 : :
145 : 0 : if ( normalized == QLatin1String( "count" ) )
146 : 0 : return Count;
147 : 0 : else if ( normalized == QLatin1String( "count_distinct" ) )
148 : 0 : return CountDistinct;
149 : 0 : else if ( normalized == QLatin1String( "count_missing" ) )
150 : 0 : return CountMissing;
151 : 0 : else if ( normalized == QLatin1String( "min" ) )
152 : 0 : return Min;
153 : 0 : else if ( normalized == QLatin1String( "max" ) )
154 : 0 : return Max;
155 : 0 : else if ( normalized == QLatin1String( "sum" ) )
156 : 0 : return Sum;
157 : 0 : else if ( normalized == QLatin1String( "mean" ) )
158 : 0 : return Mean;
159 : 0 : else if ( normalized == QLatin1String( "median" ) )
160 : 0 : return Median;
161 : 0 : else if ( normalized == QLatin1String( "stdev" ) )
162 : 0 : return StDev;
163 : 0 : else if ( normalized == QLatin1String( "stdevsample" ) )
164 : 0 : return StDevSample;
165 : 0 : else if ( normalized == QLatin1String( "range" ) )
166 : 0 : return Range;
167 : 0 : else if ( normalized == QLatin1String( "minority" ) )
168 : 0 : return Minority;
169 : 0 : else if ( normalized == QLatin1String( "majority" ) )
170 : 0 : return Majority;
171 : 0 : else if ( normalized == QLatin1String( "q1" ) )
172 : 0 : return FirstQuartile;
173 : 0 : else if ( normalized == QLatin1String( "q3" ) )
174 : 0 : return ThirdQuartile;
175 : 0 : else if ( normalized == QLatin1String( "iqr" ) )
176 : 0 : return InterQuartileRange;
177 : 0 : else if ( normalized == QLatin1String( "min_length" ) )
178 : 0 : return StringMinimumLength;
179 : 0 : else if ( normalized == QLatin1String( "max_length" ) )
180 : 0 : return StringMaximumLength;
181 : 0 : else if ( normalized == QLatin1String( "concatenate" ) )
182 : 0 : return StringConcatenate;
183 : 0 : else if ( normalized == QLatin1String( "concatenate_unique" ) )
184 : 0 : return StringConcatenateUnique;
185 : 0 : else if ( normalized == QLatin1String( "collect" ) )
186 : 0 : return GeometryCollect;
187 : 0 : else if ( normalized == QLatin1String( "array_agg" ) )
188 : 0 : return ArrayAggregate;
189 : :
190 : 0 : if ( ok )
191 : 0 : *ok = false;
192 : :
193 : 0 : return Count;
194 : 0 : }
195 : :
196 : 0 : QList<QgsAggregateCalculator::AggregateInfo> QgsAggregateCalculator::aggregates()
197 : : {
198 : 0 : QList< AggregateInfo > aggregates;
199 : 0 : aggregates
200 : 0 : << AggregateInfo
201 : 0 : {
202 : 0 : QStringLiteral( "count" ),
203 : 0 : QCoreApplication::tr( "Count" ),
204 : 0 : QSet<QVariant::Type>()
205 : 0 : << QVariant::DateTime
206 : 0 : << QVariant::Date
207 : 0 : << QVariant::Int
208 : 0 : << QVariant::UInt
209 : 0 : << QVariant::LongLong
210 : 0 : << QVariant::ULongLong
211 : 0 : << QVariant::String
212 : 0 : }
213 : 0 : << AggregateInfo
214 : 0 : {
215 : 0 : QStringLiteral( "count_distinct" ),
216 : 0 : QCoreApplication::tr( "Count Distinct" ),
217 : 0 : QSet<QVariant::Type>()
218 : 0 : << QVariant::DateTime
219 : 0 : << QVariant::Date
220 : 0 : << QVariant::UInt
221 : 0 : << QVariant::Int
222 : 0 : << QVariant::LongLong
223 : 0 : << QVariant::ULongLong
224 : 0 : << QVariant::String
225 : : }
226 : 0 : << AggregateInfo
227 : 0 : {
228 : 0 : QStringLiteral( "count_missing" ),
229 : 0 : QCoreApplication::tr( "Count Missing" ),
230 : 0 : QSet<QVariant::Type>()
231 : 0 : << QVariant::DateTime
232 : 0 : << QVariant::Date
233 : 0 : << QVariant::Int
234 : 0 : << QVariant::UInt
235 : 0 : << QVariant::LongLong
236 : 0 : << QVariant::String
237 : : }
238 : 0 : << AggregateInfo
239 : 0 : {
240 : 0 : QStringLiteral( "min" ),
241 : 0 : QCoreApplication::tr( "Min" ),
242 : 0 : QSet<QVariant::Type>()
243 : 0 : << QVariant::DateTime
244 : 0 : << QVariant::Date
245 : 0 : << QVariant::Int
246 : 0 : << QVariant::UInt
247 : 0 : << QVariant::LongLong
248 : 0 : << QVariant::ULongLong
249 : 0 : << QVariant::Double
250 : 0 : << QVariant::String
251 : : }
252 : 0 : << AggregateInfo
253 : 0 : {
254 : 0 : QStringLiteral( "max" ),
255 : 0 : QCoreApplication::tr( "Max" ),
256 : 0 : QSet<QVariant::Type>()
257 : 0 : << QVariant::DateTime
258 : 0 : << QVariant::Date
259 : 0 : << QVariant::Int
260 : 0 : << QVariant::UInt
261 : 0 : << QVariant::LongLong
262 : 0 : << QVariant::ULongLong
263 : 0 : << QVariant::Double
264 : 0 : << QVariant::String
265 : : }
266 : 0 : << AggregateInfo
267 : 0 : {
268 : 0 : QStringLiteral( "sum" ),
269 : 0 : QCoreApplication::tr( "Sum" ),
270 : 0 : QSet<QVariant::Type>()
271 : 0 : << QVariant::Int
272 : 0 : << QVariant::UInt
273 : 0 : << QVariant::LongLong
274 : 0 : << QVariant::ULongLong
275 : 0 : << QVariant::Double
276 : : }
277 : 0 : << AggregateInfo
278 : 0 : {
279 : 0 : QStringLiteral( "mean" ),
280 : 0 : QCoreApplication::tr( "Mean" ),
281 : 0 : QSet<QVariant::Type>()
282 : 0 : << QVariant::Int
283 : 0 : << QVariant::UInt
284 : 0 : << QVariant::LongLong
285 : 0 : << QVariant::ULongLong
286 : 0 : << QVariant::Double
287 : : }
288 : 0 : << AggregateInfo
289 : 0 : {
290 : 0 : QStringLiteral( "median" ),
291 : 0 : QCoreApplication::tr( "Median" ),
292 : 0 : QSet<QVariant::Type>()
293 : 0 : << QVariant::Int
294 : 0 : << QVariant::UInt
295 : 0 : << QVariant::Double
296 : : }
297 : 0 : << AggregateInfo
298 : 0 : {
299 : 0 : QStringLiteral( "stdev" ),
300 : 0 : QCoreApplication::tr( "Stdev" ),
301 : 0 : QSet<QVariant::Type>()
302 : 0 : << QVariant::Int
303 : 0 : << QVariant::UInt
304 : 0 : << QVariant::LongLong
305 : 0 : << QVariant::ULongLong
306 : 0 : << QVariant::Double
307 : : }
308 : 0 : << AggregateInfo
309 : 0 : {
310 : 0 : QStringLiteral( "stdevsample" ),
311 : 0 : QCoreApplication::tr( "Stdev Sample" ),
312 : 0 : QSet<QVariant::Type>()
313 : 0 : << QVariant::Int
314 : 0 : << QVariant::UInt
315 : 0 : << QVariant::LongLong
316 : 0 : << QVariant::ULongLong
317 : 0 : << QVariant::Double
318 : : }
319 : 0 : << AggregateInfo
320 : 0 : {
321 : 0 : QStringLiteral( "range" ),
322 : 0 : QCoreApplication::tr( "Range" ),
323 : 0 : QSet<QVariant::Type>()
324 : 0 : << QVariant::Date
325 : 0 : << QVariant::DateTime
326 : 0 : << QVariant::Int
327 : 0 : << QVariant::UInt
328 : 0 : << QVariant::LongLong
329 : 0 : << QVariant::ULongLong
330 : 0 : << QVariant::Double
331 : : }
332 : 0 : << AggregateInfo
333 : 0 : {
334 : 0 : QStringLiteral( "minority" ),
335 : 0 : QCoreApplication::tr( "Minority" ),
336 : 0 : QSet<QVariant::Type>()
337 : 0 : << QVariant::Int
338 : 0 : << QVariant::UInt
339 : 0 : << QVariant::LongLong
340 : 0 : << QVariant::ULongLong
341 : 0 : << QVariant::Double
342 : 0 : << QVariant::String
343 : : }
344 : 0 : << AggregateInfo
345 : 0 : {
346 : 0 : QStringLiteral( "majority" ),
347 : 0 : QCoreApplication::tr( "Majority" ),
348 : 0 : QSet<QVariant::Type>()
349 : 0 : << QVariant::Int
350 : 0 : << QVariant::UInt
351 : 0 : << QVariant::LongLong
352 : 0 : << QVariant::ULongLong
353 : 0 : << QVariant::Double
354 : 0 : << QVariant::String
355 : : }
356 : 0 : << AggregateInfo
357 : 0 : {
358 : 0 : QStringLiteral( "q1" ),
359 : 0 : QCoreApplication::tr( "Q1" ),
360 : 0 : QSet<QVariant::Type>()
361 : 0 : << QVariant::Int
362 : 0 : << QVariant::UInt
363 : 0 : << QVariant::LongLong
364 : 0 : << QVariant::ULongLong
365 : 0 : << QVariant::Double
366 : : }
367 : 0 : << AggregateInfo
368 : 0 : {
369 : 0 : QStringLiteral( "q3" ),
370 : 0 : QCoreApplication::tr( "Q3" ),
371 : 0 : QSet<QVariant::Type>()
372 : 0 : << QVariant::Int
373 : 0 : << QVariant::UInt
374 : 0 : << QVariant::LongLong
375 : 0 : << QVariant::ULongLong
376 : 0 : << QVariant::Double
377 : : }
378 : 0 : << AggregateInfo
379 : 0 : {
380 : 0 : QStringLiteral( "iqr" ),
381 : 0 : QCoreApplication::tr( "InterQuartileRange" ),
382 : 0 : QSet<QVariant::Type>()
383 : 0 : << QVariant::Int
384 : 0 : << QVariant::UInt
385 : 0 : << QVariant::LongLong
386 : 0 : << QVariant::ULongLong
387 : 0 : << QVariant::Double
388 : : }
389 : 0 : << AggregateInfo
390 : 0 : {
391 : 0 : QStringLiteral( "min_length" ),
392 : 0 : QCoreApplication::tr( "Min Length" ),
393 : 0 : QSet<QVariant::Type>()
394 : 0 : << QVariant::String
395 : : }
396 : 0 : << AggregateInfo
397 : 0 : {
398 : 0 : QStringLiteral( "max_length" ),
399 : 0 : QCoreApplication::tr( "Max Length" ),
400 : 0 : QSet<QVariant::Type>()
401 : 0 : << QVariant::String
402 : : }
403 : 0 : << AggregateInfo
404 : 0 : {
405 : 0 : QStringLiteral( "concatenate" ),
406 : 0 : QCoreApplication::tr( "Concatenate" ),
407 : 0 : QSet<QVariant::Type>()
408 : 0 : << QVariant::String
409 : : }
410 : 0 : << AggregateInfo
411 : 0 : {
412 : 0 : QStringLiteral( "collect" ),
413 : 0 : QCoreApplication::tr( "Collect" ),
414 : 0 : QSet<QVariant::Type>()
415 : : }
416 : 0 : << AggregateInfo
417 : 0 : {
418 : 0 : QStringLiteral( "array_agg" ),
419 : 0 : QCoreApplication::tr( "Array Aggregate" ),
420 : 0 : QSet<QVariant::Type>()
421 : : };
422 : :
423 : 0 : return aggregates;
424 : 0 : }
425 : :
426 : 0 : QVariant QgsAggregateCalculator::calculate( QgsAggregateCalculator::Aggregate aggregate, QgsFeatureIterator &fit, QVariant::Type resultType,
427 : : int attr, QgsExpression *expression, const QString &delimiter, QgsExpressionContext *context, bool *ok )
428 : : {
429 : 0 : if ( ok )
430 : 0 : *ok = false;
431 : :
432 : 0 : if ( aggregate == QgsAggregateCalculator::ArrayAggregate )
433 : : {
434 : 0 : if ( ok )
435 : 0 : *ok = true;
436 : 0 : return calculateArrayAggregate( fit, attr, expression, context );
437 : : }
438 : :
439 : 0 : switch ( resultType )
440 : : {
441 : : case QVariant::Int:
442 : : case QVariant::UInt:
443 : : case QVariant::LongLong:
444 : : case QVariant::ULongLong:
445 : : case QVariant::Double:
446 : : {
447 : 0 : bool statOk = false;
448 : 0 : QgsStatisticalSummary::Statistic stat = numericStatFromAggregate( aggregate, &statOk );
449 : 0 : if ( !statOk )
450 : 0 : return QVariant();
451 : :
452 : 0 : if ( ok )
453 : 0 : *ok = true;
454 : 0 : return calculateNumericAggregate( fit, attr, expression, context, stat );
455 : : }
456 : :
457 : : case QVariant::Date:
458 : : case QVariant::DateTime:
459 : : {
460 : 0 : bool statOk = false;
461 : 0 : QgsDateTimeStatisticalSummary::Statistic stat = dateTimeStatFromAggregate( aggregate, &statOk );
462 : 0 : if ( !statOk )
463 : 0 : return QVariant();
464 : :
465 : 0 : if ( ok )
466 : 0 : *ok = true;
467 : 0 : return calculateDateTimeAggregate( fit, attr, expression, context, stat );
468 : : }
469 : :
470 : : case QVariant::UserType:
471 : : {
472 : 0 : if ( aggregate == GeometryCollect )
473 : : {
474 : 0 : if ( ok )
475 : 0 : *ok = true;
476 : 0 : return calculateGeometryAggregate( fit, expression, context );
477 : : }
478 : : else
479 : : {
480 : 0 : return QVariant();
481 : : }
482 : : }
483 : :
484 : : default:
485 : : {
486 : : // treat as string
487 : 0 : if ( aggregate == StringConcatenate )
488 : : {
489 : : //special case
490 : 0 : if ( ok )
491 : 0 : *ok = true;
492 : 0 : return concatenateStrings( fit, attr, expression, context, delimiter );
493 : : }
494 : 0 : else if ( aggregate == StringConcatenateUnique )
495 : : {
496 : : //special case
497 : 0 : if ( ok )
498 : 0 : *ok = true;
499 : 0 : return concatenateStrings( fit, attr, expression, context, delimiter, true );
500 : : }
501 : :
502 : 0 : bool statOk = false;
503 : 0 : QgsStringStatisticalSummary::Statistic stat = stringStatFromAggregate( aggregate, &statOk );
504 : 0 : if ( !statOk )
505 : 0 : return QVariant();
506 : :
507 : 0 : if ( ok )
508 : 0 : *ok = true;
509 : 0 : return calculateStringAggregate( fit, attr, expression, context, stat );
510 : : }
511 : : }
512 : :
513 : : #ifndef _MSC_VER
514 : : return QVariant();
515 : : #endif
516 : 0 : }
517 : :
518 : 0 : QgsStatisticalSummary::Statistic QgsAggregateCalculator::numericStatFromAggregate( QgsAggregateCalculator::Aggregate aggregate, bool *ok )
519 : : {
520 : 0 : if ( ok )
521 : 0 : *ok = true;
522 : :
523 : 0 : switch ( aggregate )
524 : : {
525 : : case Count:
526 : 0 : return QgsStatisticalSummary::Count;
527 : : case CountDistinct:
528 : 0 : return QgsStatisticalSummary::Variety;
529 : : case CountMissing:
530 : 0 : return QgsStatisticalSummary::CountMissing;
531 : : case Min:
532 : 0 : return QgsStatisticalSummary::Min;
533 : : case Max:
534 : 0 : return QgsStatisticalSummary::Max;
535 : : case Sum:
536 : 0 : return QgsStatisticalSummary::Sum;
537 : : case Mean:
538 : 0 : return QgsStatisticalSummary::Mean;
539 : : case Median:
540 : 0 : return QgsStatisticalSummary::Median;
541 : : case StDev:
542 : 0 : return QgsStatisticalSummary::StDev;
543 : : case StDevSample:
544 : 0 : return QgsStatisticalSummary::StDevSample;
545 : : case Range:
546 : 0 : return QgsStatisticalSummary::Range;
547 : : case Minority:
548 : 0 : return QgsStatisticalSummary::Minority;
549 : : case Majority:
550 : 0 : return QgsStatisticalSummary::Majority;
551 : : case FirstQuartile:
552 : 0 : return QgsStatisticalSummary::FirstQuartile;
553 : : case ThirdQuartile:
554 : 0 : return QgsStatisticalSummary::ThirdQuartile;
555 : : case InterQuartileRange:
556 : 0 : return QgsStatisticalSummary::InterQuartileRange;
557 : : case StringMinimumLength:
558 : : case StringMaximumLength:
559 : : case StringConcatenate:
560 : : case StringConcatenateUnique:
561 : : case GeometryCollect:
562 : : case ArrayAggregate:
563 : : {
564 : 0 : if ( ok )
565 : 0 : *ok = false;
566 : 0 : return QgsStatisticalSummary::Count;
567 : : }
568 : : }
569 : :
570 : 0 : if ( ok )
571 : 0 : *ok = false;
572 : 0 : return QgsStatisticalSummary::Count;
573 : 0 : }
574 : :
575 : 0 : QgsStringStatisticalSummary::Statistic QgsAggregateCalculator::stringStatFromAggregate( QgsAggregateCalculator::Aggregate aggregate, bool *ok )
576 : : {
577 : 0 : if ( ok )
578 : 0 : *ok = true;
579 : :
580 : 0 : switch ( aggregate )
581 : : {
582 : : case Count:
583 : 0 : return QgsStringStatisticalSummary::Count;
584 : : case CountDistinct:
585 : 0 : return QgsStringStatisticalSummary::CountDistinct;
586 : : case CountMissing:
587 : 0 : return QgsStringStatisticalSummary::CountMissing;
588 : : case Min:
589 : 0 : return QgsStringStatisticalSummary::Min;
590 : : case Max:
591 : 0 : return QgsStringStatisticalSummary::Max;
592 : : case StringMinimumLength:
593 : 0 : return QgsStringStatisticalSummary::MinimumLength;
594 : : case StringMaximumLength:
595 : 0 : return QgsStringStatisticalSummary::MaximumLength;
596 : : case Minority:
597 : 0 : return QgsStringStatisticalSummary::Minority;
598 : : case Majority:
599 : 0 : return QgsStringStatisticalSummary::Majority;
600 : :
601 : : case Sum:
602 : : case Mean:
603 : : case Median:
604 : : case StDev:
605 : : case StDevSample:
606 : : case Range:
607 : : case FirstQuartile:
608 : : case ThirdQuartile:
609 : : case InterQuartileRange:
610 : : case StringConcatenate:
611 : : case StringConcatenateUnique:
612 : : case GeometryCollect:
613 : : case ArrayAggregate:
614 : : {
615 : 0 : if ( ok )
616 : 0 : *ok = false;
617 : 0 : return QgsStringStatisticalSummary::Count;
618 : : }
619 : : }
620 : :
621 : 0 : if ( ok )
622 : 0 : *ok = false;
623 : 0 : return QgsStringStatisticalSummary::Count;
624 : 0 : }
625 : :
626 : 0 : QgsDateTimeStatisticalSummary::Statistic QgsAggregateCalculator::dateTimeStatFromAggregate( QgsAggregateCalculator::Aggregate aggregate, bool *ok )
627 : : {
628 : 0 : if ( ok )
629 : 0 : *ok = true;
630 : :
631 : 0 : switch ( aggregate )
632 : : {
633 : : case Count:
634 : 0 : return QgsDateTimeStatisticalSummary::Count;
635 : : case CountDistinct:
636 : 0 : return QgsDateTimeStatisticalSummary::CountDistinct;
637 : : case CountMissing:
638 : 0 : return QgsDateTimeStatisticalSummary::CountMissing;
639 : : case Min:
640 : 0 : return QgsDateTimeStatisticalSummary::Min;
641 : : case Max:
642 : 0 : return QgsDateTimeStatisticalSummary::Max;
643 : : case Range:
644 : 0 : return QgsDateTimeStatisticalSummary::Range;
645 : :
646 : : case Sum:
647 : : case Mean:
648 : : case Median:
649 : : case StDev:
650 : : case StDevSample:
651 : : case Minority:
652 : : case Majority:
653 : : case FirstQuartile:
654 : : case ThirdQuartile:
655 : : case InterQuartileRange:
656 : : case StringMinimumLength:
657 : : case StringMaximumLength:
658 : : case StringConcatenate:
659 : : case StringConcatenateUnique:
660 : : case GeometryCollect:
661 : : case ArrayAggregate:
662 : : {
663 : 0 : if ( ok )
664 : 0 : *ok = false;
665 : 0 : return QgsDateTimeStatisticalSummary::Count;
666 : : }
667 : : }
668 : :
669 : 0 : if ( ok )
670 : 0 : *ok = false;
671 : 0 : return QgsDateTimeStatisticalSummary::Count;
672 : 0 : }
673 : :
674 : 0 : QVariant QgsAggregateCalculator::calculateNumericAggregate( QgsFeatureIterator &fit, int attr, QgsExpression *expression,
675 : : QgsExpressionContext *context, QgsStatisticalSummary::Statistic stat )
676 : : {
677 : : Q_ASSERT( expression || attr >= 0 );
678 : :
679 : 0 : QgsStatisticalSummary s( stat );
680 : 0 : QgsFeature f;
681 : :
682 : 0 : while ( fit.nextFeature( f ) )
683 : : {
684 : 0 : if ( expression )
685 : : {
686 : : Q_ASSERT( context );
687 : 0 : context->setFeature( f );
688 : 0 : QVariant v = expression->evaluate( context );
689 : 0 : s.addVariant( v );
690 : 0 : }
691 : : else
692 : : {
693 : 0 : s.addVariant( f.attribute( attr ) );
694 : : }
695 : : }
696 : 0 : s.finalize();
697 : 0 : double val = s.statistic( stat );
698 : 0 : return std::isnan( val ) ? QVariant() : val;
699 : 0 : }
700 : :
701 : 0 : QVariant QgsAggregateCalculator::calculateStringAggregate( QgsFeatureIterator &fit, int attr, QgsExpression *expression,
702 : : QgsExpressionContext *context, QgsStringStatisticalSummary::Statistic stat )
703 : : {
704 : : Q_ASSERT( expression || attr >= 0 );
705 : :
706 : 0 : QgsStringStatisticalSummary s( stat );
707 : 0 : QgsFeature f;
708 : :
709 : 0 : while ( fit.nextFeature( f ) )
710 : : {
711 : 0 : if ( expression )
712 : : {
713 : : Q_ASSERT( context );
714 : 0 : context->setFeature( f );
715 : 0 : QVariant v = expression->evaluate( context );
716 : 0 : s.addValue( v );
717 : 0 : }
718 : : else
719 : : {
720 : 0 : s.addValue( f.attribute( attr ) );
721 : : }
722 : : }
723 : 0 : s.finalize();
724 : 0 : return s.statistic( stat );
725 : 0 : }
726 : :
727 : 0 : QVariant QgsAggregateCalculator::calculateGeometryAggregate( QgsFeatureIterator &fit, QgsExpression *expression, QgsExpressionContext *context )
728 : : {
729 : : Q_ASSERT( expression );
730 : :
731 : 0 : QgsFeature f;
732 : 0 : QVector< QgsGeometry > geometries;
733 : 0 : while ( fit.nextFeature( f ) )
734 : : {
735 : : Q_ASSERT( context );
736 : 0 : context->setFeature( f );
737 : 0 : QVariant v = expression->evaluate( context );
738 : 0 : if ( v.canConvert<QgsGeometry>() )
739 : : {
740 : 0 : geometries << v.value<QgsGeometry>();
741 : 0 : }
742 : 0 : }
743 : :
744 : 0 : return QVariant::fromValue( QgsGeometry::collectGeometry( geometries ) );
745 : 0 : }
746 : :
747 : 0 : QVariant QgsAggregateCalculator::concatenateStrings( QgsFeatureIterator &fit, int attr, QgsExpression *expression,
748 : : QgsExpressionContext *context, const QString &delimiter, bool unique )
749 : : {
750 : : Q_ASSERT( expression || attr >= 0 );
751 : :
752 : 0 : QgsFeature f;
753 : 0 : QStringList results;
754 : 0 : while ( fit.nextFeature( f ) )
755 : : {
756 : 0 : QString result;
757 : 0 : if ( expression )
758 : : {
759 : : Q_ASSERT( context );
760 : 0 : context->setFeature( f );
761 : 0 : QVariant v = expression->evaluate( context );
762 : 0 : result = v.toString();
763 : 0 : }
764 : : else
765 : : {
766 : 0 : result = f.attribute( attr ).toString();
767 : : }
768 : :
769 : 0 : if ( !unique || !results.contains( result ) )
770 : 0 : results << result;
771 : 0 : }
772 : :
773 : 0 : return results.join( delimiter );
774 : 0 : }
775 : :
776 : 0 : QVariant QgsAggregateCalculator::defaultValue( QgsAggregateCalculator::Aggregate aggregate ) const
777 : : {
778 : : // value to return when NO features are aggregated:
779 : 0 : switch ( aggregate )
780 : : {
781 : : // sensible values:
782 : : case Count:
783 : : case CountDistinct:
784 : : case CountMissing:
785 : 0 : return 0;
786 : :
787 : : case StringConcatenate:
788 : : case StringConcatenateUnique:
789 : 0 : return ""; // zero length string - not null!
790 : :
791 : : case ArrayAggregate:
792 : 0 : return QVariantList(); // empty list
793 : :
794 : : // undefined - nothing makes sense here
795 : : case Sum:
796 : : case Min:
797 : : case Max:
798 : : case Mean:
799 : : case Median:
800 : : case StDev:
801 : : case StDevSample:
802 : : case Range:
803 : : case Minority:
804 : : case Majority:
805 : : case FirstQuartile:
806 : : case ThirdQuartile:
807 : : case InterQuartileRange:
808 : : case StringMinimumLength:
809 : : case StringMaximumLength:
810 : : case GeometryCollect:
811 : 0 : return QVariant();
812 : : }
813 : 0 : return QVariant();
814 : 0 : }
815 : :
816 : 0 : QVariant QgsAggregateCalculator::calculateDateTimeAggregate( QgsFeatureIterator &fit, int attr, QgsExpression *expression,
817 : : QgsExpressionContext *context, QgsDateTimeStatisticalSummary::Statistic stat )
818 : : {
819 : : Q_ASSERT( expression || attr >= 0 );
820 : :
821 : 0 : QgsDateTimeStatisticalSummary s( stat );
822 : 0 : QgsFeature f;
823 : :
824 : 0 : while ( fit.nextFeature( f ) )
825 : : {
826 : 0 : if ( expression )
827 : : {
828 : : Q_ASSERT( context );
829 : 0 : context->setFeature( f );
830 : 0 : QVariant v = expression->evaluate( context );
831 : 0 : s.addValue( v );
832 : 0 : }
833 : : else
834 : : {
835 : 0 : s.addValue( f.attribute( attr ) );
836 : : }
837 : : }
838 : 0 : s.finalize();
839 : 0 : return s.statistic( stat );
840 : 0 : }
841 : :
842 : 0 : QVariant QgsAggregateCalculator::calculateArrayAggregate( QgsFeatureIterator &fit, int attr, QgsExpression *expression,
843 : : QgsExpressionContext *context )
844 : : {
845 : : Q_ASSERT( expression || attr >= 0 );
846 : :
847 : 0 : QgsFeature f;
848 : :
849 : 0 : QVariantList array;
850 : :
851 : 0 : while ( fit.nextFeature( f ) )
852 : : {
853 : 0 : if ( expression )
854 : : {
855 : : Q_ASSERT( context );
856 : 0 : context->setFeature( f );
857 : 0 : QVariant v = expression->evaluate( context );
858 : 0 : array.append( v );
859 : 0 : }
860 : : else
861 : : {
862 : 0 : array.append( f.attribute( attr ) );
863 : : }
864 : : }
865 : 0 : return array;
866 : 0 : }
867 : :
|