File indexing completed on 2024-04-14 14:53:10

0001 /* This file is part of the KDE project
0002    Copyright (C) 2003-2015 Jarosław Staniek <staniek@kde.org>
0003    Copyright (C) 2014 Radoslaw Wicik <radoslaw@wicik.pl>
0004 
0005    Design based on nexp.h : Parser module of Python-like language
0006    (C) 2001 Jarosław Staniek, MIMUW (www.mimuw.edu.pl)
0007 
0008    This library is free software; you can redistribute it and/or
0009    modify it under the terms of the GNU Library General Public
0010    License as published by the Free Software Foundation; either
0011    version 2 of the License, or (at your option) any later version.
0012 
0013    This library is distributed in the hope that it will be useful,
0014    but WITHOUT ANY WARRANTY; without even the implied warranty of
0015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0016    Library General Public License for more details.
0017 
0018    You should have received a copy of the GNU Library General Public License
0019    along with this library; see the file COPYING.LIB.  If not, write to
0020    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0021  * Boston, MA 02110-1301, USA.
0022 */
0023 
0024 #ifndef KDB_EXPRESSION_H
0025 #define KDB_EXPRESSION_H
0026 
0027 #include "KDbField.h"
0028 #include "KDbEscapedString.h"
0029 #include "KDbExpressionData.h"
0030 
0031 //! Maximum number of arguments in function
0032 //! Reasonable number, set after https://www.sqlite.org/limits.html#max_function_arg
0033 #define KDB_MAX_FUNCTION_ARGS 100
0034 
0035 //! @return class name of class @a c
0036 KDB_EXPORT QString expressionClassName(KDb::ExpressionClass c);
0037 
0038 class KDbBinaryExpression;
0039 class KDbConstExpression;
0040 class KDbFunctionExpression;
0041 class KDbNArgExpression;
0042 class KDbParseInfo;
0043 class KDbQueryParameterExpression;
0044 class KDbQuerySchemaParameter;
0045 class KDbQuerySchemaParameterValueListIterator;
0046 class KDbToken;
0047 class KDbUnaryExpression;
0048 class KDbVariableExpression;
0049 
0050 //! The KDbExpression class represents a base class for all expressions.
0051 class KDB_EXPORT KDbExpression
0052 {
0053 public:
0054     /*! Constructs a null expression.
0055       @see KDbExpression::isNull() */
0056     KDbExpression();
0057 
0058     virtual ~KDbExpression();
0059 
0060     //! @return true if this expression is null.
0061     //! Equivalent of expressionClass() == KDb::UnknownExpression.
0062     //! @note Returns false for expressions of type KDbField::Null (SQL's NULL).
0063     bool isNull() const;
0064 
0065     //! Creates a deep (not shallow) copy of the KDbExpression.
0066     KDbExpression clone() const;
0067 
0068     /*!
0069     @return the token for this expression. Tokens are characters (e.g. '+', '-')
0070     or identifiers (e.g. SQL_NULL) of elements used by the KDbSQL parser.
0071     By default token is 0.
0072     */
0073     KDbToken token() const;
0074 
0075     /*! Sets token @a token for this expression. */
0076     void setToken(KDbToken token);
0077 
0078     /*!
0079     @return class identifier of this expression.
0080     Default expressionClass is KDb::UnknownExpression.
0081     */
0082     KDb::ExpressionClass expressionClass() const;
0083 
0084     /*! Sets expression class @a aClass for this expression. */
0085     void setExpressionClass(KDb::ExpressionClass aClass);
0086 
0087     /*! @return type of this expression, based on effect of its evaluation.
0088      Default type is KDbField::InvalidType. @see isValid() */
0089     KDbField::Type type() const;
0090 
0091     //! @return true if type of this object is not KDbField::InvalidType.
0092     /*! A covenience method. @see type() */
0093     bool isValid() const;
0094 
0095     //! @return true if type of this object belong to a group of text types.
0096     /*! A covenience method. @see type() */
0097     bool isTextType() const;
0098 
0099     //! \return true if type of this object belong to a group of integer types.
0100     /*! A covenience method. @see type() */
0101     bool isIntegerType() const;
0102 
0103     //! @return true if type of this object belong to a group of numeric types.
0104     /*! A covenience method. @see type() */
0105     bool isNumericType() const;
0106 
0107     //! @return true if type of this object belong to a group of floating-point numeric types.
0108     /*! A covenience method. @see type() */
0109     bool isFPNumericType() const;
0110 
0111     //! @return true if type of this object belong to a group of time, date and date/time types.
0112     /*! A covenience method. @see type() */
0113     bool isDateTimeType() const;
0114 
0115     /*! @return true if evaluation of this expression succeeded. */
0116     bool validate(KDbParseInfo *parseInfo);
0117 
0118     /*! @return string as a representation of this expression element
0119                 by running recursive calls.
0120      @a param, if not 0, points to a list item containing value
0121      of a query parameter (used in QueryParameterExpr).
0122      The result may depend on the optional @a driver parameter.
0123      If @a driver is 0, representation for portable KDbSQL dialect is returned. */
0124     KDbEscapedString toString(const KDbDriver *driver,
0125                               KDbQuerySchemaParameterValueListIterator *params = nullptr,
0126                               KDb::ExpressionCallStack *callStack = nullptr) const;
0127 
0128     /*! Collects query parameters (messages and types) recursively and saves them to @a params.
0129      The leaf nodes are objects of QueryParameterExpr class.
0130      @note @a params must not be 0. */
0131     void getQueryParameters(QList<KDbQuerySchemaParameter>* params);
0132 
0133     //! @return expression class for token @a token.
0134     //! @todo support more tokens
0135     static KDb::ExpressionClass classForToken(KDbToken token);
0136 
0137     //! Convenience type casts.
0138     KDbNArgExpression toNArg() const;
0139     KDbUnaryExpression toUnary() const;
0140     KDbBinaryExpression toBinary() const;
0141     KDbConstExpression toConst() const;
0142     KDbVariableExpression toVariable() const;
0143     KDbFunctionExpression toFunction() const;
0144     KDbQueryParameterExpression toQueryParameter() const;
0145 
0146     bool isNArg() const;
0147     bool isUnary() const;
0148     bool isBinary() const;
0149     bool isConst() const;
0150     bool isVariable() const;
0151     bool isFunction() const;
0152     bool isQueryParameter() const;
0153 
0154     QDebug debug(QDebug dbg, KDb::ExpressionCallStack* callStack) const;
0155 
0156     bool operator==(const KDbExpression& e) const;
0157 
0158     bool operator!=(const KDbExpression& e) const;
0159 
0160     /*! @return the parent expression. */
0161     KDbExpression parent() const;
0162 
0163 protected:
0164     /*! @return the list of children expressions. */
0165     QList<ExplicitlySharedExpressionDataPointer> children() const;
0166 
0167     void appendChild(const KDbExpression& child);
0168 
0169     void prependChild(const KDbExpression& child);
0170 
0171     KDbExpression takeChild(int i);
0172 
0173     bool removeChild(const KDbExpression& child);
0174 
0175     void removeChild(int i);
0176 
0177     void insertChild(int i, const KDbExpression& child);
0178 
0179     //! Used for inserting placeholders, e.g. in KDbBinaryExpression::KDbBinaryExpression()
0180     void insertEmptyChild(int i);
0181 
0182     void appendChild(const ExplicitlySharedExpressionDataPointer& child);
0183 
0184     int indexOfChild(const KDbExpression& child, int from = 0) const;
0185 
0186     int lastIndexOfChild(const KDbExpression& child, int from = -1) const;
0187 
0188     bool checkBeforeInsert(const ExplicitlySharedExpressionDataPointer& child);
0189 
0190     //! Only for KDbBinaryExpression::setLeft() and KDbBinaryExpression::setRight()
0191     void setLeftOrRight(const KDbExpression& right, int index);
0192 
0193     explicit KDbExpression(KDbExpressionData* data);
0194 
0195     KDbExpression(KDbExpressionData* data, KDb::ExpressionClass aClass, KDbToken token);
0196 
0197     explicit KDbExpression(const ExplicitlySharedExpressionDataPointer &ptr);
0198 
0199     //! @internal
0200     ExplicitlySharedExpressionDataPointer d;
0201 
0202     friend class KDbNArgExpression;
0203     friend class KDbUnaryExpression;
0204     friend class KDbBinaryExpression;
0205     friend class KDbConstExpression;
0206     friend class KDbQueryParameterExpression;
0207     friend class KDbVariableExpression;
0208     friend class KDbFunctionExpression;
0209 };
0210 
0211 //! The KDbNArgExpression class represents a base class N-argument expression.
0212 class KDB_EXPORT KDbNArgExpression : public KDbExpression
0213 {
0214 public:
0215     /*! Constructs a null N-argument expression.
0216       @see KDbExpression::isNull() */
0217     KDbNArgExpression();
0218 
0219     //! Constructs an N-argument expression of class @a aClass and token @a token.
0220     KDbNArgExpression(KDb::ExpressionClass aClass, KDbToken token);
0221 
0222     /*! Constructs a copy of other N-argument expression @a expr.
0223      Resulting object is not a deep copy but rather a reference to the object @a expr. */
0224     KDbNArgExpression(const KDbNArgExpression& expr);
0225 
0226     //! Destroys the expression.
0227     ~KDbNArgExpression() override;
0228 
0229     //! Inserts expression argument @a expr at the end of this expression.
0230     void append(const KDbExpression& expr);
0231 
0232     //! Inserts expression argument @a expr at the beginning of this expression.
0233     void prepend(const KDbExpression& expr);
0234 
0235     /*! Inserts expression argument @a expr at index position @a i in this expression.
0236      If @a i is 0, the expression is prepended to the list of arguments.
0237      If @a i is argCount(), the value is appended to the list of arguments.
0238      @a i must be a valid index position in the list (i.e., 0 <= i < argCount()). */
0239     void insert(int i, const KDbExpression& expr);
0240 
0241     //! Replaces expression argument at index @a i with expression @a expr.
0242     //! @a i must be a valid index position in the list (i.e., 0 <= i < argCount()). */
0243     void replace(int i, const KDbExpression& expr);
0244 
0245     /*! Removes the expression argument @a expr and returns true on success;
0246         otherwise returns false. */
0247     bool remove(const KDbExpression& expr);
0248 
0249     /*! Removes the expression at index position @a i.
0250      @a i must be a valid index position in the list (i.e., 0 <= i < argCount()). */
0251     void removeAt(int i);
0252 
0253     /*! Removes the expression at index position @a i and returns it.
0254       @a i must be a valid index position in the list (i.e., 0 <= i < argCount()).
0255       If you don't use the return value, removeAt() is more efficient. */
0256     KDbExpression takeAt(int i);
0257 
0258     /*! @return the index position of the first occurrence of expression argument
0259       @a expr in this expression, searching forward from index position @a from.
0260       @return -1 if no argument matched.
0261       @see lastIndexOf() */
0262     int indexOf(const KDbExpression& expr, int from = 0) const;
0263 
0264     /*! @return the index position of the last occurrence of expression argument
0265       @a expr in this expression, searching backward from index position @a from.
0266       If from is -1 (the default), the search starts at the last item.
0267       Returns -1 if no argument matched.
0268       @see indexOf() */
0269     int lastIndexOf(const KDbExpression& expr, int from = -1) const;
0270 
0271     //! @return expression index @a i in the list of arguments.
0272     //! If the index @a i is out of bounds, the function returns null expression.
0273     KDbExpression arg(int i) const;
0274 
0275     //! @return the number of expression arguments in this expression.
0276     int argCount() const;
0277 
0278     //! @return true if the expression contains no arguments; otherwise returns false.
0279     bool isEmpty() const;
0280 
0281     //! @return true if any argument is invalid (!KDbExpression::isValid()).
0282     bool containsInvalidArgument() const;
0283 
0284     //! @return true if any argument is NULL (type KDbField::Null).
0285     bool containsNullArgument() const;
0286 
0287 protected:
0288     explicit KDbNArgExpression(KDbExpressionData* data);
0289 
0290     explicit KDbNArgExpression(const ExplicitlySharedExpressionDataPointer &ptr);
0291 
0292     friend class KDbExpression;
0293     friend class KDbFunctionExpression;
0294     friend class KDbFunctionExpressionData;
0295 };
0296 
0297 //! The KDbUnaryExpression class represents unary expression (with a single argument).
0298 /*! operation: + - NOT (or !) ~ "IS NULL" "IS NOT NULL"
0299   */
0300 class KDB_EXPORT KDbUnaryExpression : public KDbExpression
0301 {
0302 public:
0303     /*! Constructs a null unary expression.
0304       @see KDbExpression::isNull() */
0305     KDbUnaryExpression();
0306 
0307     //! Constructs unary expression with token @a token and argument @a arg.
0308     KDbUnaryExpression(KDbToken token, const KDbExpression& arg);
0309 
0310     /*! Constructs a copy of other unary expression @a expr.
0311      Resulting object is not a deep copy but rather a reference to the object @a expr. */
0312     KDbUnaryExpression(const KDbUnaryExpression& expr);
0313 
0314     ~KDbUnaryExpression() override;
0315 
0316     //! @return expression that is argument for this unary expression
0317     KDbExpression arg() const;
0318 
0319     //! Sets expression argument @a expr for this unary expression.
0320     void setArg(const KDbExpression &arg);
0321 
0322 protected:
0323     explicit KDbUnaryExpression(KDbExpressionData* data);
0324 
0325     explicit KDbUnaryExpression(const ExplicitlySharedExpressionDataPointer &ptr);
0326 
0327     friend class KDbExpression;
0328 };
0329 
0330 //! The KDbBinaryExpression class represents binary operation.
0331 /*
0332  - arithmetic operations: + - / * % << >> & | ||
0333  - relational operations: = (or ==) < > <= >= <> (or !=) LIKE 'NOT LIKE' IN 'SIMILAR TO'
0334                           'NOT SIMILAR TO'
0335  - logical operations: OR (or ||) AND (or &&) XOR
0336  - SpecialBinary "pseudo operators":
0337     * e.g. "f1 f2" : token == 0
0338     * e.g. "f1 AS f2" : token == AS
0339 */
0340 class KDB_EXPORT KDbBinaryExpression : public KDbExpression
0341 {
0342 public:
0343     /*! Constructs a null binary expression.
0344       @see KDbExpression::isNull() */
0345     KDbBinaryExpression();
0346 
0347     /*! Constructs binary expression with left expression @a leftExpr,
0348      token @a token, and right expression @a rightExpr. */
0349     KDbBinaryExpression(const KDbExpression& leftExpr, KDbToken token, const KDbExpression& rightExpr);
0350 
0351     /*! Constructs a copy of other unary expression @a expr.
0352      Resulting object is not a deep copy but rather a reference to the object @a expr. */
0353     KDbBinaryExpression(const KDbBinaryExpression& expr);
0354 
0355     ~KDbBinaryExpression() override;
0356 
0357     KDbExpression left() const;
0358 
0359     void setLeft(const KDbExpression& leftExpr);
0360 
0361     KDbExpression right() const;
0362 
0363     void setRight(const KDbExpression& rightExpr);
0364 
0365 protected:
0366     explicit KDbBinaryExpression(KDbExpressionData* data);
0367 
0368     explicit KDbBinaryExpression(const ExplicitlySharedExpressionDataPointer &ptr);
0369 
0370     friend class KDbExpression;
0371     friend class KDbBinaryExpressionData;
0372 };
0373 
0374 
0375 //! The KDbConstExpression class represents const expression.
0376 /*! Types are string, integer, float constants. Also includes NULL value.
0377  Token can be: IDENTIFIER, SQL_NULL, SQL_TRUE, SQL_FALSE, CHARACTER_STRING_LITERAL,
0378  INTEGER_CONST, REAL_CONST, DATE_CONST, DATETIME_CONST, TIME_CONST.
0379 
0380  @note For REAL_CONST accepted values can be of type qreal, double and QPoint.
0381        In the case of QPoint, integer value (with a sign) is stored in QPoint::x
0382        and the fraction part (that should be always positive) is stored in QPoint::y.
0383        This gives 31 bits for the integer part (10 decimal digits) and 31 bits for the part
0384        (10 decimal digits).
0385 */
0386 class KDB_EXPORT KDbConstExpression : public KDbExpression
0387 {
0388 public:
0389     /*! Constructs a null const expression.
0390       @see KDbExpression::isNull() */
0391     KDbConstExpression();
0392 
0393     /*! Constructs const expression token @a token and value @a value. */
0394     KDbConstExpression(KDbToken token, const QVariant& value);
0395 
0396     /*! Constructs a copy of other const expression @a expr.
0397      Resulting object is not a deep copy but rather a reference to the object @a expr. */
0398     KDbConstExpression(const KDbConstExpression& expr);
0399 
0400     ~KDbConstExpression() override;
0401 
0402     QVariant value() const;
0403 
0404     void setValue(const QVariant& value);
0405 
0406 protected:
0407     //! Internal, used by KDbQueryParameterExpression(const QString& message).
0408     KDbConstExpression(KDbExpressionData* data, KDb::ExpressionClass aClass, KDbToken token);
0409     explicit KDbConstExpression(KDbExpressionData* data);
0410     explicit KDbConstExpression(const ExplicitlySharedExpressionDataPointer &ptr);
0411 
0412     friend class KDbExpression;
0413 };
0414 
0415 //! The KDbQueryParameterExpression class represents query parameter expression.
0416 /*! Query parameter is used to getting user input of constant values.
0417  It contains a message that is displayed to the user.
0418 */
0419 class KDB_EXPORT KDbQueryParameterExpression : public KDbConstExpression
0420 {
0421 public:
0422     /*! Constructs a null query parameter expression.
0423       @see KDbExpression::isNull() */
0424     KDbQueryParameterExpression();
0425 
0426     /*! Constructs query parameter expression with message @a message. */
0427     explicit KDbQueryParameterExpression(const QString& message);
0428 
0429     /*! Constructs a copy of other query parameter expression @a expr.
0430      Resulting object is not a deep copy but rather a reference to the object @a expr. */
0431     KDbQueryParameterExpression(const KDbQueryParameterExpression& expr);
0432 
0433     ~KDbQueryParameterExpression() override;
0434 
0435     /*! Sets expected type of the parameter. The default is String.
0436      This method is called from parent's expression validate().
0437      This depends on the type of the related expression.
0438      For instance: query "SELECT * FROM cars WHERE name=[enter name]",
0439      "[enter name]" has parameter of the same type as "name" field.
0440      "=" binary expression's validate() will be called for the left side
0441      of the expression and then the right side will have type set to String. */
0442     void setType(KDbField::Type type);
0443 
0444 protected:
0445     explicit KDbQueryParameterExpression(KDbExpressionData* data);
0446     explicit KDbQueryParameterExpression(const ExplicitlySharedExpressionDataPointer &ptr);
0447 
0448     friend class KDbExpression;
0449 };
0450 
0451 //! The KDbVariableExpression class represents variables such as <i>fieldname</i> or <i>tablename</i>.<i>fieldname</i>
0452 class KDB_EXPORT KDbVariableExpression : public KDbExpression
0453 {
0454 public:
0455     /*! Constructs a null variable expression.
0456       @see KDbExpression::isNull() */
0457     KDbVariableExpression();
0458 
0459     /*! Constructs variable expression with name @a name. */
0460     explicit KDbVariableExpression(const QString& name);
0461 
0462     /*! Constructs a copy of other variable expression @a expr.
0463      Resulting object is not a deep copy but rather a reference to the object @a expr. */
0464     KDbVariableExpression(const KDbVariableExpression& expr);
0465 
0466     ~KDbVariableExpression() override;
0467 
0468     /*! Verbatim name as returned by scanner. */
0469     QString name() const;
0470 
0471     /*! 0 by default. After successful validate() it returns a field,
0472      if the variable is of a form "tablename.fieldname" or "fieldname",
0473      otherwise (eg. for asterisks) still 0.
0474      Only meaningful for column expressions within a query. */
0475     KDbField *field() const;
0476 
0477     /*! -1 by default. After successful validate() it returns a position of a table
0478      within query that needs to be bound to the field.
0479      This value can be either be -1 if no binding is needed.
0480      This value is used in the Parser to call
0481       KDbQuerySchema::addField(KDbField* field, int bindToTable);
0482      Only meaningful for column expressions within a query. */
0483     int tablePositionForField() const;
0484 
0485     /*! @c nullptr by default. After successful validate() it returns table that
0486      is referenced by asterisk, i.e. "*.tablename".
0487      It is @c nullptr if this variable is not an asterisk of that form. */
0488     KDbTableSchema *tableForQueryAsterisk() const;
0489 
0490 protected:
0491     explicit KDbVariableExpression(KDbExpressionData* data);
0492     explicit KDbVariableExpression(const ExplicitlySharedExpressionDataPointer &ptr);
0493 
0494     friend class KDbExpression;
0495 };
0496 
0497 //! The KDbFunctionExpression class represents expression that use functional notation F(x, ...)
0498 /*! The functions list include:
0499  - aggregation functions like SUM, COUNT, MAX, ...
0500  - builtin functions like CURRENT_TIME()
0501  - user defined functions */
0502 class KDB_EXPORT KDbFunctionExpression : public KDbExpression
0503 {
0504 public:
0505     /*! Constructs a null function expression.
0506       @see KDbExpression::isNull() */
0507     KDbFunctionExpression();
0508 
0509     /*! Constructs function expression with name @a name, without arguments. */
0510     explicit KDbFunctionExpression(const QString& name);
0511 
0512     /*! Constructs function expression with name @a name and arguments @a arguments. */
0513     KDbFunctionExpression(const QString& name, const KDbNArgExpression &arguments);
0514 
0515     /*! Constructs a copy of other function expression @a expr.
0516      Resulting object is not a deep copy but rather a reference to the object @a expr. */
0517     KDbFunctionExpression(const KDbFunctionExpression& expr);
0518 
0519     ~KDbFunctionExpression() override;
0520 
0521     //! @return name of the function.
0522     QString name() const;
0523 
0524     //! Sets name of the function to @a name.
0525     void setName(const QString &name);
0526 
0527     //! @return list of arguments of the function.
0528     KDbNArgExpression arguments();
0529 
0530     //! Sets the list of arguments to @a arguments.
0531     void setArguments(const KDbNArgExpression &arguments);
0532 
0533     static QStringList builtInAggregates();
0534 
0535     static bool isBuiltInAggregate(const QString& function);
0536 
0537     using KDbExpression::toString;
0538 
0539     /*! Constructs function expression with name @a name and args @a args. */
0540     static KDbEscapedString toString(const QString &name, const KDbDriver *driver,
0541                                      const KDbNArgExpression &args,
0542                                      KDbQuerySchemaParameterValueListIterator* params,
0543                                      KDb::ExpressionCallStack* callStack);
0544 
0545     //! @return a native (driver-specific) GREATEST() and LEAST() function calls generated
0546     //! to string using CASE WHEN... keywords.
0547     //! This is a workaround for cases when LEAST()/GREATEST() function ignores
0548     //! NULL values and only returns NULL if all the expressions evaluate to NULL.
0549     //! Instead of using F(v0,..,vN), this is used:
0550     //! (CASE WHEN (v0) IS NULL OR .. OR (vN) IS NULL THEN NULL ELSE F(v0,..,vN) END)
0551     //! where F == GREATEST or LEAST.
0552     //! Actually it is needed by MySQL < 5.0.13 and PostgreSQL.
0553     static KDbEscapedString greatestOrLeastFunctionUsingCaseToString(
0554                                         const QString &name,
0555                                         const KDbDriver *driver,
0556                                         const KDbNArgExpression &args,
0557                                         KDbQuerySchemaParameterValueListIterator* params,
0558                                         KDb::ExpressionCallStack* callStack);
0559 
0560 protected:
0561     explicit KDbFunctionExpression(KDbExpressionData* data);
0562     explicit KDbFunctionExpression(const ExplicitlySharedExpressionDataPointer &ptr);
0563 
0564     friend class KDbExpression;
0565     friend class KDbFunctionExpressionData;
0566 };
0567 
0568 //! Sends information about expression  @a expr to debug output @a dbg.
0569 KDB_EXPORT QDebug operator<<(QDebug dbg, const KDbExpression& expr);
0570 
0571 #endif