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)
00131 {
00132 int type = sqlite3_column_type(prepared_st_handle, i);
00133 if (type==SQLITE_NULL) {
00134 return QVariant();
00135 }
00136 else if (!f || 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->type()) {
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 SQLiteCursor::SQLiteCursor(Connection* conn, const QString& statement, uint options)
00201 : Cursor( conn, statement, options )
00202 , d( new SQLiteCursorData(conn) )
00203 {
00204 d->data = static_cast<SQLiteConnection*>(conn)->d->data;
00205 }
00206
00207 SQLiteCursor::SQLiteCursor(Connection* conn, QuerySchema& query, uint options )
00208 : Cursor( conn, query, options )
00209 , d( new SQLiteCursorData(conn) )
00210 {
00211 d->data = static_cast<SQLiteConnection*>(conn)->d->data;
00212 }
00213
00214 SQLiteCursor::~SQLiteCursor()
00215 {
00216 close();
00217 delete d;
00218 }
00219
00220 bool SQLiteCursor::drv_open()
00221 {
00222
00223
00224
00225
00226
00227 if(! d->data) {
00228
00229
00230
00231 kdWarning() << "SQLiteCursor::drv_open(): Database handle undefined." << endl;
00232 return false;
00233 }
00234
00235 #ifdef SQLITE2
00236 d->st = m_sql.local8Bit();
00237 d->res = sqlite_compile(
00238 d->data,
00239 d->st.data(),
00240 (const char**)&d->utail,
00241 &d->prepared_st_handle,
00242 &d->errmsg_p );
00243 #else //SQLITE3
00244 d->st = m_sql.utf8();
00245 d->res = sqlite3_prepare(
00246 d->data,
00247 d->st.data(),
00248 d->st.length(),
00249 &d->prepared_st_handle,
00250 0
00251 );
00252 #endif
00253 if (d->res!=SQLITE_OK) {
00254 d->storeResult();
00255 return false;
00256 }
00257
00258
00259
00260 if (isBuffered()) {
00261 d->records.resize(128);
00262 }
00263
00264 return true;
00265 }
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 bool SQLiteCursor::drv_close()
00280 {
00281 #ifdef SQLITE2
00282 d->res = sqlite_finalize( d->prepared_st_handle, &d->errmsg_p );
00283 #else //SQLITE3
00284 d->res = sqlite3_finalize( d->prepared_st_handle );
00285 #endif
00286 if (d->res!=SQLITE_OK) {
00287 d->storeResult();
00288 return false;
00289 }
00290 return true;
00291 }
00292
00293 void SQLiteCursor::drv_getNextRecord()
00294 {
00295 #ifdef SQLITE2
00296 static int _fieldCount;
00297 d->res = sqlite_step(
00298 d->prepared_st_handle,
00299 &_fieldCount,
00300 &d->curr_coldata,
00301 &d->curr_colname);
00302 #else //SQLITE3
00303 d->res = sqlite3_step( d->prepared_st_handle );
00304 #endif
00305 if (d->res == SQLITE_ROW) {
00306 m_result = FetchOK;
00307 #ifdef SQLITE2
00308 m_fieldCount = (uint)_fieldCount;
00309 #else
00310 m_fieldCount = sqlite3_data_count(d->prepared_st_handle);
00311
00312
00313
00314 #endif
00315
00316 } else {
00317
00318
00319
00320 if (d->res==SQLITE_DONE)
00321 m_result = FetchEnd;
00322 else
00323 m_result = FetchError;
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 }
00336
00337 void SQLiteCursor::drv_appendCurrentRecordToBuffer()
00338 {
00339
00340 if (!d->cols_pointers_mem_size)
00341 d->cols_pointers_mem_size = m_fieldCount * sizeof(char*);
00342 const char **record = (const char**)malloc(d->cols_pointers_mem_size);
00343 const char **src_col = d->curr_coldata;
00344 const char **dest_col = record;
00345 for (uint i=0; i<m_fieldCount; i++,src_col++,dest_col++) {
00346
00347
00348 *dest_col = *src_col ? strdup(*src_col) : 0;
00349 }
00350 d->records.insert(m_records_in_buf,record);
00351
00352 }
00353
00354 void SQLiteCursor::drv_bufferMovePointerNext()
00355 {
00356 d->curr_coldata++;
00357 }
00358
00359 void SQLiteCursor::drv_bufferMovePointerPrev()
00360 {
00361 d->curr_coldata--;
00362 }
00363
00364
00365
00366 void SQLiteCursor::drv_bufferMovePointerTo(Q_LLONG at)
00367 {
00368 d->curr_coldata = d->records.at(at);
00369 }
00370
00371 void SQLiteCursor::drv_clearBuffer()
00372 {
00373 if (d->cols_pointers_mem_size>0) {
00374 const uint records_in_buf = m_records_in_buf;
00375 const char ***r_ptr = d->records.data();
00376 for (uint i=0; i<records_in_buf; i++, r_ptr++) {
00377
00378 const char **field_data = *r_ptr;
00379
00380 for (uint col=0; col<m_fieldCount; col++, field_data++) {
00381 free((void*)*field_data);
00382 }
00383 free(*r_ptr);
00384 }
00385 }
00386
00387
00388 m_records_in_buf=0;
00389 d->cols_pointers_mem_size=0;
00390
00391 d->records.clear();
00392 }
00393
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 const char ** SQLiteCursor::rowData() const
00421 {
00422 return d->curr_coldata;
00423 }
00424
00425 void SQLiteCursor::storeCurrentRow(RowData &data) const
00426 {
00427 #ifdef SQLITE2
00428 const char **col = d->curr_coldata;
00429 #endif
00430
00431 data.resize(m_fieldCount);
00432 if (!m_fieldsExpanded) {
00433 for( uint i=0; i<m_fieldCount; i++ ) {
00434 #ifdef SQLITE2
00435 data[i] = QVariant( *col );
00436 col++;
00437 #else //SQLITE3
00438 data[i] = QString::fromUtf8( (const char*)sqlite3_column_text(d->prepared_st_handle, i) );
00439 #endif
00440 }
00441 return;
00442 }
00443
00444
00445 const uint maxCount = QMIN(m_fieldCount, m_fieldsExpanded->count());
00446
00447 for( uint i=0, j=0; i<m_fieldCount; i++, j++ ) {
00448
00449
00450 while (j < maxCount && !m_fieldsExpanded->at(j)->visible)
00451 j++;
00452 if (j >= (maxCount )) {
00453
00454 break;
00455 }
00456
00457 Field *f = (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);
00504 #endif
00505 }
00506 }
00507
00508 QVariant SQLiteCursor::value(uint i)
00509 {
00510
00511 if (i > (m_fieldCount-1))
00512 return QVariant();
00513
00514
00515 KexiDB::Field *f = (m_fieldsExpanded && i<m_fieldsExpanded->count())
00516 ? m_fieldsExpanded->at(i)->field : 0;
00517 #ifdef SQLITE2
00518
00519
00520 if (!f || f->isIntegerType())
00521 return QVariant( QCString(d->curr_coldata[i]).toInt() );
00522 else if (!f || f->isTextType())
00523 return QVariant( d->curr_coldata[i] );
00524 else if (f->isFPNumericType())
00525 return QVariant( QCString(d->curr_coldata[i]).toDouble() );
00526
00527 return QVariant( d->curr_coldata[i] );
00528 #else
00529 return d->getValue(f, i);
00530 #endif
00531 }
00532
00543 int SQLiteCursor::serverResult()
00544 {
00545 return d->res;
00546 }
00547
00548 QString SQLiteCursor::serverResultName()
00549 {
00550 #ifdef SQLITE2
00551 return QString::fromLatin1( sqlite_error_string(d->res) );
00552 #else //SQLITE3
00553 return QString::fromLatin1( d->result_name );
00554 #endif
00555 }
00556
00557 QString SQLiteCursor::serverErrorMsg()
00558 {
00559 return d->errmsg;
00560 }
00561
00562 void SQLiteCursor::drv_clearServerResult()
00563 {
00564 d->res = SQLITE_OK;
00565 d->errmsg_p = 0;
00566 }
00567