00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "sqlitecursor.h"
00021
00022 #include "sqliteconnection.h"
00023 #include "sqliteconnection_p.h"
00024
00025 #include <kexidb/error.h>
00026 #include <kexidb/driver.h>
00027 #include <kexiutils/utils.h>
00028
00029 #include <assert.h>
00030 #include <string.h>
00031 #include <stdlib.h>
00032
00033 #include <kdebug.h>
00034 #include <klocale.h>
00035
00036 #include <qptrvector.h>
00037 #include <qdatetime.h>
00038
00039 using namespace KexiDB;
00040
00042 static bool sqliteStringToBool(const QString& s)
00043 {
00044 return s.lower()=="yes" || (s.lower()!="no" && s!="0");
00045 }
00046
00047
00048
00049 class KexiDB::SQLiteCursorData : public SQLiteConnectionInternal
00050 {
00051 public:
00052 SQLiteCursorData(Connection* conn)
00053 :
00054 SQLiteConnectionInternal(conn)
00055
00056
00057
00058 , curr_coldata(0)
00059 , curr_colname(0)
00060 , cols_pointers_mem_size(0)
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 {
00071 data_owned = false;
00072 }
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 QCString st;
00088
00089
00090 #ifdef SQLITE2
00091 sqlite_vm *prepared_st_handle;
00092 #else //SQLITE3
00093 sqlite3_stmt *prepared_st_handle;
00094 #endif
00095
00096 char *utail;
00097
00098
00099
00100
00101
00102
00103 const char **curr_coldata;
00104 const char **curr_colname;
00105
00106 int next_cols;
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 uint cols_pointers_mem_size;
00124 QPtrVector<const char*> records;
00125
00126
00127
00128
00129 #ifdef SQLITE3
00130 inline QVariant getValue(Field *f, int i, bool ROWID)
00131 {
00132 int type = sqlite3_column_type(prepared_st_handle, i);
00133 if (type==SQLITE_NULL) {
00134 return QVariant();
00135 }
00136 else if ((!f && !ROWID) || type==SQLITE_TEXT) {
00137
00138 #define GET_sqlite3_column_text QString::fromUtf8( (const char*)sqlite3_column_text(prepared_st_handle, i) )
00139 if (!f || f->isTextType())
00140 return GET_sqlite3_column_text;
00141 else {
00142 switch (f->type()) {
00143 case Field::Date:
00144 return QDate::fromString( GET_sqlite3_column_text, Qt::ISODate );
00145 case Field::Time:
00146
00147 return KexiUtils::stringToHackedQTime(GET_sqlite3_column_text);
00148 case Field::DateTime: {
00149 QString tmp( GET_sqlite3_column_text );
00150 tmp[10] = 'T';
00151 return QDateTime::fromString( tmp, Qt::ISODate );
00152 }
00153 case Field::Boolean:
00154 return QVariant(sqliteStringToBool(GET_sqlite3_column_text), 1);
00155 default:
00156 return QVariant();
00157 }
00158 }
00159 }
00160 else if (type==SQLITE_INTEGER) {
00161 switch (f ? f->type() : Field::Integer ) {
00162 case Field::Byte:
00163 case Field::ShortInteger:
00164 case Field::Integer:
00165 return QVariant( sqlite3_column_int(prepared_st_handle, i) );
00166 case Field::BigInteger:
00167 return QVariant( (Q_LLONG)sqlite3_column_int64(prepared_st_handle, i) );
00168 case Field::Boolean:
00169 return QVariant( sqlite3_column_int(prepared_st_handle, i)!=0, 1 );
00170 default:;
00171 }
00172 if (f->isFPNumericType())
00173 return QVariant( (double)sqlite3_column_int(prepared_st_handle, i) );
00174 else
00175 return QVariant();
00176 }
00177 else if (type==SQLITE_FLOAT) {
00178 if (f && f->isFPNumericType())
00179 return QVariant( sqlite3_column_double(prepared_st_handle, i) );
00180 else if (!f || f->isIntegerType())
00181 return QVariant( (double)sqlite3_column_double(prepared_st_handle, i) );
00182 else
00183 return QVariant();
00184 }
00185 else if (type==SQLITE_BLOB) {
00186 if (f && f->type()==Field::BLOB) {
00187 QByteArray ba;
00189 ba.duplicate((const char*)sqlite3_column_blob(prepared_st_handle, i),
00190 sqlite3_column_bytes(prepared_st_handle, i));
00191 return ba;
00192 } else
00193 return QVariant();
00194 }
00195 return QVariant();
00196 }
00197 #endif //SQLITE3
00198 };
00199
00200
00201
00202 SQLiteCursor::SQLiteCursor(Connection* conn, const QString& statement, uint options)
00203 : Cursor( conn, statement, options )
00204 , d( new SQLiteCursorData(conn) )
00205 {
00206 d->data = static_cast<SQLiteConnection*>(conn)->d->data;
00207 }
00208
00209 SQLiteCursor::SQLiteCursor(Connection* conn, QuerySchema& query, uint options )
00210 : Cursor( conn, query, options )
00211 , d( new SQLiteCursorData(conn) )
00212 {
00213 d->data = static_cast<SQLiteConnection*>(conn)->d->data;
00214 }
00215
00216 SQLiteCursor::~SQLiteCursor()
00217 {
00218 close();
00219 delete d;
00220 }
00221
00222 bool SQLiteCursor::drv_open()
00223 {
00224
00225
00226
00227
00228
00229 if(! d->data) {
00230
00231
00232
00233 kdWarning() << "SQLiteCursor::drv_open(): Database handle undefined." << endl;
00234 return false;
00235 }
00236
00237 #ifdef SQLITE2
00238 d->st = m_sql.local8Bit();
00239 d->res = sqlite_compile(
00240 d->data,
00241 d->st.data(),
00242 (const char**)&d->utail,
00243 &d->prepared_st_handle,
00244 &d->errmsg_p );
00245 #else //SQLITE3
00246 d->st = m_sql.utf8();
00247 d->res = sqlite3_prepare(
00248 d->data,
00249 d->st.data(),
00250 d->st.length(),
00251 &d->prepared_st_handle,
00252 0
00253 );
00254 #endif
00255 if (d->res!=SQLITE_OK) {
00256 d->storeResult();
00257 return false;
00258 }
00259
00260
00261
00262 if (isBuffered()) {
00263 d->records.resize(128);
00264 }
00265
00266 return true;
00267 }
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 bool SQLiteCursor::drv_close()
00282 {
00283 #ifdef SQLITE2
00284 d->res = sqlite_finalize( d->prepared_st_handle, &d->errmsg_p );
00285 #else //SQLITE3
00286 d->res = sqlite3_finalize( d->prepared_st_handle );
00287 #endif
00288 if (d->res!=SQLITE_OK) {
00289 d->storeResult();
00290 return false;
00291 }
00292 return true;
00293 }
00294
00295 void SQLiteCursor::drv_getNextRecord()
00296 {
00297 #ifdef SQLITE2
00298 static int _fieldCount;
00299 d->res = sqlite_step(
00300 d->prepared_st_handle,
00301 &_fieldCount,
00302 &d->curr_coldata,
00303 &d->curr_colname);
00304 #else //SQLITE3
00305 d->res = sqlite3_step( d->prepared_st_handle );
00306 #endif
00307 if (d->res == SQLITE_ROW) {
00308 m_result = FetchOK;
00309 #ifdef SQLITE2
00310 m_fieldCount = (uint)_fieldCount;
00311 #else
00312 m_fieldCount = sqlite3_data_count(d->prepared_st_handle);
00313
00314
00315
00316 #endif
00317 m_fieldCount -= (m_containsROWIDInfo ? 1 : 0);
00318 } else {
00319
00320
00321
00322 if (d->res==SQLITE_DONE)
00323 m_result = FetchEnd;
00324 else
00325 m_result = FetchError;
00326 }
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 }
00338
00339 void SQLiteCursor::drv_appendCurrentRecordToBuffer()
00340 {
00341
00342 if (!d->cols_pointers_mem_size)
00343 d->cols_pointers_mem_size = m_fieldCount * sizeof(char*);
00344 const char **record = (const char**)malloc(d->cols_pointers_mem_size);
00345 const char **src_col = d->curr_coldata;
00346 const char **dest_col = record;
00347 for (uint i=0; i<m_fieldCount; i++,src_col++,dest_col++) {
00348
00349
00350 *dest_col = *src_col ? strdup(*src_col) : 0;
00351 }
00352 d->records.insert(m_records_in_buf,record);
00353
00354 }
00355
00356 void SQLiteCursor::drv_bufferMovePointerNext()
00357 {
00358 d->curr_coldata++;
00359 }
00360
00361 void SQLiteCursor::drv_bufferMovePointerPrev()
00362 {
00363 d->curr_coldata--;
00364 }
00365
00366
00367
00368 void SQLiteCursor::drv_bufferMovePointerTo(Q_LLONG at)
00369 {
00370 d->curr_coldata = d->records.at(at);
00371 }
00372
00373 void SQLiteCursor::drv_clearBuffer()
00374 {
00375 if (d->cols_pointers_mem_size>0) {
00376 const uint records_in_buf = m_records_in_buf;
00377 const char ***r_ptr = d->records.data();
00378 for (uint i=0; i<records_in_buf; i++, r_ptr++) {
00379
00380 const char **field_data = *r_ptr;
00381
00382 for (uint col=0; col<m_fieldCount; col++, field_data++) {
00383 free((void*)*field_data);
00384 }
00385 free(*r_ptr);
00386 }
00387 }
00388
00389
00390 m_records_in_buf=0;
00391 d->cols_pointers_mem_size=0;
00392
00393 d->records.clear();
00394 }
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422 const char ** SQLiteCursor::rowData() const
00423 {
00424 return d->curr_coldata;
00425 }
00426
00427 void SQLiteCursor::storeCurrentRow(RowData &data) const
00428 {
00429 #ifdef SQLITE2
00430 const char **col = d->curr_coldata;
00431 #endif
00432 const uint realCount = m_fieldCount + (m_containsROWIDInfo ? 1 : 0);
00433 data.resize(realCount);
00434 if (!m_fieldsExpanded) {
00435 for( uint i=0; i<realCount; i++ ) {
00436 #ifdef SQLITE2
00437 data[i] = QVariant( *col );
00438 col++;
00439 #else //SQLITE3
00440 data[i] = QString::fromUtf8( (const char*)sqlite3_column_text(d->prepared_st_handle, i) );
00441 #endif
00442 }
00443 return;
00444 }
00445
00446 const uint fieldsExpandedCount = m_fieldsExpanded->count();
00447 for( uint i=0, j=0; i<realCount; i++, j++ ) {
00448
00449
00450 while (j < fieldsExpandedCount && !m_fieldsExpanded->at(j)->visible)
00451 j++;
00452 if (j >= (fieldsExpandedCount+(m_containsROWIDInfo ? 1 : 0))) {
00453
00454 break;
00455 }
00456
00457 Field *f = (m_containsROWIDInfo && i>=m_fieldCount) ? 0 : m_fieldsExpanded->at(j)->field;
00458
00459
00460 #ifdef SQLITE2
00461 if (!*col)
00462 data[i] = QVariant();
00463 else if (f && f->isTextType())
00464 # ifdef SQLITE_UTF8
00465 data[i] = QString::fromUtf8( *col );
00466 # else
00467 data[i] = QVariant( *col );
00468 # endif
00469 else if (f && f->isFPNumericType())
00470 data[i] = QVariant( QCString(*col).toDouble() );
00471 else {
00472 switch (f ? f->type() : Field::Integer) {
00473
00474 case Field::Byte:
00475 case Field::ShortInteger:
00476 case Field::Integer:
00477 data[i] = QVariant( QCString(*col).toInt() );
00478 case Field::BigInteger:
00479 data[i] = QVariant( QString::fromLatin1(*col).toLongLong() );
00480 case Field::Boolean:
00481 data[i] = QVariant( sqliteStringToBool(QString::fromLatin1(*col)), 1 );
00482 break;
00483 case Field::Date:
00484 data[i] = QDate::fromString( QString::fromLatin1(*col), Qt::ISODate );
00485 break;
00486 case Field::Time:
00487
00488 data[i] = KexiUtils::stringToHackedQTime(QString::fromLatin1(*col));
00489 break;
00490 case Field::DateTime: {
00491 QString tmp( QString::fromLatin1(*col) );
00492 tmp[10] = 'T';
00493 data[i] = QDateTime::fromString( tmp, Qt::ISODate );
00494 break;
00495 }
00496 default:
00497 data[i] = QVariant( *col );
00498 }
00499 }
00500
00501 col++;
00502 #else //SQLITE3
00503 data[i] = d->getValue(f, i, !f );
00504 #endif
00505 }
00506 }
00507
00508 QVariant SQLiteCursor::value(uint i)
00509 {
00510 if (i > (m_fieldCount-1+(m_containsROWIDInfo?1:0)))
00511 return QVariant();
00512
00513
00514 KexiDB::Field *f = (m_fieldsExpanded && i<m_fieldsExpanded->count())
00515 ? m_fieldsExpanded->at(i)->field : 0;
00516 #ifdef SQLITE2
00517
00518 if (i==m_fieldCount || f && f->isIntegerType())
00519 return QVariant( QCString(d->curr_coldata[i]).toInt() );
00520 if (!f || f->isTextType())
00521 return QVariant( d->curr_coldata[i] );
00522 else if (f->isFPNumericType())
00523 return QVariant( QCString(d->curr_coldata[i]).toDouble() );
00524
00525 return QVariant( d->curr_coldata[i] );
00526 #else
00527 return d->getValue(f, i, i==m_fieldCount);
00528 #endif
00529 }
00530
00541 int SQLiteCursor::serverResult()
00542 {
00543 return d->res;
00544 }
00545
00546 QString SQLiteCursor::serverResultName()
00547 {
00548 #ifdef SQLITE2
00549 return QString::fromLatin1( sqlite_error_string(d->res) );
00550 #else //SQLITE3
00551 return QString::fromLatin1( d->result_name );
00552 #endif
00553 }
00554
00555 QString SQLiteCursor::serverErrorMsg()
00556 {
00557 return d->errmsg;
00558 }
00559
00560 void SQLiteCursor::drv_clearServerResult()
00561 {
00562 d->res = SQLITE_OK;
00563 d->errmsg_p = 0;
00564 }
00565