File indexing completed on 2024-05-05 16:47:14

0001 /* This file is part of the KDE project
0002    Copyright (C) 2003 Adam Pigg <adam@piggz.co.uk>
0003    Copyright (C) 2010-2016 Jarosław Staniek <staniek@kde.org>
0004 
0005    This program is free software; you can redistribute it and/or
0006    modify it under the terms of the GNU Library General Public
0007    License as published by the Free Software Foundation; either
0008    version 2 of the License, or (at your option) any later version.
0009 
0010    This program is distributed in the hope that it will be useful,
0011    but WITHOUT ANY WARRANTY; without even the implied warranty of
0012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013    Library General Public License for more details.
0014 
0015    You should have received a copy of the GNU Library General Public License
0016    along with this program; see the file COPYING.  If not, write to
0017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018  * Boston, MA 02110-1301, USA.
0019 */
0020 
0021 #ifndef KDB_POSTGRESQLDRIVER_H
0022 #define KDB_POSTGRESQLDRIVER_H
0023 
0024 #include "KDbDriver.h"
0025 
0026 class KDbConnection;
0027 
0028 //! PostgreSQL database driver.
0029 class PostgresqlDriver : public KDbDriver
0030 {
0031     Q_OBJECT
0032 
0033 public:
0034     PostgresqlDriver(QObject *parent, const QVariantList &args);
0035 
0036     ~PostgresqlDriver() override;
0037 
0038     //! @todo implement
0039     bool isSystemObjectName(const QString& name) const override;
0040 
0041     bool isSystemDatabaseName(const QString& name) const override;
0042 
0043     //! Escape a string for use as a value
0044     KDbEscapedString escapeString(const QString& str) const override;
0045     KDbEscapedString escapeString(const QByteArray& str) const override;
0046     //! Overrides the default implementation to allow for NUMERIC type natively
0047     QString sqlTypeName(KDbField::Type type, const KDbField &field) const override;
0048 
0049     //! Escape BLOB value @a array
0050     KDbEscapedString escapeBLOB(const QByteArray& array) const override;
0051 
0052     //! Converts information converted from PQfmod() to length. -1 if missing.
0053     inline static int pqfmodToLength(int pqfmod) {
0054         int len;
0055         if (pqfmod > 0) {
0056             const int PGSQL_VAR_HDRSZ = 4;
0057             len = pqfmod - PGSQL_VAR_HDRSZ; //!< See e.g. postgis_get_char_length()
0058         } else {
0059             len = -1;
0060         }
0061         return len;
0062     }
0063 
0064     //! Uses information obtained from PQfmod() and adjust type @a t if possible.
0065     //! Also sets @a maxTextLength.
0066     //! @todo using pqfmod not tested
0067     //! @todo more types such as decimal
0068     inline static KDbField::Type typeForSize(KDbField::Type t, int pqfmod, int *maxTextLength) {
0069         KDbField::Type newType = t;
0070         if (maxTextLength) {
0071             *maxTextLength = -1;
0072         }
0073         if (t == KDbField::Integer) {
0074             if (pqfmod == 1) {
0075                 newType = KDbField::Byte;
0076             } else if (pqfmod == 2) {
0077                 newType = KDbField::ShortInteger;
0078             } else if (pqfmod == 8) {
0079                 newType = KDbField::BigInteger;
0080             }
0081         } else if (t == KDbField::LongText) {
0082             const int len = pqfmodToLength(pqfmod);
0083             if (len > 0 && len <= 255) {
0084                 newType = KDbField::Text;
0085                 if (maxTextLength) {
0086                     *maxTextLength = len;
0087                 }
0088             }
0089         }
0090         return newType;
0091     }
0092 
0093     //! @return KDb field type for PostgreSQL type @a pqtype and modifier @a pqfmod.
0094     //! If type cannot be found KDbField::InvalidType is returned.
0095     //! Used in cursors to speed up data conversion.
0096     inline KDbField::Type pgsqlToKDbType(int pqtype, int pqfmod, int *maxTextLength) const {
0097         KDbField::Type t = m_pgsqlToKDbTypes.value(pqtype, KDbField::InvalidType);
0098         return typeForSize(t, pqfmod, maxTextLength);
0099     }
0100 
0101     //! Generates native (driver-specific) HEX() function call.
0102     //! Uses UPPER(ENCODE(val, 'hex')).
0103     //! See https://www.postgresql.org/docs/9.3/static/functions-string.html#FUNCTIONS-STRING-OTHER */
0104     KDbEscapedString hexFunctionToString(const KDbNArgExpression &args,
0105                                          KDbQuerySchemaParameterValueListIterator* params,
0106                                          KDb::ExpressionCallStack* callStack) const override;
0107 
0108     //! Generates native (driver-specific) IFNULL() function call.
0109     //! Uses COALESCE().
0110     KDbEscapedString ifnullFunctionToString(const KDbNArgExpression &args,
0111                                             KDbQuerySchemaParameterValueListIterator* params,
0112                                             KDb::ExpressionCallStack* callStack) const override;
0113 
0114     //! Generates native (driver-specific) LENGTH() function call.
0115     //! For text types default LENGTH(val) is used, for BLOBs OCTET_LENGTH(val) is used because
0116     //! LENGTH(val) for BLOB returns number of bits.
0117     KDbEscapedString lengthFunctionToString(const KDbNArgExpression &args,
0118                                             KDbQuerySchemaParameterValueListIterator* params,
0119                                             KDb::ExpressionCallStack* callStack) const override;
0120 
0121     //! Generates native (driver-specific) GREATEST() and LEAST() function calls.
0122     //! Since PostgreSQL's LEAST()/GREATEST() function ignores NULL values, it only returns NULL
0123     //! if all the expressions evaluate to NULL. So this is used for F(v0,..,vN):
0124     //! (CASE WHEN (v0) IS NULL OR .. OR (vN) IS NULL THEN NULL ELSE F(v0,..,vN) END)
0125     //! where F == GREATEST or LEAST.
0126     KDbEscapedString greatestOrLeastFunctionToString(const QString &name,
0127                                                      const KDbNArgExpression &args,
0128                                                      KDbQuerySchemaParameterValueListIterator* params,
0129                                                      KDb::ExpressionCallStack* callStack) const override;
0130 
0131     //! Generates native (driver-specific) UNICODE() function call.
0132     //! Uses ASCII(X).
0133     KDbEscapedString unicodeFunctionToString(const KDbNArgExpression &args,
0134                                              KDbQuerySchemaParameterValueListIterator* params,
0135                                              KDb::ExpressionCallStack* callStack) const override;
0136 
0137 protected:
0138     QString drv_escapeIdentifier(const QString& str) const override;
0139     QByteArray drv_escapeIdentifier(const QByteArray& str) const override;
0140     KDbConnection *drv_createConnection(const KDbConnectionData& connData,
0141                                         const KDbConnectionOptions &options) override;
0142     bool drv_isSystemFieldName(const QString& name)const override;
0143 
0144 private:
0145     void initPgsqlToKDbMap();
0146 
0147     static const char *m_keywords[];
0148     QMap<int, KDbField::Type> m_pgsqlToKDbTypes;
0149     Q_DISABLE_COPY(PostgresqlDriver)
0150 };
0151 
0152 #endif // KDB_DRIVER_POSTGRESQLDRIVER_H