QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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 #include "qgsstringutils.h"
23 
24 #include <QRegularExpression>
25 
26 const char *QgsExpressionNodeBinaryOperator::BINARY_OPERATOR_TEXT[] =
27 {
28  // this must correspond (number and order of element) to the declaration of the enum BinaryOperator
29  "OR", "AND",
30  "=", "<>", "<=", ">=", "<", ">", "~", "LIKE", "NOT LIKE", "ILIKE", "NOT ILIKE", "IS", "IS NOT",
31  "+", "-", "*", "/", "//", "%", "^",
32  "||"
33 };
34 
35 const char *QgsExpressionNodeUnaryOperator::UNARY_OPERATOR_TEXT[] =
36 {
37  // this must correspond (number and order of element) to the declaration of the enum UnaryOperator
38  "NOT", "-"
39 };
40 
42 {
43  bool needs = false;
44  const QList< QgsExpressionNode * > nodeList = mList->list();
45  for ( QgsExpressionNode *n : nodeList )
46  needs |= n->needsGeometry();
47  return needs;
48 }
49 
51 {
52  qDeleteAll( mList );
53 }
54 
56 {
57  mList.append( node->node );
58  mNameList.append( cleanNamedNodeName( node->name ) );
59  mHasNamedNodes = true;
60  delete node;
61 }
62 
64 {
65  NodeList *nl = new NodeList;
66  for ( QgsExpressionNode *node : mList )
67  {
68  nl->mList.append( node->clone() );
69  }
70  nl->mNameList = mNameList;
71 
72  return nl;
73 }
74 
76 {
77  QString msg;
78  bool first = true;
79  for ( QgsExpressionNode *n : mList )
80  {
81  if ( !first ) msg += QLatin1String( ", " );
82  else first = false;
83  msg += n->dump();
84  }
85  return msg;
86 }
87 
88 QString QgsExpressionNode::NodeList::cleanNamedNodeName( const QString &name )
89 {
90  QString cleaned = name.toLower();
91 
92  // upgrade older argument names to standard versions
93  if ( cleaned == QLatin1String( "geom" ) )
94  cleaned = QStringLiteral( "geometry" );
95  else if ( cleaned == QLatin1String( "val" ) )
96  cleaned = QStringLiteral( "value" );
97  else if ( cleaned == QLatin1String( "geometry a" ) )
98  cleaned = QStringLiteral( "geometry1" );
99  else if ( cleaned == QLatin1String( "geometry b" ) )
100  cleaned = QStringLiteral( "geometry2" );
101 
102  return cleaned;
103 }
104 
105 
106 //
107 
109 {
110  QVariant val = mOperand->eval( parent, context );
112 
113  switch ( mOp )
114  {
115  case uoNot:
116  {
117  QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( val, parent );
119  return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::NOT[tvl] );
120  }
121 
122  case uoMinus:
123  if ( QgsExpressionUtils::isIntSafe( val ) )
124  return QVariant( - QgsExpressionUtils::getIntValue( val, parent ) );
125  else if ( QgsExpressionUtils::isDoubleSafe( val ) )
126  return QVariant( - QgsExpressionUtils::getDoubleValue( val, parent ) );
127  else
128  SET_EVAL_ERROR( tr( "Unary minus only for numeric values." ) )
129  }
130  return QVariant();
131 }
132 
134 {
135  return ntUnaryOperator;
136 }
137 
139 {
140  return mOperand->prepare( parent, context );
141 }
142 
144 {
145  if ( dynamic_cast<QgsExpressionNodeBinaryOperator *>( mOperand ) )
146  return QStringLiteral( "%1 ( %2 )" ).arg( UNARY_OPERATOR_TEXT[mOp], mOperand->dump() );
147  else
148  return QStringLiteral( "%1 %2" ).arg( UNARY_OPERATOR_TEXT[mOp], mOperand->dump() );
149 }
150 
152 {
153  if ( hasCachedStaticValue() )
154  return QSet< QString >();
155 
156  return mOperand->referencedColumns();
157 }
158 
160 {
161  return mOperand->referencedVariables();
162 }
163 
165 {
166  return mOperand->referencedFunctions();
167 }
168 
169 QList<const QgsExpressionNode *> QgsExpressionNodeUnaryOperator::nodes() const
170 {
171  QList<const QgsExpressionNode *> lst;
172  lst.append( this );
173  lst += mOperand->nodes();
174  return lst;
175 }
176 
178 {
179  return mOperand->needsGeometry();
180 }
181 
183 {
184  QgsExpressionNodeUnaryOperator *copy = new QgsExpressionNodeUnaryOperator( mOp, mOperand->clone() );
185  cloneTo( copy );
186  return copy;
187 }
188 
190 {
191  return mOperand->isStatic( parent, context );
192 }
193 
195 {
196  return UNARY_OPERATOR_TEXT[mOp];
197 }
198 
199 //
200 
202 {
203  QVariant vL = mOpLeft->eval( parent, context );
205 
206  if ( mOp == boAnd || mOp == boOr )
207  {
208  QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent );
210  if ( mOp == boAnd && tvlL == QgsExpressionUtils::False )
211  return TVL_False; // shortcut -- no need to evaluate right-hand side
212  if ( mOp == boOr && tvlL == QgsExpressionUtils::True )
213  return TVL_True; // shortcut -- no need to evaluate right-hand side
214  }
215 
216  QVariant vR = mOpRight->eval( parent, context );
218 
219  switch ( mOp )
220  {
221  case boPlus:
222  if ( vL.type() == QVariant::String && vR.type() == QVariant::String )
223  {
224  QString sL = QgsExpressionUtils::isNull( vL ) ? QString() : QgsExpressionUtils::getStringValue( vL, parent );
226  QString sR = QgsExpressionUtils::isNull( vR ) ? QString() : QgsExpressionUtils::getStringValue( vR, parent );
228  return QVariant( sL + sR );
229  }
230  //intentional fall-through
232  case boMinus:
233  case boMul:
234  case boDiv:
235  case boMod:
236  {
237  if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
238  return QVariant();
239  else if ( mOp != boDiv && QgsExpressionUtils::isIntSafe( vL ) && QgsExpressionUtils::isIntSafe( vR ) )
240  {
241  // both are integers - let's use integer arithmetic
242  qlonglong iL = QgsExpressionUtils::getIntValue( vL, parent );
244  qlonglong iR = QgsExpressionUtils::getIntValue( vR, parent );
246 
247  if ( mOp == boMod && iR == 0 )
248  return QVariant();
249 
250  return QVariant( computeInt( iL, iR ) );
251  }
252  else if ( QgsExpressionUtils::isDateTimeSafe( vL ) && QgsExpressionUtils::isIntervalSafe( vR ) )
253  {
254  QDateTime dL = QgsExpressionUtils::getDateTimeValue( vL, parent );
256  QgsInterval iL = QgsExpressionUtils::getInterval( vR, parent );
258  if ( mOp == boDiv || mOp == boMul || mOp == boMod )
259  {
260  parent->setEvalErrorString( tr( "Can't perform /, *, or % on DateTime and Interval" ) );
261  return QVariant();
262  }
263  return QVariant( computeDateTimeFromInterval( dL, &iL ) );
264  }
265  else if ( mOp == boPlus && ( ( vL.type() == QVariant::Date && vR.type() == QVariant::Time ) ||
266  ( vR.type() == QVariant::Date && vL.type() == QVariant::Time ) ) )
267  {
268  QDate date = QgsExpressionUtils::getDateValue( vL.type() == QVariant::Date ? vL : vR, parent );
270  QTime time = QgsExpressionUtils::getTimeValue( vR.type() == QVariant::Time ? vR : vL, parent );
272  QDateTime dt = QDateTime( date, time );
273  return QVariant( dt );
274  }
275  else if ( mOp == boMinus && vL.type() == QVariant::Date && vR.type() == QVariant::Date )
276  {
277  QDate date1 = QgsExpressionUtils::getDateValue( vL, parent );
279  QDate date2 = QgsExpressionUtils::getDateValue( vR, parent );
281  return date1 - date2;
282  }
283  else if ( mOp == boMinus && vL.type() == QVariant::Time && vR.type() == QVariant::Time )
284  {
285  QTime time1 = QgsExpressionUtils::getTimeValue( vL, parent );
287  QTime time2 = QgsExpressionUtils::getTimeValue( vR, parent );
289  return time1 - time2;
290  }
291  else if ( mOp == boMinus && vL.type() == QVariant::DateTime && vR.type() == QVariant::DateTime )
292  {
293  QDateTime datetime1 = QgsExpressionUtils::getDateTimeValue( vL, parent );
295  QDateTime datetime2 = QgsExpressionUtils::getDateTimeValue( vR, parent );
297  return datetime1 - datetime2;
298  }
299  else
300  {
301  // general floating point arithmetic
302  double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
304  double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
306  if ( ( mOp == boDiv || mOp == boMod ) && fR == 0. )
307  return QVariant(); // silently handle division by zero and return NULL
308  return QVariant( computeDouble( fL, fR ) );
309  }
310  }
311  case boIntDiv:
312  {
313  //integer division
314  double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
316  double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
318  if ( fR == 0. )
319  return QVariant(); // silently handle division by zero and return NULL
320  return QVariant( qlonglong( std::floor( fL / fR ) ) );
321  }
322  case boPow:
323  if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
324  return QVariant();
325  else
326  {
327  double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
329  double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
331  return QVariant( std::pow( fL, fR ) );
332  }
333 
334  case boAnd:
335  {
336  QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent ), tvlR = QgsExpressionUtils::getTVLValue( vR, parent );
338  return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::AND[tvlL][tvlR] );
339  }
340 
341  case boOr:
342  {
343  QgsExpressionUtils::TVL tvlL = QgsExpressionUtils::getTVLValue( vL, parent ), tvlR = QgsExpressionUtils::getTVLValue( vR, parent );
345  return QgsExpressionUtils::tvl2variant( QgsExpressionUtils::OR[tvlL][tvlR] );
346  }
347 
348  case boEQ:
349  case boNE:
350  case boLT:
351  case boGT:
352  case boLE:
353  case boGE:
354  if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
355  {
356  return TVL_Unknown;
357  }
358  else if ( QgsExpressionUtils::isList( vL ) || QgsExpressionUtils::isList( vR ) )
359  {
360  // verify that we have two lists
361  if ( !QgsExpressionUtils::isList( vL ) || !QgsExpressionUtils::isList( vR ) )
362  return TVL_Unknown;
363 
364  // and search for not equal respective items
365  QVariantList lL = vL.toList();
366  QVariantList lR = vR.toList();
367  for ( int i = 0; i < lL.length() && i < lR.length(); i++ )
368  {
369  if ( QgsExpressionUtils::isNull( lL.at( i ) ) && QgsExpressionUtils::isNull( lR.at( i ) ) )
370  continue; // same behavior as PostgreSQL
371 
372  if ( QgsExpressionUtils::isNull( lL.at( i ) ) || QgsExpressionUtils::isNull( lR.at( i ) ) )
373  {
374  switch ( mOp )
375  {
376  case boEQ:
377  return false;
378  case boNE:
379  return true;
380  case boLT:
381  case boLE:
382  return QgsExpressionUtils::isNull( lR.at( i ) );
383  case boGT:
384  case boGE:
385  return QgsExpressionUtils::isNull( lL.at( i ) );
386  default:
387  Q_ASSERT( false );
388  return TVL_Unknown;
389  }
390  }
391 
392  QgsExpressionNodeLiteral nL( lL.at( i ) );
393  QgsExpressionNodeLiteral nR( lR.at( i ) );
394  QgsExpressionNodeBinaryOperator eqNode( boEQ, nL.clone(), nR.clone() );
395  QVariant eq = eqNode.eval( parent, context );
397  if ( eq == TVL_False )
398  {
399  // return the two items comparison
400  QgsExpressionNodeBinaryOperator node( mOp, nL.clone(), nR.clone() );
401  QVariant v = node.eval( parent, context );
403  return v;
404  }
405  }
406 
407  // default to length comparison
408  switch ( mOp )
409  {
410  case boEQ:
411  return lL.length() == lR.length();
412  case boNE:
413  return lL.length() != lR.length();
414  case boLT:
415  return lL.length() < lR.length();
416  case boGT:
417  return lL.length() > lR.length();
418  case boLE:
419  return lL.length() <= lR.length();
420  case boGE:
421  return lL.length() >= lR.length();
422  default:
423  Q_ASSERT( false );
424  return TVL_Unknown;
425  }
426  }
427  else if ( ( vL.type() == QVariant::DateTime && vR.type() == QVariant::DateTime ) )
428  {
429  QDateTime dL = QgsExpressionUtils::getDateTimeValue( vL, parent );
431  QDateTime dR = QgsExpressionUtils::getDateTimeValue( vR, parent );
433 
434  // while QDateTime has innate handling of timezones, we don't expose these ANYWHERE
435  // in QGIS. So to avoid confusion where seemingly equal datetime values give unexpected
436  // results (due to different hidden timezones), we force all datetime comparisons to treat
437  // all datetime values as having the same time zone
438  dL.setTimeSpec( Qt::UTC );
439  dR.setTimeSpec( Qt::UTC );
440 
441  return compare( dR.msecsTo( dL ) ) ? TVL_True : TVL_False;
442  }
443  else if ( ( vL.type() == QVariant::Date && vR.type() == QVariant::Date ) )
444  {
445  const QDate dL = QgsExpressionUtils::getDateValue( vL, parent );
447  const QDate dR = QgsExpressionUtils::getDateValue( vR, parent );
449  return compare( dR.daysTo( dL ) ) ? TVL_True : TVL_False;
450  }
451  else if ( ( vL.type() == QVariant::Time && vR.type() == QVariant::Time ) )
452  {
453  const QTime dL = QgsExpressionUtils::getTimeValue( vL, parent );
455  const QTime dR = QgsExpressionUtils::getTimeValue( vR, parent );
457  return compare( dR.msecsTo( dL ) ) ? TVL_True : TVL_False;
458  }
459  else if ( ( vL.type() != QVariant::String || vR.type() != QVariant::String ) &&
460  QgsExpressionUtils::isDoubleSafe( vL ) && QgsExpressionUtils::isDoubleSafe( vR ) )
461  {
462  // do numeric comparison if both operators can be converted to numbers,
463  // and they aren't both string
464  double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
466  double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
468  return compare( fL - fR ) ? TVL_True : TVL_False;
469  }
470  // warning - QgsExpression::isIntervalSafe is VERY expensive and should not be used here
471  else if ( vL.canConvert< QgsInterval >() && vR.canConvert< QgsInterval >() )
472  {
473  double fL = QgsExpressionUtils::getInterval( vL, parent ).seconds();
475  double fR = QgsExpressionUtils::getInterval( vR, parent ).seconds();
477  return compare( fL - fR ) ? TVL_True : TVL_False;
478  }
479  else
480  {
481  // do string comparison otherwise
482  QString sL = QgsExpressionUtils::getStringValue( vL, parent );
484  QString sR = QgsExpressionUtils::getStringValue( vR, parent );
486  int diff = QString::compare( sL, sR );
487  return compare( diff ) ? TVL_True : TVL_False;
488  }
489 
490  case boIs:
491  case boIsNot:
492  if ( QgsExpressionUtils::isNull( vL ) && QgsExpressionUtils::isNull( vR ) ) // both operators null
493  return ( mOp == boIs ? TVL_True : TVL_False );
494  else if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) ) // one operator null
495  return ( mOp == boIs ? TVL_False : TVL_True );
496  else // both operators non-null
497  {
498  bool equal = false;
499  if ( QgsExpressionUtils::isDoubleSafe( vL ) && QgsExpressionUtils::isDoubleSafe( vR ) &&
500  ( vL.type() != QVariant::String || vR.type() != QVariant::String ) )
501  {
502  double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
504  double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
506  equal = qgsDoubleNear( fL, fR );
507  }
508  else
509  {
510  QString sL = QgsExpressionUtils::getStringValue( vL, parent );
512  QString sR = QgsExpressionUtils::getStringValue( vR, parent );
514  equal = QString::compare( sL, sR ) == 0;
515  }
516  if ( equal )
517  return mOp == boIs ? TVL_True : TVL_False;
518  else
519  return mOp == boIs ? TVL_False : TVL_True;
520  }
521 
522  case boRegexp:
523  case boLike:
524  case boNotLike:
525  case boILike:
526  case boNotILike:
527  if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
528  return TVL_Unknown;
529  else
530  {
531  QString str = QgsExpressionUtils::getStringValue( vL, parent );
533  QString regexp = QgsExpressionUtils::getStringValue( vR, parent );
535  // TODO: cache QRegularExpression in case that regexp is a literal string (i.e. it will stay constant)
536  bool matches;
537  if ( mOp == boLike || mOp == boILike || mOp == boNotLike || mOp == boNotILike ) // change from LIKE syntax to regexp
538  {
539  QString esc_regexp = QgsStringUtils::qRegExpEscape( regexp );
540  // manage escape % and _
541  if ( esc_regexp.startsWith( '%' ) )
542  {
543  esc_regexp.replace( 0, 1, QStringLiteral( ".*" ) );
544  }
545  const thread_local QRegularExpression rx1( QStringLiteral( "[^\\\\](%)" ) );
546  int pos = 0;
547  while ( ( pos = esc_regexp.indexOf( rx1, pos ) ) != -1 )
548  {
549  esc_regexp.replace( pos + 1, 1, QStringLiteral( ".*" ) );
550  pos += 1;
551  }
552  const thread_local QRegularExpression rx2( QStringLiteral( "\\\\%" ) );
553  esc_regexp.replace( rx2, QStringLiteral( "%" ) );
554  if ( esc_regexp.startsWith( '_' ) )
555  {
556  esc_regexp.replace( 0, 1, QStringLiteral( "." ) );
557  }
558  const thread_local QRegularExpression rx3( QStringLiteral( "[^\\\\](_)" ) );
559  pos = 0;
560  while ( ( pos = esc_regexp.indexOf( rx3, pos ) ) != -1 )
561  {
562  esc_regexp.replace( pos + 1, 1, '.' );
563  pos += 1;
564  }
565  esc_regexp.replace( QLatin1String( "\\\\_" ), QLatin1String( "_" ) );
566 
567  matches = QRegularExpression( QRegularExpression::anchoredPattern( esc_regexp ), mOp == boLike || mOp == boNotLike ? QRegularExpression::DotMatchesEverythingOption : QRegularExpression::DotMatchesEverythingOption | QRegularExpression::CaseInsensitiveOption ).match( str ).hasMatch();
568  }
569  else
570  {
571  matches = QRegularExpression( regexp ).match( str ).hasMatch();
572  }
573 
574  if ( mOp == boNotLike || mOp == boNotILike )
575  {
576  matches = !matches;
577  }
578 
579  return matches ? TVL_True : TVL_False;
580  }
581 
582  case boConcat:
583  if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
584  return QVariant();
585  else
586  {
587  QString sL = QgsExpressionUtils::getStringValue( vL, parent );
589  QString sR = QgsExpressionUtils::getStringValue( vR, parent );
591  return QVariant( sL + sR );
592  }
593  }
594  Q_ASSERT( false );
595  return QVariant();
596 }
597 
598 bool QgsExpressionNodeBinaryOperator::compare( double diff )
599 {
600  switch ( mOp )
601  {
602  case boEQ:
603  return qgsDoubleNear( diff, 0.0 );
604  case boNE:
605  return !qgsDoubleNear( diff, 0.0 );
606  case boLT:
607  return diff < 0;
608  case boGT:
609  return diff > 0;
610  case boLE:
611  return diff <= 0;
612  case boGE:
613  return diff >= 0;
614  default:
615  Q_ASSERT( false );
616  return false;
617  }
618 }
619 
620 qlonglong QgsExpressionNodeBinaryOperator::computeInt( qlonglong x, qlonglong y )
621 {
622  switch ( mOp )
623  {
624  case boPlus:
625  return x + y;
626  case boMinus:
627  return x - y;
628  case boMul:
629  return x * y;
630  case boDiv:
631  return x / y;
632  case boMod:
633  return x % y;
634  default:
635  Q_ASSERT( false );
636  return 0;
637  }
638 }
639 
640 QDateTime QgsExpressionNodeBinaryOperator::computeDateTimeFromInterval( const QDateTime &d, QgsInterval *i )
641 {
642  switch ( mOp )
643  {
644  case boPlus:
645  return d.addSecs( i->seconds() );
646  case boMinus:
647  return d.addSecs( -i->seconds() );
648  default:
649  Q_ASSERT( false );
650  return QDateTime();
651  }
652 }
653 
654 double QgsExpressionNodeBinaryOperator::computeDouble( double x, double y )
655 {
656  switch ( mOp )
657  {
658  case boPlus:
659  return x + y;
660  case boMinus:
661  return x - y;
662  case boMul:
663  return x * y;
664  case boDiv:
665  return x / y;
666  case boMod:
667  return std::fmod( x, y );
668  default:
669  Q_ASSERT( false );
670  return 0;
671  }
672 }
673 
675 {
676  return ntBinaryOperator;
677 }
678 
680 {
681  bool resL = mOpLeft->prepare( parent, context );
682  bool resR = mOpRight->prepare( parent, context );
683  return resL && resR;
684 }
685 
687 {
688  // see left/right in qgsexpressionparser.yy
689  switch ( mOp )
690  {
691  case boOr:
692  return 1;
693 
694  case boAnd:
695  return 2;
696 
697  case boEQ:
698  case boNE:
699  case boLE:
700  case boGE:
701  case boLT:
702  case boGT:
703  case boRegexp:
704  case boLike:
705  case boILike:
706  case boNotLike:
707  case boNotILike:
708  case boIs:
709  case boIsNot:
710  return 3;
711 
712  case boPlus:
713  case boMinus:
714  return 4;
715 
716  case boMul:
717  case boDiv:
718  case boIntDiv:
719  case boMod:
720  return 5;
721 
722  case boPow:
723  return 6;
724 
725  case boConcat:
726  return 7;
727  }
728  Q_ASSERT( false && "unexpected binary operator" );
729  return -1;
730 }
731 
733 {
734  // see left/right in qgsexpressionparser.yy
735  switch ( mOp )
736  {
737  case boOr:
738  case boAnd:
739  case boEQ:
740  case boNE:
741  case boLE:
742  case boGE:
743  case boLT:
744  case boGT:
745  case boRegexp:
746  case boLike:
747  case boILike:
748  case boNotLike:
749  case boNotILike:
750  case boIs:
751  case boIsNot:
752  case boPlus:
753  case boMinus:
754  case boMul:
755  case boDiv:
756  case boIntDiv:
757  case boMod:
758  case boConcat:
759  return true;
760 
761  case boPow:
762  return false;
763  }
764  Q_ASSERT( false && "unexpected binary operator" );
765  return false;
766 }
767 
769 {
770  QgsExpressionNodeBinaryOperator *lOp = dynamic_cast<QgsExpressionNodeBinaryOperator *>( mOpLeft );
771  QgsExpressionNodeBinaryOperator *rOp = dynamic_cast<QgsExpressionNodeBinaryOperator *>( mOpRight );
772  QgsExpressionNodeUnaryOperator *ruOp = dynamic_cast<QgsExpressionNodeUnaryOperator *>( mOpRight );
773 
774  QString rdump( mOpRight->dump() );
775 
776  // avoid dumping "IS (NOT ...)" as "IS NOT ..."
777  if ( mOp == boIs && ruOp && ruOp->op() == QgsExpressionNodeUnaryOperator::uoNot )
778  {
779  rdump.prepend( '(' ).append( ')' );
780  }
781 
782  QString fmt;
783  if ( leftAssociative() )
784  {
785  fmt += lOp && ( lOp->precedence() < precedence() ) ? QStringLiteral( "(%1)" ) : QStringLiteral( "%1" );
786  fmt += QLatin1String( " %2 " );
787  fmt += rOp && ( rOp->precedence() <= precedence() ) ? QStringLiteral( "(%3)" ) : QStringLiteral( "%3" );
788  }
789  else
790  {
791  fmt += lOp && ( lOp->precedence() <= precedence() ) ? QStringLiteral( "(%1)" ) : QStringLiteral( "%1" );
792  fmt += QLatin1String( " %2 " );
793  fmt += rOp && ( rOp->precedence() < precedence() ) ? QStringLiteral( "(%3)" ) : QStringLiteral( "%3" );
794  }
795 
796  return fmt.arg( mOpLeft->dump(), BINARY_OPERATOR_TEXT[mOp], rdump );
797 }
798 
800 {
801  if ( hasCachedStaticValue() )
802  return QSet< QString >();
803 
804  return mOpLeft->referencedColumns() + mOpRight->referencedColumns();
805 }
806 
808 {
809  return mOpLeft->referencedVariables() + mOpRight->referencedVariables();
810 }
811 
813 {
814  return mOpLeft->referencedFunctions() + mOpRight->referencedFunctions();
815 }
816 
817 QList<const QgsExpressionNode *> QgsExpressionNodeBinaryOperator::nodes() const
818 {
819  QList<const QgsExpressionNode *> lst;
820  lst << this;
821  lst += mOpLeft->nodes() + mOpRight->nodes();
822  return lst;
823 }
824 
826 {
827  return mOpLeft->needsGeometry() || mOpRight->needsGeometry();
828 }
829 
831 {
832  QgsExpressionNodeBinaryOperator *copy = new QgsExpressionNodeBinaryOperator( mOp, mOpLeft->clone(), mOpRight->clone() );
833  cloneTo( copy );
834  return copy;
835 }
836 
838 {
839  const bool leftStatic = mOpLeft->isStatic( parent, context );
840  const bool rightStatic = mOpRight->isStatic( parent, context );
841 
842  if ( leftStatic && rightStatic )
843  return true;
844 
845  // special logic for certain ops...
846  switch ( mOp )
847  {
849  {
850  // if either node is static AND evaluates to TRUE, then the result will ALWAYS be true regardless
851  // of the value of the other node!
852  if ( leftStatic )
853  {
854  mOpLeft->prepare( parent, context );
855  if ( mOpLeft->hasCachedStaticValue() )
856  {
857  QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpLeft->cachedStaticValue(), parent );
858  if ( !parent->hasEvalError() && tvl == QgsExpressionUtils::True )
859  {
860  mCachedStaticValue = true;
861  mHasCachedValue = true;
862  return true;
863  }
864  }
865  }
866  else if ( rightStatic )
867  {
868  mOpRight->prepare( parent, context );
869  if ( mOpRight->hasCachedStaticValue() )
870  {
871  QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpRight->cachedStaticValue(), parent );
872  if ( !parent->hasEvalError() && tvl == QgsExpressionUtils::True )
873  {
874  mCachedStaticValue = true;
875  mHasCachedValue = true;
876  return true;
877  }
878  }
879  }
880 
881  break;
882  }
884  {
885  // if either node is static AND evaluates to FALSE, then the result will ALWAYS be false regardless
886  // of the value of the other node!
887 
888  if ( leftStatic )
889  {
890  mOpLeft->prepare( parent, context );
891  if ( mOpLeft->hasCachedStaticValue() )
892  {
893  QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpLeft->cachedStaticValue(), parent );
894  if ( !parent->hasEvalError() && tvl == QgsExpressionUtils::False )
895  {
896  mCachedStaticValue = false;
897  mHasCachedValue = true;
898  return true;
899  }
900  }
901  }
902  else if ( rightStatic )
903  {
904  mOpRight->prepare( parent, context );
905  if ( mOpRight->hasCachedStaticValue() )
906  {
907  QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( mOpRight->cachedStaticValue(), parent );
908  if ( !parent->hasEvalError() && tvl == QgsExpressionUtils::False )
909  {
910  mCachedStaticValue = false;
911  mHasCachedValue = true;
912  return true;
913  }
914  }
915  }
916 
917  break;
918  }
919 
941  break;
942  }
943 
944  return false;
945 }
946 
947 //
948 
950 {
951  if ( mList->count() == 0 )
952  return mNotIn ? TVL_True : TVL_False;
953  QVariant v1 = mNode->eval( parent, context );
955  if ( QgsExpressionUtils::isNull( v1 ) )
956  return TVL_Unknown;
957 
958  bool listHasNull = false;
959 
960  const QList< QgsExpressionNode * > nodeList = mList->list();
961  for ( QgsExpressionNode *n : nodeList )
962  {
963  QVariant v2 = n->eval( parent, context );
965  if ( QgsExpressionUtils::isNull( v2 ) )
966  listHasNull = true;
967  else
968  {
969  bool equal = false;
970  // check whether they are equal
971  if ( ( v1.type() != QVariant::String || v2.type() != QVariant::String ) &&
972  QgsExpressionUtils::isDoubleSafe( v1 ) && QgsExpressionUtils::isDoubleSafe( v2 ) )
973  {
974  // do numeric comparison if both operators can be converted to numbers,
975  // and they aren't both string
976  double f1 = QgsExpressionUtils::getDoubleValue( v1, parent );
978  double f2 = QgsExpressionUtils::getDoubleValue( v2, parent );
980  equal = qgsDoubleNear( f1, f2 );
981  }
982  else
983  {
984  QString s1 = QgsExpressionUtils::getStringValue( v1, parent );
986  QString s2 = QgsExpressionUtils::getStringValue( v2, parent );
988  equal = QString::compare( s1, s2 ) == 0;
989  }
990 
991  if ( equal ) // we know the result
992  return mNotIn ? TVL_False : TVL_True;
993  }
994  }
995 
996  // item not found
997  if ( listHasNull )
998  return TVL_Unknown;
999  else
1000  return mNotIn ? TVL_True : TVL_False;
1001 }
1002 
1004 {
1005  delete mNode;
1006  delete mList;
1007 }
1008 
1010 {
1011  return ntInOperator;
1012 }
1013 
1015 {
1016  bool res = mNode->prepare( parent, context );
1017  const QList< QgsExpressionNode * > nodeList = mList->list();
1018  for ( QgsExpressionNode *n : nodeList )
1019  {
1020  res = res && n->prepare( parent, context );
1021  }
1022  return res;
1023 }
1024 
1026 {
1027  return QStringLiteral( "%1 %2 IN (%3)" ).arg( mNode->dump(), mNotIn ? "NOT" : "", mList->dump() );
1028 }
1029 
1031 {
1032  QgsExpressionNodeInOperator *copy = new QgsExpressionNodeInOperator( mNode->clone(), mList->clone(), mNotIn );
1033  cloneTo( copy );
1034  return copy;
1035 }
1036 
1038 {
1039  if ( !mNode->isStatic( parent, context ) )
1040  return false;
1041 
1042  const QList< QgsExpressionNode * > nodeList = mList->list();
1043  for ( QgsExpressionNode *n : nodeList )
1044  {
1045  if ( !n->isStatic( parent, context ) )
1046  return false;
1047  }
1048 
1049  return true;
1050 }
1051 
1052 //
1053 
1055 {
1056  QString name = QgsExpression::QgsExpression::Functions()[mFnIndex]->name();
1057  QgsExpressionFunction *fd = context && context->hasFunction( name ) ? context->function( name ) : QgsExpression::QgsExpression::Functions()[mFnIndex];
1058 
1059  QVariant res = fd->run( mArgs, context, parent, this );
1061 
1062  // everything went fine
1063  return res;
1064 }
1065 
1067  : mFnIndex( fnIndex )
1068 {
1069  const QgsExpressionFunction::ParameterList &functionParams = QgsExpression::QgsExpression::Functions()[mFnIndex]->parameters();
1070  if ( functionParams.isEmpty() )
1071  {
1072  // function does not support parameters
1073  mArgs = args;
1074  }
1075  else if ( !args )
1076  {
1077  // no arguments specified, but function has parameters. Build a list of default parameter values for the arguments list.
1078  mArgs = new NodeList();
1079  for ( const QgsExpressionFunction::Parameter &param : functionParams )
1080  {
1081  // insert default value for QgsExpressionFunction::Parameter
1082  mArgs->append( new QgsExpressionNodeLiteral( param.defaultValue() ) );
1083  }
1084  }
1085  else
1086  {
1087  mArgs = new NodeList();
1088 
1089  int idx = 0;
1090  //first loop through unnamed arguments
1091  while ( idx < args->names().size() && args->names().at( idx ).isEmpty() )
1092  {
1093  mArgs->append( args->list().at( idx )->clone() );
1094  idx++;
1095  }
1096 
1097  //next copy named QgsExpressionFunction::Parameters in order expected by function
1098  for ( ; idx < functionParams.count(); ++idx )
1099  {
1100  int nodeIdx = args->names().indexOf( functionParams.at( idx ).name().toLower() );
1101  if ( nodeIdx < 0 )
1102  {
1103  //QgsExpressionFunction::Parameter not found - insert default value for QgsExpressionFunction::Parameter
1104  mArgs->append( new QgsExpressionNodeLiteral( functionParams.at( idx ).defaultValue() ) );
1105  }
1106  else
1107  {
1108  mArgs->append( args->list().at( nodeIdx )->clone() );
1109  }
1110  }
1111 
1112  delete args;
1113  }
1114 }
1115 
1117 {
1118  delete mArgs;
1119 }
1120 
1122 {
1123  return ntFunction;
1124 }
1125 
1127 {
1128  QgsExpressionFunction *fd = QgsExpression::QgsExpression::Functions()[mFnIndex];
1129 
1130  bool res = fd->prepare( this, parent, context );
1131  if ( mArgs && !fd->lazyEval() )
1132  {
1133  const QList< QgsExpressionNode * > nodeList = mArgs->list();
1134  for ( QgsExpressionNode *n : nodeList )
1135  {
1136  res = res && n->prepare( parent, context );
1137  }
1138  }
1139  return res;
1140 }
1141 
1143 {
1144  QgsExpressionFunction *fd = QgsExpression::QgsExpression::Functions()[mFnIndex];
1145  if ( fd->params() == 0 )
1146  return QStringLiteral( "%1%2" ).arg( fd->name(), fd->name().startsWith( '$' ) ? QString() : QStringLiteral( "()" ) ); // special column
1147  else
1148  return QStringLiteral( "%1(%2)" ).arg( fd->name(), mArgs ? mArgs->dump() : QString() ); // function
1149 }
1150 
1152 {
1153  if ( hasCachedStaticValue() )
1154  return QSet< QString >();
1155 
1156  QgsExpressionFunction *fd = QgsExpression::QgsExpression::Functions()[mFnIndex];
1157  QSet<QString> functionColumns = fd->referencedColumns( this );
1158 
1159  if ( !mArgs )
1160  {
1161  //no referenced columns in arguments, just return function's referenced columns
1162  return functionColumns;
1163  }
1164 
1165  int paramIndex = 0;
1166  const QList< QgsExpressionNode * > nodeList = mArgs->list();
1167  for ( QgsExpressionNode *n : nodeList )
1168  {
1169  if ( fd->parameters().count() <= paramIndex || !fd->parameters().at( paramIndex ).isSubExpression() )
1170  functionColumns.unite( n->referencedColumns() );
1171  paramIndex++;
1172  }
1173 
1174  return functionColumns;
1175 }
1176 
1178 {
1179  QgsExpressionFunction *fd = QgsExpression::QgsExpression::Functions()[mFnIndex];
1180  if ( fd->name() == QLatin1String( "var" ) )
1181  {
1182  if ( !mArgs->list().isEmpty() )
1183  {
1184  QgsExpressionNodeLiteral *var = dynamic_cast<QgsExpressionNodeLiteral *>( mArgs->list().at( 0 ) );
1185  if ( var )
1186  return QSet<QString>() << var->value().toString();
1187  }
1188  return QSet<QString>() << QString();
1189  }
1190  else
1191  {
1192  QSet<QString> functionVariables = QSet<QString>();
1193 
1194  if ( !mArgs )
1195  return functionVariables;
1196 
1197  const QList< QgsExpressionNode * > nodeList = mArgs->list();
1198  for ( QgsExpressionNode *n : nodeList )
1199  {
1200  functionVariables.unite( n->referencedVariables() );
1201  }
1202 
1203  return functionVariables;
1204  }
1205 }
1206 
1208 {
1209  QgsExpressionFunction *fd = QgsExpression::QgsExpression::Functions()[mFnIndex];
1210  QSet<QString> functions = QSet<QString>();
1211  functions.insert( fd->name() );
1212 
1213  if ( !mArgs )
1214  return functions;
1215 
1216  const QList< QgsExpressionNode * > nodeList = mArgs->list();
1217  for ( QgsExpressionNode *n : nodeList )
1218  {
1219  functions.unite( n->referencedFunctions() );
1220  }
1221  return functions;
1222 }
1223 
1224 QList<const QgsExpressionNode *> QgsExpressionNodeFunction::nodes() const
1225 {
1226  QList<const QgsExpressionNode *> lst;
1227  lst << this;
1228  if ( !mArgs )
1229  return lst;
1230 
1231  const QList< QgsExpressionNode * > nodeList = mArgs->list();
1232  for ( QgsExpressionNode *n : nodeList )
1233  {
1234  lst += n->nodes();
1235  }
1236  return lst;
1237 }
1238 
1240 {
1241  bool needs = QgsExpression::QgsExpression::Functions()[mFnIndex]->usesGeometry( this );
1242  if ( mArgs )
1243  {
1244  const QList< QgsExpressionNode * > nodeList = mArgs->list();
1245  for ( QgsExpressionNode *n : nodeList )
1246  needs |= n->needsGeometry();
1247  }
1248  return needs;
1249 }
1250 
1252 {
1253  QgsExpressionNodeFunction *copy = new QgsExpressionNodeFunction( mFnIndex, mArgs ? mArgs->clone() : nullptr );
1254  cloneTo( copy );
1255  return copy;
1256 }
1257 
1259 {
1260  return QgsExpression::Functions()[mFnIndex]->isStatic( this, parent, context );
1261 }
1262 
1264 {
1265  if ( !args || !args->hasNamedNodes() )
1266  return true;
1267 
1268  const QgsExpressionFunction::ParameterList &functionParams = QgsExpression::Functions()[fnIndex]->parameters();
1269  if ( functionParams.isEmpty() )
1270  {
1271  error = QStringLiteral( "%1 does not support named QgsExpressionFunction::Parameters" ).arg( QgsExpression::Functions()[fnIndex]->name() );
1272  return false;
1273  }
1274  else
1275  {
1276  QSet< int > providedArgs;
1277  QSet< int > handledArgs;
1278  int idx = 0;
1279  //first loop through unnamed arguments
1280  while ( args->names().at( idx ).isEmpty() )
1281  {
1282  providedArgs << idx;
1283  handledArgs << idx;
1284  idx++;
1285  }
1286 
1287  //next check named QgsExpressionFunction::Parameters
1288  for ( ; idx < functionParams.count(); ++idx )
1289  {
1290  int nodeIdx = args->names().indexOf( functionParams.at( idx ).name().toLower() );
1291  if ( nodeIdx < 0 )
1292  {
1293  if ( !functionParams.at( idx ).optional() )
1294  {
1295  error = QStringLiteral( "No value specified for QgsExpressionFunction::Parameter '%1' for %2" ).arg( functionParams.at( idx ).name(), QgsExpression::Functions()[fnIndex]->name() );
1296  return false;
1297  }
1298  }
1299  else
1300  {
1301  if ( providedArgs.contains( idx ) )
1302  {
1303  error = QStringLiteral( "Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2" ).arg( functionParams.at( idx ).name(), QgsExpression::Functions()[fnIndex]->name() );
1304  return false;
1305  }
1306  }
1307  providedArgs << idx;
1308  handledArgs << nodeIdx;
1309  }
1310 
1311  //last check for bad names
1312  idx = 0;
1313  const QStringList nameList = args->names();
1314  for ( const QString &name : nameList )
1315  {
1316  if ( !name.isEmpty() && !functionParams.contains( name ) )
1317  {
1318  error = QStringLiteral( "Invalid QgsExpressionFunction::Parameter name '%1' for %2" ).arg( name, QgsExpression::Functions()[fnIndex]->name() );
1319  return false;
1320  }
1321  if ( !name.isEmpty() && !handledArgs.contains( idx ) )
1322  {
1323  int functionIdx = functionParams.indexOf( name );
1324  if ( providedArgs.contains( functionIdx ) )
1325  {
1326  error = QStringLiteral( "Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2" ).arg( functionParams.at( functionIdx ).name(), QgsExpression::Functions()[fnIndex]->name() );
1327  return false;
1328  }
1329  }
1330  idx++;
1331  }
1332 
1333  }
1334  return true;
1335 }
1336 
1337 //
1338 
1340 {
1341  Q_UNUSED( context )
1342  Q_UNUSED( parent )
1343  return mValue;
1344 }
1345 
1347 {
1348  return ntLiteral;
1349 }
1350 
1352 {
1353  Q_UNUSED( parent )
1354  Q_UNUSED( context )
1355  return true;
1356 }
1357 
1358 
1360 {
1361  if ( mValue.isNull() )
1362  return QStringLiteral( "NULL" );
1363 
1364  switch ( mValue.type() )
1365  {
1366  case QVariant::Int:
1367  return QString::number( mValue.toInt() );
1368  case QVariant::Double:
1369  return QString::number( mValue.toDouble() );
1370  case QVariant::LongLong:
1371  return QString::number( mValue.toLongLong() );
1372  case QVariant::String:
1373  return QgsExpression::quotedString( mValue.toString() );
1374  case QVariant::Bool:
1375  return mValue.toBool() ? QStringLiteral( "TRUE" ) : QStringLiteral( "FALSE" );
1376  default:
1377  return tr( "[unsupported type: %1; value: %2]" ).arg( mValue.typeName(), mValue.toString() );
1378  }
1379 }
1380 
1382 {
1383  return valueAsString();
1384 }
1385 
1387 {
1388  return QSet<QString>();
1389 }
1390 
1392 {
1393  return QSet<QString>();
1394 }
1395 
1397 {
1398  return QSet<QString>();
1399 }
1400 
1401 QList<const QgsExpressionNode *> QgsExpressionNodeLiteral::nodes() const
1402 {
1403  QList<const QgsExpressionNode *> lst;
1404  lst << this;
1405  return lst;
1406 }
1407 
1409 {
1410  return false;
1411 }
1412 
1414 {
1415  QgsExpressionNodeLiteral *copy = new QgsExpressionNodeLiteral( mValue );
1416  cloneTo( copy );
1417  return copy;
1418 }
1419 
1421 {
1422  Q_UNUSED( context )
1423  Q_UNUSED( parent )
1424  return true;
1425 }
1426 
1427 //
1428 
1430 {
1431  Q_UNUSED( parent )
1432  int index = mIndex;
1433 
1434  if ( index < 0 )
1435  {
1436  // have not yet found field index - first check explicitly set fields collection
1437  if ( context && context->hasVariable( QgsExpressionContext::EXPR_FIELDS ) )
1438  {
1439  QgsFields fields = qvariant_cast<QgsFields>( context->variable( QgsExpressionContext::EXPR_FIELDS ) );
1440  index = fields.lookupField( mName );
1441  }
1442  }
1443 
1444  if ( context )
1445  {
1446  QgsFeature feature = context->feature();
1447  if ( feature.isValid() )
1448  {
1449  if ( index >= 0 )
1450  return feature.attribute( index );
1451  else
1452  return feature.attribute( mName );
1453  }
1454  else
1455  {
1456  parent->setEvalErrorString( tr( "No feature available for field '%1' evaluation" ).arg( mName ) );
1457  }
1458  }
1459  if ( index < 0 )
1460  parent->setEvalErrorString( tr( "Field '%1' not found" ).arg( mName ) );
1461  return QVariant();
1462 }
1463 
1465 {
1466  return ntColumnRef;
1467 }
1468 
1470 {
1471  if ( !context || !context->hasVariable( QgsExpressionContext::EXPR_FIELDS ) )
1472  return false;
1473 
1474  QgsFields fields = qvariant_cast<QgsFields>( context->variable( QgsExpressionContext::EXPR_FIELDS ) );
1475 
1476  mIndex = fields.lookupField( mName );
1477 
1478  if ( mIndex == -1 && context->hasFeature() )
1479  {
1480  mIndex = context->feature().fieldNameIndex( mName );
1481  }
1482 
1483  if ( mIndex == -1 )
1484  {
1485  parent->setEvalErrorString( tr( "Field '%1' not found" ).arg( mName ) );
1486  return false;
1487  }
1488  return true;
1489 }
1490 
1492 {
1493  const thread_local QRegularExpression re( QStringLiteral( "^[A-Za-z_\x80-\xff][A-Za-z0-9_\x80-\xff]*$" ) );
1494  const QRegularExpressionMatch match = re.match( mName );
1495  return match.hasMatch() ? mName : QgsExpression::quotedColumnRef( mName );
1496 }
1497 
1499 {
1500  return QSet<QString>() << mName;
1501 }
1502 
1504 {
1505  return QSet<QString>();
1506 }
1507 
1509 {
1510  return QSet<QString>();
1511 }
1512 
1513 QList<const QgsExpressionNode *> QgsExpressionNodeColumnRef::nodes() const
1514 {
1515  QList<const QgsExpressionNode *> result;
1516  result << this;
1517  return result;
1518 }
1519 
1521 {
1522  return false;
1523 }
1524 
1526 {
1528  cloneTo( copy );
1529  return copy;
1530 }
1531 
1533 {
1534  Q_UNUSED( context )
1535  Q_UNUSED( parent )
1536  return false;
1537 }
1538 
1539 //
1540 
1542  : mConditions( *conditions )
1543  , mElseExp( elseExp )
1544 {
1545  delete conditions;
1546 }
1547 
1549 {
1550  delete mElseExp;
1551  qDeleteAll( mConditions );
1552 }
1553 
1555 {
1556  return ntCondition;
1557 }
1558 
1560 {
1561  for ( WhenThen *cond : std::as_const( mConditions ) )
1562  {
1563  QVariant vWhen = cond->mWhenExp->eval( parent, context );
1564  QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( vWhen, parent );
1566  if ( tvl == QgsExpressionUtils::True )
1567  {
1568  QVariant vRes = cond->mThenExp->eval( parent, context );
1570  return vRes;
1571  }
1572  }
1573 
1574  if ( mElseExp )
1575  {
1576  QVariant vElse = mElseExp->eval( parent, context );
1578  return vElse;
1579  }
1580 
1581  // return NULL if no condition is matching
1582  return QVariant();
1583 }
1584 
1586 {
1587  bool foundAnyNonStaticConditions = false;
1588  for ( WhenThen *cond : std::as_const( mConditions ) )
1589  {
1590  const bool res = cond->mWhenExp->prepare( parent, context )
1591  && cond->mThenExp->prepare( parent, context );
1592  if ( !res )
1593  return false;
1594 
1595  foundAnyNonStaticConditions |= !cond->mWhenExp->hasCachedStaticValue();
1596  if ( !foundAnyNonStaticConditions && QgsExpressionUtils::getTVLValue( cond->mWhenExp->cachedStaticValue(), parent ) == QgsExpressionUtils::True )
1597  {
1598  // ok, we now that we'll ALWAYS be picking the same condition, as the "WHEN" clause for this condition (and all previous conditions) is a static
1599  // value, and the static value for this WHEN clause is True.
1600  if ( cond->mThenExp->hasCachedStaticValue() )
1601  {
1602  // then "THEN" clause ALSO has a static value, so we can replace the whole node with a static value
1603  mCachedStaticValue = cond->mThenExp->cachedStaticValue();
1604  mHasCachedValue = true;
1605  return true;
1606  }
1607  else
1608  {
1609  // we know at least that we'll ALWAYS be picking the same condition, so even though the THEN node is non-static we can effectively replace
1610  // this whole QgsExpressionNodeCondition node with just the THEN node for this condition.
1611  mCompiledSimplifiedNode.reset( cond->mThenExp->effectiveNode()->clone() );
1612  return true;
1613  }
1614  }
1615  }
1616 
1617  if ( mElseExp )
1618  {
1619  const bool res = mElseExp->prepare( parent, context );
1620  if ( !res )
1621  return false;
1622 
1623  if ( !foundAnyNonStaticConditions )
1624  {
1625  // all condition nodes are static conditions and not TRUE, so we know we'll ALWAYS be picking the ELSE node
1626  if ( mElseExp->hasCachedStaticValue() )
1627  {
1628  mCachedStaticValue = mElseExp->cachedStaticValue();
1629  mHasCachedValue = true;
1630  return true;
1631  }
1632  else
1633  {
1634  // so even though the ELSE node is non-static we can effectively replace
1635  // this whole QgsExpressionNodeCondition node with just the ELSE node for this condition.
1636  mCompiledSimplifiedNode.reset( mElseExp->effectiveNode()->clone() );
1637  return true;
1638  }
1639  }
1640  }
1641 
1642  return true;
1643 }
1644 
1646 {
1647  QString msg( QStringLiteral( "CASE" ) );
1648  for ( WhenThen *cond : mConditions )
1649  {
1650  msg += QStringLiteral( " WHEN %1 THEN %2" ).arg( cond->mWhenExp->dump(), cond->mThenExp->dump() );
1651  }
1652  if ( mElseExp )
1653  msg += QStringLiteral( " ELSE %1" ).arg( mElseExp->dump() );
1654  msg += QLatin1String( " END" );
1655  return msg;
1656 }
1657 
1659 {
1660  if ( hasCachedStaticValue() )
1661  return QSet< QString >();
1662 
1663  QSet<QString> lst;
1664  for ( WhenThen *cond : mConditions )
1665  {
1666  lst += cond->mWhenExp->referencedColumns() + cond->mThenExp->referencedColumns();
1667  }
1668 
1669  if ( mElseExp )
1670  lst += mElseExp->referencedColumns();
1671 
1672  return lst;
1673 }
1674 
1676 {
1677  QSet<QString> lst;
1678  for ( WhenThen *cond : mConditions )
1679  {
1680  lst += cond->mWhenExp->referencedVariables() + cond->mThenExp->referencedVariables();
1681  }
1682 
1683  if ( mElseExp )
1684  lst += mElseExp->referencedVariables();
1685 
1686  return lst;
1687 }
1688 
1690 {
1691  QSet<QString> lst;
1692  for ( WhenThen *cond : mConditions )
1693  {
1694  lst += cond->mWhenExp->referencedFunctions() + cond->mThenExp->referencedFunctions();
1695  }
1696 
1697  if ( mElseExp )
1698  lst += mElseExp->referencedFunctions();
1699 
1700  return lst;
1701 }
1702 
1703 QList<const QgsExpressionNode *> QgsExpressionNodeCondition::nodes() const
1704 {
1705  QList<const QgsExpressionNode *> lst;
1706  lst << this;
1707  for ( WhenThen *cond : mConditions )
1708  {
1709  lst += cond->mWhenExp->nodes() + cond->mThenExp->nodes();
1710  }
1711 
1712  if ( mElseExp )
1713  lst += mElseExp->nodes();
1714 
1715  return lst;
1716 }
1717 
1719 {
1720  for ( WhenThen *cond : mConditions )
1721  {
1722  if ( cond->mWhenExp->needsGeometry() ||
1723  cond->mThenExp->needsGeometry() )
1724  return true;
1725  }
1726 
1727  return mElseExp && mElseExp->needsGeometry();
1728 }
1729 
1731 {
1733  conditions.reserve( mConditions.size() );
1734  for ( WhenThen *wt : mConditions )
1735  conditions.append( wt->clone() );
1736 
1737  QgsExpressionNodeCondition *copy = new QgsExpressionNodeCondition( conditions, mElseExp ? mElseExp->clone() : nullptr );
1738  cloneTo( copy );
1739  return copy;
1740 }
1741 
1743 {
1744  for ( WhenThen *wt : mConditions )
1745  {
1746  if ( !wt->mWhenExp->isStatic( parent, context ) || !wt->mThenExp->isStatic( parent, context ) )
1747  return false;
1748  }
1749 
1750  if ( mElseExp )
1751  return mElseExp->isStatic( parent, context );
1752 
1753  return true;
1754 }
1755 
1757 {
1758  if ( hasCachedStaticValue() )
1759  return QSet< QString >();
1760 
1761  QSet<QString> lst( mNode->referencedColumns() );
1762  const QList< QgsExpressionNode * > nodeList = mList->list();
1763  for ( const QgsExpressionNode *n : nodeList )
1764  lst.unite( n->referencedColumns() );
1765  return lst;
1766 }
1767 
1769 {
1770  QSet<QString> lst( mNode->referencedVariables() );
1771  const QList< QgsExpressionNode * > nodeList = mList->list();
1772  for ( const QgsExpressionNode *n : nodeList )
1773  lst.unite( n->referencedVariables() );
1774  return lst;
1775 }
1776 
1778 {
1779  QSet<QString> lst( mNode->referencedFunctions() );
1780  const QList< QgsExpressionNode * > nodeList = mList->list();
1781  for ( const QgsExpressionNode *n : nodeList )
1782  lst.unite( n->referencedFunctions() );
1783  return lst;
1784 }
1785 
1786 QList<const QgsExpressionNode *> QgsExpressionNodeInOperator::nodes() const
1787 {
1788  QList<const QgsExpressionNode *> lst;
1789  lst << this;
1790  const QList< QgsExpressionNode * > nodeList = mList->list();
1791  for ( const QgsExpressionNode *n : nodeList )
1792  lst += n->nodes();
1793  return lst;
1794 }
1795 
1796 
1798 {
1799  delete mNode;
1800  delete mLowerBound;
1801  delete mHigherBound;
1802 }
1803 
1805 {
1806  return ntBetweenOperator;
1807 }
1808 
1810 {
1811  bool res = mNode->prepare( parent, context );
1812  res = res && mLowerBound->prepare( parent, context );
1813  res = res && mHigherBound->prepare( parent, context );
1814  return res;
1815 }
1816 
1818 {
1819  const QVariant nodeVal = mNode->eval( parent, context );
1820  if ( nodeVal.isNull() )
1821  {
1822  return QVariant();
1823  }
1824 
1825  const QgsExpressionNodeLiteral nodeValNode { nodeVal };
1826 
1827  QgsExpressionNodeBinaryOperator lowBound { QgsExpressionNodeBinaryOperator::BinaryOperator::boGE, nodeValNode.clone(), mLowerBound->clone() };
1828  const QVariant lowBoundValue = lowBound.eval( parent, context );
1829  const bool lowBoundBool { lowBoundValue.toBool() };
1830 
1831  if ( ! lowBoundValue.isNull() && ! lowBoundBool )
1832  {
1833  return QVariant( mNegate );
1834  }
1835 
1836  QgsExpressionNodeBinaryOperator highBound { QgsExpressionNodeBinaryOperator::BinaryOperator::boLE, nodeValNode.clone(), mHigherBound->clone() };
1837  const QVariant highBoundValue = highBound.eval( parent, context );
1838 
1839  if ( lowBoundValue.isNull() && highBoundValue.isNull() )
1840  {
1841  return QVariant();
1842  }
1843 
1844  const bool highBoundBool { highBoundValue.toBool() };
1845 
1846  // We already checked if both are nulls
1847  if ( lowBoundValue.isNull() || highBoundValue.isNull() )
1848  {
1849 
1850  // In this case we can return a boolean
1851  if ( ( lowBoundValue.isNull() && ! highBoundBool ) ||
1852  ( highBoundValue.isNull() && ! lowBoundBool ) )
1853  {
1854  return QVariant( mNegate );
1855  }
1856 
1857  // Indetermined
1858  return QVariant();
1859 
1860  }
1861 
1862  if ( ! highBoundValue.isNull() && ! highBoundBool )
1863  {
1864  return QVariant( mNegate );
1865  }
1866 
1867  const bool res { lowBoundBool &&highBoundBool };
1868  return mNegate ? QVariant( ! res ) : QVariant( res );
1869 
1870 }
1871 
1873 {
1874  return QStringLiteral( "%1 %2 %3 AND %4" ).arg( mNode->dump(), mNegate ? QStringLiteral( "NOT BETWEEN" ) : QStringLiteral( "BETWEEN" ), mLowerBound->dump(), mHigherBound->dump() );
1875 }
1876 
1878 {
1879  QSet<QString> lst( mNode->referencedVariables() );
1880  lst.unite( mLowerBound->referencedVariables() );
1881  lst.unite( mHigherBound->referencedVariables() );
1882  return lst;
1883 }
1884 
1886 {
1887  QSet<QString> lst( mNode->referencedFunctions() );
1888  lst.unite( mLowerBound->referencedFunctions() );
1889  lst.unite( mHigherBound->referencedFunctions() );
1890  return lst;
1891 }
1892 
1893 QList<const QgsExpressionNode *> QgsExpressionNodeBetweenOperator::nodes() const
1894 {
1895  return { this, mLowerBound, mHigherBound };
1896 }
1897 
1899 {
1900  QSet<QString> lst( mNode->referencedColumns() );
1901  lst.unite( mLowerBound->referencedColumns() );
1902  lst.unite( mHigherBound->referencedColumns() );
1903  return lst;
1904 }
1905 
1907 {
1908  if ( mNode->needsGeometry() )
1909  return true;
1910 
1911  if ( mLowerBound->needsGeometry() )
1912  return true;
1913 
1914  if ( mHigherBound->needsGeometry() )
1915  return true;
1916 
1917  return false;
1918 }
1919 
1921 {
1922  QgsExpressionNodeBetweenOperator *copy = new QgsExpressionNodeBetweenOperator( mNode->clone(), mLowerBound->clone(), mHigherBound->clone(), mNegate );
1923  cloneTo( copy );
1924  return copy;
1925 }
1926 
1928 {
1929  if ( !mNode->isStatic( parent, context ) )
1930  return false;
1931 
1932  if ( !mLowerBound->isStatic( parent, context ) )
1933  return false;
1934 
1935  if ( !mHigherBound->isStatic( parent, context ) )
1936  return false;
1937 
1938  return true;
1939 }
1940 
1942 {
1943  return mLowerBound;
1944 }
1945 
1947 {
1948  return mHigherBound;
1949 }
1950 
1952 {
1953  return mNegate;
1954 }
1955 
1957  : mWhenExp( whenExp )
1958  , mThenExp( thenExp )
1959 {
1960 }
1961 
1963 {
1964  delete mWhenExp;
1965  delete mThenExp;
1966 }
1967 
1969 {
1970  return new WhenThen( mWhenExp->clone(), mThenExp->clone() );
1971 }
1972 
1974 {
1975  return BINARY_OPERATOR_TEXT[mOp];
1976 }
1977 
1978 //
1979 
1981 {
1982  const QVariant container = mContainer->eval( parent, context );
1984  const QVariant index = mIndex->eval( parent, context );
1986 
1987  switch ( container.type() )
1988  {
1989  case QVariant::Map:
1990  return QgsExpressionUtils::getMapValue( container, parent ).value( index.toString() );
1991 
1992  case QVariant::List:
1993  case QVariant::StringList:
1994  {
1995  const QVariantList list = QgsExpressionUtils::getListValue( container, parent );
1996  qlonglong pos = QgsExpressionUtils::getIntValue( index, parent );
1997  if ( pos >= list.length() || pos < -list.length() )
1998  {
1999  return QVariant();
2000  }
2001  if ( pos < 0 )
2002  {
2003  // negative indices are from back of list
2004  pos += list.length();
2005  }
2006 
2007  return list.at( pos );
2008  }
2009 
2010  default:
2011  if ( !container.isNull() )
2012  parent->setEvalErrorString( tr( "[] can only be used with map or array values, not %1" ).arg( QMetaType::typeName( container.type() ) ) );
2013  return QVariant();
2014  }
2015 }
2016 
2018 {
2019  return ntIndexOperator;
2020 }
2021 
2023 {
2024  bool resC = mContainer->prepare( parent, context );
2025  bool resV = mIndex->prepare( parent, context );
2026  return resC && resV;
2027 }
2028 
2030 {
2031  return QStringLiteral( "%1[%2]" ).arg( mContainer->dump(), mIndex->dump() );
2032 }
2033 
2035 {
2036  if ( hasCachedStaticValue() )
2037  return QSet< QString >();
2038 
2039  return mContainer->referencedColumns() + mIndex->referencedColumns();
2040 }
2041 
2043 {
2044  return mContainer->referencedVariables() + mIndex->referencedVariables();
2045 }
2046 
2048 {
2049  return mContainer->referencedFunctions() + mIndex->referencedFunctions();
2050 }
2051 
2052 QList<const QgsExpressionNode *> QgsExpressionNodeIndexOperator::nodes() const
2053 {
2054  QList<const QgsExpressionNode *> lst;
2055  lst << this;
2056  lst += mContainer->nodes() + mIndex->nodes();
2057  return lst;
2058 }
2059 
2061 {
2062  return mContainer->needsGeometry() || mIndex->needsGeometry();
2063 }
2064 
2066 {
2067  QgsExpressionNodeIndexOperator *copy = new QgsExpressionNodeIndexOperator( mContainer->clone(), mIndex->clone() );
2068  cloneTo( copy );
2069  return copy;
2070 }
2071 
2073 {
2074  return mContainer->isStatic( parent, context ) && mIndex->isStatic( parent, context );
2075 }
QgsExpressionNode::dump
virtual QString dump() const =0
Dump this node into a serialized (part) of an expression.
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:406
QgsExpressionNodeFunction::nodeType
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
Definition: qgsexpressionnodeimpl.cpp:1121
QgsExpressionNode::NamedNode::name
QString name
Node name.
Definition: qgsexpressionnode.h:111
QgsExpressionNodeBetweenOperator::prepareNode
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
Definition: qgsexpressionnodeimpl.cpp:1809
QgsExpression::quotedString
static QString quotedString(QString text)
Returns a quoted version of a string (in single quotes)
Definition: qgsexpression.cpp:73
QgsInterval::seconds
double seconds() const
Returns the interval duration in seconds.
Definition: qgsinterval.h:236
QgsExpressionNodeFunction::needsGeometry
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
Definition: qgsexpressionnodeimpl.cpp:1239
QgsExpressionNodeBinaryOperator::prepareNode
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
Definition: qgsexpressionnodeimpl.cpp:679
QgsExpressionNode::cloneTo
void cloneTo(QgsExpressionNode *target) const
Copies the members of this node to the node provided in target.
Definition: qgsexpressionnode.cpp:83
QgsExpressionNodeLiteral::prepareNode
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
Definition: qgsexpressionnodeimpl.cpp:1351
QgsExpressionNodeIndexOperator::referencedVariables
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:2042
qgsfeaturerequest.h
QgsExpressionNodeBinaryOperator::boILike
@ boILike
Definition: qgsexpressionnodeimpl.h:123
QgsExpressionNodeBinaryOperator::boPlus
@ boPlus
Definition: qgsexpressionnodeimpl.h:129
QgsExpressionNodeColumnRef::referencedVariables
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:1503
QgsExpressionNodeLiteral
An expression node for literal values.
Definition: qgsexpressionnodeimpl.h:461
QgsExpressionNodeColumnRef::QgsExpressionNodeColumnRef
QgsExpressionNodeColumnRef(const QString &name)
Constructor for QgsExpressionNodeColumnRef, referencing the column with the specified name.
Definition: qgsexpressionnodeimpl.h:520
QgsExpressionNode::effectiveNode
const QgsExpressionNode * effectiveNode() const
Returns a reference to the simplest node which represents this node, after any compilation optimizati...
Definition: qgsexpressionnode.h:348
QgsExpressionNodeCondition::referencedFunctions
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:1689
QgsExpressionNodeUnaryOperator::needsGeometry
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
Definition: qgsexpressionnodeimpl.cpp:177
QgsExpressionNodeBinaryOperator
A binary expression operator, which operates on two values.
Definition: qgsexpressionnodeimpl.h:99
QgsExpressionNodeBinaryOperator::dump
QString dump() const override
Dump this node into a serialized (part) of an expression.
Definition: qgsexpressionnodeimpl.cpp:768
QgsExpressionNodeColumnRef::referencedFunctions
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:1508
QgsExpressionNode::ntBetweenOperator
@ ntBetweenOperator
Between operator.
Definition: qgsexpressionnode.h:87
QgsExpressionNodeUnaryOperator::clone
QgsExpressionNode * clone() const override
Generate a clone of this node.
Definition: qgsexpressionnodeimpl.cpp:182
QgsExpressionNodeCondition::prepareNode
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
Definition: qgsexpressionnodeimpl.cpp:1585
QgsExpressionNodeBinaryOperator::text
QString text() const
Returns a the name of this operator without the operands.
Definition: qgsexpressionnodeimpl.cpp:1973
QgsExpressionNodeBinaryOperator::boRegexp
@ boRegexp
Definition: qgsexpressionnodeimpl.h:120
QgsExpressionNodeBinaryOperator::boLE
@ boLE
<=
Definition: qgsexpressionnodeimpl.h:116
qgsexpression.h
QgsExpressionNode::ntCondition
@ ntCondition
Definition: qgsexpressionnode.h:85
QgsExpressionNode::NodeType
NodeType
Known node types.
Definition: qgsexpressionnode.h:77
QgsExpressionNode::NodeList::hasNamedNodes
bool hasNamedNodes() const
Returns true if list contains any named nodes.
Definition: qgsexpressionnode.h:143
QgsExpressionNode::NamedNode::node
QgsExpressionNode * node
Node.
Definition: qgsexpressionnode.h:114
QgsExpressionNodeColumnRef::referencedColumns
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
Definition: qgsexpressionnodeimpl.cpp:1498
QgsExpressionNodeFunction::QgsExpressionNodeFunction
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...
Definition: qgsexpressionnodeimpl.cpp:1066
QgsExpressionNode::ntColumnRef
@ ntColumnRef
Definition: qgsexpressionnode.h:84
QgsExpressionNodeUnaryOperator::evalNode
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
Definition: qgsexpressionnodeimpl.cpp:108
qgsstringutils.h
QgsExpressionNodeBinaryOperator::boGE
@ boGE
>=
Definition: qgsexpressionnodeimpl.h:117
QgsExpressionNodeInOperator::~QgsExpressionNodeInOperator
~QgsExpressionNodeInOperator() override
Definition: qgsexpressionnodeimpl.cpp:1003
QgsExpressionNodeColumnRef
An expression node which takes it value from a feature's field.
Definition: qgsexpressionnodeimpl.h:512
QgsExpressionNodeLiteral::value
QVariant value() const
The value of the literal.
Definition: qgsexpressionnodeimpl.h:481
QgsExpressionNodeFunction::fnIndex
int fnIndex() const
Returns the index of the node's function.
Definition: qgsexpressionnodeimpl.h:428
QgsFields
Container of fields for a vector layer.
Definition: qgsfields.h:44
QgsExpressionNodeLiteral::nodeType
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
Definition: qgsexpressionnodeimpl.cpp:1346
QgsExpressionNodeUnaryOperator::nodeType
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
Definition: qgsexpressionnodeimpl.cpp:133
QgsExpressionNodeBinaryOperator::referencedColumns
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
Definition: qgsexpressionnodeimpl.cpp:799
QgsExpressionNodeBetweenOperator::dump
QString dump() const override
Dump this node into a serialized (part) of an expression.
Definition: qgsexpressionnodeimpl.cpp:1872
QgsExpressionNodeCondition::WhenThen::WhenThen
WhenThen(QgsExpressionNode *whenExp, QgsExpressionNode *thenExp)
A combination of when and then.
Definition: qgsexpressionnodeimpl.cpp:1956
QgsExpressionNodeLiteral::nodes
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:1401
QgsExpressionNodeUnaryOperator
A unary node is either negative as in boolean (not) or as in numbers (minus).
Definition: qgsexpressionnodeimpl.h:27
QgsExpressionNodeBetweenOperator::needsGeometry
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
Definition: qgsexpressionnodeimpl.cpp:1906
QgsExpressionNodeBetweenOperator::lowerBound
QgsExpressionNode * lowerBound() const
Returns the lower bound expression node of the range.
Definition: qgsexpressionnodeimpl.cpp:1941
QgsExpressionNodeUnaryOperator::referencedVariables
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:159
QgsExpressionNodeIndexOperator::referencedColumns
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
Definition: qgsexpressionnodeimpl.cpp:2034
QgsExpressionNode::clone
virtual QgsExpressionNode * clone() const =0
Generate a clone of this node.
QgsExpressionNodeCondition
An expression node for CASE WHEN clauses.
Definition: qgsexpressionnodeimpl.h:560
QgsExpressionNodeFunction::clone
QgsExpressionNode * clone() const override
Generate a clone of this node.
Definition: qgsexpressionnodeimpl.cpp:1251
QgsExpressionNodeCondition::dump
QString dump() const override
Dump this node into a serialized (part) of an expression.
Definition: qgsexpressionnodeimpl.cpp:1645
QgsExpressionNodeLiteral::QgsExpressionNodeLiteral
QgsExpressionNodeLiteral(const QVariant &value)
Constructor for QgsExpressionNodeLiteral, with the specified literal value.
Definition: qgsexpressionnodeimpl.h:468
QgsStringUtils::qRegExpEscape
static QString qRegExpEscape(const QString &string)
Returns an escaped string matching the behavior of QRegExp::escape.
Definition: qgsstringutils.cpp:710
QgsExpressionNodeBinaryOperator::precedence
int precedence() const
Returns the precedence index for the operator.
Definition: qgsexpressionnodeimpl.cpp:686
QgsExpressionNodeInOperator::clone
QgsExpressionNode * clone() const override
Generate a clone of this node.
Definition: qgsexpressionnodeimpl.cpp:1030
FALLTHROUGH
#define FALLTHROUGH
Definition: qgis.h:2847
QgsExpressionNode::mCachedStaticValue
QVariant mCachedStaticValue
Contains the static, precalculated value for the node if mHasCachedValue is true.
Definition: qgsexpressionnode.h:387
QgsExpressionNodeUnaryOperator::op
QgsExpressionNodeUnaryOperator::UnaryOperator op() const
Returns the unary operator.
Definition: qgsexpressionnodeimpl.h:74
QgsExpressionContext::variable
QVariant variable(const QString &name) const
Fetches a matching variable from the context.
Definition: qgsexpressioncontext.cpp:300
QgsExpressionNodeCondition::evalNode
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
Definition: qgsexpressionnodeimpl.cpp:1559
QgsExpressionNodeIndexOperator::dump
QString dump() const override
Dump this node into a serialized (part) of an expression.
Definition: qgsexpressionnodeimpl.cpp:2029
QgsExpressionNodeBinaryOperator::boMod
@ boMod
Definition: qgsexpressionnodeimpl.h:134
QgsExpressionNode::mCompiledSimplifiedNode
std::unique_ptr< QgsExpressionNode > mCompiledSimplifiedNode
Contains a compiled node which represents a simplified version of this node as a result of compilatio...
Definition: qgsexpressionnode.h:399
QgsFeature::fieldNameIndex
int fieldNameIndex(const QString &fieldName) const
Utility method to get attribute index from name.
Definition: qgsfeature.cpp:342
QgsExpressionNodeInOperator
An expression node for value IN or NOT IN clauses.
Definition: qgsexpressionnodeimpl.h:343
QgsExpressionNodeCondition::referencedColumns
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
Definition: qgsexpressionnodeimpl.cpp:1658
QgsExpressionNodeUnaryOperator::text
QString text() const
Returns a the name of this operator without the operands.
Definition: qgsexpressionnodeimpl.cpp:194
QgsExpressionNodeUnaryOperator::referencedColumns
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
Definition: qgsexpressionnodeimpl.cpp:151
QgsExpressionFunction::referencedColumns
virtual QSet< QString > referencedColumns(const QgsExpressionNodeFunction *node) const
Returns a set of field names which are required for this function.
Definition: qgsexpressionfunction.cpp:149
QgsExpressionNodeInOperator::needsGeometry
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
Definition: qgsexpressionnodeimpl.cpp:41
QgsExpressionNodeUnaryOperator::referencedFunctions
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:164
QgsExpressionNodeBinaryOperator::boMinus
@ boMinus
Definition: qgsexpressionnodeimpl.h:130
QgsExpressionNodeFunction::referencedColumns
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
Definition: qgsexpressionnodeimpl.cpp:1151
QgsExpressionNodeCondition::needsGeometry
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
Definition: qgsexpressionnodeimpl.cpp:1718
QgsExpressionNodeBetweenOperator::higherBound
QgsExpressionNode * higherBound() const
Returns the higher bound expression node of the range.
Definition: qgsexpressionnodeimpl.cpp:1946
QgsExpressionNode::referencedFunctions
virtual QSet< QString > referencedFunctions() const =0
Returns a set of all functions which are used in this expression.
QgsExpressionNodeInOperator::prepareNode
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
Definition: qgsexpressionnodeimpl.cpp:1014
QgsExpressionNodeColumnRef::isStatic
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
Definition: qgsexpressionnodeimpl.cpp:1532
QgsExpression::setEvalErrorString
void setEvalErrorString(const QString &str)
Sets evaluation error (used internally by evaluation functions)
Definition: qgsexpression.cpp:388
QgsExpressionNodeCondition::QgsExpressionNodeCondition
QgsExpressionNodeCondition(QgsExpressionNodeCondition::WhenThenList *conditions, QgsExpressionNode *elseExp=nullptr)
Create a new node with the given list of conditions and an optional elseExp expression.
Definition: qgsexpressionnodeimpl.cpp:1541
QgsExpressionNodeColumnRef::nodes
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:1513
QgsExpression::hasEvalError
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
Definition: qgsexpression.cpp:378
QgsExpressionNode::ntFunction
@ ntFunction
Definition: qgsexpressionnode.h:82
QgsExpressionFunction::params
int params() const
The number of parameters this function takes.
Definition: qgsexpressionfunction.h:193
QgsExpressionFunction::Parameter
Represents a single parameter passed to a function.
Definition: qgsexpressionfunction.h:54
QgsExpressionFunction::ParameterList
QList< QgsExpressionFunction::Parameter > ParameterList
List of parameters, used for function definition.
Definition: qgsexpressionfunction.h:104
QgsExpressionNodeLiteral::isStatic
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
Definition: qgsexpressionnodeimpl.cpp:1420
QgsExpressionNodeLiteral::referencedFunctions
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:1396
QgsExpressionNodeBetweenOperator::clone
QgsExpressionNode * clone() const override
Generate a clone of this node.
Definition: qgsexpressionnodeimpl.cpp:1920
QgsExpressionNode::eval
QVariant eval(QgsExpression *parent, const QgsExpressionContext *context)
Evaluate this node with the given context and parent.
Definition: qgsexpressionnode.cpp:20
QgsExpressionNodeBinaryOperator::boPow
@ boPow
Definition: qgsexpressionnodeimpl.h:135
QgsExpressionContext::EXPR_FIELDS
static const QString EXPR_FIELDS
Inbuilt variable name for fields storage.
Definition: qgsexpressioncontext.h:803
QgsExpressionNodeCondition::clone
QgsExpressionNode * clone() const override
Generate a clone of this node.
Definition: qgsexpressionnodeimpl.cpp:1730
QgsExpressionNodeColumnRef::evalNode
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
Definition: qgsexpressionnodeimpl.cpp:1429
QgsExpressionNodeBetweenOperator::evalNode
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
Definition: qgsexpressionnodeimpl.cpp:1817
QgsExpressionNodeFunction::args
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
Definition: qgsexpressionnodeimpl.h:433
QgsExpressionNodeBinaryOperator::referencedFunctions
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:812
QgsExpressionNodeIndexOperator::needsGeometry
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
Definition: qgsexpressionnodeimpl.cpp:2060
QgsFeature::isValid
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:216
QgsExpressionNodeFunction::referencedFunctions
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:1207
QgsExpressionNodeBinaryOperator::boConcat
@ boConcat
Definition: qgsexpressionnodeimpl.h:138
QgsExpressionNodeBinaryOperator::referencedVariables
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:807
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:2265
QgsExpressionNode::referencedColumns
virtual QSet< QString > referencedColumns() const =0
Abstract virtual method which returns a list of columns required to evaluate this node.
QgsExpressionNodeBetweenOperator::referencedFunctions
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:1885
QgsExpressionNodeBinaryOperator::clone
QgsExpressionNode * clone() const override
Generate a clone of this node.
Definition: qgsexpressionnodeimpl.cpp:830
QgsExpressionNodeInOperator::nodes
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:1786
QgsExpressionNodeLiteral::dump
QString dump() const override
Dump this node into a serialized (part) of an expression.
Definition: qgsexpressionnodeimpl.cpp:1381
QgsExpressionNode::referencedVariables
virtual QSet< QString > referencedVariables() const =0
Returns a set of all variables which are used in this expression.
QgsExpressionNode::needsGeometry
virtual bool needsGeometry() const =0
Abstract virtual method which returns if the geometry is required to evaluate this expression.
QgsExpressionNodeCondition::nodes
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:1703
QgsExpressionNodeCondition::conditions
WhenThenList conditions() const
The list of WHEN THEN expression parts of the expression.
Definition: qgsexpressionnodeimpl.h:636
QgsExpressionNodeFunction::prepareNode
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
Definition: qgsexpressionnodeimpl.cpp:1126
qgsexpressionutils.h
QgsExpressionNodeBinaryOperator::boLT
@ boLT
<
Definition: qgsexpressionnodeimpl.h:118
QgsExpressionNodeBetweenOperator::referencedColumns
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
Definition: qgsexpressionnodeimpl.cpp:1898
ENSURE_NO_EVAL_ERROR
#define ENSURE_NO_EVAL_ERROR
Definition: qgsexpressionutils.h:36
QgsExpressionNodeBinaryOperator::boNotILike
@ boNotILike
Definition: qgsexpressionnodeimpl.h:124
QgsExpressionNodeIndexOperator::referencedFunctions
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:2047
QgsExpressionNodeBetweenOperator
SQL-like BETWEEN and NOT BETWEEN predicates.
Definition: qgsexpressionnodeimpl.h:281
QgsExpressionNodeColumnRef::dump
QString dump() const override
Dump this node into a serialized (part) of an expression.
Definition: qgsexpressionnodeimpl.cpp:1491
QgsExpressionNodeFunction::dump
QString dump() const override
Dump this node into a serialized (part) of an expression.
Definition: qgsexpressionnodeimpl.cpp:1142
QgsExpressionNodeLiteral::referencedColumns
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
Definition: qgsexpressionnodeimpl.cpp:1386
QgsExpressionNodeBetweenOperator::~QgsExpressionNodeBetweenOperator
~QgsExpressionNodeBetweenOperator() override
Definition: qgsexpressionnodeimpl.cpp:1797
QgsExpressionNodeBetweenOperator::referencedVariables
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:1877
QgsExpressionNode::mHasCachedValue
bool mHasCachedValue
true if the node has a static, precalculated value.
Definition: qgsexpressionnode.h:380
QgsFeature::attribute
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Definition: qgsfeature.cpp:327
SET_EVAL_ERROR
#define SET_EVAL_ERROR(x)
Definition: qgsexpressionutils.h:37
typeName
const QString & typeName
Definition: qgswfsgetfeature.cpp:109
QgsExpressionNode::ntBinaryOperator
@ ntBinaryOperator
Definition: qgsexpressionnode.h:80
QgsExpressionContext::function
QgsExpressionFunction * function(const QString &name) const
Fetches a matching function from the context.
Definition: qgsexpressioncontext.cpp:476
QgsExpressionNodeBinaryOperator::evalNode
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
Definition: qgsexpressionnodeimpl.cpp:201
QgsExpressionNodeFunction
An expression node for expression functions.
Definition: qgsexpressionnodeimpl.h:395
QgsExpressionNodeUnaryOperator::isStatic
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
Definition: qgsexpressionnodeimpl.cpp:189
QgsExpressionNodeBinaryOperator::boNE
@ boNE
<>
Definition: qgsexpressionnodeimpl.h:115
QgsExpressionNode::ntLiteral
@ ntLiteral
Definition: qgsexpressionnode.h:83
QgsExpression::Functions
static const QList< QgsExpressionFunction * > & Functions()
Definition: qgsexpressionfunction.cpp:7316
QgsExpressionNodeBinaryOperator::boIsNot
@ boIsNot
Definition: qgsexpressionnodeimpl.h:126
QgsExpressionNodeBinaryOperator::boLike
@ boLike
Definition: qgsexpressionnodeimpl.h:121
QgsExpressionNodeInOperator::referencedColumns
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node.
Definition: qgsexpressionnodeimpl.cpp:1756
QgsExpressionNodeIndexOperator::isStatic
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
Definition: qgsexpressionnodeimpl.cpp:2072
QgsExpressionNodeUnaryOperator::uoNot
@ uoNot
Definition: qgsexpressionnodeimpl.h:63
QgsExpressionFunction::prepare
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.
Definition: qgsexpressionfunction.cpp:141
QgsExpressionNodeBinaryOperator::nodes
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:817
QgsExpressionNodeFunction::validateParams
static bool validateParams(int fnIndex, QgsExpressionNode::NodeList *args, QString &error)
Tests whether the provided argument list is valid for the matching function.
Definition: qgsexpressionnodeimpl.cpp:1263
QgsExpressionNodeColumnRef::clone
QgsExpressionNode * clone() const override
Generate a clone of this node.
Definition: qgsexpressionnodeimpl.cpp:1525
QgsExpressionNodeBinaryOperator::boNotLike
@ boNotLike
Definition: qgsexpressionnodeimpl.h:122
QgsExpressionNode::NodeList::list
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
Definition: qgsexpressionnode.h:148
QgsExpressionNode
Abstract base class for all nodes that can appear in an expression.
Definition: qgsexpressionnode.h:34
QgsExpressionNodeBetweenOperator::negate
bool negate() const
Returns true if the predicate is an exclusion test (NOT BETWEEN).
Definition: qgsexpressionnodeimpl.cpp:1951
QgsExpressionNodeInOperator::isStatic
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
Definition: qgsexpressionnodeimpl.cpp:1037
QgsExpressionNode::NodeList::clone
QgsExpressionNode::NodeList * clone() const
Creates a deep copy of this list. Ownership is transferred to the caller.
Definition: qgsexpressionnodeimpl.cpp:63
QgsExpressionNodeInOperator::evalNode
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
Definition: qgsexpressionnodeimpl.cpp:949
QgsExpressionNode::isStatic
virtual bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const =0
Returns true if this node can be evaluated for a static value.
QgsExpressionNodeCondition::nodeType
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
Definition: qgsexpressionnodeimpl.cpp:1554
QgsExpressionNodeBinaryOperator::boEQ
@ boEQ
=
Definition: qgsexpressionnodeimpl.h:114
QgsExpressionNodeBinaryOperator::boIntDiv
@ boIntDiv
Definition: qgsexpressionnodeimpl.h:133
QgsExpressionNodeColumnRef::nodeType
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
Definition: qgsexpressionnodeimpl.cpp:1464
QgsExpressionNodeBinaryOperator::boIs
@ boIs
Definition: qgsexpressionnodeimpl.h:125
QgsExpressionNodeUnaryOperator::nodes
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:169
QgsExpressionNode::NodeList::dump
virtual QString dump() const
Returns a string dump of the expression node.
Definition: qgsexpressionnodeimpl.cpp:75
QgsExpressionFunction::lazyEval
bool lazyEval() const
true if this function should use lazy evaluation.
Definition: qgsexpressionfunction.h:232
QgsExpressionNodeBinaryOperator::boGT
@ boGT
Definition: qgsexpressionnodeimpl.h:119
qgsgeometry.h
QgsExpressionNodeCondition::WhenThen::clone
QgsExpressionNodeCondition::WhenThen * clone() const
Gets a deep copy of this WhenThen combination.
Definition: qgsexpressionnodeimpl.cpp:1968
QgsExpressionNodeLiteral::evalNode
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
Definition: qgsexpressionnodeimpl.cpp:1339
qgsexpressionnodeimpl.h
QgsExpressionFunction::run
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's...
Definition: qgsexpressionfunction.cpp:89
QgsExpressionFunction
A abstract base class for defining QgsExpression functions.
Definition: qgsexpressionfunction.h:40
str
#define str(x)
Definition: qgis.cpp:37
QgsExpressionNode::ntUnaryOperator
@ ntUnaryOperator
Definition: qgsexpressionnode.h:79
QgsExpressionNode::NodeList::append
void append(QgsExpressionNode *node)
Takes ownership of the provided node.
Definition: qgsexpressionnode.h:126
QgsExpressionNodeInOperator::dump
QString dump() const override
Dump this node into a serialized (part) of an expression.
Definition: qgsexpressionnodeimpl.cpp:1025
QgsExpressionNodeBetweenOperator::isStatic
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
Definition: qgsexpressionnodeimpl.cpp:1927
QgsExpressionNodeColumnRef::prepareNode
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
Definition: qgsexpressionnodeimpl.cpp:1469
QgsExpressionContext::feature
QgsFeature feature() const
Convenience function for retrieving the feature for the context, if set.
Definition: qgsexpressioncontext.cpp:543
QgsInterval
A representation of the interval between two datetime values.
Definition: qgsinterval.h:41
QgsExpressionNodeCondition::WhenThen
Represents a "WHEN... THEN..." portation of a CASE WHEN clause in an expression.
Definition: qgsexpressionnodeimpl.h:568
QgsExpressionFunction::name
QString name() const
The name of the function.
Definition: qgsexpressionfunction.h:190
QgsExpressionFunction::parameters
const QgsExpressionFunction::ParameterList & parameters() const
Returns the list of named parameters for the function, if set.
Definition: qgsexpressionfunction.h:214
QgsExpressionNodeBinaryOperator::isStatic
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
Definition: qgsexpressionnodeimpl.cpp:837
QgsExpression::quotedColumnRef
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
Definition: qgsexpression.cpp:68
QgsExpressionNodeUnaryOperator::dump
QString dump() const override
Dump this node into a serialized (part) of an expression.
Definition: qgsexpressionnodeimpl.cpp:143
QgsExpressionNodeFunction::referencedVariables
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:1177
QgsExpressionNodeFunction::nodes
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:1224
QgsExpressionNodeBinaryOperator::needsGeometry
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
Definition: qgsexpressionnodeimpl.cpp:825
QgsExpressionNodeColumnRef::needsGeometry
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
Definition: qgsexpressionnodeimpl.cpp:1520
QgsExpressionNode::hasCachedStaticValue
bool hasCachedStaticValue() const
Returns true if the node can be replaced by a static cached value.
Definition: qgsexpressionnode.h:326
QgsExpressionNodeFunction::evalNode
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
Definition: qgsexpressionnodeimpl.cpp:1054
QgsExpressionNodeBinaryOperator::boDiv
@ boDiv
Definition: qgsexpressionnodeimpl.h:132
QgsExpressionNodeInOperator::nodeType
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
Definition: qgsexpressionnodeimpl.cpp:1009
QgsExpressionNodeInOperator::referencedVariables
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:1768
QgsExpressionNodeBetweenOperator::nodeType
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
Definition: qgsexpressionnodeimpl.cpp:1804
QgsExpressionNodeUnaryOperator::prepareNode
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
Definition: qgsexpressionnodeimpl.cpp:138
QgsExpressionNodeFunction::~QgsExpressionNodeFunction
~QgsExpressionNodeFunction() override
Definition: qgsexpressionnodeimpl.cpp:1116
QgsExpressionNodeIndexOperator::evalNode
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
Definition: qgsexpressionnodeimpl.cpp:1980
QgsFeature
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:55
QgsExpressionNodeBinaryOperator::boAnd
@ boAnd
Definition: qgsexpressionnodeimpl.h:111
QgsExpressionNodeBetweenOperator::QgsExpressionNodeBetweenOperator
QgsExpressionNodeBetweenOperator(QgsExpressionNode *node, QgsExpressionNode *nodeLowerBound, QgsExpressionNode *nodeHigherBound, bool negate=false)
This node tests if the result of node is between the result of nodeLowerBound and nodeHigherBound nod...
Definition: qgsexpressionnodeimpl.h:288
QgsExpressionNodeCondition::~QgsExpressionNodeCondition
~QgsExpressionNodeCondition() override
Definition: qgsexpressionnodeimpl.cpp:1548
QgsExpressionNodeIndexOperator::clone
QgsExpressionNode * clone() const override
Generate a clone of this node.
Definition: qgsexpressionnodeimpl.cpp:2065
QgsExpressionNode::nodes
virtual QList< const QgsExpressionNode * > nodes() const =0
Returns a list of all nodes which are used in this expression.
QgsExpressionNodeBinaryOperator::boMul
@ boMul
Definition: qgsexpressionnodeimpl.h:131
QgsExpressionNodeCondition::isStatic
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
Definition: qgsexpressionnodeimpl.cpp:1742
QgsExpressionNodeLiteral::clone
QgsExpressionNode * clone() const override
Generate a clone of this node.
Definition: qgsexpressionnodeimpl.cpp:1413
QgsExpressionContext::hasFunction
bool hasFunction(const QString &name) const
Checks whether a specified function is contained in the context.
Definition: qgsexpressioncontext.cpp:452
QgsExpressionNodeLiteral::valueAsString
QString valueAsString() const
Returns a string representation of the node's literal value.
Definition: qgsexpressionnodeimpl.cpp:1359
QgsExpressionNodeBinaryOperator::boOr
@ boOr
Definition: qgsexpressionnodeimpl.h:110
QgsExpressionNodeIndexOperator::nodeType
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
Definition: qgsexpressionnodeimpl.cpp:2017
QgsExpressionNodeIndexOperator
A indexing expression operator, which allows use of square brackets [] to reference map and array ite...
Definition: qgsexpressionnodeimpl.h:230
QgsFields::lookupField
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:349
QgsExpression
Class for parsing and evaluation of expressions (formerly called "search strings")....
Definition: qgsexpression.h:102
QgsExpressionNode::NodeList::~NodeList
virtual ~NodeList()
Definition: qgsexpressionnodeimpl.cpp:50
QgsExpressionNode::prepare
bool prepare(QgsExpression *parent, const QgsExpressionContext *context)
Prepare this node for evaluation.
Definition: qgsexpressionnode.cpp:37
QgsExpressionNode::NamedNode
Named node.
Definition: qgsexpressionnode.h:96
QgsExpressionNodeBinaryOperator::nodeType
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
Definition: qgsexpressionnodeimpl.cpp:674
QgsExpressionNodeFunction::isStatic
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
Definition: qgsexpressionnodeimpl.cpp:1258
QgsExpressionNode::ntIndexOperator
@ ntIndexOperator
Index operator.
Definition: qgsexpressionnode.h:86
QgsExpressionNodeLiteral::needsGeometry
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression.
Definition: qgsexpressionnodeimpl.cpp:1408
QgsExpressionNodeInOperator::referencedFunctions
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:1777
QgsExpressionNodeIndexOperator::nodes
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:2052
QgsExpressionNode::NodeList::names
QStringList names() const
Returns a list of names for nodes.
Definition: qgsexpressionnode.h:161
QgsExpressionNodeIndexOperator::prepareNode
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
Definition: qgsexpressionnodeimpl.cpp:2022
QgsExpressionNode::NodeList
A list of expression nodes.
Definition: qgsexpressionnode.h:121
QgsExpressionContext::hasVariable
bool hasVariable(const QString &name) const
Check whether a variable is specified by any scope within the context.
Definition: qgsexpressioncontext.cpp:289
QgsExpressionNodeCondition::WhenThen::~WhenThen
~WhenThen()
Definition: qgsexpressionnodeimpl.cpp:1962
QgsExpressionNodeCondition::WhenThenList
QList< QgsExpressionNodeCondition::WhenThen * > WhenThenList
Definition: qgsexpressionnodeimpl.h:610
QgsExpressionNodeLiteral::referencedVariables
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:1391
QgsExpressionContext::hasFeature
bool hasFeature() const
Returns true if the context has a feature associated with it.
Definition: qgsexpressioncontext.cpp:533
QgsExpressionNode::ntInOperator
@ ntInOperator
Definition: qgsexpressionnode.h:81
QgsExpressionNodeCondition::referencedVariables
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:1675
QgsExpressionNode::cachedStaticValue
QVariant cachedStaticValue() const
Returns the node's static cached value.
Definition: qgsexpressionnode.h:334
QgsExpressionNodeBinaryOperator::leftAssociative
bool leftAssociative() const
Returns true if the operator is left-associative.
Definition: qgsexpressionnodeimpl.cpp:732
QgsExpressionNodeBetweenOperator::nodes
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
Definition: qgsexpressionnodeimpl.cpp:1893