QGIS API Documentation  2.7.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 #include "qgsfield.h"
26 #include "qgsdistancearea.h"
27 
28 class QgsFeature;
29 class QgsGeometry;
30 class QgsOgcUtils;
31 class QgsVectorLayer;
33 
34 class QDomElement;
35 
87 class CORE_EXPORT QgsExpression
88 {
89  public:
90  QgsExpression( const QString& expr );
91  ~QgsExpression();
92 
94  bool hasParserError() const { return !mParserErrorString.isNull(); }
96  QString parserErrorString() const { return mParserErrorString; }
97 
98  class Node;
99 
101  const Node* rootNode() const { return mRootNode; }
102 
104  bool prepare( const QgsFields &fields );
105 
112  QStringList referencedColumns() const;
113 
115  bool needsGeometry() const;
116 
117  // evaluation
118 
121  QVariant evaluate( const QgsFeature* f = NULL );
122 
126  inline QVariant evaluate( const QgsFeature& f ) { return evaluate( &f ); }
127 
130  QVariant evaluate( const QgsFeature* f, const QgsFields& fields );
131 
135  inline QVariant evaluate( const QgsFeature& f, const QgsFields& fields ) { return evaluate( &f, fields ); }
136 
138  bool hasEvalError() const { return !mEvalErrorString.isNull(); }
140  QString evalErrorString() const { return mEvalErrorString; }
142  void setEvalErrorString( QString str ) { mEvalErrorString = str; }
143 
145  void setCurrentRowNumber( int rowNumber ) { mRowNumber = rowNumber; }
147  int currentRowNumber() { return mRowNumber; }
148 
150  static void setSpecialColumn( const QString& name, QVariant value );
152  static void unsetSpecialColumn( const QString& name );
154  static QVariant specialColumn( const QString& name );
157  static bool hasSpecialColumn( const QString& name );
158 
159  static bool isValid( const QString& text, const QgsFields& fields, QString &errorMessage );
160 
161  void setScale( double scale ) { mScale = scale; }
162 
163  double scale() { return mScale; }
164 
166  const QString expression() const
167  {
168  if ( !mExp.isNull() )
169  return mExp;
170  else
171  return dump();
172  }
173 
175  QString dump() const;
176 
179  QgsDistanceArea *geomCalculator() { initGeomCalculator(); return mCalc; }
180 
182  // instead of the default.
183  void setGeomCalculator( const QgsDistanceArea &calc );
184 
198  static QString replaceExpressionText( const QString &action, const QgsFeature *feat,
199  QgsVectorLayer *layer,
200  const QMap<QString, QVariant> *substitutionMap = 0,
201  const QgsDistanceArea* distanceArea = 0
202  );
203 
211  static double evaluateToDouble( const QString& text, const double fallbackValue );
212 
218  {
221  };
222 
228  {
229  // logical
232 
233  // comparison
234  boEQ, // =
235  boNE, // <>
236  boLE, // <=
237  boGE, // >=
238  boLT, // <
239  boGT, // >
247 
248  // math
256 
257  // strings
259  };
261  {
271  };
272 
273  static const char* BinaryOperatorText[];
274  static const char* UnaryOperatorText[];
275 
276  typedef QVariant( *FcnEval )( const QVariantList& values, const QgsFeature* f, QgsExpression* parent );
277 
278 
282  class CORE_EXPORT Function
283  {
284  public:
285  Function( QString fnname, int params, QString group, QString helpText = QString(), bool usesGeometry = false, QStringList referencedColumns = QStringList(), bool lazyEval = false )
286  : mName( fnname ), mParams( params ), mUsesGeometry( usesGeometry ), mGroup( group ), mHelpText( helpText ), mReferencedColumns( referencedColumns ), mLazyEval( lazyEval ) {}
288  QString name() { return mName; }
290  int params() { return mParams; }
292  bool usesgeometry() { return mUsesGeometry; }
293 
297  bool lazyEval() { return mLazyEval; }
298 
299  virtual QStringList referencedColumns() const { return mReferencedColumns; }
300 
302  QString group() { return mGroup; }
304  QString helptext() { return mHelpText.isEmpty() ? QgsExpression::helptext( mName ) : mHelpText; }
305 
306  virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) = 0;
307 
308  bool operator==( const Function& other ) const
309  {
310  if ( QString::compare( mName, other.mName, Qt::CaseInsensitive ) == 0 )
311  return true;
312 
313  return false;
314  }
315 
316  private:
317  QString mName;
318  int mParams;
319  bool mUsesGeometry;
320  QString mGroup;
321  QString mHelpText;
322  QStringList mReferencedColumns;
323  bool mLazyEval;
324  };
325 
326  class StaticFunction : public Function
327  {
328  public:
329  StaticFunction( QString fnname, int params, FcnEval fcn, QString group, QString helpText = QString(), bool usesGeometry = false, QStringList referencedColumns = QStringList(), bool lazyEval = false )
330  : Function( fnname, params, group, helpText, usesGeometry, referencedColumns, lazyEval ), mFnc( fcn ) {}
331 
332  virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) override
333  {
334  return mFnc( values, f, parent );
335  }
336 
337  private:
338  FcnEval mFnc;
339  };
340 
341  static const QList<Function*> &Functions();
342  static QList<Function*> gmFunctions;
343 
344  static QStringList gmBuiltinFunctions;
345  static const QStringList &BuiltinFunctions();
346 
347  static bool registerFunction( Function* function );
348  static bool unregisterFunction( QString name );
349 
350  // tells whether the identifier is a name of existing function
351  static bool isFunctionName( QString name );
352 
353  // return index of the function in Functions array
354  static int functionIndex( QString name );
355 
359  static int functionCount();
360 
364  static QList<Function*> specialColumns();
365 
367  static QString quotedColumnRef( QString name );
369  static QString quotedString( QString text );
370 
372 
373  class Visitor; // visitor interface is defined below
374 
375  enum NodeType
376  {
383  ntCondition
384  };
385 
386  class CORE_EXPORT Node
387  {
388  public:
389  virtual ~Node() {}
390  virtual NodeType nodeType() const = 0;
391  // abstract virtual eval function
392  // errors are reported to the parent
393  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) = 0;
394 
395  // abstract virtual preparation function
396  // errors are reported to the parent
397  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) = 0;
398 
399  virtual QString dump() const = 0;
400 
401  virtual QStringList referencedColumns() const = 0;
402  virtual bool needsGeometry() const = 0;
403 
404  // support for visitor pattern
405  virtual void accept( Visitor& v ) const = 0;
406  };
407 
408  class CORE_EXPORT NodeList
409  {
410  public:
411  NodeList() {}
412  virtual ~NodeList() { qDeleteAll( mList ); }
413  void append( Node* node ) { mList.append( node ); }
414  int count() { return mList.count(); }
415  QList<Node*> list() { return mList; }
416 
417  virtual QString dump() const;
418 
419  protected:
420  QList<Node*> mList;
421  };
422 
423  class CORE_EXPORT Interval
424  {
425  // YEAR const value taken from postgres query
426  // SELECT EXTRACT(EPOCH FROM interval '1 year')
427  static const int YEARS = 31557600;
428  static const int MONTHS = 60 * 60 * 24 * 30;
429  static const int WEEKS = 60 * 60 * 24 * 7;
430  static const int DAY = 60 * 60 * 24;
431  static const int HOUR = 60 * 60;
432  static const int MINUTE = 60;
433  public:
434  Interval( double seconds = 0 ) : mSeconds( seconds ), mValid( true ) { }
435  ~Interval();
436  double years() { return mSeconds / YEARS;}
437  double months() { return mSeconds / MONTHS; }
438  double weeks() { return mSeconds / WEEKS;}
439  double days() { return mSeconds / DAY;}
440  double hours() { return mSeconds / HOUR;}
441  double minutes() { return mSeconds / MINUTE;}
442  double seconds() { return mSeconds; }
443  bool isValid() { return mValid; }
444  void setValid( bool valid ) { mValid = valid; }
445  bool operator==( const QgsExpression::Interval& other ) const;
446  static QgsExpression::Interval invalidInterVal();
447  static QgsExpression::Interval fromString( QString string );
448  private:
449  double mSeconds;
450  bool mValid;
451  };
452 
453  class CORE_EXPORT NodeUnaryOperator : public Node
454  {
455  public:
456  NodeUnaryOperator( UnaryOperator op, Node* operand ) : mOp( op ), mOperand( operand ) {}
457  ~NodeUnaryOperator() { delete mOperand; }
458 
459  UnaryOperator op() const { return mOp; }
460  Node* operand() const { return mOperand; }
461 
462  virtual NodeType nodeType() const override { return ntUnaryOperator; }
463  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
464  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
465  virtual QString dump() const override;
466 
467  virtual QStringList referencedColumns() const override { return mOperand->referencedColumns(); }
468  virtual bool needsGeometry() const override { return mOperand->needsGeometry(); }
469  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
470 
471  protected:
474  };
475 
476  class CORE_EXPORT NodeBinaryOperator : public Node
477  {
478  public:
479  NodeBinaryOperator( BinaryOperator op, Node* opLeft, Node* opRight ) : mOp( op ), mOpLeft( opLeft ), mOpRight( opRight ) {}
480  ~NodeBinaryOperator() { delete mOpLeft; delete mOpRight; }
481 
482  BinaryOperator op() const { return mOp; }
483  Node* opLeft() const { return mOpLeft; }
484  Node* opRight() const { return mOpRight; }
485 
486  virtual NodeType nodeType() const override { return ntBinaryOperator; }
487  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
488  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
489  virtual QString dump() const override;
490 
491  virtual QStringList referencedColumns() const override { return mOpLeft->referencedColumns() + mOpRight->referencedColumns(); }
492  virtual bool needsGeometry() const override { return mOpLeft->needsGeometry() || mOpRight->needsGeometry(); }
493  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
494 
495  int precedence() const;
496 
497  protected:
498  bool compare( double diff );
499  int computeInt( int x, int y );
500  double computeDouble( double x, double y );
501  QDateTime computeDateTimeFromInterval( QDateTime d, QgsExpression::Interval *i );
502 
506  };
507 
508  class CORE_EXPORT NodeInOperator : public Node
509  {
510  public:
511  NodeInOperator( Node* node, NodeList* list, bool notin = false ) : mNode( node ), mList( list ), mNotIn( notin ) {}
512  virtual ~NodeInOperator() { delete mNode; delete mList; }
513 
514  Node* node() const { return mNode; }
515  bool isNotIn() const { return mNotIn; }
516  NodeList* list() const { return mList; }
517 
518  virtual NodeType nodeType() const override { return ntInOperator; }
519  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
520  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
521  virtual QString dump() const override;
522 
523  virtual QStringList referencedColumns() const override { QStringList lst( mNode->referencedColumns() ); foreach ( Node* n, mList->list() ) lst.append( n->referencedColumns() ); return lst; }
524  virtual bool needsGeometry() const override { bool needs = false; foreach ( Node* n, mList->list() ) needs |= n->needsGeometry(); return needs; }
525  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
526 
527  protected:
530  bool mNotIn;
531  };
532 
533  class CORE_EXPORT NodeFunction : public Node
534  {
535  public:
536  NodeFunction( int fnIndex, NodeList* args ) : mFnIndex( fnIndex ), mArgs( args ) {}
537  //NodeFunction( QString name, NodeList* args ) : mName(name), mArgs(args) {}
538  virtual ~NodeFunction() { delete mArgs; }
539 
540  int fnIndex() const { return mFnIndex; }
541  NodeList* args() const { return mArgs; }
542 
543  virtual NodeType nodeType() const override { return ntFunction; }
544  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
545  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
546  virtual QString dump() const override;
547 
548  virtual QStringList referencedColumns() const override;
549  virtual bool needsGeometry() const override { bool needs = Functions()[mFnIndex]->usesgeometry(); if ( mArgs ) { foreach ( Node* n, mArgs->list() ) needs |= n->needsGeometry(); } return needs; }
550  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
551 
552  protected:
553  //QString mName;
554  int mFnIndex;
556  };
557 
558  class CORE_EXPORT NodeLiteral : public Node
559  {
560  public:
561  NodeLiteral( QVariant value ) : mValue( value ) {}
562 
563  QVariant value() const { return mValue; }
564 
565  virtual NodeType nodeType() const override { return ntLiteral; }
566  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
567  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
568  virtual QString dump() const override;
569 
570  virtual QStringList referencedColumns() const override { return QStringList(); }
571  virtual bool needsGeometry() const override { return false; }
572  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
573 
574  protected:
575  QVariant mValue;
576  };
577 
578  class CORE_EXPORT NodeColumnRef : public Node
579  {
580  public:
581  NodeColumnRef( QString name ) : mName( name ), mIndex( -1 ) {}
582 
583  QString name() const { return mName; }
584 
585  virtual NodeType nodeType() const override { return ntColumnRef; }
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( mName ); }
591  virtual bool needsGeometry() const override { return false; }
592 
593  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
594 
595  protected:
596  QString mName;
597  int mIndex;
598  };
599 
600  class CORE_EXPORT WhenThen
601  {
602  public:
603  WhenThen( Node* whenExp, Node* thenExp ) : mWhenExp( whenExp ), mThenExp( thenExp ) {}
604  ~WhenThen() { delete mWhenExp; delete mThenExp; }
605 
606  //protected:
609  };
610  typedef QList<WhenThen*> WhenThenList;
611 
612  class CORE_EXPORT NodeCondition : public Node
613  {
614  public:
615  NodeCondition( WhenThenList* conditions, Node* elseExp = NULL ) : mConditions( *conditions ), mElseExp( elseExp ) { delete conditions; }
616  ~NodeCondition() { delete mElseExp; qDeleteAll( mConditions ); }
617 
618  virtual NodeType nodeType() const override { return ntCondition; }
619  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
620  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
621  virtual QString dump() const override;
622 
623  virtual QStringList referencedColumns() const override;
624  virtual bool needsGeometry() const override;
625  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
626 
627  protected:
628  WhenThenList mConditions;
630  };
631 
633 
636  class CORE_EXPORT Visitor
637  {
638  public:
639  virtual ~Visitor() {}
640  virtual void visit( const NodeUnaryOperator& n ) = 0;
641  virtual void visit( const NodeBinaryOperator& n ) = 0;
642  virtual void visit( const NodeInOperator& n ) = 0;
643  virtual void visit( const NodeFunction& n ) = 0;
644  virtual void visit( const NodeLiteral& n ) = 0;
645  virtual void visit( const NodeColumnRef& n ) = 0;
646  virtual void visit( const NodeCondition& n ) = 0;
647  };
648 
650  void acceptVisitor( Visitor& v ) const;
651 
652  static QString helptext( QString name );
653  static QString group( QString group );
654 
655  protected:
659  QgsExpression() : mRootNode( 0 ), mRowNumber( 0 ), mCalc( 0 ) {}
660 
661  void initGeomCalculator();
662 
664 
667 
669  double mScale;
670  QString mExp;
671 
673 
674  static QMap<QString, QVariant> gmSpecialColumns;
675  static QMap<QString, QString> gmSpecialColumnGroups;
676 
677  static QHash<QString, QString> gFunctionHelpTexts;
678  static QHash<QString, QString> gGroups;
679 
680  static void initFunctionHelp();
681 
682  friend class QgsOgcUtils;
683 
684  private:
685  Q_DISABLE_COPY( QgsExpression ) // for now - until we have proper copy constructor / implicit sharing
686 };
687 
690 
691 #endif // QGSEXPRESSION_H
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:87
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:94
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)
static QString helptext(QString name)
QgsExpression()
Used by QgsOgcUtils to create an empty.
Container of fields for a vector layer.
Definition: qgsfield.h:172
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:113
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)
double scale()
QString helptext()
The help text for the function.
static QList< Function * > gmFunctions
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)
NodeLiteral(QVariant value)
StaticFunction(QString fnname, int params, FcnEval fcn, QString group, QString helpText=QString(), bool usesGeometry=false, QStringList referencedColumns=QStringList(), bool lazyEval=false)
NodeUnaryOperator(UnaryOperator op, Node *operand)
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.
Function(QString fnname, int params, QString group, QString helpText=QString(), bool usesGeometry=false, QStringList referencedColumns=QStringList(), bool lazyEval=false)
QList< WhenThen * > WhenThenList
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.
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)
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.
QString parserErrorString() const
Returns parser error.
Definition: qgsexpression.h:96
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