QGIS API Documentation  2.9.0-Master
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 
25 class QgsFeature;
26 class QgsGeometry;
27 class QgsOgcUtils;
28 class QgsVectorLayer;
30 class QgsField;
31 class QgsFields;
32 class QgsDistanceArea;
33 class QDomElement;
34 
86 class CORE_EXPORT QgsExpression
87 {
88  public:
89  QgsExpression( const QString& expr );
90  ~QgsExpression();
91 
93  bool hasParserError() const { return !mParserErrorString.isNull(); }
95  QString parserErrorString() const { return mParserErrorString; }
96 
97  class Node;
98 
100  const Node* rootNode() const { return mRootNode; }
101 
103  bool prepare( const QgsFields &fields );
104 
111  QStringList referencedColumns() const;
112 
114  bool needsGeometry() const;
115 
116  // evaluation
117 
120  QVariant evaluate( const QgsFeature* f = NULL );
121 
125  inline QVariant evaluate( const QgsFeature& f ) { return evaluate( &f ); }
126 
129  QVariant evaluate( const QgsFeature* f, const QgsFields& fields );
130 
134  inline QVariant evaluate( const QgsFeature& f, const QgsFields& fields ) { return evaluate( &f, fields ); }
135 
137  bool hasEvalError() const { return !mEvalErrorString.isNull(); }
139  QString evalErrorString() const { return mEvalErrorString; }
141  void setEvalErrorString( QString str ) { mEvalErrorString = str; }
142 
144  void setCurrentRowNumber( int rowNumber ) { mRowNumber = rowNumber; }
146  int currentRowNumber() { return mRowNumber; }
147 
149  static void setSpecialColumn( const QString& name, QVariant value );
151  static void unsetSpecialColumn( const QString& name );
153  static QVariant specialColumn( const QString& name );
156  static bool hasSpecialColumn( const QString& name );
157 
161  bool isField() const { return rootNode() && dynamic_cast<const NodeColumnRef*>( rootNode() ) ;}
162 
163  static bool isValid( const QString& text, const QgsFields& fields, QString &errorMessage );
164 
165  void setScale( double scale ) { mScale = scale; }
166 
167  double scale() { return mScale; }
168 
170  const QString expression() const
171  {
172  if ( !mExp.isNull() )
173  return mExp;
174  else
175  return dump();
176  }
177 
179  QString dump() const;
180 
183  QgsDistanceArea *geomCalculator() { initGeomCalculator(); return mCalc; }
184 
186  // instead of the default.
187  void setGeomCalculator( const QgsDistanceArea &calc );
188 
202  static QString replaceExpressionText( const QString &action, const QgsFeature *feat,
203  QgsVectorLayer *layer,
204  const QMap<QString, QVariant> *substitutionMap = 0,
205  const QgsDistanceArea* distanceArea = 0
206  );
207 
215  static double evaluateToDouble( const QString& text, const double fallbackValue );
216 
222  {
225  };
226 
232  {
233  // logical
236 
237  // comparison
238  boEQ, // =
239  boNE, // <>
240  boLE, // <=
241  boGE, // >=
242  boLT, // <
243  boGT, // >
251 
252  // math
260 
261  // strings
263  };
265  {
275  };
276 
277  static const char* BinaryOperatorText[];
278  static const char* UnaryOperatorText[];
279 
280  typedef QVariant( *FcnEval )( const QVariantList& values, const QgsFeature* f, QgsExpression* parent );
281 
282 
286  class CORE_EXPORT Function
287  {
288  public:
289  Function( const QString& fnname, int params, QString group, QString helpText = QString(), bool usesGeometry = false, QStringList referencedColumns = QStringList(), bool lazyEval = false )
290  : mName( fnname ), mParams( params ), mUsesGeometry( usesGeometry ), mGroup( group ), mHelpText( helpText ), mReferencedColumns( referencedColumns ), mLazyEval( lazyEval ) {}
292  QString name() { return mName; }
294  int params() { return mParams; }
296  bool usesgeometry() { return mUsesGeometry; }
297 
303  virtual QStringList aliases() const { return QStringList(); }
304 
308  bool lazyEval() { return mLazyEval; }
309 
310  virtual QStringList referencedColumns() const { return mReferencedColumns; }
311 
313  QString group() { return mGroup; }
315  const QString helptext() { return mHelpText.isEmpty() ? QgsExpression::helptext( mName ) : mHelpText; }
316 
317  virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) = 0;
318 
319  bool operator==( const Function& other ) const
320  {
321  if ( QString::compare( mName, other.mName, Qt::CaseInsensitive ) == 0 )
322  return true;
323 
324  return false;
325  }
326 
327  private:
328  QString mName;
329  int mParams;
330  bool mUsesGeometry;
331  QString mGroup;
332  QString mHelpText;
333  QStringList mReferencedColumns;
334  bool mLazyEval;
335  };
336 
337  class StaticFunction : public Function
338  {
339  public:
340  StaticFunction( QString fnname, int params, FcnEval fcn, QString group, QString helpText = QString(), bool usesGeometry = false, QStringList referencedColumns = QStringList(), bool lazyEval = false, const QStringList& aliases = QStringList() )
341  : Function( fnname, params, group, helpText, usesGeometry, referencedColumns, lazyEval ), mFnc( fcn ), mAliases( aliases ) {}
342 
343  virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) override
344  {
345  return mFnc( values, f, parent );
346  }
347 
348  virtual QStringList aliases() const override { return mAliases; }
349 
350  private:
351  FcnEval mFnc;
352  QStringList mAliases;
353  };
354 
355  static QList<Function*> gmFunctions;
356  static const QList<Function*>& Functions();
357 
358  static QStringList gmBuiltinFunctions;
359  static const QStringList& BuiltinFunctions();
360 
361  static bool registerFunction( Function* function );
362  static bool unregisterFunction( QString name );
363 
364  // tells whether the identifier is a name of existing function
365  static bool isFunctionName( QString name );
366 
367  // return index of the function in Functions array
368  static int functionIndex( const QString& name );
369 
373  static int functionCount();
374 
378  static QList<Function*> specialColumns();
379 
381  static QString quotedColumnRef( QString name );
383  static QString quotedString( QString text );
384 
386 
387  class Visitor; // visitor interface is defined below
388 
389  enum NodeType
390  {
397  ntCondition
398  };
399 
400  class CORE_EXPORT Node
401  {
402  public:
403  virtual ~Node() {}
404  virtual NodeType nodeType() const = 0;
405  // abstract virtual eval function
406  // errors are reported to the parent
407  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) = 0;
408 
409  // abstract virtual preparation function
410  // errors are reported to the parent
411  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) = 0;
412 
413  virtual QString dump() const = 0;
414 
415  virtual QStringList referencedColumns() const = 0;
416  virtual bool needsGeometry() const = 0;
417 
418  // support for visitor pattern
419  virtual void accept( Visitor& v ) const = 0;
420  };
421 
422  class CORE_EXPORT NodeList
423  {
424  public:
425  NodeList() {}
426  virtual ~NodeList() { qDeleteAll( mList ); }
428  void append( Node* node ) { mList.append( node ); }
429  int count() { return mList.count(); }
430  QList<Node*> list() { return mList; }
431 
432  virtual QString dump() const;
433 
434  protected:
435  QList<Node*> mList;
436  };
437 
438  class CORE_EXPORT Interval
439  {
440  // YEAR const value taken from postgres query
441  // SELECT EXTRACT(EPOCH FROM interval '1 year')
442  static const int YEARS = 31557600;
443  static const int MONTHS = 60 * 60 * 24 * 30;
444  static const int WEEKS = 60 * 60 * 24 * 7;
445  static const int DAY = 60 * 60 * 24;
446  static const int HOUR = 60 * 60;
447  static const int MINUTE = 60;
448  public:
449  Interval( double seconds = 0 ) : mSeconds( seconds ), mValid( true ) { }
450  ~Interval();
451  double years() { return mSeconds / YEARS;}
452  double months() { return mSeconds / MONTHS; }
453  double weeks() { return mSeconds / WEEKS;}
454  double days() { return mSeconds / DAY;}
455  double hours() { return mSeconds / HOUR;}
456  double minutes() { return mSeconds / MINUTE;}
457  double seconds() { return mSeconds; }
458  bool isValid() { return mValid; }
459  void setValid( bool valid ) { mValid = valid; }
460  bool operator==( const QgsExpression::Interval& other ) const;
461  static QgsExpression::Interval invalidInterVal();
462  static QgsExpression::Interval fromString( QString string );
463  private:
464  double mSeconds;
465  bool mValid;
466  };
467 
468  class CORE_EXPORT NodeUnaryOperator : public Node
469  {
470  public:
471  NodeUnaryOperator( UnaryOperator op, Node* operand ) : mOp( op ), mOperand( operand ) {}
472  ~NodeUnaryOperator() { delete mOperand; }
473 
474  UnaryOperator op() const { return mOp; }
475  Node* operand() const { return mOperand; }
476 
477  virtual NodeType nodeType() const override { return ntUnaryOperator; }
478  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
479  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
480  virtual QString dump() const override;
481 
482  virtual QStringList referencedColumns() const override { return mOperand->referencedColumns(); }
483  virtual bool needsGeometry() const override { return mOperand->needsGeometry(); }
484  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
485 
486  protected:
489  };
490 
491  class CORE_EXPORT NodeBinaryOperator : public Node
492  {
493  public:
494  NodeBinaryOperator( BinaryOperator op, Node* opLeft, Node* opRight ) : mOp( op ), mOpLeft( opLeft ), mOpRight( opRight ) {}
495  ~NodeBinaryOperator() { delete mOpLeft; delete mOpRight; }
496 
497  BinaryOperator op() const { return mOp; }
498  Node* opLeft() const { return mOpLeft; }
499  Node* opRight() const { return mOpRight; }
500 
501  virtual NodeType nodeType() const override { return ntBinaryOperator; }
502  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
503  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
504  virtual QString dump() const override;
505 
506  virtual QStringList referencedColumns() const override { return mOpLeft->referencedColumns() + mOpRight->referencedColumns(); }
507  virtual bool needsGeometry() const override { return mOpLeft->needsGeometry() || mOpRight->needsGeometry(); }
508  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
509 
510  int precedence() const;
511 
512  protected:
513  bool compare( double diff );
514  int computeInt( int x, int y );
515  double computeDouble( double x, double y );
516  QDateTime computeDateTimeFromInterval( QDateTime d, QgsExpression::Interval *i );
517 
521  };
522 
523  class CORE_EXPORT NodeInOperator : public Node
524  {
525  public:
526  NodeInOperator( Node* node, NodeList* list, bool notin = false ) : mNode( node ), mList( list ), mNotIn( notin ) {}
527  virtual ~NodeInOperator() { delete mNode; delete mList; }
528 
529  Node* node() const { return mNode; }
530  bool isNotIn() const { return mNotIn; }
531  NodeList* list() const { return mList; }
532 
533  virtual NodeType nodeType() const override { return ntInOperator; }
534  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
535  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
536  virtual QString dump() const override;
537 
538  virtual QStringList referencedColumns() const override { QStringList lst( mNode->referencedColumns() ); foreach ( Node* n, mList->list() ) lst.append( n->referencedColumns() ); return lst; }
539  virtual bool needsGeometry() const override { bool needs = false; foreach ( Node* n, mList->list() ) needs |= n->needsGeometry(); return needs; }
540  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
541 
542  protected:
545  bool mNotIn;
546  };
547 
548  class CORE_EXPORT NodeFunction : public Node
549  {
550  public:
551  NodeFunction( int fnIndex, NodeList* args ) : mFnIndex( fnIndex ), mArgs( args ) {}
552  //NodeFunction( QString name, NodeList* args ) : mName(name), mArgs(args) {}
553  virtual ~NodeFunction() { delete mArgs; }
554 
555  int fnIndex() const { return mFnIndex; }
556  NodeList* args() const { return mArgs; }
557 
558  virtual NodeType nodeType() const override { return ntFunction; }
559  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
560  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
561  virtual QString dump() const override;
562 
563  virtual QStringList referencedColumns() const override;
564  virtual bool needsGeometry() const override { bool needs = Functions()[mFnIndex]->usesgeometry(); if ( mArgs ) { foreach ( Node* n, mArgs->list() ) needs |= n->needsGeometry(); } return needs; }
565  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
566 
567  protected:
568  //QString mName;
569  int mFnIndex;
571  };
572 
573  class CORE_EXPORT NodeLiteral : public Node
574  {
575  public:
576  NodeLiteral( const QVariant& value ) : mValue( value ) {}
577 
578  inline QVariant value() const { return mValue; }
579 
580  virtual NodeType nodeType() const override { return ntLiteral; }
581  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
582  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
583  virtual QString dump() const override;
584 
585  virtual QStringList referencedColumns() const override { return QStringList(); }
586  virtual bool needsGeometry() const override { return false; }
587  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
588 
589  protected:
590  QVariant mValue;
591  };
592 
593  class CORE_EXPORT NodeColumnRef : public Node
594  {
595  public:
596  NodeColumnRef( const QString& name ) : mName( name ), mIndex( -1 ) {}
597 
598  QString name() const { return mName; }
599 
600  virtual NodeType nodeType() const override { return ntColumnRef; }
601  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
602  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
603  virtual QString dump() const override;
604 
605  virtual QStringList referencedColumns() const override { return QStringList( mName ); }
606  virtual bool needsGeometry() const override { return false; }
607 
608  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
609 
610  protected:
611  QString mName;
612  int mIndex;
613  };
614 
615  class CORE_EXPORT WhenThen
616  {
617  public:
618  WhenThen( Node* whenExp, Node* thenExp ) : mWhenExp( whenExp ), mThenExp( thenExp ) {}
619  ~WhenThen() { delete mWhenExp; delete mThenExp; }
620 
621  //protected:
624  };
625  typedef QList<WhenThen*> WhenThenList;
626 
627  class CORE_EXPORT NodeCondition : public Node
628  {
629  public:
630  NodeCondition( WhenThenList* conditions, Node* elseExp = NULL ) : mConditions( *conditions ), mElseExp( elseExp ) { delete conditions; }
631  ~NodeCondition() { delete mElseExp; qDeleteAll( mConditions ); }
632 
633  virtual NodeType nodeType() const override { return ntCondition; }
634  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
635  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
636  virtual QString dump() const override;
637 
638  virtual QStringList referencedColumns() const override;
639  virtual bool needsGeometry() const override;
640  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
641 
642  protected:
643  WhenThenList mConditions;
645  };
646 
648 
651  class CORE_EXPORT Visitor
652  {
653  public:
654  virtual ~Visitor() {}
655  virtual void visit( const NodeUnaryOperator& n ) = 0;
656  virtual void visit( const NodeBinaryOperator& n ) = 0;
657  virtual void visit( const NodeInOperator& n ) = 0;
658  virtual void visit( const NodeFunction& n ) = 0;
659  virtual void visit( const NodeLiteral& n ) = 0;
660  virtual void visit( const NodeColumnRef& n ) = 0;
661  virtual void visit( const NodeCondition& n ) = 0;
662  };
663 
665  void acceptVisitor( Visitor& v ) const;
666 
667  static QString helptext( QString name );
668  static QString group( QString group );
669 
670  protected:
674  QgsExpression() : mRootNode( 0 ), mRowNumber( 0 ), mScale( 0.0 ), mCalc( 0 ) {}
675 
676  void initGeomCalculator();
677 
679 
682 
684  double mScale;
685  QString mExp;
686 
688 
689  static QMap<QString, QVariant> gmSpecialColumns;
690  static QMap<QString, QString> gmSpecialColumnGroups;
691 
692  static QHash<QString, QString> gFunctionHelpTexts;
693  static QHash<QString, QString> gGroups;
694 
695  static void initFunctionHelp();
696 
697  friend class QgsOgcUtils;
698 
699  private:
700  Q_DISABLE_COPY( QgsExpression ) // for now - until we have proper copy constructor / implicit sharing
701 };
702 
705 
706 #endif // QGSEXPRESSION_H
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:86
virtual QStringList referencedColumns() const =0
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
QVariant evaluate(const QgsFeature &f, const QgsFields &fields)
Evaluate the feature and return the result.
UnaryOperator
list of unary operators
virtual bool needsGeometry() const override
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
Definition: qgsexpression.h:93
virtual QStringList referencedColumns() const override
virtual NodeType nodeType() const override
bool lazyEval()
True if this function should use lazy evaluation.
const QString expression() const
Alias for dump()
Node is a class used by Line3D.
Definition: Node.h:23
A abstract base class for defining QgsExpression functions.
bool operator==(const QgsFeatureIterator &fi1, const QgsFeatureIterator &fi2)
virtual NodeType nodeType() const override
virtual QString dump() const =0
NodeCondition(WhenThenList *conditions, Node *elseExp=NULL)
NodeColumnRef(const QString &name)
static QString helptext(QString name)
QgsExpression()
Used by QgsOgcUtils to create an empty.
Container of fields for a vector layer.
Definition: qgsfield.h:173
Interval(double seconds=0)
virtual QStringList referencedColumns() const override
virtual bool prepare(QgsExpression *parent, const QgsFields &fields)=0
NodeList * list() const
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:119
StaticFunction(QString fnname, int params, FcnEval fcn, QString group, QString helpText=QString(), bool usesGeometry=false, QStringList referencedColumns=QStringList(), bool lazyEval=false, const QStringList &aliases=QStringList())
QVariant value() const
virtual NodeType nodeType() const override
virtual QVariant func(const QVariantList &values, const QgsFeature *f, QgsExpression *parent) override
int currentRowNumber()
Return the number used for $rownum special column.
virtual void accept(Visitor &v) const override
QString mEvalErrorString
virtual bool needsGeometry() const override
NodeBinaryOperator(BinaryOperator op, Node *opLeft, Node *opRight)
QString mParserErrorString
virtual NodeType nodeType() const override
static const QList< Function * > & Functions()
static QHash< QString, QString > gFunctionHelpTexts
virtual QStringList referencedColumns() const override
QgsDistanceArea * geomCalculator()
Return calculator used for distance and area calculations (used by internal functions) ...
NodeList * args() const
virtual void accept(Visitor &v) const override
QgsDistanceArea * mCalc
QList< Node * > mList
static QHash< QString, QString > gGroups
const Node * rootNode() const
Returns root node of the expression. Root node is null is parsing has failed.
NodeInOperator(Node *node, NodeList *list, bool notin=false)
bool isField() const
Checks whether an expression consists only of a single field reference.
double scale()
static QList< Function * > gmFunctions
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:38
virtual void accept(Visitor &v) const override
QString name()
The name of the function.
void setCurrentRowNumber(int rowNumber)
Set the number for $rownum special column.
WhenThen(Node *whenExp, Node *thenExp)
NodeUnaryOperator(UnaryOperator op, Node *operand)
Function(const QString &fnname, int params, QString group, QString helpText=QString(), bool usesGeometry=false, QStringList referencedColumns=QStringList(), bool lazyEval=false)
BinaryOperator op() const
virtual void accept(Visitor &v) const override
virtual QVariant eval(QgsExpression *parent, const QgsFeature *f)=0
virtual NodeType nodeType() const override
virtual QStringList referencedColumns() const override
virtual QStringList referencedColumns() const
virtual void accept(Visitor &v) const override
void setEvalErrorString(QString str)
Set evaluation error (used internally by evaluation functions)
NodeFunction(int fnIndex, NodeList *args)
General purpose distance and area calculator.
static QMap< QString, QString > gmSpecialColumnGroups
virtual bool needsGeometry() const override
virtual void accept(Visitor &v) const override
virtual NodeType nodeType() const override
virtual bool needsGeometry() const override
BinaryOperator
list of binary operators
QString group()
The group the function belongs to.
QList< WhenThen * > WhenThenList
virtual QStringList aliases() const
Returns a list of possible aliases for the function.
virtual void visit(const NodeUnaryOperator &n)=0
QVariant evaluate(const QgsFeature &f)
Evaluate the feature and return the result.
int params()
The number of parameters this function takes.
NodeLiteral(const QVariant &value)
const QString helptext()
The help text for the function.
support for visitor pattern - algorithms dealing with the expressions may be implemented without modi...
virtual bool needsGeometry() const =0
bool operator==(const Function &other) const
static QStringList gmBuiltinFunctions
virtual bool needsGeometry() const override
void append(Node *node)
Takes ownership of the provided node.
UnaryOperator op() const
virtual void accept(Visitor &v) const override
void setValid(bool valid)
virtual NodeType nodeType() const override
This is the base class for vector data providers.
void setScale(double scale)
Represents a vector layer which manages a vector based data sets.
virtual QStringList aliases() const override
Returns a list of possible aliases for the function.
QString parserErrorString() const
Returns parser error.
Definition: qgsexpression.h:95
Q_DECLARE_METATYPE(QgsExpression::Interval)
The QgsOgcUtils class provides various utility functions for conversion between OGC (Open Geospatial ...
Definition: qgsogcutils.h:28
QString evalErrorString() const
Returns evaluation error.
bool usesgeometry()
Does this function use a geometry object.
virtual bool needsGeometry() const override
QList< Node * > list()
virtual QStringList referencedColumns() const override
static QMap< QString, QVariant > gmSpecialColumns