KDb

MysqlDriver.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2002 Lucijan Busch <lucijan@gmx.at>
3 Copyright (C) 2003 Daniel Molkentin <molkentin@kde.org>
4 Copyright (C) 2003 Joseph Wenninger<jowenn@kde.org>
5 Copyright (C) 2003-2016 Jarosław Staniek <staniek@kde.org>
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public License
18 along with this program; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21*/
22
23#include "MysqlDriver.h"
24#include "KDbDriverBehavior.h"
25#include "KDbExpression.h"
26#include "KDbPreparedStatement.h"
27#include "MysqlConnection.h"
28
29#include <KPluginFactory>
30
31#include <mysql.h>
32
33K_PLUGIN_CLASS_WITH_JSON(MysqlDriver, "kdb_mysqldriver.json")
34
35/*! @todo Implement buffered/unbuffered cursor, rather than buffer everything.
36 Each MYSQL connection can only handle at most one unbuffered cursor,
37 so MysqlConnection should keep count?
38 */
39
40MysqlDriver::MysqlDriver(QObject *parent, const QVariantList &args)
41 : KDbDriver(parent, args)
42 , m_longTextPrimaryKeyType(QLatin1String("VARCHAR(255)")) // fair enough for PK
43{
44 KDbDriverBehavior *beh = behavior();
45 beh->features = IgnoreTransactions | CursorForward;
46
47 beh->ROW_ID_FIELD_NAME = QLatin1String("LAST_INSERT_ID()");
53 //! @todo add configuration option
54 beh->TEXT_TYPE_MAX_LENGTH = 255;
55 beh->RANDOM_FUNCTION = QLatin1String("RAND");
56 beh->GET_TABLE_NAMES_SQL = KDbEscapedString("SHOW TABLES");
57
58 initDriverSpecificKeywords(keywords);
59
60 //predefined properties
61#if MYSQL_VERSION_ID < 40000
62 beh->properties["client_library_version"] = MYSQL_SERVER_VERSION; //nothing better
63 beh->properties["default_server_encoding"] = MYSQL_CHARSET; //nothing better
64#else
65 // https://dev.mysql.com/doc/refman/5.7/en/mysql-get-client-version.html
66 beh->properties.insert("client_library_version", int(mysql_get_client_version()));
67#endif
68
69 beh->typeNames[KDbField::Byte] = QLatin1String("TINYINT");
73 // Can use BOOLEAN here, but BOOL has been in MySQL longer
75 beh->typeNames[KDbField::Date] = QLatin1String("DATE");
76 beh->typeNames[KDbField::DateTime] = QLatin1String("DATETIME");
77 beh->typeNames[KDbField::Time] = QLatin1String("TIME");
80 beh->typeNames[KDbField::Text] = QLatin1String("VARCHAR");
81 beh->typeNames[KDbField::LongText] = QLatin1String("LONGTEXT");
83}
84
85MysqlDriver::~MysqlDriver()
86{
87}
88
90 const KDbConnectionOptions &options)
91{
92 return new MysqlConnection(this, connData, options);
93}
94
96{
97 Q_UNUSED(name);
98 return false;
99}
100
102{
103 return 0 == name.compare(QLatin1String("mysql"), Qt::CaseInsensitive)
104 || 0 == name.compare(QLatin1String("information_schema"), Qt::CaseInsensitive)
105 || 0 == name.compare(QLatin1String("performance_schema"), Qt::CaseInsensitive);
106}
107
109{
110 Q_UNUSED(name);
111 return false;
112}
113
115{
116 switch(field.type()) {
118 case KDbField::BLOB:
119 return false;
120 default:
121 return true;
122 }
123}
124
126{
127 //escape as in https://dev.mysql.com/doc/refman/5.0/en/string-syntax.html
128//! @todo support more characters, like %, _
129
130 const int old_length = str.length();
131 int i;
132 for (i = 0; i < old_length; i++) { //anything to escape?
133 const unsigned int ch = str[i].unicode();
134 if (ch == '\\' || ch == '\'' || ch == '"' || ch == '\n' || ch == '\r' || ch == '\t' || ch == '\b' || ch == '\0')
135 break;
136 }
137 if (i >= old_length) { //no characters to escape
138 return KDbEscapedString("'") + KDbEscapedString(str) + '\'';
139 }
140
141 QChar *new_string = new QChar[ old_length * 3 + 1 ]; // a worst case approximation
142//! @todo move new_string to KDbDriver::m_new_string or so...
143 int new_length = 0;
144 new_string[new_length++] = QLatin1Char('\''); //prepend '
145 for (i = 0; i < old_length; i++, new_length++) {
146 const unsigned int ch = str[i].unicode();
147 if (ch == '\\') {
148 new_string[new_length++] = QLatin1Char('\\');
149 new_string[new_length] = QLatin1Char('\\');
150 } else if (ch <= '\'') {//check for speedup
151 if (ch == '\'') {
152 new_string[new_length++] = QLatin1Char('\\');
153 new_string[new_length] = QLatin1Char('\'');
154 } else if (ch == '"') {
155 new_string[new_length++] = QLatin1Char('\\');
156 new_string[new_length] = QLatin1Char('"');
157 } else if (ch == '\n') {
158 new_string[new_length++] = QLatin1Char('\\');
159 new_string[new_length] = QLatin1Char('n');
160 } else if (ch == '\r') {
161 new_string[new_length++] = QLatin1Char('\\');
162 new_string[new_length] = QLatin1Char('r');
163 } else if (ch == '\t') {
164 new_string[new_length++] = QLatin1Char('\\');
165 new_string[new_length] = QLatin1Char('t');
166 } else if (ch == '\b') {
167 new_string[new_length++] = QLatin1Char('\\');
168 new_string[new_length] = QLatin1Char('b');
169 } else if (ch == '\0') {
170 new_string[new_length++] = QLatin1Char('\\');
171 new_string[new_length] = QLatin1Char('0');
172 } else
173 new_string[new_length] = str[i];
174 } else
175 new_string[new_length] = str[i];
176 }
177
178 new_string[new_length++] = QLatin1Char('\''); //append '
179 KDbEscapedString result(QString(new_string, new_length));
180 delete [] new_string;
181 return result;
182}
183
188
190{
191//! @todo optimize using mysql_real_escape_string()?
192//! see https://dev.mysql.com/doc/refman/5.0/en/string-syntax.html
193
194 return KDbEscapedString("'") + KDbEscapedString(str)
195 .replace('\\', "\\\\")
196 .replace('\'', "\\''")
197 .replace('"', "\\\"")
198 + '\'';
199}
200
201/*! Add back-ticks to an identifier, and replace any back-ticks within
202 * the name with single quotes.
203 */
205{
206 return QString(str).replace(QLatin1Char('"'), QLatin1String("\"\""));
207}
208
210{
211 return QByteArray(str).replace('`', '\'');
212}
213
214//! Overrides the default implementation
216{
217 if (field.isPrimaryKey() && type == KDbField::LongText) {
218 return m_longTextPrimaryKeyType;
219 }
220 return KDbDriver::sqlTypeName(type, field);
221}
222
225 KDb::ExpressionCallStack* callStack) const
226{
228 QLatin1String("CHAR_LENGTH"), this, args, params, callStack);
229}
230
239
241 const KDbNArgExpression &args,
243 KDb::ExpressionCallStack* callStack) const
244{
245 Q_ASSERT(args.argCount() == 1);
246 return KDbEscapedString("ORD(CONVERT(%1 USING UTF16))")
247 .arg(args.arg(0).toString(this, params, callStack));
248}
249
252 KDb::ExpressionCallStack* callStack) const
253{
254 return KDbEscapedString("CONCAT(%1, %2)").arg(args.left().toString(this, params, callStack))
255 .arg(args.right().toString(this, params, callStack));
256}
257
258#include "MysqlDriver.moc"
The KDbBinaryExpression class represents binary operation.
Database specific connection data, e.g. host, port.
Generic options for a single connection. The options are accessible using key/value pairs....
Provides database connection, allowing queries and data modification.
Detailed definition of driver's default behavior.
bool ROW_ID_FIELD_RETURNS_LAST_AUTOINCREMENTED_VALUE
KDbEscapedString GET_TABLE_NAMES_SQL
SQL statement used to obtain list of physical table names.
char OPENING_QUOTATION_MARK_BEGIN_FOR_IDENTIFIER
KDbUtils::PropertySet properties
QVector< QString > typeNames
real type names for this engine
char CLOSING_QUOTATION_MARK_BEGIN_FOR_IDENTIFIER
bool _1ST_ROW_READ_AHEAD_REQUIRED_TO_KNOW_IF_THE_RESULT_IS_EMPTY
Database driver's abstraction.
Definition KDbDriver.h:50
virtual QString sqlTypeName(KDbField::Type type, const KDbField &field) const
Specialized string for escaping.
KDbEscapedString toString(const KDbDriver *driver, KDbQuerySchemaParameterValueListIterator *params=nullptr, KDb::ExpressionCallStack *callStack=nullptr) const
Meta-data for a field.
Definition KDbField.h:72
@ Integer
Definition KDbField.h:90
@ Boolean
Definition KDbField.h:92
@ ShortInteger
Definition KDbField.h:89
@ BigInteger
Definition KDbField.h:91
@ LongText
Definition KDbField.h:99
Type type() const
Definition KDbField.cpp:379
bool isPrimaryKey() const
Definition KDbField.h:287
static KDbEscapedString greatestOrLeastFunctionUsingCaseToString(const QString &name, const KDbDriver *driver, const KDbNArgExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack)
static KDbEscapedString toString(const QString &name, const KDbDriver *driver, const KDbNArgExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack)
The KDbNArgExpression class represents a base class N-argument expression.
KDbExpression arg(int i) const
An iterator for a list of values of query schema parameters Allows to iterate over parameters and ret...
void insert(const QByteArray &name, const QVariant &value, const QString &caption=QString())
Inserts property with a given name, value and caption.
Definition KDbUtils.cpp:660
#define K_PLUGIN_CLASS_WITH_JSON(classname, jsonFile)
Provides database connection, allowing queries and data modification.
MySQL database driver.
Definition MysqlDriver.h:30
QString drv_escapeIdentifier(const QString &str) const override
bool supportsDefaultValue(const KDbField &field) const override
KDbEscapedString concatenateFunctionToString(const KDbBinaryExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack) const
Generates native (driver-specific) function call for concatenation of two strings.
KDbEscapedString escapeString(const QString &str) const override
Escape a string for use as a value.
KDbConnection * drv_createConnection(const KDbConnectionData &connData, const KDbConnectionOptions &options) override
bool isSystemDatabaseName(const QString &name) const override
QString sqlTypeName(KDbField::Type type, const KDbField &field) const override
Overrides the default implementation.
KDbEscapedString escapeBLOB(const QByteArray &array) const override
Escape BLOB value array.
bool isSystemObjectName(const QString &name) const override
bool drv_isSystemFieldName(const QString &name) const override
KDbEscapedString unicodeFunctionToString(const KDbNArgExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack) const override
Generates native (driver-specific) UNICODE() function call.
KDbEscapedString lengthFunctionToString(const KDbNArgExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack) const override
Generates native (driver-specific) LENGTH() function call.
KDbEscapedString greatestOrLeastFunctionToString(const QString &name, const KDbNArgExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack) const override
Generates native (driver-specific) GREATEST() and LEAST() function call.
@ ZeroXHex
Escaping like 0x1FAD, used by mysql (hex numbers)
KDB_EXPORT QString escapeBLOB(const QByteArray &array, BLOBEscapingType type)
QByteArray & replace(QByteArrayView before, QByteArrayView after)
int compare(QLatin1StringView s1, const QString &s2, Qt::CaseSensitivity cs)
qsizetype length() const const
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
const QChar * unicode() const const
CaseInsensitive
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:20:59 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.