24#include "KDbExpression.h"
27#include "KDbQuerySchema.h"
28#include "KDbParser_p.h"
30#include "generated/sqlparser.h"
35class KDbExpressionClassNames
38 KDbExpressionClassNames()
40 QLatin1String(
"Unknown"),
41 QLatin1String(
"Unary"),
42 QLatin1String(
"Arithm"),
43 QLatin1String(
"Logical"),
44 QLatin1String(
"Relational"),
45 QLatin1String(
"SpecialBinary"),
46 QLatin1String(
"Const"),
47 QLatin1String(
"Variable"),
48 QLatin1String(
"Function"),
49 QLatin1String(
"Aggregation"),
50 QLatin1String(
"FieldList"),
51 QLatin1String(
"TableList"),
52 QLatin1String(
"ArgumentList"),
53 QLatin1String(
"QueryParameter")})
56 const std::vector<QString> names;
59Q_GLOBAL_STATIC(KDbExpressionClassNames, KDb_expressionClassNames)
63 Q_ASSERT(
size_t(c) < KDb_expressionClassNames->names.size());
64 return KDb_expressionClassNames->names[c];
69 KDb::ExpressionCallStack callStack;
70 return expr.debug(dbg.
nospace(), &callStack);
75KDbExpressionData::KDbExpressionData()
76 : expressionClass(
KDb::UnknownExpression)
91KDbExpressionData::~KDbExpressionData()
98 ExpressionDebug <<
"KDbExpressionData::clone" << *
this;
99 return new KDbExpressionData(*
this);
102KDbField::Type KDbExpressionData::typeInternal(KDb::ExpressionCallStack* callStack)
const
110 if (!addToCallStack(
nullptr, callStack)) {
120 KDb::ExpressionCallStack callStack;
121 return type(&callStack);
124bool KDbExpressionData::isValid()
const
129bool KDbExpressionData::isTextType()
const
134bool KDbExpressionData::isIntegerType()
const
139bool KDbExpressionData::isNumericType()
const
144bool KDbExpressionData::isFPNumericType()
const
149bool KDbExpressionData::isDateTimeType()
const
154bool KDbExpressionData::validate(KDbParseInfo *parseInfo)
156 KDb::ExpressionCallStack callStack;
157 return validate(parseInfo, &callStack);
160bool KDbExpressionData::validate(KDbParseInfo *parseInfo, KDb::ExpressionCallStack* callStack)
162 if (!addToCallStack(
nullptr, callStack)) {
165 bool result = validateInternal(parseInfo, callStack);
170bool KDbExpressionData::validateInternal(KDbParseInfo *parseInfo, KDb::ExpressionCallStack* callStack)
180 KDb::ExpressionCallStack* callStack)
const
182 const bool owned = !callStack;
184 callStack =
new KDb::ExpressionCallStack();
186 if (!addToCallStack(
nullptr, callStack)) {
190 return KDbEscapedString(
"<CYCLE!>");
192 KDbEscapedString s = toStringInternal(driver, params, callStack);
203 KDb::ExpressionCallStack* callStack)
const
208 return KDbEscapedString(
"<UNKNOWN!>");
216bool KDbExpressionData::addToCallStack(
QDebug *dbg, KDb::ExpressionCallStack* callStack)
const
222 QDebug
debug(&warning);
223 debug.nospace() <<
"Cycle detected in expression (depth " << callStack->
length() <<
"):";
225 for (
const KDbExpressionData *data : qAsConst(*callStack)) {
227 debug.space().noquote() << expressionClassName(data->expressionClass);
228 debug.nospace() << data->token;
231 kdbWarning().noquote() << warning;
240 if (!addToCallStack(&dbg, callStack)) {
250 KDb::ExpressionCallStack callStack;
266 ExpressionDebug <<
"KDbExpression ctor ()" << *
this <<
d->ref;
272 d->expressionClass = aClass;
279 ExpressionDebug <<
"KDbExpression ctor (KDbExpressionData*)" << *
this;
287KDbExpression::~KDbExpression()
290 if (
d->parent &&
d->ref == 1) {
291 d->parent->children.removeOne(
d);
297 return d->expressionClass == KDb::UnknownExpression;
317 return d->expressionClass;
322 d->expressionClass = aClass;
327 return d->validate(parseInfo);
342 return d->isTextType();
347 return d->isIntegerType();
352 return d->isNumericType();
357 return d->isFPNumericType();
362 return d->isDateTimeType();
377 appendChild(child.
d);
382 if (!checkBeforeInsert(child.
d))
384 d->children.prepend(child.
d);
388void KDbExpression::insertChild(
int i,
const KDbExpression& child)
390 if (!checkBeforeInsert(child.
d))
392 if (i < 0 || i >
d->children.count())
394 d->children.insert(i, child.
d);
400 if (i < 0 || i >
d->children.count())
403 d->children.insert(i, child.
d);
411 child.
d->parent.reset();
412 return d->children.removeOne(child.
d);
415void KDbExpression::removeChild(
int i)
419 if (i < 0 || i >=
d->children.count())
422 d->children.removeAt(i);
429 if (i < 0 || i >=
d->children.count())
431 ExplicitlySharedExpressionDataPointer child =
d->children.takeAt(i);
434 child->parent.reset();
438int KDbExpression::indexOfChild(
const KDbExpression& child,
int from)
const
440 return d->children.indexOf(child.
d, from);
443int KDbExpression::lastIndexOfChild(
const KDbExpression& child,
int from)
const
445 return d->children.lastIndexOf(child.
d, from);
448bool KDbExpression::checkBeforeInsert(
const ExplicitlySharedExpressionDataPointer& child)
454 if (child->parent ==
d)
457 child->parent->children.removeOne(child);
461void KDbExpression::appendChild(
const ExplicitlySharedExpressionDataPointer& child)
463 if (!checkBeforeInsert(child))
465 d->children.append(child);
471 KDb::ExpressionCallStack* callStack)
const
475 return d->toString(driver, params, callStack);
481 d->getQueryParameters(params);
484QDebug KDbExpression::debug(
QDebug dbg, KDb::ExpressionCallStack* callStack)
const
487 d->debug(dbg, callStack);
498 return !operator==(e);
501bool KDbExpression::isNArg()
const
503 return d->convertConst<KDbNArgExpressionData>();
506bool KDbExpression::isUnary()
const
508 return d->convertConst<KDbUnaryExpressionData>();
511bool KDbExpression::isBinary()
const
513 return d->convertConst<KDbBinaryExpressionData>();
516bool KDbExpression::isConst()
const
518 return d->convertConst<KDbConstExpressionData>();
521bool KDbExpression::isVariable()
const
523 return d->convertConst<KDbVariableExpressionData>();
526bool KDbExpression::isFunction()
const
528 return d->convertConst<KDbFunctionExpressionData>();
531bool KDbExpression::isQueryParameter()
const
533 return d->convertConst<KDbQueryParameterExpressionData>();
537 d->convert<T ## Data>() ? T(d) : T()
541 return CAST(KDbNArgExpression);
551 return CAST(KDbBinaryExpression);
556 return CAST(KDbConstExpression);
561 return CAST(KDbQueryParameterExpression);
566 return CAST(KDbVariableExpression);
571 return CAST(KDbFunctionExpression);
577 kdbWarning() <<
"Expression" << *
this <<
"cannot be set as own child";
580 if (
d->children.indexOf(e.
d) == index) {
583 if (
d->children[index == 0 ? 1 : 0] == e.
d) {
584 d->children[index] = e.
d;
589 e.
d->parent->children.removeOne(e.
d);
591 d->children[index] = e.
d;
598 switch (
token.value()) {
606 case BITWISE_SHIFT_RIGHT:
607 case BITWISE_SHIFT_LEFT:
609 return KDb::ArithmeticExpression;
616 case GREATER_OR_EQUAL:
622 return KDb::RelationalExpression;
626 return KDb::LogicalExpression;
629 return KDb::SpecialBinaryExpression;
632 return KDb::UnknownExpression;
The KDbBinaryExpression class represents binary operation.
The KDbConstExpression class represents const expression.
Database driver's abstraction.
static QString defaultSqlTypeName(KDbField::Type type)
Specialized string for escaping.
Internal data class used to implement implicitly shared class KDbExpression.
KDbField::Type type() const
virtual void debugInternal(QDebug dbg, KDb::ExpressionCallStack *callStack) const
Sends information about this expression to debug output dbg (internal).
QDebug debug(QDebug dbg, KDb::ExpressionCallStack *callStack) const
Sends information about this expression to debug output dbg.
The KDbExpression class represents a base class for all expressions.
bool isFPNumericType() const
KDb::ExpressionClass expressionClass() const
static KDb::ExpressionClass classForToken(KDbToken token)
bool validate(KDbParseInfo *parseInfo)
void setExpressionClass(KDb::ExpressionClass aClass)
void setToken(KDbToken token)
KDbExpression parent() const
KDbEscapedString toString(const KDbDriver *driver, KDbQuerySchemaParameterValueListIterator *params=nullptr, KDb::ExpressionCallStack *callStack=nullptr) const
bool isNumericType() const
bool isDateTimeType() const
void getQueryParameters(QList< KDbQuerySchemaParameter > *params)
void setLeftOrRight(const KDbExpression &right, int index)
Only for KDbBinaryExpression::setLeft() and KDbBinaryExpression::setRight()
void insertEmptyChild(int i)
Used for inserting placeholders, e.g. in KDbBinaryExpression::KDbBinaryExpression()
KDbField::Type type() const
KDbExpression clone() const
Creates a deep (not shallow) copy of the KDbExpression.
bool isIntegerType() const
QList< ExplicitlySharedExpressionDataPointer > children() const
KDbNArgExpression toNArg() const
Convenience type casts.
ExplicitlySharedExpressionDataPointer d
bool isNumericType() const
bool isDateTimeType() const
bool isFPNumericType() const
bool isIntegerType() const
The KDbFunctionExpression class represents expression that use functional notation F(x,...
The KDbQueryParameterExpression class represents query parameter expression.
An iterator for a list of values of query schema parameters Allows to iterate over parameters and ret...
A type-safe KDbSQL token It can be used in KDb expressions.
The KDbUnaryExpression class represents unary expression (with a single argument).
The KDbVariableExpression class represents variables such as fieldname or tablename....
A database connectivity and creation framework.
ExpressionClass
Classes of expressions.
QStringView level(QStringView ifopt)
void append(QList< T > &&value)
bool contains(const AT &value) const const
qsizetype length() const const
QString arg(Args &&... args) const const
QString fromLatin1(QByteArrayView str)
QTextStream & endl(QTextStream &stream)