File indexing completed on 2024-12-01 10:28:56

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 "KDbDriver.h"
0026 #include "KDbQuerySchema.h"
0027 #include "KDbParser_p.h"
0028 #include "kdb_debug.h"
0029 
0030 KDbNArgExpressionData::KDbNArgExpressionData()
0031  : KDbExpressionData()
0032 {
0033     ExpressionDebug << "NArgExpressionData" << ref;
0034 }
0035 
0036 KDbNArgExpressionData::~KDbNArgExpressionData()
0037 {
0038     ExpressionDebug << "~NArgExpressionData" << ref;
0039 }
0040 
0041 KDbField::Type KDbNArgExpressionData::typeInternal(KDb::ExpressionCallStack *callStack) const
0042 {
0043     if (token == KDbToken::BETWEEN_AND || token == KDbToken::NOT_BETWEEN_AND) {
0044         for (int i = 0; i < children.count(); i++) {
0045             KDbField::Type t = children.at(0)->type(callStack);
0046             if (t == KDbField::InvalidType || t == KDbField::Null) {
0047                 return t;
0048             }
0049         }
0050         return KDbField::Boolean;
0051     }
0052     return KDbField::Tuple;
0053 }
0054 
0055 KDbNArgExpressionData* KDbNArgExpressionData::clone()
0056 {
0057     ExpressionDebug << "NArgExpressionData::clone" << *this;
0058     return new KDbNArgExpressionData(*this);
0059 }
0060 
0061 bool KDbNArgExpressionData::validateInternal(KDbParseInfo *parseInfo, KDb::ExpressionCallStack* callStack)
0062 {
0063     foreach(ExplicitlySharedExpressionDataPointer data, children) {
0064         if (!data->validate(parseInfo, callStack))
0065             return false;
0066     }
0067 
0068     if (token == KDbToken::BETWEEN_AND || token == KDbToken::NOT_BETWEEN_AND) {
0069         if (children.count() != 3) {
0070             parseInfo->setErrorMessage(tr("Three arguments required"));
0071             parseInfo->setErrorDescription(
0072                 tr("%1 operator requires exactly three arguments.", "BETWEEN..AND error")
0073                                   .arg(QLatin1String("BETWEEN...AND")));
0074             return false;
0075         }
0076         const KDbField::Type t0 = children[0]->type();
0077         const KDbField::Type t1 = children[1]->type();
0078         const KDbField::Type t2 = children[2]->type();
0079         if (t0 == KDbField::Null || t1 == KDbField::Null || t2 == KDbField::Null) {
0080             return true;
0081         }
0082         if (!(   !KDbField::isNumericType(t0)
0083               || !KDbField::isNumericType(t1)
0084               || !KDbField::isNumericType(t2)))
0085         {
0086             return true;
0087         } else if (!(   !KDbField::isTextType(t0)
0088                      || !KDbField::isTextType(t1)
0089                      || !KDbField::isTextType(t2)))
0090         {
0091             return true;
0092         }
0093 
0094         if (t0 == t1 && t1 == t2) {
0095             return true;
0096         }
0097 
0098         parseInfo->setErrorMessage(tr("Incompatible types of arguments"));
0099         parseInfo->setErrorDescription(
0100                            tr("Operator \"%1\" requires compatible types of arguments. "
0101                               "Specified arguments are of type %2, %3, %4.",
0102                               "BETWEEN..AND arguments type error")
0103                               .arg(QLatin1String("BETWEEN..AND"),
0104                                    KDbField::typeName(t0),
0105                                    KDbField::typeName(t1),
0106                                    KDbField::typeName(t2)));
0107         return false;
0108     }
0109     return true;
0110 }
0111 
0112 void KDbNArgExpressionData::debugInternal(QDebug dbg, KDb::ExpressionCallStack* callStack) const
0113 {
0114     dbg.nospace() << "NArgExp("
0115         << token.name() << ", class=" << expressionClassName(expressionClass);
0116     foreach(ExplicitlySharedExpressionDataPointer data, children) {
0117         dbg.nospace() << ", ";
0118         data->debug(dbg, callStack);
0119     }
0120     dbg.nospace() << ",type=" << KDbDriver::defaultSqlTypeName(type()) << ")";
0121 }
0122 
0123 KDbEscapedString KDbNArgExpressionData::toStringInternal(
0124                                         const KDbDriver *driver,
0125                                         KDbQuerySchemaParameterValueListIterator* params,
0126                                         KDb::ExpressionCallStack* callStack) const
0127 {
0128     if (token == KDbToken::BETWEEN_AND && children.count() == 3) {
0129         return children[0]->toString(driver, params, callStack) + " BETWEEN "
0130                 + children[1]->toString(driver, params, callStack) + " AND "
0131                 + children[2]->toString(driver, params, callStack);
0132     }
0133     if (token == KDbToken::NOT_BETWEEN_AND && children.count() == 3) {
0134         return children[0]->toString(driver, params, callStack) + " NOT BETWEEN "
0135                 + children[1]->toString(driver, params, callStack) + " AND "
0136                 + children[2]->toString(driver, params, callStack);
0137     }
0138 
0139     KDbEscapedString s;
0140     s.reserve(256);
0141     foreach(ExplicitlySharedExpressionDataPointer data, children) {
0142         if (!s.isEmpty())
0143             s += ", ";
0144         s += data->toString(driver, params, callStack);
0145     }
0146     return s;
0147 }
0148 
0149 void KDbNArgExpressionData::getQueryParameters(QList<KDbQuerySchemaParameter>* params)
0150 {
0151     Q_ASSERT(params);
0152     foreach(ExplicitlySharedExpressionDataPointer data, children) {
0153         data->getQueryParameters(params);
0154     }
0155 }
0156 
0157 bool KDbNArgExpressionData::containsInvalidArgument() const
0158 {
0159     foreach(ExplicitlySharedExpressionDataPointer data, children) {
0160         const KDbField::Type type = data->type();
0161         if (type == KDbField::InvalidType) {
0162             return true;
0163         }
0164     }
0165     return false;
0166 }
0167 
0168 bool KDbNArgExpressionData::containsNullArgument() const
0169 {
0170     foreach(ExplicitlySharedExpressionDataPointer data, children) {
0171         const KDbField::Type type = data->type();
0172         if (type == KDbField::Null) {
0173             return true;
0174         }
0175     }
0176     return false;
0177 }
0178 
0179 //=========================================
0180 
0181 KDbNArgExpression::KDbNArgExpression()
0182  : KDbExpression(new KDbNArgExpressionData)
0183 {
0184     ExpressionDebug << "KDbNArgExpression() ctor" << *this;
0185 }
0186 
0187 KDbNArgExpression::KDbNArgExpression(KDbExpressionData* data)
0188  : KDbExpression(data)
0189 {
0190     ExpressionDebug << "KDbNArgExpression(KDbExpressionData*) ctor" << *this;
0191 }
0192 
0193 KDbNArgExpression::KDbNArgExpression(KDb::ExpressionClass aClass, KDbToken token)
0194         : KDbExpression(new KDbNArgExpressionData, aClass, token)
0195 {
0196     ExpressionDebug << "KDbNArgExpression(KDb::ExpressionClass, int) ctor" << *this;
0197 }
0198 
0199 KDbNArgExpression::KDbNArgExpression(const KDbNArgExpression& expr)
0200         : KDbExpression(expr)
0201 {
0202 }
0203 
0204 KDbNArgExpression::KDbNArgExpression(const ExplicitlySharedExpressionDataPointer &ptr)
0205     : KDbExpression(ptr)
0206 {
0207 }
0208 
0209 KDbNArgExpression::~KDbNArgExpression()
0210 {
0211 }
0212 
0213 void KDbNArgExpression::append(const KDbExpression& expr)
0214 {
0215     appendChild(expr);
0216 }
0217 
0218 void KDbNArgExpression::prepend(const KDbExpression& expr)
0219 {
0220     prependChild(expr);
0221 }
0222 
0223 KDbExpression KDbNArgExpression::arg(int i) const
0224 {
0225     return KDbExpression(d->children.value(i));
0226 }
0227 
0228 void KDbNArgExpression::insert(int i, const KDbExpression& expr)
0229 {
0230     insertChild(i, expr);
0231 }
0232 
0233 void KDbNArgExpression::replace(int i, const KDbExpression& expr)
0234 {
0235     if (!checkBeforeInsert(expr.d))
0236         return;
0237     if (i < 0 || i > d->children.count())
0238         return;
0239     d->children.at(i)->parent.reset();
0240     d->children.replace(i, expr.d);
0241     expr.d->parent = d;
0242 }
0243 
0244 bool KDbNArgExpression::remove(const KDbExpression& expr)
0245 {
0246     return removeChild(expr);
0247 }
0248 
0249 void KDbNArgExpression::removeAt(int i)
0250 {
0251     removeChild(i);
0252 }
0253 
0254 KDbExpression KDbNArgExpression::takeAt(int i)
0255 {
0256     return takeChild(i);
0257 }
0258 
0259 int KDbNArgExpression::indexOf(const KDbExpression& expr, int from) const
0260 {
0261     return indexOfChild(expr, from);
0262 }
0263 
0264 int KDbNArgExpression::lastIndexOf(const KDbExpression& expr, int from) const
0265 {
0266     return lastIndexOfChild(expr, from);
0267 }
0268 
0269 int KDbNArgExpression::argCount() const
0270 {
0271     return d->children.count();
0272 }
0273 
0274 bool KDbNArgExpression::isEmpty() const
0275 {
0276     return d->children.isEmpty();
0277 }
0278 
0279 bool KDbNArgExpression::containsInvalidArgument() const
0280 {
0281     return d->convert<KDbNArgExpressionData>()->containsInvalidArgument();
0282 }
0283 
0284 bool KDbNArgExpression::containsNullArgument() const
0285 {
0286     return d->convert<KDbNArgExpressionData>()->containsNullArgument();
0287 }