added sql function and alias
This commit is contained in:
parent
145c4dc0a3
commit
72f9d28d0d
|
|
@ -270,7 +270,7 @@ void sqlite_query_result::read_value(const char *id, size_t index, sql::any_type
|
|||
throw std::logic_error("data type blob not supported");
|
||||
}
|
||||
case sql::data_type_t::type_unknown: {
|
||||
value = result_[row_index_][index];
|
||||
value = std::string(result_[row_index_][index]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,15 +12,11 @@
|
|||
|
||||
namespace matador::sql {
|
||||
|
||||
namespace detail {
|
||||
|
||||
|
||||
}
|
||||
class column {
|
||||
public:
|
||||
explicit column(std::string name)
|
||||
: name_(std::move(name))
|
||||
, attributes_(utils::null_attributes) {}
|
||||
column(sql_function_t func, std::string name);
|
||||
column(const char *name, std::string alias = ""); // NOLINT(*-explicit-constructor)
|
||||
column(std::string name, std::string alias = ""); // NOLINT(*-explicit-constructor)
|
||||
|
||||
column(const column&) = default;
|
||||
column& operator=(const column&) = default;
|
||||
|
|
@ -50,9 +46,12 @@ public:
|
|||
[[nodiscard]] size_t index() const;
|
||||
[[nodiscard]] const utils::field_attributes& attributes() const;
|
||||
[[nodiscard]] data_type_t type() const;
|
||||
[[nodiscard]] const std::string& alias() const;
|
||||
[[nodiscard]] const std::string& ref_table() const;
|
||||
[[nodiscard]] const std::string& ref_column() const;
|
||||
|
||||
void alias(const std::string &as);
|
||||
|
||||
template< typename Type >
|
||||
[[nodiscard]] bool is_type_of() const {
|
||||
return std::holds_alternative<Type>(value_);
|
||||
|
|
@ -94,6 +93,9 @@ public:
|
|||
return visitor.result;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool is_function() const;
|
||||
[[nodiscard]] sql_function_t function() const;
|
||||
|
||||
private:
|
||||
template<class Operator>
|
||||
void process(Operator &op)
|
||||
|
|
@ -113,6 +115,8 @@ private:
|
|||
utils::field_attributes attributes_;
|
||||
data_type_t type_{data_type_t::type_unknown};
|
||||
any_type value_;
|
||||
sql_function_t function_{sql_function_t::NONE};
|
||||
std::string alias_;
|
||||
std::string ref_table_;
|
||||
std::string ref_column_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
#include "matador/utils/access.hpp"
|
||||
#include "matador/utils/field_attributes.hpp"
|
||||
#include "matador/utils/identifier.hpp"
|
||||
|
||||
#include <typeindex>
|
||||
#include <vector>
|
||||
|
||||
namespace matador::sql {
|
||||
|
|
|
|||
|
|
@ -30,14 +30,13 @@ public:
|
|||
[[nodiscard]] const connection_info& info() const;
|
||||
|
||||
[[nodiscard]] record describe(const std::string &table_name) const;
|
||||
bool exists(const std::string &table_name) const;
|
||||
[[nodiscard]] bool exists(const std::string &table_name) const;
|
||||
|
||||
template<class Type>
|
||||
query_result<Type> fetch(const std::string &sql)
|
||||
{
|
||||
return query_result<Type>(connection_->fetch(sql));
|
||||
}
|
||||
[[nodiscard]] query_result<record> fetch(const std::string &sql) const;
|
||||
[[nodiscard]] std::pair<size_t, std::string> execute(const std::string &sql) const;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
namespace matador::sql {
|
||||
|
||||
class column;
|
||||
|
||||
class dialect
|
||||
{
|
||||
public:
|
||||
|
|
@ -61,6 +63,7 @@ public:
|
|||
|
||||
using token_to_string_map = std::unordered_map<token_t, std::string>;
|
||||
using data_type_to_string_map = std::unordered_map<data_type_t, std::string>;
|
||||
using sql_func_to_string_map = std::unordered_map<sql_function_t, std::string>;
|
||||
|
||||
public:
|
||||
dialect() = default;
|
||||
|
|
@ -79,7 +82,7 @@ public:
|
|||
* @param str The identifier string to be prepared
|
||||
* @return The prepared string
|
||||
*/
|
||||
std::string prepare_identifier(const std::string &str) const;
|
||||
std::string prepare_identifier(const column &col) const;
|
||||
|
||||
/**
|
||||
* Prepare string literal
|
||||
|
|
@ -196,6 +199,15 @@ private:
|
|||
{data_type_t::type_null, "NULL"},
|
||||
{data_type_t::type_unknown, "UNKNOWN"}
|
||||
};
|
||||
|
||||
sql_func_to_string_map sql_func_map_ {
|
||||
{sql_function_t::NONE, "NONE" },
|
||||
{sql_function_t::COUNT, "COUNT" },
|
||||
{sql_function_t::AVG, "AVG" },
|
||||
{sql_function_t::SUM, "SUM" },
|
||||
{sql_function_t::MIN, "MIN" },
|
||||
{sql_function_t::MAX, "MAX" },
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,10 @@ struct any_type_to_string_visitor
|
|||
|
||||
}
|
||||
|
||||
column alias(const std::string &column, const std::string &as);
|
||||
column alias(column &&col, const std::string &as);
|
||||
column count(const std::string &column);
|
||||
|
||||
enum class join_type_t {
|
||||
INNER, OUTER, LEFT, RIGHT
|
||||
};
|
||||
|
|
@ -103,8 +107,8 @@ public:
|
|||
|
||||
query_builder& create();
|
||||
query_builder& drop();
|
||||
query_builder& select(std::initializer_list<std::string> column_names);
|
||||
query_builder& select(const std::vector<std::string> &column_names);
|
||||
query_builder& select(std::initializer_list<column> columns);
|
||||
query_builder& select(const std::vector<column> &columns);
|
||||
query_builder& insert();
|
||||
query_builder& update(const std::string &table);
|
||||
query_builder& remove();
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ protected:
|
|||
class query_select_intermediate : public query_start_intermediate
|
||||
{
|
||||
public:
|
||||
query_select_intermediate(session &s, std::vector<std::string> column_names);
|
||||
query_select_intermediate(session &s, const std::vector<column>& columns);
|
||||
|
||||
query_from_intermediate from(const std::string &table, const std::string &as = "");
|
||||
};
|
||||
|
|
|
|||
|
|
@ -105,6 +105,19 @@ private:
|
|||
query_result<Type> *result_{nullptr};
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template < typename Type >
|
||||
Type* create_prototype(const record &/*prototype*/)
|
||||
{
|
||||
return new Type{};
|
||||
}
|
||||
|
||||
template <>
|
||||
record* create_prototype<record>(const record &prototype);
|
||||
|
||||
}
|
||||
|
||||
template < typename Type >
|
||||
class query_result
|
||||
{
|
||||
|
|
@ -116,8 +129,8 @@ public:
|
|||
explicit query_result(std::unique_ptr<query_result_impl> impl)
|
||||
: impl_(std::move(impl)) {}
|
||||
|
||||
query_result(std::unique_ptr<query_result_impl> impl, creator_func creator)
|
||||
: creator_(creator)
|
||||
query_result(std::unique_ptr<query_result_impl> impl, record record_prototype)
|
||||
: record_prototype_(std::move(record_prototype))
|
||||
, impl_(std::move(impl)) {}
|
||||
|
||||
iterator begin() { return std::move(++iterator(this)); }
|
||||
|
|
@ -126,7 +139,7 @@ public:
|
|||
private:
|
||||
friend class query_result_iterator<Type>;
|
||||
|
||||
Type* create() { return creator_(); }
|
||||
Type* create() { return detail::create_prototype<Type>(record_prototype_); }
|
||||
|
||||
void bind(const Type &obj)
|
||||
{
|
||||
|
|
@ -139,7 +152,7 @@ private:
|
|||
}
|
||||
|
||||
private:
|
||||
creator_func creator_ = []{ return new Type; };
|
||||
record record_prototype_;
|
||||
std::unique_ptr<query_result_impl> impl_;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef QUERY_SESSION_HPP
|
||||
#define QUERY_SESSION_HPP
|
||||
|
||||
#include "matador/sql/column_name_generator.hpp"
|
||||
#include "matador/sql/column_generator.hpp"
|
||||
#include "matador/sql/connection.hpp"
|
||||
#include "matador/sql/connection_pool.hpp"
|
||||
#include "matador/sql/query_builder.hpp"
|
||||
|
|
@ -24,9 +24,9 @@ public:
|
|||
template < class Type >
|
||||
query_select_intermediate select()
|
||||
{
|
||||
return query_select_intermediate{*this, column_name_generator::generate<Type>()};
|
||||
return query_select_intermediate{*this, column_generator::generate<Type>(table_repository_)};
|
||||
}
|
||||
query_select_intermediate select(std::initializer_list<std::string> column_names);
|
||||
query_select_intermediate select(std::initializer_list<column> columns);
|
||||
query_insert_intermediate insert();
|
||||
query_update_intermediate update(const std::string &table);
|
||||
query_delete_intermediate remove();
|
||||
|
|
|
|||
|
|
@ -53,6 +53,16 @@ enum struct database_type_t : uint8_t {
|
|||
type_unknown /*!< Data type unknown */
|
||||
};
|
||||
|
||||
enum class sql_function_t {
|
||||
NONE,
|
||||
COUNT,
|
||||
AVG,
|
||||
SUM,
|
||||
MIN,
|
||||
MAX
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @tparam T The type of the traits
|
||||
* @brief Type traits for database types
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@ set(SQL_SOURCES
|
|||
sql/key_value_generator.cpp
|
||||
sql/fk_value_extractor.cpp
|
||||
sql/table_repository.cpp
|
||||
sql/any_type_to_visitor.cpp)
|
||||
sql/any_type_to_visitor.cpp
|
||||
sql/query_result.cpp)
|
||||
|
||||
set(SQL_HEADER
|
||||
../include/matador/sql/dialect.hpp
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ void convert(std::string &dest, bool source)
|
|||
|
||||
void convert(std::string &dest, const char *source)
|
||||
{
|
||||
dest = source;
|
||||
dest.assign(source);
|
||||
}
|
||||
|
||||
long long to_long_long(const char *source)
|
||||
|
|
|
|||
|
|
@ -1,28 +1,24 @@
|
|||
#include <utility>
|
||||
|
||||
#include "matador/sql/column.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
const column::data_type_index column::data_type_index_ {
|
||||
data_type_t::type_char,
|
||||
data_type_t::type_short,
|
||||
data_type_t::type_int,
|
||||
data_type_t::type_long,
|
||||
data_type_t::type_long_long,
|
||||
data_type_t::type_unsigned_char,
|
||||
data_type_t::type_unsigned_short,
|
||||
data_type_t::type_unsigned_int,
|
||||
data_type_t::type_unsigned_long,
|
||||
data_type_t::type_unsigned_long_long,
|
||||
data_type_t::type_float,
|
||||
data_type_t::type_double,
|
||||
data_type_t::type_bool,
|
||||
data_type_t::type_char_pointer,
|
||||
data_type_t::type_varchar,
|
||||
data_type_t::type_text,
|
||||
data_type_t::type_null,
|
||||
};
|
||||
column::column(sql_function_t func, std::string name)
|
||||
: name_(std::move(name))
|
||||
, type_(data_type_t::type_int)
|
||||
, attributes_(utils::null_attributes)
|
||||
, function_(func) {}
|
||||
|
||||
column::column(const char *name, std::string alias)
|
||||
: name_(name)
|
||||
, attributes_(utils::null_attributes)
|
||||
, alias_(std::move(alias)) {}
|
||||
|
||||
column::column(std::string name, std::string alias)
|
||||
: name_(std::move(name))
|
||||
, attributes_(utils::null_attributes)
|
||||
, alias_(std::move(alias)) {}
|
||||
|
||||
column::column(std::string name, data_type_t type, utils::field_attributes attr)
|
||||
: name_(std::move(name))
|
||||
|
|
@ -57,6 +53,11 @@ data_type_t column::type() const
|
|||
return type_;
|
||||
}
|
||||
|
||||
const std::string &column::alias() const
|
||||
{
|
||||
return alias_;
|
||||
}
|
||||
|
||||
const std::string &column::ref_table() const
|
||||
{
|
||||
return ref_table_;
|
||||
|
|
@ -67,6 +68,11 @@ const std::string &column::ref_column() const
|
|||
return ref_column_;
|
||||
}
|
||||
|
||||
void column::alias(const std::string &as)
|
||||
{
|
||||
alias_ = as;
|
||||
}
|
||||
|
||||
std::string column::str() const
|
||||
{
|
||||
any_type_to_visitor<std::string> visitor;
|
||||
|
|
@ -74,9 +80,19 @@ std::string column::str() const
|
|||
return visitor.result;
|
||||
}
|
||||
|
||||
bool column::is_function() const
|
||||
{
|
||||
return function_ != sql_function_t::NONE;
|
||||
}
|
||||
|
||||
sql_function_t column::function() const
|
||||
{
|
||||
return function_;
|
||||
}
|
||||
|
||||
column operator "" _col(const char *name, size_t len)
|
||||
{
|
||||
return column(std::string(name, len));
|
||||
return {std::string(name, len)};
|
||||
}
|
||||
|
||||
column make_column( const std::string& name, data_type_t type, utils::field_attributes attr )
|
||||
|
|
|
|||
|
|
@ -73,12 +73,6 @@ bool connection::exists(const std::string &table_name) const
|
|||
return connection_->exists(table_name);
|
||||
}
|
||||
|
||||
query_result<record> connection::fetch(const std::string &sql) const
|
||||
{
|
||||
auto rec = connection_->describe("person");
|
||||
return {connection_->fetch(sql), [rec](){ return new record(rec); }};
|
||||
}
|
||||
|
||||
std::pair<size_t, std::string> connection::execute(const std::string &sql) const
|
||||
{
|
||||
return {connection_->execute(sql), sql};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "matador/sql/dialect.hpp"
|
||||
#include "matador/sql/column.hpp"
|
||||
|
||||
#include "matador/utils/string.hpp"
|
||||
|
||||
|
|
@ -33,11 +34,15 @@ const std::string &dialect::data_type_at(data_type_t type) const
|
|||
return data_types_.at(type);
|
||||
}
|
||||
|
||||
std::string dialect::prepare_identifier(const std::string &str) const
|
||||
std::string dialect::prepare_identifier(const column &col) const
|
||||
{
|
||||
std::string result(str);
|
||||
std::string result(col.name());
|
||||
escape_quotes_in_identifier(result);
|
||||
quote_identifier(result);
|
||||
if (!col.is_function()) {
|
||||
quote_identifier(result);
|
||||
} else {
|
||||
return sql_func_map_.at(col.function()) + "(" + result + ")";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -97,12 +97,12 @@ query_builder& query_builder::drop() {
|
|||
return *this;
|
||||
}
|
||||
|
||||
query_builder& query_builder::select(std::initializer_list<std::string> column_names)
|
||||
query_builder& query_builder::select(std::initializer_list<column> columns)
|
||||
{
|
||||
return select(std::vector<std::string>{column_names});
|
||||
return select(std::vector<column>{columns});
|
||||
}
|
||||
|
||||
query_builder& query_builder::select(const std::vector<std::string> &column_names)
|
||||
query_builder &query_builder::select(const std::vector<column> &columns)
|
||||
{
|
||||
initialize(command_t::SELECT, state_t::QUERY_SELECT);
|
||||
|
||||
|
|
@ -111,15 +111,16 @@ query_builder& query_builder::select(const std::vector<std::string> &column_name
|
|||
query_.prototype.clear();
|
||||
|
||||
std::string result;
|
||||
if (column_names.size() < 2) {
|
||||
for (const auto &col : column_names) {
|
||||
if (columns.size() < 2) {
|
||||
for (const auto &col : columns) {
|
||||
result.append(dialect_.prepare_identifier(col));
|
||||
query_.prototype.append(column{col});
|
||||
query_.prototype.append(col);
|
||||
}
|
||||
} else {
|
||||
auto it = column_names.begin();
|
||||
auto it = columns.begin();
|
||||
result.append(dialect_.prepare_identifier(*it++));
|
||||
for (; it != column_names.end(); ++it) {
|
||||
query_.prototype.append(column{*it});
|
||||
for (; it != columns.end(); ++it) {
|
||||
result.append(", ");
|
||||
result.append(dialect_.prepare_identifier(*it));
|
||||
query_.prototype.append(column{*it});
|
||||
|
|
@ -444,4 +445,19 @@ std::string build_create_column(const column &col, const dialect &d, column_cont
|
|||
return result;
|
||||
}
|
||||
|
||||
column alias(const std::string &column, const std::string &as)
|
||||
{
|
||||
return {column, as};
|
||||
}
|
||||
|
||||
column alias(column &&col, const std::string &as) {
|
||||
col.alias(as);
|
||||
return std::move(col);
|
||||
}
|
||||
|
||||
column count(const std::string &column)
|
||||
{
|
||||
return {sql_function_t::COUNT, column};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -76,10 +76,10 @@ query_where_intermediate query_from_intermediate::where(const basic_condition &c
|
|||
return query_where_intermediate{session_, builder_.where(cond)};
|
||||
}
|
||||
|
||||
query_select_intermediate::query_select_intermediate(session &s, std::vector<std::string> column_names)
|
||||
query_select_intermediate::query_select_intermediate(session &s, const std::vector<column>& columns)
|
||||
: query_start_intermediate(s)
|
||||
{
|
||||
builder_.select(std::move(column_names));
|
||||
builder_.select(columns);
|
||||
}
|
||||
|
||||
query_from_intermediate query_select_intermediate::from(const std::string &table, const std::string &as)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
#include "matador/sql/query_result.hpp"
|
||||
|
||||
namespace matador::sql::detail {
|
||||
|
||||
template<>
|
||||
record *create_prototype<record>(const record &prototype)
|
||||
{
|
||||
return new record{prototype};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -20,10 +20,9 @@ query_drop_intermediate session::drop()
|
|||
return query_drop_intermediate{*this};
|
||||
}
|
||||
|
||||
query_select_intermediate session::select(std::initializer_list<std::string> column_names)
|
||||
query_select_intermediate session::select(std::initializer_list<column> columns)
|
||||
{
|
||||
|
||||
return query_select_intermediate{*this, column_names};
|
||||
return {*this, columns};
|
||||
}
|
||||
|
||||
query_insert_intermediate session::insert()
|
||||
|
|
@ -52,7 +51,8 @@ query_result<record> session::fetch(const query &q) const
|
|||
it = prototypes_.emplace(q.table_name, c->describe(q.table_name)).first;
|
||||
}
|
||||
auto res = c->call_fetch(q.sql);
|
||||
return query_result<record>{std::move(res), [it]() { return new record(it->second); }};
|
||||
return query_result<record>{std::move(res), q.prototype};
|
||||
// return query_result<record>{std::move(res), [it]() { return new record(it->second); }};
|
||||
}
|
||||
|
||||
//query_result<record> session::fetch(const std::string &sql) const
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ add_executable(tests builder.cpp
|
|||
models/flight.hpp
|
||||
models/person.hpp
|
||||
AnyTypeToVisitorTest.cpp
|
||||
ColumnTest.cpp)
|
||||
ColumnTest.cpp
|
||||
SessionRecordTest.cpp)
|
||||
target_link_libraries(tests PRIVATE
|
||||
Catch2::Catch2WithMain
|
||||
matador
|
||||
|
|
|
|||
|
|
@ -0,0 +1,200 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include <matador/sql/condition.hpp>
|
||||
#include <matador/sql/session.hpp>
|
||||
|
||||
#include <list>
|
||||
|
||||
using namespace matador::sql;
|
||||
|
||||
TEST_CASE("Create and drop table statement", "[session record]") {
|
||||
connection_pool<connection> pool("sqlite://sqlite.db", 4);
|
||||
session s(pool);
|
||||
|
||||
auto res = s.create()
|
||||
.table("person", {
|
||||
make_pk_column<unsigned long>("id"),
|
||||
make_column<std::string>("name", 255),
|
||||
make_column<unsigned short>("age")
|
||||
})
|
||||
.execute();
|
||||
|
||||
REQUIRE(res.second == R"(CREATE TABLE "person" ("id" BIGINT NOT NULL, "name" VARCHAR(255), "age" INTEGER, CONSTRAINT PK_person PRIMARY KEY (id)))");
|
||||
|
||||
res = s.drop()
|
||||
.table("person")
|
||||
.execute();
|
||||
|
||||
REQUIRE(res.second == R"(DROP TABLE "person")");
|
||||
}
|
||||
|
||||
TEST_CASE("Execute insert record statement", "[session record]") {
|
||||
connection_pool<connection> pool("sqlite://sqlite.db", 4);
|
||||
session s(pool);
|
||||
|
||||
auto res = s.create()
|
||||
.table("person", {
|
||||
make_pk_column<unsigned long>("id"),
|
||||
make_column<std::string>("name", 255),
|
||||
make_column<unsigned short>("age")
|
||||
})
|
||||
.execute();
|
||||
|
||||
REQUIRE(res.first == 0);
|
||||
|
||||
res = s.insert()
|
||||
.into("person", {"id", "name", "age"})
|
||||
.values({7, "george", 45})
|
||||
.execute();
|
||||
|
||||
REQUIRE(res.first == 1);
|
||||
REQUIRE(res.second == R"(INSERT INTO "person" ("id", "name", "age") VALUES (7, 'george', 45))");
|
||||
|
||||
auto result = s.select({"id", "name", "age"})
|
||||
.from("person")
|
||||
.fetch_all();
|
||||
|
||||
for (const auto& i : result) {
|
||||
REQUIRE(i.size() == 3);
|
||||
REQUIRE(i.at(0).name() == "id");
|
||||
REQUIRE(i.at(0).type() == data_type_t::type_long_long);
|
||||
REQUIRE(i.at(0).as<long long>() == 7);
|
||||
REQUIRE(i.at(1).name() == "name");
|
||||
REQUIRE(i.at(1).type() == data_type_t::type_varchar);
|
||||
REQUIRE(i.at(1).as<std::string>() == "george");
|
||||
REQUIRE(i.at(2).name() == "age");
|
||||
REQUIRE(i.at(2).type() == matador::sql::data_type_t::type_int);
|
||||
REQUIRE(i.at(2).as<int>() == 45);
|
||||
}
|
||||
|
||||
s.drop()
|
||||
.table("person")
|
||||
.execute();
|
||||
}
|
||||
|
||||
TEST_CASE("Execute update record statement", "[session record]") {
|
||||
connection_pool<connection> pool("sqlite://sqlite.db", 4);
|
||||
session s(pool);
|
||||
|
||||
auto res = s.create()
|
||||
.table("person", {
|
||||
make_pk_column<unsigned long>("id"),
|
||||
make_column<std::string>("name", 255),
|
||||
make_column<unsigned short>("age")
|
||||
})
|
||||
.execute();
|
||||
|
||||
REQUIRE(res.first == 0);
|
||||
|
||||
res = s.insert()
|
||||
.into("person", {"id", "name", "age"})
|
||||
.values({7, "george", 45})
|
||||
.execute();
|
||||
|
||||
REQUIRE(res.first == 1);
|
||||
REQUIRE(res.second == R"(INSERT INTO "person" ("id", "name", "age") VALUES (7, 'george', 45))");
|
||||
|
||||
res = s.update("person")
|
||||
.set({{"id", 7}, {"name", "jane"}, {"age", 35}})
|
||||
.where("id"_col == 7)
|
||||
.execute();
|
||||
|
||||
REQUIRE(res.first == 1);
|
||||
REQUIRE(res.second == R"(UPDATE "person" SET "id"=7, "name"='jane', "age"=35 WHERE "id" = 7)");
|
||||
|
||||
auto result = s.select({"id", "name", "age"})
|
||||
.from("person")
|
||||
.fetch_all();
|
||||
|
||||
for (const auto& i : result) {
|
||||
REQUIRE(i.size() == 3);
|
||||
REQUIRE(i.at(0).name() == "id");
|
||||
REQUIRE(i.at(0).type() == data_type_t::type_long_long);
|
||||
REQUIRE(i.at(0).as<long long>() == 7);
|
||||
REQUIRE(i.at(1).name() == "name");
|
||||
REQUIRE(i.at(1).type() == data_type_t::type_varchar);
|
||||
REQUIRE(i.at(1).as<std::string>() == "jane");
|
||||
REQUIRE(i.at(2).name() == "age");
|
||||
REQUIRE(i.at(2).type() == matador::sql::data_type_t::type_int);
|
||||
REQUIRE(i.at(2).as<int>() == 35);
|
||||
}
|
||||
|
||||
s.drop().table("person").execute();
|
||||
}
|
||||
|
||||
TEST_CASE("Execute select statement with order by", "[session record]") {
|
||||
connection_pool<connection> pool("sqlite://sqlite.db", 4);
|
||||
session s(pool);
|
||||
|
||||
auto res = s.create()
|
||||
.table("person", {
|
||||
make_pk_column<unsigned long>("id"),
|
||||
make_column<std::string>("name", 255),
|
||||
make_column<unsigned short>("age")
|
||||
})
|
||||
.execute();
|
||||
|
||||
REQUIRE(res.first == 0);
|
||||
|
||||
res = s.insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute();
|
||||
REQUIRE(res.first == 1);
|
||||
res = s.insert().into("person", {"id", "name", "age"}).values({2, "jane", 32}).execute();
|
||||
REQUIRE(res.first == 1);
|
||||
res = s.insert().into("person", {"id", "name", "age"}).values({3, "michael", 67}).execute();
|
||||
REQUIRE(res.first == 1);
|
||||
res = s.insert().into("person", {"id", "name", "age"}).values({4, "bob", 13}).execute();
|
||||
REQUIRE(res.first == 1);
|
||||
|
||||
auto result = s.select({"id", "name", "age"})
|
||||
.from("person")
|
||||
.where("id"_col == 8)
|
||||
.order_by("name").desc()
|
||||
.fetch_all();
|
||||
|
||||
std::list<std::string> expected_names {"bob", "george", "jane", "michael"};
|
||||
for (const auto &p : result) {
|
||||
REQUIRE(p.at(1).str() == expected_names.front());
|
||||
expected_names.pop_front();
|
||||
}
|
||||
|
||||
s.drop().table("person").execute();
|
||||
}
|
||||
|
||||
TEST_CASE("Execute select statement with group by and order by", "[session record]") {
|
||||
connection_pool<connection> pool("sqlite://sqlite.db", 4);
|
||||
session s(pool);
|
||||
|
||||
auto res = s.create()
|
||||
.table("person", {
|
||||
make_pk_column<unsigned long>("id"),
|
||||
make_column<std::string>("name", 255),
|
||||
make_column<unsigned short>("age")
|
||||
})
|
||||
.execute();
|
||||
|
||||
res = s.insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute();
|
||||
REQUIRE(res.first == 1);
|
||||
res = s.insert().into("person", {"id", "name", "age"}).values({2, "jane", 45}).execute();
|
||||
REQUIRE(res.first == 1);
|
||||
res = s.insert().into("person", {"id", "name", "age"}).values({3, "michael", 13}).execute();
|
||||
REQUIRE(res.first == 1);
|
||||
res = s.insert().into("person", {"id", "name", "age"}).values({4, "bob", 13}).execute();
|
||||
REQUIRE(res.first == 1);
|
||||
res = s.insert().into("person", {"id", "name", "age"}).values({5, "charlie", 67}).execute();
|
||||
REQUIRE(res.first == 1);
|
||||
|
||||
auto result = s.select({alias(count("age"), "age_count"), "age"})
|
||||
.from("person")
|
||||
.group_by("age")
|
||||
.order_by("age_count").asc()
|
||||
.fetch_all();
|
||||
|
||||
std::list<std::pair<int, int>> expected_values {{2, 13}, {2, 45}, {1, 67}};
|
||||
for (const auto &r : result) {
|
||||
REQUIRE(r.at(0).as<int>() == expected_values.front().first);
|
||||
REQUIRE(r.at(1).as<int>() == expected_values.front().second);
|
||||
expected_values.pop_front();
|
||||
}
|
||||
|
||||
s.drop().table("person").execute();
|
||||
}
|
||||
166
test/session.cpp
166
test/session.cpp
|
|
@ -12,24 +12,6 @@
|
|||
using namespace matador::sql;
|
||||
using namespace matador::test;
|
||||
|
||||
TEST_CASE("Create and drop table statement", "[session]") {
|
||||
connection_pool<connection> pool("sqlite://sqlite.db", 4);
|
||||
session s(pool);
|
||||
|
||||
auto res = s.create()
|
||||
.table("person", {
|
||||
make_pk_column<unsigned long>("id"),
|
||||
make_column<std::string>("name", 255),
|
||||
make_column<unsigned short>("age")
|
||||
}).execute();
|
||||
|
||||
REQUIRE(res.second == R"(CREATE TABLE "person" ("id" BIGINT NOT NULL, "name" VARCHAR(255), "age" INTEGER, CONSTRAINT PK_person PRIMARY KEY (id)))");
|
||||
|
||||
res = s.drop().table("person").execute();
|
||||
|
||||
REQUIRE(res.second == R"(DROP TABLE "person")");
|
||||
}
|
||||
|
||||
TEST_CASE("Create table with foreign key relation", "[session]") {
|
||||
connection_pool<connection> pool("sqlite://sqlite.db", 4);
|
||||
session s(pool);
|
||||
|
|
@ -46,104 +28,6 @@ TEST_CASE("Create table with foreign key relation", "[session]") {
|
|||
s.drop().table("airplane").execute();
|
||||
}
|
||||
|
||||
TEST_CASE("Execute insert record statement", "[session]") {
|
||||
connection_pool<connection> pool("sqlite://sqlite.db", 4);
|
||||
session s(pool);
|
||||
|
||||
auto res = s
|
||||
.create()
|
||||
.table("person", {
|
||||
make_pk_column<unsigned long>("id"),
|
||||
make_column<std::string>("name", 255),
|
||||
make_column<unsigned short>("age")
|
||||
})
|
||||
.execute();
|
||||
|
||||
REQUIRE(res.first == 0);
|
||||
|
||||
res = s
|
||||
.insert()
|
||||
.into("person", {"id", "name", "age"})
|
||||
.values({7, "george", 45})
|
||||
.execute();
|
||||
|
||||
REQUIRE(res.first == 1);
|
||||
REQUIRE(res.second == R"(INSERT INTO "person" ("id", "name", "age") VALUES (7, 'george', 45))");
|
||||
|
||||
auto result = s
|
||||
.select({"id", "name", "age"})
|
||||
.from("person")
|
||||
.fetch_all();
|
||||
|
||||
for (const auto& i : result) {
|
||||
REQUIRE(i.size() == 3);
|
||||
REQUIRE(i.at(0).name() == "id");
|
||||
REQUIRE(i.at(0).type() == data_type_t::type_long_long);
|
||||
REQUIRE(i.at(0).as<long long>() == 7);
|
||||
REQUIRE(i.at(1).name() == "name");
|
||||
REQUIRE(i.at(1).type() == data_type_t::type_varchar);
|
||||
REQUIRE(i.at(1).as<std::string>() == "george");
|
||||
REQUIRE(i.at(2).name() == "age");
|
||||
REQUIRE(i.at(2).type() == matador::sql::data_type_t::type_int);
|
||||
REQUIRE(i.at(2).as<int>() == 45);
|
||||
}
|
||||
|
||||
s.drop().table("person").execute();
|
||||
}
|
||||
|
||||
TEST_CASE("Execute update record statement", "[session]") {
|
||||
connection_pool<connection> pool("sqlite://sqlite.db", 4);
|
||||
session s(pool);
|
||||
|
||||
auto res = s
|
||||
.create()
|
||||
.table("person", {
|
||||
make_pk_column<unsigned long>("id"),
|
||||
make_column<std::string>("name", 255),
|
||||
make_column<unsigned short>("age")
|
||||
})
|
||||
.execute();
|
||||
|
||||
REQUIRE(res.first == 0);
|
||||
|
||||
res = s
|
||||
.insert()
|
||||
.into("person", {"id", "name", "age"})
|
||||
.values({7, "george", 45})
|
||||
.execute();
|
||||
|
||||
REQUIRE(res.first == 1);
|
||||
REQUIRE(res.second == R"(INSERT INTO "person" ("id", "name", "age") VALUES (7, 'george', 45))");
|
||||
|
||||
res = s.update("person")
|
||||
.set({{"id", 7}, {"name", "jane"}, {"age", 35}})
|
||||
.where("id"_col == 7)
|
||||
.execute();
|
||||
|
||||
REQUIRE(res.first == 1);
|
||||
REQUIRE(res.second == R"(UPDATE "person" SET "id"=7, "name"='jane', "age"=35 WHERE "id" = 7)");
|
||||
|
||||
auto result = s
|
||||
.select({"id", "name", "age"})
|
||||
.from("person")
|
||||
.fetch_all();
|
||||
|
||||
for (const auto& i : result) {
|
||||
REQUIRE(i.size() == 3);
|
||||
REQUIRE(i.at(0).name() == "id");
|
||||
REQUIRE(i.at(0).type() == data_type_t::type_long_long);
|
||||
REQUIRE(i.at(0).as<long long>() == 7);
|
||||
REQUIRE(i.at(1).name() == "name");
|
||||
REQUIRE(i.at(1).type() == data_type_t::type_varchar);
|
||||
REQUIRE(i.at(1).as<std::string>() == "jane");
|
||||
REQUIRE(i.at(2).name() == "age");
|
||||
REQUIRE(i.at(2).type() == matador::sql::data_type_t::type_int);
|
||||
REQUIRE(i.at(2).as<int>() == 35);
|
||||
}
|
||||
|
||||
s.drop().table("person").execute();
|
||||
}
|
||||
|
||||
TEST_CASE("Execute select statement with where clause", "[session]") {
|
||||
connection_pool<connection> pool("sqlite://sqlite.db", 4);
|
||||
session s(pool);
|
||||
|
|
@ -213,56 +97,6 @@ TEST_CASE("Execute select statement with where clause", "[session]") {
|
|||
s.drop().table("person").execute();
|
||||
}
|
||||
|
||||
TEST_CASE("Execute select statement with order by", "[session]") {
|
||||
connection_pool<connection> pool("sqlite://sqlite.db", 4);
|
||||
session s(pool);
|
||||
|
||||
auto res = s
|
||||
.create()
|
||||
.table("person", {
|
||||
make_pk_column<unsigned long>("id"),
|
||||
make_column<std::string>("name", 255),
|
||||
make_column<std::string>("color", 63)
|
||||
})
|
||||
.execute();
|
||||
|
||||
REQUIRE(res.first == 0);
|
||||
|
||||
auto result = s.select({"id", "name", "color"})
|
||||
.from("person")
|
||||
.where("id"_col == 8)
|
||||
.order_by("name").desc()
|
||||
.fetch_all();
|
||||
|
||||
// Todo: prepare test data
|
||||
|
||||
s.drop().table("person").execute();
|
||||
}
|
||||
|
||||
TEST_CASE("Execute select statement with group by and order by", "[session]") {
|
||||
connection_pool<connection> pool("sqlite://sqlite.db", 4);
|
||||
session s(pool);
|
||||
|
||||
auto res = s.create()
|
||||
.table("person", {
|
||||
make_pk_column<unsigned long>("id"),
|
||||
make_column<std::string>("name", 255),
|
||||
make_column<std::string>("color", 63)
|
||||
})
|
||||
.execute();
|
||||
|
||||
auto result = s.select({"id", "name", "color"})
|
||||
.from("person")
|
||||
.where("id"_col == 8)
|
||||
.group_by("color")
|
||||
.order_by("name").asc()
|
||||
.fetch_all();
|
||||
|
||||
// Todo: prepare test data
|
||||
|
||||
s.drop().table("person").execute();
|
||||
}
|
||||
|
||||
TEST_CASE("Execute insert statement", "[session]") {
|
||||
connection_pool<connection> pool("sqlite://sqlite.db", 4);
|
||||
session s(pool);
|
||||
|
|
|
|||
Loading…
Reference in New Issue