added sqlite query result and enhanced column generator and value extractor
This commit is contained in:
@@ -9,6 +9,7 @@ set(SOURCES
|
||||
src/sqlite_connection.cpp
|
||||
src/sqlite_error.cpp
|
||||
src/sqlite_dialect.cpp
|
||||
src/sqlite_query_result.cpp
|
||||
)
|
||||
|
||||
add_library(matador-sqlite SHARED ${SOURCES} ${HEADER})
|
||||
|
||||
@@ -26,9 +26,14 @@ public:
|
||||
void close() override;
|
||||
bool is_open() override;
|
||||
|
||||
void execute(const std::string &stmt) override;
|
||||
std::unique_ptr<sql::query_result_impl> fetch(const std::string &stmt) override;
|
||||
void prepare(const std::string &stmt) override;
|
||||
|
||||
size_t execute(const std::string &stmt) override;
|
||||
|
||||
private:
|
||||
static int parse_result(void* param, int column_count, char** values, char** columns);
|
||||
|
||||
private:
|
||||
sqlite3 *sqlite_db_{};
|
||||
};
|
||||
|
||||
@@ -1,10 +1,46 @@
|
||||
#ifndef QUERY_SQLITE_QUERY_RESULT_HPP
|
||||
#define QUERY_SQLITE_QUERY_RESULT_HPP
|
||||
|
||||
#include "matador/sql/query_result_impl.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace matador::backends::sqlite {
|
||||
|
||||
class sqlite_query_result {
|
||||
class sqlite_query_result : public sql::query_result_impl {
|
||||
public:
|
||||
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;
|
||||
void read_value(const char *id, size_t index, long &value) override;
|
||||
void read_value(const char *id, size_t index, long long int &value) override;
|
||||
void read_value(const char *id, size_t index, unsigned char &value) override;
|
||||
void read_value(const char *id, size_t index, unsigned short &value) override;
|
||||
void read_value(const char *id, size_t index, unsigned int &value) override;
|
||||
void read_value(const char *id, size_t index, unsigned long &value) override;
|
||||
void read_value(const char *id, size_t index, unsigned long long int &value) override;
|
||||
void read_value(const char *id, size_t index, bool &value) override;
|
||||
void read_value(const char *id, size_t index, float &value) override;
|
||||
void read_value(const char *id, size_t index, double &value) override;
|
||||
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;
|
||||
|
||||
protected:
|
||||
[[nodiscard]] bool next_row() override;
|
||||
|
||||
private:
|
||||
friend class sqlite_connection;
|
||||
|
||||
private:
|
||||
void push_back(char **row_values, int column_count);
|
||||
|
||||
private:
|
||||
using columns = std::vector<char*>;
|
||||
using rows = std::vector<columns>;
|
||||
|
||||
rows result_;
|
||||
size_t row_index_ = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#include "sqlite_connection.hpp"
|
||||
#include "sqlite_error.hpp"
|
||||
#include "sqlite_query_result.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace matador::backends::sqlite {
|
||||
|
||||
sqlite_connection::sqlite_connection(const sql::connection_info &info)
|
||||
@@ -32,14 +35,37 @@ bool sqlite_connection::is_open()
|
||||
return sqlite_db_ != nullptr;
|
||||
}
|
||||
|
||||
void sqlite_connection::execute(const std::string &stmt)
|
||||
int sqlite_connection::parse_result(void* param, int column_count, char** values, char** columns)
|
||||
{
|
||||
auto *result = static_cast<sqlite_query_result*>(param);
|
||||
result->push_back(values, column_count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t sqlite_connection::execute(const std::string &stmt)
|
||||
{
|
||||
char *errmsg = nullptr;
|
||||
int ret = sqlite3_exec(sqlite_db_, stmt.c_str(), nullptr, nullptr, &errmsg);
|
||||
|
||||
throw_sqlite_error(ret, sqlite_db_, "sqlite", stmt);
|
||||
|
||||
return sqlite3_changes(sqlite_db_);
|
||||
}
|
||||
|
||||
std::unique_ptr<sql::query_result_impl> sqlite_connection::fetch(const std::string &stmt)
|
||||
{
|
||||
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);
|
||||
|
||||
throw_sqlite_error(ret, sqlite_db_, "sqlite", stmt);
|
||||
|
||||
return std::move(result);
|
||||
}
|
||||
|
||||
void sqlite_connection::prepare(const std::string &stmt)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
#include "sqlite_query_result.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace matador::backends::sqlite {
|
||||
|
||||
template < class Type >
|
||||
void read(Type &x, const char *val, typename std::enable_if<std::is_integral<Type>::value && std::is_signed<Type>::value>::type* = nullptr)
|
||||
{
|
||||
if (strlen(val) == 0) {
|
||||
return;
|
||||
}
|
||||
char *end;
|
||||
x = static_cast<Type>(strtoll(val, &end, 10));
|
||||
if (end != nullptr) {
|
||||
// Todo: check error
|
||||
throw std::logic_error("couldn't convert value to number");
|
||||
}
|
||||
}
|
||||
|
||||
template < class Type >
|
||||
void read(Type &x, const char *val, typename std::enable_if<std::is_integral<Type>::value && std::is_unsigned<Type>::value>::type* = nullptr)
|
||||
{
|
||||
if (strlen(val) == 0) {
|
||||
return;
|
||||
}
|
||||
char *end;
|
||||
x = static_cast<Type>(strtoull(val, &end, 10));
|
||||
if (end != nullptr) {
|
||||
// Todo: check error
|
||||
throw std::logic_error("couldn't convert value to number");
|
||||
}
|
||||
}
|
||||
|
||||
template < class Type >
|
||||
void read(Type &x, const char *val, typename std::enable_if<std::is_floating_point<Type>::value>::type* = nullptr)
|
||||
{
|
||||
if (strlen(val) == 0) {
|
||||
return;
|
||||
}
|
||||
char *end;
|
||||
x = static_cast<Type>(strtold(val, &end));
|
||||
if (end != nullptr) {
|
||||
// Todo: check error
|
||||
throw std::logic_error("couldn't convert value to number");
|
||||
}
|
||||
}
|
||||
|
||||
void sqlite_query_result::read_value(const char *id, size_t index, char &value)
|
||||
{
|
||||
read(value, result_[row_index_][index]);
|
||||
}
|
||||
|
||||
void sqlite_query_result::read_value(const char *id, size_t index, short &value)
|
||||
{
|
||||
read(value, result_[row_index_][index]);
|
||||
}
|
||||
|
||||
void sqlite_query_result::read_value(const char *id, size_t index, int &value)
|
||||
{
|
||||
read(value, result_[row_index_][index]);
|
||||
}
|
||||
|
||||
void sqlite_query_result::read_value(const char *id, size_t index, long &value)
|
||||
{
|
||||
read(value, result_[row_index_][index]);
|
||||
}
|
||||
|
||||
void sqlite_query_result::read_value(const char *id, size_t index, long long int &value)
|
||||
{
|
||||
read(value, result_[row_index_][index]);
|
||||
}
|
||||
|
||||
void sqlite_query_result::read_value(const char *id, size_t index, unsigned char &value)
|
||||
{
|
||||
read(value, result_[row_index_][index]);
|
||||
}
|
||||
|
||||
void sqlite_query_result::read_value(const char *id, size_t index, unsigned short &value)
|
||||
{
|
||||
read(value, result_[row_index_][index]);
|
||||
}
|
||||
|
||||
void sqlite_query_result::read_value(const char *id, size_t index, unsigned int &value)
|
||||
{
|
||||
read(value, result_[row_index_][index]);
|
||||
}
|
||||
|
||||
void sqlite_query_result::read_value(const char *id, size_t index, unsigned long &value)
|
||||
{
|
||||
read(value, result_[row_index_][index]);
|
||||
}
|
||||
|
||||
void sqlite_query_result::read_value(const char *id, size_t index, unsigned long long int &value)
|
||||
{
|
||||
read(value, result_[row_index_][index]);
|
||||
}
|
||||
|
||||
void sqlite_query_result::read_value(const char *id, size_t index, bool &value)
|
||||
{
|
||||
read(value, result_[row_index_][index]);
|
||||
}
|
||||
|
||||
void sqlite_query_result::read_value(const char *id, size_t index, float &value)
|
||||
{
|
||||
read(value, result_[row_index_][index]);
|
||||
}
|
||||
|
||||
void sqlite_query_result::read_value(const char *id, size_t index, double &value)
|
||||
{
|
||||
read(value, result_[row_index_][index]);
|
||||
}
|
||||
|
||||
void sqlite_query_result::read_value(const char *id, size_t index, char *value, size_t size)
|
||||
{
|
||||
auto val = result_[row_index_][index];
|
||||
size_t len = strlen(val);
|
||||
if (len > size) {
|
||||
#ifdef _MSC_VER
|
||||
strncpy_s(value, size, val, len);
|
||||
#else
|
||||
strncpy(value, val, size);
|
||||
#endif
|
||||
value[size-1] = '\n';
|
||||
} else {
|
||||
#ifdef _MSC_VER
|
||||
strcpy_s(value, size, val);
|
||||
#else
|
||||
strcpy(value, val);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void sqlite_query_result::read_value(const char *id, size_t index, std::string &value)
|
||||
{
|
||||
value.assign(result_[row_index_][index]);
|
||||
}
|
||||
|
||||
void sqlite_query_result::read_value(const char *id, size_t index, std::string &value, size_t s)
|
||||
{
|
||||
value.assign(result_[row_index_][index]);
|
||||
}
|
||||
|
||||
void sqlite_query_result::push_back(char **row_values, int column_count)
|
||||
{
|
||||
columns data;
|
||||
for(int i = 0; i < column_count; ++i) {
|
||||
// copy and store column data;
|
||||
if (row_values[i] == nullptr) {
|
||||
auto val = new char[1];
|
||||
val[0] = '\0';
|
||||
data.push_back(val);
|
||||
} else {
|
||||
size_t size = strlen(row_values[i]);
|
||||
auto val = new char[size + 1];
|
||||
std::memcpy(val, row_values[i], size);
|
||||
val[size] = '\0';
|
||||
data.push_back(val);
|
||||
}
|
||||
}
|
||||
result_.emplace_back(data);
|
||||
}
|
||||
|
||||
bool sqlite_query_result::next_row()
|
||||
{
|
||||
column_index_ = 0;
|
||||
return row_index_++ < result_.size();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user