QGIS API Documentation  3.2.0-Bonn (bc43194)
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
196  FALLTHROUGH;
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  if ( mIndex >= 0 )
1265  {
1266  return true;
1267  }
1268  else
1269  {
1270  parent->setEvalErrorString( tr( "Column '%1' not found" ).arg( mName ) );
1271  mIndex = -1;
1272  return false;
1273  }
1274 }
1275 
1277 {
1278  return QRegExp( "^[A-Za-z_\x80-\xff][A-Za-z0-9_\x80-\xff]*$" ).exactMatch( mName ) ? mName : QgsExpression::quotedColumnRef( mName );
1279 }
1280 
1282 {
1283  return QSet<QString>() << mName;
1284 }
1285 
1287 {
1288  return QSet<QString>();
1289 }
1290 
1292 {
1293  return QSet<QString>();
1294 }
1295 
1296 QList<const QgsExpressionNode *> QgsExpressionNodeColumnRef::nodes() const
1297 {
1298  QList<const QgsExpressionNode *> result;
1299  result << this;
1300  return result;
1301 }
1302 
1304 {
1305  return false;
1306 }
1307 
1309 {
1311  cloneTo( copy );
1312  return copy;
1313 }
1314 
1316 {
1317  Q_UNUSED( context )
1318  Q_UNUSED( parent )
1319  return false;
1320 }
1321 
1322 //
1323 
1325  : mConditions( *conditions )
1326  , mElseExp( elseExp )
1327 {
1328  delete conditions;
1329 }
1330 
1332 {
1333  delete mElseExp;
1334  qDeleteAll( mConditions );
1335 }
1336 
1338 {
1339  return ntCondition;
1340 }
1341 
1343 {
1344  for ( WhenThen *cond : qgis::as_const( mConditions ) )
1345  {
1346  QVariant vWhen = cond->mWhenExp->eval( parent, context );
1347  QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( vWhen, parent );
1349  if ( tvl == QgsExpressionUtils::True )
1350  {
1351  QVariant vRes = cond->mThenExp->eval( parent, context );
1353  return vRes;
1354  }
1355  }
1356 
1357  if ( mElseExp )
1358  {
1359  QVariant vElse = mElseExp->eval( parent, context );
1361  return vElse;
1362  }
1363 
1364  // return NULL if no condition is matching
1365  return QVariant();
1366 }
1367 
1369 {
1370  bool res;
1371  for ( WhenThen *cond : qgis::as_const( mConditions ) )
1372  {
1373  res = cond->mWhenExp->prepare( parent, context )
1374  & cond->mThenExp->prepare( parent, context );
1375  if ( !res )
1376  return false;
1377  }
1378 
1379  if ( mElseExp )
1380  return mElseExp->prepare( parent, context );
1381 
1382  return true;
1383 }
1384 
1386 {
1387  QString msg( QStringLiteral( "CASE" ) );
1388  for ( WhenThen *cond : mConditions )
1389  {
1390  msg += QStringLiteral( " WHEN %1 THEN %2" ).arg( cond->mWhenExp->dump(), cond->mThenExp->dump() );
1391  }
1392  if ( mElseExp )
1393  msg += QStringLiteral( " ELSE %1" ).arg( mElseExp->dump() );
1394  msg += QStringLiteral( " END" );
1395  return msg;
1396 }
1397 
1399 {
1400  QSet<QString> lst;
1401  for ( WhenThen *cond : mConditions )
1402  {
1403  lst += cond->mWhenExp->referencedColumns() + cond->mThenExp->referencedColumns();
1404  }
1405 
1406  if ( mElseExp )
1407  lst += mElseExp->referencedColumns();
1408 
1409  return lst;
1410 }
1411 
1413 {
1414  QSet<QString> lst;
1415  for ( WhenThen *cond : mConditions )
1416  {
1417  lst += cond->mWhenExp->referencedVariables() + cond->mThenExp->referencedVariables();
1418  }
1419 
1420  if ( mElseExp )
1421  lst += mElseExp->referencedVariables();
1422 
1423  return lst;
1424 }
1425 
1427 {
1428  QSet<QString> lst;
1429  for ( WhenThen *cond : mConditions )
1430  {
1431  lst += cond->mWhenExp->referencedFunctions() + cond->mThenExp->referencedFunctions();
1432  }
1433 
1434  if ( mElseExp )
1435  lst += mElseExp->referencedFunctions();
1436 
1437  return lst;
1438 }
1439 
1440 QList<const QgsExpressionNode *> QgsExpressionNodeCondition::nodes() const
1441 {
1442  QList<const QgsExpressionNode *> lst;
1443  lst << this;
1444  for ( WhenThen *cond : mConditions )
1445  {
1446  lst += cond->mWhenExp->nodes() + cond->mThenExp->nodes();
1447  }
1448 
1449  if ( mElseExp )
1450  lst += mElseExp->nodes();
1451 
1452  return lst;
1453 }
1454 
1456 {
1457  for ( WhenThen *cond : mConditions )
1458  {
1459  if ( cond->mWhenExp->needsGeometry() ||
1460  cond->mThenExp->needsGeometry() )
1461  return true;
1462  }
1463 
1464  return mElseExp && mElseExp->needsGeometry();
1465 }
1466 
1468 {
1470  for ( WhenThen *wt : mConditions )
1471  conditions.append( wt->clone() );
1472 
1473  QgsExpressionNodeCondition *copy = new QgsExpressionNodeCondition( conditions, mElseExp ? mElseExp->clone() : nullptr );
1474  cloneTo( copy );
1475  return copy;
1476 }
1477 
1479 {
1480  for ( WhenThen *wt : mConditions )
1481  {
1482  if ( !wt->mWhenExp->isStatic( parent, context ) || !wt->mThenExp->isStatic( parent, context ) )
1483  return false;
1484  }
1485 
1486  if ( mElseExp )
1487  return mElseExp->isStatic( parent, context );
1488 
1489  return true;
1490 }
1491 
1493 {
1494  QSet<QString> lst( mNode->referencedColumns() );
1495  const QList< QgsExpressionNode * > nodeList = mList->list();
1496  for ( const QgsExpressionNode *n : nodeList )
1497  lst.unite( n->referencedColumns() );
1498  return lst;
1499 }
1500 
1502 {
1503  QSet<QString> lst( mNode->referencedVariables() );
1504  const QList< QgsExpressionNode * > nodeList = mList->list();
1505  for ( const QgsExpressionNode *n : nodeList )
1506  lst.unite( n->referencedVariables() );
1507  return lst;
1508 }
1509 
1511 {
1512  QSet<QString> lst( mNode->referencedFunctions() );
1513  const QList< QgsExpressionNode * > nodeList = mList->list();
1514  for ( const QgsExpressionNode *n : nodeList )
1515  lst.unite( n->referencedFunctions() );
1516  return lst;
1517 }
1518 
1519 QList<const QgsExpressionNode *> QgsExpressionNodeInOperator::nodes() const
1520 {
1521  QList<const QgsExpressionNode *> lst;
1522  lst << this;
1523  const QList< QgsExpressionNode * > nodeList = mList->list();
1524  for ( const QgsExpressionNode *n : nodeList )
1525  lst += n->nodes();
1526  return lst;
1527 }
1528 
1530  : mWhenExp( whenExp )
1531  , mThenExp( thenExp )
1532 {
1533 }
1534 
1536 {
1537  delete mWhenExp;
1538  delete mThenExp;
1539 }
1540 
1542 {
1543  return new WhenThen( mWhenExp->clone(), mThenExp->clone() );
1544 }
1545 
1547 {
1548  return BINARY_OPERATOR_TEXT[mOp];
1549 }
1550 
int lookupField(const QString &fieldName) const
Look up field&#39;s index from the field name.
Definition: qgsfields.cpp:299
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.
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:251
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:62
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.
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.
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.
QString text() const
Returns a the name of this operator without the operands.
#define SET_EVAL_ERROR(x)
#define FALLTHROUGH
Definition: qgis.h:570
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 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.
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.
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< 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.
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 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:255
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 > 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.
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.