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