KDb

MysqlConnection.cpp
1 /* This file is part of the KDE project
2  Copyright (C) 2002 Lucijan Busch <[email protected]>
3  Copyright (C) 2003 Joseph Wenninger<[email protected]>
4  Copyright (C) 2004-2016 JarosÅ‚aw Staniek <[email protected]>
5 
6  This program is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Library General Public
8  License as published by the Free Software Foundation; either
9  version 2 of the License, or (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Library General Public License for more details.
15 
16  You should have received a copy of the GNU Library General Public License
17  along with this program; see the file COPYING. If not, write to
18  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20 */
21 
22 #include "MysqlConnection.h"
23 #include "MysqlDriver.h"
24 #include "MysqlCursor.h"
25 #include "MysqlPreparedStatement.h"
26 #include "mysql_debug.h"
27 #include "KDbConnectionData.h"
28 #include "KDbVersionInfo.h"
29 
30 #include <QRegularExpression>
31 
33  const KDbConnectionOptions &options)
34  : KDbConnection(driver, connData, options)
35  , d(new MysqlConnectionInternal(this))
36 {
37 }
38 
39 MysqlConnection::~MysqlConnection()
40 {
41  destroy();
42  delete d;
43 }
44 
46 {
47  const bool ok = d->db_connect(data());
48  if (!ok) {
49  storeResult(); //store error msg, if any - can be destroyed after disconnect()
50  d->db_disconnect();
51  return false;
52  }
53 
54  // Get lower_case_table_name value so we know if there's case sensitivity supported
55  // See https://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html
56  int intLowerCaseTableNames = 0;
57  const tristate res = querySingleNumber(
58  KDbEscapedString("SHOW VARIABLES LIKE 'lower_case_table_name'"), &intLowerCaseTableNames,
59  0 /*col*/,
61  if (res == false) // sanity
62  return false;
63  d->lowerCaseTableNames = intLowerCaseTableNames > 0;
64  return true;
65 }
66 
68 {
69  // https://dev.mysql.com/doc/refman/5.1/en/mysql-get-server-info.html
70  version->setString(QLatin1String(mysql_get_server_info(d->mysql)));
71 
72  // get the version info using 'version' built-in variable:
73 //! @todo this is hardcoded for now; define api for retrieving variables and use this API...
74  // https://dev.mysql.com/doc/refman/5.1/en/mysql-get-server-version.html
76  tristate res = querySingleString(KDbEscapedString("SELECT @@version"), &versionString,
77  /*column*/ 0,
79 
80  QRegularExpression versionRe(QLatin1String("^(\\d+)\\.(\\d+)\\.(\\d+)$"));
81  QRegularExpressionMatch match = versionRe.match(versionString);
82  if (res == false) // sanity
83  return false;
84  if (match.hasMatch()) {
85  // (if querySingleString failed, the version will be 0.0.0...
86  version->setMajor(match.captured(1).toInt());
87  version->setMinor(match.captured(2).toInt());
88  version->setRelease(match.captured(3).toInt());
89  }
90  return true;
91 }
92 
94 {
95  return d->db_disconnect();
96 }
97 
99 {
100  return new MysqlCursor(this, sql, options);
101 }
102 
104 {
105  return new MysqlCursor(this, query, options);
106 }
107 
109 {
110  mysqlDebug();
111  list->clear();
112  MYSQL_RES *res = mysql_list_dbs(d->mysql, nullptr);
113  if (res != nullptr) {
114  MYSQL_ROW row;
115  while ((row = mysql_fetch_row(res)) != nullptr) {
116  *list << QString::fromUtf8(row[0]);
117  }
118  mysql_free_result(res);
119  return true;
120  }
121  storeResult();
122  return false;
123 }
124 
125 bool MysqlConnection::drv_databaseExists(const QString &dbName, bool ignoreErrors)
126 {
127  /* db names can be lower case in mysql */
128  const QString storedDbName(d->lowerCaseTableNames ? dbName.toLower() : dbName);
129  const tristate result = resultExists(
130  KDbEscapedString("SHOW DATABASES LIKE %1").arg(escapeString(storedDbName)));
131  if (result == true) {
132  return true;
133  }
134  if (!ignoreErrors) {
135  m_result = KDbResult(ERR_OBJECT_NOT_FOUND,
136  tr("The database \"%1\" does not exist.").arg(storedDbName));
137  }
138  return false;
139 }
140 
142 {
143  const QString storedDbName(d->lowerCaseTableNames ? dbName.toLower() : dbName);
144  mysqlDebug() << storedDbName;
145  // mysql_create_db deprecated, use SQL here.
146  // db names are lower case in mysql
147  return drv_executeSql(KDbEscapedString("CREATE DATABASE %1").arg(escapeIdentifier(storedDbName)));
148 }
149 
150 bool MysqlConnection::drv_useDatabase(const QString &dbName, bool *cancelled, KDbMessageHandler* msgHandler)
151 {
152  Q_UNUSED(cancelled);
153  Q_UNUSED(msgHandler);
154 //! @todo is here escaping needed?
155  const QString storedDbName(d->lowerCaseTableNames ? dbName.toLower() : dbName);
156  if (!d->useDatabase(storedDbName)) {
157  storeResult();
158  return false;
159  }
160  return true;
161 }
162 
164 {
165 //! @todo free resources, as far as I know, mysql doesn't support that
166  return true;
167 }
168 
170 {
171 //! @todo is here escaping needed?
172  const QString storedDbName(d->lowerCaseTableNames ? dbName.toLower() : dbName);
173  return drv_executeSql(KDbEscapedString("DROP DATABASE %1").arg(escapeIdentifier(storedDbName)));
174 }
175 
177 {
178  if (!drv_executeSql(sql)) {
179  return nullptr;
180  }
181  MYSQL_RES *data = mysql_use_result(d->mysql); // more optimal than mysql_store_result
182  //! @todo use mysql_error()
183  return new MysqlSqlResult(this, data);
184 }
185 
187 {
188  if (!d->executeSql(sql)) {
189  storeResult();
190  return false;
191  }
192  return true;
193 }
194 
196 {
197  return MysqlConnectionInternal::serverResultName(d->mysql);
198 }
199 
201 {
202  return resultExists(KDbEscapedString("SHOW TABLES LIKE %1")
203  .arg(escapeString(tableName)));
204 }
205 
207 {
208  return new MysqlPreparedStatement(d);
209 }
210 
211 void MysqlConnection::storeResult()
212 {
213  d->storeResult(&m_result);
214 }
bool drv_getServerVersion(KDbServerVersionInfo *version) override
Provides database cursor functionality.
Definition: KDbCursor.h:68
tristate querySingleNumber(const KDbEscapedString &sql, int *number, int column=0, QueryRecordOptions options=QueryRecordOption::Default)
const char * versionString()
QString fromUtf8(const char *str, int size)
The KDbSqlResult class abstracts result of a raw SQL query preparation by KDbConnection::prepareSql()
Definition: KDbSqlResult.h:44
QString serverResultName() const override
Implemented for KDbResultable.
tristate querySingleString(const KDbEscapedString &sql, QString *value, int column=0, QueryRecordOptions options=QueryRecordOption::Default)
Specialized string for escaping.
virtual QString escapeIdentifier(const QString &id) const
Identifier escaping function in the associated KDbDriver.
Database driver's abstraction.
Definition: KDbDriver.h:49
tristate drv_containsTable(const QString &tableName) override
bool drv_executeSql(const KDbEscapedString &sql) override
Executes query for a raw SQL statement sql without returning resulting records.
bool drv_getDatabasesList(QStringList *list) override
bool drv_connect() override
bool drv_createDatabase(const QString &dbName=QString()) override
KDbConnectionData data() const
bool drv_disconnect() override
3-state logical type with three values: true, false and cancelled and convenient operators.
Definition: KDbTristate.h:100
bool drv_dropDatabase(const QString &dbName=QString()) override
bool drv_useDatabase(const QString &dbName=QString(), bool *cancelled=nullptr, KDbMessageHandler *msgHandler=nullptr) override
QRegularExpressionMatch match(const QString &subject, int offset, QRegularExpression::MatchType matchType, QRegularExpression::MatchOptions matchOptions) const const
tristate resultExists(const KDbEscapedString &sql, QueryRecordOptions options=QueryRecordOption::Default)
virtual KDbEscapedString escapeString(const QString &str) const
KDbSqlResult * drv_prepareSql(const KDbEscapedString &sql) override
Prepares query for a raw SQL statement sql with possibility of returning records.
QString toLower() const const
Prepared statement interface for backend-dependent implementations.
KDbQuerySchema provides information about database query.
@ AddLimitTo1
Adds a "LIMIT 1" clause to the query for optimization purposes (it should not include one already)
unsigned int version()
Definition: KDb.cpp:336
KDbConnectionOptions * options()
Database specific connection data, e.g. host, port.
bool drv_closeDatabase() override
void clear()
Generic options for a single connection. The options are accessible using key/value pairs....
Provides database connection, allowing queries and data modification.
Definition: KDbConnection.h:51
bool drv_databaseExists(const QString &dbName, bool ignoreErrors=true) override
reimplemented using "SHOW DATABASES LIKE..." because MySQL stores db names in lower case.
KDbPreparedStatementInterface * prepareStatementInternal() override
KDbCursor * prepareQuery(const KDbEscapedString &sql, KDbCursor::Options options=KDbCursor::Option::None) override
MysqlConnection(KDbDriver *driver, const KDbConnectionData &connData, const KDbConnectionOptions &options)
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.