kexi

mysqlcursor.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2003 Joseph Wenninger<jowenn@kde.org>
00003    Copyright (C) 2005 Jaroslaw Staniek <js@iidea.pl>
00004 
00005    This program is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this program; see the file COPYING.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "mysqlcursor.h"
00022 #include "mysqlconnection.h"
00023 #include "mysqlconnection_p.h"
00024 #include <kexidb/error.h>
00025 #include <kexidb/utils.h>
00026 #include <klocale.h>
00027 #include <kdebug.h>
00028 #include <limits.h>
00029 
00030 #define BOOL bool
00031 
00032 using namespace KexiDB;
00033 
00034 MySqlCursor::MySqlCursor(KexiDB::Connection* conn, const QString& statement, uint cursor_options)
00035     : Cursor(conn,statement,cursor_options)
00036     , d( new MySqlCursorData(conn) )
00037 {
00038     m_options |= Buffered;
00039     d->mysql = static_cast<MySqlConnection*>(conn)->d->mysql;
00040 //  KexiDBDrvDbg << "MySqlCursor: constructor for query statement" << endl;
00041 }
00042 
00043 MySqlCursor::MySqlCursor(Connection* conn, QuerySchema& query, uint options )
00044     : Cursor( conn, query, options )
00045     , d( new MySqlCursorData(conn) )
00046 {
00047     m_options |= Buffered;
00048     d->mysql = static_cast<MySqlConnection*>(conn)->d->mysql;
00049 //  KexiDBDrvDbg << "MySqlCursor: constructor for query statement" << endl;
00050 }
00051 
00052 MySqlCursor::~MySqlCursor() {
00053     close();
00054 }
00055 
00056 bool MySqlCursor::drv_open() {
00057 //  KexiDBDrvDbg << "MySqlCursor::drv_open:" << m_sql << endl;
00058     // This can't be right?  mysql_real_query takes a length in order that
00059     // queries can have binary data - but strlen does not allow binary data.
00060     if(mysql_real_query(d->mysql, m_sql.utf8(), strlen(m_sql.utf8())) == 0) {
00061         if(mysql_errno(d->mysql) == 0) {
00062             d->mysqlres= mysql_store_result(d->mysql);
00063             m_fieldCount=mysql_num_fields(d->mysqlres);
00064             d->numRows=mysql_num_rows(d->mysqlres);
00065             m_at=0;
00066             
00067             m_opened=true;
00068             m_records_in_buf = d->numRows;
00069             m_buffering_completed = true;
00070             m_afterLast=false;
00071             return true;
00072             }
00073     }
00074     
00075     setError(ERR_DB_SPECIFIC,QString::fromUtf8(mysql_error(d->mysql)));
00076     return false;
00077 }
00078 
00079 bool MySqlCursor::drv_close() {
00080     mysql_free_result(d->mysqlres);
00081     d->mysqlres=0;
00082     d->mysqlrow=0;
00083 //js: done in superclass:   m_numFields=0;
00084     d->lengths=0;
00085     m_opened=false;
00086     d->numRows=0;
00087     return true;
00088 }
00089 
00090 /*bool MySqlCursor::drv_moveFirst() {
00091     return true; //TODO
00092 }*/
00093 
00094 void MySqlCursor::drv_getNextRecord() {
00095 //  KexiDBDrvDbg << "MySqlCursor::drv_getNextRecord" << endl;
00096     if (at() < d->numRows && at() >=0) {
00097         d->lengths=mysql_fetch_lengths(d->mysqlres);
00098         m_result=FetchOK;
00099     }
00100     else if (at() >= d->numRows) {
00101         m_result = FetchEnd;
00102     }
00103     else {
00104         m_result = FetchError;
00105     }
00106 }
00107 
00108 // This isn't going to work right now as it uses d->mysqlrow
00109 QVariant MySqlCursor::value(uint pos) {
00110     if (!d->mysqlrow || pos>=m_fieldCount || d->mysqlrow[pos]==0)
00111         return QVariant();
00112 
00113     KexiDB::Field *f = (m_fieldsExpanded && pos<m_fieldsExpanded->count())
00114         ? m_fieldsExpanded->at(pos)->field : 0;
00115     
00117 
00118     return KexiDB::cstringToVariant(d->mysqlrow[pos], f, d->lengths[pos]);
00119 /* moved to cstringToVariant()
00120     //from most to least frequently used types:
00121     if (!f || f->isTextType())
00122         return QVariant( QString::fromUtf8((const char*)d->mysqlrow[pos], d->lengths[pos]) );
00123     else if (f->isIntegerType())
00125         return QVariant( QCString((const char*)d->mysqlrow[pos], d->lengths[pos]).toInt() );
00126     else if (f->isFPNumericType())
00127         return QVariant( QCString((const char*)d->mysqlrow[pos], d->lengths[pos]).toDouble() );
00128 
00129     //default
00130     return QVariant(QString::fromUtf8((const char*)d->mysqlrow[pos], d->lengths[pos]));*/
00131 }
00132 
00133 
00134 /* As with sqlite, the DB library returns all values (including numbers) as
00135    strings. So just put that string in a QVariant and let KexiDB deal with it.
00136  */
00137 void MySqlCursor::storeCurrentRow(RowData &data) const
00138 {
00139 //  KexiDBDrvDbg << "MySqlCursor::storeCurrentRow: Position is " << (long)m_at<< endl;
00140     if (d->numRows<=0)
00141         return;
00142 
00145 
00146     data.resize(m_fieldCount);
00147     const uint fieldsExpandedCount = m_fieldsExpanded ? m_fieldsExpanded->count() : UINT_MAX;
00148     const uint realCount = QMIN(fieldsExpandedCount, m_fieldCount);
00149     for( uint i=0; i<realCount; i++) {
00150         Field *f = m_fieldsExpanded ? m_fieldsExpanded->at(i)->field : 0;
00151         if (m_fieldsExpanded && !f)
00152             continue;
00153         data[i] = KexiDB::cstringToVariant(d->mysqlrow[i], f, d->lengths[i]);
00154 /* moved to cstringToVariant()
00155         if (f && f->type()==Field::BLOB) {
00156             QByteArray ba;
00157             ba.duplicate(d->mysqlrow[i], d->lengths[i]);
00158             data[i] = ba;
00159             KexiDBDbg << data[i].toByteArray().size() << endl;
00160         }
00163         else {
00164             data[i] = QVariant(QString::fromUtf8((const char*)d->mysqlrow[i], d->lengths[i]));
00165         }*/
00166     }
00167 }
00168 
00169 void MySqlCursor::drv_appendCurrentRecordToBuffer() {
00170 }
00171 
00172 
00173 void MySqlCursor::drv_bufferMovePointerNext() {
00174     d->mysqlrow=mysql_fetch_row(d->mysqlres);
00175     d->lengths=mysql_fetch_lengths(d->mysqlres);
00176 }
00177 
00178 void MySqlCursor::drv_bufferMovePointerPrev() {
00179     //MYSQL_ROW_OFFSET ro=mysql_row_tell(d->mysqlres);
00180     mysql_data_seek(d->mysqlres,m_at-1);
00181     d->mysqlrow=mysql_fetch_row(d->mysqlres);
00182     d->lengths=mysql_fetch_lengths(d->mysqlres);
00183 }
00184 
00185 
00186 void MySqlCursor::drv_bufferMovePointerTo(Q_LLONG to) {
00187     //MYSQL_ROW_OFFSET ro=mysql_row_tell(d->mysqlres);
00188     mysql_data_seek(d->mysqlres, to);
00189     d->mysqlrow=mysql_fetch_row(d->mysqlres);
00190     d->lengths=mysql_fetch_lengths(d->mysqlres);
00191 }
00192 
00193 const char** MySqlCursor::rowData() const {
00195     return 0;
00196 }
00197 
00198 int MySqlCursor::serverResult()
00199 {
00200     return d->res;
00201 }
00202 
00203 QString MySqlCursor::serverResultName()
00204 {
00205     return QString::null;
00206 }
00207 
00208 void MySqlCursor::drv_clearServerResult()
00209 {
00210     if (!d)
00211         return;
00212     d->res = 0;
00213 }
00214 
00215 QString MySqlCursor::serverErrorMsg()
00216 {
00217     return d->errmsg;
00218 }
KDE Home | KDE Accessibility Home | Description of Access Keys