Modularize expressions

The file qgsexpressions.h has grown to one monolithic piece over the
years. This makes it hard to maintain and slows down compilation because
even small changes at one end will result in recompiling big parts of
the source tree. It also requires the compiler to keep track of all
these implementation details for said big parts of the source tree.

This splits this implementation into smaller pieces. There are soe API
changes connected to this, but since these can be considered
implementation details, on which not many plugins rely, this shouldn't
have a big impact on the ecosystem outside the source tree.
This commit is contained in:
Matthias Kuhn 2017-05-14 11:20:29 +02:00
parent ac50214347
commit ec40199862
52 changed files with 3965 additions and 3908 deletions

View File

@ -49,7 +49,6 @@
%Include qgseditorwidgetsetup.sip
%Include qgsellipsoidutils.sip
%Include qgserror.sip
%Include qgsexpression.sip
%Include qgsexpressioncontext.sip
%Include qgsexpressioncontextgenerator.sip
%Include qgsfeature.sip
@ -403,3 +402,8 @@
%Include geometry/qgstriangle.sip
%Include geometry/qgswkbtypes.sip
%Include geometry/qgswkbptr.sip
%Include expression/qgsexpression.sip
%Include expression/qgsexpressionnodeimpl.sip
%Include expression/qgsexpressionnode.sip
%Include expression/qgsexpressionfunction.sip

View File

@ -0,0 +1,514 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/expression/qgsexpression.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsExpression
{
%Docstring
Class for parsing and evaluation of expressions (formerly called "search strings").
The expressions try to follow both syntax and semantics of SQL expressions.
Usage:
\code{.cpp}
QgsExpression exp("gid*2 > 10 and type not in ('D','F'));
if (exp.hasParserError())
{
// show error message with parserErrorString() and exit
}
QVariant result = exp.evaluate(feature, fields);
if (exp.hasEvalError())
{
// show error message with evalErrorString()
}
else
{
// examine the result
}
\endcode
Three Value Logic
=================
Similarly to SQL, this class supports three-value logic: true/false/unknown.
Unknown value may be a result of operations with missing data (NULL). Please note
that NULL is different value than zero or an empty string. For example
3 > NULL returns unknown.
There is no special (three-value) 'boolean' type: true/false is represented as
1/0 integer, unknown value is represented the same way as NULL values: NULL QVariant.
Performance
===========
For better performance with many evaluations you may first call prepare(fields) function
to find out indices of columns and then repeatedly call evaluate(feature).
Type conversion
===============
Operators and functions that expect arguments to be of a particular
type automatically convert the arguments to that type, e.g. sin('2.1') will convert
the argument to a double, length(123) will first convert the number to a string.
Explicit conversion can be achieved with to_int, to_real, to_string functions.
If implicit or explicit conversion is invalid, the evaluation returns an error.
Comparison operators do numeric comparison in case both operators are numeric (int/double)
or they can be converted to numeric types.
Implicit sharing
================
This class is implicitly shared, copying has a very low overhead.
It is normally preferable to call `QgsExpression( otherExpression )` instead of
`QgsExpression( otherExpression.expression() )`. A deep copy will only be made
when prepare() is called. For usage this means mainly, that you should
normally keep an unprepared master copy of a QgsExpression and whenever using it
with a particular QgsFeatureIterator copy it just before and prepare it using the
same context as the iterator.
Implicit sharing was added in 2.14
%End
%TypeHeaderCode
#include "qgsexpression.h"
%End
public:
QgsExpression( const QString &expr );
%Docstring
Creates a new expression based on the provided string.
The string will immediately be parsed. For optimization
prepare() should always be called before every
loop in which this expression is used.
%End
QgsExpression( const QgsExpression &other );
%Docstring
Create a copy of this expression. This is preferred
over recreating an expression from a string since
it does not need to be re-parsed.
%End
QgsExpression();
%Docstring
Create an empty expression.
.. versionadded:: 3.0
%End
~QgsExpression();
bool operator==( const QgsExpression &other ) const;
%Docstring
Compares two expressions. The operator returns true
if the expression string is equal.
.. versionadded:: 3.0
:rtype: bool
%End
bool isValid() const;
%Docstring
Checks if this expression is valid.
A valid expression could be parsed but does not necessarily evaluate properly.
.. versionadded:: 3.0
:rtype: bool
%End
bool hasParserError() const;
%Docstring
Returns true if an error occurred when parsing the input expression
:rtype: bool
%End
QString parserErrorString() const;
%Docstring
Returns parser error
:rtype: str
%End
const QgsExpressionNode *rootNode() const;
%Docstring
Returns root node of the expression. Root node is null is parsing has failed
:rtype: QgsExpressionNode
%End
bool prepare( const QgsExpressionContext *context );
%Docstring
Get the expression ready for evaluation - find out column indexes.
\param context context for preparing expression
.. versionadded:: 2.12
:rtype: bool
%End
QSet<QString> referencedColumns() const;
%Docstring
Get list of columns referenced by the expression.
.. note::
If the returned list contains the QgsFeatureRequest.AllAttributes constant then
all attributes from the layer are required for evaluation of the expression.
QgsFeatureRequest.setSubsetOfAttributes automatically handles this case.
.. seealso:: referencedAttributeIndexes()
:rtype: set of str
%End
QSet<QString> referencedVariables() const;
%Docstring
Return a list of all variables which are used in this expression.
If the list contains a NULL QString, there is a variable name used
which is determined at runtime.
.. versionadded:: 3.0
:rtype: set of str
%End
QSet<int> referencedAttributeIndexes( const QgsFields &fields ) const;
%Docstring
Return a list of field name indexes obtained from the provided fields.
.. versionadded:: 3.0
:rtype: set of int
%End
bool needsGeometry() const;
%Docstring
Returns true if the expression uses feature geometry for some computation
:rtype: bool
%End
QVariant evaluate();
%Docstring
Evaluate the feature and return the result.
.. note::
this method does not expect that prepare() has been called on this instance
.. versionadded:: 2.12
:rtype: QVariant
%End
QVariant evaluate( const QgsExpressionContext *context );
%Docstring
Evaluate the expression against the specified context and return the result.
\param context context for evaluating expression
.. note::
prepare() should be called before calling this method.
.. versionadded:: 2.12
:rtype: QVariant
%End
bool hasEvalError() const;
%Docstring
Returns true if an error occurred when evaluating last input
:rtype: bool
%End
QString evalErrorString() const;
%Docstring
Returns evaluation error
:rtype: str
%End
void setEvalErrorString( const QString &str );
%Docstring
Set evaluation error (used internally by evaluation functions)
%End
bool isField() const;
%Docstring
Checks whether an expression consists only of a single field reference
.. versionadded:: 2.9
:rtype: bool
%End
static bool checkExpression( const QString &text, const QgsExpressionContext *context, QString &errorMessage /Out/ );
%Docstring
Tests whether a string is a valid expression.
\param text string to test
\param context optional expression context
\param errorMessage will be filled with any error message from the validation
:return: true if string is a valid expression
.. versionadded:: 2.12
:rtype: bool
%End
void setExpression( const QString &expression );
%Docstring
Set the expression string, will reset the whole internal structure.
.. versionadded:: 3.0
%End
QString expression() const;
%Docstring
API calls, dump() will be used to create one instead.
:rtype: str
%End
QString dump() const;
%Docstring
expression() instead.
:rtype: str
%End
QgsDistanceArea *geomCalculator();
%Docstring
Return calculator used for distance and area calculations
(used by $length, $area and $perimeter functions only)
.. seealso:: setGeomCalculator()
.. seealso:: distanceUnits()
.. seealso:: areaUnits()
:rtype: QgsDistanceArea
%End
void setGeomCalculator( const QgsDistanceArea *calc );
%Docstring
Sets the geometry calculator used for distance and area calculations in expressions.
(used by $length, $area and $perimeter functions only). By default, no geometry
calculator is set and all distance and area calculations are performed using simple
cartesian methods (ie no ellipsoidal calculations).
\param calc geometry calculator. Ownership is not transferred. Set to a None to force
cartesian calculations.
.. seealso:: geomCalculator()
%End
QgsUnitTypes::DistanceUnit distanceUnits() const;
%Docstring
Returns the desired distance units for calculations involving geomCalculator(), e.g., "$length" and "$perimeter".
.. note::
distances are only converted when a geomCalculator() has been set
.. versionadded:: 2.14
.. seealso:: setDistanceUnits()
.. seealso:: areaUnits()
:rtype: QgsUnitTypes.DistanceUnit
%End
void setDistanceUnits( QgsUnitTypes::DistanceUnit unit );
%Docstring
Sets the desired distance units for calculations involving geomCalculator(), e.g., "$length" and "$perimeter".
.. note::
distances are only converted when a geomCalculator() has been set
.. versionadded:: 2.14
.. seealso:: distanceUnits()
.. seealso:: setAreaUnits()
%End
QgsUnitTypes::AreaUnit areaUnits() const;
%Docstring
Returns the desired areal units for calculations involving geomCalculator(), e.g., "$area".
.. note::
areas are only converted when a geomCalculator() has been set
.. versionadded:: 2.14
.. seealso:: setAreaUnits()
.. seealso:: distanceUnits()
:rtype: QgsUnitTypes.AreaUnit
%End
void setAreaUnits( QgsUnitTypes::AreaUnit unit );
%Docstring
Sets the desired areal units for calculations involving geomCalculator(), e.g., "$area".
.. note::
areas are only converted when a geomCalculator() has been set
.. versionadded:: 2.14
.. seealso:: areaUnits()
.. seealso:: setDistanceUnits()
%End
static QString replaceExpressionText( const QString &action, const QgsExpressionContext *context,
const QgsDistanceArea *distanceArea = 0 );
%Docstring
This function replaces each expression between [% and %]
in the string with the result of its evaluation with the specified context
Additional substitutions can be passed through the substitutionMap parameter
\param action The source string in which placeholders should be replaced.
\param context Expression context
\param distanceArea Optional QgsDistanceArea. If specified, the QgsDistanceArea is used for distance
and area conversion
.. versionadded:: 2.12
:rtype: str
%End
static double evaluateToDouble( const QString &text, const double fallbackValue );
%Docstring
Attempts to evaluate a text string as an expression to a resultant double
value.
\param text text to evaluate as expression
\param fallbackValue value to return if text can not be evaluated as a double
:return: evaluated double value, or fallback value
.. versionadded:: 2.7
.. note::
this method is inefficient for bulk evaluation of expressions, it is intended
for one-off evaluations only.
:rtype: float
%End
enum SpatialOperator
{
soBbox,
soIntersects,
soContains,
soCrosses,
soEquals,
soDisjoint,
soOverlaps,
soTouches,
soWithin,
};
static const QList<QgsExpressionFunction *> &Functions();
%Docstring
:rtype: list of QgsExpressionFunction
%End
static const QStringList &BuiltinFunctions();
%Docstring
:rtype: list of str
%End
static bool registerFunction( QgsExpressionFunction *function, bool transferOwnership = false );
%Docstring
Registers a function to the expression engine. This is required to allow expressions to utilize the function.
\param function function to register
\param transferOwnership set to true to transfer ownership of function to expression engine
:return: true on successful registration
.. seealso:: unregisterFunction
:rtype: bool
%End
static bool unregisterFunction( const QString &name );
%Docstring
Unregisters a function from the expression engine. The function will no longer be usable in expressions.
\param name function name
.. seealso:: registerFunction
:rtype: bool
%End
static void cleanRegisteredFunctions();
%Docstring
Deletes all registered functions whose ownership have been transferred to the expression engine.
.. versionadded:: 2.12
%End
static bool isFunctionName( const QString &name );
%Docstring
tells whether the identifier is a name of existing function
:rtype: bool
%End
static int functionIndex( const QString &name );
%Docstring
return index of the function in Functions array
:rtype: int
%End
static int functionCount();
%Docstring
Returns the number of functions defined in the parser
:return: The number of function defined in the parser.
:rtype: int
%End
static QString quotedColumnRef( QString name );
%Docstring
Returns a quoted column reference (in double quotes)
.. seealso:: quotedString()
.. seealso:: quotedValue()
:rtype: str
%End
static QString quotedString( QString text );
%Docstring
Returns a quoted version of a string (in single quotes)
.. seealso:: quotedValue()
.. seealso:: quotedColumnRef()
:rtype: str
%End
static QString quotedValue( const QVariant &value );
%Docstring
Returns a string representation of a literal value, including appropriate
quotations where required.
\param value value to convert to a string representation
.. versionadded:: 2.14
.. seealso:: quotedString()
.. seealso:: quotedColumnRef()
:rtype: str
%End
static QString quotedValue( const QVariant &value, QVariant::Type type );
%Docstring
Returns a string representation of a literal value, including appropriate
quotations where required.
\param value value to convert to a string representation
\param type value type
.. versionadded:: 2.14
.. seealso:: quotedString()
.. seealso:: quotedColumnRef()
:rtype: str
%End
static QString helpText( QString name );
%Docstring
Returns the help text for a specified function.
\param name function name
.. seealso:: variableHelpText()
:rtype: str
%End
static QString variableHelpText( const QString &variableName, bool showValue = true, const QVariant &value = QVariant() );
%Docstring
Returns the help text for a specified variable.
\param variableName name of variable
\param showValue set to true to include current value of variable in help text
\param value current value of variable to show in help text
.. seealso:: helpText()
.. versionadded:: 2.12
:rtype: str
%End
static QString group( const QString &group );
%Docstring
Returns the translated name for a function group.
\param group untranslated group name
:rtype: str
%End
static QString formatPreviewString( const QVariant &value );
%Docstring
Formats an expression result for friendly display to the user. Truncates the result to a sensible
length, and presents text representations of non numeric/text types (e.g., geometries and features).
\param value expression result to format
:return: formatted string, may contain HTML formatting characters
.. versionadded:: 2.14
:rtype: str
%End
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/expression/qgsexpression.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -0,0 +1,286 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/expression/qgsexpressionfunction.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsExpressionFunction
{
%Docstring
A abstract base class for defining QgsExpression functions.
%End
%TypeHeaderCode
#include "qgsexpressionfunction.h"
%End
public:
class Parameter
{
%Docstring
Represents a single parameter passed to a function.
.. versionadded:: 2.16
%End
%TypeHeaderCode
#include "qgsexpressionfunction.h"
%End
public:
Parameter( const QString &name,
bool optional = false,
const QVariant &defaultValue = QVariant() );
%Docstring
Constructor for Parameter.
\param name parameter name, used when named parameter are specified in an expression
\param optional set to true if parameter should be optional
\param defaultValue default value to use for optional parameters
%End
QString name() const;
%Docstring
Returns the name of the parameter.
:rtype: str
%End
bool optional() const;
%Docstring
Returns true if the parameter is optional.
:rtype: bool
%End
QVariant defaultValue() const;
%Docstring
Returns the default value for the parameter.
:rtype: QVariant
%End
bool operator==( const QgsExpressionFunction::Parameter &other ) const;
%Docstring
:rtype: bool
%End
};
typedef QList< QgsExpressionFunction::Parameter > ParameterList;
QgsExpressionFunction( const QString &fnname,
int params,
const QString &group,
const QString &helpText = QString(),
bool lazyEval = false,
bool handlesNull = false,
bool isContextual = false );
%Docstring
Constructor for function which uses unnamed parameters
%End
QgsExpressionFunction( const QString &fnname,
int params,
const QStringList &groups,
const QString &helpText = QString(),
bool lazyEval = false,
bool handlesNull = false,
bool isContextual = false );
%Docstring
Constructor for function which uses unnamed parameters and group list
.. versionadded:: 3.0
%End
QgsExpressionFunction( const QString &fnname,
const QgsExpressionFunction::ParameterList &params,
const QString &group,
const QString &helpText = QString(),
bool lazyEval = false,
bool handlesNull = false,
bool isContextual = false );
%Docstring
Constructor for function which uses named parameter list.
.. versionadded:: 2.16
%End
QgsExpressionFunction( const QString &fnname,
const QgsExpressionFunction::ParameterList &params,
const QStringList &groups,
const QString &helpText = QString(),
bool lazyEval = false,
bool handlesNull = false,
bool isContextual = false );
%Docstring
Constructor for function which uses named parameter list and group list.
.. versionadded:: 3.0
%End
virtual ~QgsExpressionFunction();
QString name() const;
%Docstring
The name of the function.
:rtype: str
%End
int params() const;
%Docstring
The number of parameters this function takes.
:rtype: int
%End
int minParams() const;
%Docstring
The minimum number of parameters this function takes.
:rtype: int
%End
const QgsExpressionFunction::ParameterList &parameters() const;
%Docstring
Returns the list of named parameters for the function, if set.
.. versionadded:: 2.16
:rtype: QgsExpressionFunction.ParameterList
%End
virtual bool usesGeometry( const QgsExpressionNodeFunction *node ) const;
%Docstring
Does this function use a geometry object.
:rtype: bool
%End
virtual QStringList aliases() const;
%Docstring
Returns a list of possible aliases for the function. These include
other permissible names for the function, e.g., deprecated names.
:return: list of known aliases
.. versionadded:: 2.9
:rtype: list of str
%End
bool lazyEval() const;
%Docstring
True if this function should use lazy evaluation. Lazy evaluation functions take QgsExpression.Node objects
rather than the node results when called. You can use node->eval(parent, feature) to evaluate the node and return the result
Functions are non lazy default and will be given the node return value when called.
:rtype: bool
%End
virtual bool isStatic( const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) const;
%Docstring
Will be called during prepare to determine if the function is static.
A function is static if it will return the same value for every feature with different
attributes and/or geometry.
By default this will return true, if all arguments that have been passed to the function
are also static.
.. versionadded:: 3.0
:rtype: bool
%End
virtual bool prepare( const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) const;
%Docstring
This will be called during the prepare step() of an expression if it is not static.
This can be used by functions to do any preparation steps that might help to speedup the upcoming
evaluation.
.. versionadded:: 3.0
:rtype: bool
%End
virtual QSet<QString> referencedColumns( const QgsExpressionNodeFunction *node ) const;
%Docstring
Returns a set of field names which are required for this function.
May contain QgsFeatureRequest.AllAttributes to signal that all
attributes are required.
If in doubt this will return more fields than strictly required.
.. versionadded:: 3.0
:rtype: set of str
%End
bool isContextual() const;
%Docstring
Returns whether the function is only available if provided by a QgsExpressionContext object.
.. versionadded:: 2.12
:rtype: bool
%End
virtual bool isDeprecated() const;
%Docstring
Returns true if the function is deprecated and should not be presented as a valid option
to users in expression builders.
.. versionadded:: 3.0
:rtype: bool
%End
QString group() const;
%Docstring
Returns the first group which the function belongs to.
.. note::
consider using groups() instead, as some functions naturally belong in multiple groups
:rtype: str
%End
QStringList groups() const;
%Docstring
Returns a list of the groups the function belongs to.
.. versionadded:: 3.0
.. seealso:: group()
:rtype: list of str
%End
const QString helpText() const;
%Docstring
The help text for the function.
:rtype: str
%End
virtual QVariant func( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent ) = 0;
%Docstring
Returns result of evaluating the function.
\param values list of values passed to the function
\param context context expression is being evaluated against
\param parent parent expression
:return: result of function
:rtype: QVariant
%End
bool operator==( const QgsExpressionFunction &other ) const;
%Docstring
:rtype: bool
%End
virtual bool handlesNull() const;
%Docstring
:rtype: bool
%End
protected:
static bool allParamsStatic( const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context );
%Docstring
This will return true if all the params for the provided function ``node`` are static within the
constraints imposed by the ``context`` within the given ``parent``.
This can be used as callback for custom implementations of subclasses. It is the default for implementation
for StaticFunction.isStatic.
.. versionadded:: 3.0
:rtype: bool
%End
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/expression/qgsexpressionfunction.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -0,0 +1,250 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/expression/qgsexpressionnode.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsExpressionNode /Abstract/
{
%Docstring
Abstract base class for all nodes that can appear in an expression.
%End
%TypeHeaderCode
#include "qgsexpressionnode.h"
%End
%ConvertToSubClassCode
switch ( sipCpp->nodeType() )
{
case QgsExpressionNode::ntUnaryOperator:
sipType = sipType_QgsExpressionNodeUnaryOperator;
break;
case QgsExpressionNode::ntBinaryOperator:
sipType = sipType_QgsExpressionNodeBinaryOperator;
break;
case QgsExpressionNode::ntInOperator:
sipType = sipType_QgsExpressionNodeInOperator;
break;
case QgsExpressionNode::ntFunction:
sipType = sipType_QgsExpressionNodeFunction;
break;
case QgsExpressionNode::ntLiteral:
sipType = sipType_QgsExpressionNodeLiteral;
break;
case QgsExpressionNode::ntColumnRef:
sipType = sipType_QgsExpressionNodeColumnRef;
break;
case QgsExpressionNode::ntCondition:
sipType = sipType_QgsExpressionNodeCondition;
break;
default:
sipType = 0;
break;
}
%End
public:
enum NodeType
{
ntUnaryOperator,
ntBinaryOperator,
ntInOperator,
ntFunction,
ntLiteral,
ntColumnRef,
ntCondition
};
struct NamedNode
{
public:
NamedNode( const QString &name, QgsExpressionNode *node );
%Docstring
Constructor for NamedNode
\param name node name
\param node node
%End
QString name;
%Docstring
Node name
%End
QgsExpressionNode *node;
%Docstring
Node
%End
};
class NodeList
{
public:
virtual ~NodeList();
void append( QgsExpressionNode *node /Transfer/ );
%Docstring
Takes ownership of the provided node
%End
void append( QgsExpressionNode::NamedNode *node /Transfer/ );
%Docstring
Adds a named node. Takes ownership of the provided node.
.. versionadded:: 2.16
%End
int count() const;
%Docstring
Returns the number of nodes in the list.
:rtype: int
%End
bool hasNamedNodes() const;
%Docstring
.. versionadded:: 2.16
:rtype: bool
%End
QList<QgsExpressionNode *> list();
%Docstring
Get a list of all the nodes.
:rtype: list of QgsExpressionNode
%End
QgsExpressionNode *at( int i );
%Docstring
Get the node at position i in the list.
.. versionadded:: 3.0
:rtype: QgsExpressionNode
%End
QStringList names() const;
%Docstring
.. versionadded:: 2.16
:rtype: list of str
%End
NodeList *clone() const;
%Docstring
Creates a deep copy of this list. Ownership is transferred to the caller
:rtype: NodeList
%End
virtual QString dump() const;
%Docstring
:rtype: str
%End
public:
};
virtual ~QgsExpressionNode();
virtual QgsExpressionNode::NodeType nodeType() const = 0;
%Docstring
Get the type of this node.
:return: The type of this node
:rtype: QgsExpressionNode.NodeType
%End
virtual QString dump() const = 0;
%Docstring
Dump this node into a serialized (part) of an expression.
The returned expression does not necessarily literally match
the original expression, it's just guaranteed to behave the same way.
:rtype: str
%End
QVariant eval( QgsExpression *parent, const QgsExpressionContext *context );
%Docstring
Evaluate this node with the given context and parent.
This will return a cached value if it has been determined to be static
during the prepare() execution.
.. versionadded:: 2.12
:rtype: QVariant
%End
virtual QgsExpressionNode *clone() const = 0;
%Docstring
Generate a clone of this node.
Ownership is transferred to the caller.
:return: a deep copy of this node.
:rtype: QgsExpressionNode
%End
virtual QSet<QString> referencedColumns() const = 0;
%Docstring
Abstract virtual method which returns a list of columns required to
evaluate this node.
When reimplementing this, you need to return any column that is required to
evaluate this node and in addition recursively collect all the columns required
to evaluate child nodes.
:return: A list of columns required to evaluate this expression
:rtype: set of str
%End
virtual QSet<QString> referencedVariables() const = 0;
%Docstring
Return a set of all variables which are used in this expression.
:rtype: set of str
%End
virtual bool needsGeometry() const = 0;
%Docstring
Abstract virtual method which returns if the geometry is required to evaluate
this expression.
This needs to call `needsGeometry()` recursively on any child nodes.
:return: true if a geometry is required to evaluate this expression
:rtype: bool
%End
virtual bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const = 0;
%Docstring
Returns true if this node can be evaluated for a static value. This is used during
the prepare() step and in case it returns true, the value of this node will already
be evaluated and the result cached (and therefore not re-evaluated in subsequent calls
to eval()). In case this returns true, prepareNode() will never be called.
.. versionadded:: 3.0
:rtype: bool
%End
bool prepare( QgsExpression *parent, const QgsExpressionContext *context );
%Docstring
Prepare this node for evaluation.
This will check if the node content is static and in this case cache the value.
If it's not static it will call prepareNode() to allow the node to do initialization
work like for example resolving a column name to an attribute index.
.. versionadded:: 2.12
:rtype: bool
%End
protected:
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/expression/qgsexpressionnode.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -0,0 +1,355 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/expression/qgsexpressionnodeimpl.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsExpressionNodeUnaryOperator : QgsExpressionNode
{
%Docstring
A unary node is either negative as in boolean (not) or as in numbers (minus).
%End
%TypeHeaderCode
#include "qgsexpressionnodeimpl.h"
%End
public:
enum UnaryOperator
{
uoNot,
uoMinus,
};
QgsExpressionNodeUnaryOperator( QgsExpressionNodeUnaryOperator::UnaryOperator op, QgsExpressionNode *operand /Transfer/ );
%Docstring
A node unary operator is modifying the value of ``operand`` by negating it with ``op``.
%End
~QgsExpressionNodeUnaryOperator();
QgsExpressionNodeUnaryOperator::UnaryOperator op() const;
%Docstring
:rtype: QgsExpressionNodeUnaryOperator.UnaryOperator
%End
QgsExpressionNode *operand() const;
%Docstring
:rtype: QgsExpressionNode
%End
virtual QgsExpressionNode::NodeType nodeType() const;
virtual bool prepareNode( QgsExpression *parent, const QgsExpressionContext *context );
virtual QVariant evalNode( QgsExpression *parent, const QgsExpressionContext *context );
virtual QString dump() const;
virtual QSet<QString> referencedColumns() const;
virtual QSet<QString> referencedVariables() const;
virtual bool needsGeometry() const;
virtual QgsExpressionNode *clone() const;
virtual bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const;
QString text() const;
%Docstring
Returns a the name of this operator without the operands.
I.e. "NOT" or "-"
:rtype: str
%End
};
class QgsExpressionNodeBinaryOperator : QgsExpressionNode
{
%TypeHeaderCode
#include "qgsexpressionnodeimpl.h"
%End
public:
enum BinaryOperator
{
// logical
boOr,
boAnd,
// comparison
boEQ,
boNE,
boLE,
boGE,
boLT,
boGT,
boRegexp,
boLike,
boNotLike,
boILike,
boNotILike,
boIs,
boIsNot,
// math
boPlus,
boMinus,
boMul,
boDiv,
boIntDiv,
boMod,
boPow,
// strings
boConcat,
};
QgsExpressionNodeBinaryOperator( QgsExpressionNodeBinaryOperator::BinaryOperator op, QgsExpressionNode *opLeft /Transfer/, QgsExpressionNode *opRight /Transfer/ );
%Docstring
Binary combination of the left and the right with op.
%End
~QgsExpressionNodeBinaryOperator();
QgsExpressionNodeBinaryOperator::BinaryOperator op() const;
%Docstring
:rtype: QgsExpressionNodeBinaryOperator.BinaryOperator
%End
QgsExpressionNode *opLeft() const;
%Docstring
:rtype: QgsExpressionNode
%End
QgsExpressionNode *opRight() const;
%Docstring
:rtype: QgsExpressionNode
%End
virtual QgsExpressionNode::NodeType nodeType() const;
virtual bool prepareNode( QgsExpression *parent, const QgsExpressionContext *context );
virtual QVariant evalNode( QgsExpression *parent, const QgsExpressionContext *context );
virtual QString dump() const;
virtual QSet<QString> referencedColumns() const;
virtual QSet<QString> referencedVariables() const;
virtual bool needsGeometry() const;
virtual QgsExpressionNode *clone() const;
virtual bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const;
int precedence() const;
%Docstring
:rtype: int
%End
bool leftAssociative() const;
%Docstring
:rtype: bool
%End
QString text() const;
%Docstring
Returns a the name of this operator without the operands.
I.e. "AND", "OR", ...
:rtype: str
%End
};
class QgsExpressionNodeInOperator : QgsExpressionNode
{
%TypeHeaderCode
#include "qgsexpressionnodeimpl.h"
%End
public:
QgsExpressionNodeInOperator( QgsExpressionNode *node /Transfer/, QgsExpressionNode::NodeList *list /Transfer/, bool notin = false );
%Docstring
This node tests if the result of ``node`` is in the result of ``list``. Optionally it can be inverted with ``notin`` which by default is false.
%End
virtual ~QgsExpressionNodeInOperator();
QgsExpressionNode *node() const;
%Docstring
:rtype: QgsExpressionNode
%End
bool isNotIn() const;
%Docstring
:rtype: bool
%End
QgsExpressionNode::NodeList *list() const;
%Docstring
:rtype: QgsExpressionNode.NodeList
%End
virtual QgsExpressionNode::NodeType nodeType() const;
virtual bool prepareNode( QgsExpression *parent, const QgsExpressionContext *context );
virtual QVariant evalNode( QgsExpression *parent, const QgsExpressionContext *context );
virtual QString dump() const;
virtual QSet<QString> referencedColumns() const;
virtual QSet<QString> referencedVariables() const;
virtual bool needsGeometry() const;
virtual QgsExpressionNode *clone() const;
virtual bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const;
};
class QgsExpressionNodeFunction : QgsExpressionNode
{
%TypeHeaderCode
#include "qgsexpressionnodeimpl.h"
%End
public:
QgsExpressionNodeFunction( int fnIndex, QgsExpressionNode::NodeList *args /Transfer/ );
%Docstring
A function node consists of an index of the function in the global function array and
a list of arguments that will be passed to it.
%End
virtual ~QgsExpressionNodeFunction();
int fnIndex() const;
%Docstring
:rtype: int
%End
QgsExpressionNode::NodeList *args() const;
%Docstring
:rtype: QgsExpressionNode.NodeList
%End
virtual QgsExpressionNode::NodeType nodeType() const;
virtual bool prepareNode( QgsExpression *parent, const QgsExpressionContext *context );
virtual QVariant evalNode( QgsExpression *parent, const QgsExpressionContext *context );
virtual QString dump() const;
virtual QSet<QString> referencedColumns() const;
virtual QSet<QString> referencedVariables() const;
virtual bool needsGeometry() const;
virtual QgsExpressionNode *clone() const;
virtual bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const;
static bool validateParams( int fnIndex, QgsExpressionNode::NodeList *args, QString &error );
%Docstring
Tests whether the provided argument list is valid for the matching function
:rtype: bool
%End
};
class QgsExpressionNodeLiteral : QgsExpressionNode
{
%TypeHeaderCode
#include "qgsexpressionnodeimpl.h"
%End
public:
QgsExpressionNodeLiteral( const QVariant &value );
QVariant value() const;
%Docstring
The value of the literal.
:rtype: QVariant
%End
virtual QgsExpressionNode::NodeType nodeType() const;
virtual bool prepareNode( QgsExpression *parent, const QgsExpressionContext *context );
virtual QVariant evalNode( QgsExpression *parent, const QgsExpressionContext *context );
virtual QString dump() const;
virtual QSet<QString> referencedColumns() const;
virtual QSet<QString> referencedVariables() const;
virtual bool needsGeometry() const;
virtual QgsExpressionNode *clone() const;
virtual bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const;
};
class QgsExpressionNodeColumnRef : QgsExpressionNode
{
%TypeHeaderCode
#include "qgsexpressionnodeimpl.h"
%End
public:
QgsExpressionNodeColumnRef( const QString &name );
QString name() const;
%Docstring
The name of the column.
:rtype: str
%End
virtual QgsExpressionNode::NodeType nodeType() const;
virtual bool prepareNode( QgsExpression *parent, const QgsExpressionContext *context );
virtual QVariant evalNode( QgsExpression *parent, const QgsExpressionContext *context );
virtual QString dump() const;
virtual QSet<QString> referencedColumns() const;
virtual QSet<QString> referencedVariables() const;
virtual bool needsGeometry() const;
virtual QgsExpressionNode *clone() const;
virtual bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const;
};
class QgsExpressionNodeCondition : QgsExpressionNode
{
%TypeHeaderCode
#include "qgsexpressionnodeimpl.h"
%End
public:
class WhenThen
{
%TypeHeaderCode
#include "qgsexpressionnodeimpl.h"
%End
public:
WhenThen( QgsExpressionNode *whenExp, QgsExpressionNode *thenExp );
%Docstring
A combination of when and then. Simple as that.
%End
~WhenThen();
QgsExpressionNodeCondition::WhenThen *clone() const;
%Docstring
Get a deep copy of this WhenThen combination.
:rtype: QgsExpressionNodeCondition.WhenThen
%End
private:
WhenThen( const QgsExpressionNodeCondition::WhenThen &rh );
};
typedef QList<QgsExpressionNodeCondition::WhenThen *> WhenThenList;
QgsExpressionNodeCondition( QgsExpressionNodeCondition::WhenThenList *conditions, QgsExpressionNode *elseExp = 0 );
%Docstring
Create a new node with the given list of ``conditions`` and an optional ``elseExp`` expression.
%End
~QgsExpressionNodeCondition();
virtual QgsExpressionNode::NodeType nodeType() const;
virtual QVariant evalNode( QgsExpression *parent, const QgsExpressionContext *context );
virtual bool prepareNode( QgsExpression *parent, const QgsExpressionContext *context );
virtual QString dump() const;
virtual QSet<QString> referencedColumns() const;
virtual QSet<QString> referencedVariables() const;
virtual bool needsGeometry() const;
virtual QgsExpressionNode *clone() const;
virtual bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const;
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/expression/qgsexpressionnodeimpl.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,7 @@
class QgsScopedExpressionFunction : QgsExpression::Function
class QgsScopedExpressionFunction : QgsExpressionFunction
{
%Docstring
Expression function for use within a QgsExpressionContextScope. This differs from a
@ -39,7 +39,7 @@ class QgsScopedExpressionFunction : QgsExpression::Function
%End
QgsScopedExpressionFunction( const QString &fnname,
const QgsExpression::ParameterList &params,
const QgsExpressionFunction::ParameterList &params,
const QString &group,
const QString &helpText = QString(),
bool usesGeometry = false,
@ -61,11 +61,11 @@ class QgsScopedExpressionFunction : QgsExpression::Function
:rtype: QgsScopedExpressionFunction
%End
virtual bool usesGeometry( const QgsExpression::NodeFunction *node ) const;
virtual bool usesGeometry( const QgsExpressionNodeFunction *node ) const;
virtual QSet<QString> referencedColumns( const QgsExpression::NodeFunction *node ) const;
virtual QSet<QString> referencedColumns( const QgsExpressionNodeFunction *node ) const;
virtual bool isStatic( const QgsExpression::NodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) const;
virtual bool isStatic( const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) const;
};
@ -240,7 +240,7 @@ A static variable can be cached for the lifetime of a context
:rtype: bool
%End
QgsExpression::Function *function( const QString &name ) const;
QgsExpressionFunction *function( const QString &name ) const;
%Docstring
Retrieves a function from the scope.
\param name function name
@ -248,7 +248,7 @@ A static variable can be cached for the lifetime of a context
.. seealso:: hasFunction()
.. seealso:: functionNames()
.. seealso:: variable()
:rtype: QgsExpression.Function
:rtype: QgsExpressionFunction
%End
QStringList functionNames() const;
@ -492,7 +492,7 @@ class QgsExpressionContext
:rtype: list of str
%End
QgsExpression::Function *function( const QString &name ) const;
QgsExpressionFunction *function( const QString &name ) const;
%Docstring
Fetches a matching function from the context. The function will be fetched
from the last scope contained within the context which has a matching
@ -500,7 +500,7 @@ class QgsExpressionContext
\param name function name
:return: function if contained by the context, otherwise null.
.. seealso:: hasFunction
:rtype: QgsExpression.Function
:rtype: QgsExpressionFunction
%End
int scopeCount() const;

View File

@ -1,93 +0,0 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsvertexmarker.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsVertexMarker : QgsMapCanvasItem
{
%Docstring
A class for marking vertices of features using e.g. circles or 'x'.
%End
%TypeHeaderCode
#include "qgsvertexmarker.h"
%End
public:
enum IconType
{
ICON_NONE,
ICON_CROSS,
ICON_X,
ICON_BOX,
ICON_CIRCLE
};
QgsVertexMarker( QgsMapCanvas *mapCanvas /TransferThis/ );
void setCenter( const QgsPoint &point );
void setIconType( int iconType );
void setIconSize( int iconSize );
void setColor( const QColor &color );
%Docstring
Sets the stroke ``color`` for the marker.
.. seealso:: color()
.. seealso:: setFillColor()
%End
QColor color() const;
%Docstring
Returns the stroke color for the marker.
.. seealso:: setColor()
.. seealso:: fillColor()
.. versionadded:: 3.0
:rtype: QColor
%End
void setFillColor( const QColor &color );
%Docstring
Sets the fill ``color`` for the marker. This setting only
applies to some icon types.
.. versionadded:: 3.0
.. seealso:: fillColor()
.. seealso:: setColor()
%End
QColor fillColor() const;
%Docstring
Returns the fill ``color`` for the marker. This setting only
applies to some icon types.
.. versionadded:: 3.0
.. seealso:: setFillColor()
.. seealso:: color()
:rtype: QColor
%End
void setPenWidth( int width );
virtual void paint( QPainter *p );
virtual QRectF boundingRect() const;
virtual void updatePosition();
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsvertexmarker.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -158,11 +158,12 @@ SET(QGIS_ANALYSIS_HDRS
INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/../core/
${CMAKE_CURRENT_SOURCE_DIR}/../core/geometry
${CMAKE_CURRENT_SOURCE_DIR}/../core/raster
${CMAKE_CURRENT_SOURCE_DIR}/../core/symbology-ng
${CMAKE_CURRENT_SOURCE_DIR}/../core/metadata
${CMAKE_SOURCE_DIR}/src/core/
${CMAKE_SOURCE_DIR}/src/core/geometry
${CMAKE_SOURCE_DIR}/src/core/raster
${CMAKE_SOURCE_DIR}/src/core/symbology-ng
${CMAKE_SOURCE_DIR}/src/core/metadata
${CMAKE_SOURCE_DIR}/src/core/expression
${CMAKE_BINARY_DIR}/src/core
${CMAKE_BINARY_DIR}/src/analysis
interpolation

View File

@ -87,6 +87,11 @@ SET(QGIS_CORE_SRCS
annotations/qgssvgannotation.cpp
annotations/qgstextannotation.cpp
expression/qgsexpression.cpp
expression/qgsexpressionnode.cpp
expression/qgsexpressionnodeimpl.cpp
expression/qgsexpressionfunction.cpp
processing/qgsnativealgorithms.cpp
processing/qgsprocessingalgorithm.cpp
processing/qgsprocessingparameters.cpp
@ -146,7 +151,6 @@ SET(QGIS_CORE_SRCS
qgseditformconfig.cpp
qgsellipsoidutils.cpp
qgserror.cpp
qgsexpression.cpp
qgsexpressioncontext.cpp
qgsexpressionfieldbuffer.cpp
qgsfeature.cpp
@ -697,6 +701,11 @@ SET(QGIS_CORE_HDRS
${CMAKE_BINARY_DIR}/qgsconfig.h
../plugins/qgisplugin.h
expression/qgsexpression.h
expression/qgsexpressionnode.h
expression/qgsexpressionnodeimpl.h
expression/qgsexpressionfunction.h
qgis.h
qgis_sip.h
qgsaction.h
@ -736,7 +745,6 @@ SET(QGIS_CORE_HDRS
qgsellipsoidutils.h
qgserror.h
qgsexception.h
qgsexpression.h
qgsexpressioncontext.h
qgsexpressioncontextgenerator.h
qgsexpressionfieldbuffer.h
@ -1019,6 +1027,7 @@ INCLUDE_DIRECTORIES(
composer
dxf
effects
${CMAKE_SOURCE_DIR}/src/core/expression
fieldformatter
geometry
layertree

View File

@ -0,0 +1,552 @@
/***************************************************************************
qgsexpression.h
-------------------
begin : August 2011
copyright : (C) 2011 Martin Dobias
email : wonder.sk at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSEXPRESSION_H
#define QGSEXPRESSION_H
#include "qgis_core.h"
#include <QMetaType>
#include <QStringList>
#include <QVariant>
#include <QList>
#include <QDomDocument>
#include <QCoreApplication>
#include <QSet>
#include <functional>
#include "qgis.h"
#include "qgsunittypes.h"
#include "qgsinterval.h"
class QgsFeature;
class QgsGeometry;
class QgsOgcUtils;
class QgsVectorLayer;
class QgsVectorDataProvider;
class QgsField;
class QgsFields;
class QgsDistanceArea;
class QDomElement;
class QgsExpressionContext;
class QgsExpressionPrivate;
class QgsExpressionNode;
class QgsExpressionFunction;
/** \ingroup core
Class for parsing and evaluation of expressions (formerly called "search strings").
The expressions try to follow both syntax and semantics of SQL expressions.
Usage:
\code{.cpp}
QgsExpression exp("gid*2 > 10 and type not in ('D','F'));
if (exp.hasParserError())
{
// show error message with parserErrorString() and exit
}
QVariant result = exp.evaluate(feature, fields);
if (exp.hasEvalError())
{
// show error message with evalErrorString()
}
else
{
// examine the result
}
\endcode
Three Value Logic
=================
Similarly to SQL, this class supports three-value logic: true/false/unknown.
Unknown value may be a result of operations with missing data (NULL). Please note
that NULL is different value than zero or an empty string. For example
3 > NULL returns unknown.
There is no special (three-value) 'boolean' type: true/false is represented as
1/0 integer, unknown value is represented the same way as NULL values: NULL QVariant.
Performance
===========
For better performance with many evaluations you may first call prepare(fields) function
to find out indices of columns and then repeatedly call evaluate(feature).
Type conversion
===============
Operators and functions that expect arguments to be of a particular
type automatically convert the arguments to that type, e.g. sin('2.1') will convert
the argument to a double, length(123) will first convert the number to a string.
Explicit conversion can be achieved with to_int, to_real, to_string functions.
If implicit or explicit conversion is invalid, the evaluation returns an error.
Comparison operators do numeric comparison in case both operators are numeric (int/double)
or they can be converted to numeric types.
Implicit sharing
================
This class is implicitly shared, copying has a very low overhead.
It is normally preferable to call `QgsExpression( otherExpression )` instead of
`QgsExpression( otherExpression.expression() )`. A deep copy will only be made
when prepare() is called. For usage this means mainly, that you should
normally keep an unprepared master copy of a QgsExpression and whenever using it
with a particular QgsFeatureIterator copy it just before and prepare it using the
same context as the iterator.
Implicit sharing was added in 2.14
*/
class CORE_EXPORT QgsExpression
{
Q_DECLARE_TR_FUNCTIONS( QgsExpression )
public:
/**
* Creates a new expression based on the provided string.
* The string will immediately be parsed. For optimization
* prepare() should always be called before every
* loop in which this expression is used.
*/
QgsExpression( const QString &expr );
/**
* Create a copy of this expression. This is preferred
* over recreating an expression from a string since
* it does not need to be re-parsed.
*/
QgsExpression( const QgsExpression &other );
/**
* Create a copy of this expression. This is preferred
* over recreating an expression from a string since
* it does not need to be re-parsed.
*/
QgsExpression &operator=( const QgsExpression &other );
/**
* Create an empty expression.
*
* \since QGIS 3.0
*/
QgsExpression();
~QgsExpression();
/**
* Compares two expressions. The operator returns true
* if the expression string is equal.
*
* \since QGIS 3.0
*/
bool operator==( const QgsExpression &other ) const;
/**
* Checks if this expression is valid.
* A valid expression could be parsed but does not necessarily evaluate properly.
*
* \since QGIS 3.0
*/
bool isValid() const;
//! Returns true if an error occurred when parsing the input expression
bool hasParserError() const;
//! Returns parser error
QString parserErrorString() const;
//! Returns root node of the expression. Root node is null is parsing has failed
const QgsExpressionNode *rootNode() const;
/** Get the expression ready for evaluation - find out column indexes.
* \param context context for preparing expression
* \since QGIS 2.12
*/
bool prepare( const QgsExpressionContext *context );
/**
* Get list of columns referenced by the expression.
*
* \note If the returned list contains the QgsFeatureRequest::AllAttributes constant then
* all attributes from the layer are required for evaluation of the expression.
* QgsFeatureRequest::setSubsetOfAttributes automatically handles this case.
*
* \see referencedAttributeIndexes()
*/
QSet<QString> referencedColumns() const;
/**
* Return a list of all variables which are used in this expression.
* If the list contains a NULL QString, there is a variable name used
* which is determined at runtime.
*
* \since QGIS 3.0
*/
QSet<QString> referencedVariables() const;
/**
* Return a list of field name indexes obtained from the provided fields.
*
* \since QGIS 3.0
*/
QSet<int> referencedAttributeIndexes( const QgsFields &fields ) const;
//! Returns true if the expression uses feature geometry for some computation
bool needsGeometry() const;
// evaluation
/** Evaluate the feature and return the result.
* \note this method does not expect that prepare() has been called on this instance
* \since QGIS 2.12
*/
QVariant evaluate();
/** Evaluate the expression against the specified context and return the result.
* \param context context for evaluating expression
* \note prepare() should be called before calling this method.
* \since QGIS 2.12
*/
QVariant evaluate( const QgsExpressionContext *context );
//! Returns true if an error occurred when evaluating last input
bool hasEvalError() const;
//! Returns evaluation error
QString evalErrorString() const;
//! Set evaluation error (used internally by evaluation functions)
void setEvalErrorString( const QString &str );
/** Checks whether an expression consists only of a single field reference
* \since QGIS 2.9
*/
bool isField() const;
/** Tests whether a string is a valid expression.
* \param text string to test
* \param context optional expression context
* \param errorMessage will be filled with any error message from the validation
* \returns true if string is a valid expression
* \since QGIS 2.12
*/
static bool checkExpression( const QString &text, const QgsExpressionContext *context, QString &errorMessage SIP_OUT );
/**
* Set the expression string, will reset the whole internal structure.
*
* \since QGIS 3.0
*/
void setExpression( const QString &expression );
//! Return the original, unmodified expression string.
//! If there was none supplied because it was constructed by sole
//! API calls, dump() will be used to create one instead.
QString expression() const;
//! Return an expression string, constructed from the internal
//! abstract syntax tree. This does not contain any nice whitespace
//! formatting or comments. In general it is preferable to use
//! expression() instead.
QString dump() const;
/** Return calculator used for distance and area calculations
* (used by $length, $area and $perimeter functions only)
* \see setGeomCalculator()
* \see distanceUnits()
* \see areaUnits()
*/
QgsDistanceArea *geomCalculator();
/** Sets the geometry calculator used for distance and area calculations in expressions.
* (used by $length, $area and $perimeter functions only). By default, no geometry
* calculator is set and all distance and area calculations are performed using simple
* cartesian methods (ie no ellipsoidal calculations).
* \param calc geometry calculator. Ownership is not transferred. Set to a nullptr to force
* cartesian calculations.
* \see geomCalculator()
*/
void setGeomCalculator( const QgsDistanceArea *calc );
/** Returns the desired distance units for calculations involving geomCalculator(), e.g., "$length" and "$perimeter".
* \note distances are only converted when a geomCalculator() has been set
* \since QGIS 2.14
* \see setDistanceUnits()
* \see areaUnits()
*/
QgsUnitTypes::DistanceUnit distanceUnits() const;
/** Sets the desired distance units for calculations involving geomCalculator(), e.g., "$length" and "$perimeter".
* \note distances are only converted when a geomCalculator() has been set
* \since QGIS 2.14
* \see distanceUnits()
* \see setAreaUnits()
*/
void setDistanceUnits( QgsUnitTypes::DistanceUnit unit );
/** Returns the desired areal units for calculations involving geomCalculator(), e.g., "$area".
* \note areas are only converted when a geomCalculator() has been set
* \since QGIS 2.14
* \see setAreaUnits()
* \see distanceUnits()
*/
QgsUnitTypes::AreaUnit areaUnits() const;
/** Sets the desired areal units for calculations involving geomCalculator(), e.g., "$area".
* \note areas are only converted when a geomCalculator() has been set
* \since QGIS 2.14
* \see areaUnits()
* \see setDistanceUnits()
*/
void setAreaUnits( QgsUnitTypes::AreaUnit unit );
/** This function replaces each expression between [% and %]
* in the string with the result of its evaluation with the specified context
*
* Additional substitutions can be passed through the substitutionMap parameter
* \param action The source string in which placeholders should be replaced.
* \param context Expression context
* \param distanceArea Optional QgsDistanceArea. If specified, the QgsDistanceArea is used for distance
* and area conversion
* \since QGIS 2.12
*/
static QString replaceExpressionText( const QString &action, const QgsExpressionContext *context,
const QgsDistanceArea *distanceArea = nullptr );
/** Attempts to evaluate a text string as an expression to a resultant double
* value.
* \param text text to evaluate as expression
* \param fallbackValue value to return if text can not be evaluated as a double
* \returns evaluated double value, or fallback value
* \since QGIS 2.7
* \note this method is inefficient for bulk evaluation of expressions, it is intended
* for one-off evaluations only.
*/
static double evaluateToDouble( const QString &text, const double fallbackValue );
enum SpatialOperator
{
soBbox,
soIntersects,
soContains,
soCrosses,
soEquals,
soDisjoint,
soOverlaps,
soTouches,
soWithin,
};
//! \note not available in Python bindings
static QList<QgsExpressionFunction *> sFunctions SIP_SKIP;
static const QList<QgsExpressionFunction *> &Functions();
//! \note not available in Python bindings
static QStringList sBuiltinFunctions SIP_SKIP;
static const QStringList &BuiltinFunctions();
/** Registers a function to the expression engine. This is required to allow expressions to utilize the function.
* \param function function to register
* \param transferOwnership set to true to transfer ownership of function to expression engine
* \returns true on successful registration
* \see unregisterFunction
*/
static bool registerFunction( QgsExpressionFunction *function, bool transferOwnership = false );
/** Unregisters a function from the expression engine. The function will no longer be usable in expressions.
* \param name function name
* \see registerFunction
*/
static bool unregisterFunction( const QString &name );
//! List of functions owned by the expression engine
//! \note not available in Python bindings
static QList<QgsExpressionFunction *> sOwnedFunctions SIP_SKIP;
/** Deletes all registered functions whose ownership have been transferred to the expression engine.
* \since QGIS 2.12
*/
static void cleanRegisteredFunctions();
//! tells whether the identifier is a name of existing function
static bool isFunctionName( const QString &name );
//! return index of the function in Functions array
static int functionIndex( const QString &name );
/** Returns the number of functions defined in the parser
* \returns The number of function defined in the parser.
*/
static int functionCount();
/** Returns a quoted column reference (in double quotes)
* \see quotedString()
* \see quotedValue()
*/
static QString quotedColumnRef( QString name );
/** Returns a quoted version of a string (in single quotes)
* \see quotedValue()
* \see quotedColumnRef()
*/
static QString quotedString( QString text );
/** Returns a string representation of a literal value, including appropriate
* quotations where required.
* \param value value to convert to a string representation
* \since QGIS 2.14
* \see quotedString()
* \see quotedColumnRef()
*/
static QString quotedValue( const QVariant &value );
/** Returns a string representation of a literal value, including appropriate
* quotations where required.
* \param value value to convert to a string representation
* \param type value type
* \since QGIS 2.14
* \see quotedString()
* \see quotedColumnRef()
*/
static QString quotedValue( const QVariant &value, QVariant::Type type );
//////
/** Returns the help text for a specified function.
* \param name function name
* \see variableHelpText()
*/
static QString helpText( QString name );
/** Returns the help text for a specified variable.
* \param variableName name of variable
* \param showValue set to true to include current value of variable in help text
* \param value current value of variable to show in help text
* \see helpText()
* \since QGIS 2.12
*/
static QString variableHelpText( const QString &variableName, bool showValue = true, const QVariant &value = QVariant() );
/** Returns the translated name for a function group.
* \param group untranslated group name
*/
static QString group( const QString &group );
/** Formats an expression result for friendly display to the user. Truncates the result to a sensible
* length, and presents text representations of non numeric/text types (e.g., geometries and features).
* \param value expression result to format
* \returns formatted string, may contain HTML formatting characters
* \since QGIS 2.14
*/
static QString formatPreviewString( const QVariant &value );
private:
void initGeomCalculator();
struct HelpArg SIP_SKIP
{
HelpArg( const QString &arg, const QString &desc, bool descOnly = false, bool syntaxOnly = false,
bool optional = false, const QString &defaultVal = QString() )
: mArg( arg )
, mDescription( desc )
, mDescOnly( descOnly )
, mSyntaxOnly( syntaxOnly )
, mOptional( optional )
, mDefaultVal( defaultVal )
{}
QString mArg;
QString mDescription;
bool mDescOnly;
bool mSyntaxOnly;
bool mOptional;
QString mDefaultVal;
};
struct HelpExample SIP_SKIP
{
HelpExample( const QString &expression, const QString &returns, const QString &note = QString::null )
: mExpression( expression )
, mReturns( returns )
, mNote( note )
{}
QString mExpression;
QString mReturns;
QString mNote;
};
struct HelpVariant SIP_SKIP
{
HelpVariant( const QString &name, const QString &description,
const QList<QgsExpression::HelpArg> &arguments = QList<QgsExpression::HelpArg>(),
bool variableLenArguments = false,
const QList<QgsExpression::HelpExample> &examples = QList<QgsExpression::HelpExample>(),
const QString &notes = QString::null )
: mName( name )
, mDescription( description )
, mArguments( arguments )
, mVariableLenArguments( variableLenArguments )
, mExamples( examples )
, mNotes( notes )
{}
QString mName;
QString mDescription;
QList<QgsExpression::HelpArg> mArguments;
bool mVariableLenArguments;
QList<QgsExpression::HelpExample> mExamples;
QString mNotes;
};
struct Help SIP_SKIP
{
Help() {}
Help( const QString &name, const QString &type, const QString &description, const QList<QgsExpression::HelpVariant> &variants )
: mName( name )
, mType( type )
, mDescription( description )
, mVariants( variants )
{}
QString mName;
QString mType;
QString mDescription;
QList<QgsExpression::HelpVariant> mVariants;
};
/**
* Helper for implicit sharing. When called will create
* a new deep copy of this expression.
*
* \note not available in Python bindings
*/
void detach() SIP_SKIP;
QgsExpressionPrivate *d = nullptr;
static QHash<QString, Help> sFunctionHelpTexts;
static QHash<QString, QString> sVariableHelpTexts;
static QHash<QString, QString> sGroups;
//! \note not available in Python bindings
static void initFunctionHelp() SIP_SKIP;
//! \note not available in Python bindings
static void initVariableHelp() SIP_SKIP;
friend class QgsOgcUtils;
};
Q_DECLARE_METATYPE( QgsExpression )
#endif // QGSEXPRESSION_H

View File

@ -0,0 +1,7 @@
#include "qgsexpressionfunction.h"
#include "qgsexpression.h"
const QString QgsExpressionFunction::helpText() const
{
return mHelpText.isEmpty() ? QgsExpression::helpText( mName ) : mHelpText;
}

View File

@ -0,0 +1,438 @@
#ifndef QGSEXPRESSIONFUNCTION_H
#define QGSEXPRESSIONFUNCTION_H
#include <QString>
#include <QVariant>
#include <QSet>
#include "qgis.h"
#include "qgis_core.h"
class QgsExpressionNodeFunction;
class QgsExpression;
class QgsExpressionContext;
/** \ingroup core
* A abstract base class for defining QgsExpression functions.
*/
class CORE_EXPORT QgsExpressionFunction
{
public:
/** Function definition for evaluation against an expression context, using a list of values as parameters to the function.
*/
typedef QVariant( *FcnEval )( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent ) SIP_SKIP;
/** \ingroup core
* Represents a single parameter passed to a function.
* \since QGIS 2.16
*/
class CORE_EXPORT Parameter
{
public:
/** Constructor for Parameter.
* \param name parameter name, used when named parameter are specified in an expression
* \param optional set to true if parameter should be optional
* \param defaultValue default value to use for optional parameters
*/
Parameter( const QString &name,
bool optional = false,
const QVariant &defaultValue = QVariant() )
: mName( name )
, mOptional( optional )
, mDefaultValue( defaultValue )
{}
//! Returns the name of the parameter.
QString name() const { return mName; }
//! Returns true if the parameter is optional.
bool optional() const { return mOptional; }
//! Returns the default value for the parameter.
QVariant defaultValue() const { return mDefaultValue; }
bool operator==( const QgsExpressionFunction::Parameter &other ) const
{
return ( QString::compare( mName, other.mName, Qt::CaseInsensitive ) == 0 );
}
private:
QString mName;
bool mOptional;
QVariant mDefaultValue;
};
//! List of parameters, used for function definition
typedef QList< QgsExpressionFunction::Parameter > ParameterList;
//! Constructor for function which uses unnamed parameters
QgsExpressionFunction( const QString &fnname,
int params,
const QString &group,
const QString &helpText = QString(),
bool lazyEval = false,
bool handlesNull = false,
bool isContextual = false )
: mName( fnname )
, mParams( params )
, mGroups( group.isEmpty() ? QStringList() : QStringList() << group )
, mHelpText( helpText )
, mLazyEval( lazyEval )
, mHandlesNull( handlesNull )
, mIsContextual( isContextual )
{
}
/** Constructor for function which uses unnamed parameters and group list
* \since QGIS 3.0
*/
QgsExpressionFunction( const QString &fnname,
int params,
const QStringList &groups,
const QString &helpText = QString(),
bool lazyEval = false,
bool handlesNull = false,
bool isContextual = false )
: mName( fnname )
, mParams( params )
, mGroups( groups )
, mHelpText( helpText )
, mLazyEval( lazyEval )
, mHandlesNull( handlesNull )
, mIsContextual( isContextual )
{
}
/** Constructor for function which uses named parameter list.
* \since QGIS 2.16
*/
QgsExpressionFunction( const QString &fnname,
const QgsExpressionFunction::ParameterList &params,
const QString &group,
const QString &helpText = QString(),
bool lazyEval = false,
bool handlesNull = false,
bool isContextual = false )
: mName( fnname )
, mParams( 0 )
, mParameterList( params )
, mGroups( group.isEmpty() ? QStringList() : QStringList() << group )
, mHelpText( helpText )
, mLazyEval( lazyEval )
, mHandlesNull( handlesNull )
, mIsContextual( isContextual )
{}
/** Constructor for function which uses named parameter list and group list.
* \since QGIS 3.0
*/
QgsExpressionFunction( const QString &fnname,
const QgsExpressionFunction::ParameterList &params,
const QStringList &groups,
const QString &helpText = QString(),
bool lazyEval = false,
bool handlesNull = false,
bool isContextual = false )
: mName( fnname )
, mParams( 0 )
, mParameterList( params )
, mGroups( groups )
, mHelpText( helpText )
, mLazyEval( lazyEval )
, mHandlesNull( handlesNull )
, mIsContextual( isContextual )
{}
virtual ~QgsExpressionFunction() = default;
//! The name of the function.
QString name() const { return mName; }
//! The number of parameters this function takes.
int params() const { return mParameterList.isEmpty() ? mParams : mParameterList.count(); }
//! The minimum number of parameters this function takes.
int minParams() const
{
if ( mParameterList.isEmpty() )
return mParams;
int min = 0;
Q_FOREACH ( const Parameter &param, mParameterList )
{
if ( !param.optional() )
min++;
}
return min;
}
/** Returns the list of named parameters for the function, if set.
* \since QGIS 2.16
*/
const QgsExpressionFunction::ParameterList &parameters() const { return mParameterList; }
//! Does this function use a geometry object.
virtual bool usesGeometry( const QgsExpressionNodeFunction *node ) const;
/**
* Returns a list of possible aliases for the function. These include
* other permissible names for the function, e.g., deprecated names.
* \returns list of known aliases
* \since QGIS 2.9
*/
virtual QStringList aliases() const;
/**
* True if this function should use lazy evaluation. Lazy evaluation functions take QgsExpression::Node objects
* rather than the node results when called. You can use node->eval(parent, feature) to evaluate the node and return the result
* Functions are non lazy default and will be given the node return value when called.
*/
bool lazyEval() const { return mLazyEval; }
/**
* Will be called during prepare to determine if the function is static.
* A function is static if it will return the same value for every feature with different
* attributes and/or geometry.
*
* By default this will return true, if all arguments that have been passed to the function
* are also static.
*
* \since QGIS 3.0
*/
virtual bool isStatic( const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) const;
/**
* This will be called during the prepare step() of an expression if it is not static.
*
* This can be used by functions to do any preparation steps that might help to speedup the upcoming
* evaluation.
*
* \since QGIS 3.0
*/
virtual bool prepare( const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) const;
/**
* Returns a set of field names which are required for this function.
* May contain QgsFeatureRequest::AllAttributes to signal that all
* attributes are required.
* If in doubt this will return more fields than strictly required.
*
* \since QGIS 3.0
*/
virtual QSet<QString> referencedColumns( const QgsExpressionNodeFunction *node ) const;
/** Returns whether the function is only available if provided by a QgsExpressionContext object.
* \since QGIS 2.12
*/
bool isContextual() const { return mIsContextual; }
/** Returns true if the function is deprecated and should not be presented as a valid option
* to users in expression builders.
* \since QGIS 3.0
*/
virtual bool isDeprecated() const;
/** Returns the first group which the function belongs to.
* \note consider using groups() instead, as some functions naturally belong in multiple groups
*/
QString group() const { return mGroups.isEmpty() ? QString() : mGroups.at( 0 ); }
/** Returns a list of the groups the function belongs to.
* \since QGIS 3.0
* \see group()
*/
QStringList groups() const { return mGroups; }
//! The help text for the function.
const QString helpText() const;
/** Returns result of evaluating the function.
* \param values list of values passed to the function
* \param context context expression is being evaluated against
* \param parent parent expression
* \returns result of function
*/
virtual QVariant func( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent ) = 0;
bool operator==( const QgsExpressionFunction &other ) const;
virtual bool handlesNull() const;
protected:
/**
* This will return true if all the params for the provided function \a node are static within the
* constraints imposed by the \a context within the given \a parent.
*
* This can be used as callback for custom implementations of subclasses. It is the default for implementation
* for StaticFunction::isStatic.
*
* \since QGIS 3.0
*/
static bool allParamsStatic( const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context );
private:
QString mName;
int mParams;
QgsExpressionFunction::ParameterList mParameterList;
QStringList mGroups;
QString mHelpText;
bool mLazyEval;
bool mHandlesNull;
bool mIsContextual; //if true function is only available through an expression context
};
/** \ingroup core
* c++ helper class for defining QgsExpression functions.
* \note not available in Python bindings
*/
#ifndef SIP_RUN
class QgsStaticExpressionFunction : public QgsExpressionFunction
{
public:
/** Static function for evaluation against a QgsExpressionContext, using an unnamed list of parameter values.
*/
QgsStaticExpressionFunction( const QString &fnname,
int params,
FcnEval fcn,
const QString &group,
const QString &helpText = QString(),
bool usesGeometry = false,
const QSet<QString> &referencedColumns = QSet<QString>(),
bool lazyEval = false,
const QStringList &aliases = QStringList(),
bool handlesNull = false )
: QgsExpressionFunction( fnname, params, group, helpText, lazyEval, handlesNull )
, mFnc( fcn )
, mAliases( aliases )
, mUsesGeometry( usesGeometry )
, mReferencedColumns( referencedColumns )
{
}
/** Static function for evaluation against a QgsExpressionContext, using a named list of parameter values.
*/
QgsStaticExpressionFunction( const QString &fnname,
const QgsExpressionFunction::ParameterList &params,
FcnEval fcn,
const QString &group,
const QString &helpText = QString(),
bool usesGeometry = false,
const QSet<QString> &referencedColumns = QSet<QString>(),
bool lazyEval = false,
const QStringList &aliases = QStringList(),
bool handlesNull = false )
: QgsExpressionFunction( fnname, params, group, helpText, lazyEval, handlesNull )
, mFnc( fcn )
, mAliases( aliases )
, mUsesGeometry( usesGeometry )
, mReferencedColumns( referencedColumns )
{}
/**
* Static function for evaluation against a QgsExpressionContext, using a named list of parameter values.
*
* Lambda functions can be provided that will be called to determine if a geometry is used an which
* columns are referenced.
* This is only required if this cannot be determined by calling each parameter node's usesGeometry() or
* referencedColumns() method. For example, an aggregate expression requires the geometry and all columns
* if the parent variable is used.
* If a nullptr is passed as a node to these functions, they should stay on the safe side and return if they
* could potentially require a geometry or columns.
*/
QgsStaticExpressionFunction( const QString &fnname,
const QgsExpressionFunction::ParameterList &params,
FcnEval fcn,
const QString &group,
const QString &helpText,
std::function < bool ( const QgsExpressionNodeFunction *node ) > usesGeometry,
std::function < QSet<QString>( const QgsExpressionNodeFunction *node ) > referencedColumns,
bool lazyEval = false,
const QStringList &aliases = QStringList(),
bool handlesNull = false );
/** Static function for evaluation against a QgsExpressionContext, using a named list of parameter values and list
* of groups.
*/
QgsStaticExpressionFunction( const QString &fnname,
const QgsExpressionFunction::ParameterList &params,
FcnEval fcn,
const QStringList &groups,
const QString &helpText = QString(),
bool usesGeometry = false,
const QSet<QString> &referencedColumns = QSet<QString>(),
bool lazyEval = false,
const QStringList &aliases = QStringList(),
bool handlesNull = false )
: QgsExpressionFunction( fnname, params, groups, helpText, lazyEval, handlesNull )
, mFnc( fcn )
, mAliases( aliases )
, mUsesGeometry( usesGeometry )
, mReferencedColumns( referencedColumns )
{}
/** Returns result of evaluating the function.
* \param values list of values passed to the function
* \param context context expression is being evaluated against
* \param parent parent expression
* \returns result of function
*/
virtual QVariant func( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent ) override
{
return mFnc ? mFnc( values, context, parent ) : QVariant();
}
virtual QStringList aliases() const override;
virtual bool usesGeometry( const QgsExpressionNodeFunction *node ) const override;
virtual QSet<QString> referencedColumns( const QgsExpressionNodeFunction *node ) const override;
virtual bool isStatic( const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) const override;
virtual bool prepare( const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) const override;
/**
* Set a function that will be called in the prepare step to determine if the function is
* static or not.
* By default this is set to a function that checks all arguments that have been passed to the variable
* and if all of them are static, it will be assumed that the function is static as well.
*/
void setIsStaticFunction( std::function < bool( const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) > isStatic );
/**
* Tag this function as either static or not static.
* This will indicate that the function is always expected to return the same value for
* an iteration (or explicitly request that it's going to be called for every feature, if false).
*
* \see setIsStaticFunction
*/
void setIsStatic( bool isStatic );
/**
* Set a function that will be called in the prepare step to determine if the function is
* static or not.
* By default this is set to a function that checks all arguments that have been passed to the variable
* and if all of them are static, it will be assumed that the function is static as well.
*/
void setPrepareFunction( std::function < bool( const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) > prepareFunc );
private:
FcnEval mFnc;
QStringList mAliases;
bool mUsesGeometry;
std::function < bool( const QgsExpressionNodeFunction *node ) > mUsesGeometryFunc;
std::function < QSet<QString>( const QgsExpressionNodeFunction *node ) > mReferencedColumnsFunc;
std::function < bool( const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) > mIsStaticFunc = allParamsStatic;
std::function < bool( const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) > mPrepareFunc;
QSet<QString> mReferencedColumns;
bool mIsStatic = false;
};
#endif
#endif // QGSEXPRESSIONFUNCTION_H

View File

@ -0,0 +1 @@
#include "qgsexpressionnode.h"

View File

@ -0,0 +1,259 @@
#ifndef QGSEXPRESSIONNODE_H
#define QGSEXPRESSIONNODE_H
#include <QSet>
#include <QVariant>
#include <QCoreApplication>
#include "qgis.h"
class QgsExpression;
class QgsExpressionContext;
/**
* \ingroup core
*
* Abstract base class for all nodes that can appear in an expression.
*/
class CORE_EXPORT QgsExpressionNode SIP_ABSTRACT
{
#ifdef SIP_RUN
SIP_CONVERT_TO_SUBCLASS_CODE
switch ( sipCpp->nodeType() )
{
case QgsExpressionNode::ntUnaryOperator:
sipType = sipType_QgsExpressionNodeUnaryOperator;
break;
case QgsExpressionNode::ntBinaryOperator:
sipType = sipType_QgsExpressionNodeBinaryOperator;
break;
case QgsExpressionNode::ntInOperator:
sipType = sipType_QgsExpressionNodeInOperator;
break;
case QgsExpressionNode::ntFunction:
sipType = sipType_QgsExpressionNodeFunction;
break;
case QgsExpressionNode::ntLiteral:
sipType = sipType_QgsExpressionNodeLiteral;
break;
case QgsExpressionNode::ntColumnRef:
sipType = sipType_QgsExpressionNodeColumnRef;
break;
case QgsExpressionNode::ntCondition:
sipType = sipType_QgsExpressionNodeCondition;
break;
default:
sipType = 0;
break;
}
SIP_END
#endif
Q_DECLARE_TR_FUNCTIONS( QgsExpressionNode );
public:
enum NodeType
{
ntUnaryOperator, //!< \see QgsExpression::Node::NodeUnaryOperator
ntBinaryOperator, //!< \see QgsExpression::Node::NodeBinaryOperator
ntInOperator, //!< \see QgsExpression::Node::NodeInOperator
ntFunction, //!< \see QgsExpression::Node::NodeFunction
ntLiteral, //!< \see QgsExpression::Node::NodeLiteral
ntColumnRef, //!< \see QgsExpression::Node::NodeColumnRef
ntCondition //!< \see QgsExpression::Node::NodeCondition
};
//! Named node
//! \since QGIS 2.16
//! \ingroup core
struct NamedNode
{
public:
/** Constructor for NamedNode
* \param name node name
* \param node node
*/
NamedNode( const QString &name, QgsExpressionNode *node )
: name( name )
, node( node )
{}
//! Node name
QString name;
//! Node
QgsExpressionNode *node = nullptr;
};
/** \ingroup core
*/
class NodeList
{
public:
virtual ~NodeList();
//! Takes ownership of the provided node
void append( QgsExpressionNode *node SIP_TRANSFER ) { mList.append( node ); mNameList.append( QString() ); }
/** Adds a named node. Takes ownership of the provided node.
* \since QGIS 2.16
*/
void append( QgsExpressionNode::NamedNode *node SIP_TRANSFER );
/** Returns the number of nodes in the list.
*/
int count() const { return mList.count(); }
//! Returns true if list contains any named nodes
//! \since QGIS 2.16
bool hasNamedNodes() const { return mHasNamedNodes; }
/**
* Get a list of all the nodes.
*/
QList<QgsExpressionNode *> list() { return mList; }
/**
* Get the node at position i in the list.
*
* \since QGIS 3.0
*/
QgsExpressionNode *at( int i ) { return mList.at( i ); }
//! Returns a list of names for nodes. Unnamed nodes will be indicated by an empty string in the list.
//! \since QGIS 2.16
QStringList names() const { return mNameList; }
//! Creates a deep copy of this list. Ownership is transferred to the caller
NodeList *clone() const;
virtual QString dump() const;
private:
QList<QgsExpressionNode *> mList;
QStringList mNameList;
bool mHasNamedNodes = false;
public:
};
virtual ~QgsExpressionNode() = default;
/**
* Get the type of this node.
*
* \returns The type of this node
*/
virtual QgsExpressionNode::NodeType nodeType() const = 0;
/**
* Dump this node into a serialized (part) of an expression.
* The returned expression does not necessarily literally match
* the original expression, it's just guaranteed to behave the same way.
*/
virtual QString dump() const = 0;
/**
* Evaluate this node with the given context and parent.
* This will return a cached value if it has been determined to be static
* during the prepare() execution.
*
* \since QGIS 2.12
*/
QVariant eval( QgsExpression *parent, const QgsExpressionContext *context );
/**
* Generate a clone of this node.
* Ownership is transferred to the caller.
*
* \returns a deep copy of this node.
*/
virtual QgsExpressionNode *clone() const = 0;
/**
* Abstract virtual method which returns a list of columns required to
* evaluate this node.
*
* When reimplementing this, you need to return any column that is required to
* evaluate this node and in addition recursively collect all the columns required
* to evaluate child nodes.
*
* \returns A list of columns required to evaluate this expression
*/
virtual QSet<QString> referencedColumns() const = 0;
/**
* Return a set of all variables which are used in this expression.
*/
virtual QSet<QString> referencedVariables() const = 0;
/**
* Abstract virtual method which returns if the geometry is required to evaluate
* this expression.
*
* This needs to call `needsGeometry()` recursively on any child nodes.
*
* \returns true if a geometry is required to evaluate this expression
*/
virtual bool needsGeometry() const = 0;
/**
* Returns true if this node can be evaluated for a static value. This is used during
* the prepare() step and in case it returns true, the value of this node will already
* be evaluated and the result cached (and therefore not re-evaluated in subsequent calls
* to eval()). In case this returns true, prepareNode() will never be called.
*
* \since QGIS 3.0
*/
virtual bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const = 0;
/**
* Prepare this node for evaluation.
* This will check if the node content is static and in this case cache the value.
* If it's not static it will call prepareNode() to allow the node to do initialization
* work like for example resolving a column name to an attribute index.
*
* \since QGIS 2.12
*/
bool prepare( QgsExpression *parent, const QgsExpressionContext *context );
protected:
/**
* Copies the members of this node to the node provided in \a target.
* Needs to be called by all subclasses as part of their clone() implementation.
*
* \note Not available in python bindings, QgsExpression::Node is not
* going to be subclassed from python. If that's what you are looking
* for, look into writing a custom python expression function.
* \since QGIS 3.0
*/
void cloneTo( QgsExpressionNode *target ) const SIP_SKIP;
private:
/**
* Abstract virtual preparation method
* Errors are reported to the parent
* \since QGIS 3.0
*/
virtual bool prepareNode( QgsExpression *parent, const QgsExpressionContext *context ) = 0;
/**
* Abstract virtual eval method
* Errors are reported to the parent
* \since QGIS 3.0
*/
virtual QVariant evalNode( QgsExpression *parent, const QgsExpressionContext *context ) = 0;
bool mHasCachedValue = false;
QVariant mCachedStaticValue;
};
Q_DECLARE_METATYPE( QgsExpressionNode * )
#endif // QGSEXPRESSIONNODE_H

View File

@ -0,0 +1,6 @@
#include "qgsexpressionnodeimpl.h"
QString QgsExpressionNodeBinaryOperator::text() const
{
return BINARY_OPERATOR_TEXT[mOp];
}

View File

@ -0,0 +1,356 @@
#ifndef QGSEXPRESSIONNODEIMPL_H
#define QGSEXPRESSIONNODEIMPL_H
#include "qgsexpressionnode.h"
#include "qgsinterval.h"
/** \ingroup core
* A unary node is either negative as in boolean (not) or as in numbers (minus).
*/
class CORE_EXPORT QgsExpressionNodeUnaryOperator : public QgsExpressionNode
{
public:
/**
* \brief list of unary operators
* \note if any change is made here, the definition of QgsExpression::UnaryOperatorText[] must be adapted.
*/
enum UnaryOperator
{
uoNot,
uoMinus,
};
/**
* A node unary operator is modifying the value of \a operand by negating it with \a op.
*/
QgsExpressionNodeUnaryOperator( QgsExpressionNodeUnaryOperator::UnaryOperator op, QgsExpressionNode *operand SIP_TRANSFER )
: mOp( op )
, mOperand( operand )
{}
~QgsExpressionNodeUnaryOperator() { delete mOperand; }
QgsExpressionNodeUnaryOperator::UnaryOperator op() const { return mOp; }
QgsExpressionNode *operand() const { return mOperand; }
virtual QgsExpressionNode::NodeType nodeType() const override;
virtual bool prepareNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
virtual QVariant evalNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
virtual QString dump() const override;
virtual QSet<QString> referencedColumns() const override;
virtual QSet<QString> referencedVariables() const override;
virtual bool needsGeometry() const override;
virtual QgsExpressionNode *clone() const override;
virtual bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const override;
/**
* Returns a the name of this operator without the operands.
* I.e. "NOT" or "-"
*/
QString text() const;
private:
UnaryOperator mOp;
QgsExpressionNode *mOperand = nullptr;
static const char *UNARY_OPERATOR_TEXT[];
};
/** \ingroup core
*/
class CORE_EXPORT QgsExpressionNodeBinaryOperator : public QgsExpressionNode
{
public:
/**
* \brief list of binary operators
* \note if any change is made here, the definition of QgsExpression::BinaryOperatorText[] must be adapted.
*/
enum BinaryOperator
{
// logical
boOr,
boAnd,
// comparison
boEQ, //!< =
boNE, //!< <>
boLE, //!< <=
boGE, //!< >=
boLT, //!< <
boGT, //!< >
boRegexp,
boLike,
boNotLike,
boILike,
boNotILike,
boIs,
boIsNot,
// math
boPlus,
boMinus,
boMul,
boDiv,
boIntDiv,
boMod,
boPow,
// strings
boConcat,
};
/**
* Binary combination of the left and the right with op.
*/
QgsExpressionNodeBinaryOperator( QgsExpressionNodeBinaryOperator::BinaryOperator op, QgsExpressionNode *opLeft SIP_TRANSFER, QgsExpressionNode *opRight SIP_TRANSFER )
: mOp( op )
, mOpLeft( opLeft )
, mOpRight( opRight )
{}
~QgsExpressionNodeBinaryOperator() { delete mOpLeft; delete mOpRight; }
QgsExpressionNodeBinaryOperator::BinaryOperator op() const { return mOp; }
QgsExpressionNode *opLeft() const { return mOpLeft; }
QgsExpressionNode *opRight() const { return mOpRight; }
virtual QgsExpressionNode::NodeType nodeType() const override;
virtual bool prepareNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
virtual QVariant evalNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
virtual QString dump() const override;
virtual QSet<QString> referencedColumns() const override;
virtual QSet<QString> referencedVariables() const override;
virtual bool needsGeometry() const override;
virtual QgsExpressionNode *clone() const override;
virtual bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const override;
int precedence() const;
bool leftAssociative() const;
/**
* Returns a the name of this operator without the operands.
* I.e. "AND", "OR", ...
*/
QString text() const;
private:
bool compare( double diff );
qlonglong computeInt( qlonglong x, qlonglong y );
double computeDouble( double x, double y );
/** Computes the result date time calculation from a start datetime and an interval
* \param d start datetime
* \param i interval to add or subtract (depending on mOp)
*/
QDateTime computeDateTimeFromInterval( const QDateTime &d, QgsInterval *i );
BinaryOperator mOp;
QgsExpressionNode *mOpLeft = nullptr;
QgsExpressionNode *mOpRight = nullptr;
static const char *BINARY_OPERATOR_TEXT[];
};
/** \ingroup core
*/
class CORE_EXPORT QgsExpressionNodeInOperator : public QgsExpressionNode
{
public:
/**
* 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.
*/
QgsExpressionNodeInOperator( QgsExpressionNode *node SIP_TRANSFER, QgsExpressionNode::NodeList *list SIP_TRANSFER, bool notin = false )
: mNode( node )
, mList( list )
, mNotIn( notin )
{}
virtual ~QgsExpressionNodeInOperator();
QgsExpressionNode *node() const { return mNode; }
bool isNotIn() const { return mNotIn; }
QgsExpressionNode::NodeList *list() const { return mList; }
virtual QgsExpressionNode::NodeType nodeType() const override;
virtual bool prepareNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
virtual QVariant evalNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
virtual QString dump() const override;
virtual QSet<QString> referencedColumns() const override;
virtual QSet<QString> referencedVariables() const override;
virtual bool needsGeometry() const override;
virtual QgsExpressionNode *clone() const override;
virtual bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const override;
private:
QgsExpressionNode *mNode = nullptr;
QgsExpressionNodeInOperator::NodeList *mList = nullptr;
bool mNotIn;
};
/** \ingroup core
*/
class CORE_EXPORT QgsExpressionNodeFunction : public QgsExpressionNode
{
public:
/**
* A function node consists of an index of the function in the global function array and
* a list of arguments that will be passed to it.
*/
QgsExpressionNodeFunction( int fnIndex, QgsExpressionNode::NodeList *args SIP_TRANSFER );
virtual ~QgsExpressionNodeFunction();
int fnIndex() const { return mFnIndex; }
QgsExpressionNode::NodeList *args() const { return mArgs; }
virtual QgsExpressionNode::NodeType nodeType() const override;
virtual bool prepareNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
virtual QVariant evalNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
virtual QString dump() const override;
virtual QSet<QString> referencedColumns() const override;
virtual QSet<QString> referencedVariables() const override;
virtual bool needsGeometry() const override;
virtual QgsExpressionNode *clone() const override;
virtual bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const override;
//! Tests whether the provided argument list is valid for the matching function
static bool validateParams( int fnIndex, QgsExpressionNode::NodeList *args, QString &error );
private:
int mFnIndex;
NodeList *mArgs = nullptr;
};
/** \ingroup core
*/
class CORE_EXPORT QgsExpressionNodeLiteral : public QgsExpressionNode
{
public:
QgsExpressionNodeLiteral( const QVariant &value )
: mValue( value )
{}
//! The value of the literal.
inline QVariant value() const { return mValue; }
virtual QgsExpressionNode::NodeType nodeType() const override;
virtual bool prepareNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
virtual QVariant evalNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
virtual QString dump() const override;
virtual QSet<QString> referencedColumns() const override;
virtual QSet<QString> referencedVariables() const override;
virtual bool needsGeometry() const override;
virtual QgsExpressionNode *clone() const override;
virtual bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const override;
private:
QVariant mValue;
};
/** \ingroup core
*/
class CORE_EXPORT QgsExpressionNodeColumnRef : public QgsExpressionNode
{
public:
QgsExpressionNodeColumnRef( const QString &name )
: mName( name )
, mIndex( -1 )
{}
//! The name of the column.
QString name() const { return mName; }
virtual QgsExpressionNode::NodeType nodeType() const override;
virtual bool prepareNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
virtual QVariant evalNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
virtual QString dump() const override;
virtual QSet<QString> referencedColumns() const override;
virtual QSet<QString> referencedVariables() const override;
virtual bool needsGeometry() const override;
virtual QgsExpressionNode *clone() const override;
virtual bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const override;
private:
QString mName;
int mIndex;
};
/** \ingroup core
*/
class CORE_EXPORT QgsExpressionNodeCondition : public QgsExpressionNode
{
public:
class CORE_EXPORT WhenThen
{
public:
/**
* A combination of when and then. Simple as that.
*/
WhenThen( QgsExpressionNode *whenExp, QgsExpressionNode *thenExp );
~WhenThen();
//! WhenThen nodes cannot be copied.
WhenThen( const WhenThen &rh ) = delete;
//! WhenThen nodes cannot be copied.
WhenThen &operator=( const WhenThen &rh ) = delete;
/**
* Get a deep copy of this WhenThen combination.
*/
QgsExpressionNodeCondition::WhenThen *clone() const;
private:
#ifdef SIP_RUN
WhenThen( const QgsExpressionNodeCondition::WhenThen &rh );
#endif
QgsExpressionNode *mWhenExp = nullptr;
QgsExpressionNode *mThenExp = nullptr;
friend class QgsExpressionNodeCondition;
};
typedef QList<QgsExpressionNodeCondition::WhenThen *> WhenThenList;
/**
* Create a new node with the given list of \a conditions and an optional \a elseExp expression.
*/
QgsExpressionNodeCondition( QgsExpressionNodeCondition::WhenThenList *conditions, QgsExpressionNode *elseExp = nullptr );
/**
* Create a new node with the given list of \a conditions and an optional \a elseExp expression.
*/
QgsExpressionNodeCondition( const QgsExpressionNodeCondition::WhenThenList &conditions, QgsExpressionNode *elseExp = nullptr ) SIP_SKIP
: mConditions( conditions )
, mElseExp( elseExp )
{}
~QgsExpressionNodeCondition();
virtual QgsExpressionNode::NodeType nodeType() const override;
virtual QVariant evalNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
virtual bool prepareNode( QgsExpression *parent, const QgsExpressionContext *context ) override;
virtual QString dump() const override;
virtual QSet<QString> referencedColumns() const override;
virtual QSet<QString> referencedVariables() const override;
virtual bool needsGeometry() const override;
virtual QgsExpressionNode *clone() const override;
virtual bool isStatic( QgsExpression *parent, const QgsExpressionContext *context ) const override;
private:
WhenThenList mConditions;
QgsExpressionNode *mElseExp = nullptr;
};
#endif // QGSEXPRESSIONNODEIMPL_H

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,7 @@
#include "qgslogger.h"
#include "qgsexpression.h"
#include "qgsexpressionfunction.h"
#include "qgsfields.h"
#include "qgsvectorlayer.h"
#include "qgsproject.h"
@ -190,7 +191,7 @@ bool QgsExpressionContextScope::hasFunction( const QString &name ) const
return mFunctions.contains( name );
}
QgsExpression::Function *QgsExpressionContextScope::function( const QString &name ) const
QgsExpressionFunction *QgsExpressionContextScope::function( const QString &name ) const
{
return mFunctions.contains( name ) ? mFunctions.value( name ) : nullptr;
}
@ -423,7 +424,7 @@ QStringList QgsExpressionContext::functionNames() const
return result;
}
QgsExpression::Function *QgsExpressionContext::function( const QString &name ) const
QgsExpressionFunction *QgsExpressionContext::function( const QString &name ) const
{
//iterate through stack backwards, so that higher priority variables take precedence
QList< QgsExpressionContextScope * >::const_iterator it = mStack.constEnd();
@ -638,7 +639,7 @@ class GetComposerItemVariables : public QgsScopedExpressionFunction
{
public:
GetComposerItemVariables( const QgsComposition *c )
: QgsScopedExpressionFunction( QStringLiteral( "item_variables" ), QgsExpression::ParameterList() << QgsExpression::Parameter( QStringLiteral( "id" ) ), QStringLiteral( "Composition" ) )
: QgsScopedExpressionFunction( QStringLiteral( "item_variables" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "id" ) ), QStringLiteral( "Composition" ) )
, mComposition( c )
{}
@ -673,7 +674,7 @@ class GetLayerVisibility : public QgsScopedExpressionFunction
{
public:
GetLayerVisibility( const QList<QgsMapLayer *> &layers )
: QgsScopedExpressionFunction( QStringLiteral( "is_layer_visible" ), QgsExpression::ParameterList() << QgsExpression::Parameter( QStringLiteral( "id" ) ), QStringLiteral( "General" ) )
: QgsScopedExpressionFunction( QStringLiteral( "is_layer_visible" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "id" ) ), QStringLiteral( "General" ) )
, mLayers( layers )
{}
@ -1081,19 +1082,19 @@ void QgsExpressionContextUtils::registerContextFunctions()
QgsExpression::registerFunction( new GetLayerVisibility( QList<QgsMapLayer *>() ) );
}
bool QgsScopedExpressionFunction::usesGeometry( const QgsExpression::NodeFunction *node ) const
bool QgsScopedExpressionFunction::usesGeometry( const QgsExpressionNodeFunction *node ) const
{
Q_UNUSED( node )
return mUsesGeometry;
}
QSet<QString> QgsScopedExpressionFunction::referencedColumns( const QgsExpression::NodeFunction *node ) const
QSet<QString> QgsScopedExpressionFunction::referencedColumns( const QgsExpressionNodeFunction *node ) const
{
Q_UNUSED( node )
return mReferencedColumns;
}
bool QgsScopedExpressionFunction::isStatic( const QgsExpression::NodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) const
bool QgsScopedExpressionFunction::isStatic( const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) const
{
return allParamsStatic( node, parent, context );
}

View File

@ -25,8 +25,10 @@
#include <QSet>
#include "qgsfeature.h"
#include "qgsexpression.h"
#include "qgsexpressionfunction.h"
class QgsExpression;
class QgsExpressionNodeFunction;
class QgsMapLayer;
class QgsComposition;
class QgsComposerItem;
@ -43,7 +45,7 @@ class QgsSymbol;
* \since QGIS 2.12
*/
class CORE_EXPORT QgsScopedExpressionFunction : public QgsExpression::Function
class CORE_EXPORT QgsScopedExpressionFunction : public QgsExpressionFunction
{
public:
@ -61,7 +63,7 @@ class CORE_EXPORT QgsScopedExpressionFunction : public QgsExpression::Function
bool lazyEval = false,
bool handlesNull = false,
bool isContextual = true )
: QgsExpression::Function( fnname, params, group, helpText, lazyEval, handlesNull, isContextual )
: QgsExpressionFunction( fnname, params, group, helpText, lazyEval, handlesNull, isContextual )
, mUsesGeometry( usesGeometry )
, mReferencedColumns( referencedColumns )
{}
@ -72,7 +74,7 @@ class CORE_EXPORT QgsScopedExpressionFunction : public QgsExpression::Function
* \since QGIS 3.0
*/
QgsScopedExpressionFunction( const QString &fnname,
const QgsExpression::ParameterList &params,
const QgsExpressionFunction::ParameterList &params,
const QString &group,
const QString &helpText = QString(),
bool usesGeometry = false,
@ -80,7 +82,7 @@ class CORE_EXPORT QgsScopedExpressionFunction : public QgsExpression::Function
bool lazyEval = false,
bool handlesNull = false,
bool isContextual = true )
: QgsExpression::Function( fnname, params, group, helpText, lazyEval, handlesNull, isContextual )
: QgsExpressionFunction( fnname, params, group, helpText, lazyEval, handlesNull, isContextual )
, mUsesGeometry( usesGeometry )
, mReferencedColumns( referencedColumns )
{}
@ -91,11 +93,11 @@ class CORE_EXPORT QgsScopedExpressionFunction : public QgsExpression::Function
*/
virtual QgsScopedExpressionFunction *clone() const = 0 SIP_FACTORY;
virtual bool usesGeometry( const QgsExpression::NodeFunction *node ) const override;
virtual bool usesGeometry( const QgsExpressionNodeFunction *node ) const override;
virtual QSet<QString> referencedColumns( const QgsExpression::NodeFunction *node ) const override;
virtual QSet<QString> referencedColumns( const QgsExpressionNodeFunction *node ) const override;
virtual bool isStatic( const QgsExpression::NodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) const override;
virtual bool isStatic( const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) const override;
private:
bool mUsesGeometry;
@ -253,7 +255,7 @@ class CORE_EXPORT QgsExpressionContextScope
* \see functionNames()
* \see variable()
*/
QgsExpression::Function *function( const QString &name ) const;
QgsExpressionFunction *function( const QString &name ) const;
/** Retrieves a list of names of functions contained in the scope.
* \see function()
@ -479,7 +481,7 @@ class CORE_EXPORT QgsExpressionContext
* \returns function if contained by the context, otherwise null.
* \see hasFunction
*/
QgsExpression::Function *function( const QString &name ) const;
QgsExpressionFunction *function( const QString &name ) const;
/** Returns the number of scopes contained in the context.
*/

View File

@ -31,7 +31,9 @@
#include <stdlib.h> // atof()
#include "qgsexpression.h"
struct expression_parser_context;
#include "expression/qgsexpressionnodeimpl.h"
#include "qgsexpressionfunction.h"
struct expression_parser_context;
#include "qgsexpressionparser.hpp"
#include <QLocale>
@ -47,8 +49,8 @@ struct expression_parser_context;
#define YY_NO_UNISTD_H
#endif
#define B_OP(x) yylval->b_op = QgsExpression::x
#define U_OP(x) yylval->u_op = QgsExpression::x
#define B_OP(x) yylval->b_op = QgsExpressionNodeBinaryOperator::x
#define U_OP(x) yylval->u_op = QgsExpressionNodeUnaryOperator::x
#define TEXT yylval->text = new QString( QString::fromUtf8(yytext) );
#define TEXT_FILTER(filter_fn) yylval->text = new QString( filter_fn( QString::fromUtf8(yytext) ) );

View File

@ -17,7 +17,10 @@
#include <qglobal.h>
#include <QList>
#include <cstdlib>
#include "qgsexpression.h"
#include "expression/qgsexpression.h"
#include "expression/qgsexpressionnode.h"
#include "expression/qgsexpressionnodeimpl.h"
#include "expression/qgsexpressionfunction.h"
#ifdef _MSC_VER
# pragma warning( disable: 4065 ) // switch statement contains 'default' but no 'case' labels
@ -41,7 +44,7 @@ extern YY_BUFFER_STATE exp__scan_string(const char* buffer, yyscan_t scanner);
/** returns parsed tree, otherwise returns nullptr and sets parserErrorMsg
(interface function to be called from QgsExpression)
*/
QgsExpression::Node* parseExpression(const QString& str, QString& parserErrorMsg);
QgsExpressionNode* parseExpression(const QString& str, QString& parserErrorMsg);
/** error handler for bison */
void exp_error(expression_parser_context* parser_ctx, const char* msg);
@ -54,7 +57,7 @@ struct expression_parser_context
// varible where the parser error will be stored
QString errorMsg;
// root node of the expression
QgsExpression::Node* rootNode;
QgsExpressionNode* rootNode;
};
#define scanner parser_ctx->flex_scanner
@ -62,7 +65,7 @@ struct expression_parser_context
// we want verbose error messages
#define YYERROR_VERBOSE 1
#define BINOP(x, y, z) new QgsExpression::NodeBinaryOperator(x, y, z)
#define BINOP(x, y, z) new QgsExpressionNodeBinaryOperator(x, y, z)
%}
@ -75,17 +78,17 @@ struct expression_parser_context
%union
{
QgsExpression::Node* node;
QgsExpression::NodeList* nodelist;
QgsExpression::NamedNode* namednode;
QgsExpressionNode* node;
QgsExpressionNode::NodeList* nodelist;
QgsExpressionNode::NamedNode* namednode;
double numberFloat;
int numberInt;
bool boolVal;
QString* text;
QgsExpression::BinaryOperator b_op;
QgsExpression::UnaryOperator u_op;
QgsExpression::WhenThen* whenthen;
QgsExpression::WhenThenList* whenthenlist;
QgsExpressionNodeBinaryOperator::BinaryOperator b_op;
QgsExpressionNodeUnaryOperator::UnaryOperator u_op;
QgsExpressionNodeCondition::WhenThen* whenthen;
QgsExpressionNodeCondition::WhenThenList* whenthenlist;
}
%start root
@ -180,7 +183,7 @@ expression:
| expression MOD expression { $$ = BINOP($2, $1, $3); }
| expression POW expression { $$ = BINOP($2, $1, $3); }
| expression CONCAT expression { $$ = BINOP($2, $1, $3); }
| NOT expression { $$ = new QgsExpression::NodeUnaryOperator($1, $2); }
| NOT expression { $$ = new QgsExpressionNodeUnaryOperator($1, $2); }
| '(' expression ')' { $$ = $2; }
| FUNCTION '(' exp_list ')'
{
@ -195,7 +198,7 @@ expression:
YYERROR;
}
QString paramError;
if ( !QgsExpression::NodeFunction::validateParams( fnIndex, $3, paramError ) )
if ( !QgsExpressionNodeFunction::validateParams( fnIndex, $3, paramError ) )
{
exp_error( parser_ctx, paramError.toLocal8Bit().constData() );
delete $3;
@ -209,7 +212,7 @@ expression:
delete $3;
YYERROR;
}
$$ = new QgsExpression::NodeFunction(fnIndex, $3);
$$ = new QgsExpressionNodeFunction(fnIndex, $3);
}
| FUNCTION '(' ')'
@ -230,20 +233,20 @@ expression:
exp_error(parser_ctx, QString( "%1 function is called with wrong number of arguments" ).arg( QgsExpression::Functions()[fnIndex]->name() ).toLocal8Bit().constData() );
YYERROR;
}
$$ = new QgsExpression::NodeFunction(fnIndex, new QgsExpression::NodeList());
$$ = new QgsExpressionNodeFunction(fnIndex, new QgsExpressionNode::NodeList());
}
| expression IN '(' exp_list ')' { $$ = new QgsExpression::NodeInOperator($1, $4, false); }
| expression NOT IN '(' exp_list ')' { $$ = new QgsExpression::NodeInOperator($1, $5, true); }
| expression IN '(' exp_list ')' { $$ = new QgsExpressionNodeInOperator($1, $4, false); }
| expression NOT IN '(' exp_list ')' { $$ = new QgsExpressionNodeInOperator($1, $5, true); }
| PLUS expression %prec UMINUS { $$ = $2; }
| MINUS expression %prec UMINUS { $$ = new QgsExpression::NodeUnaryOperator( QgsExpression::uoMinus, $2); }
| MINUS expression %prec UMINUS { $$ = new QgsExpressionNodeUnaryOperator( QgsExpressionNodeUnaryOperator::uoMinus, $2); }
| CASE when_then_clauses END { $$ = new QgsExpression::NodeCondition($2); }
| CASE when_then_clauses ELSE expression END { $$ = new QgsExpression::NodeCondition($2,$4); }
| CASE when_then_clauses END { $$ = new QgsExpressionNodeCondition($2); }
| CASE when_then_clauses ELSE expression END { $$ = new QgsExpressionNodeCondition($2,$4); }
// columns
| COLUMN_REF { $$ = new QgsExpression::NodeColumnRef( *$1 ); delete $1; }
| COLUMN_REF { $$ = new QgsExpressionNodeColumnRef( *$1 ); delete $1; }
// special columns (actually functions with no arguments)
| SPECIAL_COL
@ -251,7 +254,7 @@ expression:
int fnIndex = QgsExpression::functionIndex(*$1);
if (fnIndex >= 0)
{
$$ = new QgsExpression::NodeFunction( fnIndex, nullptr );
$$ = new QgsExpressionNodeFunction( fnIndex, nullptr );
}
else
{
@ -265,23 +268,23 @@ expression:
| VARIABLE
{
// @var is equivalent to var( "var" )
QgsExpression::NodeList* args = new QgsExpression::NodeList();
QgsExpression::NodeLiteral* literal = new QgsExpression::NodeLiteral( QString(*$1).mid(1) );
QgsExpressionNode::NodeList* args = new QgsExpressionNode::NodeList();
QgsExpressionNodeLiteral* literal = new QgsExpressionNodeLiteral( QString(*$1).mid(1) );
args->append( literal );
$$ = new QgsExpression::NodeFunction( QgsExpression::functionIndex( "var" ), args );
$$ = new QgsExpressionNodeFunction( QgsExpression::functionIndex( "var" ), args );
delete $1;
}
// literals
| NUMBER_FLOAT { $$ = new QgsExpression::NodeLiteral( QVariant($1) ); }
| NUMBER_INT { $$ = new QgsExpression::NodeLiteral( QVariant($1) ); }
| BOOLEAN { $$ = new QgsExpression::NodeLiteral( QVariant($1) ); }
| STRING { $$ = new QgsExpression::NodeLiteral( QVariant(*$1) ); delete $1; }
| NULLVALUE { $$ = new QgsExpression::NodeLiteral( QVariant() ); }
| NUMBER_FLOAT { $$ = new QgsExpressionNodeLiteral( QVariant($1) ); }
| NUMBER_INT { $$ = new QgsExpressionNodeLiteral( QVariant($1) ); }
| BOOLEAN { $$ = new QgsExpressionNodeLiteral( QVariant($1) ); }
| STRING { $$ = new QgsExpressionNodeLiteral( QVariant(*$1) ); delete $1; }
| NULLVALUE { $$ = new QgsExpressionNodeLiteral( QVariant() ); }
;
named_node:
NAMED_NODE expression { $$ = new QgsExpression::NamedNode( *$1, $2 ); delete $1; }
NAMED_NODE expression { $$ = new QgsExpressionNode::NamedNode( *$1, $2 ); delete $1; }
;
exp_list:
@ -299,24 +302,24 @@ exp_list:
}
}
| exp_list COMMA named_node { $$ = $1; $1->append($3); }
| expression { $$ = new QgsExpression::NodeList(); $$->append($1); }
| named_node { $$ = new QgsExpression::NodeList(); $$->append($1); }
| expression { $$ = new QgsExpressionNode::NodeList(); $$->append($1); }
| named_node { $$ = new QgsExpressionNode::NodeList(); $$->append($1); }
;
when_then_clauses:
when_then_clauses when_then_clause { $$ = $1; $1->append($2); }
| when_then_clause { $$ = new QgsExpression::WhenThenList(); $$->append($1); }
| when_then_clause { $$ = new QgsExpressionNodeCondition::WhenThenList(); $$->append($1); }
;
when_then_clause:
WHEN expression THEN expression { $$ = new QgsExpression::WhenThen($2,$4); }
WHEN expression THEN expression { $$ = new QgsExpressionNodeCondition::WhenThen($2,$4); }
;
%%
// returns parsed tree, otherwise returns nullptr and sets parserErrorMsg
QgsExpression::Node* parseExpression(const QString& str, QString& parserErrorMsg)
QgsExpressionNode* parseExpression(const QString& str, QString& parserErrorMsg)
{
expression_parser_context ctx;
ctx.rootNode = 0;

View File

@ -60,7 +60,7 @@ class QgsExpressionPrivate
QAtomicInt ref;
QgsExpression::Node *mRootNode = nullptr;
QgsExpressionNode *mRootNode = nullptr;
QString mParserErrorString;
QString mEvalErrorString;

View File

@ -141,18 +141,18 @@ class CORE_EXPORT QgsMapLayer : public QObject
/**
* Returns the layer's data provider.
*/
virtual QgsDataProvider *dataProvider() { return nullptr; }
virtual QgsDataProvider *dataProvider();
/**
* Returns the layer's data provider in a const-correct manner
* \note not available in Python bindings
*/
virtual const QgsDataProvider *dataProvider() const SIP_SKIP { return nullptr; }
virtual const QgsDataProvider *dataProvider() const SIP_SKIP;
/** Returns the original name of the layer.
* \returns the original layer name
*/
QString originalName() const { return mLayerOrigName; }
QString originalName() const;
/** Sets the short name of the layer
* used by QGIS Server to identify the layer.
@ -397,7 +397,7 @@ class CORE_EXPORT QgsMapLayer : public QObject
/** Returns true if the layer is considered a spatial layer, ie it has some form of geometry associated with it.
* \since QGIS 2.16
*/
virtual bool isSpatial() const { return true; }
virtual bool isSpatial() const;
/** Sets state from Dom document
\param layerElement The Dom element corresponding to ``maplayer'' tag
@ -465,7 +465,7 @@ class CORE_EXPORT QgsMapLayer : public QObject
* for which layer cannot work and thus is not valid. It is not last error
* after accessing data by draw() etc.
*/
virtual QgsError error() const { return mError; }
virtual QgsError error() const;
/** Returns the layer's spatial reference system.
\since QGIS 1.4
@ -762,7 +762,7 @@ class CORE_EXPORT QgsMapLayer : public QObject
* \see setMetadata()
* \see metadataChanged()
*/
virtual const QgsLayerMetadata &metadata() const { return mMetadata; }
virtual const QgsLayerMetadata &metadata() const;
/**
* Sets the layer's \a metadata store.
@ -779,7 +779,7 @@ class CORE_EXPORT QgsMapLayer : public QObject
virtual QString htmlMetadata() const;
//! Time stamp of data source in the moment when data/metadata were loaded by provider
virtual QDateTime timestamp() const { return QDateTime() ; }
virtual QDateTime timestamp() const;
/**
* Gets the list of dependencies. This includes data dependencies set by the user (\see setDataDependencies)
@ -1032,7 +1032,7 @@ class CORE_EXPORT QgsMapLayer : public QObject
* This method returns true by default but can be overwritten to specify
* that a certain layer is writable.
*/
virtual bool isReadOnly() const { return true; }
virtual bool isReadOnly() const;
/** Layer's spatial reference system.
private to make sure setCrs must be used and crsChanged() is emitted */

View File

@ -15,6 +15,8 @@
#include "qgsogcutils.h"
#include "qgsexpression.h"
#include "qgsexpressionnodeimpl.h"
#include "qgsexpressionfunction.h"
#include "qgsexpressionprivate.h"
#include "qgsgeometry.h"
#include "qgswkbptr.h"
@ -1617,7 +1619,7 @@ QgsExpression *QgsOgcUtils::expressionFromOgcFilter( const QDomElement &element
while ( !childElem.isNull() )
{
QString errorMsg;
QgsExpression::Node *node = nodeFromOgcFilter( childElem, errorMsg );
QgsExpressionNode *node = nodeFromOgcFilter( childElem, errorMsg );
if ( !node )
{
// invalid expression, parser error
@ -1632,7 +1634,7 @@ QgsExpression *QgsOgcUtils::expressionFromOgcFilter( const QDomElement &element
}
else
{
expr->d->mRootNode = new QgsExpression::NodeBinaryOperator( QgsExpression::boConcat, expr->d->mRootNode, node );
expr->d->mRootNode = new QgsExpressionNodeBinaryOperator( QgsExpressionNodeBinaryOperator::boConcat, expr->d->mRootNode, node );
}
childElem = childElem.nextSiblingElement();
@ -1648,21 +1650,21 @@ QgsExpression *QgsOgcUtils::expressionFromOgcFilter( const QDomElement &element
static const QMap<QString, int> BINARY_OPERATORS_TAG_NAMES_MAP
{
// logical
{ QStringLiteral( "Or" ), QgsExpression::boOr },
{ QStringLiteral( "And" ), QgsExpression::boAnd },
{ QStringLiteral( "Or" ), QgsExpressionNodeBinaryOperator::boOr },
{ QStringLiteral( "And" ), QgsExpressionNodeBinaryOperator::boAnd },
// comparison
{ QStringLiteral( "PropertyIsEqualTo" ), QgsExpression::boEQ },
{ QStringLiteral( "PropertyIsNotEqualTo" ), QgsExpression::boNE },
{ QStringLiteral( "PropertyIsLessThanOrEqualTo" ), QgsExpression::boLE },
{ QStringLiteral( "PropertyIsGreaterThanOrEqualTo" ), QgsExpression::boGE },
{ QStringLiteral( "PropertyIsLessThan" ), QgsExpression::boLT },
{ QStringLiteral( "PropertyIsGreaterThan" ), QgsExpression::boGT },
{ QStringLiteral( "PropertyIsLike" ), QgsExpression::boLike },
{ QStringLiteral( "PropertyIsEqualTo" ), QgsExpressionNodeBinaryOperator::boEQ },
{ QStringLiteral( "PropertyIsNotEqualTo" ), QgsExpressionNodeBinaryOperator::boNE },
{ QStringLiteral( "PropertyIsLessThanOrEqualTo" ), QgsExpressionNodeBinaryOperator::boLE },
{ QStringLiteral( "PropertyIsGreaterThanOrEqualTo" ), QgsExpressionNodeBinaryOperator::boGE },
{ QStringLiteral( "PropertyIsLessThan" ), QgsExpressionNodeBinaryOperator::boLT },
{ QStringLiteral( "PropertyIsGreaterThan" ), QgsExpressionNodeBinaryOperator::boGT },
{ QStringLiteral( "PropertyIsLike" ), QgsExpressionNodeBinaryOperator::boLike },
// arithmetics
{ QStringLiteral( "Add" ), QgsExpression::boPlus },
{ QStringLiteral( "Sub" ), QgsExpression::boMinus },
{ QStringLiteral( "Mul" ), QgsExpression::boMul },
{ QStringLiteral( "Div" ), QgsExpression::boDiv },
{ QStringLiteral( "Add" ), QgsExpressionNodeBinaryOperator::boPlus },
{ QStringLiteral( "Sub" ), QgsExpressionNodeBinaryOperator::boMinus },
{ QStringLiteral( "Mul" ), QgsExpressionNodeBinaryOperator::boMul },
{ QStringLiteral( "Div" ), QgsExpressionNodeBinaryOperator::boDiv },
};
static int binaryOperatorFromTagName( const QString &tagName )
@ -1671,9 +1673,9 @@ static int binaryOperatorFromTagName( const QString &tagName )
return BINARY_OPERATORS_TAG_NAMES_MAP.value( tagName, -1 );
}
static QString binaryOperatorToTagName( QgsExpression::BinaryOperator op )
static QString binaryOperatorToTagName( QgsExpressionNodeBinaryOperator::BinaryOperator op )
{
if ( op == QgsExpression::boILike )
if ( op == QgsExpressionNodeBinaryOperator::boILike )
{
return QStringLiteral( "PropertyIsLike" );
}
@ -1700,7 +1702,7 @@ static bool isSpatialOperator( const QString &tagName )
QgsExpression::Node *QgsOgcUtils::nodeFromOgcFilter( QDomElement &element, QString &errorMessage )
QgsExpressionNode *QgsOgcUtils::nodeFromOgcFilter( QDomElement &element, QString &errorMessage )
{
if ( element.isNull() )
return nullptr;
@ -1750,7 +1752,7 @@ QgsExpression::Node *QgsOgcUtils::nodeFromOgcFilter( QDomElement &element, QStri
QgsExpression::NodeBinaryOperator *QgsOgcUtils::nodeBinaryOperatorFromOgcFilter( QDomElement &element, QString &errorMessage )
QgsExpressionNodeBinaryOperator *QgsOgcUtils::nodeBinaryOperatorFromOgcFilter( QDomElement &element, QString &errorMessage )
{
if ( element.isNull() )
return nullptr;
@ -1763,13 +1765,13 @@ QgsExpression::NodeBinaryOperator *QgsOgcUtils::nodeBinaryOperatorFromOgcFilter(
return nullptr;
}
if ( op == QgsExpression::boLike && element.hasAttribute( QStringLiteral( "matchCase" ) ) && element.attribute( QStringLiteral( "matchCase" ) ) == QLatin1String( "false" ) )
if ( op == QgsExpressionNodeBinaryOperator::boLike && element.hasAttribute( QStringLiteral( "matchCase" ) ) && element.attribute( QStringLiteral( "matchCase" ) ) == QLatin1String( "false" ) )
{
op = QgsExpression::boILike;
op = QgsExpressionNodeBinaryOperator::boILike;
}
QDomElement operandElem = element.firstChildElement();
QgsExpression::Node *expr = nodeFromOgcFilter( operandElem, errorMessage ), *leftOp = expr;
QgsExpressionNode *expr = nodeFromOgcFilter( operandElem, errorMessage ), *leftOp = expr;
if ( !expr )
{
if ( errorMessage.isEmpty() )
@ -1779,7 +1781,7 @@ QgsExpression::NodeBinaryOperator *QgsOgcUtils::nodeBinaryOperatorFromOgcFilter(
for ( operandElem = operandElem.nextSiblingElement(); !operandElem.isNull(); operandElem = operandElem.nextSiblingElement() )
{
QgsExpression::Node *opRight = nodeFromOgcFilter( operandElem, errorMessage );
QgsExpressionNode *opRight = nodeFromOgcFilter( operandElem, errorMessage );
if ( !opRight )
{
if ( errorMessage.isEmpty() )
@ -1788,7 +1790,7 @@ QgsExpression::NodeBinaryOperator *QgsOgcUtils::nodeBinaryOperatorFromOgcFilter(
return nullptr;
}
if ( op == QgsExpression::boLike || op == QgsExpression::boILike )
if ( op == QgsExpressionNodeBinaryOperator::boLike || op == QgsExpressionNodeBinaryOperator::boILike )
{
QString wildCard;
if ( element.hasAttribute( QStringLiteral( "wildCard" ) ) )
@ -1806,7 +1808,7 @@ QgsExpression::NodeBinaryOperator *QgsOgcUtils::nodeBinaryOperatorFromOgcFilter(
escape = element.attribute( QStringLiteral( "escape" ) );
}
// replace
QString oprValue = static_cast<const QgsExpression::NodeLiteral *>( opRight )->value().toString();
QString oprValue = static_cast<const QgsExpressionNodeLiteral *>( opRight )->value().toString();
if ( !wildCard.isEmpty() && wildCard != QLatin1String( "%" ) )
{
oprValue.replace( '%', QLatin1String( "\\%" ) );
@ -1843,10 +1845,10 @@ QgsExpression::NodeBinaryOperator *QgsOgcUtils::nodeBinaryOperatorFromOgcFilter(
{
oprValue.replace( escape + escape, escape );
}
opRight = new QgsExpression::NodeLiteral( oprValue );
opRight = new QgsExpressionNodeLiteral( oprValue );
}
expr = new QgsExpression::NodeBinaryOperator( static_cast< QgsExpression::BinaryOperator >( op ), expr, opRight );
expr = new QgsExpressionNodeBinaryOperator( static_cast< QgsExpressionNodeBinaryOperator::BinaryOperator >( op ), expr, opRight );
}
if ( expr == leftOp )
@ -1857,7 +1859,7 @@ QgsExpression::NodeBinaryOperator *QgsOgcUtils::nodeBinaryOperatorFromOgcFilter(
return nullptr;
}
QgsExpression::NodeBinaryOperator *ret = dynamic_cast< QgsExpression::NodeBinaryOperator * >( expr );
QgsExpressionNodeBinaryOperator *ret = dynamic_cast< QgsExpressionNodeBinaryOperator * >( expr );
if ( !ret )
delete expr;
@ -1865,12 +1867,12 @@ QgsExpression::NodeBinaryOperator *QgsOgcUtils::nodeBinaryOperatorFromOgcFilter(
}
QgsExpression::NodeFunction *QgsOgcUtils::nodeSpatialOperatorFromOgcFilter( QDomElement &element, QString &errorMessage )
QgsExpressionNodeFunction *QgsOgcUtils::nodeSpatialOperatorFromOgcFilter( QDomElement &element, QString &errorMessage )
{
// we are exploiting the fact that our function names are the same as the XML tag names
int opIdx = QgsExpression::functionIndex( element.tagName().toLower() );
QgsExpression::NodeList *gml2Args = new QgsExpression::NodeList();
QgsExpressionNode::NodeList *gml2Args = new QgsExpressionNode::NodeList();
QDomElement childElem = element.firstChildElement();
QString gml2Str;
while ( !childElem.isNull() && gml2Str.isEmpty() )
@ -1884,7 +1886,7 @@ QgsExpression::NodeFunction *QgsOgcUtils::nodeSpatialOperatorFromOgcFilter( QDom
}
if ( !gml2Str.isEmpty() )
{
gml2Args->append( new QgsExpression::NodeLiteral( QVariant( gml2Str.remove( '\n' ) ) ) );
gml2Args->append( new QgsExpressionNodeLiteral( QVariant( gml2Str.remove( '\n' ) ) ) );
}
else
{
@ -1893,21 +1895,21 @@ QgsExpression::NodeFunction *QgsOgcUtils::nodeSpatialOperatorFromOgcFilter( QDom
return nullptr;
}
QgsExpression::NodeList *opArgs = new QgsExpression::NodeList();
opArgs->append( new QgsExpression::NodeFunction( QgsExpression::functionIndex( QStringLiteral( "$geometry" ) ), new QgsExpression::NodeList() ) );
opArgs->append( new QgsExpression::NodeFunction( QgsExpression::functionIndex( QStringLiteral( "geomFromGML" ) ), gml2Args ) );
QgsExpressionNode::NodeList *opArgs = new QgsExpressionNode::NodeList();
opArgs->append( new QgsExpressionNodeFunction( QgsExpression::functionIndex( QStringLiteral( "$geometry" ) ), new QgsExpressionNode::NodeList() ) );
opArgs->append( new QgsExpressionNodeFunction( QgsExpression::functionIndex( QStringLiteral( "geomFromGML" ) ), gml2Args ) );
return new QgsExpression::NodeFunction( opIdx, opArgs );
return new QgsExpressionNodeFunction( opIdx, opArgs );
}
QgsExpression::NodeUnaryOperator *QgsOgcUtils::nodeNotFromOgcFilter( QDomElement &element, QString &errorMessage )
QgsExpressionNodeUnaryOperator *QgsOgcUtils::nodeNotFromOgcFilter( QDomElement &element, QString &errorMessage )
{
if ( element.tagName() != QLatin1String( "Not" ) )
return nullptr;
QDomElement operandElem = element.firstChildElement();
QgsExpression::Node *operand = nodeFromOgcFilter( operandElem, errorMessage );
QgsExpressionNode *operand = nodeFromOgcFilter( operandElem, errorMessage );
if ( !operand )
{
if ( errorMessage.isEmpty() )
@ -1915,11 +1917,11 @@ QgsExpression::NodeUnaryOperator *QgsOgcUtils::nodeNotFromOgcFilter( QDomElement
return nullptr;
}
return new QgsExpression::NodeUnaryOperator( QgsExpression::uoNot, operand );
return new QgsExpressionNodeUnaryOperator( QgsExpressionNodeUnaryOperator::uoNot, operand );
}
QgsExpression::NodeFunction *QgsOgcUtils::nodeFunctionFromOgcFilter( QDomElement &element, QString &errorMessage )
QgsExpressionNodeFunction *QgsOgcUtils::nodeFunctionFromOgcFilter( QDomElement &element, QString &errorMessage )
{
if ( element.isNull() || element.tagName() != QLatin1String( "Function" ) )
{
@ -1929,17 +1931,17 @@ QgsExpression::NodeFunction *QgsOgcUtils::nodeFunctionFromOgcFilter( QDomElement
for ( int i = 0; i < QgsExpression::Functions().size(); i++ )
{
QgsExpression::Function *funcDef = QgsExpression::Functions()[i];
QgsExpressionFunction *funcDef = QgsExpression::Functions()[i];
if ( element.attribute( QStringLiteral( "name" ) ) != funcDef->name() )
continue;
QgsExpression::NodeList *args = new QgsExpression::NodeList();
QgsExpressionNode::NodeList *args = new QgsExpressionNode::NodeList();
QDomElement operandElem = element.firstChildElement();
while ( !operandElem.isNull() )
{
QgsExpression::Node *op = nodeFromOgcFilter( operandElem, errorMessage );
QgsExpressionNode *op = nodeFromOgcFilter( operandElem, errorMessage );
if ( !op )
{
delete args;
@ -1950,7 +1952,7 @@ QgsExpression::NodeFunction *QgsOgcUtils::nodeFunctionFromOgcFilter( QDomElement
operandElem = operandElem.nextSiblingElement();
}
return new QgsExpression::NodeFunction( i, args );
return new QgsExpressionNodeFunction( i, args );
}
return nullptr;
@ -1958,7 +1960,7 @@ QgsExpression::NodeFunction *QgsOgcUtils::nodeFunctionFromOgcFilter( QDomElement
QgsExpression::Node *QgsOgcUtils::nodeLiteralFromOgcFilter( QDomElement &element, QString &errorMessage )
QgsExpressionNode *QgsOgcUtils::nodeLiteralFromOgcFilter( QDomElement &element, QString &errorMessage )
{
if ( element.isNull() || element.tagName() != QLatin1String( "Literal" ) )
{
@ -1966,13 +1968,13 @@ QgsExpression::Node *QgsOgcUtils::nodeLiteralFromOgcFilter( QDomElement &element
return nullptr;
}
QgsExpression::Node *root = nullptr;
QgsExpressionNode *root = nullptr;
// the literal content can have more children (e.g. CDATA section, text, ...)
QDomNode childNode = element.firstChild();
while ( !childNode.isNull() )
{
QgsExpression::Node *operand = nullptr;
QgsExpressionNode *operand = nullptr;
if ( childNode.nodeType() == QDomNode::ElementNode )
{
@ -2000,7 +2002,7 @@ QgsExpression::Node *QgsOgcUtils::nodeLiteralFromOgcFilter( QDomElement &element
if ( ok )
value = d;
operand = new QgsExpression::NodeLiteral( value );
operand = new QgsExpressionNodeLiteral( value );
if ( !operand )
continue;
}
@ -2012,7 +2014,7 @@ QgsExpression::Node *QgsOgcUtils::nodeLiteralFromOgcFilter( QDomElement &element
}
else
{
root = new QgsExpression::NodeBinaryOperator( QgsExpression::boConcat, root, operand );
root = new QgsExpressionNodeBinaryOperator( QgsExpressionNodeBinaryOperator::boConcat, root, operand );
}
childNode = childNode.nextSibling();
@ -2025,7 +2027,7 @@ QgsExpression::Node *QgsOgcUtils::nodeLiteralFromOgcFilter( QDomElement &element
}
QgsExpression::NodeColumnRef *QgsOgcUtils::nodeColumnRefFromOgcFilter( QDomElement &element, QString &errorMessage )
QgsExpressionNodeColumnRef *QgsOgcUtils::nodeColumnRefFromOgcFilter( QDomElement &element, QString &errorMessage )
{
if ( element.isNull() || element.tagName() != QLatin1String( "PropertyName" ) )
{
@ -2033,15 +2035,15 @@ QgsExpression::NodeColumnRef *QgsOgcUtils::nodeColumnRefFromOgcFilter( QDomEleme
return nullptr;
}
return new QgsExpression::NodeColumnRef( element.firstChild().nodeValue() );
return new QgsExpressionNodeColumnRef( element.firstChild().nodeValue() );
}
QgsExpression::Node *QgsOgcUtils::nodeIsBetweenFromOgcFilter( QDomElement &element, QString &errorMessage )
QgsExpressionNode *QgsOgcUtils::nodeIsBetweenFromOgcFilter( QDomElement &element, QString &errorMessage )
{
// <ogc:PropertyIsBetween> encode a Range check
QgsExpression::Node *operand = nullptr, *lowerBound = nullptr;
QgsExpression::Node *operand2 = nullptr, *upperBound = nullptr;
QgsExpressionNode *operand = nullptr, *lowerBound = nullptr;
QgsExpressionNode *operand2 = nullptr, *upperBound = nullptr;
QDomElement operandElem = element.firstChildElement();
while ( !operandElem.isNull() )
@ -2086,13 +2088,13 @@ QgsExpression::Node *QgsOgcUtils::nodeIsBetweenFromOgcFilter( QDomElement &eleme
return nullptr;
}
QgsExpression::Node *geOperator = new QgsExpression::NodeBinaryOperator( QgsExpression::boGE, operand, lowerBound );
QgsExpression::Node *leOperator = new QgsExpression::NodeBinaryOperator( QgsExpression::boLE, operand2, upperBound );
return new QgsExpression::NodeBinaryOperator( QgsExpression::boAnd, geOperator, leOperator );
QgsExpressionNode *geOperator = new QgsExpressionNodeBinaryOperator( QgsExpressionNodeBinaryOperator::boGE, operand, lowerBound );
QgsExpressionNode *leOperator = new QgsExpressionNodeBinaryOperator( QgsExpressionNodeBinaryOperator::boLE, operand2, upperBound );
return new QgsExpressionNodeBinaryOperator( QgsExpressionNodeBinaryOperator::boAnd, geOperator, leOperator );
}
QgsExpression::NodeBinaryOperator *QgsOgcUtils::nodePropertyIsNullFromOgcFilter( QDomElement &element, QString &errorMessage )
QgsExpressionNodeBinaryOperator *QgsOgcUtils::nodePropertyIsNullFromOgcFilter( QDomElement &element, QString &errorMessage )
{
// convert ogc:PropertyIsNull to IS operator with NULL right operand
if ( element.tagName() != QLatin1String( "PropertyIsNull" ) )
@ -2101,12 +2103,12 @@ QgsExpression::NodeBinaryOperator *QgsOgcUtils::nodePropertyIsNullFromOgcFilter(
}
QDomElement operandElem = element.firstChildElement();
QgsExpression::Node *opLeft = nodeFromOgcFilter( operandElem, errorMessage );
QgsExpressionNode *opLeft = nodeFromOgcFilter( operandElem, errorMessage );
if ( !opLeft )
return nullptr;
QgsExpression::Node *opRight = new QgsExpression::NodeLiteral( QVariant() );
return new QgsExpression::NodeBinaryOperator( QgsExpression::boIs, opLeft, opRight );
QgsExpressionNode *opRight = new QgsExpressionNodeLiteral( QVariant() );
return new QgsExpressionNodeBinaryOperator( QgsExpressionNodeBinaryOperator::boIs, opLeft, opRight );
}
@ -2172,15 +2174,15 @@ QDomElement QgsOgcUtils::expressionToOgcExpression( const QgsExpression &exp,
bool invertAxisOrientation,
QString *errorMessage )
{
const QgsExpression::Node *node = exp.rootNode();
const QgsExpressionNode *node = exp.rootNode();
if ( !node )
return QDomElement();
switch ( node->nodeType() )
{
case QgsExpression::ntFunction:
case QgsExpression::ntLiteral:
case QgsExpression::ntColumnRef:
case QgsExpressionNode::ntFunction:
case QgsExpressionNode::ntLiteral:
case QgsExpressionNode::ntColumnRef:
{
QgsOgcUtilsExprToFilter utils( doc, gmlVersion, filterVersion, geometryName, srsName, honourAxisOrientation, invertAxisOrientation );
QDomElement exprRootElem = utils.expressionNodeToOgcFilter( node );
@ -2243,22 +2245,22 @@ QDomElement QgsOgcUtils::SQLStatementToOgcFilter( const QgsSQLStatement &stateme
//
QDomElement QgsOgcUtilsExprToFilter::expressionNodeToOgcFilter( const QgsExpression::Node *node )
QDomElement QgsOgcUtilsExprToFilter::expressionNodeToOgcFilter( const QgsExpressionNode *node )
{
switch ( node->nodeType() )
{
case QgsExpression::ntUnaryOperator:
return expressionUnaryOperatorToOgcFilter( static_cast<const QgsExpression::NodeUnaryOperator *>( node ) );
case QgsExpression::ntBinaryOperator:
return expressionBinaryOperatorToOgcFilter( static_cast<const QgsExpression::NodeBinaryOperator *>( node ) );
case QgsExpression::ntInOperator:
return expressionInOperatorToOgcFilter( static_cast<const QgsExpression::NodeInOperator *>( node ) );
case QgsExpression::ntFunction:
return expressionFunctionToOgcFilter( static_cast<const QgsExpression::NodeFunction *>( node ) );
case QgsExpression::ntLiteral:
return expressionLiteralToOgcFilter( static_cast<const QgsExpression::NodeLiteral *>( node ) );
case QgsExpression::ntColumnRef:
return expressionColumnRefToOgcFilter( static_cast<const QgsExpression::NodeColumnRef *>( node ) );
case QgsExpressionNode::ntUnaryOperator:
return expressionUnaryOperatorToOgcFilter( static_cast<const QgsExpressionNodeUnaryOperator *>( node ) );
case QgsExpressionNode::ntBinaryOperator:
return expressionBinaryOperatorToOgcFilter( static_cast<const QgsExpressionNodeBinaryOperator *>( node ) );
case QgsExpressionNode::ntInOperator:
return expressionInOperatorToOgcFilter( static_cast<const QgsExpressionNodeInOperator *>( node ) );
case QgsExpressionNode::ntFunction:
return expressionFunctionToOgcFilter( static_cast<const QgsExpressionNodeFunction *>( node ) );
case QgsExpressionNode::ntLiteral:
return expressionLiteralToOgcFilter( static_cast<const QgsExpressionNodeLiteral *>( node ) );
case QgsExpressionNode::ntColumnRef:
return expressionColumnRefToOgcFilter( static_cast<const QgsExpressionNodeColumnRef *>( node ) );
default:
mErrorMessage = QObject::tr( "Node type not supported: %1" ).arg( node->nodeType() );
@ -2267,7 +2269,7 @@ QDomElement QgsOgcUtilsExprToFilter::expressionNodeToOgcFilter( const QgsExpress
}
QDomElement QgsOgcUtilsExprToFilter::expressionUnaryOperatorToOgcFilter( const QgsExpression::NodeUnaryOperator *node )
QDomElement QgsOgcUtilsExprToFilter::expressionUnaryOperatorToOgcFilter( const QgsExpressionNodeUnaryOperator *node )
{
QDomElement operandElem = expressionNodeToOgcFilter( node->operand() );
@ -2277,9 +2279,9 @@ QDomElement QgsOgcUtilsExprToFilter::expressionUnaryOperatorToOgcFilter( const Q
QDomElement uoElem;
switch ( node->op() )
{
case QgsExpression::uoMinus:
case QgsExpressionNodeUnaryOperator::uoMinus:
uoElem = mDoc.createElement( mFilterPrefix + ":Literal" );
if ( node->operand()->nodeType() == QgsExpression::ntLiteral )
if ( node->operand()->nodeType() == QgsExpressionNode::ntLiteral )
{
// operand expression already created a Literal node:
// take the literal value, prepend - and remove old literal node
@ -2292,13 +2294,13 @@ QDomElement QgsOgcUtilsExprToFilter::expressionUnaryOperatorToOgcFilter( const Q
return QDomElement();
}
break;
case QgsExpression::uoNot:
case QgsExpressionNodeUnaryOperator::uoNot:
uoElem = mDoc.createElement( mFilterPrefix + ":Not" );
uoElem.appendChild( operandElem );
break;
default:
mErrorMessage = QObject::tr( "Unary operator %1 not implemented yet" ).arg( QgsExpression::UNARY_OPERATOR_TEXT[node->op()] );
mErrorMessage = QObject::tr( "Unary operator '%1' not implemented yet" ).arg( node->text() );
return QDomElement();
}
@ -2306,27 +2308,27 @@ QDomElement QgsOgcUtilsExprToFilter::expressionUnaryOperatorToOgcFilter( const Q
}
QDomElement QgsOgcUtilsExprToFilter::expressionBinaryOperatorToOgcFilter( const QgsExpression::NodeBinaryOperator *node )
QDomElement QgsOgcUtilsExprToFilter::expressionBinaryOperatorToOgcFilter( const QgsExpressionNodeBinaryOperator *node )
{
QDomElement leftElem = expressionNodeToOgcFilter( node->opLeft() );
if ( !mErrorMessage.isEmpty() )
return QDomElement();
QgsExpression::BinaryOperator op = node->op();
QgsExpressionNodeBinaryOperator::BinaryOperator op = node->op();
// before right operator is parsed: to allow NULL handling
if ( op == QgsExpression::boIs || op == QgsExpression::boIsNot )
if ( op == QgsExpressionNodeBinaryOperator::boIs || op == QgsExpressionNodeBinaryOperator::boIsNot )
{
if ( node->opRight()->nodeType() == QgsExpression::ntLiteral )
if ( node->opRight()->nodeType() == QgsExpressionNode::ntLiteral )
{
const QgsExpression::NodeLiteral *rightLit = static_cast<const QgsExpression::NodeLiteral *>( node->opRight() );
const QgsExpressionNodeLiteral *rightLit = static_cast<const QgsExpressionNodeLiteral *>( node->opRight() );
if ( rightLit->value().isNull() )
{
QDomElement elem = mDoc.createElement( mFilterPrefix + ":PropertyIsNull" );
elem.appendChild( leftElem );
if ( op == QgsExpression::boIsNot )
if ( op == QgsExpressionNodeBinaryOperator::boIsNot )
{
QDomElement notElem = mDoc.createElement( mFilterPrefix + ":Not" );
notElem.appendChild( elem );
@ -2337,7 +2339,7 @@ QDomElement QgsOgcUtilsExprToFilter::expressionBinaryOperatorToOgcFilter( const
}
// continue with equal / not equal operator once the null case is handled
op = ( op == QgsExpression::boIs ? QgsExpression::boEQ : QgsExpression::boNE );
op = ( op == QgsExpressionNodeBinaryOperator::boIs ? QgsExpressionNodeBinaryOperator::boEQ : QgsExpressionNodeBinaryOperator::boNE );
}
}
@ -2352,15 +2354,15 @@ QDomElement QgsOgcUtilsExprToFilter::expressionBinaryOperatorToOgcFilter( const
{
// not implemented binary operators
// TODO: regex, % (mod), ^ (pow) are not supported yet
mErrorMessage = QObject::tr( "Binary operator %1 not implemented yet" ).arg( QgsExpression::BINARY_OPERATOR_TEXT[op] );
mErrorMessage = QObject::tr( "Binary operator %1 not implemented yet" ).arg( node->text() );
return QDomElement();
}
QDomElement boElem = mDoc.createElement( mFilterPrefix + ":" + opText );
if ( op == QgsExpression::boLike || op == QgsExpression::boILike )
if ( op == QgsExpressionNodeBinaryOperator::boLike || op == QgsExpressionNodeBinaryOperator::boILike )
{
if ( op == QgsExpression::boILike )
if ( op == QgsExpressionNodeBinaryOperator::boILike )
boElem.setAttribute( QStringLiteral( "matchCase" ), QStringLiteral( "false" ) );
// setup wildCards to <ogc:PropertyIsLike>
@ -2378,7 +2380,7 @@ QDomElement QgsOgcUtilsExprToFilter::expressionBinaryOperatorToOgcFilter( const
}
QDomElement QgsOgcUtilsExprToFilter::expressionLiteralToOgcFilter( const QgsExpression::NodeLiteral *node )
QDomElement QgsOgcUtilsExprToFilter::expressionLiteralToOgcFilter( const QgsExpressionNodeLiteral *node )
{
QString value;
switch ( node->value().type() )
@ -2404,7 +2406,7 @@ QDomElement QgsOgcUtilsExprToFilter::expressionLiteralToOgcFilter( const QgsExpr
}
QDomElement QgsOgcUtilsExprToFilter::expressionColumnRefToOgcFilter( const QgsExpression::NodeColumnRef *node )
QDomElement QgsOgcUtilsExprToFilter::expressionColumnRefToOgcFilter( const QgsExpressionNodeColumnRef *node )
{
QDomElement propElem = mDoc.createElement( mFilterPrefix + ":" + mPropertyName );
propElem.appendChild( mDoc.createTextNode( node->name() ) );
@ -2413,7 +2415,7 @@ QDomElement QgsOgcUtilsExprToFilter::expressionColumnRefToOgcFilter( const QgsEx
QDomElement QgsOgcUtilsExprToFilter::expressionInOperatorToOgcFilter( const QgsExpression::NodeInOperator *node )
QDomElement QgsOgcUtilsExprToFilter::expressionInOperatorToOgcFilter( const QgsExpressionNodeInOperator *node )
{
if ( node->list()->list().size() == 1 )
return expressionNodeToOgcFilter( node->list()->list()[0] );
@ -2421,7 +2423,7 @@ QDomElement QgsOgcUtilsExprToFilter::expressionInOperatorToOgcFilter( const QgsE
QDomElement orElem = mDoc.createElement( mFilterPrefix + ":Or" );
QDomElement leftNode = expressionNodeToOgcFilter( node->node() );
Q_FOREACH ( QgsExpression::Node *n, node->list()->list() )
Q_FOREACH ( QgsExpressionNode *n, node->list()->list() )
{
QDomElement listNode = expressionNodeToOgcFilter( n );
if ( !mErrorMessage.isEmpty() )
@ -2465,31 +2467,31 @@ static QString tagNameForSpatialOperator( const QString &fnName )
return BINARY_SPATIAL_OPS_MAP.value( fnName );
}
static bool isGeometryColumn( const QgsExpression::Node *node )
static bool isGeometryColumn( const QgsExpressionNode *node )
{
if ( node->nodeType() != QgsExpression::ntFunction )
if ( node->nodeType() != QgsExpressionNode::ntFunction )
return false;
const QgsExpression::NodeFunction *fn = static_cast<const QgsExpression::NodeFunction *>( node );
QgsExpression::Function *fd = QgsExpression::Functions()[fn->fnIndex()];
const QgsExpressionNodeFunction *fn = static_cast<const QgsExpressionNodeFunction *>( node );
QgsExpressionFunction *fd = QgsExpression::Functions()[fn->fnIndex()];
return fd->name() == QLatin1String( "$geometry" );
}
static QgsGeometry geometryFromConstExpr( const QgsExpression::Node *node )
static QgsGeometry geometryFromConstExpr( const QgsExpressionNode *node )
{
// Right now we support only geomFromWKT(' ..... ')
// Ideally we should support any constant sub-expression (not dependent on feature's geometry or attributes)
if ( node->nodeType() == QgsExpression::ntFunction )
if ( node->nodeType() == QgsExpressionNode::ntFunction )
{
const QgsExpression::NodeFunction *fnNode = static_cast<const QgsExpression::NodeFunction *>( node );
QgsExpression::Function *fnDef = QgsExpression::Functions()[fnNode->fnIndex()];
const QgsExpressionNodeFunction *fnNode = static_cast<const QgsExpressionNodeFunction *>( node );
QgsExpressionFunction *fnDef = QgsExpression::Functions()[fnNode->fnIndex()];
if ( fnDef->name() == QLatin1String( "geom_from_wkt" ) )
{
const QList<QgsExpression::Node *> &args = fnNode->args()->list();
if ( args[0]->nodeType() == QgsExpression::ntLiteral )
const QList<QgsExpressionNode *> &args = fnNode->args()->list();
if ( args[0]->nodeType() == QgsExpressionNode::ntLiteral )
{
QString wkt = static_cast<const QgsExpression::NodeLiteral *>( args[0] )->value().toString();
QString wkt = static_cast<const QgsExpressionNodeLiteral *>( args[0] )->value().toString();
return QgsGeometry::fromWkt( wkt );
}
}
@ -2498,13 +2500,13 @@ static QgsGeometry geometryFromConstExpr( const QgsExpression::Node *node )
}
QDomElement QgsOgcUtilsExprToFilter::expressionFunctionToOgcFilter( const QgsExpression::NodeFunction *node )
QDomElement QgsOgcUtilsExprToFilter::expressionFunctionToOgcFilter( const QgsExpressionNodeFunction *node )
{
QgsExpression::Function *fd = QgsExpression::Functions()[node->fnIndex()];
QgsExpressionFunction *fd = QgsExpression::Functions()[node->fnIndex()];
if ( fd->name() == QLatin1String( "intersects_bbox" ) )
{
QList<QgsExpression::Node *> argNodes = node->args()->list();
QList<QgsExpressionNode *> argNodes = node->args()->list();
Q_ASSERT( argNodes.count() == 2 ); // binary spatial ops must have two args
QgsGeometry geom = geometryFromConstExpr( argNodes[1] );
@ -2535,10 +2537,10 @@ QDomElement QgsOgcUtilsExprToFilter::expressionFunctionToOgcFilter( const QgsExp
if ( isBinarySpatialOperator( fd->name() ) )
{
QList<QgsExpression::Node *> argNodes = node->args()->list();
QList<QgsExpressionNode *> argNodes = node->args()->list();
Q_ASSERT( argNodes.count() == 2 ); // binary spatial ops must have two args
QgsExpression::Node *otherNode = nullptr;
QgsExpressionNode *otherNode = nullptr;
if ( isGeometryColumn( argNodes[0] ) )
otherNode = argNodes[1];
else if ( isGeometryColumn( argNodes[1] ) )
@ -2552,23 +2554,23 @@ QDomElement QgsOgcUtilsExprToFilter::expressionFunctionToOgcFilter( const QgsExp
QDomElement otherGeomElem;
// the other node must be a geometry constructor
if ( otherNode->nodeType() != QgsExpression::ntFunction )
if ( otherNode->nodeType() != QgsExpressionNode::ntFunction )
{
mErrorMessage = QObject::tr( "spatial operator: the other operator must be a geometry constructor function" );
return QDomElement();
}
const QgsExpression::NodeFunction *otherFn = static_cast<const QgsExpression::NodeFunction *>( otherNode );
QgsExpression::Function *otherFnDef = QgsExpression::Functions()[otherFn->fnIndex()];
const QgsExpressionNodeFunction *otherFn = static_cast<const QgsExpressionNodeFunction *>( otherNode );
QgsExpressionFunction *otherFnDef = QgsExpression::Functions()[otherFn->fnIndex()];
if ( otherFnDef->name() == QLatin1String( "geom_from_wkt" ) )
{
QgsExpression::Node *firstFnArg = otherFn->args()->list()[0];
if ( firstFnArg->nodeType() != QgsExpression::ntLiteral )
QgsExpressionNode *firstFnArg = otherFn->args()->list()[0];
if ( firstFnArg->nodeType() != QgsExpressionNode::ntLiteral )
{
mErrorMessage = QObject::tr( "geom_from_wkt: argument must be string literal" );
return QDomElement();
}
QString wkt = static_cast<const QgsExpression::NodeLiteral *>( firstFnArg )->value().toString();
QString wkt = static_cast<const QgsExpressionNodeLiteral *>( firstFnArg )->value().toString();
QgsGeometry geom = QgsGeometry::fromWkt( wkt );
otherGeomElem = QgsOgcUtils::geometryToGML( &geom, mDoc, mGMLVersion, mSrsName, mInvertAxisOrientation,
QStringLiteral( "qgis_id_geom_%1" ).arg( mGeomId ) );
@ -2576,15 +2578,15 @@ QDomElement QgsOgcUtilsExprToFilter::expressionFunctionToOgcFilter( const QgsExp
}
else if ( otherFnDef->name() == QLatin1String( "geom_from_gml" ) )
{
QgsExpression::Node *firstFnArg = otherFn->args()->list()[0];
if ( firstFnArg->nodeType() != QgsExpression::ntLiteral )
QgsExpressionNode *firstFnArg = otherFn->args()->list()[0];
if ( firstFnArg->nodeType() != QgsExpressionNode::ntLiteral )
{
mErrorMessage = QObject::tr( "geom_from_gml: argument must be string literal" );
return QDomElement();
}
QDomDocument geomDoc;
QString gml = static_cast<const QgsExpression::NodeLiteral *>( firstFnArg )->value().toString();
QString gml = static_cast<const QgsExpressionNodeLiteral *>( firstFnArg )->value().toString();
if ( !geomDoc.setContent( gml, true ) )
{
mErrorMessage = QObject::tr( "geom_from_gml: unable to parse XML" );
@ -2619,7 +2621,7 @@ QDomElement QgsOgcUtilsExprToFilter::expressionFunctionToOgcFilter( const QgsExp
// this is somehow wrong - we are just hoping that the other side supports the same functions as we do...
QDomElement funcElem = mDoc.createElement( mFilterPrefix + ":Function" );
funcElem.setAttribute( QStringLiteral( "name" ), fd->name() );
Q_FOREACH ( QgsExpression::Node *n, node->args()->list() )
Q_FOREACH ( QgsExpressionNode *n, node->args()->list() )
{
QDomElement childElem = expressionNodeToOgcFilter( n );
if ( !mErrorMessage.isEmpty() )

View File

@ -34,6 +34,8 @@ class QgsRectangle;
#include "qgsgeometry.h"
#include "qgsexpression.h"
#include "qgsexpressionnode.h"
#include "qgsexpressionnodeimpl.h"
#include "qgssqlstatement.h"
/** \ingroup core
@ -275,23 +277,23 @@ class CORE_EXPORT QgsOgcUtils
static QDomElement createGMLPositions( const QgsPolyline &points, QDomDocument &doc );
//! handle a generic sub-expression
static QgsExpression::Node *nodeFromOgcFilter( QDomElement &element, QString &errorMessage );
static QgsExpressionNode *nodeFromOgcFilter( QDomElement &element, QString &errorMessage );
//! handle a generic binary operator
static QgsExpression::NodeBinaryOperator *nodeBinaryOperatorFromOgcFilter( QDomElement &element, QString &errorMessage );
static QgsExpressionNodeBinaryOperator *nodeBinaryOperatorFromOgcFilter( QDomElement &element, QString &errorMessage );
//! handles various spatial operation tags (\verbatim <Intersects> \endverbatim, \verbatim <Touches> \endverbatim etc.)
static QgsExpression::NodeFunction *nodeSpatialOperatorFromOgcFilter( QDomElement &element, QString &errorMessage );
static QgsExpressionNodeFunction *nodeSpatialOperatorFromOgcFilter( QDomElement &element, QString &errorMessage );
//! handle \verbatim <Not> \endverbatim tag
static QgsExpression::NodeUnaryOperator *nodeNotFromOgcFilter( QDomElement &element, QString &errorMessage );
static QgsExpressionNodeUnaryOperator *nodeNotFromOgcFilter( QDomElement &element, QString &errorMessage );
//! handles \verbatim <Function> \endverbatim tag
static QgsExpression::NodeFunction *nodeFunctionFromOgcFilter( QDomElement &element, QString &errorMessage );
static QgsExpressionNodeFunction *nodeFunctionFromOgcFilter( QDomElement &element, QString &errorMessage );
//! handles \verbatim <Literal> \endverbatim tag
static QgsExpression::Node *nodeLiteralFromOgcFilter( QDomElement &element, QString &errorMessage );
static QgsExpressionNode *nodeLiteralFromOgcFilter( QDomElement &element, QString &errorMessage );
//! handles \verbatim <PropertyName> \endverbatim tag
static QgsExpression::NodeColumnRef *nodeColumnRefFromOgcFilter( QDomElement &element, QString &errorMessage );
static QgsExpressionNodeColumnRef *nodeColumnRefFromOgcFilter( QDomElement &element, QString &errorMessage );
//! handles \verbatim <PropertyIsBetween> \endverbatim tag
static QgsExpression::Node *nodeIsBetweenFromOgcFilter( QDomElement &element, QString &errorMessage );
static QgsExpressionNode *nodeIsBetweenFromOgcFilter( QDomElement &element, QString &errorMessage );
//! handles \verbatim <PropertyIsNull> \endverbatim tag
static QgsExpression::NodeBinaryOperator *nodePropertyIsNullFromOgcFilter( QDomElement &element, QString &errorMessage );
static QgsExpressionNodeBinaryOperator *nodePropertyIsNullFromOgcFilter( QDomElement &element, QString &errorMessage );
};
#ifndef SIP_RUN
@ -313,7 +315,7 @@ class QgsOgcUtilsExprToFilter
bool invertAxisOrientation );
//! Convert an expression to a OGC filter
QDomElement expressionNodeToOgcFilter( const QgsExpression::Node *node );
QDomElement expressionNodeToOgcFilter( const QgsExpressionNode *node );
//! Return whether the gml: namespace is used
bool GMLNamespaceUsed() const { return mGMLUsed; }
@ -334,12 +336,12 @@ class QgsOgcUtilsExprToFilter
QString mPropertyName;
int mGeomId;
QDomElement expressionUnaryOperatorToOgcFilter( const QgsExpression::NodeUnaryOperator *node );
QDomElement expressionBinaryOperatorToOgcFilter( const QgsExpression::NodeBinaryOperator *node );
QDomElement expressionLiteralToOgcFilter( const QgsExpression::NodeLiteral *node );
QDomElement expressionColumnRefToOgcFilter( const QgsExpression::NodeColumnRef *node );
QDomElement expressionInOperatorToOgcFilter( const QgsExpression::NodeInOperator *node );
QDomElement expressionFunctionToOgcFilter( const QgsExpression::NodeFunction *node );
QDomElement expressionUnaryOperatorToOgcFilter( const QgsExpressionNodeUnaryOperator *node );
QDomElement expressionBinaryOperatorToOgcFilter( const QgsExpressionNodeBinaryOperator *node );
QDomElement expressionLiteralToOgcFilter( const QgsExpressionNodeLiteral *node );
QDomElement expressionColumnRefToOgcFilter( const QgsExpressionNodeColumnRef *node );
QDomElement expressionInOperatorToOgcFilter( const QgsExpressionNodeInOperator *node );
QDomElement expressionFunctionToOgcFilter( const QgsExpressionNodeFunction *node );
};
/** \ingroup core

View File

@ -17,6 +17,7 @@
#include "qgslogger.h"
#include "qgsexpression.h"
#include "qgsexpressionnodeimpl.h"
#include "qgsfeature.h"
#include "qgssymbollayerutils.h"
#include "qgscolorramp.h"
@ -251,17 +252,17 @@ QgsGenericNumericTransformer *QgsGenericNumericTransformer::fromExpression( cons
if ( !e.rootNode() )
return nullptr;
const QgsExpression::NodeFunction *f = dynamic_cast<const QgsExpression::NodeFunction *>( e.rootNode() );
const QgsExpressionNodeFunction *f = dynamic_cast<const QgsExpressionNodeFunction *>( e.rootNode() );
if ( !f )
return nullptr;
QList<QgsExpression::Node *> args = f->args()->list();
QList<QgsExpressionNode *> args = f->args()->list();
// the scale function may be enclosed in a coalesce(expr, 0) to avoid NULL value
// to be drawn with the default size
if ( "coalesce" == QgsExpression::Functions()[f->fnIndex()]->name() )
{
f = dynamic_cast<const QgsExpression::NodeFunction *>( args[0] );
f = dynamic_cast<const QgsExpressionNodeFunction *>( args[0] );
if ( !f )
return nullptr;
nullValue = QgsExpression( args[1]->dump() ).evaluate().toDouble( &ok );
@ -298,9 +299,9 @@ QgsGenericNumericTransformer *QgsGenericNumericTransformer::fromExpression( cons
return nullptr;
}
if ( args[0]->nodeType() == QgsExpression::ntColumnRef )
if ( args[0]->nodeType() == QgsExpressionNode::ntColumnRef )
{
fieldName = static_cast< QgsExpression::NodeColumnRef * >( args[0] )->name();
fieldName = static_cast< QgsExpressionNodeColumnRef * >( args[0] )->name();
}
else
{
@ -485,17 +486,17 @@ QgsSizeScaleTransformer *QgsSizeScaleTransformer::fromExpression( const QString
if ( !e.rootNode() )
return nullptr;
const QgsExpression::NodeFunction *f = dynamic_cast<const QgsExpression::NodeFunction *>( e.rootNode() );
const QgsExpressionNodeFunction *f = dynamic_cast<const QgsExpressionNodeFunction *>( e.rootNode() );
if ( !f )
return nullptr;
QList<QgsExpression::Node *> args = f->args()->list();
QList<QgsExpressionNode *> args = f->args()->list();
// the scale function may be enclosed in a coalesce(expr, 0) to avoid NULL value
// to be drawn with the default size
if ( "coalesce" == QgsExpression::Functions()[f->fnIndex()]->name() )
{
f = dynamic_cast<const QgsExpression::NodeFunction *>( args[0] );
f = dynamic_cast<const QgsExpressionNodeFunction *>( args[0] );
if ( !f )
return nullptr;
nullSize = QgsExpression( args[1]->dump() ).evaluate().toDouble( &ok );
@ -540,9 +541,9 @@ QgsSizeScaleTransformer *QgsSizeScaleTransformer::fromExpression( const QString
return nullptr;
}
if ( args[0]->nodeType() == QgsExpression::ntColumnRef )
if ( args[0]->nodeType() == QgsExpressionNode::ntColumnRef )
{
fieldName = static_cast< QgsExpression::NodeColumnRef * >( args[0] )->name();
fieldName = static_cast< QgsExpressionNodeColumnRef * >( args[0] )->name();
}
else
{

View File

@ -14,6 +14,8 @@
***************************************************************************/
#include "qgssqlexpressioncompiler.h"
#include "qgsexpressionnodeimpl.h"
#include "qgsexpressionfunction.h"
QgsSqlExpressionCompiler::QgsSqlExpressionCompiler( const QgsFields &fields, Flags flags )
: mResult( None )
@ -71,16 +73,16 @@ QString QgsSqlExpressionCompiler::quotedValue( const QVariant &value, bool &ok )
}
}
QgsSqlExpressionCompiler::Result QgsSqlExpressionCompiler::compileNode( const QgsExpression::Node *node, QString &result )
QgsSqlExpressionCompiler::Result QgsSqlExpressionCompiler::compileNode( const QgsExpressionNode *node, QString &result )
{
switch ( node->nodeType() )
{
case QgsExpression::ntUnaryOperator:
case QgsExpressionNode::ntUnaryOperator:
{
const QgsExpression::NodeUnaryOperator *n = static_cast<const QgsExpression::NodeUnaryOperator *>( node );
const QgsExpressionNodeUnaryOperator *n = static_cast<const QgsExpressionNodeUnaryOperator *>( node );
switch ( n->op() )
{
case QgsExpression::uoNot:
case QgsExpressionNodeUnaryOperator::uoNot:
{
QString right;
if ( compileNode( n->operand(), right ) == Complete )
@ -92,7 +94,7 @@ QgsSqlExpressionCompiler::Result QgsSqlExpressionCompiler::compileNode( const Qg
return Fail;
}
case QgsExpression::uoMinus:
case QgsExpressionNodeUnaryOperator::uoMinus:
{
if ( mFlags.testFlag( NoUnaryMinus ) )
return Fail;
@ -111,17 +113,17 @@ QgsSqlExpressionCompiler::Result QgsSqlExpressionCompiler::compileNode( const Qg
break;
}
case QgsExpression::ntBinaryOperator:
case QgsExpressionNodeBinaryOperator::ntBinaryOperator:
{
const QgsExpression::NodeBinaryOperator *n = static_cast<const QgsExpression::NodeBinaryOperator *>( node );
const QgsExpressionNodeBinaryOperator *n = static_cast<const QgsExpressionNodeBinaryOperator *>( node );
QString op;
bool partialCompilation = false;
bool failOnPartialNode = false;
switch ( n->op() )
{
case QgsExpression::boEQ:
if ( mFlags.testFlag( CaseInsensitiveStringMatch ) && n->opLeft()->nodeType() == QgsExpression::ntColumnRef && n->opRight()->nodeType() == QgsExpression::ntColumnRef )
case QgsExpressionNodeBinaryOperator::boEQ:
if ( mFlags.testFlag( CaseInsensitiveStringMatch ) && n->opLeft()->nodeType() == QgsExpressionNode::ntColumnRef && n->opRight()->nodeType() == QgsExpressionNode::ntColumnRef )
{
// equality between column refs results in a partial compilation, since provider is performing
// case-insensitive matches between strings
@ -131,50 +133,50 @@ QgsSqlExpressionCompiler::Result QgsSqlExpressionCompiler::compileNode( const Qg
op = QStringLiteral( "=" );
break;
case QgsExpression::boGE:
case QgsExpressionNodeBinaryOperator::boGE:
op = QStringLiteral( ">=" );
break;
case QgsExpression::boGT:
case QgsExpressionNodeBinaryOperator::boGT:
op = QStringLiteral( ">" );
break;
case QgsExpression::boLE:
case QgsExpressionNodeBinaryOperator::boLE:
op = QStringLiteral( "<=" );
break;
case QgsExpression::boLT:
case QgsExpressionNodeBinaryOperator::boLT:
op = QStringLiteral( "<" );
break;
case QgsExpression::boIs:
case QgsExpressionNodeBinaryOperator::boIs:
op = QStringLiteral( "IS" );
break;
case QgsExpression::boIsNot:
case QgsExpressionNodeBinaryOperator::boIsNot:
op = QStringLiteral( "IS NOT" );
failOnPartialNode = mFlags.testFlag( CaseInsensitiveStringMatch );
break;
case QgsExpression::boLike:
case QgsExpressionNodeBinaryOperator::boLike:
op = QStringLiteral( "LIKE" );
partialCompilation = mFlags.testFlag( LikeIsCaseInsensitive );
break;
case QgsExpression::boILike:
case QgsExpressionNodeBinaryOperator::boILike:
if ( mFlags.testFlag( LikeIsCaseInsensitive ) )
op = QStringLiteral( "LIKE" );
else
op = QStringLiteral( "ILIKE" );
break;
case QgsExpression::boNotLike:
case QgsExpressionNodeBinaryOperator::boNotLike:
op = QStringLiteral( "NOT LIKE" );
partialCompilation = mFlags.testFlag( LikeIsCaseInsensitive );
failOnPartialNode = mFlags.testFlag( CaseInsensitiveStringMatch );
break;
case QgsExpression::boNotILike:
case QgsExpressionNodeBinaryOperator::boNotILike:
failOnPartialNode = mFlags.testFlag( CaseInsensitiveStringMatch );
if ( mFlags.testFlag( LikeIsCaseInsensitive ) )
op = QStringLiteral( "NOT LIKE" );
@ -182,7 +184,7 @@ QgsSqlExpressionCompiler::Result QgsSqlExpressionCompiler::compileNode( const Qg
op = QStringLiteral( "NOT ILIKE" );
break;
case QgsExpression::boOr:
case QgsExpressionNodeBinaryOperator::boOr:
if ( mFlags.testFlag( NoNullInBooleanLogic ) )
{
if ( nodeIsNullLiteral( n->opLeft() ) || nodeIsNullLiteral( n->opRight() ) )
@ -192,7 +194,7 @@ QgsSqlExpressionCompiler::Result QgsSqlExpressionCompiler::compileNode( const Qg
op = QStringLiteral( "OR" );
break;
case QgsExpression::boAnd:
case QgsExpressionNodeBinaryOperator::boAnd:
if ( mFlags.testFlag( NoNullInBooleanLogic ) )
{
if ( nodeIsNullLiteral( n->opLeft() ) || nodeIsNullLiteral( n->opRight() ) )
@ -202,44 +204,44 @@ QgsSqlExpressionCompiler::Result QgsSqlExpressionCompiler::compileNode( const Qg
op = QStringLiteral( "AND" );
break;
case QgsExpression::boNE:
case QgsExpressionNodeBinaryOperator::boNE:
failOnPartialNode = mFlags.testFlag( CaseInsensitiveStringMatch );
op = QStringLiteral( "<>" );
break;
case QgsExpression::boMul:
case QgsExpressionNodeBinaryOperator::boMul:
op = QStringLiteral( "*" );
break;
case QgsExpression::boPlus:
case QgsExpressionNodeBinaryOperator::boPlus:
op = QStringLiteral( "+" );
break;
case QgsExpression::boMinus:
case QgsExpressionNodeBinaryOperator::boMinus:
op = QStringLiteral( "-" );
break;
case QgsExpression::boDiv:
case QgsExpressionNodeBinaryOperator::boDiv:
op = QStringLiteral( "/" );
break;
case QgsExpression::boMod:
case QgsExpressionNodeBinaryOperator::boMod:
op = QStringLiteral( "%" );
break;
case QgsExpression::boConcat:
case QgsExpressionNodeBinaryOperator::boConcat:
op = QStringLiteral( "||" );
break;
case QgsExpression::boIntDiv:
case QgsExpressionNodeBinaryOperator::boIntDiv:
op = QStringLiteral( "/" );
break;
case QgsExpression::boPow:
case QgsExpressionNodeBinaryOperator::boPow:
op = QStringLiteral( "^" );
break;
case QgsExpression::boRegexp:
case QgsExpressionNodeBinaryOperator::boRegexp:
op = QStringLiteral( "~" );
break;
}
@ -256,7 +258,7 @@ QgsSqlExpressionCompiler::Result QgsSqlExpressionCompiler::compileNode( const Qg
if ( failOnPartialNode && ( lr == Partial || rr == Partial ) )
return Fail;
if ( n->op() == QgsExpression::boDiv && mFlags.testFlag( IntegerDivisionResultsInInteger ) )
if ( n->op() == QgsExpressionNodeBinaryOperator::boDiv && mFlags.testFlag( IntegerDivisionResultsInInteger ) )
{
right = castToReal( right );
if ( right.isEmpty() )
@ -267,7 +269,7 @@ QgsSqlExpressionCompiler::Result QgsSqlExpressionCompiler::compileNode( const Qg
}
result = '(' + left + ' ' + op + ' ' + right + ')';
if ( n->op() == QgsExpression::boIntDiv )
if ( n->op() == QgsExpressionNodeBinaryOperator::boIntDiv )
{
result = castToInt( result );
if ( result.isEmpty() )
@ -285,9 +287,9 @@ QgsSqlExpressionCompiler::Result QgsSqlExpressionCompiler::compileNode( const Qg
return Fail;
}
case QgsExpression::ntLiteral:
case QgsExpressionNode::ntLiteral:
{
const QgsExpression::NodeLiteral *n = static_cast<const QgsExpression::NodeLiteral *>( node );
const QgsExpressionNodeLiteral *n = static_cast<const QgsExpressionNodeLiteral *>( node );
bool ok = false;
if ( mFlags.testFlag( CaseInsensitiveStringMatch ) && n->value().type() == QVariant::String )
{
@ -303,9 +305,9 @@ QgsSqlExpressionCompiler::Result QgsSqlExpressionCompiler::compileNode( const Qg
}
}
case QgsExpression::ntColumnRef:
case QgsExpressionNode::ntColumnRef:
{
const QgsExpression::NodeColumnRef *n = static_cast<const QgsExpression::NodeColumnRef *>( node );
const QgsExpressionNodeColumnRef *n = static_cast<const QgsExpressionNodeColumnRef *>( node );
if ( mFields.indexFromName( n->name() ) == -1 )
// Not a provider field
@ -316,13 +318,13 @@ QgsSqlExpressionCompiler::Result QgsSqlExpressionCompiler::compileNode( const Qg
return Complete;
}
case QgsExpression::ntInOperator:
case QgsExpressionNode::ntInOperator:
{
const QgsExpression::NodeInOperator *n = static_cast<const QgsExpression::NodeInOperator *>( node );
const QgsExpressionNodeInOperator *n = static_cast<const QgsExpressionNodeInOperator *>( node );
QStringList list;
Result inResult = Complete;
Q_FOREACH ( const QgsExpression::Node *ln, n->list()->list() )
Q_FOREACH ( const QgsExpressionNode *ln, n->list()->list() )
{
QString s;
Result r = compileNode( ln, s );
@ -345,10 +347,10 @@ QgsSqlExpressionCompiler::Result QgsSqlExpressionCompiler::compileNode( const Qg
return ( inResult == Partial || rn == Partial ) ? Partial : Complete;
}
case QgsExpression::ntFunction:
case QgsExpressionNode::ntFunction:
{
const QgsExpression::NodeFunction *n = static_cast<const QgsExpression::NodeFunction *>( node );
QgsExpression::Function *fd = QgsExpression::Functions()[n->fnIndex()];
const QgsExpressionNodeFunction *n = static_cast<const QgsExpressionNodeFunction *>( node );
QgsExpressionFunction *fd = QgsExpression::Functions()[n->fnIndex()];
// get sql function to compile node expression
QString nd = sqlFunctionFromFunctionName( fd->name() );
@ -359,7 +361,7 @@ QgsSqlExpressionCompiler::Result QgsSqlExpressionCompiler::compileNode( const Qg
// compile arguments
QStringList args;
Result inResult = Complete;
Q_FOREACH ( const QgsExpression::Node *ln, n->args()->list() )
Q_FOREACH ( const QgsExpressionNode *ln, n->args()->list() )
{
QString s;
Result r = compileNode( ln, s );
@ -381,7 +383,7 @@ QgsSqlExpressionCompiler::Result QgsSqlExpressionCompiler::compileNode( const Qg
return inResult == Partial ? Partial : Complete;
}
case QgsExpression::ntCondition:
case QgsExpressionNode::ntCondition:
break;
}
@ -412,11 +414,11 @@ QString QgsSqlExpressionCompiler::castToInt( const QString &value ) const
return QString();
}
bool QgsSqlExpressionCompiler::nodeIsNullLiteral( const QgsExpression::Node *node ) const
bool QgsSqlExpressionCompiler::nodeIsNullLiteral( const QgsExpressionNode *node ) const
{
if ( node->nodeType() != QgsExpression::ntLiteral )
if ( node->nodeType() != QgsExpressionNode::ntLiteral )
return false;
const QgsExpression::NodeLiteral *nLit = static_cast<const QgsExpression::NodeLiteral *>( node );
const QgsExpressionNodeLiteral *nLit = static_cast<const QgsExpressionNodeLiteral *>( node );
return nLit->value().isNull();
}

View File

@ -93,7 +93,7 @@ class CORE_EXPORT QgsSqlExpressionCompiler
* \param str string representing compiled node should be stored in this parameter
* \returns result of node compilation
*/
virtual Result compileNode( const QgsExpression::Node *node, QString &str );
virtual Result compileNode( const QgsExpressionNode *node, QString &str );
/** Return the SQL function for the expression function.
* Derived classes should override this to help compile functions
@ -132,7 +132,7 @@ class CORE_EXPORT QgsSqlExpressionCompiler
Flags mFlags;
bool nodeIsNullLiteral( const QgsExpression::Node *node ) const;
bool nodeIsNullLiteral( const QgsExpressionNode *node ) const;
};

View File

@ -17,22 +17,23 @@
#include "qgssqliteexpressioncompiler.h"
#include "qgssqlexpressioncompiler.h"
#include "qgsexpressionnodeimpl.h"
QgsSQLiteExpressionCompiler::QgsSQLiteExpressionCompiler( const QgsFields &fields )
: QgsSqlExpressionCompiler( fields, QgsSqlExpressionCompiler::LikeIsCaseInsensitive | QgsSqlExpressionCompiler::IntegerDivisionResultsInInteger )
{
}
QgsSqlExpressionCompiler::Result QgsSQLiteExpressionCompiler::compileNode( const QgsExpression::Node *node, QString &result )
QgsSqlExpressionCompiler::Result QgsSQLiteExpressionCompiler::compileNode( const QgsExpressionNode *node, QString &result )
{
switch ( node->nodeType() )
{
case QgsExpression::ntBinaryOperator:
case QgsExpressionNode::ntBinaryOperator:
{
switch ( static_cast<const QgsExpression::NodeBinaryOperator *>( node )->op() )
switch ( static_cast<const QgsExpressionNodeBinaryOperator *>( node )->op() )
{
case QgsExpression::boPow:
case QgsExpression::boRegexp:
case QgsExpressionNodeBinaryOperator::boPow:
case QgsExpressionNodeBinaryOperator::boRegexp:
return Fail; //not supported by SQLite
default:

View File

@ -42,7 +42,7 @@ class CORE_EXPORT QgsSQLiteExpressionCompiler : public QgsSqlExpressionCompiler
protected:
virtual Result compileNode( const QgsExpression::Node *node, QString &str ) override;
virtual Result compileNode( const QgsExpressionNode *node, QString &str ) override;
virtual QString quotedIdentifier( const QString &identifier ) override;
virtual QString quotedValue( const QVariant &value, bool &ok ) override;
virtual QString sqlFunctionFromFunctionName( const QString &fnName ) const override;

View File

@ -650,7 +650,7 @@ class CORE_EXPORT QgsSQLStatement
public:
//! Constructor
NodeSelect( const QList<NodeTableDef *> &tableList, const QList<NodeSelectedColumn *> &columns, bool distinct ) : mTableList( tableList ), mColumns( columns ), mDistinct( distinct ), mWhere( nullptr ) {}
virtual ~NodeSelect() { qDeleteAll( mTableList ); qDeleteAll( mColumns ); qDeleteAll( mJoins ); delete mWhere; qDeleteAll( mOrderBy ); }
virtual ~NodeSelect();
//! Set joins
void setJoins( const QList<NodeJoin *> &joins ) { qDeleteAll( mJoins ); mJoins = joins; }

View File

@ -46,6 +46,7 @@
#include "qgscurve.h"
#include "qgsdatasourceuri.h"
#include "qgsexpressionfieldbuffer.h"
#include "qgsexpressionnodeimpl.h"
#include "qgsfeature.h"
#include "qgsfeaturerequest.h"
#include "qgsfields.h"
@ -2610,7 +2611,7 @@ QString QgsVectorLayer::displayField() const
QgsExpression exp( mDisplayExpression );
if ( exp.isField() )
{
return static_cast<const QgsExpression::NodeColumnRef *>( exp.rootNode() )->name();
return static_cast<const QgsExpressionNodeColumnRef *>( exp.rootNode() )->name();
}
return QString();

View File

@ -20,6 +20,7 @@
#include "qgssymbol.h"
#include "qgscolorramp.h"
#include "qgsexpression.h"
#include "qgsexpressionnode.h"
#include "qgspainteffect.h"
#include "qgspainteffectregistry.h"
#include "qgsapplication.h"
@ -3768,10 +3769,10 @@ QgsExpression *QgsSymbolLayerUtils::fieldOrExpressionToExpression( const QString
QString QgsSymbolLayerUtils::fieldOrExpressionFromExpression( QgsExpression *expression )
{
const QgsExpression::Node *n = expression->rootNode();
const QgsExpressionNode *n = expression->rootNode();
if ( n && n->nodeType() == QgsExpression::ntColumnRef )
return static_cast<const QgsExpression::NodeColumnRef *>( n )->name();
if ( n && n->nodeType() == QgsExpressionNode::ntColumnRef )
return static_cast<const QgsExpressionNodeColumnRef *>( n )->name();
return expression->expression();
}

View File

@ -746,35 +746,34 @@ INCLUDE_DIRECTORIES(SYSTEM
${QT_QTUITOOLS_INCLUDE_DIR}
)
INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/symbology-ng
${CMAKE_CURRENT_SOURCE_DIR}/attributetable
${CMAKE_CURRENT_SOURCE_DIR}/auth
${CMAKE_CURRENT_SOURCE_DIR}/editorwidgets
${CMAKE_CURRENT_SOURCE_DIR}/editorwidgets/core
${CMAKE_CURRENT_SOURCE_DIR}/layertree
${CMAKE_CURRENT_SOURCE_DIR}/locator
${CMAKE_CURRENT_SOURCE_DIR}/effects
${CMAKE_SOURCE_DIR}/src/gui
${CMAKE_SOURCE_DIR}/src/gui/symbology-ng
${CMAKE_SOURCE_DIR}/src/gui/attributetable
${CMAKE_SOURCE_DIR}/src/gui/auth
${CMAKE_SOURCE_DIR}/src/gui/editorwidgets
${CMAKE_SOURCE_DIR}/src/gui/editorwidgets/core
${CMAKE_SOURCE_DIR}/src/gui/layertree
${CMAKE_SOURCE_DIR}/src/gui/effects
${CMAKE_SOURCE_DIR}/src/core
${CMAKE_SOURCE_DIR}/src/core/annotations
${CMAKE_SOURCE_DIR}/src/core/auth
${CMAKE_SOURCE_DIR}/src/core/composer
${CMAKE_SOURCE_DIR}/src/core/fieldformatter
${CMAKE_SOURCE_DIR}/src/core/geometry
${CMAKE_SOURCE_DIR}/src/core/layertree
${CMAKE_SOURCE_DIR}/src/core/locator
${CMAKE_SOURCE_DIR}/src/core/metadata
${CMAKE_SOURCE_DIR}/src/core/providers/memory
${CMAKE_SOURCE_DIR}/src/core/raster
${CMAKE_SOURCE_DIR}/src/core/scalebar
${CMAKE_SOURCE_DIR}/src/core/symbology-ng
${CMAKE_SOURCE_DIR}/src/core/effects
${CMAKE_SOURCE_DIR}/src/core/metadata
${CMAKE_SOURCE_DIR}/src/core/expression
${CMAKE_SOURCE_DIR}/src/native
${CMAKE_BINARY_DIR}/src/core
${CMAKE_BINARY_DIR}/src/gui
${CMAKE_BINARY_DIR}/src/native
../core
../core/annotations
../core/auth
../core/composer
../core/fieldformatter
../core/geometry
../core/layertree
../core/metadata
../core/providers/memory
../core/raster
../core/scalebar
../core/symbology-ng
../core/effects
../core/metadata
../native
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_BINARY_DIR}/../ui
)
INCLUDE_DIRECTORIES(SYSTEM
${QCA_INCLUDE_DIR}

View File

@ -34,6 +34,8 @@
#include "qgssymbollayerutils.h"
#include "qgsfieldformatterregistry.h"
#include "qgsgui.h"
#include "qgsexpressionnodeimpl.h"
#include <QVariant>
#include <limits>
@ -803,7 +805,7 @@ void QgsAttributeTableModel::prefetchSortData( const QString &expressionString )
if ( mSortCacheExpression.isField() )
{
QString fieldName = static_cast<const QgsExpression::NodeColumnRef *>( mSortCacheExpression.rootNode() )->name();
QString fieldName = static_cast<const QgsExpressionNodeColumnRef *>( mSortCacheExpression.rootNode() )->name();
mSortFieldIndex = mLayerCache->layer()->fields().lookupField( fieldName );
}

View File

@ -16,6 +16,7 @@
#include "qgsexpressionbuilderwidget.h"
#include "qgslogger.h"
#include "qgsexpression.h"
#include "qgsexpressionfunction.h"
#include "qgsmessageviewer.h"
#include "qgsapplication.h"
#include "qgspythonrunner.h"
@ -476,7 +477,7 @@ void QgsExpressionBuilderWidget::updateFunctionTree()
int count = QgsExpression::functionCount();
for ( int i = 0; i < count; i++ )
{
QgsExpression::Function *func = QgsExpression::Functions()[i];
QgsExpressionFunction *func = QgsExpression::Functions()[i];
QString name = func->name();
if ( name.startsWith( '_' ) ) // do not display private functions
continue;
@ -596,7 +597,7 @@ void QgsExpressionBuilderWidget::loadExpressionContext()
QStringList contextFunctions = mExpressionContext.functionNames();
Q_FOREACH ( const QString &functionName, contextFunctions )
{
QgsExpression::Function *func = mExpressionContext.function( functionName );
QgsExpressionFunction *func = mExpressionContext.function( functionName );
QString name = func->name();
if ( name.startsWith( '_' ) ) // do not display private functions
continue;

View File

@ -23,7 +23,7 @@
#include <QString>
#include <QStringList>
#include <qgsbabelformat.h>
#include "qgsbabelformat.h"
class QgsGPSDevice : public QgsBabelFormat

View File

@ -17,6 +17,7 @@
***************************************************************************/
#include "qgsdb2expressioncompiler.h"
#include "qgsexpressionnodeimpl.h"
#include "qgslogger.h"
QgsDb2ExpressionCompiler::QgsDb2ExpressionCompiler( QgsDb2FeatureSource *source )
@ -26,16 +27,16 @@ QgsDb2ExpressionCompiler::QgsDb2ExpressionCompiler( QgsDb2FeatureSource *source
}
QString nodeType( const QgsExpression::Node *node )
QString nodeType( const QgsExpressionNode *node )
{
QString opString = QStringLiteral( "?" );
if ( node->nodeType() == QgsExpression::ntUnaryOperator ) opString = QStringLiteral( "ntUnaryOperator" );
if ( node->nodeType() == QgsExpression::ntBinaryOperator ) opString = QStringLiteral( "ntBinaryOperator" );
if ( node->nodeType() == QgsExpression::ntInOperator ) opString = QStringLiteral( "ntInOperator" );
if ( node->nodeType() == QgsExpression::ntFunction ) opString = QStringLiteral( "ntFunction" );
if ( node->nodeType() == QgsExpression::ntLiteral ) opString = QStringLiteral( "ntLiteral" );
if ( node->nodeType() == QgsExpression::ntColumnRef ) opString = QStringLiteral( "ntColumnRef" );
if ( node->nodeType() == QgsExpression::ntCondition ) opString = QStringLiteral( "ntCondition" );
if ( node->nodeType() == QgsExpressionNode::ntUnaryOperator ) opString = QStringLiteral( "ntUnaryOperator" );
if ( node->nodeType() == QgsExpressionNode::ntBinaryOperator ) opString = QStringLiteral( "ntBinaryOperator" );
if ( node->nodeType() == QgsExpressionNode::ntInOperator ) opString = QStringLiteral( "ntInOperator" );
if ( node->nodeType() == QgsExpressionNode::ntFunction ) opString = QStringLiteral( "ntFunction" );
if ( node->nodeType() == QgsExpressionNode::ntLiteral ) opString = QStringLiteral( "ntLiteral" );
if ( node->nodeType() == QgsExpressionNode::ntColumnRef ) opString = QStringLiteral( "ntColumnRef" );
if ( node->nodeType() == QgsExpressionNode::ntCondition ) opString = QStringLiteral( "ntCondition" );
QString result = QStringLiteral( "%1 - " ).arg( node->nodeType() ) + opString;
return result;
@ -51,12 +52,12 @@ QString resultType( QgsSqlExpressionCompiler::Result result )
}
QgsSqlExpressionCompiler::Result QgsDb2ExpressionCompiler::compileNode( const QgsExpression::Node *node, QString &result )
QgsSqlExpressionCompiler::Result QgsDb2ExpressionCompiler::compileNode( const QgsExpressionNode *node, QString &result )
{
QgsDebugMsg( QString( "nodeType: %1" ).arg( nodeType( node ) ) );
if ( node->nodeType() == QgsExpression::ntColumnRef )
if ( node->nodeType() == QgsExpressionNode::ntColumnRef )
{
const QgsExpression::NodeColumnRef *n( static_cast<const QgsExpression::NodeColumnRef *>( node ) );
const QgsExpressionNodeColumnRef *n( static_cast<const QgsExpressionNodeColumnRef *>( node ) );
QgsDebugMsg( QString( "column ref node: " ) + n->dump() );
// TODO - consider escaped names - not sure how to handle
QString upperName = n->name().toUpper();
@ -73,7 +74,7 @@ QgsSqlExpressionCompiler::Result QgsDb2ExpressionCompiler::compileNode( const Qg
}
// Seemed necessary in initial Python testing but can't identify failing case now
#if 0
if ( node->nodeType() == QgsExpression::ntLiteral )
if ( node->nodeType() == QgsExpressionNode::ntLiteral )
{
const QgsExpression::NodeLiteral *n = static_cast<const QgsExpression::NodeLiteral *>( node );
@ -103,13 +104,13 @@ QgsSqlExpressionCompiler::Result QgsDb2ExpressionCompiler::compileNode( const Qg
}
#endif
if ( node->nodeType() == QgsExpression::ntUnaryOperator )
if ( node->nodeType() == QgsExpressionNode::ntUnaryOperator )
{
const QgsExpression::NodeUnaryOperator *n = static_cast<const QgsExpression::NodeUnaryOperator *>( node );
const QgsExpressionNodeUnaryOperator *n = static_cast<const QgsExpressionNodeUnaryOperator *>( node );
Result rr = Fail;
switch ( n->op() )
{
case QgsExpression::uoNot:
case QgsExpressionNodeUnaryOperator::uoNot:
rr = compileNode( n->operand(), result );
if ( "NULL" == result.toUpper() )
{
@ -121,14 +122,14 @@ QgsSqlExpressionCompiler::Result QgsDb2ExpressionCompiler::compileNode( const Qg
QgsDebugMsg( QString( "NOT; result: %1; right: %2" ).arg( resultType( rr ), result ) );
return rr;
case QgsExpression::uoMinus:
case QgsExpressionNodeUnaryOperator::uoMinus:
break;
}
}
if ( node->nodeType() == QgsExpression::ntBinaryOperator )
if ( node->nodeType() == QgsExpressionNode::ntBinaryOperator )
{
const QgsExpression::NodeBinaryOperator *bin( static_cast<const QgsExpression::NodeBinaryOperator *>( node ) );
const QgsExpressionNodeBinaryOperator *bin( static_cast<const QgsExpressionNodeBinaryOperator *>( node ) );
QString left, right;
Result lr = compileNode( bin->opLeft(), left );
@ -141,33 +142,33 @@ QgsSqlExpressionCompiler::Result QgsDb2ExpressionCompiler::compileNode( const Qg
// NULL can not appear on the left, only as part of IS NULL or IS NOT NULL
if ( "NULL" == left.toUpper() ) return Fail;
// NULL can only be on the right for IS and IS NOT
if ( "NULL" == right.toUpper() && ( bin->op() != QgsExpression::boIs && bin->op() != QgsExpression::boIsNot ) )
if ( "NULL" == right.toUpper() && ( bin->op() != QgsExpressionNodeBinaryOperator::boIs && bin->op() != QgsExpressionNodeBinaryOperator::boIsNot ) )
return Fail;
switch ( bin->op() )
{
case QgsExpression::boMod:
case QgsExpressionNodeBinaryOperator::boMod:
result = QStringLiteral( "MOD(%1,%2)" ).arg( left, right );
compileResult = ( lr == Partial || rr == Partial ) ? Partial : Complete;
QgsDebugMsg( QString( "MOD compile status: %1" ).arg( compileResult ) + "; " + result );
return compileResult;
case QgsExpression::boPow:
case QgsExpressionNodeBinaryOperator::boPow:
result = QStringLiteral( "power(%1,%2)" ).arg( left, right );
compileResult = ( lr == Partial || rr == Partial ) ? Partial : Complete;
QgsDebugMsg( QString( "POWER compile status: %1" ).arg( compileResult ) + "; " + result );
return compileResult;
case QgsExpression::boRegexp:
case QgsExpressionNodeBinaryOperator::boRegexp:
return Fail; //not supported, regexp syntax is too different to Qt
case QgsExpression::boConcat:
case QgsExpressionNodeBinaryOperator::boConcat:
result = QStringLiteral( "%1 || %2" ).arg( left, right );
compileResult = ( lr == Partial || rr == Partial ) ? Partial : Complete;
QgsDebugMsg( QString( "CONCAT compile status: %1" ).arg( compileResult ) + "; " + result );
return compileResult;
case QgsExpression::boILike:
case QgsExpressionNodeBinaryOperator::boILike:
QgsDebugMsg( "ILIKE is not supported by DB2" );
return Fail;
/*
@ -177,7 +178,7 @@ QgsSqlExpressionCompiler::Result QgsDb2ExpressionCompiler::compileNode( const Qg
return compileResult;
*/
case QgsExpression::boNotILike:
case QgsExpressionNodeBinaryOperator::boNotILike:
QgsDebugMsg( "NOT ILIKE is not supported by DB2" );
return Fail;
/*
@ -188,10 +189,10 @@ QgsSqlExpressionCompiler::Result QgsDb2ExpressionCompiler::compileNode( const Qg
*/
// We only support IS NULL if the operand on the left is a column
case QgsExpression::boIs:
case QgsExpressionNodeBinaryOperator::boIs:
if ( "NULL" == right.toUpper() )
{
if ( bin->opLeft()->nodeType() != QgsExpression::ntColumnRef )
if ( bin->opLeft()->nodeType() != QgsExpressionNode::ntColumnRef )
{
QgsDebugMsg( "Failing IS NULL with non-column on left: " + left );
return Fail;
@ -199,10 +200,10 @@ QgsSqlExpressionCompiler::Result QgsDb2ExpressionCompiler::compileNode( const Qg
}
break;
// We only support IS NULL if the operand on the left is a column
case QgsExpression::boIsNot:
case QgsExpressionNodeBinaryOperator::boIsNot:
if ( "NULL" == right.toUpper() )
{
if ( bin->opLeft()->nodeType() != QgsExpression::ntColumnRef )
if ( bin->opLeft()->nodeType() != QgsExpressionNode::ntColumnRef )
{
QgsDebugMsg( "Failing IS NOT NULL with non-column on left: " + left );
return Fail;

View File

@ -29,7 +29,7 @@ class QgsDb2ExpressionCompiler : public QgsSqlExpressionCompiler
explicit QgsDb2ExpressionCompiler( QgsDb2FeatureSource *source );
protected:
virtual Result compileNode( const QgsExpression::Node *node, QString &result ) override;
virtual Result compileNode( const QgsExpressionNode *node, QString &result ) override;
virtual QString quotedValue( const QVariant &value, bool &ok ) override;
};

View File

@ -16,9 +16,11 @@ SET (GPX_MOC_HDRS
# Build
INCLUDE_DIRECTORIES(
../../core
../../core/geometry
../../core/metadata
${CMAKE_SOURCE_DIR}/src/core
${CMAKE_SOURCE_DIR}/src/core/geometry
${CMAKE_SOURCE_DIR}/src/core/metadata
${CMAKE_SOURCE_DIR}/src/core/expression
${CMAKE_BINARY_DIR}/src/core
${CMAKE_BINARY_DIR}/src/gui
)

View File

@ -14,6 +14,7 @@
***************************************************************************/
#include "qgsmssqlexpressioncompiler.h"
#include "qgsexpressionnodeimpl.h"
QgsMssqlExpressionCompiler::QgsMssqlExpressionCompiler( QgsMssqlFeatureSource *source )
: QgsSqlExpressionCompiler( source->mFields,
@ -24,9 +25,9 @@ QgsMssqlExpressionCompiler::QgsMssqlExpressionCompiler( QgsMssqlFeatureSource *s
QgsSqlExpressionCompiler::Result QgsMssqlExpressionCompiler::compileNode( const QgsExpression::Node *node, QString &result )
{
if ( node->nodeType() == QgsExpression::ntBinaryOperator )
if ( node->nodeType() == QgsExpressionNode::ntBinaryOperator )
{
const QgsExpression::NodeBinaryOperator *bin( static_cast<const QgsExpression::NodeBinaryOperator *>( node ) );
const QgsExpressionNodeBinaryOperator *bin( static_cast<const QgsExpressionNodeBinaryOperator *>( node ) );
QString op1, op2;
Result result1 = compileNode( bin->opLeft(), op1 );
@ -36,14 +37,14 @@ QgsSqlExpressionCompiler::Result QgsMssqlExpressionCompiler::compileNode( const
switch ( bin->op() )
{
case QgsExpression::boPow:
case QgsExpressionNodeBinaryOperator::boPow:
result = QStringLiteral( "power(%1,%2)" ).arg( op1, op2 );
return result1 == Partial || result2 == Partial ? Partial : Complete;
case QgsExpression::boRegexp:
case QgsExpressionNodeBinaryOperator::boRegexp:
return Fail; //not supported, regexp syntax is too different to Qt
case QgsExpression::boConcat:
case QgsExpressionNodeBinaryOperator::boConcat:
result = QStringLiteral( "%1 + %2" ).arg( op1, op2 );
return result1 == Partial || result2 == Partial ? Partial : Complete;

View File

@ -9,11 +9,12 @@ SET(OGR_MOC_HDRS qgsogrprovider.h qgsogrdataitems.h qgsogrconnpool.h)
QT5_WRAP_CPP(OGR_MOC_SRCS ${OGR_MOC_HDRS})
INCLUDE_DIRECTORIES(
.
../../core
../../core/geometry
../../core/metadata
${CMAKE_CURRENT_SOURCE_DIR}/../../core/symbology-ng
${CMAKE_SOURCE_DIR}/src/core
${CMAKE_SOURCE_DIR}/src/core/geometry
${CMAKE_SOURCE_DIR}/src/core/metadata
${CMAKE_SOURCE_DIR}/src/core/symbology-ng
${CMAKE_SOURCE_DIR}/src/core/expression
${CMAKE_BINARY_DIR}/src/core
${CMAKE_BINARY_DIR}/src/gui
)

View File

@ -49,18 +49,18 @@ QgsSqlExpressionCompiler::Result QgsOgrExpressionCompiler::compileNode( const Qg
{
switch ( node->nodeType() )
{
case QgsExpression::ntBinaryOperator:
case QgsExpressionNode::ntBinaryOperator:
{
switch ( static_cast<const QgsExpression::NodeBinaryOperator *>( node )->op() )
{
case QgsExpression::boILike:
case QgsExpression::boNotILike:
case QgsExpressionNodeBinaryOperator::boILike:
case QgsExpressionNodeBinaryOperator::boNotILike:
return Fail; //disabled until https://trac.osgeo.org/gdal/ticket/5132 is fixed
case QgsExpression::boMod:
case QgsExpression::boConcat:
case QgsExpression::boPow:
case QgsExpression::boRegexp:
case QgsExpressionNodeBinaryOperator::boMod:
case QgsExpressionNodeBinaryOperator::boConcat:
case QgsExpressionNodeBinaryOperator::boPow:
case QgsExpressionNodeBinaryOperator::boRegexp:
return Fail; //not supported by OGR
default:
@ -69,15 +69,15 @@ QgsSqlExpressionCompiler::Result QgsOgrExpressionCompiler::compileNode( const Qg
}
}
case QgsExpression::ntFunction:
case QgsExpression::ntCondition:
case QgsExpressionNode::ntFunction:
case QgsExpressionNode::ntCondition:
//not support by OGR
return Fail;
case QgsExpression::ntUnaryOperator:
case QgsExpression::ntColumnRef:
case QgsExpression::ntInOperator:
case QgsExpression::ntLiteral:
case QgsExpressionNode::ntUnaryOperator:
case QgsExpressionNode::ntColumnRef:
case QgsExpressionNode::ntInOperator:
case QgsExpressionNode::ntLiteral:
break;
}

View File

@ -15,6 +15,7 @@
#include "qgspostgresexpressioncompiler.h"
#include "qgssqlexpressioncompiler.h"
#include "qgsexpressionnodeimpl.h"
QgsPostgresExpressionCompiler::QgsPostgresExpressionCompiler( QgsPostgresFeatureSource *source )
: QgsSqlExpressionCompiler( source->mFields, QgsSqlExpressionCompiler::IntegerDivisionResultsInInteger )

View File

@ -15,12 +15,13 @@ email : hugo dot mercier at oslandia dot com
* *
***************************************************************************/
#include <qgsvirtuallayerfeatureiterator.h>
#include <qgsmessagelog.h>
#include <qgsgeometry.h>
#include <stdexcept>
#include "qgsvirtuallayerfeatureiterator.h"
#include "qgsmessagelog.h"
#include "qgsgeometry.h"
#include "qgsvirtuallayerblob.h"
#include <stdexcept>
static QString quotedColumn( QString name )
{
return "\"" + name.replace( QLatin1String( "\"" ), QLatin1String( "\"\"" ) ) + "\"";

View File

@ -18,8 +18,9 @@ email : hugo dot mercier at oslandia dot com
#define QGSVIRTUALLAYER_FEATURE_ITERATOR_H
#include <qgsvirtuallayerprovider.h>
#include <qgsfeatureiterator.h>
#include "qgsvirtuallayerprovider.h"
#include "qgsfeatureiterator.h"
#include <memory>
#include <QPointer>

View File

@ -727,7 +727,7 @@ void qgisFunctionWrapper( sqlite3_context *ctxt, int nArgs, sqlite3_value **args
// geometries are converted between spatialite and QgsGeometry
// other data types (datetime mainly) are represented as BLOBs thanks to QVariant serializing functions
QgsExpression::Function *foo = reinterpret_cast<QgsExpression::Function *>( sqlite3_user_data( ctxt ) );
QgsExpressionFunction *foo = reinterpret_cast<QgsExpressionFunction *>( sqlite3_user_data( ctxt ) );
QVariantList variants;
for ( int i = 0; i < nArgs; i++ )
@ -849,7 +849,7 @@ void registerQgisFunctions( sqlite3 *db )
QStringList reservedFunctions;
reservedFunctions << QStringLiteral( "left" ) << QStringLiteral( "right" ) << QStringLiteral( "union" );
// register QGIS expression functions
Q_FOREACH ( QgsExpression::Function *foo, QgsExpression::Functions() )
Q_FOREACH ( QgsExpressionFunction *foo, QgsExpression::Functions() )
{
if ( foo->usesGeometry( nullptr ) || foo->lazyEval() )
{

View File

@ -11,6 +11,7 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/src/annotations
${CMAKE_SOURCE_DIR}/src/core/auth
${CMAKE_SOURCE_DIR}/src/core/composer
${CMAKE_SOURCE_DIR}/src/core/expression
${CMAKE_SOURCE_DIR}/src/core/geometry
${CMAKE_SOURCE_DIR}/src/core/metadata
${CMAKE_SOURCE_DIR}/src/core/effects

View File

@ -19,12 +19,12 @@
#include <qgsapplication.h>
//header for class being tested
#include <qgsexpression.h>
#include <qgsfeature.h>
#include "qgsexpression.h"
#include "qgsfeature.h"
#include "qgsfeatureiterator.h"
#include <qgsfeaturerequest.h>
#include <qgsgeometry.h>
#include <qgsrenderchecker.h>
#include "qgsfeaturerequest.h"
#include "qgsgeometry.h"
#include "qgsrenderchecker.h"
#include "qgsexpressioncontext.h"
#include "qgsrelationmanager.h"
#include "qgsvectorlayer.h"
@ -32,6 +32,7 @@
#include "qgsdistancearea.h"
#include "qgsrasterlayer.h"
#include "qgsproject.h"
#include "qgsexpressionnodeimpl.h"
static void _parseAndEvalExpr( int arg )
{
@ -1211,12 +1212,6 @@ class TestQgsExpression: public QObject
run_evaluation_test( exp4, evalError, result );
}
void eval_precedence()
{
QCOMPARE( QgsExpression::BINARY_OPERATOR_TEXT[QgsExpression::boDiv], "/" );
QCOMPARE( QgsExpression::BINARY_OPERATOR_TEXT[QgsExpression::boConcat], "||" );
}
void eval_columns()
{
QgsFields fields;

View File

@ -114,7 +114,7 @@ class TestQgsExpressionContext : public QObject
/**
* This function is not static, it's value changes with every invocation.
*/
virtual bool isStatic( const QgsExpression::NodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) const override
virtual bool isStatic( const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) const override
{
Q_UNUSED( node )
Q_UNUSED( parent )