KDb

KDbVariableExpression.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2003-2012 Jarosław Staniek <staniek@kde.org>
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
30KDbVariableExpressionData::KDbVariableExpressionData()
32 , field(nullptr)
33 , tablePositionForField(-1)
34 , tableForQueryAsterisk(nullptr)
35{
36 ExpressionDebug << "VariableExpressionData" << ref;
37}
38
39KDbVariableExpressionData::KDbVariableExpressionData(const QString& aName)
41 , name(aName)
42 , field(nullptr)
43 , tablePositionForField(-1)
44 , tableForQueryAsterisk(nullptr)
45{
46 ExpressionDebug << "VariableExpressionData" << ref;
47}
48
49KDbVariableExpressionData::~KDbVariableExpressionData()
50{
51 ExpressionDebug << "~VariableExpressionData" << ref;
52}
53
54KDbVariableExpressionData* KDbVariableExpressionData::clone()
55{
56 ExpressionDebug << "VariableExpressionData::clone" << *this;
57 return new KDbVariableExpressionData(*this);
58}
59
61{
62 Q_UNUSED(callStack);
63 dbg.nospace() << qPrintable(QString::fromLatin1("VariableExp(\"%1\",type=%2)")
65 : QLatin1String("FIELD_NOT_DEFINED_YET")));
66}
67
68KDbEscapedString KDbVariableExpressionData::toStringInternal(
69 const KDbDriver *driver,
71 KDb::ExpressionCallStack* callStack) const
72{
73 Q_UNUSED(driver);
74 Q_UNUSED(params);
75 Q_UNUSED(callStack);
76 return KDbEscapedString(name);
77}
78
79void KDbVariableExpressionData::getQueryParameters(QList<KDbQuerySchemaParameter>* params)
80{
81 Q_UNUSED(params);
82}
83
84//! We're assuming it's called after VariableExpr::validate()
86{
87 Q_UNUSED(callStack);
88 if (field)
89 return field->type();
90
91 //BTW, asterisks are not stored in VariableExpr outside of parser, so ok.
93}
94
95static void validateImplError(KDbParseInfo *parseInfo_, const QString &errmsg)
96{
97 KDbParseInfoInternal *parseInfo = static_cast<KDbParseInfoInternal*>(parseInfo_);
98 parseInfo->setErrorMessage(QLatin1String("Implementation error"));
99 parseInfo->setErrorDescription(errmsg);
100}
101
103{
104 Q_UNUSED(callStack);
105 KDbParseInfoInternal *parseInfo = static_cast<KDbParseInfoInternal*>(parseInfo_);
106 field = nullptr;
108 tableForQueryAsterisk = nullptr;
109
110 /* taken from parser's addColumn(): */
111 kdbDebug() << "checking variable name: " << name;
112 QString tableName, fieldName;
113 if (!KDb::splitToTableAndFieldParts(name, &tableName, &fieldName,
115 {
116 return false;
117 }
118 //! @todo shall we also support db name?
119 if (tableName.isEmpty()) {//fieldname only
120 if (fieldName == QLatin1String("*")) {
121 return true;
122 }
123
124 //find first table that has this field
125 KDbField *firstField = nullptr;
126 foreach(KDbTableSchema *table, *parseInfo->querySchema()->tables()) {
127 KDbField *f = table->field(fieldName);
128 if (f) {
129 if (!firstField) {
130 firstField = f;
131 } else if (f->table() != firstField->table()) {
132 //ambiguous field name
133 parseInfo->setErrorMessage(tr("Ambiguous field name"));
134 parseInfo->setErrorDescription(
135 tr("Both table \"%1\" and \"%2\" have defined \"%3\" field. "
136 "Use \"<tableName>.%4\" notation to specify table name.",
137 "Note: translate also <tableName>")
138 .arg(firstField->table()->name(), f->table()->name(),
139 fieldName, fieldName));
140 return false;
141 }
142 }
143 }
144 if (!firstField) {
145 parseInfo->setErrorMessage(tr("Field not found"));
146 parseInfo->setErrorDescription(
147 tr("Could not find table containing field \"%1\".").arg(fieldName));
148 return false;
149 }
150 //ok
151 field = firstField; //store
152 return true;
153 }
154
155 //table.fieldname or tableAlias.fieldname
156 KDbTableSchema *ts = parseInfo->querySchema()->table(tableName);
157 int tablePosition = -1;
158 if (ts) {//table.fieldname
159 //check if "table" is covered by an alias
160 const QList<int> tPositions = parseInfo->querySchema()->tablePositions(tableName);
161 QString tableAlias;
162 bool covered = true;
163 foreach(int position, tPositions) {
164 tableAlias = parseInfo->querySchema()->tableAlias(position);
165 if (tableAlias.isEmpty() || tableAlias.toLower() == tableName) {
166 covered = false; //uncovered
167 break;
168 }
169 kdbDebug() << " --" << "covered by " << tableAlias << " alias";
170 }
171 if (covered) {
172 parseInfo->setErrorMessage(tr("Could not access the table directly using its name"));
173 parseInfo->setErrorDescription(
174 tr("Table name \"%1\" is covered by aliases. "
175 "Instead of \"%2\", \"%3\" can be used.")
176 .arg(tableName,
177 tableName + QLatin1Char('.') + fieldName,
178 tableAlias + QLatin1Char('.') + fieldName));
179 return false;
180 }
181 if (!tPositions.isEmpty()) {
182 tablePosition = tPositions.first();
183 }
184 }
185 else {//try to find tableAlias
186 tablePosition = parseInfo->querySchema()->tablePositionForAlias(tableName);
187 if (tablePosition >= 0) {
188 ts = parseInfo->querySchema()->tables()->at(tablePosition);
189 if (ts) {
190// kdbDebug() << " --it's a tableAlias.name";
191 }
192 }
193 }
194
195 if (!ts) {
196 parseInfo->setErrorMessage(tr("Table not found"));
197 parseInfo->setErrorDescription(tr("Unknown table \"%1\".").arg(tableName));
198 return false;
199 }
200
201 const QList<int> positionsList(parseInfo->tablesAndAliasesForName(tableName));
202 if (positionsList.isEmpty()) { //for sanity
203 validateImplError(parseInfo,
204 QString::fromLatin1("%1.%2, !positionsList ").arg(tableName, fieldName));
205 return false;
206 }
207
208 //it's a table.*
209 if (fieldName == QLatin1String("*")) {
210 if (positionsList.count() > 1) {
211 parseInfo->setErrorMessage(tr("Ambiguous \"%1.*\" expression").arg(tableName));
212 parseInfo->setErrorDescription(tr("More than one \"%1\" table or alias defined.").arg(tableName));
213 return false;
214 }
216 return true;
217 }
218
219// kdbDebug() << " --it's a table.name";
220 KDbField *realField = ts->field(fieldName);
221 if (!realField) {
222 parseInfo->setErrorMessage(tr("Field not found"));
223 parseInfo->setErrorDescription(
224 tr("Table \"%1\" has no \"%2\" field.").arg(tableName, fieldName));
225 return false;
226 }
227
228 // check if table or alias is used twice and both have the same column
229 // (so the column is ambiguous)
230 if (positionsList.count() > 1) {
231 parseInfo->setErrorMessage(tr("Ambiguous \"%1.%2\" expression").arg(tableName, fieldName));
232 parseInfo->setErrorDescription(
233 tr("More than one \"%1\" table or alias defined containing \"%2\" field.")
234 .arg(tableName, fieldName));
235 return false;
236 }
237 field = realField; //store
238 tablePositionForField = tablePosition;
239 return true;
240}
241
242//=========================================
243
246{
247 ExpressionDebug << "KDbVariableExpression() ctor" << *this;
248}
249
252 KDb::VariableExpression, KDbToken()/*undefined*/)
253{
254}
255
260
262 : KDbExpression(data)
263{
264 ExpressionDebug << "KDbVariableExpression ctor (KDbExpressionData*)" << *this;
265}
266
268 : KDbExpression(ptr)
269{
270}
271
272KDbVariableExpression::~KDbVariableExpression()
273{
274}
275
277{
278 return d->convert<KDbVariableExpressionData>()->name;
279}
280
282{
283 return d->convert<KDbVariableExpressionData>()->field;
284}
285
290
Database driver's abstraction.
Definition KDbDriver.h:50
static QString defaultSqlTypeName(KDbField::Type type)
Specialized string for escaping.
Internal data class used to implement implicitly shared class KDbExpression.
KDbField::Type type() const
The KDbExpression class represents a base class for all expressions.
ExplicitlySharedExpressionDataPointer d
virtual KDbField * field(int id)
Meta-data for a field.
Definition KDbField.h:72
KDbTableSchema * table()
Definition KDbField.cpp:585
@ InvalidType
Definition KDbField.h:86
Type type() const
Definition KDbField.cpp:379
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:37
Internal data class used to implement implicitly shared class KDbVariableExpression.
void debugInternal(QDebug dbg, KDb::ExpressionCallStack *callStack) const override
Sends information about this expression to debug output dbg (internal).
KDbField::Type typeInternal(KDb::ExpressionCallStack *callStack) const override
We're assuming it's called after VariableExpr::validate()
KDbTableSchema * tableForQueryAsterisk
bool validateInternal(KDbParseInfo *parseInfo, KDb::ExpressionCallStack *callStack) override
The KDbVariableExpression class represents variables such as fieldname or tablename....
KDbTableSchema * tableForQueryAsterisk() const
A database connectivity and creation framework.
@ SetFieldNameIfNoTableName
see splitToTableAndFieldParts()
Definition KDb.h:248
KDB_EXPORT bool splitToTableAndFieldParts(const QString &string, QString *tableName, QString *fieldName, SplitToTableAndFieldPartsOptions option=FailIfNoTableOrFieldName)
Definition KDb.cpp:603
QString name(StandardShortcut id)
QDebug & nospace()
qsizetype count() const const
T & first()
bool isEmpty() const const
QString fromLatin1(QByteArrayView str)
bool isEmpty() const const
QString toLower() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:20:59 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.