KDb

KDbDriver.cpp
1 /* This file is part of the KDE project
2  Copyright (C) 2003-2018 JarosÅ‚aw Staniek <[email protected]>
3 
4  This program is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License as published by the Free Software Foundation; either
7  version 2 of the License, or (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Library General Public License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this program; see the file COPYING. If not, write to
16  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18 */
19 
20 #include "KDbDriver.h"
21 #include "KDbAdmin.h"
22 #include "KDbConnectionData.h"
23 #include "KDbConnection.h"
24 #include "KDbConnectionOptions.h"
25 #include "KDbDriverManager_p.h"
26 #include "KDbDriverMetaData.h"
27 #include "KDbDriver_p.h"
28 #include "KDbDriverBehavior.h"
29 #include "KDbError.h"
30 #include "KDbExpression.h"
31 #include "kdb_debug.h"
32 
33 #include <algorithm>
34 
35 /*! @internal Used in KDbDriver::defaultSqlTypeName(int)
36  when we do not have KDbDriver instance yet, or when we cannot get one */
37 static const char* const KDb_defaultSqlTypeNames[] = {
38  "InvalidType",
39  "Byte",
40  "ShortInteger",
41  "Integer",
42  "BigInteger",
43  "Boolean",
44  "Date",
45  "DateTime",
46  "Time",
47  "Float",
48  "Double",
49  "Text",
50  "LongText",
51  "BLOB"
52 };
53 
54 //---------------------------------------------
55 
56 KDbDriver::KDbDriver(QObject *parent, const QVariantList &args)
57  : QObject(parent)
58  , d(new KDbDriverPrivate(this))
59 {
60  Q_UNUSED(args);
61  d->driverBehavior.typeNames.resize(KDbField::LastType + 1);
62 }
63 
65 {
66  // make a copy because d->connections will be touched by ~KDbConnection
67  QSet<KDbConnection*> connections(d->connections);
68  qDeleteAll(connections);
69  d->connections.clear();
70  delete d;
71 // kdbDebug() << "ok";
72 }
73 
75 {
76  return &d->driverBehavior;
77 }
78 
80 {
81  return &d->driverBehavior;
82 }
83 
85 {
86  clearResult();
87  QString inv_impl(tr("Invalid database driver's \"%1\" implementation.").arg(metaData()->name()));
88  QString not_init(tr("Value of \"%1\" is not initialized for the driver."));
89  if (d->driverBehavior.ROW_ID_FIELD_NAME.isEmpty()) {
90  m_result = KDbResult(ERR_INVALID_DRIVER_IMPL,
91  inv_impl + QLatin1Char(' ')
92  + not_init.arg(QLatin1String("KDbDriverBehavior::ROW_ID_FIELD_NAME")));
93  return false;
94  }
95  return true;
96 }
97 
99 {
100  return d->connections;
101 }
102 
104 {
105  return d->metaData;
106 }
107 
109 {
110  return d->driverBehavior.features;
111 }
112 
114 {
115  return d->driverBehavior.features & (SingleTransactions | MultipleTransactions);
116 }
117 
119 {
120  if (!d->adminTools)
121  d->adminTools = drv_createAdminTools();
122  return *d->adminTools;
123 }
124 
126 {
127  return new KDbAdminTools(); //empty impl.
128 }
129 
131 {
132  Q_UNUSED(field);
133  if (type > KDbField::InvalidType && type <= KDbField::LastType) { /*sanity*/
134  return d->driverBehavior.typeNames[type];
135  }
136  return d->driverBehavior.typeNames[KDbField::InvalidType];
137 }
138 
140  const KDbConnectionOptions &options)
141 {
142  clearResult();
143  if (!isValid())
144  return nullptr;
145 
146  KDbConnection *conn = drv_createConnection(connData, options);
147 
148 //! @todo needed? connData->setDriverId(id());
149  d->connections.insert(conn);
150  return conn;
151 }
152 
154 {
155  return createConnection(connData, KDbConnectionOptions());
156 }
157 
159 {
160  clearResult();
161  if (d->connections.remove(conn))
162  return conn;
163  return nullptr;
164 }
165 
167 {
168  if (type > KDbField::LastType)
169  return QLatin1String("Null");
170  return QLatin1String(KDb_defaultSqlTypeNames[type]);
171 }
172 
174 {
175  if (!name.startsWith(QLatin1String("kexi__"), Qt::CaseInsensitive))
176  return false;
178 }
179 
180 bool KDbDriver::isSystemFieldName(const QString& name) const
181 {
182  if (!d->driverBehavior.ROW_ID_FIELD_NAME.isEmpty()
183  && 0 == name.compare(d->driverBehavior.ROW_ID_FIELD_NAME, Qt::CaseInsensitive))
184  {
185  return true;
186  }
187  return drv_isSystemFieldName(name);
188 }
189 
190 KDbEscapedString valueToSqlInternal(const KDbDriver *driver, KDbField::Type ftype, const QVariant& v)
191 {
192  if (v.isNull() || ftype == KDbField::Null) {
193  return KDbEscapedString("NULL");
194  }
195  switch (ftype) {
196  case KDbField::Text:
197  case KDbField::LongText: {
198  return driver ? driver->escapeString(v.toString())
200  }
201  case KDbField::Byte:
203  case KDbField::Integer:
205  return KDbEscapedString(v.toByteArray());
206  case KDbField::Float:
207  case KDbField::Double: {
208  if (v.type() == QVariant::String) {
209  //workaround for values stored as string that should be casted to floating-point
211  return s.replace(',', '.');
212  }
213  return KDbEscapedString(v.toByteArray());
214  }
215 //! @todo here special encoding method needed
216  case KDbField::Boolean:
217  return driver
218  ? KDbEscapedString(v.toInt() == 0 ? KDbDriverPrivate::behavior(driver)->BOOLEAN_FALSE_LITERAL
219  : KDbDriverPrivate::behavior(driver)->BOOLEAN_TRUE_LITERAL)
220  : KDbEscapedString(v.toInt() == 0 ? "FALSE" : "TRUE");
221  case KDbField::Time:
222  return driver ? driver->timeToSql(v) : KDb::timeToSql(v);
223  case KDbField::Date:
224  return driver ? driver->dateToSql(v) : KDb::dateToSql(v);
225  case KDbField::DateTime:
226  return driver ? driver->dateTimeToSql(v) : KDb::dateTimeToSql(v);
227  case KDbField::BLOB: {
228  if (v.toByteArray().isEmpty()) {
229  return KDbEscapedString("NULL");
230  }
231  if (v.type() == QVariant::String) {
232  return driver ? driver->escapeBLOB(v.toString().toUtf8())
234  }
235  return driver ? driver->escapeBLOB(v.toByteArray())
237  }
239  return KDbEscapedString("!INVALIDTYPE!");
240  default:
241  kdbDebug() << KDbEscapedString("UNKNOWN!");
242  }
243  return KDbEscapedString();
244 }
245 
247 {
248  //! @note it was compatible with SQLite: https://www.sqlite.org/lang_datefunc.html
249  return valueToSqlInternal(this, ftype, v);
250 }
251 
253 {
254  return KDb::dateToIsoString(v);
255 }
256 
258 {
259  return KDb::timeToIsoString(v);
260 }
261 
263 {
264  return KDb::dateTimeToIsoString(v);
265 }
266 
268 {
269  return dateTimeToSql(QVariant(v));
270 }
271 
273 {
274  return QLatin1Char(d->driverBehavior.OPENING_QUOTATION_MARK_BEGIN_FOR_IDENTIFIER)
275  + drv_escapeIdentifier(str)
276  + QLatin1Char(d->driverBehavior.CLOSING_QUOTATION_MARK_BEGIN_FOR_IDENTIFIER);
277 }
278 
280 {
281  return d->driverBehavior.OPENING_QUOTATION_MARK_BEGIN_FOR_IDENTIFIER
282  + drv_escapeIdentifier(str)
283  + d->driverBehavior.CLOSING_QUOTATION_MARK_BEGIN_FOR_IDENTIFIER;
284 }
285 
287 {
288  return d->driverBehavior.properties.property(name);
289 }
290 
292 {
293  QList<QByteArray> names(d->driverBehavior.properties.names());
294  std::sort(names.begin(), names.end());
295  return names;
296 }
297 
298 void KDbDriver::initDriverSpecificKeywords(const char* const* keywords)
299 {
300  d->driverSpecificSqlKeywords.setStrings(keywords);
301 }
302 
304 {
305  return add ? (sql + " LIMIT 1") : sql;
306 }
307 
309 {
310  return d->driverSpecificSqlKeywords.contains(word);
311 }
312 
314 {
315  d->metaData = metaData;
316  d->driverBehavior.initInternalProperties();
317 }
318 
320  const KDbNArgExpression &args,
322  KDb::ExpressionCallStack* callStack) const
323 {
324  return KDbFunctionExpression::toString(QLatin1String("HEX"), this, args, params, callStack);
325 }
326 
328  const KDbNArgExpression &args,
330  KDb::ExpressionCallStack* callStack) const
331 {
332  return KDbFunctionExpression::toString(QLatin1String("IFNULL"), this, args, params, callStack);
333 }
334 
336  const KDbNArgExpression &args,
338  KDb::ExpressionCallStack* callStack) const
339 {
340  return KDbFunctionExpression::toString(QLatin1String("LENGTH"), this, args, params, callStack);
341 }
342 
344  const QString &name,
345  const KDbNArgExpression &args,
347  KDb::ExpressionCallStack* callStack) const
348 {
349  return KDbFunctionExpression::toString(name, this, args, params, callStack);
350 }
351 
353  const KDbNArgExpression &args,
355  KDb::ExpressionCallStack* callStack) const
356 {
357  static QLatin1String randomStatic("()");
358  if (!args.isNull() || args.argCount() < 1 ) {
359  return KDbEscapedString(d->driverBehavior.RANDOM_FUNCTION + randomStatic);
360  }
361  if (args.argCount() != 2) {
362  return KDbEscapedString();
363  }
364  const KDbEscapedString x(args.arg(0).toString(this, params, callStack));
365  const KDbEscapedString y(args.arg(1).toString(this, params, callStack));
366  static KDbEscapedString floorRandomStatic("+FLOOR(");
367  static KDbEscapedString floorRandomStatic2("()*(");
368  static KDbEscapedString floorRandomStatic3(")))");
369  return KDbEscapedString('(') + x + floorRandomStatic + d->driverBehavior.RANDOM_FUNCTION
370  + floorRandomStatic2 + y + QLatin1Char('-') + x + floorRandomStatic3;
371 }
372 
374  const QString &name,
375  const KDbNArgExpression &args,
377  KDb::ExpressionCallStack* callStack) const
378 {
379  return KDbFunctionExpression::toString(name, this, args, params, callStack);
380 }
381 
383  const KDbNArgExpression &args,
385  KDb::ExpressionCallStack* callStack) const
386 {
387  return KDbFunctionExpression::toString(QLatin1String("UNICODE"), this, args, params, callStack);
388 }
389 
392  KDb::ExpressionCallStack* callStack) const
393 {
394  return args.left().toString(this, params, callStack) + KDbEscapedString("||")
395  + args.right().toString(this, params, callStack);
396 }
397 
398 //---------------
399 
400 Q_GLOBAL_STATIC_WITH_ARGS(
402  KDb_kdbSqlKeywords,
403  (KDbDriverPrivate::kdbSQLKeywords) )
404 
405 KDB_EXPORT bool KDb::isKDbSqlKeyword(const QByteArray& word)
406 {
407  return KDb_kdbSqlKeywords->contains(word.toUpper());
408 }
409 
410 KDB_EXPORT QString KDb::escapeIdentifier(const KDbDriver* driver,
411  const QString& str)
412 {
413  return driver ? driver->escapeIdentifier(str)
414  : KDb::escapeIdentifier(str);
415 }
416 
417 KDB_EXPORT QByteArray KDb::escapeIdentifier(const KDbDriver* driver,
418  const QByteArray& str)
419 {
420  return driver ? driver->escapeIdentifier(str)
421  : KDb::escapeIdentifier(str);
422 }
virtual KDbAdminTools * drv_createAdminTools() const
Definition: KDbDriver.cpp:125
bool isNull() const const
virtual QString sqlTypeName(KDbField::Type type, const KDbField &field) const
Definition: KDbDriver.cpp:130
KDbAdminTools & adminTools() const
Definition: KDbDriver.cpp:118
bool transactionsSupported() const
Definition: KDbDriver.cpp:113
KDB_EXPORT QString escapeIdentifier(const QString &string)
Definition: KDb.cpp:1334
const QSet< KDbConnection * > connections() const
Definition: KDbDriver.cpp:98
bool isDriverSpecificKeyword(const QByteArray &word) const
Definition: KDbDriver.cpp:308
Provides information about a single driver plugin.
virtual KDbEscapedString timeToSql(const QVariant &v) const
Converts time value to string.
Definition: KDbDriver.cpp:257
virtual KDbConnection * drv_createConnection(const KDbConnectionData &connData, const KDbConnectionOptions &options)=0
KDbExpression arg(int i) const
CaseInsensitive
An iterator for a list of values of query schema parameters Allows to iterate over parameters and ret...
@ InvalidType
Definition: KDbField.h:86
The KDbBinaryExpression class represents binary operation.
QList< QByteArray > internalPropertyNames() const
Definition: KDbDriver.cpp:291
static QStringList kdbSystemTableNames()
~KDbDriver() override
Definition: KDbDriver.cpp:64
virtual KDbEscapedString dateToSql(const QVariant &v) const
Converts date value to string.
Definition: KDbDriver.cpp:252
@ Text
Definition: KDbField.h:98
@ ZeroXHex
Escaping like 0x1FAD, used by mysql (hex numbers)
KDbUtils::Property internalProperty(const QByteArray &name) const
Definition: KDbDriver.cpp:286
bool contains(const QString &str, Qt::CaseSensitivity cs) const const
KDB_EXPORT KDbEscapedString dateTimeToIsoString(const QVariant &v)
Converts date/time value to its string representation in ISO 8601 DateTime format - with "T" delimite...
Definition: KDb.cpp:2297
A set created from static (0-terminated) array of raw null-terminated strings.
Definition: KDbUtils.h:387
Specialized string for escaping.
KDB_EXPORT KDbEscapedString dateToSql(const QVariant &v)
Converts date value to its string representation required by KDBSQL commands.
Definition: KDb.cpp:2223
KDbConnection * removeConnection(KDbConnection *conn)
Definition: KDbDriver.cpp:158
Database driver's abstraction.
Definition: KDbDriver.h:49
QByteArray toByteArray() const const
QString escapeIdentifier(const QString &str) const
Definition: KDbDriver.cpp:272
KDB_DEPRECATED_EXPORT KDbEscapedString dateTimeToSql(const QDateTime &v)
Converts date/time value to its string representation in ISO 8601 DateTime format - with "T" delimite...
Definition: KDb.cpp:2282
virtual KDbEscapedString ifnullFunctionToString(const KDbNArgExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack) const
Generates native (driver-specific) IFNULL() function call.
Definition: KDbDriver.cpp:327
@ LastType
Definition: KDbField.h:102
static QString defaultSqlTypeName(KDbField::Type type)
Definition: KDbDriver.cpp:166
virtual KDbEscapedString escapeString(const QString &str) const =0
virtual KDbEscapedString addLimitTo1(const KDbEscapedString &sql, bool add=true)
Definition: KDbDriver.cpp:303
virtual KDbEscapedString randomFunctionToString(const KDbNArgExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack) const
Generates native (driver-specific) RANDOM() and RANDOM(X,Y) function calls.
Definition: KDbDriver.cpp:352
KDB_EXPORT bool isKDbSqlKeyword(const QByteArray &word)
QVariant::Type type() const const
@ SingleTransactions
single trasactions are only supported
Definition: KDbDriver.h:58
A single property.
Definition: KDbUtils.h:446
KDbConnection * createConnection(const KDbConnectionData &connData, const KDbConnectionOptions &options)
Definition: KDbDriver.cpp:139
@ Integer
Definition: KDbField.h:90
QByteArray toUtf8() const const
KDbEscapedString toString(const KDbDriver *driver, KDbQuerySchemaParameterValueListIterator *params=nullptr, KDb::ExpressionCallStack *callStack=nullptr) const
int toInt(bool *ok) const const
virtual QString drv_escapeIdentifier(const QString &str) const =0
static bool isKDbSystemObjectName(const QString &name)
Definition: KDbDriver.cpp:173
QByteArray toUpper() const const
@ BigInteger
Definition: KDbField.h:91
KDbDriverBehavior * behavior()
Returns structure that provides detailed information about driver's default behavior.
Definition: KDbDriver.cpp:74
virtual KDbEscapedString greatestOrLeastFunctionToString(const QString &name, const KDbNArgExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack) const
Generates native (driver-specific) GREATEST() and LEAST() function calls.
Definition: KDbDriver.cpp:343
void initDriverSpecificKeywords(const char *const *keywords)
Definition: KDbDriver.cpp:298
@ Double
Definition: KDbField.h:97
bool isSystemFieldName(const QString &name) const
Definition: KDbDriver.cpp:180
@ LongText
Definition: KDbField.h:99
@ Byte
Definition: KDbField.h:87
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
The KDbNArgExpression class represents a base class N-argument expression.
virtual KDbEscapedString valueToSql(KDbField::Type ftype, const QVariant &v) const
Definition: KDbDriver.cpp:246
KDB_EXPORT QString escapeBLOB(const QByteArray &array, BLOBEscapingType type)
An interface containing a set of tools for database administration.
Definition: KDbAdmin.h:30
Detailed definition of driver's default behavior.
KDB_EXPORT KDbEscapedString dateToIsoString(const QVariant &v)
Converts date value to its string representation in ISO 8601 DateTime format.
Definition: KDb.cpp:2287
bool isEmpty() const const
@ Boolean
Definition: KDbField.h:92
KDbDriver(QObject *parent, const QVariantList &args)
Definition: KDbDriver.cpp:56
virtual KDbEscapedString unicodeFunctionToString(const KDbNArgExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack) const
Generates native (driver-specific) UNICODE() function call.
Definition: KDbDriver.cpp:382
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
bool isNull() const
int features() const
Definition: KDbDriver.cpp:108
static KDbEscapedString toString(const QString &name, const KDbDriver *driver, const KDbNArgExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack)
Database specific connection data, e.g. host, port.
virtual KDbEscapedString lengthFunctionToString(const KDbNArgExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack) const
Generates native (driver-specific) LENGTH() function call.
Definition: KDbDriver.cpp:335
Generic options for a single connection. The options are accessible using key/value pairs....
Meta-data for a field.
Definition: KDbField.h:71
KDB_EXPORT QString escapeString(const QString &string)
Definition: KDb.cpp:1356
QList::iterator begin()
@ Float
Definition: KDbField.h:96
@ MultipleTransactions
multiple concurrent trasactions are supported (this implies !SingleTransactions)
Definition: KDbDriver.h:61
int compare(const QString &other, Qt::CaseSensitivity cs) const const
KDbEscapedString concatenateFunctionToString(const KDbBinaryExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack) const
Generates native (driver-specific) function call for concatenation of two strings.
Definition: KDbDriver.cpp:390
KDB_EXPORT KDbEscapedString timeToSql(const QVariant &v)
Converts time value to its string representation required by KDBSQL commands.
Definition: KDb.cpp:2249
Provides database connection, allowing queries and data modification.
Definition: KDbConnection.h:51
virtual bool drv_isSystemFieldName(const QString &name) const =0
QList::iterator end()
virtual KDbEscapedString dateTimeToSql(const QVariant &v) const
Converts date/time value to string.
Definition: KDbDriver.cpp:262
QString tr(const char *sourceText, const char *disambiguation, int n)
@ ShortInteger
Definition: KDbField.h:89
virtual bool isValid()
Definition: KDbDriver.cpp:84
void setMetaData(const KDbDriverMetaData *metaData)
Definition: KDbDriver.cpp:313
virtual KDbEscapedString escapeBLOB(const QByteArray &array) const =0
const KDbDriverMetaData * metaData() const
Definition: KDbDriver.cpp:103
virtual KDbEscapedString hexFunctionToString(const KDbNArgExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack) const
Generates native (driver-specific) HEX() function call.
Definition: KDbDriver.cpp:319
KDB_EXPORT KDbEscapedString timeToIsoString(const QVariant &v)
Converts time value to its string representation in ISO 8601 Time format.
Definition: KDb.cpp:2292
QString toString() const const
virtual KDbEscapedString ceilingOrFloorFunctionToString(const QString &name, const KDbNArgExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack) const
Generates native (driver-specific) CEILING() and FLOOR() function calls.
Definition: KDbDriver.cpp:373
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon May 8 2023 04:07:51 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.