26#include <QRegularExpression>
29using namespace Qt::StringLiterals;
39 "OR",
"AND",
"=",
"<>",
"<=",
">=",
"<",
">",
"LIKE",
"NOT LIKE",
"ILIKE",
"NOT ILIKE",
"IS",
"IS NOT",
"+",
"-",
"*",
"/",
"//",
"%",
"^",
"||"
73 return tr(
"(no root)" );
80 return u
"\"%1\""_s.arg( name.replace(
'\"',
"\"\""_L1 ) );
86 static const char *
const RESERVED_KEYWORDS[] = {
"AND",
"OR",
"NOT",
"LIKE",
"IN",
"IS",
"BETWEEN",
"NULL",
"SELECT",
"ALL",
"DISTINCT",
"CAST",
87 "AS",
"FROM",
"JOIN",
"ON",
"USING",
"WHERE",
"ORDER",
"BY",
"ASC",
"DESC",
"LEFT",
"RIGHT",
88 "INNER",
"OUTER",
"CROSS",
"FULL",
"NATURAL",
"UNION",
"OFFSET",
"LIMIT",
"GROUP",
"HAVING" };
90 for (
size_t i = 0; i <
sizeof( RESERVED_KEYWORDS ) /
sizeof( RESERVED_KEYWORDS[0] ); ++i )
92 if ( name.compare( QString( RESERVED_KEYWORDS[i] ), Qt::CaseInsensitive ) == 0 )
97 const thread_local QRegularExpression IDENTIFIER_RE(
"^[A-Za-z_\\x80-\\xff][A-Za-z0-9_\\x80-\\xff]*$" );
98 return IDENTIFIER_RE.match( name ).hasMatch() ? name :
quotedIdentifier( name );
103 if ( text.length() >= 2 && text[0] ==
'"' && text[text.length() - 1] ==
'"' )
106 text = text.mid( 1, text.length() - 2 );
109 text.replace(
"\"\""_L1,
"\""_L1 );
116 if ( text.length() >= 2 && text[0] ==
'[' && text[text.length() - 1] ==
']' )
119 text = text.mid( 1, text.length() - 2 );
126 text.replace(
'\'',
"''"_L1 );
127 text.replace(
'\\',
"\\\\"_L1 );
128 text.replace(
'\n',
"\\n"_L1 );
129 text.replace(
'\t',
"\\t"_L1 );
130 return u
"'%1'"_s.arg( text );
153 if ( &other !=
this )
189 const auto constTables = n.
tables();
192 table->accept( *
this );
194 const auto constColumns = n.
columns();
197 column->accept( *
this );
199 const auto constJoins = n.
joins();
202 join->accept( *
this );
207 const auto constOrderBy = n.
orderBy();
210 column->accept( *
this );
263 errorMsgOut = tr(
"No root node" );
273 if ( !errorMsgOut.isEmpty() )
274 errorMsgOut +=
' '_L1;
275 errorMsgOut += tr(
"Table %1 is referenced by column %2, but not selected in FROM / JOIN." ).arg( pair.first, pair.second );
279 return errorMsgOut.isEmpty();
296 const auto constMList =
mList;
297 for (
Node *node : constMList )
299 nl->
mList.append( node->clone() );
309 const auto constMList =
mList;
310 for (
Node *n : constMList )
382 Q_ASSERT(
false &&
"unexpected binary operator" );
417 Q_ASSERT(
false &&
"unexpected binary operator" );
437 rdump.prepend(
'(' ).append(
')' );
466 return u
"%1 %2IN (%3)"_s.arg(
mNode->dump(),
mNotIn ?
"NOT " :
"",
mList->dump() );
505 switch (
mValue.userType() )
507 case QMetaType::Type::Int:
508 return QString::number(
mValue.toInt() );
509 case QMetaType::Type::LongLong:
510 return QString::number(
mValue.toLongLong() );
511 case QMetaType::Type::Double:
512 return QString::number(
mValue.toDouble() );
513 case QMetaType::Type::QString:
515 case QMetaType::Type::Bool:
516 return mValue.toBool() ?
"TRUE" :
"FALSE";
518 return tr(
"[unsupported type: %1; value: %2]" ).arg(
mValue.typeName(),
mValue.toString() );
532 switch (
mValue.userType() )
534 case QMetaType::Type::Int:
535 return QString::number(
mValue.toInt() );
536 case QMetaType::Type::Double:
538 case QMetaType::Type::LongLong:
539 return QString::number(
mValue.toLongLong() );
540 case QMetaType::Type::QString:
542 case QMetaType::Type::QTime:
544 case QMetaType::Type::QDate:
546 case QMetaType::Type::QDateTime:
548 case QMetaType::Type::Bool:
549 return mValue.toBool() ? u
"TRUE"_s : u
"FALSE"_s;
551 return tr(
"[unsupported type: %1; value: %2]" ).arg(
mValue.typeName(),
mValue.toString() );
561 ret +=
"DISTINCT "_L1;
647 QString ret = u
"SELECT "_s;
649 ret +=
"DISTINCT "_L1;
650 bool bFirstColumn =
true;
651 const auto constMColumns =
mColumns;
656 bFirstColumn =
false;
657 ret += column->dump();
660 bool bFirstTable =
true;
667 ret += table->dump();
669 const auto constMJoins =
mJoins;
682 ret +=
" ORDER BY "_L1;
684 const auto constMOrderBy =
mOrderBy;
698 QList<QgsSQLStatement::NodeSelectedColumn *> newColumnList;
699 const auto constMColumns =
mColumns;
702 newColumnList.push_back( column->cloneThis() );
704 QList<QgsSQLStatement::NodeTableDef *> newTableList;
708 newTableList.push_back( table->cloneThis() );
711 const auto constMJoins =
mJoins;
720 QList<QgsSQLStatement::NodeColumnSorted *> newOrderByList;
721 const auto constMOrderBy =
mOrderBy;
724 newOrderByList.push_back( columnSorted->cloneThis() );
749 ret +=
" USING ("_L1;
752 for ( QString column : constMUsingColumns )
802 QString ret( u
"CAST("_s );
803 ret +=
mNode->dump();
static QString quotedString(QString text)
Returns a quoted version of a string (in single quotes).
QgsSQLStatementCollectTableNames()=default
Constructor for QgsSQLStatementCollectTableNames.
QSet< TableColumnPair > tableNamesReferenced
QPair< QString, QString > TableColumnPair
QSet< QString > tableNamesDeclared
void visit(const QgsSQLStatement::NodeColumnRef &n) override
Visit NodeColumnRef.
QgsSQLStatementFragment(const QString &fragment)
Constructor for QgsSQLStatementFragment of the specified fragment.
std::unique_ptr< Node > mMaxVal
std::unique_ptr< Node > mNode
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
std::unique_ptr< Node > mMinVal
NodeBetweenOperator(QgsSQLStatement::Node *node, QgsSQLStatement::Node *minVal, QgsSQLStatement::Node *maxVal, bool notBetween=false)
Constructor.
QString dump() const override
Abstract virtual dump method.
Binary logical/arithmetical operator (AND, OR, =, +, ...).
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
std::unique_ptr< Node > mOpLeft
int precedence() const
Precedence.
QString dump() const override
Abstract virtual dump method.
QString text() const
Returns a the name of this operator without the operands.
NodeBinaryOperator(QgsSQLStatement::BinaryOperator op, QgsSQLStatement::Node *opLeft, QgsSQLStatement::Node *opRight)
Constructor.
std::unique_ptr< Node > mOpRight
bool leftAssociative() const
Is left associative ?
NodeCast(QgsSQLStatement::Node *node, const QString &type)
Constructor.
QString dump() const override
Abstract virtual dump method.
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
std::unique_ptr< Node > mNode
QString name() const
The name of the column.
NodeColumnRef(const QString &name, bool star)
Constructor with column name only.
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
QString tableName() const
The name of the table. May be empty.
QString dump() const override
Abstract virtual dump method.
void setDistinct(bool distinct=true)
Sets whether this is prefixed by DISTINCT.
QgsSQLStatement::NodeColumnRef * cloneThis() const
Clone with same type return.
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
QgsSQLStatement::NodeColumnSorted * cloneThis() const
Clone with same type return.
QString dump() const override
Abstract virtual dump method.
std::unique_ptr< NodeColumnRef > mColumn
NodeColumnSorted(QgsSQLStatement::NodeColumnRef *column, bool asc)
Constructor.
NodeFunction(const QString &name, QgsSQLStatement::NodeList *args)
Constructor.
QString dump() const override
Abstract virtual dump method.
std::unique_ptr< NodeList > mArgs
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
std::unique_ptr< NodeList > mList
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
std::unique_ptr< Node > mNode
NodeInOperator(QgsSQLStatement::Node *node, QgsSQLStatement::NodeList *list, bool notin=false)
Constructor.
QString dump() const override
Abstract virtual dump method.
QList< QString > mUsingColumns
QgsSQLStatement::NodeTableDef * tableDef() const
Table definition.
std::unique_ptr< Node > mOnExpr
QgsSQLStatement::Node * onExpr() const
On expression. Will be nullptr if usingColumns() is not empty.
NodeJoin(QgsSQLStatement::NodeTableDef *tabledef, QgsSQLStatement::Node *onExpr, QgsSQLStatement::JoinType type)
Constructor with table definition, ON expression.
std::unique_ptr< NodeTableDef > mTableDef
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
QString dump() const override
Abstract virtual dump method.
QgsSQLStatement::NodeJoin * cloneThis() const
Clone with same type return.
QgsSQLStatement::NodeList * clone() const
Creates a deep copy of this list. Ownership is transferred to the caller.
void accept(QgsSQLStatement::Visitor &v) const
Accept visitor.
virtual QString dump() const
Dump list.
QString dump() const override
Abstract virtual dump method.
QString valueAsString() const
Returns a string representation of the node's literal value.
NodeLiteral(const QVariant &value)
Constructor.
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
NodeSelect(const QList< QgsSQLStatement::NodeTableDef * > &tableList, const QList< QgsSQLStatement::NodeSelectedColumn * > &columns, bool distinct)
Constructor.
QList< QgsSQLStatement::NodeColumnSorted * > orderBy() const
Returns the list of order by columns.
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
void setWhere(QgsSQLStatement::Node *where)
Sets where clause.
QList< NodeColumnSorted * > mOrderBy
QList< QgsSQLStatement::NodeSelectedColumn * > columns() const
Returns the list of columns.
QList< NodeSelectedColumn * > mColumns
void appendJoin(QgsSQLStatement::NodeJoin *join)
Append a join.
void setOrderBy(const QList< QgsSQLStatement::NodeColumnSorted * > &orderBy)
Sets order by columns.
std::unique_ptr< Node > mWhere
QList< QgsSQLStatement::NodeJoin * > joins() const
Returns the list of joins.
QList< NodeJoin * > mJoins
QList< NodeTableDef * > mTableList
QgsSQLStatement::Node * where() const
Returns the where clause.
QString dump() const override
Abstract virtual dump method.
QList< QgsSQLStatement::NodeTableDef * > tables() const
Returns the list of tables.
NodeSelectedColumn(QgsSQLStatement::Node *node)
Constructor.
void setAlias(const QString &alias)
Sets alias name.
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
QString dump() const override
Abstract virtual dump method.
QgsSQLStatement::NodeSelectedColumn * cloneThis() const
Clone with same type return.
std::unique_ptr< Node > mColumnNode
QString name() const
Table name.
QString dump() const override
Abstract virtual dump method.
NodeTableDef(const QString &name)
Constructor with table name.
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
void accept(QgsSQLStatement::Visitor &v) const override
Support the visitor pattern.
QString alias() const
Table alias.
QString schema() const
Returns the schema name.
QgsSQLStatement::NodeTableDef * cloneThis() const
Clone with same type return.
Unary logical/arithmetical operator ( NOT, - ).
QString dump() const override
Abstract virtual dump method.
NodeUnaryOperator(QgsSQLStatement::UnaryOperator op, QgsSQLStatement::Node *operand)
Constructor.
std::unique_ptr< Node > mOperand
QgsSQLStatement::UnaryOperator op() const
Operator.
QString text() const
Returns a the name of this operator without the operands.
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
Abstract node class for SQL statement nodes.
virtual void accept(QgsSQLStatement::Visitor &v) const =0
Support the visitor pattern.
A visitor that recursively explores all children.
void visit(const QgsSQLStatement::NodeUnaryOperator &n) override
Visit NodeUnaryOperator.
Support for visitor pattern - algorithms dealing with the statement may be implemented without modify...
bool doBasicValidationChecks(QString &errorMsgOut) const
Performs basic validity checks.
static QString stripQuotedIdentifier(QString text)
Remove double quotes from an identifier.
static QString quotedIdentifierIfNeeded(const QString &name)
Returns a quoted column reference (in double quotes) if needed, or otherwise the original string.
QString mParserErrorString
static QString quotedIdentifier(QString name)
Returns a quoted column reference (in double quotes).
QString parserErrorString() const
Returns parser error.
static const char * JOIN_TYPE_TEXT[]
QgsSQLStatement & operator=(const QgsSQLStatement &other)
static QString stripMsQuotedIdentifier(QString text)
Remove double quotes from an Microsoft style identifier.
static const char * BINARY_OPERATOR_TEXT[]
static QString quotedString(QString text)
Returns a quoted version of a string (in single quotes).
QString dump() const
Returns the statement string, constructed from the internal abstract syntax tree.
virtual ~QgsSQLStatement()
void acceptVisitor(QgsSQLStatement::Visitor &v) const
Entry function for the visitor pattern.
std::unique_ptr< QgsSQLStatement::Node > mRootNode
bool hasParserError() const
Returns true if an error occurred when parsing the input statement.
const QgsSQLStatement::Node * rootNode() const
Returns the root node of the statement.
QString statement() const
Returns the original, unmodified statement string.
QgsSQLStatement(const QString &statement)
Creates a new statement based on the provided string.
static const char * UNARY_OPERATOR_TEXT[]
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
QgsSQLStatement::Node * parse(const QString &str, QString &parserErrorMsg, bool allowFragments)