00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <kexidb/cursor.h>
00021
00022 #include <kexidb/driver.h>
00023 #include <kexidb/driver_p.h>
00024 #include <kexidb/error.h>
00025 #include <kexidb/roweditbuffer.h>
00026 #include <kexiutils/utils.h>
00027
00028 #include <kdebug.h>
00029 #include <klocale.h>
00030
00031 #include <assert.h>
00032 #include <stdlib.h>
00033
00034 using namespace KexiDB;
00035
00036 #ifdef KEXI_DEBUG_GUI
00037
00038 #endif
00039
00040 Cursor::Cursor(Connection* conn, const QString& statement, uint options)
00041 : QObject()
00042 , m_conn(conn)
00043 , m_query(0)
00044 , m_rawStatement(statement)
00045 , m_options(options)
00046 {
00047 #ifdef KEXI_DEBUG_GUI
00048 KexiUtils::addKexiDBDebug(QString("Create cursor: ")+statement);
00049 #endif
00050 init();
00051 }
00052
00053 Cursor::Cursor(Connection* conn, QuerySchema& query, uint options )
00054 : QObject()
00055 , m_conn(conn)
00056 , m_query(&query)
00057 , m_options(options)
00058 {
00059 #ifdef KEXI_DEBUG_GUI
00060 KexiUtils::addKexiDBDebug(QString("Create cursor for query \"%1\": ").arg(query.name())+query.debugString());
00061 #endif
00062 init();
00063 }
00064
00065 void Cursor::init()
00066 {
00067 assert(m_conn);
00068 m_conn->m_cursors.insert(this,this);
00069 m_opened = false;
00070
00071
00072
00073 m_atLast = false;
00074 m_afterLast = false;
00075 m_readAhead = false;
00076 m_at = 0;
00077
00078
00079
00080
00081
00082 m_records_in_buf = 0;
00083 m_buffering_completed = false;
00084 m_at_buffer = false;
00085 m_result = -1;
00086
00087 m_containsROWIDInfo = (m_query && m_query->masterTable())
00088 && m_conn->driver()->beh->ROW_ID_FIELD_RETURNS_LAST_AUTOINCREMENTED_VALUE == false;
00089
00090 if (m_query) {
00091
00092 m_fieldsExpanded = new QueryColumnInfo::Vector();
00093 *m_fieldsExpanded = m_query->fieldsExpanded(
00094 m_containsROWIDInfo ? QuerySchema::WithInternalFieldsAndRowID : QuerySchema::WithInternalFields);
00095 m_logicalFieldCount = m_fieldsExpanded->count()
00096 - m_query->internalFields().count() - (m_containsROWIDInfo?1:0);
00097 m_fieldCount = m_fieldsExpanded->count();
00098 } else {
00099 m_fieldsExpanded = 0;
00100 m_logicalFieldCount = 0;
00101 m_fieldCount = 0;
00102 }
00103 m_orderByColumnList = 0;
00104 m_queryParameters = 0;
00105 }
00106
00107 Cursor::~Cursor()
00108 {
00109 #ifdef KEXI_DEBUG_GUI
00110 if (m_query)
00111 KexiUtils::addKexiDBDebug(QString("~ Delete cursor for query"));
00112 else
00113 KexiUtils::addKexiDBDebug(QString("~ Delete cursor: ")+m_rawStatement);
00114 #endif
00115
00116
00117
00118
00119
00120
00121 if (!m_conn->m_destructor_started)
00122 m_conn->m_cursors.take(this);
00123 else {
00124 KexiDBDbg << "Cursor::~Cursor() can be destroyed with Conenction::deleteCursor(), not with delete operator !"<< endl;
00125 exit(1);
00126 }
00127 delete m_fieldsExpanded;
00128 delete m_queryParameters;
00129 }
00130
00131 bool Cursor::open()
00132 {
00133 if (m_opened) {
00134 if (!close())
00135 return false;
00136 }
00137 if (!m_rawStatement.isEmpty())
00138 m_conn->m_sql = m_rawStatement;
00139 else {
00140 if (!m_query) {
00141 KexiDBDbg << "Cursor::open(): no query statement (or schema) defined!" << endl;
00142 setError(ERR_SQL_EXECUTION_ERROR, i18n("No query statement or schema defined."));
00143 return false;
00144 }
00145 Connection::SelectStatementOptions options;
00146 options.alsoRetrieveROWID = m_containsROWIDInfo;
00147 m_conn->m_sql = m_queryParameters
00148 ? m_conn->selectStatement( *m_query, *m_queryParameters, options )
00149 : m_conn->selectStatement( *m_query, options );
00150 if (m_conn->m_sql.isEmpty()) {
00151 KexiDBDbg << "Cursor::open(): empty statement!" << endl;
00152 setError(ERR_SQL_EXECUTION_ERROR, i18n("Query statement is empty."));
00153 return false;
00154 }
00155 }
00156 m_sql = m_conn->m_sql;
00157 m_opened = drv_open();
00158
00159 m_afterLast = false;
00160 m_at = 0;
00161 if (!m_opened) {
00162 setError(ERR_SQL_EXECUTION_ERROR, i18n("Error opening database cursor."));
00163 return false;
00164 }
00165 m_validRecord = false;
00166
00167
00168
00169 if (m_conn->driver()->beh->_1ST_ROW_READ_AHEAD_REQUIRED_TO_KNOW_IF_THE_RESULT_IS_EMPTY) {
00170
00171 m_readAhead = getNextRecord();
00172
00173 }
00174 m_at = 0;
00175 return !error();
00176 }
00177
00178 bool Cursor::close()
00179 {
00180 if (!m_opened)
00181 return true;
00182 bool ret = drv_close();
00183
00184 clearBuffer();
00185
00186 m_opened = false;
00187
00188 m_afterLast = false;
00189 m_readAhead = false;
00190 m_fieldCount = 0;
00191 m_logicalFieldCount = 0;
00192 m_at = -1;
00193
00194
00195 return ret;
00196 }
00197
00198 bool Cursor::reopen()
00199 {
00200 if (!m_opened)
00201 return open();
00202 return close() && open();
00203 }
00204
00205 bool Cursor::moveFirst()
00206 {
00207 if (!m_opened)
00208 return false;
00209
00210 if (!m_readAhead) {
00211 if (m_options & Buffered) {
00212 if (m_records_in_buf==0 && m_buffering_completed) {
00213
00214 m_afterLast = true;
00215 m_at = 0;
00216 return false;
00217 }
00218 if (m_records_in_buf>0) {
00219
00220 m_at_buffer = false;
00221 m_at = 0;
00222
00223
00224 m_afterLast = !getNextRecord();
00225 return !m_afterLast;
00226 }
00227 }
00228 if (m_afterLast && m_at==0)
00229 return false;
00230 if (!reopen())
00231 return false;
00232 if (m_afterLast)
00233 return false;
00234 }
00235 else {
00236
00237 m_at = 1;
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248 m_afterLast = false;
00249 m_readAhead = false;
00250
00251 return m_validRecord;
00252 }
00253
00254 bool Cursor::moveLast()
00255 {
00256 if (!m_opened)
00257 return false;
00258 if (m_afterLast || m_atLast) {
00259 return m_validRecord;
00260 }
00261 if (!getNextRecord()) {
00262
00263 m_afterLast = true;
00264 m_validRecord = false;
00265 m_atLast = false;
00266 return false;
00267 }
00268 while (getNextRecord())
00269 ;
00270
00271 m_afterLast = false;
00272
00273 m_atLast = true;
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 return true;
00290 }
00291
00292 bool Cursor::moveNext()
00293 {
00294 if (!m_opened || m_afterLast)
00295 return false;
00296 if (getNextRecord()) {
00297
00298 return true;
00299 }
00300 return false;
00301 }
00302
00303 bool Cursor::movePrev()
00304 {
00305 if (!m_opened || !(m_options & Buffered))
00306 return false;
00307
00308
00309
00310 if (m_afterLast && (m_records_in_buf>0)) {
00311 drv_bufferMovePointerTo(m_records_in_buf-1);
00312 m_at=m_records_in_buf;
00313 m_at_buffer = true;
00314 m_validRecord=true;
00315 m_afterLast=false;
00316 return true;
00317 }
00318
00319 if ((m_at <= 1) || (m_records_in_buf <= 1)) {
00320 m_at=0;
00321 m_at_buffer = false;
00322 m_validRecord=false;
00323 return false;
00324 }
00325
00326 m_at--;
00327 if (m_at_buffer) {
00328 drv_bufferMovePointerPrev();
00329 } else {
00330
00331 drv_bufferMovePointerTo(m_at-1);
00332 m_at_buffer = true;
00333 }
00334 m_validRecord=true;
00335 m_afterLast=false;
00336 return true;
00337 }
00338
00339 bool Cursor::eof() const
00340 {
00341 return m_afterLast;
00342 }
00343
00344 bool Cursor::bof() const
00345 {
00346 return m_at==0;
00347 }
00348
00349 Q_LLONG Cursor::at() const
00350 {
00351 if (m_readAhead)
00352 return 0;
00353 return m_at - 1;
00354 }
00355
00356 bool Cursor::isBuffered() const
00357 {
00358 return m_options & Buffered;
00359 }
00360
00361 void Cursor::setBuffered(bool buffered)
00362 {
00363 if (!m_opened)
00364 return;
00365 if (isBuffered()==buffered)
00366 return;
00367 m_options ^= Buffered;
00368 }
00369
00370 void Cursor::clearBuffer()
00371 {
00372 if ( !isBuffered() || m_fieldCount==0)
00373 return;
00374
00375 drv_clearBuffer();
00376
00377 m_records_in_buf=0;
00378 m_at_buffer=false;
00379 }
00380
00381 bool Cursor::getNextRecord()
00382 {
00383 m_result = -1;
00384
00385 if ((m_options & Buffered)) {
00386
00387
00388 if (m_at < m_records_in_buf) {
00390
00391 if (m_at_buffer) {
00392 drv_bufferMovePointerNext();
00393 } else {
00394
00395 drv_bufferMovePointerTo(m_at-1+1);
00396
00397 m_at_buffer = true;
00398 }
00399 }
00400 else {
00401 if (!m_readAhead) {
00402 if (!m_buffering_completed) {
00403
00404
00405
00406 drv_getNextRecord();
00407 }
00408 if ((FetchResult) m_result != FetchOK) {
00409 m_buffering_completed = true;
00410
00411 m_validRecord = false;
00412 m_afterLast = true;
00413
00414 m_at = -1;
00415 if ((FetchResult) m_result == FetchEnd) {
00416 return false;
00417 }
00418 setError(ERR_CURSOR_RECORD_FETCHING, i18n("Cannot fetch next record."));
00419 return false;
00420 }
00421
00422 drv_appendCurrentRecordToBuffer();
00423 m_records_in_buf++;
00424 }
00425 else
00426 m_readAhead = false;
00427 }
00428 }
00429 else {
00430 if (!m_readAhead) {
00431
00432 drv_getNextRecord();
00433 if ((FetchResult)m_result != FetchOK) {
00434
00435 m_validRecord = false;
00436 m_afterLast = true;
00437 m_at = -1;
00438 if ((FetchResult) m_result == FetchEnd) {
00439 return false;
00440 }
00441 setError(ERR_CURSOR_RECORD_FETCHING, i18n("Cannot fetch next record."));
00442 return false;
00443 }
00444 }
00445 else
00446 m_readAhead = false;
00447 }
00448
00449 m_at++;
00450
00451
00452
00453
00454
00455
00456
00457 m_validRecord = true;
00458 return true;
00459 }
00460
00461 bool Cursor::updateRow(RowData& data, RowEditBuffer& buf, bool useROWID)
00462 {
00464 clearError();
00465 if (!m_query)
00466 return false;
00467 return m_conn->updateRow(*m_query, data, buf, useROWID);
00468 }
00469
00470 bool Cursor::insertRow(RowData& data, RowEditBuffer& buf, bool getROWID)
00471 {
00473 clearError();
00474 if (!m_query)
00475 return false;
00476 return m_conn->insertRow(*m_query, data, buf, getROWID);
00477 }
00478
00479 bool Cursor::deleteRow(RowData& data, bool useROWID)
00480 {
00482 clearError();
00483 if (!m_query)
00484 return false;
00485 return m_conn->deleteRow(*m_query, data, useROWID);
00486 }
00487
00488 bool Cursor::deleteAllRows()
00489 {
00491 clearError();
00492 if (!m_query)
00493 return false;
00494 return m_conn->deleteAllRows(*m_query);
00495 }
00496
00497 QString Cursor::debugString() const
00498 {
00499 QString dbg = "CURSOR( ";
00500 if (!m_query) {
00501 dbg += "RAW STATEMENT: '";
00502 dbg += m_rawStatement;
00503 dbg += "'\n";
00504 }
00505 else {
00506 dbg += "QuerySchema: '";
00507 dbg += m_conn->selectStatement( *m_query );
00508 dbg += "'\n";
00509 }
00510 if (isOpened())
00511 dbg += " OPENED";
00512 else
00513 dbg += " NOT_OPENED";
00514 if (isBuffered())
00515 dbg += " BUFFERED";
00516 else
00517 dbg += " NOT_BUFFERED";
00518 dbg += " AT=";
00519 dbg += QString::number((unsigned long)at());
00520 dbg += " )";
00521 return dbg;
00522 }
00523
00524 void Cursor::debug() const
00525 {
00526 KexiDBDbg << debugString() << endl;
00527 }
00528
00529 void Cursor::setOrderByColumnList(const QStringList& columnNames)
00530 {
00531 Q_UNUSED(columnNames);
00533
00534
00535
00536
00537
00538 }
00539
00541 void Cursor::setOrderByColumnList(const QString& column1, const QString& column2,
00542 const QString& column3, const QString& column4, const QString& column5)
00543 {
00544 Q_UNUSED(column1);
00545 Q_UNUSED(column2);
00546 Q_UNUSED(column3);
00547 Q_UNUSED(column4);
00548 Q_UNUSED(column5);
00551 }
00552
00553 QueryColumnInfo::Vector Cursor::orderByColumnList() const
00554 {
00555 return m_orderByColumnList ? *m_orderByColumnList: QueryColumnInfo::Vector();
00556 }
00557
00558 QValueList<QVariant> Cursor::queryParameters() const
00559 {
00560 return m_queryParameters ? *m_queryParameters : QValueList<QVariant>();
00561 }
00562
00563 void Cursor::setQueryParameters(const QValueList<QVariant>& params)
00564 {
00565 if (!m_queryParameters)
00566 m_queryParameters = new QValueList<QVariant>(params);
00567 else
00568 *m_queryParameters = params;
00569 }
00570
00571 #include "cursor.moc"