20#include "sqlitecursor.h"
22#include "sqliteconnection.h"
23#include "sqliteconnection_p.h"
25#include <kexidb/error.h>
26#include <kexidb/driver.h>
27#include <kexiutils/utils.h>
36#include <tqptrvector.h>
37#include <tqdatetime.h>
42static bool sqliteStringToBool(
const TQString& s)
44 return s.lower()==
"yes" || (s.lower()!=
"no" && s!=
"0");
49class KexiDB::SQLiteCursorData :
public SQLiteConnectionInternal
52 SQLiteCursorData(Connection* conn)
54 SQLiteConnectionInternal(conn)
60 , cols_pointers_mem_size(0)
91 sqlite_vm *prepared_st_handle;
93 sqlite3_stmt *prepared_st_handle;
103 const char **curr_coldata;
104 const char **curr_colname;
123 uint cols_pointers_mem_size;
124 TQPtrVector<const char*> records;
130 inline TQVariant getValue(Field *f,
int i)
132 int type = sqlite3_column_type(prepared_st_handle, i);
133 if (type==SQLITE_NULL) {
136 else if (!f || type==SQLITE_TEXT) {
138#define GET_sqlite3_column_text TQString::fromUtf8( (const char*)sqlite3_column_text(prepared_st_handle, i) )
140 return GET_sqlite3_column_text;
144 return TQDate::fromString( GET_sqlite3_column_text, TQt::ISODate );
148 case Field::DateTime: {
149 TQString tmp( GET_sqlite3_column_text );
151 return TQDateTime::fromString( tmp, TQt::ISODate );
154 return TQVariant(sqliteStringToBool(GET_sqlite3_column_text));
160 else if (type==SQLITE_INTEGER) {
165 return TQVariant( sqlite3_column_int(prepared_st_handle, i) );
167 return TQVariant( (TQ_LLONG)sqlite3_column_int64(prepared_st_handle, i) );
169 return TQVariant( sqlite3_column_int(prepared_st_handle, i)!=0 );
173 return TQVariant( (
double)sqlite3_column_int(prepared_st_handle, i) );
177 else if (type==SQLITE_FLOAT) {
179 return TQVariant( sqlite3_column_double(prepared_st_handle, i) );
181 return TQVariant( (
double)sqlite3_column_double(prepared_st_handle, i) );
185 else if (type==SQLITE_BLOB) {
189 ba.duplicate((
const char*)sqlite3_column_blob(prepared_st_handle, i),
190 sqlite3_column_bytes(prepared_st_handle, i));
200SQLiteCursor::SQLiteCursor(
Connection* conn,
const TQString& statement, uint options)
201 :
Cursor( conn, statement, options )
202 , d( new SQLiteCursorData(conn) )
208 :
Cursor( conn, query, options )
209 , d( new SQLiteCursorData(conn) )
214SQLiteCursor::~SQLiteCursor()
220bool SQLiteCursor::drv_open()
231 kdWarning() <<
"SQLiteCursor::drv_open(): Database handle undefined." << endl;
236 d->st =
m_sql.local8Bit();
237 d->res = sqlite_compile(
240 (
const char**)&d->utail,
241 &d->prepared_st_handle,
244 d->st =
m_sql.utf8();
245 d->res = sqlite3_prepare(
249 &d->prepared_st_handle,
253 if (d->res!=SQLITE_OK) {
261 d->records.resize(128);
279bool SQLiteCursor::drv_close()
282 d->res = sqlite_finalize( d->prepared_st_handle, &d->errmsg_p );
284 d->res = sqlite3_finalize( d->prepared_st_handle );
286 if (d->res!=SQLITE_OK) {
293void SQLiteCursor::drv_getNextRecord()
296 static int _fieldCount;
297 d->res = sqlite_step(
298 d->prepared_st_handle,
303 d->res = sqlite3_step( d->prepared_st_handle );
305 if (d->res == SQLITE_ROW) {
310 m_fieldCount = sqlite3_data_count(d->prepared_st_handle);
320 if (d->res==SQLITE_DONE)
339 if (!d->curr_coldata)
342 if (!d->cols_pointers_mem_size)
343 d->cols_pointers_mem_size =
m_fieldCount *
sizeof(
char*);
344 const char **record = (
const char**)malloc(d->cols_pointers_mem_size);
345 const char **src_col = d->curr_coldata;
346 const char **dest_col = record;
347 for (uint i=0; i<
m_fieldCount; i++,src_col++,dest_col++) {
350 *dest_col = *src_col ? strdup(*src_col) : 0;
368void SQLiteCursor::drv_bufferMovePointerTo(TQ_LLONG at)
370 d->curr_coldata = d->records.at(
at);
375 if (d->cols_pointers_mem_size>0) {
377 const char ***r_ptr = d->records.data();
378 for (uint i=0; i<records_in_buf; i++, r_ptr++) {
380 const char **field_data = *r_ptr;
382 for (uint col=0; col<
m_fieldCount; col++, field_data++) {
383 free((
void*)*field_data);
391 d->cols_pointers_mem_size=0;
424 return d->curr_coldata;
427void SQLiteCursor::storeCurrentRow(
RowData &data)
const
430 const char **col = d->curr_coldata;
437 data[i] = TQVariant( *col );
440 data[i] = TQString::fromUtf8( (
const char*)sqlite3_column_text(d->prepared_st_handle, i) );
452 while (j < maxCount && !m_fieldsExpanded->
at(j)->visible)
454 if (j >= (maxCount )) {
464 data[i] = TQVariant();
467 data[i] = TQString::fromUtf8( *col );
469 data[i] = TQVariant( *col );
472 data[i] = TQVariant( TQCString(*col).toDouble() );
474 switch (f ? f->type() : Field::Integer) {
477 case Field::ShortInteger:
479 data[i] = TQVariant( TQCString(*col).toInt() );
480 case Field::BigInteger:
481 data[i] = TQVariant( TQString::fromLatin1(*col).toLongLong() );
483 data[i] = TQVariant( sqliteStringToBool(TQString::fromLatin1(*col)) );
486 data[i] = TQDate::fromString( TQString::fromLatin1(*col), TQt::ISODate );
490 data[i] = KexiUtils::stringToHackedTQTime(TQString::fromLatin1(*col));
492 case Field::DateTime: {
493 TQString tmp( TQString::fromLatin1(*col) );
495 data[i] = TQDateTime::fromString( tmp, TQt::ISODate );
499 data[i] = TQVariant( *col );
505 data[i] = d->getValue(f, i);
510TQVariant SQLiteCursor::value(uint i)
523 return TQVariant( TQCString(d->curr_coldata[i]).toInt() );
525 return TQVariant( d->curr_coldata[i] );
527 return TQVariant( TQCString(d->curr_coldata[i]).toDouble() );
529 return TQVariant( d->curr_coldata[i] );
531 return d->getValue(f, i);
553 return TQString::fromLatin1( sqlite_error_string(d->res) );
555 return TQString::fromLatin1( d->result_name );
Provides database connection, allowing queries and data modification.
Provides database cursor functionality.
int m_records_in_buf
number of records currently stored in the buffer
virtual void drv_clearBuffer()
virtual TQString serverResultName()
char m_result
result of a row fetching
QueryColumnInfo::Vector * m_fieldsExpanded
Useful e.g. for value(int) method when we need access to schema def.
virtual void drv_appendCurrentRecordToBuffer()=0
virtual int serverResult()
uint m_fieldCount
cached field count information
virtual void drv_bufferMovePointerNext()=0
virtual void drv_bufferMovePointerPrev()=0
virtual const char ** rowData() const =0
virtual TQString serverErrorMsg()
virtual void drv_clearServerResult()=0
bool isFPNumericType() const
bool isIntegerType() const
TQString m_sql
used to store of actually executed SQL statement
KexiDB::QuerySchema provides information about database query.
sqlite-specific connection
High-level database connectivity library with database backend drivers.
TQValueVector< TQVariant > RowData
structure for storing single record with type information
TQDateTime stringToHackedTQTime(const TQString &s)
TQDateTime - a hack needed because TQVariant(TQTime) has broken isNull().