File indexing completed on 2024-09-15 04:13:14
0001 /* This file is part of the KDE project 0002 Copyright (C) 2011-2016 Jarosław Staniek <staniek@kde.org> 0003 0004 This library is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This library is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this library; see the file COPYING.LIB. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 * Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #include "ExpressionsTest.h" 0021 0022 #include <QtTest> 0023 0024 #include <KDbDateTime> 0025 #include <KDbExpression> 0026 #include "parser/generated/sqlparser.h" 0027 #include "parser/KDbParser_p.h" 0028 0029 Q_DECLARE_METATYPE(KDb::ExpressionClass) 0030 Q_DECLARE_METATYPE(KDbEscapedString) 0031 Q_DECLARE_METATYPE(KDbField::Type) 0032 Q_DECLARE_METATYPE(KDbToken) 0033 0034 namespace QTest { 0035 template<> 0036 char *toString(const KDbEscapedString &string) 0037 { 0038 return qstrdup(qPrintable(string.toString())); 0039 } 0040 0041 template<> 0042 char *toString(const KDbField::Type &type) 0043 { 0044 return qstrdup(qPrintable(KDbField::typeString(type))); 0045 } 0046 0047 //! Adds a quote if this is the single-character token to match the format of Bison 0048 template<> 0049 char* toString(const KDbToken &token) 0050 { 0051 return qstrdup(qPrintable( 0052 token.toChar() ? QString::fromLatin1("'%1'").arg(token.toString()) 0053 : token.toString() 0054 )); 0055 } 0056 } 0057 0058 QTEST_GUILESS_MAIN(ExpressionsTest) 0059 0060 //! Used in macros so characters and KDbTokens can be used interchangeably 0061 static inline KDbToken TO_TOKEN(char charValue) 0062 { 0063 return KDbToken(charValue); 0064 } 0065 0066 //! Used in macros so characters and KDbTokens can be used interchangeably 0067 static inline KDbToken TO_TOKEN(KDbToken token) 0068 { 0069 return token; 0070 } 0071 0072 void ExpressionsTest::initTestCase() 0073 { 0074 } 0075 0076 //! compares two expression @a e1 and @a e2 based on strings/debug strings 0077 //! and token strings 0078 template <typename T1, typename T2> 0079 static void compareStrings(const T1 &e1, const T2 &e2) 0080 { 0081 //qDebug() << "compareStrings():" 0082 // << "\ne1:" << e1.toString() << e1.token() << e1.token().ToString() 0083 // << "\ne2:" << e2.toString() << e2.token() << e2.token().toString(); 0084 QCOMPARE(e1.toString(nullptr), e2.toString(nullptr)); 0085 QCOMPARE(e1.token(), e2.token()); 0086 QCOMPARE(e1.token().value(), e2.token().value()); 0087 QCOMPARE(e1.token().toString(), e2.token().toString()); 0088 } 0089 0090 //! tests clone and copy ctor for @a e1 0091 template <typename T> 0092 static void testCloneExpression(const T &e1) 0093 { 0094 KDbExpression e1clone = e1.clone(); 0095 //qDebug() << e1; 0096 //qDebug() << e1clone; 0097 QVERIFY(e1 != e1.clone()); 0098 QVERIFY(e1 != e1clone); 0099 QVERIFY(e1.clone() != e1clone); 0100 QVERIFY(e1.expressionClass() == e1clone.expressionClass()); 0101 QVERIFY(e1.token() == e1clone.token()); 0102 compareStrings(e1, e1clone); 0103 0104 const T copied(e1); 0105 QVERIFY(e1 == copied); 0106 QVERIFY(e1.clone() != copied); 0107 QVERIFY(e1.expressionClass() == copied.expressionClass()); 0108 QVERIFY(e1.token() == copied.token()); 0109 compareStrings(e1, copied); 0110 } 0111 0112 //! Validates expression @a expr and shows error message on failure 0113 static bool validate(KDbExpression *expr) 0114 { 0115 KDbParseInfoInternal parseInfo(nullptr); 0116 bool ok = expr->validate(&parseInfo); 0117 if (!ok) { 0118 qInfo() << "Validation of" << *expr << "FAILED."; 0119 if (!parseInfo.errorMessage().isEmpty()) { 0120 qInfo() << "Error message:" << parseInfo.errorMessage(); 0121 } 0122 if (!parseInfo.errorDescription().isEmpty()) { 0123 qInfo() << "Error description:" << parseInfo.errorDescription(); 0124 } 0125 } 0126 return ok; 0127 } 0128 0129 void ExpressionsTest::testNullExpression() 0130 { 0131 QVERIFY(KDbExpression() != KDbExpression()); 0132 0133 KDbExpression e1; 0134 KDbExpression e2; 0135 QVERIFY(e1.isNull()); 0136 QVERIFY(!e1.isValid()); 0137 QVERIFY(!e1.isBinary()); 0138 QVERIFY(e1.toBinary().isNull()); 0139 QVERIFY(!e1.isConst()); 0140 QVERIFY(e1.toConst().isNull()); 0141 QVERIFY(!e1.isFunction()); 0142 QVERIFY(e1.toFunction().isNull()); 0143 QVERIFY(!e1.isNArg()); 0144 QVERIFY(e1.toNArg().isNull()); 0145 QVERIFY(!e1.isQueryParameter()); 0146 QVERIFY(e1.toQueryParameter().isNull()); 0147 QVERIFY(!e1.isUnary()); 0148 QVERIFY(e1.toUnary().isNull()); 0149 QVERIFY(!e1.isVariable()); 0150 QVERIFY(e1.toVariable().isNull()); 0151 QCOMPARE(e1.expressionClass(), KDb::UnknownExpression); 0152 QCOMPARE(e1.token(), KDbToken()); 0153 QVERIFY(e1 != KDbExpression()); 0154 QVERIFY(e1 == e1); 0155 QVERIFY(e1 != e2); 0156 0157 e1 = e2; 0158 QVERIFY(e1.isNull()); 0159 QCOMPARE(e1, e2); 0160 QCOMPARE(e1.toString(nullptr), KDbEscapedString("<UNKNOWN!>")); 0161 QCOMPARE(e1.token().name(), QLatin1String("<INVALID_TOKEN>")); 0162 QCOMPARE(e1.token().toString(nullptr), QString("<INVALID_TOKEN>")); 0163 compareStrings(e1, e2); 0164 0165 KDbExpression e3(e2); 0166 QVERIFY(e3.isNull()); 0167 QCOMPARE(e2, e3); 0168 compareStrings(e2, e3); 0169 //ExpressionDebug << "$$$" << e1.toString() << e1.token() << e1.token().toString(); 0170 0171 e1 = KDbExpression(); 0172 testCloneExpression(e1); 0173 } 0174 0175 void ExpressionsTest::testExpressionClassName_data() 0176 { 0177 QTest::addColumn<KDb::ExpressionClass>("expClass"); 0178 QTest::addColumn<QString>("name"); 0179 0180 int c = 0; 0181 #define T(n, t) ++c; QTest::newRow(n) << t << n 0182 T("Unknown", KDb::UnknownExpression); 0183 T("Unary", KDb::UnaryExpression); 0184 T("Arithm", KDb::ArithmeticExpression); 0185 T("Logical", KDb::LogicalExpression); 0186 T("Relational", KDb::RelationalExpression); 0187 T("SpecialBinary", KDb::SpecialBinaryExpression); 0188 T("Const", KDb::ConstExpression); 0189 T("Variable", KDb::VariableExpression); 0190 T("Function", KDb::FunctionExpression); 0191 T("Aggregation", KDb::AggregationExpression); 0192 T("FieldList", KDb::FieldListExpression); 0193 T("TableList", KDb::TableListExpression); 0194 T("ArgumentList", KDb::ArgumentListExpression); 0195 T("QueryParameter", KDb::QueryParameterExpression); 0196 #undef T 0197 QCOMPARE(c, int(KDb::LastExpressionClass) + 1); 0198 } 0199 0200 void ExpressionsTest::testExpressionClassName() 0201 { 0202 QFETCH(KDb::ExpressionClass, expClass); 0203 QTEST(expressionClassName(expClass), "name"); 0204 } 0205 0206 #include "KDbUtils_p.h" 0207 0208 void ExpressionsTest::testExpressionToken() 0209 { 0210 KDbExpression e1; 0211 QVERIFY(!e1.isValid()); 0212 QVERIFY(!KDbToken().isValid()); 0213 QCOMPARE(e1.token(), KDbToken()); 0214 QVERIFY(KDbToken('+').toChar() > 0); 0215 QCOMPARE(KDbToken('*'), KDbToken('*')); 0216 QCOMPARE(KDbToken('*').toChar(), '*'); 0217 QCOMPARE(KDbToken('*').value(), int('*')); 0218 QCOMPARE(KDbToken('*').name(), QString::fromLatin1("*")); 0219 QCOMPARE(KDbToken('*').toString(), QString::fromLatin1("*")); 0220 QCOMPARE(KDbToken::LEFT.toChar(), char(0)); 0221 QCOMPARE(KDbToken().toChar(), char(0)); 0222 QVERIFY(KDbToken::LEFT.isValid()); 0223 QVERIFY(KDbToken::maxCharTokenValue > 0); 0224 QVERIFY(KDbToken::LEFT.value() > KDbToken::maxCharTokenValue); 0225 const QList<KDbToken> allTokens(KDbToken::allTokens()); 0226 QVERIFY(!allTokens.isEmpty()); 0227 0228 for(const KDbToken &t : allTokens) { 0229 //qDebug() << t << t.value(); 0230 if (t.toChar() > 0) { 0231 QVERIFY(t.value() <= KDbToken::maxCharTokenValue); 0232 QCOMPARE(t, KDbToken(char(t.value()))); 0233 QCOMPARE(t.name(), isprint(t.value()) ? QString(QLatin1Char(uchar(t.value()))) 0234 : QString::number(t.value())); 0235 QCOMPARE(QTest::toString(t), QString::fromLatin1(g_tokenName(t.value())).toLatin1().data()); 0236 } 0237 else { 0238 QCOMPARE(t.name(), QString::fromLatin1(g_tokenName(t.value()))); 0239 } 0240 } 0241 } 0242 0243 void ExpressionsTest::testNArgExpression() 0244 { 0245 KDbNArgExpression n; 0246 KDbNArgExpression n2; 0247 KDbConstExpression c; 0248 KDbConstExpression c1; 0249 KDbConstExpression c2; 0250 KDbConstExpression c3; 0251 0252 // -- empty 0253 KDbNArgExpression emptyNarg; 0254 QVERIFY(emptyNarg.isNArg()); 0255 QVERIFY(emptyNarg.clone().isNArg()); 0256 QVERIFY(emptyNarg.isEmpty()); 0257 QCOMPARE(emptyNarg.argCount(), 0); 0258 QVERIFY(emptyNarg.arg(-1).isNull()); 0259 QVERIFY(emptyNarg.arg(0).isNull()); 0260 QVERIFY(!emptyNarg.containsInvalidArgument()); 0261 QVERIFY(!emptyNarg.containsNullArgument()); 0262 0263 // -- copy ctor & cloning 0264 n = KDbNArgExpression(KDb::ArithmeticExpression, '+'); 0265 c1 = KDbConstExpression(KDbToken::INTEGER_CONST, 7); 0266 c2 = KDbConstExpression(KDbToken::INTEGER_CONST, 8); 0267 n.append(c1); 0268 n.append(c2); 0269 testCloneExpression(n); 0270 0271 // copy on stack 0272 n = KDbNArgExpression(KDb::ArithmeticExpression, '+'); 0273 { 0274 KDbConstExpression s1(KDbToken::INTEGER_CONST, 7); 0275 KDbConstExpression s2(KDbToken::INTEGER_CONST, 8); 0276 n.append(s1); 0277 n.append(s2); 0278 c1 = s1; 0279 c2 = s2; 0280 } 0281 QCOMPARE(n.argCount(), 2); 0282 QCOMPARE(n.arg(0).toConst(), c1); 0283 QCOMPARE(n.arg(1).toConst(), c2); 0284 0285 QCOMPARE(n.token().name(), QString("+")); 0286 QCOMPARE(n.toString(nullptr), KDbEscapedString("7, 8")); 0287 n.setToken('*'); 0288 QCOMPARE(n.token().name(), QString("*")); 0289 0290 // -- append(KDbExpression), prepend(KDbExpression) 0291 KDbExpression e; 0292 KDbNArgExpression nNull; 0293 QCOMPARE(nNull.argCount(), 0); // empty 0294 nNull.append(e); 0295 QCOMPARE(nNull.argCount(), 1); // n-arg expression can have null elements 0296 nNull = KDbNArgExpression(); 0297 QCOMPARE(nNull.argCount(), 0); // cleared 0298 0299 n = KDbNArgExpression(KDb::ArithmeticExpression, '+'); 0300 c1 = KDbConstExpression(KDbToken::INTEGER_CONST, 1); 0301 n.append(c1); 0302 QVERIFY(!n.isEmpty()); 0303 QCOMPARE(n.argCount(), 1); 0304 QCOMPARE(n.arg(0).toConst(), c1); 0305 QCOMPARE(c1.parent().toNArg(), n); 0306 0307 n = KDbNArgExpression(KDb::ArithmeticExpression, '+'); 0308 n.append(n); 0309 QCOMPARE(n.argCount(), 0); // append should fail since appending expression 0310 // to itself is not allowed 0311 n.prepend(n); 0312 QCOMPARE(n.argCount(), 0); // append should fail since prepending expression 0313 // to itself is not allowed 0314 0315 n = KDbNArgExpression(KDb::ArithmeticExpression, '+'); 0316 c1 = KDbConstExpression(KDbToken::INTEGER_CONST, 2); 0317 n.append(c1); 0318 n.append(c1); // cannot append the same expression twice 0319 QCOMPARE(n.argCount(), 1); 0320 QCOMPARE(n.arg(0).toConst(), c1); 0321 0322 n = KDbNArgExpression(KDb::ArithmeticExpression, '+'); 0323 c1 = KDbConstExpression(KDbToken::INTEGER_CONST, 3); 0324 n.prepend(c1); 0325 n.prepend(c1); // cannot prepend the same expression twice 0326 QCOMPARE(n.argCount(), 1); 0327 QCOMPARE(n.arg(0).toConst(), c1); 0328 n.append(c1); // cannot append/prepend the same expression twice 0329 QCOMPARE(n.argCount(), 1); 0330 QCOMPARE(n.arg(0).toConst(), c1); 0331 0332 n = KDbNArgExpression(KDb::ArithmeticExpression, '+'); 0333 n2 = KDbNArgExpression(KDb::ArithmeticExpression, '+'); 0334 c1 = KDbConstExpression(KDbToken::INTEGER_CONST, 4); 0335 n.append(c1); 0336 n2.append(c1); // c moves from n to n2 0337 QVERIFY(n.isEmpty()); 0338 QCOMPARE(n2.argCount(), 1); 0339 QCOMPARE(c1.parent().toNArg(), n2); 0340 n.prepend(c1); // c moves from n2 to n 0341 QCOMPARE(n.argCount(), 1); 0342 QVERIFY(n2.isEmpty()); 0343 QCOMPARE(c1.parent().toNArg(), n); 0344 0345 // -- insert(int, KDbExpression) 0346 n = KDbNArgExpression(KDb::ArithmeticExpression, '+'); 0347 c1 = KDbConstExpression(KDbToken::INTEGER_CONST, 3); 0348 c2 = KDbConstExpression(KDbToken::INTEGER_CONST, 4); 0349 // it must be a valid index position in the list (i.e., 0 <= i < argCount()). 0350 n.insert(-10, c1); 0351 QVERIFY(n.isEmpty()); 0352 n.insert(1, c1); 0353 QVERIFY(n.isEmpty()); 0354 // if i is 0, the expression is prepended to the list of arguments 0355 n.insert(0, c1); 0356 QCOMPARE(n.arg(0).toConst(), c1); 0357 QCOMPARE(n.argCount(), 1); 0358 QCOMPARE(c1.parent().toNArg(), n); 0359 n.insert(0, c2); 0360 QCOMPARE(n.argCount(), 2); 0361 QCOMPARE(n.arg(0).toConst(), c2); 0362 QCOMPARE(n.arg(1).toConst(), c1); 0363 0364 // if i is argCount(), the value is appended to the list of arguments 0365 n = KDbNArgExpression(KDb::ArithmeticExpression, '+'); 0366 n.insert(0, c1); 0367 n.insert(1, c2); 0368 QCOMPARE(n.argCount(), 2); 0369 QCOMPARE(n.arg(0).toConst(), c1); 0370 QCOMPARE(n.arg(1).toConst(), c2); 0371 0372 // expression cannot be own child 0373 n = KDbNArgExpression(KDb::ArithmeticExpression, '+'); 0374 n.insert(0, n); 0375 QVERIFY(n.isEmpty()); 0376 0377 // cannot insert child twice 0378 n = KDbNArgExpression(KDb::ArithmeticExpression, '+'); 0379 n.insert(0, c1); 0380 n.insert(1, c1); 0381 QCOMPARE(n.argCount(), 1); 0382 0383 // -- remove(KDbExpression) 0384 n = KDbNArgExpression(KDb::ArithmeticExpression, '+'); 0385 n.append(c1); 0386 n.append(c2); 0387 n.remove(c1); // remove first 0388 QCOMPARE(n.argCount(), 1); 0389 QCOMPARE(n.arg(0).toConst(), c2); 0390 0391 // -- remove(KDbExpression) 0392 n = KDbNArgExpression(KDb::ArithmeticExpression, '+'); 0393 n.prepend(c1); 0394 n.append(c2); 0395 c3 = KDbConstExpression(KDbToken::INTEGER_CONST, 5); 0396 QVERIFY(!n.remove(c3)); // not found 0397 QCOMPARE(n.argCount(), 2); 0398 n.append(c3); 0399 QCOMPARE(n.argCount(), 3); 0400 QVERIFY(n.remove(c2)); // remove 2nd of 3, leaves c1 and c3 0401 QCOMPARE(n.argCount(), 2); 0402 QCOMPARE(n.arg(0).toConst(), c1); 0403 QCOMPARE(n.arg(1).toConst(), c3); 0404 0405 // -- removeAt(int) 0406 n = KDbNArgExpression(KDb::ArithmeticExpression, '+'); 0407 n.prepend(c1); 0408 n.append(c2); 0409 n.removeAt(-1); // not found 0410 QCOMPARE(n.argCount(), 2); 0411 n.removeAt(3); // not found 0412 QCOMPARE(n.argCount(), 2); 0413 n.append(c3); 0414 n.removeAt(1); // remove 2nd of 3, leaves c1 and c3 0415 QCOMPARE(n.argCount(), 2); 0416 QCOMPARE(n.arg(0).toConst(), c1); 0417 QCOMPARE(n.arg(1).toConst(), c3); 0418 n.removeAt(0); 0419 QCOMPARE(n.argCount(), 1); 0420 n.removeAt(0); 0421 QCOMPARE(n.argCount(), 0); 0422 0423 // -- takeAt(int) 0424 n = KDbNArgExpression(KDb::ArithmeticExpression, '+'); 0425 n2 = n; 0426 c1 = KDbConstExpression(KDbToken::INTEGER_CONST, 1); 0427 c2 = KDbConstExpression(KDbToken::INTEGER_CONST, 2); 0428 c3 = KDbConstExpression(KDbToken::INTEGER_CONST, 3); 0429 n.append(c1); 0430 n.append(c2); 0431 n.append(c3); 0432 n.takeAt(-1); // not found 0433 QCOMPARE(n.argCount(), 3); 0434 n.takeAt(3); // not found 0435 QCOMPARE(n.argCount(), 3); 0436 e = n.takeAt(1); 0437 QCOMPARE(e.toConst(), c2); // e is 2nd 0438 QCOMPARE(n.argCount(), 2); // 1 arg taken 0439 QCOMPARE(n, n2); 0440 0441 // -- indexOf(KDbExpression, int) 0442 n = KDbNArgExpression(KDb::ArithmeticExpression, '+'); 0443 c = KDbConstExpression(KDbToken::INTEGER_CONST, 0); 0444 c1 = KDbConstExpression(KDbToken::INTEGER_CONST, 1); 0445 c2 = KDbConstExpression(KDbToken::INTEGER_CONST, 2); 0446 c3 = KDbConstExpression(KDbToken::INTEGER_CONST, 3); 0447 n.append(c1); 0448 n.append(c2); 0449 n.append(c3); 0450 0451 QCOMPARE(n.indexOf(c), -1); 0452 QCOMPARE(n.indexOf(c1), 0); 0453 QCOMPARE(n.indexOf(c2), 1); 0454 QCOMPARE(n.indexOf(c3), 2); 0455 QCOMPARE(n.indexOf(c1, 1), -1); 0456 QCOMPARE(n.indexOf(c2, 1), 1); 0457 0458 // -- lastIndexOf(KDbExpression, int) 0459 QCOMPARE(n.lastIndexOf(c), -1); 0460 QCOMPARE(n.lastIndexOf(c1), 0); 0461 QCOMPARE(n.lastIndexOf(c2), 1); 0462 QCOMPARE(n.lastIndexOf(c3), 2); 0463 QCOMPARE(n.lastIndexOf(c1, 1), 0); 0464 QCOMPARE(n.lastIndexOf(c2, 0), -1); 0465 0466 // -- a list of arguments 0467 n = KDbNArgExpression(KDb::ArgumentListExpression, ','); 0468 n.append(KDbConstExpression(KDbToken::INTEGER_CONST, 1)); 0469 n.append(KDbConstExpression(KDbToken::INTEGER_CONST, 2)); 0470 n.append(KDbConstExpression(KDbToken::INTEGER_CONST, 3)); 0471 QCOMPARE(n.toString(nullptr), KDbEscapedString("1, 2, 3")); 0472 QCOMPARE(n.argCount(), 3); 0473 QVERIFY(!n.containsInvalidArgument()); 0474 QVERIFY(!n.containsNullArgument()); 0475 0476 // -- a list of arguments contains invalid argument 0477 n = KDbNArgExpression(KDb::ArgumentListExpression, ','); 0478 n.append(KDbConstExpression(KDbToken::INTEGER_CONST, 1)); 0479 n.append(KDbExpression()); 0480 n.append(KDbConstExpression(KDbToken::INTEGER_CONST, 3)); 0481 QVERIFY(n.containsInvalidArgument()); 0482 QVERIFY(!n.containsNullArgument()); 0483 QVERIFY(!n.isNull()); 0484 QCOMPARE(n.toString(nullptr), KDbEscapedString("1, <UNKNOWN!>, 3")); 0485 0486 // -- a list of arguments contains null argument 0487 n = KDbNArgExpression(KDb::ArgumentListExpression, ','); 0488 n.append(KDbConstExpression(KDbToken::INTEGER_CONST, 1)); 0489 n.append(KDbConstExpression(KDbToken::SQL_NULL, QVariant())); 0490 n.prepend(KDbConstExpression(KDbToken::INTEGER_CONST, 0)); 0491 QVERIFY(!n.containsInvalidArgument()); 0492 QVERIFY(n.containsNullArgument()); 0493 QCOMPARE(n.toString(nullptr), KDbEscapedString("0, 1, NULL")); 0494 } 0495 0496 void ExpressionsTest::testUnaryExpression() 0497 { 0498 KDbUnaryExpression u; 0499 KDbUnaryExpression u2; 0500 KDbConstExpression c; 0501 KDbConstExpression c1; 0502 0503 // -- empty 0504 KDbUnaryExpression emptyUnary; 0505 QVERIFY(emptyUnary.isUnary()); 0506 QVERIFY(emptyUnary.clone().isUnary()); 0507 QVERIFY(emptyUnary.arg().isNull()); 0508 0509 u = KDbUnaryExpression('-', KDbExpression()); 0510 QVERIFY(u.arg().isNull()); 0511 0512 // -- copy ctor & cloning 0513 c1 = KDbConstExpression(KDbToken::INTEGER_CONST, 7); 0514 u = KDbUnaryExpression('-', c1); 0515 testCloneExpression(u); 0516 QCOMPARE(u.token().name(), QString("-")); 0517 QCOMPARE(u.toString(nullptr), KDbEscapedString("-7")); 0518 QCOMPARE(c1, u.arg().toConst()); 0519 0520 u2 = KDbUnaryExpression('-', u); 0521 testCloneExpression(u); 0522 QCOMPARE(u2.token().name(), QString("-")); 0523 QCOMPARE(u2.toString(nullptr), KDbEscapedString("--7")); 0524 QCOMPARE(u, u2.arg().toUnary()); 0525 0526 u = KDbUnaryExpression('(', c1); 0527 testCloneExpression(u); 0528 QCOMPARE(u.toString(nullptr), KDbEscapedString("(7)")); 0529 QCOMPARE(c1, u.arg().toConst()); 0530 0531 c1 = KDbConstExpression(KDbToken::SQL_TRUE, true); 0532 u = KDbUnaryExpression(KDbToken::NOT, c1); 0533 testCloneExpression(u); 0534 QCOMPARE(u.toString(nullptr), KDbEscapedString("NOT TRUE")); 0535 QCOMPARE(c1, u.arg().toConst()); 0536 0537 c1 = KDbConstExpression(KDbToken::SQL_NULL, QVariant()); 0538 u = KDbUnaryExpression(KDbToken::NOT, c1); 0539 testCloneExpression(u); 0540 QCOMPARE(u.toString(nullptr), KDbEscapedString("NOT NULL")); 0541 QCOMPARE(c1, u.arg().toConst()); 0542 0543 c1 = KDbConstExpression(KDbToken::SQL_NULL, QVariant()); 0544 u = KDbUnaryExpression(KDbToken::SQL_IS_NULL, c1); 0545 testCloneExpression(u); 0546 QCOMPARE(u.toString(nullptr), KDbEscapedString("NULL IS NULL")); 0547 QCOMPARE(c1, u.arg().toConst()); 0548 0549 c1 = KDbConstExpression(KDbToken::SQL_NULL, QVariant()); 0550 u = KDbUnaryExpression(KDbToken::SQL_IS_NOT_NULL, c1); 0551 testCloneExpression(u); 0552 QCOMPARE(u.toString(nullptr), KDbEscapedString("NULL IS NOT NULL")); 0553 QCOMPARE(c1, u.arg().toConst()); 0554 0555 c1 = KDbConstExpression(KDbToken::INTEGER_CONST, 17); 0556 u = KDbUnaryExpression(KDbToken::SQL, c1); 0557 testCloneExpression(u); 0558 QCOMPARE(u.toString(nullptr), KDbEscapedString("SQL 17")); 0559 QCOMPARE(c1, u.arg().toConst()); 0560 0561 // -- exchanging arg between two unary expressions 0562 c = KDbConstExpression(KDbToken::INTEGER_CONST, 17); 0563 u = KDbUnaryExpression('-', c); 0564 c1 = KDbConstExpression(KDbToken::INTEGER_CONST, 3); 0565 u2 = KDbUnaryExpression('+', c1); 0566 u2.setArg(c); // this should take c arg from u to u2 0567 QCOMPARE(c, u2.arg().toConst()); // c is now in u2 0568 QVERIFY(u.arg().isNull()); // u has null arg now 0569 0570 c = KDbConstExpression(KDbToken::INTEGER_CONST, 17); 0571 u = KDbUnaryExpression('-', c); 0572 u2 = KDbUnaryExpression('+', c); 0573 // u2 takes c arg from u 0574 QCOMPARE(c, u2.arg().toConst()); // c is now in u2 0575 QVERIFY(u.arg().isNull()); // u has null arg now 0576 0577 // -- cycles 0578 c = KDbConstExpression(KDbToken::INTEGER_CONST, 17); 0579 u = KDbUnaryExpression('-', c); 0580 c1 = KDbConstExpression(KDbToken::INTEGER_CONST, 3); 0581 u2 = KDbUnaryExpression('+', c1); 0582 u2.setArg(u); 0583 u.setArg(u2); 0584 0585 QTest::ignoreMessage(QtWarningMsg, R"w(Cycle detected in expression (depth 2): 0586 1: Unary - 0587 2: Unary +)w"); 0588 QCOMPARE(u.toString(nullptr), KDbEscapedString("-+<CYCLE!>")); 0589 0590 QTest::ignoreMessage(QtWarningMsg, R"w(Cycle detected in expression (depth 2): 0591 1: Unary + 0592 2: Unary -)w"); 0593 QCOMPARE(u2.toString(nullptr), KDbEscapedString("+-<CYCLE!>")); 0594 } 0595 0596 void ExpressionsTest::testBinaryExpression() 0597 { 0598 KDbBinaryExpression b; 0599 KDbBinaryExpression b2; 0600 KDbConstExpression c; 0601 KDbConstExpression c1; 0602 0603 // -- empty 0604 KDbBinaryExpression emptyBinary; 0605 QVERIFY(emptyBinary.isNull()); 0606 QVERIFY(emptyBinary.isBinary()); 0607 QVERIFY(emptyBinary.clone().isBinary()); 0608 QVERIFY(emptyBinary.left().isNull()); 0609 QVERIFY(emptyBinary.right().isNull()); 0610 0611 QTest::ignoreMessage(QtWarningMsg, 0612 "Setting KDbBinaryExpression to null because left argument is not specified"); 0613 b = KDbBinaryExpression(KDbExpression(), '-', KDbExpression()); 0614 QVERIFY(b.left().isNull()); 0615 QVERIFY(b.right().isNull()); 0616 QVERIFY(b.isNull()); // it's null because args are null 0617 //qDebug() << b.toString(nullptr); 0618 QCOMPARE(b.toString(nullptr), KDbEscapedString("<UNKNOWN!>")); 0619 c = KDbConstExpression(KDbToken::INTEGER_CONST, 10); 0620 QTest::ignoreMessage(QtWarningMsg, 0621 "Setting KDbBinaryExpression to null because right argument is not specified"); 0622 b = KDbBinaryExpression(c, '-', KDbExpression()); 0623 QVERIFY(b.left().isNull()); 0624 QVERIFY(b.right().isNull()); 0625 QVERIFY(b.isNull()); // it's null because one arg is null 0626 //qDebug() << b.toString(nullptr); 0627 QCOMPARE(b.toString(nullptr), KDbEscapedString("<UNKNOWN!>")); 0628 QTest::ignoreMessage(QtWarningMsg, 0629 "Setting KDbBinaryExpression to null because left argument is not specified"); 0630 b = KDbBinaryExpression(KDbExpression(), '-', c); 0631 QVERIFY(b.left().isNull()); 0632 QVERIFY(b.right().isNull()); 0633 QVERIFY(b.isNull()); // it's null because one arg is null 0634 //qDebug() << b.toString(nullptr); 0635 QCOMPARE(b.toString(nullptr), KDbEscapedString("<UNKNOWN!>")); 0636 0637 // -- copy ctor & cloning 0638 c = KDbConstExpression(KDbToken::INTEGER_CONST, 3); 0639 c1 = KDbConstExpression(KDbToken::INTEGER_CONST, 4); 0640 b = KDbBinaryExpression(c, '/', c1); 0641 testCloneExpression(b); 0642 QCOMPARE(b.token().name(), QString("/")); 0643 QCOMPARE(b.toString(nullptr), KDbEscapedString("3 / 4")); 0644 QCOMPARE(c1, b.right().toConst()); 0645 0646 b2 = KDbBinaryExpression(b, '*', b.clone()); 0647 testCloneExpression(b2); 0648 QCOMPARE(b2.token().name(), QString("*")); 0649 QCOMPARE(b2.toString(nullptr), KDbEscapedString("3 / 4 * 3 / 4")); 0650 QCOMPARE(b, b2.left().toBinary()); 0651 0652 // -- cycles 0653 // --- ref to parent 0654 b = KDbBinaryExpression( 0655 KDbConstExpression(KDbToken::INTEGER_CONST, 1), '+', KDbConstExpression(KDbToken::INTEGER_CONST, 2)); 0656 KDbEscapedString s = b.toString(nullptr); 0657 QTest::ignoreMessage(QtWarningMsg, 0658 QRegularExpression("Expression BinaryExp(.*) cannot be set as own child")); 0659 b.setLeft(b); // should not work 0660 //qDebug() << b.toString(nullptr); 0661 QCOMPARE(s, b.toString(nullptr)); 0662 // --- cannot set twice 0663 c = b.left().toConst(); 0664 b.setLeft(c); 0665 QCOMPARE(s, b.toString(nullptr)); 0666 // --- ref to grandparent 0667 b = KDbBinaryExpression( 0668 KDbConstExpression(KDbToken::INTEGER_CONST, 1), '+', KDbConstExpression(KDbToken::INTEGER_CONST, 2)); 0669 c = KDbConstExpression(KDbToken::INTEGER_CONST, 10); 0670 b2 = KDbBinaryExpression(b, '-', c); 0671 //qDebug() << b2.toString(nullptr); 0672 QCOMPARE(b2.toString(nullptr), KDbEscapedString("1 + 2 - 10")); 0673 QTest::ignoreMessage(QtWarningMsg, R"w(Cycle detected in expression (depth 2): 0674 1: Arithm - 0675 2: Arithm +)w"); 0676 b.setRight(b2); 0677 //qDebug() << b2.toString(nullptr); 0678 QCOMPARE(b2.toString(nullptr), KDbEscapedString("1 + <CYCLE!> - 10")); 0679 0680 // -- moving right argument to left should remove right arg 0681 b = KDbBinaryExpression( 0682 KDbConstExpression(KDbToken::INTEGER_CONST, 1), '+', KDbConstExpression(KDbToken::INTEGER_CONST, 2)); 0683 c = b.right().toConst(); 0684 b.setLeft(c); 0685 //qDebug() << b.toString(nullptr); 0686 QCOMPARE(b.toString(nullptr), KDbEscapedString("2 + <UNKNOWN!>")); 0687 0688 // -- moving left argument to right should remove left arg 0689 b = KDbBinaryExpression( 0690 KDbConstExpression(KDbToken::INTEGER_CONST, 1), '+', KDbConstExpression(KDbToken::INTEGER_CONST, 2)); 0691 c = b.left().toConst(); 0692 b.setRight(c); 0693 //qDebug() << b.toString(nullptr); 0694 QCOMPARE(b.toString(nullptr), KDbEscapedString("<UNKNOWN!> + 1")); 0695 } 0696 0697 void ExpressionsTest::testBinaryExpressionCloning_data() 0698 { 0699 QTest::addColumn<KDbToken>("type1"); 0700 QTest::addColumn<QVariant>("const1"); 0701 QTest::addColumn<KDbToken>("token"); 0702 QTest::addColumn<KDbToken>("type2"); 0703 QTest::addColumn<QVariant>("const2"); 0704 QTest::addColumn<QString>("string"); 0705 0706 #define T(type1, const1, token, type2, const2, string) \ 0707 QTest::newRow(qPrintable(TO_TOKEN(token).name())) \ 0708 << type1 << QVariant(const1) << TO_TOKEN(token) \ 0709 << type2 << QVariant(const2) << QString(string) 0710 0711 T(KDbToken::INTEGER_CONST, 3, '/', KDbToken::INTEGER_CONST, 4, "3 / 4"); 0712 T(KDbToken::INTEGER_CONST, 3, KDbToken::BITWISE_SHIFT_RIGHT, KDbToken::INTEGER_CONST, 4, "3 >> 4"); 0713 T(KDbToken::INTEGER_CONST, 3, KDbToken::BITWISE_SHIFT_LEFT, KDbToken::INTEGER_CONST, 4, "3 << 4"); 0714 T(KDbToken::INTEGER_CONST, 3, KDbToken::NOT_EQUAL, KDbToken::INTEGER_CONST, 4, "3 <> 4"); 0715 T(KDbToken::INTEGER_CONST, 3, KDbToken::NOT_EQUAL2, KDbToken::INTEGER_CONST, 4, "3 != 4"); 0716 T(KDbToken::INTEGER_CONST, 3, KDbToken::LESS_OR_EQUAL, KDbToken::INTEGER_CONST, 4, "3 <= 4"); 0717 T(KDbToken::INTEGER_CONST, 3, KDbToken::GREATER_OR_EQUAL, KDbToken::INTEGER_CONST, 4, "3 >= 4"); 0718 T(KDbToken::CHARACTER_STRING_LITERAL, "ABC", KDbToken::LIKE, KDbToken::CHARACTER_STRING_LITERAL, "A%", "'ABC' LIKE 'A%'"); 0719 T(KDbToken::INTEGER_CONST, 3, KDbToken::SQL_IN, KDbToken::INTEGER_CONST, 4, "3 IN 4"); 0720 T(KDbToken::INTEGER_CONST, 3, KDbToken::SIMILAR_TO, KDbToken::INTEGER_CONST, 4, "3 SIMILAR TO 4"); 0721 T(KDbToken::INTEGER_CONST, 3, KDbToken::NOT_SIMILAR_TO, KDbToken::INTEGER_CONST, 4, "3 NOT SIMILAR TO 4"); 0722 T(KDbToken::SQL_TRUE, true, KDbToken::OR, KDbToken::SQL_FALSE, false, "TRUE OR FALSE"); 0723 T(KDbToken::INTEGER_CONST, 3, KDbToken::AND, KDbToken::INTEGER_CONST, 4, "3 AND 4"); 0724 T(KDbToken::INTEGER_CONST, 3, KDbToken::XOR, KDbToken::INTEGER_CONST, 4, "3 XOR 4"); 0725 T(KDbToken::CHARACTER_STRING_LITERAL, "AB", KDbToken::CONCATENATION, KDbToken::CHARACTER_STRING_LITERAL, "CD", "'AB' || 'CD'"); 0726 T(KDbToken::CHARACTER_STRING_LITERAL, "AB", '+', KDbToken::CHARACTER_STRING_LITERAL, "CD", "'AB' + 'CD'"); 0727 #undef T 0728 } 0729 0730 void ExpressionsTest::testBinaryExpressionCloning() 0731 { 0732 QFETCH(KDbToken, type1); 0733 QFETCH(QVariant, const1); 0734 QFETCH(KDbToken, token); 0735 QFETCH(KDbToken, type2); 0736 QFETCH(QVariant, const2); 0737 QFETCH(QString, string); 0738 0739 KDbConstExpression c(type1, const1); 0740 KDbConstExpression c1(type2, const2); 0741 KDbBinaryExpression b(c, token, c1); 0742 testCloneExpression(b); 0743 QCOMPARE(b.token(), token); 0744 QCOMPARE(b.token().name(), token.name()); 0745 //qDebug() << token << b; 0746 QCOMPARE(b.toString(nullptr), KDbEscapedString(string)); 0747 QCOMPARE(c, b.left().toConst()); 0748 QCOMPARE(c1, b.right().toConst()); 0749 } 0750 0751 void ExpressionsTest::testFunctionExpression() 0752 { 0753 KDbFunctionExpression emptyFunction; 0754 QVERIFY(emptyFunction.isFunction()); 0755 QVERIFY(emptyFunction.clone().isFunction()); 0756 QVERIFY(emptyFunction.arguments().isEmpty()); 0757 QVERIFY(emptyFunction.isNull()); 0758 0759 KDbNArgExpression args; 0760 args.append(KDbConstExpression(KDbToken::CHARACTER_STRING_LITERAL, "abc")); 0761 args.append(KDbConstExpression(KDbToken::INTEGER_CONST, 2)); 0762 KDbFunctionExpression f_substr("SUBSTR", args); 0763 //qDebug() << f_substr.toString(); 0764 //qDebug() << f_substr.token().name(); 0765 //qDebug() << f_substr.token().toString(); 0766 0767 testCloneExpression(f_substr); 0768 QCOMPARE(f_substr.type(), KDbField::Text); 0769 0770 args.append(KDbConstExpression(KDbToken::INTEGER_CONST, 1)); 0771 KDbFunctionExpression f_substr2("SUBSTR", args); 0772 testCloneExpression(f_substr2); 0773 QCOMPARE(f_substr2.type(), KDbField::Text); 0774 //qDebug() << f_substr.toString(); 0775 //qDebug() << f_substr2.toString(); 0776 QVERIFY(f_substr != f_substr2); // other objects 0777 QCOMPARE(f_substr.toString(nullptr), f_substr2.toString(nullptr)); // the same signatures 0778 QCOMPARE(f_substr.arguments(), f_substr2.arguments()); // the same arg lists 0779 0780 // clone the args 0781 KDbNArgExpression args2 = args.clone().toNArg(); 0782 //qDebug() << f_substr2; 0783 f_substr2.setArguments(args2); 0784 //qDebug() << f_substr2; 0785 QCOMPARE(f_substr.toString(nullptr), f_substr2.toString(nullptr)); // still the same signatures 0786 QVERIFY(f_substr.arguments() != f_substr2.arguments()); // not the same arg lists 0787 0788 KDbExpression e = f_substr; 0789 QCOMPARE(e.toFunction(), f_substr); 0790 QCOMPARE(e.toFunction(), f_substr.toFunction()); 0791 QVERIFY(e.isFunction()); 0792 0793 // nested functions 0794 f_substr2.arguments().replace(0, f_substr); 0795 QCOMPARE(f_substr2.type(), KDbField::Text); 0796 } 0797 0798 void ExpressionsTest::testConstExpressionValidate() 0799 { 0800 KDbConstExpression c; 0801 0802 c = KDbConstExpression(KDbToken::SQL_NULL, QVariant()); 0803 QCOMPARE(c.type(), KDbField::Null); 0804 QVERIFY(c.isValid()); 0805 QVERIFY(!c.isNull()); 0806 QVERIFY(validate(&c)); 0807 0808 // null 0809 c = KDbConstExpression(KDbToken::SQL_NULL, QVariant()); 0810 QCOMPARE(c.type(), KDbField::Null); 0811 QVERIFY(validate(&c)); 0812 testCloneExpression(c); 0813 //qDebug() << c; 0814 0815 // integer 0816 c = KDbConstExpression(KDbToken::INTEGER_CONST, -0x7f); 0817 QCOMPARE(c.type(), KDbField::Byte); 0818 QVERIFY(c.isValid()); 0819 QVERIFY(c.isNumericType()); 0820 QVERIFY(!c.isNull()); 0821 QCOMPARE(c.value(), QVariant(-0x7f)); 0822 QVERIFY(validate(&c)); 0823 testCloneExpression(c); 0824 c.setValue(-0x80); 0825 QCOMPARE(c.type(), KDbField::ShortInteger); // type has been changed by setValue 0826 QCOMPARE(c.value(), QVariant(-0x80)); 0827 QVERIFY(validate(&c)); 0828 testCloneExpression(c); 0829 //qDebug() << c; 0830 0831 c = KDbConstExpression(KDbToken::INTEGER_CONST, -10); 0832 QCOMPARE(c.type(), KDbField::Byte); 0833 QVERIFY(c.isValid()); 0834 QVERIFY(c.isNumericType()); 0835 QCOMPARE(c.value(), QVariant(-10)); 0836 QVERIFY(validate(&c)); 0837 testCloneExpression(c); 0838 //qDebug() << c; 0839 0840 c = KDbConstExpression(KDbToken::INTEGER_CONST, 0); 0841 QCOMPARE(c.type(), KDbField::Byte); 0842 QVERIFY(c.isValid()); 0843 QVERIFY(c.isNumericType()); 0844 QCOMPARE(c.value(), QVariant(0)); 0845 QVERIFY(validate(&c)); 0846 testCloneExpression(c); 0847 //qDebug() << c; 0848 0849 c = KDbConstExpression(KDbToken::INTEGER_CONST, 20); 0850 QCOMPARE(c.type(), KDbField::Byte); 0851 QVERIFY(c.isValid()); 0852 QVERIFY(c.isNumericType()); 0853 QCOMPARE(c.value(), QVariant(20)); 0854 QVERIFY(validate(&c)); 0855 testCloneExpression(c); 0856 //qDebug() << c; 0857 0858 c = KDbConstExpression(KDbToken::INTEGER_CONST, 255); 0859 QCOMPARE(c.type(), KDbField::Byte); 0860 QVERIFY(c.isValid()); 0861 QVERIFY(c.isNumericType()); 0862 QCOMPARE(c.value(), QVariant(255)); 0863 QVERIFY(validate(&c)); 0864 testCloneExpression(c); 0865 //qDebug() << c; 0866 0867 c = KDbConstExpression(KDbToken::INTEGER_CONST, -0x80); 0868 QCOMPARE(c.type(), KDbField::ShortInteger); 0869 QVERIFY(c.isValid()); 0870 QVERIFY(c.isNumericType()); 0871 QCOMPARE(c.value(), QVariant(-0x80)); 0872 QVERIFY(validate(&c)); 0873 testCloneExpression(c); 0874 //qDebug() << c; 0875 0876 c = KDbConstExpression(KDbToken::INTEGER_CONST, -0x7fff); 0877 QCOMPARE(c.type(), KDbField::ShortInteger); 0878 QVERIFY(c.isValid()); 0879 QVERIFY(c.isNumericType()); 0880 QCOMPARE(c.value(), QVariant(-0x7fff)); 0881 QVERIFY(validate(&c)); 0882 testCloneExpression(c); 0883 //qDebug() << c; 0884 0885 c = KDbConstExpression(KDbToken::INTEGER_CONST, 256); 0886 QCOMPARE(c.type(), KDbField::ShortInteger); 0887 QVERIFY(c.isValid()); 0888 QVERIFY(c.isNumericType()); 0889 QCOMPARE(c.value(), QVariant(256)); 0890 QVERIFY(validate(&c)); 0891 testCloneExpression(c); 0892 //qDebug() << c; 0893 0894 c = KDbConstExpression(KDbToken::INTEGER_CONST, 0xffff); 0895 QCOMPARE(c.type(), KDbField::ShortInteger); 0896 QVERIFY(c.isValid()); 0897 QVERIFY(c.isNumericType()); 0898 QCOMPARE(c.value(), QVariant(0xffff)); 0899 QVERIFY(validate(&c)); 0900 testCloneExpression(c); 0901 //qDebug() << c; 0902 0903 c = KDbConstExpression(KDbToken::INTEGER_CONST, -0x8000); 0904 QCOMPARE(c.type(), KDbField::Integer); 0905 QVERIFY(c.isValid()); 0906 QVERIFY(c.isNumericType()); 0907 QCOMPARE(c.value(), QVariant(-0x8000)); 0908 QVERIFY(validate(&c)); 0909 testCloneExpression(c); 0910 //qDebug() << c; 0911 0912 c = KDbConstExpression(KDbToken::INTEGER_CONST, uint(0x10000)); 0913 QCOMPARE(c.type(), KDbField::Integer); 0914 QVERIFY(c.isValid()); 0915 QVERIFY(c.isNumericType()); 0916 QCOMPARE(c.value(), QVariant(0x10000)); 0917 QVERIFY(validate(&c)); 0918 testCloneExpression(c); 0919 //qDebug() << c; 0920 0921 c = KDbConstExpression(KDbToken::INTEGER_CONST, qlonglong(-0x100000)); 0922 QCOMPARE(c.type(), KDbField::BigInteger); 0923 QVERIFY(c.isValid()); 0924 QVERIFY(c.isNumericType()); 0925 QCOMPARE(c.value(), QVariant(-0x100000)); 0926 QVERIFY(validate(&c)); 0927 testCloneExpression(c); 0928 //qDebug() << c; 0929 0930 c = KDbConstExpression(KDbToken::INTEGER_CONST, qulonglong(0x1000000)); 0931 QCOMPARE(c.type(), KDbField::BigInteger); 0932 QVERIFY(c.isValid()); 0933 QVERIFY(c.isNumericType()); 0934 QCOMPARE(c.value(), QVariant(0x1000000)); 0935 QVERIFY(validate(&c)); 0936 testCloneExpression(c); 0937 //qDebug() << c; 0938 0939 // string 0940 int oldMaxLen = KDbField::defaultMaxLength(); // save 0941 KDbField::setDefaultMaxLength(0); 0942 c = KDbConstExpression(KDbToken::CHARACTER_STRING_LITERAL, "01234567890"); 0943 QVERIFY(c.isValid()); 0944 QVERIFY(c.isTextType()); 0945 QCOMPARE(c.type(), KDbField::Text); 0946 QCOMPARE(c.value(), QVariant("01234567890")); 0947 QVERIFY(validate(&c)); 0948 testCloneExpression(c); 0949 //qDebug() << c; 0950 0951 KDbField::setDefaultMaxLength(10); 0952 c = KDbConstExpression(KDbToken::CHARACTER_STRING_LITERAL, QString()); 0953 QCOMPARE(c.type(), KDbField::Text); 0954 QVERIFY(c.isValid()); 0955 QVERIFY(c.isTextType()); 0956 QCOMPARE(c.value(), QVariant(QString())); 0957 QVERIFY(validate(&c)); 0958 testCloneExpression(c); 0959 //qDebug() << c; 0960 0961 c = KDbConstExpression(KDbToken::CHARACTER_STRING_LITERAL, QVariant()); 0962 QCOMPARE(c.type(), KDbField::Text); 0963 QVERIFY(c.isValid()); 0964 QVERIFY(c.isTextType()); 0965 QCOMPARE(c.value(), QVariant()); 0966 QVERIFY(validate(&c)); 0967 testCloneExpression(c); 0968 //qDebug() << c; 0969 0970 c = KDbConstExpression(KDbToken::CHARACTER_STRING_LITERAL, "01234567890"); 0971 QCOMPARE(c.type(), KDbField::LongText); 0972 QVERIFY(c.isValid()); 0973 QVERIFY(c.isTextType()); 0974 QCOMPARE(c.value(), QVariant("01234567890")); 0975 QVERIFY(validate(&c)); 0976 //qDebug() << c; 0977 c.setValue("ąćę"); 0978 QCOMPARE(c.value(), QVariant("ąćę")); 0979 QCOMPARE(c.type(), KDbField::Text); 0980 QVERIFY(validate(&c)); 0981 testCloneExpression(c); 0982 //qDebug() << c; 0983 0984 KDbField::setDefaultMaxLength(oldMaxLen); // restore 0985 0986 // bool 0987 c = KDbConstExpression(KDbToken::SQL_TRUE, true); 0988 QCOMPARE(c.type(), KDbField::Boolean); 0989 QVERIFY(c.isValid()); 0990 QVERIFY(!c.isTextType()); 0991 QVERIFY(!c.isNumericType()); 0992 QCOMPARE(c.value(), QVariant(true)); 0993 QVERIFY(validate(&c)); 0994 //qDebug() << c; 0995 c.setValue(false); 0996 QCOMPARE(c.value(), QVariant(false)); 0997 QVERIFY(validate(&c)); 0998 testCloneExpression(c); 0999 //qDebug() << c; 1000 1001 c = KDbConstExpression(KDbToken::SQL_FALSE, false); 1002 QCOMPARE(c.type(), KDbField::Boolean); 1003 QVERIFY(c.isValid()); 1004 QVERIFY(!c.isTextType()); 1005 QVERIFY(!c.isNumericType()); 1006 QCOMPARE(c.value(), QVariant(false)); 1007 QVERIFY(validate(&c)); 1008 testCloneExpression(c); 1009 //qDebug() << c; 1010 1011 // real 1012 c = KDbConstExpression(KDbToken::REAL_CONST, QVariant()); 1013 QCOMPARE(c.type(), KDbField::Double); 1014 QVERIFY(c.isValid()); 1015 QVERIFY(c.isNumericType()); 1016 QVERIFY(c.isFPNumericType()); 1017 QCOMPARE(c.value(), QVariant()); 1018 QCOMPARE(c.toString(nullptr), KDbEscapedString()); 1019 QVERIFY(validate(&c)); 1020 testCloneExpression(c); 1021 //qDebug() << c; 1022 1023 c = KDbConstExpression(KDbToken::REAL_CONST, 3.14159); 1024 QCOMPARE(c.type(), KDbField::Double); 1025 QVERIFY(c.isValid()); 1026 QVERIFY(c.isNumericType()); 1027 QVERIFY(c.isFPNumericType()); 1028 QCOMPARE(c.value(), QVariant(3.14159)); 1029 QString piString("3.14159"); 1030 // limit precision because it depends on the OS 1031 QCOMPARE(c.toString(nullptr).toString().left(piString.length() - 1), piString.left(piString.length() - 1)); 1032 QVERIFY(validate(&c)); 1033 //qDebug() << c; 1034 c.setValue(-18.012); 1035 QCOMPARE(c.value(), QVariant(-18.012)); 1036 QCOMPARE(c.toString(nullptr), KDbEscapedString("-18.012")); 1037 QVERIFY(validate(&c)); 1038 testCloneExpression(c); 1039 //qDebug() << c; 1040 1041 QByteArray largeDecimal("2147483647.2147483647"); 1042 c = KDbConstExpression(KDbToken::REAL_CONST, largeDecimal); 1043 QCOMPARE(c.type(), KDbField::Double); 1044 QVERIFY(c.isValid()); 1045 QVERIFY(c.isNumericType()); 1046 QVERIFY(c.isFPNumericType()); 1047 QCOMPARE(c.value(), QVariant(largeDecimal)); 1048 QCOMPARE(c.toString(nullptr), KDbEscapedString(largeDecimal)); 1049 largeDecimal = "-10.2147483647"; 1050 QVERIFY(validate(&c)); 1051 testCloneExpression(c); 1052 //qDebug() << c; 1053 c = KDbConstExpression(KDbToken::REAL_CONST, largeDecimal); 1054 QCOMPARE(c.value(), QVariant(largeDecimal)); 1055 QCOMPARE(c.toString(nullptr), KDbEscapedString(largeDecimal)); 1056 QVERIFY(validate(&c)); 1057 testCloneExpression(c); 1058 //qDebug() << c; 1059 1060 // date 1061 QDate date(QDate::currentDate()); 1062 c = KDbConstExpression(KDbToken::DATE_CONST, date); 1063 QVERIFY(c.isValid()); 1064 QVERIFY(c.isDateTimeType()); 1065 QCOMPARE(c.type(), KDbField::Date); 1066 QCOMPARE(c.value(), QVariant(date)); 1067 QVERIFY(validate(&c)); 1068 testCloneExpression(c); 1069 //qDebug() << c; 1070 date = date.addDays(17); 1071 c.setValue(date); 1072 QCOMPARE(c.value(), QVariant(date)); 1073 QVERIFY(c.isValid()); 1074 QVERIFY(c.isDateTimeType()); 1075 QVERIFY(validate(&c)); 1076 testCloneExpression(c); 1077 1078 KDbDate dateKDb(KDbYear("2018"), "11", "27"); 1079 c.setValue(QVariant::fromValue(dateKDb)); 1080 QCOMPARE(c.value(), QVariant::fromValue(dateKDb)); 1081 QVERIFY(c.isValid()); 1082 QVERIFY(c.isDateTimeType()); 1083 QVERIFY(validate(&c)); 1084 testCloneExpression(c); 1085 1086 // time 1087 QTime time(QTime::currentTime()); 1088 c = KDbConstExpression(KDbToken::TIME_CONST, time); 1089 QCOMPARE(c.type(), KDbField::Time); 1090 QVERIFY(c.isValid()); 1091 QVERIFY(c.isDateTimeType()); 1092 QCOMPARE(c.value(), QVariant(time)); 1093 testCloneExpression(c); 1094 QVERIFY(validate(&c)); 1095 time = time.addMSecs(1200123); 1096 c.setValue(time); 1097 QCOMPARE(c.value(), QVariant(time)); 1098 QVERIFY(c.isValid()); 1099 QVERIFY(c.isDateTimeType()); 1100 QVERIFY(validate(&c)); 1101 testCloneExpression(c); 1102 1103 KDbTime timeKDb("12", "34", "56", "789"); 1104 c.setValue(QVariant::fromValue(timeKDb)); 1105 QCOMPARE(c.value(), QVariant::fromValue(timeKDb)); 1106 QVERIFY(c.isValid()); 1107 QVERIFY(c.isDateTimeType()); 1108 QVERIFY(validate(&c)); 1109 testCloneExpression(c); 1110 1111 // date/time 1112 QDateTime dateTime(QDateTime::currentDateTime()); 1113 c = KDbConstExpression(KDbToken::DATETIME_CONST, dateTime); 1114 QCOMPARE(c.type(), KDbField::DateTime); 1115 QVERIFY(c.isValid()); 1116 QVERIFY(c.isDateTimeType()); 1117 QCOMPARE(c.value(), QVariant(dateTime)); 1118 QVERIFY(validate(&c)); 1119 testCloneExpression(c); 1120 //qDebug() << c; 1121 dateTime = dateTime.addDays(-17); 1122 c.setValue(dateTime); 1123 QCOMPARE(c.value(), QVariant(dateTime)); 1124 QVERIFY(c.isValid()); 1125 QVERIFY(c.isDateTimeType()); 1126 QVERIFY(validate(&c)); 1127 testCloneExpression(c); 1128 //qDebug() << c; 1129 KDbDateTime dateTimeKDb(dateKDb, timeKDb); 1130 c.setValue(QVariant::fromValue(dateTimeKDb)); 1131 // qDebug() << QVariant::fromValue(dateTimeKDb); 1132 // qDebug() << QVariant::fromValue(dateTimeKDb).isValid(); 1133 // qDebug() << c.value(); 1134 // qDebug() << c.value().isValid(); 1135 // qDebug() << (QVariant::fromValue(dateTimeKDb) == c.value()); 1136 QCOMPARE(c.value(), QVariant::fromValue(dateTimeKDb)); 1137 QVERIFY(c.isValid()); 1138 QVERIFY(c.isDateTimeType()); 1139 QVERIFY(validate(&c)); 1140 testCloneExpression(c); 1141 1142 // setValue() 1143 c = KDbConstExpression(KDbToken::INTEGER_CONST, 124); 1144 QCOMPARE(c.value(), QVariant(124)); 1145 c.setValue(299); 1146 QCOMPARE(c.value(), QVariant(299)); 1147 QVERIFY(c.isValid()); 1148 QVERIFY(c.isNumericType()); 1149 QVERIFY(!c.isFPNumericType()); 1150 testCloneExpression(c); 1151 //qDebug() << c; 1152 } 1153 1154 void ExpressionsTest::testUnaryExpressionValidate() 1155 { 1156 KDbConstExpression c; 1157 KDbConstExpression c1; 1158 KDbUnaryExpression u; 1159 KDbUnaryExpression u2; 1160 1161 // cycles detected by validate() 1162 c = KDbConstExpression(KDbToken::INTEGER_CONST, 17); 1163 u = KDbUnaryExpression('-', c); 1164 c1 = KDbConstExpression(KDbToken::INTEGER_CONST, 3); 1165 u2 = KDbUnaryExpression('+', c1); 1166 u2.setArg(u); 1167 u.setArg(u2); 1168 const char *warning = R"w(Cycle detected in expression (depth 2): 1169 1: Unary - 1170 2: Unary +)w"; 1171 QTest::ignoreMessage(QtWarningMsg, warning); 1172 warning = R"w(Cycle detected in expression (depth 2): 1173 1: Unary + 1174 2: Unary -)w"; 1175 QTest::ignoreMessage(QtWarningMsg, warning); 1176 warning = R"w(Cycle detected in expression (depth 2): 1177 1: Unary - 1178 2: Unary +)w"; 1179 QTest::ignoreMessage(QtWarningMsg, warning); 1180 QTest::ignoreMessage(QtWarningMsg, warning); 1181 QVERIFY(!validate(&u)); 1182 ////qDebug() << c << u << c1 << u2; 1183 1184 // NOT NULL is NULL 1185 c = KDbConstExpression(KDbToken::SQL_NULL, QVariant()); 1186 u = KDbUnaryExpression(KDbToken::NOT, c); 1187 QCOMPARE(u.type(), KDbField::Null); 1188 QVERIFY(validate(&u)); 1189 testCloneExpression(u); 1190 1191 // NOT "abc" is INVALID 1192 c = KDbConstExpression(KDbToken::CHARACTER_STRING_LITERAL, "abc"); 1193 u = KDbUnaryExpression(KDbToken::NOT, c); 1194 QCOMPARE(u.type(), KDbField::InvalidType); 1195 QVERIFY(!validate(&u)); 1196 testCloneExpression(u); 1197 } 1198 1199 void ExpressionsTest::testNArgExpressionValidate() 1200 { 1201 KDbNArgExpression n; 1202 KDbConstExpression c; 1203 KDbConstExpression c1; 1204 KDbConstExpression c2; 1205 1206 c = KDbConstExpression(KDbToken::SQL_NULL, QVariant()); 1207 QCOMPARE(c.type(), KDbField::Null); 1208 QVERIFY(validate(&c)); 1209 1210 n = KDbNArgExpression(KDb::ArithmeticExpression, '+'); 1211 c = KDbConstExpression(KDbToken::INTEGER_CONST, 0); 1212 c1 = KDbConstExpression(KDbToken::INTEGER_CONST, 1); 1213 n.append(c); 1214 n.append(c1); 1215 QCOMPARE(n.type(), KDbField::Tuple); 1216 QVERIFY(validate(&n)); 1217 testCloneExpression(n); 1218 ////qDebug() << c << c1 << n; 1219 1220 // -- a list of arguments 1221 n = KDbNArgExpression(KDb::ArgumentListExpression, ','); 1222 c = KDbConstExpression(KDbToken::INTEGER_CONST, 1); 1223 c1 = KDbConstExpression(KDbToken::INTEGER_CONST, 2); 1224 c2 = KDbConstExpression(KDbToken::INTEGER_CONST, 3); 1225 n.append(c); 1226 n.append(c1); 1227 n.append(c2); 1228 QCOMPARE(n.type(), KDbField::Tuple); 1229 QVERIFY(validate(&n)); 1230 QVERIFY(n.isValid()); 1231 } 1232 1233 void ExpressionsTest::testBinaryExpressionValidate_data() 1234 { 1235 QTest::addColumn<KDbToken>("type1"); 1236 QTest::addColumn<QVariant>("const1"); 1237 QTest::addColumn<KDbToken>("token"); 1238 QTest::addColumn<KDbToken>("type2"); 1239 QTest::addColumn<QVariant>("const2"); 1240 QTest::addColumn<KDbField::Type>("type3"); 1241 1242 // invalid 1243 KDbConstExpression c(KDbToken::INTEGER_CONST, 7); 1244 QTest::ignoreMessage(QtWarningMsg, 1245 "Setting KDbBinaryExpression to null because right argument is not specified"); 1246 KDbBinaryExpression b(c, '+', KDbExpression()); 1247 QCOMPARE(b.type(), KDbField::InvalidType); 1248 QVERIFY(!validate(&b)); 1249 testCloneExpression(b); 1250 //qDebug() << b; 1251 1252 QTest::ignoreMessage(QtWarningMsg, 1253 "Setting KDbBinaryExpression to null because left argument is not specified"); 1254 b = KDbBinaryExpression(KDbExpression(), '/', KDbExpression()); 1255 QCOMPARE(b.type(), KDbField::InvalidType); 1256 QVERIFY(!validate(&b)); // unknown class 1257 testCloneExpression(b); 1258 //qDebug() << b; 1259 1260 // invalid left or right 1261 QTest::ignoreMessage(QtWarningMsg, 1262 "Setting KDbBinaryExpression to null because left argument is not specified"); 1263 KDbBinaryExpression b2(b, '*', c.clone()); 1264 QCOMPARE(b2.type(), KDbField::InvalidType); 1265 QVERIFY(!validate(&b2)); // unknown class 1266 testCloneExpression(b2); 1267 //qDebug() << b2; 1268 1269 QTest::ignoreMessage(QtWarningMsg, 1270 "Setting KDbBinaryExpression to null because right argument is not specified"); 1271 KDbBinaryExpression b3(c.clone(), '*', b); 1272 QCOMPARE(b3.type(), KDbField::InvalidType); 1273 QVERIFY(!validate(&b3)); // unknown class 1274 testCloneExpression(b3); 1275 //qDebug() << b3; 1276 1277 #define TNAME(type) type.name().toLatin1() 1278 1279 #define T1(type1, const1, tokenOrChar, type2, const2, type3) \ 1280 QTest::newRow( \ 1281 qPrintable(QString::number(__LINE__) + ": " + TNAME(type1) + " " \ 1282 + QVariant(const1).toString() + " " \ 1283 + TNAME(TO_TOKEN(tokenOrChar)) + " " \ 1284 + TNAME(type2) + " " \ 1285 + QVariant(const2).toString().toLatin1())) \ 1286 << type1 << QVariant(const1) \ 1287 << TO_TOKEN(tokenOrChar) << type2 << QVariant(const2) \ 1288 << type3 1289 // tests both f(x, y) and f(y, x) 1290 #define T(type1, const1, token, type2, const2, type3) \ 1291 T1(type1, const1, token, type2, const2, type3); \ 1292 T1(type2, const2, token, type1, const1, type3) 1293 1294 // null 1295 T(KDbToken::SQL_NULL, QVariant(), '+', KDbToken::INTEGER_CONST, 7, KDbField::Null); 1296 // NULL OR true is true 1297 T(KDbToken::SQL_NULL, QVariant(), KDbToken::OR, KDbToken::SQL_TRUE, true, KDbField::Boolean); 1298 // NULL AND true is NULL 1299 T(KDbToken::SQL_NULL, QVariant(), KDbToken::AND, KDbToken::SQL_TRUE, true, KDbField::Null); 1300 // NULL OR false is NULL 1301 T(KDbToken::SQL_NULL, QVariant(), KDbToken::OR, KDbToken::SQL_FALSE, false, KDbField::Null); 1302 // NULL AND false is false 1303 T(KDbToken::SQL_NULL, QVariant(), KDbToken::AND, KDbToken::SQL_FALSE, false, KDbField::Boolean); 1304 // NULL AND NULL is NULL 1305 T(KDbToken::SQL_NULL, QVariant(), KDbToken::AND, KDbToken::SQL_NULL, QVariant(), KDbField::Null); 1306 // NULL OR NULL is NULL 1307 T(KDbToken::SQL_NULL, QVariant(), KDbToken::OR, KDbToken::SQL_NULL, QVariant(), KDbField::Null); 1308 // NULL XOR TRUE is NULL 1309 T(KDbToken::SQL_NULL, QVariant(), KDbToken::XOR, KDbToken::SQL_TRUE, true, KDbField::Null); 1310 // NULL XOR NULL is NULL 1311 T(KDbToken::SQL_NULL, QVariant(), KDbToken::XOR, KDbToken::SQL_NULL, QVariant(), KDbField::Null); 1312 // NULL AND "xyz" is invalid 1313 T(KDbToken::SQL_NULL, QVariant(), KDbToken::OR, KDbToken::CHARACTER_STRING_LITERAL, "xyz", KDbField::InvalidType); 1314 // integer 1315 // -- KDb::ArithmeticExpression only: resulting type is Integer or more 1316 // see explanation for KDb::maximumForIntegerFieldTypes() 1317 T(KDbToken::INTEGER_CONST, 50, '+', KDbToken::INTEGER_CONST, 20, KDbField::Integer); 1318 T(KDbToken::INTEGER_CONST, 50, '-', KDbToken::INTEGER_CONST, 20, KDbField::Integer); 1319 T(KDbToken::INTEGER_CONST, 50, '*', KDbToken::INTEGER_CONST, 20, KDbField::Integer); 1320 T(KDbToken::INTEGER_CONST, 50, '/', KDbToken::INTEGER_CONST, 20, KDbField::Integer); 1321 T(KDbToken::INTEGER_CONST, 50, '&', KDbToken::INTEGER_CONST, 20, KDbField::Integer); 1322 T(KDbToken::INTEGER_CONST, 50, '|', KDbToken::INTEGER_CONST, 20, KDbField::Integer); 1323 T(KDbToken::INTEGER_CONST, 50, '%', KDbToken::INTEGER_CONST, 20, KDbField::Integer); 1324 T(KDbToken::INTEGER_CONST, 50, KDbToken::BITWISE_SHIFT_RIGHT, KDbToken::INTEGER_CONST, 20, KDbField::Integer); 1325 T(KDbToken::INTEGER_CONST, 50, KDbToken::BITWISE_SHIFT_LEFT, KDbToken::INTEGER_CONST, 20, KDbField::Integer); 1326 T(KDbToken::INTEGER_CONST, 300, '+', KDbToken::INTEGER_CONST, 20, KDbField::Integer); 1327 T(KDbToken::INTEGER_CONST, 300, '+', KDbToken::INTEGER_CONST, 300, KDbField::Integer); 1328 T(KDbToken::INTEGER_CONST, 300, '+', KDbToken::INTEGER_CONST, 300, KDbField::Integer); 1329 T(KDbToken::INTEGER_CONST, 50, '+', KDbToken::INTEGER_CONST, qulonglong(INT_MAX), KDbField::BigInteger); 1330 T(KDbToken::INTEGER_CONST, INT_MAX, '+', KDbToken::INTEGER_CONST, qulonglong(INT_MAX), KDbField::BigInteger); 1331 1332 T(KDbToken::INTEGER_CONST, 50, '<', KDbToken::INTEGER_CONST, 20, KDbField::Boolean); 1333 T(KDbToken::INTEGER_CONST, 50, '=', KDbToken::INTEGER_CONST, 20, KDbField::Boolean); 1334 T(KDbToken::INTEGER_CONST, 50, '>', KDbToken::INTEGER_CONST, 20, KDbField::Boolean); 1335 T(KDbToken::INTEGER_CONST, 50, '<', KDbToken::INTEGER_CONST, INT_MAX, KDbField::Boolean); 1336 T(KDbToken::INTEGER_CONST, 50, '<', KDbToken::INTEGER_CONST, qulonglong(INT_MAX), KDbField::Boolean); 1337 T(KDbToken::INTEGER_CONST, qulonglong(INT_MAX), '<', KDbToken::INTEGER_CONST, INT_MAX, KDbField::Boolean); 1338 T(KDbToken::INTEGER_CONST, 300, KDbToken::LESS_OR_EQUAL, KDbToken::INTEGER_CONST, 20, KDbField::Boolean); 1339 T(KDbToken::INTEGER_CONST, 300, KDbToken::GREATER_OR_EQUAL, KDbToken::INTEGER_CONST, 300, KDbField::Boolean); 1340 T(KDbToken::INTEGER_CONST, 300, '>', KDbToken::INTEGER_CONST, 300, KDbField::Boolean); 1341 1342 T(KDbToken::INTEGER_CONST, 300, KDbToken::OR, KDbToken::INTEGER_CONST, 20, KDbField::InvalidType); 1343 T(KDbToken::INTEGER_CONST, 300, KDbToken::AND, KDbToken::INTEGER_CONST, 20, KDbField::InvalidType); 1344 T(KDbToken::INTEGER_CONST, 300, KDbToken::XOR, KDbToken::INTEGER_CONST, 20, KDbField::InvalidType); 1345 T(KDbToken::INTEGER_CONST, 300, KDbToken::OR, KDbToken::SQL_NULL, QVariant(), KDbField::InvalidType); 1346 // real 1347 T(KDbToken::REAL_CONST, 0.5, '+', KDbToken::REAL_CONST, -9.4, KDbField::Double); 1348 T(KDbToken::REAL_CONST, 0.5, '-', KDbToken::REAL_CONST, -9.4, KDbField::Double); 1349 T(KDbToken::REAL_CONST, 0.5, '*', KDbToken::REAL_CONST, -9.4, KDbField::Double); 1350 T(KDbToken::REAL_CONST, 0.5, '/', KDbToken::REAL_CONST, -9.4, KDbField::Double); 1351 T(KDbToken::REAL_CONST, 0.5, '&', KDbToken::REAL_CONST, -9.4, KDbField::Integer); 1352 T(KDbToken::REAL_CONST, 0.5, '&', KDbToken::INTEGER_CONST, 9, KDbField::Byte); 1353 T(KDbToken::REAL_CONST, 0.5, '&', KDbToken::INTEGER_CONST, 1000, KDbField::ShortInteger); 1354 T(KDbToken::REAL_CONST, 0.5, '&', KDbToken::INTEGER_CONST, qulonglong(INT_MAX), KDbField::BigInteger); 1355 T(KDbToken::REAL_CONST, 0.5, '%', KDbToken::REAL_CONST, -9.4, KDbField::Double); 1356 T(KDbToken::REAL_CONST, 0.5, KDbToken::BITWISE_SHIFT_RIGHT, KDbToken::REAL_CONST, 9.4, KDbField::Integer); 1357 T(KDbToken::REAL_CONST, 0.5, KDbToken::BITWISE_SHIFT_LEFT, KDbToken::REAL_CONST, 9.4, KDbField::Integer); 1358 T(KDbToken::REAL_CONST, 0.5, '+', KDbToken::INTEGER_CONST, 300, KDbField::Double); 1359 T(KDbToken::REAL_CONST, 0.5, '-', KDbToken::INTEGER_CONST, 300, KDbField::Double); 1360 T(KDbToken::REAL_CONST, 0.5, '/', KDbToken::INTEGER_CONST, 300, KDbField::Double); 1361 T(KDbToken::REAL_CONST, 0.5, '-', KDbToken::SQL_NULL, QVariant(), KDbField::Null); 1362 1363 T(KDbToken::REAL_CONST, 0.5, '>', KDbToken::REAL_CONST, -9.4, KDbField::Boolean); 1364 T(KDbToken::REAL_CONST, 0.5, '>', KDbToken::INTEGER_CONST, 300, KDbField::Boolean); 1365 T(KDbToken::REAL_CONST, 0.5, '=', KDbToken::INTEGER_CONST, 300, KDbField::Boolean); 1366 T(KDbToken::REAL_CONST, 0.5, '<', KDbToken::INTEGER_CONST, qulonglong(INT_MAX), KDbField::Boolean); 1367 T(KDbToken::REAL_CONST, 0.5, KDbToken::LESS_OR_EQUAL, KDbToken::INTEGER_CONST, 300, KDbField::Boolean); 1368 T(KDbToken::REAL_CONST, 0.5, KDbToken::GREATER_OR_EQUAL, KDbToken::INTEGER_CONST, 300, KDbField::Boolean); 1369 T(KDbToken::REAL_CONST, 0.5, '>', KDbToken::SQL_NULL, QVariant(), KDbField::Null); 1370 1371 T(KDbToken::REAL_CONST, 30.2, KDbToken::OR, KDbToken::REAL_CONST, 20, KDbField::InvalidType); 1372 T(KDbToken::REAL_CONST, 30.2, KDbToken::AND, KDbToken::REAL_CONST, 20, KDbField::InvalidType); 1373 T(KDbToken::REAL_CONST, 30.2, KDbToken::XOR, KDbToken::REAL_CONST, 20, KDbField::InvalidType); 1374 // string 1375 T(KDbToken::CHARACTER_STRING_LITERAL, "ab", KDbToken::CONCATENATION, KDbToken::CHARACTER_STRING_LITERAL, "cd", KDbField::Text); 1376 T(KDbToken::CHARACTER_STRING_LITERAL, "ab", '+', KDbToken::CHARACTER_STRING_LITERAL, "cd", KDbField::Text); 1377 1378 T(KDbToken::SQL_NULL, QVariant(), KDbToken::CONCATENATION, KDbToken::CHARACTER_STRING_LITERAL, "cd", KDbField::Null); 1379 T(KDbToken::SQL_NULL, QVariant(), '+', KDbToken::CHARACTER_STRING_LITERAL, "cd", KDbField::Null); 1380 1381 T(KDbToken::INTEGER_CONST, 50, KDbToken::CONCATENATION, KDbToken::INTEGER_CONST, 20, KDbField::InvalidType); 1382 T(KDbToken::CHARACTER_STRING_LITERAL, "ab", KDbToken::CONCATENATION, KDbToken::INTEGER_CONST, 20, KDbField::InvalidType); 1383 T(KDbToken::CHARACTER_STRING_LITERAL, "ab", '+', KDbToken::INTEGER_CONST, 20, KDbField::InvalidType); 1384 1385 T(KDbToken::CHARACTER_STRING_LITERAL, "ab", KDbToken::GREATER_OR_EQUAL, KDbToken::CHARACTER_STRING_LITERAL, "cd", KDbField::Boolean); 1386 T(KDbToken::CHARACTER_STRING_LITERAL, "ab", '<', KDbToken::INTEGER_CONST, 3, KDbField::InvalidType); 1387 T(KDbToken::CHARACTER_STRING_LITERAL, "ab", '+', KDbToken::CHARACTER_STRING_LITERAL, "cd", KDbField::Text); 1388 T(KDbToken::CHARACTER_STRING_LITERAL, "A", KDbToken::OR, KDbToken::REAL_CONST, 20, KDbField::InvalidType); 1389 T(KDbToken::CHARACTER_STRING_LITERAL, "A", KDbToken::AND, KDbToken::REAL_CONST, 20, KDbField::InvalidType); 1390 T(KDbToken::CHARACTER_STRING_LITERAL, "A", KDbToken::XOR, KDbToken::REAL_CONST, 20, KDbField::InvalidType); 1391 // bool 1392 T(KDbToken::SQL_TRUE, true, '<', KDbToken::SQL_FALSE, false, KDbField::Boolean); 1393 T(KDbToken::SQL_TRUE, true, '=', KDbToken::SQL_FALSE, false, KDbField::Boolean); 1394 T(KDbToken::SQL_TRUE, true, '+', KDbToken::SQL_FALSE, false, KDbField::InvalidType); 1395 T(KDbToken::SQL_TRUE, true, '<', KDbToken::INTEGER_CONST, 20, KDbField::Boolean); 1396 T(KDbToken::SQL_TRUE, true, '<', KDbToken::REAL_CONST, -10.1, KDbField::Boolean); 1397 T(KDbToken::SQL_TRUE, true, '-', KDbToken::SQL_NULL, QVariant(), KDbField::Null); 1398 T(KDbToken::SQL_TRUE, true, '<', KDbToken::SQL_NULL, QVariant(), KDbField::Null); 1399 T(KDbToken::SQL_TRUE, true, KDbToken::OR, KDbToken::SQL_FALSE, false, KDbField::Boolean); 1400 T(KDbToken::SQL_TRUE, true, KDbToken::AND, KDbToken::SQL_FALSE, false, KDbField::Boolean); 1401 T(KDbToken::SQL_TRUE, true, KDbToken::XOR, KDbToken::SQL_FALSE, false, KDbField::Boolean); 1402 // date/time 1403 T(KDbToken::DATE_CONST, QDate(2001, 1, 2), '=', KDbToken::DATE_CONST, QDate(2002, 1, 2), KDbField::Boolean); 1404 T(KDbToken::DATETIME_CONST, QDateTime(QDate(2001, 1, 2), QTime(1, 2, 3)), KDbToken::LESS_OR_EQUAL, KDbToken::DATE_CONST, QDateTime::currentDateTime(), KDbField::Boolean); 1405 T(KDbToken::TIME_CONST, QTime(1, 2, 3), '<', KDbToken::TIME_CONST, QTime::currentTime(), KDbField::Boolean); 1406 T(KDbToken::DATE_CONST, QDate(2001, 1, 2), '=', KDbToken::INTEGER_CONST, 17, KDbField::InvalidType); 1407 T(KDbToken::DATE_CONST, QDate(2001, 1, 2), '=', KDbToken::SQL_NULL, QVariant(), KDbField::Null); 1408 T(KDbToken::DATE_CONST, QDate(2001, 1, 2), KDbToken::OR, KDbToken::SQL_FALSE, false, KDbField::InvalidType); 1409 T(KDbToken::DATE_CONST, QDate(2001, 1, 2), KDbToken::AND, KDbToken::SQL_FALSE, false, KDbField::InvalidType); 1410 T(KDbToken::DATE_CONST, QDate(2001, 1, 2), KDbToken::XOR, KDbToken::SQL_FALSE, false, KDbField::InvalidType); 1411 #undef T 1412 #undef T1 1413 #undef TNAME 1414 } 1415 1416 void ExpressionsTest::testBinaryExpressionValidate() 1417 { 1418 QFETCH(KDbToken, type1); 1419 QFETCH(QVariant, const1); 1420 QFETCH(KDbToken, token); 1421 QFETCH(KDbToken, type2); 1422 QFETCH(QVariant, const2); 1423 QFETCH(KDbField::Type, type3); 1424 1425 KDbConstExpression c(type1, const1); 1426 KDbConstExpression c1(type2, const2); 1427 KDbBinaryExpression b(c, token, c1); 1428 //qDebug() << b.type(); 1429 //qDebug() << type3; 1430 QCOMPARE(b.type(), type3); 1431 QVERIFY(validate(&b) == (type3 != KDbField::InvalidType)); 1432 testCloneExpression(b); 1433 } 1434 1435 void ExpressionsTest::testFunctionExpressionValidate() 1436 { 1437 KDbFunctionExpression emptyFunction; 1438 QVERIFY(!validate(&emptyFunction)); 1439 1440 KDbNArgExpression args; 1441 args.append(KDbConstExpression(KDbToken::CHARACTER_STRING_LITERAL, "abc")); 1442 args.append(KDbConstExpression(KDbToken::INTEGER_CONST, 2)); 1443 KDbFunctionExpression f_substr("SUBSTR", args); 1444 QVERIFY(validate(&f_substr)); 1445 1446 args.append(KDbConstExpression(KDbToken::INTEGER_CONST, 1)); 1447 KDbFunctionExpression f_substr2("SUBSTR", args); 1448 QVERIFY(validate(&f_substr2)); 1449 1450 // clone the args 1451 KDbNArgExpression args2 = args.clone().toNArg(); 1452 f_substr2.setArguments(args2); 1453 QVERIFY(validate(&f_substr2)); 1454 1455 // wrong type (1st arg) 1456 args = KDbNArgExpression(); 1457 args.append(KDbConstExpression(KDbToken::DATETIME_CONST, QDateTime::currentDateTime())); 1458 args.append(KDbConstExpression(KDbToken::INTEGER_CONST, 1)); 1459 f_substr2.setArguments(args); 1460 QVERIFY(!validate(&f_substr2)); 1461 1462 // fixed type 1463 KDbConstExpression first = args.arg(0).toConst(); 1464 first.setToken(KDbToken::CHARACTER_STRING_LITERAL); 1465 first.setValue("xyz"); 1466 QVERIFY(validate(&f_substr2)); 1467 1468 // wrong type (2nd arg) 1469 KDbConstExpression second = args.arg(1).toConst(); 1470 second.setToken(KDbToken::REAL_CONST); 1471 second.setValue(3.14); 1472 QVERIFY(!validate(&f_substr2)); 1473 1474 // nested functions 1475 KDbFunctionExpression f_substr3 = f_substr.clone().toFunction(); 1476 f_substr3.arguments().replace(0, f_substr.clone()); 1477 QVERIFY(validate(&f_substr3)); 1478 1479 // fixed type 1480 args.replace(1, KDbConstExpression(KDbToken::INTEGER_CONST, 1)); 1481 QVERIFY(validate(&f_substr2)); 1482 1483 // wrong type (3rd arg) 1484 args.append(KDbConstExpression(KDbToken::REAL_CONST, 1.111)); 1485 //qDebug() << args; 1486 //qDebug() << f_substr2; 1487 QVERIFY(!validate(&f_substr2)); 1488 1489 // wrong number of args 1490 f_substr2.setArguments(KDbNArgExpression()); 1491 args.append(KDbConstExpression(KDbToken::INTEGER_CONST, 77)); 1492 QVERIFY(!validate(&f_substr2)); 1493 1494 KDbFunctionExpression f_noname("", args); 1495 QVERIFY(!validate(&f_noname)); 1496 } 1497 1498 void ExpressionsTest::cleanupTestCase() 1499 { 1500 }