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 ) {}
291 
292  virtual ~Function() {}
293 
295  QString name() { return mName; }
297  int params() { return mParams; }
299  bool usesgeometry() { return mUsesGeometry; }
300 
306  virtual QStringList aliases() const { return QStringList(); }
307 
311  bool lazyEval() { return mLazyEval; }
312 
313  virtual QStringList referencedColumns() const { return mReferencedColumns; }
314 
316  QString group() { return mGroup; }
318  const QString helptext() { return mHelpText.isEmpty() ? QgsExpression::helptext( mName ) : mHelpText; }
319 
320  virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) = 0;
321 
322  bool operator==( const Function& other ) const
323  {
324  if ( QString::compare( mName, other.mName, Qt::CaseInsensitive ) == 0 )
325  return true;
326 
327  return false;
328  }
329 
330  private:
331  QString mName;
332  int mParams;
333  bool mUsesGeometry;
334  QString mGroup;
335  QString mHelpText;
336  QStringList mReferencedColumns;
337  bool mLazyEval;
338  };
339 
340  class StaticFunction : public Function
341  {
342  public:
343  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() )
344  : Function( fnname, params, group, helpText, usesGeometry, referencedColumns, lazyEval ), mFnc( fcn ), mAliases( aliases ) {}
345 
346  virtual ~StaticFunction() {}
347 
348  virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) override
349  {
350  return mFnc( values, f, parent );
351  }
352 
353  virtual QStringList aliases() const override { return mAliases; }
354 
355  private:
356  FcnEval mFnc;
357  QStringList mAliases;
358  };
359 
360  static QList<Function*> gmFunctions;
361  static const QList<Function*>& Functions();
362 
363  static QStringList gmBuiltinFunctions;
364  static const QStringList& BuiltinFunctions();
365 
366  static bool registerFunction( Function* function );
367  static bool unregisterFunction( QString name );
368 
369  // tells whether the identifier is a name of existing function
370  static bool isFunctionName( QString name );
371 
372  // return index of the function in Functions array
373  static int functionIndex( const QString& name );
374 
378  static int functionCount();
379 
383  static QList<Function*> specialColumns();
384 
386  static QString quotedColumnRef( QString name );
388  static QString quotedString( QString text );
389 
391 
392  class Visitor; // visitor interface is defined below
393 
394  enum NodeType
395  {
402  ntCondition
403  };
404 
405  class CORE_EXPORT Node
406  {
407  public:
408  virtual ~Node() {}
409  virtual NodeType nodeType() const = 0;
410  // abstract virtual eval function
411  // errors are reported to the parent
412  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) = 0;
413 
414  // abstract virtual preparation function
415  // errors are reported to the parent
416  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) = 0;
417 
418  virtual QString dump() const = 0;
419 
420  virtual QStringList referencedColumns() const = 0;
421  virtual bool needsGeometry() const = 0;
422 
423  // support for visitor pattern
424  virtual void accept( Visitor& v ) const = 0;
425  };
426 
427  class CORE_EXPORT NodeList
428  {
429  public:
430  NodeList() {}
431  virtual ~NodeList() { qDeleteAll( mList ); }
433  void append( Node* node ) { mList.append( node ); }
434  int count() { return mList.count(); }
435  QList<Node*> list() { return mList; }
436 
437  virtual QString dump() const;
438 
439  protected:
440  QList<Node*> mList;
441  };
442 
443  class CORE_EXPORT Interval
444  {
445  // YEAR const value taken from postgres query
446  // SELECT EXTRACT(EPOCH FROM interval '1 year')
447  static const int YEARS = 31557600;
448  static const int MONTHS = 60 * 60 * 24 * 30;
449  static const int WEEKS = 60 * 60 * 24 * 7;
450  static const int DAY = 60 * 60 * 24;
451  static const int HOUR = 60 * 60;
452  static const int MINUTE = 60;
453  public:
454  Interval( double seconds = 0 ) : mSeconds( seconds ), mValid( true ) { }
455  ~Interval();
456  double years() { return mSeconds / YEARS;}
457  double months() { return mSeconds / MONTHS; }
458  double weeks() { return mSeconds / WEEKS;}
459  double days() { return mSeconds / DAY;}
460  double hours() { return mSeconds / HOUR;}
461  double minutes() { return mSeconds / MINUTE;}
462  double seconds() { return mSeconds; }
463  bool isValid() { return mValid; }
464  void setValid( bool valid ) { mValid = valid; }
465  bool operator==( const QgsExpression::Interval& other ) const;
466  static QgsExpression::Interval invalidInterVal();
467  static QgsExpression::Interval fromString( QString string );
468  private:
469  double mSeconds;
470  bool mValid;
471  };
472 
473  class CORE_EXPORT NodeUnaryOperator : public Node
474  {
475  public:
476  NodeUnaryOperator( UnaryOperator op, Node* operand ) : mOp( op ), mOperand( operand ) {}
477  ~NodeUnaryOperator() { delete mOperand; }
478 
479  UnaryOperator op() const { return mOp; }
480  Node* operand() const { return mOperand; }
481 
482  virtual NodeType nodeType() const override { return ntUnaryOperator; }
483  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
484  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
485  virtual QString dump() const override;
486 
487  virtual QStringList referencedColumns() const override { return mOperand->referencedColumns(); }
488  virtual bool needsGeometry() const override { return mOperand->needsGeometry(); }
489  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
490 
491  protected:
494  };
495 
496  class CORE_EXPORT NodeBinaryOperator : public Node
497  {
498  public:
499  NodeBinaryOperator( BinaryOperator op, Node* opLeft, Node* opRight ) : mOp( op ), mOpLeft( opLeft ), mOpRight( opRight ) {}
500  ~NodeBinaryOperator() { delete mOpLeft; delete mOpRight; }
501 
502  BinaryOperator op() const { return mOp; }
503  Node* opLeft() const { return mOpLeft; }
504  Node* opRight() const { return mOpRight; }
505 
506  virtual NodeType nodeType() const override { return ntBinaryOperator; }
507  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
508  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
509  virtual QString dump() const override;
510 
511  virtual QStringList referencedColumns() const override { return mOpLeft->referencedColumns() + mOpRight->referencedColumns(); }
512  virtual bool needsGeometry() const override { return mOpLeft->needsGeometry() || mOpRight->needsGeometry(); }
513  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
514 
515  int precedence() const;
516 
517  protected:
518  bool compare( double diff );
519  int computeInt( int x, int y );
520  double computeDouble( double x, double y );
521  QDateTime computeDateTimeFromInterval( QDateTime d, QgsExpression::Interval *i );
522 
526  };
527 
528  class CORE_EXPORT NodeInOperator : public Node
529  {
530  public:
531  NodeInOperator( Node* node, NodeList* list, bool notin = false ) : mNode( node ), mList( list ), mNotIn( notin ) {}
532  virtual ~NodeInOperator() { delete mNode; delete mList; }
533 
534  Node* node() const { return mNode; }
535  bool isNotIn() const { return mNotIn; }
536  NodeList* list() const { return mList; }
537 
538  virtual NodeType nodeType() const override { return ntInOperator; }
539  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
540  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
541  virtual QString dump() const override;
542 
543  virtual QStringList referencedColumns() const override { QStringList lst( mNode->referencedColumns() ); foreach ( Node* n, mList->list() ) lst.append( n->referencedColumns() ); return lst; }
544  virtual bool needsGeometry() const override { bool needs = false; foreach ( Node* n, mList->list() ) needs |= n->needsGeometry(); return needs; }
545  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
546 
547  protected:
550  bool mNotIn;
551  };
552 
553  class CORE_EXPORT NodeFunction : public Node
554  {
555  public:
556  NodeFunction( int fnIndex, NodeList* args ) : mFnIndex( fnIndex ), mArgs( args ) {}
557  //NodeFunction( QString name, NodeList* args ) : mName(name), mArgs(args) {}
558  virtual ~NodeFunction() { delete mArgs; }
559 
560  int fnIndex() const { return mFnIndex; }
561  NodeList* args() const { return mArgs; }
562 
563  virtual NodeType nodeType() const override { return ntFunction; }
564  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
565  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
566  virtual QString dump() const override;
567 
568  virtual QStringList referencedColumns() const override;
569  virtual bool needsGeometry() const override { bool needs = Functions()[mFnIndex]->usesgeometry(); if ( mArgs ) { foreach ( Node* n, mArgs->list() ) needs |= n->needsGeometry(); } return needs; }
570  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
571 
572  protected:
573  //QString mName;
574  int mFnIndex;
576  };
577 
578  class CORE_EXPORT NodeLiteral : public Node
579  {
580  public:
581  NodeLiteral( const QVariant& value ) : mValue( value ) {}
582 
583  inline QVariant value() const { return mValue; }
584 
585  virtual NodeType nodeType() const override { return ntLiteral; }
586  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
587  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
588  virtual QString dump() const override;
589 
590  virtual QStringList referencedColumns() const override { return QStringList(); }
591  virtual bool needsGeometry() const override { return false; }
592  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
593 
594  protected:
595  QVariant mValue;
596  };
597 
598  class CORE_EXPORT NodeColumnRef : public Node
599  {
600  public:
601  NodeColumnRef( const QString& name ) : mName( name ), mIndex( -1 ) {}
602 
603  QString name() const { return mName; }
604 
605  virtual NodeType nodeType() const override { return ntColumnRef; }
606  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
607  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
608  virtual QString dump() const override;
609 
610  virtual QStringList referencedColumns() const override { return QStringList( mName ); }
611  virtual bool needsGeometry() const override { return false; }
612 
613  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
614 
615  protected:
616  QString mName;
617  int mIndex;
618  };
619 
620  class CORE_EXPORT WhenThen
621  {
622  public:
623  WhenThen( Node* whenExp, Node* thenExp ) : mWhenExp( whenExp ), mThenExp( thenExp ) {}
624  ~WhenThen() { delete mWhenExp; delete mThenExp; }
625 
626  //protected:
629  };
630  typedef QList<WhenThen*> WhenThenList;
631 
632  class CORE_EXPORT NodeCondition : public Node
633  {
634  public:
635  NodeCondition( WhenThenList* conditions, Node* elseExp = NULL ) : mConditions( *conditions ), mElseExp( elseExp ) { delete conditions; }
636  ~NodeCondition() { delete mElseExp; qDeleteAll( mConditions ); }
637 
638  virtual NodeType nodeType() const override { return ntCondition; }
639  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
640  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
641  virtual QString dump() const override;
642 
643  virtual QStringList referencedColumns() const override;
644  virtual bool needsGeometry() const override;
645  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
646 
647  protected:
648  WhenThenList mConditions;
650  };
651 
653 
656  class CORE_EXPORT Visitor
657  {
658  public:
659  virtual ~Visitor() {}
660  virtual void visit( const NodeUnaryOperator& n ) = 0;
661  virtual void visit( const NodeBinaryOperator& n ) = 0;
662  virtual void visit( const NodeInOperator& n ) = 0;
663  virtual void visit( const NodeFunction& n ) = 0;
664  virtual void visit( const NodeLiteral& n ) = 0;
665  virtual void visit( const NodeColumnRef& n ) = 0;
666  virtual void visit( const NodeCondition& n ) = 0;
667  };
668 
670  void acceptVisitor( Visitor& v ) const;
671 
672  static QString helptext( QString name );
673  static QString group( QString group );
674 
675  protected:
679  QgsExpression() : mRootNode( 0 ), mRowNumber( 0 ), mScale( 0.0 ), mCalc( 0 ) {}
680 
681  void initGeomCalculator();
682 
684 
687 
689  double mScale;
690  QString mExp;
691 
693 
694  static QMap<QString, QVariant> gmSpecialColumns;
695  static QMap<QString, QString> gmSpecialColumnGroups;
696 
697  static QHash<QString, QString> gFunctionHelpTexts;
698  static QHash<QString, QString> gGroups;
699 
700  static void initFunctionHelp();
701 
702  friend class QgsOgcUtils;
703 
704  private:
705  Q_DISABLE_COPY( QgsExpression ) // for now - until we have proper copy constructor / implicit sharing
706 };
707 
710 
711 #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