20#include "SqliteCursor.h"
22#include "SqliteConnection.h"
23#include "SqliteConnection_p.h"
24#include "sqlite_debug.h"
28#include "KDbRecordData.h"
36static bool sqliteStringToBool(
const QString& s)
44class SqliteCursorData :
public SqliteConnectionInternal
48 : SqliteConnectionInternal(conn)
49 , prepared_st_handle(nullptr)
51 , curr_coldata(nullptr)
52 , curr_colname(nullptr)
53 , cols_pointers_mem_size(0)
71 sqlite3_stmt *prepared_st_handle;
74 const char **curr_coldata;
75 const char **curr_colname;
76 int cols_pointers_mem_size;
80 int type = sqlite3_column_type(prepared_st_handle, i);
81 if (type == SQLITE_NULL) {
83 }
else if (!f || type == SQLITE_TEXT) {
86 (
const char*)sqlite3_column_text(prepared_st_handle, i),
87 sqlite3_column_bytes(prepared_st_handle, i)));
94 }
else if (t == KDbField::Date) {
96 }
else if (t == KDbField::Time) {
98 return KDbUtils::stringToHackedQTime(text);
99 }
else if (t == KDbField::DateTime) {
100 if (text.length() > 10) {
103 return KDbUtils::dateTimeFromISODateStringWithMs(text);
105 return sqliteStringToBool(text);
109 }
else if (type == SQLITE_INTEGER) {
112 return QVariant(qint64(sqlite3_column_int64(prepared_st_handle, i)));
114 const int intVal = sqlite3_column_int(prepared_st_handle, i);
117 return sqlite3_column_int(prepared_st_handle, i) != 0;
119 return QVariant(
double(sqlite3_column_int(prepared_st_handle, i)));
123 }
else if (type == SQLITE_FLOAT) {
126 return QVariant(sqlite3_column_double(prepared_st_handle, i));
128 return QVariant(qint64(sqlite3_column_int64(prepared_st_handle, i)));
130 const double doubleVal = sqlite3_column_double(prepared_st_handle, i);
135 }
else if (type == SQLITE_BLOB) {
138 return QByteArray((
const char*)sqlite3_column_blob(prepared_st_handle, i),
139 sqlite3_column_bytes(prepared_st_handle, i));
145 Q_DISABLE_COPY(SqliteCursorData)
151 , d(new SqliteCursorData(conn))
158 , d(new SqliteCursorData(conn))
163SqliteCursor::~SqliteCursor()
176 sqliteWarning() <<
"Missing database handle";
180 int res = sqlite3_prepare(
184 &d->prepared_st_handle,
187 if (res != SQLITE_OK) {
194 d->records.resize(128);
200bool SqliteCursor::drv_close()
202 int res = sqlite3_finalize(d->prepared_st_handle);
203 if (res != SQLITE_OK) {
211void SqliteCursor::drv_getNextRecord()
213 int res = sqlite3_step(d->prepared_st_handle);
214 if (res == SQLITE_ROW) {
216 m_fieldCount = sqlite3_data_count(d->prepared_st_handle);
222 if (res == SQLITE_DONE) {
241void SqliteCursor::drv_appendCurrentRecordToBuffer()
244 if (!d->curr_coldata)
246 if (!d->cols_pointers_mem_size)
247 d->cols_pointers_mem_size =
m_fieldCount *
sizeof(
char*);
248 const char **record = (
const char**)malloc(d->cols_pointers_mem_size);
249 const char **src_col = d->curr_coldata;
250 const char **dest_col = record;
251 for (
int i = 0; i <
m_fieldCount; i++, src_col++, dest_col++) {
254 *dest_col = *src_col ? strdup(*src_col) : nullptr;
260void SqliteCursor::drv_bufferMovePointerNext()
265void SqliteCursor::drv_bufferMovePointerPrev()
272void SqliteCursor::drv_bufferMovePointerTo(qint64 at)
274 d->curr_coldata = d->records.at(
at);
277void SqliteCursor::drv_clearBuffer()
279 if (d->cols_pointers_mem_size > 0) {
281 const char ***r_ptr = d->records.data();
282 for (
int i = 0; i < records_in_buf; i++, r_ptr++) {
283 const char **field_data = *r_ptr;
284 for (
int col = 0; col <
m_fieldCount; col++, field_data++) {
285 free((
void*)*field_data);
291 d->cols_pointers_mem_size = 0;
304const char ** SqliteCursor::recordData()
const
306 return d->curr_coldata;
309bool SqliteCursor::drv_storeCurrentRecord(
KDbRecordData* data)
const
314 (
const char*)sqlite3_column_text(d->prepared_st_handle, i),
315 sqlite3_column_bytes(d->prepared_st_handle, i));
322 (*data)[i] = d->getValue(f, i);
334 return d->getValue(f, i);
337QString SqliteCursor::serverResultName()
const
339 return SqliteConnectionInternal::serverResultName(m_result.
serverErrorCode());
342void SqliteCursor::storeResult()
344 d->storeResult(&m_result);
Provides database cursor functionality.
int m_fieldsToStoreInRecord
Used by storeCurrentRecord(), reimplement if needed (e.g.
int m_fieldCount
cached field count information
int m_records_in_buf
number of records currently stored in the buffer
KDbQueryColumnInfo::Vector * m_visibleFieldsExpanded
Useful e.g. for value(int) method to obtain access to schema definition.
FetchResult m_fetchResult
result of a record fetching
Specialized string for escaping.
bool isFPNumericType() const
bool isIntegerType() const
bool isUnsigned() const
if the type has the unsigned attribute
KDbQuerySchema provides information about database query.
Structure for storing single record with type information.
void setServerErrorCode(int errorCode)
Sets an implementation-specific error code of server-side operation.
SQLite-specific connection Following connection options are supported (see KDbConnectionOptions):
Type type(const QSqlDatabase &db)
std::optional< QSqlQuery > query(const QString &queryStatement)
QDate fromString(QStringView string, QStringView format, QCalendar cal)
const_reference at(qsizetype i) const const
qsizetype count() const const
int compare(QLatin1StringView s1, const QString &s2, Qt::CaseSensitivity cs)
QString fromUtf8(QByteArrayView str)