File indexing completed on 2024-04-21 15:29:53

0001 /* This file is part of the KDE project
0002    Copyright (C) 2003-2016 Jarosław Staniek <staniek@kde.org>
0003 
0004    Based on nexp.cpp : Parser module of Python-like language
0005    (C) 2001 Jarosław Staniek, MIMUW (www.mimuw.edu.pl)
0006 
0007    This library is free software; you can redistribute it and/or
0008    modify it under the terms of the GNU Library General Public
0009    License as published by the Free Software Foundation; either
0010    version 2 of the License, or (at your option) any later version.
0011 
0012    This library is distributed in the hope that it will be useful,
0013    but WITHOUT ANY WARRANTY; without even the implied warranty of
0014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015    Library General Public License for more details.
0016 
0017    You should have received a copy of the GNU Library General Public License
0018    along with this library; see the file COPYING.LIB.  If not, write to
0019    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0020  * Boston, MA 02110-1301, USA.
0021  */
0022 
0023 #include "KDbExpression.h"
0024 #include "KDb.h"
0025 #include "KDbQuerySchema.h"
0026 #include "KDbDriver.h"
0027 #include "KDbParser_p.h"
0028 #include "kdb_debug.h"
0029 #include "generated/sqlparser.h"
0030 
0031 KDbBinaryExpressionData::KDbBinaryExpressionData()
0032  : KDbExpressionData()
0033 {
0034     ExpressionDebug << "BinaryExpressionData" << ref;
0035 }
0036 
0037 KDbBinaryExpressionData::~KDbBinaryExpressionData()
0038 {
0039 }
0040 
0041 bool KDbBinaryExpressionData::validateInternal(KDbParseInfo *parseInfo, KDb::ExpressionCallStack* callStack)
0042 {
0043     if (children.count() != 2)
0044         return false;
0045 
0046     if (!left()->validate(parseInfo, callStack))
0047         return false;
0048     if (!right()->validate(parseInfo, callStack))
0049         return false;
0050 
0051     //update type for query parameters
0052 //! @todo IMPORTANT: update type for query parameters
0053 #if 0
0054     if (left()->isQueryParameter()) {
0055         KDbQueryParameterExpression queryParameter = left()->toQueryParameter();
0056         queryParameter->setType(left()->type());
0057     }
0058     if (right()->isQueryParameter()) {
0059         KDbQueryParameterExpression queryParameter = right()->toQueryParameter();
0060         queryParameter->setType(right()->type());
0061     }
0062 #endif
0063     if (typeInternal(callStack) == KDbField::InvalidType) {
0064         parseInfo->setErrorMessage(tr("Incompatible types of arguments"));
0065         parseInfo->setErrorDescription(
0066                            tr("Expression \"%1\" requires compatible types of arguments. "
0067                               "Specified arguments are of type %2 and %3.",
0068                               "Binary expression arguments type error")
0069                               .arg(toStringInternal(nullptr, nullptr, callStack).toString(),
0070                                    KDbField::typeName(left()->type()),
0071                                    KDbField::typeName(right()->type())));
0072         return false;
0073     }
0074     return true;
0075 }
0076 
0077 KDbField::Type KDbBinaryExpressionData::typeInternal(KDb::ExpressionCallStack* callStack) const
0078 {
0079     if (children.count() != 2 || expressionClass == KDb::UnknownExpression)
0080         return KDbField::InvalidType;
0081     const KDbField::Type lt = left()->type(callStack);
0082     const KDbField::Type rt = right()->type(callStack);
0083     if (lt == KDbField::InvalidType || rt == KDbField::InvalidType)
0084         return KDbField::InvalidType;
0085 
0086     const bool ltNull = lt == KDbField::Null;
0087     const bool rtNull = rt == KDbField::Null;
0088     const bool ltText = KDbField::isTextType(lt);
0089     const bool rtText = KDbField::isTextType(rt);
0090     const bool ltInt = KDbField::isIntegerType(lt);
0091     const bool rtInt = KDbField::isIntegerType(rt);
0092     const bool ltFP = KDbField::isFPNumericType(lt);
0093     const bool rtFP = KDbField::isFPNumericType(rt);
0094     const bool ltBool = lt == KDbField::Boolean;
0095     const bool rtBool = rt == KDbField::Boolean;
0096     const KDbField::TypeGroup ltGroup = KDbField::typeGroup(lt);
0097     const KDbField::TypeGroup rtGroup = KDbField::typeGroup(rt);
0098     const bool lAny = left()->convertConst<KDbQueryParameterExpressionData>();
0099     const bool rAny = right()->convertConst<KDbQueryParameterExpressionData>();
0100 
0101     if (ltNull || rtNull) {
0102         switch (token.value()) {
0103         //! @todo add general support, e.g. for "NULL AND (1 == 1)"; for now we only support
0104         //! constants because there's no evaluation and operations with NULL depend on whether we have TRUE or FALSE
0105         //! See https://www.postgresql.org/docs/9.4/static/functions-logical.html
0106         //!     https://dev.mysql.com/doc/refman/5.0/en/logical-operators.html
0107         case OR: {
0108             const KDbConstExpressionData *leftConst = left()->convertConst<KDbConstExpressionData>();
0109             const KDbConstExpressionData *rightConst = right()->convertConst<KDbConstExpressionData>();
0110             if ((ltBool && leftConst && leftConst->value.toBool())       // true OR NULL is true
0111                 || (rtBool && rightConst && rightConst->value.toBool())) // NULL OR true is true
0112             {
0113                 return KDbField::Boolean;
0114             }
0115             else if ((ltBool && leftConst && !leftConst->value.toBool())  // false OR NULL is NULL
0116                      || (rtBool && rightConst && !rightConst->value.toBool())  // NULL OR false is NULL
0117                      || lAny  // Any OR NULL may be NULL
0118                      || rAny) // NULL OR Any may be NULL
0119                 //! @todo Any OR NULL may be also TRUE -- but this needs support of fuzzy/multivalue types
0120                 //! @todo NULL OR Any may be also TRUE -- but this needs support of fuzzy/multivalue types
0121             {
0122                 return KDbField::Null;
0123             }
0124             break;
0125         }
0126         case AND: {
0127             const KDbConstExpressionData *leftConst = left()->convertConst<KDbConstExpressionData>();
0128             const KDbConstExpressionData *rightConst = right()->convertConst<KDbConstExpressionData>();
0129             if ((ltBool && leftConst && !leftConst->value.toBool())       // false AND NULL is false
0130                 || (rtBool && rightConst && !rightConst->value.toBool())) // NULL AND false is false
0131             {
0132                 return KDbField::Boolean;
0133             }
0134             else if ((ltBool && leftConst && leftConst->value.toBool())       // true AND NULL is NULL
0135                      || (rtBool && rightConst && rightConst->value.toBool()) // NULL AND true is NULL
0136                      || lAny  // Any AND NULL may be NULL
0137                      || rAny) // NULL AND Any may be NULL
0138                 //! @todo Any AND NULL may be also FALSE -- but this needs support of fuzzy/multivalue types
0139                 //! @todo NULL AND Any may be also FALSE -- but this needs support of fuzzy/multivalue types
0140             {
0141                 return KDbField::Null;
0142             }
0143             break;
0144         }
0145         case XOR: {// Logical XOR. Returns NULL if either operand is NULL. For non-NULL operands,
0146                    // evaluates to 1 if an odd number of operands is nonzero, otherwise 0 is returned.
0147                    // a XOR b is mathematically equal to (a AND (NOT b)) OR ((NOT a) and b).
0148                    // https://dev.mysql.com/doc/refman/5.0/en/logical-operators.html#operator_xor
0149             return KDbField::Null;
0150         }
0151         default:
0152             return KDbField::Null;
0153         }
0154     }
0155 
0156     switch (token.value()) {
0157     case OR:
0158     case AND:
0159     case XOR: {
0160         if (ltNull && rtNull) {
0161             return KDbField::Null;
0162         } else if ((ltBool && rtBool)
0163                    || (ltBool && rAny)
0164                    || (lAny && rtBool)
0165                    || (lAny && rAny))
0166         {
0167             return KDbField::Boolean;
0168         }
0169         return KDbField::InvalidType;
0170     }
0171     case '+':
0172     case CONCATENATION:
0173         if (lt == KDbField::Text && rt == KDbField::Text) {
0174             return KDbField::Text;
0175         }
0176         else if ((ltText && rtText)
0177                  || (ltText && rAny)
0178                  || (lAny && rtText))
0179         {
0180             return KDbField::LongText;
0181         }
0182         else if ((ltText && rtNull)
0183             || (ltNull && rtText)
0184             || (lAny && rtNull)
0185             || (ltNull && rAny))
0186         {
0187             return KDbField::Null;
0188         } else if (token.value() == CONCATENATION) {
0189             if (lAny && rAny) {
0190                 return KDbField::LongText;
0191             }
0192             return KDbField::InvalidType;
0193         }
0194         break; // '+' can still be handled below for non-text types
0195     default:;
0196     }
0197 
0198     if (expressionClass == KDb::RelationalExpression) {
0199         if ((ltText && rtText)
0200             || (ltText && rAny)
0201             || (lAny && rtText)
0202             || (lAny && rAny)
0203 
0204             || (ltInt && rtInt)
0205             || (ltInt && rAny)
0206             || (lAny && rtInt)
0207 
0208             || (ltFP && rtFP) || (ltInt && rtFP) || (ltFP && rtInt)
0209             || (ltFP && rAny) || (lAny && rtFP)
0210 
0211             || (ltBool && rtBool) || (ltBool && rtInt) || (ltInt && rtBool)
0212             || (ltBool && rAny) || (lAny && rtBool)
0213 
0214             || (ltBool && rtFP) || (ltFP && rtBool)
0215 
0216             || (ltGroup == KDbField::DateTimeGroup && rtGroup == KDbField::DateTimeGroup)
0217             || (ltGroup == KDbField::DateTimeGroup && rAny)
0218             || (lAny && rtGroup == KDbField::DateTimeGroup))
0219         {
0220             return KDbField::Boolean;
0221         }
0222         return KDbField::InvalidType;
0223     }
0224 
0225     if (expressionClass == KDb::ArithmeticExpression) {
0226         if (lAny && rAny) {
0227             return KDbField::Integer;
0228         } else if ((ltInt && rtInt)
0229                    || (ltInt && rAny)
0230                    || (lAny && rtInt))
0231         {
0232             /* From documentation of KDb::maximumForIntegerFieldTypes():
0233              In case of KDb::ArithmeticExpression:
0234              returned type may not fit to the result of evaluated expression that involves the arguments.
0235              For example, 100 is within Byte type, maximumForIntegerFieldTypes(Byte, Byte) is Byte but result
0236              of 100 * 100 exceeds the range of Byte.
0237 
0238              Solution: for types smaller than Integer (e.g. Byte and ShortInteger) we are returning
0239              Integer type.
0240             */
0241             KDbField::Type t;
0242             if (lAny) {
0243                 t = rt;
0244             } else if (rAny) {
0245                 t = lt;
0246             } else {
0247                 t = KDb::maximumForIntegerFieldTypes(lt, rt);
0248             }
0249             if (t == KDbField::Byte || t == KDbField::ShortInteger) {
0250                 return KDbField::Integer;
0251             }
0252             return t;
0253         }
0254 
0255         switch (token.value()) {
0256         case '&':
0257         case BITWISE_SHIFT_RIGHT:
0258         case BITWISE_SHIFT_LEFT:
0259             if ((ltFP && rtFP)
0260                  || (ltFP && rAny)  //! @todo can be other Integer too
0261                  || (lAny && rtFP)) //! @todo can be other Integer too
0262             {
0263                 return KDbField::Integer;
0264             }
0265             else if ((ltFP && rtInt) // inherit from right
0266                      || (lAny && rtInt))
0267             {
0268                 return rt;
0269             }
0270             else if ((ltInt && rtFP) // inherit from left
0271                      || (ltInt && rAny))
0272             {
0273                 return lt;
0274             }
0275             break;
0276         default:;
0277         }
0278 
0279         /* inherit floating point (Float or Double) type */
0280         if (ltFP && (rtInt || lt == rt || rAny))
0281             return lt;
0282         if (rtFP && (ltInt || lt == rt || lAny))
0283             return rt;
0284     }
0285     return KDbField::InvalidType;
0286 }
0287 
0288 KDbBinaryExpressionData* KDbBinaryExpressionData::clone()
0289 {
0290     ExpressionDebug << "BinaryExpressionData::clone" << *this;
0291     return new KDbBinaryExpressionData(*this);
0292 }
0293 
0294 void KDbBinaryExpressionData::debugInternal(QDebug dbg, KDb::ExpressionCallStack* callStack) const
0295 {
0296     dbg.nospace() << "BinaryExp(class="
0297         << expressionClassName(expressionClass)
0298         << ",";
0299     if (children.count() == 2 && left().constData()) {
0300         left()->debug(dbg, callStack);
0301     }
0302     else {
0303         dbg.nospace() << "<NONE>";
0304     }
0305     dbg.nospace() << "," << token << ",";
0306     if (children.count() == 2 && right().constData()) {
0307         right()->debug(dbg, callStack);
0308     }
0309     else {
0310         dbg.nospace() << "<NONE>";
0311     }
0312     dbg.nospace() << ",type=" << KDbDriver::defaultSqlTypeName(type()) << ")";
0313 }
0314 
0315 KDbEscapedString KDbBinaryExpressionData::toStringInternal(
0316                                         const KDbDriver *driver,
0317                                         KDbQuerySchemaParameterValueListIterator* params,
0318                                         KDb::ExpressionCallStack* callStack) const
0319 {
0320     switch (token.value()) {
0321     case '+':
0322     case CONCATENATION: {
0323         if (driver && KDbField::isTextType(type())) {
0324             const KDbBinaryExpression binaryExpr(const_cast<KDbBinaryExpressionData*>(this));
0325             return driver->concatenateFunctionToString(binaryExpr, params, callStack);
0326         }
0327         break;
0328     }
0329     default:;
0330     }
0331 
0332 #define INFIX(a) \
0333     (left().constData() ? left()->toString(driver, params, callStack) : KDbEscapedString("<NULL>")) \
0334     + " " + a + " " + (right().constData() ? right()->toString(driver, params, callStack) : KDbEscapedString("<NULL>"))
0335     return INFIX(token.toString(driver));
0336 #undef INFIX
0337 }
0338 
0339 void KDbBinaryExpressionData::getQueryParameters(QList<KDbQuerySchemaParameter>* params)
0340 {
0341     Q_ASSERT(params);
0342     if (left().constData())
0343         left()->getQueryParameters(params);
0344     if (right().constData())
0345         right()->getQueryParameters(params);
0346 }
0347 
0348 ExplicitlySharedExpressionDataPointer KDbBinaryExpressionData::left() const
0349 {
0350     return (children.count() > 0) ? children.at(0) : ExplicitlySharedExpressionDataPointer();
0351 }
0352 ExplicitlySharedExpressionDataPointer KDbBinaryExpressionData::right() const
0353 {
0354     return (children.count() > 1) ? children.at(1) : ExplicitlySharedExpressionDataPointer();
0355 }
0356 
0357 //=========================================
0358 
0359 static KDb::ExpressionClass classForArgs(const KDbExpression& leftExpr,
0360                                          KDbToken token,
0361                                          const KDbExpression& rightExpr)
0362 {
0363     if (leftExpr.isNull()) {
0364         kdbWarning() << "Setting KDbBinaryExpression to null because left argument is not specified";
0365         return KDb::UnknownExpression;
0366     }
0367     if (rightExpr.isNull()) {
0368         kdbWarning() << "Setting KDbBinaryExpression to null because right argument is not specified";
0369         return KDb::UnknownExpression;
0370     }
0371     return KDbExpression::classForToken(token);
0372 }
0373 
0374 KDbBinaryExpression::KDbBinaryExpression()
0375  : KDbExpression(new KDbBinaryExpressionData)
0376 {
0377     ExpressionDebug << "KDbBinaryExpression() ctor" << *this;
0378 }
0379 
0380 KDbBinaryExpression::KDbBinaryExpression(const KDbExpression& leftExpr,
0381                                          KDbToken token,
0382                                          const KDbExpression& rightExpr)
0383     : KDbExpression(new KDbBinaryExpressionData, classForArgs(leftExpr, token, rightExpr), token)
0384 {
0385     if (!isNull()) {
0386         appendChild(leftExpr.d);
0387         appendChild(rightExpr.d);
0388     }
0389 }
0390 
0391 KDbBinaryExpression::KDbBinaryExpression(const KDbBinaryExpression& expr)
0392         : KDbExpression(expr)
0393 {
0394 }
0395 
0396 KDbBinaryExpression::KDbBinaryExpression(KDbExpressionData* data)
0397  : KDbExpression(data)
0398 {
0399     ExpressionDebug << "KDbBinaryExpression(KDbExpressionData*) ctor" << *this;
0400 }
0401 
0402 KDbBinaryExpression::KDbBinaryExpression(const ExplicitlySharedExpressionDataPointer &ptr)
0403     : KDbExpression(ptr)
0404 {
0405 }
0406 
0407 KDbBinaryExpression::~KDbBinaryExpression()
0408 {
0409 }
0410 
0411 KDbExpression KDbBinaryExpression::left() const
0412 {
0413     return (d->children.count() > 0) ? KDbExpression(d->children.at(0)) : KDbExpression();
0414 }
0415 
0416 void KDbBinaryExpression::setLeft(const KDbExpression& leftExpr)
0417 {
0418     KDbExpression::setLeftOrRight(leftExpr, 0);
0419 }
0420 
0421 KDbExpression KDbBinaryExpression::right() const
0422 {
0423     return (d->children.count() > 1) ? KDbExpression(d->children.at(1)) : KDbExpression();
0424 }
0425 
0426 void KDbBinaryExpression::setRight(const KDbExpression& rightExpr)
0427 {
0428     KDbExpression::setLeftOrRight(rightExpr, 1);
0429 }