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