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<QMIN(m_fieldsExpanded->count(), m_fieldCount))
00275 ? m_fieldsExpanded->at(pos)->field : 0;
00276
00277
00278
00279
00280 if (f)
00281 {
00282 if ((f->isIntegerType()) || (!f && m_containsROWIDInfo && pos==m_fieldCount))
00283 {
00284 return QVariant((*m_res)[at()][pos].as(int()));
00285 }
00286 else if (f->isTextType())
00287 {
00288 return QVariant((*m_res)[at()][pos].c_str());
00289 }
00290 else if (f->isFPNumericType())
00291 {
00292 return QVariant((*m_res)[at()][pos].as(double()));
00293 }
00294 else if (f->type() == KexiDB::Field::Boolean)
00295 {
00296 return QVariant((*m_res)[at()][pos].as(bool()));
00297 }
00298 else if (f->typeGroup() == Field::BLOBGroup)
00299 {
00300
00301
00302 return QVariant(processBinaryData( (*m_res)[at()][pos] ));
00303 }
00304 }
00305 else
00306 {
00307
00308 switch((*m_res)[at()][pos].type())
00309 {
00310 case BOOLOID:
00311 return QVariant((*m_res)[at()][pos].as(bool()));
00312 case INT2OID:
00313 case INT4OID:
00314 case INT8OID:
00315 return QVariant((*m_res)[at()][pos].as(int()));
00316 case FLOAT4OID:
00317 case FLOAT8OID:
00318 case NUMERICOID:
00319 return QVariant((*m_res)[at()][pos].as(double()));
00320 case DATEOID:
00321 return QVariant((*m_res)[at()][pos].c_str());
00322 case TIMEOID:
00323 return QVariant((*m_res)[at()][pos].c_str());
00324 case TIMESTAMPOID:
00325 return QVariant((*m_res)[at()][pos].c_str());
00326 case BYTEAOID:
00327 return QVariant(processBinaryData( (*m_res)[at()][pos] ));
00328 case BPCHAROID:
00329 case VARCHAROID:
00330 case TEXTOID:
00331 return QVariant((*m_res)[at()][pos].c_str());
00332 default:
00333 return QVariant((*m_res)[at()][pos].c_str());
00334 }
00335
00336 }
00337
00338
00339 return QVariant((*m_res)[at()][pos].c_str());
00340
00341 }
00342
00343
00344
00345
00346 const char** pqxxSqlCursor::rowData() const
00347 {
00348
00349
00350 const char** row;
00351
00352 row = (const char**)malloc(m_res->columns()+1);
00353 row[m_res->columns()] = NULL;
00354 if (at() >= 0 && at() < m_res->size())
00355 {
00356 for(int i = 0; i < (int)m_res->columns(); i++)
00357 {
00358 row[i] = (char*)malloc(strlen((*m_res)[at()][i].c_str())+1);
00359 strcpy((char*)(*m_res)[at()][i].c_str(), row[i]);
00360
00361 }
00362 }
00363 else
00364 {
00365 KexiDBDrvWarn << "pqxxSqlCursor::recordData: m_at is invalid" << endl;
00366 }
00367 return row;
00368 }
00369
00370
00371
00372 void pqxxSqlCursor::storeCurrentRow(RowData &data) const
00373 {
00374
00375
00376 if (m_res->size()<=0)
00377 return;
00378
00379 const uint realCount = m_fieldCount + (m_containsROWIDInfo ? 1 : 0);
00380 data.resize(realCount);
00381
00382 for( uint i=0; i<realCount; i++)
00383 {
00384 data[i] = pValue(i);
00385 }
00386 }
00387
00388
00389
00390 void pqxxSqlCursor::drv_clearServerResult()
00391 {
00393 }
00394
00395
00396
00397
00398
00399 void pqxxSqlCursor::drv_appendCurrentRecordToBuffer()
00400 {
00401
00402 }
00403
00404
00405
00406
00407 void pqxxSqlCursor::drv_bufferMovePointerNext()
00408 {
00409
00410 }
00411
00412
00413
00414
00415 void pqxxSqlCursor::drv_bufferMovePointerPrev()
00416 {
00417
00418 }
00419
00420
00421
00422
00423 void pqxxSqlCursor::drv_bufferMovePointerTo(Q_LLONG to)
00424 {
00425 Q_UNUSED(to);
00426 }
00427
|