QGIS API Documentation  2.11.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties 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 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,
290  int params,
291  QString group,
292  QString helpText = QString(),
293  bool usesGeometry = false,
294  QStringList referencedColumns = QStringList(),
295  bool lazyEval = false,
296  bool handlesNull = false )
297  : mName( fnname )
298  , mParams( params )
299  , mUsesGeometry( usesGeometry )
300  , mGroup( group )
301  , mHelpText( helpText )
302  , mReferencedColumns( referencedColumns )
303  , mLazyEval( lazyEval )
304  , mHandlesNull( handlesNull )
305  {}
306 
307  virtual ~Function() {}
308 
310  QString name() { return mName; }
312  int params() { return mParams; }
314  bool usesgeometry() { return mUsesGeometry; }
315 
321  virtual QStringList aliases() const { return QStringList(); }
322 
326  bool lazyEval() { return mLazyEval; }
327 
328  virtual QStringList referencedColumns() const { return mReferencedColumns; }
329 
331  QString group() { return mGroup; }
333  const QString helptext() { return mHelpText.isEmpty() ? QgsExpression::helptext( mName ) : mHelpText; }
334 
335  virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) = 0;
336 
337  bool operator==( const Function& other ) const
338  {
339  if ( QString::compare( mName, other.mName, Qt::CaseInsensitive ) == 0 )
340  return true;
341 
342  return false;
343  }
344 
345  virtual bool handlesNull() const { return mHandlesNull; }
346 
347  private:
348  QString mName;
349  int mParams;
350  bool mUsesGeometry;
351  QString mGroup;
352  QString mHelpText;
353  QStringList mReferencedColumns;
354  bool mLazyEval;
355  bool mHandlesNull;
356  };
357 
358  class StaticFunction : public Function
359  {
360  public:
362  int params,
363  FcnEval fcn,
364  QString group,
365  QString helpText = QString(),
366  bool usesGeometry = false,
367  QStringList referencedColumns = QStringList(),
368  bool lazyEval = false,
369  const QStringList& aliases = QStringList(),
370  bool handlesNull = false )
371  : Function( fnname, params, group, helpText, usesGeometry, referencedColumns, lazyEval, handlesNull )
372  , mFnc( fcn )
373  , mAliases( aliases )
374  {}
375 
376  virtual ~StaticFunction() {}
377 
378  virtual QVariant func( const QVariantList& values, const QgsFeature* f, QgsExpression* parent ) override
379  {
380  return mFnc( values, f, parent );
381  }
382 
383  virtual QStringList aliases() const override { return mAliases; }
384 
385  private:
386  FcnEval mFnc;
387  QStringList mAliases;
388  };
389 
391  static const QList<Function*>& Functions();
392 
394  static const QStringList& BuiltinFunctions();
395 
396  static bool registerFunction( Function* function );
397  static bool unregisterFunction( QString name );
398 
399  // tells whether the identifier is a name of existing function
400  static bool isFunctionName( QString name );
401 
402  // return index of the function in Functions array
403  static int functionIndex( const QString& name );
404 
408  static int functionCount();
409 
413  static QList<Function*> specialColumns();
414 
416  static QString quotedColumnRef( QString name );
418  static QString quotedString( QString text );
419 
421 
422  class Visitor; // visitor interface is defined below
423 
424  enum NodeType
425  {
432  ntCondition
433  };
434 
435  class CORE_EXPORT Node
436  {
437  public:
438  virtual ~Node() {}
439  virtual NodeType nodeType() const = 0;
440  // abstract virtual eval function
441  // errors are reported to the parent
442  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) = 0;
443 
444  // abstract virtual preparation function
445  // errors are reported to the parent
446  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) = 0;
447 
448  virtual QString dump() const = 0;
449 
450  virtual QStringList referencedColumns() const = 0;
451  virtual bool needsGeometry() const = 0;
452 
453  // support for visitor pattern
454  virtual void accept( Visitor& v ) const = 0;
455  };
456 
457  class CORE_EXPORT NodeList
458  {
459  public:
460  NodeList() {}
461  virtual ~NodeList() { qDeleteAll( mList ); }
463  void append( Node* node ) { mList.append( node ); }
464  int count() { return mList.count(); }
465  QList<Node*> list() { return mList; }
466 
467  virtual QString dump() const;
468 
469  protected:
471  };
472 
473  class CORE_EXPORT Interval
474  {
475  // YEAR const value taken from postgres query
476  // SELECT EXTRACT(EPOCH FROM interval '1 year')
477  static const int YEARS = 31557600;
478  static const int MONTHS = 60 * 60 * 24 * 30;
479  static const int WEEKS = 60 * 60 * 24 * 7;
480  static const int DAY = 60 * 60 * 24;
481  static const int HOUR = 60 * 60;
482  static const int MINUTE = 60;
483  public:
484  Interval( double seconds = 0 ) : mSeconds( seconds ), mValid( true ) { }
485  ~Interval();
486  double years() { return mSeconds / YEARS;}
487  double months() { return mSeconds / MONTHS; }
488  double weeks() { return mSeconds / WEEKS;}
489  double days() { return mSeconds / DAY;}
490  double hours() { return mSeconds / HOUR;}
491  double minutes() { return mSeconds / MINUTE;}
492  double seconds() { return mSeconds; }
493  bool isValid() { return mValid; }
494  void setValid( bool valid ) { mValid = valid; }
495  bool operator==( const QgsExpression::Interval& other ) const;
496  static QgsExpression::Interval invalidInterVal();
497  static QgsExpression::Interval fromString( QString string );
498  private:
499  double mSeconds;
500  bool mValid;
501  };
502 
503  class CORE_EXPORT NodeUnaryOperator : public Node
504  {
505  public:
506  NodeUnaryOperator( UnaryOperator op, Node* operand ) : mOp( op ), mOperand( operand ) {}
507  ~NodeUnaryOperator() { delete mOperand; }
508 
509  UnaryOperator op() const { return mOp; }
510  Node* operand() const { return mOperand; }
511 
512  virtual NodeType nodeType() const override { return ntUnaryOperator; }
513  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
514  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
515  virtual QString dump() const override;
516 
517  virtual QStringList referencedColumns() const override { return mOperand->referencedColumns(); }
518  virtual bool needsGeometry() const override { return mOperand->needsGeometry(); }
519  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
520 
521  protected:
524  };
525 
526  class CORE_EXPORT NodeBinaryOperator : public Node
527  {
528  public:
529  NodeBinaryOperator( BinaryOperator op, Node* opLeft, Node* opRight ) : mOp( op ), mOpLeft( opLeft ), mOpRight( opRight ) {}
530  ~NodeBinaryOperator() { delete mOpLeft; delete mOpRight; }
531 
532  BinaryOperator op() const { return mOp; }
533  Node* opLeft() const { return mOpLeft; }
534  Node* opRight() const { return mOpRight; }
535 
536  virtual NodeType nodeType() const override { return ntBinaryOperator; }
537  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
538  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
539  virtual QString dump() const override;
540 
541  virtual QStringList referencedColumns() const override { return mOpLeft->referencedColumns() + mOpRight->referencedColumns(); }
542  virtual bool needsGeometry() const override { return mOpLeft->needsGeometry() || mOpRight->needsGeometry(); }
543  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
544 
545  int precedence() const;
546  bool leftAssociative() const;
547 
548  protected:
549  bool compare( double diff );
550  int computeInt( int x, int y );
551  double computeDouble( double x, double y );
552  QDateTime computeDateTimeFromInterval( QDateTime d, QgsExpression::Interval *i );
553 
557  };
558 
559  class CORE_EXPORT NodeInOperator : public Node
560  {
561  public:
562  NodeInOperator( Node* node, NodeList* list, bool notin = false ) : mNode( node ), mList( list ), mNotIn( notin ) {}
563  virtual ~NodeInOperator() { delete mNode; delete mList; }
564 
565  Node* node() const { return mNode; }
566  bool isNotIn() const { return mNotIn; }
567  NodeList* list() const { return mList; }
568 
569  virtual NodeType nodeType() const override { return ntInOperator; }
570  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
571  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
572  virtual QString dump() const override;
573 
574  virtual QStringList referencedColumns() const override { QStringList lst( mNode->referencedColumns() ); foreach ( Node* n, mList->list() ) lst.append( n->referencedColumns() ); return lst; }
575  virtual bool needsGeometry() const override { bool needs = false; foreach ( Node* n, mList->list() ) needs |= n->needsGeometry(); return needs; }
576  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
577 
578  protected:
581  bool mNotIn;
582  };
583 
584  class CORE_EXPORT NodeFunction : public Node
585  {
586  public:
587  NodeFunction( int fnIndex, NodeList* args ) : mFnIndex( fnIndex ), mArgs( args ) {}
588  //NodeFunction( QString name, NodeList* args ) : mName(name), mArgs(args) {}
589  virtual ~NodeFunction() { delete mArgs; }
590 
591  int fnIndex() const { return mFnIndex; }
592  NodeList* args() const { return mArgs; }
593 
594  virtual NodeType nodeType() const override { return ntFunction; }
595  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
596  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
597  virtual QString dump() const override;
598 
599  virtual QStringList referencedColumns() const override;
600  virtual bool needsGeometry() const override { bool needs = Functions()[mFnIndex]->usesgeometry(); if ( mArgs ) { foreach ( Node* n, mArgs->list() ) needs |= n->needsGeometry(); } return needs; }
601  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
602 
603  protected:
604  //QString mName;
605  int mFnIndex;
607  };
608 
609  class CORE_EXPORT NodeLiteral : public Node
610  {
611  public:
612  NodeLiteral( const QVariant& value ) : mValue( value ) {}
613 
614  inline QVariant value() const { return mValue; }
615 
616  virtual NodeType nodeType() const override { return ntLiteral; }
617  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
618  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
619  virtual QString dump() const override;
620 
621  virtual QStringList referencedColumns() const override { return QStringList(); }
622  virtual bool needsGeometry() const override { return false; }
623  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
624 
625  protected:
627  };
628 
629  class CORE_EXPORT NodeColumnRef : public Node
630  {
631  public:
632  NodeColumnRef( const QString& name ) : mName( name ), mIndex( -1 ) {}
633 
634  QString name() const { return mName; }
635 
636  virtual NodeType nodeType() const override { return ntColumnRef; }
637  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
638  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
639  virtual QString dump() const override;
640 
641  virtual QStringList referencedColumns() const override { return QStringList( mName ); }
642  virtual bool needsGeometry() const override { return false; }
643 
644  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
645 
646  protected:
648  int mIndex;
649  };
650 
651  class CORE_EXPORT WhenThen
652  {
653  public:
654  WhenThen( Node* whenExp, Node* thenExp ) : mWhenExp( whenExp ), mThenExp( thenExp ) {}
655  ~WhenThen() { delete mWhenExp; delete mThenExp; }
656 
657  //protected:
660  };
662 
663  class CORE_EXPORT NodeCondition : public Node
664  {
665  public:
666  NodeCondition( WhenThenList* conditions, Node* elseExp = NULL ) : mConditions( *conditions ), mElseExp( elseExp ) { delete conditions; }
667  ~NodeCondition() { delete mElseExp; qDeleteAll( mConditions ); }
668 
669  virtual NodeType nodeType() const override { return ntCondition; }
670  virtual QVariant eval( QgsExpression* parent, const QgsFeature* f ) override;
671  virtual bool prepare( QgsExpression* parent, const QgsFields &fields ) override;
672  virtual QString dump() const override;
673 
674  virtual QStringList referencedColumns() const override;
675  virtual bool needsGeometry() const override;
676  virtual void accept( Visitor& v ) const override { v.visit( *this ); }
677 
678  protected:
679  WhenThenList mConditions;
681  };
682 
684 
687  class CORE_EXPORT Visitor
688  {
689  public:
690  virtual ~Visitor() {}
691  virtual void visit( const NodeUnaryOperator& n ) = 0;
692  virtual void visit( const NodeBinaryOperator& n ) = 0;
693  virtual void visit( const NodeInOperator& n ) = 0;
694  virtual void visit( const NodeFunction& n ) = 0;
695  virtual void visit( const NodeLiteral& n ) = 0;
696  virtual void visit( const NodeColumnRef& n ) = 0;
697  virtual void visit( const NodeCondition& n ) = 0;
698  };
699 
701  void acceptVisitor( Visitor& v ) const;
702 
703  static QString helptext( QString name );
704  static QString group( QString group );
705 
706  protected:
710  QgsExpression() : mRootNode( 0 ), mRowNumber( 0 ), mScale( 0.0 ), mCalc( 0 ) {}
711 
712  void initGeomCalculator();
713 
715 
718 
720  double mScale;
722 
724 
727 
730 
731  static void initFunctionHelp();
732 
733  friend class QgsOgcUtils;
734 
735  private:
736  Q_DISABLE_COPY( QgsExpression ) // for now - until we have proper copy constructor / implicit sharing
737 };
738 
741 
742 #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 bool handlesNull() const
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
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(), bool handlesNull=false)
NodeCondition(WhenThenList *conditions, Node *elseExp=NULL)
NodeColumnRef(const QString &name)
static QString helptext(QString name)
QgsExpression()
Used by QgsOgcUtils to create an empty.
Function(const QString &fnname, int params, QString group, QString helpText=QString(), bool usesGeometry=false, QStringList referencedColumns=QStringList(), bool lazyEval=false, bool handlesNull=false)
Container of fields for a vector layer.
Definition: qgsfield.h:173
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:75
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:162
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
void append(const T &value)
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.
bool isEmpty() const
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)
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.
int compare(const QString &other) const
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