QGIS API Documentation  3.12.1-BucureČ™ti (121cc00ff0)
qgsexpressionnodeimpl.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsexpressionnodeimpl.cpp
3  -------------------
4  begin : May 2017
5  copyright : (C) 2017 Matthias Kuhn
6  email : [email protected]
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsexpressionnodeimpl.h"
17 #include "qgsexpressionutils.h"
18 #include "qgsexpression.h"
19 
20 #include "qgsgeometry.h"
21 #include "qgsfeaturerequest.h"
22 
23 const char *QgsExpressionNodeBinaryOperator::BINARY_OPERATOR_TEXT[] =
24 {
25  // this must correspond (number and order of element) to the declaration of the enum BinaryOperator
26  "OR", "AND",
27  "=", "<>", "<=", ">=", "<", ">", "~", "LIKE", "NOT LIKE", "ILIKE", "NOT ILIKE", "IS", "IS NOT",
28  "+", "-", "*", "/", "//", "%", "^",
29  "||"
30 };
31 
32 const char *QgsExpressionNodeUnaryOperator::UNARY_OPERATOR_TEXT[] =
33 {
34  // this must correspond (number and order of element) to the declaration of the enum UnaryOperator
35  "NOT", "-"
36 };
37 
39 {
40  bool needs = false;
41  const QList< QgsExpressionNode * > nodeList = mList->list();
42  for ( QgsExpressionNode *n : nodeList )
43  needs |= n->needsGeometry();
44  return needs;
45 }
46 
48 {
49  qDeleteAll( mList );
50 }
51 
53 {
54  mList.append( node->node );
55  mNameList.append( node->name.toLower() );
56  mHasNamedNodes = true;
57  delete node;
58 }
59 
61 {
62  NodeList *nl = new NodeList;
63  for ( QgsExpressionNode *node : mList )
64  {
65  nl->mList.append( node->clone() );
66  }
67  nl->mNameList = mNameList;
68 
69  return nl;
70 }
71 
73 {
74  QString msg;
75  bool first = true;
76  for ( QgsExpressionNode *n : mList )
77  {
78  if ( !first ) msg += QLatin1String( ", " );
79  else first = false;
80  msg += n->dump();
81  }
82  return msg;
83 }
84 
85 
86 //
87 
89 {
90  QVariant val = mOperand->eval( parent, context );
92 
93  switch ( mOp )
94  {
95  case uoNot:
96  {
97  QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( val, parent );
99  return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::NOT[tvl] );
100  }
101 
102  case uoMinus:
103  if ( QgsExpressionUtils::isIntSafe( val ) )
104  return QVariant( - QgsExpressionUtils::getIntValue( val, parent ) );
105  else if ( QgsExpressionUtils::isDoubleSafe( val ) )
106  return QVariant( - QgsExpressionUtils::getDoubleValue( val, parent ) );
107  else
108  SET_EVAL_ERROR( tr( "Unary minus only for numeric values." ) );
109  default:
110  Q_ASSERT( false && "unknown unary operation" );
111  }
112  return QVariant();
113 }
114 
116 {
117  return ntUnaryOperator;
118 }
119 
121 {
122  return mOperand->prepare( parent, context );
123 }
124 
126 {
127  if ( dynamic_cast<QgsExpressionNodeBinaryOperator *>( mOperand ) )
128  return QStringLiteral( "%1 ( %2 )" ).arg( UNARY_OPERATOR_TEXT[mOp], mOperand->dump() );
129  else
130  return QStringLiteral( "%1 %2" ).arg( UNARY_OPERATOR_TEXT[mOp], mOperand->dump() );
131 }
132 
134 {
135  return mOperand->referencedColumns();
136 }
137 
139 {
140  return mOperand->referencedVariables();
141 }
142 
144 {
145  return mOperand->referencedFunctions();
146 }
147 
148 QList<const QgsExpressionNode *> QgsExpressionNodeUnaryOperator::nodes() const
149 {
150  QList<const QgsExpressionNode *> lst;
151  lst.append( this );
152  lst += mOperand->nodes();
153  return lst;
154 }
155 
157 {
158  return mOperand->needsGeometry();
159 }
160 
162 {
163  QgsExpressionNodeUnaryOperator *copy = new QgsExpressionNodeUnaryOperator( mOp, mOperand->clone() );
164  cloneTo( copy );
165  return copy;
166 }
167 
169 {
170  return mOperand->isStatic( parent, context );
171 }
172 
174 {
175  return UNARY_OPERATOR_TEXT[mOp];
176 }
177 
178 //
179 
181 {
182  QVariant vL = mOpLeft->eval( parent, context );
184 
185  if ( mOp == boAnd || mOp == boOr )
186  {
187  QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent );
189  if ( mOp == boAnd && tvlL == QgsExpressionUtils::False )
190  return TVL_False; // shortcut -- no need to evaluate right-hand side
191  if ( mOp == boOr && tvlL == QgsExpressionUtils::True )
192  return TVL_True; // shortcut -- no need to evaluate right-hand side
193  }
194 
195  QVariant vR = mOpRight->eval( parent, context );
197 
198  switch ( mOp )
199  {
200  case boPlus:
201  if ( vL.type() == QVariant::String && vR.type() == QVariant::String )
202  {
203  QString sL = QgsExpressionUtils::isNull( vL ) ? QString() : QgsExpressionUtils::getStringValue( vL, parent );
205  QString sR = QgsExpressionUtils::isNull( vR ) ? QString() : QgsExpressionUtils::getStringValue( vR, parent );
207  return QVariant( sL + sR );
208  }
209  //intentional fall-through
211  case boMinus:
212  case boMul:
213  case boDiv:
214  case boMod:
215  {
216  if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
217  return QVariant();
218  else if ( mOp != boDiv && QgsExpressionUtils::isIntSafe( vL ) && QgsExpressionUtils::isIntSafe( vR ) )
219  {
220  // both are integers - let's use integer arithmetic
221  qlonglong iL = QgsExpressionUtils::getIntValue( vL, parent );
223  qlonglong iR = QgsExpressionUtils::getIntValue( vR, parent );
225 
226  if ( mOp == boMod && iR == 0 )
227  return QVariant();
228 
229  return QVariant( computeInt( iL, iR ) );
230  }
231  else if ( QgsExpressionUtils::isDateTimeSafe( vL ) && QgsExpressionUtils::isIntervalSafe( vR ) )
232  {
233  QDateTime dL = QgsExpressionUtils::getDateTimeValue( vL, parent );
235  QgsInterval iL = QgsExpressionUtils::getInterval( vR, parent );
237  if ( mOp == boDiv || mOp == boMul || mOp == boMod )
238  {
239  parent->setEvalErrorString( tr( "Can't perform /, *, or % on DateTime and Interval" ) );
240  return QVariant();
241  }
242  return QVariant( computeDateTimeFromInterval( dL, &iL ) );
243  }
244  else if ( mOp == boPlus && ( ( vL.type() == QVariant::Date && vR.type() == QVariant::Time ) ||
245  ( vR.type() == QVariant::Date && vL.type() == QVariant::Time ) ) )
246  {
247  QDate date = QgsExpressionUtils::getDateValue( vL.type() == QVariant::Date ? vL : vR, parent );
249  QTime time = QgsExpressionUtils::getTimeValue( vR.type() == QVariant::Time ? vR : vL, parent );
251  QDateTime dt = QDateTime( date, time );
252  return QVariant( dt );
253  }
254  else if ( mOp == boMinus && vL.type() == QVariant::Date && vR.type() == QVariant::Date )
255  {
256  QDate date1 = QgsExpressionUtils::getDateValue( vL, parent );
258  QDate date2 = QgsExpressionUtils::getDateValue( vR, parent );
260  return date1 - date2;
261  }
262  else if ( mOp == boMinus && vL.type() == QVariant::Time && vR.type() == QVariant::Time )
263  {
264  QTime time1 = QgsExpressionUtils::getTimeValue( vL, parent );
266  QTime time2 = QgsExpressionUtils::getTimeValue( vR, parent );
268  return time1 - time2;
269  }
270  else if ( mOp == boMinus && vL.type() == QVariant::DateTime && vR.type() == QVariant::DateTime )
271  {
272  QDateTime datetime1 = QgsExpressionUtils::getDateTimeValue( vL, parent );
274  QDateTime datetime2 = QgsExpressionUtils::getDateTimeValue( vR, parent );
276  return datetime1 - datetime2;
277  }
278  else
279  {
280  // general floating point arithmetic
281  double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
283  double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
285  if ( ( mOp == boDiv || mOp == boMod ) && fR == 0. )
286  return QVariant(); // silently handle division by zero and return NULL
287  return QVariant( computeDouble( fL, fR ) );
288  }
289  }
290  case boIntDiv:
291  {
292  //integer division
293  double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
295  double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
297  if ( fR == 0. )
298  return QVariant(); // silently handle division by zero and return NULL
299  return QVariant( qlonglong( std::floor( fL / fR ) ) );
300  }
301  case boPow:
302  if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
303  return QVariant();
304  else
305  {
306  double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
308  double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
310  return QVariant( std::pow( fL, fR ) );
311  }
312 
313  case boAnd:
314  {
315  QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent ), tvlR = QgsExpressionUtils::getTVLValue( vR, parent );
317  return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::AND[tvlL][tvlR] );
318  }
319 
320  case boOr:
321  {
322  QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent ), tvlR = QgsExpressionUtils::getTVLValue( vR, parent );
324  return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::OR[tvlL][tvlR] );
325  }
326 
327  case boEQ:
328  case boNE:
329  case boLT:
330  case boGT:
331  case boLE:
332  case boGE:
333  if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
334  {
335  return TVL_Unknown;
336  }
337  else if ( QgsExpressionUtils::isList( vL ) || QgsExpressionUtils::isList( vR ) )
338  {
339  // verify that we have two lists
340  if ( !QgsExpressionUtils::isList( vL ) || !QgsExpressionUtils::isList( vR ) )
341  return TVL_Unknown;
342 
343  // and search for not equal respective items
344  QVariantList lL = vL.toList();
345  QVariantList lR = vR.toList();
346  for ( int i = 0; i < lL.length() && i < lR.length(); i++ )
347  {
348  if ( QgsExpressionUtils::isNull( lL.at( i ) ) && QgsExpressionUtils::isNull( lR.at( i ) ) )
349  continue; // same behavior as PostgreSQL
350 
351  if ( QgsExpressionUtils::isNull( lL.at( i ) ) || QgsExpressionUtils::isNull( lR.at( i ) ) )
352  {
353  switch ( mOp )
354  {
355  case boEQ:
356  return false;
357  case boNE:
358  return true;
359  case boLT:
360  case boLE:
361  return QgsExpressionUtils::isNull( lR.at( i ) );
362  case boGT:
363  case boGE:
364  return QgsExpressionUtils::isNull( lL.at( i ) );
365  default:
366  Q_ASSERT( false );
367  return TVL_Unknown;
368  }
369  }
370 
371  QgsExpressionNodeLiteral nL( lL.at( i ) );
372  QgsExpressionNodeLiteral nR( lR.at( i ) );
373  QgsExpressionNodeBinaryOperator eqNode( boEQ, nL.clone(), nR.clone() );
374  QVariant eq = eqNode.eval( parent, context );
376  if ( eq == TVL_False )
377  {
378  // return the two items comparison
379  QgsExpressionNodeBinaryOperator node( mOp, nL.clone(), nR.clone() );
380  QVariant v = node.eval( parent, context );
382  return v;
383  }
384  }
385 
386  // default to length comparison
387  switch ( mOp )
388  {
389  case boEQ:
390  return lL.length() == lR.length();
391  case boNE:
392  return lL.length() != lR.length();
393  case boLT:
394  return lL.length() < lR.length();
395  case boGT:
396  return lL.length() > lR.length();
397  case boLE:
398  return lL.length() <= lR.length();
399  case boGE:
400  return lL.length() >= lR.length();
401  default:
402  Q_ASSERT( false );
403  return TVL_Unknown;
404  }
405  }
406  else if ( ( vL.type() != QVariant::String || vR.type() != QVariant::String ) &&
407  QgsExpressionUtils::isDoubleSafe( vL ) && QgsExpressionUtils::isDoubleSafe( vR ) )
408  {
409  // do numeric comparison if both operators can be converted to numbers,
410  // and they aren't both string
411  double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
413  double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
415  return compare( fL - fR ) ? TVL_True : TVL_False;
416  }
417  // warning - QgsExpression::isIntervalSafe is VERY expensive and should not be used here
418  else if ( vL.canConvert< QgsInterval >() && vR.canConvert< QgsInterval >() )
419  {
420  double fL = QgsExpressionUtils::getInterval( vL, parent ).seconds();
422  double fR = QgsExpressionUtils::getInterval( vR, parent ).seconds();
424  return compare( fL - fR ) ? TVL_True : TVL_False;
425  }
426  else
427  {
428  // do string comparison otherwise
429  QString sL = QgsExpressionUtils::getStringValue( vL, parent );
431  QString sR = QgsExpressionUtils::getStringValue( vR, parent );
433  int diff = QString::compare( sL, sR );
434  return compare( diff ) ? TVL_True : TVL_False;
435  }
436 
437  case boIs:
438  case boIsNot:
439  if ( QgsExpressionUtils::isNull( vL ) && QgsExpressionUtils::isNull( vR ) ) // both operators null
440  return ( mOp == boIs ? TVL_True : TVL_False );
441  else if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) ) // one operator null
442  return ( mOp == boIs ? TVL_False : TVL_True );
443  else // both operators non-null
444  {
445  bool equal = false;
446  if ( QgsExpressionUtils::isDoubleSafe( vL ) && QgsExpressionUtils::isDoubleSafe( vR ) &&
447  ( vL.type() != QVariant::String || vR.type() != QVariant::String ) )
448  {
449  double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
451  double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
453  equal = qgsDoubleNear( fL, fR );
454  }
455  else
456  {
457  QString sL = QgsExpressionUtils::getStringValue( vL, parent );
459  QString sR = QgsExpressionUtils::getStringValue( vR, parent );
461  equal = QString::compare( sL, sR ) == 0;
462  }
463  if ( equal )
464  return mOp == boIs ? TVL_True : TVL_False;
465  else
466  return mOp == boIs ? TVL_False : TVL_True;
467  }
468 
469  case boRegexp:
470  case boLike:
471  case boNotLike:
472  case boILike:
473  case boNotILike:
474  if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
475  return TVL_Unknown;
476  else
477  {
478  QString str = QgsExpressionUtils::getStringValue( vL, parent );
480  QString regexp = QgsExpressionUtils::getStringValue( vR, parent );
482  // TODO: cache QRegExp in case that regexp is a literal string (i.e. it will stay constant)
483  bool matches;
484  if ( mOp == boLike || mOp == boILike || mOp == boNotLike || mOp == boNotILike ) // change from LIKE syntax to regexp
485  {
486  QString esc_regexp = QRegExp::escape( regexp );
487  // manage escape % and _
488  if ( esc_regexp.startsWith( '%' ) )
489  {
490  esc_regexp.replace( 0, 1, QStringLiteral( ".*" ) );
491  }
492  QRegExp rx( "[^\\\\](%)" );
493  int pos = 0;
494  while ( ( pos = rx.indexIn( esc_regexp, pos ) ) != -1 )
495  {
496  esc_regexp.replace( pos + 1, 1, QStringLiteral( ".*" ) );
497  pos += 1;
498  }
499  rx.setPattern( QStringLiteral( "\\\\%" ) );
500  esc_regexp.replace( rx, QStringLiteral( "%" ) );
501  if ( esc_regexp.startsWith( '_' ) )
502  {
503  esc_regexp.replace( 0, 1, QStringLiteral( "." ) );
504  }
505  rx.setPattern( QStringLiteral( "[^\\\\](_)" ) );
506  pos = 0;
507  while ( ( pos = rx.indexIn( esc_regexp, pos ) ) != -1 )
508  {
509  esc_regexp.replace( pos + 1, 1, '.' );
510  pos += 1;
511  }
512  rx.setPattern( QStringLiteral( "\\\\_" ) );
513  esc_regexp.replace( rx, QStringLiteral( "_" ) );
514  matches = QRegExp( esc_regexp, mOp == boLike || mOp == boNotLike ? Qt::CaseSensitive : Qt::CaseInsensitive ).exactMatch( str );
515  }
516  else
517  {
518  matches = QRegExp( regexp ).indexIn( str ) != -1;
519  }
520 
521  if ( mOp == boNotLike || mOp == boNotILike )
522  {
523  matches = !matches;
524  }
525 
526  return matches ? TVL_True : TVL_False;
527  }
528 
529  case boConcat:
530  if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
531  return QVariant();
532  else
533  {
534  QString sL = QgsExpressionUtils::getStringValue( vL, parent );
536  QString sR = QgsExpressionUtils::getStringValue( vR, parent );
538  return QVariant( sL + sR );
539  }
540 
541  default:
542  break;
543  }
544  Q_ASSERT( false );
545  return QVariant();
546 }
547 
548 bool QgsExpressionNodeBinaryOperator::compare( double diff )
549 {
550  switch ( mOp )
551  {
552  case boEQ:
553  return qgsDoubleNear( diff, 0.0 );
554  case boNE:
555  return !qgsDoubleNear( diff, 0.0 );
556  case boLT:
557  return diff < 0;
558  case boGT:
559  return diff > 0;
560  case boLE:
561  return diff <= 0;
562  case boGE:
563  return diff >= 0;
564  default:
565  Q_ASSERT( false );
566  return false;
567  }
568 }
569 
570 qlonglong QgsExpressionNodeBinaryOperator::computeInt( qlonglong x, qlonglong y )
571 {
572  switch ( mOp )
573  {
574  case boPlus:
575  return x + y;
576  case boMinus:
577  return x - y;
578  case boMul:
579  return x * y;
580  case boDiv:
581  return x / y;
582  case boMod:
583  return x % y;
584  default:
585  Q_ASSERT( false );
586  return 0;
587  }
588 }
589 
590 QDateTime QgsExpressionNodeBinaryOperator::computeDateTimeFromInterval( const QDateTime &d, QgsInterval *i )
591 {
592  switch ( mOp )
593  {
594  case boPlus:
595  return d.addSecs( i->seconds() );
596  case boMinus:
597  return d.addSecs( -i->seconds() );
598  default:
599  Q_ASSERT( false );
600  return QDateTime();
601  }
602 }
603 
604 double QgsExpressionNodeBinaryOperator::computeDouble( double x, double y )
605 {
606  switch ( mOp )
607  {
608  case boPlus:
609  return x + y;
610  case boMinus:
611  return x - y;
612  case boMul:
613  return x * y;
614  case boDiv:
615  return x / y;
616  case boMod:
617  return std::fmod( x, y );
618  default:
619  Q_ASSERT( false );
620  return 0;
621  }
622 }
623 
625 {
626  return ntBinaryOperator;
627 }
628 
630 {
631  bool resL = mOpLeft->prepare( parent, context );
632  bool resR = mOpRight->prepare( parent, context );
633  return resL && resR;
634 }
635 
637 {
638  // see left/right in qgsexpressionparser.yy
639  switch ( mOp )
640  {
641  case boOr:
642  return 1;
643 
644  case boAnd:
645  return 2;
646 
647  case boEQ:
648  case boNE:
649  case boLE:
650  case boGE:
651  case boLT:
652  case boGT:
653  case boRegexp:
654  case boLike:
655  case boILike:
656  case boNotLike:
657  case boNotILike:
658  case boIs:
659  case boIsNot:
660  return 3;
661 
662  case boPlus:
663  case boMinus:
664  return 4;
665 
666  case boMul:
667  case boDiv:
668  case boIntDiv:
669  case boMod:
670  return 5;
671 
672  case boPow:
673  return 6;
674 
675  case boConcat:
676  return 7;
677  }
678  Q_ASSERT( false && "unexpected binary operator" );
679  return -1;
680 }
681 
683 {
684  // see left/right in qgsexpressionparser.yy
685  switch ( mOp )
686  {
687  case boOr:
688  case boAnd:
689  case boEQ:
690  case boNE:
691  case boLE:
692  case boGE:
693  case boLT:
694  case boGT:
695  case boRegexp:
696  case boLike:
697  case boILike:
698  case boNotLike:
699  case boNotILike:
700  case boIs:
701  case boIsNot:
702  case boPlus:
703  case boMinus:
704  case boMul:
705  case boDiv:
706  case boIntDiv:
707  case boMod:
708  case boConcat:
709  return true;
710 
711  case boPow:
712  return false;
713  }
714  Q_ASSERT( false && "unexpected binary operator" );
715  return false;
716 }
717 
719 {
720  QgsExpressionNodeBinaryOperator *lOp = dynamic_cast<QgsExpressionNodeBinaryOperator *>( mOpLeft );
721  QgsExpressionNodeBinaryOperator *rOp = dynamic_cast<QgsExpressionNodeBinaryOperator *>( mOpRight );
722  QgsExpressionNodeUnaryOperator *ruOp = dynamic_cast<QgsExpressionNodeUnaryOperator *>( mOpRight );
723 
724  QString rdump( mOpRight->dump() );
725 
726  // avoid dumping "IS (NOT ...)" as "IS NOT ..."
727  if ( mOp == boIs && ruOp && ruOp->op() == QgsExpressionNodeUnaryOperator::uoNot )
728  {
729  rdump.prepend( '(' ).append( ')' );
730  }
731 
732  QString fmt;
733  if ( leftAssociative() )
734  {
735  fmt += lOp && ( lOp->precedence() < precedence() ) ? QStringLiteral( "(%1)" ) : QStringLiteral( "%1" );
736  fmt += QLatin1String( " %2 " );
737  fmt += rOp && ( rOp->precedence() <= precedence() ) ? QStringLiteral( "(%3)" ) : QStringLiteral( "%3" );
738  }
739  else
740  {
741  fmt += lOp && ( lOp->precedence() <= precedence() ) ? QStringLiteral( "(%1)" ) : QStringLiteral( "%1" );
742  fmt += QLatin1String( " %2 " );
743  fmt += rOp && ( rOp->precedence() < precedence() ) ? QStringLiteral( "(%3)" ) : QStringLiteral( "%3" );
744  }
745 
746  return fmt.arg( mOpLeft->dump(), BINARY_OPERATOR_TEXT[mOp], rdump );
747 }
748 
750 {
751  return mOpLeft->referencedColumns() + mOpRight->referencedColumns();
752 }
753 
755 {
756  return mOpLeft->referencedVariables() + mOpRight->referencedVariables();
757 }
758 
760 {
761  return mOpLeft->referencedFunctions() + mOpRight->referencedFunctions();
762 }
763 
764 QList<const QgsExpressionNode *> QgsExpressionNodeBinaryOperator::nodes() const
765 {
766  QList<const QgsExpressionNode *> lst;
767  lst << this;
768  lst += mOpLeft->nodes() + mOpRight->nodes();
769  return lst;
770 }
771 
773 {
774  return mOpLeft->needsGeometry() || mOpRight->needsGeometry();
775 }
776 
778 {
779  QgsExpressionNodeBinaryOperator *copy = new QgsExpressionNodeBinaryOperator( mOp, mOpLeft->clone(), mOpRight->clone() );
780  cloneTo( copy );
781  return copy;
782 }
783 
785 {
786  return mOpLeft->isStatic( parent, context ) && mOpRight->isStatic( parent, context );
787 }
788 
789 //
790 
792 {
793  if ( mList->count() == 0 )
794  return mNotIn ? TVL_True : TVL_False;
795  QVariant v1 = mNode->eval( parent, context );
797  if ( QgsExpressionUtils::isNull( v1 ) )
798  return TVL_Unknown;
799 
800  bool listHasNull = false;
801 
802  const QList< QgsExpressionNode * > nodeList = mList->list();
803  for ( QgsExpressionNode *n : nodeList )
804  {
805  QVariant v2 = n->eval( parent, context );
807  if ( QgsExpressionUtils::isNull( v2 ) )
808  listHasNull = true;
809  else
810  {
811  bool equal = false;
812  // check whether they are equal
813  if ( ( v1.type() != QVariant::String || v2.type() != QVariant::String ) &&
814  QgsExpressionUtils::isDoubleSafe( v1 ) && QgsExpressionUtils::isDoubleSafe( v2 ) )
815  {
816  // do numeric comparison if both operators can be converted to numbers,
817  // and they aren't both string
818  double f1 = QgsExpressionUtils::getDoubleValue( v1, parent );
820  double f2 = QgsExpressionUtils::getDoubleValue( v2, parent );
822  equal = qgsDoubleNear( f1, f2 );
823  }
824  else
825  {
826  QString s1 = QgsExpressionUtils::getStringValue( v1, parent );
828  QString s2 = QgsExpressionUtils::getStringValue( v2, parent );
830  equal = QString::compare( s1, s2 ) == 0;
831  }
832 
833  if ( equal ) // we know the result
834  return mNotIn ? TVL_False : TVL_True;
835  }
836  }
837 
838  // item not found
839  if ( listHasNull )
840  return TVL_Unknown;
841  else
842  return mNotIn ? TVL_True : TVL_False;
843 }
844 
846 {
847  delete mNode;
848  delete mList;
849 }
850 
852 {
853  return ntInOperator;
854 }
855 
857 {
858  bool res = mNode->prepare( parent, context );
859  const QList< QgsExpressionNode * > nodeList = mList->list();
860  for ( QgsExpressionNode *n : nodeList )
861  {
862  res = res && n->prepare( parent, context );
863  }
864  return res;
865 }
866 
868 {
869  return QStringLiteral( "%1 %2 IN (%3)" ).arg( mNode->dump(), mNotIn ? "NOT" : "", mList->dump() );
870 }
871 
873 {
874  QgsExpressionNodeInOperator *copy = new QgsExpressionNodeInOperator( mNode->clone(), mList->clone(), mNotIn );
875  cloneTo( copy );
876  return copy;
877 }
878 
880 {
881  if ( !mNode->isStatic( parent, context ) )
882  return false;
883 
884  const QList< QgsExpressionNode * > nodeList = mList->list();
885  for ( QgsExpressionNode *n : nodeList )
886  {
887  if ( !n->isStatic( parent, context ) )
888  return false;
889  }
890 
891  return true;
892 }
893 
894 //
895 
897 {
898  QString name = QgsExpression::QgsExpression::Functions()[mFnIndex]->name();
899  QgsExpressionFunction *fd = context && context->hasFunction( name ) ? context->function( name ) : QgsExpression::QgsExpression::Functions()[mFnIndex];
900 
901  QVariant res = fd->run( mArgs, context, parent, this );
903 
904  // everything went fine
905  return res;
906 }
907 
909  : mFnIndex( fnIndex )
910 {
911  const QgsExpressionFunction::ParameterList &functionParams = QgsExpression::QgsExpression::Functions()[mFnIndex]->parameters();
912  if ( !args || functionParams.isEmpty() )
913  {
914  // no QgsExpressionFunction::Parameters, or function does not support them
915  mArgs = args;
916  }
917  else
918  {
919  mArgs = new NodeList();
920 
921  int idx = 0;
922  //first loop through unnamed arguments
923  while ( idx < args->names().size() && args->names().at( idx ).isEmpty() )
924  {
925  mArgs->append( args->list().at( idx )->clone() );
926  idx++;
927  }
928 
929  //next copy named QgsExpressionFunction::Parameters in order expected by function
930  for ( ; idx < functionParams.count(); ++idx )
931  {
932  int nodeIdx = args->names().indexOf( functionParams.at( idx ).name().toLower() );
933  if ( nodeIdx < 0 )
934  {
935  //QgsExpressionFunction::Parameter not found - insert default value for QgsExpressionFunction::Parameter
936  mArgs->append( new QgsExpressionNodeLiteral( functionParams.at( idx ).defaultValue() ) );
937  }
938  else
939  {
940  mArgs->append( args->list().at( nodeIdx )->clone() );
941  }
942  }
943 
944  delete args;
945  }
946 }
947 
949 {
950  delete mArgs;
951 }
952 
954 {
955  return ntFunction;
956 }
957 
959 {
960  QgsExpressionFunction *fd = QgsExpression::QgsExpression::Functions()[mFnIndex];
961 
962  bool res = fd->prepare( this, parent, context );
963  if ( mArgs && !fd->lazyEval() )
964  {
965  const QList< QgsExpressionNode * > nodeList = mArgs->list();
966  for ( QgsExpressionNode *n : nodeList )
967  {
968  res = res && n->prepare( parent, context );
969  }
970  }
971  return res;
972 }
973 
975 {
976  QgsExpressionFunction *fd = QgsExpression::QgsExpression::Functions()[mFnIndex];
977  if ( fd->params() == 0 )
978  return QStringLiteral( "%1%2" ).arg( fd->name(), fd->name().startsWith( '$' ) ? "" : "()" ); // special column
979  else
980  return QStringLiteral( "%1(%2)" ).arg( fd->name(), mArgs ? mArgs->dump() : QString() ); // function
981 }
982 
984 {
985  QgsExpressionFunction *fd = QgsExpression::QgsExpression::Functions()[mFnIndex];
986  QSet<QString> functionColumns = fd->referencedColumns( this );
987 
988  if ( !mArgs )
989  {
990  //no referenced columns in arguments, just return function's referenced columns
991  return functionColumns;
992  }
993 
994  int paramIndex = 0;
995  const QList< QgsExpressionNode * > nodeList = mArgs->list();
996  for ( QgsExpressionNode *n : nodeList )
997  {
998  if ( fd->parameters().count() <= paramIndex || !fd->parameters().at( paramIndex ).isSubExpression() )
999  functionColumns.unite( n->referencedColumns() );
1000  paramIndex++;
1001  }
1002 
1003  return functionColumns;
1004 }
1005 
1007 {
1008  QgsExpressionFunction *fd = QgsExpression::QgsExpression::Functions()[mFnIndex];
1009  if ( fd->name() == QLatin1String( "var" ) )
1010  {
1011  if ( !mArgs->list().isEmpty() )
1012  {
1013  QgsExpressionNodeLiteral *var = dynamic_cast<QgsExpressionNodeLiteral *>( mArgs->list().at( 0 ) );
1014  if ( var )
1015  return QSet<QString>() << var->value().toString();
1016  }
1017  return QSet<QString>() << QString();
1018  }
1019  else
1020  {
1021  QSet<QString> functionVariables = QSet<QString>();
1022 
1023  if ( !mArgs )
1024  return functionVariables;
1025 
1026  const QList< QgsExpressionNode * > nodeList = mArgs->list();
1027  for ( QgsExpressionNode *n : nodeList )
1028  {
1029  functionVariables.unite( n->referencedVariables() );
1030  }
1031 
1032  return functionVariables;
1033  }
1034 }
1035 
1037 {
1038  QgsExpressionFunction *fd = QgsExpression::QgsExpression::Functions()[mFnIndex];
1039  QSet<QString> functions = QSet<QString>();
1040  functions.insert( fd->name() );
1041 
1042  if ( !mArgs )
1043  return functions;
1044 
1045  const QList< QgsExpressionNode * > nodeList = mArgs->list();
1046  for ( QgsExpressionNode *n : nodeList )
1047  {
1048  functions.unite( n->referencedFunctions() );
1049  }
1050  return functions;
1051 }
1052 
1053 QList<const QgsExpressionNode *> QgsExpressionNodeFunction::nodes() const
1054 {
1055  QList<const QgsExpressionNode *> lst;
1056  lst << this;
1057  if ( !mArgs )
1058  return lst;
1059 
1060  const QList< QgsExpressionNode * > nodeList = mArgs->list();
1061  for ( QgsExpressionNode *n : nodeList )
1062  {
1063  lst += n->nodes();
1064  }
1065  return lst;
1066 }
1067 
1069 {
1070  bool needs = QgsExpression::QgsExpression::Functions()[mFnIndex]->usesGeometry( this );
1071  if ( mArgs )
1072  {
1073  const QList< QgsExpressionNode * > nodeList = mArgs->list();
1074  for ( QgsExpressionNode *n : nodeList )
1075  needs |= n->needsGeometry();
1076  }
1077  return needs;
1078 }
1079 
1081 {
1082  QgsExpressionNodeFunction *copy = new QgsExpressionNodeFunction( mFnIndex, mArgs ? mArgs->clone() : nullptr );
1083  cloneTo( copy );
1084  return copy;
1085 }
1086 
1088 {
1089  return QgsExpression::Functions()[mFnIndex]->isStatic( this, parent, context );
1090 }
1091 
1093 {
1094  if ( !args || !args->hasNamedNodes() )
1095  return true;
1096 
1097  const QgsExpressionFunction::ParameterList &functionParams = QgsExpression::Functions()[fnIndex]->parameters();
1098  if ( functionParams.isEmpty() )
1099  {
1100  error = QStringLiteral( "%1 does not support named QgsExpressionFunction::Parameters" ).arg( QgsExpression::Functions()[fnIndex]->name() );
1101  return false;
1102  }
1103  else
1104  {
1105  QSet< int > providedArgs;
1106  QSet< int > handledArgs;
1107  int idx = 0;
1108  //first loop through unnamed arguments
1109  while ( args->names().at( idx ).isEmpty() )
1110  {
1111  providedArgs << idx;
1112  handledArgs << idx;
1113  idx++;
1114  }
1115 
1116  //next check named QgsExpressionFunction::Parameters
1117  for ( ; idx < functionParams.count(); ++idx )
1118  {
1119  int nodeIdx = args->names().indexOf( functionParams.at( idx ).name().toLower() );
1120  if ( nodeIdx < 0 )
1121  {
1122  if ( !functionParams.at( idx ).optional() )
1123  {
1124  error = QStringLiteral( "No value specified for QgsExpressionFunction::Parameter '%1' for %2" ).arg( functionParams.at( idx ).name(), QgsExpression::Functions()[fnIndex]->name() );
1125  return false;
1126  }
1127  }
1128  else
1129  {
1130  if ( providedArgs.contains( idx ) )
1131  {
1132  error = QStringLiteral( "Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2" ).arg( functionParams.at( idx ).name(), QgsExpression::Functions()[fnIndex]->name() );
1133  return false;
1134  }
1135  }
1136  providedArgs << idx;
1137  handledArgs << nodeIdx;
1138  }
1139 
1140  //last check for bad names
1141  idx = 0;
1142  const QStringList nameList = args->names();
1143  for ( const QString &name : nameList )
1144  {
1145  if ( !name.isEmpty() && !functionParams.contains( name ) )
1146  {
1147  error = QStringLiteral( "Invalid QgsExpressionFunction::Parameter name '%1' for %2" ).arg( name, QgsExpression::Functions()[fnIndex]->name() );
1148  return false;
1149  }
1150  if ( !name.isEmpty() && !handledArgs.contains( idx ) )
1151  {
1152  int functionIdx = functionParams.indexOf( name );
1153  if ( providedArgs.contains( functionIdx ) )
1154  {
1155  error = QStringLiteral( "Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2" ).arg( functionParams.at( functionIdx ).name(), QgsExpression::Functions()[fnIndex]->name() );
1156  return false;
1157  }
1158  }
1159  idx++;
1160  }
1161 
1162  }
1163  return true;
1164 }
1165 
1166 //
1167 
1169 {
1170  Q_UNUSED( context )
1171  Q_UNUSED( parent )
1172  return mValue;
1173 }
1174 
1176 {
1177  return ntLiteral;
1178 }
1179 
1181 {
1182  Q_UNUSED( parent )
1183  Q_UNUSED( context )
1184  return true;
1185 }
1186 
1187 
1189 {
1190  if ( mValue.isNull() )
1191  return QStringLiteral( "NULL" );
1192 
1193  switch ( mValue.type() )
1194  {
1195  case QVariant::Int:
1196  return QString::number( mValue.toInt() );
1197  case QVariant::Double:
1198  return QString::number( mValue.toDouble() );
1199  case QVariant::LongLong:
1200  return QString::number( mValue.toLongLong() );
1201  case QVariant::String:
1202  return QgsExpression::quotedString( mValue.toString() );
1203  case QVariant::Bool:
1204  return mValue.toBool() ? QStringLiteral( "TRUE" ) : QStringLiteral( "FALSE" );
1205  default:
1206  return tr( "[unsupported type: %1; value: %2]" ).arg( mValue.typeName(), mValue.toString() );
1207  }
1208 }
1209 
1211 {
1212  return QSet<QString>();
1213 }
1214 
1216 {
1217  return QSet<QString>();
1218 }
1219 
1221 {
1222  return QSet<QString>();
1223 }
1224 
1225 QList<const QgsExpressionNode *> QgsExpressionNodeLiteral::nodes() const
1226 {
1227  QList<const QgsExpressionNode *> lst;
1228  lst << this;
1229  return lst;
1230 }
1231 
1233 {
1234  return false;
1235 }
1236 
1238 {
1239  QgsExpressionNodeLiteral *copy = new QgsExpressionNodeLiteral( mValue );
1240  cloneTo( copy );
1241  return copy;
1242 }
1243 
1245 {
1246  Q_UNUSED( context )
1247  Q_UNUSED( parent )
1248  return true;
1249 }
1250 
1251 //
1252 
1254 {
1255  Q_UNUSED( parent )
1256  int index = mIndex;
1257 
1258  if ( index < 0 )
1259  {
1260  // have not yet found field index - first check explicitly set fields collection
1261  if ( context && context->hasVariable( QgsExpressionContext::EXPR_FIELDS ) )
1262  {
1263  QgsFields fields = qvariant_cast<QgsFields>( context->variable( QgsExpressionContext::EXPR_FIELDS ) );
1264  index = fields.lookupField( mName );
1265  }
1266  }
1267 
1268  if ( context )
1269  {
1270  QgsFeature feature = context->feature();
1271  if ( feature.isValid() )
1272  {
1273  if ( index >= 0 )
1274  return feature.attribute( index );
1275  else
1276  return feature.attribute( mName );
1277  }
1278  }
1279  parent->setEvalErrorString( QStringLiteral( "Column '%1' not found" ).arg( mName ) );
1280  return QVariant();
1281 }
1282 
1284 {
1285  return ntColumnRef;
1286 }
1287 
1289 {
1290  if ( !context || !context->hasVariable( QgsExpressionContext::EXPR_FIELDS ) )
1291  return false;
1292 
1293  QgsFields fields = qvariant_cast<QgsFields>( context->variable( QgsExpressionContext::EXPR_FIELDS ) );
1294 
1295  mIndex = fields.lookupField( mName );
1296 
1297  if ( mIndex == -1 && context->hasFeature() )
1298  {
1299  mIndex = context->feature().fieldNameIndex( mName );
1300  }
1301 
1302  if ( mIndex == -1 )
1303  {
1304  parent->setEvalErrorString( tr( "Column '%1' not found" ).arg( mName ) );
1305  return false;
1306  }
1307  return true;
1308 }
1309 
1311 {
1312  return QRegExp( "^[A-Za-z_\x80-\xff][A-Za-z0-9_\x80-\xff]*$" ).exactMatch( mName ) ? mName : QgsExpression::quotedColumnRef( mName );
1313 }
1314 
1316 {
1317  return QSet<QString>() << mName;
1318 }
1319 
1321 {
1322  return QSet<QString>();
1323 }
1324 
1326 {
1327  return QSet<QString>();
1328 }
1329 
1330 QList<const QgsExpressionNode *> QgsExpressionNodeColumnRef::nodes() const
1331 {
1332  QList<const QgsExpressionNode *> result;
1333  result << this;
1334  return result;
1335 }
1336 
1338 {
1339  return false;
1340 }
1341 
1343 {
1345  cloneTo( copy );
1346  return copy;
1347 }
1348 
1350 {
1351  Q_UNUSED( context )
1352  Q_UNUSED( parent )
1353  return false;
1354 }
1355 
1356 //
1357 
1359  : mConditions( *conditions )
1360  , mElseExp( elseExp )
1361 {
1362  delete conditions;
1363 }
1364 
1366 {
1367  delete mElseExp;
1368  qDeleteAll( mConditions );
1369 }
1370 
1372 {
1373  return ntCondition;
1374 }
1375 
1377 {
1378  for ( WhenThen *cond : qgis::as_const( mConditions ) )
1379  {
1380  QVariant vWhen = cond->mWhenExp->eval( parent, context );
1381  QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( vWhen, parent );
1383  if ( tvl == QgsExpressionUtils::True )
1384  {
1385  QVariant vRes = cond->mThenExp->eval( parent, context );
1387  return vRes;
1388  }
1389  }
1390 
1391  if ( mElseExp )
1392  {
1393  QVariant vElse = mElseExp->eval( parent, context );
1395  return vElse;
1396  }
1397 
1398  // return NULL if no condition is matching
1399  return QVariant();
1400 }
1401 
1403 {
1404  bool res;
1405  for ( WhenThen *cond : qgis::as_const( mConditions ) )
1406  {
1407  res = cond->mWhenExp->prepare( parent, context )
1408  & cond->mThenExp->prepare( parent, context );
1409  if ( !res )
1410  return false;
1411  }
1412 
1413  if ( mElseExp )
1414  return mElseExp->prepare( parent, context );
1415 
1416  return true;
1417 }
1418 
1420 {
1421  QString msg( QStringLiteral( "CASE" ) );
1422  for ( WhenThen *cond : mConditions )
1423  {
1424  msg += QStringLiteral( " WHEN %1 THEN %2" ).arg( cond->mWhenExp->dump(), cond->mThenExp->dump() );
1425  }
1426  if ( mElseExp )
1427  msg += QStringLiteral( " ELSE %1" ).arg( mElseExp->dump() );
1428  msg += QStringLiteral( " END" );
1429  return msg;
1430 }
1431 
1433 {
1434  QSet<QString> lst;
1435  for ( WhenThen *cond : mConditions )
1436  {
1437  lst += cond->mWhenExp->referencedColumns() + cond->mThenExp->referencedColumns();
1438  }
1439 
1440  if ( mElseExp )
1441  lst += mElseExp->referencedColumns();
1442 
1443  return lst;
1444 }
1445 
1447 {
1448  QSet<QString> lst;
1449  for ( WhenThen *cond : mConditions )
1450  {
1451  lst += cond->mWhenExp->referencedVariables() + cond->mThenExp->referencedVariables();
1452  }
1453 
1454  if ( mElseExp )
1455  lst += mElseExp->referencedVariables();
1456 
1457  return lst;
1458 }
1459 
1461 {
1462  QSet<QString> lst;
1463  for ( WhenThen *cond : mConditions )
1464  {
1465  lst += cond->mWhenExp->referencedFunctions() + cond->mThenExp->referencedFunctions();
1466  }
1467 
1468  if ( mElseExp )
1469  lst += mElseExp->referencedFunctions();
1470 
1471  return lst;
1472 }
1473 
1474 QList<const QgsExpressionNode *> QgsExpressionNodeCondition::nodes() const
1475 {
1476  QList<const QgsExpressionNode *> lst;
1477  lst << this;
1478  for ( WhenThen *cond : mConditions )
1479  {
1480  lst += cond->mWhenExp->nodes() + cond->mThenExp->nodes();
1481  }
1482 
1483  if ( mElseExp )
1484  lst += mElseExp->nodes();
1485 
1486  return lst;
1487 }
1488 
1490 {
1491  for ( WhenThen *cond : mConditions )
1492  {
1493  if ( cond->mWhenExp->needsGeometry() ||
1494  cond->mThenExp->needsGeometry() )
1495  return true;
1496  }
1497 
1498  return mElseExp && mElseExp->needsGeometry();
1499 }
1500 
1502 {
1504  for ( WhenThen *wt : mConditions )
1505  conditions.append( wt->clone() );
1506 
1507  QgsExpressionNodeCondition *copy = new QgsExpressionNodeCondition( conditions, mElseExp ? mElseExp->clone() : nullptr );
1508  cloneTo( copy );
1509  return copy;
1510 }
1511 
1513 {
1514  for ( WhenThen *wt : mConditions )
1515  {
1516  if ( !wt->mWhenExp->isStatic( parent, context ) || !wt->mThenExp->isStatic( parent, context ) )
1517  return false;
1518  }
1519 
1520  if ( mElseExp )
1521  return mElseExp->isStatic( parent, context );
1522 
1523  return true;
1524 }
1525 
1527 {
1528  QSet<QString> lst( mNode->referencedColumns() );
1529  const QList< QgsExpressionNode * > nodeList = mList->list();
1530  for ( const QgsExpressionNode *n : nodeList )
1531  lst.unite( n->referencedColumns() );
1532  return lst;
1533 }
1534 
1536 {
1537  QSet<QString> lst( mNode->referencedVariables() );
1538  const QList< QgsExpressionNode * > nodeList = mList->list();
1539  for ( const QgsExpressionNode *n : nodeList )
1540  lst.unite( n->referencedVariables() );
1541  return lst;
1542 }
1543 
1545 {
1546  QSet<QString> lst( mNode->referencedFunctions() );
1547  const QList< QgsExpressionNode * > nodeList = mList->list();
1548  for ( const QgsExpressionNode *n : nodeList )
1549  lst.unite( n->referencedFunctions() );
1550  return lst;
1551 }
1552 
1553 QList<const QgsExpressionNode *> QgsExpressionNodeInOperator::nodes() const
1554 {
1555  QList<const QgsExpressionNode *> lst;
1556  lst << this;
1557  const QList< QgsExpressionNode * > nodeList = mList->list();
1558  for ( const QgsExpressionNode *n : nodeList )
1559  lst += n->nodes();
1560  return lst;
1561 }
1562 
1564  : mWhenExp( whenExp )
1565  , mThenExp( thenExp )
1566 {
1567 }
1568 
1570 {
1571  delete mWhenExp;
1572  delete mThenExp;
1573 }
1574 
1576 {
1577  return new WhenThen( mWhenExp->clone(), mThenExp->clone() );
1578 }
1579 
1581 {
1582  return BINARY_OPERATOR_TEXT[mOp];
1583 }
1584 
1585 //
1586 
1588 {
1589  const QVariant container = mContainer->eval( parent, context );
1591  const QVariant index = mIndex->eval( parent, context );
1593 
1594  switch ( container.type() )
1595  {
1596  case QVariant::Map:
1597  return QgsExpressionUtils::getMapValue( container, parent ).value( index.toString() );
1598 
1599  case QVariant::List:
1600  case QVariant::StringList:
1601  {
1602  const QVariantList list = QgsExpressionUtils::getListValue( container, parent );
1603  qlonglong pos = QgsExpressionUtils::getIntValue( index, parent );
1604  if ( pos >= list.length() || pos < -list.length() )
1605  {
1606  return QVariant();
1607  }
1608  if ( pos < 0 )
1609  {
1610  // negative indices are from back of list
1611  pos += list.length();
1612  }
1613 
1614  return list.at( pos );
1615  }
1616 
1617  default:
1618  parent->setEvalErrorString( tr( "[] can only be used with map or array values, not %1" ).arg( QMetaType::typeName( container.type() ) ) );
1619  return QVariant();
1620  }
1621 }
1622 
1624 {
1625  return ntIndexOperator;
1626 }
1627 
1629 {
1630  bool resC = mContainer->prepare( parent, context );
1631  bool resV = mIndex->prepare( parent, context );
1632  return resC && resV;
1633 }
1634 
1636 {
1637  return QStringLiteral( "%1[%2]" ).arg( mContainer->dump(), mIndex->dump() );
1638 }
1639 
1641 {
1642  return mContainer->referencedColumns() + mIndex->referencedColumns();
1643 }
1644 
1646 {
1647  return mContainer->referencedVariables() + mIndex->referencedVariables();
1648 }
1649 
1651 {
1652  return mContainer->referencedFunctions() + mIndex->referencedFunctions();
1653 }
1654 
1655 QList<const QgsExpressionNode *> QgsExpressionNodeIndexOperator::nodes() const
1656 {
1657  QList<const QgsExpressionNode *> lst;
1658  lst << this;
1659  lst += mContainer->nodes() + mIndex->nodes();
1660  return lst;
1661 }
1662 
1664 {
1665  return mContainer->needsGeometry() || mIndex->needsGeometry();
1666 }
1667 
1669 {
1670  QgsExpressionNodeIndexOperator *copy = new QgsExpressionNodeIndexOperator( mContainer->clone(), mIndex->clone() );
1671  cloneTo( copy );
1672  return copy;
1673 }
1674 
1676 {
1677  return mContainer->isStatic( parent, context ) && mIndex->isStatic( parent, context );
1678 }
int lookupField(const QString &fieldName) const
Looks up field&#39;s index from the field name.
Definition: qgsfields.cpp:324
void cloneTo(QgsExpressionNode *target) const
Copies the members of this node to the node provided in target.
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:183
Class for parsing and evaluation of expressions (formerly called "search strings").
QStringList names() const
Returns a list of names for nodes.
QgsExpressionNode * node
Node.
virtual QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)
Evaluates the function, first evaluating all required arguments before passing them to the function&#39;s...
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
bool prepare(QgsExpression *parent, const QgsExpressionContext *context)
Prepare this node for evaluation.
QgsExpressionNodeFunction(int fnIndex, QgsExpressionNode::NodeList *args)
A function node consists of an index of the function in the global function array and a list of argum...
virtual QString dump() const =0
Dump this node into a serialized (part) of an expression.
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node...
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
QgsExpressionNodeCondition(QgsExpressionNodeCondition::WhenThenList *conditions, QgsExpressionNode *elseExp=nullptr)
Create a new node with the given list of conditions and an optional elseExp expression.
int params() const
The number of parameters this function takes.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
int precedence() const
Returns the precedence index for the operator.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
bool hasFunction(const QString &name) const
Checks whether a specified function is contained in the context.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
WhenThenList conditions() const
The list of WHEN THEN expression parts of the expression.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:315
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node...
NodeType
Known node types.
QgsExpressionNodeInOperator(QgsExpressionNode *node, QgsExpressionNode::NodeList *list, bool notin=false)
This node tests if the result of node is in the result of list.
An expression node for CASE WHEN clauses.
double seconds() const
Returns the interval duration in seconds.
Definition: qgsinterval.h:151
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
virtual QSet< QString > referencedColumns(const QgsExpressionNodeFunction *node) const
Returns a set of field names which are required for this function.
Container of fields for a vector layer.
Definition: qgsfields.h:42
bool hasVariable(const QString &name) const
Check whether a variable is specified by any scope within the context.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
virtual QgsExpressionNode * clone() const =0
Generate a clone of this node.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node...
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QList< QgsExpressionFunction::Parameter > ParameterList
List of parameters, used for function definition.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression...
QVariant variable(const QString &name) const
Fetches a matching variable from the context.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node...
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
void setEvalErrorString(const QString &str)
Sets evaluation error (used internally by evaluation functions)
bool hasFeature() const
Returns true if the context has a feature associated with it.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QgsExpressionNode * clone() const override
Generate a clone of this node.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression...
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression...
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
#define ENSURE_NO_EVAL_ERROR
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QString text() const
Returns a the name of this operator without the operands.
#define SET_EVAL_ERROR(x)
#define FALLTHROUGH
Definition: qgis.h:763
virtual QSet< QString > referencedColumns() const =0
Abstract virtual method which returns a list of columns required to evaluate this node...
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node...
virtual QSet< QString > referencedVariables() const =0
Returns a set of all variables which are used in this expression.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
const QString & typeName
const QgsExpressionFunction::ParameterList & parameters() const
Returns the list of named parameters for the function, if set.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
An expression node for value IN or NOT IN clauses.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node...
QgsExpressionNode * clone() const override
Generate a clone of this node.
QgsExpressionNode * clone() const override
Generate a clone of this node.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
An expression node which takes it value from a feature&#39;s field.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
virtual QSet< QString > referencedFunctions() const =0
Returns a set of all functions which are used in this expression.
QString dump() const override
Dump this node into a serialized (part) of an expression.
Abstract base class for all nodes that can appear in an expression.
virtual QString dump() const
Returns a string dump of the expression node.
static const QString EXPR_FIELDS
Inbuilt variable name for fields storage.
QgsExpressionNode * clone() const override
Generate a clone of this node.
An expression node for expression functions.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
static const QList< QgsExpressionFunction * > & Functions()
QVariant eval(QgsExpression *parent, const QgsExpressionContext *context)
Evaluate this node with the given context and parent.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
bool lazyEval() const
true if this function should use lazy evaluation.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
QList< QgsExpressionNodeCondition::WhenThen * > WhenThenList
QgsExpressionNode * clone() const override
Generate a clone of this node.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
QgsExpressionNode::NodeList * clone() const
Creates a deep copy of this list. Ownership is transferred to the caller.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QgsExpressionNode * clone() const override
Generate a clone of this node.
QString name() const
The name of the function.
A representation of the interval between two datetime values.
Definition: qgsinterval.h:39
virtual bool needsGeometry() const =0
Abstract virtual method which returns if the geometry is required to evaluate this expression...
QString dump() const override
Dump this node into a serialized (part) of an expression.
int fieldNameIndex(const QString &fieldName) const
Utility method to get attribute index from name.
Definition: qgsfeature.cpp:277
A abstract base class for defining QgsExpression functions.
A list of expression nodes.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression...
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
QgsExpressionNodeUnaryOperator::UnaryOperator op() const
Returns the unary operator.
QgsExpressionNode * clone() const override
Generate a clone of this node.
A indexing expression operator, which allows use of square brackets [] to reference map and array ite...
An expression node for literal values.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression...
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression...
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
A unary node is either negative as in boolean (not) or as in numbers (minus).
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
A binary expression operator, which operates on two values.
QString dump() const override
Dump this node into a serialized (part) of an expression.
WhenThen(QgsExpressionNode *whenExp, QgsExpressionNode *thenExp)
A combination of when and then.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
QString text() const
Returns a the name of this operator without the operands.
static QString quotedString(QString text)
Returns a quoted version of a string (in single quotes)
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
QgsFeature feature() const
Convenience function for retrieving the feature for the context, if set.
QgsExpressionNodeCondition::WhenThen * clone() const
Gets a deep copy of this WhenThen combination.
virtual bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const =0
Returns true if this node can be evaluated for a static value.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression...
bool leftAssociative() const
Returns true if the operator is left-associative.
int count() const
Returns the number of nodes in the list.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
void append(QgsExpressionNode *node)
Takes ownership of the provided node.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
virtual QList< const QgsExpressionNode * > nodes() const =0
Returns a list of all nodes which are used in this expression.
QgsExpressionNode * node() const
Returns the expression node.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:262
QString dump() const override
Dump this node into a serialized (part) of an expression.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
Represents a "WHEN... THEN..." portation of a CASE WHEN clause in an expression.
virtual bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const
This will be called during the prepare step() of an expression if it is not static.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QgsExpressionFunction * function(const QString &name) const
Fetches a matching function from the context.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression...
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node...
QgsExpressionNode * clone() const override
Generate a clone of this node.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
QVariant value() const
The value of the literal.
bool hasNamedNodes() const
Returns true if list contains any named nodes.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node...
int fnIndex() const
Returns the index of the node&#39;s function.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QString dump() const override
Dump this node into a serialized (part) of an expression.
static bool validateParams(int fnIndex, QgsExpressionNode::NodeList *args, QString &error)
Tests whether the provided argument list is valid for the matching function.