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