initial matador ng commit
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
add_subdirectory(core)
|
||||
add_subdirectory(orm)
|
||||
@@ -0,0 +1,57 @@
|
||||
add_library(matador-core STATIC
|
||||
../../include/matador/utils/access.hpp
|
||||
../../include/matador/utils/attribute_reader.hpp
|
||||
../../include/matador/utils/attribute_writer.hpp
|
||||
../../include/matador/utils/base_class.hpp
|
||||
../../include/matador/utils/basic_type_converter.hpp
|
||||
../../include/matador/utils/basic_types.hpp
|
||||
../../include/matador/utils/cascade_type.hpp
|
||||
../../include/matador/utils/constraints.hpp
|
||||
../../include/matador/utils/convert.hpp
|
||||
../../include/matador/utils/data_type_traits.hpp
|
||||
../../include/matador/utils/default_type_traits.hpp
|
||||
../../include/matador/utils/di.hpp
|
||||
../../include/matador/utils/enum_mapper.hpp
|
||||
../../include/matador/utils/error.hpp
|
||||
../../include/matador/utils/errors.hpp
|
||||
../../include/matador/utils/export.hpp
|
||||
../../include/matador/utils/fetch_type.hpp
|
||||
../../include/matador/utils/field_attributes.hpp
|
||||
../../include/matador/utils/foreign_attributes.hpp
|
||||
../../include/matador/utils/identifier.hpp
|
||||
../../include/matador/utils/library.hpp
|
||||
../../include/matador/utils/os.hpp
|
||||
../../include/matador/utils/placeholder.hpp
|
||||
../../include/matador/utils/result.hpp
|
||||
../../include/matador/utils/singleton.hpp
|
||||
../../include/matador/utils/string.hpp
|
||||
../../include/matador/utils/types.hpp
|
||||
../../include/matador/utils/value.hpp
|
||||
../../include/matador/utils/version.hpp
|
||||
utils/default_type_traits.cpp
|
||||
utils/error.cpp
|
||||
utils/field_attributes.cpp
|
||||
utils/identifier.cpp
|
||||
utils/library.cpp
|
||||
utils/os.cpp
|
||||
utils/string.cpp
|
||||
utils/types.cpp
|
||||
utils/value.cpp
|
||||
utils/version.cpp
|
||||
utils/errors.cpp
|
||||
../../include/matador/object/basic_object_info.hpp
|
||||
../../include/matador/object/error_code.hpp
|
||||
../../include/matador/object/schema.hpp
|
||||
../../include/matador/object/schema_node.hpp
|
||||
object/error_code.cpp
|
||||
object/schema.cpp
|
||||
object/schema_node.cpp
|
||||
object/basic_object_info.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(matador-core ${CMAKE_DL_LIBS})
|
||||
|
||||
target_include_directories(matador-core
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../include
|
||||
)
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "matador/object/basic_object_info.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace matador::object {
|
||||
|
||||
basic_object_info::basic_object_info(schema_node &node, const std::type_index type_index)
|
||||
: node_(node)
|
||||
, type_index_(type_index) {}
|
||||
|
||||
std::type_index basic_object_info::type_index() const { return type_index_; }
|
||||
|
||||
} // namespace matador::object
|
||||
@@ -0,0 +1,37 @@
|
||||
#include "matador/object/error_code.hpp"
|
||||
|
||||
namespace matador::object {
|
||||
|
||||
const char * object_category_impl::name() const noexcept {
|
||||
return "sql";
|
||||
}
|
||||
|
||||
std::string object_category_impl::message(const int ev) const {
|
||||
switch (static_cast<error_code>(ev)) {
|
||||
case error_code::OK:
|
||||
return "OK";
|
||||
case error_code::NodeNotFound:
|
||||
return "Node not found";
|
||||
case error_code::NodeAlreadyExists:
|
||||
return "Node already exists";
|
||||
case error_code::Failure:
|
||||
return "Failure";
|
||||
default:
|
||||
return "Unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
const std::error_category & object_category() {
|
||||
static object_category_impl instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
std::error_code make_error_code(error_code e) {
|
||||
return {static_cast<int>(e), object_category()};
|
||||
}
|
||||
|
||||
std::error_condition make_error_condition(error_code e) {
|
||||
return {static_cast<int>(e), object_category()};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
#include "matador/object/schema.hpp"
|
||||
|
||||
namespace matador::object {
|
||||
|
||||
utils::error make_error(const error_code ec, const std::string& msg) {
|
||||
return utils::error(ec, msg);
|
||||
}
|
||||
|
||||
schema::schema()
|
||||
: root_(std::shared_ptr<schema_node>(new schema_node(*this))) {
|
||||
root_->first_child_ = std::shared_ptr<schema_node>(new schema_node(*this));
|
||||
root_->last_child_ = std::shared_ptr<schema_node>(new schema_node(*this));
|
||||
root_->first_child_->next_sibling_ = root_->last_child_;
|
||||
root_->last_child_->previous_sibling_ = root_->first_child_;
|
||||
}
|
||||
|
||||
bool schema::empty() const {
|
||||
return root_->first_child_ == root_->last_child_->previous_sibling_;
|
||||
}
|
||||
|
||||
size_t schema::size() const { return 0; }
|
||||
|
||||
utils::result<std::shared_ptr<schema_node>, utils::error> schema::attach_node(const std::shared_ptr<schema_node> &node,
|
||||
const std::string &parent) {
|
||||
if (!has_node(node->type_index(), node->name())) {
|
||||
return utils::failure(make_error(error_code::NodeAlreadyExists, "Node '" + node->name() + "' already exists."));
|
||||
}
|
||||
|
||||
// set node to root node
|
||||
auto parent_node = root_;
|
||||
auto result = find_parent(parent);
|
||||
if (!result.is_ok() && result.err().ec() != error_code::NodeNotFound) {
|
||||
return result;
|
||||
}
|
||||
parent_node = *result;
|
||||
|
||||
result = push_back_child(root_, node);
|
||||
|
||||
// if (!pk.is_null()) {
|
||||
// node->primary_key_ = pk;
|
||||
// }
|
||||
// store prototype in map
|
||||
// Todo: check return value
|
||||
node_map_.insert(std::make_pair(node->name(), node))/*.first*/;
|
||||
type_index_node_map_[node->type_index()].insert(std::make_pair(node->name(), node));
|
||||
|
||||
// return nptr.release();
|
||||
return {};
|
||||
}
|
||||
|
||||
utils::result<std::shared_ptr<schema_node>, utils::error> schema::find_parent(const std::string &name) const {
|
||||
if (name.empty()) {
|
||||
return utils::failure(make_error(error_code::Failure, "Name of parent cannot be empty"));
|
||||
}
|
||||
|
||||
return find_node(name);
|
||||
}
|
||||
|
||||
utils::result<std::shared_ptr<schema_node>, utils::error> schema::find_node(const std::string &name) const {
|
||||
// first search in the prototype map
|
||||
const auto i = node_map_.find(name);
|
||||
if (i == node_map_.end()) {
|
||||
// if not found search in the typeid to prototype map
|
||||
// const auto j = type_index_node_map_.find(name);
|
||||
// if (j == type_index_node_map_.end()) {
|
||||
// return utils::failure(
|
||||
// make_error(error_code::NodeNotFound, std::string("Could not find node with name '") + name + "'"));
|
||||
// }
|
||||
// const t_node_map &val = j->second;
|
||||
/*
|
||||
* if size is greater one (1) the name
|
||||
* is a typeid and has more than one prototype
|
||||
* node and therefor it is not unique and an
|
||||
* exception is thrown
|
||||
*/
|
||||
// if (val.size() > 1) {
|
||||
// return utils::failure(make_error(error_code::NodeNotFound, std::string("Type id '") + name + "' is not unique"));
|
||||
// }
|
||||
// // return the only prototype
|
||||
// return utils::ok(val.begin()->second);
|
||||
}
|
||||
return utils::ok(i->second);
|
||||
}
|
||||
utils::result<std::shared_ptr<schema_node>, utils::error> schema::push_back_child(const node_ptr &parent, const node_ptr &child) {
|
||||
child->parent_ = parent;
|
||||
child->previous_sibling_ = parent->last_child_->previous_sibling_;
|
||||
child->next_sibling_ = parent->last_child_;
|
||||
parent->last_child_->previous_sibling_->next_sibling_ = child;
|
||||
parent->last_child_->previous_sibling_ = child;
|
||||
// set depth
|
||||
// child->depth = depth + 1;
|
||||
}
|
||||
|
||||
bool schema::has_node(const std::type_index &index, const std::string &name) const {
|
||||
return node_map_.count(name) > 0 || type_index_node_map_.count(index) > 0;
|
||||
}
|
||||
|
||||
} // namespace matador::object
|
||||
@@ -0,0 +1,60 @@
|
||||
#include <utility>
|
||||
|
||||
#include "matador/object/schema_node.hpp"
|
||||
|
||||
namespace matador::object {
|
||||
|
||||
schema_node::schema_node(schema &tree)
|
||||
: schema_(tree)
|
||||
, info_(std::make_unique<null_info>(*this))
|
||||
{}
|
||||
|
||||
std::string schema_node::name() const {
|
||||
return name_;
|
||||
}
|
||||
|
||||
std::type_index schema_node::type_index() const {
|
||||
return info_->type_index();
|
||||
}
|
||||
|
||||
void schema_node::append(const std::shared_ptr<schema_node> &sibling) {
|
||||
sibling->parent_ = parent_;
|
||||
|
||||
// sibling->previous_sibling_ = this;
|
||||
// sibling->next_sibling_ = next_sibling_;
|
||||
// next_sibling_ = sibling;
|
||||
// sibling->next_sibling_->previous_sibling_ = sibling;
|
||||
// sibling->depth = depth;
|
||||
|
||||
// if (!parent_) {
|
||||
// sibling->op_first = new object_proxy();
|
||||
// sibling->op_last = sibling->op_marker = new object_proxy();
|
||||
// sibling->op_first->link(sibling->op_last);
|
||||
// } else {
|
||||
// throw object_exception("failed to add node as sibling: node has no parent");
|
||||
// }
|
||||
}
|
||||
|
||||
void schema_node::insert(const std::shared_ptr<schema_node> &child) {
|
||||
// child->parent_ = this;
|
||||
// child->previous_sibling_ = last_child_->previous_sibling_;
|
||||
// child->next_sibling_ = last_child_;
|
||||
// last_child_->previous_sibling_->next_sibling_ = child;
|
||||
// last_child_->previous_sibling_ = child;
|
||||
// set depth
|
||||
// child->depth = depth + 1;
|
||||
// set object proxy pointer
|
||||
// 1. first
|
||||
// if (op_first->next() == op_last) {
|
||||
// // node hasn't any serializable (proxy)
|
||||
// child->op_first = op_first;
|
||||
// } else {
|
||||
// // node has some objects (proxy)
|
||||
// child->op_first = op_last->prev();
|
||||
// }
|
||||
// // 2. marker
|
||||
// child->op_marker = op_last;
|
||||
// // 3. last
|
||||
// child->op_last = op_last;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
#include "matador/utils/default_type_traits.hpp"
|
||||
|
||||
#include "matador/utils/attribute_reader.hpp"
|
||||
#include "matador/utils/attribute_writer.hpp"
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
void data_type_traits<nullptr_t>::read_value(attribute_reader &/*reader*/, const char * /*id*/, size_t /*index*/, nullptr_t &/*value*/)
|
||||
{}
|
||||
|
||||
void data_type_traits<nullptr_t>::bind_value(attribute_writer &/*binder*/, size_t /*index*/, nullptr_t &/*value*/)
|
||||
{}
|
||||
|
||||
void data_type_traits<int8_t>::read_value(attribute_reader &reader, const char *id, const size_t index, int8_t &value)
|
||||
{
|
||||
reader.read_value(id, index, value);
|
||||
}
|
||||
|
||||
void data_type_traits<int8_t>::bind_value(attribute_writer &binder, const size_t index, const int8_t &value)
|
||||
{
|
||||
binder.write_value(index, value);
|
||||
}
|
||||
|
||||
void data_type_traits<int16_t>::read_value(attribute_reader &reader, const char *id, const size_t index, int16_t &value)
|
||||
{
|
||||
reader.read_value(id, index, value);
|
||||
}
|
||||
|
||||
void data_type_traits<int16_t>::bind_value(attribute_writer &binder, const size_t index, const int16_t &value)
|
||||
{
|
||||
binder.write_value(index, value);
|
||||
}
|
||||
|
||||
void data_type_traits<int32_t>::read_value(attribute_reader &reader, const char *id, const size_t index, int32_t &value)
|
||||
{
|
||||
reader.read_value(id, index, value);
|
||||
}
|
||||
|
||||
void data_type_traits<int32_t>::bind_value(attribute_writer &binder, const size_t index, const int32_t &value)
|
||||
{
|
||||
binder.write_value(index, value);
|
||||
}
|
||||
|
||||
void data_type_traits<int64_t>::read_value(attribute_reader &reader, const char *id, const size_t index, int64_t &value)
|
||||
{
|
||||
reader.read_value(id, index, value);
|
||||
}
|
||||
|
||||
void data_type_traits<int64_t>::bind_value(attribute_writer &binder, const size_t index, const int64_t &value)
|
||||
{
|
||||
binder.write_value(index, value);
|
||||
}
|
||||
|
||||
void data_type_traits<uint8_t>::read_value(attribute_reader &reader, const char *id, const size_t index, uint8_t &value)
|
||||
{
|
||||
reader.read_value(id, index, value);
|
||||
}
|
||||
|
||||
void data_type_traits<uint8_t>::bind_value(attribute_writer &binder, const size_t index, const uint8_t &value)
|
||||
{
|
||||
binder.write_value(index, value);
|
||||
}
|
||||
|
||||
void data_type_traits<uint16_t>::read_value(attribute_reader &reader, const char *id, const size_t index, uint16_t &value)
|
||||
{
|
||||
reader.read_value(id, index, value);
|
||||
}
|
||||
|
||||
void data_type_traits<uint16_t>::bind_value(attribute_writer &binder, const size_t index, const uint16_t &value)
|
||||
{
|
||||
binder.write_value(index, value);
|
||||
}
|
||||
|
||||
void data_type_traits<uint32_t>::read_value(attribute_reader &reader, const char *id, const size_t index, uint32_t &value)
|
||||
{
|
||||
reader.read_value(id, index, value);
|
||||
}
|
||||
|
||||
void data_type_traits<uint32_t>::bind_value(attribute_writer &binder, const size_t index, const uint32_t &value)
|
||||
{
|
||||
binder.write_value(index, value);
|
||||
}
|
||||
|
||||
void data_type_traits<uint64_t>::read_value(attribute_reader &reader, const char *id, const size_t index, uint64_t &value)
|
||||
{
|
||||
reader.read_value(id, index, value);
|
||||
}
|
||||
|
||||
void data_type_traits<uint64_t>::bind_value(attribute_writer &binder, const size_t index, const uint64_t &value)
|
||||
{
|
||||
binder.write_value(index, value);
|
||||
}
|
||||
|
||||
void data_type_traits<bool>::read_value(attribute_reader &reader, const char *id, const size_t index, bool &value)
|
||||
{
|
||||
reader.read_value(id, index, value);
|
||||
}
|
||||
|
||||
void data_type_traits<bool>::bind_value(attribute_writer &binder, const size_t index, const bool &value)
|
||||
{
|
||||
binder.write_value(index, value);
|
||||
}
|
||||
|
||||
void data_type_traits<float>::read_value(attribute_reader &reader, const char *id, const size_t index, float &value)
|
||||
{
|
||||
reader.read_value(id, index, value);
|
||||
}
|
||||
|
||||
void data_type_traits<float>::bind_value(attribute_writer &binder, const size_t index, const float &value)
|
||||
{
|
||||
binder.write_value(index, value);
|
||||
}
|
||||
|
||||
void data_type_traits<double>::read_value(attribute_reader &reader, const char *id, const size_t index, double &value)
|
||||
{
|
||||
reader.read_value(id, index, value);
|
||||
}
|
||||
|
||||
void data_type_traits<double>::bind_value(attribute_writer &binder, const size_t index, const double &value)
|
||||
{
|
||||
binder.write_value(index, value);
|
||||
}
|
||||
|
||||
void data_type_traits<const char*>::read_value(attribute_reader &reader, const char *id, const size_t index, const char* value, const size_t size)
|
||||
{
|
||||
reader.read_value(id, index, const_cast<char*>(value), size);
|
||||
}
|
||||
|
||||
void data_type_traits<const char *>::bind_value(attribute_writer &binder, const size_t index, const char *value, const size_t size)
|
||||
{
|
||||
binder.write_value(index, value, size);
|
||||
}
|
||||
|
||||
void data_type_traits<char*>::read_value(attribute_reader &reader, const char *id, const size_t index, char* value, const size_t size)
|
||||
{
|
||||
reader.read_value(id, index, value, size);
|
||||
}
|
||||
|
||||
void data_type_traits<char *>::bind_value(attribute_writer &binder, const size_t index, const char *value, const size_t size)
|
||||
{
|
||||
binder.write_value(index, value, size);
|
||||
}
|
||||
|
||||
void data_type_traits<std::string>::read_value(attribute_reader &reader, const char *id, size_t index, std::string &value, size_t size)
|
||||
{
|
||||
reader.read_value(id, index, value, size);
|
||||
}
|
||||
|
||||
void data_type_traits<std::string>::bind_value(attribute_writer &binder, size_t index, std::string &value, size_t size)
|
||||
{
|
||||
binder.write_value(index, value, size);
|
||||
}
|
||||
|
||||
void data_type_traits<utils::blob, void>::read_value(attribute_reader &reader, const char *id, size_t index, utils::blob &value)
|
||||
{
|
||||
reader.read_value(id, index, value);
|
||||
}
|
||||
|
||||
void data_type_traits<utils::blob, void>::bind_value(attribute_writer &binder, size_t index, utils::blob &value)
|
||||
{
|
||||
binder.write_value(index, value);
|
||||
}
|
||||
|
||||
// void data_type_traits<matador::date>::read_value(attribute_reader &reader, const char *id, size_t index, date &value)
|
||||
// {
|
||||
// reader.read_value(id, index, value);
|
||||
// }
|
||||
//
|
||||
// void data_type_traits<matador::date>::bind_value(attribute_writer &binder, size_t index, date &value)
|
||||
// {
|
||||
// binder.write_value(index, value);
|
||||
// }
|
||||
//
|
||||
// void data_type_traits<matador::time>::read_value(attribute_reader &reader, const char *id, size_t index, time &value)
|
||||
// {
|
||||
// reader.read_value(id, index, value);
|
||||
// }
|
||||
//
|
||||
// void data_type_traits<matador::time>::bind_value(attribute_writer &binder, size_t index, time &value)
|
||||
// {
|
||||
// binder.write_value(index, value);
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
#include "matador/utils/error.hpp"
|
||||
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
std::string error::message() const {
|
||||
return ec_.message();
|
||||
}
|
||||
|
||||
std::string error::category() const {
|
||||
return ec_.category().name();
|
||||
}
|
||||
|
||||
std::error_code error::ec() const {
|
||||
return ec_;
|
||||
}
|
||||
|
||||
const std::vector<error> & error::error_trace() const {
|
||||
return error_trace_;
|
||||
}
|
||||
|
||||
std::optional<std::string> error::error_info(const std::string &key) const {
|
||||
const auto info = error_infos_.find(key);
|
||||
if (info == error_infos_.end()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return info->second;
|
||||
}
|
||||
|
||||
void error::add_error_info(const std::string &key, std::string value) {
|
||||
error_infos_[key] = std::move(value);
|
||||
}
|
||||
|
||||
void error::remove_error_info(const std::string &key) {
|
||||
error_infos_.erase(key);
|
||||
}
|
||||
|
||||
std::vector<std::string> error::error_info_keys() const {
|
||||
std::vector<std::string> keys;
|
||||
|
||||
std::transform(
|
||||
std::begin(error_infos_),
|
||||
std::end(error_infos_),
|
||||
std::back_inserter(keys),
|
||||
[](const auto &pair){return pair.first;});
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
bool operator==(const error &lhs, const error &rhs) {
|
||||
return lhs.ec_ == rhs.ec_;
|
||||
}
|
||||
|
||||
bool operator==(const error &lhs, const std::error_code &rhs) {
|
||||
return lhs.ec_ == rhs;
|
||||
}
|
||||
|
||||
bool operator==(const error &lhs, const std::error_condition &rhs) {
|
||||
return lhs.ec_ == rhs;
|
||||
}
|
||||
|
||||
bool operator!=(const error &lhs, const error &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
bool operator!=(const error &lhs, const std::error_code &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
bool operator!=(const error &lhs, const std::error_condition &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
bool operator<(const error &lhs, const error &rhs) {
|
||||
return lhs.ec_ < rhs.ec_;
|
||||
}
|
||||
|
||||
bool operator<(const error &lhs, const std::error_code &rhs) {
|
||||
return lhs.ec_ < rhs;
|
||||
}
|
||||
|
||||
// std::ostream & operator<<(std::ostream &out, const error &err) {
|
||||
// out << err.ec_ << " " << err.ec_.message();
|
||||
// return out;
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#include "matador/utils/errors.hpp"
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
const char * utils_category_impl::name() const noexcept {
|
||||
return "utils";
|
||||
}
|
||||
|
||||
std::string utils_category_impl::message(const int ev) const {
|
||||
switch (static_cast<utils_error>(ev)) {
|
||||
case (utils_error::InvalidVersionString):
|
||||
return "Invalid version string";
|
||||
default:
|
||||
return "Unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
const std::error_category & sql_category() {
|
||||
static utils_category_impl instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
std::error_code make_error_code(utils_error e) {
|
||||
return {static_cast<int>(e), sql_category()};
|
||||
}
|
||||
|
||||
std::error_condition make_error_condition(utils_error e) {
|
||||
return {static_cast<int>(e), sql_category()};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#include "matador/utils/field_attributes.hpp"
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
field_attributes::field_attributes(const size_t size)
|
||||
: size_(size)
|
||||
{}
|
||||
|
||||
field_attributes::field_attributes(const constraints options)
|
||||
: options_(options)
|
||||
{}
|
||||
|
||||
field_attributes::field_attributes(const size_t size, const constraints options)
|
||||
: size_(size), options_(options)
|
||||
{}
|
||||
|
||||
field_attributes& field_attributes::operator=(const size_t size) {
|
||||
size_ = size;
|
||||
options_ = constraints::NONE;
|
||||
return *this;
|
||||
}
|
||||
field_attributes& field_attributes::operator=(constraints opt) {
|
||||
options_ = opt;
|
||||
size_ = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
size_t field_attributes::size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
constraints field_attributes::options() const
|
||||
{
|
||||
return options_;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
#include "matador/utils/identifier.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <ostream>
|
||||
|
||||
namespace matador::utils {
|
||||
size_t detail::hash(const char *value) {
|
||||
return std::hash<std::string_view>()(std::string_view(value, std::strlen(value)));
|
||||
}
|
||||
|
||||
bool identifier_type_traits<const char*>::is_valid(const char *value) {
|
||||
return value != nullptr && strlen(value) > 0;
|
||||
}
|
||||
|
||||
std::string identifier_type_traits<const char*>::to_string(const char *value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
identifier::base::base(const std::type_index &ti, const basic_type type)
|
||||
: type_index_(ti)
|
||||
, type_(type)
|
||||
{}
|
||||
|
||||
identifier::null_pk::null_pk()
|
||||
: base(std::type_index(typeid(null_type_t)), basic_type::type_null)
|
||||
{}
|
||||
|
||||
identifier::base* identifier::null_pk::copy() const
|
||||
{
|
||||
return new null_pk;
|
||||
}
|
||||
|
||||
bool identifier::null_pk::equal_to(const base &x) const
|
||||
{
|
||||
return type_index_ == x.type_index_;
|
||||
}
|
||||
|
||||
bool identifier::null_pk::less(const base &x) const
|
||||
{
|
||||
return type_index_ == x.type_index_;
|
||||
}
|
||||
|
||||
bool identifier::null_pk::is_valid() const
|
||||
{
|
||||
return identifier_type_traits<null_type_t>::is_valid();
|
||||
}
|
||||
|
||||
std::string identifier::null_pk::str() const
|
||||
{
|
||||
return identifier_type_traits<null_type_t>::to_string();
|
||||
}
|
||||
|
||||
void identifier::null_pk::serialize(identifier_serializer &s)
|
||||
{
|
||||
s.serialize(null_, {});
|
||||
}
|
||||
|
||||
size_t identifier::null_pk::hash() const
|
||||
{
|
||||
return std::hash<nullptr_t>()(nullptr);
|
||||
}
|
||||
|
||||
identifier::identifier()
|
||||
: id_(std::make_shared<null_pk>()) {}
|
||||
|
||||
identifier::identifier(const identifier &x)
|
||||
: id_(x.id_->copy()) {}
|
||||
|
||||
identifier &identifier::operator=(const identifier &x) {
|
||||
if (this == &x) {
|
||||
return *this;
|
||||
}
|
||||
id_.reset(x.id_->copy());
|
||||
return *this;
|
||||
}
|
||||
|
||||
identifier::identifier(identifier &&x) noexcept
|
||||
: id_(std::move(x.id_)) {
|
||||
x.clear();
|
||||
}
|
||||
|
||||
identifier &identifier::operator=(identifier &&x) noexcept {
|
||||
id_ = std::move(x.id_);
|
||||
x.clear();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool identifier::operator==(const identifier &x) const {
|
||||
return id_->equal_to(*x.id_);
|
||||
}
|
||||
|
||||
bool identifier::operator!=(const identifier &x) const {
|
||||
return !operator==(x);
|
||||
}
|
||||
|
||||
bool identifier::operator<(const identifier &x) const {
|
||||
return id_->less(*x.id_);
|
||||
}
|
||||
|
||||
bool identifier::operator<=(const identifier &x) const {
|
||||
return operator==(x) || operator<(x);
|
||||
}
|
||||
|
||||
bool identifier::operator>(const identifier &x) const {
|
||||
return !operator<=(x);
|
||||
}
|
||||
|
||||
bool identifier::operator>=(const identifier &x) const {
|
||||
return !operator<(x);
|
||||
}
|
||||
|
||||
std::string identifier::str() const {
|
||||
return id_->str();
|
||||
}
|
||||
|
||||
const std::type_index &identifier::type_index() const {
|
||||
return id_->type_index_;
|
||||
}
|
||||
|
||||
basic_type identifier::type() const {
|
||||
return id_->type_;
|
||||
}
|
||||
|
||||
identifier identifier::share() const
|
||||
{
|
||||
return identifier(id_);
|
||||
}
|
||||
|
||||
size_t identifier::use_count() const
|
||||
{
|
||||
return id_.use_count();
|
||||
}
|
||||
|
||||
bool identifier::is_integer() const {
|
||||
return id_->type_ >= basic_type::type_int8 && id_->type_ <= basic_type::type_uint64;
|
||||
}
|
||||
|
||||
bool identifier::is_floating_point() const {
|
||||
return id_->type_ == basic_type::type_float || id_->type_ == basic_type::type_double;
|
||||
}
|
||||
|
||||
bool identifier::is_bool() const {
|
||||
return id_->type_ == basic_type::type_bool;
|
||||
}
|
||||
|
||||
bool identifier::is_varchar() const {
|
||||
return id_->type_ == basic_type::type_varchar;
|
||||
}
|
||||
|
||||
bool identifier::is_date() const {
|
||||
return id_->type_ == basic_type::type_date;
|
||||
}
|
||||
|
||||
bool identifier::is_time() const {
|
||||
return id_->type_ == basic_type::type_time;
|
||||
}
|
||||
|
||||
bool identifier::is_blob() const {
|
||||
return id_->type_ == basic_type::type_blob;
|
||||
}
|
||||
|
||||
bool identifier::is_null() const
|
||||
{
|
||||
return type_index() == null_identifier.type_index();
|
||||
}
|
||||
|
||||
bool identifier::is_valid() const
|
||||
{
|
||||
return id_->is_valid();
|
||||
}
|
||||
|
||||
void identifier::clear()
|
||||
{
|
||||
id_ = std::make_unique<null_pk>();
|
||||
}
|
||||
|
||||
void identifier::serialize(identifier_serializer &s) const {
|
||||
id_->serialize(s);
|
||||
}
|
||||
|
||||
size_t identifier::hash() const
|
||||
{
|
||||
return id_->hash();
|
||||
}
|
||||
|
||||
identifier::identifier(const std::shared_ptr<base> &id)
|
||||
: id_(id)
|
||||
{}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const identifier &id)
|
||||
{
|
||||
out << id.str();
|
||||
return out;
|
||||
}
|
||||
|
||||
size_t id_pk_hash::operator()(const identifier &id) const
|
||||
{
|
||||
return id.hash();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
#include "matador/utils/library.hpp"
|
||||
#include "matador/utils/os.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
library::library(std::string lib)
|
||||
: lib_(std::move(lib))
|
||||
{}
|
||||
|
||||
library::~library()
|
||||
{
|
||||
unload();
|
||||
}
|
||||
|
||||
bool library::load()
|
||||
{
|
||||
auto path = os::getenv("MATADOR_BACKENDS_PATH");
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
auto cookie = AddDllDirectory(std::wstring(path.begin(), path.end()).c_str());
|
||||
handle_ = LoadLibraryExA((lib_ + ".dll").c_str(), nullptr, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
|
||||
RemoveDllDirectory(cookie);
|
||||
#elif defined(__APPLE__)
|
||||
handle_ = dlopen(std::string("lib" + lib_ + ".dylib").c_str(), RTLD_LAZY);
|
||||
#else
|
||||
handle_ = dlopen((path + "/lib" + lib_ + ".so").c_str(), RTLD_LAZY);
|
||||
#endif
|
||||
if (!handle_) {
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
DWORD errorMessageID = ::GetLastError();
|
||||
auto errstr = utils::os::error_string(errorMessageID);
|
||||
#else
|
||||
// TODO: handle win32 and linux error
|
||||
fprintf(stdout, "dlopen error: %s", dlerror());
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool library::load(const std::string &lib)
|
||||
{
|
||||
if (handle_) {
|
||||
return false;
|
||||
}
|
||||
lib_ = lib;
|
||||
return load();
|
||||
}
|
||||
|
||||
bool library::unload()
|
||||
{
|
||||
bool ret(true);
|
||||
if (handle_) {
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
ret = FreeLibrary(handle_) == TRUE;
|
||||
#else
|
||||
ret = dlclose(handle_) == 0;
|
||||
#endif
|
||||
if (!ret) {
|
||||
} else {
|
||||
handle_ = nullptr;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
func_ptr library::function(const std::string &f) const
|
||||
{
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
return GetProcAddress(handle_, f.c_str());
|
||||
#else
|
||||
return dlsym(handle_, f.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,360 @@
|
||||
#include "matador/utils/os.hpp"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace matador::utils::os {
|
||||
|
||||
void setenv(const char *name, const char *value, override_env_value override_value)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
_putenv_s(name, value);
|
||||
#else
|
||||
::setenv(name, value, static_cast<int>(override_value));
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
std::string error_string(unsigned long error) {
|
||||
char* lpMsgBuf;
|
||||
auto bufLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
nullptr,
|
||||
error,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
nullptr);
|
||||
std::string result;
|
||||
if (bufLen) {
|
||||
result.append(lpMsgBuf, lpMsgBuf+bufLen);
|
||||
LocalFree(lpMsgBuf);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string getenv(const char *name) {
|
||||
#ifdef _WIN32
|
||||
char var[1024];
|
||||
size_t len{};
|
||||
const auto error = getenv_s(&len, var, 1024, name);
|
||||
if (error > 0) {
|
||||
throw std::logic_error(error_string(error));
|
||||
};
|
||||
|
||||
return var;
|
||||
#else
|
||||
const char *path = ::getenv(name);
|
||||
return path == nullptr ? "" : path;
|
||||
#endif
|
||||
}
|
||||
|
||||
void unsetenv(const char *name)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
_putenv_s(name, nullptr);
|
||||
#else
|
||||
::unsetenv(name);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace matador::os {
|
||||
FILE* fopen(const std::string &path, const char *modes)
|
||||
{
|
||||
return fopen(path.c_str(), modes);
|
||||
}
|
||||
|
||||
FILE* fopen(const char *path, const char *modes)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return _fsopen(path, modes, _SH_DENYWR);
|
||||
#else
|
||||
return ::fopen(path, modes);
|
||||
#endif
|
||||
}
|
||||
|
||||
FILE* freopen(const std::string &path, const char *modes, FILE *stream)
|
||||
{
|
||||
return os::freopen(path.c_str(), modes, stream);
|
||||
}
|
||||
|
||||
FILE* freopen(const char *path, const char *modes, FILE *stream)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FILE* redirected_stream;
|
||||
freopen_s(&redirected_stream, path, "w+", stream);
|
||||
return redirected_stream;
|
||||
#else
|
||||
return ::freopen(path, modes, stream);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool fclose(FILE *f)
|
||||
{
|
||||
return ::fclose(f) == 0;
|
||||
}
|
||||
|
||||
bool remove(const std::string &name)
|
||||
{
|
||||
return os::remove(name.c_str());
|
||||
}
|
||||
|
||||
bool remove(const char *name)
|
||||
{
|
||||
return ::remove(name) == 0;
|
||||
}
|
||||
|
||||
bool rename(const std::string &old_name, const std::string &new_name)
|
||||
{
|
||||
return os::rename(old_name.c_str(), new_name.c_str());
|
||||
}
|
||||
|
||||
bool rename(const char *old_name, const char *new_name)
|
||||
{
|
||||
return ::rename(old_name, new_name) == 0;
|
||||
}
|
||||
|
||||
bool access(const std::string &path, int mode)
|
||||
{
|
||||
return os::access(path.c_str(), mode);
|
||||
}
|
||||
|
||||
bool access(const char *path, int mode)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return _access(path, mode) == 0;
|
||||
#else
|
||||
return ::access(path, mode) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int dup(FILE *stream)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return _dup(_fileno(stream));
|
||||
#else
|
||||
return ::dup(fileno(stream));
|
||||
#endif
|
||||
}
|
||||
|
||||
bool mkdir(const std::string &dirname)
|
||||
{
|
||||
return os::mkdir(dirname.c_str());
|
||||
}
|
||||
|
||||
bool mkdir(const char *dirname)
|
||||
{
|
||||
if (dirname == nullptr || strlen(dirname) == 0) {
|
||||
return true;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
return ::_mkdir(dirname) == 0;
|
||||
#else
|
||||
return ::mkdir(dirname, S_IRWXU) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool chdir(const std::string &dirname)
|
||||
{
|
||||
return os::chdir(dirname.c_str());
|
||||
}
|
||||
|
||||
bool chdir(const char *dirname)
|
||||
{
|
||||
if (dirname == nullptr || strlen(dirname) == 0) {
|
||||
return true;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
return _chdir(dirname) == 0;
|
||||
#else
|
||||
return ::chdir(dirname) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool rmdir(const std::string &dirname)
|
||||
{
|
||||
return os::rmdir(dirname.c_str());
|
||||
}
|
||||
|
||||
bool rmdir(const char *dirname)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return _rmdir(dirname) == 0;
|
||||
#else
|
||||
return ::rmdir(dirname) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string get_current_dir()
|
||||
{
|
||||
char buffer[1024];
|
||||
#ifdef _WIN32
|
||||
char *dir = _getcwd(buffer, 1024);
|
||||
#else
|
||||
char *dir = ::getcwd(buffer, 1024);
|
||||
#endif
|
||||
if (dir == nullptr) {
|
||||
#ifdef _WIN32
|
||||
::strerror_s(buffer, 1024, errno);
|
||||
throw std::logic_error(buffer);
|
||||
#else
|
||||
throw std::logic_error(::strerror(errno));
|
||||
#endif
|
||||
}
|
||||
return std::string(buffer);
|
||||
}
|
||||
|
||||
bool mkpath(const std::string &path)
|
||||
{
|
||||
return os::mkpath(path.c_str());
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
char DIR_SEPARATOR = '\\';
|
||||
const char* DIR_SEPARATOR_STRING = "\\";
|
||||
#else
|
||||
char DIR_SEPARATOR = '/';
|
||||
const char* DIR_SEPARATOR_STRING = "/";
|
||||
#endif
|
||||
|
||||
bool mkpath(const char *path)
|
||||
{
|
||||
char tmp[256];
|
||||
char *p = nullptr;
|
||||
size_t len;
|
||||
|
||||
snprintf(tmp, sizeof(tmp),"%s",path);
|
||||
len = strlen(tmp);
|
||||
if (len == 0) {
|
||||
return true;
|
||||
}
|
||||
if(tmp[len - 1] == DIR_SEPARATOR) {
|
||||
tmp[len - 1] = 0;
|
||||
}
|
||||
for(p = tmp + 1; *p; p++) {
|
||||
if (*p == DIR_SEPARATOR) {
|
||||
*p = 0;
|
||||
if (!os::mkdir(tmp)) {
|
||||
return false;
|
||||
}
|
||||
*p = DIR_SEPARATOR;
|
||||
}
|
||||
}
|
||||
return os::mkdir(tmp);
|
||||
}
|
||||
|
||||
bool rmpath(const std::string &path)
|
||||
{
|
||||
return os::rmpath(path.c_str());
|
||||
}
|
||||
|
||||
bool rmpath(const char *path)
|
||||
{
|
||||
// change next to last path segment
|
||||
|
||||
std::vector<char> pathcopy(path, path+::strlen(path)+1);
|
||||
std::vector<std::string> segments;
|
||||
#ifdef _WIN32
|
||||
char *next_token = nullptr;
|
||||
char *segment = ::strtok_s(pathcopy.data(), DIR_SEPARATOR_STRING, &next_token);
|
||||
#else
|
||||
char *segment = ::strtok(pathcopy.data(), DIR_SEPARATOR_STRING);
|
||||
#endif
|
||||
|
||||
while (segment != nullptr) {
|
||||
os::chdir(segment);
|
||||
segments.emplace_back(segment);
|
||||
#ifdef _WIN32
|
||||
segment = ::strtok_s(nullptr, DIR_SEPARATOR_STRING, &next_token);
|
||||
#else
|
||||
segment = ::strtok(nullptr, DIR_SEPARATOR_STRING);
|
||||
#endif
|
||||
}
|
||||
|
||||
auto first = segments.rbegin();
|
||||
for (auto it=first; it!=segments.rend(); ++it) {
|
||||
os::chdir("..");
|
||||
os::rmdir(*it);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_readable(const std::string &path)
|
||||
{
|
||||
return is_readable(path.c_str());
|
||||
}
|
||||
|
||||
bool is_readable(const char *path)
|
||||
{
|
||||
return os::access(path, 2);
|
||||
}
|
||||
|
||||
bool is_writable(const std::string &path)
|
||||
{
|
||||
return is_writable(path.c_str());
|
||||
}
|
||||
|
||||
bool is_writable(const char *path)
|
||||
{
|
||||
return os::access(path, 4);
|
||||
}
|
||||
|
||||
bool exists(const std::string &path)
|
||||
{
|
||||
return exists(path.c_str());
|
||||
}
|
||||
|
||||
bool exists(const char *path)
|
||||
{
|
||||
return os::access(path, 0);
|
||||
}
|
||||
|
||||
size_t file_size(FILE *stream)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
int fd = _fileno(stream);
|
||||
return ::_filelength(fd);
|
||||
#else
|
||||
int fd = ::fileno(stream);
|
||||
struct stat buf{};
|
||||
::fstat(fd, &buf);
|
||||
return buf.st_size;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string build_path(const std::string &a, const std::string &b)
|
||||
{
|
||||
return a + DIR_SEPARATOR_STRING + b;
|
||||
}
|
||||
|
||||
char* strerror(int err, char* errbuf, size_t bufsize)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
::strerror_s(errbuf, bufsize, err);
|
||||
return errbuf;
|
||||
#else
|
||||
auto msg = ::strerror(err);
|
||||
auto s = strlen(msg);
|
||||
if (s < bufsize - 1) {
|
||||
return strcpy(errbuf, msg);
|
||||
} else {
|
||||
errbuf[bufsize - 1] = '\0';
|
||||
return strncpy(errbuf, msg, bufsize - 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
#include "matador/utils/string.hpp"
|
||||
#include "matador/utils/export.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace matador::utils {
|
||||
std::string to_string(const blob& data) {
|
||||
static constexpr char HEXITS[] = "0123456789ABCDEF";
|
||||
|
||||
std::string str(2 * data.size(), '\0');
|
||||
auto item = str.begin();
|
||||
|
||||
for(const auto c : data) {
|
||||
*item++ = HEXITS[c >> 4];
|
||||
*item++ = HEXITS[c & 0x0F];
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
size_t split(const std::string &str, char delim, std::vector<std::string> &values)
|
||||
{
|
||||
std::stringstream ss(str);
|
||||
std::string item;
|
||||
while (std::getline(ss, item, delim)) {
|
||||
values.push_back(item);
|
||||
}
|
||||
return values.size();
|
||||
}
|
||||
|
||||
std::vector<std::string> split(const std::string &str, char delim)
|
||||
{
|
||||
std::stringstream ss(str);
|
||||
std::string item;
|
||||
std::vector<std::string> result;
|
||||
while (std::getline(ss, item, delim)) {
|
||||
result.push_back(item);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t split(const std::string &str, const char delim, std::list<std::string> &values)
|
||||
{
|
||||
std::stringstream ss(str);
|
||||
std::string item;
|
||||
while (std::getline(ss, item, delim)) {
|
||||
values.push_back(item);
|
||||
}
|
||||
return values.size();
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// const char* date_format::ISO8601 = "%Y-%m-%d";
|
||||
// const char* time_format::ISO8601 = "%Y-%m-%dT%H:%M:%S";
|
||||
#endif
|
||||
|
||||
std::string trim(const std::string& str, const std::string& whitespace)
|
||||
{
|
||||
const auto first = str.find_first_not_of(whitespace);
|
||||
if (first == std::string::npos)
|
||||
return ""; // no content
|
||||
|
||||
const auto end = str.find_last_not_of(whitespace);
|
||||
const auto range = end - first + 1;
|
||||
|
||||
return str.substr(first, range);
|
||||
}
|
||||
|
||||
void replace_all(std::string &in, const std::string &from, const std::string &to)
|
||||
{
|
||||
if(from.empty()) {
|
||||
return;
|
||||
}
|
||||
size_t start_pos = 0;
|
||||
while((start_pos = in.find(from, start_pos)) != std::string::npos) {
|
||||
in.replace(start_pos, from.length(), to);
|
||||
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "matador/utils/types.hpp"
|
||||
#include "matador/utils/basic_types.hpp"
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
void initialize_by_basic_type(const basic_type type, database_type &val)
|
||||
{
|
||||
switch (type) {
|
||||
case basic_type::type_int8:
|
||||
val.emplace<int8_t>();
|
||||
break;
|
||||
case basic_type::type_int16:
|
||||
val.emplace<int16_t>();
|
||||
break;
|
||||
case basic_type::type_int32:
|
||||
val.emplace<int32_t>();
|
||||
break;
|
||||
case basic_type::type_int64:
|
||||
val.emplace<int64_t>();
|
||||
break;
|
||||
case basic_type::type_uint8:
|
||||
val.emplace<uint8_t>();
|
||||
break;
|
||||
case basic_type::type_uint16:
|
||||
val.emplace<uint16_t>();
|
||||
break;
|
||||
case basic_type::type_uint32:
|
||||
val.emplace<uint32_t>();
|
||||
break;
|
||||
case basic_type::type_uint64:
|
||||
val.emplace<uint64_t>();
|
||||
break;
|
||||
case basic_type::type_bool:
|
||||
val.emplace<bool>();
|
||||
break;
|
||||
case basic_type::type_float:
|
||||
val.emplace<float>();
|
||||
break;
|
||||
case basic_type::type_double:
|
||||
val.emplace<double>();
|
||||
break;
|
||||
case basic_type::type_varchar:
|
||||
case basic_type::type_text:
|
||||
val.emplace<std::string>();
|
||||
break;
|
||||
// case basic_type::type_date:
|
||||
// val.emplace<date>();
|
||||
// break;
|
||||
// case basic_type::type_time:
|
||||
// val.emplace<time>();
|
||||
// break;
|
||||
case basic_type::type_blob:
|
||||
val.emplace<utils::blob>();
|
||||
break;
|
||||
default:
|
||||
val.emplace<nullptr_t>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
#include "matador/utils/value.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace matador::utils {
|
||||
namespace detail {
|
||||
|
||||
size_t determine_size(const std::string &val)
|
||||
{
|
||||
return val.size();
|
||||
}
|
||||
|
||||
size_t determine_size(const char *val)
|
||||
{
|
||||
return strlen(val);
|
||||
}
|
||||
|
||||
size_t determine_size(const blob &val)
|
||||
{
|
||||
return val.size();
|
||||
}
|
||||
|
||||
}
|
||||
value::value(const basic_type data_type, const size_t size)
|
||||
: size_(size)
|
||||
, type_(data_type)
|
||||
{
|
||||
initialize_by_basic_type(type_, value_);
|
||||
}
|
||||
|
||||
value::value(value &&x) noexcept
|
||||
: value_(std::move(x.value_))
|
||||
, type_(x.type_)
|
||||
{
|
||||
x.value_ = nullptr;
|
||||
x.type_ = basic_type::type_null;
|
||||
}
|
||||
|
||||
value &value::operator=(value &&x) noexcept
|
||||
{
|
||||
value_ = std::move(x.value_);
|
||||
type_ = x.type_;
|
||||
x.value_ = nullptr;
|
||||
x.type_ = basic_type::type_null;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::string value::str() const
|
||||
{
|
||||
return as<std::string>().value_or("");
|
||||
}
|
||||
|
||||
size_t value::size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
basic_type value::type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
bool value::is_integer() const
|
||||
{
|
||||
return type_ >= basic_type::type_int8 && type_ <= basic_type::type_uint64;
|
||||
}
|
||||
|
||||
bool value::is_floating_point() const
|
||||
{
|
||||
return type_ == basic_type::type_float || type_ == basic_type::type_double;
|
||||
}
|
||||
|
||||
bool value::is_bool() const
|
||||
{
|
||||
return type_ == basic_type::type_bool;
|
||||
}
|
||||
|
||||
bool value::is_string() const
|
||||
{
|
||||
return type_ == basic_type::type_text;
|
||||
}
|
||||
|
||||
bool value::is_varchar() const
|
||||
{
|
||||
return type_ == basic_type::type_varchar;
|
||||
}
|
||||
|
||||
bool value::is_date() const
|
||||
{
|
||||
return type_ == basic_type::type_date;
|
||||
}
|
||||
|
||||
bool value::is_time() const
|
||||
{
|
||||
return type_ == basic_type::type_time;
|
||||
}
|
||||
|
||||
bool value::is_blob() const
|
||||
{
|
||||
return type_ == basic_type::type_blob;
|
||||
}
|
||||
|
||||
bool value::is_null() const
|
||||
{
|
||||
return type_ == basic_type::type_null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
#include <matador/utils/version.hpp>
|
||||
|
||||
#include <matador/utils/errors.hpp>
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
version::version(unsigned int major, unsigned int minor, unsigned int patch)
|
||||
: major_(major)
|
||||
, minor_(minor)
|
||||
, patch_(patch)
|
||||
{}
|
||||
|
||||
bool version::operator==(const version &x) const
|
||||
{
|
||||
return major_ == x.major_ &&
|
||||
minor_ == x.minor_ &&
|
||||
patch_ == x.patch_;
|
||||
}
|
||||
|
||||
bool version::operator!=(const version &x) const
|
||||
{
|
||||
return !(*this == x);
|
||||
}
|
||||
|
||||
bool version::operator>(const version &x) const
|
||||
{
|
||||
return !(*this <= x);
|
||||
}
|
||||
|
||||
bool version::operator>=(const version &x) const
|
||||
{
|
||||
return !(*this < x);
|
||||
}
|
||||
|
||||
bool version::operator<(const version &x) const
|
||||
{
|
||||
return (major_ < x.major_) ||
|
||||
(major_ == x.major_ && minor_ < x.minor_) ||
|
||||
(major_ == x.major_ && minor_ == x.minor_ && patch_ < x.patch_);
|
||||
}
|
||||
|
||||
bool version::operator<=(const version &x) const
|
||||
{
|
||||
return *this < x || *this == x;
|
||||
}
|
||||
|
||||
std::string version::str() const
|
||||
{
|
||||
char buf[32];
|
||||
sprintf(buf, "%d.%d.%d", major_, minor_, patch_);
|
||||
return buf;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const version &v)
|
||||
{
|
||||
out << v.str();
|
||||
return out;
|
||||
}
|
||||
|
||||
result<version, error> version::from_string(const std::string &version_string)
|
||||
{
|
||||
version result;
|
||||
if (const auto ret = sscanf(version_string.c_str(), "%u.%u.%u", &result.major_, &result.minor_, &result.patch_); ret != 3) {
|
||||
return failure(error(utils_error::InvalidVersionString, version_string));
|
||||
}
|
||||
|
||||
return ok(result);
|
||||
}
|
||||
|
||||
unsigned int version::major() const
|
||||
{
|
||||
return major_;
|
||||
}
|
||||
|
||||
unsigned int version::minor() const
|
||||
{
|
||||
return minor_;
|
||||
}
|
||||
|
||||
unsigned int version::patch() const
|
||||
{
|
||||
return patch_;
|
||||
}
|
||||
|
||||
void version::major(unsigned int m)
|
||||
{
|
||||
major_ = m;
|
||||
}
|
||||
|
||||
void version::minor(unsigned int m)
|
||||
{
|
||||
minor_ = m;
|
||||
}
|
||||
|
||||
void version::patch(unsigned int p)
|
||||
{
|
||||
patch_ = p;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
add_library(matador-orm STATIC
|
||||
../../include/matador/query/attribute_string_writer.hpp
|
||||
../../include/matador/query/basic_condition.hpp
|
||||
../../include/matador/query/condition.hpp
|
||||
../../include/matador/query/fk_value_extractor.hpp
|
||||
../../include/matador/query/intermediates/executable_query.hpp
|
||||
../../include/matador/query/intermediates/executable_query.hpp
|
||||
../../include/matador/query/intermediates/fetchable_query.hpp
|
||||
../../include/matador/query/intermediates/query_create_intermediate.hpp
|
||||
../../include/matador/query/intermediates/query_delete_from_intermediate.hpp
|
||||
../../include/matador/query/intermediates/query_delete_intermediate.hpp
|
||||
../../include/matador/query/intermediates/query_drop_intermediate.hpp
|
||||
../../include/matador/query/intermediates/query_execute_limit_intermediate.hpp
|
||||
../../include/matador/query/intermediates/query_execute_offset_intermediate.hpp
|
||||
../../include/matador/query/intermediates/query_execute_order_by_intermediate.hpp
|
||||
../../include/matador/query/intermediates/query_execute_order_direction_intermediate.hpp
|
||||
../../include/matador/query/intermediates/query_execute_where_intermediate.hpp
|
||||
../../include/matador/query/intermediates/query_from_intermediate.hpp
|
||||
../../include/matador/query/intermediates/query_group_by_intermediate.hpp
|
||||
../../include/matador/query/intermediates/query_insert_intermediate.hpp
|
||||
../../include/matador/query/intermediates/query_intermediate.hpp
|
||||
../../include/matador/query/intermediates/query_into_intermediate.hpp
|
||||
../../include/matador/query/intermediates/query_join_intermediate.hpp
|
||||
../../include/matador/query/intermediates/query_limit_intermediate.hpp
|
||||
../../include/matador/query/intermediates/query_offset_intermediate.hpp
|
||||
../../include/matador/query/intermediates/query_order_by_intermediate.hpp
|
||||
../../include/matador/query/intermediates/query_order_direction_intermediate.hpp
|
||||
../../include/matador/query/intermediates/query_select_intermediate.hpp
|
||||
../../include/matador/query/intermediates/query_set_intermediate.hpp
|
||||
../../include/matador/query/intermediates/query_update_intermediate.hpp
|
||||
../../include/matador/query/intermediates/query_where_intermediate.hpp
|
||||
../../include/matador/query/internal/basic_type_to_string_visitor.hpp
|
||||
../../include/matador/query/internal/key_value_pair.hpp
|
||||
../../include/matador/query/internal/query_parts.hpp
|
||||
../../include/matador/query/join_data.hpp
|
||||
../../include/matador/query/key_value_generator.hpp
|
||||
../../include/matador/query/query.hpp
|
||||
../../include/matador/query/query_compiler.hpp
|
||||
../../include/matador/query/query_data.hpp
|
||||
../../include/matador/query/query_intermediates.hpp
|
||||
../../include/matador/query/query_part.hpp
|
||||
../../include/matador/query/value_extractor.hpp
|
||||
../../include/matador/sql/abstract_sql_logger.hpp
|
||||
../../include/matador/sql/backend_provider.hpp
|
||||
../../include/matador/sql/column.hpp
|
||||
../../include/matador/sql/column_definition.hpp
|
||||
../../include/matador/sql/connection.hpp
|
||||
../../include/matador/sql/connection_info.hpp
|
||||
../../include/matador/sql/dialect.hpp
|
||||
../../include/matador/sql/dialect_builder.hpp
|
||||
../../include/matador/sql/dialect_token.hpp
|
||||
../../include/matador/sql/error_code.hpp
|
||||
../../include/matador/sql/executor.hpp
|
||||
../../include/matador/sql/field.hpp
|
||||
../../include/matador/sql/interface/connection_impl.hpp
|
||||
../../include/matador/sql/interface/parameter_binder.hpp
|
||||
../../include/matador/sql/interface/query_result_reader.hpp
|
||||
../../include/matador/sql/interface/statement_impl.hpp
|
||||
../../include/matador/sql/internal/object_result_binder.hpp
|
||||
../../include/matador/sql/internal/query_result_impl.hpp
|
||||
../../include/matador/sql/query_context.hpp
|
||||
../../include/matador/sql/query_result.hpp
|
||||
../../include/matador/sql/record.hpp
|
||||
../../include/matador/sql/statement.hpp
|
||||
../../include/matador/sql/table.hpp
|
||||
query/attribute_string_writer.cpp
|
||||
query/basic_condition.cpp
|
||||
query/condition.cpp
|
||||
query/fk_value_extractor.cpp
|
||||
query/intermediates/executable_query.cpp
|
||||
query/intermediates/fetchable_query.cpp
|
||||
query/intermediates/query_create_intermediate.cpp
|
||||
query/intermediates/query_delete_from_intermediate.cpp
|
||||
query/intermediates/query_delete_intermediate.cpp
|
||||
query/intermediates/query_drop_intermediate.cpp
|
||||
query/intermediates/query_execute_limit_intermediate.cpp
|
||||
query/intermediates/query_execute_offset_intermediate.cpp
|
||||
query/intermediates/query_execute_order_by_intermediate.cpp
|
||||
query/intermediates/query_execute_order_direction_intermediate.cpp
|
||||
query/intermediates/query_execute_where_intermediate.cpp
|
||||
query/intermediates/query_from_intermediate.cpp
|
||||
query/intermediates/query_group_by_intermediate.cpp
|
||||
query/intermediates/query_insert_intermediate.cpp
|
||||
query/intermediates/query_intermediate.cpp
|
||||
query/intermediates/query_into_intermediate.cpp
|
||||
query/intermediates/query_join_intermediate.cpp
|
||||
query/intermediates/query_limit_intermediate.cpp
|
||||
query/intermediates/query_offset_intermediate.cpp
|
||||
query/intermediates/query_order_by_intermediate.cpp
|
||||
query/intermediates/query_order_direction_intermediate.cpp
|
||||
query/intermediates/query_select_intermediate.cpp
|
||||
query/intermediates/query_set_intermediate.cpp
|
||||
query/intermediates/query_where_intermediate.cpp
|
||||
query/internal/basic_type_to_string_visitor.cpp
|
||||
query/internal/key_value_pair.cpp
|
||||
query/internal/query_parts.cpp
|
||||
query/internal/query_result_impl.cpp
|
||||
query/key_value_generator.cpp
|
||||
query/query.cpp
|
||||
query/query_compiler.cpp
|
||||
query/query_part.cpp
|
||||
query/query_update_intermediate.cpp
|
||||
query/value_extractor.cpp
|
||||
sql/backend_provider.cpp
|
||||
sql/column.cpp
|
||||
sql/column_definition.cpp
|
||||
sql/connection.cpp
|
||||
sql/connection_info.cpp
|
||||
sql/dialect.cpp
|
||||
sql/dialect_builder.cpp
|
||||
sql/executor.cpp
|
||||
sql/field.cpp
|
||||
sql/interface/connection_impl.cpp
|
||||
sql/interface/query_result_reader.cpp
|
||||
sql/interface/statement_impl.cpp
|
||||
sql/internal/object_result_binder.cpp
|
||||
sql/object_parameter_binder.cpp
|
||||
sql/query_result.cpp
|
||||
sql/record.cpp
|
||||
sql/statement.cpp
|
||||
sql/table.cpp
|
||||
sql/error_code.cpp
|
||||
)
|
||||
|
||||
target_include_directories(matador-orm
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../include
|
||||
)
|
||||
|
||||
target_link_libraries(matador-orm matador-core)
|
||||
@@ -0,0 +1,109 @@
|
||||
#include "matador/query/attribute_string_writer.hpp"
|
||||
|
||||
// #include "matador/sql/connection_impl.hpp"
|
||||
#include <matador/utils/convert.hpp>
|
||||
|
||||
|
||||
#include "matador/sql/dialect.hpp"
|
||||
|
||||
#include "matador/utils/string.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
attribute_string_writer::attribute_string_writer(const sql::dialect &d, const std::optional<std::reference_wrapper<const sql::connection_impl>> conn)
|
||||
: dialect_(d)
|
||||
, conn_(conn) {}
|
||||
|
||||
const sql::dialect& attribute_string_writer::dialect() const {
|
||||
return dialect_;
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const int8_t& x ) {
|
||||
result_ = std::to_string(x) ;
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const int16_t& x ) {
|
||||
result_ = std::to_string(x) ;
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const int32_t& x ) {
|
||||
result_ = std::to_string(x) ;
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const int64_t& x ) {
|
||||
result_ = std::to_string(x) ;
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const uint8_t& x ) {
|
||||
result_ = std::to_string(x) ;
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const uint16_t& x ) {
|
||||
result_ = std::to_string(x) ;
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const uint32_t& x ) {
|
||||
result_ = std::to_string(x) ;
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const uint64_t& x ) {
|
||||
result_ = std::to_string(x) ;
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const bool& x ) {
|
||||
// result_ = "'" + conn_->dialect().prepare_literal(x ? "true" : "false") + "'";
|
||||
result_ = dialect_.to_string(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()) {
|
||||
result_ = *res;
|
||||
}
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const double& x ) {
|
||||
if (const auto res = utils::to<std::string>(x); res.is_error()) {
|
||||
result_ = *res;
|
||||
}
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const time& /*x*/ ) {
|
||||
// result_ = "'" + dialect_.prepare_literal(utils::to_string(x, "%F %T.%f")) + "'";
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const date& /*x*/ ) {
|
||||
// result_ = "'" + dialect_.prepare_literal(utils::to_string(x)) + "'";
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t pos, const char* x ) {
|
||||
write_value(pos, std::string(x) );
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t pos, const char* x, size_t /*size*/) {
|
||||
write_value(pos, std::string(x) );
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const std::string& x ) {
|
||||
result_ = "'" + dialect_.prepare_literal(x) + "'";
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const std::string& x, size_t /*size*/) {
|
||||
result_ = "'" + dialect_.prepare_literal(x) + "'";
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const utils::blob& x ) {
|
||||
// "This is a binary Data string" as binary data:
|
||||
// MySQL: X'5468697320697320612062616E617279204461746120737472696E67'
|
||||
// Postgres: '\\x5468697320697320612062616E617279204461746120737472696E67'
|
||||
// MSSQL: 0x5468697320697320612062616E617279204461746120737472696E67
|
||||
// Sqlite: X'5468697320697320612062616E617279204461746120737472696E67'
|
||||
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);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const utils::value &/*x*/, size_t /*size*/) {}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "matador/query/basic_condition.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
std::unordered_map<basic_condition::operand_type, std::string> basic_condition::operands{
|
||||
{operand_type::EQUAL, "="},
|
||||
{operand_type::NOT_EQUAL, "<>"},
|
||||
{operand_type::LESS, "<"},
|
||||
{operand_type::LESS_EQUAL, "<="},
|
||||
{operand_type::GREATER, ">"},
|
||||
{operand_type::GREATER_EQUAL, ">="},
|
||||
{operand_type::OR, "OR"},
|
||||
{operand_type::AND, "AND"},
|
||||
{operand_type::NOT, "NOT"},
|
||||
{operand_type::IN_LIST, "IN"},
|
||||
{operand_type::LIKE, "LIKE"}
|
||||
};
|
||||
|
||||
basic_column_condition::basic_column_condition(sql::column fld, const operand_type op)
|
||||
: field_(std::move(fld)), operand(operands[op])
|
||||
{ }
|
||||
|
||||
basic_in_condition::basic_in_condition(sql::column fld)
|
||||
: field_(std::move(fld))
|
||||
{ }
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#include "matador/query/condition.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
condition<sql::column, utils::placeholder>::condition(const sql::column &fld, const operand_type op, const utils::placeholder &val)
|
||||
: basic_column_condition(fld, op), value(val)
|
||||
{}
|
||||
|
||||
std::string condition<sql::column, utils::placeholder>::evaluate(const sql::dialect &d, sql::query_context &query) const
|
||||
{
|
||||
query.bind_vars.emplace_back(field_.name);
|
||||
return d.prepare_identifier(field_) + " " + operand + " " + d.next_placeholder(query.bind_vars);
|
||||
}
|
||||
|
||||
condition<sql::column, sql::query_context>::condition(sql::column col, const operand_type op, sql::query_context &q)
|
||||
: basic_column_condition(std::move(col), op), query_(q)
|
||||
{}
|
||||
|
||||
std::string condition<sql::column, sql::query_context>::evaluate(const sql::dialect &d, sql::query_context &/*query*/) const
|
||||
{
|
||||
std::string result(d.prepare_identifier(field_) + " " + operand + " (");
|
||||
result += query_.sql;
|
||||
result += ")";
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string condition<sql::column, sql::column>::evaluate(const sql::dialect &d, sql::query_context &/*query*/) const {
|
||||
return d.prepare_condition(field_) + " " + operand + " " + d.prepare_condition(other_column_);
|
||||
}
|
||||
|
||||
condition<sql::column, sql::query_context> in(const sql::column &col, sql::query_context &&q)
|
||||
{
|
||||
return {col, basic_condition::operand_type::IN_LIST, q};
|
||||
}
|
||||
|
||||
condition<sql::column, std::string> like(const sql::column &col, const std::string &val) {
|
||||
return { col, basic_condition::operand_type::LIKE, val };
|
||||
}
|
||||
|
||||
condition<sql::column, sql::column> operator==(const sql::column &a, const sql::column &b)
|
||||
{
|
||||
return {a, basic_condition::operand_type::EQUAL, b};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#include "matador/query/fk_value_extractor.hpp"
|
||||
|
||||
namespace matador::query::detail {
|
||||
|
||||
void fk_value_extractor::on_primary_key(const char *, std::string &pk, size_t)
|
||||
{
|
||||
value_ = pk;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "matador/query/intermediates/executable_query.hpp"
|
||||
#include "matador/query/query_compiler.hpp"
|
||||
|
||||
#include "matador/sql/executor.hpp"
|
||||
#include "matador/sql/statement.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
utils::result<size_t, utils::error> executable_query::execute(const sql::executor &exec) const
|
||||
{
|
||||
query_compiler compiler;
|
||||
return exec.execute(compiler.compile(*context_, exec.dialect(), std::nullopt));
|
||||
}
|
||||
|
||||
utils::result<sql::statement, utils::error> executable_query::prepare(const sql::executor &exec) const
|
||||
{
|
||||
query_compiler compiler;
|
||||
return exec.prepare(compiler.compile(*context_, exec.dialect(), std::nullopt));
|
||||
}
|
||||
|
||||
std::string executable_query::str(const sql::executor &exec) const
|
||||
{
|
||||
query_compiler compiler;
|
||||
return exec.str(compiler.compile(*context_, exec.dialect(), std::nullopt));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
#include "../../../../include/matador/query/intermediates/fetchable_query.hpp"
|
||||
|
||||
#include "../../../../include/matador/sql/executor.hpp"
|
||||
#include "../../../../include/matador/sql/statement.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
utils::result<sql::query_result<sql::record>, utils::error> fetchable_query::fetch_all(const sql::executor &exec) const
|
||||
{
|
||||
query_compiler compiler;
|
||||
return exec.fetch(compiler.compile(*context_, exec.dialect(), std::nullopt))
|
||||
.and_then([](auto &&res) {
|
||||
return utils::ok(sql::query_result<sql::record>(std::forward<decltype(res)>(res)));
|
||||
});
|
||||
// if (!result.is_ok()) {
|
||||
// return utils::error(result.err());
|
||||
// }
|
||||
//
|
||||
// return utils::ok(query_result<record>(std::move(*result)));
|
||||
}
|
||||
|
||||
utils::result<std::optional<sql::record>, utils::error> fetchable_query::fetch_one(const sql::executor &exec) const
|
||||
{
|
||||
query_compiler compiler;
|
||||
auto result = exec.fetch(compiler.compile(*context_, exec.dialect(), std::nullopt));
|
||||
if (!result.is_ok()) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
|
||||
sql::query_result<sql::record> records(std::move(*result));
|
||||
auto first = records.begin();
|
||||
if (first == records.end()) {
|
||||
return utils::ok(std::optional<sql::record>{std::nullopt});
|
||||
}
|
||||
|
||||
return utils::ok(std::optional<sql::record>{*first.get()});
|
||||
}
|
||||
|
||||
std::string fetchable_query::str(const sql::executor &exec) const
|
||||
{
|
||||
query_compiler compiler;
|
||||
return exec.str(compiler.compile(*context_, exec.dialect(), std::nullopt));
|
||||
}
|
||||
|
||||
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> fetchable_query::fetch(const sql::executor &exec) const
|
||||
{
|
||||
query_compiler compiler;
|
||||
return exec.fetch(compiler.compile(*context_, exec.dialect(), std::nullopt));
|
||||
}
|
||||
|
||||
utils::result<sql::statement, utils::error> fetchable_query::prepare(const sql::executor &exec) const
|
||||
{
|
||||
query_compiler compiler;
|
||||
return exec.prepare(compiler.compile(*context_, exec.dialect(), std::nullopt));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#include "matador/query/intermediates/query_create_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_create_intermediate::query_create_intermediate()
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_create_part>());
|
||||
}
|
||||
|
||||
executable_query query_create_intermediate::table(const sql::table &table, const std::initializer_list<sql::column_definition> columns)
|
||||
{
|
||||
return this->table(table, std::vector<sql::column_definition>{columns});
|
||||
}
|
||||
|
||||
executable_query query_create_intermediate::table(const sql::table &table, const std::vector<sql::column_definition> &columns)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_create_table_part>(table, columns));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "matador/query/intermediates/query_delete_from_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_execute_where_intermediate query_delete_from_intermediate::where_clause(std::unique_ptr<basic_condition> &&cond)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_where_part>(std::move(cond)));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#include "matador/query/intermediates/query_delete_intermediate.hpp"
|
||||
|
||||
#include "matador/query/intermediates/query_delete_from_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_delete_intermediate::query_delete_intermediate()
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_delete_part>());
|
||||
}
|
||||
|
||||
query_delete_from_intermediate query_delete_intermediate::from(const sql::table &table)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_delete_from_part>(table));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#include "matador/query/intermediates/query_drop_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_drop_intermediate::query_drop_intermediate()
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_drop_part>());
|
||||
}
|
||||
|
||||
executable_query query_drop_intermediate::table(const sql::table &table)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_drop_table_part>(table));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "matador/query/intermediates/query_execute_limit_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_execute_offset_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_execute_offset_intermediate query_execute_limit_intermediate::offset(size_t offset) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_offset_part>(offset));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
} // namespace matador::query
|
||||
@@ -0,0 +1,11 @@
|
||||
#include "matador/query/intermediates/query_execute_offset_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_execute_limit_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
query_execute_limit_intermediate query_execute_offset_intermediate::limit(size_t limit) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_limit_part>(limit));
|
||||
return {context_};
|
||||
}
|
||||
} // namespace matador::query
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "matador/query/intermediates/query_execute_order_by_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_execute_order_direction_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_execute_order_direction_intermediate query_execute_order_by_intermediate::asc() {
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_asc_part>());
|
||||
return {context_};
|
||||
}
|
||||
query_execute_order_direction_intermediate query_execute_order_by_intermediate::desc() {
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_desc_part>());
|
||||
return {context_};
|
||||
}
|
||||
|
||||
} // namespace matador::query
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "matador/query/intermediates/query_execute_order_direction_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_execute_limit_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_execute_limit_intermediate query_execute_order_direction_intermediate::limit(size_t limit) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_limit_part>(limit));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#include "matador/query/intermediates/query_execute_where_intermediate.hpp"
|
||||
|
||||
#include "matador/query/intermediates/query_execute_limit_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_execute_order_by_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_execute_limit_intermediate query_execute_where_intermediate::limit(size_t limit)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_limit_part>(limit));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_execute_order_by_intermediate query_execute_where_intermediate::order_by(const sql::column &col)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_part>(col));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
#include "matador/query/intermediates/query_from_intermediate.hpp"
|
||||
|
||||
#include "matador/query/intermediates/query_join_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_group_by_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_order_by_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_join_intermediate query_from_intermediate::join_left(const sql::table &t)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_join_part>(t));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_from_intermediate query_from_intermediate::join_left(join_data &data)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_join_part>(*data.join_table));
|
||||
context_->parts.push_back(std::make_unique<internal::query_on_part>(std::move(data.condition)));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_from_intermediate query_from_intermediate::join_left(std::vector<join_data> &data_vector)
|
||||
{
|
||||
for (auto &data : data_vector) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_join_part>(*data.join_table));
|
||||
context_->parts.push_back(std::make_unique<internal::query_on_part>(std::move(data.condition)));
|
||||
}
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_where_intermediate query_from_intermediate::where_clause(std::unique_ptr<basic_condition> &&cond)
|
||||
{
|
||||
if (cond) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_where_part>(std::move(cond)));
|
||||
}
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_group_by_intermediate query_from_intermediate::group_by(const sql::column &col)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_group_by_part>(col));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_order_by_intermediate query_from_intermediate::order_by(const sql::column &col)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_part>(col));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#include "matador/query/intermediates/query_group_by_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_order_by_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_order_by_intermediate query_group_by_intermediate::order_by(const sql::column &col)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_part>(col));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#include "matador/query/intermediates/query_insert_intermediate.hpp"
|
||||
|
||||
#include "matador/query/intermediates/query_into_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_insert_intermediate::query_insert_intermediate()
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_insert_part>());
|
||||
}
|
||||
|
||||
query_into_intermediate query_insert_intermediate::into(const sql::table &table, std::initializer_list<sql::column> columns)
|
||||
{
|
||||
return into(table, std::move(std::vector<sql::column>{columns}));
|
||||
}
|
||||
|
||||
query_into_intermediate query_insert_intermediate::into(const sql::table &table, std::vector<sql::column> &&columns)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_into_part>(table, columns));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_into_intermediate query_insert_intermediate::into(const sql::table &table, const std::vector<std::string> &column_names) {
|
||||
std::vector<sql::column> columns;
|
||||
columns.reserve(column_names.size());
|
||||
for (const auto &col_name : column_names) {
|
||||
columns.emplace_back(col_name);
|
||||
}
|
||||
return into(table, std::move(columns));
|
||||
}
|
||||
|
||||
query_into_intermediate query_insert_intermediate::into(const sql::table &table)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_into_part>(table, table.columns));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "matador/query/intermediates/query_intermediate.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_intermediate::query_intermediate()
|
||||
: context_(std::make_shared<query_data>()) {}
|
||||
|
||||
query_intermediate::query_intermediate(const std::shared_ptr<query_data> &context)
|
||||
: context_(context)
|
||||
{}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "matador/query/intermediates/query_into_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
executable_query query_into_intermediate::values(const std::initializer_list<std::variant<utils::placeholder, utils::database_type>> values)
|
||||
{
|
||||
return this->values(std::vector(values));
|
||||
}
|
||||
|
||||
executable_query query_into_intermediate::values(std::vector<std::variant<utils::placeholder, utils::database_type>> &&values) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_values_part>(std::move(values)));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
} // namespace matador::query
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "matador/query/intermediates/query_join_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_on_intermediate query_join_intermediate::on_clause(std::unique_ptr<basic_condition> &&cond)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_on_part>(std::move(cond)));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "matador/query/intermediates/query_limit_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_offset_intermediate.hpp"
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_offset_intermediate query_limit_intermediate::offset(size_t offset)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_offset_part>(offset));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "matador/query/intermediates/query_offset_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_limit_intermediate.hpp"
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_limit_intermediate query_offset_intermediate::limit(size_t limit)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_limit_part>(limit));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#include "matador/query/intermediates/query_order_by_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_order_direction_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_order_direction_intermediate query_order_by_intermediate::asc()
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_asc_part>());
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_order_direction_intermediate query_order_by_intermediate::desc()
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_desc_part>());
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#include "matador/query/intermediates/query_order_direction_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_limit_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_limit_intermediate query_order_direction_intermediate::limit(size_t limit)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_limit_part>(limit));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#include "matador/query/intermediates/query_select_intermediate.hpp"
|
||||
|
||||
#include "matador/query/intermediates/query_join_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_select_intermediate::query_select_intermediate(const std::vector<sql::column>& columns)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_select_part>(columns));
|
||||
}
|
||||
|
||||
query_from_intermediate query_select_intermediate::from(const sql::table& t)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_from_part>(t));
|
||||
context_->tables.insert({t.name, t});
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "matador/query/intermediates/query_set_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_execute_where_intermediate query_set_intermediate::where_clause(std::unique_ptr<basic_condition> &&cond)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_where_part>(std::move(cond)));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#include "matador/query/intermediates/query_where_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_group_by_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_order_by_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_group_by_intermediate query_where_intermediate::group_by(const sql::column &col)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_group_by_part>(col));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_order_by_intermediate query_where_intermediate::order_by(const sql::column &col)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_part>(col));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "matador/query/internal/basic_type_to_string_visitor.hpp"
|
||||
|
||||
namespace matador::query::internal {
|
||||
|
||||
basic_type_to_string_visitor::basic_type_to_string_visitor(attribute_string_writer &writer, sql::query_context &query)
|
||||
: writer(&writer), query(query)
|
||||
{}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#include "matador/query/internal/key_value_pair.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace matador::query::internal {
|
||||
|
||||
key_value_pair::key_value_pair(std::string name, utils::database_type value)
|
||||
: name_(std::move(name))
|
||||
, value_(std::move(value)) {
|
||||
}
|
||||
|
||||
key_value_pair::key_value_pair(const sql::column &col, utils::database_type value)
|
||||
: name_(col.name)
|
||||
, value_(std::move(value)) {
|
||||
}
|
||||
|
||||
key_value_pair::key_value_pair(const char *name, utils::database_type value)
|
||||
: name_(name)
|
||||
, value_(std::move(value)) {
|
||||
}
|
||||
|
||||
const std::string &key_value_pair::name() const {
|
||||
return name_;
|
||||
}
|
||||
|
||||
const utils::database_type& key_value_pair::value() const {
|
||||
return value_;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,299 @@
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace matador::query::internal {
|
||||
|
||||
query_select_part::query_select_part(std::vector<sql::column> columns)
|
||||
: query_part(sql::dialect_token::SELECT)
|
||||
, columns_(std::move(columns)) {}
|
||||
|
||||
void query_select_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
const std::vector<sql::column>& query_select_part::columns() const
|
||||
{
|
||||
return columns_;
|
||||
}
|
||||
|
||||
query_from_part::query_from_part(sql::table t)
|
||||
: query_part(sql::dialect_token::FROM)
|
||||
, table_(std::move(t)) {}
|
||||
|
||||
const sql::table &query_from_part::table() const
|
||||
{
|
||||
return table_;
|
||||
}
|
||||
|
||||
void query_from_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_join_part::query_join_part(sql::table t)
|
||||
: query_part(sql::dialect_token::JOIN)
|
||||
, table_(std::move(t)) {}
|
||||
|
||||
const sql::table &query_join_part::table() const
|
||||
{
|
||||
return table_;
|
||||
}
|
||||
|
||||
void query_join_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_on_part::query_on_part(std::unique_ptr<basic_condition> &&cond)
|
||||
: query_part(sql::dialect_token::ON)
|
||||
, condition_(std::move(cond)) {}
|
||||
|
||||
const basic_condition &query_on_part::condition() const
|
||||
{
|
||||
return *condition_;
|
||||
}
|
||||
|
||||
void query_on_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_where_part::query_where_part(std::unique_ptr<basic_condition> &&cond)
|
||||
: query_part(sql::dialect_token::WHERE)
|
||||
, condition_(std::move(cond)) {}
|
||||
|
||||
void query_where_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
const basic_condition &query_where_part::condition() const
|
||||
{
|
||||
return *condition_;
|
||||
}
|
||||
|
||||
query_table_name_part::query_table_name_part(sql::dialect_token token, std::string table_name)
|
||||
: query_part(token)
|
||||
, table_name_(std::move(table_name)) {}
|
||||
|
||||
query_group_by_part::query_group_by_part(sql::column col)
|
||||
: query_part(sql::dialect_token::GROUP_BY)
|
||||
, column_(std::move(col))
|
||||
{}
|
||||
|
||||
const sql::column &query_group_by_part::column() const
|
||||
{
|
||||
return column_;
|
||||
}
|
||||
|
||||
void query_group_by_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_order_by_part::query_order_by_part(sql::column col)
|
||||
: query_part(sql::dialect_token::ORDER_BY)
|
||||
, column_(std::move(col))
|
||||
{}
|
||||
|
||||
const sql::column &query_order_by_part::column() const
|
||||
{
|
||||
return column_;
|
||||
}
|
||||
|
||||
void query_order_by_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_order_by_asc_part::query_order_by_asc_part()
|
||||
: query_part(sql::dialect_token::ASC)
|
||||
{}
|
||||
|
||||
void query_order_by_asc_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_order_by_desc_part::query_order_by_desc_part()
|
||||
: query_part(sql::dialect_token::DESC)
|
||||
{}
|
||||
|
||||
void query_order_by_desc_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_offset_part::query_offset_part(size_t offset)
|
||||
: query_part(sql::dialect_token::OFFSET)
|
||||
, offset_(offset) {}
|
||||
|
||||
size_t query_offset_part::offset() const
|
||||
{
|
||||
return offset_;
|
||||
}
|
||||
|
||||
void query_offset_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_limit_part::query_limit_part(size_t limit)
|
||||
: query_part(sql::dialect_token::LIMIT)
|
||||
, limit_(limit) {}
|
||||
|
||||
size_t query_limit_part::limit() const
|
||||
{
|
||||
return limit_;
|
||||
}
|
||||
|
||||
void query_limit_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_insert_part::query_insert_part()
|
||||
: query_part(sql::dialect_token::INSERT) {}
|
||||
|
||||
void query_insert_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_into_part::query_into_part(sql::table t, std::vector<sql::column> columns)
|
||||
: query_part(sql::dialect_token::INSERT)
|
||||
, table_(std::move(t))
|
||||
, columns_(std::move(columns)) {}
|
||||
|
||||
const sql::table &query_into_part::table() const
|
||||
{
|
||||
return table_;
|
||||
}
|
||||
|
||||
const std::vector<sql::column> &query_into_part::columns() const
|
||||
{
|
||||
return columns_;
|
||||
}
|
||||
|
||||
void query_into_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_values_part::query_values_part(std::vector<std::variant<utils::placeholder, utils::database_type>> &&values)
|
||||
: query_part(sql::dialect_token::VALUES)
|
||||
, values_(std::move(values)) {}
|
||||
|
||||
const std::vector<std::variant<utils::placeholder, utils::database_type>>& query_values_part::values() const
|
||||
{
|
||||
return values_;
|
||||
}
|
||||
|
||||
void query_values_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_update_part::query_update_part(sql::table table)
|
||||
: query_part(sql::dialect_token::UPDATE)
|
||||
, table_(std::move(table)) {}
|
||||
|
||||
const sql::table& query_update_part::table() const
|
||||
{
|
||||
return table_;
|
||||
}
|
||||
|
||||
void query_update_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_set_part::query_set_part(const std::vector<key_value_pair>& key_value_pairs)
|
||||
: query_part(sql::dialect_token::SET)
|
||||
, key_value_pairs_(key_value_pairs) {}
|
||||
|
||||
const std::vector<key_value_pair> &query_set_part::key_values() const
|
||||
{
|
||||
return key_value_pairs_;
|
||||
}
|
||||
|
||||
void query_set_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_delete_part::query_delete_part()
|
||||
: query_part(sql::dialect_token::REMOVE) {}
|
||||
|
||||
void query_delete_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_delete_from_part::query_delete_from_part(sql::table table)
|
||||
: query_part(sql::dialect_token::FROM)
|
||||
, table_(std::move(table)) {}
|
||||
|
||||
const sql::table &query_delete_from_part::table() const
|
||||
{
|
||||
return table_;
|
||||
}
|
||||
|
||||
void query_delete_from_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_create_part::query_create_part()
|
||||
: query_part(sql::dialect_token::CREATE) {}
|
||||
|
||||
void query_create_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_create_table_part::query_create_table_part(sql::table table, std::vector<sql::column_definition> columns)
|
||||
: query_part(sql::dialect_token::TABLE)
|
||||
, table_(std::move(table))
|
||||
, columns_(std::move(columns)) {}
|
||||
|
||||
const sql::table &query_create_table_part::table() const
|
||||
{
|
||||
return table_;
|
||||
}
|
||||
|
||||
const std::vector<sql::column_definition> &query_create_table_part::columns() const
|
||||
{
|
||||
return columns_;
|
||||
}
|
||||
|
||||
void query_create_table_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_drop_part::query_drop_part()
|
||||
: query_part(sql::dialect_token::DROP) {}
|
||||
|
||||
void query_drop_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_drop_table_part::query_drop_table_part(sql::table table)
|
||||
: query_part(sql::dialect_token::TABLE)
|
||||
, table_(std::move(table)) {}
|
||||
|
||||
const sql::table &query_drop_table_part::table() const
|
||||
{
|
||||
return table_;
|
||||
}
|
||||
|
||||
void query_drop_table_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "matador/sql/internal/query_result_impl.hpp"
|
||||
|
||||
#include "matador/sql/interface/query_result_reader.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
detail::pk_reader::pk_reader(query_result_reader &reader)
|
||||
: reader_(reader) {}
|
||||
|
||||
void detail::pk_reader::on_primary_key(const char *id, std::string &value, size_t size)
|
||||
{
|
||||
utils::data_type_traits<std::string>::read_value(reader_, id, column_index_++, value, size);
|
||||
}
|
||||
|
||||
query_result_impl::query_result_impl(std::unique_ptr<query_result_reader> &&reader, std::vector<column_definition> &&prototype, const size_t column_index)
|
||||
: column_index_(column_index)
|
||||
, prototype_(std::move(prototype))
|
||||
, reader_(std::move(reader))
|
||||
, pk_reader_(*reader_)
|
||||
{}
|
||||
|
||||
query_result_impl::query_result_impl(std::unique_ptr<query_result_reader> &&reader, const std::vector<column_definition> &prototype, const size_t column_index)
|
||||
: column_index_(column_index)
|
||||
, prototype_(prototype)
|
||||
, reader_(std::move(reader))
|
||||
, pk_reader_(*reader_)
|
||||
{}
|
||||
|
||||
void query_result_impl::on_primary_key(const char *id, std::string &value, size_t size)
|
||||
{
|
||||
utils::data_type_traits<std::string>::read_value(*reader_, id, column_index_++, value, size);
|
||||
}
|
||||
|
||||
void query_result_impl::on_revision(const char *id, uint64_t &rev)
|
||||
{
|
||||
utils::data_type_traits<uint64_t>::read_value(*reader_, id, column_index_++, rev);
|
||||
reader_->read_value(id, column_index_++, rev);
|
||||
}
|
||||
|
||||
void query_result_impl::on_attribute(const char *id, char *value, const utils::field_attributes &attr)
|
||||
{
|
||||
utils::data_type_traits<char*>::read_value(*reader_, id, column_index_++, value, attr.size());
|
||||
}
|
||||
|
||||
void query_result_impl::on_attribute(const char *id, std::string &value, const utils::field_attributes &attr)
|
||||
{
|
||||
utils::data_type_traits<std::string>::read_value(*reader_, id, column_index_++, value, attr.size());
|
||||
}
|
||||
|
||||
void
|
||||
query_result_impl::on_attribute(const char *id, utils::value &val, const utils::field_attributes &attr)
|
||||
{
|
||||
reader_->read_value(id, column_index_++, val, attr.size());
|
||||
}
|
||||
|
||||
const std::vector<column_definition>& query_result_impl::prototype() const
|
||||
{
|
||||
return prototype_;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "matador/query/key_value_generator.hpp"
|
||||
|
||||
#include "matador/query/value_extractor.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
void key_value_generator::on_primary_key(const char *id, std::string &x, size_t)
|
||||
{
|
||||
result_.emplace_back(id, x);
|
||||
}
|
||||
|
||||
void key_value_generator::on_revision(const char *id, unsigned long long int &x)
|
||||
{
|
||||
result_.emplace_back(id, x);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
#include "matador/query/query.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
sql::column alias(const std::string &column, const std::string &as)
|
||||
{
|
||||
return sql::column{column, as};
|
||||
}
|
||||
|
||||
sql::column alias(sql::column &&col, const std::string &as)
|
||||
{
|
||||
col.as(as);
|
||||
return std::move(col);
|
||||
}
|
||||
|
||||
sql::column count(const std::string &column)
|
||||
{
|
||||
return {sql::sql_function_t::COUNT, column};
|
||||
}
|
||||
|
||||
sql::column count_all()
|
||||
{
|
||||
return count("*");
|
||||
}
|
||||
|
||||
query_create_intermediate query::create()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
query_drop_intermediate query::drop() {
|
||||
return {};
|
||||
}
|
||||
|
||||
query_select_intermediate query::select( const std::initializer_list<sql::column> columns) {
|
||||
return select(std::vector<sql::column>{columns});
|
||||
}
|
||||
|
||||
query_select_intermediate query::select(const std::vector<sql::column>& columns) {
|
||||
return query_select_intermediate{columns};
|
||||
}
|
||||
|
||||
query_select_intermediate query::select(const std::vector<std::string> &column_names) {
|
||||
std::vector<sql::column> columns;
|
||||
columns.reserve(column_names.size());
|
||||
for (const auto &col_name : column_names) {
|
||||
columns.emplace_back(col_name);
|
||||
}
|
||||
return select(columns);
|
||||
}
|
||||
|
||||
query_select_intermediate query::select(std::vector<sql::column> columns, const std::initializer_list<sql::column> additional_columns) {
|
||||
for (const auto &col : additional_columns) {
|
||||
columns.push_back(col);
|
||||
}
|
||||
return query_select_intermediate{columns};
|
||||
}
|
||||
|
||||
query_insert_intermediate query::insert() {
|
||||
return {};
|
||||
}
|
||||
|
||||
query_update_intermediate query::update(const sql::table &table) {
|
||||
return query_update_intermediate{table};
|
||||
}
|
||||
|
||||
query_delete_intermediate query::remove() {
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,357 @@
|
||||
#include "matador/query/query_compiler.hpp"
|
||||
|
||||
#include "matador/query/attribute_string_writer.hpp"
|
||||
#include "matador/query/query_data.hpp"
|
||||
|
||||
#include "matador/query/internal/basic_type_to_string_visitor.hpp"
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
#include "matador/sql/query_context.hpp"
|
||||
#include "matador/sql/connection.hpp"
|
||||
#include "matador/sql/dialect.hpp"
|
||||
|
||||
#include "matador/utils/string.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
sql::query_context query_compiler::compile(const query_data &data,
|
||||
const sql::dialect &d,
|
||||
std::optional<std::reference_wrapper<const sql::connection_impl>> conn)
|
||||
{
|
||||
data_ = &data;
|
||||
dialect_ = &d;
|
||||
connection_ = conn;
|
||||
query_ = {};
|
||||
for (const auto &part: data.parts) {
|
||||
part->accept(*this);
|
||||
}
|
||||
connection_ = std::nullopt;
|
||||
dialect_ = nullptr;
|
||||
data_ = nullptr;
|
||||
|
||||
return query_;
|
||||
}
|
||||
|
||||
std::string handle_column(sql::query_context &ctx, const sql::dialect *d, const query_data &data, const sql::column &col) {
|
||||
ctx.result_vars.emplace_back(col.name);
|
||||
const auto& column_table = col.table_.get();
|
||||
ctx.column_aliases.insert({column_table->has_alias() ? column_table->alias : column_table->name + "." + col.name, col.alias});
|
||||
if (col.is_function()) {
|
||||
ctx.prototype.emplace_back(col.has_alias() ? col.alias : col.name);
|
||||
ctx.prototype.back().type(utils::basic_type::type_int32);
|
||||
} else {
|
||||
ctx.prototype.emplace_back(col.name);
|
||||
}
|
||||
|
||||
if (const auto it = data.tables.find(col.table_->name); it != data.tables.end()) {
|
||||
return d->prepare_identifier({it->second, col.name, col.alias});
|
||||
}
|
||||
|
||||
return d->prepare_identifier(col);
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_select_part &select_part)
|
||||
{
|
||||
query_.command = sql::sql_command::SQL_CMD_SELECT;
|
||||
query_.sql = dialect_->token_at(sql::dialect_token::SELECT) + " ";
|
||||
|
||||
query_.prototype.clear();
|
||||
|
||||
std::string result;
|
||||
if (const auto &columns = select_part.columns(); columns.size() < 2) {
|
||||
for (const auto &col: columns) {
|
||||
result.append(handle_column(query_, dialect_, *data_, col ));
|
||||
}
|
||||
} else {
|
||||
auto it = columns.begin();
|
||||
result.append(handle_column(query_, dialect_, *data_, *it++));
|
||||
for (; it != columns.end(); ++it) {
|
||||
result.append(", ");
|
||||
result.append(handle_column(query_, dialect_, *data_, *it));
|
||||
}
|
||||
}
|
||||
|
||||
query_.sql += result;
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_from_part &from_part)
|
||||
{
|
||||
query_.table = from_part.table();
|
||||
query_.sql += " " + query_compiler::build_table_name(from_part.token(), *dialect_, query_.table);
|
||||
query_.table_aliases.insert({query_.table.name, query_.table.alias});
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_join_part &join_part)
|
||||
{
|
||||
query_.sql += " " + query_compiler::build_table_name(join_part.token(), *dialect_, join_part.table());
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_on_part &on_part)
|
||||
{
|
||||
query_.sql += " " + dialect_->token_at(sql::dialect_token::ON) +
|
||||
" " + on_part.condition().evaluate(*dialect_, query_);
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_where_part &where_part)
|
||||
{
|
||||
query_.sql += " " + dialect_->token_at(sql::dialect_token::WHERE) +
|
||||
" " + where_part.condition().evaluate(*dialect_, query_);
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_group_by_part &group_by_part)
|
||||
{
|
||||
query_.sql += " " + dialect_->token_at(sql::dialect_token::GROUP_BY) + " " + dialect_->prepare_identifier(group_by_part.column());
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_order_by_part &order_by_part)
|
||||
{
|
||||
query_.sql += " " + dialect_->token_at(sql::dialect_token::ORDER_BY) +
|
||||
" " + dialect_->prepare_condition(order_by_part.column());
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_order_by_asc_part &/*order_by_asc_part*/)
|
||||
{
|
||||
query_.sql += " " + dialect_->token_at(sql::dialect_token::ASC);
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_order_by_desc_part &/*order_by_desc_part*/)
|
||||
{
|
||||
query_.sql += " " + dialect_->token_at(sql::dialect_token::DESC);
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_offset_part &offset_part)
|
||||
{
|
||||
query_.sql += " " + dialect_->token_at(sql::dialect_token::OFFSET) + " " + std::to_string(offset_part.offset());
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_limit_part &limit_part)
|
||||
{
|
||||
query_.sql += " " + dialect_->token_at(sql::dialect_token::LIMIT) + " " + std::to_string(limit_part.limit());
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_insert_part &/*insert_part*/)
|
||||
{
|
||||
query_.command = sql::sql_command::SQL_CMD_INSERT;
|
||||
query_.sql = dialect_->token_at(sql::dialect_token::INSERT);
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_into_part &into_part)
|
||||
{
|
||||
query_.table = into_part.table();
|
||||
query_.sql += " " + dialect_->token_at(sql::dialect_token::INTO) +
|
||||
" " + dialect_->prepare_identifier_string(into_part.table().name);
|
||||
|
||||
std::string result{"("};
|
||||
if (into_part.columns().size() < 2) {
|
||||
for (const auto &col: into_part.columns()) {
|
||||
result.append(dialect_->prepare_identifier_string(col.name));
|
||||
}
|
||||
} else {
|
||||
auto it = into_part.columns().begin();
|
||||
result.append(dialect_->prepare_identifier_string((it++)->name));
|
||||
for (; it != into_part.columns().end(); ++it) {
|
||||
result.append(", ");
|
||||
result.append(dialect_->prepare_identifier_string(it->name));
|
||||
}
|
||||
}
|
||||
result += (")");
|
||||
query_.sql += " " + result;
|
||||
}
|
||||
|
||||
struct value_visitor {
|
||||
value_visitor(attribute_string_writer &w, sql::query_context &ctx)
|
||||
: value_to_string_visitor(w, ctx) {}
|
||||
|
||||
void operator()(const utils::database_type &val) {
|
||||
std::visit(value_to_string_visitor, val);
|
||||
|
||||
}
|
||||
void operator()(const utils::placeholder &/*val*/) {
|
||||
value_to_string_visitor.query.bind_vars.emplace_back("unknown");
|
||||
value_to_string_visitor.result = value_to_string_visitor.writer->dialect().next_placeholder(value_to_string_visitor.query.bind_vars);
|
||||
}
|
||||
|
||||
internal::basic_type_to_string_visitor value_to_string_visitor;
|
||||
};
|
||||
|
||||
void query_compiler::visit(internal::query_values_part &values_part)
|
||||
{
|
||||
query_.sql += " " + dialect_->token_at(sql::dialect_token::VALUES);
|
||||
|
||||
attribute_string_writer writer(*dialect_, connection_);
|
||||
|
||||
value_visitor visitor(writer, query_);
|
||||
std::string result{"("};
|
||||
if (values_part.values().size() < 2) {
|
||||
for (const auto& val: values_part.values()) {
|
||||
std::visit(visitor, val);
|
||||
result.append(visitor.value_to_string_visitor.result);
|
||||
}
|
||||
} else {
|
||||
auto it = values_part.values().begin();
|
||||
auto val = *it++;
|
||||
std::visit(visitor, val);
|
||||
result.append(visitor.value_to_string_visitor.result);
|
||||
for (; it != values_part.values().end(); ++it) {
|
||||
result.append(", ");
|
||||
val = *it;
|
||||
std::visit(visitor, val);
|
||||
result.append(visitor.value_to_string_visitor.result);
|
||||
}
|
||||
}
|
||||
result += (")");
|
||||
|
||||
query_.sql += " " + result;
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_update_part &update_part)
|
||||
{
|
||||
query_.command = sql::sql_command::SQL_CMD_UPDATE;
|
||||
query_.table = update_part.table();
|
||||
query_.sql += query_compiler::build_table_name(update_part.token(), *dialect_, query_.table);
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_delete_part &/*delete_part*/)
|
||||
{
|
||||
query_.command = sql::sql_command::SQL_CMD_DELETE;
|
||||
query_.sql = dialect_->token_at(sql::dialect_token::REMOVE);
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_delete_from_part &delete_from_part)
|
||||
{
|
||||
query_.table = delete_from_part.table();
|
||||
query_.sql += " " + query_compiler::build_table_name(delete_from_part.token(), *dialect_, query_.table);
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_create_part &/*create_part*/)
|
||||
{
|
||||
query_.command = sql::sql_command::SQL_CMD_CREATE;
|
||||
query_.sql = dialect_->token_at(sql::dialect_token::CREATE);
|
||||
}
|
||||
|
||||
struct fk_context
|
||||
{
|
||||
std::string column;
|
||||
std::string ref_table;
|
||||
std::string ref_column;
|
||||
};
|
||||
|
||||
struct column_context
|
||||
{
|
||||
std::vector<std::string> primary_keys;
|
||||
std::vector<fk_context> foreign_contexts;
|
||||
};
|
||||
|
||||
std::string build_create_column(const sql::column_definition &col, const sql::dialect &d, column_context &context);
|
||||
|
||||
void query_compiler::visit(internal::query_create_table_part &create_table_part)
|
||||
{
|
||||
query_.sql += " " + dialect_->token_at(sql::dialect_token::TABLE) + " " + dialect_->prepare_identifier_string(create_table_part.table().name) + " ";
|
||||
query_.table = create_table_part.table();
|
||||
|
||||
std::string result = "(";
|
||||
|
||||
column_context context;
|
||||
|
||||
if (create_table_part.columns().size() < 2) {
|
||||
for (const auto &col: create_table_part.columns()) {
|
||||
result.append(build_create_column(col, *dialect_, context));
|
||||
}
|
||||
} else {
|
||||
auto it = create_table_part.columns().begin();
|
||||
result.append(build_create_column(*it++, *dialect_, context));
|
||||
for (; it != create_table_part.columns().end(); ++it) {
|
||||
result.append(", ");
|
||||
result.append(build_create_column(*it, *dialect_, context));
|
||||
}
|
||||
}
|
||||
|
||||
if (!context.primary_keys.empty()) {
|
||||
result.append(", CONSTRAINT PK_" + create_table_part.table().name + " PRIMARY KEY (" + utils::join(context.primary_keys, ", ") + ")");
|
||||
}
|
||||
for (const auto &fk: context.foreign_contexts) {
|
||||
result += ", CONSTRAINT FK_" + create_table_part.table().name;
|
||||
result += "_" + fk.column;
|
||||
result += " FOREIGN KEY (" + fk.column + ")";
|
||||
result += " REFERENCES " + fk.ref_table + "(" + fk.ref_column + ")";
|
||||
}
|
||||
|
||||
result += ")";
|
||||
query_.sql += result;
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_drop_part &/*drop_part*/)
|
||||
{
|
||||
query_.command = sql::sql_command::SQL_CMD_DROP;
|
||||
query_.sql = dialect_->token_at(sql::dialect_token::DROP);
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_set_part &set_part)
|
||||
{
|
||||
query_.sql += " " + dialect_->token_at(sql::dialect_token::SET) + " ";
|
||||
|
||||
attribute_string_writer writer(*dialect_, connection_);
|
||||
internal::basic_type_to_string_visitor value_to_string(writer, query_);
|
||||
std::string result;
|
||||
if (set_part.key_values().size() < 2) {
|
||||
for (const auto &col: set_part.key_values()) {
|
||||
result.append(dialect_->prepare_identifier_string(col.name()) + "=");
|
||||
auto var = col.value();
|
||||
std::visit(value_to_string, var);
|
||||
result.append(value_to_string.result);
|
||||
}
|
||||
} else {
|
||||
auto it = set_part.key_values().begin();
|
||||
result.append(dialect_->prepare_identifier_string(it->name()) + "=");
|
||||
auto var = (it++)->value();
|
||||
std::visit(value_to_string, var);
|
||||
result.append(value_to_string.result);
|
||||
for (; it != set_part.key_values().end(); ++it) {
|
||||
result.append(", ");
|
||||
result.append(dialect_->prepare_identifier_string(it->name()) + "=");
|
||||
var = it->value();
|
||||
std::visit(value_to_string, var);
|
||||
result.append(value_to_string.result);
|
||||
}
|
||||
}
|
||||
|
||||
query_.sql += result;
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_drop_table_part &drop_table_part)
|
||||
{
|
||||
query_.table = drop_table_part.table();
|
||||
query_.sql += " " + query_compiler::build_table_name(drop_table_part.token(), *dialect_, query_.table);
|
||||
}
|
||||
|
||||
std::string build_create_column(const sql::column_definition &col, const sql::dialect &d, column_context &context)
|
||||
{
|
||||
std::string result = d.prepare_identifier_string(col.name()) + " " + d.data_type_at(col.type());
|
||||
if (col.attributes().size() > 0) {
|
||||
result.append("(" + std::to_string(col.attributes().size()) + ")");
|
||||
}
|
||||
if (!col.is_nullable()) {
|
||||
result.append(" NOT NULL");
|
||||
}
|
||||
if (is_constraint_set(col.attributes().options(), utils::constraints::UNIQUE)) {
|
||||
result.append(" UNIQUE");
|
||||
}
|
||||
if (is_constraint_set(col.attributes().options(), utils::constraints::PRIMARY_KEY)) {
|
||||
context.primary_keys.emplace_back(col.name());
|
||||
}
|
||||
if (is_constraint_set(col.attributes().options(), utils::constraints::FOREIGN_KEY)) {
|
||||
context.foreign_contexts.push_back({col.name(), col.ref_table(), col.ref_column()});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string query_compiler::build_table_name(const sql::dialect_token token, const sql::dialect &d, const sql::table& t)
|
||||
{
|
||||
return d.token_at(token) + " " +
|
||||
(!d.default_schema_name().empty() ? d.prepare_identifier_string(d.default_schema_name()) + "." : "") +
|
||||
d.prepare_identifier_string(t.name) +
|
||||
(t.alias.empty() ? "" : " " + d.prepare_identifier_string(t.alias));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "matador/query/query_part.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_part::query_part(const sql::dialect_token token)
|
||||
: token_(token) {}
|
||||
|
||||
sql::dialect_token query_part::token() const {
|
||||
return token_;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#include "matador/query/intermediates/query_update_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_update_intermediate::query_update_intermediate(const sql::table& table)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_update_part>(table));
|
||||
}
|
||||
|
||||
query_set_intermediate query_update_intermediate::set(std::initializer_list<internal::key_value_pair> columns)
|
||||
{
|
||||
return set(std::vector<internal::key_value_pair>{columns});
|
||||
}
|
||||
|
||||
query_set_intermediate query_update_intermediate::set(std::vector<internal::key_value_pair> &&columns)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_set_part>(std::move(columns)));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
#include "matador/query/value_extractor.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
value_extractor::value_extractor(std::vector<utils::database_type> &values)
|
||||
: values_(values)
|
||||
{}
|
||||
|
||||
void value_extractor::on_primary_key(const char *, std::string &pk, size_t s)
|
||||
{
|
||||
utils::data_type_traits<std::string>::bind_value(*this, 0, pk, s);
|
||||
}
|
||||
|
||||
void value_extractor::on_revision(const char *, uint64_t &rev)
|
||||
{
|
||||
utils::data_type_traits<uint64_t>::bind_value(*this, 0, rev);
|
||||
}
|
||||
|
||||
void value_extractor::on_attribute(const char *, char *x, const utils::field_attributes &attr)
|
||||
{
|
||||
utils::data_type_traits<char*>::bind_value(*this, 0, x, attr.size());
|
||||
}
|
||||
|
||||
void value_extractor::on_attribute(const char *, std::string &x, const utils::field_attributes &attr)
|
||||
{
|
||||
utils::data_type_traits<std::string>::bind_value(*this, 0, x, attr.size());
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const int8_t &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const int16_t &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const int32_t &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const int64_t &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const uint8_t &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const uint16_t &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const uint32_t &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const uint64_t &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const bool &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const float &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const double &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const time &/*x*/)
|
||||
{
|
||||
// values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const date &/*x*/)
|
||||
{
|
||||
// values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const char *x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const char *x, size_t /*size*/)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const std::string &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const std::string &x, size_t /*size*/)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const utils::blob &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const utils::value &/*x*/, size_t /*size*/)
|
||||
{
|
||||
// values_.emplace_back(x);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
#include "matador/sql/backend_provider.hpp"
|
||||
// #include "matador/sql/noop_connection.hpp"
|
||||
// #include "matador/sql/dialect_builder.hpp"
|
||||
|
||||
#include "matador/sql/interface/connection_impl.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <cstdint>
|
||||
|
||||
namespace matador::sql {
|
||||
backend_provider::backend_provider() = default;
|
||||
// {
|
||||
// backends_.emplace("noop", std::make_unique<noop_backend_context>());
|
||||
// }
|
||||
|
||||
backend_provider &backend_provider::instance() {
|
||||
static backend_provider provider;
|
||||
return provider;
|
||||
}
|
||||
|
||||
connection_impl *backend_provider::create_connection(const std::string &connection_type, const connection_info &info)
|
||||
{
|
||||
auto it = backends_.find(connection_type);
|
||||
if (it == backends_.end()) {
|
||||
it = backends_.emplace(connection_type, std::make_unique<backend_service>(connection_type)).first;
|
||||
}
|
||||
return it->second->create(info);
|
||||
}
|
||||
|
||||
void backend_provider::destroy_connection(const std::string &connection_type, connection_impl *c)
|
||||
{
|
||||
auto it = backends_.find(connection_type);
|
||||
if (it == backends_.end()) {
|
||||
it = backends_.emplace(connection_type, std::make_unique<backend_service>(connection_type)).first;
|
||||
}
|
||||
return it->second->destroy(c);
|
||||
}
|
||||
|
||||
const dialect &backend_provider::connection_dialect(const std::string &connection_type) {
|
||||
auto it = backends_.find(connection_type);
|
||||
if (it == backends_.end()) {
|
||||
it = backends_.emplace(connection_type, std::make_unique<backend_service>(connection_type)).first;
|
||||
}
|
||||
return *it->second->dialect();
|
||||
}
|
||||
void backend_provider::register_backend(const std::string &connection_type, std::unique_ptr<basic_backend_service> &&service) {
|
||||
backends_.emplace(connection_type, std::move(service));
|
||||
}
|
||||
|
||||
backend_provider::backend_service::backend_service(const std::string &connection_type)
|
||||
{
|
||||
if (!lib.load("matador-" + connection_type)) {
|
||||
throw std::runtime_error("couldn't load library '" + connection_type + "'");
|
||||
}
|
||||
|
||||
create_connection = reinterpret_cast<create_func>(reinterpret_cast<std::uintptr_t>(lib.function("create_database")));
|
||||
destroy_connection = reinterpret_cast<destroy_func>(reinterpret_cast<std::uintptr_t>(lib.function("destroy_database")));
|
||||
get_dialect = reinterpret_cast<dialect_func >(reinterpret_cast<std::uintptr_t>(lib.function("get_dialect")));
|
||||
}
|
||||
|
||||
connection_impl *backend_provider::backend_service::create(const connection_info &info)
|
||||
{
|
||||
return (create_connection)(info);
|
||||
}
|
||||
|
||||
void backend_provider::backend_service::destroy(connection_impl *conn)
|
||||
{
|
||||
(destroy_connection)(conn);
|
||||
}
|
||||
|
||||
const dialect *backend_provider::backend_service::dialect() const
|
||||
{
|
||||
return (get_dialect)();
|
||||
}
|
||||
|
||||
backend_provider::backend_service::~backend_service()
|
||||
{
|
||||
lib.unload();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#include <utility>
|
||||
|
||||
#include "matador/sql/column.hpp"
|
||||
#include "matador/sql/table.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
column operator ""_col(const char *name, size_t len)
|
||||
{
|
||||
return column{{name, len}};
|
||||
}
|
||||
|
||||
column::column(const char *name, const std::string& as)
|
||||
: column(std::string(name), as)
|
||||
{}
|
||||
|
||||
column::column(std::string name, std::string as)
|
||||
: table_(std::make_shared<sql::table>())
|
||||
, name(std::move(name))
|
||||
, alias(std::move(as)) {}
|
||||
|
||||
column::column(const sql_function_t func, std::string name)
|
||||
: table_(std::make_shared<sql::table>())
|
||||
, name(std::move(name))
|
||||
, function_(func) {}
|
||||
|
||||
column::column(const struct sql::table& t, std::string name, std::string as)
|
||||
: table_(std::make_shared<sql::table>(t))
|
||||
, name(std::move(name))
|
||||
, alias(std::move(as)) {
|
||||
table_->columns.push_back(*this);
|
||||
}
|
||||
|
||||
column::column(const std::shared_ptr<table>& t, std::string name, std::string as)
|
||||
: table_(t)
|
||||
, name(std::move(name))
|
||||
, alias(std::move(as)) {
|
||||
}
|
||||
|
||||
bool column::equals(const column &x) const
|
||||
{
|
||||
return *table_ == *x.table_ &&
|
||||
name == x.name &&
|
||||
alias == x.alias &&
|
||||
function_ == x.function_;
|
||||
}
|
||||
|
||||
column &column::as(std::string a)
|
||||
{
|
||||
alias = std::move(a);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool column::is_function() const
|
||||
{
|
||||
return function_ != sql_function_t::NONE;
|
||||
}
|
||||
|
||||
bool column::has_alias() const {
|
||||
return !alias.empty();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
#include "matador/sql/column_definition.hpp"
|
||||
|
||||
#include <ostream>
|
||||
#include <utility>
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
column_definition::column_definition(const char *name)
|
||||
: name_(name)
|
||||
, attributes_(utils::null_attributes)
|
||||
{}
|
||||
|
||||
column_definition::column_definition(std::string name)
|
||||
: name_(std::move(name))
|
||||
, attributes_(utils::null_attributes)
|
||||
{}
|
||||
|
||||
column_definition::column_definition(std::string name, const utils::basic_type type, const utils::field_attributes& attr, const null_option null_opt, const size_t index)
|
||||
: name_(std::move(name))
|
||||
, index_(index)
|
||||
, attributes_(attr)
|
||||
, null_option_(null_opt)
|
||||
, value_(type, attr.size())
|
||||
{}
|
||||
|
||||
column_definition::column_definition(std::string name,
|
||||
const utils::basic_type type,
|
||||
const size_t index,
|
||||
std::string ref_table,
|
||||
std::string ref_column,
|
||||
const utils::field_attributes& attr, const null_option null_opt)
|
||||
: name_(std::move(name))
|
||||
, index_(index)
|
||||
, attributes_(attr)
|
||||
, null_option_(null_opt)
|
||||
, value_(type, attr.size())
|
||||
, ref_table_(std::move(ref_table))
|
||||
, ref_column_(std::move(ref_column))
|
||||
{}
|
||||
|
||||
const std::string &column_definition::name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
std::string column_definition::full_name() const
|
||||
{
|
||||
return table_ + "." + name_;
|
||||
}
|
||||
|
||||
std::string column_definition::table_name() const
|
||||
{
|
||||
return table_;
|
||||
}
|
||||
|
||||
int column_definition::index() const
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
|
||||
const utils::field_attributes &column_definition::attributes() const
|
||||
{
|
||||
return attributes_;
|
||||
}
|
||||
|
||||
bool column_definition::is_nullable() const
|
||||
{
|
||||
return null_option_ == null_option::NULLABLE;
|
||||
}
|
||||
|
||||
utils::basic_type column_definition::type() const
|
||||
{
|
||||
return value_.type();
|
||||
}
|
||||
|
||||
const std::string &column_definition::ref_table() const
|
||||
{
|
||||
return ref_table_;
|
||||
}
|
||||
|
||||
const std::string &column_definition::ref_column() const
|
||||
{
|
||||
return ref_column_;
|
||||
}
|
||||
|
||||
bool column_definition::is_foreign_reference() const
|
||||
{
|
||||
return !ref_column_.empty() && !ref_table_.empty();
|
||||
}
|
||||
|
||||
bool column_definition::is_integer() const
|
||||
{
|
||||
return value_.is_integer();
|
||||
}
|
||||
|
||||
bool column_definition::is_floating_point() const
|
||||
{
|
||||
return value_.is_floating_point();
|
||||
}
|
||||
|
||||
bool column_definition::is_bool() const
|
||||
{
|
||||
return value_.is_bool();
|
||||
}
|
||||
|
||||
bool column_definition::is_string() const
|
||||
{
|
||||
return value_.is_string();
|
||||
}
|
||||
|
||||
bool column_definition::is_varchar() const
|
||||
{
|
||||
return value_.is_varchar();
|
||||
}
|
||||
|
||||
bool column_definition::is_date() const
|
||||
{
|
||||
return value_.is_date();
|
||||
}
|
||||
|
||||
bool column_definition::is_time() const
|
||||
{
|
||||
return value_.is_time();
|
||||
}
|
||||
|
||||
bool column_definition::is_blob() const
|
||||
{
|
||||
return value_.is_blob();
|
||||
}
|
||||
|
||||
bool column_definition::is_null() const
|
||||
{
|
||||
return value_.is_null();
|
||||
}
|
||||
|
||||
void column_definition::type(utils::basic_type /*type*/)
|
||||
{
|
||||
// type_ = type;
|
||||
// utils::initialize_by_utils::basic_type(type, value_);
|
||||
}
|
||||
|
||||
std::string column_definition::str() const
|
||||
{
|
||||
return value_.str();
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream &out, const column_definition &col)
|
||||
{
|
||||
out << col.str();
|
||||
return out;
|
||||
}
|
||||
|
||||
column_definition make_column(const std::string &name, utils::basic_type type, utils::field_attributes attr, null_option null_opt)
|
||||
{
|
||||
return {name, type, attr, null_opt};
|
||||
}
|
||||
|
||||
template<>
|
||||
column_definition make_column<std::string>(const std::string &name, utils::field_attributes attr, null_option null_opt)
|
||||
{
|
||||
return make_column(name, utils::data_type_traits<std::string>::type(attr.size()), attr, null_opt);
|
||||
}
|
||||
|
||||
template<>
|
||||
column_definition make_pk_column<std::string>(const std::string &name, size_t size)
|
||||
{
|
||||
return make_column<std::string>(name, {size, utils::constraints::FOREIGN_KEY});
|
||||
}
|
||||
|
||||
template<>
|
||||
[[maybe_unused]] column_definition make_fk_column<std::string>(const std::string &name, size_t size, const std::string &ref_table,
|
||||
const std::string &ref_column)
|
||||
{
|
||||
return {name, utils::data_type_traits<std::string>::type(size), 0, ref_table, ref_column, {size, utils::constraints::FOREIGN_KEY}, null_option::NOT_NULL};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
#include "matador/sql/connection.hpp"
|
||||
|
||||
#include "matador/sql/backend_provider.hpp"
|
||||
#include "matador/sql/dialect.hpp"
|
||||
#include "matador/sql/dialect_token.hpp"
|
||||
// #include "matador/sql/schema.hpp"
|
||||
// #include "matador/sql/query_compile_context.hpp"
|
||||
#include "matador/sql/interface/connection_impl.hpp"
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
connection::connection(connection_info info, const std::shared_ptr<abstract_sql_logger> &sql_logger)
|
||||
: connection_info_(std::move(info))
|
||||
, logger_(sql_logger)
|
||||
{
|
||||
connection_.reset(backend_provider::instance().create_connection(connection_info_.type, connection_info_));
|
||||
}
|
||||
|
||||
connection::connection(const std::string& dns, const std::shared_ptr<abstract_sql_logger> &sql_logger)
|
||||
: connection(connection_info::parse(dns), sql_logger)
|
||||
{}
|
||||
|
||||
connection::connection(const connection &x)
|
||||
: connection_info_(x.connection_info_)
|
||||
{
|
||||
if (x.connection_) {
|
||||
throw std::runtime_error("couldn't copy connection with valid connection impl");
|
||||
}
|
||||
}
|
||||
|
||||
connection &connection::operator=(const connection &x) {
|
||||
if (this == &x) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
connection_info_ = x.connection_info_;
|
||||
if (x.connection_) {
|
||||
throw std::runtime_error("couldn't copy connection with valid connection impl");
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
connection & connection::operator=(connection &&x) noexcept {
|
||||
connection_info_ = std::move(x.connection_info_);
|
||||
connection_ = std::move(x.connection_);
|
||||
logger_ = std::move(x.logger_);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
connection::~connection()
|
||||
{
|
||||
if (connection_->is_open()) {
|
||||
connection_->close();
|
||||
}
|
||||
backend_provider::instance().destroy_connection(connection_info_.type, connection_.release());
|
||||
connection_ = nullptr;
|
||||
}
|
||||
|
||||
utils::result<void, utils::error> connection::open() const
|
||||
{
|
||||
const auto res = is_open();
|
||||
if (res.is_error()) {
|
||||
return utils::failure(res.err());
|
||||
}
|
||||
if (*res) {
|
||||
logger_->on_connect();
|
||||
return connection_->open();
|
||||
}
|
||||
return utils::ok<void>();
|
||||
}
|
||||
|
||||
utils::result<void, utils::error> connection::close() const
|
||||
{
|
||||
logger_->on_close();
|
||||
return connection_->close();
|
||||
}
|
||||
|
||||
utils::result<bool, utils::error> connection::is_open() const
|
||||
{
|
||||
return connection_->is_open();
|
||||
}
|
||||
|
||||
const connection_info &connection::info() const
|
||||
{
|
||||
return connection_info_;
|
||||
}
|
||||
|
||||
std::string connection::type() const {
|
||||
return connection_info_.type;
|
||||
}
|
||||
|
||||
utils::result<void, utils::error> connection::begin() const {
|
||||
const auto res = connection_->execute(dialect().token_at(dialect_token::BEGIN));
|
||||
if (res.is_error()) {
|
||||
return utils::failure(res.err());
|
||||
}
|
||||
|
||||
return utils::ok<void>();
|
||||
}
|
||||
|
||||
utils::result<void, utils::error> connection::commit() const {
|
||||
const auto res = connection_->execute(dialect().token_at(dialect_token::COMMIT));
|
||||
if (res.is_error()) {
|
||||
return utils::failure(res.err());
|
||||
}
|
||||
|
||||
return utils::ok<void>();
|
||||
}
|
||||
|
||||
utils::result<void, utils::error> connection::rollback() const {
|
||||
const auto res = connection_->execute(dialect().token_at(dialect_token::ROLLBACK));
|
||||
if (res.is_error()) {
|
||||
return utils::failure(res.err());
|
||||
}
|
||||
|
||||
return utils::ok<void>();
|
||||
}
|
||||
|
||||
utils::result<std::vector<column_definition>, utils::error> connection::describe(const std::string &table_name) const
|
||||
{
|
||||
return connection_->describe(table_name);
|
||||
}
|
||||
|
||||
utils::result<bool, utils::error> connection::exists(const std::string &schema_name, const std::string &table_name) const
|
||||
{
|
||||
return connection_->exists(schema_name, table_name);
|
||||
}
|
||||
|
||||
utils::result<bool, utils::error> connection::exists(const std::string &table_name) const
|
||||
{
|
||||
return connection_->exists(dialect().default_schema_name(), table_name);
|
||||
}
|
||||
|
||||
utils::result<size_t, utils::error> connection::execute(const std::string &sql) const
|
||||
{
|
||||
// logger_.debug(sql);
|
||||
return connection_->execute(sql);
|
||||
}
|
||||
|
||||
bool has_unknown_columns(const std::vector<sql::column_definition> &columns) {
|
||||
return std::any_of(std::begin(columns), std::end(columns), [](const auto &col) {
|
||||
return col.type() == utils::basic_type::type_null;
|
||||
});
|
||||
}
|
||||
|
||||
// query_result<record> connection::fetch(const query_context &ctx) const
|
||||
// {
|
||||
// if (ctx.prototype.empty() || is_unknown(ctx.prototype)) {
|
||||
// const auto table_prototype = describe(ctx.table.name);
|
||||
// for (auto &col : ctx.prototype) {
|
||||
// const auto rit = std::find_if(std::begin(table_prototype), std::end(table_prototype), [&col](const auto &value) {
|
||||
// return value.name() == col.name();
|
||||
// });
|
||||
// if (col.type() == data_type::type_unknown && rit != table_prototype.end()) {
|
||||
// const_cast<column_definition&>(col).type(rit->type());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// // auto it = prototypes_.find(q.table_name);
|
||||
// // if (it == prototypes_.end()) {
|
||||
// // it = prototypes_.emplace(q.table_name, describe(q.table_name)).first;
|
||||
// // }
|
||||
// // // adjust columns from given query
|
||||
// // for (auto &col : q.prototype) {
|
||||
// // if (const auto rit = it->second.find(col.name()); col.type() == data_type_t::type_unknown && rit != it->second.end()) {
|
||||
// // const_cast<column&>(col).type(rit->type());
|
||||
// // }
|
||||
// // }
|
||||
// auto res = fetch(ctx.sql);
|
||||
// return query_result<record>{std::move(res), ctx.prototype};
|
||||
// }
|
||||
|
||||
utils::result<std::unique_ptr<query_result_impl>, utils::error> connection::fetch(const query_context &ctx) const
|
||||
{
|
||||
// logger_.debug(sql);
|
||||
return connection_->fetch(ctx);
|
||||
// return connection_->fetch(dialect().compile(ctx, *connection_));
|
||||
}
|
||||
|
||||
utils::result<size_t, utils::error> connection::execute(const query_context& ctx) const
|
||||
{
|
||||
return execute(ctx.sql);
|
||||
// return execute(dialect().compile(ctx, *connection_).sql);
|
||||
}
|
||||
|
||||
utils::result<statement, utils::error> connection::prepare(const query_context &ctx) const
|
||||
{
|
||||
if (ctx.command != sql_command::SQL_CMD_CREATE && (ctx.prototype.empty() || has_unknown_columns(ctx.prototype))) {
|
||||
if (const auto result = describe(ctx.table.name); result.is_ok()) {
|
||||
for (auto &col: ctx.prototype) {
|
||||
const auto rit = std::find_if(std::begin(*result), std::end(*result),
|
||||
[&col](const auto &value) {
|
||||
return value.name() == col.name();
|
||||
});
|
||||
if (col.type() == utils::basic_type::type_null && rit != result->end()) {
|
||||
const_cast<column_definition &>(col).type(rit->type());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return connection_->prepare(qry).and_then([](auto &&res) {
|
||||
// return statement(std::forward<decltype(res)>(res));
|
||||
// });
|
||||
if (auto result = connection_->prepare(ctx); result.is_ok()) {
|
||||
return utils::ok(statement(result.release()));
|
||||
}
|
||||
|
||||
return utils::ok(statement(std::unique_ptr<statement_impl>{}));
|
||||
}
|
||||
|
||||
std::string connection::str( const query_context& ctx ) const
|
||||
{
|
||||
return ctx.sql;
|
||||
}
|
||||
|
||||
const class dialect &connection::dialect() const
|
||||
{
|
||||
return connection_->dialect();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
#include "matador/sql/connection_info.hpp"
|
||||
|
||||
#include <regex>
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
connection_info connection_info::parse(const std::string &info, unsigned short default_port, const std::string &default_driver) {
|
||||
static const std::regex DNS_RGX (R"((\w+):\/\/((([\w]+)(:([\w!]+))?)@)?((((([\w.\(\)\\]+)([:]([\d]+))?)?)\/)?(([\w.]+)( \((.*)\))?)))");
|
||||
|
||||
std::smatch what;
|
||||
|
||||
if (!std::regex_match(info, what, DNS_RGX)) {
|
||||
throw std::logic_error("connect invalid dns: " + info);
|
||||
}
|
||||
|
||||
connection_info ci{};
|
||||
ci.type = what[1].str();
|
||||
ci.user = what[4].str();
|
||||
ci.password = what[6].str();
|
||||
|
||||
// get connection part
|
||||
ci.hostname = what[11].str();
|
||||
if (what[13].matched) {
|
||||
char *end;
|
||||
ci.port = static_cast<unsigned short>(std::strtoul(what[13].str().c_str(), &end, 10));
|
||||
} else {
|
||||
ci.port = default_port;
|
||||
}
|
||||
|
||||
// Should we just ignore the "instance" part?
|
||||
// const std::string instance = what[5].str();
|
||||
ci.database = what[15].str();
|
||||
|
||||
if (what[17].matched) {
|
||||
ci.driver = what[17].str();
|
||||
} else {
|
||||
ci.driver = default_driver;
|
||||
}
|
||||
|
||||
return ci;
|
||||
}
|
||||
|
||||
std::string connection_info::to_string(const connection_info &ci) {
|
||||
std::string dns{ci.type};
|
||||
dns += "://";
|
||||
|
||||
if (!ci.user.empty()) {
|
||||
dns += ci.user;
|
||||
if (!ci.password.empty()) {
|
||||
dns += ":" + ci.password;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ci.hostname.empty()) {
|
||||
dns += "@" + ci.hostname;
|
||||
if (ci.port > 0) {
|
||||
dns += ":" + std::to_string(ci.port);
|
||||
}
|
||||
}
|
||||
|
||||
if (!dns.empty()) {
|
||||
dns += "/";
|
||||
}
|
||||
dns += ci.database;
|
||||
|
||||
if (!ci.driver.empty()) {
|
||||
dns += " (" + ci.driver +")";
|
||||
}
|
||||
return dns;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
#include "matador/sql/dialect.hpp"
|
||||
|
||||
#include "matador/sql/interface/connection_impl.hpp"
|
||||
|
||||
#include "matador/utils/string.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
const std::string& dialect::token_at(const dialect_token token) const
|
||||
{
|
||||
return tokens_.at(token);
|
||||
}
|
||||
|
||||
const std::string &dialect::data_type_at(const utils::basic_type type) const
|
||||
{
|
||||
return data_types_.at(type);
|
||||
}
|
||||
|
||||
std::string dialect::prepare_identifier(const column &col) const
|
||||
{
|
||||
std::string result;
|
||||
if (!col.is_function()) {
|
||||
if (!col.table_->name.empty()) {
|
||||
result = prepare_identifier_string(col.table_->has_alias() ? col.table_->alias : col.table_->name) + ".";
|
||||
}
|
||||
result += prepare_identifier_string(col.name);
|
||||
} else {
|
||||
result = sql_func_map_.at(col.function_) + "(" + col.name + ")";
|
||||
}
|
||||
if (!col.alias.empty()) {
|
||||
result += " AS " + col.alias;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string dialect::prepare_condition(const column& col) const
|
||||
{
|
||||
std::string result;
|
||||
if (!col.is_function()) {
|
||||
// if (!col.alias.empty()) {
|
||||
// result = col.alias;
|
||||
// } else {
|
||||
if (!col.table_->name.empty()) {
|
||||
result = prepare_identifier_string(col.table_->has_alias() ? col.table_->alias : col.table_->name) + ".";
|
||||
}
|
||||
result += prepare_identifier_string(col.name);
|
||||
// }
|
||||
} else {
|
||||
result = sql_func_map_.at(col.function_) + "(" + col.name + ")";
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const std::string& dialect::to_string(const bool val) const
|
||||
{
|
||||
return bool_strings_[static_cast<int>(val)];
|
||||
}
|
||||
|
||||
void dialect::bool_strings(const std::string &true_string, const std::string &false_string)
|
||||
{
|
||||
bool_strings_[0] = false_string;
|
||||
bool_strings_[1] = true_string;
|
||||
}
|
||||
|
||||
std::string dialect::prepare_identifier_string(const std::string &col) const
|
||||
{
|
||||
auto parts = utils::split(col, '.');
|
||||
|
||||
for (auto &part : parts) {
|
||||
escape_quotes_in_identifier(part);
|
||||
quote_identifier(part);
|
||||
}
|
||||
return utils::join(parts, ".");
|
||||
}
|
||||
|
||||
std::string dialect::prepare_literal(const std::string &str) const
|
||||
{
|
||||
std::string result(str);
|
||||
escape_quotes_in_literals(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void dialect::quote_identifier(std::string &str) const
|
||||
{
|
||||
str.insert(0, token_at(dialect_token::START_QUOTE));
|
||||
str += token_at(dialect_token::END_QUOTE);
|
||||
}
|
||||
|
||||
void dialect::escape_quotes_in_identifier(std::string &str) const
|
||||
{
|
||||
const std::string open_char(token_at(dialect_token::START_QUOTE));
|
||||
const std::string close_char(token_at(dialect_token::END_QUOTE));
|
||||
if (identifier_escape_type() == escape_identifier_t::ESCAPE_CLOSING_BRACKET) {
|
||||
utils::replace_all(str, close_char, close_char + close_char);
|
||||
} else {
|
||||
utils::replace_all(str, open_char, open_char + open_char);
|
||||
}
|
||||
}
|
||||
|
||||
void dialect::escape_quotes_in_literals(std::string &str) const
|
||||
{
|
||||
const std::string single_quote(token_at(dialect_token::STRING_QUOTE));
|
||||
const std::string double_quote(token_at(dialect_token::STRING_QUOTE) + token_at(dialect_token::STRING_QUOTE));
|
||||
utils::replace_all(str, single_quote, double_quote);
|
||||
}
|
||||
|
||||
dialect::escape_identifier_t dialect::identifier_escape_type() const {
|
||||
return identifier_escape_type_;
|
||||
}
|
||||
|
||||
void dialect::identifier_escape_type(escape_identifier_t escape_identifier) {
|
||||
identifier_escape_type_ = escape_identifier;
|
||||
}
|
||||
|
||||
std::string dialect::next_placeholder(const std::vector<std::string> &bind_vars) const
|
||||
{
|
||||
return placeholder_func_(bind_vars.size());
|
||||
}
|
||||
|
||||
std::string dialect::to_escaped_string(const utils::blob &value, const connection_impl *conn) const
|
||||
{
|
||||
if (conn != nullptr) {
|
||||
return conn->to_escaped_string(value);
|
||||
}
|
||||
|
||||
return {};
|
||||
// return to_escaped_string_func_(value);
|
||||
}
|
||||
|
||||
std::string dialect::default_schema_name() const
|
||||
{
|
||||
return default_schema_name_;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
#include "matador/sql/dialect_builder.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
dialect_builder &dialect_builder::builder()
|
||||
{
|
||||
static dialect_builder instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
dialect_builder &dialect_builder::create()
|
||||
{
|
||||
dialect_ = {};
|
||||
return *this;
|
||||
}
|
||||
|
||||
dialect_builder& dialect_builder::with_token_replace_map(const dialect::token_to_string_map &token_replace_map)
|
||||
{
|
||||
for (const auto &token : token_replace_map) {
|
||||
dialect_.tokens_[token.first] = token.second;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
dialect_builder& dialect_builder::with_data_type_replace_map(const dialect::data_type_to_string_map &data_type_replace_map)
|
||||
{
|
||||
for (const auto &data_type : data_type_replace_map) {
|
||||
dialect_.data_types_[data_type.first] = data_type.second;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
dialect_builder& dialect_builder::with_placeholder_func(const dialect::next_placeholder_func &func)
|
||||
{
|
||||
dialect_.placeholder_func_ = func;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
dialect_builder &dialect_builder::with_default_schema_name(const std::string &schema_name)
|
||||
{
|
||||
dialect_.default_schema_name_ = schema_name;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
dialect_builder &dialect_builder::with_bool_strings(const std::string &true_string, const std::string &false_string)
|
||||
{
|
||||
dialect_.bool_strings(true_string, false_string);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
dialect dialect_builder::build()
|
||||
{
|
||||
return std::move(dialect_);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
#include "matador/sql/error_code.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
const char * sql_category_impl::name() const noexcept {
|
||||
return "sql";
|
||||
}
|
||||
|
||||
std::string sql_category_impl::message(const int ev) const {
|
||||
switch (static_cast<error_code>(ev)) {
|
||||
case error_code::OK:
|
||||
return "OK";
|
||||
case error_code::INVALID_QUERY:
|
||||
return "Invalid query";
|
||||
case error_code::UNKNOWN_TABLE:
|
||||
return "Unknown table";
|
||||
case error_code::UNKNOWN_COLUMN:
|
||||
return "Unknown column";
|
||||
case error_code::BIND_FAILED:
|
||||
return "Bind failed";
|
||||
case error_code::EXECUTE_FAILED:
|
||||
return "Execute failed";
|
||||
case error_code::FETCH_FAILED:
|
||||
return "Fetch failed";
|
||||
case error_code::PREPARE_FAILED:
|
||||
return "Prepare failed";
|
||||
case error_code::DESCRIBE_FAILED:
|
||||
return "Describe failed";
|
||||
case error_code::TABLE_EXISTS_FAILED:
|
||||
return "Table exists failed";
|
||||
case error_code::RETRIEVE_DATA_FAILED:
|
||||
return "Retrieve data failed";
|
||||
case error_code::RESET_FAILED:
|
||||
return "Reset failed";
|
||||
case error_code::OPEN_ERROR:
|
||||
return "Open failed";
|
||||
case error_code::CLOSE_ERROR:
|
||||
return "Close failed";
|
||||
case error_code::FAILURE:
|
||||
return "Failure";
|
||||
default:
|
||||
return "Unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
const std::error_category & sql_category() {
|
||||
static sql_category_impl instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
std::error_code make_error_code(error_code e) {
|
||||
return {static_cast<int>(e), sql_category()};
|
||||
}
|
||||
|
||||
std::error_condition make_error_condition(error_code e) {
|
||||
return {static_cast<int>(e), sql_category()};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
#include "matador/sql/executor.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
executor::~executor() = default;
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
#include "matador/sql/field.hpp"
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
field::field(std::string name)
|
||||
: name_(std::move(name))
|
||||
, value_(nullptr)
|
||||
{}
|
||||
|
||||
field::field(std::string name, const utils::basic_type dt, const size_t size, const int index)
|
||||
: name_(std::move(name))
|
||||
, index_(index)
|
||||
, value_(dt, size) {}
|
||||
|
||||
field::field(field &&x) noexcept
|
||||
: name_(std::move(x.name_))
|
||||
, index_(x.index_)
|
||||
, value_(std::move(x.value_))
|
||||
{
|
||||
x.value_ = nullptr;
|
||||
x.index_ = -1;
|
||||
}
|
||||
|
||||
field &field::operator=(field &&x) noexcept
|
||||
{
|
||||
name_ = std::move(x.name_);
|
||||
index_ = x.index_;
|
||||
value_ = std::move(x.value_);
|
||||
x.index_ = -1;
|
||||
x.value_ = nullptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const std::string &field::name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
size_t field::size() const
|
||||
{
|
||||
return value_.size();
|
||||
}
|
||||
|
||||
int field::index() const
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const field &col)
|
||||
{
|
||||
out << col.str();
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string field::str() const
|
||||
{
|
||||
return as<std::string>().value_or("");
|
||||
}
|
||||
|
||||
bool field::is_integer() const
|
||||
{
|
||||
return value_.is_integer();
|
||||
}
|
||||
|
||||
bool field::is_floating_point() const
|
||||
{
|
||||
return value_.is_floating_point();
|
||||
}
|
||||
|
||||
bool field::is_bool() const
|
||||
{
|
||||
return value_.is_bool();
|
||||
}
|
||||
|
||||
bool field::is_string() const
|
||||
{
|
||||
return value_.is_string();
|
||||
}
|
||||
|
||||
bool field::is_varchar() const
|
||||
{
|
||||
return value_.is_varchar();
|
||||
}
|
||||
|
||||
bool field::is_blob() const
|
||||
{
|
||||
return value_.is_blob();
|
||||
}
|
||||
|
||||
bool field::is_null() const
|
||||
{
|
||||
return value_.is_null();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#include "matador/sql/interface/connection_impl.hpp"
|
||||
|
||||
#include "matador/sql/backend_provider.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
connection_impl::connection_impl(const connection_info &info)
|
||||
: info_(info)
|
||||
, dialect_(backend_provider::instance().connection_dialect(info.type))
|
||||
{}
|
||||
|
||||
const connection_info &connection_impl::info() const {
|
||||
return info_;
|
||||
}
|
||||
|
||||
const class dialect & connection_impl::dialect() const {
|
||||
return dialect_;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#include "matador/sql/interface/query_result_reader.hpp"
|
||||
|
||||
#include "matador/utils/basic_types.hpp"
|
||||
#include "matador/utils/convert.hpp"
|
||||
#include "matador/utils/string.hpp"
|
||||
#include "matador/utils/value.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
template < typename Type >
|
||||
void convert(const char *val_str, utils::value &val)
|
||||
{
|
||||
if (val_str == nullptr) {
|
||||
val = utils::value(Type{});
|
||||
return;
|
||||
}
|
||||
Type local_val{};
|
||||
const auto res = utils::to<Type>(val_str);
|
||||
val = *res;
|
||||
}
|
||||
|
||||
// utils::blob query_result_reader::read_blob(const size_t index)
|
||||
// {
|
||||
// const auto *data = column(index);
|
||||
// if (data == nullptr) {
|
||||
// return {};
|
||||
// }
|
||||
// const auto len = strlen(data);
|
||||
// const auto *bytes = reinterpret_cast<const unsigned char*>(data);
|
||||
// return utils::blob{bytes, bytes+len};
|
||||
// }
|
||||
|
||||
// utils::attribute_reader &query_result_reader::result_binder()
|
||||
// {
|
||||
// return empty_result_binder_;
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "matador/sql/interface/statement_impl.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
statement_impl::statement_impl(query_context query)
|
||||
: query_(std::move(query))
|
||||
{}
|
||||
|
||||
void statement_impl::bind(const size_t pos, const char *value, const size_t size)
|
||||
{
|
||||
utils::data_type_traits<const char*>::bind_value(binder(), adjust_index(pos), value, size);
|
||||
}
|
||||
|
||||
void statement_impl::bind(const size_t pos, std::string &val, const size_t size)
|
||||
{
|
||||
utils::data_type_traits<std::string>::bind_value(binder(), adjust_index(pos), val, size);
|
||||
}
|
||||
|
||||
const std::vector<std::string> &statement_impl::bind_vars() const
|
||||
{
|
||||
return query_.bind_vars;
|
||||
}
|
||||
|
||||
bool statement_impl::is_valid_host_var(const std::string &host_var, const size_t pos) const
|
||||
{
|
||||
const auto host_var_at_pos = bind_vars().at(pos);
|
||||
|
||||
return host_var_at_pos == host_var;
|
||||
}
|
||||
|
||||
size_t statement_impl::start_index() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t statement_impl::adjust_index( size_t index ) const
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#include "matador/sql/internal/object_result_binder.hpp"
|
||||
|
||||
#include "matador/utils/data_type_traits.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
namespace detail {
|
||||
|
||||
void fk_result_binder::on_primary_key(const char * /*id*/, std::string &value, const size_t size)
|
||||
{
|
||||
utils::data_type_traits<std::string>::read_value(*binder_, id_, index_++, value, size);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void object_result_binder::reset()
|
||||
{
|
||||
index_ = 0;
|
||||
}
|
||||
|
||||
void object_result_binder::on_primary_key(const char *id, std::string &value, const size_t size)
|
||||
{
|
||||
utils::data_type_traits<std::string>::read_value(*binder_, id, index_++, value, size);
|
||||
}
|
||||
|
||||
void object_result_binder::on_revision(const char *id, uint64_t &value)
|
||||
{
|
||||
utils::data_type_traits<uint64_t>::read_value(*binder_, id, index_++, value);
|
||||
}
|
||||
|
||||
void object_result_binder::on_attribute(const char *id, char *value, const utils::field_attributes &attr)
|
||||
{
|
||||
utils::data_type_traits<char*>::read_value(*binder_, id, index_++, value, attr.size());
|
||||
}
|
||||
|
||||
void object_result_binder::on_attribute(const char *id, std::string &value, const utils::field_attributes &attr)
|
||||
{
|
||||
utils::data_type_traits<std::string>::read_value(*binder_, id, index_++, value, attr.size());
|
||||
}
|
||||
|
||||
void object_result_binder::on_attribute(const char * /*id*/, utils::value &/*val*/, const utils::field_attributes &/*attr*/)
|
||||
{
|
||||
// utils::data_type_traits<utils::value>::read_value(*binder_, id, index_++, val);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "matador/sql/object_parameter_binder.hpp"
|
||||
#include "matador/sql/interface/parameter_binder.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
namespace detail {
|
||||
|
||||
void fk_binder::on_primary_key(const char * /*id*/, std::string &value, size_t /*size*/)
|
||||
{
|
||||
utils::data_type_traits<std::string>::bind_value(*binder_, index_++, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void object_parameter_binder::reset(const size_t start_index)
|
||||
{
|
||||
index_ = start_index;
|
||||
}
|
||||
|
||||
void object_parameter_binder::on_primary_key(const char * /*id*/, std::string &val, const size_t size)
|
||||
{
|
||||
utils::data_type_traits<std::string>::bind_value(*binder_, index_++, val, size);
|
||||
}
|
||||
|
||||
void object_parameter_binder::on_revision(const char * /*id*/, uint64_t &rev)
|
||||
{
|
||||
utils::data_type_traits<uint64_t>::bind_value(*binder_, index_++, rev);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "matador/sql/query_result.hpp"
|
||||
#include "matador/sql/record.hpp"
|
||||
|
||||
#include "matador/sql/internal/query_result_impl.hpp"
|
||||
|
||||
namespace matador::sql::detail {
|
||||
|
||||
template<>
|
||||
record *create_prototype<record>(const std::vector<column_definition> &prototype)
|
||||
{
|
||||
auto result = std::make_unique<record>();
|
||||
for (const auto &col: prototype) {
|
||||
result->append({col.name(), col.type(), col.attributes().size(), col.index()});
|
||||
}
|
||||
return result.release();
|
||||
}
|
||||
|
||||
|
||||
} // namespace matador::sql
|
||||
@@ -0,0 +1,165 @@
|
||||
#include "matador/sql/record.hpp"
|
||||
#include "matador/sql/column.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
record::record(std::initializer_list<field> columns)
|
||||
{
|
||||
for (auto &&col :columns) {
|
||||
const auto it = fields_by_name_.emplace(col.name(), field_index_pair {col, fields_.size()});
|
||||
fields_.push_back(std::ref(it.first->second.first));
|
||||
}
|
||||
}
|
||||
|
||||
record::record(const std::vector<field> &columns)
|
||||
{
|
||||
for (auto &&col :columns) {
|
||||
const auto it = fields_by_name_.emplace(col.name(), field_index_pair {col, fields_.size()});
|
||||
fields_.push_back(std::ref(it.first->second.first));
|
||||
}
|
||||
}
|
||||
|
||||
record::record(const record &x)
|
||||
: fields_by_name_(x.fields_by_name_)
|
||||
//, pk_index_(x.pk_index_)
|
||||
{
|
||||
for (auto& col : x.fields_) {
|
||||
auto &it = fields_by_name_.at(col.get().name());
|
||||
fields_.push_back(std::ref(it.first));
|
||||
}
|
||||
}
|
||||
|
||||
record &record::operator=(const record &x)
|
||||
{
|
||||
if (&x == this) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
fields_by_name_ = x.fields_by_name_;
|
||||
fields_.clear();
|
||||
// pk_index_ = x.pk_index_;
|
||||
for (auto& col : x.fields_) {
|
||||
auto &it = fields_by_name_.at(col.get().name());
|
||||
fields_.push_back(std::ref(it.first));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
const std::vector<record::field_ref> &record::columns() const
|
||||
{
|
||||
return fields_;
|
||||
}
|
||||
|
||||
//bool record::has_primary_key() const
|
||||
//{
|
||||
// return pk_index_ > -1;
|
||||
//}
|
||||
//
|
||||
//std::optional<field> record::primary_key() const
|
||||
//{
|
||||
// if (!has_primary_key()) {
|
||||
// return std::nullopt;
|
||||
// }
|
||||
//
|
||||
// return columns_[pk_index_];
|
||||
//}
|
||||
|
||||
const field &record::at(const column &col) const
|
||||
{
|
||||
const auto &res = fields_by_name_.at(col.name);
|
||||
const auto &f = res.first;
|
||||
return f;
|
||||
}
|
||||
|
||||
const field &record::at(size_t index) const
|
||||
{
|
||||
return fields_.at(index);
|
||||
}
|
||||
|
||||
record::iterator record::find(const std::string &column_name)
|
||||
{
|
||||
auto it = fields_by_name_.find(column_name);
|
||||
return it != fields_by_name_.end() ? fields_.begin() + it->second.second : fields_.end();
|
||||
}
|
||||
|
||||
record::const_iterator record::find(const std::string &column_name) const {
|
||||
auto it = fields_by_name_.find(column_name);
|
||||
return it != fields_by_name_.end() ? fields_.begin() + it->second.second : fields_.end();
|
||||
}
|
||||
|
||||
void record::append(const field &col)
|
||||
{
|
||||
const auto it = fields_by_name_.emplace(col.name(), field_index_pair {col, fields_.size()});
|
||||
fields_.push_back(std::ref(it.first->second.first));
|
||||
}
|
||||
|
||||
record::iterator record::begin()
|
||||
{
|
||||
return fields_.begin();
|
||||
}
|
||||
|
||||
record::const_iterator record::begin() const
|
||||
{
|
||||
return fields_.begin();
|
||||
}
|
||||
|
||||
record::const_iterator record::cbegin() const
|
||||
{
|
||||
return fields_.cbegin();
|
||||
}
|
||||
|
||||
record::iterator record::end()
|
||||
{
|
||||
return fields_.end();
|
||||
}
|
||||
|
||||
record::const_iterator record::end() const
|
||||
{
|
||||
return fields_.end();
|
||||
}
|
||||
|
||||
record::const_iterator record::cend() const
|
||||
{
|
||||
return fields_.cend();
|
||||
}
|
||||
|
||||
size_t record::size() const
|
||||
{
|
||||
return fields_.size();
|
||||
}
|
||||
|
||||
bool record::empty() const
|
||||
{
|
||||
return fields_.empty();
|
||||
}
|
||||
|
||||
void record::clear()
|
||||
{
|
||||
fields_.clear();
|
||||
fields_by_name_.clear();
|
||||
}
|
||||
|
||||
//bool record::unknown() const
|
||||
//{
|
||||
// return std::all_of(std::begin(columns_), std::end(columns_), [](const auto &col) {
|
||||
// return col.type() == data_type_t::type_unknown;
|
||||
// });
|
||||
//}
|
||||
|
||||
void record::init()
|
||||
{
|
||||
size_t index{0};
|
||||
for(auto &col : fields_) {
|
||||
add_to_map(col, index++);
|
||||
}
|
||||
}
|
||||
|
||||
void record::add_to_map(field &col, size_t index)
|
||||
{
|
||||
fields_by_name_.emplace(col.name(), field_index_pair {std::ref(col), index});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
#include "matador/sql/statement.hpp"
|
||||
#include "matador/sql/record.hpp"
|
||||
#include "matador/sql/field.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
statement::statement(std::unique_ptr<statement_impl> impl, const std::shared_ptr<abstract_sql_logger> &logger)
|
||||
: statement_(std::move(impl))
|
||||
, logger_(logger)
|
||||
{}
|
||||
|
||||
statement &statement::bind(const size_t pos, const char *value)
|
||||
{
|
||||
statement_->bind(pos, value, 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
statement &statement::bind(const size_t pos, std::string &val, const size_t size)
|
||||
{
|
||||
statement_->bind(pos, val, size);
|
||||
return *this;
|
||||
}
|
||||
|
||||
utils::result<size_t, utils::error> statement::execute() const
|
||||
{
|
||||
// logger_.info(statement_->query_.sql);
|
||||
return statement_->execute();
|
||||
}
|
||||
|
||||
//bool is_unknown(const std::vector<sql::column_definition> &columns) {
|
||||
// return std::all_of(std::begin(columns), std::end(columns), [](const auto &col) {
|
||||
// return col.is_unknown();
|
||||
// });
|
||||
//}
|
||||
|
||||
utils::result<query_result<record>, utils::error> statement::fetch() const
|
||||
{
|
||||
// if (is_unknown(statement_->query_.prototype)) {
|
||||
//
|
||||
// }
|
||||
|
||||
auto result = statement_->fetch();
|
||||
if (!result.is_ok()) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
// logger_.info(statement_->query_.sql);
|
||||
return utils::ok(query_result<record>{std::move(*result)});
|
||||
}
|
||||
|
||||
utils::result<std::optional<record>, utils::error> statement::fetch_one() const {
|
||||
// logger_.info(statement_->query_.sql);
|
||||
auto result = statement_->fetch();
|
||||
if (!result.is_ok()) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
|
||||
query_result<record> records(std::move(*result));
|
||||
auto first = records.begin();
|
||||
if (first == records.end()) {
|
||||
return utils::ok(std::optional<record>{std::nullopt});
|
||||
}
|
||||
|
||||
return utils::ok(std::optional{*first.release()});
|
||||
}
|
||||
|
||||
void statement::reset() const
|
||||
{
|
||||
statement_->reset();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#include "matador/sql/table.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
table::table(const char* name)
|
||||
: table(std::string(name))
|
||||
{}
|
||||
|
||||
table::table(std::string name)
|
||||
: name(std::move(name))
|
||||
{}
|
||||
|
||||
table::table(const char *name, std::string as)
|
||||
: name(name)
|
||||
, alias(std::move(as))
|
||||
{}
|
||||
|
||||
table::table(std::string name, std::string as)
|
||||
: name(std::move(name))
|
||||
, alias(std::move(as))
|
||||
{}
|
||||
|
||||
bool table::operator==( const table& x ) const {
|
||||
return name == x.name;
|
||||
}
|
||||
|
||||
table & table::as(const std::string &a) {
|
||||
alias = a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
table table::as(const std::string &a) const {
|
||||
return { name, a, columns };
|
||||
}
|
||||
|
||||
bool table::has_alias() const {
|
||||
return !alias.empty();
|
||||
}
|
||||
|
||||
table operator ""_tab(const char *name, size_t len) {
|
||||
return {{name, len}};
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user