?? qsql_mysql.cpp
字號:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the QtSql module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qsql_mysql.h"#include <qcoreapplication.h>#include <qvariant.h>#include <qdatetime.h>#include <qsqlerror.h>#include <qsqlfield.h>#include <qsqlindex.h>#include <qsqlquery.h>#include <qsqlrecord.h>#include <qstringlist.h>#include <qtextcodec.h>#include <qvector.h>#include <qdebug.h>#ifdef Q_OS_WIN32// comment the next line out if you want to use MySQL/embedded on Win32 systems.// note that it will crash if you don't statically link to the mysql/e library!# define Q_NO_MYSQL_EMBEDDED#endifQ_DECLARE_METATYPE(MYSQL_RES*)Q_DECLARE_METATYPE(MYSQL*)#if MYSQL_VERSION_ID >= 40108Q_DECLARE_METATYPE(MYSQL_STMT*)#endif#if MYSQL_VERSION_ID >= 40100# define Q_CLIENT_MULTI_STATEMENTS CLIENT_MULTI_STATEMENTS#else# define Q_CLIENT_MULTI_STATEMENTS 0#endifclass QMYSQLDriverPrivate{public: QMYSQLDriverPrivate() : mysql(0), tc(0), preparedQuerys(false), preparedQuerysEnabled(false) {} MYSQL *mysql; QTextCodec *tc; bool preparedQuerys; bool preparedQuerysEnabled;};static inline QString toUnicode(QTextCodec *tc, const char *str){#ifdef QT_NO_TEXTCODEC Q_UNUSED(tc); return QString::fromLatin1(str);#else return tc->toUnicode(str);#endif}static inline QString toUnicode(QTextCodec *tc, const char *str, int length){#ifdef QT_NO_TEXTCODEC Q_UNUSED(tc); return QString::fromLatin1(str, length);#else return tc->toUnicode(str, length);#endif}static inline QByteArray fromUnicode(QTextCodec *tc, const QString &str){#ifdef QT_NO_TEXTCODEC Q_UNUSED(tc); return str.toLatin1();#else return tc->fromUnicode(str);#endif}static inline QVariant qDateFromString(const QString &val){#ifdef QT_NO_DATESTRING Q_UNUSED(val); return QVariant(val);#else if (val.isEmpty()) return QVariant(QDate()); return QVariant(QDate::fromString(val, Qt::ISODate));#endif}static inline QVariant qTimeFromString(const QString &val){#ifdef QT_NO_DATESTRING Q_UNUSED(val); return QVariant(val);#else if (val.isEmpty()) return QVariant(QTime()); return QVariant(QTime::fromString(val, Qt::ISODate));#endif}static inline QVariant qDateTimeFromString(QString &val){#ifdef QT_NO_DATESTRING Q_UNUSED(val); return QVariant(val);#else if (val.isEmpty()) return QVariant(QDateTime()); if (val.length() == 14) // TIMESTAMPS have the format yyyyMMddhhmmss val.insert(4, QLatin1Char('-')).insert(7, QLatin1Char('-')).insert(10, QLatin1Char('T')).insert(13, QLatin1Char(':')).insert(16, QLatin1Char(':')); return QVariant(QDateTime::fromString(val, Qt::ISODate));#endif}class QMYSQLResultPrivate : public QMYSQLDriverPrivate{public: QMYSQLResultPrivate() : QMYSQLDriverPrivate(), result(0),#ifndef QT_NO_TEXTCODEC tc(QTextCodec::codecForLocale()),#else tc(0),#endif rowsAffected(0), hasBlobs(false)#if MYSQL_VERSION_ID >= 40108 , stmt(0), meta(0), inBinds(0), outBinds(0)#endif {} MYSQL_RES *result; MYSQL_ROW row; QTextCodec *tc; int rowsAffected; bool bindInValues(); void bindBlobs(); bool hasBlobs; struct QMyField { QMyField() : outField(0), nullIndicator(false), bufLength(0ul), myField(0), type(QVariant::Invalid) {} char *outField; my_bool nullIndicator; ulong bufLength; MYSQL_FIELD *myField; QVariant::Type type; }; QVector<QMyField> fields;#if MYSQL_VERSION_ID >= 40108 MYSQL_STMT* stmt; MYSQL_RES* meta; MYSQL_BIND *inBinds; MYSQL_BIND *outBinds;#endif};#ifndef QT_NO_TEXTCODECstatic QTextCodec* codec(MYSQL* mysql){#if MYSQL_VERSION_ID >= 32321 QTextCodec* heuristicCodec = QTextCodec::codecForName(mysql_character_set_name(mysql)); if (heuristicCodec) return heuristicCodec;#endif return QTextCodec::codecForLocale();}#endif // QT_NO_TEXTCODECstatic QSqlError qMakeError(const QString& err, QSqlError::ErrorType type, const QMYSQLDriverPrivate* p){ const char *cerr = mysql_error(p->mysql); return QSqlError(QLatin1String("QMYSQL: ") + err, p->tc ? toUnicode(p->tc, cerr) : QString::fromLatin1(cerr), type, mysql_errno(p->mysql));}static QVariant::Type qDecodeMYSQLType(int mysqltype, uint flags){ QVariant::Type type; switch (mysqltype) { case FIELD_TYPE_TINY : case FIELD_TYPE_SHORT : case FIELD_TYPE_LONG : case FIELD_TYPE_INT24 : type = (flags & UNSIGNED_FLAG) ? QVariant::UInt : QVariant::Int; break; case FIELD_TYPE_YEAR : type = QVariant::Int; break; case FIELD_TYPE_LONGLONG : type = (flags & UNSIGNED_FLAG) ? QVariant::ULongLong : QVariant::LongLong; break; case FIELD_TYPE_FLOAT : case FIELD_TYPE_DOUBLE : type = QVariant::Double; break; case FIELD_TYPE_DATE : type = QVariant::Date; break; case FIELD_TYPE_TIME : type = QVariant::Time; break; case FIELD_TYPE_DATETIME : case FIELD_TYPE_TIMESTAMP : type = QVariant::DateTime; break; case FIELD_TYPE_BLOB : case FIELD_TYPE_TINY_BLOB : case FIELD_TYPE_MEDIUM_BLOB : case FIELD_TYPE_LONG_BLOB : type = (flags & BINARY_FLAG) ? QVariant::ByteArray : QVariant::String; break; default: case FIELD_TYPE_ENUM : case FIELD_TYPE_SET : case FIELD_TYPE_STRING : case FIELD_TYPE_VAR_STRING : case FIELD_TYPE_DECIMAL : type = QVariant::String; break; } return type;}static QSqlField qToField(MYSQL_FIELD *field, QTextCodec *tc){ QSqlField f(toUnicode(tc, field->name), qDecodeMYSQLType(int(field->type), field->flags)); f.setRequired(IS_NOT_NULL(field->flags)); f.setLength(field->length); f.setPrecision(field->decimals); f.setSqlType(field->type); return f;}#if MYSQL_VERSION_ID >= 40108static QSqlError qMakeStmtError(const QString& err, QSqlError::ErrorType type, MYSQL_STMT* stmt){ const char *cerr = mysql_stmt_error(stmt); return QSqlError(QLatin1String("QMYSQL3: ") + err, QString::fromLatin1(cerr), type, mysql_stmt_errno(stmt));}static bool qIsBlob(int t){ return t == MYSQL_TYPE_TINY_BLOB || t == MYSQL_TYPE_BLOB || t == MYSQL_TYPE_MEDIUM_BLOB || t == MYSQL_TYPE_LONG_BLOB;}void QMYSQLResultPrivate::bindBlobs(){ int i; MYSQL_FIELD *fieldInfo; MYSQL_BIND *bind;// Q_ASSERT(meta); for(i = 0; i < fields.count(); ++i) { fieldInfo = fields.at(i).myField; if (qIsBlob(inBinds[i].buffer_type) && meta && fieldInfo) { bind = &inBinds[i]; bind->buffer_length = fieldInfo->max_length; delete[] static_cast<char*>(bind->buffer); bind->buffer = new char[fieldInfo->max_length]; fields[i].outField = static_cast<char*>(bind->buffer); bind->buffer_type = MYSQL_TYPE_STRING; } }}bool QMYSQLResultPrivate::bindInValues(){ MYSQL_BIND *bind; char *field; int i = 0; if (!meta) meta = mysql_stmt_result_metadata(stmt); if (!meta) return false; fields.resize(mysql_num_fields(meta)); inBinds = new MYSQL_BIND[fields.size()]; memset(inBinds, 0, fields.size() * sizeof(MYSQL_BIND)); MYSQL_FIELD *fieldInfo; while((fieldInfo = mysql_fetch_field(meta))) { QMyField &f = fields[i]; f.myField = fieldInfo; f.type = qDecodeMYSQLType(fieldInfo->type, fieldInfo->flags); if (qIsBlob(fieldInfo->type)) { // the size of a blob-field is available as soon as we call // mysql_stmt_store_result() // after mysql_stmt_exec() in QMYSQLResult::exec() fieldInfo->length = 0; hasBlobs = true; } else { fieldInfo->type = MYSQL_TYPE_STRING; } bind = &inBinds[i]; field = new char[fieldInfo->length + 1]; memset(field, 0, fieldInfo->length + 1); bind->buffer_type = fieldInfo->type; bind->buffer = field; bind->buffer_length = f.bufLength = fieldInfo->length + 1; bind->is_null = &f.nullIndicator; bind->length = &f.bufLength; f.outField=field; ++i; } return true;}#endifQMYSQLResult::QMYSQLResult(const QMYSQLDriver* db): QSqlResult(db){ d = new QMYSQLResultPrivate(); d->mysql = db->d->mysql; d->tc = db->d->tc; d->preparedQuerysEnabled = db->d->preparedQuerysEnabled;}QMYSQLResult::~QMYSQLResult(){ cleanup(); delete d;}QVariant QMYSQLResult::handle() const{#if MYSQL_VERSION_ID >= 40108 return d->meta ? qVariantFromValue(d->meta) : qVariantFromValue(d->stmt);#else return qVariantFromValue(d->result);#endif}void QMYSQLResult::cleanup(){ if (d->result) mysql_free_result(d->result);#if MYSQL_VERSION_ID >= 40108 if (d->stmt) { if (mysql_stmt_close(d->stmt)) qWarning("QMYSQLResult::cleanup: unable to free statement handle"); d->stmt = 0; } if (d->meta) { mysql_free_result(d->meta); d->meta = 0; } int i; for (i = 0; i < d->fields.count(); ++i) delete[] d->fields[i].outField; if (d->outBinds) { delete[] d->outBinds; d->outBinds = 0; } if (d->inBinds) { delete[] d->inBinds; d->inBinds = 0; }// for(i = 0; i < d->outFields.size(); ++i)// delete[] d->outFields.at(i);#endif d->hasBlobs = false; d->fields.clear(); d->result = NULL; d->row = NULL; setAt(-1); setActive(false); d->preparedQuerys = d->preparedQuerysEnabled;}bool QMYSQLResult::fetch(int i){
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -