KDb

KDbNArgExpression.cpp
1 /* This file is part of the KDE project
2  Copyright (C) 2003-2016 JarosÅ‚aw Staniek <[email protected]>
3 
4  Based on nexp.cpp : Parser module of Python-like language
5  (C) 2001 JarosÅ‚aw Staniek, MIMUW (www.mimuw.edu.pl)
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Library General Public
9  License as published by the Free Software Foundation; either
10  version 2 of the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Library General Public License for more details.
16 
17  You should have received a copy of the GNU Library General Public License
18  along with this library; see the file COPYING.LIB. If not, write to
19  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #include "KDbExpression.h"
24 #include "KDb.h"
25 #include "KDbDriver.h"
26 #include "KDbQuerySchema.h"
27 #include "KDbParser_p.h"
28 #include "kdb_debug.h"
29 
30 KDbNArgExpressionData::KDbNArgExpressionData()
32 {
33  ExpressionDebug << "NArgExpressionData" << ref;
34 }
35 
36 KDbNArgExpressionData::~KDbNArgExpressionData()
37 {
38  ExpressionDebug << "~NArgExpressionData" << ref;
39 }
40 
41 KDbField::Type KDbNArgExpressionData::typeInternal(KDb::ExpressionCallStack *callStack) const
42 {
43  if (token == KDbToken::BETWEEN_AND || token == KDbToken::NOT_BETWEEN_AND) {
44  for (int i = 0; i < children.count(); i++) {
45  KDbField::Type t = children.at(0)->type(callStack);
46  if (t == KDbField::InvalidType || t == KDbField::Null) {
47  return t;
48  }
49  }
50  return KDbField::Boolean;
51  }
52  return KDbField::Tuple;
53 }
54 
55 KDbNArgExpressionData* KDbNArgExpressionData::clone()
56 {
57  ExpressionDebug << "NArgExpressionData::clone" << *this;
58  return new KDbNArgExpressionData(*this);
59 }
60 
61 bool KDbNArgExpressionData::validateInternal(KDbParseInfo *parseInfo, KDb::ExpressionCallStack* callStack)
62 {
63  foreach(ExplicitlySharedExpressionDataPointer data, children) {
64  if (!data->validate(parseInfo, callStack))
65  return false;
66  }
67 
68  if (token == KDbToken::BETWEEN_AND || token == KDbToken::NOT_BETWEEN_AND) {
69  if (children.count() != 3) {
70  parseInfo->setErrorMessage(tr("Three arguments required"));
71  parseInfo->setErrorDescription(
72  tr("%1 operator requires exactly three arguments.", "BETWEEN..AND error")
73  .arg(QLatin1String("BETWEEN...AND")));
74  return false;
75  }
76  const KDbField::Type t0 = children[0]->type();
77  const KDbField::Type t1 = children[1]->type();
78  const KDbField::Type t2 = children[2]->type();
79  if (t0 == KDbField::Null || t1 == KDbField::Null || t2 == KDbField::Null) {
80  return true;
81  }
82  if (!( !KDbField::isNumericType(t0)
84  || !KDbField::isNumericType(t2)))
85  {
86  return true;
87  } else if (!( !KDbField::isTextType(t0)
88  || !KDbField::isTextType(t1)
89  || !KDbField::isTextType(t2)))
90  {
91  return true;
92  }
93 
94  if (t0 == t1 && t1 == t2) {
95  return true;
96  }
97 
98  parseInfo->setErrorMessage(tr("Incompatible types of arguments"));
99  parseInfo->setErrorDescription(
100  tr("Operator \"%1\" requires compatible types of arguments. "
101  "Specified arguments are of type %2, %3, %4.",
102  "BETWEEN..AND arguments type error")
103  .arg(QLatin1String("BETWEEN..AND"),
104  KDbField::typeName(t0),
105  KDbField::typeName(t1),
106  KDbField::typeName(t2)));
107  return false;
108  }
109  return true;
110 }
111 
113 {
114  dbg.nospace() << "NArgExp("
115  << token.name() << ", class=" << expressionClassName(expressionClass);
116  foreach(ExplicitlySharedExpressionDataPointer data, children) {
117  dbg.nospace() << ", ";
118  data->debug(dbg, callStack);
119  }
120  dbg.nospace() << ",type=" << KDbDriver::defaultSqlTypeName(type()) << ")";
121 }
122 
123 KDbEscapedString KDbNArgExpressionData::toStringInternal(
124  const KDbDriver *driver,
126  KDb::ExpressionCallStack* callStack) const
127 {
128  if (token == KDbToken::BETWEEN_AND && children.count() == 3) {
129  return children[0]->toString(driver, params, callStack) + " BETWEEN "
130  + children[1]->toString(driver, params, callStack) + " AND "
131  + children[2]->toString(driver, params, callStack);
132  }
133  if (token == KDbToken::NOT_BETWEEN_AND && children.count() == 3) {
134  return children[0]->toString(driver, params, callStack) + " NOT BETWEEN "
135  + children[1]->toString(driver, params, callStack) + " AND "
136  + children[2]->toString(driver, params, callStack);
137  }
138 
140  s.reserve(256);
141  foreach(ExplicitlySharedExpressionDataPointer data, children) {
142  if (!s.isEmpty())
143  s += ", ";
144  s += data->toString(driver, params, callStack);
145  }
146  return s;
147 }
148 
149 void KDbNArgExpressionData::getQueryParameters(QList<KDbQuerySchemaParameter>* params)
150 {
151  Q_ASSERT(params);
152  foreach(ExplicitlySharedExpressionDataPointer data, children) {
153  data->getQueryParameters(params);
154  }
155 }
156 
157 bool KDbNArgExpressionData::containsInvalidArgument() const
158 {
159  foreach(ExplicitlySharedExpressionDataPointer data, children) {
160  const KDbField::Type type = data->type();
161  if (type == KDbField::InvalidType) {
162  return true;
163  }
164  }
165  return false;
166 }
167 
168 bool KDbNArgExpressionData::containsNullArgument() const
169 {
170  foreach(ExplicitlySharedExpressionDataPointer data, children) {
171  const KDbField::Type type = data->type();
172  if (type == KDbField::Null) {
173  return true;
174  }
175  }
176  return false;
177 }
178 
179 //=========================================
180 
183 {
184  ExpressionDebug << "KDbNArgExpression() ctor" << *this;
185 }
186 
188  : KDbExpression(data)
189 {
190  ExpressionDebug << "KDbNArgExpression(KDbExpressionData*) ctor" << *this;
191 }
192 
194  : KDbExpression(new KDbNArgExpressionData, aClass, token)
195 {
196  ExpressionDebug << "KDbNArgExpression(KDb::ExpressionClass, int) ctor" << *this;
197 }
198 
200  : KDbExpression(expr)
201 {
202 }
203 
205  : KDbExpression(ptr)
206 {
207 }
208 
210 {
211 }
212 
214 {
215  appendChild(expr);
216 }
217 
219 {
220  prependChild(expr);
221 }
222 
224 {
225  return KDbExpression(d->children.value(i));
226 }
227 
228 void KDbNArgExpression::insert(int i, const KDbExpression& expr)
229 {
230  insertChild(i, expr);
231 }
232 
234 {
235  if (!checkBeforeInsert(expr.d))
236  return;
237  if (i < 0 || i > d->children.count())
238  return;
239  d->children.at(i)->parent.reset();
240  d->children.replace(i, expr.d);
241  expr.d->parent = d;
242 }
243 
245 {
246  return removeChild(expr);
247 }
248 
250 {
251  removeChild(i);
252 }
253 
255 {
256  return takeChild(i);
257 }
258 
259 int KDbNArgExpression::indexOf(const KDbExpression& expr, int from) const
260 {
261  return indexOfChild(expr, from);
262 }
263 
264 int KDbNArgExpression::lastIndexOf(const KDbExpression& expr, int from) const
265 {
266  return lastIndexOfChild(expr, from);
267 }
268 
270 {
271  return d->children.count();
272 }
273 
275 {
276  return d->children.isEmpty();
277 }
278 
280 {
281  return d->convert<KDbNArgExpressionData>()->containsInvalidArgument();
282 }
283 
285 {
286  return d->convert<KDbNArgExpressionData>()->containsNullArgument();
287 }
bool containsInvalidArgument() const
Internal data class used to implement implicitly shared class KDbExpression.
void debugInternal(QDebug dbg, KDb::ExpressionCallStack *callStack) const override
Sends information about this expression to debug output dbg (internal).
KDbExpression arg(int i) const
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.
Definition: KDbToken.h:36
@ InvalidType
Definition: KDbField.h:86
void ref()
QDebug & nospace()
KDbField::Type type() const
Specialized string for escaping.
Database driver's abstraction.
Definition: KDbDriver.h:49
static const KDbToken BETWEEN_AND
Custom tokens are not used in parser but used as an extension in expression classes.
Definition: KDbToken.h:173
void replace(int i, const KDbExpression &expr)
Replaces expression argument at index i with expression expr.
static QString defaultSqlTypeName(KDbField::Type type)
Definition: KDbDriver.cpp:166
QString typeName() const
Definition: KDbField.h:377
bool isTextType() const
Definition: KDbField.h:353
void insert(int i, const KDbExpression &expr)
KDbExpression takeAt(int i)
ExplicitlySharedExpressionDataPointer d
void append(const KDbExpression &expr)
Inserts expression argument expr at the end of this expression.
int lastIndexOf(const KDbExpression &expr, int from=-1) const
ExpressionClass
Classes of expressions.
bool isNumericType() const
Definition: KDbField.h:317
Internal data class used to implement implicitly shared class KDbNArgExpression.
The KDbNArgExpression class represents a base class N-argument expression.
QString name() const
Definition: KDbToken.cpp:38
@ Boolean
Definition: KDbField.h:92
The KDbExpression class represents a base class for all expressions.
Definition: KDbExpression.h:51
int indexOf(const KDbExpression &expr, int from=0) const
KDb::ExpressionClass expressionClass
~KDbNArgExpression() override
Destroys the expression.
void prepend(const KDbExpression &expr)
Inserts expression argument expr at the beginning of this expression.
bool remove(const KDbExpression &expr)
bool containsNullArgument() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Nov 28 2023 04:08:45 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.