File indexing completed on 2024-04-28 15:58:50
0001 /* This file is part of the KDE project 0002 Copyright (C) 2003 Joseph Wenninger<jowenn@kde.org> 0003 Copyright (C) 2005-2016 Jarosław Staniek <staniek@kde.org> 0004 0005 This program is free software; you can redistribute it and/or 0006 modify it under the terms of the GNU Library General Public 0007 License as published by the Free Software Foundation; either 0008 version 2 of the License, or (at your option) any later version. 0009 0010 This program is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 Library General Public License for more details. 0014 0015 You should have received a copy of the GNU Library General Public License 0016 along with this program; see the file COPYING. If not, write to 0017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 * Boston, MA 02110-1301, USA. 0019 */ 0020 0021 #include "MysqlCursor.h" 0022 #include "MysqlConnection.h" 0023 #include "MysqlConnection_p.h" 0024 #include "KDbError.h" 0025 #include "KDb.h" 0026 #include "KDbRecordData.h" 0027 0028 #include <limits.h> 0029 0030 #define BOOL bool 0031 0032 MysqlCursor::MysqlCursor(KDbConnection* conn, const KDbEscapedString& sql, 0033 KDbCursor::Options options) 0034 : KDbCursor(conn, sql, options | KDbCursor::Option::Buffered) 0035 , d(new MysqlCursorData(conn)) 0036 { 0037 } 0038 0039 MysqlCursor::MysqlCursor(KDbConnection* conn, KDbQuerySchema* query, KDbCursor::Options options) 0040 : KDbCursor(conn, query, options | KDbCursor::Option::Buffered) 0041 , d(new MysqlCursorData(conn)) 0042 { 0043 } 0044 0045 MysqlCursor::~MysqlCursor() 0046 { 0047 close(); 0048 delete d; 0049 } 0050 0051 bool MysqlCursor::drv_open(const KDbEscapedString& sql) 0052 { 0053 if (mysql_real_query(d->mysql, sql.constData(), sql.length()) == 0) { 0054 if (mysql_errno(d->mysql) == 0) { 0055 //! @todo Add option somewhere so we can use more optimal mysql_num_rows(). 0056 //! In this case mysql_num_rows() does not work however. 0057 d->mysqlres = mysql_store_result(d->mysql); 0058 m_fieldCount = mysql_num_fields(d->mysqlres); 0059 m_fieldsToStoreInRecord = m_fieldCount; 0060 d->numRows = mysql_num_rows(d->mysqlres); 0061 0062 m_records_in_buf = d->numRows; 0063 m_buffering_completed = true; 0064 return true; 0065 } 0066 } 0067 0068 storeResult(); 0069 return false; 0070 } 0071 0072 bool MysqlCursor::drv_close() 0073 { 0074 mysql_free_result(d->mysqlres); 0075 d->mysqlres = nullptr; 0076 d->mysqlrow = nullptr; 0077 d->lengths = nullptr; 0078 d->numRows = 0; 0079 return true; 0080 } 0081 0082 void MysqlCursor::drv_getNextRecord() 0083 { 0084 if (at() >= d->numRows) { 0085 m_fetchResult = FetchResult::End; 0086 } 0087 else if (at() < 0) { 0088 // control will reach here only when at() < 0 ( which is usually -1 ) 0089 // -1 is same as "1 beyond the End" 0090 m_fetchResult = FetchResult::End; 0091 } 0092 else { // 0 <= at() < d->numRows 0093 d->lengths = mysql_fetch_lengths(d->mysqlres); 0094 m_fetchResult = FetchResult::Ok; 0095 } 0096 } 0097 0098 // This isn't going to work right now as it uses d->mysqlrow 0099 QVariant MysqlCursor::value(int pos) 0100 { 0101 if (!d->mysqlrow || pos >= m_fieldCount || d->mysqlrow[pos] == nullptr) 0102 return QVariant(); 0103 0104 KDbField *f = (m_visibleFieldsExpanded && pos < m_visibleFieldsExpanded->count()) 0105 ? m_visibleFieldsExpanded->at(pos)->field() : nullptr; 0106 0107 //! @todo js: use MYSQL_FIELD::type here! 0108 0109 bool ok; 0110 return KDb::cstringToVariant(d->mysqlrow[pos], f ? f->type() : KDbField::Text, 0111 &ok, d->lengths[pos]); 0112 } 0113 0114 /* As with sqlite, the DB library returns all values (including numbers) as 0115 strings. So just put that string in a QVariant and let KDb deal with it. 0116 */ 0117 bool MysqlCursor::drv_storeCurrentRecord(KDbRecordData* data) const 0118 { 0119 // mysqlDebug() << "position is " << (long)m_at; 0120 if (d->numRows == 0) 0121 return false; 0122 0123 if (!m_visibleFieldsExpanded) {//simple version: without types 0124 for (int i = 0; i < m_fieldCount; ++i) { 0125 (*data)[i] = QString::fromUtf8(d->mysqlrow[i], d->lengths[i]); 0126 } 0127 return true; 0128 } 0129 for (int i = 0; i < m_fieldCount; ++i) { 0130 KDbField *f = m_visibleFieldsExpanded->at(i)->field(); 0131 bool ok; 0132 (*data)[i] = KDb::cstringToVariant(d->mysqlrow[i], f ? f->type() : KDbField::Text, 0133 &ok, d->lengths[i]); 0134 if (!ok) { 0135 return false; 0136 } 0137 } 0138 return true; 0139 } 0140 0141 void MysqlCursor::drv_appendCurrentRecordToBuffer() 0142 { 0143 } 0144 0145 0146 void MysqlCursor::drv_bufferMovePointerNext() 0147 { 0148 d->mysqlrow = mysql_fetch_row(d->mysqlres); 0149 d->lengths = mysql_fetch_lengths(d->mysqlres); 0150 } 0151 0152 void MysqlCursor::drv_bufferMovePointerPrev() 0153 { 0154 mysql_data_seek(d->mysqlres, m_at - 1); 0155 d->mysqlrow = mysql_fetch_row(d->mysqlres); 0156 d->lengths = mysql_fetch_lengths(d->mysqlres); 0157 } 0158 0159 0160 void MysqlCursor::drv_bufferMovePointerTo(qint64 to) 0161 { 0162 mysql_data_seek(d->mysqlres, to); 0163 d->mysqlrow = mysql_fetch_row(d->mysqlres); 0164 d->lengths = mysql_fetch_lengths(d->mysqlres); 0165 } 0166 0167 const char** MysqlCursor::recordData() const 0168 { 0169 //! @todo 0170 return nullptr; 0171 } 0172 0173 QString MysqlCursor::serverResultName() const 0174 { 0175 return MysqlConnectionInternal::serverResultName(d->mysql); 0176 } 0177 0178 void MysqlCursor::storeResult() 0179 { 0180 d->storeResult(&m_result); 0181 }