mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
840 lines
28 KiB
C++
840 lines
28 KiB
C++
/***************************************************************************
|
|
qgssqlstatement.h
|
|
---------------------
|
|
begin : April 2016
|
|
copyright : (C) 2011 by Martin Dobias
|
|
copyright : (C) 2016 by Even Rouault
|
|
email : even.rouault at spatialys.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 QGSSQLSTATEMENT_H
|
|
#define QGSSQLSTATEMENT_H
|
|
|
|
#include <QCoreApplication>
|
|
#include "qgis_sip.h"
|
|
#include <QMetaType>
|
|
#include <QStringList>
|
|
#include <QVariant>
|
|
#include <QList>
|
|
#include <QSet>
|
|
|
|
#include "qgis_core.h"
|
|
|
|
/**
|
|
* \ingroup core
|
|
Class for parsing SQL statements.
|
|
* \since QGIS 2.16
|
|
*/
|
|
|
|
class CORE_EXPORT QgsSQLStatement
|
|
{
|
|
Q_DECLARE_TR_FUNCTIONS( QgsSQLStatement )
|
|
public:
|
|
|
|
/**
|
|
* Creates a new statement based on the provided string.
|
|
*/
|
|
QgsSQLStatement( const QString &statement );
|
|
|
|
/**
|
|
* Create a copy of this statement.
|
|
*/
|
|
QgsSQLStatement( const QgsSQLStatement &other );
|
|
|
|
/**
|
|
* Create a copy of this statement.
|
|
*/
|
|
QgsSQLStatement &operator=( const QgsSQLStatement &other );
|
|
~QgsSQLStatement();
|
|
|
|
//! Returns TRUE if an error occurred when parsing the input statement
|
|
bool hasParserError() const;
|
|
//! Returns parser error
|
|
QString parserErrorString() const;
|
|
|
|
/**
|
|
* Performs basic validity checks. Basically checking that columns referencing
|
|
* a table, references a specified table. Returns TRUE if the validation is
|
|
* successful
|
|
*/
|
|
bool doBasicValidationChecks( QString &errorMsgOut SIP_OUT ) const;
|
|
|
|
class Node;
|
|
|
|
/**
|
|
* Returns the root node of the statement.
|
|
* The root node is NULLPTR if parsing has failed.
|
|
*/
|
|
const QgsSQLStatement::Node *rootNode() const;
|
|
|
|
/**
|
|
* Returns the original, unmodified statement string.
|
|
* If there was none supplied because it was constructed by sole
|
|
* API calls, dump() will be used to create one instead.
|
|
*/
|
|
QString statement() const;
|
|
|
|
/**
|
|
* Returns the statement 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
|
|
* statement() instead.
|
|
*/
|
|
QString dump() const;
|
|
|
|
/**
|
|
* Returns a quoted column reference (in double quotes)
|
|
* \see quotedString(), quotedIdentifierIfNeeded()
|
|
*/
|
|
static QString quotedIdentifier( QString name );
|
|
|
|
/**
|
|
* Returns a quoted column reference (in double quotes) if needed, or
|
|
* otherwise the original string.
|
|
* \see quotedString(), quotedIdentifier()
|
|
*/
|
|
static QString quotedIdentifierIfNeeded( const QString &name );
|
|
|
|
/**
|
|
* Remove double quotes from an identifier.
|
|
* \see quotedIdentifier()
|
|
*/
|
|
static QString stripQuotedIdentifier( QString text );
|
|
|
|
/**
|
|
* Returns a quoted version of a string (in single quotes)
|
|
* \see quotedIdentifier(), quotedIdentifierIfNeeded()
|
|
*/
|
|
static QString quotedString( QString text );
|
|
|
|
/**
|
|
* \brief list of unary operators
|
|
* \note if any change is made here, the definition of QgsSQLStatement::UnaryOperatorText[] must be adapted.
|
|
*/
|
|
enum UnaryOperator
|
|
{
|
|
uoNot,
|
|
uoMinus,
|
|
};
|
|
|
|
/**
|
|
* \brief list of binary operators
|
|
* \note if any change is made here, the definition of QgsSQLStatement::BinaryOperatorText[] must be adapted.
|
|
*/
|
|
enum BinaryOperator
|
|
{
|
|
// logical
|
|
boOr,
|
|
boAnd,
|
|
|
|
// comparison
|
|
boEQ, // =
|
|
boNE, // <>
|
|
boLE, // <=
|
|
boGE, // >=
|
|
boLT, // <
|
|
boGT, // >
|
|
boLike,
|
|
boNotLike,
|
|
boILike,
|
|
boNotILike,
|
|
boIs,
|
|
boIsNot,
|
|
|
|
// math
|
|
boPlus,
|
|
boMinus,
|
|
boMul,
|
|
boDiv,
|
|
boIntDiv,
|
|
boMod,
|
|
boPow,
|
|
|
|
// strings
|
|
boConcat,
|
|
};
|
|
|
|
/**
|
|
* \brief list of join types
|
|
* \note if any change is made here, the definition of QgsSQLStatement::JoinTypeText[] must be adapted.
|
|
*/
|
|
enum JoinType
|
|
{
|
|
jtDefault,
|
|
jtLeft,
|
|
jtLeftOuter,
|
|
jtRight,
|
|
jtRightOuter,
|
|
jtCross,
|
|
jtInner,
|
|
jtFull
|
|
};
|
|
|
|
//! \note not available in Python bindings
|
|
static const char *BINARY_OPERATOR_TEXT[] SIP_SKIP;
|
|
|
|
//! \note not available in Python bindings
|
|
static const char *UNARY_OPERATOR_TEXT[] SIP_SKIP;
|
|
|
|
//! \note not available in Python bindings
|
|
static const char *JOIN_TYPE_TEXT[] SIP_SKIP;
|
|
|
|
//////
|
|
|
|
class Visitor; // visitor interface is defined below
|
|
|
|
//! Node type
|
|
enum NodeType
|
|
{
|
|
ntUnaryOperator,
|
|
ntBinaryOperator,
|
|
ntInOperator,
|
|
ntBetweenOperator,
|
|
ntFunction,
|
|
ntLiteral,
|
|
ntColumnRef,
|
|
ntSelectedColumn,
|
|
ntSelect,
|
|
ntTableDef,
|
|
ntJoin,
|
|
ntColumnSorted,
|
|
ntCast
|
|
};
|
|
|
|
/**
|
|
* \ingroup core
|
|
* Abstract node class
|
|
*/
|
|
class CORE_EXPORT Node
|
|
{
|
|
|
|
#ifdef SIP_RUN
|
|
SIP_CONVERT_TO_SUBCLASS_CODE
|
|
switch ( sipCpp->nodeType() )
|
|
{
|
|
case QgsSQLStatement::ntUnaryOperator: sipType = sipType_QgsSQLStatement_NodeUnaryOperator; break;
|
|
case QgsSQLStatement::ntBinaryOperator: sipType = sipType_QgsSQLStatement_NodeBinaryOperator; break;
|
|
case QgsSQLStatement::ntInOperator: sipType = sipType_QgsSQLStatement_NodeInOperator; break;
|
|
case QgsSQLStatement::ntBetweenOperator: sipType = sipType_QgsSQLStatement_NodeBetweenOperator; break;
|
|
case QgsSQLStatement::ntFunction: sipType = sipType_QgsSQLStatement_NodeFunction; break;
|
|
case QgsSQLStatement::ntLiteral: sipType = sipType_QgsSQLStatement_NodeLiteral; break;
|
|
case QgsSQLStatement::ntColumnRef: sipType = sipType_QgsSQLStatement_NodeColumnRef; break;
|
|
case QgsSQLStatement::ntSelectedColumn: sipType = sipType_QgsSQLStatement_NodeSelectedColumn; break;
|
|
case QgsSQLStatement::ntSelect: sipType = sipType_QgsSQLStatement_NodeSelect; break;
|
|
case QgsSQLStatement::ntTableDef: sipType = sipType_QgsSQLStatement_NodeTableDef; break;
|
|
case QgsSQLStatement::ntJoin: sipType = sipType_QgsSQLStatement_NodeJoin; break;
|
|
case QgsSQLStatement::ntColumnSorted: sipType = sipType_QgsSQLStatement_NodeColumnSorted; break;
|
|
case QgsSQLStatement::ntCast: sipType = sipType_QgsSQLStatement_NodeCast; break;
|
|
default: sipType = 0; break;
|
|
}
|
|
SIP_END
|
|
#endif
|
|
|
|
public:
|
|
virtual ~Node() = default;
|
|
|
|
/**
|
|
* Abstract virtual that returns the type of this node.
|
|
*
|
|
* \returns The type of this node
|
|
*/
|
|
virtual QgsSQLStatement::NodeType nodeType() const = 0;
|
|
|
|
/**
|
|
* Abstract virtual dump method
|
|
*
|
|
* \returns A statement which represents this node as string
|
|
*/
|
|
virtual QString dump() const = 0;
|
|
|
|
/**
|
|
* Generate a clone of this node.
|
|
* Make sure that the clone does not contain any information which is
|
|
* generated in prepare and context related.
|
|
* Ownership is transferred to the caller.
|
|
*
|
|
* \returns a deep copy of this node.
|
|
*/
|
|
virtual QgsSQLStatement::Node *clone() const = 0 SIP_FACTORY;
|
|
|
|
/**
|
|
* Support the visitor pattern.
|
|
*
|
|
* For any implementation this should look like
|
|
*
|
|
* C++:
|
|
*
|
|
* v.visit( *this );
|
|
*
|
|
* Python:
|
|
*
|
|
* v.visit( self)
|
|
*
|
|
* \param v A visitor that visits this node.
|
|
*/
|
|
virtual void accept( QgsSQLStatement::Visitor &v ) const = 0;
|
|
};
|
|
|
|
/**
|
|
* A list of nodes.
|
|
* \ingroup core
|
|
*/
|
|
class CORE_EXPORT NodeList
|
|
{
|
|
public:
|
|
//! Constructor
|
|
NodeList() = default;
|
|
virtual ~NodeList() { qDeleteAll( mList ); }
|
|
|
|
//! Takes ownership of the provided node
|
|
void append( QgsSQLStatement::Node *node SIP_TRANSFER ) { mList.append( node ); }
|
|
|
|
//! Returns list
|
|
QList<QgsSQLStatement::Node *> list() { return mList; }
|
|
|
|
/**
|
|
* Returns the number of nodes in the list.
|
|
*/
|
|
int count() const { return mList.count(); }
|
|
|
|
//! Accept visitor
|
|
void accept( QgsSQLStatement::Visitor &v ) const;
|
|
|
|
//! Creates a deep copy of this list. Ownership is transferred to the caller
|
|
QgsSQLStatement::NodeList *clone() const SIP_FACTORY;
|
|
|
|
//! Dump list
|
|
virtual QString dump() const;
|
|
|
|
protected:
|
|
QList<Node *> mList;
|
|
};
|
|
|
|
/**
|
|
* \ingroup core
|
|
* Unary logicial/arithmetical operator ( NOT, - )
|
|
*/
|
|
class CORE_EXPORT NodeUnaryOperator : public QgsSQLStatement::Node
|
|
{
|
|
public:
|
|
//! Constructor
|
|
NodeUnaryOperator( QgsSQLStatement::UnaryOperator op, QgsSQLStatement::Node *operand SIP_TRANSFER ) : mOp( op ), mOperand( operand ) {}
|
|
~NodeUnaryOperator() override { delete mOperand; }
|
|
|
|
//! Operator
|
|
QgsSQLStatement::UnaryOperator op() const { return mOp; }
|
|
|
|
//! Operand
|
|
QgsSQLStatement::Node *operand() const { return mOperand; }
|
|
|
|
QgsSQLStatement::NodeType nodeType() const override { return ntUnaryOperator; }
|
|
QString dump() const override;
|
|
|
|
void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
|
|
QgsSQLStatement::Node *clone() const override SIP_FACTORY;
|
|
|
|
protected:
|
|
UnaryOperator mOp;
|
|
Node *mOperand = nullptr;
|
|
};
|
|
|
|
/**
|
|
* \ingroup core
|
|
* Binary logical/arithmetical operator (AND, OR, =, +, ...)
|
|
*/
|
|
class CORE_EXPORT NodeBinaryOperator : public QgsSQLStatement::Node
|
|
{
|
|
public:
|
|
//! Constructor
|
|
NodeBinaryOperator( QgsSQLStatement::BinaryOperator op, QgsSQLStatement::Node *opLeft SIP_TRANSFER, QgsSQLStatement::Node *opRight SIP_TRANSFER )
|
|
: mOp( op )
|
|
, mOpLeft( opLeft )
|
|
, mOpRight( opRight )
|
|
{}
|
|
~NodeBinaryOperator() override { delete mOpLeft; delete mOpRight; }
|
|
|
|
//! Operator
|
|
QgsSQLStatement::BinaryOperator op() const { return mOp; }
|
|
|
|
//! Left operand
|
|
QgsSQLStatement::Node *opLeft() const { return mOpLeft; }
|
|
|
|
//! Right operand
|
|
QgsSQLStatement::Node *opRight() const { return mOpRight; }
|
|
|
|
QgsSQLStatement::NodeType nodeType() const override { return ntBinaryOperator; }
|
|
QString dump() const override;
|
|
|
|
void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
|
|
QgsSQLStatement::Node *clone() const override SIP_FACTORY;
|
|
|
|
//! Precedence
|
|
int precedence() const;
|
|
|
|
//! Is left associative ?
|
|
bool leftAssociative() const;
|
|
|
|
protected:
|
|
|
|
BinaryOperator mOp;
|
|
Node *mOpLeft = nullptr;
|
|
Node *mOpRight = nullptr;
|
|
};
|
|
|
|
/**
|
|
* \ingroup core
|
|
* 'x IN (y, z)' operator
|
|
*/
|
|
class CORE_EXPORT NodeInOperator : public QgsSQLStatement::Node
|
|
{
|
|
public:
|
|
//! Constructor
|
|
NodeInOperator( QgsSQLStatement::Node *node SIP_TRANSFER, QgsSQLStatement::NodeList *list SIP_TRANSFER, bool notin = false ) : mNode( node ), mList( list ), mNotIn( notin ) {}
|
|
~NodeInOperator() override { delete mNode; delete mList; }
|
|
|
|
//! Variable at the left of IN
|
|
QgsSQLStatement::Node *node() const { return mNode; }
|
|
|
|
//! Whether this is a NOT IN operator
|
|
bool isNotIn() const { return mNotIn; }
|
|
|
|
//! Values list
|
|
QgsSQLStatement::NodeList *list() const { return mList; }
|
|
|
|
QgsSQLStatement::NodeType nodeType() const override { return ntInOperator; }
|
|
QString dump() const override;
|
|
|
|
void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
|
|
QgsSQLStatement::Node *clone() const override SIP_FACTORY;
|
|
|
|
protected:
|
|
Node *mNode = nullptr;
|
|
NodeList *mList = nullptr;
|
|
bool mNotIn;
|
|
};
|
|
|
|
/**
|
|
* \ingroup core
|
|
* 'X BETWEEN y and z' operator
|
|
*/
|
|
class CORE_EXPORT NodeBetweenOperator : public QgsSQLStatement::Node
|
|
{
|
|
public:
|
|
//! Constructor
|
|
NodeBetweenOperator( QgsSQLStatement::Node *node SIP_TRANSFER, QgsSQLStatement::Node *minVal SIP_TRANSFER, QgsSQLStatement::Node *maxVal SIP_TRANSFER, bool notBetween = false )
|
|
: mNode( node ), mMinVal( minVal ), mMaxVal( maxVal ), mNotBetween( notBetween ) {}
|
|
~NodeBetweenOperator() override { delete mNode; delete mMinVal; delete mMaxVal; }
|
|
|
|
//! Variable at the left of BETWEEN
|
|
QgsSQLStatement::Node *node() const { return mNode; }
|
|
|
|
//! Whether this is a NOT BETWEEN operator
|
|
bool isNotBetween() const { return mNotBetween; }
|
|
|
|
//! Minimum bound
|
|
QgsSQLStatement::Node *minVal() const { return mMinVal; }
|
|
|
|
//! Maximum bound
|
|
QgsSQLStatement::Node *maxVal() const { return mMaxVal; }
|
|
|
|
QgsSQLStatement::NodeType nodeType() const override { return ntBetweenOperator; }
|
|
QString dump() const override;
|
|
|
|
void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
|
|
QgsSQLStatement::Node *clone() const override SIP_FACTORY;
|
|
|
|
protected:
|
|
Node *mNode = nullptr;
|
|
Node *mMinVal = nullptr;
|
|
Node *mMaxVal = nullptr;
|
|
bool mNotBetween;
|
|
};
|
|
|
|
/**
|
|
* \ingroup core
|
|
* Function with a name and arguments node
|
|
*/
|
|
class CORE_EXPORT NodeFunction : public QgsSQLStatement::Node
|
|
{
|
|
public:
|
|
//! Constructor
|
|
NodeFunction( const QString &name, QgsSQLStatement::NodeList *args SIP_TRANSFER ) : mName( name ), mArgs( args ) {}
|
|
~NodeFunction() override { delete mArgs; }
|
|
|
|
//! Returns function name
|
|
QString name() const { return mName; }
|
|
|
|
//! Returns arguments
|
|
QgsSQLStatement::NodeList *args() const { return mArgs; }
|
|
|
|
QgsSQLStatement::NodeType nodeType() const override { return ntFunction; }
|
|
QString dump() const override;
|
|
|
|
void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
|
|
QgsSQLStatement::Node *clone() const override SIP_FACTORY;
|
|
|
|
protected:
|
|
QString mName;
|
|
NodeList *mArgs = nullptr;
|
|
|
|
};
|
|
|
|
/**
|
|
* \ingroup core
|
|
* Literal value (integer, integer64, double, string)
|
|
*/
|
|
class CORE_EXPORT NodeLiteral : public QgsSQLStatement::Node
|
|
{
|
|
public:
|
|
//! Constructor
|
|
NodeLiteral( const QVariant &value ) : mValue( value ) {}
|
|
|
|
//! The value of the literal.
|
|
inline QVariant value() const { return mValue; }
|
|
|
|
QgsSQLStatement::NodeType nodeType() const override { return ntLiteral; }
|
|
QString dump() const override;
|
|
|
|
void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
|
|
QgsSQLStatement::Node *clone() const override SIP_FACTORY;
|
|
|
|
protected:
|
|
QVariant mValue;
|
|
};
|
|
|
|
/**
|
|
* \ingroup core
|
|
* Reference to a column
|
|
*/
|
|
class CORE_EXPORT NodeColumnRef : public QgsSQLStatement::Node
|
|
{
|
|
public:
|
|
//! Constructor with column name only
|
|
NodeColumnRef( const QString &name, bool star ) : mName( name ), mDistinct( false ), mStar( star ) {}
|
|
//! Constructor with table and column name
|
|
NodeColumnRef( const QString &tableName, const QString &name, bool star ) : mTableName( tableName ), mName( name ), mDistinct( false ), mStar( star ) {}
|
|
|
|
//! Sets whether this is prefixed by DISTINCT
|
|
void setDistinct( bool distinct = true ) { mDistinct = distinct; }
|
|
|
|
//! The name of the table. May be empty.
|
|
QString tableName() const { return mTableName; }
|
|
|
|
//! The name of the column.
|
|
QString name() const { return mName; }
|
|
|
|
//! Whether this is the * column
|
|
bool star() const { return mStar; }
|
|
|
|
//! Whether this is prefixed by DISTINCT
|
|
bool distinct() const { return mDistinct; }
|
|
|
|
QgsSQLStatement::NodeType nodeType() const override { return ntColumnRef; }
|
|
QString dump() const override;
|
|
|
|
void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
|
|
QgsSQLStatement::Node *clone() const override SIP_FACTORY;
|
|
//! Clone with same type return
|
|
QgsSQLStatement::NodeColumnRef *cloneThis() const SIP_FACTORY;
|
|
|
|
protected:
|
|
QString mTableName;
|
|
QString mName;
|
|
bool mDistinct;
|
|
bool mStar;
|
|
};
|
|
|
|
/**
|
|
* \ingroup core
|
|
* Selected column
|
|
*/
|
|
class CORE_EXPORT NodeSelectedColumn : public QgsSQLStatement::Node
|
|
{
|
|
public:
|
|
//! Constructor
|
|
NodeSelectedColumn( QgsSQLStatement::Node *node SIP_TRANSFER ) : mColumnNode( node ) {}
|
|
~NodeSelectedColumn() override { delete mColumnNode; }
|
|
|
|
//! Sets alias name
|
|
void setAlias( const QString &alias ) { mAlias = alias; }
|
|
|
|
//! Column that is referred to
|
|
QgsSQLStatement::Node *column() const { return mColumnNode; }
|
|
|
|
//! Alias name
|
|
QString alias() const { return mAlias; }
|
|
|
|
QgsSQLStatement::NodeType nodeType() const override { return ntSelectedColumn; }
|
|
QString dump() const override;
|
|
|
|
void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
|
|
QgsSQLStatement::Node *clone() const override SIP_FACTORY;
|
|
//! Clone with same type return
|
|
QgsSQLStatement::NodeSelectedColumn *cloneThis() const SIP_FACTORY;
|
|
|
|
protected:
|
|
Node *mColumnNode = nullptr;
|
|
QString mAlias;
|
|
};
|
|
|
|
/**
|
|
* \ingroup core
|
|
* CAST operator
|
|
*/
|
|
class CORE_EXPORT NodeCast : public QgsSQLStatement::Node
|
|
{
|
|
public:
|
|
//! Constructor
|
|
NodeCast( QgsSQLStatement::Node *node SIP_TRANSFER, const QString &type ) : mNode( node ), mType( type ) {}
|
|
~NodeCast() override { delete mNode; }
|
|
|
|
//! Node that is referred to
|
|
QgsSQLStatement::Node *node() const { return mNode; }
|
|
|
|
//! Type
|
|
QString type() const { return mType; }
|
|
|
|
QgsSQLStatement::NodeType nodeType() const override { return ntCast; }
|
|
QString dump() const override;
|
|
|
|
void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
|
|
QgsSQLStatement::Node *clone() const override SIP_FACTORY;
|
|
|
|
protected:
|
|
Node *mNode = nullptr;
|
|
QString mType;
|
|
};
|
|
|
|
/**
|
|
* \ingroup core
|
|
* Table definition
|
|
*/
|
|
class CORE_EXPORT NodeTableDef : public QgsSQLStatement::Node
|
|
{
|
|
public:
|
|
//! Constructor with table name
|
|
NodeTableDef( const QString &name ) : mName( name ) {}
|
|
//! Constructor with table name and alias
|
|
NodeTableDef( const QString &name, const QString &alias ) : mName( name ), mAlias( alias ) {}
|
|
|
|
//! Table name
|
|
QString name() const { return mName; }
|
|
|
|
//! Table alias
|
|
QString alias() const { return mAlias; }
|
|
|
|
QgsSQLStatement::NodeType nodeType() const override { return ntTableDef; }
|
|
QString dump() const override;
|
|
|
|
void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
|
|
QgsSQLStatement::Node *clone() const override SIP_FACTORY;
|
|
//! Clone with same type return
|
|
QgsSQLStatement::NodeTableDef *cloneThis() const SIP_FACTORY;
|
|
|
|
protected:
|
|
QString mName;
|
|
QString mAlias;
|
|
};
|
|
|
|
/**
|
|
* \ingroup core
|
|
* Join definition
|
|
*/
|
|
class CORE_EXPORT NodeJoin : public QgsSQLStatement::Node
|
|
{
|
|
public:
|
|
//! Constructor with table definition, ON expression
|
|
NodeJoin( QgsSQLStatement::NodeTableDef *tabledef SIP_TRANSFER, QgsSQLStatement::Node *onExpr SIP_TRANSFER, QgsSQLStatement::JoinType type ) : mTableDef( tabledef ), mOnExpr( onExpr ), mType( type ) {}
|
|
//! Constructor with table definition and USING columns
|
|
NodeJoin( QgsSQLStatement::NodeTableDef *tabledef SIP_TRANSFER, const QList<QString> &usingColumns, QgsSQLStatement::JoinType type ) : mTableDef( tabledef ), mUsingColumns( usingColumns ), mType( type ) {}
|
|
~NodeJoin() override { delete mTableDef; delete mOnExpr; }
|
|
|
|
//! Table definition
|
|
QgsSQLStatement::NodeTableDef *tableDef() const { return mTableDef; }
|
|
|
|
//! On expression. Will be NULLPTR if usingColumns() is not empty
|
|
QgsSQLStatement::Node *onExpr() const { return mOnExpr; }
|
|
|
|
//! Columns referenced by USING
|
|
QList<QString> usingColumns() const { return mUsingColumns; }
|
|
|
|
//! Join type
|
|
QgsSQLStatement::JoinType type() const { return mType; }
|
|
|
|
QgsSQLStatement::NodeType nodeType() const override { return ntJoin; }
|
|
QString dump() const override;
|
|
|
|
void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
|
|
QgsSQLStatement::Node *clone() const override SIP_FACTORY;
|
|
//! Clone with same type return
|
|
QgsSQLStatement::NodeJoin *cloneThis() const SIP_FACTORY;
|
|
|
|
protected:
|
|
NodeTableDef *mTableDef = nullptr;
|
|
Node *mOnExpr = nullptr;
|
|
QList<QString> mUsingColumns;
|
|
JoinType mType;
|
|
};
|
|
|
|
/**
|
|
* \ingroup core
|
|
* Column in a ORDER BY
|
|
*/
|
|
class CORE_EXPORT NodeColumnSorted : public QgsSQLStatement::Node
|
|
{
|
|
public:
|
|
//! Constructor
|
|
NodeColumnSorted( QgsSQLStatement::NodeColumnRef *column SIP_TRANSFER, bool asc ) : mColumn( column ), mAsc( asc ) {}
|
|
~NodeColumnSorted() override { delete mColumn; }
|
|
|
|
//! The name of the column.
|
|
QgsSQLStatement::NodeColumnRef *column() const { return mColumn; }
|
|
|
|
//! Whether the column is sorted in ascending order
|
|
bool ascending() const { return mAsc; }
|
|
|
|
QgsSQLStatement::NodeType nodeType() const override { return ntColumnSorted; }
|
|
QString dump() const override;
|
|
|
|
void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
|
|
QgsSQLStatement::Node *clone() const override SIP_FACTORY;
|
|
//! Clone with same type return
|
|
QgsSQLStatement::NodeColumnSorted *cloneThis() const SIP_FACTORY;
|
|
|
|
protected:
|
|
NodeColumnRef *mColumn = nullptr;
|
|
bool mAsc;
|
|
};
|
|
|
|
/**
|
|
* \ingroup core
|
|
* SELECT node
|
|
*/
|
|
class CORE_EXPORT NodeSelect : public QgsSQLStatement::Node
|
|
{
|
|
public:
|
|
//! Constructor
|
|
NodeSelect( const QList<QgsSQLStatement::NodeTableDef *> &tableList SIP_TRANSFER, const QList<QgsSQLStatement::NodeSelectedColumn *> &columns SIP_TRANSFER, bool distinct ) : mTableList( tableList ), mColumns( columns ), mDistinct( distinct ) {}
|
|
~NodeSelect() override;
|
|
|
|
//! Sets joins
|
|
void setJoins( const QList<QgsSQLStatement::NodeJoin *> &joins SIP_TRANSFER ) { qDeleteAll( mJoins ); mJoins = joins; }
|
|
//! Append a join
|
|
void appendJoin( QgsSQLStatement::NodeJoin *join SIP_TRANSFER ) { mJoins.append( join ); }
|
|
//! Sets where clause
|
|
void setWhere( QgsSQLStatement::Node *where SIP_TRANSFER ) { delete mWhere; mWhere = where; }
|
|
//! Sets order by columns
|
|
void setOrderBy( const QList<QgsSQLStatement::NodeColumnSorted *> &orderBy SIP_TRANSFER ) { qDeleteAll( mOrderBy ); mOrderBy = orderBy; }
|
|
|
|
//! Returns the list of tables
|
|
QList<QgsSQLStatement::NodeTableDef *> tables() const { return mTableList; }
|
|
//! Returns the list of columns
|
|
QList<QgsSQLStatement::NodeSelectedColumn *> columns() const { return mColumns; }
|
|
//! Returns if the SELECT is DISTINCT
|
|
bool distinct() const { return mDistinct; }
|
|
//! Returns the list of joins
|
|
QList<QgsSQLStatement::NodeJoin *> joins() const { return mJoins; }
|
|
//! Returns the where clause
|
|
QgsSQLStatement::Node *where() const { return mWhere; }
|
|
//! Returns the list of order by columns
|
|
QList<QgsSQLStatement::NodeColumnSorted *> orderBy() const { return mOrderBy; }
|
|
|
|
QgsSQLStatement::NodeType nodeType() const override { return ntSelect; }
|
|
QString dump() const override;
|
|
|
|
void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
|
|
QgsSQLStatement::Node *clone() const override SIP_FACTORY;
|
|
|
|
protected:
|
|
QList<NodeTableDef *> mTableList;
|
|
QList<NodeSelectedColumn *> mColumns;
|
|
bool mDistinct;
|
|
QList<NodeJoin *> mJoins;
|
|
Node *mWhere = nullptr;
|
|
QList<NodeColumnSorted *> mOrderBy;
|
|
};
|
|
|
|
//////
|
|
|
|
/**
|
|
* \ingroup core
|
|
* Support for visitor pattern - algorithms dealing with the statement
|
|
may be implemented without modifying the Node classes
|
|
*/
|
|
class CORE_EXPORT Visitor
|
|
{
|
|
public:
|
|
virtual ~Visitor() = default;
|
|
//! Visit NodeUnaryOperator
|
|
virtual void visit( const QgsSQLStatement::NodeUnaryOperator &n ) = 0;
|
|
//! Visit NodeBinaryOperator
|
|
virtual void visit( const QgsSQLStatement::NodeBinaryOperator &n ) = 0;
|
|
//! Visit NodeInOperator
|
|
virtual void visit( const QgsSQLStatement::NodeInOperator &n ) = 0;
|
|
//! Visit NodeBetweenOperator
|
|
virtual void visit( const QgsSQLStatement::NodeBetweenOperator &n ) = 0;
|
|
//! Visit NodeFunction
|
|
virtual void visit( const QgsSQLStatement::NodeFunction &n ) = 0;
|
|
//! Visit NodeLiteral
|
|
virtual void visit( const QgsSQLStatement::NodeLiteral &n ) = 0;
|
|
//! Visit NodeColumnRef
|
|
virtual void visit( const QgsSQLStatement::NodeColumnRef &n ) = 0;
|
|
//! Visit NodeSelectedColumn
|
|
virtual void visit( const QgsSQLStatement::NodeSelectedColumn &n ) = 0;
|
|
//! Visit NodeTableDef
|
|
virtual void visit( const QgsSQLStatement::NodeTableDef &n ) = 0;
|
|
//! Visit NodeSelect
|
|
virtual void visit( const QgsSQLStatement::NodeSelect &n ) = 0;
|
|
//! Visit NodeJoin
|
|
virtual void visit( const QgsSQLStatement::NodeJoin &n ) = 0;
|
|
//! Visit NodeColumnSorted
|
|
virtual void visit( const QgsSQLStatement::NodeColumnSorted &n ) = 0;
|
|
//! Visit NodeCast
|
|
virtual void visit( const QgsSQLStatement::NodeCast &n ) = 0;
|
|
};
|
|
|
|
/**
|
|
* \ingroup core
|
|
* A visitor that recursively explores all children
|
|
*/
|
|
class CORE_EXPORT RecursiveVisitor: public QgsSQLStatement::Visitor
|
|
{
|
|
public:
|
|
//! Constructor
|
|
RecursiveVisitor() = default;
|
|
|
|
void visit( const QgsSQLStatement::NodeUnaryOperator &n ) override { n.operand()->accept( *this ); }
|
|
void visit( const QgsSQLStatement::NodeBinaryOperator &n ) override { n.opLeft()->accept( *this ); n.opRight()->accept( *this ); }
|
|
void visit( const QgsSQLStatement::NodeInOperator &n ) override { n.node()->accept( *this ); n.list()->accept( *this ); }
|
|
void visit( const QgsSQLStatement::NodeBetweenOperator &n ) override { n.node()->accept( *this ); n.minVal()->accept( *this ); n.maxVal()->accept( *this ); }
|
|
void visit( const QgsSQLStatement::NodeFunction &n ) override { n.args()->accept( *this ); }
|
|
void visit( const QgsSQLStatement::NodeLiteral & ) override {}
|
|
void visit( const QgsSQLStatement::NodeColumnRef & ) override { }
|
|
void visit( const QgsSQLStatement::NodeSelectedColumn &n ) override { n.column()->accept( *this ); }
|
|
void visit( const QgsSQLStatement::NodeTableDef & ) override {}
|
|
void visit( const QgsSQLStatement::NodeSelect &n ) override;
|
|
void visit( const QgsSQLStatement::NodeJoin &n ) override;
|
|
void visit( const QgsSQLStatement::NodeColumnSorted &n ) override { n.column()->accept( *this ); }
|
|
void visit( const QgsSQLStatement::NodeCast &n ) override { n.node()->accept( *this ); }
|
|
};
|
|
|
|
//! Entry function for the visitor pattern
|
|
void acceptVisitor( QgsSQLStatement::Visitor &v ) const;
|
|
|
|
protected:
|
|
QgsSQLStatement::Node *mRootNode = nullptr;
|
|
QString mStatement;
|
|
QString mParserErrorString;
|
|
};
|
|
|
|
Q_DECLARE_METATYPE( QgsSQLStatement::Node * )
|
|
|
|
#endif // QGSSQLSTATEMENT_H
|