added sqlite query result and enhanced column generator and value extractor
This commit is contained in:
+9
-4
@@ -13,7 +13,9 @@ set(SQL_SOURCES
|
||||
sql/backend_provider.cpp
|
||||
sql/query_result_impl.cpp
|
||||
sql/column_generator.cpp
|
||||
sql/column_name_generator.cpp)
|
||||
sql/column_name_generator.cpp
|
||||
sql/key_value_generator.cpp
|
||||
sql/fk_value_extractor.cpp)
|
||||
|
||||
set(SQL_HEADER
|
||||
../include/matador/sql/dialect.hpp
|
||||
@@ -36,8 +38,11 @@ set(SQL_HEADER
|
||||
../include/matador/sql/query_result_impl.hpp
|
||||
../include/matador/sql/column_generator.hpp
|
||||
../include/matador/sql/column_name_generator.hpp
|
||||
../include/matador/sql/value_generator.hpp
|
||||
../include/matador/sql/any_type.hpp)
|
||||
../include/matador/sql/value_extractor.hpp
|
||||
../include/matador/sql/any_type.hpp
|
||||
../include/matador/sql/key_value_generator.hpp
|
||||
../include/matador/sql/foreign.hpp
|
||||
../include/matador/sql/fk_value_extractor.hpp)
|
||||
|
||||
set(UTILS_HEADER
|
||||
../include/matador/utils/field_attributes.hpp
|
||||
@@ -57,7 +62,7 @@ set(UTILS_SOURCES
|
||||
utils/library.cpp
|
||||
utils/os.cpp
|
||||
utils/identifier.cpp
|
||||
sql/value_generator.cpp)
|
||||
sql/value_extractor.cpp)
|
||||
|
||||
add_library(matador STATIC ${SQL_SOURCES} ${SQL_HEADER} ${UTILS_SOURCES} ${UTILS_HEADER})
|
||||
target_include_directories(matador PUBLIC ${PROJECT_SOURCE_DIR}/include)
|
||||
|
||||
+30
-7
@@ -8,18 +8,38 @@ column::column(std::string name, data_type_t type, utils::field_attributes attr)
|
||||
, type_(type)
|
||||
, attributes_(attr) {}
|
||||
|
||||
const std::string &column::name() const {
|
||||
column::column(std::string name, data_type_t type, std::string ref_table, std::string ref_column, utils::field_attributes attr)
|
||||
: name_(std::move(name))
|
||||
, type_(type)
|
||||
, attributes_(attr)
|
||||
, ref_table_(std::move(ref_table))
|
||||
, ref_column_(std::move(ref_column)) {}
|
||||
|
||||
const std::string &column::name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
const utils::field_attributes &column::attributes() const {
|
||||
const utils::field_attributes &column::attributes() const
|
||||
{
|
||||
return attributes_;
|
||||
}
|
||||
|
||||
data_type_t column::type() const {
|
||||
data_type_t column::type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
const std::string &column::ref_table() const
|
||||
{
|
||||
return ref_table_;
|
||||
}
|
||||
|
||||
const std::string &column::ref_column() const
|
||||
{
|
||||
return ref_column_;
|
||||
}
|
||||
|
||||
column operator "" _col(const char *name, size_t len)
|
||||
{
|
||||
return column(std::string(name, len));
|
||||
@@ -31,17 +51,20 @@ column make_column( const std::string& name, data_type_t type, utils::field_attr
|
||||
}
|
||||
|
||||
template<>
|
||||
column make_column<std::string>( const std::string& name, utils::field_attributes attr ) {
|
||||
column make_column<std::string>( const std::string& name, utils::field_attributes attr )
|
||||
{
|
||||
return make_column(name, data_type_traits<std::string>::builtin_type(attr.size()), attr);
|
||||
}
|
||||
|
||||
template<>
|
||||
column make_fk_column<std::string>( const std::string& name, size_t size ) {
|
||||
column make_pk_column<std::string>( const std::string& name, size_t size )
|
||||
{
|
||||
return make_column<std::string>(name, { size, utils::constraints::FOREIGN_KEY });
|
||||
}
|
||||
|
||||
template<>
|
||||
column make_pk_column<std::string>( const std::string& name, size_t size ) {
|
||||
return make_column<std::string>(name, { size, utils::constraints::PRIMARY_KEY | utils::constraints::NOT_NULL});
|
||||
[[maybe_unused]] column make_fk_column<std::string>(const std::string& name, size_t size, const std::string &ref_table, const std::string &ref_column)
|
||||
{
|
||||
return {name, data_type_traits<std::string>::builtin_type(size), ref_table, ref_column, { size, utils::constraints::PRIMARY_KEY | utils::constraints::NOT_NULL}};
|
||||
}
|
||||
}
|
||||
@@ -20,70 +20,77 @@ void column_generator::on_revision(const char *id, unsigned long long int &x)
|
||||
void column_generator::on_belongs_to(const char *id, utils::identifiable &x, utils::cascade_type)
|
||||
{
|
||||
columns_.push_back(fk_column_generator_.generate(id, x));
|
||||
// x.primary_key().serialize(fk_column_generator)
|
||||
}
|
||||
|
||||
void column_generator::on_has_one(const char *id, utils::identifiable &x, utils::cascade_type)
|
||||
{
|
||||
|
||||
columns_.push_back(fk_column_generator_.generate(id, x));
|
||||
}
|
||||
|
||||
column fk_column_generator::generate(const char *id, utils::identifiable &x)
|
||||
{
|
||||
identifiable_ = x;
|
||||
id_ = id;
|
||||
x.primary_key().serialize(*this);
|
||||
return column_;
|
||||
return column{id, type_, { utils::constraints::FOREIGN_KEY }};
|
||||
}
|
||||
|
||||
template < typename Type >
|
||||
data_type_t determine_data_type(const Type &)
|
||||
{
|
||||
return data_type_traits<Type>::builtin_type(0);
|
||||
}
|
||||
|
||||
data_type_t determine_data_type(const std::string&, size_t size)
|
||||
{
|
||||
return data_type_traits<std::string>::builtin_type(size);
|
||||
}
|
||||
|
||||
void fk_column_generator::serialize(short &i, const utils::field_attributes &attributes)
|
||||
{
|
||||
column_.
|
||||
|
||||
type_ = determine_data_type(i);
|
||||
}
|
||||
|
||||
void fk_column_generator::serialize(int &i, const utils::field_attributes &attributes)
|
||||
{
|
||||
|
||||
type_ = determine_data_type(i);
|
||||
}
|
||||
|
||||
void fk_column_generator::serialize(long &i, const utils::field_attributes &attributes)
|
||||
{
|
||||
|
||||
type_ = determine_data_type(i);
|
||||
}
|
||||
|
||||
void fk_column_generator::serialize(long long int &i, const utils::field_attributes &attributes)
|
||||
{
|
||||
|
||||
type_ = determine_data_type(i);
|
||||
}
|
||||
|
||||
void fk_column_generator::serialize(unsigned short &i, const utils::field_attributes &attributes)
|
||||
{
|
||||
|
||||
type_ = determine_data_type(i);
|
||||
}
|
||||
|
||||
void fk_column_generator::serialize(unsigned int &i, const utils::field_attributes &attributes)
|
||||
{
|
||||
|
||||
type_ = determine_data_type(i);
|
||||
}
|
||||
|
||||
void fk_column_generator::serialize(unsigned long &i, const utils::field_attributes &attributes)
|
||||
{
|
||||
|
||||
type_ = determine_data_type(i);
|
||||
}
|
||||
|
||||
void fk_column_generator::serialize(unsigned long long int &i, const utils::field_attributes &attributes)
|
||||
{
|
||||
|
||||
type_ = determine_data_type(i);
|
||||
}
|
||||
|
||||
void fk_column_generator::serialize(std::string &string, const utils::field_attributes &attributes)
|
||||
void fk_column_generator::serialize(std::string &x, const utils::field_attributes &attributes)
|
||||
{
|
||||
|
||||
type_ = determine_data_type(x, attributes.size());
|
||||
}
|
||||
|
||||
void fk_column_generator::serialize(utils::null_type_t &type, const utils::field_attributes &attributes)
|
||||
{
|
||||
|
||||
type_ = data_type_t::type_null;
|
||||
}
|
||||
}
|
||||
+21
-4
@@ -3,6 +3,7 @@
|
||||
#include "matador/sql/backend_provider.hpp"
|
||||
#include "matador/sql/connection_impl.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
namespace matador::sql {
|
||||
@@ -10,19 +11,35 @@ namespace matador::sql {
|
||||
connection::connection(connection_info info)
|
||||
: connection_info_(std::move(info))
|
||||
{
|
||||
connection_ = backend_provider::instance().create_connection(connection_info_.type, connection_info_);
|
||||
connection_.reset(backend_provider::instance().create_connection(connection_info_.type, connection_info_));
|
||||
}
|
||||
|
||||
connection::connection(const std::string& dns)
|
||||
: connection(connection_info::parse(dns))
|
||||
{}
|
||||
|
||||
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) {
|
||||
connection_info_ = x.connection_info_;
|
||||
if (x.connection_) {
|
||||
throw std::runtime_error("couldn't copy connection with valid connection impl");
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
connection::~connection()
|
||||
{
|
||||
if (connection_->is_open()) {
|
||||
connection_->close();
|
||||
}
|
||||
backend_provider::instance().destroy_connection(connection_info_.type, connection_);
|
||||
backend_provider::instance().destroy_connection(connection_info_.type, connection_.release());
|
||||
connection_ = nullptr;
|
||||
}
|
||||
|
||||
@@ -48,11 +65,11 @@ const connection_info &connection::info() const
|
||||
|
||||
query_result<record> connection::fetch(const std::string &sql)
|
||||
{
|
||||
return {sql};
|
||||
return query_result<record>(connection_->fetch(sql));
|
||||
}
|
||||
|
||||
std::pair<size_t, std::string> connection::execute(const std::string &sql)
|
||||
{
|
||||
return {0, sql};
|
||||
return {connection_->execute(sql), sql};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#include "matador/sql/fk_value_extractor.hpp"
|
||||
|
||||
namespace matador::sql::detail {
|
||||
|
||||
void fk_value_extractor::on_primary_key(const char *, std::string &pk, size_t)
|
||||
{
|
||||
value_ = pk;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#include "matador/sql/key_value_generator.hpp"
|
||||
|
||||
#include "matador/sql/value_extractor.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "matador/sql/query_builder.hpp"
|
||||
#include "matador/sql/dialect.hpp"
|
||||
|
||||
#include "matador/utils/string.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace matador::sql {
|
||||
@@ -18,7 +20,6 @@ void any_type_to_string_visitor::to_string(std::string &val)
|
||||
}
|
||||
|
||||
}
|
||||
std::string build_create_column(const column &col, const dialect &d);
|
||||
|
||||
// poor mens state machine
|
||||
// but does the job for query
|
||||
@@ -148,6 +149,21 @@ query_builder& query_builder::table(const std::string &table, std::initializer_l
|
||||
return this->table(table, std::vector<column>{columns});
|
||||
}
|
||||
|
||||
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 column &col, const dialect &d, column_context &context);
|
||||
|
||||
query_builder &query_builder::table(const std::string &table, const std::vector<column> &columns) {
|
||||
transition_to(state_t::QUERY_TABLE_CREATE);
|
||||
|
||||
@@ -155,19 +171,31 @@ query_builder &query_builder::table(const std::string &table, const std::vector<
|
||||
|
||||
std::string result = "(";
|
||||
|
||||
column_context context;
|
||||
|
||||
if (columns.size() < 2) {
|
||||
for (const auto &col : columns) {
|
||||
result.append(build_create_column(col, dialect_));
|
||||
result.append(build_create_column(col, dialect_, context));
|
||||
}
|
||||
} else {
|
||||
auto it = columns.begin();
|
||||
result.append(build_create_column(*it++, dialect_));
|
||||
result.append(build_create_column(*it++, dialect_, context));
|
||||
for (; it != columns.end(); ++it) {
|
||||
result.append(", ");
|
||||
result.append(build_create_column(*it, dialect_));
|
||||
result.append(build_create_column(*it, dialect_, context));
|
||||
}
|
||||
}
|
||||
|
||||
if (!context.primary_keys.empty()) {
|
||||
result.append(", CONSTRAINT PK_" + table + " PRIMARY KEY (" + utils::join(context.primary_keys, ", ") + ")");
|
||||
}
|
||||
for (const auto &fk : context.foreign_contexts) {
|
||||
result += ", CONSTRAINT FK_" + table;
|
||||
result += "_" + fk.column;
|
||||
result += " FOREIGN KEY (" + fk.column + ")";
|
||||
result += " REFERENCES " + fk.ref_table + "(" + fk.ref_column + ")";
|
||||
}
|
||||
|
||||
result += ")";
|
||||
query_parts_.emplace_back(result);
|
||||
return *this;
|
||||
@@ -181,7 +209,13 @@ query_builder& query_builder::table(const std::string &table) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
query_builder& query_builder::into(const std::string &table, std::initializer_list<std::string> column_names) {
|
||||
query_builder& query_builder::into(const std::string &table, std::initializer_list<std::string> column_names)
|
||||
{
|
||||
return into(table, std::vector<std::string>{column_names});
|
||||
}
|
||||
|
||||
query_builder &query_builder::into(const std::string &table, const std::vector<std::string> &column_names)
|
||||
{
|
||||
transition_to(state_t::QUERY_INTO);
|
||||
|
||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::INTO) + " " + dialect_.prepare_identifier(table) + " ");
|
||||
@@ -205,7 +239,12 @@ query_builder& query_builder::into(const std::string &table, std::initializer_li
|
||||
return *this;
|
||||
}
|
||||
|
||||
query_builder& query_builder::values(std::initializer_list<any_type> values) {
|
||||
query_builder& query_builder::values(std::initializer_list<any_type> values)
|
||||
{
|
||||
return this->values(std::vector<any_type>{values});
|
||||
}
|
||||
|
||||
query_builder& query_builder::values(const std::vector<any_type> &values) {
|
||||
transition_to(state_t::QUERY_VALUES);
|
||||
|
||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::VALUES) + " ");
|
||||
@@ -252,7 +291,12 @@ query_builder &query_builder::on(const std::string &column, const std::string &j
|
||||
return *this;
|
||||
}
|
||||
|
||||
query_builder& query_builder::set(std::initializer_list<key_value_pair> key_values) {
|
||||
query_builder &query_builder::set(std::initializer_list<key_value_pair> key_values)
|
||||
{
|
||||
return set(std::vector<key_value_pair>{key_values});
|
||||
}
|
||||
|
||||
query_builder& query_builder::set(const std::vector<key_value_pair> &key_values) {
|
||||
transition_to(state_t::QUERY_SET);
|
||||
|
||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::SET) + " ");
|
||||
@@ -364,7 +408,7 @@ void query_builder::initialize(query_builder::command_t cmd, query_builder::stat
|
||||
query_parts_.clear();
|
||||
}
|
||||
|
||||
std::string build_create_column(const column &col, const dialect &d) {
|
||||
std::string build_create_column(const column &col, const dialect &d, column_context &context) {
|
||||
std::string result = d.prepare_identifier(col.name()) + " " + d.data_type_at(col.type());
|
||||
if (col.attributes().size() > 0) {
|
||||
result.append("(" + std::to_string(col.attributes().size()) +")");
|
||||
@@ -373,7 +417,12 @@ std::string build_create_column(const column &col, const dialect &d) {
|
||||
result.append(" NOT NULL");
|
||||
}
|
||||
if (is_constraint_set(col.attributes().options(), utils::constraints::PRIMARY_KEY)) {
|
||||
result.append(" PRIMARY KEY");
|
||||
// result.append(" PRIMARY KEY");
|
||||
context.primary_keys.emplace_back(col.name());
|
||||
}
|
||||
if (is_constraint_set(col.attributes().options(), utils::constraints::FOREIGN_KEY)) {
|
||||
// result.append(" FOREIGN KEY");
|
||||
context.foreign_contexts.push_back({col.name(), col.ref_table(), col.ref_column()});
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "matador/sql/query_intermediates.hpp"
|
||||
#include "matador/sql/session.hpp"
|
||||
#include "matador/sql/query_builder.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
session &query_intermediate::db()
|
||||
@@ -20,7 +19,7 @@ query_result<record> query_select_finish::fetch_all()
|
||||
|
||||
record query_select_finish::fetch_one()
|
||||
{
|
||||
return db().fetch(query().compile()).begin();
|
||||
return *db().fetch(query().compile()).begin().get();
|
||||
}
|
||||
|
||||
query_intermediate::query_intermediate(session &db, query_builder &query)
|
||||
@@ -131,8 +130,8 @@ query_execute_where_intermediate query_delete_from_intermediate::where(const bas
|
||||
return {db(), query().where(cond)};
|
||||
}
|
||||
|
||||
query_delete_from_intermediate query_delete_intermediate::from(const std::string &table, const std::string &as)
|
||||
query_delete_from_intermediate query_delete_intermediate::from(const std::string &table)
|
||||
{
|
||||
return {db(), query().from(table, as)};
|
||||
return {db(), query().from(table)};
|
||||
}
|
||||
}
|
||||
@@ -22,4 +22,14 @@ void query_result_impl::on_attribute(const char *id, std::string &value, const u
|
||||
read_value(id, column_index_++, value, attr.size());
|
||||
}
|
||||
|
||||
void query_result_impl::on_belongs_to(const char *id, utils::identifiable &x, utils::cascade_type)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void query_result_impl::on_has_one(const char *id, utils::identifiable &x, utils::cascade_type)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#include "matador/sql/value_extractor.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
value_extractor::value_extractor(std::vector<any_type> &values)
|
||||
: values_(values)
|
||||
{}
|
||||
|
||||
void value_extractor::on_primary_key(const char *, std::string &pk, size_t)
|
||||
{
|
||||
append(pk);
|
||||
}
|
||||
|
||||
void value_extractor::on_revision(const char *, unsigned long long int &rev)
|
||||
{
|
||||
append(rev);
|
||||
}
|
||||
|
||||
void value_extractor::on_attribute(const char *, char *x, const utils::field_attributes &)
|
||||
{
|
||||
append(x);
|
||||
}
|
||||
|
||||
void value_extractor::on_attribute(const char *, std::string &x, const utils::field_attributes &)
|
||||
{
|
||||
append(x);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
#include "matador/sql/value_generator.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
value_generator::value_generator(std::vector<any_type> &values)
|
||||
: values_(values)
|
||||
{}
|
||||
|
||||
void value_generator::on_primary_key(const char *, std::string &pk, size_t)
|
||||
{
|
||||
append(pk);
|
||||
}
|
||||
|
||||
void value_generator::on_revision(const char *, unsigned long long int &rev)
|
||||
{
|
||||
append(rev);
|
||||
}
|
||||
|
||||
void value_generator::on_attribute(const char *, char *x, const utils::field_attributes &)
|
||||
{
|
||||
append(x);
|
||||
}
|
||||
|
||||
void value_generator::on_attribute(const char *, std::string &x, const utils::field_attributes &)
|
||||
{
|
||||
append(x);
|
||||
}
|
||||
|
||||
void value_generator::on_belongs_to(const char *, utils::identifiable &x, utils::cascade_type) {
|
||||
|
||||
}
|
||||
|
||||
void value_generator::on_has_one(const char *, utils::identifiable &x, utils::cascade_type) {
|
||||
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -19,7 +19,8 @@ std::string getenv(const char *name) {
|
||||
|
||||
return var;
|
||||
#else
|
||||
return ::getenv(name);
|
||||
char *path = ::getenv(name);
|
||||
return path == nullptr ? "" : path;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -14,4 +14,9 @@ void replace_all(std::string &in, const std::string &from, const std::string &to
|
||||
}
|
||||
}
|
||||
|
||||
const std::string &to_string(const std::string &str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user