fixed backend tests (progress)
This commit is contained in:
parent
d070a5a0ac
commit
6e64ba99de
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include "matador/sql/internal/query_result_impl.hpp"
|
#include "matador/sql/internal/query_result_impl.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
namespace matador::backends::postgres {
|
namespace matador::backends::postgres {
|
||||||
|
|
@ -79,6 +80,8 @@ utils::result<utils::version, utils::error> postgres_connection::server_version(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
utils::basic_type oid2type(Oid oid);
|
||||||
|
|
||||||
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> postgres_connection::fetch(const sql::query_context &context) {
|
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> postgres_connection::fetch(const sql::query_context &context) {
|
||||||
PGresult *res = PQexec(conn_, context.sql.c_str());
|
PGresult *res = PQexec(conn_, context.sql.c_str());
|
||||||
|
|
||||||
|
|
@ -86,16 +89,28 @@ utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> postgres_co
|
||||||
return utils::failure(make_error(sql::error_code::FETCH_FAILED, res, conn_, "Failed to fetch", context.sql));
|
return utils::failure(make_error(sql::error_code::FETCH_FAILED, res, conn_, "Failed to fetch", context.sql));
|
||||||
}
|
}
|
||||||
|
|
||||||
// std::vector<object::column_definition> prototype;
|
// const auto is_unknown = std::all_of( context.prototype.begin(), context.prototype.end(), [](const object::attribute_definition &a) {return a.is_null();} );
|
||||||
// const auto num_col = PQnfields(res);
|
// if (!is_unknown) {
|
||||||
// for (int i = 0; i < num_col; ++i) {
|
// return utils::ok(std::make_unique<sql::query_result_impl>(std::make_unique<postgres_result_reader>(res), context.prototype));
|
||||||
// const char *col_name = PQfname(res, i);
|
|
||||||
// auto type = PQftype(res, i);
|
|
||||||
// auto size = PQfmod(res, i);
|
|
||||||
// prototype.emplace_back(col_name);
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
return utils::ok(std::make_unique<sql::query_result_impl>(std::make_unique<postgres_result_reader>(res), context.prototype));
|
std::vector<object::attribute_definition> prototype = context.prototype;
|
||||||
|
|
||||||
|
const auto num_col = PQnfields(res);
|
||||||
|
if (prototype.size() != num_col) {
|
||||||
|
return utils::failure(make_error(sql::error_code::FETCH_FAILED, res, conn_, "Number of received columns doesn't match expected columns.", context.sql));
|
||||||
|
}
|
||||||
|
for (int i = 0; i < num_col; ++i) {
|
||||||
|
if (!prototype.at(i).is_null()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto type = oid2type(PQftype(res, i));
|
||||||
|
// const char *col_name = PQfname(res, i);
|
||||||
|
// const auto size = PQfmod(res, i);
|
||||||
|
prototype.at(i).type(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return utils::ok(std::make_unique<sql::query_result_impl>(std::make_unique<postgres_result_reader>(res), prototype));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string postgres_connection::generate_statement_name(const sql::query_context &query) {
|
std::string postgres_connection::generate_statement_name(const sql::query_context &query) {
|
||||||
|
|
@ -141,6 +156,37 @@ utils::result<size_t, utils::error> postgres_connection::execute(const std::stri
|
||||||
return utils::ok(static_cast<size_t>(affected_rows));
|
return utils::ok(static_cast<size_t>(affected_rows));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
utils::basic_type oid2type(const Oid oid) {
|
||||||
|
switch (oid) {
|
||||||
|
case 16:
|
||||||
|
return utils::basic_type::type_bool;
|
||||||
|
case 17:
|
||||||
|
return utils::basic_type::type_blob;
|
||||||
|
case 18:
|
||||||
|
return utils::basic_type::type_int8;
|
||||||
|
case 21:
|
||||||
|
return utils::basic_type::type_int16;
|
||||||
|
case 23:
|
||||||
|
return utils::basic_type::type_int32;
|
||||||
|
case 20:
|
||||||
|
return utils::basic_type::type_int64;
|
||||||
|
case 24:
|
||||||
|
return utils::basic_type::type_text;
|
||||||
|
case 1043:
|
||||||
|
return utils::basic_type::type_varchar;
|
||||||
|
case 700:
|
||||||
|
return utils::basic_type::type_float;
|
||||||
|
case 701:
|
||||||
|
return utils::basic_type::type_double;
|
||||||
|
case 1082:
|
||||||
|
return utils::basic_type::type_date;
|
||||||
|
case 1114:
|
||||||
|
return utils::basic_type::type_time;
|
||||||
|
default:
|
||||||
|
return utils::basic_type::type_null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
utils::basic_type string2type(const char *type) {
|
utils::basic_type string2type(const char *type) {
|
||||||
if (strcmp(type, "int2") == 0) {
|
if (strcmp(type, "int2") == 0) {
|
||||||
return utils::basic_type::type_int16;
|
return utils::basic_type::type_int16;
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
return "$" + std::to_string(index);
|
return "$" + std::to_string(index);
|
||||||
})
|
})
|
||||||
.with_token_replace_map({
|
.with_token_replace_map({
|
||||||
{dialect_token::BEGIN_BINARY_DATA, "'"}
|
{dialect_token::BEGIN_BINARY_DATA, "'\\x"}
|
||||||
})
|
})
|
||||||
.with_data_type_replace_map({
|
.with_data_type_replace_map({
|
||||||
{matador::utils::basic_type::type_int8, "SMALLINT"},
|
{matador::utils::basic_type::type_int8, "SMALLINT"},
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@ result<DestType, conversion_error> to(const std::string &source, std::enable_if_
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename DestType >
|
template < typename DestType >
|
||||||
result<DestType, conversion_error> to(const std::string &source, std::enable_if_t<std::is_integral_v<DestType> && std::is_unsigned_v<DestType>>* = nullptr)
|
result<DestType, conversion_error> to(const std::string &source, std::enable_if_t<std::is_integral_v<DestType> && std::is_unsigned_v<DestType> && !std::is_same_v<DestType, bool>>* = nullptr)
|
||||||
{
|
{
|
||||||
if (source.empty()) {
|
if (source.empty()) {
|
||||||
return failure(conversion_error::MissingData/*, "failed to convert empty string"}*/);
|
return failure(conversion_error::MissingData/*, "failed to convert empty string"}*/);
|
||||||
|
|
@ -167,17 +167,27 @@ result<DestType, conversion_error> to(const blob &source, std::enable_if_t<std::
|
||||||
return ok(source);
|
return ok(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// template < typename DestType >
|
||||||
|
// result<DestType, conversion_error> to(const std::string &source, std::enable_if_t<std::is_same_v<DestType, blob>>* = nullptr) {
|
||||||
|
// if (source.empty()) {
|
||||||
|
// return failure(conversion_error::MissingData/*, "failed to convert empty string"}*/);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//
|
||||||
static std::unordered_map<std::string, bool> string_to_bool_map = {
|
static std::unordered_map<std::string, bool> string_to_bool_map = {
|
||||||
{"true", true},
|
{"true", true},
|
||||||
|
{"t", true},
|
||||||
{"on", true},
|
{"on", true},
|
||||||
{"1", true},
|
{"1", true},
|
||||||
{"false", false},
|
{"false", false},
|
||||||
|
{"f", false},
|
||||||
{"off", false},
|
{"off", false},
|
||||||
{"0", false}
|
{"0", false}
|
||||||
};
|
};
|
||||||
|
|
||||||
template < typename DestType, typename SourceType >
|
template < typename DestType >
|
||||||
result<DestType, conversion_error> to(const SourceType &source, std::enable_if_t<std::is_same_v<SourceType, std::string> &&std::is_same_v<DestType, bool>>* = nullptr) {
|
result<DestType, conversion_error> to(const std::string &source, std::enable_if_t<std::is_same_v<DestType, bool>>* = nullptr) {
|
||||||
if (source.empty()) {
|
if (source.empty()) {
|
||||||
return failure(conversion_error::MissingData);
|
return failure(conversion_error::MissingData);
|
||||||
}
|
}
|
||||||
|
|
@ -188,6 +198,18 @@ result<DestType, conversion_error> to(const SourceType &source, std::enable_if_t
|
||||||
return ok(it->second);
|
return ok(it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template < typename DestType >
|
||||||
|
result<DestType, conversion_error> to(const char *source, std::enable_if_t<std::is_same_v<DestType, bool>>* = nullptr) {
|
||||||
|
if (strlen(source) == 0) {
|
||||||
|
return failure(conversion_error::MissingData);
|
||||||
|
}
|
||||||
|
const auto it = string_to_bool_map.find(source);
|
||||||
|
if (it == string_to_bool_map.end()) {
|
||||||
|
return failure(conversion_error::NotConvertable);
|
||||||
|
}
|
||||||
|
return ok(it->second);
|
||||||
|
}
|
||||||
|
|
||||||
template < typename DestType, typename SourceType >
|
template < typename DestType, typename SourceType >
|
||||||
result<DestType, conversion_error> to(const SourceType &source, std::enable_if_t<std::is_same_v<SourceType, bool> &&std::is_same_v<DestType, std::string>>* = nullptr) {
|
result<DestType, conversion_error> to(const SourceType &source, std::enable_if_t<std::is_same_v<SourceType, bool> &&std::is_same_v<DestType, std::string>>* = nullptr) {
|
||||||
return ok(std::string(source ? "true" : "false"));
|
return ok(std::string(source ? "true" : "false"));
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include "matador/query/attribute_string_writer.hpp"
|
#include "matador/query/attribute_string_writer.hpp"
|
||||||
|
|
||||||
// #include "matador/sql/connection_impl.hpp"
|
#include "matador/sql/interface/connection_impl.hpp"
|
||||||
#include <matador/utils/convert.hpp>
|
#include <matador/utils/convert.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -56,13 +56,13 @@ void attribute_string_writer::write_value(size_t /*pos*/, const bool& x ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void attribute_string_writer::write_value(size_t /*pos*/, const float& x ) {
|
void attribute_string_writer::write_value(size_t /*pos*/, const float& x ) {
|
||||||
if (const auto res = utils::to<std::string>(x); res.is_error()) {
|
if (const auto res = utils::to<std::string>(x); !res.is_error()) {
|
||||||
result_ = *res;
|
result_ = *res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void attribute_string_writer::write_value(size_t /*pos*/, const double& x ) {
|
void attribute_string_writer::write_value(size_t /*pos*/, const double& x ) {
|
||||||
if (const auto res = utils::to<std::string>(x); res.is_error()) {
|
if (const auto res = utils::to<std::string>(x); !res.is_error()) {
|
||||||
result_ = *res;
|
result_ = *res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -98,7 +98,7 @@ void attribute_string_writer::write_value(size_t /*pos*/, const utils::blob& x )
|
||||||
// MSSQL: 0x5468697320697320612062616E617279204461746120737472696E67
|
// MSSQL: 0x5468697320697320612062616E617279204461746120737472696E67
|
||||||
// Sqlite: X'5468697320697320612062616E617279204461746120737472696E67'
|
// Sqlite: X'5468697320697320612062616E617279204461746120737472696E67'
|
||||||
if (conn_.has_value()) {
|
if (conn_.has_value()) {
|
||||||
// result_ = dialect_.token_at(sql::dialect_token::BEGIN_BINARY_DATA) + conn_.value().get().to_escaped_string(x) + dialect_.token_at(sql::dialect_token::END_BINARY_DATA);
|
result_ = dialect_.token_at(sql::dialect_token::BEGIN_BINARY_DATA) + conn_.value().get().to_escaped_string(x) + dialect_.token_at(sql::dialect_token::END_BINARY_DATA);
|
||||||
} else {
|
} else {
|
||||||
result_ = dialect_.token_at(sql::dialect_token::BEGIN_BINARY_DATA) + dialect_.to_escaped_string(x) + dialect_.token_at(sql::dialect_token::END_BINARY_DATA);
|
result_ = dialect_.token_at(sql::dialect_token::BEGIN_BINARY_DATA) + dialect_.to_escaped_string(x) + dialect_.token_at(sql::dialect_token::END_BINARY_DATA);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ TEST_CASE_METHOD( QueryFixture, "Insert and select basic datatypes", "[query][da
|
||||||
};
|
};
|
||||||
|
|
||||||
res = query::insert()
|
res = query::insert()
|
||||||
.into("types", matador::sql::column_generator::generate<types>(schema, true))
|
.into("types", column_generator::generate<types>(schema, true))
|
||||||
.values(t)
|
.values(t)
|
||||||
.execute(db);
|
.execute(db);
|
||||||
REQUIRE(res.is_ok());
|
REQUIRE(res.is_ok());
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,8 @@ TEST_CASE_METHOD(QueryFixture, "Test all data types for record", "[query][record
|
||||||
tables_to_drop.emplace("types");
|
tables_to_drop.emplace("types");
|
||||||
|
|
||||||
auto cols = std::vector<std::string>{"id",
|
auto cols = std::vector<std::string>{"id",
|
||||||
"val_char", "val_short", "val_int", "val_long", "val_long_long",
|
"val_char", "val_short", "val_int", "val_long_long",
|
||||||
"val_uchar", "val_ushort", "val_uint", "val_ulong", "val_ulong_long",
|
"val_uchar", "val_ushort", "val_uint", "val_ulong_long",
|
||||||
"val_bool",
|
"val_bool",
|
||||||
"val_float", "val_double",
|
"val_float", "val_double",
|
||||||
"val_string", "val_varchar",
|
"val_string", "val_varchar",
|
||||||
|
|
@ -426,8 +426,7 @@ TEST_CASE_METHOD(QueryFixture, "Execute select statement with order by", "[query
|
||||||
REQUIRE(expected_names.empty());
|
REQUIRE(expected_names.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_METHOD(QueryFixture, "Execute select statement with group by and order by", "[query][record]")
|
TEST_CASE_METHOD(QueryFixture, "Execute select statement with group by and order by", "[query][record]") {
|
||||||
{
|
|
||||||
auto res = query::create()
|
auto res = query::create()
|
||||||
.table("person", {
|
.table("person", {
|
||||||
make_pk_column<uint32_t>("id"),
|
make_pk_column<uint32_t>("id"),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue