1 /***************************************************************************
2                                qgsexpressionnodeimpl.h
3                              -------------------
4     begin                : May 2017
5     copyright            : (C) 2017 Matthias Kuhn
6     email                : matthias@opengis.ch
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 
17 #ifndef QGSEXPRESSIONNODEIMPL_H
18 #define QGSEXPRESSIONNODEIMPL_H
19 
20 #include "qgsexpressionnode.h"
21 #include "qgsinterval.h"
22 
23 /**
24  * \ingroup core
25  * \brief A unary node is either negative as in boolean (not) or as in numbers (minus).
26  */
27 class CORE_EXPORT QgsExpressionNodeUnaryOperator : public QgsExpressionNode
28 {
29   public:
30 
31     /**
32      * \brief list of unary operators
33      * \note if any change is made here, the definition of QgsExpression::UnaryOperatorText[] must be adapted.
34      */
35     enum UnaryOperator
36     {
37       uoNot,
38       uoMinus,
39     };
40 
41     /**
42      * A node unary operator is modifying the value of \a operand by negating it with \a op.
43      */
QgsExpressionNodeUnaryOperator(QgsExpressionNodeUnaryOperator::UnaryOperator op,QgsExpressionNode * operand SIP_TRANSFER)44     QgsExpressionNodeUnaryOperator( QgsExpressionNodeUnaryOperator::UnaryOperator op, QgsExpressionNode *operand SIP_TRANSFER )
45       : mOp( op )
46       , mOperand( operand )
47     {}
~QgsExpressionNodeUnaryOperator()48     ~QgsExpressionNodeUnaryOperator() override { delete mOperand; }
49 
50 #ifdef SIP_RUN
51     SIP_PYOBJECT __repr__();
52     % MethodCode
53     QString str = QStringLiteral( "<QgsExpressionNodeUnaryOperator: %1>" ).arg( sipCpp->text() );
54     sipRes = PyUnicode_FromString( str.toUtf8().constData() );
55     % End
56 #endif
57 
58     /**
59      * Returns the unary operator.
60      */
61     QgsExpressionNodeUnaryOperator::UnaryOperator op() const { return mOp; }
62 
63     /**
64      * Returns the node the operator will operate upon.
65      */
operand()66     QgsExpressionNode *operand() const { return mOperand; }
67 
68     QgsExpressionNode::NodeType nodeType() const override;
69     bool prepareNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
70     QVariant evalNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
71     QString dump() const override;
72 
73     QSet<QString> referencedColumns() const override;
74     QSet<QString> referencedVariables() const override;
75     QSet<QString> referencedFunctions() const override;
76     QList<const QgsExpressionNode *> nodes() const override; SIP_SKIP
77     bool needsGeometry() const override;
78     QgsExpressionNode *clone() const override SIP_FACTORY;
79 
80     bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const override;
81 
82     /**
83      * Returns a the name of this operator without the operands.
84      * I.e. "NOT" or "-"
85      */
86     QString text() const;
87 
88   private:
89     UnaryOperator mOp;
90     QgsExpressionNode *mOperand = nullptr;
91 
92     static const char *UNARY_OPERATOR_TEXT[];
93 };
94 
95 /**
96  * \brief A binary expression operator, which operates on two values.
97  * \ingroup core
98  */
99 class CORE_EXPORT QgsExpressionNodeBinaryOperator : public QgsExpressionNode
100 {
101   public:
102 
103     /**
104      * \brief list of binary operators
105      * \note if any change is made here, the definition of QgsExpression::BinaryOperatorText[] must be adapted.
106      */
107     enum BinaryOperator
108     {
109       // logical
110       boOr,
111       boAnd,
112 
113       // comparison
114       boEQ,  //!< =
115       boNE,  //!< <>
116       boLE,  //!< <=
117       boGE,  //!< >=
118       boLT,  //!< <
119       boGT,  //!< >
120       boRegexp,
121       boLike,
122       boNotLike,
123       boILike,
124       boNotILike,
125       boIs,
126       boIsNot,
127 
128       // math
129       boPlus,
130       boMinus,
131       boMul,
132       boDiv,
133       boIntDiv,
134       boMod,
135       boPow,
136 
137       // strings
138       boConcat,
139     };
140 
141     /**
142      * Binary combination of the left and the right with op.
143      */
QgsExpressionNodeBinaryOperator(QgsExpressionNodeBinaryOperator::BinaryOperator op,QgsExpressionNode * opLeft SIP_TRANSFER,QgsExpressionNode * opRight SIP_TRANSFER)144     QgsExpressionNodeBinaryOperator( QgsExpressionNodeBinaryOperator::BinaryOperator op, QgsExpressionNode *opLeft SIP_TRANSFER, QgsExpressionNode *opRight SIP_TRANSFER )
145       : mOp( op )
146       , mOpLeft( opLeft )
147       , mOpRight( opRight )
148     {}
~QgsExpressionNodeBinaryOperator()149     ~QgsExpressionNodeBinaryOperator() override { delete mOpLeft; delete mOpRight; }
150 
151 #ifdef SIP_RUN
152     SIP_PYOBJECT __repr__();
153     % MethodCode
154     QString str = QStringLiteral( "<QgsExpressionNodeBinaryOperator: %1>" ).arg( sipCpp->text() );
155     sipRes = PyUnicode_FromString( str.toUtf8().constData() );
156     % End
157 #endif
158 
159     /**
160      * Returns the binary operator.
161      */
162     QgsExpressionNodeBinaryOperator::BinaryOperator op() const { return mOp; }
163 
164     /**
165      * Returns the node to the left of the operator.
166      * \see opRight()
167      */
opLeft()168     QgsExpressionNode *opLeft() const { return mOpLeft; }
169 
170     /**
171      * Returns the node to the right of the operator.
172      * \see opLeft()
173      */
opRight()174     QgsExpressionNode *opRight() const { return mOpRight; }
175 
176     QgsExpressionNode::NodeType nodeType() const override;
177     bool prepareNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
178     QVariant evalNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
179     QString dump() const override;
180 
181     QSet<QString> referencedColumns() const override;
182     QSet<QString> referencedVariables() const override;
183     QSet<QString> referencedFunctions() const override;
184     QList<const QgsExpressionNode *> nodes( ) const override; SIP_SKIP
185 
186     bool needsGeometry() const override;
187     QgsExpressionNode *clone() const override SIP_FACTORY;
188     bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const override;
189 
190     /**
191      * Returns the precedence index for the operator. Higher values have higher precedence.
192      */
193     int precedence() const;
194 
195     /**
196      * Returns TRUE if the operator is left-associative.
197      */
198     bool leftAssociative() const;
199 
200     /**
201      * Returns a the name of this operator without the operands.
202      * I.e. "AND", "OR", ...
203      */
204     QString text() const;
205 
206   private:
207     bool compare( double diff );
208     qlonglong computeInt( qlonglong x, qlonglong y );
209     double computeDouble( double x, double y );
210 
211     /**
212      * Computes the result date time calculation from a start datetime and an interval
213      * \param d start datetime
214      * \param i interval to add or subtract (depending on mOp)
215      */
216     QDateTime computeDateTimeFromInterval( const QDateTime &d, QgsInterval *i );
217 
218     BinaryOperator mOp;
219     QgsExpressionNode *mOpLeft = nullptr;
220     QgsExpressionNode *mOpRight = nullptr;
221 
222     static const char *BINARY_OPERATOR_TEXT[];
223 };
224 
225 /**
226  * \brief A indexing expression operator, which allows use of square brackets [] to reference map and array items.
227  * \ingroup core
228  * \since QGIS 3.6
229  */
230 class CORE_EXPORT QgsExpressionNodeIndexOperator : public QgsExpressionNode
231 {
232   public:
233 
234     /**
235      * Constructor for QgsExpressionNodeIndexOperator.
236      */
QgsExpressionNodeIndexOperator(QgsExpressionNode * container SIP_TRANSFER,QgsExpressionNode * index SIP_TRANSFER)237     QgsExpressionNodeIndexOperator( QgsExpressionNode *container SIP_TRANSFER, QgsExpressionNode *index SIP_TRANSFER )
238       : mContainer( container )
239       , mIndex( index )
240     {}
~QgsExpressionNodeIndexOperator()241     ~QgsExpressionNodeIndexOperator() override { delete mContainer; delete mIndex; }
242 
243     /**
244      * Returns the container node, representing an array or map value.
245      * \see index()
246      */
container()247     QgsExpressionNode *container() const { return mContainer; }
248 
249     /**
250      * Returns the index node, representing an array element index or map key.
251      * \see container()
252      */
index()253     QgsExpressionNode *index() const { return mIndex; }
254 
255     QgsExpressionNode::NodeType nodeType() const override;
256     bool prepareNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
257     QVariant evalNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
258     QString dump() const override;
259 
260     QSet<QString> referencedColumns() const override;
261     QSet<QString> referencedVariables() const override;
262     QSet<QString> referencedFunctions() const override;
263     QList<const QgsExpressionNode *> nodes( ) const override; SIP_SKIP
264 
265     bool needsGeometry() const override;
266     QgsExpressionNode *clone() const override SIP_FACTORY;
267     bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const override;
268 
269   private:
270 
271     QgsExpressionNode *mContainer = nullptr;
272     QgsExpressionNode *mIndex = nullptr;
273 
274 };
275 
276 /**
277  * \brief An expression node for value IN or NOT IN clauses.
278  * \ingroup core
279  */
280 class CORE_EXPORT QgsExpressionNodeInOperator : public QgsExpressionNode
281 {
282   public:
283 
284     /**
285      * This node tests if the result of \a node is in the result of \a list. Optionally it can be inverted with \a notin which by default is FALSE.
286      */
287     QgsExpressionNodeInOperator( QgsExpressionNode *node SIP_TRANSFER, QgsExpressionNode::NodeList *list SIP_TRANSFER, bool notin = false )
mNode(node)288       : mNode( node )
289       , mList( list )
290       , mNotIn( notin )
291     {}
292     ~QgsExpressionNodeInOperator() override;
293 
294     /**
295      * Returns the expression node.
296      */
node()297     QgsExpressionNode *node() const { return mNode; }
298 
299     /**
300      * Returns TRUE if this node is a "NOT IN" operator, or FALSE if the node is a normal "IN" operator.
301      */
isNotIn()302     bool isNotIn() const { return mNotIn; }
303 
304     /**
305      * Returns the list of nodes to search for matching values within.
306      */
list()307     QgsExpressionNode::NodeList *list() const { return mList; }
308 
309     QgsExpressionNode::NodeType nodeType() const override;
310     bool prepareNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
311     QVariant evalNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
312     QString dump() const override;
313 
314     QSet<QString> referencedColumns() const override;
315     QSet<QString> referencedVariables() const override;
316     QSet<QString> referencedFunctions() const override;
317     QList<const QgsExpressionNode *> nodes() const override; SIP_SKIP
318     bool needsGeometry() const override;
319     QgsExpressionNode *clone() const override SIP_FACTORY;
320     bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const override;
321 
322   private:
323     QgsExpressionNode *mNode = nullptr;
324     QgsExpressionNodeInOperator::NodeList *mList = nullptr;
325     bool mNotIn;
326 };
327 
328 /**
329  * \brief An expression node for expression functions.
330  * \ingroup core
331  */
332 class CORE_EXPORT QgsExpressionNodeFunction : public QgsExpressionNode
333 {
334   public:
335 
336     /**
337      * A function node consists of an index of the function in the global function array and
338      * a list of arguments that will be passed to it.
339      */
340     QgsExpressionNodeFunction( int fnIndex, QgsExpressionNode::NodeList *args SIP_TRANSFER );
341 
342     ~QgsExpressionNodeFunction() override;
343 
344 #ifdef SIP_RUN
345     SIP_PYOBJECT __repr__();
346     % MethodCode
347     QString function;
348     if ( QgsExpressionFunction *fd = QgsExpression::QgsExpression::Functions()[sipCpp->fnIndex()] )
349     {
350       function = fd->name();
351     }
352     else
353     {
354       function = QString::number( sipCpp->fnIndex() );
355     }
356 
357     QString str = QStringLiteral( "<QgsExpressionNodeFunction: %1>" ).arg( function );
358     sipRes = PyUnicode_FromString( str.toUtf8().constData() );
359     % End
360 #endif
361 
362     /**
363      * Returns the index of the node's function.
364      */
365     int fnIndex() const { return mFnIndex; }
366 
367     /**
368      * Returns a list of arguments specified for the function.
369      */
args()370     QgsExpressionNode::NodeList *args() const { return mArgs; }
371 
372     QgsExpressionNode::NodeType nodeType() const override;
373     bool prepareNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
374     QVariant evalNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
375     QString dump() const override;
376 
377     QSet<QString> referencedColumns() const override;
378     QSet<QString> referencedVariables() const override;
379     QSet<QString> referencedFunctions() const override;
380 
381     QList<const QgsExpressionNode *> nodes() const override; SIP_SKIP
382     bool needsGeometry() const override;
383     QgsExpressionNode *clone() const override SIP_FACTORY;
384     bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const override;
385 
386     //! Tests whether the provided argument list is valid for the matching function
387     static bool validateParams( int fnIndex, QgsExpressionNode::NodeList *args, QString &error );
388 
389   private:
390     int mFnIndex;
391     NodeList *mArgs = nullptr;
392 };
393 
394 /**
395  * \brief An expression node for literal values.
396  * \ingroup core
397  */
398 class CORE_EXPORT QgsExpressionNodeLiteral : public QgsExpressionNode
399 {
400   public:
401 
402     /**
403      * Constructor for QgsExpressionNodeLiteral, with the specified literal \a value.
404      */
QgsExpressionNodeLiteral(const QVariant & value)405     QgsExpressionNodeLiteral( const QVariant &value )
406       : mValue( value )
407     {}
408 
409 #ifdef SIP_RUN
410     SIP_PYOBJECT __repr__();
411     % MethodCode
412     QString str = QStringLiteral( "<QgsExpressionNodeLiteral: %1>" ).arg( sipCpp->valueAsString() );
413     sipRes = PyUnicode_FromString( str.toUtf8().constData() );
414     % End
415 #endif
416 
417     //! The value of the literal.
418     inline QVariant value() const { return mValue; }
419 
420     QgsExpressionNode::NodeType nodeType() const override;
421     bool prepareNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
422     QVariant evalNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
423     QString dump() const override;
424 
425     QSet<QString> referencedColumns() const override;
426     QSet<QString> referencedVariables() const override;
427     QSet<QString> referencedFunctions() const override;
428 
429     QList<const QgsExpressionNode *> nodes() const override; SIP_SKIP
430     bool needsGeometry() const override;
431     QgsExpressionNode *clone() const override SIP_FACTORY;
432     bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const override;
433 
434     /**
435      * Returns a string representation of the node's literal value.
436      *
437      * \since QGIS 3.20
438      */
439     QString valueAsString() const;
440 
441   private:
442     QVariant mValue;
443 };
444 
445 /**
446  * \brief An expression node which takes it value from a feature's field.
447  * \ingroup core
448  */
449 class CORE_EXPORT QgsExpressionNodeColumnRef : public QgsExpressionNode
450 {
451   public:
452 
453     /**
454      * Constructor for QgsExpressionNodeColumnRef, referencing the column
455      * with the specified \a name.
456      */
QgsExpressionNodeColumnRef(const QString & name)457     QgsExpressionNodeColumnRef( const QString &name )
458       : mName( name )
459       , mIndex( -1 )
460     {}
461 
462 #ifdef SIP_RUN
463     SIP_PYOBJECT __repr__();
464     % MethodCode
465     QString str = QStringLiteral( "<QgsExpressionNodeColumnRef: \"%1\">" ).arg( sipCpp->name() );
466     sipRes = PyUnicode_FromString( str.toUtf8().constData() );
467     % End
468 #endif
469 
470     //! The name of the column.
471     QString name() const { return mName; }
472 
473     QgsExpressionNode::NodeType nodeType() const override;
474     bool prepareNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
475     QVariant evalNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
476     QString dump() const override;
477 
478     QSet<QString> referencedColumns() const override;
479     QSet<QString> referencedVariables() const override;
480     QSet<QString> referencedFunctions() const override;
481     QList<const QgsExpressionNode *> nodes( ) const override; SIP_SKIP
482 
483     bool needsGeometry() const override;
484 
485     QgsExpressionNode *clone() const override SIP_FACTORY;
486     bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const override;
487 
488   private:
489     QString mName;
490     int mIndex;
491 };
492 
493 /**
494  * \brief An expression node for CASE WHEN clauses.
495  * \ingroup core
496  */
497 class CORE_EXPORT QgsExpressionNodeCondition : public QgsExpressionNode
498 {
499   public:
500 
501     /**
502      * \brief Represents a "WHEN... THEN..." portation of a CASE WHEN clause in an expression.
503      * \ingroup core
504      */
505     class CORE_EXPORT WhenThen
506     {
507       public:
508 
509         /**
510          * A combination of when and then. Simple as that.
511          */
512         WhenThen( QgsExpressionNode *whenExp, QgsExpressionNode *thenExp );
513         ~WhenThen();
514 
515         //! WhenThen nodes cannot be copied.
516         WhenThen( const WhenThen &rh ) = delete;
517         //! WhenThen nodes cannot be copied.
518         WhenThen &operator=( const WhenThen &rh ) = delete;
519 
520         /**
521          * Gets a deep copy of this WhenThen combination.
522          */
523         QgsExpressionNodeCondition::WhenThen *clone() const SIP_FACTORY;
524 
525         /**
526          * The expression that makes the WHEN part of the condition.
527          * \return The expression node that makes the WHEN part of the condition check.
528          */
whenExp()529         QgsExpressionNode *whenExp() const { return mWhenExp; }
530 
531         /**
532          * The expression node that makes the THEN result part of the condition.
533          * \return The expression node that makes the THEN result part of the condition.
534          */
535 
thenExp()536         QgsExpressionNode *thenExp() const { return mThenExp; }
537 
538       private:
539 #ifdef SIP_RUN
540         WhenThen( const QgsExpressionNodeCondition::WhenThen &rh );
541 #endif
542         QgsExpressionNode *mWhenExp = nullptr;
543         QgsExpressionNode *mThenExp = nullptr;
544 
545         friend class QgsExpressionNodeCondition;
546     };
547     typedef QList<QgsExpressionNodeCondition::WhenThen *> WhenThenList;
548 
549     /**
550      * Create a new node with the given list of \a conditions and an optional \a elseExp expression.
551      */
552     QgsExpressionNodeCondition( QgsExpressionNodeCondition::WhenThenList *conditions, QgsExpressionNode *elseExp = nullptr );
553 
554     /**
555      * Create a new node with the given list of \a conditions and an optional \a elseExp expression.
556      */
557     QgsExpressionNodeCondition( const QgsExpressionNodeCondition::WhenThenList &conditions, QgsExpressionNode *elseExp = nullptr ) SIP_SKIP
mConditions(conditions)558   : mConditions( conditions )
559     , mElseExp( elseExp )
560     {}
561 
562     ~QgsExpressionNodeCondition() override;
563 
564     QgsExpressionNode::NodeType nodeType() const override;
565     QVariant evalNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
566     bool prepareNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
567     QString dump() const override;
568 
569     /**
570      * The list of WHEN THEN expression parts of the expression.
571      * \return The list of WHEN THEN expression parts of the expression.
572      */
conditions()573     WhenThenList conditions() const { return mConditions; }
574 
575     /**
576      * The ELSE expression used for the condition.
577      * \return The ELSE expression used for the condition.
578      */
elseExp()579     QgsExpressionNode *elseExp() const { return mElseExp; }
580 
581     QSet<QString> referencedColumns() const override;
582     QSet<QString> referencedVariables() const override;
583     QSet<QString> referencedFunctions() const override;
584 
585     QList<const QgsExpressionNode *> nodes() const override; SIP_SKIP
586 
587     bool needsGeometry() const override;
588     QgsExpressionNode *clone() const override SIP_FACTORY;
589     bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const override;
590 
591   private:
592     WhenThenList mConditions;
593     QgsExpressionNode *mElseExp = nullptr;
594 };
595 
596 
597 #endif // QGSEXPRESSIONNODEIMPL_H
598