kexi
pqxxcursor.cpp00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "pqxxcursor.h"
00021 #include "pqxxconnection.h"
00022 #include "pqxxconnection_p.h"
00023
00024 #include <kexidb/error.h>
00025 #include <kexidb/global.h>
00026
00027 #include <klocale.h>
00028 #include <kdebug.h>
00029
00030 #include <migration/pqxx/pg_type.h>
00031 using namespace KexiDB;
00032
00033
00034 unsigned int pqxxSqlCursor_trans_num=0;
00035
00037 QByteArray processBinaryData(const pqxx::result::field r)
00038 {
00039 const int size = r.size();
00040 QByteArray array;
00041 int output=0;
00042 for (int pass=0; pass<2; pass++) {
00043
00044 const char* s = r.c_str();
00045 const char* end = s + size;
00046 if (pass==1) {
00047 KexiDBDrvDbg << "processBinaryData(): real size == " << output << endl;
00048 array.resize(output);
00049 output=0;
00050 }
00051 for (int input=0; s < end; output++) {
00052
00053 if (s[0]=='\\' && (s+1)<end) {
00054
00055 if (s[1]=='\'') {
00056 if (pass==1)
00057 array[output] = '\'';
00058 s+=2;
00059 }
00060 else if (s[1]=='\\') {
00061 if (pass==1)
00062 array[output] = '\\';
00063 s+=2;
00064 }
00065 else if ((input+3)<size) {
00066 if (pass==1)
00067 array[output] = char( (int(s[1]-'0')*8+int(s[2]-'0'))*8+int(s[3]-'0') );
00068 s+=4;
00069 }
00070 else {
00071 KexiDBDrvWarn << "processBinaryData(): no octal value after backslash" << endl;
00072 s++;
00073 }
00074 }
00075 else {
00076 if (pass==1)
00077 array[output] = s[0];
00078 s++;
00079 }
00080
00081 }
00082 }
00083 return array;
00084 }
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 pqxxSqlCursor::pqxxSqlCursor(KexiDB::Connection* conn, const QString& statement, uint options):
00099 Cursor(conn,statement, options)
00100 {
00101
00102 my_conn = static_cast<pqxxSqlConnection*>(conn)->d->m_pqxxsql;
00103 m_options = Buffered;
00104 m_res = 0;
00105
00106 m_implicityStarted = false;
00107 }
00108
00109
00110
00111 pqxxSqlCursor::pqxxSqlCursor(Connection* conn, QuerySchema& query, uint options )
00112 : Cursor( conn, query, options )
00113 {
00114
00115 my_conn = static_cast<pqxxSqlConnection*>(conn)->d->m_pqxxsql;
00116 m_options = Buffered;
00117 m_res = 0;
00118
00119 m_implicityStarted = false;
00120 }
00121
00122
00123
00124 pqxxSqlCursor::~pqxxSqlCursor()
00125 {
00126 close();
00127 }
00128
00129
00130
00131 bool pqxxSqlCursor::drv_open()
00132 {
00133
00134
00135 if (!my_conn->is_open())
00136 {
00138
00139 setError(ERR_NO_CONNECTION,i18n("No connection for cursor open operation specified"));
00140 return false;
00141 }
00142
00143 QCString cur_name;
00144
00145 try
00146 {
00147
00148 cur_name.sprintf("cursor_transaction%d", pqxxSqlCursor_trans_num++);
00149
00150
00151 if (!((pqxxSqlConnection*)connection())->m_trans) {
00152
00153
00154 (void)new pqxxTransactionData((pqxxSqlConnection*)connection(), true);
00155 m_implicityStarted = true;
00156 }
00157
00158 m_res = new pqxx::result(((pqxxSqlConnection*)connection())->m_trans->data->exec(m_sql.utf8()));
00159 ((pqxxSqlConnection*)connection())
00160 ->drv_commitTransaction(((pqxxSqlConnection*)connection())->m_trans);
00161
00162
00163
00164
00165 m_fieldCount = m_res->columns() - (m_containsROWIDInfo ? 1 : 0);
00166
00167 m_afterLast=false;
00168 m_records_in_buf = m_res->size();
00169 m_buffering_completed = true;
00170 return true;
00171 }
00172 catch (const std::exception &e)
00173 {
00174 setError(ERR_DB_SPECIFIC, QString::fromUtf8( e.what()) );
00175 KexiDBDrvWarn << "pqxxSqlCursor::drv_open:exception - " << QString::fromUtf8( e.what() ) << endl;
00176 }
00177 catch(...)
00178 {
00179 setError();
00180 }
00181
00182
00183 if (m_implicityStarted) {
00184 delete ((pqxxSqlConnection*)connection())->m_trans;
00185 m_implicityStarted = false;
00186 }
00187
00188 return false;
00189 }
00190
00191
00192
00193 bool pqxxSqlCursor::drv_close()
00194 {
00195
00196
00197 delete m_res;
00198 m_res = 0;
00199
00200
00201
00202
00203
00204
00205
00206 return true;
00207 }
00208
00209
00210
00211 void pqxxSqlCursor::drv_getNextRecord()
00212 {
00213
00214 if(at() < m_res->size() && at() >=0)
00215 {
00216 m_result = FetchOK;
00217 }
00218 else if (at() >= m_res->size())
00219 {
00220 m_result = FetchEnd;
00221 }
00222 else
00223 {
00224 m_result = FetchError;
00225 }
00226 }
00227
00228
00229
00230 void pqxxSqlCursor::drv_getPrevRecord()
00231 {
00232
00233
00234 if(at() < m_res->size() && at() >=0)
00235 {
00236 m_result = FetchOK;
00237 }
00238 else if (at() >= m_res->size())
00239 {
00240 m_result = FetchEnd;
00241 }
00242 else
00243 {
00244 m_result = FetchError;
00245 }
00246 }
00247
00248
00249
00250 QVariant pqxxSqlCursor::value(uint pos)
00251 {
00252 if (pos < m_fieldCount)
00253 return pValue(pos);
00254 else
00255 return QVariant();
00256 }
00257
00258
00259
00260 QVariant pqxxSqlCursor::pValue(uint pos)const
00261 {
00262 if (m_res->size() <= 0)
00263 {
00264 KexiDBDrvWarn << "pqxxSqlCursor::value - ERROR: result size not greater than 0" << endl;
00265 return QVariant();
00266 }
00267
00268 if (pos>=(m_fieldCount+(m_containsROWIDInfo ? 1 : 0)))
00269 {
00270
00271 return QVariant();
00272 }
00273
00274 KexiDB::Field *f = (m_fieldsExpanded && pos<m_fieldCount) ? m_fieldsExpanded->at(pos)->field : 0;
00275
00276
00277
00278
00279 if (f)
00280 {
00281 if ((f->isIntegerType()) || (!f && m_containsROWIDInfo && pos==m_fieldCount))
00282 {
00283 return QVariant((*m_res)[at()][pos].as(int()));
00284 }
00285 else if (f->isTextType())
00286 {
00287 return QVariant((*m_res)[at()][pos].c_str());
00288 }
00289 else if (f->isFPNumericType())
00290 {
00291 return QVariant((*m_res)[at()][pos].as(double()));
00292 }
00293 else if (f->typeGroup() == Field::BLOBGroup)
00294 {
00295
00296
00297 return QVariant(processBinaryData( (*m_res)[at()][pos] ));
00298 }
00299 }
00300 else
00301 {
00302
00303 switch((*m_res)[at()][pos].type())
00304 {
00305 case BOOLOID:
00306 return QVariant((*m_res)[at()][pos].c_str());
00307 case INT2OID:
00308 case INT4OID:
00309 case INT8OID:
00310 return QVariant((*m_res)[at()][pos].as(int()));
00311 case FLOAT4OID:
00312 case FLOAT8OID:
00313 case NUMERICOID:
00314 return QVariant((*m_res)[at()][pos].as(double()));
00315 case DATEOID:
00316 return QVariant((*m_res)[at()][pos].c_str());
00317 case TIMEOID:
00318 return QVariant((*m_res)[at()][pos].c_str());
00319 case TIMESTAMPOID:
00320 return QVariant((*m_res)[at()][pos].c_str());
00321 case BYTEAOID:
00322 return QVariant(processBinaryData( (*m_res)[at()][pos] ));
00323 case BPCHAROID:
00324 case VARCHAROID:
00325 case TEXTOID:
00326 return QVariant((*m_res)[at()][pos].c_str());
00327 default:
00328 return QVariant((*m_res)[at()][pos].c_str());
00329 }
00330
00331 }
00332
00333
00334 return QVariant((*m_res)[at()][pos].c_str());
00335
00336 }
00337
00338
00339
00340
00341 const char** pqxxSqlCursor::rowData() const
00342 {
00343
00344
00345 const char** row;
00346
00347 row = (const char**)malloc(m_res->columns()+1);
00348 row[m_res->columns()] = NULL;
00349 if (at() >= 0 && at() < m_res->size())
00350 {
00351 for(int i = 0; i < (int)m_res->columns(); i++)
00352 {
00353 row[i] = (char*)malloc(strlen((*m_res)[at()][i].c_str())+1);
00354 strcpy((char*)(*m_res)[at()][i].c_str(), row[i]);
00355
00356 }
00357 }
00358 else
00359 {
00360 KexiDBDrvWarn << "pqxxSqlCursor::recordData: m_at is invalid" << endl;
00361 }
00362 return row;
00363 }
00364
00365
00366
00367 void pqxxSqlCursor::storeCurrentRow(RowData &data) const
00368 {
00369
00370
00371 if (m_res->size()<=0)
00372 return;
00373
00374 const uint realCount = m_fieldCount + (m_containsROWIDInfo ? 1 : 0);
00375 data.resize(realCount);
00376
00377 for( uint i=0; i<realCount; i++)
00378 {
00379 data[i] = pValue(i);
00380 }
00381 }
00382
00383
00384
00385 void pqxxSqlCursor::drv_clearServerResult()
00386 {
00388 }
00389
00390
00391
00392
00393
00394 void pqxxSqlCursor::drv_appendCurrentRecordToBuffer()
00395 {
00396
00397 }
00398
00399
00400
00401
00402 void pqxxSqlCursor::drv_bufferMovePointerNext()
00403 {
00404
00405 }
00406
00407
00408
00409
00410 void pqxxSqlCursor::drv_bufferMovePointerPrev()
00411 {
00412
00413 }
00414
00415
00416
00417
00418 void pqxxSqlCursor::drv_bufferMovePointerTo(Q_LLONG to)
00419 {
00420 Q_UNUSED(to);
00421 }
00422
|