1 /* This file is part of the KDE project
2 Copyright (C) 2003-2018 Jarosław Staniek <staniek@kde.org>
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 #ifndef KDB_DRIVER_H
21 #define KDB_DRIVER_H
22
23 #include <QDateTime>
24
25 #include "KDb.h"
26 #include "KDbResult.h"
27 #include "KDbEscapedString.h"
28 #include "KDbExpressionData.h"
29
30 class KDbAdminTools;
31 class KDbConnection;
32 class KDbConnectionData;
33 class KDbConnectionOptions;
34 class KDbDriverBehavior;
35 class KDbDriverMetaData;
36 class KDbBinaryExpression;
37 class KDbNArgExpression;
38 class KDbQuerySchemaParameterValueListIterator;
39 class KDbDriverPrivate;
40
41 #define KDB_DRIVER_PLUGIN_FACTORY(class_name, name) \
42 K_PLUGIN_FACTORY_WITH_JSON(class_name ## Factory, name, registerPlugin<class_name>();)
43
44 //! Database driver's abstraction.
45 /*! This class is a prototype of the database driver.
46 KDbDriver allows new connections to be created, and groups as their parent.
47 Before destruction, all owned connections are destructed.
48 */
49 class KDB_EXPORT KDbDriver : public QObject, public KDbResultable
50 {
51 Q_OBJECT
52
53 public:
54 /*! Features supported by driver (sum of few Features enum items). */
55 enum Features {
56 NoFeatures = 0,
57 //! single trasactions are only supported
58 SingleTransactions = 1,
59 //! multiple concurrent trasactions are supported
60 //! (this implies !SingleTransactions)
61 MultipleTransactions = 2,
62 //(js) NOT YET IN USE:
63 /*! nested trasactions are supported
64 (this should imply !SingleTransactions and MultipleTransactions) */
65 NestedTransactions = 4,
66 /*! forward moving is supported for cursors
67 (if not available, no cursors available at all) */
68 CursorForward = 8,
69 /*! backward moving is supported for cursors (this implies CursorForward) */
70 CursorBackward = (CursorForward + 16),
71 /*! compacting database supported (aka VACUUM) */
72 CompactingDatabaseSupported = 32,
73 //-- temporary options: can be removed later, use at your own risk --
74 /*! If set, actions related to transactions will be silently bypassed
75 with success. Set this if your driver does not support transactions at all
76 Currently, this is only way to get it working with KDb.
77 Keep in mind that this hack do not provide data integrity!
78 This flag is currently used for MySQL driver. */
79 IgnoreTransactions = 1024
80 };
81
82 /*! Creates connection using @a connData as parameters.
83 @return @c nullptr and sets error message on error.
84 driverId member of @a connData will be updated with the driver's ID.
85 @a options can be set for the new connection. */
86 KDbConnection *createConnection(const KDbConnectionData& connData,
87 const KDbConnectionOptions &options);
88
89 //! @overload createConnection(const KDbConnectionData&, const KDbConnectionOptions&)
90 KDbConnection *createConnection(const KDbConnectionData& connData);
91
92 /*! @return Set of created connections. */
93 const QSet<KDbConnection*> connections() const;
94
95 /*! Info about the driver. */
96 const KDbDriverMetaData* metaData() const;
97
98 /*! @return true if @a n is a database type-specific system object's name,
99 e.g. name of a built-in system table that cannot be created by the user,
100 and in most cases a name that user shouldn't even see.
101 @see isSystemDatabaseName() isKDbSystemObjectName() isSystemFieldName()
102 */
103 virtual bool isSystemObjectName(const QString& name) const = 0;
104
105 /*! @return true if @a name is a related to KDb's 'system' object's
106 name, i.e. when @a name starts with "kexi__" prefix.
107 @see isSystemDatabaseName() isSystemObjectName() isSystemFieldName()
108 */
109 static bool isKDbSystemObjectName(const QString& name);
110
111 /*! @return true if @a name is a database type-specific system database's name,
112 e.g. name of a built-in system database that cannot be created by a user,
113 and in most cases user a name that user shouldn't even see.
114 @see isKDbSystemObjectName() isSystemObjectName() isSystemFieldName()
115 */
116 virtual bool isSystemDatabaseName(const QString& name) const = 0;
117
118 /*! @return true if @a name is a system field's name, build-in system
119 field that cannot be used or created by a user,
120 and in most cases user even shouldn't see this. The list is specific for
121 a given driver implementation.
122 @see isSystemDatabaseName() isKDbSystemObjectName() isSystemObjectName()
123 */
124 bool isSystemFieldName(const QString& name) const;
125
126 /*! @return true if @a word is a driver-specific keyword.
127 @see KDb::isKDbSqlKeyword(const QByteArray&) */
128 bool isDriverSpecificKeyword(const QByteArray& word) const;
129
130 /*! @return driver's features that are combination of KDbDriver::Features enum.
131 @todo change int to Features */
132 int features() const;
133
134 /*! @return true if transaction are supported (single or multiple). */
135 bool transactionsSupported() const;
136
137 /*! @return admin tools object providing a number of database administration
138 tools for the driver. Tools availablility varies from driver to driver.
139 You can check it using features(). */
140 KDbAdminTools& adminTools() const;
141
142 /*! SQL-implementation-dependent name of given type */
143 virtual QString sqlTypeName(KDbField::Type type, const KDbField &field) const;
144
145 /*! used when we do not have KDbDriver instance yet */
146 static QString defaultSqlTypeName(KDbField::Type type);
147
148 /*! Escapes and converts value @a v (for type @a ftype)
149 to string representation required by SQL commands.
150 Reimplement this if you need other behavior (eg. for 'date' type handling)
151 This implementation return date, datetime and time values in ISO format,
152 what seems to be accepted by SQL servers.
153 @see Qt::DateFormat */
154 virtual KDbEscapedString valueToSql(KDbField::Type ftype, const QVariant& v) const;
155
156 //! Like above but with the fildtype as string.
valueToSql(const QString & ftype,const QVariant & v)157 inline KDbEscapedString valueToSql(const QString& ftype, const QVariant& v) const {
158 return valueToSql(KDbField::typeForString(ftype), v);
159 }
160
161 //! Like above method, for @a field.
valueToSql(const KDbField * field,const QVariant & v)162 inline KDbEscapedString valueToSql(const KDbField *field, const QVariant& v) const {
163 return valueToSql((field ? field->type() : KDbField::InvalidType), v);
164 }
165
166 /**
167 * Converts date value to string
168 *
169 * Default implementation uses KDb::dateToSql().
170 *
171 * Not compatible with all drivers - reimplement.
172 *
173 * @since 3.2.0
174 */
175 virtual KDbEscapedString dateToSql(const QVariant &v) const;
176
177 /**
178 * Converts time value to string
179 *
180 * Default implementation uses KDb::timeToIsoString().
181 *
182 * Not compatible with all drivers - reimplement.
183 *
184 * @since 3.2.0
185 */
186 virtual KDbEscapedString timeToSql(const QVariant &v) const;
187
188 /**
189 * Converts date/time value to string
190 *
191 * Default implementation uses KDb::dateTimeToIsoString().
192 *
193 * Not compatible with all drivers - reimplement.
194 *
195 * @since 3.2.0
196 */
197 virtual KDbEscapedString dateTimeToSql(const QVariant &v) const;
198
199 /**
200 * Converts date/time value to string
201 *
202 * Default implementation uses dateTimeToSql(QVariant).
203 * Deprecated, use dateTimeToSql(QVariant).
204 *
205 * Not compatible with all drivers - reimplement.
206 */
207 KDB_DEPRECATED virtual KDbEscapedString dateTimeToSql(const QDateTime& v) const;
208
209 /*! Driver-specific SQL string escaping.
210 Implement escaping for any character like " or ' as your
211 database engine requires. Prepend and append quotation marks.
212 */
213 virtual KDbEscapedString escapeString(const QString& str) const = 0;
214
215 /*! This is overloaded version of escapeString( const QString& str )
216 to be implemented in the same way.
217 */
218 virtual KDbEscapedString escapeString(const QByteArray& str) const = 0;
219
220 /*! Driver-specific SQL BLOB value escaping.
221 Implement escaping for any character like " or ' and \\0 as your
222 database engine requires. Prepend and append quotation marks.
223 */
224 virtual KDbEscapedString escapeBLOB(const QByteArray& array) const = 0;
225
226 /*! @return SQL clause to add for unicode text collation sequence
227 used in ORDER BY clauses of SQL statements generated by KDb.
228 Later other clauses may use this statement.
229 One space character should be be prepended.
230 Can be reimplemented for other drivers, e.g. the SQLite3 driver returns " COLLATE ''".
231 Default implementation returns empty string. */
collationSql()232 virtual KDbEscapedString collationSql() const {
233 return KDbEscapedString();
234 }
235
236 //! @return @a str string with applied driver-specific identifier escaping
237 /*! This escaping can be used for field, table, database names, etc.
238 @see KDb::escapeIdentifier */
239 QString escapeIdentifier(const QString& str) const;
240
241 //! @overload QString escapeIdentifier(const QString&) const
242 QByteArray escapeIdentifier(const QByteArray& str) const;
243
244 //! @return internal property with a name @a name for this driver.
245 //! If there's no such property defined for driver, a null property is returned.
246 KDbUtils::Property internalProperty(const QByteArray& name) const;
247
248 //! @return a list of internal property names for this driver.
249 QList<QByteArray> internalPropertyNames() const;
250
251 //! @internal
252 ~KDbDriver() override;
253
254 //! Generates native (driver-specific) HEX() function call.
255 //! Default implementation uses HEX(val).
256 virtual KDbEscapedString hexFunctionToString(
257 const KDbNArgExpression &args,
258 KDbQuerySchemaParameterValueListIterator* params,
259 KDb::ExpressionCallStack* callStack) const;
260
261 //! Generates native (driver-specific) IFNULL() function call.
262 //! Default implementation uses IFNULL().
263 virtual KDbEscapedString ifnullFunctionToString(
264 const KDbNArgExpression &args,
265 KDbQuerySchemaParameterValueListIterator* params,
266 KDb::ExpressionCallStack* callStack) const;
267
268 //! Generates native (driver-specific) LENGTH() function call.
269 //! Default implementation uses LENGTH().
270 virtual KDbEscapedString lengthFunctionToString(
271 const KDbNArgExpression &args,
272 KDbQuerySchemaParameterValueListIterator* params,
273 KDb::ExpressionCallStack* callStack) const;
274
275 //! Generates native (driver-specific) GREATEST() and LEAST() function calls.
276 //! Default implementation just uses GREATEST() and LEAST(), respectively.
277 //! (this works only with MySQL >= 5.0.13).
278 //! For backends workarounds are added.
279 virtual KDbEscapedString greatestOrLeastFunctionToString(
280 const QString &name,
281 const KDbNArgExpression &args,
282 KDbQuerySchemaParameterValueListIterator* params,
283 KDb::ExpressionCallStack* callStack) const;
284
285 //! Generates native (driver-specific) RANDOM() and RANDOM(X,Y) function calls.
286 //! Accepted @a args can contain zero or two positive integer arguments X, Y; X < Y.
287 //! In case of numeric arguments, RANDOM(X, Y) returns a random integer that is equal
288 //! or greater than X and less than Y.
289 //! Default implementation for RANDOM() returns F() where F is behavior()->RANDOM_FUNCTION.
290 //! This works with PostgreSQL.
291 //! Default implementation for RANDOM(X,Y) returns (X + FLOOR(F()*(Y-X+1))) where
292 //! F is behavior()->RANDOM_FUNCTION. This works with PostgreSQL.
293 //! If @a args has neither zero nor two arguments, empty string is returned.
294 virtual KDbEscapedString randomFunctionToString(
295 const KDbNArgExpression &args,
296 KDbQuerySchemaParameterValueListIterator* params,
297 KDb::ExpressionCallStack* callStack) const;
298
299 //! Generates native (driver-specific) CEILING() and FLOOR() function calls.
300 //! Default implementation USES CEILING() and FLOOR(), respectively.
301 //! Special case is for SQLite.
302 virtual KDbEscapedString ceilingOrFloorFunctionToString(
303 const QString &name,
304 const KDbNArgExpression &args,
305 KDbQuerySchemaParameterValueListIterator* params,
306 KDb::ExpressionCallStack* callStack) const;
307
308 //! Generates native (driver-specific) UNICODE() function call.
309 //! Default implementation USES UNICODE().
310 //! Special case is for MYSQL and PostgreSQL.
311 virtual KDbEscapedString unicodeFunctionToString(
312 const KDbNArgExpression &args,
313 KDbQuerySchemaParameterValueListIterator* params,
314 KDb::ExpressionCallStack* callStack) const;
315
316 //! Generates native (driver-specific) function call for concatenation of two strings.
317 //! Default implementation USES infix "||" operator.
318 //! Special case is for MYSQL (CONCAT()).
319 //! @todo API supporting KDbNArgExpression would be useful so instead of a||b||c can be
320 //! expressed as CONCAT(a,b,c) instead of CONCAT(CONCAT(a,b),c).
321 //! This requires changes to the KDbSQL parser.
322 KDbEscapedString concatenateFunctionToString(const KDbBinaryExpression &args,
323 KDbQuerySchemaParameterValueListIterator* params,
324 KDb::ExpressionCallStack* callStack) const;
325
326 protected:
327 /**
328 * @brief Returns structure that provides detailed information about driver's default behavior
329 *
330 * @since 3.1
331 */
332 KDbDriverBehavior *behavior();
333
334 /**
335 * @overload
336 */
337 const KDbDriverBehavior *behavior() const;
338
339 /*! Used by KDbDriverManager.
340 Note for driver developers: Reimplement this.
341 In your reimplementation you should initialize:
342 - beh->typeNames - to types accepted by your engine
343 - beh->features - to combination of selected values from Features enum
344
345 You may also want to change options in KDbDriverBehavior *beh member.
346 See drivers/mySQL/mysqldriver.cpp for usage example.
347 */
348 KDbDriver(QObject *parent, const QVariantList &args);
349
350 /*! For reimplementation: creates and returns connection object
351 with additional structures specific for a given driver.
352 KDbConnection object should inherit KDbConnection and have a destructor
353 that descructs all allocated driver-dependent connection structures. */
354 virtual KDbConnection *drv_createConnection(const KDbConnectionData& connData,
355 const KDbConnectionOptions &options) = 0;
356
357 /*! Driver-specific SQL string escaping.
358 This method is used by escapeIdentifier().
359 Implement escaping for any character like " or ' as your
360 database engine requires. Do not append or prepend any quotation
361 marks characters - it is automatically done by escapeIdentifier() using
362 KDbDriverBehavior::OPENING_QUOTATION_MARK_BEGIN_FOR_IDENTIFIER
363 and KDbDriverBehavior::CLOSING_QUOTATION_MARK_BEGIN_FOR_IDENTIFIER.
364 */
365 virtual QString drv_escapeIdentifier(const QString& str) const = 0;
366
367 /*! This is overloaded version of drv_escapeIdentifier( const QString& str )
368 to be implemented in the same way.
369 */
370 virtual QByteArray drv_escapeIdentifier(const QByteArray& str) const = 0;
371
372 /*! @return true if @a name is a system field's name, build-in system
373 field that cannot be used or created by a user,
374 and in most cases user even shouldn't see this. The list is specific for
375 a given driver implementation. For implementation.*/
376 virtual bool drv_isSystemFieldName(const QString& name) const = 0;
377
378 /*! Creates admin tools object providing a number of database administration
379 tools for the driver. This is called once per driver.
380
381 Note for driver developers: Reimplement this method by returning
382 a KDbAdminTools-derived object. Default implementation creates
383 anmd returns an empty admin tools KDbAdminTools object.
384 @see adminTools() */
385 virtual KDbAdminTools* drv_createAdminTools() const;
386
387 /*! @return connection @a conn, does not delete it nor affect.
388 Returns @c nullptr if @a conn is not owned by this driver.
389 After this, you are owner of @a conn object, so you should
390 eventually delete it. Better use KDbConnection destructor. */
391 KDbConnection* removeConnection(KDbConnection *conn);
392
393 /*! Used to initialise the dictionary of driver-specific keywords.
394 Should be called by the driver's constructor.
395 @a keywords should be 0-terminated array of null-terminated strings. */
396 void initDriverSpecificKeywords(const char* const* keywords);
397
398 /*! @return SQL statement @a sql modified by appending a "LIMIT 1" clause,
399 (if possible and if @a add is @c true). Used for optimization for the server side.
400 Can be reimplemented for other drivers. */
401 virtual KDbEscapedString addLimitTo1(const KDbEscapedString& sql, bool add = true);
402
403 /*! @return true if the database supports specifying default values for field @a field.
404 @c true by default.
405 For example MySQL does not support default values for BLOB, TEXT, GEOMETRY, and JSON types.
406 (https://dev.mysql.com/doc/refman/5.7/en/data-type-defaults.html). */
supportsDefaultValue(const KDbField & field)407 virtual bool supportsDefaultValue(const KDbField &field) const { Q_UNUSED(field); return true; }
408
409 /*! Used by the driver manager to set metaData for just loaded driver. */
410 void setMetaData(const KDbDriverMetaData *metaData);
411
412 /*! @return true if this driver's implementation is valid.
413 Just a few constraints are checked to ensure that driver developer didn't forget something.
414 This method is called automatically on createConnection(), and proper error message
415 is set properly on error.
416 Drivers can reimpement this method but should call KDbDriver::isValid() first. */
417 virtual bool isValid();
418
419 friend class KDbConnection;
420 friend class KDbCursor;
421 friend class KDbDriverBehavior;
422 friend class KDbNativeStatementBuilder;
423 friend class DriverManagerInternal;
424 friend class KDbDriverPrivate;
425
426 KDbDriverPrivate * const d;
427 private:
428 Q_DISABLE_COPY(KDbDriver)
429 };
430
431 namespace KDb {
432
433 //! @return string @a string with applied driver-specific identifier escaping if @a driver
434 //! is not KDbSQL general identifier escaping when @a driver is 0.
435 /*! This escaping can be used for field, table, database names, etc.
436 @see KDb::escapeIdentifier */
437 KDB_EXPORT QString escapeIdentifier(const KDbDriver* driver,
438 const QString& string);
439
440 //! @overload QString escapeIdentifier(const KDbDriver*, const QString&)
441 KDB_EXPORT QByteArray escapeIdentifier(const KDbDriver* driver,
442 const QByteArray& str);
443
valueToSql(const KDbDriver * driver,KDbField::Type ftype,const QVariant & v)444 inline KDbEscapedString valueToSql(const KDbDriver *driver, KDbField::Type ftype, const QVariant& v)
445 {
446 return driver ? driver->valueToSql(ftype, v) : KDb::valueToSql(ftype, v);
447 }
448
449 }
450
451 #endif
452