query progress
This commit is contained in:
parent
b9709d14c2
commit
7e1713ddd3
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
A fluent sql query_context builder
|
A fluent sql query_context builder
|
||||||
|
|
||||||
|
```MATADOR_BACKENDS_PATH=/home/sascha/Develop/query/cmake-build-debug/backends```
|
||||||
|
|
||||||
Object definition
|
Object definition
|
||||||
```cpp
|
```cpp
|
||||||
enum class Color {
|
enum class Color {
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ std::unique_ptr<sql::query_result_impl> postgres_connection::fetch(const std::st
|
||||||
std::string postgres_connection::generate_statement_name(const sql::query_context &query)
|
std::string postgres_connection::generate_statement_name(const sql::query_context &query)
|
||||||
{
|
{
|
||||||
std::stringstream name;
|
std::stringstream name;
|
||||||
name << query.table_name << "_" << query.command_name;
|
name << query.table.name << "_" << query.command_name;
|
||||||
auto result = postgres_connection::statement_name_map_.find(name.str());
|
auto result = postgres_connection::statement_name_map_.find(name.str());
|
||||||
|
|
||||||
if (result == postgres_connection::statement_name_map_.end()) {
|
if (result == postgres_connection::statement_name_map_.end()) {
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras)
|
||||||
include(CTest)
|
include(CTest)
|
||||||
include(Catch)
|
include(Catch)
|
||||||
|
|
||||||
set(POSTGRES_CONNECTION_STRING "postgres://test:test123@127.0.0.1:15432/test")
|
set(POSTGRES_CONNECTION_STRING "postgres://test:test123@127.0.0.1:5432/matador_test")
|
||||||
|
|
||||||
configure_file(Connection.hpp.in ${PROJECT_BINARY_DIR}/backends/postgres/test/connection.hpp @ONLY IMMEDIATE)
|
configure_file(Connection.hpp.in ${PROJECT_BINARY_DIR}/backends/postgres/test/connection.hpp @ONLY IMMEDIATE)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ TEST_CASE_METHOD(QueryFixture, "Execute select statement with where clause", "[s
|
||||||
for (const auto &i: result_record) {
|
for (const auto &i: result_record) {
|
||||||
REQUIRE(i.size() == 4);
|
REQUIRE(i.size() == 4);
|
||||||
REQUIRE(i.at(0).name() == "id");
|
REQUIRE(i.at(0).name() == "id");
|
||||||
REQUIRE(i.at(0).type() == data_type_t::type_unsigned_long);
|
REQUIRE(i.at(0).type() == data_type_t::type_long_long);
|
||||||
REQUIRE(i.at(0).as<long long>() == george.id);
|
REQUIRE(i.at(0).as<long long>() == george.id);
|
||||||
REQUIRE(i.at(1).name() == "name");
|
REQUIRE(i.at(1).name() == "name");
|
||||||
REQUIRE(i.at(1).type() == data_type_t::type_varchar);
|
REQUIRE(i.at(1).type() == data_type_t::type_varchar);
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#include "matador/utils/access.hpp"
|
#include "matador/utils/access.hpp"
|
||||||
|
|
||||||
#include "query_helper.hpp"
|
#include "matador/sql/query_helper.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
@ -20,8 +20,9 @@ struct author
|
||||||
unsigned short year_of_birth{};
|
unsigned short year_of_birth{};
|
||||||
bool distinguished{false};
|
bool distinguished{false};
|
||||||
|
|
||||||
template < typename Operator >
|
template<typename Operator>
|
||||||
void process(Operator &op) {
|
void process(Operator &op)
|
||||||
|
{
|
||||||
namespace field = matador::utils::access;
|
namespace field = matador::utils::access;
|
||||||
field::primary_key(op, "id", id);
|
field::primary_key(op, "id", id);
|
||||||
field::attribute(op, "first_name", first_name, 63);
|
field::attribute(op, "first_name", first_name, 63);
|
||||||
|
|
@ -39,8 +40,9 @@ struct book
|
||||||
std::string title;
|
std::string title;
|
||||||
unsigned short published_in{};
|
unsigned short published_in{};
|
||||||
|
|
||||||
template < typename Operator >
|
template<typename Operator>
|
||||||
void process(Operator &op) {
|
void process(Operator &op)
|
||||||
|
{
|
||||||
namespace field = matador::utils::access;
|
namespace field = matador::utils::access;
|
||||||
field::primary_key(op, "id", id);
|
field::primary_key(op, "id", id);
|
||||||
field::attribute(op, "title", title, 511);
|
field::attribute(op, "title", title, 511);
|
||||||
|
|
@ -60,7 +62,6 @@ int main()
|
||||||
const std::string env_var{"MATADOR_BACKENDS_PATH"};
|
const std::string env_var{"MATADOR_BACKENDS_PATH"};
|
||||||
|
|
||||||
std::string dns{"sqlite://demo.db"};
|
std::string dns{"sqlite://demo.db"};
|
||||||
// std::string dns{"memory://test"};
|
|
||||||
auto s = std::make_shared<schema>("main");
|
auto s = std::make_shared<schema>("main");
|
||||||
s->attach<author>("authors");
|
s->attach<author>("authors");
|
||||||
s->attach<book>("books");
|
s->attach<book>("books");
|
||||||
|
|
@ -71,10 +72,12 @@ int main()
|
||||||
auto create_authors_sql = c.query(s)
|
auto create_authors_sql = c.query(s)
|
||||||
.create()
|
.create()
|
||||||
.table<author>(qh::authors)
|
.table<author>(qh::authors)
|
||||||
// .str();
|
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
c.query(s).create().table<book>(qh::books).execute();
|
c.query(s)
|
||||||
|
.create()
|
||||||
|
.table<book>(qh::books)
|
||||||
|
.execute();
|
||||||
|
|
||||||
std::cout << "SQL: " << create_authors_sql << "\n";
|
std::cout << "SQL: " << create_authors_sql << "\n";
|
||||||
|
|
||||||
|
|
@ -90,7 +93,6 @@ int main()
|
||||||
.into<author>(qh::authors)
|
.into<author>(qh::authors)
|
||||||
.values(*mc)
|
.values(*mc)
|
||||||
.execute();
|
.execute();
|
||||||
// .str();
|
|
||||||
|
|
||||||
std::cout << "SQL: " << insert_authors_sql << "\n";
|
std::cout << "SQL: " << insert_authors_sql << "\n";
|
||||||
|
|
||||||
|
|
@ -99,16 +101,16 @@ int main()
|
||||||
.from(qh::authors)
|
.from(qh::authors)
|
||||||
.fetch_all();
|
.fetch_all();
|
||||||
|
|
||||||
for (const auto &row : result) {
|
for (const auto &row: result) {
|
||||||
std::cout << "Author " << row.at(qh::authors.first_name) << "\n";
|
std::cout << "Author " << row.at(qh::authors.first_name) << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
auto update_authors_sql = c.query(s)
|
auto update_authors_sql = c.query(s)
|
||||||
.update(qh::authors)
|
.update(qh::authors)
|
||||||
.set({{qh::authors.first_name, "Stephen"}, {qh::authors.last_name, "King"}})
|
.set({{qh::authors.first_name, "Stephen"},
|
||||||
|
{qh::authors.last_name, "King"}})
|
||||||
.where(qh::authors.last_name == "Crichton")
|
.where(qh::authors.last_name == "Crichton")
|
||||||
.execute();
|
.execute();
|
||||||
// .str();
|
|
||||||
|
|
||||||
std::cout << "SQL: " << update_authors_sql << "\n";
|
std::cout << "SQL: " << update_authors_sql << "\n";
|
||||||
|
|
||||||
|
|
@ -117,7 +119,7 @@ int main()
|
||||||
.from(qh::authors)
|
.from(qh::authors)
|
||||||
.fetch_all<author>();
|
.fetch_all<author>();
|
||||||
|
|
||||||
for (const auto &a : authors) {
|
for (const auto &a: authors) {
|
||||||
std::cout << "Author " << a.first_name << "\n";
|
std::cout << "Author " << a.first_name << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -143,13 +145,9 @@ int main()
|
||||||
.order_by(qh::books.title).asc()
|
.order_by(qh::books.title).asc()
|
||||||
.limit(5)
|
.limit(5)
|
||||||
.offset(2)
|
.offset(2)
|
||||||
// .str();
|
|
||||||
.fetch_all();
|
.fetch_all();
|
||||||
// .fetch_all<book>();
|
|
||||||
|
|
||||||
// std::cout << "SQL: " << select_books_sql << "\n";
|
for (const auto &r: select_books_sql) {
|
||||||
|
|
||||||
for (const auto &r : select_books_sql) {
|
|
||||||
std::cout << "R: " << r.at(qh::books.title) << ", " << r.at(qh::authors.last_name) << "\n";
|
std::cout << "R: " << r.at(qh::books.title) << ", " << r.at(qh::authors.last_name) << "\n";
|
||||||
}
|
}
|
||||||
// SELECT book.title, book.id, book.author_id, book.published_in, author.name
|
// SELECT book.title, book.id, book.author_id, book.published_in, author.name
|
||||||
|
|
@ -159,21 +157,11 @@ int main()
|
||||||
// ORDER BY "book.title" ASC
|
// ORDER BY "book.title" ASC
|
||||||
// OFFSET 2 LIMIT 5
|
// OFFSET 2 LIMIT 5
|
||||||
|
|
||||||
// char var[1024];
|
|
||||||
// size_t len{};
|
|
||||||
// const auto error = getenv_s(&len, var, 1024, env_var.c_str());
|
|
||||||
// if (error > 0) {
|
|
||||||
// std::cout << "error: unknown env var " << env_var << "\n";
|
|
||||||
// } else {
|
|
||||||
// std::cout << "env var: " << var << "\n";
|
|
||||||
// }
|
|
||||||
|
|
||||||
c.query(s).drop().table(qh::books).execute();
|
c.query(s).drop().table(qh::books).execute();
|
||||||
|
|
||||||
auto drop_authors_sql = c.query(s)
|
auto drop_authors_sql = c.query(s)
|
||||||
.drop()
|
.drop()
|
||||||
.table(qh::authors)
|
.table(qh::authors)
|
||||||
// .str();
|
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
std::cout << "SQL: " << drop_authors_sql << "\n";
|
std::cout << "SQL: " << drop_authors_sql << "\n";
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
#ifndef QUERY_ANY_TYPE_TO_STRING_VISITOR_HPP
|
||||||
|
#define QUERY_ANY_TYPE_TO_STRING_VISITOR_HPP
|
||||||
|
|
||||||
|
#include "matador/utils/types.hpp"
|
||||||
|
|
||||||
|
#include "matador/sql/placeholder.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
|
||||||
|
class dialect;
|
||||||
|
class query_context;
|
||||||
|
|
||||||
|
struct any_type_to_string_visitor
|
||||||
|
{
|
||||||
|
explicit any_type_to_string_visitor(const dialect &d, query_context &query);
|
||||||
|
|
||||||
|
void operator()(char &x) { to_string(x); }
|
||||||
|
void operator()(short &x) { to_string(x); }
|
||||||
|
void operator()(int &x) { to_string(x); }
|
||||||
|
void operator()(long &x) { to_string(x); }
|
||||||
|
void operator()(long long &x) { to_string(x); }
|
||||||
|
void operator()(unsigned char &x) { to_string(x); }
|
||||||
|
void operator()(unsigned short &x) { to_string(x); }
|
||||||
|
void operator()(unsigned int &x) { to_string(x); }
|
||||||
|
void operator()(unsigned long &x) { to_string(x); }
|
||||||
|
void operator()(unsigned long long &x) { to_string(x); }
|
||||||
|
void operator()(bool &x) { to_string(x); }
|
||||||
|
void operator()(float &x) { to_string(x); }
|
||||||
|
void operator()(double &x) { to_string(x); }
|
||||||
|
void operator()(const char *x) { to_string(x); }
|
||||||
|
void operator()(std::string &x) { to_string(x); }
|
||||||
|
void operator()(utils::blob &x) { to_string(x); }
|
||||||
|
void operator()(placeholder &x) { to_string(x); }
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
void to_string(Type &val)
|
||||||
|
{
|
||||||
|
result = std::to_string(val);
|
||||||
|
}
|
||||||
|
void to_string(const char *val);
|
||||||
|
void to_string(std::string &val);
|
||||||
|
void to_string(utils::blob &val);
|
||||||
|
void to_string(placeholder &val);
|
||||||
|
|
||||||
|
const dialect &d;
|
||||||
|
query_context &query;
|
||||||
|
std::string result;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif //QUERY_ANY_TYPE_TO_STRING_VISITOR_HPP
|
||||||
|
|
@ -41,6 +41,7 @@ private:
|
||||||
void visit(query_set_part &set_part) override;
|
void visit(query_set_part &set_part) override;
|
||||||
|
|
||||||
void visit(query_delete_part &delete_part) override;
|
void visit(query_delete_part &delete_part) override;
|
||||||
|
void visit(query_delete_from_part &delete_from_part) override;
|
||||||
|
|
||||||
void visit(query_create_part &create_part) override;
|
void visit(query_create_part &create_part) override;
|
||||||
void visit(query_create_table_part &create_table_part) override;
|
void visit(query_create_table_part &create_table_part) override;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#define QUERY_QUERY_CONTEXT_HPP
|
#define QUERY_QUERY_CONTEXT_HPP
|
||||||
|
|
||||||
#include "matador/sql/record.hpp"
|
#include "matador/sql/record.hpp"
|
||||||
|
#include "matador/sql/table.hpp"
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
||||||
|
|
@ -9,7 +10,7 @@ struct query_context
|
||||||
{
|
{
|
||||||
std::string sql;
|
std::string sql;
|
||||||
std::string command_name;
|
std::string command_name;
|
||||||
std::string table_name;
|
sql::table table{""};
|
||||||
record prototype;
|
record prototype;
|
||||||
std::vector<std::string> result_vars;
|
std::vector<std::string> result_vars;
|
||||||
std::vector<std::string> bind_vars;
|
std::vector<std::string> bind_vars;
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ public:
|
||||||
|
|
||||||
size_t execute();
|
size_t execute();
|
||||||
statement prepare();
|
statement prepare();
|
||||||
[[nodiscard]] std::string str() const;
|
[[nodiscard]] query_context build() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class query_select_finish : public query_intermediate
|
class query_select_finish : public query_intermediate
|
||||||
|
|
@ -72,7 +72,7 @@ public:
|
||||||
|
|
||||||
statement prepare();
|
statement prepare();
|
||||||
|
|
||||||
[[nodiscard]] std::string str() const;
|
[[nodiscard]] query_context build() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<query_result_impl> fetch();
|
std::unique_ptr<query_result_impl> fetch();
|
||||||
|
|
@ -275,7 +275,7 @@ class query_execute_where_intermediate : public query_execute_finish
|
||||||
public:
|
public:
|
||||||
using query_execute_finish::query_execute_finish;
|
using query_execute_finish::query_execute_finish;
|
||||||
|
|
||||||
query_execute_finish limit(int limit);
|
query_order_by_intermediate order_by(const column &col);
|
||||||
};
|
};
|
||||||
|
|
||||||
class query_set_intermediate : public query_execute_finish
|
class query_set_intermediate : public query_execute_finish
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ public:
|
||||||
virtual ~query_part() = default;
|
virtual ~query_part() = default;
|
||||||
virtual void accept(query_part_visitor &visitor) = 0;
|
virtual void accept(query_part_visitor &visitor) = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] dialect::token_t token() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
sql::dialect::token_t token_;
|
sql::dialect::token_t token_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ class query_values_part;
|
||||||
class query_update_part;
|
class query_update_part;
|
||||||
class query_set_part;
|
class query_set_part;
|
||||||
class query_delete_part;
|
class query_delete_part;
|
||||||
|
class query_delete_from_part;
|
||||||
class query_create_part;
|
class query_create_part;
|
||||||
class query_create_table_part;
|
class query_create_table_part;
|
||||||
class query_drop_part;
|
class query_drop_part;
|
||||||
|
|
@ -50,6 +51,7 @@ public:
|
||||||
virtual void visit(query_set_part &set_part) = 0;
|
virtual void visit(query_set_part &set_part) = 0;
|
||||||
|
|
||||||
virtual void visit(query_delete_part &delete_part) = 0;
|
virtual void visit(query_delete_part &delete_part) = 0;
|
||||||
|
virtual void visit(query_delete_from_part &delete_from_part) = 0;
|
||||||
|
|
||||||
virtual void visit(query_create_part &create_part) = 0;
|
virtual void visit(query_create_part &create_part) = 0;
|
||||||
virtual void visit(query_create_table_part &create_table_part) = 0;
|
virtual void visit(query_create_table_part &create_table_part) = 0;
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,7 @@ class query_offset_part : public query_part
|
||||||
public:
|
public:
|
||||||
explicit query_offset_part(size_t offset);
|
explicit query_offset_part(size_t offset);
|
||||||
|
|
||||||
size_t offset() const;
|
[[nodiscard]] size_t offset() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void accept(query_part_visitor &visitor) override;
|
void accept(query_part_visitor &visitor) override;
|
||||||
|
|
@ -171,7 +171,7 @@ class query_limit_part : public query_part
|
||||||
public:
|
public:
|
||||||
explicit query_limit_part(size_t limit);
|
explicit query_limit_part(size_t limit);
|
||||||
|
|
||||||
size_t limit() const;
|
[[nodiscard]] size_t limit() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void accept(query_part_visitor &visitor) override;
|
void accept(query_part_visitor &visitor) override;
|
||||||
|
|
@ -210,7 +210,7 @@ private:
|
||||||
class query_values_part : public query_part
|
class query_values_part : public query_part
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
query_values_part(std::vector<any_type> &&values);
|
explicit query_values_part(std::vector<any_type> &&values);
|
||||||
|
|
||||||
[[nodiscard]] const std::vector<any_type>& values() const;
|
[[nodiscard]] const std::vector<any_type>& values() const;
|
||||||
|
|
||||||
|
|
@ -258,6 +258,20 @@ private:
|
||||||
void accept(query_part_visitor &visitor) override;
|
void accept(query_part_visitor &visitor) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class query_delete_from_part : public query_part
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
query_delete_from_part(sql::table table);
|
||||||
|
|
||||||
|
[[nodiscard]] const sql::table& table() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void accept(query_part_visitor &visitor) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
sql::table table_;
|
||||||
|
};
|
||||||
|
|
||||||
class query_create_part : public query_part
|
class query_create_part : public query_part
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -273,7 +287,7 @@ public:
|
||||||
query_create_table_part(sql::table table, std::vector<sql::column_definition> columns);
|
query_create_table_part(sql::table table, std::vector<sql::column_definition> columns);
|
||||||
|
|
||||||
[[nodiscard]] const sql::table& table() const;
|
[[nodiscard]] const sql::table& table() const;
|
||||||
const std::vector<sql::column_definition>& columns() const;
|
[[nodiscard]] const std::vector<sql::column_definition>& columns() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void accept(query_part_visitor &visitor) override;
|
void accept(query_part_visitor &visitor) override;
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ struct table_info
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
record prototype;
|
record prototype;
|
||||||
void create(connection &conn) const;
|
void create(connection &conn, schema &scm) const;
|
||||||
void drop(connection &conn) const;
|
void drop(connection &conn, schema &scm) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class schema
|
class schema
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ set(SQL_SOURCES
|
||||||
sql/query_compiler.cpp
|
sql/query_compiler.cpp
|
||||||
sql/noop_connection.cpp
|
sql/noop_connection.cpp
|
||||||
sql/query_part.cpp
|
sql/query_part.cpp
|
||||||
|
sql/any_type_to_string_visitor.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SQL_HEADER
|
set(SQL_HEADER
|
||||||
|
|
@ -83,6 +84,8 @@ set(SQL_HEADER
|
||||||
../include/matador/sql/table.hpp
|
../include/matador/sql/table.hpp
|
||||||
../include/matador/sql/noop_connection.hpp
|
../include/matador/sql/noop_connection.hpp
|
||||||
../include/matador/sql/query_part.hpp
|
../include/matador/sql/query_part.hpp
|
||||||
|
../include/matador/sql/any_type_to_string_visitor.hpp
|
||||||
|
../include/matador/sql/query_helper.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(QUERY_SOURCES
|
set(QUERY_SOURCES
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
#include "matador/sql/any_type_to_string_visitor.hpp"
|
||||||
|
|
||||||
|
#include "matador/sql/dialect.hpp"
|
||||||
|
#include "matador/sql/query_context.hpp"
|
||||||
|
|
||||||
|
#include "matador/utils/string.hpp"
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
|
||||||
|
any_type_to_string_visitor::any_type_to_string_visitor(const dialect &d, query_context &query)
|
||||||
|
: d(d), query(query)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void any_type_to_string_visitor::to_string(const char *val)
|
||||||
|
{
|
||||||
|
result = "'" + d.prepare_literal(val) + "'";
|
||||||
|
}
|
||||||
|
|
||||||
|
void any_type_to_string_visitor::to_string(std::string &val)
|
||||||
|
{
|
||||||
|
result = "'" + d.prepare_literal(val) + "'";
|
||||||
|
}
|
||||||
|
|
||||||
|
void any_type_to_string_visitor::to_string(utils::blob &val)
|
||||||
|
{
|
||||||
|
// "This is a binary Data string" as binary data:
|
||||||
|
// MySQL: X'5468697320697320612062616E617279204461746120737472696E67'
|
||||||
|
// Postgres: E'\\x5468697320697320612062616E617279204461746120737472696E67'
|
||||||
|
// MSSQL: 0x5468697320697320612062616E617279204461746120737472696E67
|
||||||
|
// Sqlite: X'5468697320697320612062616E617279204461746120737472696E67'
|
||||||
|
result = d.token_at(dialect::token_t::BEGIN_BINARY_DATA) + utils::to_string(val) + d.token_at(dialect::token_t::END_BINARY_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
void any_type_to_string_visitor::to_string(placeholder &/*val*/)
|
||||||
|
{
|
||||||
|
query.bind_vars.emplace_back("unknown");
|
||||||
|
result = d.next_placeholder(query.bind_vars);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -97,7 +97,7 @@ sql::query connection::query(const std::shared_ptr<sql::schema> &schema) const
|
||||||
query_result<record> connection::fetch(const query_context &q) const
|
query_result<record> connection::fetch(const query_context &q) const
|
||||||
{
|
{
|
||||||
if (q.prototype.empty() || q.prototype.unknown()) {
|
if (q.prototype.empty() || q.prototype.unknown()) {
|
||||||
const auto table_prototype = describe(q.table_name);
|
const auto table_prototype = describe(q.table.name);
|
||||||
for (auto &col : q.prototype) {
|
for (auto &col : q.prototype) {
|
||||||
if (const auto rit = table_prototype.find(col.name()); col.type() == data_type_t::type_unknown && rit != table_prototype.end()) {
|
if (const auto rit = table_prototype.find(col.name()); col.type() == data_type_t::type_unknown && rit != table_prototype.end()) {
|
||||||
const_cast<column_definition&>(col).type(rit->type());
|
const_cast<column_definition&>(col).type(rit->type());
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,7 @@ query_builder &query_builder::update(const std::string &table)
|
||||||
{
|
{
|
||||||
initialize(command_t::UPDATE, state_t::QUERY_UPDATE);
|
initialize(command_t::UPDATE, state_t::QUERY_UPDATE);
|
||||||
|
|
||||||
query_.table_name = table;
|
query_.table = {table};
|
||||||
query_parts_.emplace_back(dialect::token_t::UPDATE, dialect_.token_at(dialect::token_t::UPDATE) + " " + dialect_.prepare_identifier(table));
|
query_parts_.emplace_back(dialect::token_t::UPDATE, dialect_.token_at(dialect::token_t::UPDATE) + " " + dialect_.prepare_identifier(table));
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
|
|
@ -213,7 +213,7 @@ query_builder &query_builder::table(const std::string &table, const std::vector<
|
||||||
transition_to(state_t::QUERY_TABLE_CREATE);
|
transition_to(state_t::QUERY_TABLE_CREATE);
|
||||||
|
|
||||||
query_parts_.emplace_back(dialect::token_t::TABLE, " " + dialect_.token_at(dialect::token_t::TABLE) + " " + dialect_.prepare_identifier(table) + " ");
|
query_parts_.emplace_back(dialect::token_t::TABLE, " " + dialect_.token_at(dialect::token_t::TABLE) + " " + dialect_.prepare_identifier(table) + " ");
|
||||||
query_.table_name = table;
|
query_.table = {table};
|
||||||
|
|
||||||
std::string result = "(";
|
std::string result = "(";
|
||||||
|
|
||||||
|
|
@ -252,7 +252,7 @@ query_builder &query_builder::table(const std::string &table)
|
||||||
transition_to(state_t::QUERY_TABLE_DROP);
|
transition_to(state_t::QUERY_TABLE_DROP);
|
||||||
|
|
||||||
query_parts_.emplace_back(dialect::token_t::TABLE, " " + dialect_.token_at(dialect::token_t::TABLE) + " " + dialect_.prepare_identifier(table));
|
query_parts_.emplace_back(dialect::token_t::TABLE, " " + dialect_.token_at(dialect::token_t::TABLE) + " " + dialect_.prepare_identifier(table));
|
||||||
query_.table_name = table;
|
query_.table = {table};
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
@ -267,7 +267,7 @@ query_builder &query_builder::into(const std::string &table, const std::vector<c
|
||||||
transition_to(state_t::QUERY_INTO);
|
transition_to(state_t::QUERY_INTO);
|
||||||
|
|
||||||
query_parts_.emplace_back(dialect::token_t::INTO, " " + dialect_.token_at(dialect::token_t::INTO) + " " + dialect_.prepare_identifier(table) + " ");
|
query_parts_.emplace_back(dialect::token_t::INTO, " " + dialect_.token_at(dialect::token_t::INTO) + " " + dialect_.prepare_identifier(table) + " ");
|
||||||
query_.table_name = table;
|
query_.table = {table};
|
||||||
|
|
||||||
std::string result{"("};
|
std::string result{"("};
|
||||||
if (column_names.size() < 2) {
|
if (column_names.size() < 2) {
|
||||||
|
|
@ -337,7 +337,7 @@ query_builder &query_builder::from(const std::string &table, const std::string &
|
||||||
"." + dialect_.prepare_identifier(table) +
|
"." + dialect_.prepare_identifier(table) +
|
||||||
(as.empty() ? "" : " AS " + dialect_.prepare_identifier(as)));
|
(as.empty() ? "" : " AS " + dialect_.prepare_identifier(as)));
|
||||||
}
|
}
|
||||||
query_.table_name = table;
|
query_.table = {table};
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
#include "matador/sql/query_data.hpp"
|
#include "matador/sql/query_data.hpp"
|
||||||
#include "matador/sql/column_definition.hpp"
|
#include "matador/sql/column_definition.hpp"
|
||||||
#include "matador/sql/dialect.hpp"
|
#include "matador/sql/dialect.hpp"
|
||||||
#include "matador/sql/query_builder.hpp"
|
#include "matador/sql/any_type_to_string_visitor.hpp"
|
||||||
|
|
||||||
#include "matador/utils/string.hpp"
|
#include "matador/utils/string.hpp"
|
||||||
|
|
||||||
|
|
@ -53,7 +53,7 @@ void query_compiler::visit(query_select_part &select_part)
|
||||||
|
|
||||||
void query_compiler::visit(query_from_part &from_part)
|
void query_compiler::visit(query_from_part &from_part)
|
||||||
{
|
{
|
||||||
query_.table_name = from_part.table().name;
|
query_.table = from_part.table();
|
||||||
if (dialect_.default_schema_name().empty()) {
|
if (dialect_.default_schema_name().empty()) {
|
||||||
query_.sql += " " + dialect_.token_at(dialect::token_t::FROM) +
|
query_.sql += " " + dialect_.token_at(dialect::token_t::FROM) +
|
||||||
" " + dialect_.prepare_identifier(from_part.table().name) +
|
" " + dialect_.prepare_identifier(from_part.table().name) +
|
||||||
|
|
@ -125,7 +125,7 @@ void query_compiler::visit(query_insert_part &insert_part)
|
||||||
|
|
||||||
void query_compiler::visit(query_into_part &into_part)
|
void query_compiler::visit(query_into_part &into_part)
|
||||||
{
|
{
|
||||||
query_.table_name = into_part.table().name;
|
query_.table = into_part.table();
|
||||||
query_.sql += " " + dialect_.token_at(dialect::token_t::INTO) +
|
query_.sql += " " + dialect_.token_at(dialect::token_t::INTO) +
|
||||||
" " + dialect_.prepare_identifier(into_part.table().name);
|
" " + dialect_.prepare_identifier(into_part.table().name);
|
||||||
|
|
||||||
|
|
@ -150,7 +150,7 @@ void query_compiler::visit(query_values_part &values_part)
|
||||||
{
|
{
|
||||||
query_.sql += " " + dialect_.token_at(dialect::token_t::VALUES);
|
query_.sql += " " + dialect_.token_at(dialect::token_t::VALUES);
|
||||||
|
|
||||||
detail::any_type_to_string_visitor value_to_string(dialect_, query_);
|
any_type_to_string_visitor value_to_string(dialect_, query_);
|
||||||
|
|
||||||
std::string result{"("};
|
std::string result{"("};
|
||||||
if (values_part.values().size() < 2) {
|
if (values_part.values().size() < 2) {
|
||||||
|
|
@ -177,13 +177,20 @@ void query_compiler::visit(query_values_part &values_part)
|
||||||
|
|
||||||
void query_compiler::visit(query_update_part &update_part)
|
void query_compiler::visit(query_update_part &update_part)
|
||||||
{
|
{
|
||||||
query_.table_name = update_part.table().name;
|
query_.table = update_part.table();
|
||||||
query_.sql = dialect_.token_at(dialect::token_t::UPDATE) + " " + dialect_.prepare_identifier(update_part.table().name);
|
query_.sql = dialect_.token_at(dialect::token_t::UPDATE) + " " + dialect_.prepare_identifier(update_part.table().name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void query_compiler::visit(query_delete_part &delete_part)
|
void query_compiler::visit(query_delete_part &delete_part)
|
||||||
{
|
{
|
||||||
|
query_.sql = dialect_.token_at(dialect::token_t::REMOVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void query_compiler::visit(query_delete_from_part &delete_from_part)
|
||||||
|
{
|
||||||
|
query_.table = delete_from_part.table();
|
||||||
|
query_.sql += " " + dialect_.token_at(delete_from_part.token()) +
|
||||||
|
" " + dialect_.prepare_identifier(delete_from_part.table().name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void query_compiler::visit(query_create_part &create_part)
|
void query_compiler::visit(query_create_part &create_part)
|
||||||
|
|
@ -209,7 +216,7 @@ std::string build_create_column(const column_definition &col, const dialect &d,
|
||||||
void query_compiler::visit(query_create_table_part &create_table_part)
|
void query_compiler::visit(query_create_table_part &create_table_part)
|
||||||
{
|
{
|
||||||
query_.sql += " " + dialect_.token_at(dialect::token_t::TABLE) + " " + dialect_.prepare_identifier(create_table_part.table().name) + " ";
|
query_.sql += " " + dialect_.token_at(dialect::token_t::TABLE) + " " + dialect_.prepare_identifier(create_table_part.table().name) + " ";
|
||||||
query_.table_name = create_table_part.table().name;
|
query_.table = create_table_part.table();
|
||||||
|
|
||||||
std::string result = "(";
|
std::string result = "(";
|
||||||
|
|
||||||
|
|
@ -251,7 +258,7 @@ void query_compiler::visit(query_set_part &set_part)
|
||||||
{
|
{
|
||||||
query_.sql += " " + dialect_.token_at(dialect::token_t::SET) + " ";
|
query_.sql += " " + dialect_.token_at(dialect::token_t::SET) + " ";
|
||||||
|
|
||||||
detail::any_type_to_string_visitor value_to_string(dialect_, query_);
|
any_type_to_string_visitor value_to_string(dialect_, query_);
|
||||||
std::string result;
|
std::string result;
|
||||||
if (set_part.key_values().size() < 2) {
|
if (set_part.key_values().size() < 2) {
|
||||||
for (const auto &col: set_part.key_values()) {
|
for (const auto &col: set_part.key_values()) {
|
||||||
|
|
@ -281,7 +288,7 @@ void query_compiler::visit(query_set_part &set_part)
|
||||||
void query_compiler::visit(query_drop_table_part &drop_table_part)
|
void query_compiler::visit(query_drop_table_part &drop_table_part)
|
||||||
{
|
{
|
||||||
query_.sql += " " + dialect_.token_at(dialect::token_t::TABLE) + " " + dialect_.prepare_identifier(drop_table_part.table().name);
|
query_.sql += " " + dialect_.token_at(dialect::token_t::TABLE) + " " + dialect_.prepare_identifier(drop_table_part.table().name);
|
||||||
query_.table_name = drop_table_part.table().name;
|
query_.table = drop_table_part.table();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string build_create_column(const column_definition &col, const dialect &d, column_context &context)
|
std::string build_create_column(const column_definition &col, const dialect &d, column_context &context)
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,10 @@ record query_select_finish::fetch_one()
|
||||||
return *connection_.fetch(compiler.compile(&data_)).begin().get();
|
return *connection_.fetch(compiler.compile(&data_)).begin().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string query_select_finish::str() const
|
query_context query_select_finish::build() const
|
||||||
{
|
{
|
||||||
query_compiler compiler(connection_.dialect());
|
query_compiler compiler(connection_.dialect());
|
||||||
return compiler.compile(&data_).sql;
|
return compiler.compile(&data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<query_result_impl> query_select_finish::fetch()
|
std::unique_ptr<query_result_impl> query_select_finish::fetch()
|
||||||
|
|
@ -184,10 +184,10 @@ statement query_execute_finish::prepare()
|
||||||
return connection_.prepare(compiler.compile(&data_));
|
return connection_.prepare(compiler.compile(&data_));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string query_execute_finish::str() const
|
query_context query_execute_finish::build() const
|
||||||
{
|
{
|
||||||
query_compiler compiler(connection_.dialect());
|
query_compiler compiler(connection_.dialect());
|
||||||
return compiler.compile(&data_).sql;
|
return compiler.compile(&data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_execute_finish query_into_intermediate::values(std::initializer_list<any_type> values)
|
query_execute_finish query_into_intermediate::values(std::initializer_list<any_type> values)
|
||||||
|
|
@ -229,10 +229,10 @@ query_execute_finish query_drop_intermediate::table(const sql::table &table)
|
||||||
return {connection_, schema_, data_};
|
return {connection_, schema_, data_};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_execute_finish query_execute_where_intermediate::limit(int limit)
|
query_order_by_intermediate query_execute_where_intermediate::order_by(const column &col)
|
||||||
{
|
{
|
||||||
|
data_.parts.push_back(std::make_unique<query_order_by_part>(col));
|
||||||
return {connection_, schema_, data_};
|
return {connection_, schema_, data_};
|
||||||
// return {connection_, builder_.limit(limit)};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
query_execute_where_intermediate query_set_intermediate::where_clause(std::unique_ptr<basic_condition> &&cond)
|
query_execute_where_intermediate query_set_intermediate::where_clause(std::unique_ptr<basic_condition> &&cond)
|
||||||
|
|
@ -273,6 +273,7 @@ query_delete_intermediate::query_delete_intermediate(connection &db, const std::
|
||||||
|
|
||||||
query_delete_from_intermediate query_delete_intermediate::from(const sql::table &table)
|
query_delete_from_intermediate query_delete_intermediate::from(const sql::table &table)
|
||||||
{
|
{
|
||||||
|
data_.parts.push_back(std::make_unique<query_delete_from_part>(table));
|
||||||
return {connection_, schema_, data_};
|
return {connection_, schema_, data_};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,5 +5,9 @@ namespace matador::sql {
|
||||||
query_part::query_part(sql::dialect::token_t token)
|
query_part::query_part(sql::dialect::token_t token)
|
||||||
: token_(token) {}
|
: token_(token) {}
|
||||||
|
|
||||||
|
dialect::token_t query_part::token() const
|
||||||
|
{
|
||||||
|
return token_;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -233,6 +233,20 @@ void query_delete_part::accept(query_part_visitor &visitor)
|
||||||
visitor.visit(*this);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query_delete_from_part::query_delete_from_part(sql::table table)
|
||||||
|
: query_part(sql::dialect::token_t::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_create_part::query_create_part()
|
||||||
: query_part(sql::dialect::token_t::CREATE) {}
|
: query_part(sql::dialect::token_t::CREATE) {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,12 @@
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
||||||
void table_info::create(connection &conn) const
|
void table_info::create(connection &conn, schema &scm) const
|
||||||
{
|
{
|
||||||
// conn.query().create().table(name, prototype.columns()).execute();
|
// conn.query().create().table(name, prototype.columns()).execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
void table_info::drop(connection &conn) const
|
void table_info::drop(connection &conn, schema &scm) const
|
||||||
{
|
{
|
||||||
// conn.query().drop().table(name).execute();
|
// conn.query().drop().table(name).execute();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ void session::create_schema()
|
||||||
{
|
{
|
||||||
auto c = pool_.acquire();
|
auto c = pool_.acquire();
|
||||||
for (const auto &t : *schema_) {
|
for (const auto &t : *schema_) {
|
||||||
t.second.create(*c);
|
t.second.create(*c, *schema_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,9 +35,9 @@ query_result<record> session::fetch(const query_context &q) const
|
||||||
if (!c.valid()) {
|
if (!c.valid()) {
|
||||||
throw std::logic_error("no database connection available");
|
throw std::logic_error("no database connection available");
|
||||||
}
|
}
|
||||||
auto it = prototypes_.find(q.table_name);
|
auto it = prototypes_.find(q.table.name);
|
||||||
if (it == prototypes_.end()) {
|
if (it == prototypes_.end()) {
|
||||||
it = prototypes_.emplace(q.table_name, c->describe(q.table_name)).first;
|
it = prototypes_.emplace(q.table.name, c->describe(q.table.name)).first;
|
||||||
}
|
}
|
||||||
// adjust columns from given query
|
// adjust columns from given query
|
||||||
for (auto &col : q.prototype) {
|
for (auto &col : q.prototype) {
|
||||||
|
|
|
||||||
|
|
@ -10,190 +10,242 @@
|
||||||
using namespace matador::sql;
|
using namespace matador::sql;
|
||||||
using namespace matador::utils;
|
using namespace matador::utils;
|
||||||
|
|
||||||
TEST_CASE("Create table sql statement string", "[query]") {
|
TEST_CASE("Create table sql statement string", "[query]")
|
||||||
|
{
|
||||||
connection noop("noop://noop.db");
|
connection noop("noop://noop.db");
|
||||||
auto scm = std::make_shared<schema>("noop");
|
auto scm = std::make_shared<schema>("noop");
|
||||||
query qu(noop, scm);
|
query q(noop, scm);
|
||||||
auto s = qu.create().table({"person"}, {
|
auto result = q.create().table({"person"}, {
|
||||||
make_pk_column<unsigned long>("id"),
|
make_pk_column<unsigned long>("id"),
|
||||||
make_column<std::string>("name", 255),
|
make_column<std::string>("name", 255),
|
||||||
make_column<unsigned short>("age")
|
make_column<unsigned short>("age")
|
||||||
}).str();
|
}).build();
|
||||||
|
|
||||||
dialect d = dialect_builder::builder().create().build();
|
REQUIRE(result.sql == R"##(CREATE TABLE "person" ("id" BIGINT NOT NULL, "name" VARCHAR(255) NOT NULL, "age" INTEGER NOT NULL, CONSTRAINT PK_person PRIMARY KEY (id)))##");
|
||||||
query_builder query(d);
|
REQUIRE(result.table.name == "person");
|
||||||
auto q = query.create().table("person", {
|
|
||||||
make_pk_column<unsigned long>("id"),
|
|
||||||
make_column<std::string>("name", 255),
|
|
||||||
make_column<unsigned short>("age")
|
|
||||||
}).compile();
|
|
||||||
|
|
||||||
REQUIRE(s == R"##(CREATE TABLE "person" ("id" BIGINT NOT NULL, "name" VARCHAR(255) NOT NULL, "age" INTEGER NOT NULL, CONSTRAINT PK_person PRIMARY KEY (id)))##");
|
result = q.create().table("person", {
|
||||||
// REQUIRE(q.sql == R"##(CREATE TABLE "person" ("id" BIGINT NOT NULL, "name" VARCHAR(255) NOT NULL, "age" INTEGER NOT NULL, CONSTRAINT PK_person PRIMARY KEY (id)))##");
|
make_pk_column<unsigned long>("id"),
|
||||||
REQUIRE(q.table_name == "person");
|
make_column<std::string>("name", {255, constraints::UNIQUE}, null_option::NOT_NULL),
|
||||||
|
make_column<unsigned short>("age"),
|
||||||
|
make_fk_column<unsigned long>("address", "address", "id")
|
||||||
|
}).build();
|
||||||
|
|
||||||
q = query.create().table("person", {
|
REQUIRE(result.sql == R"##(CREATE TABLE "person" ("id" BIGINT NOT NULL, "name" VARCHAR(255) NOT NULL UNIQUE, "age" INTEGER NOT NULL, "address" BIGINT NOT NULL, CONSTRAINT PK_person PRIMARY KEY (id), CONSTRAINT FK_person_address FOREIGN KEY (address) REFERENCES address(id)))##");
|
||||||
make_pk_column<unsigned long>("id"),
|
REQUIRE(result.table.name == "person");
|
||||||
make_column<std::string>("name", { 255, constraints::UNIQUE }, null_option::NOT_NULL),
|
|
||||||
make_column<unsigned short>("age"),
|
|
||||||
make_fk_column<unsigned long>("address", "address", "id")
|
|
||||||
}).compile();
|
|
||||||
|
|
||||||
REQUIRE(q.sql == R"##(CREATE TABLE "person" ("id" BIGINT NOT NULL, "name" VARCHAR(255) NOT NULL UNIQUE, "age" INTEGER NOT NULL, "address" BIGINT NOT NULL, CONSTRAINT PK_person PRIMARY KEY (id), CONSTRAINT FK_person_address FOREIGN KEY (address) REFERENCES address(id)))##");
|
|
||||||
REQUIRE(q.table_name == "person");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Drop table sql statement string", "[query]") {
|
TEST_CASE("Drop table sql statement string", "[query]")
|
||||||
dialect d = dialect_builder::builder().create().build();
|
{
|
||||||
query_builder query(d);
|
connection noop("noop://noop.db");
|
||||||
const auto q = query.drop().table("person").compile();
|
auto scm = std::make_shared<schema>("noop");
|
||||||
|
query q(noop, scm);
|
||||||
|
const auto result = q.drop().table("person").build();
|
||||||
|
|
||||||
REQUIRE(q.sql == R"(DROP TABLE "person")");
|
REQUIRE(result.sql == R"(DROP TABLE "person")");
|
||||||
REQUIRE(q.table_name == "person");
|
REQUIRE(result.table.name == "person");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Select sql statement string", "[query]") {
|
TEST_CASE("Select sql statement string", "[query]")
|
||||||
dialect d = dialect_builder::builder().create().build();
|
{
|
||||||
query_builder query(d);
|
connection noop("noop://noop.db");
|
||||||
const auto q = query.select({"id", "name", "age"}).from("person").compile();
|
auto scm = std::make_shared<schema>("noop");
|
||||||
|
query q(noop, scm);
|
||||||
|
const auto result = q.select({"id", "name", "age"}).from("person").build();
|
||||||
|
|
||||||
REQUIRE(q.sql == R"(SELECT "id", "name", "age" FROM "person")");
|
REQUIRE(result.sql == R"(SELECT "id", "name", "age" FROM "person")");
|
||||||
REQUIRE(q.table_name == "person");
|
REQUIRE(result.table.name == "person");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Insert sql statement string", "[query]") {
|
TEST_CASE("Insert sql statement string", "[query]")
|
||||||
dialect d = dialect_builder::builder().create().build();
|
{
|
||||||
query_builder query(d);
|
connection noop("noop://noop.db");
|
||||||
const auto q = query.insert().into("person", {
|
auto scm = std::make_shared<schema>("noop");
|
||||||
"id", "name", "age"
|
query q(noop, scm);
|
||||||
}).values({7UL, "george", 65U}).compile();
|
const auto result = q.insert().into("person", {
|
||||||
|
|
||||||
REQUIRE(q.sql == R"(INSERT INTO "person" ("id", "name", "age") VALUES (7, 'george', 65))");
|
|
||||||
REQUIRE(q.table_name == "person");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Update sql statement string", "[query]") {
|
|
||||||
dialect d = dialect_builder::builder().create().build();
|
|
||||||
query_builder query(d);
|
|
||||||
const auto q = query.update("person").set({
|
|
||||||
{"id", 7UL},
|
|
||||||
{"name", "george"},
|
|
||||||
{"age", 65U}
|
|
||||||
}).compile();
|
|
||||||
|
|
||||||
REQUIRE(q.sql == R"(UPDATE "person" SET "id"=7, "name"='george', "age"=65)");
|
|
||||||
REQUIRE(q.table_name == "person");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Delete sql statement string", "[query]") {
|
|
||||||
dialect d = dialect_builder::builder().create().build();
|
|
||||||
query_builder query(d);
|
|
||||||
const auto q = query.remove().from("person").compile();
|
|
||||||
|
|
||||||
REQUIRE(q.sql == R"(DELETE FROM "person")");
|
|
||||||
REQUIRE(q.table_name == "person");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Select sql statement string with where clause", "[query]") {
|
|
||||||
dialect d = dialect_builder::builder().create().build();
|
|
||||||
query_builder query(d);
|
|
||||||
auto q = query.select({"id", "name", "age"})
|
|
||||||
.from("person")
|
|
||||||
.where("id"_col == 8 && "age"_col > 50)
|
|
||||||
.compile();
|
|
||||||
|
|
||||||
REQUIRE(q.sql == R"(SELECT "id", "name", "age" FROM "person" WHERE ("id" = 8 AND "age" > 50))");
|
|
||||||
REQUIRE(q.table_name == "person");
|
|
||||||
|
|
||||||
q = query.select({"id", "name", "age"})
|
|
||||||
.from("person")
|
|
||||||
.where("id"_col == _ && "age"_col > 50)
|
|
||||||
.compile();
|
|
||||||
|
|
||||||
REQUIRE(q.sql == R"(SELECT "id", "name", "age" FROM "person" WHERE ("id" = ? AND "age" > 50))");
|
|
||||||
REQUIRE(q.table_name == "person");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Insert sql statement with placeholder", "[query]") {
|
|
||||||
dialect d = dialect_builder::builder().create().build();
|
|
||||||
query_builder query(d);
|
|
||||||
const auto q = query.insert().into("person", {
|
|
||||||
"id", "name", "age"
|
"id", "name", "age"
|
||||||
}).values({_, _, _}).compile();
|
}).values({7UL, "george", 65U}).build();
|
||||||
|
|
||||||
REQUIRE(q.sql == R"(INSERT INTO "person" ("id", "name", "age") VALUES (?, ?, ?))");
|
REQUIRE(result.sql == R"(INSERT INTO "person" ("id", "name", "age") VALUES (7, 'george', 65))");
|
||||||
REQUIRE(q.table_name == "person");
|
REQUIRE(result.table.name == "person");
|
||||||
REQUIRE(q.bind_vars.size() == 3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Select sql statement string with order by", "[query]") {
|
TEST_CASE("Update sql statement string", "[query]")
|
||||||
dialect d = dialect_builder::builder().create().build();
|
{
|
||||||
query_builder query(d);
|
connection noop("noop://noop.db");
|
||||||
const auto q = query.select({"id", "name", "age"})
|
auto scm = std::make_shared<schema>("noop");
|
||||||
.from("person")
|
query q(noop, scm);
|
||||||
.order_by("name").asc()
|
const auto result = q.update("person").set({
|
||||||
.compile();
|
{"id", 7UL},
|
||||||
|
{"name", "george"},
|
||||||
|
{"age", 65U}
|
||||||
|
}).build();
|
||||||
|
|
||||||
REQUIRE(q.sql == R"(SELECT "id", "name", "age" FROM "person" ORDER BY "name" ASC)");
|
REQUIRE(result.sql == R"(UPDATE "person" SET "id"=7, "name"='george', "age"=65)");
|
||||||
REQUIRE(q.table_name == "person");
|
REQUIRE(result.table.name == "person");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Select sql statement string with group by", "[query]") {
|
TEST_CASE("Update limit sql statement", "[query][update][limit]")
|
||||||
dialect d = dialect_builder::builder().create().build();
|
{
|
||||||
query_builder query(d);
|
connection noop("noop://noop.db");
|
||||||
const auto q = query.select({"id", "name", "age"})
|
auto scm = std::make_shared<schema>("noop");
|
||||||
.from("person")
|
query q(noop, scm);
|
||||||
.group_by("age")
|
const auto result = q.update("person")
|
||||||
.compile();
|
.set({{"id", 7UL}, {"name", "george"}, {"age", 65U}})
|
||||||
|
.where("name"_col == "george")
|
||||||
|
.order_by("id"_col).asc()
|
||||||
|
.limit(2)
|
||||||
|
.build();
|
||||||
|
|
||||||
REQUIRE(q.sql == R"(SELECT "id", "name", "age" FROM "person" GROUP BY "age")");
|
REQUIRE(result.sql == R"(UPDATE "person" SET "id"=7, "name"='george', "age"=65 WHERE "name" = 'george' ORDER BY "id" ASC LIMIT 2)");
|
||||||
REQUIRE(q.table_name == "person");
|
REQUIRE(result.table.name == "person");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Select sql statement string with offset and limit", "[query]") {
|
TEST_CASE("Delete sql statement string", "[query]")
|
||||||
dialect d = dialect_builder::builder().create().build();
|
{
|
||||||
query_builder query(d);
|
connection noop("noop://noop.db");
|
||||||
const auto q = query.select({"id", "name", "age"})
|
auto scm = std::make_shared<schema>("noop");
|
||||||
.from("person")
|
query q(noop, scm);
|
||||||
.offset(10)
|
const auto result = q.remove().from("person").build();
|
||||||
.limit(20)
|
|
||||||
.compile();
|
|
||||||
|
|
||||||
REQUIRE(q.sql == R"(SELECT "id", "name", "age" FROM "person" OFFSET 10 LIMIT 20)");
|
REQUIRE(result.sql == R"(DELETE FROM "person")");
|
||||||
REQUIRE(q.table_name == "person");
|
REQUIRE(result.table.name == "person");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Create, insert and select a blob column", "[query][blob]") {
|
TEST_CASE("Delete limit sql statement", "[query][delete][limit]")
|
||||||
dialect d = dialect_builder::builder().create().build();
|
{
|
||||||
query_builder query(d);
|
connection noop("noop://noop.db");
|
||||||
auto q = query.create().table("person", {
|
auto scm = std::make_shared<schema>("noop");
|
||||||
make_pk_column<unsigned long>("id"),
|
query q(noop, scm);
|
||||||
make_column<std::string>("name", 255),
|
const auto result = q.remove()
|
||||||
make_column<blob>("data")
|
.from("person")
|
||||||
}).compile();
|
.where("name"_col == "george")
|
||||||
|
.order_by("id"_col).asc()
|
||||||
|
.limit(2)
|
||||||
|
.build();
|
||||||
|
|
||||||
REQUIRE(q.sql == R"##(CREATE TABLE "person" ("id" BIGINT NOT NULL, "name" VARCHAR(255) NOT NULL, "data" BLOB NOT NULL, CONSTRAINT PK_person PRIMARY KEY (id)))##");
|
REQUIRE(result.sql == R"(DELETE FROM "person" WHERE "name" = 'george' ORDER BY "id" ASC LIMIT 2)");
|
||||||
REQUIRE(q.table_name == "person");
|
REQUIRE(result.table.name == "person");
|
||||||
|
|
||||||
q = query.insert().into("person", {
|
|
||||||
{ "id", "name", "data" }
|
|
||||||
}).values({7UL, "george", blob{1, 'A', 3, 4}}).compile();
|
|
||||||
|
|
||||||
REQUIRE(q.sql == R"(INSERT INTO "person" ("id", "name", "data") VALUES (7, 'george', X'01410304'))");
|
|
||||||
REQUIRE(q.table_name == "person");
|
|
||||||
|
|
||||||
q = query.select({"id", "name", "data"}).from("person").compile();
|
|
||||||
|
|
||||||
REQUIRE(q.sql == R"(SELECT "id", "name", "data" FROM "person")");
|
|
||||||
REQUIRE(q.table_name == "person");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Select statement with join_left", "[query][join_left]") {
|
TEST_CASE("Select sql statement string with where clause", "[query]")
|
||||||
dialect d = dialect_builder::builder().create().build();
|
{
|
||||||
query_builder query(d);
|
connection noop("noop://noop.db");
|
||||||
|
auto scm = std::make_shared<schema>("noop");
|
||||||
|
query q(noop, scm);
|
||||||
|
auto result = q.select({"id", "name", "age"})
|
||||||
|
.from("person")
|
||||||
|
.where("id"_col == 8 && "age"_col > 50)
|
||||||
|
.build();
|
||||||
|
|
||||||
auto q = query.select({"f.id", "ap.brand", "f.pilot_name"}).from("flight", "f").join("airplane", join_type_t::INNER, "ap").on("f.airplane_id", "ap.id").compile();
|
REQUIRE(result.sql == R"(SELECT "id", "name", "age" FROM "person" WHERE ("id" = 8 AND "age" > 50))");
|
||||||
|
REQUIRE(result.table.name == "person");
|
||||||
|
|
||||||
REQUIRE(q.sql == R"(SELECT "f.id", "ap.brand", "f.pilot_name" FROM "flight" AS "f" INNER JOIN "airplane" AS "ap" ON "f.airplane_id"="ap.id")");
|
result = q.select({"id", "name", "age"})
|
||||||
REQUIRE(q.table_name == "flight");
|
.from("person")
|
||||||
|
.where("id"_col == _ && "age"_col > 50)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
REQUIRE(result.sql == R"(SELECT "id", "name", "age" FROM "person" WHERE ("id" = ? AND "age" > 50))");
|
||||||
|
REQUIRE(result.table.name == "person");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Insert sql statement with placeholder", "[query]")
|
||||||
|
{
|
||||||
|
connection noop("noop://noop.db");
|
||||||
|
auto scm = std::make_shared<schema>("noop");
|
||||||
|
query q(noop, scm);
|
||||||
|
const auto result = q.insert().into("person", {
|
||||||
|
"id", "name", "age"
|
||||||
|
}).values({_, _, _}).build();
|
||||||
|
|
||||||
|
REQUIRE(result.sql == R"(INSERT INTO "person" ("id", "name", "age") VALUES (?, ?, ?))");
|
||||||
|
REQUIRE(result.table.name == "person");
|
||||||
|
REQUIRE(result.bind_vars.size() == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Select sql statement string with order by", "[query]")
|
||||||
|
{
|
||||||
|
connection noop("noop://noop.db");
|
||||||
|
auto scm = std::make_shared<schema>("noop");
|
||||||
|
query q(noop, scm);
|
||||||
|
const auto result = q.select({"id", "name", "age"})
|
||||||
|
.from("person")
|
||||||
|
.order_by("name").asc()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
REQUIRE(result.sql == R"(SELECT "id", "name", "age" FROM "person" ORDER BY "name" ASC)");
|
||||||
|
REQUIRE(result.table.name == "person");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Select sql statement string with group by", "[query]")
|
||||||
|
{
|
||||||
|
connection noop("noop://noop.db");
|
||||||
|
auto scm = std::make_shared<schema>("noop");
|
||||||
|
query q(noop, scm);
|
||||||
|
const auto result = q.select({"id", "name", "age"})
|
||||||
|
.from("person")
|
||||||
|
.group_by("age")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
REQUIRE(result.sql == R"(SELECT "id", "name", "age" FROM "person" GROUP BY "age")");
|
||||||
|
REQUIRE(result.table.name == "person");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Select sql statement string with offset and limit", "[query]")
|
||||||
|
{
|
||||||
|
connection noop("noop://noop.db");
|
||||||
|
auto scm = std::make_shared<schema>("noop");
|
||||||
|
query q(noop, scm);
|
||||||
|
const auto result = q.select({"id", "name", "age"})
|
||||||
|
.from("person")
|
||||||
|
.order_by("id"_col).asc()
|
||||||
|
.limit(20)
|
||||||
|
.offset(10)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
REQUIRE(result.sql == R"(SELECT "id", "name", "age" FROM "person" ORDER BY "id" ASC LIMIT 20 OFFSET 10)");
|
||||||
|
REQUIRE(result.table.name == "person");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Create, insert and select a blob column", "[query][blob]")
|
||||||
|
{
|
||||||
|
connection noop("noop://noop.db");
|
||||||
|
auto scm = std::make_shared<schema>("noop");
|
||||||
|
query q(noop, scm);
|
||||||
|
auto result = q.create().table("person", {
|
||||||
|
make_pk_column<unsigned long>("id"),
|
||||||
|
make_column<std::string>("name", 255),
|
||||||
|
make_column<blob>("data")
|
||||||
|
}).build();
|
||||||
|
|
||||||
|
REQUIRE(result.sql == R"##(CREATE TABLE "person" ("id" BIGINT NOT NULL, "name" VARCHAR(255) NOT NULL, "data" BLOB NOT NULL, CONSTRAINT PK_person PRIMARY KEY (id)))##");
|
||||||
|
REQUIRE(result.table.name == "person");
|
||||||
|
|
||||||
|
result = q.insert().into("person", {
|
||||||
|
"id", "name", "data"
|
||||||
|
}).values({7UL, "george", blob{1, 'A', 3, 4}}).build();
|
||||||
|
|
||||||
|
REQUIRE(result.sql == R"(INSERT INTO "person" ("id", "name", "data") VALUES (7, 'george', X'01410304'))");
|
||||||
|
REQUIRE(result.table.name == "person");
|
||||||
|
|
||||||
|
result = q.select({"id", "name", "data"}).from("person").build();
|
||||||
|
|
||||||
|
REQUIRE(result.sql == R"(SELECT "id", "name", "data" FROM "person")");
|
||||||
|
REQUIRE(result.table.name == "person");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Select statement with join_left", "[query][join_left]")
|
||||||
|
{
|
||||||
|
connection noop("noop://noop.db");
|
||||||
|
auto scm = std::make_shared<schema>("noop");
|
||||||
|
query q(noop, scm);
|
||||||
|
auto result = q.select({"f.id", "ap.brand", "f.pilot_name"})
|
||||||
|
.from({"flight", "f"})
|
||||||
|
.join_left({"airplane", "ap"})
|
||||||
|
.on("f.airplane_id"_col == "ap.id"_col)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
REQUIRE(result.sql == R"(SELECT "f"."id", "ap"."brand", "f"."pilot_name" FROM "flight" AS "f" INNER JOIN "airplane" AS "ap" ON "f"."airplane_id" = "ap"."id")");
|
||||||
|
REQUIRE(result.table.name == "flight");
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue