KDb

MysqlDriver.cpp
1 /* This file is part of the KDE project
2  Copyright (C) 2002 Lucijan Busch <[email protected]>
3  Copyright (C) 2003 Daniel Molkentin <[email protected]>
4  Copyright (C) 2003 Joseph Wenninger<[email protected]>
5  Copyright (C) 2003-2016 JarosÅ‚aw Staniek <[email protected]>
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 
33 K_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 
40 MysqlDriver::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");
78  beh->typeNames[KDbField::Float] = QLatin1String("FLOAT");
79  beh->typeNames[KDbField::Double] = QLatin1String("DOUBLE");
80  beh->typeNames[KDbField::Text] = QLatin1String("VARCHAR");
81  beh->typeNames[KDbField::LongText] = QLatin1String("LONGTEXT");
82  beh->typeNames[KDbField::BLOB] = QLatin1String("BLOB");
83 }
84 
85 MysqlDriver::~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()) {
117  case KDbField::LongText:
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 
185 {
187 }
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 
232  const KDbNArgExpression &args,
234  KDb::ExpressionCallStack* callStack) const
235 {
237  name, this, args, params, callStack);
238 }
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"
KDbEscapedString GET_TABLE_NAMES_SQL
SQL statement used to obtain list of physical table names.
virtual QString sqlTypeName(KDbField::Type type, const KDbField &field) const
Definition: KDbDriver.cpp:128
bool isPrimaryKey() const
Definition: KDbField.h:287
void insert(const QByteArray &name, const QVariant &value, const QString &caption=QString())
Inserts property with a given name, value and caption.
Definition: KDbUtils.cpp:659
KDbEscapedString unicodeFunctionToString(const KDbNArgExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack) const override
Generates native (driver-specific) UNICODE() function call.
KDbExpression arg(int i) const
CaseInsensitive
An iterator for a list of values of query schema parameters Allows to iterate over parameters and ret...
KDbEscapedString escapeBLOB(const QByteArray &array) const override
Escape BLOB value array.
The KDbBinaryExpression class represents binary operation.
@ Text
Definition: KDbField.h:98
@ ZeroXHex
Escaping like 0x1FAD, used by mysql (hex numbers)
bool USING_DATABASE_REQUIRED_TO_CONNECT
Specialized string for escaping.
Database driver's abstraction.
Definition: KDbDriver.h:49
QVector< QString > typeNames
real type names for this engine
const QChar * unicode() const const
KDbEscapedString greatestOrLeastFunctionToString(const QString &name, const KDbNArgExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack) const override
Generates native (driver-specific) GREATEST() and LEAST() function call.
QString sqlTypeName(KDbField::Type type, const KDbField &field) const override
Overrides the default implementation.
bool isSystemDatabaseName(const QString &name) const override
KDbEscapedString lengthFunctionToString(const KDbNArgExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack) const override
Generates native (driver-specific) LENGTH() function call.
@ Integer
Definition: KDbField.h:90
int length() const const
KDbEscapedString toString(const KDbDriver *driver, KDbQuerySchemaParameterValueListIterator *params=nullptr, KDb::ExpressionCallStack *callStack=nullptr) const
QString drv_escapeIdentifier(const QString &str) const override
bool supportsDefaultValue(const KDbField &field) const override
KDbUtils::PropertySet properties
bool isSystemObjectName(const QString &name) const override
Definition: MysqlDriver.cpp:95
static KDbEscapedString greatestOrLeastFunctionUsingCaseToString(const QString &name, const KDbDriver *driver, const KDbNArgExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack)
@ BigInteger
Definition: KDbField.h:91
Type type() const
Definition: KDbField.cpp:379
@ Double
Definition: KDbField.h:97
@ LongText
Definition: KDbField.h:99
QByteArray & replace(int pos, int len, const char *after)
QString & replace(int position, int n, QChar after)
@ Byte
Definition: KDbField.h:87
The KDbNArgExpression class represents a base class N-argument expression.
KDB_EXPORT QString escapeBLOB(const QByteArray &array, BLOBEscapingType type)
bool drv_isSystemFieldName(const QString &name) const override
Detailed definition of driver's default behavior.
@ Boolean
Definition: KDbField.h:92
static KDbEscapedString toString(const QString &name, const KDbDriver *driver, const KDbNArgExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack)
Database specific connection data, e.g. host, port.
Generic options for a single connection. The options are accessible using key/value pairs....
char CLOSING_QUOTATION_MARK_BEGIN_FOR_IDENTIFIER
KDbConnection * drv_createConnection(const KDbConnectionData &connData, const KDbConnectionOptions &options) override
Definition: MysqlDriver.cpp:89
Meta-data for a field.
Definition: KDbField.h:71
@ Float
Definition: KDbField.h:96
int compare(const QString &other, Qt::CaseSensitivity cs) const const
Provides database connection, allowing queries and data modification.
Definition: KDbConnection.h:51
#define K_PLUGIN_CLASS_WITH_JSON(classname, jsonFile)
bool _1ST_ROW_READ_AHEAD_REQUIRED_TO_KNOW_IF_THE_RESULT_IS_EMPTY
bool ROW_ID_FIELD_RETURNS_LAST_AUTOINCREMENTED_VALUE
@ ShortInteger
Definition: KDbField.h:89
KDbEscapedString escapeString(const QString &str) const override
Escape a string for use as a value.
char OPENING_QUOTATION_MARK_BEGIN_FOR_IDENTIFIER
Provides database connection, allowing queries and data modification.
KDbEscapedString concatenateFunctionToString(const KDbBinaryExpression &args, KDbQuerySchemaParameterValueListIterator *params, KDb::ExpressionCallStack *callStack) const
Generates native (driver-specific) function call for concatenation of two strings.
MySQL database driver.
Definition: MysqlDriver.h:29
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Sat Jun 25 2022 06:21:34 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.