File indexing completed on 2024-12-08 07:18:20

0001 /* This file is part of the KDE project
0002    Copyright (C) 2003-2018 Jarosław Staniek <staniek@kde.org>
0003 
0004    This program is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU Library General Public
0006    License as published by the Free Software Foundation; either
0007    version 2 of the License, or (at your option) any later version.
0008 
0009    This program is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this program; see the file COPYING.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017  * Boston, MA 02110-1301, USA.
0018 */
0019 
0020 #ifndef KDB_DRIVER_H
0021 #define KDB_DRIVER_H
0022 
0023 #include <QDateTime>
0024 
0025 #include "KDb.h"
0026 #include "KDbResult.h"
0027 #include "KDbEscapedString.h"
0028 #include "KDbExpressionData.h"
0029 
0030 class KDbAdminTools;
0031 class KDbConnection;
0032 class KDbConnectionData;
0033 class KDbConnectionOptions;
0034 class KDbDriverBehavior;
0035 class KDbDriverMetaData;
0036 class KDbBinaryExpression;
0037 class KDbNArgExpression;
0038 class KDbQuerySchemaParameterValueListIterator;
0039 class KDbDriverPrivate;
0040 
0041 #define KDB_DRIVER_PLUGIN_FACTORY(class_name, name) \
0042     K_PLUGIN_FACTORY_WITH_JSON(class_name ## Factory, name, registerPlugin<class_name>();)
0043 
0044 //! Database driver's abstraction.
0045 /*! This class is a prototype of the database driver.
0046  KDbDriver allows new connections to be created, and groups as their parent.
0047  Before destruction, all owned connections are destructed.
0048 */
0049 class KDB_EXPORT KDbDriver : public QObject, public KDbResultable
0050 {
0051     Q_OBJECT
0052 
0053 public:
0054     /*! Features supported by driver (sum of few Features enum items). */
0055     enum Features {
0056         NoFeatures = 0,
0057         //! single trasactions are only supported
0058         SingleTransactions = 1,
0059         //! multiple concurrent trasactions are supported
0060         //! (this implies !SingleTransactions)
0061         MultipleTransactions = 2,
0062 //(js) NOT YET IN USE:
0063         /*! nested trasactions are supported
0064          (this should imply !SingleTransactions and MultipleTransactions) */
0065         NestedTransactions = 4,
0066         /*! forward moving is supported for cursors
0067          (if not available, no cursors available at all) */
0068         CursorForward = 8,
0069         /*! backward moving is supported for cursors (this implies CursorForward) */
0070         CursorBackward = (CursorForward + 16),
0071         /*! compacting database supported (aka VACUUM) */
0072         CompactingDatabaseSupported = 32,
0073         //-- temporary options: can be removed later, use at your own risk --
0074         /*! If set, actions related to transactions will be silently bypassed
0075          with success. Set this if your driver does not support transactions at all
0076          Currently, this is only way to get it working with KDb.
0077          Keep in mind that this hack do not provide data integrity!
0078          This flag is currently used for MySQL driver. */
0079         IgnoreTransactions = 1024
0080     };
0081 
0082     /*! Creates connection using @a connData as parameters.
0083      @return @c nullptr and sets error message on error.
0084      driverId member of @a connData will be updated with the driver's ID.
0085      @a options can be set for the new connection. */
0086     KDbConnection *createConnection(const KDbConnectionData& connData,
0087                                     const KDbConnectionOptions &options);
0088 
0089     //! @overload createConnection(const KDbConnectionData&, const KDbConnectionOptions&)
0090     KDbConnection *createConnection(const KDbConnectionData& connData);
0091 
0092     /*! @return Set of created connections. */
0093     const QSet<KDbConnection*> connections() const;
0094 
0095     /*! Info about the driver. */
0096     const KDbDriverMetaData* metaData() const;
0097 
0098     /*! @return true if @a n is a database type-specific system object's name,
0099      e.g. name of a built-in system table that cannot be created by the user,
0100      and in most cases a name that user shouldn't even see.
0101      @see isSystemDatabaseName() isKDbSystemObjectName() isSystemFieldName()
0102     */
0103     virtual bool isSystemObjectName(const QString& name) const = 0;
0104 
0105     /*! @return true if @a name is a related to KDb's 'system' object's
0106      name, i.e. when @a name starts with "kexi__" prefix.
0107      @see isSystemDatabaseName() isSystemObjectName() isSystemFieldName()
0108     */
0109     static bool isKDbSystemObjectName(const QString& name);
0110 
0111     /*! @return true if @a name is a database type-specific system database's name,
0112      e.g. name of a built-in system database that cannot be created by a user,
0113      and in most cases user a name that user shouldn't even see.
0114      @see isKDbSystemObjectName() isSystemObjectName() isSystemFieldName()
0115     */
0116     virtual bool isSystemDatabaseName(const QString& name) const = 0;
0117 
0118     /*! @return true if @a name is a system field's name, build-in system
0119      field that cannot be used or created by a user,
0120      and in most cases user even shouldn't see this. The list is specific for
0121      a given driver implementation.
0122      @see isSystemDatabaseName() isKDbSystemObjectName() isSystemObjectName()
0123     */
0124     bool isSystemFieldName(const QString& name) const;
0125 
0126     /*! @return true if @a word is a driver-specific keyword.
0127      @see KDb::isKDbSqlKeyword(const QByteArray&) */
0128     bool isDriverSpecificKeyword(const QByteArray& word) const;
0129 
0130     /*! @return driver's features that are combination of KDbDriver::Features enum.
0131     @todo change int to Features */
0132     int features() const;
0133 
0134     /*! @return true if transaction are supported (single or multiple). */
0135     bool transactionsSupported() const;
0136 
0137     /*! @return admin tools object providing a number of database administration
0138      tools for the driver. Tools availablility varies from driver to driver.
0139      You can check it using features().  */
0140     KDbAdminTools& adminTools() const;
0141 
0142     /*! SQL-implementation-dependent name of given type */
0143     virtual QString sqlTypeName(KDbField::Type type, const KDbField &field) const;
0144 
0145     /*! used when we do not have KDbDriver instance yet */
0146     static QString defaultSqlTypeName(KDbField::Type type);
0147 
0148     /*! Escapes and converts value @a v (for type @a ftype)
0149      to string representation required by SQL commands.
0150      Reimplement this if you need other behavior (eg. for 'date' type handling)
0151      This implementation return date, datetime and time values in ISO format,
0152      what seems to be accepted by SQL servers.
0153      @see Qt::DateFormat */
0154     virtual KDbEscapedString valueToSql(KDbField::Type ftype, const QVariant& v) const;
0155 
0156     //! Like above but with the fildtype as string.
0157     inline KDbEscapedString valueToSql(const QString& ftype, const QVariant& v) const {
0158         return valueToSql(KDbField::typeForString(ftype), v);
0159     }
0160 
0161     //! Like above method, for @a field.
0162     inline KDbEscapedString valueToSql(const KDbField *field, const QVariant& v) const {
0163         return valueToSql((field ? field->type() : KDbField::InvalidType), v);
0164     }
0165 
0166     /**
0167      * Converts date value to string
0168      *
0169      * Default implementation uses KDb::dateToSql().
0170      *
0171      * Not compatible with all drivers - reimplement.
0172      *
0173      * @since 3.2.0
0174      */
0175     virtual KDbEscapedString dateToSql(const QVariant &v) const;
0176 
0177     /**
0178      * Converts time value to string
0179      *
0180      * Default implementation uses KDb::timeToIsoString().
0181      *
0182      * Not compatible with all drivers - reimplement.
0183      *
0184      * @since 3.2.0
0185      */
0186     virtual KDbEscapedString timeToSql(const QVariant &v) const;
0187 
0188     /**
0189      * Converts date/time value to string
0190      *
0191      * Default implementation uses KDb::dateTimeToIsoString().
0192      *
0193      * Not compatible with all drivers - reimplement.
0194      *
0195      * @since 3.2.0
0196      */
0197     virtual KDbEscapedString dateTimeToSql(const QVariant &v) const;
0198 
0199     /**
0200      * Converts date/time value to string
0201      *
0202      * Default implementation uses dateTimeToSql(QVariant).
0203      * Deprecated, use dateTimeToSql(QVariant).
0204      *
0205      * Not compatible with all drivers - reimplement.
0206      */
0207     KDB_DEPRECATED virtual KDbEscapedString dateTimeToSql(const QDateTime& v) const;
0208 
0209     /*! Driver-specific SQL string escaping.
0210      Implement escaping for any character like " or ' as your
0211      database engine requires. Prepend and append quotation marks.
0212     */
0213     virtual KDbEscapedString escapeString(const QString& str) const = 0;
0214 
0215     /*! This is overloaded version of escapeString( const QString& str )
0216      to be implemented in the same way.
0217     */
0218     virtual KDbEscapedString escapeString(const QByteArray& str) const = 0;
0219 
0220     /*! Driver-specific SQL BLOB value escaping.
0221      Implement escaping for any character like " or ' and \\0 as your
0222      database engine requires. Prepend and append quotation marks.
0223     */
0224     virtual KDbEscapedString escapeBLOB(const QByteArray& array) const = 0;
0225 
0226     /*! @return SQL clause to add for unicode text collation sequence
0227      used in ORDER BY clauses of SQL statements generated by KDb.
0228      Later other clauses may use this statement.
0229      One space character should be be prepended.
0230      Can be reimplemented for other drivers, e.g. the SQLite3 driver returns " COLLATE ''".
0231      Default implementation returns empty string. */
0232     virtual KDbEscapedString collationSql() const {
0233         return KDbEscapedString();
0234     }
0235 
0236     //! @return @a str string with applied driver-specific identifier escaping
0237     /*! This escaping can be used for field, table, database names, etc.
0238         @see KDb::escapeIdentifier */
0239     QString escapeIdentifier(const QString& str) const;
0240 
0241     //! @overload QString escapeIdentifier(const QString&) const
0242     QByteArray escapeIdentifier(const QByteArray& str) const;
0243 
0244     //! @return internal property with a name @a name for this driver.
0245     //! If there's no such property defined for driver, a null property is returned.
0246     KDbUtils::Property internalProperty(const QByteArray& name) const;
0247 
0248     //! @return a list of internal property names for this driver.
0249     QList<QByteArray> internalPropertyNames() const;
0250 
0251     //! @internal
0252     ~KDbDriver() override;
0253 
0254     //! Generates native (driver-specific) HEX() function call.
0255     //! Default implementation uses HEX(val).
0256     virtual KDbEscapedString hexFunctionToString(
0257                                         const KDbNArgExpression &args,
0258                                         KDbQuerySchemaParameterValueListIterator* params,
0259                                         KDb::ExpressionCallStack* callStack) const;
0260 
0261     //! Generates native (driver-specific) IFNULL() function call.
0262     //! Default implementation uses IFNULL().
0263     virtual KDbEscapedString ifnullFunctionToString(
0264                                            const KDbNArgExpression &args,
0265                                            KDbQuerySchemaParameterValueListIterator* params,
0266                                            KDb::ExpressionCallStack* callStack) const;
0267 
0268     //! Generates native (driver-specific) LENGTH() function call.
0269     //! Default implementation uses LENGTH().
0270     virtual KDbEscapedString lengthFunctionToString(
0271                                            const KDbNArgExpression &args,
0272                                            KDbQuerySchemaParameterValueListIterator* params,
0273                                            KDb::ExpressionCallStack* callStack) const;
0274 
0275     //! Generates native (driver-specific) GREATEST() and LEAST() function calls.
0276     //! Default implementation just uses GREATEST() and LEAST(), respectively.
0277     //! (this works only with MySQL >= 5.0.13).
0278     //! For backends workarounds are added.
0279     virtual KDbEscapedString greatestOrLeastFunctionToString(
0280                                                     const QString &name,
0281                                                     const KDbNArgExpression &args,
0282                                                     KDbQuerySchemaParameterValueListIterator* params,
0283                                                     KDb::ExpressionCallStack* callStack) const;
0284 
0285     //! Generates native (driver-specific) RANDOM() and RANDOM(X,Y) function calls.
0286     //! Accepted @a args can contain zero or two positive integer arguments X, Y; X < Y.
0287     //! In case of numeric arguments, RANDOM(X, Y) returns a random integer that is equal
0288     //! or greater than X and less than Y.
0289     //! Default implementation for RANDOM() returns F() where F is behavior()->RANDOM_FUNCTION.
0290     //! This works with PostgreSQL.
0291     //! Default implementation for RANDOM(X,Y) returns (X + FLOOR(F()*(Y-X+1))) where
0292     //! F is behavior()->RANDOM_FUNCTION. This works with PostgreSQL.
0293     //! If @a args has neither zero nor two arguments, empty string is returned.
0294     virtual KDbEscapedString randomFunctionToString(
0295                                            const KDbNArgExpression &args,
0296                                            KDbQuerySchemaParameterValueListIterator* params,
0297                                            KDb::ExpressionCallStack* callStack) const;
0298 
0299     //! Generates native (driver-specific) CEILING() and FLOOR() function calls.
0300     //! Default implementation USES CEILING() and FLOOR(), respectively.
0301     //! Special case is for SQLite.
0302     virtual KDbEscapedString ceilingOrFloorFunctionToString(
0303                                             const QString &name,
0304                                             const KDbNArgExpression &args,
0305                                             KDbQuerySchemaParameterValueListIterator* params,
0306                                             KDb::ExpressionCallStack* callStack) const;
0307 
0308     //! Generates native (driver-specific) UNICODE() function call.
0309     //! Default implementation USES UNICODE().
0310     //! Special case is for MYSQL and PostgreSQL.
0311     virtual KDbEscapedString unicodeFunctionToString(
0312                                             const KDbNArgExpression &args,
0313                                             KDbQuerySchemaParameterValueListIterator* params,
0314                                             KDb::ExpressionCallStack* callStack) const;
0315 
0316     //! Generates native (driver-specific) function call for concatenation of two strings.
0317     //! Default implementation USES infix "||" operator.
0318     //! Special case is for MYSQL (CONCAT()).
0319     //! @todo API supporting KDbNArgExpression would be useful so instead of a||b||c can be
0320     //!       expressed as CONCAT(a,b,c) instead of CONCAT(CONCAT(a,b),c).
0321     //!       This requires changes to the KDbSQL parser.
0322     KDbEscapedString concatenateFunctionToString(const KDbBinaryExpression &args,
0323                                                  KDbQuerySchemaParameterValueListIterator* params,
0324                                                  KDb::ExpressionCallStack* callStack) const;
0325 
0326 protected:
0327     /**
0328      * @brief Returns structure that provides detailed information about driver's default behavior
0329      *
0330      * @since 3.1
0331      */
0332     KDbDriverBehavior *behavior();
0333 
0334     /**
0335      * @overload
0336      */
0337     const KDbDriverBehavior *behavior() const;
0338 
0339     /*! Used by KDbDriverManager.
0340      Note for driver developers: Reimplement this.
0341      In your reimplementation you should initialize:
0342      - beh->typeNames - to types accepted by your engine
0343      - beh->features - to combination of selected values from Features enum
0344 
0345      You may also want to change options in KDbDriverBehavior *beh member.
0346      See drivers/mySQL/mysqldriver.cpp for usage example.
0347      */
0348     KDbDriver(QObject *parent, const QVariantList &args);
0349 
0350     /*! For reimplementation: creates and returns connection object
0351      with additional structures specific for a given driver.
0352      KDbConnection object should inherit KDbConnection and have a destructor
0353      that descructs all allocated driver-dependent connection structures. */
0354     virtual KDbConnection *drv_createConnection(const KDbConnectionData& connData,
0355                                                 const KDbConnectionOptions &options) = 0;
0356 
0357     /*! Driver-specific SQL string escaping.
0358      This method is used by escapeIdentifier().
0359      Implement escaping for any character like " or ' as your
0360      database engine requires. Do not append or prepend any quotation
0361      marks characters - it is automatically done by escapeIdentifier() using
0362      KDbDriverBehavior::OPENING_QUOTATION_MARK_BEGIN_FOR_IDENTIFIER
0363      and KDbDriverBehavior::CLOSING_QUOTATION_MARK_BEGIN_FOR_IDENTIFIER.
0364     */
0365     virtual QString drv_escapeIdentifier(const QString& str) const = 0;
0366 
0367     /*! This is overloaded version of drv_escapeIdentifier( const QString& str )
0368      to be implemented in the same way.
0369     */
0370     virtual QByteArray drv_escapeIdentifier(const QByteArray& str) const = 0;
0371 
0372     /*! @return true if @a name is a system field's name, build-in system
0373      field that cannot be used or created by a user,
0374      and in most cases user even shouldn't see this. The list is specific for
0375      a given driver implementation. For implementation.*/
0376     virtual bool drv_isSystemFieldName(const QString& name) const = 0;
0377 
0378     /*! Creates admin tools object providing a number of database administration
0379      tools for the driver. This is called once per driver.
0380 
0381      Note for driver developers: Reimplement this method by returning
0382      a KDbAdminTools-derived object. Default implementation creates
0383      anmd returns an empty admin tools KDbAdminTools object.
0384      @see adminTools() */
0385     virtual KDbAdminTools* drv_createAdminTools() const;
0386 
0387     /*! @return connection @a conn, does not delete it nor affect.
0388      Returns @c nullptr if @a conn is not owned by this driver.
0389      After this, you are owner of @a conn object, so you should
0390      eventually delete it. Better use KDbConnection destructor. */
0391     KDbConnection* removeConnection(KDbConnection *conn);
0392 
0393     /*! Used to initialise the dictionary of driver-specific keywords.
0394       Should be called by the driver's constructor.
0395       @a keywords should be 0-terminated array of null-terminated strings. */
0396     void initDriverSpecificKeywords(const char* const* keywords);
0397 
0398     /*! @return SQL statement @a sql modified by appending a "LIMIT 1" clause,
0399      (if possible and if @a add is @c true). Used for optimization for the server side.
0400      Can be reimplemented for other drivers. */
0401     virtual KDbEscapedString addLimitTo1(const KDbEscapedString& sql, bool add = true);
0402 
0403     /*! @return true if the database supports specifying default values for field @a field.
0404      @c true by default.
0405      For example MySQL does not support default values for BLOB, TEXT, GEOMETRY, and JSON types.
0406      (https://dev.mysql.com/doc/refman/5.7/en/data-type-defaults.html). */
0407     virtual bool supportsDefaultValue(const KDbField &field) const { Q_UNUSED(field); return true; }
0408 
0409     /*! Used by the driver manager to set metaData for just loaded driver. */
0410     void setMetaData(const KDbDriverMetaData *metaData);
0411 
0412     /*! @return true if this driver's implementation is valid.
0413      Just a few constraints are checked to ensure that driver developer didn't forget something.
0414      This method is called automatically on createConnection(), and proper error message
0415      is set properly on error.
0416      Drivers can reimpement this method but should call KDbDriver::isValid() first. */
0417     virtual bool isValid();
0418 
0419     friend class KDbConnection;
0420     friend class KDbCursor;
0421     friend class KDbDriverBehavior;
0422     friend class KDbNativeStatementBuilder;
0423     friend class DriverManagerInternal;
0424     friend class KDbDriverPrivate;
0425 
0426     KDbDriverPrivate * const d;
0427 private:
0428     Q_DISABLE_COPY(KDbDriver)
0429 };
0430 
0431 namespace KDb {
0432 
0433 //! @return string @a string with applied driver-specific identifier escaping if @a driver
0434 //!         is not KDbSQL general identifier escaping when @a driver is 0.
0435 /*! This escaping can be used for field, table, database names, etc.
0436     @see KDb::escapeIdentifier */
0437 KDB_EXPORT QString escapeIdentifier(const KDbDriver* driver,
0438                                     const QString& string);
0439 
0440 //! @overload QString escapeIdentifier(const KDbDriver*, const QString&)
0441 KDB_EXPORT QByteArray escapeIdentifier(const KDbDriver* driver,
0442                                        const QByteArray& str);
0443 
0444 inline KDbEscapedString valueToSql(const KDbDriver *driver, KDbField::Type ftype, const QVariant& v)
0445 {
0446     return driver ? driver->valueToSql(ftype, v) : KDb::valueToSql(ftype, v);
0447 }
0448 
0449 }
0450 
0451 #endif