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