1 /***************************************************************************
2 qgssqlstatement.h
3 ---------------------
4 begin : April 2016
5 copyright : (C) 2011 by Martin Dobias
6 copyright : (C) 2016 by Even Rouault
7 email : even.rouault at spatialys.com
8 ***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
17 #ifndef QGSSQLSTATEMENT_H
18 #define QGSSQLSTATEMENT_H
19
20 #include <QCoreApplication>
21 #include "qgis_sip.h"
22 #include <QMetaType>
23 #include <QStringList>
24 #include <QVariant>
25 #include <QList>
26 #include <QSet>
27
28 #include "qgis_core.h"
29
30 /**
31 * \ingroup core
32 * \brief Class for parsing SQL statements.
33 * \since QGIS 2.16
34 */
35 class CORE_EXPORT QgsSQLStatement
36 {
37 Q_DECLARE_TR_FUNCTIONS( QgsSQLStatement )
38 public:
39
40 /**
41 * Creates a new statement based on the provided string.
42 */
43 QgsSQLStatement( const QString &statement );
44
45 /**
46 * Create a copy of this statement.
47 */
48 QgsSQLStatement( const QgsSQLStatement &other );
49
50 /**
51 * Create a copy of this statement.
52 */
53 QgsSQLStatement &operator=( const QgsSQLStatement &other );
54 virtual ~QgsSQLStatement();
55
56 //! Returns TRUE if an error occurred when parsing the input statement
57 bool hasParserError() const;
58 //! Returns parser error
59 QString parserErrorString() const;
60
61 /**
62 * Performs basic validity checks. Basically checking that columns referencing
63 * a table, references a specified table. Returns TRUE if the validation is
64 * successful
65 */
66 bool doBasicValidationChecks( QString &errorMsgOut SIP_OUT ) const;
67
68 class Node;
69
70 /**
71 * Returns the root node of the statement.
72 * The root node is NULLPTR if parsing has failed.
73 */
74 const QgsSQLStatement::Node *rootNode() const;
75
76 /**
77 * Returns the original, unmodified statement string.
78 * If there was none supplied because it was constructed by sole
79 * API calls, dump() will be used to create one instead.
80 */
81 QString statement() const;
82
83 /**
84 * Returns the statement string, constructed from the internal
85 * abstract syntax tree. This does not contain any nice whitespace
86 * formatting or comments. In general it is preferable to use
87 * statement() instead.
88 */
89 QString dump() const;
90
91 /**
92 * Returns a quoted column reference (in double quotes)
93 * \see quotedString(), quotedIdentifierIfNeeded()
94 */
95 static QString quotedIdentifier( QString name );
96
97 /**
98 * Returns a quoted column reference (in double quotes) if needed, or
99 * otherwise the original string.
100 * \see quotedString(), quotedIdentifier()
101 */
102 static QString quotedIdentifierIfNeeded( const QString &name );
103
104 /**
105 * Remove double quotes from an identifier.
106 * \see quotedIdentifier()
107 */
108 static QString stripQuotedIdentifier( QString text );
109
110 /**
111 * Remove double quotes from an Microsoft style identifier.
112 * \see quotedIdentifier()
113 */
114 static QString stripMsQuotedIdentifier( QString text );
115
116 /**
117 * Returns a quoted version of a string (in single quotes)
118 * \see quotedIdentifier(), quotedIdentifierIfNeeded()
119 */
120 static QString quotedString( QString text );
121
122 /**
123 * \brief list of unary operators
124 * \note if any change is made here, the definition of QgsSQLStatement::UnaryOperatorText[] must be adapted.
125 */
126 enum UnaryOperator
127 {
128 uoNot,
129 uoMinus,
130 };
131
132 /**
133 * \brief list of binary operators
134 * \note if any change is made here, the definition of QgsSQLStatement::BinaryOperatorText[] must be adapted.
135 */
136 enum BinaryOperator
137 {
138 // logical
139 boOr,
140 boAnd,
141
142 // comparison
143 boEQ, // =
144 boNE, // <>
145 boLE, // <=
146 boGE, // >=
147 boLT, // <
148 boGT, // >
149 boLike,
150 boNotLike,
151 boILike,
152 boNotILike,
153 boIs,
154 boIsNot,
155
156 // math
157 boPlus,
158 boMinus,
159 boMul,
160 boDiv,
161 boIntDiv,
162 boMod,
163 boPow,
164
165 // strings
166 boConcat,
167 };
168
169 /**
170 * \brief list of join types
171 * \note if any change is made here, the definition of QgsSQLStatement::JoinTypeText[] must be adapted.
172 */
173 enum JoinType
174 {
175 jtDefault,
176 jtLeft,
177 jtLeftOuter,
178 jtRight,
179 jtRightOuter,
180 jtCross,
181 jtInner,
182 jtFull
183 };
184
185 //! \note not available in Python bindings
186 static const char *BINARY_OPERATOR_TEXT[] SIP_SKIP;
187
188 //! \note not available in Python bindings
189 static const char *UNARY_OPERATOR_TEXT[] SIP_SKIP;
190
191 //! \note not available in Python bindings
192 static const char *JOIN_TYPE_TEXT[] SIP_SKIP;
193
194 //////
195
196 class Visitor; // visitor interface is defined below
197
198 //! Node type
199 enum NodeType
200 {
201 ntUnaryOperator,
202 ntBinaryOperator,
203 ntInOperator,
204 ntBetweenOperator,
205 ntFunction,
206 ntLiteral,
207 ntColumnRef,
208 ntSelectedColumn,
209 ntSelect,
210 ntTableDef,
211 ntJoin,
212 ntColumnSorted,
213 ntCast
214 };
215
216 /**
217 * \ingroup core
218 * \brief Abstract node class
219 */
220 class CORE_EXPORT Node
221 {
222
223 #ifdef SIP_RUN
224 SIP_CONVERT_TO_SUBCLASS_CODE
225 switch ( sipCpp->nodeType() )
226 {
227 case QgsSQLStatement::ntUnaryOperator: sipType = sipType_QgsSQLStatement_NodeUnaryOperator; break;
228 case QgsSQLStatement::ntBinaryOperator: sipType = sipType_QgsSQLStatement_NodeBinaryOperator; break;
229 case QgsSQLStatement::ntInOperator: sipType = sipType_QgsSQLStatement_NodeInOperator; break;
230 case QgsSQLStatement::ntBetweenOperator: sipType = sipType_QgsSQLStatement_NodeBetweenOperator; break;
231 case QgsSQLStatement::ntFunction: sipType = sipType_QgsSQLStatement_NodeFunction; break;
232 case QgsSQLStatement::ntLiteral: sipType = sipType_QgsSQLStatement_NodeLiteral; break;
233 case QgsSQLStatement::ntColumnRef: sipType = sipType_QgsSQLStatement_NodeColumnRef; break;
234 case QgsSQLStatement::ntSelectedColumn: sipType = sipType_QgsSQLStatement_NodeSelectedColumn; break;
235 case QgsSQLStatement::ntSelect: sipType = sipType_QgsSQLStatement_NodeSelect; break;
236 case QgsSQLStatement::ntTableDef: sipType = sipType_QgsSQLStatement_NodeTableDef; break;
237 case QgsSQLStatement::ntJoin: sipType = sipType_QgsSQLStatement_NodeJoin; break;
238 case QgsSQLStatement::ntColumnSorted: sipType = sipType_QgsSQLStatement_NodeColumnSorted; break;
239 case QgsSQLStatement::ntCast: sipType = sipType_QgsSQLStatement_NodeCast; break;
240 default: sipType = 0; break;
241 }
242 SIP_END
243 #endif
244
245 public:
246 virtual ~Node() = default;
247
248 /**
249 * Abstract virtual that returns the type of this node.
250 *
251 * \returns The type of this node
252 */
253 virtual QgsSQLStatement::NodeType nodeType() const = 0;
254
255 /**
256 * Abstract virtual dump method
257 *
258 * \returns A statement which represents this node as string
259 */
260 virtual QString dump() const = 0;
261
262 /**
263 * Generate a clone of this node.
264 * Make sure that the clone does not contain any information which is
265 * generated in prepare and context related.
266 * Ownership is transferred to the caller.
267 *
268 * \returns a deep copy of this node.
269 */
270 virtual QgsSQLStatement::Node *clone() const = 0 SIP_FACTORY;
271
272 /**
273 * Support the visitor pattern.
274 *
275 * For any implementation this should look like
276 *
277 * C++:
278 *
279 * v.visit( *this );
280 *
281 * Python:
282 *
283 * v.visit( self)
284 *
285 * \param v A visitor that visits this node.
286 */
287 virtual void accept( QgsSQLStatement::Visitor &v ) const = 0;
288 };
289
290 /**
291 * A list of nodes.
292 * \ingroup core
293 */
294 class CORE_EXPORT NodeList
295 {
296 public:
297 //! Constructor
298 NodeList() = default;
~NodeList()299 virtual ~NodeList() { qDeleteAll( mList ); }
300
301 //! Takes ownership of the provided node
append(QgsSQLStatement::Node * node SIP_TRANSFER)302 void append( QgsSQLStatement::Node *node SIP_TRANSFER ) { mList.append( node ); }
303
304 //! Returns list
list()305 QList<QgsSQLStatement::Node *> list() { return mList; }
306
307 /**
308 * Returns the number of nodes in the list.
309 */
count()310 int count() const { return mList.count(); }
311
312 //! Accept visitor
313 void accept( QgsSQLStatement::Visitor &v ) const;
314
315 //! Creates a deep copy of this list. Ownership is transferred to the caller
316 QgsSQLStatement::NodeList *clone() const SIP_FACTORY;
317
318 //! Dump list
319 virtual QString dump() const;
320
321 protected:
322 QList<Node *> mList;
323 };
324
325 /**
326 * \ingroup core
327 * \brief Unary logicial/arithmetical operator ( NOT, - )
328 */
329 class CORE_EXPORT NodeUnaryOperator : public QgsSQLStatement::Node
330 {
331 public:
332 //! Constructor
NodeUnaryOperator(QgsSQLStatement::UnaryOperator op,QgsSQLStatement::Node * operand SIP_TRANSFER)333 NodeUnaryOperator( QgsSQLStatement::UnaryOperator op, QgsSQLStatement::Node *operand SIP_TRANSFER ) : mOp( op ), mOperand( operand ) {}
~NodeUnaryOperator()334 ~NodeUnaryOperator() override { delete mOperand; }
335
336 //! Operator
op()337 QgsSQLStatement::UnaryOperator op() const { return mOp; }
338
339 //! Operand
operand()340 QgsSQLStatement::Node *operand() const { return mOperand; }
341
nodeType()342 QgsSQLStatement::NodeType nodeType() const override { return ntUnaryOperator; }
343 QString dump() const override;
344
accept(QgsSQLStatement::Visitor & v)345 void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
346 QgsSQLStatement::Node *clone() const override SIP_FACTORY;
347
348 protected:
349 UnaryOperator mOp;
350 Node *mOperand = nullptr;
351 };
352
353 /**
354 * \ingroup core
355 * \brief Binary logical/arithmetical operator (AND, OR, =, +, ...)
356 */
357 class CORE_EXPORT NodeBinaryOperator : public QgsSQLStatement::Node
358 {
359 public:
360 //! Constructor
NodeBinaryOperator(QgsSQLStatement::BinaryOperator op,QgsSQLStatement::Node * opLeft SIP_TRANSFER,QgsSQLStatement::Node * opRight SIP_TRANSFER)361 NodeBinaryOperator( QgsSQLStatement::BinaryOperator op, QgsSQLStatement::Node *opLeft SIP_TRANSFER, QgsSQLStatement::Node *opRight SIP_TRANSFER )
362 : mOp( op )
363 , mOpLeft( opLeft )
364 , mOpRight( opRight )
365 {}
~NodeBinaryOperator()366 ~NodeBinaryOperator() override { delete mOpLeft; delete mOpRight; }
367
368 //! Operator
op()369 QgsSQLStatement::BinaryOperator op() const { return mOp; }
370
371 //! Left operand
opLeft()372 QgsSQLStatement::Node *opLeft() const { return mOpLeft; }
373
374 //! Right operand
opRight()375 QgsSQLStatement::Node *opRight() const { return mOpRight; }
376
nodeType()377 QgsSQLStatement::NodeType nodeType() const override { return ntBinaryOperator; }
378 QString dump() const override;
379
accept(QgsSQLStatement::Visitor & v)380 void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
381 QgsSQLStatement::Node *clone() const override SIP_FACTORY;
382
383 //! Precedence
384 int precedence() const;
385
386 //! Is left associative ?
387 bool leftAssociative() const;
388
389 protected:
390
391 BinaryOperator mOp;
392 Node *mOpLeft = nullptr;
393 Node *mOpRight = nullptr;
394 };
395
396 /**
397 * \ingroup core
398 * \brief 'x IN (y, z)' operator
399 */
400 class CORE_EXPORT NodeInOperator : public QgsSQLStatement::Node
401 {
402 public:
403 //! Constructor
mNode(node)404 NodeInOperator( QgsSQLStatement::Node *node SIP_TRANSFER, QgsSQLStatement::NodeList *list SIP_TRANSFER, bool notin = false ) : mNode( node ), mList( list ), mNotIn( notin ) {}
~NodeInOperator()405 ~NodeInOperator() override { delete mNode; delete mList; }
406
407 //! Variable at the left of IN
node()408 QgsSQLStatement::Node *node() const { return mNode; }
409
410 //! Whether this is a NOT IN operator
isNotIn()411 bool isNotIn() const { return mNotIn; }
412
413 //! Values list
list()414 QgsSQLStatement::NodeList *list() const { return mList; }
415
nodeType()416 QgsSQLStatement::NodeType nodeType() const override { return ntInOperator; }
417 QString dump() const override;
418
accept(QgsSQLStatement::Visitor & v)419 void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
420 QgsSQLStatement::Node *clone() const override SIP_FACTORY;
421
422 protected:
423 Node *mNode = nullptr;
424 NodeList *mList = nullptr;
425 bool mNotIn;
426 };
427
428 /**
429 * \ingroup core
430 * \brief 'X BETWEEN y and z' operator
431 */
432 class CORE_EXPORT NodeBetweenOperator : public QgsSQLStatement::Node
433 {
434 public:
435 //! Constructor
436 NodeBetweenOperator( QgsSQLStatement::Node *node SIP_TRANSFER, QgsSQLStatement::Node *minVal SIP_TRANSFER, QgsSQLStatement::Node *maxVal SIP_TRANSFER, bool notBetween = false )
mNode(node)437 : mNode( node ), mMinVal( minVal ), mMaxVal( maxVal ), mNotBetween( notBetween ) {}
~NodeBetweenOperator()438 ~NodeBetweenOperator() override { delete mNode; delete mMinVal; delete mMaxVal; }
439
440 //! Variable at the left of BETWEEN
node()441 QgsSQLStatement::Node *node() const { return mNode; }
442
443 //! Whether this is a NOT BETWEEN operator
isNotBetween()444 bool isNotBetween() const { return mNotBetween; }
445
446 //! Minimum bound
minVal()447 QgsSQLStatement::Node *minVal() const { return mMinVal; }
448
449 //! Maximum bound
maxVal()450 QgsSQLStatement::Node *maxVal() const { return mMaxVal; }
451
nodeType()452 QgsSQLStatement::NodeType nodeType() const override { return ntBetweenOperator; }
453 QString dump() const override;
454
accept(QgsSQLStatement::Visitor & v)455 void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
456 QgsSQLStatement::Node *clone() const override SIP_FACTORY;
457
458 protected:
459 Node *mNode = nullptr;
460 Node *mMinVal = nullptr;
461 Node *mMaxVal = nullptr;
462 bool mNotBetween;
463 };
464
465 /**
466 * \ingroup core
467 * \brief Function with a name and arguments node
468 */
469 class CORE_EXPORT NodeFunction : public QgsSQLStatement::Node
470 {
471 public:
472 //! Constructor
NodeFunction(const QString & name,QgsSQLStatement::NodeList * args SIP_TRANSFER)473 NodeFunction( const QString &name, QgsSQLStatement::NodeList *args SIP_TRANSFER ) : mName( name ), mArgs( args ) {}
~NodeFunction()474 ~NodeFunction() override { delete mArgs; }
475
476 //! Returns function name
name()477 QString name() const { return mName; }
478
479 //! Returns arguments
args()480 QgsSQLStatement::NodeList *args() const { return mArgs; }
481
nodeType()482 QgsSQLStatement::NodeType nodeType() const override { return ntFunction; }
483 QString dump() const override;
484
accept(QgsSQLStatement::Visitor & v)485 void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
486 QgsSQLStatement::Node *clone() const override SIP_FACTORY;
487
488 protected:
489 QString mName;
490 NodeList *mArgs = nullptr;
491
492 };
493
494 /**
495 * \ingroup core
496 * \brief Literal value (integer, integer64, double, string)
497 */
498 class CORE_EXPORT NodeLiteral : public QgsSQLStatement::Node
499 {
500 public:
501 //! Constructor
NodeLiteral(const QVariant & value)502 NodeLiteral( const QVariant &value ) : mValue( value ) {}
503
504 //! The value of the literal.
value()505 inline QVariant value() const { return mValue; }
506
nodeType()507 QgsSQLStatement::NodeType nodeType() const override { return ntLiteral; }
508 QString dump() const override;
509
accept(QgsSQLStatement::Visitor & v)510 void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
511 QgsSQLStatement::Node *clone() const override SIP_FACTORY;
512
513 protected:
514 QVariant mValue;
515 };
516
517 /**
518 * \ingroup core
519 * \brief Reference to a column
520 */
521 class CORE_EXPORT NodeColumnRef : public QgsSQLStatement::Node
522 {
523 public:
524 //! Constructor with column name only
NodeColumnRef(const QString & name,bool star)525 NodeColumnRef( const QString &name, bool star ) : mName( name ), mDistinct( false ), mStar( star ) {}
526 //! Constructor with table and column name
NodeColumnRef(const QString & tableName,const QString & name,bool star)527 NodeColumnRef( const QString &tableName, const QString &name, bool star ) : mTableName( tableName ), mName( name ), mDistinct( false ), mStar( star ) {}
528
529 //! Sets whether this is prefixed by DISTINCT
530 void setDistinct( bool distinct = true ) { mDistinct = distinct; }
531
532 //! The name of the table. May be empty.
tableName()533 QString tableName() const { return mTableName; }
534
535 //! The name of the column.
name()536 QString name() const { return mName; }
537
538 //! Whether this is the * column
star()539 bool star() const { return mStar; }
540
541 //! Whether this is prefixed by DISTINCT
distinct()542 bool distinct() const { return mDistinct; }
543
nodeType()544 QgsSQLStatement::NodeType nodeType() const override { return ntColumnRef; }
545 QString dump() const override;
546
accept(QgsSQLStatement::Visitor & v)547 void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
548 QgsSQLStatement::Node *clone() const override SIP_FACTORY;
549 //! Clone with same type return
550 QgsSQLStatement::NodeColumnRef *cloneThis() const SIP_FACTORY;
551
552 protected:
553 QString mTableName;
554 QString mName;
555 bool mDistinct;
556 bool mStar;
557 };
558
559 /**
560 * \ingroup core
561 * \brief Selected column
562 */
563 class CORE_EXPORT NodeSelectedColumn : public QgsSQLStatement::Node
564 {
565 public:
566 //! Constructor
NodeSelectedColumn(QgsSQLStatement::Node * node SIP_TRANSFER)567 NodeSelectedColumn( QgsSQLStatement::Node *node SIP_TRANSFER ) : mColumnNode( node ) {}
~NodeSelectedColumn()568 ~NodeSelectedColumn() override { delete mColumnNode; }
569
570 //! Sets alias name
setAlias(const QString & alias)571 void setAlias( const QString &alias ) { mAlias = alias; }
572
573 //! Column that is referred to
column()574 QgsSQLStatement::Node *column() const { return mColumnNode; }
575
576 //! Alias name
alias()577 QString alias() const { return mAlias; }
578
nodeType()579 QgsSQLStatement::NodeType nodeType() const override { return ntSelectedColumn; }
580 QString dump() const override;
581
accept(QgsSQLStatement::Visitor & v)582 void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
583 QgsSQLStatement::Node *clone() const override SIP_FACTORY;
584 //! Clone with same type return
585 QgsSQLStatement::NodeSelectedColumn *cloneThis() const SIP_FACTORY;
586
587 protected:
588 Node *mColumnNode = nullptr;
589 QString mAlias;
590 };
591
592 /**
593 * \ingroup core
594 * \brief CAST operator
595 */
596 class CORE_EXPORT NodeCast : public QgsSQLStatement::Node
597 {
598 public:
599 //! Constructor
NodeCast(QgsSQLStatement::Node * node SIP_TRANSFER,const QString & type)600 NodeCast( QgsSQLStatement::Node *node SIP_TRANSFER, const QString &type ) : mNode( node ), mType( type ) {}
~NodeCast()601 ~NodeCast() override { delete mNode; }
602
603 //! Node that is referred to
node()604 QgsSQLStatement::Node *node() const { return mNode; }
605
606 //! Type
type()607 QString type() const { return mType; }
608
nodeType()609 QgsSQLStatement::NodeType nodeType() const override { return ntCast; }
610 QString dump() const override;
611
accept(QgsSQLStatement::Visitor & v)612 void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
613 QgsSQLStatement::Node *clone() const override SIP_FACTORY;
614
615 protected:
616 Node *mNode = nullptr;
617 QString mType;
618 };
619
620 /**
621 * \ingroup core
622 * \brief Table definition
623 */
624 class CORE_EXPORT NodeTableDef : public QgsSQLStatement::Node
625 {
626 public:
627 //! Constructor with table name
NodeTableDef(const QString & name)628 NodeTableDef( const QString &name ) : mName( name ) {}
629 //! Constructor with table name and alias
NodeTableDef(const QString & name,const QString & alias)630 NodeTableDef( const QString &name, const QString &alias ) : mName( name ), mAlias( alias ) {}
631
632 //! Table name
name()633 QString name() const { return mName; }
634
635 //! Table alias
alias()636 QString alias() const { return mAlias; }
637
nodeType()638 QgsSQLStatement::NodeType nodeType() const override { return ntTableDef; }
639 QString dump() const override;
640
accept(QgsSQLStatement::Visitor & v)641 void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
642 QgsSQLStatement::Node *clone() const override SIP_FACTORY;
643 //! Clone with same type return
644 QgsSQLStatement::NodeTableDef *cloneThis() const SIP_FACTORY;
645
646 protected:
647 QString mName;
648 QString mAlias;
649 };
650
651 /**
652 * \ingroup core
653 * \brief Join definition
654 */
655 class CORE_EXPORT NodeJoin : public QgsSQLStatement::Node
656 {
657 public:
658 //! Constructor with table definition, ON expression
NodeJoin(QgsSQLStatement::NodeTableDef * tabledef SIP_TRANSFER,QgsSQLStatement::Node * onExpr SIP_TRANSFER,QgsSQLStatement::JoinType type)659 NodeJoin( QgsSQLStatement::NodeTableDef *tabledef SIP_TRANSFER, QgsSQLStatement::Node *onExpr SIP_TRANSFER, QgsSQLStatement::JoinType type ) : mTableDef( tabledef ), mOnExpr( onExpr ), mType( type ) {}
660 //! Constructor with table definition and USING columns
NodeJoin(QgsSQLStatement::NodeTableDef * tabledef SIP_TRANSFER,const QList<QString> & usingColumns,QgsSQLStatement::JoinType type)661 NodeJoin( QgsSQLStatement::NodeTableDef *tabledef SIP_TRANSFER, const QList<QString> &usingColumns, QgsSQLStatement::JoinType type ) : mTableDef( tabledef ), mUsingColumns( usingColumns ), mType( type ) {}
~NodeJoin()662 ~NodeJoin() override { delete mTableDef; delete mOnExpr; }
663
664 //! Table definition
tableDef()665 QgsSQLStatement::NodeTableDef *tableDef() const { return mTableDef; }
666
667 //! On expression. Will be NULLPTR if usingColumns() is not empty
onExpr()668 QgsSQLStatement::Node *onExpr() const { return mOnExpr; }
669
670 //! Columns referenced by USING
usingColumns()671 QList<QString> usingColumns() const { return mUsingColumns; }
672
673 //! Join type
type()674 QgsSQLStatement::JoinType type() const { return mType; }
675
nodeType()676 QgsSQLStatement::NodeType nodeType() const override { return ntJoin; }
677 QString dump() const override;
678
accept(QgsSQLStatement::Visitor & v)679 void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
680 QgsSQLStatement::Node *clone() const override SIP_FACTORY;
681 //! Clone with same type return
682 QgsSQLStatement::NodeJoin *cloneThis() const SIP_FACTORY;
683
684 protected:
685 NodeTableDef *mTableDef = nullptr;
686 Node *mOnExpr = nullptr;
687 QList<QString> mUsingColumns;
688 JoinType mType;
689 };
690
691 /**
692 * \ingroup core
693 * \brief Column in a ORDER BY
694 */
695 class CORE_EXPORT NodeColumnSorted : public QgsSQLStatement::Node
696 {
697 public:
698 //! Constructor
NodeColumnSorted(QgsSQLStatement::NodeColumnRef * column SIP_TRANSFER,bool asc)699 NodeColumnSorted( QgsSQLStatement::NodeColumnRef *column SIP_TRANSFER, bool asc ) : mColumn( column ), mAsc( asc ) {}
~NodeColumnSorted()700 ~NodeColumnSorted() override { delete mColumn; }
701
702 //! The name of the column.
column()703 QgsSQLStatement::NodeColumnRef *column() const { return mColumn; }
704
705 //! Whether the column is sorted in ascending order
ascending()706 bool ascending() const { return mAsc; }
707
nodeType()708 QgsSQLStatement::NodeType nodeType() const override { return ntColumnSorted; }
709 QString dump() const override;
710
accept(QgsSQLStatement::Visitor & v)711 void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
712 QgsSQLStatement::Node *clone() const override SIP_FACTORY;
713 //! Clone with same type return
714 QgsSQLStatement::NodeColumnSorted *cloneThis() const SIP_FACTORY;
715
716 protected:
717 NodeColumnRef *mColumn = nullptr;
718 bool mAsc;
719 };
720
721 /**
722 * \ingroup core
723 * \brief SELECT node
724 */
725 class CORE_EXPORT NodeSelect : public QgsSQLStatement::Node
726 {
727 public:
728 //! Constructor
NodeSelect(const QList<QgsSQLStatement::NodeTableDef * > & tableList SIP_TRANSFER,const QList<QgsSQLStatement::NodeSelectedColumn * > & columns SIP_TRANSFER,bool distinct)729 NodeSelect( const QList<QgsSQLStatement::NodeTableDef *> &tableList SIP_TRANSFER, const QList<QgsSQLStatement::NodeSelectedColumn *> &columns SIP_TRANSFER, bool distinct ) : mTableList( tableList ), mColumns( columns ), mDistinct( distinct ) {}
730 ~NodeSelect() override;
731
732 //! Sets joins
setJoins(const QList<QgsSQLStatement::NodeJoin * > & joins SIP_TRANSFER)733 void setJoins( const QList<QgsSQLStatement::NodeJoin *> &joins SIP_TRANSFER ) { qDeleteAll( mJoins ); mJoins = joins; }
734 //! Append a join
appendJoin(QgsSQLStatement::NodeJoin * join SIP_TRANSFER)735 void appendJoin( QgsSQLStatement::NodeJoin *join SIP_TRANSFER ) { mJoins.append( join ); }
736 //! Sets where clause
setWhere(QgsSQLStatement::Node * where SIP_TRANSFER)737 void setWhere( QgsSQLStatement::Node *where SIP_TRANSFER ) { delete mWhere; mWhere = where; }
738 //! Sets order by columns
setOrderBy(const QList<QgsSQLStatement::NodeColumnSorted * > & orderBy SIP_TRANSFER)739 void setOrderBy( const QList<QgsSQLStatement::NodeColumnSorted *> &orderBy SIP_TRANSFER ) { qDeleteAll( mOrderBy ); mOrderBy = orderBy; }
740
741 //! Returns the list of tables
tables()742 QList<QgsSQLStatement::NodeTableDef *> tables() const { return mTableList; }
743 //! Returns the list of columns
columns()744 QList<QgsSQLStatement::NodeSelectedColumn *> columns() const { return mColumns; }
745 //! Returns if the SELECT is DISTINCT
distinct()746 bool distinct() const { return mDistinct; }
747 //! Returns the list of joins
joins()748 QList<QgsSQLStatement::NodeJoin *> joins() const { return mJoins; }
749 //! Returns the where clause
where()750 QgsSQLStatement::Node *where() const { return mWhere; }
751 //! Returns the list of order by columns
orderBy()752 QList<QgsSQLStatement::NodeColumnSorted *> orderBy() const { return mOrderBy; }
753
nodeType()754 QgsSQLStatement::NodeType nodeType() const override { return ntSelect; }
755 QString dump() const override;
756
accept(QgsSQLStatement::Visitor & v)757 void accept( QgsSQLStatement::Visitor &v ) const override { v.visit( *this ); }
758 QgsSQLStatement::Node *clone() const override SIP_FACTORY;
759
760 protected:
761 QList<NodeTableDef *> mTableList;
762 QList<NodeSelectedColumn *> mColumns;
763 bool mDistinct;
764 QList<NodeJoin *> mJoins;
765 Node *mWhere = nullptr;
766 QList<NodeColumnSorted *> mOrderBy;
767 };
768
769 //////
770
771 /**
772 * \ingroup core
773 * \brief Support for visitor pattern - algorithms dealing with the statement
774 * may be implemented without modifying the Node classes
775 */
776 class CORE_EXPORT Visitor
777 {
778 public:
779 virtual ~Visitor() = default;
780 //! Visit NodeUnaryOperator
781 virtual void visit( const QgsSQLStatement::NodeUnaryOperator &n ) = 0;
782 //! Visit NodeBinaryOperator
783 virtual void visit( const QgsSQLStatement::NodeBinaryOperator &n ) = 0;
784 //! Visit NodeInOperator
785 virtual void visit( const QgsSQLStatement::NodeInOperator &n ) = 0;
786 //! Visit NodeBetweenOperator
787 virtual void visit( const QgsSQLStatement::NodeBetweenOperator &n ) = 0;
788 //! Visit NodeFunction
789 virtual void visit( const QgsSQLStatement::NodeFunction &n ) = 0;
790 //! Visit NodeLiteral
791 virtual void visit( const QgsSQLStatement::NodeLiteral &n ) = 0;
792 //! Visit NodeColumnRef
793 virtual void visit( const QgsSQLStatement::NodeColumnRef &n ) = 0;
794 //! Visit NodeSelectedColumn
795 virtual void visit( const QgsSQLStatement::NodeSelectedColumn &n ) = 0;
796 //! Visit NodeTableDef
797 virtual void visit( const QgsSQLStatement::NodeTableDef &n ) = 0;
798 //! Visit NodeSelect
799 virtual void visit( const QgsSQLStatement::NodeSelect &n ) = 0;
800 //! Visit NodeJoin
801 virtual void visit( const QgsSQLStatement::NodeJoin &n ) = 0;
802 //! Visit NodeColumnSorted
803 virtual void visit( const QgsSQLStatement::NodeColumnSorted &n ) = 0;
804 //! Visit NodeCast
805 virtual void visit( const QgsSQLStatement::NodeCast &n ) = 0;
806 };
807
808 /**
809 * \ingroup core
810 * \brief A visitor that recursively explores all children
811 */
812 class CORE_EXPORT RecursiveVisitor: public QgsSQLStatement::Visitor
813 {
814 public:
815 //! Constructor
816 RecursiveVisitor() = default;
817
visit(const QgsSQLStatement::NodeUnaryOperator & n)818 void visit( const QgsSQLStatement::NodeUnaryOperator &n ) override { n.operand()->accept( *this ); }
visit(const QgsSQLStatement::NodeBinaryOperator & n)819 void visit( const QgsSQLStatement::NodeBinaryOperator &n ) override { n.opLeft()->accept( *this ); n.opRight()->accept( *this ); }
visit(const QgsSQLStatement::NodeInOperator & n)820 void visit( const QgsSQLStatement::NodeInOperator &n ) override { n.node()->accept( *this ); n.list()->accept( *this ); }
visit(const QgsSQLStatement::NodeBetweenOperator & n)821 void visit( const QgsSQLStatement::NodeBetweenOperator &n ) override { n.node()->accept( *this ); n.minVal()->accept( *this ); n.maxVal()->accept( *this ); }
visit(const QgsSQLStatement::NodeFunction & n)822 void visit( const QgsSQLStatement::NodeFunction &n ) override { n.args()->accept( *this ); }
visit(const QgsSQLStatement::NodeLiteral &)823 void visit( const QgsSQLStatement::NodeLiteral & ) override {}
visit(const QgsSQLStatement::NodeColumnRef &)824 void visit( const QgsSQLStatement::NodeColumnRef & ) override { }
visit(const QgsSQLStatement::NodeSelectedColumn & n)825 void visit( const QgsSQLStatement::NodeSelectedColumn &n ) override { n.column()->accept( *this ); }
visit(const QgsSQLStatement::NodeTableDef &)826 void visit( const QgsSQLStatement::NodeTableDef & ) override {}
827 void visit( const QgsSQLStatement::NodeSelect &n ) override;
828 void visit( const QgsSQLStatement::NodeJoin &n ) override;
visit(const QgsSQLStatement::NodeColumnSorted & n)829 void visit( const QgsSQLStatement::NodeColumnSorted &n ) override { n.column()->accept( *this ); }
visit(const QgsSQLStatement::NodeCast & n)830 void visit( const QgsSQLStatement::NodeCast &n ) override { n.node()->accept( *this ); }
831 };
832
833 //! Entry function for the visitor pattern
834 void acceptVisitor( QgsSQLStatement::Visitor &v ) const;
835
836 protected:
837 QgsSQLStatement::Node *mRootNode = nullptr;
838 bool mAllowFragments = false;
839 QString mStatement;
840 QString mParserErrorString;
841
842 /**
843 * Constructor for QgsSQLStatement, with the specified \a statement.
844 *
845 * If \a allowFragments is TRUE then the parser will allow SQL fragments,
846 * such as a expression or filter where clause alone.
847 *
848 * \since QGIS 3.16
849 */
850 QgsSQLStatement( const QString &statement, bool allowFragments );
851 };
852
Q_DECLARE_METATYPE(QgsSQLStatement::Node *)853 Q_DECLARE_METATYPE( QgsSQLStatement::Node * )
854
855 /**
856 * \ingroup core
857 * \brief Class for parsing fragments of SQL statements, such as an expression or where clause.
858 * \since QGIS 3.16
859 */
860 class CORE_EXPORT QgsSQLStatementFragment : public QgsSQLStatement
861 {
862 public:
863
864 /**
865 * Constructor for QgsSQLStatementFragment of the specified \a fragment.
866 */
867 QgsSQLStatementFragment( const QString &fragment );
868
869 };
870
871
872 #endif // QGSSQLSTATEMENT_H
873