Branch data Line data Source code
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 : 0 : 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 : 0 : 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 : 0 : 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 : 0 : NodeList() = default;
299 : 0 : virtual ~NodeList() { qDeleteAll( mList ); }
300 : :
301 : : //! Takes ownership of the provided node
302 : 0 : void append( QgsSQLStatement::Node *node SIP_TRANSFER ) { mList.append( node ); }
303 : :
304 : : //! Returns list
305 : 0 : QList<QgsSQLStatement::Node *> list() { return mList; }
306 : :
307 : : /**
308 : : * Returns the number of nodes in the list.
309 : : */
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
333 : 0 : NodeUnaryOperator( QgsSQLStatement::UnaryOperator op, QgsSQLStatement::Node *operand SIP_TRANSFER ) : mOp( op ), mOperand( operand ) {}
334 : 0 : ~NodeUnaryOperator() override { delete mOperand; }
335 : :
336 : : //! Operator
337 : 0 : QgsSQLStatement::UnaryOperator op() const { return mOp; }
338 : :
339 : : //! Operand
340 : 0 : QgsSQLStatement::Node *operand() const { return mOperand; }
341 : :
342 : 0 : QgsSQLStatement::NodeType nodeType() const override { return ntUnaryOperator; }
343 : : QString dump() const override;
344 : :
345 : 0 : 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
361 : 0 : NodeBinaryOperator( QgsSQLStatement::BinaryOperator op, QgsSQLStatement::Node *opLeft SIP_TRANSFER, QgsSQLStatement::Node *opRight SIP_TRANSFER )
362 : 0 : : mOp( op )
363 : 0 : , mOpLeft( opLeft )
364 : 0 : , mOpRight( opRight )
365 : 0 : {}
366 : 0 : ~NodeBinaryOperator() override { delete mOpLeft; delete mOpRight; }
367 : :
368 : : //! Operator
369 : 0 : QgsSQLStatement::BinaryOperator op() const { return mOp; }
370 : :
371 : : //! Left operand
372 : 0 : QgsSQLStatement::Node *opLeft() const { return mOpLeft; }
373 : :
374 : : //! Right operand
375 : 0 : QgsSQLStatement::Node *opRight() const { return mOpRight; }
376 : :
377 : 0 : QgsSQLStatement::NodeType nodeType() const override { return ntBinaryOperator; }
378 : : QString dump() const override;
379 : :
380 : 0 : 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
404 : 0 : NodeInOperator( QgsSQLStatement::Node *node SIP_TRANSFER, QgsSQLStatement::NodeList *list SIP_TRANSFER, bool notin = false ) : mNode( node ), mList( list ), mNotIn( notin ) {}
405 : 0 : ~NodeInOperator() override { delete mNode; delete mList; }
406 : :
407 : : //! Variable at the left of IN
408 : 0 : QgsSQLStatement::Node *node() const { return mNode; }
409 : :
410 : : //! Whether this is a NOT IN operator
411 : 0 : bool isNotIn() const { return mNotIn; }
412 : :
413 : : //! Values list
414 : 0 : QgsSQLStatement::NodeList *list() const { return mList; }
415 : :
416 : 0 : QgsSQLStatement::NodeType nodeType() const override { return ntInOperator; }
417 : : QString dump() const override;
418 : :
419 : 0 : 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 : 0 : NodeBetweenOperator( QgsSQLStatement::Node *node SIP_TRANSFER, QgsSQLStatement::Node *minVal SIP_TRANSFER, QgsSQLStatement::Node *maxVal SIP_TRANSFER, bool notBetween = false )
437 : 0 : : mNode( node ), mMinVal( minVal ), mMaxVal( maxVal ), mNotBetween( notBetween ) {}
438 : 0 : ~NodeBetweenOperator() override { delete mNode; delete mMinVal; delete mMaxVal; }
439 : :
440 : : //! Variable at the left of BETWEEN
441 : 0 : QgsSQLStatement::Node *node() const { return mNode; }
442 : :
443 : : //! Whether this is a NOT BETWEEN operator
444 : 0 : bool isNotBetween() const { return mNotBetween; }
445 : :
446 : : //! Minimum bound
447 : 0 : QgsSQLStatement::Node *minVal() const { return mMinVal; }
448 : :
449 : : //! Maximum bound
450 : 0 : QgsSQLStatement::Node *maxVal() const { return mMaxVal; }
451 : :
452 : 0 : QgsSQLStatement::NodeType nodeType() const override { return ntBetweenOperator; }
453 : : QString dump() const override;
454 : :
455 : 0 : 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
473 : 0 : NodeFunction( const QString &name, QgsSQLStatement::NodeList *args SIP_TRANSFER ) : mName( name ), mArgs( args ) {}
474 : 0 : ~NodeFunction() override { delete mArgs; }
475 : :
476 : : //! Returns function name
477 : 0 : QString name() const { return mName; }
478 : :
479 : : //! Returns arguments
480 : 0 : QgsSQLStatement::NodeList *args() const { return mArgs; }
481 : :
482 : 0 : QgsSQLStatement::NodeType nodeType() const override { return ntFunction; }
483 : : QString dump() const override;
484 : :
485 : 0 : 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 : 0 : class CORE_EXPORT NodeLiteral : public QgsSQLStatement::Node
499 : : {
500 : : public:
501 : : //! Constructor
502 : 0 : NodeLiteral( const QVariant &value ) : mValue( value ) {}
503 : :
504 : : //! The value of the literal.
505 : 0 : inline QVariant value() const { return mValue; }
506 : :
507 : 0 : QgsSQLStatement::NodeType nodeType() const override { return ntLiteral; }
508 : : QString dump() const override;
509 : :
510 : 0 : 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 : 0 : class CORE_EXPORT NodeColumnRef : public QgsSQLStatement::Node
522 : : {
523 : : public:
524 : : //! Constructor with column name only
525 : 0 : NodeColumnRef( const QString &name, bool star ) : mName( name ), mDistinct( false ), mStar( star ) {}
526 : : //! Constructor with table and column name
527 : 0 : 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 : 0 : void setDistinct( bool distinct = true ) { mDistinct = distinct; }
531 : :
532 : : //! The name of the table. May be empty.
533 : 0 : QString tableName() const { return mTableName; }
534 : :
535 : : //! The name of the column.
536 : 0 : QString name() const { return mName; }
537 : :
538 : : //! Whether this is the * column
539 : : bool star() const { return mStar; }
540 : :
541 : : //! Whether this is prefixed by DISTINCT
542 : : bool distinct() const { return mDistinct; }
543 : :
544 : 0 : QgsSQLStatement::NodeType nodeType() const override { return ntColumnRef; }
545 : : QString dump() const override;
546 : :
547 : 0 : 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
567 : 0 : NodeSelectedColumn( QgsSQLStatement::Node *node SIP_TRANSFER ) : mColumnNode( node ) {}
568 : 0 : ~NodeSelectedColumn() override { delete mColumnNode; }
569 : :
570 : : //! Sets alias name
571 : 0 : void setAlias( const QString &alias ) { mAlias = alias; }
572 : :
573 : : //! Column that is referred to
574 : 0 : QgsSQLStatement::Node *column() const { return mColumnNode; }
575 : :
576 : : //! Alias name
577 : : QString alias() const { return mAlias; }
578 : :
579 : 0 : QgsSQLStatement::NodeType nodeType() const override { return ntSelectedColumn; }
580 : : QString dump() const override;
581 : :
582 : 0 : 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
600 : 0 : NodeCast( QgsSQLStatement::Node *node SIP_TRANSFER, const QString &type ) : mNode( node ), mType( type ) {}
601 : 0 : ~NodeCast() override { delete mNode; }
602 : :
603 : : //! Node that is referred to
604 : 0 : QgsSQLStatement::Node *node() const { return mNode; }
605 : :
606 : : //! Type
607 : : QString type() const { return mType; }
608 : :
609 : 0 : QgsSQLStatement::NodeType nodeType() const override { return ntCast; }
610 : : QString dump() const override;
611 : :
612 : 0 : 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 : 0 : class CORE_EXPORT NodeTableDef : public QgsSQLStatement::Node
625 : : {
626 : : public:
627 : : //! Constructor with table name
628 : 0 : NodeTableDef( const QString &name ) : mName( name ) {}
629 : : //! Constructor with table name and alias
630 : 0 : NodeTableDef( const QString &name, const QString &alias ) : mName( name ), mAlias( alias ) {}
631 : :
632 : : //! Table name
633 : 0 : QString name() const { return mName; }
634 : :
635 : : //! Table alias
636 : 0 : QString alias() const { return mAlias; }
637 : :
638 : 0 : QgsSQLStatement::NodeType nodeType() const override { return ntTableDef; }
639 : : QString dump() const override;
640 : :
641 : 0 : 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
659 : 0 : 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
661 : 0 : NodeJoin( QgsSQLStatement::NodeTableDef *tabledef SIP_TRANSFER, const QList<QString> &usingColumns, QgsSQLStatement::JoinType type ) : mTableDef( tabledef ), mUsingColumns( usingColumns ), mType( type ) {}
662 : 0 : ~NodeJoin() override { delete mTableDef; delete mOnExpr; }
663 : :
664 : : //! Table definition
665 : 0 : QgsSQLStatement::NodeTableDef *tableDef() const { return mTableDef; }
666 : :
667 : : //! On expression. Will be NULLPTR if usingColumns() is not empty
668 : 0 : QgsSQLStatement::Node *onExpr() const { return mOnExpr; }
669 : :
670 : : //! Columns referenced by USING
671 : 0 : QList<QString> usingColumns() const { return mUsingColumns; }
672 : :
673 : : //! Join type
674 : : QgsSQLStatement::JoinType type() const { return mType; }
675 : :
676 : 0 : QgsSQLStatement::NodeType nodeType() const override { return ntJoin; }
677 : : QString dump() const override;
678 : :
679 : 0 : 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 : 0 : 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
699 : 0 : NodeColumnSorted( QgsSQLStatement::NodeColumnRef *column SIP_TRANSFER, bool asc ) : mColumn( column ), mAsc( asc ) {}
700 : 0 : ~NodeColumnSorted() override { delete mColumn; }
701 : :
702 : : //! The name of the column.
703 : 0 : QgsSQLStatement::NodeColumnRef *column() const { return mColumn; }
704 : :
705 : : //! Whether the column is sorted in ascending order
706 : : bool ascending() const { return mAsc; }
707 : :
708 : 0 : QgsSQLStatement::NodeType nodeType() const override { return ntColumnSorted; }
709 : : QString dump() const override;
710 : :
711 : 0 : 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
729 : 0 : 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
733 : 0 : void setJoins( const QList<QgsSQLStatement::NodeJoin *> &joins SIP_TRANSFER ) { qDeleteAll( mJoins ); mJoins = joins; }
734 : : //! Append a join
735 : 0 : void appendJoin( QgsSQLStatement::NodeJoin *join SIP_TRANSFER ) { mJoins.append( join ); }
736 : : //! Sets where clause
737 : 0 : void setWhere( QgsSQLStatement::Node *where SIP_TRANSFER ) { delete mWhere; mWhere = where; }
738 : : //! Sets order by columns
739 : 0 : void setOrderBy( const QList<QgsSQLStatement::NodeColumnSorted *> &orderBy SIP_TRANSFER ) { qDeleteAll( mOrderBy ); mOrderBy = orderBy; }
740 : :
741 : : //! Returns the list of tables
742 : 0 : QList<QgsSQLStatement::NodeTableDef *> tables() const { return mTableList; }
743 : : //! Returns the list of columns
744 : 0 : QList<QgsSQLStatement::NodeSelectedColumn *> columns() const { return mColumns; }
745 : : //! Returns if the SELECT is DISTINCT
746 : : bool distinct() const { return mDistinct; }
747 : : //! Returns the list of joins
748 : 0 : QList<QgsSQLStatement::NodeJoin *> joins() const { return mJoins; }
749 : : //! Returns the where clause
750 : 0 : QgsSQLStatement::Node *where() const { return mWhere; }
751 : : //! Returns the list of order by columns
752 : 0 : QList<QgsSQLStatement::NodeColumnSorted *> orderBy() const { return mOrderBy; }
753 : :
754 : 0 : QgsSQLStatement::NodeType nodeType() const override { return ntSelect; }
755 : : QString dump() const override;
756 : :
757 : 0 : 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 : 0 : 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 : 0 : class CORE_EXPORT Visitor
777 : : {
778 : : public:
779 : 0 : 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 : 0 : class CORE_EXPORT RecursiveVisitor: public QgsSQLStatement::Visitor
813 : : {
814 : : public:
815 : : //! Constructor
816 : 0 : RecursiveVisitor() = default;
817 : :
818 : 0 : void visit( const QgsSQLStatement::NodeUnaryOperator &n ) override { n.operand()->accept( *this ); }
819 : 0 : void visit( const QgsSQLStatement::NodeBinaryOperator &n ) override { n.opLeft()->accept( *this ); n.opRight()->accept( *this ); }
820 : 0 : void visit( const QgsSQLStatement::NodeInOperator &n ) override { n.node()->accept( *this ); n.list()->accept( *this ); }
821 : 0 : void visit( const QgsSQLStatement::NodeBetweenOperator &n ) override { n.node()->accept( *this ); n.minVal()->accept( *this ); n.maxVal()->accept( *this ); }
822 : 0 : void visit( const QgsSQLStatement::NodeFunction &n ) override { n.args()->accept( *this ); }
823 : 0 : void visit( const QgsSQLStatement::NodeLiteral & ) override {}
824 : 0 : void visit( const QgsSQLStatement::NodeColumnRef & ) override { }
825 : 0 : void visit( const QgsSQLStatement::NodeSelectedColumn &n ) override { n.column()->accept( *this ); }
826 : 0 : void visit( const QgsSQLStatement::NodeTableDef & ) override {}
827 : : void visit( const QgsSQLStatement::NodeSelect &n ) override;
828 : : void visit( const QgsSQLStatement::NodeJoin &n ) override;
829 : 0 : void visit( const QgsSQLStatement::NodeColumnSorted &n ) override { n.column()->accept( *this ); }
830 : 0 : 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 : :
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 : 0 : 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
|