QGIS API Documentation  3.6.0-Noosa (5873452)
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 ( QgsExpressionUtils::isDoubleSafe( vL ) && QgsExpressionUtils::isDoubleSafe( vR ) &&
393  ( vL.type() != QVariant::String || vR.type() != QVariant::String ) )
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  else
404  {
405  // do string comparison otherwise
406  QString sL = QgsExpressionUtils::getStringValue( vL, parent );
408  QString sR = QgsExpressionUtils::getStringValue( vR, parent );
410  int diff = QString::compare( sL, sR );
411  return compare( diff ) ? TVL_True : TVL_False;
412  }
413 
414  case boIs:
415  case boIsNot:
416  if ( QgsExpressionUtils::isNull( vL ) && QgsExpressionUtils::isNull( vR ) ) // both operators null
417  return ( mOp == boIs ? TVL_True : TVL_False );
418  else if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) ) // one operator null
419  return ( mOp == boIs ? TVL_False : TVL_True );
420  else // both operators non-null
421  {
422  bool equal = false;
423  if ( QgsExpressionUtils::isDoubleSafe( vL ) && QgsExpressionUtils::isDoubleSafe( vR ) &&
424  ( vL.type() != QVariant::String || vR.type() != QVariant::String ) )
425  {
426  double fL = QgsExpressionUtils::getDoubleValue( vL, parent );
428  double fR = QgsExpressionUtils::getDoubleValue( vR, parent );
430  equal = qgsDoubleNear( fL, fR );
431  }
432  else
433  {
434  QString sL = QgsExpressionUtils::getStringValue( vL, parent );
436  QString sR = QgsExpressionUtils::getStringValue( vR, parent );
438  equal = QString::compare( sL, sR ) == 0;
439  }
440  if ( equal )
441  return mOp == boIs ? TVL_True : TVL_False;
442  else
443  return mOp == boIs ? TVL_False : TVL_True;
444  }
445 
446  case boRegexp:
447  case boLike:
448  case boNotLike:
449  case boILike:
450  case boNotILike:
451  if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
452  return TVL_Unknown;
453  else
454  {
455  QString str = QgsExpressionUtils::getStringValue( vL, parent );
457  QString regexp = QgsExpressionUtils::getStringValue( vR, parent );
459  // TODO: cache QRegExp in case that regexp is a literal string (i.e. it will stay constant)
460  bool matches;
461  if ( mOp == boLike || mOp == boILike || mOp == boNotLike || mOp == boNotILike ) // change from LIKE syntax to regexp
462  {
463  QString esc_regexp = QRegExp::escape( regexp );
464  // manage escape % and _
465  if ( esc_regexp.startsWith( '%' ) )
466  {
467  esc_regexp.replace( 0, 1, QStringLiteral( ".*" ) );
468  }
469  QRegExp rx( "[^\\\\](%)" );
470  int pos = 0;
471  while ( ( pos = rx.indexIn( esc_regexp, pos ) ) != -1 )
472  {
473  esc_regexp.replace( pos + 1, 1, QStringLiteral( ".*" ) );
474  pos += 1;
475  }
476  rx.setPattern( QStringLiteral( "\\\\%" ) );
477  esc_regexp.replace( rx, QStringLiteral( "%" ) );
478  if ( esc_regexp.startsWith( '_' ) )
479  {
480  esc_regexp.replace( 0, 1, QStringLiteral( "." ) );
481  }
482  rx.setPattern( QStringLiteral( "[^\\\\](_)" ) );
483  pos = 0;
484  while ( ( pos = rx.indexIn( esc_regexp, pos ) ) != -1 )
485  {
486  esc_regexp.replace( pos + 1, 1, '.' );
487  pos += 1;
488  }
489  rx.setPattern( QStringLiteral( "\\\\_" ) );
490  esc_regexp.replace( rx, QStringLiteral( "_" ) );
491  matches = QRegExp( esc_regexp, mOp == boLike || mOp == boNotLike ? Qt::CaseSensitive : Qt::CaseInsensitive ).exactMatch( str );
492  }
493  else
494  {
495  matches = QRegExp( regexp ).indexIn( str ) != -1;
496  }
497 
498  if ( mOp == boNotLike || mOp == boNotILike )
499  {
500  matches = !matches;
501  }
502 
503  return matches ? TVL_True : TVL_False;
504  }
505 
506  case boConcat:
507  if ( QgsExpressionUtils::isNull( vL ) || QgsExpressionUtils::isNull( vR ) )
508  return QVariant();
509  else
510  {
511  QString sL = QgsExpressionUtils::getStringValue( vL, parent );
513  QString sR = QgsExpressionUtils::getStringValue( vR, parent );
515  return QVariant( sL + sR );
516  }
517 
518  default:
519  break;
520  }
521  Q_ASSERT( false );
522  return QVariant();
523 }
524 
525 bool QgsExpressionNodeBinaryOperator::compare( double diff )
526 {
527  switch ( mOp )
528  {
529  case boEQ:
530  return qgsDoubleNear( diff, 0.0 );
531  case boNE:
532  return !qgsDoubleNear( diff, 0.0 );
533  case boLT:
534  return diff < 0;
535  case boGT:
536  return diff > 0;
537  case boLE:
538  return diff <= 0;
539  case boGE:
540  return diff >= 0;
541  default:
542  Q_ASSERT( false );
543  return false;
544  }
545 }
546 
547 qlonglong QgsExpressionNodeBinaryOperator::computeInt( qlonglong x, qlonglong y )
548 {
549  switch ( mOp )
550  {
551  case boPlus:
552  return x + y;
553  case boMinus:
554  return x - y;
555  case boMul:
556  return x * y;
557  case boDiv:
558  return x / y;
559  case boMod:
560  return x % y;
561  default:
562  Q_ASSERT( false );
563  return 0;
564  }
565 }
566 
567 QDateTime QgsExpressionNodeBinaryOperator::computeDateTimeFromInterval( const QDateTime &d, QgsInterval *i )
568 {
569  switch ( mOp )
570  {
571  case boPlus:
572  return d.addSecs( i->seconds() );
573  case boMinus:
574  return d.addSecs( -i->seconds() );
575  default:
576  Q_ASSERT( false );
577  return QDateTime();
578  }
579 }
580 
581 double QgsExpressionNodeBinaryOperator::computeDouble( double x, double y )
582 {
583  switch ( mOp )
584  {
585  case boPlus:
586  return x + y;
587  case boMinus:
588  return x - y;
589  case boMul:
590  return x * y;
591  case boDiv:
592  return x / y;
593  case boMod:
594  return std::fmod( x, y );
595  default:
596  Q_ASSERT( false );
597  return 0;
598  }
599 }
600 
602 {
603  return ntBinaryOperator;
604 }
605 
607 {
608  bool resL = mOpLeft->prepare( parent, context );
609  bool resR = mOpRight->prepare( parent, context );
610  return resL && resR;
611 }
612 
614 {
615  // see left/right in qgsexpressionparser.yy
616  switch ( mOp )
617  {
618  case boOr:
619  return 1;
620 
621  case boAnd:
622  return 2;
623 
624  case boEQ:
625  case boNE:
626  case boLE:
627  case boGE:
628  case boLT:
629  case boGT:
630  case boRegexp:
631  case boLike:
632  case boILike:
633  case boNotLike:
634  case boNotILike:
635  case boIs:
636  case boIsNot:
637  return 3;
638 
639  case boPlus:
640  case boMinus:
641  return 4;
642 
643  case boMul:
644  case boDiv:
645  case boIntDiv:
646  case boMod:
647  return 5;
648 
649  case boPow:
650  return 6;
651 
652  case boConcat:
653  return 7;
654  }
655  Q_ASSERT( false && "unexpected binary operator" );
656  return -1;
657 }
658 
660 {
661  // see left/right in qgsexpressionparser.yy
662  switch ( mOp )
663  {
664  case boOr:
665  case boAnd:
666  case boEQ:
667  case boNE:
668  case boLE:
669  case boGE:
670  case boLT:
671  case boGT:
672  case boRegexp:
673  case boLike:
674  case boILike:
675  case boNotLike:
676  case boNotILike:
677  case boIs:
678  case boIsNot:
679  case boPlus:
680  case boMinus:
681  case boMul:
682  case boDiv:
683  case boIntDiv:
684  case boMod:
685  case boConcat:
686  return true;
687 
688  case boPow:
689  return false;
690  }
691  Q_ASSERT( false && "unexpected binary operator" );
692  return false;
693 }
694 
696 {
697  QgsExpressionNodeBinaryOperator *lOp = dynamic_cast<QgsExpressionNodeBinaryOperator *>( mOpLeft );
698  QgsExpressionNodeBinaryOperator *rOp = dynamic_cast<QgsExpressionNodeBinaryOperator *>( mOpRight );
699  QgsExpressionNodeUnaryOperator *ruOp = dynamic_cast<QgsExpressionNodeUnaryOperator *>( mOpRight );
700 
701  QString rdump( mOpRight->dump() );
702 
703  // avoid dumping "IS (NOT ...)" as "IS NOT ..."
704  if ( mOp == boIs && ruOp && ruOp->op() == QgsExpressionNodeUnaryOperator::uoNot )
705  {
706  rdump.prepend( '(' ).append( ')' );
707  }
708 
709  QString fmt;
710  if ( leftAssociative() )
711  {
712  fmt += lOp && ( lOp->precedence() < precedence() ) ? QStringLiteral( "(%1)" ) : QStringLiteral( "%1" );
713  fmt += QLatin1String( " %2 " );
714  fmt += rOp && ( rOp->precedence() <= precedence() ) ? QStringLiteral( "(%3)" ) : QStringLiteral( "%3" );
715  }
716  else
717  {
718  fmt += lOp && ( lOp->precedence() <= precedence() ) ? QStringLiteral( "(%1)" ) : QStringLiteral( "%1" );
719  fmt += QLatin1String( " %2 " );
720  fmt += rOp && ( rOp->precedence() < precedence() ) ? QStringLiteral( "(%3)" ) : QStringLiteral( "%3" );
721  }
722 
723  return fmt.arg( mOpLeft->dump(), BINARY_OPERATOR_TEXT[mOp], rdump );
724 }
725 
727 {
728  return mOpLeft->referencedColumns() + mOpRight->referencedColumns();
729 }
730 
732 {
733  return mOpLeft->referencedVariables() + mOpRight->referencedVariables();
734 }
735 
737 {
738  return mOpLeft->referencedFunctions() + mOpRight->referencedFunctions();
739 }
740 
741 QList<const QgsExpressionNode *> QgsExpressionNodeBinaryOperator::nodes() const
742 {
743  QList<const QgsExpressionNode *> lst;
744  lst << this;
745  lst += mOpLeft->nodes() + mOpRight->nodes();
746  return lst;
747 }
748 
750 {
751  return mOpLeft->needsGeometry() || mOpRight->needsGeometry();
752 }
753 
755 {
756  QgsExpressionNodeBinaryOperator *copy = new QgsExpressionNodeBinaryOperator( mOp, mOpLeft->clone(), mOpRight->clone() );
757  cloneTo( copy );
758  return copy;
759 }
760 
762 {
763  return mOpLeft->isStatic( parent, context ) && mOpRight->isStatic( parent, context );
764 }
765 
766 //
767 
769 {
770  if ( mList->count() == 0 )
771  return mNotIn ? TVL_True : TVL_False;
772  QVariant v1 = mNode->eval( parent, context );
774  if ( QgsExpressionUtils::isNull( v1 ) )
775  return TVL_Unknown;
776 
777  bool listHasNull = false;
778 
779  const QList< QgsExpressionNode * > nodeList = mList->list();
780  for ( QgsExpressionNode *n : nodeList )
781  {
782  QVariant v2 = n->eval( parent, context );
784  if ( QgsExpressionUtils::isNull( v2 ) )
785  listHasNull = true;
786  else
787  {
788  bool equal = false;
789  // check whether they are equal
790  if ( QgsExpressionUtils::isDoubleSafe( v1 ) && QgsExpressionUtils::isDoubleSafe( v2 ) )
791  {
792  double f1 = QgsExpressionUtils::getDoubleValue( v1, parent );
794  double f2 = QgsExpressionUtils::getDoubleValue( v2, parent );
796  equal = qgsDoubleNear( f1, f2 );
797  }
798  else
799  {
800  QString s1 = QgsExpressionUtils::getStringValue( v1, parent );
802  QString s2 = QgsExpressionUtils::getStringValue( v2, parent );
804  equal = QString::compare( s1, s2 ) == 0;
805  }
806 
807  if ( equal ) // we know the result
808  return mNotIn ? TVL_False : TVL_True;
809  }
810  }
811 
812  // item not found
813  if ( listHasNull )
814  return TVL_Unknown;
815  else
816  return mNotIn ? TVL_True : TVL_False;
817 }
818 
820 {
821  delete mNode;
822  delete mList;
823 }
824 
826 {
827  return ntInOperator;
828 }
829 
831 {
832  bool res = mNode->prepare( parent, context );
833  const QList< QgsExpressionNode * > nodeList = mList->list();
834  for ( QgsExpressionNode *n : nodeList )
835  {
836  res = res && n->prepare( parent, context );
837  }
838  return res;
839 }
840 
842 {
843  return QStringLiteral( "%1 %2 IN (%3)" ).arg( mNode->dump(), mNotIn ? "NOT" : "", mList->dump() );
844 }
845 
847 {
848  QgsExpressionNodeInOperator *copy = new QgsExpressionNodeInOperator( mNode->clone(), mList->clone(), mNotIn );
849  cloneTo( copy );
850  return copy;
851 }
852 
854 {
855  if ( !mNode->isStatic( parent, context ) )
856  return false;
857 
858  const QList< QgsExpressionNode * > nodeList = mList->list();
859  for ( QgsExpressionNode *n : nodeList )
860  {
861  if ( !n->isStatic( parent, context ) )
862  return false;
863  }
864 
865  return true;
866 }
867 
868 //
869 
871 {
872  QString name = QgsExpression::QgsExpression::Functions()[mFnIndex]->name();
873  QgsExpressionFunction *fd = context && context->hasFunction( name ) ? context->function( name ) : QgsExpression::QgsExpression::Functions()[mFnIndex];
874 
875  QVariant res = fd->run( mArgs, context, parent, this );
877 
878  // everything went fine
879  return res;
880 }
881 
883  : mFnIndex( fnIndex )
884 {
885  const QgsExpressionFunction::ParameterList &functionParams = QgsExpression::QgsExpression::Functions()[mFnIndex]->parameters();
886  if ( !args || functionParams.isEmpty() )
887  {
888  // no QgsExpressionFunction::Parameters, or function does not support them
889  mArgs = args;
890  }
891  else
892  {
893  mArgs = new NodeList();
894 
895  int idx = 0;
896  //first loop through unnamed arguments
897  while ( idx < args->names().size() && args->names().at( idx ).isEmpty() )
898  {
899  mArgs->append( args->list().at( idx )->clone() );
900  idx++;
901  }
902 
903  //next copy named QgsExpressionFunction::Parameters in order expected by function
904  for ( ; idx < functionParams.count(); ++idx )
905  {
906  int nodeIdx = args->names().indexOf( functionParams.at( idx ).name().toLower() );
907  if ( nodeIdx < 0 )
908  {
909  //QgsExpressionFunction::Parameter not found - insert default value for QgsExpressionFunction::Parameter
910  mArgs->append( new QgsExpressionNodeLiteral( functionParams.at( idx ).defaultValue() ) );
911  }
912  else
913  {
914  mArgs->append( args->list().at( nodeIdx )->clone() );
915  }
916  }
917 
918  delete args;
919  }
920 }
921 
923 {
924  delete mArgs;
925 }
926 
928 {
929  return ntFunction;
930 }
931 
933 {
934  QgsExpressionFunction *fd = QgsExpression::QgsExpression::Functions()[mFnIndex];
935 
936  bool res = fd->prepare( this, parent, context );
937  if ( mArgs && !fd->lazyEval() )
938  {
939  const QList< QgsExpressionNode * > nodeList = mArgs->list();
940  for ( QgsExpressionNode *n : nodeList )
941  {
942  res = res && n->prepare( parent, context );
943  }
944  }
945  return res;
946 }
947 
949 {
950  QgsExpressionFunction *fd = QgsExpression::QgsExpression::Functions()[mFnIndex];
951  if ( fd->params() == 0 )
952  return QStringLiteral( "%1%2" ).arg( fd->name(), fd->name().startsWith( '$' ) ? "" : "()" ); // special column
953  else
954  return QStringLiteral( "%1(%2)" ).arg( fd->name(), mArgs ? mArgs->dump() : QString() ); // function
955 }
956 
958 {
959  QgsExpressionFunction *fd = QgsExpression::QgsExpression::Functions()[mFnIndex];
960  QSet<QString> functionColumns = fd->referencedColumns( this );
961 
962  if ( !mArgs )
963  {
964  //no referenced columns in arguments, just return function's referenced columns
965  return functionColumns;
966  }
967 
968  int paramIndex = 0;
969  const QList< QgsExpressionNode * > nodeList = mArgs->list();
970  for ( QgsExpressionNode *n : nodeList )
971  {
972  if ( fd->parameters().count() <= paramIndex || !fd->parameters().at( paramIndex ).isSubExpression() )
973  functionColumns.unite( n->referencedColumns() );
974  paramIndex++;
975  }
976 
977  return functionColumns;
978 }
979 
981 {
982  QgsExpressionFunction *fd = QgsExpression::QgsExpression::Functions()[mFnIndex];
983  if ( fd->name() == QLatin1String( "var" ) )
984  {
985  if ( !mArgs->list().isEmpty() )
986  {
987  QgsExpressionNodeLiteral *var = dynamic_cast<QgsExpressionNodeLiteral *>( mArgs->list().at( 0 ) );
988  if ( var )
989  return QSet<QString>() << var->value().toString();
990  }
991  return QSet<QString>() << QString();
992  }
993  else
994  {
995  QSet<QString> functionVariables = QSet<QString>();
996 
997  if ( !mArgs )
998  return functionVariables;
999 
1000  const QList< QgsExpressionNode * > nodeList = mArgs->list();
1001  for ( QgsExpressionNode *n : nodeList )
1002  {
1003  functionVariables.unite( n->referencedVariables() );
1004  }
1005 
1006  return functionVariables;
1007  }
1008 }
1009 
1011 {
1012  QgsExpressionFunction *fd = QgsExpression::QgsExpression::Functions()[mFnIndex];
1013  QSet<QString> functions = QSet<QString>();
1014  functions.insert( fd->name() );
1015 
1016  if ( !mArgs )
1017  return functions;
1018 
1019  const QList< QgsExpressionNode * > nodeList = mArgs->list();
1020  for ( QgsExpressionNode *n : nodeList )
1021  {
1022  functions.unite( n->referencedFunctions() );
1023  }
1024  return functions;
1025 }
1026 
1027 QList<const QgsExpressionNode *> QgsExpressionNodeFunction::nodes() const
1028 {
1029  QList<const QgsExpressionNode *> lst;
1030  lst << this;
1031  if ( !mArgs )
1032  return lst;
1033 
1034  const QList< QgsExpressionNode * > nodeList = mArgs->list();
1035  for ( QgsExpressionNode *n : nodeList )
1036  {
1037  lst += n->nodes();
1038  }
1039  return lst;
1040 }
1041 
1043 {
1044  bool needs = QgsExpression::QgsExpression::Functions()[mFnIndex]->usesGeometry( this );
1045  if ( mArgs )
1046  {
1047  const QList< QgsExpressionNode * > nodeList = mArgs->list();
1048  for ( QgsExpressionNode *n : nodeList )
1049  needs |= n->needsGeometry();
1050  }
1051  return needs;
1052 }
1053 
1055 {
1056  QgsExpressionNodeFunction *copy = new QgsExpressionNodeFunction( mFnIndex, mArgs ? mArgs->clone() : nullptr );
1057  cloneTo( copy );
1058  return copy;
1059 }
1060 
1062 {
1063  return QgsExpression::Functions()[mFnIndex]->isStatic( this, parent, context );
1064 }
1065 
1067 {
1068  if ( !args || !args->hasNamedNodes() )
1069  return true;
1070 
1071  const QgsExpressionFunction::ParameterList &functionParams = QgsExpression::Functions()[fnIndex]->parameters();
1072  if ( functionParams.isEmpty() )
1073  {
1074  error = QStringLiteral( "%1 does not support named QgsExpressionFunction::Parameters" ).arg( QgsExpression::Functions()[fnIndex]->name() );
1075  return false;
1076  }
1077  else
1078  {
1079  QSet< int > providedArgs;
1080  QSet< int > handledArgs;
1081  int idx = 0;
1082  //first loop through unnamed arguments
1083  while ( args->names().at( idx ).isEmpty() )
1084  {
1085  providedArgs << idx;
1086  handledArgs << idx;
1087  idx++;
1088  }
1089 
1090  //next check named QgsExpressionFunction::Parameters
1091  for ( ; idx < functionParams.count(); ++idx )
1092  {
1093  int nodeIdx = args->names().indexOf( functionParams.at( idx ).name().toLower() );
1094  if ( nodeIdx < 0 )
1095  {
1096  if ( !functionParams.at( idx ).optional() )
1097  {
1098  error = QStringLiteral( "No value specified for QgsExpressionFunction::Parameter '%1' for %2" ).arg( functionParams.at( idx ).name(), QgsExpression::Functions()[fnIndex]->name() );
1099  return false;
1100  }
1101  }
1102  else
1103  {
1104  if ( providedArgs.contains( idx ) )
1105  {
1106  error = QStringLiteral( "Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2" ).arg( functionParams.at( idx ).name(), QgsExpression::Functions()[fnIndex]->name() );
1107  return false;
1108  }
1109  }
1110  providedArgs << idx;
1111  handledArgs << nodeIdx;
1112  }
1113 
1114  //last check for bad names
1115  idx = 0;
1116  const QStringList nameList = args->names();
1117  for ( const QString &name : nameList )
1118  {
1119  if ( !name.isEmpty() && !functionParams.contains( name ) )
1120  {
1121  error = QStringLiteral( "Invalid QgsExpressionFunction::Parameter name '%1' for %2" ).arg( name, QgsExpression::Functions()[fnIndex]->name() );
1122  return false;
1123  }
1124  if ( !name.isEmpty() && !handledArgs.contains( idx ) )
1125  {
1126  int functionIdx = functionParams.indexOf( name );
1127  if ( providedArgs.contains( functionIdx ) )
1128  {
1129  error = QStringLiteral( "Duplicate QgsExpressionFunction::Parameter specified for '%1' for %2" ).arg( functionParams.at( functionIdx ).name(), QgsExpression::Functions()[fnIndex]->name() );
1130  return false;
1131  }
1132  }
1133  idx++;
1134  }
1135 
1136  }
1137  return true;
1138 }
1139 
1140 //
1141 
1143 {
1144  Q_UNUSED( context );
1145  Q_UNUSED( parent );
1146  return mValue;
1147 }
1148 
1150 {
1151  return ntLiteral;
1152 }
1153 
1155 {
1156  Q_UNUSED( parent );
1157  Q_UNUSED( context );
1158  return true;
1159 }
1160 
1161 
1163 {
1164  if ( mValue.isNull() )
1165  return QStringLiteral( "NULL" );
1166 
1167  switch ( mValue.type() )
1168  {
1169  case QVariant::Int:
1170  return QString::number( mValue.toInt() );
1171  case QVariant::Double:
1172  return QString::number( mValue.toDouble() );
1173  case QVariant::String:
1174  return QgsExpression::quotedString( mValue.toString() );
1175  case QVariant::Bool:
1176  return mValue.toBool() ? QStringLiteral( "TRUE" ) : QStringLiteral( "FALSE" );
1177  default:
1178  return tr( "[unsupported type: %1; value: %2]" ).arg( mValue.typeName(), mValue.toString() );
1179  }
1180 }
1181 
1183 {
1184  return QSet<QString>();
1185 }
1186 
1188 {
1189  return QSet<QString>();
1190 }
1191 
1193 {
1194  return QSet<QString>();
1195 }
1196 
1197 QList<const QgsExpressionNode *> QgsExpressionNodeLiteral::nodes() const
1198 {
1199  QList<const QgsExpressionNode *> lst;
1200  lst << this;
1201  return lst;
1202 }
1203 
1205 {
1206  return false;
1207 }
1208 
1210 {
1211  QgsExpressionNodeLiteral *copy = new QgsExpressionNodeLiteral( mValue );
1212  cloneTo( copy );
1213  return copy;
1214 }
1215 
1217 {
1218  Q_UNUSED( context )
1219  Q_UNUSED( parent )
1220  return true;
1221 }
1222 
1223 //
1224 
1226 {
1227  Q_UNUSED( parent );
1228  int index = mIndex;
1229 
1230  if ( index < 0 )
1231  {
1232  // have not yet found field index - first check explicitly set fields collection
1233  if ( context && context->hasVariable( QgsExpressionContext::EXPR_FIELDS ) )
1234  {
1235  QgsFields fields = qvariant_cast<QgsFields>( context->variable( QgsExpressionContext::EXPR_FIELDS ) );
1236  index = fields.lookupField( mName );
1237  }
1238  }
1239 
1240  if ( context && context->hasFeature() )
1241  {
1242  QgsFeature feature = context->feature();
1243  if ( index >= 0 )
1244  return feature.attribute( index );
1245  else
1246  return feature.attribute( mName );
1247  }
1248  return QVariant( '[' + mName + ']' );
1249 }
1250 
1252 {
1253  return ntColumnRef;
1254 }
1255 
1257 {
1258  if ( !context || !context->hasVariable( QgsExpressionContext::EXPR_FIELDS ) )
1259  return false;
1260 
1261  QgsFields fields = qvariant_cast<QgsFields>( context->variable( QgsExpressionContext::EXPR_FIELDS ) );
1262 
1263  mIndex = fields.lookupField( mName );
1264 
1265  if ( mIndex == -1 && context->hasFeature() )
1266  {
1267  mIndex = context->feature().fieldNameIndex( mName );
1268  }
1269 
1270  if ( mIndex == -1 )
1271  {
1272  parent->setEvalErrorString( tr( "Column '%1' not found" ).arg( mName ) );
1273  return false;
1274  }
1275  return true;
1276 }
1277 
1279 {
1280  return QRegExp( "^[A-Za-z_\x80-\xff][A-Za-z0-9_\x80-\xff]*$" ).exactMatch( mName ) ? mName : QgsExpression::quotedColumnRef( mName );
1281 }
1282 
1284 {
1285  return QSet<QString>() << mName;
1286 }
1287 
1289 {
1290  return QSet<QString>();
1291 }
1292 
1294 {
1295  return QSet<QString>();
1296 }
1297 
1298 QList<const QgsExpressionNode *> QgsExpressionNodeColumnRef::nodes() const
1299 {
1300  QList<const QgsExpressionNode *> result;
1301  result << this;
1302  return result;
1303 }
1304 
1306 {
1307  return false;
1308 }
1309 
1311 {
1313  cloneTo( copy );
1314  return copy;
1315 }
1316 
1318 {
1319  Q_UNUSED( context )
1320  Q_UNUSED( parent )
1321  return false;
1322 }
1323 
1324 //
1325 
1327  : mConditions( *conditions )
1328  , mElseExp( elseExp )
1329 {
1330  delete conditions;
1331 }
1332 
1334 {
1335  delete mElseExp;
1336  qDeleteAll( mConditions );
1337 }
1338 
1340 {
1341  return ntCondition;
1342 }
1343 
1345 {
1346  for ( WhenThen *cond : qgis::as_const( mConditions ) )
1347  {
1348  QVariant vWhen = cond->mWhenExp->eval( parent, context );
1349  QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( vWhen, parent );
1351  if ( tvl == QgsExpressionUtils::True )
1352  {
1353  QVariant vRes = cond->mThenExp->eval( parent, context );
1355  return vRes;
1356  }
1357  }
1358 
1359  if ( mElseExp )
1360  {
1361  QVariant vElse = mElseExp->eval( parent, context );
1363  return vElse;
1364  }
1365 
1366  // return NULL if no condition is matching
1367  return QVariant();
1368 }
1369 
1371 {
1372  bool res;
1373  for ( WhenThen *cond : qgis::as_const( mConditions ) )
1374  {
1375  res = cond->mWhenExp->prepare( parent, context )
1376  & cond->mThenExp->prepare( parent, context );
1377  if ( !res )
1378  return false;
1379  }
1380 
1381  if ( mElseExp )
1382  return mElseExp->prepare( parent, context );
1383 
1384  return true;
1385 }
1386 
1388 {
1389  QString msg( QStringLiteral( "CASE" ) );
1390  for ( WhenThen *cond : mConditions )
1391  {
1392  msg += QStringLiteral( " WHEN %1 THEN %2" ).arg( cond->mWhenExp->dump(), cond->mThenExp->dump() );
1393  }
1394  if ( mElseExp )
1395  msg += QStringLiteral( " ELSE %1" ).arg( mElseExp->dump() );
1396  msg += QStringLiteral( " END" );
1397  return msg;
1398 }
1399 
1401 {
1402  QSet<QString> lst;
1403  for ( WhenThen *cond : mConditions )
1404  {
1405  lst += cond->mWhenExp->referencedColumns() + cond->mThenExp->referencedColumns();
1406  }
1407 
1408  if ( mElseExp )
1409  lst += mElseExp->referencedColumns();
1410 
1411  return lst;
1412 }
1413 
1415 {
1416  QSet<QString> lst;
1417  for ( WhenThen *cond : mConditions )
1418  {
1419  lst += cond->mWhenExp->referencedVariables() + cond->mThenExp->referencedVariables();
1420  }
1421 
1422  if ( mElseExp )
1423  lst += mElseExp->referencedVariables();
1424 
1425  return lst;
1426 }
1427 
1429 {
1430  QSet<QString> lst;
1431  for ( WhenThen *cond : mConditions )
1432  {
1433  lst += cond->mWhenExp->referencedFunctions() + cond->mThenExp->referencedFunctions();
1434  }
1435 
1436  if ( mElseExp )
1437  lst += mElseExp->referencedFunctions();
1438 
1439  return lst;
1440 }
1441 
1442 QList<const QgsExpressionNode *> QgsExpressionNodeCondition::nodes() const
1443 {
1444  QList<const QgsExpressionNode *> lst;
1445  lst << this;
1446  for ( WhenThen *cond : mConditions )
1447  {
1448  lst += cond->mWhenExp->nodes() + cond->mThenExp->nodes();
1449  }
1450 
1451  if ( mElseExp )
1452  lst += mElseExp->nodes();
1453 
1454  return lst;
1455 }
1456 
1458 {
1459  for ( WhenThen *cond : mConditions )
1460  {
1461  if ( cond->mWhenExp->needsGeometry() ||
1462  cond->mThenExp->needsGeometry() )
1463  return true;
1464  }
1465 
1466  return mElseExp && mElseExp->needsGeometry();
1467 }
1468 
1470 {
1472  for ( WhenThen *wt : mConditions )
1473  conditions.append( wt->clone() );
1474 
1475  QgsExpressionNodeCondition *copy = new QgsExpressionNodeCondition( conditions, mElseExp ? mElseExp->clone() : nullptr );
1476  cloneTo( copy );
1477  return copy;
1478 }
1479 
1481 {
1482  for ( WhenThen *wt : mConditions )
1483  {
1484  if ( !wt->mWhenExp->isStatic( parent, context ) || !wt->mThenExp->isStatic( parent, context ) )
1485  return false;
1486  }
1487 
1488  if ( mElseExp )
1489  return mElseExp->isStatic( parent, context );
1490 
1491  return true;
1492 }
1493 
1495 {
1496  QSet<QString> lst( mNode->referencedColumns() );
1497  const QList< QgsExpressionNode * > nodeList = mList->list();
1498  for ( const QgsExpressionNode *n : nodeList )
1499  lst.unite( n->referencedColumns() );
1500  return lst;
1501 }
1502 
1504 {
1505  QSet<QString> lst( mNode->referencedVariables() );
1506  const QList< QgsExpressionNode * > nodeList = mList->list();
1507  for ( const QgsExpressionNode *n : nodeList )
1508  lst.unite( n->referencedVariables() );
1509  return lst;
1510 }
1511 
1513 {
1514  QSet<QString> lst( mNode->referencedFunctions() );
1515  const QList< QgsExpressionNode * > nodeList = mList->list();
1516  for ( const QgsExpressionNode *n : nodeList )
1517  lst.unite( n->referencedFunctions() );
1518  return lst;
1519 }
1520 
1521 QList<const QgsExpressionNode *> QgsExpressionNodeInOperator::nodes() const
1522 {
1523  QList<const QgsExpressionNode *> lst;
1524  lst << this;
1525  const QList< QgsExpressionNode * > nodeList = mList->list();
1526  for ( const QgsExpressionNode *n : nodeList )
1527  lst += n->nodes();
1528  return lst;
1529 }
1530 
1532  : mWhenExp( whenExp )
1533  , mThenExp( thenExp )
1534 {
1535 }
1536 
1538 {
1539  delete mWhenExp;
1540  delete mThenExp;
1541 }
1542 
1544 {
1545  return new WhenThen( mWhenExp->clone(), mThenExp->clone() );
1546 }
1547 
1549 {
1550  return BINARY_OPERATOR_TEXT[mOp];
1551 }
1552 
1553 //
1554 
1556 {
1557  const QVariant container = mContainer->eval( parent, context );
1559  const QVariant index = mIndex->eval( parent, context );
1561 
1562  switch ( container.type() )
1563  {
1564  case QVariant::Map:
1565  return QgsExpressionUtils::getMapValue( container, parent ).value( index.toString() );
1566 
1567  case QVariant::List:
1568  case QVariant::StringList:
1569  {
1570  const QVariantList list = QgsExpressionUtils::getListValue( container, parent );
1571  qlonglong pos = QgsExpressionUtils::getIntValue( index, parent );
1572  if ( pos >= list.length() || pos < -list.length() )
1573  {
1574  return QVariant();
1575  }
1576  if ( pos < 0 )
1577  {
1578  // negative indices are from back of list
1579  pos += list.length();
1580  }
1581 
1582  return list.at( pos );
1583  }
1584 
1585  default:
1586  parent->setEvalErrorString( tr( "[] can only be used with map or array values, not %1" ).arg( QMetaType::typeName( container.type() ) ) );
1587  return QVariant();
1588  }
1589 }
1590 
1592 {
1593  return ntIndexOperator;
1594 }
1595 
1597 {
1598  bool resC = mContainer->prepare( parent, context );
1599  bool resV = mIndex->prepare( parent, context );
1600  return resC && resV;
1601 }
1602 
1604 {
1605  return QStringLiteral( "%1[%2]" ).arg( mContainer->dump(), mIndex->dump() );
1606 }
1607 
1609 {
1610  return mContainer->referencedColumns() + mIndex->referencedColumns();
1611 }
1612 
1614 {
1615  return mContainer->referencedVariables() + mIndex->referencedVariables();
1616 }
1617 
1619 {
1620  return mContainer->referencedFunctions() + mIndex->referencedFunctions();
1621 }
1622 
1623 QList<const QgsExpressionNode *> QgsExpressionNodeIndexOperator::nodes() const
1624 {
1625  QList<const QgsExpressionNode *> lst;
1626  lst << this;
1627  lst += mContainer->nodes() + mIndex->nodes();
1628  return lst;
1629 }
1630 
1632 {
1633  return mContainer->needsGeometry() || mIndex->needsGeometry();
1634 }
1635 
1637 {
1638  QgsExpressionNodeIndexOperator *copy = new QgsExpressionNodeIndexOperator( mContainer->clone(), mIndex->clone() );
1639  cloneTo( copy );
1640  return copy;
1641 }
1642 
1644 {
1645  return mContainer->isStatic( parent, context ) && mIndex->isStatic( parent, context );
1646 }
int lookupField(const QString &fieldName) const
Looks up field&#39;s index from the field name.
Definition: qgsfields.cpp:324
void cloneTo(QgsExpressionNode *target) const
Copies the members of this node to the node provided in target.
Class for parsing and evaluation of expressions (formerly called "search strings").
QStringList names() const
Returns a list of names for nodes.
QgsExpressionNode * node
Node.
virtual QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)
Evaluates the function, first evaluating all required arguments before passing them to the function&#39;s...
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
bool prepare(QgsExpression *parent, const QgsExpressionContext *context)
Prepare this node for evaluation.
QgsExpressionNodeFunction(int fnIndex, QgsExpressionNode::NodeList *args)
A function node consists of an index of the function in the global function array and a list of argum...
virtual QString dump() const =0
Dump this node into a serialized (part) of an expression.
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node...
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
QgsExpressionNodeCondition(QgsExpressionNodeCondition::WhenThenList *conditions, QgsExpressionNode *elseExp=nullptr)
Create a new node with the given list of conditions and an optional elseExp expression.
int params() const
The number of parameters this function takes.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
int precedence() const
Returns the precedence index for the operator.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
bool hasFunction(const QString &name) const
Checks whether a specified function is contained in the context.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
WhenThenList conditions() const
The list of WHEN THEN expression parts of the expression.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:265
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node...
NodeType
Known node types.
QgsExpressionNodeInOperator(QgsExpressionNode *node, QgsExpressionNode::NodeList *list, bool notin=false)
This node tests if the result of node is in the result of list.
An expression node for CASE WHEN clauses.
double seconds() const
Returns the interval duration in seconds.
Definition: qgsinterval.h:151
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
virtual QSet< QString > referencedColumns(const QgsExpressionNodeFunction *node) const
Returns a set of field names which are required for this function.
Container of fields for a vector layer.
Definition: qgsfields.h:42
bool hasVariable(const QString &name) const
Check whether a variable is specified by any scope within the context.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
virtual QgsExpressionNode * clone() const =0
Generate a clone of this node.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node...
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QList< QgsExpressionFunction::Parameter > ParameterList
List of parameters, used for function definition.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression...
QVariant variable(const QString &name) const
Fetches a matching variable from the context.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node...
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
void setEvalErrorString(const QString &str)
Sets evaluation error (used internally by evaluation functions)
bool hasFeature() const
Returns true if the context has a feature associated with it.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QgsExpressionNode * clone() const override
Generate a clone of this node.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression...
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression...
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
#define ENSURE_NO_EVAL_ERROR
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QString text() const
Returns a the name of this operator without the operands.
#define SET_EVAL_ERROR(x)
#define FALLTHROUGH
Definition: qgis.h:656
virtual QSet< QString > referencedColumns() const =0
Abstract virtual method which returns a list of columns required to evaluate this node...
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node...
virtual QSet< QString > referencedVariables() const =0
Returns a set of all variables which are used in this expression.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
const QString & typeName
const QgsExpressionFunction::ParameterList & parameters() const
Returns the list of named parameters for the function, if set.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
An expression node for value IN or NOT IN clauses.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node...
QgsExpressionNode * clone() const override
Generate a clone of this node.
QgsExpressionNode * clone() const override
Generate a clone of this node.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
An expression node which takes it value from a feature&#39;s field.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
virtual QSet< QString > referencedFunctions() const =0
Returns a set of all functions which are used in this expression.
QString dump() const override
Dump this node into a serialized (part) of an expression.
Abstract base class for all nodes that can appear in an expression.
virtual QString dump() const
Returns a string dump of the expression node.
static const QString EXPR_FIELDS
Inbuilt variable name for fields storage.
QgsExpressionNode * clone() const override
Generate a clone of this node.
An expression node for expression functions.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
static const QList< QgsExpressionFunction * > & Functions()
QVariant eval(QgsExpression *parent, const QgsExpressionContext *context)
Evaluate this node with the given context and parent.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
bool lazyEval() const
True if this function should use lazy evaluation.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
QList< QgsExpressionNodeCondition::WhenThen * > WhenThenList
QgsExpressionNode * clone() const override
Generate a clone of this node.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
QgsExpressionNode::NodeList * clone() const
Creates a deep copy of this list. Ownership is transferred to the caller.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QgsExpressionNode * clone() const override
Generate a clone of this node.
QString name() const
The name of the function.
A representation of the interval between two datetime values.
Definition: qgsinterval.h:39
virtual bool needsGeometry() const =0
Abstract virtual method which returns if the geometry is required to evaluate this expression...
QString dump() const override
Dump this node into a serialized (part) of an expression.
int fieldNameIndex(const QString &fieldName) const
Utility method to get attribute index from name.
Definition: qgsfeature.cpp:277
A abstract base class for defining QgsExpression functions.
A list of expression nodes.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression...
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
QgsExpressionNodeUnaryOperator::UnaryOperator op() const
Returns the unary operator.
QgsExpressionNode * clone() const override
Generate a clone of this node.
A indexing expression operator, which allows use of square brackets [] to reference map and array ite...
An expression node for literal values.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression...
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression...
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
A unary node is either negative as in boolean (not) or as in numbers (minus).
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
A binary expression operator, which operates on two values.
QString dump() const override
Dump this node into a serialized (part) of an expression.
WhenThen(QgsExpressionNode *whenExp, QgsExpressionNode *thenExp)
A combination of when and then.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
QString text() const
Returns a the name of this operator without the operands.
static QString quotedString(QString text)
Returns a quoted version of a string (in single quotes)
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
QString dump() const override
Dump this node into a serialized (part) of an expression.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
QgsFeature feature() const
Convenience function for retrieving the feature for the context, if set.
QgsExpressionNodeCondition::WhenThen * clone() const
Gets a deep copy of this WhenThen combination.
virtual bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const =0
Returns true if this node can be evaluated for a static value.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression...
bool leftAssociative() const
Returns true if the operator is left-associative.
int count() const
Returns the number of nodes in the list.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
void append(QgsExpressionNode *node)
Takes ownership of the provided node.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
virtual QList< const QgsExpressionNode * > nodes() const =0
Returns a list of all nodes which are used in this expression.
QgsExpressionNode * node() const
Returns the expression node.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:262
QString dump() const override
Dump this node into a serialized (part) of an expression.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
Represents a "WHEN... THEN..." portation of a CASE WHEN clause in an expression.
virtual bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const
This will be called during the prepare step() of an expression if it is not static.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QgsExpressionFunction * function(const QString &name) const
Fetches a matching function from the context.
bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression...
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node...
QgsExpressionNode * clone() const override
Generate a clone of this node.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
QVariant value() const
The value of the literal.
bool hasNamedNodes() const
Returns true if list contains any named nodes.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node...
int fnIndex() const
Returns the index of the node&#39;s function.
QgsExpressionNode::NodeType nodeType() const override
Gets the type of this node.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QString dump() const override
Dump this node into a serialized (part) of an expression.
static bool validateParams(int fnIndex, QgsExpressionNode::NodeList *args, QString &error)
Tests whether the provided argument list is valid for the matching function.