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 "qgis_core.h" 20 #include <QMetaType> 21 #include <QStringList> 22 #include <QVariant> 23 #include <QList> 24 #include <QDomDocument> 25 #include <QCoreApplication> 26 #include <QSet> 27 #include <functional> 28 29 #include "qgis.h" 30 #include "qgsunittypes.h" 31 #include "qgsinterval.h" 32 #include "qgsexpressionnode.h" 33 34 class QgsFeature; 35 class QgsGeometry; 36 class QgsOgcUtils; 37 class QgsVectorLayer; 38 class QgsVectorDataProvider; 39 class QgsField; 40 class QgsFields; 41 class QgsDistanceArea; 42 class QDomElement; 43 class QgsExpressionContext; 44 class QgsExpressionPrivate; 45 class QgsExpressionFunction; 46 47 /** 48 * \ingroup core 49 * \brief Class for parsing and evaluation of expressions (formerly called "search strings"). 50 * The expressions try to follow both syntax and semantics of SQL expressions. 51 52 Usage: 53 \code{.py} 54 exp = QgsExpression("gid*2 > 10 and type not in ('D','F')") 55 if exp.hasParserError(): 56 # show error message with parserErrorString() and exit 57 58 result = exp.evaluate(feature, fields) 59 if exp.hasEvalError(): 60 # show error message with evalErrorString() 61 else: 62 # examine the result 63 \endcode 64 65 \section value_logic Three Value Logic 66 67 Similarly to SQL, this class supports three-value logic: true/false/unknown. 68 Unknown value may be a result of operations with missing data (NULL). Please note 69 that NULL is different value than zero or an empty string. For example 70 3 > NULL returns unknown. 71 72 There is no special (three-value) 'boolean' type: true/false is represented as 73 1/0 integer, unknown value is represented the same way as NULL values: NULL QVariant. 74 75 \section performance Performance 76 77 For better performance with many evaluations you may first call prepare(fields) function 78 to find out indices of columns and then repeatedly call evaluate(feature). 79 80 \section type_conversion Type conversion 81 82 Operators and functions that expect arguments to be of a particular 83 type automatically convert the arguments to that type, e.g. sin('2.1') will convert 84 the argument to a double, length(123) will first convert the number to a string. 85 Explicit conversion can be achieved with to_int, to_real, to_string functions. 86 If implicit or explicit conversion is invalid, the evaluation returns an error. 87 Comparison operators do numeric comparison in case both operators are numeric (int/double) 88 or they can be converted to numeric types. 89 90 \section implicit_sharing Implicit sharing 91 92 This class is implicitly shared, copying has a very low overhead. 93 It is normally preferable to call `QgsExpression( otherExpression )` instead of 94 `QgsExpression( otherExpression.expression() )`. A deep copy will only be made 95 when prepare() is called. For usage this means mainly, that you should 96 normally keep an unprepared master copy of a QgsExpression and whenever using it 97 with a particular QgsFeatureIterator copy it just before and prepare it using the 98 same context as the iterator. 99 100 Implicit sharing was added in 2.14 101 102 */ 103 104 class CORE_EXPORT QgsExpression 105 { 106 Q_DECLARE_TR_FUNCTIONS( QgsExpression ) 107 public: 108 109 /** 110 * Details about any parser errors that were found when parsing the expression. 111 * \since QGIS 3.0 112 */ 113 struct CORE_EXPORT ParserError 114 { 115 enum ParserErrorType 116 { 117 Unknown = 0, //!< Unknown error type. 118 FunctionUnknown = 1, //!< Function was unknown. 119 FunctionWrongArgs = 2, //!< Function was called with the wrong number of args. 120 FunctionInvalidParams = 3, //!< Function was called with invalid args. 121 FunctionNamedArgsError = 4 //!< Non named function arg used after named arg. 122 }; 123 124 /** 125 * The type of parser error that was found. 126 */ 127 ParserErrorType errorType = ParserErrorType::Unknown; 128 129 /** 130 * The message for the error at this location. 131 */ 132 QString errorMsg; 133 134 /** 135 * The first line that contained the error in the parser. 136 * Depending on the error sometimes this doesn't mean anything. 137 */ 138 int firstLine = 0; 139 140 /** 141 * The first column that contained the error in the parser. 142 * Depending on the error sometimes this doesn't mean anything. 143 */ 144 int firstColumn = 0; 145 146 /** 147 * The last line that contained the error in the parser. 148 */ 149 int lastLine = 0; 150 151 /** 152 * The last column that contained the error in the parser. 153 */ 154 int lastColumn = 0; 155 }; 156 157 /** 158 * Creates a new expression based on the provided string. 159 * The string will immediately be parsed. For optimization 160 * prepare() should always be called before every 161 * loop in which this expression is used. 162 */ 163 QgsExpression( const QString &expr ); 164 165 /** 166 * Create a copy of this expression. This is preferred 167 * over recreating an expression from a string since 168 * it does not need to be re-parsed. 169 */ 170 QgsExpression( const QgsExpression &other ); 171 172 /** 173 * Create a copy of this expression. This is preferred 174 * over recreating an expression from a string since 175 * it does not need to be re-parsed. 176 */ 177 QgsExpression &operator=( const QgsExpression &other ); 178 179 /** 180 * Automatically convert this expression to a string where requested. 181 * 182 * \since QGIS 3.0 183 */ 184 operator QString() const SIP_SKIP; 185 186 /** 187 * Create an empty expression. 188 * 189 * \since QGIS 3.0 190 */ 191 QgsExpression(); 192 193 ~QgsExpression(); 194 195 /** 196 * Compares two expressions. The operator returns TRUE 197 * if the expression string is equal. 198 * 199 * \since QGIS 3.0 200 */ 201 bool operator==( const QgsExpression &other ) const; 202 203 /** 204 * Checks if this expression is valid. 205 * A valid expression could be parsed but does not necessarily evaluate properly. 206 * 207 * \since QGIS 3.0 208 */ 209 bool isValid() const; 210 211 //! Returns TRUE if an error occurred when parsing the input expression 212 bool hasParserError() const; 213 //! Returns parser error 214 QString parserErrorString() const; 215 216 /** 217 * Returns parser error details including location of error. 218 * \since QGIS 3.0 219 */ 220 QList<QgsExpression::ParserError> parserErrors() const; 221 222 /** 223 * Returns the root node of the expression. 224 * 225 * The root node is NULLPTR if parsing has failed. 226 */ 227 const QgsExpressionNode *rootNode() const; 228 229 /** 230 * Gets the expression ready for evaluation - find out column indexes. 231 * \param context context for preparing expression 232 * \since QGIS 2.12 233 */ 234 bool prepare( const QgsExpressionContext *context ); 235 236 /** 237 * Gets list of columns referenced by the expression. 238 * 239 * \note If the returned list contains the QgsFeatureRequest::AllAttributes constant then 240 * all attributes from the layer are required for evaluation of the expression. 241 * QgsFeatureRequest::setSubsetOfAttributes automatically handles this case. 242 * 243 * \see referencedAttributeIndexes() 244 */ 245 QSet<QString> referencedColumns() const; 246 247 /** 248 * Returns a list of all variables which are used in this expression. 249 * If the list contains a NULL QString, there is a variable name used 250 * which is determined at runtime. 251 * 252 * \since QGIS 3.0 253 */ 254 QSet<QString> referencedVariables() const; 255 256 /** 257 * Returns a list of the names of all functions which are used in this expression. 258 * 259 * \since QGIS 3.2 260 */ 261 QSet<QString> referencedFunctions() const; 262 263 #ifndef SIP_RUN 264 265 /** 266 * Returns a list of all nodes which are used in this expression 267 * 268 * \note not available in Python bindings 269 * \since QGIS 3.2 270 */ 271 QList<const QgsExpressionNode *> nodes( ) const; 272 273 /** 274 * Returns a list of all nodes of the given class which are used in this expression 275 * 276 * \note not available in Python bindings 277 * \since QGIS 3.2 278 */ 279 template <class T> findNodes()280 QList<const T *> findNodes( ) const 281 { 282 QList<const T *> lst; 283 const QList<const QgsExpressionNode *> allNodes( nodes() ); 284 for ( const auto &node : allNodes ) 285 { 286 const T *n = dynamic_cast<const T *>( node ); 287 if ( n ) 288 lst << n; 289 } 290 return lst; 291 } 292 #endif 293 294 /** 295 * Returns a list of field name indexes obtained from the provided fields. 296 * 297 * \since QGIS 3.0 298 */ 299 QSet<int> referencedAttributeIndexes( const QgsFields &fields ) const; 300 301 //! Returns TRUE if the expression uses feature geometry for some computation 302 bool needsGeometry() const; 303 304 // evaluation 305 306 /** 307 * Evaluate the feature and return the result. 308 * \note this method does not expect that prepare() has been called on this instance 309 * \since QGIS 2.12 310 */ 311 QVariant evaluate(); 312 313 /** 314 * Evaluate the expression against the specified context and return the result. 315 * \param context context for evaluating expression 316 * \note prepare() should be called before calling this method. 317 * \since QGIS 2.12 318 */ 319 QVariant evaluate( const QgsExpressionContext *context ); 320 321 //! Returns TRUE if an error occurred when evaluating last input 322 bool hasEvalError() const; 323 //! Returns evaluation error 324 QString evalErrorString() const; 325 //! Sets evaluation error (used internally by evaluation functions) 326 void setEvalErrorString( const QString &str ); 327 328 /** 329 * Checks whether an expression consists only of a single field reference 330 * \since QGIS 2.9 331 */ 332 bool isField() const; 333 334 /** 335 * Tests whether a string is a valid expression. 336 * \param text string to test 337 * \param context optional expression context 338 * \param errorMessage will be filled with any error message from the validation 339 * \returns TRUE if string is a valid expression 340 * \since QGIS 2.12 341 */ 342 static bool checkExpression( const QString &text, const QgsExpressionContext *context, QString &errorMessage SIP_OUT ); 343 344 /** 345 * Set the expression string, will reset the whole internal structure. 346 * 347 * \since QGIS 3.0 348 */ 349 void setExpression( const QString &expression ); 350 351 /** 352 * Returns the original, unmodified expression string. 353 * If there was none supplied because it was constructed by sole 354 * API calls, dump() will be used to create one instead. 355 */ 356 QString expression() const; 357 358 /** 359 * Returns an expression string, constructed from the internal 360 * abstract syntax tree. This does not contain any nice whitespace 361 * formatting or comments. In general it is preferable to use 362 * expression() instead. 363 */ 364 QString dump() const; 365 366 /** 367 * Returns calculator used for distance and area calculations 368 * (used by $length, $area and $perimeter functions only) 369 * \see setGeomCalculator() 370 * \see distanceUnits() 371 * \see areaUnits() 372 */ 373 QgsDistanceArea *geomCalculator(); 374 375 /** 376 * Sets the geometry calculator used for distance and area calculations in expressions. 377 * (used by $length, $area and $perimeter functions only). 378 * If the geometry calculator is set to NULLPTR (default), prepare() will read variables 379 * from the expression context ("project_ellipsoid", "_project_transform_context" and 380 * "_layer_crs") to build a geometry calculator. 381 * If these variables does not exist and if setGeomCalculator() is not called, 382 * all distance and area calculations are performed using simple 383 * Cartesian methods (ie no ellipsoidal calculations). 384 * \param calc geometry calculator. Ownership is not transferred. Set to NULLPTR to force 385 * Cartesian calculations. 386 * \see geomCalculator() 387 */ 388 void setGeomCalculator( const QgsDistanceArea *calc ); 389 390 /** 391 * Returns the desired distance units for calculations involving geomCalculator(), e.g., "$length" and "$perimeter". 392 * \note distances are only converted when a geomCalculator() has been set 393 * \see setDistanceUnits() 394 * \see areaUnits() 395 * \since QGIS 2.14 396 */ 397 QgsUnitTypes::DistanceUnit distanceUnits() const; 398 399 /** 400 * Sets the desired distance units for calculations involving geomCalculator(), e.g., "$length" and "$perimeter". 401 * If distance units are set to QgsUnitTypes::DistanceUnknownUnit (default), prepare() will read 402 * variables from the expression context ("project_distance_units") to determine distance units. 403 * \note distances are only converted when a geomCalculator() has been set 404 * \see distanceUnits() 405 * \see setAreaUnits() 406 * \since QGIS 2.14 407 */ 408 void setDistanceUnits( QgsUnitTypes::DistanceUnit unit ); 409 410 /** 411 * Returns the desired areal units for calculations involving geomCalculator(), e.g., "$area". 412 * \note areas are only converted when a geomCalculator() has been set 413 * \see setAreaUnits() 414 * \see distanceUnits() 415 * \since QGIS 2.14 416 */ 417 QgsUnitTypes::AreaUnit areaUnits() const; 418 419 /** 420 * Sets the desired areal units for calculations involving geomCalculator(), e.g., "$area". 421 * If distance units are set to QgsUnitTypes::AreaUnknownUnit (default), prepare() will read 422 * variables from the expression context ("project_distance_units") to determine distance units. 423 * \note areas are only converted when a geomCalculator() has been set 424 * \see areaUnits() 425 * \see setDistanceUnits() 426 * \since QGIS 2.14 427 */ 428 void setAreaUnits( QgsUnitTypes::AreaUnit unit ); 429 430 /** 431 * This function replaces each expression between [% and %] 432 * in the string with the result of its evaluation with the specified context 433 * 434 * Additional substitutions can be passed through the substitutionMap parameter 435 * \param action The source string in which placeholders should be replaced. 436 * \param context Expression context 437 * \param distanceArea Optional QgsDistanceArea. If specified, the QgsDistanceArea is used for distance 438 * and area conversion 439 * \since QGIS 2.12 440 */ 441 static QString replaceExpressionText( const QString &action, const QgsExpressionContext *context, 442 const QgsDistanceArea *distanceArea = nullptr ); 443 444 /** 445 * This function returns variables in each expression between [% and %]. 446 * 447 * \param text The source string in which variables should be searched. 448 * 449 * \since QGIS 3.2 450 */ 451 static QSet<QString> referencedVariables( const QString &text ); 452 453 /** 454 * Attempts to evaluate a text string as an expression to a resultant double 455 * value. 456 * \param text text to evaluate as expression 457 * \param fallbackValue value to return if text can not be evaluated as a double 458 * \returns evaluated double value, or fallback value 459 * \note this method is inefficient for bulk evaluation of expressions, it is intended 460 * for one-off evaluations only. 461 * \since QGIS 2.7 462 */ 463 static double evaluateToDouble( const QString &text, double fallbackValue ); 464 465 enum SpatialOperator 466 { 467 soBbox, 468 soIntersects, 469 soContains, 470 soCrosses, 471 soEquals, 472 soDisjoint, 473 soOverlaps, 474 soTouches, 475 soWithin, 476 }; 477 478 static const QList<QgsExpressionFunction *> &Functions(); 479 480 static const QStringList &BuiltinFunctions(); 481 482 /** 483 * Registers a function to the expression engine. This is required to allow expressions to utilize the function. 484 * \param function function to register 485 * \param transferOwnership set to TRUE to transfer ownership of function to expression engine 486 * \returns TRUE on successful registration 487 * \see unregisterFunction 488 */ 489 static bool registerFunction( QgsExpressionFunction *function, bool transferOwnership = false ); 490 491 /** 492 * Unregisters a function from the expression engine. The function will no longer be usable in expressions. 493 * \param name function name 494 * \see registerFunction 495 */ 496 static bool unregisterFunction( const QString &name ); 497 498 /** 499 * Deletes all registered functions whose ownership have been transferred to the expression engine. 500 * \since QGIS 2.12 501 */ 502 static void cleanRegisteredFunctions(); 503 504 //! tells whether the identifier is a name of existing function 505 static bool isFunctionName( const QString &name ); 506 507 //! Returns index of the function in Functions array 508 static int functionIndex( const QString &name ); 509 510 /** 511 * Returns the number of functions defined in the parser 512 * \returns The number of function defined in the parser. 513 */ 514 static int functionCount(); 515 516 /** 517 * Returns a quoted column reference (in double quotes) 518 * \see quotedString() 519 * \see quotedValue() 520 */ 521 static QString quotedColumnRef( QString name ); 522 523 /** 524 * Returns a quoted version of a string (in single quotes) 525 * \see quotedValue() 526 * \see quotedColumnRef() 527 */ 528 static QString quotedString( QString text ); 529 530 /** 531 * Returns a string representation of a literal value, including appropriate 532 * quotations where required. 533 * \param value value to convert to a string representation 534 * \see quotedString() 535 * \see quotedColumnRef() 536 * \since QGIS 2.14 537 */ 538 static QString quotedValue( const QVariant &value ); 539 540 /** 541 * Returns a string representation of a literal value, including appropriate 542 * quotations where required. 543 * \param value value to convert to a string representation 544 * \param type value type 545 * \see quotedString() 546 * \see quotedColumnRef() 547 * \since QGIS 2.14 548 */ 549 static QString quotedValue( const QVariant &value, QVariant::Type type ); 550 551 ////// 552 553 /** 554 * Returns the help text for a specified function. 555 * \param name function name 556 * \see variableHelpText() 557 * \see formatVariableHelp() 558 */ 559 static QString helpText( QString name ); 560 561 /** 562 * Returns a string list of search tags for a specified function. 563 * \param name function name 564 * \since QGIS 3.12 565 */ 566 static QStringList tags( const QString &name ); 567 568 /** 569 * Returns the help text for a specified variable. 570 * \param variableName name of variable 571 * \see helpText() 572 * \since QGIS 2.12 573 */ 574 static QString variableHelpText( const QString &variableName ); 575 576 /** 577 * Returns formatted help text for a variable. 578 * \param description translated description of variable 579 * \param showValue set to TRUE to include current value of variable in help text 580 * \param value current value of variable to show in help text 581 * \see helpText() 582 * \see variableHelpText() 583 * \since QGIS 3.0 584 */ 585 static QString formatVariableHelp( const QString &description, bool showValue = true, const QVariant &value = QVariant() ); 586 587 /** 588 * Returns the translated name for a function group. 589 * \param group untranslated group name 590 */ 591 static QString group( const QString &group ); 592 593 /** 594 * Formats an expression result for friendly display to the user. Truncates the result to a sensible 595 * length, and presents text representations of non numeric/text types (e.g., geometries and features). 596 * \param value expression result to format 597 * \param htmlOutput set to TRUE to allow HTML formatting, or FALSE for plain text output 598 * \returns formatted string, may contain HTML formatting characters if \a htmlOutput is TRUE 599 * \since QGIS 2.14 600 */ 601 static QString formatPreviewString( const QVariant &value, bool htmlOutput = true ); 602 603 /** 604 * Create an expression allowing to evaluate if a field is equal to a 605 * value. The value may be null. 606 * \param fieldName the name of the field 607 * \param value the value of the field 608 * \returns the expression to evaluate field equality 609 * \since QGIS 3.0 610 */ 611 static QString createFieldEqualityExpression( const QString &fieldName, const QVariant &value ); 612 613 /** 614 * Returns TRUE if the given \a expression is a simple "field=value" type expression. 615 * 616 * \param expression expression to test 617 * \param field will be set to the field name if the expression is a field equality expression 618 * \param value will be set to the value if the expression is a field equality expression 619 * \returns TRUE if the expression is a field equality expression 620 * 621 * \since QGIS 3.18 622 */ 623 static bool isFieldEqualityExpression( const QString &expression, QString &field SIP_OUT, QVariant &value SIP_OUT ); 624 625 /** 626 * Attempts to reduce a list of expressions to a single "field IN (val1, val2, ... )" type expression. 627 * 628 * This will only be possible if all the input expressions form simple "field=value" OR "field IN (value1, value2)" expressions, and all 629 * reference the same field name. 630 * 631 * Returns TRUE if the given \a expressions could be converted to an IN type expression. 632 * 633 * \param expressions expressions to test 634 * \param result will be set to the calculated "field IN (...)" expression, wherever possible 635 * \returns TRUE if the expression was converted to a field IN type expression 636 * 637 * \since QGIS 3.18 638 */ 639 static bool attemptReduceToInClause( const QStringList &expressions, QString &result SIP_OUT ); 640 641 #ifdef SIP_RUN 642 SIP_PYOBJECT __repr__(); 643 % MethodCode 644 QString str = QStringLiteral( "<QgsExpression: '%1'>" ).arg( sipCpp->expression() ); 645 sipRes = PyUnicode_FromString( str.toUtf8().constData() ); 646 % End 647 #endif 648 649 private: 650 void initGeomCalculator( const QgsExpressionContext *context ); 651 652 /** 653 * Helper for implicit sharing. When called will create 654 * a new deep copy of this expression. 655 * 656 * \note not available in Python bindings 657 */ 658 void detach() SIP_SKIP; 659 660 QgsExpressionPrivate *d = nullptr; 661 662 //! \note not available in Python bindings 663 static void initFunctionHelp() SIP_SKIP; 664 //! \note not available in Python bindings 665 static void initVariableHelp() SIP_SKIP; 666 667 friend class QgsOgcUtils; 668 }; 669 670 Q_DECLARE_METATYPE( QgsExpression ) 671 672 #endif // QGSEXPRESSION_H 673