File indexing completed on 2025-03-23 04:19:43
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