2
// C++ Implementation: pqxxsqlcursor
7
// Author: Adam Pigg <piggz@defiant.piggz.co.uk>, (C) 2003
9
// Copyright: See COPYING file that comes with this distribution
12
#include "pqxxcursor.h"
13
#include "pqxxconnection.h"
15
#include <kexidb/error.h>
16
#include <kexidb/global.h>
21
using namespace KexiDB;
24
unsigned int pqxxSqlCursor_trans_num=0; //!< debug helper
26
//==================================================================================
27
//Constructor based on query statement
28
pqxxSqlCursor::pqxxSqlCursor(KexiDB::Connection* conn, const QString& statement, uint options):
29
Cursor(conn,statement, options)
31
KexiDBDrvDbg << "PQXXSQLCURSOR: constructor for query statement" << endl;
32
my_conn = static_cast<pqxxSqlConnection*>(conn)->m_pqxxsql;
38
//==================================================================================
39
//Constructor base on query object
40
pqxxSqlCursor::pqxxSqlCursor(Connection* conn, QuerySchema& query, uint options )
41
: Cursor( conn, query, options )
43
KexiDBDrvDbg << "PQXXSQLCURSOR: constructor for query schema" << endl;
44
my_conn = static_cast<pqxxSqlConnection*>(conn)->m_pqxxsql;
50
//==================================================================================
52
pqxxSqlCursor::~pqxxSqlCursor()
57
//==================================================================================
58
//Create a cursor result set
59
bool pqxxSqlCursor::drv_open(const QString& statement)
61
KexiDBDrvDbg << "pqxxSqlCursor::drv_open:" << statement << endl;
63
if (!my_conn->is_open())
65
//should never happen, but who knows
66
setError(ERR_NO_CONNECTION,i18n("No connection for cursor open operation specified"));
71
//Set up a transaction
74
//m_tran = new pqxx::work(*my_conn, "cursor_open");
75
cur_name.sprintf("cursor_transaction%d", pqxxSqlCursor_trans_num++);
77
m_tran = new pqxx::nontransaction(*my_conn, (const char*)cur_name);
79
m_res = new pqxx::result(m_tran->exec(statement.utf8()));
81
KexiDBDrvDbg << "pqxxSqlCursor::drv_open: trans. commited: " << cur_name <<endl;
83
//We should now be placed before the first row, if any
84
m_fieldCount = m_res->columns();
87
m_records_in_buf = m_res->size();
88
m_buffering_completed = true;
91
catch (const std::exception &e)
93
setError(ERR_DB_SPECIFIC,e.what());
94
KexiDBDrvDbg << "pqxxSqlCursor::drv_open:exception - " << e.what() << endl;
102
KexiDBDrvDbg << "pqxxSqlCursor::drv_open: trans. rolled back! - " << cur_name <<endl;
106
//==================================================================================
108
bool pqxxSqlCursor::drv_close()
121
//==================================================================================
122
//Gets the next record...doesnt need to do much, just return fetchend if at end of result set
123
void pqxxSqlCursor::drv_getNextRecord()
125
KexiDBDrvDbg << "pqxxSqlCursor::drv_getNextRecord, size is " <<m_res->size() << " Current Position is " << (long)at() << endl;
126
if(at() < m_res->size() && at() >=0)
130
else if (at() >= m_res->size())
136
m_result = FetchError;
140
//==================================================================================
141
//Check the current position is within boundaries
142
void pqxxSqlCursor::drv_getPrevRecord()
144
KexiDBDrvDbg << "pqxxSqlCursor::drv_getPrevRecord" << endl;
146
if(at() < m_res->size() && at() >=0)
150
else if (at() >= m_res->size())
156
m_result = FetchError;
160
//==================================================================================
161
//Return the value for a given column for the current record
162
QVariant pqxxSqlCursor::value(uint pos)
164
if (pos < m_fieldCount)
170
//==================================================================================
171
//Return the value for a given column for the current record - Private const version
172
QVariant pqxxSqlCursor::pValue(uint pos) const
174
if (!m_res->size() > 0)
176
KexiDBDrvDbg << "pqxxSqlCursor::value - ERROR: result size not greater than 0" << endl;
180
if (pos>=m_fieldCount)
182
KexiDBDrvDbg << "pqxxSqlCursor::value - ERROR: requested position is greater than the number of fields" << endl;
186
KexiDB::Field *f = m_fieldsExpanded ? m_fieldsExpanded->at(pos)->field : 0;
187
//from most to least frequently used types:
188
if (!f || f->isTextType())
190
return QVariant((*m_res)[at()][pos].c_str());
192
else if (f->isIntegerType())
194
return QVariant((*m_res)[at()][pos].as(int()));
196
else if (f->isFPNumericType())
198
return QVariant((*m_res)[at()][pos].as(double()));
201
return QVariant((*m_res)[at()][pos].c_str());
204
//==================================================================================
205
//Return the current record as a char**
206
//who'd have thought we'd be using char** in this day and age :o)
207
const char** pqxxSqlCursor::rowData() const
209
KexiDBDrvDbg << "pqxxSqlCursor::recordData" << endl;
213
row = (const char**)malloc(m_res->columns()+1);
214
row[m_res->columns()] = NULL;
215
if (at() >= 0 && at() < m_res->size())
217
for(int i = 0; i < m_res->columns(); i++)
219
row[i] = (char*)malloc(strlen((*m_res)[at()][i].c_str())+1);
220
strcpy((char*)(*m_res)[at()][i].c_str(), row[i]);
221
KexiDBDrvDbg << row[i] << endl;
226
KexiDBDrvDbg << "pqxxSqlCursor::recordData: m_at is invalid" << endl;
231
//==================================================================================
232
//Store the current record in [data]
233
void pqxxSqlCursor::storeCurrentRow(RowData &data) const
235
KexiDBDrvDbg << "pqxxSqlCursor::storeCurrentRow: POSITION IS " << (long)m_at<< endl;
237
if (!m_res->size()>0)
240
data.reserve(m_fieldCount);
242
for( uint i=0; i<m_fieldCount; i++)
248
//==================================================================================
250
void pqxxSqlCursor::drv_clearServerResult()
252
#warning TODO: stuff with server results
255
//==================================================================================
256
//Add the current record to the internal buffer
257
//Implementation required but no need in this driver
258
//Result set is a buffer so dont need another
259
void pqxxSqlCursor::drv_appendCurrentRecordToBuffer()
264
//==================================================================================
265
//Move internal pointer to internal buffer +1
266
//Implementation required but no need in this driver
267
void pqxxSqlCursor::drv_bufferMovePointerNext()
272
//==================================================================================
273
//Move internal pointer to internal buffer -1
274
//Implementation required but no need in this driver
275
void pqxxSqlCursor::drv_bufferMovePointerPrev()
280
//==================================================================================
281
//Move internal pointer to internal buffer to N
282
//Implementation required but no need in this driver
283
void pqxxSqlCursor::drv_bufferMovePointerTo(Q_LLONG to)