QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
qgsexpression.h
Go to the documentation of this file.
1 /***************************************************************************
2  qgsexpression.h
3  -------------------
4  begin : August 2011
5  copyright : (C) 2011 Martin Dobias
6  email : wonder.sk at gmail dot com
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 #ifndef QGSEXPRESSION_H
17 #define QGSEXPRESSION_H
18 
19 #include <QMetaType>
20 #include <QStringList>
21 #include <QVariant>
22 #include <QList>
23 #include <QDomDocument>
24 #include <QCoreApplication>
25 #include <QSet>
26 
27 #include "qgis.h"
28 #include "qgsunittypes.h"
29 #include "qgsinterval.h"
30 
31 class QgsFeature;
32 class QgsGeometry;
33 class QgsOgcUtils;
34 class QgsVectorLayer;
36 class QgsField;
37 class QgsFields;
38 class QgsDistanceArea;
39 class QDomElement;
41 class QgsExpressionPrivate;
42 
109 class CORE_EXPORT QgsExpression
110 {
111  Q_DECLARE_TR_FUNCTIONS( QgsExpression )
112  public:
119  QgsExpression( const QString& expr );
120 
126  QgsExpression( const QgsExpression& other );
127 
133  QgsExpression& operator=( const QgsExpression& other );
134 
140  QgsExpression();
141 
142  ~QgsExpression();
143 
150  bool operator==( const QgsExpression& other ) const;
151 
158  bool isValid() const;
159 
161  bool hasParserError() const;
163  QString parserErrorString() const;
164 
165  class Node;
166 
168  const Node* rootNode() const;
169 
172  Q_DECL_DEPRECATED bool prepare( const QgsFields &fields );
173 
178  bool prepare( const QgsExpressionContext *context );
179 
189  QStringList referencedColumns() const;
190 
192  bool needsGeometry() const;
193 
194  // evaluation
195 
199  Q_DECL_DEPRECATED QVariant evaluate( const QgsFeature* f );
200 
205  Q_DECL_DEPRECATED QVariant evaluate( const QgsFeature& f );
206 
210  Q_DECL_DEPRECATED QVariant evaluate( const QgsFeature* f, const QgsFields& fields );
211 
216  Q_DECL_DEPRECATED QVariant evaluate( const QgsFeature& f, const QgsFields& fields );
217 
222  QVariant evaluate();
223 
229  QVariant evaluate( const QgsExpressionContext* context );
230 
232  bool hasEvalError() const;
234  QString evalErrorString() const;
236  void setEvalErrorString( const QString& str );
237 
240  Q_DECL_DEPRECATED void setCurrentRowNumber( int rowNumber );
243  Q_DECL_DEPRECATED int currentRowNumber(); //TODO QGIS 3.0: make the following methods private. They are still required for replaceExpressionText
244  //but should not be publicly used
248  Q_DECL_DEPRECATED static void setSpecialColumn( const QString& name, const QVariant& value );
252  Q_DECL_DEPRECATED static void unsetSpecialColumn( const QString& name );
256  Q_DECL_DEPRECATED static QVariant specialColumn( const QString& name );
257 
261  static bool hasSpecialColumn( const QString& name );
262 
266  bool isField() const { return rootNode() && dynamic_cast<const NodeColumnRef*>( rootNode() ) ;}
267 
269  Q_DECL_DEPRECATED static bool isValid( const QString& text, const QgsFields& fields, QString &errorMessage );
270 
278  static bool isValid( const QString& text, const QgsExpressionContext* context, QString &errorMessage );
279 
285  void setExpression( const QString& expression );
286 
287  void setScale( double scale );
288 
289  double scale();
290 
294  QString expression() const;
295 
300  QString dump() const;
301 
308  QgsDistanceArea *geomCalculator();
309 
316  //TODO QGIS 3.0 change calc to a pointer, so that calculator can be cleared by passing nullptr
317  void setGeomCalculator( const QgsDistanceArea &calc );
318 
325  QGis::UnitType distanceUnits() const;
326 
333  void setDistanceUnits( QGis::UnitType unit );
334 
341  QgsUnitTypes::AreaUnit areaUnits() const;
342 
349  void setAreaUnits( QgsUnitTypes::AreaUnit unit );
350 
364  Q_DECL_DEPRECATED static QString replaceExpressionText( const QString &action, const QgsFeature *feat,
365  QgsVectorLayer *layer,
366  const QMap<QString, QVariant> *substitutionMap = nullptr,
367  const QgsDistanceArea* distanceArea = nullptr );
368 
380  static QString replaceExpressionText( const QString &action, const QgsExpressionContext* context,
381  const QMap<QString, QVariant> *substitutionMap = nullptr,
382  const QgsDistanceArea* distanceArea = nullptr );
383 
393  static double evaluateToDouble( const QString& text, const double fallbackValue );
394 
400  {
403  };
404 
410  {
411  // logical
414 
415  // comparison
416  boEQ, // =
417  boNE, // <>
418  boLE, // <=
419  boGE, // >=
420  boLT, // <
421  boGT, // >
429 
430  // math
438 
439  // strings
441  };
442 
444  {
454  };
455 
457  static const char* BinaryOperatorText[];
458 
460  static const char* UnaryOperatorText[];
461 
466  class CORE_EXPORT Parameter
467  {
468  public:
469 
475  Parameter( const QString& name,
476  bool optional = false,
477  const QVariant& defaultValue = QVariant() )
478  : mName( name )
479  , mOptional( optional )
480  , mDefaultValue( defaultValue )
481  {}
482 
484  QString name() const { return mName; }
485 
487  bool optional() const { return mOptional; }
488 
490  QVariant defaultValue() const { return mDefaultValue; }
491 
492  bool operator==( const Parameter& other ) const
493  {
494  return ( QString::compare( mName, other.mName, Qt::CaseInsensitive ) == 0 );
495  }
496 
497  private:
498  QString mName;
499  bool mOptional;
500  QVariant mDefaultValue;
501  };
502 
505 
507  typedef QVariant( *FcnEval )( const QVariantList& values, const QgsFeature* f, QgsExpression* parent );
508 
511  typedef QVariant( *FcnEvalContext )( const QVariantList& values, const QgsExpressionContext* context, QgsExpression* parent );
512 
516  class CORE_EXPORT Function
517  {
518  public:
519 
521  Function( const QString& fnname,
522  int params,
523  const QString& group,
524  const QString& helpText = QString(),
525  bool usesGeometry = false,
526  const QStringList& referencedColumns = QStringList(),
527  bool lazyEval = false,
528  bool handlesNull = false,
529  bool isContextual = false )
530  : mName( fnname )
531  , mParams( params )
532  , mUsesGeometry( usesGeometry )
533  , mGroups( group.isEmpty() ? QStringList() : QStringList() << group )
534  , mHelpText( helpText )
535  , mReferencedColumns( referencedColumns )
536  , mLazyEval( lazyEval )
537  , mHandlesNull( handlesNull )
538  , mIsContextual( isContextual )
539  {
540  }
541 
545  Function( const QString& fnname,
546  int params,
547  const QStringList& groups,
548  const QString& helpText = QString(),
549  bool usesGeometry = false,
550  const QStringList& referencedColumns = QStringList(),
551  bool lazyEval = false,
552  bool handlesNull = false,
553  bool isContextual = false )
554  : mName( fnname )
555  , mParams( params )
556  , mUsesGeometry( usesGeometry )
557  , mGroups( groups )
558  , mHelpText( helpText )
559  , mReferencedColumns( referencedColumns )
560  , mLazyEval( lazyEval )
561  , mHandlesNull( handlesNull )
562  , mIsContextual( isContextual )
563  {
564  }
565 
569  Function( const QString& fnname,
570  const ParameterList& params,
571  const QString& group,
572  const QString& helpText = QString(),
573  bool usesGeometry = false,
574  const QStringList& referencedColumns = QStringList(),
575  bool lazyEval = false,
576  bool handlesNull = false,
577  bool isContextual = false )
578  : mName( fnname )
579  , mParams( 0 )
580  , mParameterList( params )
581  , mUsesGeometry( usesGeometry )
582  , mGroups( group.isEmpty() ? QStringList() : QStringList() << group )
583  , mHelpText( helpText )
584  , mReferencedColumns( referencedColumns )
585  , mLazyEval( lazyEval )
586  , mHandlesNull( handlesNull )
587  , mIsContextual( isContextual )
588  {}
589 
593  Function( const QString& fnname,
594  const ParameterList& params,
595  const QStringList& groups,
596  const QString& helpText = QString(),
597  bool usesGeometry = false,
598  const QStringList& referencedColumns = QStringList(),
599  bool lazyEval = false,
600  bool handlesNull = false,
601  bool isContextual = false )
602  : mName( fnname )
603  , mParams( 0 )
604  , mParameterList( params )
605  , mUsesGeometry( usesGeometry )
606  , mGroups( groups )
607  , mHelpText( helpText )
608  , mReferencedColumns( referencedColumns )
609  , mLazyEval( lazyEval )
610  , mHandlesNull( handlesNull )
611  , mIsContextual( isContextual )
612  {}
613 
614 
615  virtual ~Function() {}
616 
618  QString name() const { return mName; }
619 
621  int params() const { return mParameterList.isEmpty() ? mParams : mParameterList.count(); }
622 
624  int minParams() const
625  {
626  if ( mParameterList.isEmpty() )
627  return mParams;
628 
629  int min = 0;
630  Q_FOREACH ( const Parameter& param, mParameterList )
631  {
632  if ( !param.optional() )
633  min++;
634  }
635  return min;
636  }
637 
641  const ParameterList& parameters() const { return mParameterList; }
642 
644  //TODO QGIS 3.0 - rename to usesGeometry()
645  bool usesgeometry() const { return mUsesGeometry; }
646 
652  virtual QStringList aliases() const { return QStringList(); }
653 
658  bool lazyEval() const { return mLazyEval; }
659 
660  virtual QStringList referencedColumns() const { return mReferencedColumns; }
661 
665  bool isContextual() const { return mIsContextual; }
666 
671  virtual bool isDeprecated() const { return mGroups.isEmpty() ? false : mGroups.contains( "deprecated" ); }
672 
676  QString group() const { return mGroups.isEmpty() ? QString() : mGroups.at( 0 ); }
677 
682  QStringList groups() const { return mGroups; }
683 
685  //TODO QGIS 3.0 - rename to helpText()
686  const QString helptext() const { return mHelpText.isEmpty() ? QgsExpression::helptext( mName ) : mHelpText; }
687 
689  Q_DECL_DEPRECATED virtual QVariant func( const QVariantList&, const QgsFeature*, QgsExpression* );
690 
698  //TODO QGIS 3.0 - rename python method
699  virtual QVariant func( const QVariantList& values, const QgsExpressionContext* context, QgsExpression* parent );
700 
701  bool operator==( const Function& other ) const
702  {
703  if ( QString::compare( mName, other.mName, Qt::CaseInsensitive ) == 0 )
704  return true;
705 
706  return false;
707  }
708 
709  virtual bool handlesNull() const { return mHandlesNull; }
710 
711  private:
712  QString mName;
713  int mParams;
714  ParameterList mParameterList;
715  bool mUsesGeometry;
716  QStringList mGroups;
717  QString mHelpText;
718  QStringList mReferencedColumns;
719  bool mLazyEval;
720  bool mHandlesNull;
721  bool mIsContextual; //if true function is only available through an expression context
722  };
723 
728  class StaticFunction : public Function
729  {
730  public:
732  Q_DECL_DEPRECATED StaticFunction( const QString& fnname,
733  int params,
734  FcnEval fcn,
735  const QString& group,
736  const QString& helpText = QString(),
737  bool usesGeometry = false,
738  const QStringList& referencedColumns = QStringList(),
739  bool lazyEval = false,
740  const QStringList& aliases = QStringList(),
741  bool handlesNull = false )
742  : Function( fnname, params, group, helpText, usesGeometry, referencedColumns, lazyEval, handlesNull )
743  , mFnc( fcn )
744  , mContextFnc( nullptr )
745  , mAliases( aliases )
746  {}
747 
748  virtual ~StaticFunction() {}
749 
752  StaticFunction( const QString& fnname,
753  int params,
754  FcnEvalContext fcn,
755  const QString& group,
756  const QString& helpText = QString(),
757  bool usesGeometry = false,
758  const QStringList& referencedColumns = QStringList(),
759  bool lazyEval = false,
760  const QStringList& aliases = QStringList(),
761  bool handlesNull = false )
762  : Function( fnname, params, group, helpText, usesGeometry, referencedColumns, lazyEval, handlesNull )
763  , mFnc( nullptr )
764  , mContextFnc( fcn )
765  , mAliases( aliases )
766  {}
767 
770  StaticFunction( const QString& fnname,
771  const ParameterList& params,
772  FcnEvalContext fcn,
773  const QString& group,
774  const QString& helpText = QString(),
775  bool usesGeometry = false,
776  const QStringList& referencedColumns = QStringList(),
777  bool lazyEval = false,
778  const QStringList& aliases = QStringList(),
779  bool handlesNull = false )
780  : Function( fnname, params, group, helpText, usesGeometry, referencedColumns, lazyEval, handlesNull )
781  , mFnc( nullptr )
782  , mContextFnc( fcn )
783  , mAliases( aliases )
784  {}
785 
789  StaticFunction( const QString& fnname,
790  const ParameterList& params,
791  FcnEvalContext fcn,
792  const QStringList& groups,
793  const QString& helpText = QString(),
794  bool usesGeometry = false,
795  const QStringList& referencedColumns = QStringList(),
796  bool lazyEval = false,
797  const QStringList& aliases = QStringList(),
798  bool handlesNull = false )
799  : Function( fnname, params, groups, helpText, usesGeometry, referencedColumns, lazyEval, handlesNull )
800  , mFnc( nullptr )
801  , mContextFnc( fcn )
802  , mAliases( aliases )
803  {}
804 
806  Q_DECL_DEPRECATED virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) override;
807 
814  virtual QVariant func( const QVariantList& values, const QgsExpressionContext* context, QgsExpression* parent ) override
815  {
816  return mContextFnc ? mContextFnc( values, context, parent ) : QVariant();
817  }
818 
819  virtual QStringList aliases() const override { return mAliases; }
820 
821  private:
822  FcnEval mFnc;
823  FcnEvalContext mContextFnc;
824  QStringList mAliases;
825  };
826 
829  static const QList<Function*>& Functions();
830 
833  static const QStringList& BuiltinFunctions();
834 
841  static bool registerFunction( Function* function, bool transferOwnership = false );
842 
847  static bool unregisterFunction( const QString& name );
848 
852 
856  static void cleanRegisteredFunctions();
857 
859  static bool isFunctionName( const QString& name );
860 
862  static int functionIndex( const QString& name );
863 
867  static int functionCount();
868 
872  static QList<Function*> specialColumns();
873 
878  static QString quotedColumnRef( QString name );
879 
884  static QString quotedString( QString text );
885 
893  static QString quotedValue( const QVariant& value );
894 
903  static QString quotedValue( const QVariant& value, QVariant::Type type );
904 
906 
907  class Visitor; // visitor interface is defined below
908 
909  enum NodeType
910  {
917  ntCondition
918  };
919 
922  class CORE_EXPORT Node
923  {
924  public:
925  virtual ~Node() {}
926 
932  virtual NodeType nodeType() const = 0;
933 
939  Q_DECL_DEPRECATED virtual QVariant eval( QgsExpression* parent, const QgsFeature* f );
940 
946  virtual QVariant eval( QgsExpression* parent, const QgsExpressionContext* context );
947 
953  Q_DECL_DEPRECATED virtual bool prepare( QgsExpression* parent, const QgsFields &fields );
954 
960  virtual bool prepare( QgsExpression* parent, const QgsExpressionContext* context );
961 
967  virtual QString dump() const = 0;
968 
977  virtual Node* clone() const = 0;
978 
989  virtual QStringList referencedColumns() const = 0;
990 
999  virtual bool needsGeometry() const = 0;
1000 
1016  virtual void accept( Visitor& v ) const = 0;
1017  };
1018 
1022  class CORE_EXPORT NamedNode
1023  {
1024  public:
1025 
1030  NamedNode( const QString& name, Node* node )
1031  : name( name )
1032  , node( node )
1033  {}
1034 
1037 
1040  };
1041 
1044  class CORE_EXPORT NodeList
1045  {
1046  public:
1047  NodeList() : mHasNamedNodes( false ) {}
1048  virtual ~NodeList() { qDeleteAll( mList ); }
1050  void append( Node* node ) { mList.append( node ); mNameList.append( QString() ); }
1051 
1055  void append( NamedNode* node ) { mList.append( node->node ); mNameList.append( node->name.toLower() ); mHasNamedNodes = true; delete node; }
1056 
1059  int count() const { return mList.count(); }
1060 
1063  bool hasNamedNodes() const { return mHasNamedNodes; }
1064 
1065  QList<Node*> list() { return mList; }
1066 
1069  QStringList names() const { return mNameList; }
1070 
1072  NodeList* clone() const;
1073 
1074  virtual QString dump() const;
1075 
1076  protected:
1079 
1080  private:
1081 
1082  bool mHasNamedNodes;
1083  };
1084 
1085  //TODO QGIS 3.0 - remove
1089 
1092  class CORE_EXPORT NodeUnaryOperator : public Node
1093  {
1094  public:
1096  : mOp( op )
1097  , mOperand( operand )
1098  {}
1099  ~NodeUnaryOperator() { delete mOperand; }
1100 
1101  UnaryOperator op() const { return mOp; }
1102  Node* operand() const { return mOperand; }
1103 
1104  virtual NodeType nodeType() const override { return ntUnaryOperator; }
1105  virtual bool prepare( QgsExpression* parent, const QgsExpressionContext* context ) override;
1106  virtual QVariant eval( QgsExpression* parent, const QgsExpressionContext* context ) override;
1107  virtual QString dump() const override;
1108 
1109  virtual QStringList referencedColumns() const override { return mOperand->referencedColumns(); }
1110  virtual bool needsGeometry() const override { return mOperand->needsGeometry(); }
1111  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
1112  virtual Node* clone() const override;
1113 
1114  protected:
1117  };
1118 
1121  class CORE_EXPORT NodeBinaryOperator : public Node
1122  {
1123  public:
1124  NodeBinaryOperator( BinaryOperator op, Node* opLeft, Node* opRight )
1125  : mOp( op )
1126  , mOpLeft( opLeft )
1127  , mOpRight( opRight )
1128  {}
1129  ~NodeBinaryOperator() { delete mOpLeft; delete mOpRight; }
1130 
1131  BinaryOperator op() const { return mOp; }
1132  Node* opLeft() const { return mOpLeft; }
1133  Node* opRight() const { return mOpRight; }
1134 
1135  virtual NodeType nodeType() const override { return ntBinaryOperator; }
1136  virtual bool prepare( QgsExpression* parent, const QgsExpressionContext* context ) override;
1137  virtual QVariant eval( QgsExpression* parent, const QgsExpressionContext* context ) override;
1138  virtual QString dump() const override;
1139 
1140  virtual QStringList referencedColumns() const override { return mOpLeft->referencedColumns() + mOpRight->referencedColumns(); }
1141  virtual bool needsGeometry() const override { return mOpLeft->needsGeometry() || mOpRight->needsGeometry(); }
1142  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
1143  virtual Node* clone() const override;
1144 
1145  int precedence() const;
1146  bool leftAssociative() const;
1147 
1148  protected:
1149  bool compare( double diff );
1150  int computeInt( int x, int y );
1151  double computeDouble( double x, double y );
1152 
1157  QDateTime computeDateTimeFromInterval( const QDateTime& d, QgsInterval* i );
1158 
1162  };
1163 
1166  class CORE_EXPORT NodeInOperator : public Node
1167  {
1168  public:
1169  NodeInOperator( Node* node, NodeList* list, bool notin = false )
1170  : mNode( node )
1171  , mList( list )
1172  , mNotIn( notin )
1173  {}
1174  virtual ~NodeInOperator() { delete mNode; delete mList; }
1175 
1176  Node* node() const { return mNode; }
1177  bool isNotIn() const { return mNotIn; }
1178  NodeList* list() const { return mList; }
1179 
1180  virtual NodeType nodeType() const override { return ntInOperator; }
1181  virtual bool prepare( QgsExpression* parent, const QgsExpressionContext* context ) override;
1182  virtual QVariant eval( QgsExpression* parent, const QgsExpressionContext* context ) override;
1183  virtual QString dump() const override;
1184 
1185  virtual QStringList referencedColumns() const override { QStringList lst( mNode->referencedColumns() ); Q_FOREACH ( const Node* n, mList->list() ) lst.append( n->referencedColumns() ); return lst; }
1186  virtual bool needsGeometry() const override { bool needs = false; Q_FOREACH ( Node* n, mList->list() ) needs |= n->needsGeometry(); return needs; }
1187  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
1188  virtual Node* clone() const override;
1189 
1190  protected:
1193  bool mNotIn;
1194  };
1195 
1198  class CORE_EXPORT NodeFunction : public Node
1199  {
1200  public:
1201  NodeFunction( int fnIndex, NodeList* args ) : mFnIndex( fnIndex )
1202  {
1203  const ParameterList& functionParams = Functions()[mFnIndex]->parameters();
1204  if ( !args || !args->hasNamedNodes() || functionParams.isEmpty() )
1205  {
1206  // no named parameters, or function does not support them
1207  mArgs = args;
1208  }
1209  else
1210  {
1211  mArgs = new NodeList();
1212 
1213  int idx = 0;
1214  //first loop through unnamed arguments
1215  while ( args->names().at( idx ).isEmpty() )
1216  {
1217  mArgs->append( args->list().at( idx )->clone() );
1218  idx++;
1219  }
1220 
1221  //next copy named parameters in order expected by function
1222  for ( ; idx < functionParams.count(); ++idx )
1223  {
1224  int nodeIdx = args->names().indexOf( functionParams.at( idx ).name().toLower() );
1225  if ( nodeIdx < 0 )
1226  {
1227  //parameter not found - insert default value for parameter
1228  mArgs->append( new NodeLiteral( functionParams.at( idx ).defaultValue() ) );
1229  }
1230  else
1231  {
1232  mArgs->append( args->list().at( nodeIdx )->clone() );
1233  }
1234  }
1235 
1236  delete args;
1237  }
1238  }
1239 
1240  virtual ~NodeFunction() { delete mArgs; }
1241 
1242  int fnIndex() const { return mFnIndex; }
1243  NodeList* args() const { return mArgs; }
1244 
1245  virtual NodeType nodeType() const override { return ntFunction; }
1246  virtual bool prepare( QgsExpression* parent, const QgsExpressionContext* context ) override;
1247  virtual QVariant eval( QgsExpression* parent, const QgsExpressionContext* context ) override;
1248  virtual QString dump() const override;
1249 
1250  virtual QStringList referencedColumns() const override;
1251  virtual bool needsGeometry() const override { bool needs = Functions()[mFnIndex]->usesgeometry(); if ( mArgs ) { Q_FOREACH ( Node* n, mArgs->list() ) needs |= n->needsGeometry(); } return needs; }
1252  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
1253  virtual Node* clone() const override;
1254 
1256  static bool validateParams( int fnIndex, NodeList* args, QString& error )
1257  {
1258  if ( !args || !args->hasNamedNodes() )
1259  return true;
1260 
1261  const ParameterList& functionParams = Functions()[fnIndex]->parameters();
1262  if ( functionParams.isEmpty() )
1263  {
1264  error = QString( "%1 does not supported named parameters" ).arg( Functions()[fnIndex]->name() );
1265  return false;
1266  }
1267  else
1268  {
1269  QSet< int > providedArgs;
1270  QSet< int > handledArgs;
1271  int idx = 0;
1272  //first loop through unnamed arguments
1273  while ( args->names().at( idx ).isEmpty() )
1274  {
1275  providedArgs << idx;
1276  handledArgs << idx;
1277  idx++;
1278  }
1279 
1280  //next check named parameters
1281  for ( ; idx < functionParams.count(); ++idx )
1282  {
1283  int nodeIdx = args->names().indexOf( functionParams.at( idx ).name().toLower() );
1284  if ( nodeIdx < 0 )
1285  {
1286  if ( !functionParams.at( idx ).optional() )
1287  {
1288  error = QString( "No value specified for parameter '%1' for %2" ).arg( functionParams.at( idx ).name(), Functions()[fnIndex]->name() );
1289  return false;
1290  }
1291  }
1292  else
1293  {
1294  if ( providedArgs.contains( idx ) )
1295  {
1296  error = QString( "Duplicate parameter specified for '%1' for %2" ).arg( functionParams.at( idx ).name(), Functions()[fnIndex]->name() );
1297  return false;
1298  }
1299  }
1300  providedArgs << idx;
1301  handledArgs << nodeIdx;
1302  }
1303 
1304  //last check for bad names
1305  idx = 0;
1306  Q_FOREACH ( const QString& name, args->names() )
1307  {
1308  if ( !name.isEmpty() && !functionParams.contains( name ) )
1309  {
1310  error = QString( "Invalid parameter name '%1' for %2" ).arg( name, Functions()[fnIndex]->name() );
1311  return false;
1312  }
1313  if ( !name.isEmpty() && !handledArgs.contains( idx ) )
1314  {
1315  int functionIdx = functionParams.indexOf( name );
1316  if ( providedArgs.contains( functionIdx ) )
1317  {
1318  error = QString( "Duplicate parameter specified for '%1' for %2" ).arg( functionParams.at( functionIdx ).name(), Functions()[fnIndex]->name() );
1319  return false;
1320  }
1321  }
1322  idx++;
1323  }
1324 
1325  }
1326  return true;
1327  }
1328 
1329  protected:
1332 
1333  };
1334 
1337  class CORE_EXPORT NodeLiteral : public Node
1338  {
1339  public:
1340  NodeLiteral( const QVariant& value )
1341  : mValue( value )
1342  {}
1343 
1345  inline QVariant value() const { return mValue; }
1346 
1347  virtual NodeType nodeType() const override { return ntLiteral; }
1348  virtual bool prepare( QgsExpression* parent, const QgsExpressionContext* context ) override;
1349  virtual QVariant eval( QgsExpression* parent, const QgsExpressionContext* context ) override;
1350  virtual QString dump() const override;
1351 
1352  virtual QStringList referencedColumns() const override { return QStringList(); }
1353  virtual bool needsGeometry() const override { return false; }
1354  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
1355  virtual Node* clone() const override;
1356 
1357  protected:
1359  };
1360 
1363  class CORE_EXPORT NodeColumnRef : public Node
1364  {
1365  public:
1366  NodeColumnRef( const QString& name )
1367  : mName( name )
1368  , mIndex( -1 )
1369  {}
1370 
1372  QString name() const { return mName; }
1373 
1374  virtual NodeType nodeType() const override { return ntColumnRef; }
1375  virtual bool prepare( QgsExpression* parent, const QgsExpressionContext* context ) override;
1376  virtual QVariant eval( QgsExpression* parent, const QgsExpressionContext* context ) override;
1377  virtual QString dump() const override;
1378 
1379  virtual QStringList referencedColumns() const override { return QStringList( mName ); }
1380  virtual bool needsGeometry() const override { return false; }
1381 
1382  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
1383  virtual Node* clone() const override;
1384 
1385  protected:
1387  int mIndex;
1388  };
1389 
1392  class CORE_EXPORT WhenThen
1393  {
1394  public:
1395  WhenThen( Node* whenExp, Node* thenExp )
1396  : mWhenExp( whenExp )
1397  , mThenExp( thenExp )
1398  {}
1399  ~WhenThen() { delete mWhenExp; delete mThenExp; }
1400 
1401  // protected:
1404 
1405  private:
1406  WhenThen( const WhenThen& rh );
1407  WhenThen& operator=( const WhenThen& rh );
1408  };
1410 
1413  class CORE_EXPORT NodeCondition : public Node
1414  {
1415  public:
1416  NodeCondition( WhenThenList* conditions, Node* elseExp = nullptr )
1417  : mConditions( *conditions )
1418  , mElseExp( elseExp )
1419  { delete conditions; }
1420  NodeCondition( const WhenThenList& conditions, Node* elseExp = nullptr )
1421  : mConditions( conditions )
1422  , mElseExp( elseExp )
1423  {}
1424  ~NodeCondition() { delete mElseExp; qDeleteAll( mConditions ); }
1425 
1426  virtual NodeType nodeType() const override { return ntCondition; }
1427  virtual QVariant eval( QgsExpression* parent, const QgsExpressionContext* context ) override;
1428  virtual bool prepare( QgsExpression* parent, const QgsExpressionContext* context ) override;
1429  virtual QString dump() const override;
1430 
1431  virtual QStringList referencedColumns() const override;
1432  virtual bool needsGeometry() const override;
1433  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
1434  virtual Node* clone() const override;
1435 
1436  protected:
1437  WhenThenList mConditions;
1439  };
1440 
1442 
1447  class CORE_EXPORT Visitor
1448  {
1449  public:
1450  virtual ~Visitor() {}
1451  virtual void visit( const NodeUnaryOperator& n ) = 0;
1452  virtual void visit( const NodeBinaryOperator& n ) = 0;
1453  virtual void visit( const NodeInOperator& n ) = 0;
1454  virtual void visit( const NodeFunction& n ) = 0;
1455  virtual void visit( const NodeLiteral& n ) = 0;
1456  virtual void visit( const NodeColumnRef& n ) = 0;
1457  virtual void visit( const NodeCondition& n ) = 0;
1458  };
1459 
1461  void acceptVisitor( Visitor& v ) const;
1462 
1467  static QString helptext( QString name );
1468 
1476  static QString variableHelpText( const QString& variableName, bool showValue = true, const QVariant& value = QVariant() );
1477 
1481  static QString group( const QString& group );
1482 
1489  static QString formatPreviewString( const QVariant& value );
1490 
1498  static QString createFieldEqualityExpression( const QString &fieldName, const QVariant &value );
1499 
1500  protected:
1501  void initGeomCalculator();
1502 
1505 
1506  struct HelpArg
1507  {
1508  HelpArg( const QString& arg, const QString& desc, bool descOnly = false, bool syntaxOnly = false,
1509  bool optional = false, const QString& defaultVal = QString() )
1510  : mArg( arg )
1511  , mDescription( desc )
1512  , mDescOnly( descOnly )
1513  , mSyntaxOnly( syntaxOnly )
1514  , mOptional( optional )
1515  , mDefaultVal( defaultVal )
1516  {}
1517 
1524  };
1525 
1527  {
1528  HelpExample( const QString& expression, const QString& returns, const QString& note = QString::null )
1529  : mExpression( expression )
1530  , mReturns( returns )
1531  , mNote( note )
1532  {}
1533 
1537  };
1538 
1540  {
1541  HelpVariant( const QString& name, const QString& description,
1542  const QList<HelpArg>& arguments = QList<HelpArg>(),
1543  bool variableLenArguments = false,
1544  const QList<HelpExample>& examples = QList<HelpExample>(),
1545  const QString& notes = QString::null )
1546  : mName( name )
1547  , mDescription( description )
1548  , mArguments( arguments )
1549  , mVariableLenArguments( variableLenArguments )
1550  , mExamples( examples )
1551  , mNotes( notes )
1552  {}
1553 
1560  };
1561 
1562  struct Help
1563  {
1564  Help() {}
1565 
1566  Help( const QString& name, const QString& type, const QString& description, const QList<HelpVariant>& variants )
1567  : mName( name )
1568  , mType( type )
1569  , mDescription( description )
1570  , mVariants( variants )
1571  {}
1572 
1577  };
1578 
1585  void detach();
1586 
1587  QgsExpressionPrivate* d;
1588 
1592 
1594  static void initFunctionHelp();
1596  static void initVariableHelp();
1597 
1598  friend class QgsOgcUtils;
1599 };
1600 
1601 
1603 
1605 
1606 #endif // QGSEXPRESSION_H
Class for parsing and evaluation of expressions (formerly called "search strings").
Function(const QString &fnname, const ParameterList &params, const QString &group, const QString &helpText=QString(), bool usesGeometry=false, const QStringList &referencedColumns=QStringList(), bool lazyEval=false, bool handlesNull=false, bool isContextual=false)
Constructor for function which uses named parameter list.
virtual QStringList referencedColumns() const =0
Abstract virtual method which returns a list of columns required to evaluate this node...
UnaryOperator
list of unary operators
virtual bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression...
const QString helptext() const
The help text for the function.
virtual QStringList referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node...
Parameter(const QString &name, bool optional=false, const QVariant &defaultValue=QVariant())
Constructor for Parameter.
Function(const QString &fnname, int params, const QString &group, const QString &helpText=QString(), bool usesGeometry=false, const QStringList &referencedColumns=QStringList(), bool lazyEval=false, bool handlesNull=false, bool isContextual=false)
Constructor for function which uses unnamed parameters.
virtual NodeType nodeType() const override
Abstract virtual that returns the type of this node.
A abstract base class for defining QgsExpression functions.
bool operator==(const QgsFeatureIterator &fi1, const QgsFeatureIterator &fi2)
Function(const QString &fnname, int params, const QStringList &groups, const QString &helpText=QString(), bool usesGeometry=false, const QStringList &referencedColumns=QStringList(), bool lazyEval=false, bool handlesNull=false, bool isContextual=false)
Constructor for function which uses unnamed parameters and group list.
virtual NodeType nodeType() const override
Abstract virtual that returns the type of this node.
NodeColumnRef(const QString &name)
static QString helptext(QString name)
Returns the help text for a specified function.
HelpArg(const QString &arg, const QString &desc, bool descOnly=false, bool syntaxOnly=false, bool optional=false, const QString &defaultVal=QString())
const T & at(int i) const
QgsInterval Interval
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:515
Q_DECLARE_METATYPE(QgsMimeDataUtils::UriList)
Q_DECL_DEPRECATED StaticFunction(const QString &fnname, int params, FcnEval fcn, const QString &group, const QString &helpText=QString(), bool usesGeometry=false, const QStringList &referencedColumns=QStringList(), bool lazyEval=false, const QStringList &aliases=QStringList(), bool handlesNull=false)
Container of fields for a vector layer.
Definition: qgsfield.h:252
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:76
int count() const
Returns the number of nodes in the list.
virtual QStringList referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node...
c++ helper class for defining QgsExpression functions.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:187
QList< HelpVariant > mVariants
QString name
Node name.
virtual NodeType nodeType() const override
Abstract virtual that returns the type of this node.
virtual void accept(Visitor &v) const override
Support the visitor pattern.
bool lazyEval() const
True if this function should use lazy evaluation.
QString name() const
Returns the name of the parameter.
QString group() const
Returns the first group which the function belongs to.
virtual bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression...
virtual bool handlesNull() const
NodeBinaryOperator(BinaryOperator op, Node *opLeft, Node *opRight)
virtual NodeType nodeType() const override
Abstract virtual that returns the type of this node.
int indexOf(const T &value, int from) const
virtual QStringList referencedColumns() const
bool operator==(const Parameter &other) const
NodeCondition(WhenThenList *conditions, Node *elseExp=nullptr)
QVariant defaultValue() const
Returns the default value for the parameter.
HelpVariant(const QString &name, const QString &description, const QList< HelpArg > &arguments=QList< HelpArg >(), bool variableLenArguments=false, const QList< HelpExample > &examples=QList< HelpExample >(), const QString &notes=QString::null)
static bool validateParams(int fnIndex, NodeList *args, QString &error)
Tests whether the provided argument list is valid for the matching function.
int count(const T &value) const
virtual QStringList referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node...
void append(const T &value)
QgsExpressionPrivate * d
QList< Parameter > ParameterList
List of parameters, used for function definition.
virtual void accept(Visitor &v) const override
Support the visitor pattern.
bool hasNamedNodes() const
Returns true if list contains any named nodes.
QStringList names() const
Returns a list of names for nodes.
static QHash< QString, QString > gGroups
bool isEmpty() const
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
bool isEmpty() const
virtual QVariant func(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent) override
Returns result of evaluating the function.
bool operator==(const Function &other) const
Represents a single parameter passed to a function.
NodeInOperator(Node *node, NodeList *list, bool notin=false)
QString name() const
The name of the function.
Help(const QString &name, const QString &type, const QString &description, const QList< HelpVariant > &variants)
static QHash< QString, QString > gVariableHelpTexts
bool isContextual() const
Returns whether the function is only available if provided by a QgsExpressionContext object...
QList< HelpArg > mArguments
static QList< Function * > gmFunctions
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:44
HelpExample(const QString &expression, const QString &returns, const QString &note=QString::null)
virtual void accept(Visitor &v) const override
Support the visitor pattern.
WhenThen(Node *whenExp, Node *thenExp)
QList< HelpExample > mExamples
StaticFunction(const QString &fnname, const ParameterList &params, FcnEvalContext fcn, const QString &group, const QString &helpText=QString(), bool usesGeometry=false, const QStringList &referencedColumns=QStringList(), bool lazyEval=false, const QStringList &aliases=QStringList(), bool handlesNull=false)
Static function for evaluation against a QgsExpressionContext, using a named list of parameter values...
NodeUnaryOperator(UnaryOperator op, Node *operand)
bool usesgeometry() const
Does this function use a geometry object.
QString toLower() const
StaticFunction(const QString &fnname, const ParameterList &params, FcnEvalContext fcn, const QStringList &groups, const QString &helpText=QString(), bool usesGeometry=false, const QStringList &referencedColumns=QStringList(), bool lazyEval=false, const QStringList &aliases=QStringList(), bool handlesNull=false)
Static function for evaluation against a QgsExpressionContext, using a named list of parameter values...
virtual void accept(Visitor &v) const override
Support the visitor pattern.
bool contains(const T &value) const
A representation of the interval between two datetime values.
Definition: qgsinterval.h:34
bool optional() const
Returns true if the parameter is optional.
bool contains(const T &value) const
virtual NodeType nodeType() const override
Abstract virtual that returns the type of this node.
virtual QStringList referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node...
virtual void accept(Visitor &v) const override
Support the visitor pattern.
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:516
NodeFunction(int fnIndex, NodeList *args)
General purpose distance and area calculator.
static QMap< QString, QString > gmSpecialColumnGroups
QString name() const
The name of the column.
virtual bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression...
virtual void accept(Visitor &v) const override
Support the visitor pattern.
static QHash< QString, Help > gFunctionHelpTexts
virtual NodeType nodeType() const override
Abstract virtual that returns the type of this node.
virtual bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression...
BinaryOperator
list of binary operators
QList< WhenThen * > WhenThenList
virtual void visit(const NodeUnaryOperator &n)=0
virtual QStringList aliases() const
Returns a list of possible aliases for the function.
QVariant value() const
The value of the literal.
NodeLiteral(const QVariant &value)
bool isField() const
Checks whether an expression consists only of a single field reference.
Support for visitor pattern - algorithms dealing with the expressions may be implemented without modi...
UnitType
Map units that qgis supports.
Definition: qgis.h:159
virtual bool needsGeometry() const =0
Abstract virtual method which returns if the geometry is required to evaluate this expression...
NamedNode(const QString &name, Node *node)
Constructor for NamedNode.
static QStringList gmBuiltinFunctions
virtual bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression...
int indexOf(const QRegExp &rx, int from) const
int params() const
The number of parameters this function takes.
void append(Node *node)
Takes ownership of the provided node.
virtual void accept(Visitor &v) const override
Support the visitor pattern.
int minParams() const
The mininum number of parameters this function takes.
double ANALYSIS_EXPORT min(double x, double y)
Returns the minimum of two doubles or the first argument if both are equal.
virtual NodeType nodeType() const override
Abstract virtual that returns the type of this node.
static QList< Function * > gmOwnedFunctions
List of functions owned by the expression engine.
This is the base class for vector data providers.
Function(const QString &fnname, const ParameterList &params, const QStringList &groups, const QString &helpText=QString(), bool usesGeometry=false, const QStringList &referencedColumns=QStringList(), bool lazyEval=false, bool handlesNull=false, bool isContextual=false)
Constructor for function which uses named parameter list and group list.
QStringList groups() const
Returns a list of the groups the function belongs to.
Represents a vector layer which manages a vector based data sets.
int compare(const QString &other) const
virtual QStringList aliases() const override
Returns a list of possible aliases for the function.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
The QgsOgcUtils class provides various utility functions for conversion between OGC (Open Geospatial ...
Definition: qgsogcutils.h:43
NodeCondition(const WhenThenList &conditions, Node *elseExp=nullptr)
AreaUnit
Units of area.
Definition: qgsunittypes.h:49
void append(NamedNode *node)
Adds a named node.
const ParameterList & parameters() const
Returns the list of named parameters for the function, if set.
StaticFunction(const QString &fnname, int params, FcnEvalContext fcn, const QString &group, const QString &helpText=QString(), bool usesGeometry=false, const QStringList &referencedColumns=QStringList(), bool lazyEval=false, const QStringList &aliases=QStringList(), bool handlesNull=false)
Static function for evaluation against a QgsExpressionContext, using an unnamed list of parameter val...
virtual bool needsGeometry() const override
Abstract virtual method which returns if the geometry is required to evaluate this expression...
QList< Node * > list()
virtual bool isDeprecated() const
Returns true if the function is deprecated and should not be presented as a valid option to users in ...
virtual QStringList referencedColumns() const override
Abstract virtual method which returns a list of columns required to evaluate this node...
static QMap< QString, QVariant > gmSpecialColumns