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