22 static const QRegExp IDENTIFIER_RE(
"^[A-Za-z_\x80-\xff][A-Za-z0-9_\x80-\xff]*$" );
34 "=",
"<>",
"<=",
">=",
"<",
">",
"LIKE",
"NOT LIKE",
"ILIKE",
"NOT ILIKE",
"IS",
"IS NOT",
35 "+",
"-",
"*",
"/",
"//",
"%",
"^",
48 "",
"LEFT",
"LEFT OUTER",
"RIGHT",
"RIGHT OUTER",
"CROSS",
"INNER",
"FULL" 64 return tr(
"(no root)" );
71 return QStringLiteral(
"\"%1\"" ).arg( name.replace(
'\"', QLatin1String(
"\"\"" ) ) );
77 static const char *
const RESERVED_KEYWORDS[] =
79 "AND",
"OR",
"NOT",
"LIKE",
"IN",
"IS",
"BETWEEN",
"NULL",
"SELECT",
"ALL",
"DISTINCT",
"CAST",
"AS",
80 "FROM",
"JOIN",
"ON",
"USING",
"WHERE",
"ORDER",
"BY",
"ASC",
"DESC",
81 "LEFT",
"RIGHT",
"INNER",
"OUTER",
"CROSS",
"FULL",
"NATURAL",
"UNION",
82 "OFFSET",
"LIMIT",
"GROUP",
"HAVING" 85 for (
size_t i = 0; i <
sizeof( RESERVED_KEYWORDS ) /
sizeof( RESERVED_KEYWORDS[0] ); ++i )
87 if ( name.compare( QString( RESERVED_KEYWORDS[i] ), Qt::CaseInsensitive ) == 0 )
97 if ( text.length() >= 2 && text[0] ==
'"' && text[text.length() - 1] ==
'"' )
100 text = text.mid( 1, text.length() - 2 );
103 text.replace( QLatin1String(
"\"\"" ), QLatin1String(
"\"" ) );
110 text.replace(
'\'', QLatin1String(
"''" ) );
111 text.replace(
'\\', QLatin1String(
"\\\\" ) );
112 text.replace(
'\n', QLatin1String(
"\\n" ) );
113 text.replace(
'\t', QLatin1String(
"\\t" ) );
114 return QStringLiteral(
"'%1'" ).arg( text );
131 if ( &other !=
this )
223 tableNamesDeclared.insert( n.
alias().isEmpty() ? n.
name() : n.
alias() );
232 errorMsgOut = tr(
"No root node" );
242 if ( !errorMsgOut.isEmpty() )
243 errorMsgOut += QLatin1String(
" " );
244 errorMsgOut += QString( tr(
"Table %1 is referenced by column %2, but not selected in FROM / JOIN." ) ).arg( pair.first, pair.second );
248 return errorMsgOut.isEmpty();
265 Q_FOREACH (
Node *node, mList )
277 Q_FOREACH (
Node *n, mList )
279 if ( !first ) msg += QLatin1String(
", " );
342 Q_ASSERT(
false &&
"unexpected binary operator" );
377 Q_ASSERT(
false &&
"unexpected binary operator" );
387 QString rdump( mOpRight->dump() );
392 rdump.prepend(
'(' ).append(
')' );
396 if ( leftAssociative() )
398 fmt += lOp && ( lOp->
precedence() < precedence() ) ?
"(%1)" :
"%1";
399 fmt += QLatin1String(
" %2 " );
400 fmt += rOp && ( rOp->
precedence() <= precedence() ) ?
"(%3)" :
"%3";
404 fmt += lOp && ( lOp->
precedence() <= precedence() ) ?
"(%1)" :
"%1";
405 fmt += QLatin1String(
" %2 " );
406 fmt += rOp && ( rOp->
precedence() < precedence() ) ?
"(%3)" :
"%3";
421 return QStringLiteral(
"%1 %2IN (%3)" ).arg( mNode->dump(), mNotIn ?
"NOT " :
"", mList->dump() );
426 return new NodeInOperator( mNode->clone(), mList->clone(), mNotIn );
433 return QStringLiteral(
"%1 %2BETWEEN %3 AND %4" ).arg( mNode->dump(), mNotBetween ?
"NOT " :
"", mMinVal->dump(), mMaxVal->dump() );
438 return new NodeBetweenOperator( mNode->clone(), mMinVal->clone(), mMaxVal->clone(), mNotBetween );
445 return QStringLiteral(
"%1(%2)" ).arg( mName, mArgs ? mArgs->dump() : QString() );
450 return new NodeFunction( mName, mArgs ? mArgs->clone() : nullptr );
457 if ( mValue.isNull() )
458 return QStringLiteral(
"NULL" );
460 switch ( mValue.type() )
463 return QString::number( mValue.toInt() );
464 case QVariant::LongLong:
465 return QString::number( mValue.toLongLong() );
466 case QVariant::Double:
467 return QString::number( mValue.toDouble() );
468 case QVariant::String:
471 return mValue.toBool() ?
"TRUE" :
"FALSE";
473 return tr(
"[unsupported type: %1; value: %2]" ).arg( mValue.typeName(), mValue.toString() );
488 ret += QLatin1String(
"DISTINCT " );
489 if ( !mTableName.isEmpty() )
515 ret += mColumnNode->dump();
516 if ( !mAlias.isEmpty() )
518 ret += QLatin1String(
" AS " );
541 if ( !mAlias.isEmpty() )
543 ret += QLatin1String(
" AS " );
563 qDeleteAll( mTableList );
564 qDeleteAll( mColumns );
565 qDeleteAll( mJoins );
567 qDeleteAll( mOrderBy );
572 QString ret = QStringLiteral(
"SELECT " );
574 ret += QLatin1String(
"DISTINCT " );
575 bool bFirstColumn =
true;
579 ret += QLatin1String(
", " );
580 bFirstColumn =
false;
581 ret += column->
dump();
583 ret += QLatin1String(
" FROM " );
584 bool bFirstTable =
true;
588 ret += QLatin1String(
", " );
590 ret += table->
dump();
599 ret += QLatin1String(
" WHERE " );
600 ret += mWhere->dump();
602 if ( !mOrderBy.isEmpty() )
604 ret += QLatin1String(
" ORDER BY " );
609 ret += QLatin1String(
", " );
611 ret += orderBy->
dump();
619 QList<QgsSQLStatement::NodeSelectedColumn *> newColumnList;
622 newColumnList.push_back( column->
cloneThis() );
624 QList<QgsSQLStatement::NodeTableDef *> newTableList;
627 newTableList.push_back( table->
cloneThis() );
636 newSelect->
setWhere( mWhere->clone() );
638 QList<QgsSQLStatement::NodeColumnSorted *> newOrderByList;
641 newOrderByList.push_back( columnSorted->
cloneThis() );
655 ret += QLatin1String(
" " );
657 ret += QLatin1String(
"JOIN " );
658 ret += mTableDef->dump();
661 ret += QLatin1String(
" ON " );
662 ret += mOnExpr->dump();
666 ret += QLatin1String(
" USING (" );
668 Q_FOREACH ( QString column, mUsingColumns )
671 ret += QLatin1String(
", " );
675 ret += QLatin1String(
")" );
688 return new NodeJoin( mTableDef->cloneThis(), mOnExpr->clone(), mType );
690 return new NodeJoin( mTableDef->cloneThis(), mUsingColumns, mType );
698 ret = mColumn->dump();
700 ret += QLatin1String(
" DESC" );
718 QString ret( QStringLiteral(
"CAST(" ) );
719 ret += mNode->dump();
720 ret += QLatin1String(
" AS " );
728 return new NodeCast( mNode->clone(), mType );
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
QString name() const
The name of the column.
QString parserErrorString() const
Returns parser error.
static const char * JOIN_TYPE_TEXT[]
QString alias() const
Table alias.
void setOrderBy(const QList< QgsSQLStatement::NodeColumnSorted * > &orderBy)
Sets order by columns.
void appendJoin(QgsSQLStatement::NodeJoin *join)
Append a join.
Function with a name and arguments node.
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
void accept(QgsSQLStatement::Visitor &v) const
Accept visitor.
virtual QString dump() const
Dump list.
QString dump() const override
Abstract virtual dump method.
static const char * BINARY_OPERATOR_TEXT[]
void acceptVisitor(QgsSQLStatement::Visitor &v) const
Entry function for the visitor pattern.
QList< QgsSQLStatement::NodeSelectedColumn * > columns() const
Returns the list of columns.
void visit(const QgsSQLStatement::NodeColumnRef &n) override
Visit NodeColumnRef.
QString statement() const
Returns the original, unmodified statement string.
const QgsSQLStatement::Node * rootNode() const
Returns root node of the statement. Root node is null is parsing has failed.
QString dump() const override
Abstract virtual dump method.
Binary logical/arithmetical operator (AND, OR, =, +, ...)
static QString quotedString(QString text)
Returns a quoted version of a string (in single quotes)
QString dump() const override
Abstract virtual dump method.
QgsSQLStatement::NodeTableDef * tableDef() const
Table definition.
QString dump() const
Returns the statement string, constructed from the internal abstract syntax tree. ...
QgsSQLStatement::Node * mRootNode
void accept(QgsSQLStatement::Visitor &v) const override
Support the visitor pattern.
void setWhere(QgsSQLStatement::Node *where)
Sets where clause.
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
A visitor that recursively explores all children.
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
void accept(QgsSQLStatement::Visitor &v) const override
Support the visitor pattern.
Class for parsing SQL statements.
bool doBasicValidationChecks(QString &errorMsgOut) const
Performs basic validity checks.
QString dump() const override
Abstract virtual dump method.
QPair< QString, QString > TableColumnPair
virtual QString dump() const =0
Abstract virtual dump method.
virtual QgsSQLStatement::Node * clone() const =0
Generate a clone of this node.
void accept(QgsSQLStatement::Visitor &v) const override
Support the visitor pattern.
QString dump() const override
Abstract virtual dump method.
QgsSQLStatement::UnaryOperator op() const
Operator.
QgsSQLStatement::NodeList * clone() const
Creates a deep copy of this list. Ownership is transferred to the caller.
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
Literal value (integer, integer64, double, string)
QString dump() const override
Abstract virtual dump method.
QgsSQLStatement::NodeJoin * cloneThis() const
Clone with same type return.
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
void setAlias(const QString &alias)
Sets alias name.
Unary logicial/arithmetical operator ( NOT, - )
QString dump() const override
Abstract virtual dump method.
QString dump() const override
Abstract virtual dump method.
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
QList< QgsSQLStatement::NodeColumnSorted * > orderBy() const
Returns the list of order by columns.
QSet< TableColumnPair > tableNamesReferenced
'X BETWEEN y and z' operator
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
QgsSQLStatement::NodeColumnSorted * cloneThis() const
Clone with same type return.
QList< QgsSQLStatement::NodeJoin * > joins() const
Returns the list of joins.
int precedence() const
Precedence.
void accept(QgsSQLStatement::Visitor &v) const override
Support the visitor pattern.
QgsSQLStatement & operator=(const QgsSQLStatement &other)
Create a copy of this statement.
QgsSQLStatement::NodeTableDef * cloneThis() const
Clone with same type return.
static QString stripQuotedIdentifier(QString text)
Remove double quotes from an identifier.
virtual void accept(QgsSQLStatement::Visitor &v) const =0
Support the visitor pattern.
QgsSQLStatement::NodeSelectedColumn * cloneThis() const
Clone with same type return.
QString dump() const override
Abstract virtual dump method.
void setDistinct(bool distinct=true)
Sets whether this is prefixed by DISTINCT.
QString dump() const override
Abstract virtual dump method.
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
static QString quotedIdentifierIfNeeded(const QString &name)
Returns a quoted column reference (in double quotes) if needed, or otherwise the original string...
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
void visit(const QgsSQLStatement::NodeUnaryOperator &n) override
Visit NodeUnaryOperator.
static const char * UNARY_OPERATOR_TEXT[]
Support for visitor pattern - algorithms dealing with the statement may be implemented without modify...
QSet< QString > tableNamesDeclared
QgsSQLStatement::Node * where() const
Returns the where clause.
QString name() const
Table name.
QList< QgsSQLStatement::NodeTableDef * > tables() const
Returns the list of tables.
QString dump() const override
Abstract virtual dump method.
QgsSQLStatement::Node * clone() const override
Generate a clone of this node.
QgsSQLStatement::Node * onExpr() const
On expression. Will be nullptr if usingColumns() is not empty.
QString dump() const override
Abstract virtual dump method.
QString dump() const override
Abstract virtual dump method.
static QString quotedIdentifier(QString name)
Returns a quoted column reference (in double quotes)
QgsSQLStatement::NodeColumnRef * cloneThis() const
Clone with same type return.
bool hasParserError() const
Returns true if an error occurred when parsing the input statement.
QgsSQLStatement::Node * parse(const QString &str, QString &parserErrorMsg)
bool leftAssociative() const
Is left associative ?
'x IN (y, z)' operator
QString tableName() const
The name of the table. May be empty.
QgsSQLStatement(const QString &statement)
Creates a new statement based on the provided string.
QString mParserErrorString