QGIS API Documentation  3.8.0-Zanzibar (11aff65)
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::LongLong:
1174  return QString::number( mValue.toLongLong() );
1175  case QVariant::String:
1176  return QgsExpression::quotedString( mValue.toString() );
1177  case QVariant::Bool:
1178  return mValue.toBool() ? QStringLiteral( "TRUE" ) : QStringLiteral( "FALSE" );
1179  default:
1180  return tr( "[unsupported type: %1; value: %2]" ).arg( mValue.typeName(), mValue.toString() );
1181  }
1182 }
1183 
1185 {
1186  return QSet<QString>();
1187 }
1188 
1190 {
1191  return QSet<QString>();
1192 }
1193 
1195 {
1196  return QSet<QString>();
1197 }
1198 
1199 QList<const QgsExpressionNode *> QgsExpressionNodeLiteral::nodes() const
1200 {
1201  QList<const QgsExpressionNode *> lst;
1202  lst << this;
1203  return lst;
1204 }
1205 
1207 {
1208  return false;
1209 }
1210 
1212 {
1213  QgsExpressionNodeLiteral *copy = new QgsExpressionNodeLiteral( mValue );
1214  cloneTo( copy );
1215  return copy;
1216 }
1217 
1219 {
1220  Q_UNUSED( context )
1221  Q_UNUSED( parent )
1222  return true;
1223 }
1224 
1225 //
1226 
1228 {
1229  Q_UNUSED( parent )
1230  int index = mIndex;
1231 
1232  if ( index < 0 )
1233  {
1234  // have not yet found field index - first check explicitly set fields collection
1235  if ( context && context->hasVariable( QgsExpressionContext::EXPR_FIELDS ) )
1236  {
1237  QgsFields fields = qvariant_cast<QgsFields>( context->variable( QgsExpressionContext::EXPR_FIELDS ) );
1238  index = fields.lookupField( mName );
1239  }
1240  }
1241 
1242  if ( context )
1243  {
1244  QgsFeature feature = context->feature();
1245  if ( feature.isValid() )
1246  {
1247  if ( index >= 0 )
1248  return feature.attribute( index );
1249  else
1250  return feature.attribute( mName );
1251  }
1252  }
1253  return QVariant( '[' + mName + ']' );
1254 }
1255 
1257 {
1258  return ntColumnRef;
1259 }
1260 
1262 {
1263  if ( !context || !context->hasVariable( QgsExpressionContext::EXPR_FIELDS ) )
1264  return false;
1265 
1266  QgsFields fields = qvariant_cast<QgsFields>( context->variable( QgsExpressionContext::EXPR_FIELDS ) );
1267 
1268  mIndex = fields.lookupField( mName );
1269 
1270  if ( mIndex == -1 && context->hasFeature() )
1271  {
1272  mIndex = context->feature().fieldNameIndex( mName );
1273  }
1274 
1275  if ( mIndex == -1 )
1276  {
1277  parent->setEvalErrorString( tr( "Column '%1' not found" ).arg( mName ) );
1278  return false;
1279  }
1280  return true;
1281 }
1282 
1284 {
1285  return QRegExp( "^[A-Za-z_\x80-\xff][A-Za-z0-9_\x80-\xff]*$" ).exactMatch( mName ) ? mName : QgsExpression::quotedColumnRef( mName );
1286 }
1287 
1289 {
1290  return QSet<QString>() << mName;
1291 }
1292 
1294 {
1295  return QSet<QString>();
1296 }
1297 
1299 {
1300  return QSet<QString>();
1301 }
1302 
1303 QList<const QgsExpressionNode *> QgsExpressionNodeColumnRef::nodes() const
1304 {
1305  QList<const QgsExpressionNode *> result;
1306  result << this;
1307  return result;
1308 }
1309 
1311 {
1312  return false;
1313 }
1314 
1316 {
1318  cloneTo( copy );
1319  return copy;
1320 }
1321 
1323 {
1324  Q_UNUSED( context )
1325  Q_UNUSED( parent )
1326  return false;
1327 }
1328 
1329 //
1330 
1332  : mConditions( *conditions )
1333  , mElseExp( elseExp )
1334 {
1335  delete conditions;
1336 }
1337 
1339 {
1340  delete mElseExp;
1341  qDeleteAll( mConditions );
1342 }
1343 
1345 {
1346  return ntCondition;
1347 }
1348 
1350 {
1351  for ( WhenThen *cond : qgis::as_const( mConditions ) )
1352  {
1353  QVariant vWhen = cond->mWhenExp->eval( parent, context );
1354  QgsExpressionUtils::TVL tvl = QgsExpressionUtils::getTVLValue( vWhen, parent );
1356  if ( tvl == QgsExpressionUtils::True )
1357  {
1358  QVariant vRes = cond->mThenExp->eval( parent, context );
1360  return vRes;
1361  }
1362  }
1363 
1364  if ( mElseExp )
1365  {
1366  QVariant vElse = mElseExp->eval( parent, context );
1368  return vElse;
1369  }
1370 
1371  // return NULL if no condition is matching
1372  return QVariant();
1373 }
1374 
1376 {
1377  bool res;
1378  for ( WhenThen *cond : qgis::as_const( mConditions ) )
1379  {
1380  res = cond->mWhenExp->prepare( parent, context )
1381  & cond->mThenExp->prepare( parent, context );
1382  if ( !res )
1383  return false;
1384  }
1385 
1386  if ( mElseExp )
1387  return mElseExp->prepare( parent, context );
1388 
1389  return true;
1390 }
1391 
1393 {
1394  QString msg( QStringLiteral( "CASE" ) );
1395  for ( WhenThen *cond : mConditions )
1396  {
1397  msg += QStringLiteral( " WHEN %1 THEN %2" ).arg( cond->mWhenExp->dump(), cond->mThenExp->dump() );
1398  }
1399  if ( mElseExp )
1400  msg += QStringLiteral( " ELSE %1" ).arg( mElseExp->dump() );
1401  msg += QStringLiteral( " END" );
1402  return msg;
1403 }
1404 
1406 {
1407  QSet<QString> lst;
1408  for ( WhenThen *cond : mConditions )
1409  {
1410  lst += cond->mWhenExp->referencedColumns() + cond->mThenExp->referencedColumns();
1411  }
1412 
1413  if ( mElseExp )
1414  lst += mElseExp->referencedColumns();
1415 
1416  return lst;
1417 }
1418 
1420 {
1421  QSet<QString> lst;
1422  for ( WhenThen *cond : mConditions )
1423  {
1424  lst += cond->mWhenExp->referencedVariables() + cond->mThenExp->referencedVariables();
1425  }
1426 
1427  if ( mElseExp )
1428  lst += mElseExp->referencedVariables();
1429 
1430  return lst;
1431 }
1432 
1434 {
1435  QSet<QString> lst;
1436  for ( WhenThen *cond : mConditions )
1437  {
1438  lst += cond->mWhenExp->referencedFunctions() + cond->mThenExp->referencedFunctions();
1439  }
1440 
1441  if ( mElseExp )
1442  lst += mElseExp->referencedFunctions();
1443 
1444  return lst;
1445 }
1446 
1447 QList<const QgsExpressionNode *> QgsExpressionNodeCondition::nodes() const
1448 {
1449  QList<const QgsExpressionNode *> lst;
1450  lst << this;
1451  for ( WhenThen *cond : mConditions )
1452  {
1453  lst += cond->mWhenExp->nodes() + cond->mThenExp->nodes();
1454  }
1455 
1456  if ( mElseExp )
1457  lst += mElseExp->nodes();
1458 
1459  return lst;
1460 }
1461 
1463 {
1464  for ( WhenThen *cond : mConditions )
1465  {
1466  if ( cond->mWhenExp->needsGeometry() ||
1467  cond->mThenExp->needsGeometry() )
1468  return true;
1469  }
1470 
1471  return mElseExp && mElseExp->needsGeometry();
1472 }
1473 
1475 {
1477  for ( WhenThen *wt : mConditions )
1478  conditions.append( wt->clone() );
1479 
1480  QgsExpressionNodeCondition *copy = new QgsExpressionNodeCondition( conditions, mElseExp ? mElseExp->clone() : nullptr );
1481  cloneTo( copy );
1482  return copy;
1483 }
1484 
1486 {
1487  for ( WhenThen *wt : mConditions )
1488  {
1489  if ( !wt->mWhenExp->isStatic( parent, context ) || !wt->mThenExp->isStatic( parent, context ) )
1490  return false;
1491  }
1492 
1493  if ( mElseExp )
1494  return mElseExp->isStatic( parent, context );
1495 
1496  return true;
1497 }
1498 
1500 {
1501  QSet<QString> lst( mNode->referencedColumns() );
1502  const QList< QgsExpressionNode * > nodeList = mList->list();
1503  for ( const QgsExpressionNode *n : nodeList )
1504  lst.unite( n->referencedColumns() );
1505  return lst;
1506 }
1507 
1509 {
1510  QSet<QString> lst( mNode->referencedVariables() );
1511  const QList< QgsExpressionNode * > nodeList = mList->list();
1512  for ( const QgsExpressionNode *n : nodeList )
1513  lst.unite( n->referencedVariables() );
1514  return lst;
1515 }
1516 
1518 {
1519  QSet<QString> lst( mNode->referencedFunctions() );
1520  const QList< QgsExpressionNode * > nodeList = mList->list();
1521  for ( const QgsExpressionNode *n : nodeList )
1522  lst.unite( n->referencedFunctions() );
1523  return lst;
1524 }
1525 
1526 QList<const QgsExpressionNode *> QgsExpressionNodeInOperator::nodes() const
1527 {
1528  QList<const QgsExpressionNode *> lst;
1529  lst << this;
1530  const QList< QgsExpressionNode * > nodeList = mList->list();
1531  for ( const QgsExpressionNode *n : nodeList )
1532  lst += n->nodes();
1533  return lst;
1534 }
1535 
1537  : mWhenExp( whenExp )
1538  , mThenExp( thenExp )
1539 {
1540 }
1541 
1543 {
1544  delete mWhenExp;
1545  delete mThenExp;
1546 }
1547 
1549 {
1550  return new WhenThen( mWhenExp->clone(), mThenExp->clone() );
1551 }
1552 
1554 {
1555  return BINARY_OPERATOR_TEXT[mOp];
1556 }
1557 
1558 //
1559 
1561 {
1562  const QVariant container = mContainer->eval( parent, context );
1564  const QVariant index = mIndex->eval( parent, context );
1566 
1567  switch ( container.type() )
1568  {
1569  case QVariant::Map:
1570  return QgsExpressionUtils::getMapValue( container, parent ).value( index.toString() );
1571 
1572  case QVariant::List:
1573  case QVariant::StringList:
1574  {
1575  const QVariantList list = QgsExpressionUtils::getListValue( container, parent );
1576  qlonglong pos = QgsExpressionUtils::getIntValue( index, parent );
1577  if ( pos >= list.length() || pos < -list.length() )
1578  {
1579  return QVariant();
1580  }
1581  if ( pos < 0 )
1582  {
1583  // negative indices are from back of list
1584  pos += list.length();
1585  }
1586 
1587  return list.at( pos );
1588  }
1589 
1590  default:
1591  parent->setEvalErrorString( tr( "[] can only be used with map or array values, not %1" ).arg( QMetaType::typeName( container.type() ) ) );
1592  return QVariant();
1593  }
1594 }
1595 
1597 {
1598  return ntIndexOperator;
1599 }
1600 
1602 {
1603  bool resC = mContainer->prepare( parent, context );
1604  bool resV = mIndex->prepare( parent, context );
1605  return resC && resV;
1606 }
1607 
1609 {
1610  return QStringLiteral( "%1[%2]" ).arg( mContainer->dump(), mIndex->dump() );
1611 }
1612 
1614 {
1615  return mContainer->referencedColumns() + mIndex->referencedColumns();
1616 }
1617 
1619 {
1620  return mContainer->referencedVariables() + mIndex->referencedVariables();
1621 }
1622 
1624 {
1625  return mContainer->referencedFunctions() + mIndex->referencedFunctions();
1626 }
1627 
1628 QList<const QgsExpressionNode *> QgsExpressionNodeIndexOperator::nodes() const
1629 {
1630  QList<const QgsExpressionNode *> lst;
1631  lst << this;
1632  lst += mContainer->nodes() + mIndex->nodes();
1633  return lst;
1634 }
1635 
1637 {
1638  return mContainer->needsGeometry() || mIndex->needsGeometry();
1639 }
1640 
1642 {
1643  QgsExpressionNodeIndexOperator *copy = new QgsExpressionNodeIndexOperator( mContainer->clone(), mIndex->clone() );
1644  cloneTo( copy );
1645  return copy;
1646 }
1647 
1649 {
1650  return mContainer->isStatic( parent, context ) && mIndex->isStatic( parent, context );
1651 }
int lookupField(const QString &fieldName) const
Looks up field&#39;s index from the field name.
Definition: qgsfields.cpp:324
void cloneTo(QgsExpressionNode *target) const
Copies the members of this node to the node provided in target.
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:183
Class for parsing and evaluation of expressions (formerly called "search strings").
QStringList names() const
Returns a list of names for nodes.
QgsExpressionNode * node
Node.
virtual QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)
Evaluates the function, first evaluating all required arguments before passing them to the function&#39;s...
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
bool prepare(QgsExpression *parent, const QgsExpressionContext *context)
Prepare this node for evaluation.
QgsExpressionNodeFunction(int fnIndex, QgsExpressionNode::NodeList *args)
A function node consists of an index of the function in the global function array and a list of argum...
virtual QString dump() const =0
Dump this node into a serialized (part) of an expression.
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const override
Returns true if this node can be evaluated for a static value.
QList< const QgsExpressionNode * > nodes() const override
Returns a list of all nodes which are used in this expression.
QSet< QString > referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node...
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
QgsExpressionNodeCondition(QgsExpressionNodeCondition::WhenThenList *conditions, QgsExpressionNode *elseExp=nullptr)
Create a new node with the given list of conditions and an optional elseExp expression.
int params() const
The number of parameters this function takes.
bool prepareNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual preparation method Errors are reported to the parent.
int precedence() const
Returns the precedence index for the operator.
QVariant evalNode(QgsExpression *parent, const QgsExpressionContext *context) override
Abstract virtual eval method Errors are reported to the parent.
bool hasFunction(const QString &name) const
Checks whether a specified function is contained in the context.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
QSet< QString > referencedFunctions() const override
Returns a set of all functions which are used in this expression.
WhenThenList conditions() const
The list of WHEN THEN expression parts of the expression.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h: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.