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 <klocale.h>
00026 #include <kdebug.h>
00027 #include <limits.h>
00028 
00029 #define BOOL bool
00030 
00031 using namespace KexiDB;
00032 
00033 MySqlCursor::MySqlCursor(KexiDB::Connection* conn, const QString& statement, uint cursor_options)
00034     : Cursor(conn,statement,cursor_options)
00035     , d( new MySqlCursorData(conn) )
00036 {
00037     m_options |= Buffered;
00038     d->mysql = static_cast<MySqlConnection*>(conn)->d->mysql;
00039 //  KexiDBDrvDbg << "MySqlCursor: constructor for query statement" << endl;
00040 }
00041 
00042 MySqlCursor::MySqlCursor(Connection* conn, QuerySchema& query, uint options )
00043     : Cursor( conn, query, options )
00044     , d( new MySqlCursorData(conn) )
00045 {
00046     m_options |= Buffered;
00047     d->mysql = static_cast<MySqlConnection*>(conn)->d->mysql;
00048 //  KexiDBDrvDbg << "MySqlCursor: constructor for query statement" << endl;
00049 }
00050 
00051 MySqlCursor::~MySqlCursor() {
00052     close();
00053 }
00054 
00055 bool MySqlCursor::drv_open() {
00056 //  KexiDBDrvDbg << "MySqlCursor::drv_open:" << m_sql << endl;
00057     // This can't be right?  mysql_real_query takes a length in order that
00058     // queries can have binary data - but strlen does not allow binary data.
00059     if(mysql_real_query(d->mysql, m_sql.utf8(), strlen(m_sql.utf8())) == 0) {
00060         if(mysql_errno(d->mysql) == 0) {
00061             d->mysqlres= mysql_store_result(d->mysql);
00062             m_fieldCount=mysql_num_fields(d->mysqlres);
00063             d->numRows=mysql_num_rows(d->mysqlres);
00064             m_at=0;
00065             
00066             m_opened=true;
00067             m_records_in_buf = d->numRows;
00068             m_buffering_completed = true;
00069             m_afterLast=false;
00070             return true;
00071             }
00072     }
00073     
00074     setError(ERR_DB_SPECIFIC,QString::fromUtf8(mysql_error(d->mysql)));
00075     return false;
00076 }
00077 
00078 bool MySqlCursor::drv_close() {
00079     mysql_free_result(d->mysqlres);
00080     d->mysqlres=0;
00081     d->mysqlrow=0;
00082 //js: done in superclass:   m_numFields=0;
00083     d->lengths=0;
00084     m_opened=false;
00085     d->numRows=0;
00086     return true;
00087 }
00088 
00089 /*bool MySqlCursor::drv_moveFirst() {
00090     return true; //TODO
00091 }*/
00092 
00093 void MySqlCursor::drv_getNextRecord() {
00094 //  KexiDBDrvDbg << "MySqlCursor::drv_getNextRecord" << endl;
00095     if (at() < d->numRows && at() >=0) {
00096         d->lengths=mysql_fetch_lengths(d->mysqlres);
00097         m_result=FetchOK;
00098     }
00099     else if (at() >= d->numRows) {
00100         m_result = FetchEnd;
00101     }
00102     else {
00103         m_result = FetchError;
00104     }
00105 }
00106 
00107 // This isn't going to work right now as it uses d->mysqlrow
00108 QVariant MySqlCursor::value(uint pos) {
00109     if (!d->mysqlrow || pos>=m_fieldCount || d->mysqlrow[pos]==0)
00110         return QVariant();
00111 
00112     KexiDB::Field *f = (m_fieldsExpanded && pos<m_fieldsExpanded->count())
00113         ? m_fieldsExpanded->at(pos)->field : 0;
00114     
00116 
00117     //from most to least frequently used types:
00118     if (!f || f->isTextType())
00119         return QVariant( QString::fromUtf8((const char*)d->mysqlrow[pos]) );
00120     else if (f->isIntegerType())
00122         return QVariant( QCString((const char*)d->mysqlrow[pos]).toInt() );
00123     else if (f->isFPNumericType())
00124         return QVariant( QCString((const char*)d->mysqlrow[pos]).toDouble() );
00125 
00126     //default
00127     return QVariant(QString::fromUtf8((const char*)d->mysqlrow[pos]));
00128 }
00129 
00130 
00131 /* As with sqlite, the DB library returns all values (including numbers) as
00132    strings. So just put that string in a QVariant and let KexiDB deal with it.
00133  */
00134 void MySqlCursor::storeCurrentRow(RowData &data) const {
00135 //  KexiDBDrvDbg << "MySqlCursor::storeCurrentRow: Position is " << (long)m_at<< endl;
00136     if (d->numRows<=0)
00137         return;
00138 
00141 
00142     data.resize(m_fieldCount);
00143     const uint fieldsExpandedCount = m_fieldsExpanded ? m_fieldsExpanded->count() : UINT_MAX;
00144     const uint realCount = QMIN(fieldsExpandedCount, m_fieldCount);
00145     for( uint i=0; i<realCount; i++) {
00146         Field *f = m_fieldsExpanded ? m_fieldsExpanded->at(i)->field : 0;
00147         if (m_fieldsExpanded && !f)
00148             continue;
00149         if (f && f->type()==Field::BLOB) {
00150             QByteArray ba;
00151             ba.duplicate(d->mysqlrow[i], d->mysqlres->lengths[i]);
00152             data[i] = ba;
00153             KexiDBDbg << data[i].toByteArray().size() << endl;
00154         }
00157         else {
00158             data[i] = QVariant(QString::fromUtf8((const char*)d->mysqlrow[i]));
00159         }
00160     }
00161 }
00162 
00163 void MySqlCursor::drv_appendCurrentRecordToBuffer() {
00164 }
00165 
00166 
00167 void MySqlCursor::drv_bufferMovePointerNext() {
00168     d->mysqlrow=mysql_fetch_row(d->mysqlres);
00169     d->lengths=mysql_fetch_lengths(d->mysqlres);
00170 }
00171 
00172 void MySqlCursor::drv_bufferMovePointerPrev() {
00173     //MYSQL_ROW_OFFSET ro=mysql_row_tell(d->mysqlres);
00174     mysql_data_seek(d->mysqlres,m_at-1);
00175     d->mysqlrow=mysql_fetch_row(d->mysqlres);
00176     d->lengths=mysql_fetch_lengths(d->mysqlres);
00177 }
00178 
00179 
00180 void MySqlCursor::drv_bufferMovePointerTo(Q_LLONG to) {
00181     //MYSQL_ROW_OFFSET ro=mysql_row_tell(d->mysqlres);
00182     mysql_data_seek(d->mysqlres, to);
00183     d->mysqlrow=mysql_fetch_row(d->mysqlres);
00184     d->lengths=mysql_fetch_lengths(d->mysqlres);
00185 }
00186 
00187 const char** MySqlCursor::rowData() const {
00189     return 0;
00190 }
00191 
00192 int MySqlCursor::serverResult()
00193 {
00194     return d->res;
00195 }
00196 
00197 QString MySqlCursor::serverResultName()
00198 {
00199     return QString::null;
00200 }
00201 
00202 void MySqlCursor::drv_clearServerResult()
00203 {
00204     if (!d)
00205         return;
00206     d->res = 0;
00207 }
00208 
00209 QString MySqlCursor::serverErrorMsg()
00210 {
00211     return d->errmsg;
00212 }
KDE Home | KDE Accessibility Home | Description of Access Keys