mysqlcursor.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2003 Joseph Wenninger<jowenn@kde.org>
3 Copyright (C) 2005 Jaroslaw Staniek <js@iidea.pl>
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this program; see the file COPYING. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19*/
20
21#include "mysqlcursor.h"
22#include "mysqlconnection.h"
23#include "mysqlconnection_p.h"
24#include <kexidb/error.h>
25#include <kexidb/utils.h>
26#include <tdelocale.h>
27#include <kdebug.h>
28#include <limits.h>
29
30#define BOOL bool
31
32using namespace KexiDB;
33
34MySqlCursor::MySqlCursor(KexiDB::Connection* conn, const TQString& statement, uint cursor_options)
35 : Cursor(conn,statement,cursor_options)
36 , d( new MySqlCursorData(conn) )
37{
38 m_options |= Buffered;
39 d->mysql = static_cast<MySqlConnection*>(conn)->d->mysql;
40// KexiDBDrvDbg << "MySqlCursor: constructor for query statement" << endl;
41}
42
43MySqlCursor::MySqlCursor(Connection* conn, QuerySchema& query, uint options )
44 : Cursor( conn, query, options )
45 , d( new MySqlCursorData(conn) )
46{
47 m_options |= Buffered;
48 d->mysql = static_cast<MySqlConnection*>(conn)->d->mysql;
49// KexiDBDrvDbg << "MySqlCursor: constructor for query statement" << endl;
50}
51
52MySqlCursor::~MySqlCursor() {
53 close();
54}
55
56bool MySqlCursor::drv_open() {
57// KexiDBDrvDbg << "MySqlCursor::drv_open:" << m_sql << endl;
58 // This can't be right? mysql_real_query takes a length in order that
59 // queries can have binary data - but strlen does not allow binary data.
60 if(mysql_real_query(d->mysql, m_sql.utf8(), strlen(m_sql.utf8())) == 0) {
61 if(mysql_errno(d->mysql) == 0) {
62 d->mysqlres= mysql_store_result(d->mysql);
63 m_fieldCount=mysql_num_fields(d->mysqlres);
64 d->numRows=mysql_num_rows(d->mysqlres);
65 m_at=0;
66
67 m_opened=true;
68 m_records_in_buf = d->numRows;
69 m_buffering_completed = true;
70 m_afterLast=false;
71 return true;
72 }
73 }
74
75 setError(ERR_DB_SPECIFIC,TQString::fromUtf8(mysql_error(d->mysql)));
76 return false;
77}
78
79bool MySqlCursor::drv_close() {
80 mysql_free_result(d->mysqlres);
81 d->mysqlres=0;
82 d->mysqlrow=0;
83//js: done in superclass: m_numFields=0;
84 d->lengths=0;
85 m_opened=false;
86 d->numRows=0;
87 return true;
88}
89
90/*bool MySqlCursor::drv_moveFirst() {
91 return true; //TODO
92}*/
93
94void MySqlCursor::drv_getNextRecord() {
95// KexiDBDrvDbg << "MySqlCursor::drv_getNextRecord" << endl;
96 if (at() < d->numRows && at() >=0) {
97 d->lengths=mysql_fetch_lengths(d->mysqlres);
98 m_result=FetchOK;
99 }
100 else if (at() >= d->numRows) {
101 m_result = FetchEnd;
102 }
103 else {
104 m_result = FetchError;
105 }
106}
107
108// This isn't going to work right now as it uses d->mysqlrow
109TQVariant MySqlCursor::value(uint pos) {
110 if (!d->mysqlrow || pos>=m_fieldCount || d->mysqlrow[pos]==0)
111 return TQVariant();
112
113 KexiDB::Field *f = (m_fieldsExpanded && pos<m_fieldsExpanded->count())
114 ? m_fieldsExpanded->at(pos)->field : 0;
115
117
118 return KexiDB::cstringToVariant(d->mysqlrow[pos], f, d->lengths[pos]);
119/* moved to cstringToVariant()
120 //from most to least frequently used types:
121 if (!f || f->isTextType())
122 return TQVariant( TQString::fromUtf8((const char*)d->mysqlrow[pos], d->lengths[pos]) );
123 else if (f->isIntegerType())
125 return TQVariant( TQCString((const char*)d->mysqlrow[pos], d->lengths[pos]).toInt() );
126 else if (f->isFPNumericType())
127 return TQVariant( TQCString((const char*)d->mysqlrow[pos], d->lengths[pos]).toDouble() );
128
129 //default
130 return TQVariant(TQString::fromUtf8((const char*)d->mysqlrow[pos], d->lengths[pos]));*/
131}
132
133
134/* As with sqlite, the DB library returns all values (including numbers) as
135 strings. So just put that string in a TQVariant and let KexiDB deal with it.
136 */
137void MySqlCursor::storeCurrentRow(RowData &data) const
138{
139// KexiDBDrvDbg << "MySqlCursor::storeCurrentRow: Position is " << (long)m_at<< endl;
140 if (d->numRows<=0)
141 return;
142
145
146 data.resize(m_fieldCount);
147 const uint fieldsExpandedCount = m_fieldsExpanded ? m_fieldsExpanded->count() : UINT_MAX;
148 const uint realCount = TQMIN(fieldsExpandedCount, m_fieldCount);
149 for( uint i=0; i<realCount; i++) {
150 Field *f = m_fieldsExpanded ? m_fieldsExpanded->at(i)->field : 0;
151 if (m_fieldsExpanded && !f)
152 continue;
153 data[i] = KexiDB::cstringToVariant(d->mysqlrow[i], f, d->lengths[i]);
154/* moved to cstringToVariant()
155 if (f && f->type()==Field::BLOB) {
156 TQByteArray ba;
157 ba.duplicate(d->mysqlrow[i], d->lengths[i]);
158 data[i] = ba;
159 KexiDBDbg << data[i].toByteArray().size() << endl;
160 }
163 else {
164 data[i] = TQVariant(TQString::fromUtf8((const char*)d->mysqlrow[i], d->lengths[i]));
165 }*/
166 }
167}
168
169void MySqlCursor::drv_appendCurrentRecordToBuffer() {
170}
171
172
173void MySqlCursor::drv_bufferMovePointerNext() {
174 d->mysqlrow=mysql_fetch_row(d->mysqlres);
175 d->lengths=mysql_fetch_lengths(d->mysqlres);
176}
177
178void MySqlCursor::drv_bufferMovePointerPrev() {
179 //MYSQL_ROW_OFFSET ro=mysql_row_tell(d->mysqlres);
180 mysql_data_seek(d->mysqlres,m_at-1);
181 d->mysqlrow=mysql_fetch_row(d->mysqlres);
182 d->lengths=mysql_fetch_lengths(d->mysqlres);
183}
184
185
186void MySqlCursor::drv_bufferMovePointerTo(TQ_LLONG to) {
187 //MYSQL_ROW_OFFSET ro=mysql_row_tell(d->mysqlres);
188 mysql_data_seek(d->mysqlres, to);
189 d->mysqlrow=mysql_fetch_row(d->mysqlres);
190 d->lengths=mysql_fetch_lengths(d->mysqlres);
191}
192
193const char** MySqlCursor::rowData() const {
195 return 0;
196}
197
198int MySqlCursor::serverResult()
199{
200 return d->res;
201}
202
203TQString MySqlCursor::serverResultName()
204{
205 return TQString();
206}
207
208void MySqlCursor::drv_clearServerResult()
209{
210 if (!d)
211 return;
212 d->res = 0;
213}
214
215TQString MySqlCursor::serverErrorMsg()
216{
217 return d->errmsg;
218}
Provides database connection, allowing queries and data modification.
Definition connection.h:62
Provides database cursor functionality.
Definition cursor.h:67
Meta-data for a field.
Definition field.h:73
KexiDB::QuerySchema provides information about database query.
High-level database connectivity library with database backend drivers.
TQVariant cstringToVariant(const char *data, KexiDB::Field *f, int length=-1)
TQValueVector< TQVariant > RowData
structure for storing single record with type information
Definition connection.h:47