implemented sqlite fetch
This commit is contained in:
@@ -31,6 +31,8 @@ public:
|
||||
|
||||
size_t execute(const std::string &stmt) override;
|
||||
|
||||
sql::record describe(const std::string& table) override;
|
||||
|
||||
private:
|
||||
static int parse_result(void* param, int column_count, char** values, char** columns);
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ namespace matador::backends::sqlite {
|
||||
|
||||
class sqlite_query_result : public sql::query_result_impl {
|
||||
public:
|
||||
~sqlite_query_result() override;
|
||||
|
||||
void read_value(const char *id, size_t index, char &value) override;
|
||||
void read_value(const char *id, size_t index, short &value) override;
|
||||
void read_value(const char *id, size_t index, int &value) override;
|
||||
@@ -25,9 +27,10 @@ public:
|
||||
void read_value(const char *id, size_t index, char *value, size_t size) override;
|
||||
void read_value(const char *id, size_t index, std::string &value) override;
|
||||
void read_value(const char *id, size_t index, std::string &value, size_t s) override;
|
||||
void read_value(const char *id, size_t index, sql::any_type &value, sql::data_type_t type, size_t size) override;
|
||||
|
||||
protected:
|
||||
[[nodiscard]] bool next_row() override;
|
||||
[[nodiscard]] const char* column(size_t index) const override;
|
||||
[[nodiscard]] bool fetch() override;
|
||||
|
||||
private:
|
||||
friend class sqlite_connection;
|
||||
@@ -40,8 +43,7 @@ private:
|
||||
using rows = std::vector<columns>;
|
||||
|
||||
rows result_;
|
||||
size_t row_index_ = 0;
|
||||
|
||||
long long row_index_ = -1;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
#include "sqlite_error.hpp"
|
||||
#include "sqlite_query_result.hpp"
|
||||
|
||||
#include <utility>
|
||||
#include "matador/sql/record.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace matador::backends::sqlite {
|
||||
|
||||
@@ -40,6 +42,11 @@ int sqlite_connection::parse_result(void* param, int column_count, char** values
|
||||
auto *result = static_cast<sqlite_query_result*>(param);
|
||||
result->push_back(values, column_count);
|
||||
|
||||
sql::record prototype;
|
||||
for(int i = 0; i < column_count; ++i) {
|
||||
prototype.append(sql::column{columns[i]});
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -57,7 +64,7 @@ std::unique_ptr<sql::query_result_impl> sqlite_connection::fetch(const std::stri
|
||||
{
|
||||
auto result = std::make_unique<sqlite_query_result>();
|
||||
char *errmsg = nullptr;
|
||||
int ret = sqlite3_exec(sqlite_db_, stmt.c_str(), parse_result, result.get(), &errmsg);
|
||||
const int ret = sqlite3_exec(sqlite_db_, stmt.c_str(), parse_result, result.get(), &errmsg);
|
||||
|
||||
throw_sqlite_error(ret, sqlite_db_, "sqlite", stmt);
|
||||
|
||||
@@ -68,6 +75,69 @@ void sqlite_connection::prepare(const std::string &stmt)
|
||||
{
|
||||
}
|
||||
|
||||
sql::data_type_t string2type(const char *type)
|
||||
{
|
||||
if (strncmp(type, "INTEGER", 7) == 0) {
|
||||
return sql::data_type_t::type_int;
|
||||
} else if (strncmp(type, "TINYINT", 7) == 0) {
|
||||
return sql::data_type_t::type_char;
|
||||
} else if (strncmp(type, "SMALLINT", 8) == 0) {
|
||||
return sql::data_type_t::type_short;
|
||||
} else if (strncmp(type, "BIGINT", 6) == 0) {
|
||||
return sql::data_type_t::type_long_long;
|
||||
} else if (strcmp(type, "BOOLEAN") == 0) {
|
||||
return sql::data_type_t::type_bool;
|
||||
} else if (strcmp(type, "REAL") == 0) {
|
||||
return sql::data_type_t::type_double;
|
||||
} else if (strcmp(type, "FLOAT") == 0) {
|
||||
return sql::data_type_t::type_float;
|
||||
} else if (strcmp(type, "DOUBLE") == 0) {
|
||||
return sql::data_type_t::type_double;
|
||||
} else if (strcmp(type, "BLOB") == 0) {
|
||||
return sql::data_type_t::type_blob;
|
||||
} else if (strcmp(type, "NULL") == 0) {
|
||||
return sql::data_type_t::type_null;
|
||||
} else if (strncmp(type, "VARCHAR", 7) == 0) {
|
||||
return sql::data_type_t::type_varchar;
|
||||
} else if (strcmp(type, "DATE") == 0) {
|
||||
return sql::data_type_t::type_date;
|
||||
} else if (strcmp(type, "DATETIME") == 0) {
|
||||
return sql::data_type_t::type_time;
|
||||
} else if (strcmp(type, "TEXT") == 0) {
|
||||
return sql::data_type_t::type_text;
|
||||
} else {
|
||||
return sql::data_type_t::type_unknown;
|
||||
}
|
||||
}
|
||||
|
||||
sql::record sqlite_connection::describe(const std::string& table)
|
||||
{
|
||||
std::string stmt("PRAGMA table_info(" + table + ")");
|
||||
const auto result = fetch("PRAGMA table_info(" + table + ")");
|
||||
|
||||
sql::record prototype;
|
||||
while (result->fetch()) {
|
||||
char *end = nullptr;
|
||||
// Todo: add index to column
|
||||
auto index = strtoul(result->column(0), &end, 10);
|
||||
std::string name = result->column(1);
|
||||
|
||||
// Todo: extract size
|
||||
auto type = (string2type(result->column(2)));
|
||||
end = nullptr;
|
||||
utils::constraints options{};
|
||||
if (strtoul(result->column(3), &end, 10) == 0) {
|
||||
options = utils::constraints::NOT_NULL;
|
||||
}
|
||||
// f.default_value(res->column(4));
|
||||
// end = nullptr;
|
||||
// f.is_primary_key(strtoul(res->column(3), &end, 10) == 0);
|
||||
prototype.append({name, type, {options}});
|
||||
}
|
||||
|
||||
return std::move(prototype);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "sqlite_query_result.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
|
||||
@@ -13,7 +14,7 @@ void read(Type &x, const char *val, typename std::enable_if<std::is_integral<Typ
|
||||
}
|
||||
char *end;
|
||||
x = static_cast<Type>(strtoll(val, &end, 10));
|
||||
if (end != nullptr) {
|
||||
if (end == nullptr) {
|
||||
// Todo: check error
|
||||
throw std::logic_error("couldn't convert value to number");
|
||||
}
|
||||
@@ -27,7 +28,7 @@ void read(Type &x, const char *val, typename std::enable_if<std::is_integral<Typ
|
||||
}
|
||||
char *end;
|
||||
x = static_cast<Type>(strtoull(val, &end, 10));
|
||||
if (end != nullptr) {
|
||||
if (end == nullptr) {
|
||||
// Todo: check error
|
||||
throw std::logic_error("couldn't convert value to number");
|
||||
}
|
||||
@@ -41,12 +42,21 @@ void read(Type &x, const char *val, typename std::enable_if<std::is_floating_poi
|
||||
}
|
||||
char *end;
|
||||
x = static_cast<Type>(strtold(val, &end));
|
||||
if (end != nullptr) {
|
||||
if (end == nullptr) {
|
||||
// Todo: check error
|
||||
throw std::logic_error("couldn't convert value to number");
|
||||
}
|
||||
}
|
||||
|
||||
sqlite_query_result::~sqlite_query_result()
|
||||
{
|
||||
std::for_each(result_.begin(), result_.end(), [](rows ::value_type& row) {
|
||||
std::for_each(row.begin(), row.end(), [](const char *val) {
|
||||
delete [] val;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void sqlite_query_result::read_value(const char *id, size_t index, char &value)
|
||||
{
|
||||
read(value, result_[row_index_][index]);
|
||||
@@ -162,10 +172,81 @@ void sqlite_query_result::push_back(char **row_values, int column_count)
|
||||
result_.emplace_back(data);
|
||||
}
|
||||
|
||||
bool sqlite_query_result::next_row()
|
||||
const char* sqlite_query_result::column(size_t index) const
|
||||
{
|
||||
column_index_ = 0;
|
||||
return row_index_++ < result_.size();
|
||||
return result_[row_index_][index];
|
||||
}
|
||||
|
||||
bool sqlite_query_result::fetch()
|
||||
{
|
||||
column_index_ = 0;
|
||||
return ++row_index_ < result_.size();
|
||||
}
|
||||
|
||||
void sqlite_query_result::read_value(const char *id, size_t index, sql::any_type &value, sql::data_type_t type, size_t size)
|
||||
{
|
||||
switch (type) {
|
||||
case sql::data_type_t::type_char:
|
||||
case sql::data_type_t::type_short:
|
||||
case sql::data_type_t::type_int:
|
||||
case sql::data_type_t::type_long:
|
||||
case sql::data_type_t::type_long_long: {
|
||||
long long val{};
|
||||
read(val, result_[row_index_][index]);
|
||||
value = val;
|
||||
break;
|
||||
}
|
||||
case sql::data_type_t::type_unsigned_char:
|
||||
case sql::data_type_t::type_unsigned_short:
|
||||
case sql::data_type_t::type_unsigned_int:
|
||||
case sql::data_type_t::type_unsigned_long:
|
||||
case sql::data_type_t::type_unsigned_long_long: {
|
||||
unsigned long long val{};
|
||||
read(val, result_[row_index_][index]);
|
||||
value = val;
|
||||
break;
|
||||
}
|
||||
case sql::data_type_t::type_float:
|
||||
case sql::data_type_t::type_double: {
|
||||
double val{};
|
||||
read(val, result_[row_index_][index]);
|
||||
value = val;
|
||||
break;
|
||||
}
|
||||
case sql::data_type_t::type_bool: {
|
||||
int val{};
|
||||
read(val, result_[row_index_][index]);
|
||||
value = val > 0;
|
||||
break;
|
||||
}
|
||||
case sql::data_type_t::type_text:
|
||||
case sql::data_type_t::type_varchar: {
|
||||
value = std::string{result_[row_index_][index]};
|
||||
break;
|
||||
}
|
||||
case sql::data_type_t::type_char_pointer: {
|
||||
value = result_[row_index_][index];
|
||||
break;
|
||||
}
|
||||
case sql::data_type_t::type_time:
|
||||
case sql::data_type_t::type_date: {
|
||||
value = std::string{result_[row_index_][index]};
|
||||
break;
|
||||
}
|
||||
case sql::data_type_t::type_null: {
|
||||
value = nullptr_t{};
|
||||
break;
|
||||
}
|
||||
case sql::data_type_t::type_blob: {
|
||||
throw std::logic_error("data type blob not supported");
|
||||
}
|
||||
case sql::data_type_t::type_unknown: {
|
||||
value = result_[row_index_][index];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user