summaryrefslogtreecommitdiffstats
path: root/src/sql/drivers/mysql/qsql_mysql.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/sql/drivers/mysql/qsql_mysql.cpp')
-rw-r--r--src/sql/drivers/mysql/qsql_mysql.cpp193
1 files changed, 122 insertions, 71 deletions
diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp
index 96bdcc42fa..56caf52dcb 100644
--- a/src/sql/drivers/mysql/qsql_mysql.cpp
+++ b/src/sql/drivers/mysql/qsql_mysql.cpp
@@ -1,31 +1,37 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtSql module of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
@@ -33,7 +39,6 @@
#include "qsql_mysql_p.h"
-#include <QtSql/private/qsqldriver_p.h>
#include <qcoreapplication.h>
#include <qvariant.h>
#include <qdatetime.h>
@@ -46,8 +51,9 @@
#include <qtextcodec.h>
#include <qvector.h>
#include <qfile.h>
-
#include <qdebug.h>
+#include <QtSql/private/qsqldriver_p.h>
+#include <QtSql/private/qsqlresult_p.h>
#ifdef Q_OS_WIN32
// comment the next line out if you want to use MySQL/embedded on Win32 systems.
@@ -72,6 +78,8 @@ QT_BEGIN_NAMESPACE
class QMYSQLDriverPrivate : public QSqlDriverPrivate
{
+ Q_DECLARE_PUBLIC(QMYSQLDriver)
+
public:
QMYSQLDriverPrivate() : QSqlDriverPrivate(), mysql(0),
#ifndef QT_NO_TEXTCODEC
@@ -156,24 +164,60 @@ static inline QVariant qDateTimeFromString(QString &val)
#endif
}
-class QMYSQLResultPrivate : public QObject
+class QMYSQLResultPrivate;
+
+class QMYSQLResult : public QSqlResult
{
- Q_OBJECT
+ Q_DECLARE_PRIVATE(QMYSQLResult)
+ friend class QMYSQLDriver;
+
public:
- QMYSQLResultPrivate(const QMYSQLDriver* dp, const QMYSQLResult* d) : driver(dp), result(0), q(d),
- rowsAffected(0), hasBlobs(false)
+ explicit QMYSQLResult(const QMYSQLDriver *db);
+ ~QMYSQLResult();
+
+ QVariant handle() const Q_DECL_OVERRIDE;
+protected:
+ void cleanup();
+ bool fetch(int i) Q_DECL_OVERRIDE;
+ bool fetchNext() Q_DECL_OVERRIDE;
+ bool fetchLast() Q_DECL_OVERRIDE;
+ bool fetchFirst() Q_DECL_OVERRIDE;
+ QVariant data(int field) Q_DECL_OVERRIDE;
+ bool isNull(int field) Q_DECL_OVERRIDE;
+ bool reset (const QString& query) Q_DECL_OVERRIDE;
+ int size() Q_DECL_OVERRIDE;
+ int numRowsAffected() Q_DECL_OVERRIDE;
+ QVariant lastInsertId() const Q_DECL_OVERRIDE;
+ QSqlRecord record() const Q_DECL_OVERRIDE;
+ void virtual_hook(int id, void *data) Q_DECL_OVERRIDE;
+ bool nextResult() Q_DECL_OVERRIDE;
+
+#if MYSQL_VERSION_ID >= 40108
+ bool prepare(const QString &stmt) Q_DECL_OVERRIDE;
+ bool exec() Q_DECL_OVERRIDE;
+#endif
+};
+
+class QMYSQLResultPrivate: public QSqlResultPrivate
+{
+ Q_DECLARE_PUBLIC(QMYSQLResult)
+
+public:
+ Q_DECLARE_SQLDRIVER_PRIVATE(QMYSQLDriver)
+
+ QMYSQLResultPrivate(QMYSQLResult *q, const QMYSQLDriver *drv)
+ : QSqlResultPrivate(q, drv),
+ result(0),
+ rowsAffected(0),
+ hasBlobs(false)
#if MYSQL_VERSION_ID >= 40108
, stmt(0), meta(0), inBinds(0), outBinds(0)
#endif
, preparedQuery(false)
- {
- connect(dp, SIGNAL(destroyed()), this, SLOT(driverDestroyed()));
- }
+ { }
- const QMYSQLDriver* driver;
MYSQL_RES *result;
MYSQL_ROW row;
- const QMYSQLResult* q;
int rowsAffected;
@@ -205,9 +249,6 @@ public:
#endif
bool preparedQuery;
-
-private Q_SLOTS:
- void driverDestroyed() { driver = NULL; }
};
#ifndef QT_NO_TEXTCODEC
@@ -396,19 +437,18 @@ bool QMYSQLResultPrivate::bindInValues()
#endif
QMYSQLResult::QMYSQLResult(const QMYSQLDriver* db)
-: QSqlResult(db)
+ : QSqlResult(*new QMYSQLResultPrivate(this, db))
{
- d = new QMYSQLResultPrivate(db, this);
}
QMYSQLResult::~QMYSQLResult()
{
cleanup();
- delete d;
}
QVariant QMYSQLResult::handle() const
{
+ Q_D(const QMYSQLResult);
#if MYSQL_VERSION_ID >= 40108
if(d->preparedQuery)
return d->meta ? QVariant::fromValue(d->meta) : QVariant::fromValue(d->stmt);
@@ -419,14 +459,15 @@ QVariant QMYSQLResult::handle() const
void QMYSQLResult::cleanup()
{
+ Q_D(QMYSQLResult);
if (d->result)
mysql_free_result(d->result);
// must iterate trough leftover result sets from multi-selects or stored procedures
// if this isn't done subsequent queries will fail with "Commands out of sync"
#if MYSQL_VERSION_ID >= 40100
- while (d->driver && d->driver->d_func()->mysql && mysql_next_result(d->driver->d_func()->mysql) == 0) {
- MYSQL_RES *res = mysql_store_result(d->driver->d_func()->mysql);
+ while (driver() && d->drv_d_func()->mysql && mysql_next_result(d->drv_d_func()->mysql) == 0) {
+ MYSQL_RES *res = mysql_store_result(d->drv_d_func()->mysql);
if (res)
mysql_free_result(res);
}
@@ -469,7 +510,8 @@ void QMYSQLResult::cleanup()
bool QMYSQLResult::fetch(int i)
{
- if(!d->driver)
+ Q_D(QMYSQLResult);
+ if (!driver())
return false;
if (isForwardOnly()) { // fake a forward seek
if (at() < i) {
@@ -513,7 +555,8 @@ bool QMYSQLResult::fetch(int i)
bool QMYSQLResult::fetchNext()
{
- if(!d->driver)
+ Q_D(QMYSQLResult);
+ if (!driver())
return false;
if (d->preparedQuery) {
#if MYSQL_VERSION_ID >= 40108
@@ -542,7 +585,8 @@ bool QMYSQLResult::fetchNext()
bool QMYSQLResult::fetchLast()
{
- if(!d->driver)
+ Q_D(QMYSQLResult);
+ if (!driver())
return false;
if (isForwardOnly()) { // fake this since MySQL can't seek on forward only queries
bool success = fetchNext(); // did we move at all?
@@ -579,13 +623,13 @@ bool QMYSQLResult::fetchFirst()
QVariant QMYSQLResult::data(int field)
{
-
+ Q_D(QMYSQLResult);
if (!isSelect() || field >= d->fields.count()) {
qWarning("QMYSQLResult::data: column %d out of range", field);
return QVariant();
}
- if (!d->driver)
+ if (!driver())
return QVariant();
int fieldLength = 0;
@@ -599,7 +643,7 @@ QVariant QMYSQLResult::data(int field)
return QVariant(f.type, f.outField);
if (f.type != QVariant::ByteArray)
- val = toUnicode(d->driver->d_func()->tc, f.outField, f.bufLength);
+ val = toUnicode(d->drv_d_func()->tc, f.outField, f.bufLength);
} else {
if (d->row[field] == NULL) {
// NULL value
@@ -609,7 +653,7 @@ QVariant QMYSQLResult::data(int field)
fieldLength = mysql_fetch_lengths(d->result)[field];
if (f.type != QVariant::ByteArray)
- val = toUnicode(d->driver->d_func()->tc, d->row[field], fieldLength);
+ val = toUnicode(d->drv_d_func()->tc, d->row[field], fieldLength);
}
switch (static_cast<int>(f.type)) {
@@ -677,6 +721,7 @@ QVariant QMYSQLResult::data(int field)
bool QMYSQLResult::isNull(int field)
{
+ Q_D(const QMYSQLResult);
if (field < 0 || field >= d->fields.count())
return true;
if (d->preparedQuery)
@@ -687,29 +732,30 @@ bool QMYSQLResult::isNull(int field)
bool QMYSQLResult::reset (const QString& query)
{
- if (!driver() || !driver()->isOpen() || driver()->isOpenError() || !d->driver)
+ Q_D(QMYSQLResult);
+ if (!driver() || !driver()->isOpen() || driver()->isOpenError())
return false;
d->preparedQuery = false;
cleanup();
- const QByteArray encQuery(fromUnicode(d->driver->d_func()->tc, query));
- if (mysql_real_query(d->driver->d_func()->mysql, encQuery.data(), encQuery.length())) {
+ const QByteArray encQuery(fromUnicode(d->drv_d_func()->tc, query));
+ if (mysql_real_query(d->drv_d_func()->mysql, encQuery.data(), encQuery.length())) {
setLastError(qMakeError(QCoreApplication::translate("QMYSQLResult", "Unable to execute query"),
- QSqlError::StatementError, d->driver->d_func()));
+ QSqlError::StatementError, d->drv_d_func()));
return false;
}
- d->result = mysql_store_result(d->driver->d_func()->mysql);
- if (!d->result && mysql_field_count(d->driver->d_func()->mysql) > 0) {
+ d->result = mysql_store_result(d->drv_d_func()->mysql);
+ if (!d->result && mysql_field_count(d->drv_d_func()->mysql) > 0) {
setLastError(qMakeError(QCoreApplication::translate("QMYSQLResult", "Unable to store result"),
- QSqlError::StatementError, d->driver->d_func()));
+ QSqlError::StatementError, d->drv_d_func()));
return false;
}
- int numFields = mysql_field_count(d->driver->d_func()->mysql);
+ int numFields = mysql_field_count(d->drv_d_func()->mysql);
setSelect(numFields != 0);
d->fields.resize(numFields);
- d->rowsAffected = mysql_affected_rows(d->driver->d_func()->mysql);
+ d->rowsAffected = mysql_affected_rows(d->drv_d_func()->mysql);
if (isSelect()) {
for(int i = 0; i < numFields; i++) {
@@ -724,7 +770,8 @@ bool QMYSQLResult::reset (const QString& query)
int QMYSQLResult::size()
{
- if (d->driver && isSelect())
+ Q_D(const QMYSQLResult);
+ if (driver() && isSelect())
if (d->preparedQuery)
#if MYSQL_VERSION_ID >= 40108
return mysql_stmt_num_rows(d->stmt);
@@ -739,12 +786,14 @@ int QMYSQLResult::size()
int QMYSQLResult::numRowsAffected()
{
+ Q_D(const QMYSQLResult);
return d->rowsAffected;
}
QVariant QMYSQLResult::lastInsertId() const
{
- if (!isActive() || !d->driver)
+ Q_D(const QMYSQLResult);
+ if (!isActive() || !driver())
return QVariant();
if (d->preparedQuery) {
@@ -754,7 +803,7 @@ QVariant QMYSQLResult::lastInsertId() const
return QVariant(id);
#endif
} else {
- quint64 id = mysql_insert_id(d->driver->d_func()->mysql);
+ quint64 id = mysql_insert_id(d->drv_d_func()->mysql);
if (id)
return QVariant(id);
}
@@ -763,9 +812,10 @@ QVariant QMYSQLResult::lastInsertId() const
QSqlRecord QMYSQLResult::record() const
{
+ Q_D(const QMYSQLResult);
QSqlRecord info;
MYSQL_RES *res;
- if (!isActive() || !isSelect() || !d->driver)
+ if (!isActive() || !isSelect() || !driver())
return info;
#if MYSQL_VERSION_ID >= 40108
@@ -774,11 +824,11 @@ QSqlRecord QMYSQLResult::record() const
res = d->result;
#endif
- if (!mysql_errno(d->driver->d_func()->mysql)) {
+ if (!mysql_errno(d->drv_d_func()->mysql)) {
mysql_field_seek(res, 0);
MYSQL_FIELD* field = mysql_fetch_field(res);
while(field) {
- info.append(qToField(field, d->driver->d_func()->tc));
+ info.append(qToField(field, d->drv_d_func()->tc));
field = mysql_fetch_field(res);
}
}
@@ -788,7 +838,8 @@ QSqlRecord QMYSQLResult::record() const
bool QMYSQLResult::nextResult()
{
- if(!d->driver)
+ Q_D(QMYSQLResult);
+ if (!driver())
return false;
#if MYSQL_VERSION_ID >= 40100
setAt(-1);
@@ -803,26 +854,26 @@ bool QMYSQLResult::nextResult()
delete[] d->fields[i].outField;
d->fields.clear();
- int status = mysql_next_result(d->driver->d_func()->mysql);
+ int status = mysql_next_result(d->drv_d_func()->mysql);
if (status > 0) {
setLastError(qMakeError(QCoreApplication::translate("QMYSQLResult", "Unable to execute next query"),
- QSqlError::StatementError, d->driver->d_func()));
+ QSqlError::StatementError, d->drv_d_func()));
return false;
} else if (status == -1) {
return false; // No more result sets
}
- d->result = mysql_store_result(d->driver->d_func()->mysql);
- int numFields = mysql_field_count(d->driver->d_func()->mysql);
+ d->result = mysql_store_result(d->drv_d_func()->mysql);
+ int numFields = mysql_field_count(d->drv_d_func()->mysql);
if (!d->result && numFields > 0) {
setLastError(qMakeError(QCoreApplication::translate("QMYSQLResult", "Unable to store next result"),
- QSqlError::StatementError, d->driver->d_func()));
+ QSqlError::StatementError, d->drv_d_func()));
return false;
}
setSelect(numFields > 0);
d->fields.resize(numFields);
- d->rowsAffected = mysql_affected_rows(d->driver->d_func()->mysql);
+ d->rowsAffected = mysql_affected_rows(d->drv_d_func()->mysql);
if (isSelect()) {
for (int i = 0; i < numFields; i++) {
@@ -871,11 +922,12 @@ static MYSQL_TIME *toMySqlDate(QDate date, QTime time, QVariant::Type type)
bool QMYSQLResult::prepare(const QString& query)
{
- if(!d->driver)
+ Q_D(QMYSQLResult);
+ if (!driver())
return false;
#if MYSQL_VERSION_ID >= 40108
cleanup();
- if (!d->driver->d_func()->preparedQuerysEnabled)
+ if (!d->drv_d_func()->preparedQuerysEnabled)
return QSqlResult::prepare(query);
int r;
@@ -884,14 +936,14 @@ bool QMYSQLResult::prepare(const QString& query)
return false;
if (!d->stmt)
- d->stmt = mysql_stmt_init(d->driver->d_func()->mysql);
+ d->stmt = mysql_stmt_init(d->drv_d_func()->mysql);
if (!d->stmt) {
setLastError(qMakeError(QCoreApplication::translate("QMYSQLResult", "Unable to prepare statement"),
- QSqlError::StatementError, d->driver->d_func()));
+ QSqlError::StatementError, d->drv_d_func()));
return false;
}
- const QByteArray encQuery(fromUnicode(d->driver->d_func()->tc, query));
+ const QByteArray encQuery(fromUnicode(d->drv_d_func()->tc, query));
r = mysql_stmt_prepare(d->stmt, encQuery.constData(), encQuery.length());
if (r != 0) {
setLastError(qMakeStmtError(QCoreApplication::translate("QMYSQLResult",
@@ -914,7 +966,8 @@ bool QMYSQLResult::prepare(const QString& query)
bool QMYSQLResult::exec()
{
- if (!d->driver)
+ Q_D(QMYSQLResult);
+ if (!driver())
return false;
if (!d->preparedQuery)
return QSqlResult::exec();
@@ -1011,7 +1064,7 @@ bool QMYSQLResult::exec()
break;
case QVariant::String:
default: {
- QByteArray ba = fromUnicode(d->driver->d_func()->tc, val.toString());
+ QByteArray ba = fromUnicode(d->drv_d_func()->tc, val.toString());
stringVector.append(ba);
currBind->buffer_type = MYSQL_TYPE_STRING;
currBind->buffer = const_cast<char *>(ba.constData());
@@ -1610,5 +1663,3 @@ bool QMYSQLDriver::isIdentifierEscaped(const QString &identifier, IdentifierType
}
QT_END_NAMESPACE
-
-#include "qsql_mysql.moc"