You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/kexi/kexidb/drivers/mySQL/mysqlcursor.cpp

219 lines
6.2 KiB

/* This file is part of the KDE project
Copyright (C) 2003 Joseph Wenninger<jowenn@kde.org>
Copyright (C) 2005 Jaroslaw Staniek <js@iidea.pl>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "mysqlcursor.h"
#include "mysqlconnection.h"
#include "mysqlconnection_p.h"
#include <kexidb/error.h>
#include <kexidb/utils.h>
#include <tdelocale.h>
#include <kdebug.h>
#include <limits.h>
#define BOOL bool
using namespace KexiDB;
MySqlCursor::MySqlCursor(KexiDB::Connection* conn, const TQString& statement, uint cursor_options)
: Cursor(conn,statement,cursor_options)
, d( new MySqlCursorData(conn) )
{
m_options |= Buffered;
d->mysql = static_cast<MySqlConnection*>(conn)->d->mysql;
// KexiDBDrvDbg << "MySqlCursor: constructor for query statement" << endl;
}
MySqlCursor::MySqlCursor(Connection* conn, QuerySchema& query, uint options )
: Cursor( conn, query, options )
, d( new MySqlCursorData(conn) )
{
m_options |= Buffered;
d->mysql = static_cast<MySqlConnection*>(conn)->d->mysql;
// KexiDBDrvDbg << "MySqlCursor: constructor for query statement" << endl;
}
MySqlCursor::~MySqlCursor() {
close();
}
bool MySqlCursor::drv_open() {
// KexiDBDrvDbg << "MySqlCursor::drv_open:" << m_sql << endl;
// This can't be right? mysql_real_query takes a length in order that
// queries can have binary data - but strlen does not allow binary data.
if(mysql_real_query(d->mysql, m_sql.utf8(), strlen(m_sql.utf8())) == 0) {
if(mysql_errno(d->mysql) == 0) {
d->mysqlres= mysql_store_result(d->mysql);
m_fieldCount=mysql_num_fields(d->mysqlres);
d->numRows=mysql_num_rows(d->mysqlres);
m_at=0;
m_opened=true;
m_records_in_buf = d->numRows;
m_buffering_completed = true;
m_afterLast=false;
return true;
}
}
setError(ERR_DB_SPECIFIC,TQString::fromUtf8(mysql_error(d->mysql)));
return false;
}
bool MySqlCursor::drv_close() {
mysql_free_result(d->mysqlres);
d->mysqlres=0;
d->mysqlrow=0;
//js: done in superclass: m_numFields=0;
d->lengths=0;
m_opened=false;
d->numRows=0;
return true;
}
/*bool MySqlCursor::drv_moveFirst() {
return true; //TODO
}*/
void MySqlCursor::drv_getNextRecord() {
// KexiDBDrvDbg << "MySqlCursor::drv_getNextRecord" << endl;
if (at() < d->numRows && at() >=0) {
d->lengths=mysql_fetch_lengths(d->mysqlres);
m_result=FetchOK;
}
else if (at() >= d->numRows) {
m_result = FetchEnd;
}
else {
m_result = FetchError;
}
}
// This isn't going to work right now as it uses d->mysqlrow
TQVariant MySqlCursor::value(uint pos) {
if (!d->mysqlrow || pos>=m_fieldCount || d->mysqlrow[pos]==0)
return TQVariant();
KexiDB::Field *f = (m_fieldsExpanded && pos<m_fieldsExpanded->count())
? m_fieldsExpanded->at(pos)->field : 0;
//! @todo js: use MYSQL_FIELD::type here!
return KexiDB::cstringToVariant(d->mysqlrow[pos], f, d->lengths[pos]);
/* moved to cstringToVariant()
//from most to least frequently used types:
if (!f || f->isTextType())
return TQVariant( TQString::fromUtf8((const char*)d->mysqlrow[pos], d->lengths[pos]) );
else if (f->isIntegerType())
//! @todo support BigInteger
return TQVariant( TQCString((const char*)d->mysqlrow[pos], d->lengths[pos]).toInt() );
else if (f->isFPNumericType())
return TQVariant( TQCString((const char*)d->mysqlrow[pos], d->lengths[pos]).toDouble() );
//default
return TQVariant(TQString::fromUtf8((const char*)d->mysqlrow[pos], d->lengths[pos]));*/
}
/* As with sqlite, the DB library returns all values (including numbers) as
strings. So just put that string in a TQVariant and let KexiDB deal with it.
*/
void MySqlCursor::storeCurrentRow(RowData &data) const
{
// KexiDBDrvDbg << "MySqlCursor::storeCurrentRow: Position is " << (long)m_at<< endl;
if (d->numRows<=0)
return;
//! @todo js: use MYSQL_FIELD::type here!
//! see SQLiteCursor::storeCurrentRow()
data.resize(m_fieldCount);
const uint fieldsExpandedCount = m_fieldsExpanded ? m_fieldsExpanded->count() : UINT_MAX;
const uint realCount = TQMIN(fieldsExpandedCount, m_fieldCount);
for( uint i=0; i<realCount; i++) {
Field *f = m_fieldsExpanded ? m_fieldsExpanded->at(i)->field : 0;
if (m_fieldsExpanded && !f)
continue;
data[i] = KexiDB::cstringToVariant(d->mysqlrow[i], f, d->lengths[i]);
/* moved to cstringToVariant()
if (f && f->type()==Field::BLOB) {
TQByteArray ba;
ba.duplicate(d->mysqlrow[i], d->lengths[i]);
data[i] = ba;
KexiDBDbg << data[i].toByteArray().size() << endl;
}
//! @todo more types!
//! @todo look at what type mysql declares!
else {
data[i] = TQVariant(TQString::fromUtf8((const char*)d->mysqlrow[i], d->lengths[i]));
}*/
}
}
void MySqlCursor::drv_appendCurrentRecordToBuffer() {
}
void MySqlCursor::drv_bufferMovePointerNext() {
d->mysqlrow=mysql_fetch_row(d->mysqlres);
d->lengths=mysql_fetch_lengths(d->mysqlres);
}
void MySqlCursor::drv_bufferMovePointerPrev() {
//MYSQL_ROW_OFFSET ro=mysql_row_tell(d->mysqlres);
mysql_data_seek(d->mysqlres,m_at-1);
d->mysqlrow=mysql_fetch_row(d->mysqlres);
d->lengths=mysql_fetch_lengths(d->mysqlres);
}
void MySqlCursor::drv_bufferMovePointerTo(TQ_LLONG to) {
//MYSQL_ROW_OFFSET ro=mysql_row_tell(d->mysqlres);
mysql_data_seek(d->mysqlres, to);
d->mysqlrow=mysql_fetch_row(d->mysqlres);
d->lengths=mysql_fetch_lengths(d->mysqlres);
}
const char** MySqlCursor::rowData() const {
//! @todo
return 0;
}
int MySqlCursor::serverResult()
{
return d->res;
}
TQString MySqlCursor::serverResultName()
{
return TQString();
}
void MySqlCursor::drv_clearServerResult()
{
if (!d)
return;
d->res = 0;
}
TQString MySqlCursor::serverErrorMsg()
{
return d->errmsg;
}