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