File indexing completed on 2024-04-21 15:29:55
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 "kdb_debug.h" 0028 #include "generated/sqlparser.h" 0029 0030 KDbUnaryExpressionData::KDbUnaryExpressionData() 0031 : KDbExpressionData() 0032 { 0033 ExpressionDebug << "UnaryExpressionData" << ref; 0034 } 0035 0036 KDbUnaryExpressionData::~KDbUnaryExpressionData() 0037 { 0038 ExpressionDebug << "~UnaryExpressionData" << ref; 0039 } 0040 0041 KDbUnaryExpressionData* KDbUnaryExpressionData::clone() 0042 { 0043 ExpressionDebug << "UnaryExpressionData::clone" << *this; 0044 return new KDbUnaryExpressionData(*this); 0045 } 0046 0047 void KDbUnaryExpressionData::debugInternal(QDebug dbg, KDb::ExpressionCallStack* callStack) const 0048 { 0049 dbg.nospace() << "UnaryExp(" 0050 << token << ","; 0051 if (children.isEmpty()) { 0052 dbg.nospace() << "<NONE>"; 0053 } 0054 else { 0055 ExplicitlySharedExpressionDataPointer a = arg(); 0056 if (a.data()) { 0057 a->debug(dbg, callStack); 0058 } 0059 else { 0060 dbg.nospace() << "<NONE>"; 0061 } 0062 } 0063 dbg.nospace() << qPrintable(QString::fromLatin1(",type=%1)") 0064 .arg(KDbDriver::defaultSqlTypeName(type()))); 0065 } 0066 0067 KDbEscapedString KDbUnaryExpressionData::toStringInternal( 0068 const KDbDriver *driver, 0069 KDbQuerySchemaParameterValueListIterator* params, 0070 KDb::ExpressionCallStack* callStack) const 0071 { 0072 ExplicitlySharedExpressionDataPointer a = arg(); 0073 KDbEscapedString aString = a.constData() 0074 ? a->toString(driver, params, callStack) : KDbEscapedString("<NULL>"); 0075 if (token == '(') { //parentheses (special case) 0076 return "(" + aString + ")"; 0077 } 0078 if (token.toChar() > 0) { 0079 return token.toString(driver) + aString; 0080 } 0081 switch (token.value()) { 0082 case NOT: 0083 return "NOT " + aString; 0084 case SQL_IS_NULL: 0085 return aString + " IS NULL"; 0086 case SQL_IS_NOT_NULL: 0087 return aString + " IS NOT NULL"; 0088 } 0089 return KDbEscapedString("%1 %2").arg(token.toString(driver)).arg(aString); 0090 } 0091 0092 void KDbUnaryExpressionData::getQueryParameters(QList<KDbQuerySchemaParameter>* params) 0093 { 0094 Q_ASSERT(params); 0095 ExplicitlySharedExpressionDataPointer a = arg(); 0096 if (a.constData()) 0097 a->getQueryParameters(params); 0098 } 0099 0100 KDbField::Type KDbUnaryExpressionData::typeInternal(KDb::ExpressionCallStack* callStack) const 0101 { 0102 if (children.isEmpty()) { 0103 return KDbField::InvalidType; 0104 } 0105 ExplicitlySharedExpressionDataPointer a = arg(); 0106 if (!a.constData()) 0107 return KDbField::InvalidType; 0108 0109 //NULL IS NOT NULL : BOOLEAN 0110 //NULL IS NULL : BOOLEAN 0111 switch (token.value()) { 0112 case SQL_IS_NULL: 0113 case SQL_IS_NOT_NULL: 0114 //! @todo queryParameterExpressionData->m_type still is Text but can be any type 0115 return KDbField::Boolean; 0116 } 0117 0118 KDbQueryParameterExpressionData *queryParameterExpressionData = a->convert<KDbQueryParameterExpressionData>(); 0119 if (queryParameterExpressionData) { 0120 switch (token.value()) { 0121 case '+': 0122 case '-': 0123 case '~': 0124 queryParameterExpressionData->m_type = KDbField::Integer; 0125 break; 0126 case '!': 0127 case NOT: 0128 queryParameterExpressionData->m_type = KDbField::Boolean; 0129 break; 0130 default:; 0131 } 0132 } 0133 KDbField::Type t = a->type(callStack); 0134 if (t == KDbField::Null) 0135 return KDbField::Null; 0136 if (token == KDbToken::NOT) { 0137 return t == KDbField::Boolean ? KDbField::Boolean : KDbField::InvalidType; 0138 } 0139 return t; 0140 } 0141 0142 bool KDbUnaryExpressionData::validateInternal(KDbParseInfo *parseInfo, KDb::ExpressionCallStack* callStack) 0143 { 0144 ExplicitlySharedExpressionDataPointer a = arg(); 0145 if (!a.constData()) 0146 return false; 0147 0148 if (!a->validate(parseInfo, callStack)) 0149 return false; 0150 0151 //! @todo compare types... e.g. NOT applied to Text makes no sense... 0152 0153 // update type 0154 //! @todo IMPORTANT: update type 0155 #if 0 0156 if (a->toQueryParameter()) { 0157 a->toQueryParameter()->setType(type()); 0158 } 0159 #endif 0160 0161 return typeInternal(callStack) != KDbField::InvalidType; 0162 #if 0 0163 KDbExpression *n = l.at(0); 0164 0165 n->check(); 0166 /*typ wyniku: 0167 const bool for "NOT <bool>" (negative) 0168 int for "# <str>" (string length) 0169 int for "+/- <int>" 0170 */ 0171 if (is(NOT) && n->nodeTypeIs(TYP_BOOL)) { 0172 node_type = new NConstType(TYP_BOOL); 0173 } else if (is('#') && n->nodeTypeIs(TYP_STR)) { 0174 node_type = new NConstType(TYP_INT); 0175 } else if ((is('+') || is('-')) && n->nodeTypeIs(TYP_INT)) { 0176 node_type = new NConstType(TYP_INT); 0177 } else { 0178 ERR("Invalid argument of type '%s' for operator '%s'", 0179 n->nodeTypeName(), is(NOT) ? QString("not") : QChar(typ())); 0180 } 0181 #endif 0182 } 0183 0184 //========================================= 0185 0186 KDbUnaryExpression::KDbUnaryExpression() 0187 : KDbExpression(new KDbUnaryExpressionData) 0188 { 0189 ExpressionDebug << "KDbUnaryExpression() ctor" << *this; 0190 } 0191 0192 KDbUnaryExpression::KDbUnaryExpression(KDbToken token, const KDbExpression& arg) 0193 : KDbExpression(new KDbUnaryExpressionData, KDb::UnaryExpression, token) 0194 { 0195 appendChild(arg.d); 0196 } 0197 0198 KDbUnaryExpression::KDbUnaryExpression(KDbExpressionData* data) 0199 : KDbExpression(data) 0200 { 0201 ExpressionDebug << "KDbUnaryExpression(KDbExpressionData*) ctor" << *this; 0202 } 0203 0204 KDbUnaryExpression::KDbUnaryExpression(const KDbUnaryExpression& expr) 0205 : KDbExpression(expr) 0206 { 0207 } 0208 0209 KDbUnaryExpression::KDbUnaryExpression(const ExplicitlySharedExpressionDataPointer &ptr) 0210 : KDbExpression(ptr) 0211 { 0212 } 0213 0214 KDbUnaryExpression::~KDbUnaryExpression() 0215 { 0216 } 0217 0218 KDbExpression KDbUnaryExpression::arg() const 0219 { 0220 return KDbExpression(d->convertConst<KDbUnaryExpressionData>()->arg()); 0221 } 0222 0223 void KDbUnaryExpression::setArg(const KDbExpression &arg) 0224 { 0225 if (!d->children.isEmpty()) { 0226 removeChild(0); 0227 } 0228 insertChild(0, arg); 0229 }